@skillstate/opencode 2.2.2 → 3.0.0

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
@@ -14,11 +14,15 @@
14
14
  ---
15
15
 
16
16
  `@skillstate/opencode` integrates the paper-exact runtime
17
- ([`@skillstate/core`](../core)) into **OpenCode**. It emits a `SKILL.md` so the
18
- host discovers the skill, and a plugin that hooks
17
+ ([`@skillstate/core`](../core)) into **OpenCode**. The integration is the
18
+ npm plugin `SkillStatePlugin` itself, loaded directly from the PROJECT
19
+ `opencode.json(c)` (`"plugin": ["@skillstate/opencode"]`): it hooks
19
20
  `experimental.chat.messages.transform` to **trim history before every LLM
20
21
  call** — dropping old messages and injecting only the state, which is genuine
21
- **O(1)** prompt footprint.
22
+ **O(1)** prompt footprint. The plugin is project-local and inert when the
23
+ project has no `.skillstate/` state, and OpenCode reads the shared project
24
+ `.claude/skills/skillstate/SKILL.md` too (Claude-compatible skill discovery),
25
+ so one host-neutral skill file serves both hosts.
22
26
 
23
27
  > **@non-paper** — no adapters exist in arXiv 2608.26263v3. This adapter is an
24
28
  > additive integration, not part of the paper.
@@ -34,89 +38,77 @@ Requires Node.js >= 20. TypeScript types are bundled.
34
38
  ## Quick start
35
39
 
36
40
  ```ts
37
- import { OpenCodeAdapter } from '@skillstate/opencode';
38
- import { INTERCODE_CTF_SPEC } from '@skillstate/core/schemas';
41
+ import { OpenCodeAdapter, SkillStatePlugin, createSkillStatePlugin } from '@skillstate/opencode';
39
42
 
40
43
  const adapter = new OpenCodeAdapter();
41
44
 
42
- // SKILL.md with frontmatter (name/description/version) + an
43
- // execution_context block pointing at the persisted state file:
44
- const skillMd = adapter.generateSkillMd(INTERCODE_CTF_SPEC, './.skillstate.json');
45
-
46
- // Plugin with real O(1) history trimming via experimental.chat.messages.transform.
47
- // The state path is resolved per session from the host cwd inside the plugin —
48
- // no baked path:
49
- const plugin = adapter.generatePluginCode();
50
-
51
- // Default keeps the last 3 non-system messages + state injection.
52
- // Configure history depth:
53
- const plugin2 = adapter.generatePluginCode({
54
- maxHistoryMessages: 5, // keep last 5 non-system messages
55
- });
56
-
57
- // Persist the plugin to disk atomically:
58
- const saved = await adapter.savePluginCode(
59
- './skillstate.plugin.ts',
60
- { maxHistoryMessages: 5 },
61
- );
45
+ // The plugin OpenCode loads from "plugin": ["@skillstate/opencode"] —
46
+ // the ready-made instance (the default export carries the same function):
47
+ const plugin = SkillStatePlugin;
48
+
49
+ // Need a custom configuration? Build your own instance:
50
+ const configured = createSkillStatePlugin({ maxHistoryMessages: 5 });
51
+
52
+ // Real O(1) history trimming via experimental.chat.messages.transform,
53
+ // compaction context injection via experimental.session.compacting, and
54
+ // state persistence via tool.execute.after. The state path is resolved per
55
+ // session from the host cwd inside the plugin — no baked path, and every
56
+ // state-touching hook returns early when the project has no state file.
62
57
  ```
63
58
 
64
59
  ## Install into OpenCode (host)
65
60
 
66
61
  Tested end-to-end against OpenCode ≥ 1.17 (`@opencode-ai/plugin` 1.15.x
67
- hook contracts). Four steps:
68
-
69
- **1. Generate the plugin file** (one-off, or wire into a build script):
70
-
71
- ```ts
72
- // scripts/gen-plugin.mjs (run with: node scripts/gen-plugin.mjs)
73
- import { OpenCodeAdapter } from '@skillstate/opencode';
74
- import { writeFileSync } from 'node:fs';
75
-
76
- const adapter = new OpenCodeAdapter();
77
- const code = adapter.generatePluginCode({ maxHistoryMessages: 3 });
78
- writeFileSync('/abs/path/to/skillstate.plugin.ts', code);
79
- ```
80
-
81
- Put the generated `skillstate.plugin.ts` anywhere stable (absolute path is
82
- safest), e.g. `<project>/.opencode-runtime/skillstate.plugin.ts`. The plugin
83
- must be able to resolve `@skillstate/opencode` at load time (install it in
84
- the project or globally) — hook logic lives in that package.
62
+ hook contracts). Everything below is PROJECT-LOCAL — nothing is written
63
+ into `~/.config/opencode`. The one-command path is
64
+ `npm i -g @skillstate/cli && skillstate init` in the project (it performs
65
+ steps 1–3 for every detected host); the manual equivalent:
85
66
 
