@xemahq/opencode-xema-plugin 0.3.0 → 0.4.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.
Files changed (67) hide show
  1. package/README.md +33 -40
  2. package/dist/.source-stamp.json +2 -2
  3. package/dist/context.d.ts +5 -14
  4. package/dist/context.d.ts.map +1 -1
  5. package/dist/context.js +4 -13
  6. package/dist/context.js.map +1 -1
  7. package/dist/hooks/compaction-invariants.d.ts +8 -0
  8. package/dist/hooks/compaction-invariants.d.ts.map +1 -0
  9. package/dist/hooks/compaction-invariants.js +60 -0
  10. package/dist/hooks/compaction-invariants.js.map +1 -0
  11. package/dist/hooks/root-turn-completion.d.ts +14 -0
  12. package/dist/hooks/root-turn-completion.d.ts.map +1 -0
  13. package/dist/hooks/root-turn-completion.js +84 -0
  14. package/dist/hooks/root-turn-completion.js.map +1 -0
  15. package/dist/hooks/shell-env-hygiene.d.ts +6 -0
  16. package/dist/hooks/shell-env-hygiene.d.ts.map +1 -0
  17. package/dist/hooks/shell-env-hygiene.js +10 -0
  18. package/dist/hooks/shell-env-hygiene.js.map +1 -0
  19. package/dist/hooks/subagent-fanout-ceiling.d.ts +18 -17
  20. package/dist/hooks/subagent-fanout-ceiling.d.ts.map +1 -1
  21. package/dist/hooks/subagent-fanout-ceiling.js +106 -92
  22. package/dist/hooks/subagent-fanout-ceiling.js.map +1 -1
  23. package/dist/hooks/system-overlay.d.ts +6 -0
  24. package/dist/hooks/system-overlay.d.ts.map +1 -0
  25. package/dist/hooks/system-overlay.js +40 -0
  26. package/dist/hooks/system-overlay.js.map +1 -0
  27. package/dist/hooks/tool-surface-observation.d.ts +14 -0
  28. package/dist/hooks/tool-surface-observation.d.ts.map +1 -0
  29. package/dist/hooks/tool-surface-observation.js +30 -0
  30. package/dist/hooks/tool-surface-observation.js.map +1 -0
  31. package/dist/hooks/workspace-listing.js +3 -3
  32. package/dist/hooks/workspace-listing.js.map +1 -1
  33. package/dist/index.d.ts +9 -5
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +9 -70
  36. package/dist/index.js.map +1 -1
  37. package/dist/plugin-id.d.ts +2 -0
  38. package/dist/plugin-id.d.ts.map +1 -0
  39. package/dist/plugin-id.js +2 -0
  40. package/dist/plugin-id.js.map +1 -0
  41. package/dist/plugin.d.ts +4 -0
  42. package/dist/plugin.d.ts.map +1 -0
  43. package/dist/plugin.js +86 -0
  44. package/dist/plugin.js.map +1 -0
  45. package/dist/runtime-events.d.ts +17 -0
  46. package/dist/runtime-events.d.ts.map +1 -0
  47. package/dist/runtime-events.js +39 -0
  48. package/dist/runtime-events.js.map +1 -0
  49. package/package.json +12 -16
  50. package/{plugin.mjs → plugin/xema-runtime-bridge/index.js} +407 -415
  51. package/plugin/xema-runtime-bridge/package.json +8 -0
  52. package/dist/hooks/session-idle-autocommit.d.ts +0 -11
  53. package/dist/hooks/session-idle-autocommit.d.ts.map +0 -1
  54. package/dist/hooks/session-idle-autocommit.js +0 -206
  55. package/dist/hooks/session-idle-autocommit.js.map +0 -1
  56. package/dist/hooks/system-prompt-overlay.d.ts +0 -3
  57. package/dist/hooks/system-prompt-overlay.d.ts.map +0 -1
  58. package/dist/hooks/system-prompt-overlay.js +0 -30
  59. package/dist/hooks/system-prompt-overlay.js.map +0 -1
  60. package/dist/opencode-types.d.ts +0 -49
  61. package/dist/opencode-types.d.ts.map +0 -1
  62. package/dist/opencode-types.js +0 -2
  63. package/dist/opencode-types.js.map +0 -1
  64. package/dist/plugin-entry.d.ts +0 -2
  65. package/dist/plugin-entry.d.ts.map +0 -1
  66. package/dist/plugin-entry.js +0 -2
  67. package/dist/plugin-entry.js.map +0 -1
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  <path d="M26 12 L41 21 L41 39 L26 48 L11 39 L11 21 Z" fill="#8B5CF6"/>
7
7
  </g>
