akm-opencode 0.9.21202610030351 → 0.9.21202610040152

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.
package/README.md CHANGED
@@ -17,7 +17,7 @@ Add the plugin to `opencode.json`:
17
17
  | Tool | Description |
18
18
  | --- | --- |
19
19
  | `akm_search` | Search configured bundles or registries. `source` accepts `local`, `registry`, `all`, or a configured bundle name. |
20
- | `akm_show` | Show a concept by `[bundle//]conceptId[#fragment]`. Reads are exact by default; for an opaque search fragment, `context: "lead"` adds bounded indexed-safe lead context. |
20
+ | `akm_show` | Show a concept by `[bundle//]conceptId[#fragment]`. |
21
21
  | `akm_curate` | Return ranked concepts for a task or topic. Optional `pack` is a token budget that returns the selected local assets' full content in one response; registry hits are omitted from packed items. |
22
22
  | `akm_feedback` | Record positive or negative feedback for a concept. |
23
23
  | `akm_remember` | Save durable knowledge as a searchable memory. |
@@ -26,13 +26,7 @@ Add the plugin to `opencode.json`:
26
26
 
27
27
  Use the `ref` returned by search or curate directly with show or feedback. When `akm_curate.pack` is set, the response already includes packed local content, so a separate show call is only needed for omitted or registry-only hits. Concept IDs look like `skills/code-review`, `memories/release-retro`, or `team-playbook//knowledge/deploy#Rollback`.
28
28
 
29
- For `akm_show`, `context` accepts `exact` or `lead`. Exact is the default and
30
- preserves the existing selected-fragment behavior. For an opaque fragment ref
31
- returned by search, lead context puts the indexed-safe first fragment before
32
- an explicitly labelled selected match and uses a 3,200-character default hard
33
- bound. Friendly authored heading selectors retain their existing source-live
34
- behavior. Set either `max_tokens` (estimated at four characters per token) or
35
- `max_chars`, never both. Search and show
29
+ Search and show
36
30
  responses preserve canonical `ref` while exposing `selectedRef`, `parentRef`,
37
31
  fragment ordinal/count and lines, previous/next refs, separate fragment/parent
38
32
  estimates, and context truncation metadata.
@@ -137,7 +131,7 @@ These three are read once, when the plugin module is imported, so they must be s
137
131
 
138
132
  1. Start with `akm_curate` for task-oriented discovery; set `pack` when you want the selected local content immediately.
139
133
  2. Use `akm_search` when you know the concept name and need its exact ID.
140
- 3. Fetch a concept with `akm_show` before relying on it; opt into bounded lead context only when a selected fragment needs it.
134
+ 3. Fetch a concept with `akm_show` before relying on it.
141
135
  4. Record whether the concept helped with `akm_feedback`; a failed akm call is not feedback on the asset.
142
136
  5. Use `akm_remember` for durable knowledge that should be available to future sessions.
143
137
 
package/dist/index.js CHANGED
@@ -1163,54 +1163,6 @@ function shouldRecall(prompt, options) {
1163
1163
  return { shouldRecall: false, reason: "skip-low-signal", query: text, scopeHints };
1164
1164
  }
1165
1165
 
1166
- // fragment-context.ts
1167
- function positiveSafeInteger(value, field) {
1168
- if (value === undefined)
1169
- return;
1170
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0) {
1171
- throw new Error(`${field} must be a positive integer`);
1172
- }
1173
- return value;
1174
- }
1175
- function supportsFragmentLeadContext(version) {
1176
- const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version.trim());
1177
- if (!match)
1178
- return false;
1179
- const major = Number(match[1]);
1180
- const minor = Number(match[2]);
1181
- const patch = Number(match[3]);
1182
- return major > 0 || minor > 9 || minor === 9 && patch >= 15;
1183
- }
1184
- function normalizeFragmentShowInput(input, loadedAkmApiVersion) {
1185
- const {
1186
- context,
1187
- max_tokens: rawMaxTokens,
1188
- max_chars: rawMaxChars,
1189
- ...showInput
1190
- } = input;
1191
- const maxTokens = positiveSafeInteger(rawMaxTokens, "max_tokens");
1192
- const maxChars = positiveSafeInteger(rawMaxChars, "max_chars");
1193
- if (maxTokens !== undefined && maxChars !== undefined) {
1194
- throw new Error("max_tokens and max_chars are mutually exclusive");
1195
- }
1196
- const contextMode = context;
1197
- if (contextMode === "lead" && !supportsFragmentLeadContext(loadedAkmApiVersion)) {
1198
- throw new Error(`context='lead' requires akm-cli >=0.9.15; this plugin bundles ${loadedAkmApiVersion}. ` + "Install the plugin release whose exact akm-cli pin is 0.9.15 or newer.");
1199
- }
1200
- const maxContextChars = maxChars ?? (maxTokens !== undefined ? maxTokens * 4 : undefined);
1201
- if (maxContextChars !== undefined && !Number.isSafeInteger(maxContextChars)) {
1202
- throw new Error("fragment context budget is too large");
1203
- }
1204
- if (maxContextChars !== undefined && contextMode !== "lead") {
1205
- throw new Error("max_tokens and max_chars require context='lead'");
1206
- }
1207
- return {
1208
- ...showInput,
1209
- ...contextMode !== undefined ? { contextMode } : {},
1210
- ...maxContextChars !== undefined ? { maxContextChars } : {}
1211
- };
1212
- }
1213
-
1214
1166
  // index.ts