86
- **2. Create the initial state file** (`<project>/.skillstate/skillstate.json`),
87
- matching your spec schema, e.g. for `INTERCODE_CTF_SPEC`:
67
+ **1. Register the npm plugin in the project `opencode.jsonc|json`** — add
68
+ `"@skillstate/opencode"` to the `plugin` array (npm entries are
69
+ auto-installed by OpenCode via Bun; no generated plugin file exists):
88
70
 
89
- ```json
71
+ ```jsonc
90
72
  {
91
- "discovered_flags": [],
92
- "tested_hypotheses": [],
93
- "active_files": [],
94
- "working_dir": "/abs/work/dir",
95
- "cmd_summary": "initialized"
73
+ "plugin": [
74
+ "@ai-sdk/anthropic",
75
+ "@skillstate/opencode"
76
+ ]
96
77
  }
97
78
  ```
98
79
 
99
- **3. Register the plugin in `opencode.jsonc`** — add a `file://` entry to the
100
- `plugin` array (local paths are resolved by OpenCode and imported directly;
101
- TypeScript is supported because plugins load under Bun):
80
+ **2. Register the MCP server** in the same config's `mcp` object —
81
+ `skillstate init` writes exactly this entry (`npx -y @skillstate/mcp@^3`):
102
82
 
103
83
  ```jsonc
104
84
  {
105
- "plugin": [
106
- "@ai-sdk/anthropic",
107
- "file:///abs/path/to/skillstate.plugin.ts"
108
- ]
85
+ "mcp": {
86
+ "skillstate": {
87
+ "type": "local",
88
+ "command": ["npx", "-y", "@skillstate/mcp@^3"],
89
+ "enabled": true
90
+ }
91
+ }
109
92
  }
110
93
  ```
111
94
 
112
- **4. Install the SKILL.md** — write `adapter.generateSkillMd(spec, statePath)`
113
- to `~/.config/opencode/skills/skillstate/SKILL.md` (global) or
114
- `.opencode/skills/skillstate/SKILL.md` (project). Keep the frontmatter fields
115
- `name` (must match the folder name) and a one-line `description`; the
116
- generated frontmatter may need a manual trim to those two fields.
117
-
118
- Verify with `opencode debug config` (plugin entry shows under `plugin`) and
119
- `opencode debug skill` (your skill is listed). Hook notes for OpenCode ≥ 1.17:
95
+ **3. Share the project skill** — one host-neutral
96
+ `.claude/skills/skillstate/SKILL.md` (written by `skillstate init`) serves
97
+ both OpenCode and Claude Code: OpenCode reads project `.claude/skills/` via
98
+ Claude-compatible discovery. The skill's frontmatter is exactly `name` +
99
+ `description`; the body describes the state-based execution protocol and
100
+ names no host-specific hook/plugin events — the npm plugin injects the
101
+ current state into context every turn, and everything else goes through the
102
+ host-agnostic skillstate MCP tools.
103
+
104
+ **4. Run `skillstate init` in the project** (or let it do all of the above
105
+ at once) to create the state envelope `./.skillstate/skillstate.json` —
106
+ the plugin resolves it from the session cwd and stays inert until it
107
+ exists.
108
+
109
+ Verify with `opencode debug config` (the plugin entry shows under `plugin`,
110
+ `mcp.skillstate` under `mcp`) and `opencode debug skill` (your skill is
111
+ listed). Hook notes for OpenCode ≥ 1.17:
120
112
  `messages.transform` receives `{ info: Message, parts: Part[] }` entries and
121
113
  must mutate `output.messages` **in place**; the plugin injects state as a
122
114
  synthetic `{ info, parts }` message.