8
8
  <text x="92" y="52" font-family="ui-monospace,SFMono-Regular,Menlo,monospace" font-size="22" fill="#F8FAFC" font-weight="700">@xemahq/opencode-xema-plugin</text>
9
- <text x="92" y="80" font-family="ui-sans-serif,system-ui,sans-serif" font-size="15" fill="#94A3B8">Opencode plugin exposing Xema runtime tools and overlay hook</text>
9
+ <text x="92" y="80" font-family="ui-sans-serif,system-ui,sans-serif" font-size="15" fill="#94A3B8">OpenCode V2 runtime bridge plugin — hooks only</text>
10
10
  <text x="652" y="105" text-anchor="end" font-family="ui-sans-serif,system-ui,sans-serif" font-size="12" fill="#475569">xema.dev</text>
11
11
  </svg>
12
12
  </p>
@@ -24,68 +24,61 @@
24
24
 
25
25
  # @xemahq/opencode-xema-plugin
26
26
 
27
- > Opencode plugin exposing Xema runtime tools and overlay hook
27
+ > The `xema-runtime-bridge` OpenCode V2 plugin — hooks only, zero tools
28
28
 
29
29
  ## Overview
30
30
 
31
- An Opencode plugin that registers Xema-namespaced runtime tools, a dynamic
32
- system-prompt overlay hook, and the sub-agent fan-out ceiling. The plugin is
33
- evaluated once at agent startup; it registers its tools unconditionally and
34
- defers per-role authorization to tool-execution time, where each tool reads the
35
- invocation context from the worker filesystem and rejects calls the invoking
36
- role is not permitted to make.
31
+ Builds the OpenCode 2.0.20 directory plugin `xema-runtime-bridge`
32
+ (`plugin/xema-runtime-bridge/`, a `package.json` plus a self-contained
33
+ `index.js` whose default export is `{ id, setup }`). It contributes no
34
+ model-facing tools; everything it does is a hook:
35
+
36
+ - **System overlay** (`session.hook('context')`) — appends the platform
37
+ overlay and a live workspace listing to every model request, exactly once.
38
+ - **Compaction invariants** (`session.hook('compaction')`) — tells the
39
+ summarizer which invocation identifiers and deliverable constraints must
40
+ survive compaction, without replacing the summary.
41
+ - **Root-turn completion** — when a ROOT session's execution succeeds,
42
+ notifies workspace-proxy (which performs the auto-commit).
43
+ - **Sub-agent fan-out ceiling** — bounds how many sub-agent children run at
44
+ once in one worker.
45
+ - **Tool-surface observation** — records the tools OpenCode advertises.
46
+ - **Shell env hygiene** — removes the server password from agent shells.
37
47
 
38
48
  ## When to use it
39
49
 
40
- - Use it to add the Xema runtime tools and prompt overlay to an Opencode agent
41
- runtime.
42
- - Use it to bound how many sub-agents one worker may run at once.
50
+ - Use it in an OpenCode V2 agent runtime that serves Xema invocations.
51
+ - Use it to bound sub-agent width per worker.
43
52
 
44
53
  ## The sub-agent fan-out ceiling
45
54
 