1215
1167
  var moduleDir = path4.dirname(fileURLToPath(import.meta.url));
1216
1168
  var AKM_AUTO_FEEDBACK = (process.env.AKM_AUTO_FEEDBACK ?? "1") !== "0";
@@ -2898,8 +2850,7 @@ async function runInProcess(client, operation, input, meta) {
2898
2850
  if (operation === "curate" && input.pack !== undefined && (typeof input.pack !== "number" || !Number.isInteger(input.pack) || input.pack <= 0)) {
2899
2851
  throw new Error("pack must be a positive integer token budget");
2900
2852
  }
2901
- const normalizedInput = operation === "show" ? normalizeFragmentShowInput(input, BUNDLED_AKM_API_VERSION) : input;
2902
- const result = operation === "search" ? await akmSearch(normalizedInput) : operation === "show" ? await akmShowUnified(normalizedInput) : await (async () => {
2853
+ const result = operation === "search" ? await akmSearch(input) : operation === "show" ? await akmShowUnified(input) : await (async () => {
2903
2854
  const { pack, ...curateInput } = input;
2904
2855
  const curated = await akmCurate(curateInput);
2905
2856
  return typeof pack === "number" ? packCuratedHits(curated, pack) : curated;
@@ -3417,22 +3368,13 @@ ${hint}` : hint;
3417
3368
  }
3418
3369
  }),
3419
3370
  akm_show: tool({
3420
- description: "Show an AKM asset by [bundle//]conceptId[#fragment]. Reads stay exact by default. For an opaque fragment ref returned by search, context='lead' prepends bounded indexed-safe lead context and labels the selected match last; authored heading selectors retain their existing source-live behavior. Read an asset this way before relying on it, then record akm_feedback once you know whether it helped.",
3371
+ description: "Show an AKM asset by [bundle//]conceptId[#fragment]. Read an asset this way before relying on it, then record akm_feedback once you know whether it helped.",
3421
3372
  args: {
3422
3373
  ref: tool.schema.string().describe("Asset ref returned by akm_curate or akm_search, optionally with a #fragment \u2014 e.g. `skills/code-review` or `local//knowledge/deploy#Rollback`."),
3423
- detail: tool.schema.enum(["brief", "summary", "normal", "full"]).optional().describe("Response detail level. Defaults to 'normal'."),
3424
- context: tool.schema.enum(["exact", "lead"]).optional().describe("Fragment context mode. Defaults to exact. For an opaque search fragment, use lead to prepend indexed-safe lead context while keeping the selected match last."),
3425
- max_tokens: tool.schema.number().optional().describe("Positive token budget for context='lead', estimated as four characters per token. Mutually exclusive with max_chars."),
3426
- max_chars: tool.schema.number().optional().describe("Positive character budget for context='lead'. Mutually exclusive with max_tokens. Lead defaults to 3200 characters.")
3374
+ detail: tool.schema.enum(["brief", "summary", "normal", "full"]).optional().describe("Response detail level. Defaults to 'normal'.")
3427
3375
  },
3428
- async execute({ ref, detail, context, max_tokens, max_chars }, toolContext) {
3429
- return runInProcess(client, "show", {
3430
- ref,
3431
- detail,
3432
- context,
3433
- max_tokens,
3434
- max_chars
3435
- }, { toolName: "akm_show", sessionID: toolContext.sessionID, directory: toolContext.directory });
3376
+ async execute({ ref, detail }, toolContext) {
3377
+ return runInProcess(client, "show", { ref, detail }, { toolName: "akm_show", sessionID: toolContext.sessionID, directory: toolContext.directory });
3436
3378
  }
3437
3379
  }),
3438
3380
  akm_remember: tool({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akm-opencode",
3
- "version": "0.9.21202610030351",
3
+ "version": "0.9.21202610040152",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for AKM with discovery tools, feedback, memory, and automatic learning proposals from corrections and recurring workflows.",
6
6
  "keywords": [