akm-opencode 0.9.202808220049 → 0.9.1202608242057

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.ts +31 -5
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -129,7 +129,7 @@ const AKM_WORKFLOW_INSTRUCTION = [
129
129
  "",
130
130
  "Use AKM as a reusable knowledge and workflow stash.",
131
131
  "",
132
- "Before writing from scratch:",
132
+ "Before writing or editing anything whose exact syntax or keys you are not certain of (a file already in the workspace included):",
133
133
  "1. Use `akm_curate` with a query that includes the current project name/domain (primary discovery). Fall back to `akm_search` only when you already know an asset exists and need its exact ref.",
134
134
  "2. Use `akm_show <ref>` before relying on an asset.",
135
135
  "3. Record `akm_feedback` after the result is known.",
@@ -971,10 +971,19 @@ function extractAkmRefsFromAllArgs(args: Record<string, unknown>): string[] {
971
971
  return [...refs]
972
972
  }
973
973
 
974
+ // The trigger sentence used to read "Before writing anything from scratch",
975
+ // which literally excludes the largest class of tasks retrieval helps with:
976
+ // editing a file whose conventions the model does not know. Measured across
977
+ // 138 Harbor A/B trials (issue #94), engagement on edit-shaped tasks was
978
+ // 0/24 (eval) and 3/57 (train) versus 48% and 38% on create-shaped tasks from
979
+ // the same families — three edit tasks scored 0.00 on BOTH arms because the
980
+ // model invented keys for a file it had just read. A visible file makes a task
981
+ // look self-sufficient, so the trigger has to say outright that seeing a file
982
+ // is not knowing its schema.
974
983
  const AKM_HINTS_PREFIX = [
975
984
  "# AKM is available in this session",
976
985
  "",
977
- "You have an AKM stash on this machine. Before writing anything from scratch, call `akm_curate` with a task description to find relevant assets with LLM-reranked relevance scores.",
986
+ "You have an AKM stash on this machine. Before writing **or editing** a config file, manifest, schema, or command for any tool, format, or API whose exact syntax or keys you are not certain of, call `akm_curate` with a task description to find relevant assets with LLM-reranked relevance scores. A file already being present in the workspace is not evidence that you know its schema — the values may be given to you while the key names and nesting are not, so check the stash for that format's conventions before you edit it.",
978
987
  "",
979
988
  "**Choosing the right lookup command:**",
980
989
  "",
@@ -2045,7 +2054,17 @@ const akmPlugin: Plugin = async ({ client, worktree, directory }) => {
2045
2054
  sessionWorkflow.get(sid) ? formatWorkflowContext(sessionWorkflow.get(sid)!) : "",
2046
2055
  !proposalSummary.unsupported && proposalSummary.count > 0 ? formatPendingProposalContext(proposalSummary.count) : "",
2047
2056
  ]
2048
- output.system.push(...applyContextBudget(blocks))
2057
+ // ONE entry, not N. OpenCode maps each `system` entry to its own system
2058
+ // message, and chat templates that require a single leading system
2059
+ // message reject the request outright — "Jinja Exception: System
2060
+ // message must be at the beginning", surfacing as an opaque provider
2061
+ // HTTP 500 that hits only sessions with the plugin installed (#96;
2062
+ // reproduced with a bare two-system-message request on
2063
+ // qwen3.6-35b-a3b and devstral-small-2-2512, no akm involved).
2064
+ // Budgeting is unchanged and still happens per block, so joining can
2065
+ // only re-seam blocks applyContextBudget already kept.
2066
+ const budgeted = applyContextBudget(blocks)
2067
+ if (budgeted.length > 0) output.system.push(budgeted.join("\n\n"))
2049
2068
  } catch (error: unknown) {
2050
2069
  await logHookFailure(logClient, "experimental.chat.system.transform", error)
2051
2070
  }
@@ -2120,7 +2139,7 @@ const akmPlugin: Plugin = async ({ client, worktree, directory }) => {
2120
2139
  }
2121
2140
  })()
2122
2141
  } else {
2123
- const hint = "Need more AKM context? Use `akm_search` or `akm_curate` before writing from scratch."
2142
+ const hint = "Need more AKM context? Use `akm_search` or `akm_curate` before writing or editing a file whose exact syntax you are not certain of."
2124
2143
  writeStructuredEvent({
2125
2144
  event: "prompt_recall",
2126
2145
  sessionId: input.sessionID,
@@ -2469,7 +2488,14 @@ const akmPlugin: Plugin = async ({ client, worktree, directory }) => {
2469
2488
  },
2470
2489
  }),
2471
2490
  akm_curate: tool({
2472
- description: "PRIMARY discovery entry point for the stash: describe the task in natural language and this returns the top matches as a ranked list. Pass a hit's ref to akm_show before relying on it, then record akm_feedback once the result is known.",
2491
+ // Led with the mechanism ("describe the task in natural language and
2492
+ // this returns the top matches"), which reads as project/asset
2493
+ // discovery and lost to built-in read/glob/skill on edit-shaped tasks:
2494
+ // across seven models screened on one akm-relevant task, five made
2495
+ // zero akm_* calls while curation was demonstrably available (#95).
2496
+ // Leading with the decision — when to reach for this instead of just
2497
+ // reading the file — is what it has to win on.
2498
+ description: "Reach for this BEFORE writing or editing a config file, manifest, schema, or command for any tool, format, or API whose exact syntax or keys you are not certain of — including a file already present in the workspace, since having read a file does not mean you know its schema. PRIMARY discovery entry point for the stash: describe the task in natural language and this returns the top matches as a ranked list. Pass a hit's ref to akm_show before relying on it, then record akm_feedback once the result is known.",
2473
2499
  args: {
2474
2500
  query: tool.schema.string().describe("Task, topic, or natural-language description of what you want to do."),
2475
2501
  type: tool.schema.enum(ASSET_TYPES as unknown as [string, ...string[]]).optional().describe("Optional asset type filter."),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akm-opencode",
3
- "version": "0.9.202808220049",
3
+ "version": "0.9.1202608242057",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for AKM 0.9 with in-process search, show, and curate tools plus feedback and remember.",
6
6
  "keywords": [