46
- Opencode bounds how DEEP delegation may nest (`subagent_depth`). Nothing bounds
47
- how WIDE a turn may go, so at the platform's declared depth an unbounded
48
- branching factor is an unbounded process — every `task` call is forked with no
49
- pool, no semaphore and no queue.
50
-
51
- This plugin adds the missing pool cap. It is BACKPRESSURE, not a refusal: when
52
- the worker is already running its ceiling of sub-agents, the next `task` call
53
- WAITS for a slot instead of being denied. An agent that cannot spawn a helper
54
- would produce a wrong answer; one that waits produces a slower right one.
55
-
56
- Configuration exists to TIGHTEN, never to enable:
55
+ OpenCode bounds how DEEP delegation may nest. Nothing bounds how WIDE a turn
56
+ may go. This plugin adds a pool cap counted over CHILD SESSION LIFETIME: a slot
57
+ is reserved when the `subagent` tool is called and released when the child
58
+ session's execution ends (succeeded, failed or interrupted). It is
59
+ BACKPRESSURE, not a refusal: at the ceiling the next spawn waits.
57
60
 
58
61
  | | |
59
62
  |---|---|
60
- | Default | 8 concurrent `task` calls per worker |
63
+ | Default | 8 concurrent sub-agent children per worker |
61
64
  | Tighten with | `XEMA_SUBAGENT_FANOUT_LIMIT` (1..8) |
62
65
  | Unset or empty | the platform default — never zero, never "off" |
63
66
  | Above the default | refused at boot, with the reason |
64
67
 
65
- Every degradation is logged: a task that waits says so and for how long, and
66
- both leak backstops (a `session.idle` sweep and a per-permit TTL) name what they
67
- reclaimed. A ceiling that silently stops binding is indistinguishable from
68
- working software until somebody asks.
69
-
70
68
  ## Installation
71
69
 
