@skillstate/opencode 2.1.0 → 2.2.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/dist/plugin.d.ts +33 -9
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +75 -19
- package/dist/plugin.js.map +1 -1
- package/package.json +1 -1
package/dist/plugin.d.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { mergePatch, resolveHostStateForCwd } from '@skillstate/core';
|
|
2
|
-
import type { SkillStatePlugin } from './plugin-types.js';
|
|
2
|
+
import type { OpenCodeMessage, SkillStatePlugin } from './plugin-types.js';
|
|
3
3
|
export * from './plugin-types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Resolve the per-project state file for a session working directory
|
|
6
6
|
* (`cwd` of the current opencode session) — the core single source of
|
|
7
7
|
* truth (`resolveHostStateForCwd`): `<cwd>/.skillstate/skillstate.json`,
|
|
8
8
|
* or the global bucket `<home>/.skillstate/global/skillstate.json` when
|
|
9
|
-
* cwd equals home.
|
|
10
|
-
*
|
|
9
|
+
* cwd equals home. A non-empty `agentId` scopes the file under
|
|
10
|
+
* `<bucket>/agents/<agentId>/skillstate.json`. Pure path arithmetic via
|
|
11
|
+
* `path.resolve`, no filesystem access.
|
|
11
12
|
*/
|
|
12
13
|
export { resolveHostStateForCwd as resolveStatePathForCwd };
|
|
13
14
|
export { mergePatch };
|
|
15
|
+
/** Agent scope used by the plugin when no session id is available. */
|
|
16
|
+
export declare const PLUGIN_DEFAULT_AGENT_ID = "default";
|
|
14
17
|
/** Options for {@link createSkillStatePlugin}. */
|
|
15
18
|
export interface SkillStatePluginOptions {
|
|
16
19
|
/** Non-system messages kept in the prompt (default 3). */
|
|
@@ -26,11 +29,21 @@ export declare function readSkillState(statePath: string): Record<string, unknow
|
|
|
26
29
|
/**
|
|
27
30
|
* Persist the state file (best-effort: read-only environments are ignored).
|
|
28
31
|
* Creates the parent directory when missing (the per-project resolver may
|
|
29
|
-
* target a fresh `<cwd>/.skillstate
|
|
30
|
-
* envelope so `migrate()`/runtime resume read the
|
|
31
|
-
* hook-runtime {@link saveStateEnvelope}
|
|
32
|
+
* target a fresh `<cwd>/.skillstate/agents/<id>/`). Writes the
|
|
33
|
+
* `{ version: 1, state }` envelope so `migrate()`/runtime resume read the
|
|
34
|
+
* same file — via the core hook-runtime {@link saveStateEnvelope} — under
|
|
35
|
+
* the cross-process sync lock {@link lockStateWrite} (2-3 parallel agent
|
|
36
|
+
* processes never interleave state writes).
|
|
32
37
|
*/
|
|
33
38
|
export declare function saveSkillState(statePath: string, state: Record<string, unknown>): void;
|
|
39
|
+
/**
|
|
40
|
+
* Atomic READ-MERGE-WRITE of one `state_patch` (paper ⊕: null deletes):
|
|
41
|
+
* the whole critical section runs inside {@link lockStateWrite}, so two
|
|
42
|
+
* concurrent writers apply BOTH patches instead of racing between the
|
|
43
|
+
* read and the write. Best-effort: lock contention or unwritable state
|
|
44
|
+
* files are swallowed — the tool flow never breaks.
|
|
45
|
+
*/
|
|
46
|
+
export declare function mergeSkillState(statePath: string, patch: Record<string, unknown>): Record<string, unknown>;
|
|
34
47
|
/**
|
|
35
48
|
* Extract the `state_patch` object from an LLM response's fenced ```json
|
|
36
49
|
* block; `null` when there is no block, it is malformed, or it carries no
|
|
@@ -39,15 +52,26 @@ export declare function saveSkillState(statePath: string, state: Record<string,
|
|
|
39
52
|
* `null`, preserving the legacy boolean contract).
|
|
40
53
|
*/
|
|
41
54
|
export declare function extractPatch(response: string): Record<string, unknown> | null;
|
|
55
|
+
/**
|
|
56
|
+
* Agent id for an opencode hook call: the 8-char session prefix from
|
|
57
|
+
* `input.sessionID` when the hook carries it, else the first non-synthetic
|
|
58
|
+
* message's `info.sessionID` (the transform hook input is empty — the
|
|
59
|
+
* session lives on the message envelopes), else `'default'` (the plugin
|
|
60
|
+
* trims the history of one session context).
|
|
61
|
+
*/
|
|
62
|
+
export declare function pluginAgentId(input: {
|
|
63
|
+
sessionID?: unknown;
|
|
64
|
+
}, messages?: OpenCodeMessage[]): string;
|
|
42
65
|
/**
|
|
43
66
|
* Build the OpenCode plugin function with the same behavior for every host
|
|
44
67
|
* entry point (thin generated loaders, direct imports).
|
|
45
68
|
*
|
|
46
69
|
* State resolution is ALWAYS per-project: the state file path is computed
|
|
47
70
|
* from the session cwd on EVERY hook call via
|
|
48
|
-
* `resolveStatePathForCwd(process.cwd(), os.homedir())` — each
|
|
49
|
-
* its own `<cwd>/.skillstate
|
|
50
|
-
*
|
|
71
|
+
* `resolveStatePathForCwd(process.cwd(), os.homedir(), agentId)` — each
|
|
72
|
+
* project gets its own `<cwd>/.skillstate/`, each session (sub-agent) its
|
|
73
|
+
* isolated `agents/<session>/` copy, and a session launched from `$HOME`
|
|
74
|
+
* uses the global bucket.
|
|
51
75
|
*/
|
|
52
76
|
export declare function createSkillStatePlugin(options?: SkillStatePluginOptions): SkillStatePlugin;
|
|
53
77
|
//# sourceMappingURL=plugin.d.ts.map
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AA+BA,OAAO,EAGL,UAAU,EAGV,sBAAsB,EAEvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EACV,eAAe,EAEf,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAE3B,cAAc,mBAAmB,CAAC;AAElC;;;;;;;;GAQG;AACH,OAAO,EAAE,sBAAsB,IAAI,sBAAsB,EAAE,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,YAAY,CAAC;AAEjD,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACtC,0DAA0D;IAC1D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAWtF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYzB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAG7E;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,EAC9B,QAAQ,CAAC,EAAE,eAAe,EAAE,GAC3B,MAAM,CAWR;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,uBAA4B,GAAG,gBAAgB,CAiF9F"}
|
package/dist/plugin.js
CHANGED
|
@@ -16,22 +16,34 @@
|
|
|
16
16
|
* `output.context` so the compaction summary preserves it.
|
|
17
17
|
* - `tool.execute.after` — the tool response is `output.output`; a fenced
|
|
18
18
|
* ```json `state_patch` block is merged (paper ⊕: null deletes) and saved.
|
|
19
|
+
*
|
|
20
|
+
* AGENT-SCOPED STATE: the opencode hook inputs carry the session id
|
|
21
|
+
* (`input.sessionID`; message envelopes carry `info.sessionID`), so every
|
|
22
|
+
* hook scopes the state file to `<cwd>/.skillstate/agents/<session>/` —
|
|
23
|
+
* parallel opencode sessions (sub-agents) never last-writer-win over the
|
|
24
|
+
* main state. When no session id is available the `'default'` agent is
|
|
25
|
+
* used (the plugin trims the history of one session context). Writes go
|
|
26
|
+
* through the core cross-process sync lock (`lockStateWrite`) so a
|
|
27
|
+
* session state file is never interleaved between processes.
|
|
19
28
|
*/
|
|
20
29
|
import * as fs from 'node:fs';
|
|
21
30
|
import * as os from 'node:os';
|
|
22
31
|
import * as path from 'node:path';
|
|
23
|
-
import { findFencedPatch, mergePatch, readStateEnvelope, resolveHostStateForCwd, saveStateEnvelope, } from '@skillstate/core';
|
|
32
|
+
import { findFencedPatch, lockStateWrite, mergePatch, readStateEnvelope, resolveAgentIdFromSession, resolveHostStateForCwd, saveStateEnvelope, } from '@skillstate/core';
|
|
24
33
|
export * from './plugin-types.js';
|
|
25
34
|
/**
|
|
26
35
|
* Resolve the per-project state file for a session working directory
|
|
27
36
|
* (`cwd` of the current opencode session) — the core single source of
|
|
28
37
|
* truth (`resolveHostStateForCwd`): `<cwd>/.skillstate/skillstate.json`,
|
|
29
38
|
* or the global bucket `<home>/.skillstate/global/skillstate.json` when
|
|
30
|
-
* cwd equals home.
|
|
31
|
-
*
|
|
39
|
+
* cwd equals home. A non-empty `agentId` scopes the file under
|
|
40
|
+
* `<bucket>/agents/<agentId>/skillstate.json`. Pure path arithmetic via
|
|
41
|
+
* `path.resolve`, no filesystem access.
|
|
32
42
|
*/
|
|
33
43
|
export { resolveHostStateForCwd as resolveStatePathForCwd };
|
|
34
44
|
export { mergePatch };
|
|
45
|
+
/** Agent scope used by the plugin when no session id is available. */
|
|
46
|
+
export const PLUGIN_DEFAULT_AGENT_ID = 'default';
|
|
35
47
|
/**
|
|
36
48
|
* Read the state file. Missing or corrupt files yield `{}` (best-effort).
|
|
37
49
|
* The on-disk envelope is `{ version: 1, state }` (migrations-compatible);
|
|
@@ -44,19 +56,42 @@ export function readSkillState(statePath) {
|
|
|
44
56
|
/**
|
|
45
57
|
* Persist the state file (best-effort: read-only environments are ignored).
|
|
46
58
|
* Creates the parent directory when missing (the per-project resolver may
|
|
47
|
-
* target a fresh `<cwd>/.skillstate
|
|
48
|
-
* envelope so `migrate()`/runtime resume read the
|
|
49
|
-
* hook-runtime {@link saveStateEnvelope}
|
|
59
|
+
* target a fresh `<cwd>/.skillstate/agents/<id>/`). Writes the
|
|
60
|
+
* `{ version: 1, state }` envelope so `migrate()`/runtime resume read the
|
|
61
|
+
* same file — via the core hook-runtime {@link saveStateEnvelope} — under
|
|
62
|
+
* the cross-process sync lock {@link lockStateWrite} (2-3 parallel agent
|
|
63
|
+
* processes never interleave state writes).
|
|
50
64
|
*/
|
|
51
65
|
export function saveSkillState(statePath, state) {
|
|
52
66
|
try {
|
|
53
67
|
fs.mkdirSync(path.dirname(statePath), { recursive: true });
|
|
54
|
-
saveStateEnvelope(statePath, state, (p, data) => fs.writeFileSync(p, data));
|
|
68
|
+
lockStateWrite(statePath, fs, () => saveStateEnvelope(statePath, state, (p, data) => fs.writeFileSync(p, data)));
|
|
55
69
|
}
|
|
56
70
|
catch {
|
|
57
71
|
// Best-effort: read-only environments or permission issues.
|
|
58
72
|
}
|
|
59
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Atomic READ-MERGE-WRITE of one `state_patch` (paper ⊕: null deletes):
|
|
76
|
+
* the whole critical section runs inside {@link lockStateWrite}, so two
|
|
77
|
+
* concurrent writers apply BOTH patches instead of racing between the
|
|
78
|
+
* read and the write. Best-effort: lock contention or unwritable state
|
|
79
|
+
* files are swallowed — the tool flow never breaks.
|
|
80
|
+
*/
|
|
81
|
+
export function mergeSkillState(statePath, patch) {
|
|
82
|
+
try {
|
|
83
|
+
fs.mkdirSync(path.dirname(statePath), { recursive: true });
|
|
84
|
+
let merged = {};
|
|
85
|
+
lockStateWrite(statePath, fs, () => {
|
|
86
|
+
merged = mergePatch(readSkillState(statePath), patch);
|
|
87
|
+
saveStateEnvelope(statePath, merged, (p, data) => fs.writeFileSync(p, data));
|
|
88
|
+
});
|
|
89
|
+
return merged;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return readSkillState(statePath);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
60
95
|
/**
|
|
61
96
|
* Extract the `state_patch` object from an LLM response's fenced ```json
|
|
62
97
|
* block; `null` when there is no block, it is malformed, or it carries no
|
|
@@ -68,6 +103,23 @@ export function extractPatch(response) {
|
|
|
68
103
|
const result = findFencedPatch(response);
|
|
69
104
|
return 'patch' in result ? result.patch : null;
|
|
70
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Agent id for an opencode hook call: the 8-char session prefix from
|
|
108
|
+
* `input.sessionID` when the hook carries it, else the first non-synthetic
|
|
109
|
+
* message's `info.sessionID` (the transform hook input is empty — the
|
|
110
|
+
* session lives on the message envelopes), else `'default'` (the plugin
|
|
111
|
+
* trims the history of one session context).
|
|
112
|
+
*/
|
|
113
|
+
export function pluginAgentId(input, messages) {
|
|
114
|
+
const direct = resolveAgentIdFromSession(input?.sessionID);
|
|
115
|
+
if (direct.length > 0)
|
|
116
|
+
return direct;
|
|
117
|
+
const fromMessages = (messages ?? []).find((m) => typeof m.info?.sessionID === 'string' &&
|
|
118
|
+
m.info.sessionID.length > 0 &&
|
|
119
|
+
m.info.sessionID !== 'skillstate');
|
|
120
|
+
const indirect = resolveAgentIdFromSession(fromMessages?.info.sessionID);
|
|
121
|
+
return indirect.length > 0 ? indirect : PLUGIN_DEFAULT_AGENT_ID;
|
|
122
|
+
}
|
|
71
123
|
/** Synthetic message ids for the injected state carrier. */
|
|
72
124
|
const STATE_MESSAGE_ID = 'skillstate-state-inject';
|
|
73
125
|
/**
|
|
@@ -76,12 +128,13 @@ const STATE_MESSAGE_ID = 'skillstate-state-inject';
|
|
|
76
128
|
*
|
|
77
129
|
* State resolution is ALWAYS per-project: the state file path is computed
|
|
78
130
|
* from the session cwd on EVERY hook call via
|
|
79
|
-
* `resolveStatePathForCwd(process.cwd(), os.homedir())` — each
|
|
80
|
-
* its own `<cwd>/.skillstate
|
|
81
|
-
*
|
|
131
|
+
* `resolveStatePathForCwd(process.cwd(), os.homedir(), agentId)` — each
|
|
132
|
+
* project gets its own `<cwd>/.skillstate/`, each session (sub-agent) its
|
|
133
|
+
* isolated `agents/<session>/` copy, and a session launched from `$HOME`
|
|
134
|
+
* uses the global bucket.
|
|
82
135
|
*/
|
|
83
136
|
export function createSkillStatePlugin(options = {}) {
|
|
84
|
-
const resolvePath = () => resolveHostStateForCwd(process.cwd(), os.homedir());
|
|
137
|
+
const resolvePath = (agentId) => resolveHostStateForCwd(process.cwd(), os.homedir(), agentId);
|
|
85
138
|
const maxHistory = options.maxHistoryMessages ?? 3;
|
|
86
139
|
return async () => {
|
|
87
140
|
return {
|
|
@@ -90,8 +143,9 @@ export function createSkillStatePlugin(options = {}) {
|
|
|
90
143
|
// plus the last `maxHistory` non-system messages, then injects a
|
|
91
144
|
// synthetic state element. Old messages are DROPPED from the prompt,
|
|
92
145
|
// not just hidden.
|
|
93
|
-
'experimental.chat.messages.transform': async (
|
|
94
|
-
const
|
|
146
|
+
'experimental.chat.messages.transform': async (input, output) => {
|
|
147
|
+
const agentId = pluginAgentId(input, output.messages);
|
|
148
|
+
const state = readSkillState(resolvePath(agentId));
|
|
95
149
|
const messages = output.messages;
|
|
96
150
|
const systemMessages = messages.filter((m) => m.info.role === 'system');
|
|
97
151
|
const trimmed = messages
|
|
@@ -128,8 +182,9 @@ export function createSkillStatePlugin(options = {}) {
|
|
|
128
182
|
// ── Compaction context injection ───────────────────────────────────
|
|
129
183
|
// Before compaction, inject the current state into the context so the
|
|
130
184
|
// compaction summary preserves state even after history is compressed.
|
|
131
|
-
'experimental.session.compacting': async (
|
|
132
|
-
const
|
|
185
|
+
'experimental.session.compacting': async (input, output) => {
|
|
186
|
+
const agentId = pluginAgentId(input);
|
|
187
|
+
const state = readSkillState(resolvePath(agentId));
|
|
133
188
|
if (!Array.isArray(output.context)) {
|
|
134
189
|
output.context = [];
|
|
135
190
|
}
|
|
@@ -137,15 +192,16 @@ export function createSkillStatePlugin(options = {}) {
|
|
|
137
192
|
},
|
|
138
193
|
// ── State persistence from LLM responses ───────────────────────────
|
|
139
194
|
// After tool execution, extract state_patch from the tool response
|
|
140
|
-
// (output.output), merge it
|
|
141
|
-
|
|
195
|
+
// (output.output), and atomically merge it into the session-scoped
|
|
196
|
+
// state (read + merge + write all inside the cross-process lock).
|
|
197
|
+
'tool.execute.after': async (input, output) => {
|
|
142
198
|
const response = output.output ?? '';
|
|
143
199
|
if (typeof response !== 'string')
|
|
144
200
|
return;
|
|
145
|
-
const statePath = resolvePath();
|
|
146
201
|
const patch = extractPatch(response);
|
|
147
202
|
if (patch) {
|
|
148
|
-
|
|
203
|
+
const agentId = pluginAgentId(input);
|
|
204
|
+
mergeSkillState(resolvePath(agentId), patch);
|
|
149
205
|
}
|
|
150
206
|
},
|
|
151
207
|
};
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|