Commit Graph

10 Commits

Author SHA1 Message Date
opencode-agent e795d24230 sqlite: also emit an ASCII table so the TUI shows columns
The OpenCode TUI renders tool output through a literal <text> node
(packages/tui/.../session/index.tsx, GenericTool), so a GFM table
becomes a wall of pipes. The web/desktop client passes the same output
through the markdown renderer and draws a proper grid, so a GFM table
is the most compact form there.

The previous fix emitted a markdown table and assumed the TUI would
render it. It does not. The fix: ship both. The ASCII table is space-
padded, word-wraps long cells, and stays aligned even when the TUI
shows only its collapsed 3-line preview; the markdown table follows
and is what the web/desktop client renders with a proper grid.

- New rowsToAsciiTable: cellToAscii, truncateForCell, wrapCell,
  visibleWidth, padRight. NULL -> <null>, BLOB -> <BLOB nB>, Date ->
  ISO, BigInt -> string. Cell width capped at 40 chars by default
  (configurable). Single words longer than the cap are hard-wrapped.
- sqlite_query's format=table path now emits the ASCII table first
  and the markdown table second, with a blank line between.
- README explains why the duplication and how to read both.

End-to-end verified via Code Mode (no model in the loop) after
opencode service restart picked up the new transform.
2026-10-08 17:45:44 +08:00
opencode-agent d0f31023bd sqlite: render results as Markdown tables for the TUI
OpenCode's tool content schema (Tool.Content = TextContent | FileContent)
gives a server plugin no metadata channel — the TUI's only view of tool
output is the content string. So: format the result as a Markdown
table, which the TUI's built-in markdown renderer already displays as
a real table.

- sqlite_query gains format = 'table' (default) | 'json' | 'both'.
  'table' is the new default and renders a header line, a separator
  row, and one row per record with pipes/newlines/backslashes escaped.
  'json' keeps the old behaviour for callers that need raw rows.
- Every tool that runs SQL echoes 'SQL: <stmt>  params: [...]' as the
  first line of its output, so the user sees what was executed
  including the bound values.
- Every tool that runs a statement pushes context.progress() at start
  and end, which surfaces in the TUI status bar.
- cellToMarkdown caps each cell at 80 chars to keep wide BLOBs from
  blowing up the TUI column width.

End-to-end verified via Code Mode (no model in the loop):
- format=table renders correctly with edge cases (| in text, \n in
  text, \ in text)
- format=both appends the JSON view below the table
- exec echoes the bound params as a JSON array
- write+read round-trip persists (UPDATE → SELECT sees the new value)
2026-10-08 17:36:44 +08:00
opencode-agent d1aabef771 sqlite: document what survives a process kill
User asked what happens if the window is closed mid-task. Added a
'What happens if the process dies mid-task' section that tabulates
the four exit paths (TUI close, SIGTERM, SIGKILL, power loss) and
empirically confirms that anything past the last fsync'd commit is
on disk. The only ways to lose data are :memory:, an explicit
synchronous=OFF, or a network filesystem. Also corrects the earlier
'leak fd' framing — a dead process leaks no fds, the OS reclaims
them.
2026-10-08 17:22:13 +08:00
opencode-agent f873990e72 sqlite: document lifecycle and concurrency behaviour
User asked what happens if the connection is never closed and whether
concurrent calls are safe. Adds a Lifecycle and concurrency section
to README.md covering:

- not closing only leaks fds; data is durable on commit
- 3-tier concurrency model: same service / multi-CLI same service /
  multi-process, with the actual busy_timeout default (5s) and what
  to do if a longer wait is needed (run PRAGMA busy_timeout via
  sqlite_exec)
- :memory: semantics (gone on close, even within one process)
- NFS/SMB caveat

No code changes; current defaults (busy_timeout 5s, synchronous
FULL, locking normal) are sensible and the existing test sweep
already verified end-to-end.
2026-10-08 17:20:21 +08:00
opencode-agent 9aef200ac9 Add sqlite plugin: open/query/exec/script against .db files
Adds a single-file V2 plugin that exposes eight tools under the
`sqlite` namespace (open, close, list, query, exec, script, tables,
schema) so a model can read and write SQLite databases from a session.