72
- ```bash
73
- pnpm add @xemahq/opencode-xema-plugin
74
- ```
75
-
76
- ## Usage
77
-
78
- ```ts
79
- import XemaPlugin from '@xemahq/opencode-xema-plugin';
70
+ The runtime artifact is the directory `plugin/xema-runtime-bridge/` inside the
71
+ published tarball. Copy it into the worker image and enable it by path:
80
72
 
81
- // Register the plugin with your Opencode runtime configuration.
82
- export const plugins = [XemaPlugin];
73
+ ```jsonc
74
+ {
75
+ "plugins": [{ "package": "file:///opt/xema/opencode-plugins/xema-runtime-bridge" }]
76
+ }
83
77
  ```
84
78
 
85
79
  ## Peer requirements
86
80
 
87
- - `@opencode-ai/plugin` >=1.0.0
88
- - `zod` >=4
81
+ - `@opencode/plugin` 2.0.20 (types only)
89
82
 
90
83
  ## License
91
84
 
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "algorithm": "sha256/len-framed-v1",
3
- "hash": "91dded28129122882a0e5cd97ec25a1d294fd8f648c614ff68e6f520cd42e13f",
4
- "fileCount": 10
3
+ "hash": "c405e6f7436c100dcaa147a25cf104ea9c45c33b87d946a3670692b9e846bd41",
4
+ "fileCount": 14
5
5
  }
package/dist/context.d.ts CHANGED
@@ -23,6 +23,7 @@ declare const ContextJsonSchema: z.ZodObject<{
23
23
  "pipeline-run": "pipeline-run";
24
24
  "gate-review": "gate-review";
25
25
  }>>;
26
+ stageKey: z.ZodOptional<z.ZodNullable<z.ZodString>>;
26
27
  }, z.core.$strip>;
27
28
  project: z.ZodOptional<z.ZodNullable<z.ZodObject<{
28
29
  orgId: z.ZodString;
@@ -40,20 +41,10 @@ declare const ContextJsonSchema: z.ZodObject<{
40
41
  "full-write": "full-write";
41
42
  }>;
42
43
  }, z.core.$strip>;
43
- git: z.ZodOptional<z.ZodNullable<z.ZodObject<{
44
- autoCommit: z.ZodEnum<{
45
- enabled: "enabled";
46
- disabled: "disabled";
47
- }>;
48
- repoSubPath: z.ZodOptional<z.ZodNullable<z.ZodString>>;
49
- }, z.core.$strip>>>;
50
- actor: z.ZodOptional<z.ZodNullable<z.ZodObject<{
51
- kind: z.ZodEnum<{
52
- org_user: "org_user";
53
- }>;
54
- subjectRef: z.ZodString;
55
- displayName: z.ZodString;
56
- }, z.core.$strip>>>;
44
+ workingFiles: z.ZodOptional<z.ZodArray<z.ZodObject<{
45
+ slug: z.ZodString;
46
+ path: z.ZodString;
47
+ }, z.core.$loose>>>;
57
48
  }, z.core.$strip>;
58
49
  export type InvocationContext = z.infer<typeof ContextJsonSchema>;
59
50
  export type InvocationRole = InvocationContext['invocation']['role'];
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgGrB,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAClE,MAAM,MAAM,cAAc,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAUrE,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,GACnB,iBAAiB,GAAG,IAAI,CAQ1B;AAUD,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,iBAAiB,GAAG,IAAI,CAiB1B"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuErB,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAClE,MAAM,MAAM,cAAc,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AASrE,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,GACnB,iBAAiB,GAAG,IAAI,CAQ1B;AAUD,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,iBAAiB,GAAG,IAAI,CAiB1B"}
package/dist/context.js CHANGED
@@ -23,6 +23,7 @@ const ContextJsonSchema = z.object({
23
23
  surface: z
24
24
  .enum(['pipeline-run', 'agent-session', 'design-system-builder', 'gate-review'])
25
25
  .optional(),
26
+ stageKey: z.string().nullish(),
26
27
  }),
27
28
  project: z
28
29
  .object({
@@ -38,19 +39,9 @@ const ContextJsonSchema = z.object({
38
39
  mayEditRepos: z.boolean().default(false),
39
40
  writePolicy: z.enum(['read-only', 'own-pages-only', 'full-write']),
40
41
  }),
41
- git: z
42
- .object({
43
- autoCommit: z.enum(['enabled', 'disabled']),
44
- repoSubPath: z.string().nullish(),
45
- })
46
- .nullish(),
47
- actor: z
48
- .object({
49
- kind: z.enum(['org_user']),
50
- subjectRef: z.string().min(1),
51
- displayName: z.string().min(1),
52
- })
53
- .nullish(),
42
+ workingFiles: z
43
+ .array(z.object({ slug: z.string(), path: z.string() }).loose())
44
+ .optional(),
54
45
  });
55
46
  export function readInvocationContext(workspaceDir) {
56
47
  const path = join(workspaceDir, 'context.json');
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { SessionCompaction } from '@opencode/plugin/promise/session';
2
+ import { type InvocationContext } from '../context.js';
3
+ export type CompactionHookInput = Pick<SessionCompaction, 'sessionID' | 'system'>;
4
+ export declare const XEMA_COMPACTION_METADATA_KEY = "xema.compaction-invariants";
5
+ export declare const MAX_COMPACTION_INVARIANTS_CHARS = 2000;
6
+ export declare function buildCompactionInvariantsHook(directory: string): (input: CompactionHookInput) => void;
7
+ export declare function renderCompactionInvariants(ctx: InvocationContext): string;
8
+ //# sourceMappingURL=compaction-invariants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction-invariants.d.ts","sourceRoot":"","sources":["../../src/hooks/compaction-invariants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAE1E,OAAO,EAAgC,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AASrF,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,QAAQ,CAAC,CAAC;AAElF,eAAO,MAAM,4BAA4B,+BAA+B,CAAC;AAOzE,eAAO,MAAM,+BAA+B,OAAQ,CAAC;AAgCrD,wBAAgB,6BAA6B,CAAC,SAAS,EAAE,MAAM,IACrD,OAAO,mBAAmB,KAAG,IAAI,CAqB1C;AASD,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CA0BzE"}
@@ -0,0 +1,60 @@
1
+ import { readInvocationContextForHook } from '../context.js';
2
+ import { debug } from '../logger.js';
3
+ export const XEMA_COMPACTION_METADATA_KEY = 'xema.compaction-invariants';
4
+ export const MAX_COMPACTION_INVARIANTS_CHARS = 2_000;
5
+ const MAX_LISTED_ITEMS = 20;
6
+ export function buildCompactionInvariantsHook(directory) {
7
+ return (input) => {
8
+ const ctx = readInvocationContextForHook(directory, 'session.compaction');
9
+ if (!ctx) {
10
+ return;
11
+ }
12
+ const text = renderCompactionInvariants(ctx);
13
+ const part = {
14
+ type: 'text',
15
+ text,
16
+ metadata: { [XEMA_COMPACTION_METADATA_KEY]: true },
17
+ };
18
+ const existing = input.system.findIndex((entry) => entry.metadata?.[XEMA_COMPACTION_METADATA_KEY] === true);
19
+ if (existing === -1) {
20
+ input.system.push(part);
21
+ }
22
+ else {
23
+ input.system[existing] = part;
24
+ }
25
+ debug(`session.compaction: contributed ${text.length} chars of continuation invariants`);
26
+ };
27
+ }
28
+ function listed(items) {
29
+ const shown = items.slice(0, MAX_LISTED_ITEMS).join(', ');
30
+ const more = items.length - MAX_LISTED_ITEMS;
31
+ return more > 0 ? `${shown} (+${more} more)` : shown;
32
+ }
33
+ export function renderCompactionInvariants(ctx) {
34
+ const inv = ctx.invocation;
35
+ const lines = [
36
+ 'Xema continuation invariants. Preserve these facts verbatim in the summary ' +
37
+ '(under "## Additional Context"); they identify the invocation and its ' +
38
+ 'deliverable contract and must survive compaction. Do not invent anything ' +
39
+ 'beyond them.',
40
+ `- invocation: role=${inv.role}` +
41
+ (inv.surface ? `, surface=${inv.surface}` : '') +
42
+ (inv.runId ? `, runId=${inv.runId}` : '') +
43
+ (inv.stageKey ? `, stageKey=${inv.stageKey}` : '') +
44
+ (inv.sessionId ? `, sessionId=${inv.sessionId}` : '') +
45
+ `, attempt=${inv.attempt}`,
46
+ `- writePolicy: ${ctx.authority.writePolicy}`,
47
+ ];
48
+ if (ctx.authority.mayWriteSlugs.length > 0) {
49
+ lines.push(`- deliverable slugs: ${listed(ctx.authority.mayWriteSlugs)}`);
50
+ }
51
+ const files = ctx.workingFiles ?? [];
52
+ if (files.length > 0) {
53
+ lines.push(`- working files: ${listed(files.map((file) => `${file.slug} → ${file.path}`))}`);
54
+ }
55
+ const text = lines.join('\n');
56
+ return text.length > MAX_COMPACTION_INVARIANTS_CHARS
57
+ ? `${text.slice(0, MAX_COMPACTION_INVARIANTS_CHARS - 1)}…`
58
+ : text;
59
+ }
60
+ //# sourceMappingURL=compaction-invariants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction-invariants.js","sourceRoot":"","sources":["../../src/hooks/compaction-invariants.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { SessionExecutionOutcome } from '../runtime-events.js';
2
+ export declare const TURN_COMPLETED_PATH = "/runtime/turn-completed";
3
+ export declare const WORKSPACE_PROXY_URL_ENV = "WORKSPACE_PROXY_URL";
4
+ export declare const SERVER_PASSWORD_ENV = "OPENCODE_SERVER_PASSWORD";
5
+ export interface RootTurnCompletionOptions {
6
+ readonly resolveParentId: (runtimeSessionId: string) => Promise<string | undefined>;
7
+ readonly env?: Readonly<Record<string, string | undefined>>;
8
+ }
9
+ export interface RootTurnCompletion {
10
+ readonly onSessionCreated: (sessionId: string, parentId: string | undefined) => void;
11
+ readonly onSessionTerminal: (sessionId: string, outcome: SessionExecutionOutcome, executionId: string) => Promise<void>;
12
+ }
13
+ export declare function createRootTurnCompletion(options: RootTurnCompletionOptions): RootTurnCompletion;
14
+ //# sourceMappingURL=root-turn-completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-turn-completion.d.ts","sourceRoot":"","sources":["../../src/hooks/root-turn-completion.ts"],"names":[],"mappings":"AAgDA,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,eAAO,MAAM,mBAAmB,4BAA4B,CAAC;AAC7D,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAC7D,eAAO,MAAM,mBAAmB,6BAA6B,CAAC;AAI9D,MAAM,WAAW,yBAAyB;IAExC,QAAQ,CAAC,eAAe,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEpF,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACrF,QAAQ,CAAC,iBAAiB,EAAE,CAC1B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,uBAAuB,EAChC,WAAW,EAAE,MAAM,KAChB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,yBAAyB,GAAG,kBAAkB,CAqF/F"}
@@ -0,0 +1,84 @@
1
+ import { debug, warn } from '../logger.js';
2
+ import { SessionExecutionOutcome } from '../runtime-events.js';
3
+ const HOOK_NAME = 'turn-completed';
4
+ export const TURN_COMPLETED_PATH = '/runtime/turn-completed';
5
+ export const WORKSPACE_PROXY_URL_ENV = 'WORKSPACE_PROXY_URL';
6
+ export const SERVER_PASSWORD_ENV = 'OPENCODE_SERVER_PASSWORD';
7
+ const MAX_REMEMBERED_KEYS = 1_000;
8
+ export function createRootTurnCompletion(options) {
9
+ const parentBySession = new Map();
10
+ const delivered = new Set();
11
+ async function isRoot(sessionId) {
12
+ if (parentBySession.has(sessionId))
13
+ return parentBySession.get(sessionId) === undefined;
14
+ try {
15
+ const parent = await options.resolveParentId(sessionId);
16
+ parentBySession.set(sessionId, parent);
17
+ return parent === undefined;
18
+ }
19
+ catch (err) {
20
+ warn(`hook=${HOOK_NAME}: cannot tell whether session=${sessionId} is a root ` +
21
+ `(${err instanceof Error ? err.message : String(err)}); skipping rather than guessing.`);
22
+ return undefined;
23
+ }
24
+ }
25
+ function remember(key) {
26
+ delivered.add(key);
27
+ if (delivered.size > MAX_REMEMBERED_KEYS) {
28
+ const oldest = delivered.values().next().value;
29
+ if (oldest !== undefined)
30
+ delivered.delete(oldest);
31
+ }
32
+ }
33
+ async function onSessionTerminal(sessionId, outcome, executionId) {
34
+ try {
35
+ if (outcome !== SessionExecutionOutcome.Succeeded) {
36
+ debug(`hook=${HOOK_NAME}: session=${sessionId} ended ${outcome}; not a commit point`);
37
+ return;
38
+ }
39
+ const key = `${sessionId}:${executionId}`;
40
+ if (delivered.has(key)) {
41
+ debug(`hook=${HOOK_NAME}: ${key} already notified`);
42
+ return;
43
+ }
44
+ if ((await isRoot(sessionId)) !== true)
45
+ return;
46
+ const env = options.env ?? process.env;
47
+ const base = env[WORKSPACE_PROXY_URL_ENV];
48
+ const password = env[SERVER_PASSWORD_ENV];
49
+ if (!base || !password) {
50
+ warn(`hook=${HOOK_NAME}: ${!base ? WORKSPACE_PROXY_URL_ENV : SERVER_PASSWORD_ENV} is not set; ` +
51
+ `cannot notify workspace-proxy that session=${sessionId} completed a turn.`);
52
+ return;
53
+ }
54
+ const url = `${base.replace(/\/$/, '')}${TURN_COMPLETED_PATH}`;
55
+ const res = await fetch(url, {
56
+ method: 'POST',
57
+ headers: {
58
+ 'Content-Type': 'application/json',
59
+ Authorization: `Basic ${Buffer.from(`opencode:${password}`).toString('base64')}`,
60
+ 'Idempotency-Key': key,
61
+ },
62
+ body: JSON.stringify({ runtimeSessionId: sessionId, executionId, outcome }),
63
+ });
64
+ if (!res.ok) {
65
+ const text = await res.text().catch(() => '<unreadable body>');
66
+ warn(`hook=${HOOK_NAME}: POST ${url} responded ${res.status}: ${text.slice(0, 512)}`);
67
+ return;
68
+ }
69
+ remember(key);
70
+ debug(`hook=${HOOK_NAME}: notified ${key}`);
71
+ }
72
+ catch (err) {
73
+ warn(`hook=${HOOK_NAME}: unexpected error swallowed (best-effort): ` +
74
+ (err instanceof Error ? err.message : String(err)));
75
+ }
76
+ }
77
+ return {
78
+ onSessionCreated: (sessionId, parentId) => {
79
+ parentBySession.set(sessionId, parentId);
80
+ },
81
+ onSessionTerminal,
82
+ };
83
+ }
84
+ //# sourceMappingURL=root-turn-completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-turn-completion.js","sourceRoot":"","sources":["../../src/hooks/root-turn-completion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare const SERVER_PASSWORD_ENV_KEYS: readonly string[];
2
+ export interface ShellCreateBeforeInput {
3
+ env: Record<string, string | undefined>;
4
+ }
5
+ export declare function scrubShellEnv(input: ShellCreateBeforeInput): void;
6
+ //# sourceMappingURL=shell-env-hygiene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-env-hygiene.d.ts","sourceRoot":"","sources":["../../src/hooks/shell-env-hygiene.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAGpD,CAAC;AAEH,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CACzC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAIjE"}
@@ -0,0 +1,10 @@
1
+ export const SERVER_PASSWORD_ENV_KEYS = Object.freeze([
2
+ 'OPENCODE_PASSWORD',
3
+ 'OPENCODE_SERVER_PASSWORD',
4
+ ]);
5
+ export function scrubShellEnv(input) {
6
+ for (const key of SERVER_PASSWORD_ENV_KEYS) {
7
+ delete input.env[key];
8
+ }
9
+ }
10
+ //# sourceMappingURL=shell-env-hygiene.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-env-hygiene.js","sourceRoot":"","sources":["../../src/hooks/shell-env-hygiene.ts"],"names":[],"mappings":"AAiBA,MAAM,CAAC,MAAM,wBAAwB,GAAsB,MAAM,CAAC,MAAM,CAAC;IACvE,mBAAmB;IACnB,0BAA0B;CAC3B,CAAC,CAAC;AAMH,MAAM,UAAU,aAAa,CAAC,KAA6B;IACzD,KAAK,MAAM,GAAG,IAAI,wBAAwB,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -1,38 +1,39 @@
1
- export declare const TASK_TOOL_ID = "task";
1
+ export declare const SUBAGENT_TOOL_ID = "subagent";
2
2
  export declare const DEFAULT_SUBAGENT_FANOUT_LIMIT = 8;
3
3
  export declare const DEFAULT_FANOUT_WAIT_TIMEOUT_MS: number;
4
- export declare const DEFAULT_PERMIT_TTL_MS: number;
4
+ export declare const DEFAULT_ACTIVE_CHILD_TTL_MS: number;
5
+ export declare const DEFAULT_PENDING_SLOT_TTL_MS: number;
5
6
  export declare const FANOUT_LIMIT_ENV = "XEMA_SUBAGENT_FANOUT_LIMIT";
6
7
  export declare function resolveSubagentFanoutLimit(env?: Readonly<Record<string, string | undefined>>): number;
7
8
  export interface FanoutCeilingStats {
8
9
  readonly limit: number;
9
- readonly inFlight: number;
10
+ readonly pending: number;
11
+ readonly active: number;
10
12
  readonly waiting: number;
11
13
  readonly waitedCount: number;
12
14
  readonly timedOutCount: number;
13
- readonly sweptCount: number;
14
- readonly ttlReclaimedCount: number;
15
+ readonly pendingTtlReclaimedCount: number;
16
+ readonly activeTtlReclaimedCount: number;
15
17
  readonly armedTimers: number;
16
18
  }
19
+ export interface SubagentCallInput {
20
+ readonly tool: string;
21
+ readonly sessionID: string;
22
+ readonly id: string;
23
+ }
17
24
  export interface SubagentFanoutCeiling {
18
- readonly before: (input: {
19
- tool: string;
20
- sessionID: string;
21
- callID: string;
22
- }) => Promise<void>;
23
- readonly after: (input: {
24
- tool: string;
25
- sessionID: string;
26
- callID: string;
27
- }) => void;
28
- readonly onSessionIdle: (sessionId: string) => void;
25
+ readonly beforeToolCall: (input: SubagentCallInput) => Promise<void>;
26
+ readonly afterToolCall: (input: SubagentCallInput) => void;
27
+ readonly onSessionCreated: (sessionId: string, parentId: string | undefined) => void;
28
+ readonly onSessionTerminal: (sessionId: string) => void;
29
29
  readonly dispose: () => void;
30
30
  readonly stats: () => FanoutCeilingStats;
31
31
  }
32
32
  export interface FanoutCeilingOptions {
33
33
  readonly limit: number;
34
34
  readonly waitTimeoutMs?: number;
35
- readonly permitTtlMs?: number;
35
+ readonly pendingSlotTtlMs?: number;
36
+ readonly activeChildTtlMs?: number;
36
37
  readonly now?: () => number;
37
38
  }
38
39
  export declare function createSubagentFanoutCeiling(options: FanoutCeilingOptions): SubagentFanoutCeiling;
@@ -1 +1 @@
1
- {"version":3,"file":"subagent-fanout-ceiling.d.ts","sourceRoot":"","sources":["../../src/hooks/subagent-fanout-ceiling.ts"],"names":[],"mappings":"AA0FA,eAAO,MAAM,YAAY,SAAS,CAAC;AA6CnC,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAW/C,eAAO,MAAM,8BAA8B,QAAiB,CAAC;AAU7D,eAAO,MAAM,qBAAqB,QAAiB,CAAC;AAGpD,eAAO,MAAM,gBAAgB,+BAA+B,CAAC;AAyB7D,wBAAgB,0BAA0B,CACxC,GAAG,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAe,GAC9D,MAAM,CA8BR;AAoBD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IAiBnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,qBAAqB;IAEpC,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;QACvB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KAChB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpB,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE;QACtB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KAChB,KAAK,IAAI,CAAC;IAEX,QAAQ,CAAC,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAgBpD,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,kBAAkB,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAOD,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,oBAAoB,GAC5B,qBAAqB,CAgPvB"}
1
+ {"version":3,"file":"subagent-fanout-ceiling.d.ts","sourceRoot":"","sources":["../../src/hooks/subagent-fanout-ceiling.ts"],"names":[],"mappings":"AA+DA,eAAO,MAAM,gBAAgB,aAAa,CAAC;AA6C3C,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAW/C,eAAO,MAAM,8BAA8B,QAAiB,CAAC;AAU7D,eAAO,MAAM,2BAA2B,QAAiB,CAAC;AAU1D,eAAO,MAAM,2BAA2B,QAAgB,CAAC;AAGzD,eAAO,MAAM,gBAAgB,+BAA+B,CAAC;AAyB7D,wBAAgB,0BAA0B,CACxC,GAAG,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAe,GAC9D,MAAM,CA8BR;AA2BD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;IAC1C,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IAOzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IAEpC,QAAQ,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAErE,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAE3D,QAAQ,CAAC,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAErF,QAAQ,CAAC,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAExD,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,kBAAkB,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAEnC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAMD,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,oBAAoB,GAC5B,qBAAqB,CAyMvB"}