@@ -125,24 +117,22 @@ synthetic `{ info, parts }` message.
125
117
 
126
118
  Root path `@skillstate/opencode` exports the adapter and the static plugin:
127
119
 
128
- - `new OpenCodeAdapter()` — implements `PlatformAdapter` (`name = 'opencode'`).
129
- - `generateSkillMd(spec, statePath?): string` — a `SKILL.md` body with
130
- frontmatter and a state-based process description.
131
- - `generatePluginCode(options?): string` — a thin plugin loader
132
- (`import { createSkillStatePlugin } from '@skillstate/opencode'`;
133
- `options.maxHistoryMessages`, default 3). State resolution is always
134
- per-project and lives inside the static plugin. Hooks:
135
- `experimental.chat.messages.transform` (real history trimming),
136
- `experimental.session.compacting` (inject state into compaction context),
137
- `tool.execute.after` (persist `state_patch` to disk).
120
+ - `new OpenCodeAdapter()` — implements `PlatformAdapter` (`name = 'opencode'`);
121
+ a pure prompt/parse surface (`injectState`, `extractPatch`,
122
+ `extractAction`, `formatPrompt`) — host glue is the npm plugin itself,
123
+ not generated code.
124
+ - `SkillStatePlugin` (+ default export) — the ready-made plugin instance
125
+ OpenCode loads from `"plugin": ["@skillstate/opencode"]`; identical to
126
+ `createSkillStatePlugin()`.
138
127
  - `createSkillStatePlugin({ maxHistoryMessages? })` — the static plugin
139
128
  factory (single source of truth for the hook logic); state is resolved from
140
129
  the session cwd on every hook call via
141
- `resolveStatePathForCwd(process.cwd(), os.homedir(), agentId)`. The
142
- `event` hook registers sub-agent sessions from the host bus
143
- (`session.created`/`session.updated` carry `info.parentID`): a sub-agent
144
- session resolves to `agents/<parentPrefix>-<sessionPrefix>/` instead of
145
- overwriting its parent's state file.
130
+ `resolveStatePathForCwd(process.cwd(), os.homedir(), agentId)`, and every
131
+ state-touching hook returns early when the state file does not exist
132
+ (hooks never create state files). Hooks:
133
+ `experimental.chat.messages.transform` (real history trimming),
134
+ `experimental.session.compacting` (inject state into compaction context),
135
+ `tool.execute.after` (persist `state_patch` to disk).
146
136
  - `resolveStatePathForCwd(cwd, home?, agentId?): string` — the per-project
147
137
  state path resolution (pure path arithmetic, no filesystem access).
148
138
  - `pluginAgentId(input, messages?)` / `scopedAgentId(agentId)` /
@@ -150,9 +140,6 @@ Root path `@skillstate/opencode` exports the adapter and the static plugin:
150
140
  the agent-scope plumbing (session id → `agents/` directory name).
151
141
  - `readSkillState` / `saveSkillState` / `mergePatch` / `extractPatch` — the
152
142
  plugin's state helpers, shared by the static plugin.
153
- - `savePluginCode(target, options?): Promise<string>` — writes the plugin
154
- atomically and returns the destination. `target` accepts a raw path or a
155
- `{ root, name }` ref confined by `resolveStatePath` (`..` escapes throw).
156
143
  - `injectState(state, spec): string` / `formatPrompt(state, observation, spec): string`.
157
144
  - `extractPatch(response): StatePatch | null` / `extractAction(response): string | null`.
158
145
 
@@ -163,11 +150,11 @@ Root path `@skillstate/opencode` exports the adapter and the static plugin:
163
150
  `experimental.chat.messages.transform`, so the plugin drops old messages
164
151
  instead of just hiding them — only the last N non-system messages plus an
165
152
  injected state message reach the LLM.
166
- - The generated plugin is a **thin loader**: it imports
167
- `createSkillStatePlugin` from `@skillstate/opencode` (one source of truth).
168
- Hook logic lives only in `src/plugin.ts` — regenerate rather than editing
169
- generated files. **WHERE STATE LIVES** (each opencode session reads AND
170
- writes the same path within its cwd — no cross-file surprises):
153
+ - **The plugin is the npm package, not generated code.** Hook logic lives
154
+ only in `src/plugin.ts` — nothing is emitted to disk by an installer, so
155
+ there are no generated files to edit. **WHERE STATE LIVES** (each opencode
156
+ session reads AND writes the same path within its cwd — no cross-file
157
+ surprises):
171
158
  - main session: `<cwd>/.skillstate/skillstate.json`