- OpenCode discovers it automatically from ~/.config/opencode/plugins/.
- New runtime dependency: better-sqlite3 (installed in this repo's
  node_modules so the host's module resolution picks it up).
- README documents install, copy-to-another-machine, options, and
  troubleshooting; SETUP.md is a copy-paste checklist.
- Schema/options were trimmed down while authoring: the initial draft
  registered a no-op SQLite function on every open as a 'future hook';
  removed, it was dead code.
2026-10-08 17:03:48 +08:00
xiaoshuai 3d72d7821a Add agent-memory skill and plugin
Install the three-level file-based agent memory (kurbezz/memory):
skills land in ~/.agents/skills/agent-memory via 'npx skills add',
and plugins/agent-memory.js is the installer-created symlink into it.
Pure markdown store under ~/.agent-memory, no vector DB and no API key.
2026-10-08 15:43:16 +08:00
xiaoshuai d6e29cbbad searxng-search: record that no domestic-only engine set works here
Asked for a domestic-only default, so every general-web index SearXNG ships
for China was added to keep_only, the container was restarted, and each was
measured over 5 runs per query. None of them is usable. The default stays
bing,yandex.

  engine          en hits  zh hits  outcome
  360search         5/5      5/5   reliable, 0% relevant
  quark             0/5      0/5   rate-limited dead after two good responses
  baidu              -        0   CAPTCHA, 1h IP suspension
  sogou              -        0   upstream AttributeError
  baidu kaifa        -      0/10   code index: "opencode v2" matches OpenCV2
  bilibili           -        -   video titles, not a web index
  chinaso news       -        -   falls through to the default engine set

quark was the one that looked like the fix. On its first two requests it
returned the exact article being asked about as result #1 on both the Chinese
and the English query -- better than anything else measured -- and then answered
0 results on 5 consecutive runs of each. Had it not been run 5 times, it would
have looked like the obvious upgrade.

baidu kaifa is worth remembering as a category error: it is a code search
index, so it matches "opencode v2" against OpenCV2 and returns CSDN blog posts
at 0% relevance. It is reachable and does not CAPTCHA, which makes it look
healthy in /config while being useless.

The foreign engines that were reachable (brave, duckduckgo, google, qwant,
wikipedia) were added at the same time and all returned 0, consistent with the
network timeouts already recorded in settings.yml. mojeek and startpage are not
present in this SearXNG release at all, so the earlier note calling them
"unreachable" was imprecise.

settings.yml was restored from a backup and diffed byte-identical before this
commit; the probe engines never left the instance.

cn.bing.com is the only dependable endpoint and is a China-hosted Bing, so bing
counts as the domestic option. Its one real limitation stands: it ignores the
site: operator, so site-restricted search is unavailable through this instance.

Also fixes a duplicated `bing` row left in the README engine table by the
previous commit.
2026-10-08 13:44:46 +08:00
xiaoshuai aa70b381bf searxng-search: default engines bing,yandex instead of bing,360search
The default was chosen by a single Chinese test query and generalized from
it. Measuring both a Chinese and an English technical query shows it was
inverted on both counts. Results mentioning "opencode", out of returned:

                       zh "OpenCode V2 和 V1 区别"   en "opencode v2 migrate from v1 plugin api"
  bing                          10/10                     missed the doc entirely
  360search                      0/5                      4, unrelated (sohu/toutiao)
  yandex                        14/15                     15, migration doc ranked #1
  naver                           0/9                     15, migration doc ranked #1

yandex had been excluded on the claim that it "has almost no Chinese index".
Measured, it has the best Chinese relevance of any engine here, and on the
English query the V1->V2 migration doc is its first result -- the exact
document that the old default could not find at all.

360search had been the default. It is the worst engine on both query types.
It splits the query on "V1"/"V2" and answers with Android and CANN
version-difference articles, which produced the 10-of-15 noise in the first
round of testing.

naver is left out rather than added: strongest on English, 0/9 on Chinese, so
including it would trade one kind of noise for another. It is documented as
worth passing explicitly for English lookups.

The comment above the constant now carries the measurement table, so the
default can be re-chosen from data instead of re-derived from a hunch.

Not changed, and worth knowing: cn.bing.com ignores the site: operator.
engines=bing&q=site:opencode.ai+v2+migration returns 0 results from
opencode.ai, while the same query without site: returns 3. Site-restricted
search is not available through this instance.

Unreproduced: one run of the Chinese query returned entirely unrelated
results from bing (Doubao, Zhipin, Zhihu) while four other runs with the same
parameters returned 10/10 relevant. No parameter difference was found between
the good and bad runs. Treated as transient upstream behaviour, not a plugin
bug, and not documented as a rule.

README engine table updated to the measured numbers.
2026-10-08 13:35:57 +08:00
xiaoshuai 9e10925023 searxng-search: document the plugin and how the instance was deployed
Two docs next to the plugin: README.md for the tool, SEARXNG-SETUP.md for the
Docker deployment behind it. Both are written from measurements against the
running instance, not from a guide.

The setup doc exists because the deployment decisions were only recorded as
comments inside settings.yml, which means they are unfindable unless you
already know to look there. It also records the parts that are not guessable:
why the port is 39217, why limiter is off, why the UI locale is zh-Hans-CN
rather than zh-CN, and which engine is broken how.

Corrections found while writing it:

- The rebuild steps pointed at searxng/searxng-docker, which is superseded. That
  repository now holds only a deprecation notice and its docker-compose.yml raw
  URL 404s. The templates moved to searxng/master/container/. Verified both
  local files are byte-identical to the current templates, so the deployment
  was always the current one -- only the documented URL was wrong.
- The plugin README claimed the entrypoint comes from package.json. This
  directory has no package.json; the entrypoint falls back to index.ts. Restarted
  the service with both .md files in place to confirm they do not affect
  resolution.

Documents the two SearXNG behaviours that fail silently rather than loudly,
both verified by reading the engine label on each result:

- An unknown engine name is ignored and the default engine set is searched
  instead, with no error. engines=mojeek returns 10 bing results and looks like
  a success, as does a typo. The only reliable signal is whether the requested
  engine appears in results[].engine.
- /config is not a way to check this. It reported disabled: false for every
  engine while baidu and sogou were in fact being dropped, because it reflects
  upstream defaults and not the local disabled: true overrides.

Also records that ctx.options is always {} for a directory-discovered plugin,
so the four options in PluginConfig cannot be supplied without moving the
plugin out of plugins/ and registering it in opencode.jsonc. Verified by
writing JSON.stringify(ctx.options) to a file from inside setup().

No secret_key value is in either file; settings.yml stays outside this
repository under ~/Docker.
2026-10-08 13:29:02 +08:00
xiaoshuai 15a1bbcee0 Version OpenCode skills and plugins
Repository sits at the OpenCode config root rather than inside skills/ or
plugins/. OpenCode scans exactly those two subdirectories, and a .git
directory inside either one is picked up as a plugin and fails to load:

  loading plugin id=.../plugins/.git entrypoint=.../plugins/.git/index
  failed to load plugin ... AggregateError: 2 errors building .../plugins/.git/index

The watcher.ignore config option does not help: it only suppresses filesystem
update events, not plugin discovery, and the "-" disable prefix only applies to
plugins listed in opencode.json(c), not auto-discovered ones.

.gitignore admits only skills/ and plugins/ (plus itself). Personal config
(opencode.jsonc, cli.json, service.json) and node_modules stay local.

skills/opencode-plugins  V2-only plugin authoring reference and 7 templates,
                         transcribed from the V2 docs with the URL on every file
plugins/searxng-search   searxng_search tool over a self-hosted SearXNG JSON API
2026-10-08 13:12:10 +08:00