subharness 0.0.1

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 (168) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +158 -0
  3. package/dist/adapters/claude-auth.d.ts +7 -0
  4. package/dist/adapters/claude-auth.js +87 -0
  5. package/dist/adapters/claude-auth.js.map +1 -0
  6. package/dist/adapters/claude-config.d.ts +6 -0
  7. package/dist/adapters/claude-config.js +37 -0
  8. package/dist/adapters/claude-config.js.map +1 -0
  9. package/dist/adapters/claude-input.d.ts +9 -0
  10. package/dist/adapters/claude-input.js +32 -0
  11. package/dist/adapters/claude-input.js.map +1 -0
  12. package/dist/adapters/claude-permissions.d.ts +3 -0
  13. package/dist/adapters/claude-permissions.js +24 -0
  14. package/dist/adapters/claude-permissions.js.map +1 -0
  15. package/dist/adapters/claude-settings.d.ts +14 -0
  16. package/dist/adapters/claude-settings.js +43 -0
  17. package/dist/adapters/claude-settings.js.map +1 -0
  18. package/dist/adapters/claude-tools.d.ts +9 -0
  19. package/dist/adapters/claude-tools.js +47 -0
  20. package/dist/adapters/claude-tools.js.map +1 -0
  21. package/dist/adapters/claude.d.ts +22 -0
  22. package/dist/adapters/claude.js +295 -0
  23. package/dist/adapters/claude.js.map +1 -0
  24. package/dist/adapters/codex-config.d.ts +25 -0
  25. package/dist/adapters/codex-config.js +66 -0
  26. package/dist/adapters/codex-config.js.map +1 -0
  27. package/dist/adapters/codex.d.ts +2 -0
  28. package/dist/adapters/codex.js +238 -0
  29. package/dist/adapters/codex.js.map +1 -0
  30. package/dist/adapters/fx-auth.d.ts +4 -0
  31. package/dist/adapters/fx-auth.js +116 -0
  32. package/dist/adapters/fx-auth.js.map +1 -0
  33. package/dist/adapters/fx-rpc.d.ts +29 -0
  34. package/dist/adapters/fx-rpc.js +124 -0
  35. package/dist/adapters/fx-rpc.js.map +1 -0
  36. package/dist/adapters/fx-tools.d.ts +19 -0
  37. package/dist/adapters/fx-tools.js +119 -0
  38. package/dist/adapters/fx-tools.js.map +1 -0
  39. package/dist/adapters/fx.d.ts +3 -0
  40. package/dist/adapters/fx.js +302 -0
  41. package/dist/adapters/fx.js.map +1 -0
  42. package/dist/adapters/mcp-tool-content.d.ts +12 -0
  43. package/dist/adapters/mcp-tool-content.js +8 -0
  44. package/dist/adapters/mcp-tool-content.js.map +1 -0
  45. package/dist/adapters/rpc.d.ts +28 -0
  46. package/dist/adapters/rpc.js +101 -0
  47. package/dist/adapters/rpc.js.map +1 -0
  48. package/dist/adapters/types.d.ts +28 -0
  49. package/dist/adapters/types.js +2 -0
  50. package/dist/adapters/types.js.map +1 -0
  51. package/dist/cli/args.d.ts +18 -0
  52. package/dist/cli/args.js +118 -0
  53. package/dist/cli/args.js.map +1 -0
  54. package/dist/cli/catalog-worker.d.ts +1 -0
  55. package/dist/cli/catalog-worker.js +22 -0
  56. package/dist/cli/catalog-worker.js.map +1 -0
  57. package/dist/cli/catalog.d.ts +26 -0
  58. package/dist/cli/catalog.js +41 -0
  59. package/dist/cli/catalog.js.map +1 -0
  60. package/dist/cli/help.d.ts +3 -0
  61. package/dist/cli/help.js +68 -0
  62. package/dist/cli/help.js.map +1 -0
  63. package/dist/cli/input.d.ts +5 -0
  64. package/dist/cli/input.js +69 -0
  65. package/dist/cli/input.js.map +1 -0
  66. package/dist/cli/main.d.ts +2 -0
  67. package/dist/cli/main.js +105 -0
  68. package/dist/cli/main.js.map +1 -0
  69. package/dist/cli/output.d.ts +7 -0
  70. package/dist/cli/output.js +43 -0
  71. package/dist/cli/output.js.map +1 -0
  72. package/dist/config/access.d.ts +21 -0
  73. package/dist/config/access.js +97 -0
  74. package/dist/config/access.js.map +1 -0
  75. package/dist/config/loader.d.ts +13 -0
  76. package/dist/config/loader.js +80 -0
  77. package/dist/config/loader.js.map +1 -0
  78. package/dist/config/oidc.d.ts +1 -0
  79. package/dist/config/oidc.js +53 -0
  80. package/dist/config/oidc.js.map +1 -0
  81. package/dist/config/project.d.ts +5 -0
  82. package/dist/config/project.js +56 -0
  83. package/dist/config/project.js.map +1 -0
  84. package/dist/config/resolve-access.d.ts +4 -0
  85. package/dist/config/resolve-access.js +42 -0
  86. package/dist/config/resolve-access.js.map +1 -0
  87. package/dist/errors.d.ts +9 -0
  88. package/dist/errors.js +14 -0
  89. package/dist/errors.js.map +1 -0
  90. package/dist/index.d.ts +4 -0
  91. package/dist/index.js +3 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/runtime/client.d.ts +9 -0
  94. package/dist/runtime/client.js +91 -0
  95. package/dist/runtime/client.js.map +1 -0
  96. package/dist/runtime/coordinator.d.ts +61 -0
  97. package/dist/runtime/coordinator.js +296 -0
  98. package/dist/runtime/coordinator.js.map +1 -0
  99. package/dist/runtime/daemon.d.ts +1 -0
  100. package/dist/runtime/daemon.js +28 -0
  101. package/dist/runtime/daemon.js.map +1 -0
  102. package/dist/runtime/definition.d.ts +6 -0
  103. package/dist/runtime/definition.js +19 -0
  104. package/dist/runtime/definition.js.map +1 -0
  105. package/dist/runtime/native-owner.d.ts +8 -0
  106. package/dist/runtime/native-owner.js +25 -0
  107. package/dist/runtime/native-owner.js.map +1 -0
  108. package/dist/runtime/observation.d.ts +1 -0
  109. package/dist/runtime/observation.js +15 -0
  110. package/dist/runtime/observation.js.map +1 -0
  111. package/dist/runtime/select-native.d.ts +3 -0
  112. package/dist/runtime/select-native.js +34 -0
  113. package/dist/runtime/select-native.js.map +1 -0
  114. package/dist/runtime/service.d.ts +5 -0
  115. package/dist/runtime/service.js +90 -0
  116. package/dist/runtime/service.js.map +1 -0
  117. package/dist/runtime/session-launcher.d.ts +6 -0
  118. package/dist/runtime/session-launcher.js +29 -0
  119. package/dist/runtime/session-launcher.js.map +1 -0
  120. package/dist/runtime/state.d.ts +14 -0
  121. package/dist/runtime/state.js +69 -0
  122. package/dist/runtime/state.js.map +1 -0
  123. package/dist/runtime/types.d.ts +81 -0
  124. package/dist/runtime/types.js +2 -0
  125. package/dist/runtime/types.js.map +1 -0
  126. package/dist/runtime/worker-client.d.ts +3 -0
  127. package/dist/runtime/worker-client.js +81 -0
  128. package/dist/runtime/worker-client.js.map +1 -0
  129. package/dist/runtime/worker.d.ts +1 -0
  130. package/dist/runtime/worker.js +67 -0
  131. package/dist/runtime/worker.js.map +1 -0
  132. package/dist/sdk/definitions.d.ts +6 -0
  133. package/dist/sdk/definitions.js +72 -0
  134. package/dist/sdk/definitions.js.map +1 -0
  135. package/dist/sdk/tool-result.d.ts +23 -0
  136. package/dist/sdk/tool-result.js +95 -0
  137. package/dist/sdk/tool-result.js.map +1 -0
  138. package/dist/sdk/tools.d.ts +9 -0
  139. package/dist/sdk/tools.js +73 -0
  140. package/dist/sdk/tools.js.map +1 -0
  141. package/dist/sdk/types.d.ts +49 -0
  142. package/dist/sdk/types.js +2 -0
  143. package/dist/sdk/types.js.map +1 -0
  144. package/dist/sdk/validation.d.ts +5 -0
  145. package/dist/sdk/validation.js +20 -0
  146. package/dist/sdk/validation.js.map +1 -0
  147. package/dist/shell.d.ts +2 -0
  148. package/dist/shell.js +5 -0
  149. package/dist/shell.js.map +1 -0
  150. package/package.json +61 -0
  151. package/sdk/access-config.md +52 -0
  152. package/sdk/adapter-contract.md +33 -0
  153. package/sdk/agent.md +52 -0
  154. package/sdk/authentication.md +11 -0
  155. package/sdk/cli/index.md +67 -0
  156. package/sdk/cli/output.md +28 -0
  157. package/sdk/completion-notifications.md +29 -0
  158. package/sdk/config.md +41 -0
  159. package/sdk/distribution.md +31 -0
  160. package/sdk/fx.md +71 -0
  161. package/sdk/harnesses.md +32 -0
  162. package/sdk/index.md +22 -0
  163. package/sdk/message-delivery.md +39 -0
  164. package/sdk/plugins/sub-agents.md +57 -0
  165. package/sdk/project-team.md +57 -0
  166. package/sdk/sessions.md +31 -0
  167. package/sdk/tools.md +73 -0
  168. package/sdk/v1-runtime.md +63 -0