172
159
  - sub-agent session (Task sub-agents carry `parentID` on the session):
173
160
  `<cwd>/.skillstate/agents/<parentPrefix>-<sessionPrefix>/skillstate.json`
package/dist/index.d.ts CHANGED
@@ -1,3 +1,29 @@
1
- export * from './opencode-adapter.js';
2
- export * from './plugin.js';
1
+ /**
2
+ * `@skillstate/opencode` — the OpenCode v2 plugin package.
3
+ *
4
+ * The default export IS the plugin definition: OpenCode loads
5
+ * `opencode.json` → `"plugins": ["@skillstate/opencode"]`, imports this
6
+ * module and calls `setup(ctx)`. Everything else is exported for tests and
7
+ * for embedders that want the pieces without the plugin lifecycle.
8
+ *
9
+ * See `plugin.ts` for the design contract, in particular the rule that this
10
+ * package never mutates `event.messages`.
11
+ */
12
+ export { SkillStatePlugin, PLUGIN_ID, default } from './plugin.js';
13
+ /**
14
+ * The paper-exact `PlatformAdapter` (arXiv 2608.26263v3 A.4 prompt format).
15
+ * Kept as the research surface used by the benchmark; it is NOT the host
16
+ * integration and nothing in the plugin path calls it. In particular its
17
+ * `injectState` still emits the paper's `STATE_PATCH_CONTRACT`, which is
18
+ * exactly the instruction pattern the v2 plugin avoids.
19
+ */
20
+ export { OpenCodeAdapter } from './opencode-adapter.js';
21
+ export { SessionRegistry, stateScopeFor, DEFAULT_SESSION_TTL_MS, } from './session-registry.js';
22
+ export type { SessionRecord, SessionRegistryOptions } from './session-registry.js';
23
+ export { ProjectStateStore, diffDocuments, mergeDocuments, statePathFor, } from './state-store.js';
24
+ export type { StateChanges, StateDocument, ProjectStateStoreOptions, } from './state-store.js';
25
+ export { buildStateHint, renderStateForHint, ADVERTISED_TOOLS, MAX_INLINE_STATE_CHARS, } from './system-hint.js';
26
+ export type { StateHintOptions } from './system-hint.js';
27
+ export { registerTools, normalizePatch, MAX_PATCH_BYTES } from './tools.js';
28
+ export type { MergeValue, ReadValue, ToolDeps, ToolError, ToolOk, ToolResult, UpdateValue, } from './tools.js';
3
29
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACnE;;;;;;GAMG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,eAAe,EACf,aAAa,EACb,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,YAAY,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,YAAY,EACZ,aAAa,EACb,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC5E,YAAY,EACV,UAAU,EACV,SAAS,EACT,QAAQ,EACR,SAAS,EACT,MAAM,EACN,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,25 @@
1
- // @skillstate/opencode — OpenCode platform adapter.
2
- export * from './opencode-adapter.js';
3
- export * from './plugin.js';
1
+ /**
2
+ * `@skillstate/opencode` — the OpenCode v2 plugin package.
3
+ *
4
+ * The default export IS the plugin definition: OpenCode loads
5
+ * `opencode.json` → `"plugins": ["@skillstate/opencode"]`, imports this
6
+ * module and calls `setup(ctx)`. Everything else is exported for tests and
7
+ * for embedders that want the pieces without the plugin lifecycle.
8
+ *
9
+ * See `plugin.ts` for the design contract, in particular the rule that this
10
+ * package never mutates `event.messages`.
11
+ */
12
+ export { SkillStatePlugin, PLUGIN_ID, default } from './plugin.js';
13
+ /**
14
+ * The paper-exact `PlatformAdapter` (arXiv 2608.26263v3 A.4 prompt format).
15
+ * Kept as the research surface used by the benchmark; it is NOT the host
16
+ * integration and nothing in the plugin path calls it. In particular its
17
+ * `injectState` still emits the paper's `STATE_PATCH_CONTRACT`, which is
18
+ * exactly the instruction pattern the v2 plugin avoids.
19
+ */
20
+ export { OpenCodeAdapter } from './opencode-adapter.js';
21
+ export { SessionRegistry, stateScopeFor, DEFAULT_SESSION_TTL_MS, } from './session-registry.js';
22
+ export { ProjectStateStore, diffDocuments, mergeDocuments, statePathFor, } from './state-store.js';
23
+ export { buildStateHint, renderStateForHint, ADVERTISED_TOOLS, MAX_INLINE_STATE_CHARS, } from './system-hint.js';
24
+ export { registerTools, normalizePatch, MAX_PATCH_BYTES } from './tools.js';
4
25
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACnE;;;;;;GAMG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,eAAe,EACf,aAAa,EACb,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,YAAY,GACb,MAAM,kBAAkB,CAAC;AAM1B,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
@@ -4,21 +4,17 @@
4
4
  * Bridges the skillstate runtime into OpenCode via:
5
5
  * - Prompts formatted with the skillstate XML-style skill envelope
6
6
  * (delegates to PromptTransformer.formatForOpenCode).
7
- * - A generated SKILL.md so OpenCode discovers the skill and follows the
8
- * state-based execution process.
9
- * - A generated plugin that hooks `experimental.chat.messages.transform` for
10
- * real O(1) history trimming: old messages are dropped, only the last N
11
- * non-system messages plus injected state are sent to the LLM.
12
- * - `experimental.session.compacting` injects state into compaction context.
13
- * - `tool.execute.after` persists state updates from LLM responses.
7
+ *
8
+ * Host glue is NO LONGER GENERATED by this adapter:
9
+ * - the plugin is the npm package `@skillstate/opencode` itself, loaded
10
+ * directly from the project `opencode.json`
11
+ * `"plugin": ["@skillstate/opencode"]` (see `SkillStatePlugin` /
12
+ * `createSkillStatePlugin` in `src/plugin.ts` — project-local and inert
13
+ * when the project has no skillstate state);
14
+ * - skill markdown (SKILL.md) generation is host-neutral and lives in the
15
+ * CLI, not in the platform adapters.
14
16
  */
15
17
  import type { SkillState, StatePatch, ProceduralSpec, Observation, PlatformAdapter } from '@skillstate/core';
16
- import type { StatePathRef } from '@skillstate/core';
17
- /** Options for {@link OpenCodeAdapter.generatePluginCode}. */
18
- export interface GeneratePluginOptions {
19
- /** Non-system messages kept by the plugin (default 3). */
20
- maxHistoryMessages?: number;
21
- }
22
18
  /**
23
19
  * OpenCode platform adapter (@non-paper; see module doc).
24
20
  */
@@ -46,38 +42,5 @@ export declare class OpenCodeAdapter implements PlatformAdapter {
46
42
  * Paper-exact callers use `PromptTransformer.formatPaper` (Appendix A.4).
47
43
  */
48
44
  formatPrompt(state: SkillState, observation: Observation, spec: ProceduralSpec): string;
49
- /**
50
- * Generate a SKILL.md suitable for OpenCode's skill system.
51
- *
52
- * The frontmatter carries the skill name/description plus an
53
- * execution_context block pointing at the persisted state file; the body
54
- * describes the state-based execution process. History is discarded by
55
- * the plugin's `messages.transform` hook — the LLM sees only the state.
56
- */
57
- generateSkillMd(spec: ProceduralSpec, statePath?: string): string;
58
- /**
59
- * Generate an OpenCode plugin file.
60
- *
61
- * The plugin is ALWAYS a thin loader in per-project resolver mode: the
62
- * state path is computed from the session cwd on every hook call inside
63
- * the static plugin (`resolveStatePathForCwd(process.cwd(),
64
- * os.homedir())`), so each project gets its own
65
- * `<cwd>/.skillstate/skillstate.json` and a session opened anywhere
66
- * resolves the same state for the same project.
67
- *
68
- * Hooks (see `src/plugin.ts`): `experimental.chat.messages.transform`
69
- * (real O(1) history trimming, `{ info, parts }` entries, in-place
70
- * mutation), `experimental.session.compacting` (state into compaction
71
- * context), `tool.execute.after` (persist `state_patch` from
72
- * `output.output`).
73
- */
74
- generatePluginCode(options?: GeneratePluginOptions): string;
75
- /**
76
- * @non-paper additive helper: generate the plugin and persist it via
77
- * `atomicWriteFile` (tmp + fsync + rename). The destination accepts a raw
78
- * string or a `{ root, name }` ref confined by `resolveStatePath`.
79
- * Returns the absolute destination path.
80
- */
81
- savePluginCode(target: string | StatePathRef, options?: GeneratePluginOptions): Promise<string>;
82
45
  }