@@ -0,0 +1,101 @@
1
+ import { spawn } from "node:child_process";
2
+ import { AgentError } from "../errors.js";
3
+ /** A bidirectional JSON-lines connection to an external native process. */
4
+ export class NativeRpc {
5
+ process;
6
+ pending = new Map();
7
+ sequence = 0;
8
+ buffer = "";
9
+ failure;
10
+ exited;
11
+ onMessage = () => { };
12
+ onFailure = () => { };
13
+ constructor(command, args, cwd, env) {
14
+ this.process = spawn(command, args, { cwd, env, stdio: ["pipe", "pipe", "pipe"] });
15
+ this.process.stdout.setEncoding("utf8");
16
+ this.process.stdout.on("data", chunk => this.read(chunk));
17
+ this.process.stderr.resume(); // Native diagnostics can contain credentials; never forward them.
18
+ this.process.stdin.on("error", () => this.fail(new AgentError("HARNESS_FAILED", "Codex input connection closed.")));
19
+ this.process.on("error", () => this.fail(new AgentError("HARNESS_UNAVAILABLE", "Cannot start Codex. Install its native CLI and make codex available on PATH.")));
20
+ this.exited = new Promise(resolve => this.process.once("close", () => {
21
+ this.fail(new AgentError("HARNESS_FAILED", "Codex exited before the operation completed."));
22
+ resolve();
23
+ }));
24
+ }
25
+ request(method, params) {
26
+ if (this.failure)
27
+ return Promise.reject(this.failure);
28
+ const id = ++this.sequence;
29
+ return new Promise((resolve, reject) => {
30
+ this.pending.set(id, { resolve, reject, method });
31
+ this.send({ id, method, params });
32
+ });
33
+ }
34
+ send(message) {
35
+ if (this.failure)
36
+ throw this.failure;
37
+ this.process.stdin.write(`${JSON.stringify(message)}\n`);
38
+ }
39
+ abort(error) {
40
+ this.fail(error);
41
+ void this.close();
42
+ }
43
+ async close() {
44
+ if (this.process.exitCode !== null || this.process.signalCode !== null)
45
+ return this.exited;
46
+ this.process.kill("SIGTERM");
47
+ const timer = setTimeout(() => this.process.kill("SIGKILL"), 2_000);
48
+ timer.unref();
49
+ await this.exited;
50
+ clearTimeout(timer);
51
+ }
52
+ read(chunk) {
53
+ this.buffer += chunk;
54
+ if (this.buffer.length > 16 * 1024 * 1024)
55
+ return this.invalid();
56
+ let newline;
57
+ while ((newline = this.buffer.indexOf("\n")) >= 0) {
58
+ const line = this.buffer.slice(0, newline);
59
+ this.buffer = this.buffer.slice(newline + 1);
60
+ if (!line.trim())
61
+ continue;
62
+ let message;
63
+ try {
64
+ message = JSON.parse(line);
65
+ }
66
+ catch {
67
+ return this.invalid();
68
+ }
69
+ if (!message || typeof message !== "object" || Array.isArray(message))
70
+ return this.invalid();
71
+ if (message.method)
72
+ this.onMessage(message);
73
+ else if (typeof message.id === "number") {
74
+ const pending = this.pending.get(message.id);
75
+ if (!pending)
76
+ continue;
77
+ this.pending.delete(message.id);
78
+ if (message.error) {
79
+ const unsupported = pending.method === "turn/steer" && message.error.code === -32601;
80
+ pending.reject(new AgentError(unsupported ? "UNSUPPORTED_DELIVERY" : "NATIVE_ERROR", unsupported ? "This Codex version does not support native steering." : `Codex rejected ${pending.method}. Check the native harness configuration.`));
81
+ }
82
+ else
83
+ pending.resolve(message.result);
84
+ }
85
+ }
86
+ }
87
+ invalid() {
88
+ this.fail(new AgentError("PROTOCOL_ERROR", "Codex returned invalid protocol data."));
89
+ void this.close();
90
+ }
91
+ fail(error) {
92
+ if (this.failure)
93
+ return;
94
+ this.failure = error;
95
+ for (const pending of this.pending.values())
96
+ pending.reject(error);
97
+ this.pending.clear();
98
+ this.onFailure(error);
99
+ }
100
+ }
101
+ //# sourceMappingURL=rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../src/adapters/rpc.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, type ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { AgentError } from \"../errors.js\";\n\ntype Envelope = { id?: string | number; method?: string; params?: any; result?: any; error?: unknown };\ntype Pending = { resolve(value: any): void; reject(error: Error): void; method: string };\n\n/** A bidirectional JSON-lines connection to an external native process. */\nexport class NativeRpc {\n private readonly process: ChildProcessWithoutNullStreams;\n private readonly pending = new Map<number, Pending>();\n private sequence = 0;\n private buffer = \"\";\n private failure?: AgentError;\n private readonly exited: Promise<void>;\n onMessage: (message: Envelope) => void = () => {};\n onFailure: (error: AgentError) => void = () => {};\n\n constructor(command: string, args: string[], cwd: string, env: NodeJS.ProcessEnv) {\n this.process = spawn(command, args, { cwd, env, stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n this.process.stdout.setEncoding(\"utf8\");\n this.process.stdout.on(\"data\", chunk => this.read(chunk));\n this.process.stderr.resume(); // Native diagnostics can contain credentials; never forward them.\n this.process.stdin.on(\"error\", () => this.fail(new AgentError(\"HARNESS_FAILED\", \"Codex input connection closed.\")));\n this.process.on(\"error\", () => this.fail(new AgentError(\"HARNESS_UNAVAILABLE\", \"Cannot start Codex. Install its native CLI and make codex available on PATH.\")));\n this.exited = new Promise(resolve => this.process.once(\"close\", () => {\n this.fail(new AgentError(\"HARNESS_FAILED\", \"Codex exited before the operation completed.\"));\n resolve();\n }));\n }\n\n request(method: string, params: unknown): Promise<any> {\n if (this.failure) return Promise.reject(this.failure);\n const id = ++this.sequence;\n return new Promise((resolve, reject) => {\n this.pending.set(id, { resolve, reject, method });\n this.send({ id, method, params });\n });\n }\n\n send(message: Envelope): void {\n if (this.failure) throw this.failure;\n this.process.stdin.write(`${JSON.stringify(message)}\\n`);\n }\n\n abort(error: AgentError): void {\n this.fail(error);\n void this.close();\n }\n\n async close(): Promise<void> {\n if (this.process.exitCode !== null || this.process.signalCode !== null) return this.exited;\n this.process.kill(\"SIGTERM\");\n const timer = setTimeout(() => this.process.kill(\"SIGKILL\"), 2_000);\n timer.unref();\n await this.exited;\n clearTimeout(timer);\n }\n\n private read(chunk: string): void {\n this.buffer += chunk;\n if (this.buffer.length > 16 * 1024 * 1024) return this.invalid();\n let newline: number;\n while ((newline = this.buffer.indexOf(\"\\n\")) >= 0) {\n const line = this.buffer.slice(0, newline);\n this.buffer = this.buffer.slice(newline + 1);\n if (!line.trim()) continue;\n let message: Envelope;\n try { message = JSON.parse(line); } catch { return this.invalid(); }\n if (!message || typeof message !== \"object\" || Array.isArray(message)) return this.invalid();\n if (message.method) this.onMessage(message);\n else if (typeof message.id === \"number\") {\n const pending = this.pending.get(message.id);\n if (!pending) continue;\n this.pending.delete(message.id);\n if (message.error) {\n const unsupported = pending.method === \"turn/steer\" && (message.error as { code?: number }).code === -32601;\n pending.reject(new AgentError(unsupported ? \"UNSUPPORTED_DELIVERY\" : \"NATIVE_ERROR\", unsupported ? \"This Codex version does not support native steering.\" : `Codex rejected ${pending.method}. Check the native harness configuration.`));\n }\n else pending.resolve(message.result);\n }\n }\n }\n\n private invalid(): void {\n this.fail(new AgentError(\"PROTOCOL_ERROR\", \"Codex returned invalid protocol data.\"));\n void this.close();\n }\n\n private fail(error: AgentError): void {\n if (this.failure) return;\n this.failure = error;\n for (const pending of this.pending.values()) pending.reject(error);\n this.pending.clear();\n this.onFailure(error);\n }\n}\n"]}
@@ -0,0 +1,28 @@
1
+ import type { AgentDefinition, HarnessConfig } from "../sdk/types.js";
2
+ export type HarnessRequest = HarnessConfig extends infer Config ? Config extends HarnessConfig ? Omit<Config, "model"> & {
3
+ readonly model?: Config["model"];
4
+ } : never : never;
5
+ export type ExecutionDefinition = Omit<AgentDefinition, "harness"> & {
6
+ readonly harness: HarnessRequest | readonly HarnessRequest[];
7
+ };
8
+ export type AccessType = "subscription" | "api-key" | "vercel-api-key" | "vercel-oidc";
9
+ export interface ResolvedAccess {
10
+ type: AccessType;
11
+ token?: string;
12
+ }
13
+ export interface AdapterOptions {
14
+ agent: ExecutionDefinition;
15
+ harness: HarnessRequest;
16
+ cwd: string;
17
+ env: NodeJS.ProcessEnv;
18
+ access: ResolvedAccess;
19
+ }
20
+ /** A native conversation. The external harness owns its reasoning and tool loop. */
21
+ export interface NativeSession {
22
+ turn(prompt: string): Promise<string>;
23
+ steer(prompt: string): Promise<void>;
24
+ /** Resolves only once active execution has stopped. */
25
+ interrupt(): Promise<void>;
26
+ resume(): Promise<string>;
27
+ close(): Promise<void>;
28
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentDefinition, HarnessConfig } from \"../sdk/types.js\";\n\nexport type HarnessRequest = HarnessConfig extends infer Config\n ? Config extends HarnessConfig\n ? Omit<Config, \"model\"> & { readonly model?: Config[\"model\"] }\n : never\n : never;\n\nexport type ExecutionDefinition = Omit<AgentDefinition, \"harness\"> & {\n readonly harness: HarnessRequest | readonly HarnessRequest[];\n};\n\nexport type AccessType = \"subscription\" | \"api-key\" | \"vercel-api-key\" | \"vercel-oidc\";\n\nexport interface ResolvedAccess {\n type: AccessType;\n token?: string;\n}\n\nexport interface AdapterOptions {\n agent: ExecutionDefinition;\n harness: HarnessRequest;\n cwd: string;\n env: NodeJS.ProcessEnv;\n access: ResolvedAccess;\n}\n\n/** A native conversation. The external harness owns its reasoning and tool loop. */\nexport interface NativeSession {\n turn(prompt: string): Promise<string>;\n steer(prompt: string): Promise<void>;\n /** Resolves only once active execution has stopped. */\n interrupt(): Promise<void>;\n resume(): Promise<string>;\n close(): Promise<void>;\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import { type PromptStream } from './input.js';
2
+ export type Command = 'list' | 'run' | 'send' | 'wait' | 'status' | 'queue' | 'cancel' | 'resume' | 'help' | 'version';
3
+ export interface Arguments {
4
+ command: Command;
5
+ id?: string;
6
+ cwd: string;
7
+ prompt?: string;
8
+ after?: string;
9
+ delivery: 'queue' | 'steer' | 'interrupt';
10
+ format: 'text' | 'jsonl';
11
+ full: boolean;
12
+ harness?: 'codex' | 'claudeCode' | 'fx';
13
+ model?: string;
14
+ effort?: string;
15
+ }
16
+ export declare function parseArgs(argv: string[], cwd?: string, dependencies?: {
17
+ stdin?: PromptStream;
18
+ }): Promise<Arguments>;
@@ -0,0 +1,118 @@
1
+ import { resolve } from 'node:path';
2
+ import { AgentError } from '../errors.js';
3
+ import { MAX_PROMPT_BYTES, readPromptInput } from './input.js';
4
+ const options = {
5
+ list: ['cwd'], run: ['cwd', 'prompt', 'prompt-file', 'model', 'effort'], send: ['delivery', 'prompt', 'prompt-file'],
6
+ wait: ['after'], status: ['full'], queue: [], cancel: [], resume: [],
7
+ };
8
+ const directTargets = { codex: 'codex', claude: 'claudeCode', fx: 'fx' };
9
+ const claudeEfforts = new Set(['low', 'medium', 'high', 'xhigh', 'max']);
10
+ const fail = (message) => { throw new AgentError('INVALID_ARGUMENT', message); };
11
+ export async function parseArgs(argv, cwd = process.cwd(), dependencies = {}) {
12
+ if (!argv.length)
13
+ return defaults('help', cwd);
14
+ if (argv[0] === '--help' || argv[0] === '--version') {
15
+ if (argv.length !== 1)
16
+ fail(`${argv[0]} cannot be combined with other options.`);
17
+ return defaults(argv[0] === '--help' ? 'help' : 'version', cwd);
18
+ }
19
+ const command = argv[0];
20
+ if (!Object.hasOwn(options, command))
21
+ fail(`Unknown command: ${command}. Use subharness --help.`);
22
+ const values = {};
23
+ const positionals = [];
24
+ let parseOptions = true;
25
+ for (let i = 1; i < argv.length; i++) {
26
+ const argument = argv[i];
27
+ if (parseOptions && argument === '--') {
28
+ parseOptions = false;
29
+ continue;
30
+ }
31
+ if (!parseOptions || !argument.startsWith('--')) {
32
+ positionals.push(argument);
33
+ continue;
34
+ }
35
+ const name = argument.slice(2);
36
+ if (name !== 'format' && name !== 'help' && !options[command].includes(name))
37
+ fail(`Unknown option: ${argument}`);
38
+ if (name in values)
39
+ fail(`Duplicate option: ${argument}`);
40
+ if (name === 'full' || name === 'help')
41
+ values[name] = true;
42
+ else {
43
+ const value = argv[++i];
44
+ if (value === undefined || (name !== 'prompt' && value.startsWith('--')))
45
+ fail(`Missing value for ${argument}`);
46
+ values[name] = value;
47
+ }
48
+ }
49
+ if (values.help === true) {
50
+ if (Object.keys(values).some(name => name !== 'help'))
51
+ fail('--help cannot be combined with other options.');
52
+ const target = command === 'run' && positionals[0] && Object.hasOwn(directTargets, positionals[0])
53
+ ? directTargets[positionals[0]] : undefined;
54
+ return { ...defaults('help', cwd), ...(target ? { id: positionals[0], harness: target } : {}) };
55
+ }
56
+ const promptCommand = command === 'run' || command === 'send';
57
+ const identifierCount = command === 'list' ? 0 : 1;
58
+ if (positionals.length < identifierCount)
59
+ fail(`Expected ${identifierCount ? 'one identifier' : 'no identifier'} for ${command}.`);
60
+ if (!promptCommand && positionals.length !== identifierCount)
61
+ fail(`Expected ${identifierCount ? 'one identifier' : 'no identifier'} for ${command}.`);
62
+ if (promptCommand && positionals.length > 2)
63
+ fail(`Expected one positional prompt for ${command}.`);
64
+ const format = values.format ?? 'text';
65
+ if (format !== 'text' && format !== 'jsonl')
66
+ fail('Format must be text or jsonl.');
67
+ const delivery = values.delivery ?? 'queue';
68
+ if (!['queue', 'steer', 'interrupt'].includes(String(delivery)))
69
+ fail('Delivery must be queue, steer, or interrupt.');
70
+ const result = { ...defaults(command, cwd), id: positionals[0], format, delivery,
71
+ cwd: resolve(cwd, String(values.cwd ?? '.')), full: values.full === true };
72
+ if (command === 'run') {
73
+ const direct = Object.hasOwn(directTargets, result.id)
74
+ ? directTargets[result.id] : undefined;
75
+ if (direct)
76
+ result.harness = direct;
77
+ if ('model' in values || 'effort' in values) {
78
+ if (!direct)
79
+ fail('--model and --effort are available only for direct harness targets.');
80
+ if ('model' in values && !String(values.model).trim())
81
+ fail('Model must contain text.');
82
+ if ('effort' in values && !String(values.effort).trim())
83
+ fail('Effort must contain text.');
84
+ if (direct === 'claudeCode' && 'effort' in values && !claudeEfforts.has(String(values.effort))) {
85
+ fail('Claude effort must be low, medium, high, xhigh, or max.');
86
+ }
87
+ if ('model' in values)
88
+ result.model = String(values.model);
89
+ if ('effort' in values)
90
+ result.effort = String(values.effort);
91
+ }
92
+ }
93
+ if (command === 'run' || command === 'send') {
94
+ const positionalPrompt = positionals[1];
95
+ if (Number(positionalPrompt !== undefined) + Number('prompt' in values) + Number('prompt-file' in values) !== 1) {
96
+ fail('Supply exactly one prompt source: one positional prompt, --prompt, or --prompt-file.');
97
+ }
98
+ if ('prompt-file' in values) {
99
+ result.prompt = await readPromptInput(String(values['prompt-file']), cwd, dependencies.stdin);
100
+ }
101
+ else
102
+ result.prompt = positionalPrompt ?? String(values.prompt);
103
+ if (!result.prompt?.trim())
104
+ fail('Prompt must contain text.');
105
+ if (Buffer.byteLength(result.prompt) > MAX_PROMPT_BYTES)
106
+ fail('Prompt exceeds 1 MiB.');
107
+ }
108
+ if (command === 'wait') {
109
+ if (!values.after)
110
+ fail('wait requires --after <response-id>.');
111
+ result.after = String(values.after);
112
+ }
113
+ return result;
114
+ }
115
+ function defaults(command, cwd) {
116
+ return { command, cwd, delivery: 'queue', format: 'text', full: false };
117
+ }
118
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolve } from 'node:path';\nimport { AgentError } from '../errors.js';\nimport { MAX_PROMPT_BYTES, readPromptInput, type PromptStream } from './input.js';\n\nexport type Command = 'list' | 'run' | 'send' | 'wait' | 'status' | 'queue' | 'cancel' | 'resume' | 'help' | 'version';\nexport interface Arguments {\n command: Command; id?: string; cwd: string; prompt?: string; after?: string;\n delivery: 'queue' | 'steer' | 'interrupt'; format: 'text' | 'jsonl'; full: boolean;\n harness?: 'codex' | 'claudeCode' | 'fx'; model?: string; effort?: string;\n}\nconst options: Record<string, string[]> = {\n list: ['cwd'], run: ['cwd','prompt','prompt-file','model','effort'], send: ['delivery','prompt','prompt-file'],\n wait: ['after'], status: ['full'], queue: [], cancel: [], resume: [],\n};\nconst directTargets = {codex:'codex',claude:'claudeCode',fx:'fx'} as const;\nconst claudeEfforts = new Set(['low','medium','high','xhigh','max']);\nconst fail = (message: string): never => { throw new AgentError('INVALID_ARGUMENT', message); };\n\nexport async function parseArgs(\n argv: string[], cwd = process.cwd(), dependencies: {stdin?: PromptStream} = {},\n): Promise<Arguments> {\n if (!argv.length) return defaults('help', cwd);\n if (argv[0] === '--help' || argv[0] === '--version') {\n if (argv.length !== 1) fail(`${argv[0]} cannot be combined with other options.`);\n return defaults(argv[0] === '--help' ? 'help' : 'version', cwd);\n }\n const command = argv[0]!;\n if (!Object.hasOwn(options, command)) fail(`Unknown command: ${command}. Use subharness --help.`);\n const values: Record<string, string | boolean> = {};\n const positionals: string[] = [];\n let parseOptions = true;\n for (let i = 1; i < argv.length; i++) {\n const argument = argv[i]!;\n if (parseOptions && argument === '--') { parseOptions = false; continue; }\n if (!parseOptions || !argument.startsWith('--')) { positionals.push(argument); continue; }\n const name = argument.slice(2);\n if (name !== 'format' && name !== 'help' && !options[command]!.includes(name)) fail(`Unknown option: ${argument}`);\n if (name in values) fail(`Duplicate option: ${argument}`);\n if (name === 'full' || name === 'help') values[name] = true;\n else {\n const value = argv[++i];\n if (value === undefined || (name !== 'prompt' && value.startsWith('--'))) fail(`Missing value for ${argument}`);\n values[name] = value!;\n }\n }\n if (values.help === true) {\n if (Object.keys(values).some(name => name !== 'help')) fail('--help cannot be combined with other options.');\n const target = command === 'run' && positionals[0] && Object.hasOwn(directTargets, positionals[0])\n ? directTargets[positionals[0] as keyof typeof directTargets] : undefined;\n return {...defaults('help', cwd), ...(target ? {id: positionals[0], harness: target} : {})};\n }\n const promptCommand = command === 'run' || command === 'send';\n const identifierCount = command === 'list' ? 0 : 1;\n if (positionals.length < identifierCount) fail(`Expected ${identifierCount ? 'one identifier' : 'no identifier'} for ${command}.`);\n if (!promptCommand && positionals.length !== identifierCount) fail(`Expected ${identifierCount ? 'one identifier' : 'no identifier'} for ${command}.`);\n if (promptCommand && positionals.length > 2) fail(`Expected one positional prompt for ${command}.`);\n const format = values.format ?? 'text';\n if (format !== 'text' && format !== 'jsonl') fail('Format must be text or jsonl.');\n const delivery = values.delivery ?? 'queue';\n if (!['queue','steer','interrupt'].includes(String(delivery))) fail('Delivery must be queue, steer, or interrupt.');\n const result = {...defaults(command as Command, cwd), id: positionals[0], format, delivery,\n cwd: resolve(cwd, String(values.cwd ?? '.')), full: values.full === true} as Arguments;\n if (command === 'run') {\n const direct = Object.hasOwn(directTargets, result.id!)\n ? directTargets[result.id! as keyof typeof directTargets] : undefined;\n if (direct) result.harness = direct;\n if ('model' in values || 'effort' in values) {\n if (!direct) fail('--model and --effort are available only for direct harness targets.');\n if ('model' in values && !String(values.model).trim()) fail('Model must contain text.');\n if ('effort' in values && !String(values.effort).trim()) fail('Effort must contain text.');\n if (direct === 'claudeCode' && 'effort' in values && !claudeEfforts.has(String(values.effort))) {\n fail('Claude effort must be low, medium, high, xhigh, or max.');\n }\n if ('model' in values) result.model = String(values.model);\n if ('effort' in values) result.effort = String(values.effort);\n }\n }\n if (command === 'run' || command === 'send') {\n const positionalPrompt = positionals[1];\n if (Number(positionalPrompt !== undefined) + Number('prompt' in values) + Number('prompt-file' in values) !== 1) {\n fail('Supply exactly one prompt source: one positional prompt, --prompt, or --prompt-file.');\n }\n if ('prompt-file' in values) {\n result.prompt = await readPromptInput(String(values['prompt-file']), cwd, dependencies.stdin);\n } else result.prompt = positionalPrompt ?? String(values.prompt);\n if (!result.prompt?.trim()) fail('Prompt must contain text.');\n if (Buffer.byteLength(result.prompt!) > MAX_PROMPT_BYTES) fail('Prompt exceeds 1 MiB.');\n }\n if (command === 'wait') {\n if (!values.after) fail('wait requires --after <response-id>.');\n result.after = String(values.after);\n }\n return result;\n}\nfunction defaults(command: Command, cwd: string): Arguments {\n return {command,cwd,delivery:'queue',format:'text',full:false};\n}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,22 @@
1
+ import { discover, loadDefinition } from "../config/loader.js";
2
+ import { errorInfo } from "../errors.js";
3
+ process.on("disconnect", () => process.exit());
4
+ process.once("message", async ({ cwd, parent, discover: shouldDiscover = true }) => {
5
+ let reply;
6
+ try {
7
+ const entries = shouldDiscover
8
+ ? (await discover(cwd)).map(({ id, name, description, scope, file }) => ({ id, name, description, scope, file }))
9
+ : [];
10
+ const definition = parent && 'file' in parent ? await loadDefinition(parent.file, parent.subagents) : undefined;
11
+ const children = Object.entries(definition?.subagents ?? {}).map(([name, child]) => ({ name, description: child.description }));
12
+ reply = { result: { entries, children } };
13
+ }
14
+ catch (error) {
15
+ reply = { error: errorInfo(error) };
16
+ }
17
+ // Wait until the caller receives the result, then end any timers created by trusted modules.
18
+ process.once("message", () => process.exit());
19
+ process.send?.(reply, (error) => { if (error)
20
+ process.exit(1); });
21
+ });
22
+ //# sourceMappingURL=catalog-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-worker.js","sourceRoot":"","sources":["../../src/cli/catalog-worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AAC/C,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,EAAoE,EAAE,EAAE;IACnJ,IAAI,KAAmB,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,cAAc;YAC5B,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACjH,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,UAAU,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChH,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAChI,KAAK,GAAG,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAAC,KAAK,GAAG,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IAAC,CAAC;IACxD,6FAA6F;IAC7F,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAmB,EAAE,EAAE,GAAG,IAAI,KAAK;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC,CAAC,CAAC","sourcesContent":["import { discover, loadDefinition } from \"../config/loader.js\";\nimport { errorInfo } from \"../errors.js\";\nimport type { ExecutionReference } from \"../runtime/types.js\";\nimport type { CatalogReply } from \"./catalog.js\";\n\nprocess.on(\"disconnect\", () => process.exit());\nprocess.once(\"message\", async ({ cwd, parent, discover: shouldDiscover = true }: { cwd: string; parent?: ExecutionReference; discover?: boolean }) => {\n let reply: CatalogReply;\n try {\n const entries = shouldDiscover\n ? (await discover(cwd)).map(({ id, name, description, scope, file }) => ({ id, name, description, scope, file }))\n : [];\n const definition = parent && 'file' in parent ? await loadDefinition(parent.file, parent.subagents) : undefined;\n const children = Object.entries(definition?.subagents ?? {}).map(([name, child]) => ({ name, description: child.description }));\n reply = { result: { entries, children } };\n } catch (error) { reply = { error: errorInfo(error) }; }\n // Wait until the caller receives the result, then end any timers created by trusted modules.\n process.once(\"message\", () => process.exit());\n process.send?.(reply, (error: Error | null) => { if (error) process.exit(1); });\n});\n"]}
@@ -0,0 +1,26 @@
1
+ import { type ErrorInfo } from "../errors.js";
2
+ import type { AgentReference, ExecutionReference } from "../runtime/types.js";
3
+ export interface CatalogSnapshot {
4
+ entries: {
5
+ id: string;
6
+ name: string;
7
+ description: string;
8
+ scope: "repo" | "global";
9
+ file: string;
10
+ }[];
11
+ children: {
12
+ name: string;
13
+ description: string;
14
+ }[];
15
+ }
16
+ export type CatalogReply = {
17
+ result: CatalogSnapshot;
18
+ error?: never;
19
+ } | {
20
+ result?: never;
21
+ error: ErrorInfo;
22
+ };
23
+ /** Definition modules run in their selected directory without sharing the CLI's output streams. */
24
+ export declare function loadCatalog(cwd: string, parent?: ExecutionReference): Promise<CatalogSnapshot>;
25
+ /** Declared-child lookup evaluates only the active parent's definition source. */
26
+ export declare function loadDeclaredChildren(cwd: string, parent: AgentReference): Promise<CatalogSnapshot['children']>;
@@ -0,0 +1,41 @@
1
+ import { fork } from "node:child_process";
2
+ import { fileURLToPath } from "node:url";
3
+ import { AgentError } from "../errors.js";
4
+ /** Definition modules run in their selected directory without sharing the CLI's output streams. */
5
+ export function loadCatalog(cwd, parent) {
6
+ return loadCatalogSnapshot(cwd, parent, true);
7
+ }
8
+ /** Declared-child lookup evaluates only the active parent's definition source. */
9
+ export async function loadDeclaredChildren(cwd, parent) {
10
+ return (await loadCatalogSnapshot(cwd, parent, false)).children;
11
+ }
12
+ function loadCatalogSnapshot(cwd, parent, discover) {
13
+ return new Promise((resolve, reject) => {
14
+ const extension = import.meta.url.endsWith(".ts") ? "ts" : "js";
15
+ const child = fork(fileURLToPath(new URL(`./catalog-worker.${extension}`, import.meta.url)), [], {
16
+ cwd, env: process.env, stdio: ["ignore", "ignore", "ignore", "ipc"],
17
+ execArgv: extension === "ts" ? ["--import", import.meta.resolve("tsx")] : [],
18
+ });
19
+ let reply;
20
+ const failed = () => reject(new AgentError("INVALID_DEFINITION", "The agent catalog worker exited before returning its catalog."));
21
+ child.once("error", failed);
22
+ child.once("exit", () => {
23
+ if (!reply)
24
+ failed();
25
+ else if (reply.error)
26
+ reject(new AgentError(reply.error.code, reply.error.message));
27
+ else
28
+ resolve(reply.result);
29
+ });
30
+ child.once("message", (message) => {
31
+ reply = message;
32
+ child.send({ received: true }, (error) => { if (error)
33
+ child.kill(); });
34
+ });
35
+ child.send({ cwd, parent, discover }, (error) => { if (error) {
36
+ child.kill();
37
+ failed();
38
+ } });
39
+ });
40
+ }
41
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/cli/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAkB,MAAM,cAAc,CAAC;AAS1D,mGAAmG;AACnG,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,MAA2B;IAClE,OAAO,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AAChD,CAAC;AAED,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,GAAW,EAAE,MAAsB;IAC5E,OAAO,CAAC,MAAM,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AAClE,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAW,EAAE,MAAsC,EAAE,QAAiB;IACjG,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAChE,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,oBAAoB,SAAS,EAAE,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;YAC/F,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC;YACnE,QAAQ,EAAE,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;SAC7E,CAAC,CAAC;QACH,IAAI,KAA+B,CAAC;QACpC,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,oBAAoB,EAAE,+DAA+D,CAAC,CAAC,CAAC;QACnI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;YACtB,IAAI,CAAC,KAAK;gBAAE,MAAM,EAAE,CAAC;iBAChB,IAAI,KAAK,CAAC,KAAK;gBAAE,MAAM,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;;gBAC/E,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,OAAqB,EAAE,EAAE;YAC9C,KAAK,GAAG,OAAO,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,KAAK;gBAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,KAAK,EAAE,CAAC;YAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAAC,MAAM,EAAE,CAAC;QAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { fork } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\nimport { AgentError, type ErrorInfo } from \"../errors.js\";\nimport type { AgentReference, ExecutionReference } from \"../runtime/types.js\";\n\nexport interface CatalogSnapshot {\n entries: { id: string; name: string; description: string; scope: \"repo\" | \"global\"; file: string }[];\n children: { name: string; description: string }[];\n}\nexport type CatalogReply = { result: CatalogSnapshot; error?: never } | { result?: never; error: ErrorInfo };\n\n/** Definition modules run in their selected directory without sharing the CLI's output streams. */\nexport function loadCatalog(cwd: string, parent?: ExecutionReference): Promise<CatalogSnapshot> {\n return loadCatalogSnapshot(cwd, parent, true);\n}\n\n/** Declared-child lookup evaluates only the active parent's definition source. */\nexport async function loadDeclaredChildren(cwd: string, parent: AgentReference): Promise<CatalogSnapshot['children']> {\n return (await loadCatalogSnapshot(cwd, parent, false)).children;\n}\n\nfunction loadCatalogSnapshot(cwd: string, parent: ExecutionReference | undefined, discover: boolean): Promise<CatalogSnapshot> {\n return new Promise((resolve, reject) => {\n const extension = import.meta.url.endsWith(\".ts\") ? \"ts\" : \"js\";\n const child = fork(fileURLToPath(new URL(`./catalog-worker.${extension}`, import.meta.url)), [], {\n cwd, env: process.env, stdio: [\"ignore\", \"ignore\", \"ignore\", \"ipc\"],\n execArgv: extension === \"ts\" ? [\"--import\", import.meta.resolve(\"tsx\")] : [],\n });\n let reply: CatalogReply | undefined;\n const failed = () => reject(new AgentError(\"INVALID_DEFINITION\", \"The agent catalog worker exited before returning its catalog.\"));\n child.once(\"error\", failed);\n child.once(\"exit\", () => {\n if (!reply) failed();\n else if (reply.error) reject(new AgentError(reply.error.code, reply.error.message));\n else resolve(reply.result);\n });\n child.once(\"message\", (message: CatalogReply) => {\n reply = message;\n child.send({ received: true }, (error) => { if (error) child.kill(); });\n });\n child.send({ cwd, parent, discover }, (error) => { if (error) { child.kill(); failed(); } });\n });\n}\n"]}
@@ -0,0 +1,3 @@
1
+ type DirectHarness = 'codex' | 'claudeCode' | 'fx';
2
+ export declare function renderHelp(harness?: DirectHarness): string;
3
+ export {};
@@ -0,0 +1,68 @@
1
+ const GLOBAL_HELP = `subharness — coordinate external coding agents
2
+
3
+ Usage:
4
+ subharness list [--cwd <directory>]
5
+ subharness run <target> [options] <prompt>
6
+ subharness run <target> [options] --prompt <text>
7
+ subharness run <target> [options] --prompt-file <path|->
8
+ subharness send <session-id> [--delivery queue|steer|interrupt] <prompt>
9
+ subharness send <session-id> [--delivery queue|steer|interrupt] --prompt <text>
10
+ subharness send <session-id> [--delivery queue|steer|interrupt] --prompt-file <path|->
11
+ subharness wait <task-id> --after <response-id>
12
+ subharness status <task-id> [--full]
13
+ subharness queue <session-id>
14
+ subharness cancel <task-id>
15
+ subharness resume <session-id>
16
+
17
+ Direct harness targets: codex, claude, fx. These bare names are reserved; same-named specialists require repo: or global:.
18
+ Specialist targets: repo:<name>, global:<name>, or an unambiguous bare name.
19
+ Declared child targets: subagent:<name>, resolved only from the active managed parent's declarations.
20
+ Run "subharness run <harness> --help" for harness-specific options.
21
+ Execution commands accept --format text|jsonl; text is the default.
22
+ --help and --version do not start a coordinator or native harness.
23
+ Use -- to pass a positional prompt beginning with a dash.
24
+ agent is an identical compatibility alias for subharness.
25
+ `;
26
+ const details = {
27
+ codex: {
28
+ name: 'codex',
29
+ access: 'Requires an installed Codex executable and eligible configured access.',
30
+ effort: 'Codex accepts a nonempty native effort identifier; model compatibility is checked by the adapter.',
31
+ },
32
+ claudeCode: {
33
+ name: 'claude',
34
+ access: 'Requires an installed Claude Code executable and eligible configured access.',
35
+ effort: 'Claude effort must be low, medium, high, xhigh, or max.',
36
+ },
37
+ fx: {
38
+ name: 'fx',
39
+ access: 'Requires an installed fx executable and configured Gateway access.',
40
+ effort: 'fx accepts a nonempty native effort identifier; model compatibility is checked by the adapter.',
41
+ },
42
+ };
43
+ export function renderHelp(harness) {
44
+ if (!harness)
45
+ return GLOBAL_HELP;
46
+ const target = details[harness];
47
+ return `subharness run ${target.name} — start a direct ${target.name} session
48
+
49
+ Usage:
50
+ subharness run ${target.name} [--cwd <directory>] [--model <model>] [--effort <effort>] <prompt>
51
+ subharness run ${target.name} [options] --prompt <text>
52
+ subharness run ${target.name} [options] --prompt-file <path|->
53
+
54
+ Options:
55
+ --cwd <directory> Execution directory for the new session
56
+ --model <model> Native model identifier
57
+ --effort <effort> Native effort identifier
58
+ --prompt <text> Prompt text
59
+ --prompt-file <path|-> Read the prompt from a UTF-8 file or stdin
60
+ --format text|jsonl Output format (text by default)
61
+
62
+ Omitting --model or --effort uses the verifiable native default for the selected access route.
63
+ ${target.effort}
64
+ ${target.access}
65
+ Native harness flags are not forwarded; unsupported options are errors.
66
+ `;
67
+ }
68
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwBnB,CAAC;AAEF,MAAM,OAAO,GAA0E;IACrF,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,wEAAwE;QAChF,MAAM,EAAE,mGAAmG;KAC5G;IACD,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,8EAA8E;QACtF,MAAM,EAAE,yDAAyD;KAClE;IACD,EAAE,EAAE;QACF,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,oEAAoE;QAC5E,MAAM,EAAE,gGAAgG;KACzG;CACF,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,OAAuB;IAChD,IAAI,CAAC,OAAO;QAAE,OAAO,WAAW,CAAC;IACjC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,kBAAkB,MAAM,CAAC,IAAI,qBAAqB,MAAM,CAAC,IAAI;;;mBAGnD,MAAM,CAAC,IAAI;mBACX,MAAM,CAAC,IAAI;mBACX,MAAM,CAAC,IAAI;;;;;;;;;;;EAW5B,MAAM,CAAC,MAAM;EACb,MAAM,CAAC,MAAM;;CAEd,CAAC;AACF,CAAC","sourcesContent":["type DirectHarness = 'codex' | 'claudeCode' | 'fx';\n\nconst GLOBAL_HELP = `subharness — coordinate external coding agents\n\nUsage:\n subharness list [--cwd <directory>]\n subharness run <target> [options] <prompt>\n subharness run <target> [options] --prompt <text>\n subharness run <target> [options] --prompt-file <path|->\n subharness send <session-id> [--delivery queue|steer|interrupt] <prompt>\n subharness send <session-id> [--delivery queue|steer|interrupt] --prompt <text>\n subharness send <session-id> [--delivery queue|steer|interrupt] --prompt-file <path|->\n subharness wait <task-id> --after <response-id>\n subharness status <task-id> [--full]\n subharness queue <session-id>\n subharness cancel <task-id>\n subharness resume <session-id>\n\nDirect harness targets: codex, claude, fx. These bare names are reserved; same-named specialists require repo: or global:.\nSpecialist targets: repo:<name>, global:<name>, or an unambiguous bare name.\nDeclared child targets: subagent:<name>, resolved only from the active managed parent's declarations.\nRun \"subharness run <harness> --help\" for harness-specific options.\nExecution commands accept --format text|jsonl; text is the default.\n--help and --version do not start a coordinator or native harness.\nUse -- to pass a positional prompt beginning with a dash.\nagent is an identical compatibility alias for subharness.\n`;\n\nconst details: Record<DirectHarness, {name: string; access: string; effort: string}> = {\n codex: {\n name: 'codex',\n access: 'Requires an installed Codex executable and eligible configured access.',\n effort: 'Codex accepts a nonempty native effort identifier; model compatibility is checked by the adapter.',\n },\n claudeCode: {\n name: 'claude',\n access: 'Requires an installed Claude Code executable and eligible configured access.',\n effort: 'Claude effort must be low, medium, high, xhigh, or max.',\n },\n fx: {\n name: 'fx',\n access: 'Requires an installed fx executable and configured Gateway access.',\n effort: 'fx accepts a nonempty native effort identifier; model compatibility is checked by the adapter.',\n },\n};\n\nexport function renderHelp(harness?: DirectHarness): string {\n if (!harness) return GLOBAL_HELP;\n const target = details[harness];\n return `subharness run ${target.name} — start a direct ${target.name} session\n\nUsage:\n subharness run ${target.name} [--cwd <directory>] [--model <model>] [--effort <effort>] <prompt>\n subharness run ${target.name} [options] --prompt <text>\n subharness run ${target.name} [options] --prompt-file <path|->\n\nOptions:\n --cwd <directory> Execution directory for the new session\n --model <model> Native model identifier\n --effort <effort> Native effort identifier\n --prompt <text> Prompt text\n --prompt-file <path|-> Read the prompt from a UTF-8 file or stdin\n --format text|jsonl Output format (text by default)\n\nOmitting --model or --effort uses the verifiable native default for the selected access route.\n${target.effort}\n${target.access}\nNative harness flags are not forwarded; unsupported options are errors.\n`;\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export declare const MAX_PROMPT_BYTES: number;
2
+ export type PromptStream = AsyncIterable<Uint8Array | string> & {
3
+ isTTY?: boolean;
4
+ };
5
+ export declare function readPromptInput(source: string, cwd: string, stdin?: PromptStream): Promise<string>;
@@ -0,0 +1,69 @@
1
+ import { open } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import { AgentError } from '../errors.js';
4
+ export const MAX_PROMPT_BYTES = 1024 * 1024;
5
+ const invalid = (message) => { throw new AgentError('INVALID_ARGUMENT', message); };
6
+ function decode(chunks, bytes, source) {
7
+ if (bytes > MAX_PROMPT_BYTES)
8
+ invalid('Prompt exceeds 1 MiB.');
9
+ try {
10
+ return new TextDecoder('utf-8', { fatal: true }).decode(Buffer.concat(chunks, bytes));
11
+ }
12
+ catch {
13
+ return invalid(`Cannot read UTF-8 prompt ${source}.`);
14
+ }
15
+ }
16
+ async function readStdin(stdin) {
17
+ if (stdin.isTTY)
18
+ invalid('Cannot read a prompt from interactive terminal stdin.');
19
+ const chunks = [];
20
+ let bytes = 0;
21
+ try {
22
+ for await (const value of stdin) {
23
+ const chunk = Buffer.from(value);
24
+ bytes += chunk.byteLength;
25
+ if (bytes > MAX_PROMPT_BYTES)
26
+ invalid('Prompt exceeds 1 MiB.');
27
+ chunks.push(chunk);
28
+ }
29
+ }
30
+ catch (error) {
31
+ if (error instanceof AgentError)
32
+ throw error;
33
+ invalid('Cannot read prompt from stdin.');
34
+ }
35
+ return decode(chunks, bytes, 'from stdin');
36
+ }
37
+ async function readFileBounded(path) {
38
+ let file;
39
+ try {
40
+ file = await open(path, 'r');
41
+ const chunks = [];
42
+ let bytes = 0;
43
+ while (true) {
44
+ const buffer = Buffer.allocUnsafe(Math.min(64 * 1024, MAX_PROMPT_BYTES + 1 - bytes));
45
+ const { bytesRead } = await file.read(buffer, 0, buffer.byteLength, null);
46
+ if (!bytesRead)
47
+ return decode(chunks, bytes, `file: ${path}`);
48
+ bytes += bytesRead;
49
+ if (bytes > MAX_PROMPT_BYTES)
50
+ invalid('Prompt exceeds 1 MiB.');
51
+ chunks.push(buffer.subarray(0, bytesRead));
52
+ }
53
+ }
54
+ catch (error) {
55
+ if (error instanceof AgentError)
56
+ throw error;
57
+ return invalid(`Cannot read prompt file: ${path}`);
58
+ }
59
+ finally {
60
+ try {
61
+ await file?.close();
62
+ }
63
+ catch { }
64
+ }
65
+ }
66
+ export function readPromptInput(source, cwd, stdin = process.stdin) {
67
+ return source === '-' ? readStdin(stdin) : readFileBounded(resolve(cwd, source));
68
+ }
69
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/cli/input.ts"],"names":[],"mappings":"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","sourcesContent":["import { open } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { AgentError } from '../errors.js';\n\nexport const MAX_PROMPT_BYTES = 1024 * 1024;\n\nexport type PromptStream = AsyncIterable<Uint8Array | string> & {isTTY?: boolean};\n\nconst invalid = (message: string): never => { throw new AgentError('INVALID_ARGUMENT', message); };\n\nfunction decode(chunks: Uint8Array[], bytes: number, source: string): string {\n if (bytes > MAX_PROMPT_BYTES) invalid('Prompt exceeds 1 MiB.');\n try {\n return new TextDecoder('utf-8', {fatal: true}).decode(Buffer.concat(chunks, bytes));\n } catch {\n return invalid(`Cannot read UTF-8 prompt ${source}.`);\n }\n}\n\nasync function readStdin(stdin: PromptStream): Promise<string> {\n if (stdin.isTTY) invalid('Cannot read a prompt from interactive terminal stdin.');\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n try {\n for await (const value of stdin) {\n const chunk = Buffer.from(value);\n bytes += chunk.byteLength;\n if (bytes > MAX_PROMPT_BYTES) invalid('Prompt exceeds 1 MiB.');\n chunks.push(chunk);\n }\n } catch (error) {\n if (error instanceof AgentError) throw error;\n invalid('Cannot read prompt from stdin.');\n }\n return decode(chunks, bytes, 'from stdin');\n}\n\nasync function readFileBounded(path: string): Promise<string> {\n let file;\n try {\n file = await open(path, 'r');\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n while (true) {\n const buffer = Buffer.allocUnsafe(Math.min(64 * 1024, MAX_PROMPT_BYTES + 1 - bytes));\n const {bytesRead} = await file.read(buffer, 0, buffer.byteLength, null);\n if (!bytesRead) return decode(chunks, bytes, `file: ${path}`);\n bytes += bytesRead;\n if (bytes > MAX_PROMPT_BYTES) invalid('Prompt exceeds 1 MiB.');\n chunks.push(buffer.subarray(0, bytesRead));\n }\n } catch (error) {\n if (error instanceof AgentError) throw error;\n return invalid(`Cannot read prompt file: ${path}`);\n } finally {\n try { await file?.close(); } catch {}\n }\n}\n\nexport function readPromptInput(source: string, cwd: string, stdin: PromptStream = process.stdin): Promise<string> {\n return source === '-' ? readStdin(stdin) : readFileBounded(resolve(cwd, source));\n}\n"]}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};