83
46
  //# sourceMappingURL=opencode-adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"opencode-adapter.d.ts","sourceRoot":"","sources":["../src/opencode-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,WAAW,EACX,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAS1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,8DAA8D;AAC9D,MAAM,WAAW,qBAAqB;IACpC,0DAA0D;IAC1D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,qBAAa,eAAgB,YAAW,eAAe;IACrD,QAAQ,CAAC,IAAI,cAAc;IAE3B,OAAO,CAAC,WAAW,CAAmD;IAEtE;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,GAAG,MAAM,CAe3D;IAED;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAEhD;IAED;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE7C;IAED;;;;;OAKG;IACH,YAAY,CACV,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,cAAc,GACnB,MAAM,CAER;IAED;;;;;;;OAOG;IACH,eAAe,CAAC,IAAI,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAWhE;IAED;;;;;;;;;;;;;;;OAeG;IACH,kBAAkB,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAa1D;IAED;;;;;OAKG;IACG,cAAc,CAClB,MAAM,EAAE,MAAM,GAAG,YAAY,EAC7B,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAOjB;CAKF"}
1
+ {"version":3,"file":"opencode-adapter.d.ts","sourceRoot":"","sources":["../src/opencode-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,WAAW,EACX,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAI1B;;GAEG;AACH,qBAAa,eAAgB,YAAW,eAAe;IACrD,QAAQ,CAAC,IAAI,cAAc;IAE3B,OAAO,CAAC,WAAW,CAAmD;IAEtE;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,GAAG,MAAM,CAe3D;IAED;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAEhD;IAED;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE7C;IAED;;;;;OAKG;IACH,YAAY,CACV,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,cAAc,GACnB,MAAM,CAER;CAOF"}
@@ -1,5 +1,5 @@
1
1
  import { PromptTransformer } from '@skillstate/core';
2
- import { atomicWriteFile, describeSchema, resolveStatePath, skillMdBody, STATE_PATCH_CONTRACT, } from '@skillstate/core';
2
+ import { describeSchema, STATE_PATCH_CONTRACT } from '@skillstate/core';
3
3
  /**
4
4
  * OpenCode platform adapter (@non-paper; see module doc).
5
5
  */
@@ -47,68 +47,5 @@ ${STATE_PATCH_CONTRACT}`;
47
47
  formatPrompt(state, observation, spec) {
48
48
  return this.transformer.formatForOpenCode(spec, state, observation);
49
49
  }
50
- /**
51
- * Generate a SKILL.md suitable for OpenCode's skill system.
52
- *
53
- * The frontmatter carries the skill name/description plus an
54
- * execution_context block pointing at the persisted state file; the body
55
- * describes the state-based execution process. History is discarded by
56
- * the plugin's `messages.transform` hook — the LLM sees only the state.
57
- */
58
- generateSkillMd(spec, statePath) {
59
- return skillMdBody({
60
- hostLabel: 'OpenCode',
61
- injectionPhrase: 'injected into the message list before every model call',
62
- hooks: {
63
- inject: 'messages.transform',
64
- reInject: 'session.compacting',
65
- },
66
- spec,
67
- statePath: statePath ?? './.skillstate/skillstate.json',
68
- });
69
- }
70
- /**
71
- * Generate an OpenCode plugin file.
72
- *
73
- * The plugin is ALWAYS a thin loader in per-project resolver mode: the
74
- * state path is computed from the session cwd on every hook call inside
75
- * the static plugin (`resolveStatePathForCwd(process.cwd(),
76
- * os.homedir())`), so each project gets its own
77
- * `<cwd>/.skillstate/skillstate.json` and a session opened anywhere
78
- * resolves the same state for the same project.
79
- *
80
- * Hooks (see `src/plugin.ts`): `experimental.chat.messages.transform`
81
- * (real O(1) history trimming, `{ info, parts }` entries, in-place
82
- * mutation), `experimental.session.compacting` (state into compaction
83
- * context), `tool.execute.after` (persist `state_patch` from
84
- * `output.output`).
85
- */
86
- generatePluginCode(options) {
87
- const maxHistory = options?.maxHistoryMessages ?? 3;
88
- return `// OpenCode plugin (thin loader) generated by skillstate.
89
- // Hook logic lives in the static plugin — the single source of truth —
90
- // shipped in the @skillstate/opencode package. PER-PROJECT state is
91
- // resolved from the session cwd on every hook call —
92
- // <cwd>/.skillstate/skillstate.json (global bucket when cwd === home).
93
- import { createSkillStatePlugin } from '@skillstate/opencode';
94
-
95
- export default createSkillStatePlugin({
96
- maxHistoryMessages: ${maxHistory},
97
- });
98
- `;
99
- }
100
- /**
101
- * @non-paper additive helper: generate the plugin and persist it via
102
- * `atomicWriteFile` (tmp + fsync + rename). The destination accepts a raw
103
- * string or a `{ root, name }` ref confined by `resolveStatePath`.
104
- * Returns the absolute destination path.
105
- */
106
- async savePluginCode(target, options) {
107
- const dest = typeof target === 'string'
108
- ? target
109
- : resolveStatePath(target.root, target.name);
110
- await atomicWriteFile(dest, this.generatePluginCode(options));
111
- return dest;
112
- }
113
50
  }
114
51
  //# sourceMappingURL=opencode-adapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"opencode-adapter.js","sourceRoot":"","sources":["../src/opencode-adapter.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EACL,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAS1B;;GAEG;AACH,MAAM,OAAO,eAAe;IACjB,IAAI,GAAG,UAAU,CAAC;IAEnB,WAAW,GAAG,IAAI,iBAAiB,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;IAEtE;;;;OAIG;IACH,WAAW,CAAC,KAAiB,EAAE,IAAoB;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE/C,OAAO,gBAAgB,IAAI,CAAC,EAAE;gBAClB,IAAI,CAAC,YAAY;EAC/B,UAAU;;EAEV,SAAS;;;;;;EAMT,oBAAoB,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,QAAgB;QAC3B,OAAO,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,QAAgB;QAC5B,OAAO,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC;IAED;;;;;OAKG;IACH,YAAY,CACV,KAAiB,EACjB,WAAwB,EACxB,IAAoB;QAEpB,OAAO,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;IACtE,CAAC;IAED;;;;;;;OAOG;IACH,eAAe,CAAC,IAAoB,EAAE,SAAkB;QACtD,OAAO,WAAW,CAAC;YACjB,SAAS,EAAE,UAAU;YACrB,eAAe,EAAE,wDAAwD;YACzE,KAAK,EAAE;gBACL,MAAM,EAAE,oBAAoB;gBAC5B,QAAQ,EAAE,oBAAoB;aAC/B;YACD,IAAI;YACJ,SAAS,EAAE,SAAS,IAAI,+BAA+B;SACxD,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,kBAAkB,CAAC,OAA+B;QAChD,MAAM,UAAU,GAAG,OAAO,EAAE,kBAAkB,IAAI,CAAC,CAAC;QACpD,OAAO;;;;;;;;wBAQa,UAAU;;CAEjC,CAAC;IACA,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,cAAc,CAClB,MAA6B,EAC7B,OAA+B;QAE/B,MAAM,IAAI,GACR,OAAO,MAAM,KAAK,QAAQ;YACxB,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;CAKF"}
1
+ {"version":3,"file":"opencode-adapter.js","sourceRoot":"","sources":["../src/opencode-adapter.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExE;;GAEG;AACH,MAAM,OAAO,eAAe;IACjB,IAAI,GAAG,UAAU,CAAC;IAEnB,WAAW,GAAG,IAAI,iBAAiB,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;IAEtE;;;;OAIG;IACH,WAAW,CAAC,KAAiB,EAAE,IAAoB;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE/C,OAAO,gBAAgB,IAAI,CAAC,EAAE;gBAClB,IAAI,CAAC,YAAY;EAC/B,UAAU;;EAEV,SAAS;;;;;;EAMT,oBAAoB,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,QAAgB;QAC3B,OAAO,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,QAAgB;QAC5B,OAAO,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC;IAED;;;;;OAKG;IACH,YAAY,CACV,KAAiB,EACjB,WAAwB,EACxB,IAAoB;QAEpB,OAAO,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;IACtE,CAAC;CAOF"}