subharness 0.0.3 → 0.0.4

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 (110) hide show
  1. package/README.md +3 -3
  2. package/dist/adapters/approval-context.d.ts +2 -0
  3. package/dist/adapters/approval-context.js +9 -0
  4. package/dist/adapters/approval-context.js.map +1 -0
  5. package/dist/adapters/approval-lifetime.d.ts +8 -0
  6. package/dist/adapters/approval-lifetime.js +50 -0
  7. package/dist/adapters/approval-lifetime.js.map +1 -0
  8. package/dist/adapters/claude-approvals.d.ts +4 -0
  9. package/dist/adapters/claude-approvals.js +32 -0
  10. package/dist/adapters/claude-approvals.js.map +1 -0
  11. package/dist/adapters/claude-permissions.js +1 -1
  12. package/dist/adapters/claude-permissions.js.map +1 -1
  13. package/dist/adapters/claude.js +30 -1
  14. package/dist/adapters/claude.js.map +1 -1
  15. package/dist/adapters/codex-approvals.d.ts +6 -0
  16. package/dist/adapters/codex-approvals.js +111 -0
  17. package/dist/adapters/codex-approvals.js.map +1 -0
  18. package/dist/adapters/codex.js +32 -2
  19. package/dist/adapters/codex.js.map +1 -1
  20. package/dist/adapters/fx-approvals.d.ts +2 -0
  21. package/dist/adapters/fx-approvals.js +14 -0
  22. package/dist/adapters/fx-approvals.js.map +1 -0
  23. package/dist/adapters/fx.js +49 -18
  24. package/dist/adapters/fx.js.map +1 -1
  25. package/dist/adapters/types.d.ts +2 -0
  26. package/dist/adapters/types.js.map +1 -1
  27. package/dist/approvals/schema.d.ts +4 -0
  28. package/dist/approvals/schema.js +70 -0
  29. package/dist/approvals/schema.js.map +1 -0
  30. package/dist/approvals/types.d.ts +47 -0
  31. package/dist/approvals/types.js +2 -0
  32. package/dist/approvals/types.js.map +1 -0
  33. package/dist/cli/args.d.ts +2 -1
  34. package/dist/cli/args.js +20 -2
  35. package/dist/cli/args.js.map +1 -1
  36. package/dist/cli/dashboard-client.d.ts +5 -1
  37. package/dist/cli/dashboard-client.js +161 -14
  38. package/dist/cli/dashboard-client.js.map +1 -1
  39. package/dist/cli/dashboard-detail-view.d.ts +16 -0
  40. package/dist/cli/dashboard-detail-view.js +163 -0
  41. package/dist/cli/dashboard-detail-view.js.map +1 -0
  42. package/dist/cli/dashboard-history-view.d.ts +29 -0
  43. package/dist/cli/dashboard-history-view.js +211 -0
  44. package/dist/cli/dashboard-history-view.js.map +1 -0
  45. package/dist/cli/dashboard-input.d.ts +14 -0
  46. package/dist/cli/dashboard-input.js +118 -0
  47. package/dist/cli/dashboard-input.js.map +1 -0
  48. package/dist/cli/dashboard-layout.d.ts +12 -1
  49. package/dist/cli/dashboard-layout.js +29 -27
  50. package/dist/cli/dashboard-layout.js.map +1 -1
  51. package/dist/cli/dashboard-renderer.d.ts +30 -2
  52. package/dist/cli/dashboard-renderer.js +125 -7
  53. package/dist/cli/dashboard-renderer.js.map +1 -1
  54. package/dist/cli/dashboard-style.d.ts +9 -0
  55. package/dist/cli/dashboard-style.js +36 -0
  56. package/dist/cli/dashboard-style.js.map +1 -0
  57. package/dist/cli/dashboard.d.ts +3 -1
  58. package/dist/cli/dashboard.js +127 -12
  59. package/dist/cli/dashboard.js.map +1 -1
  60. package/dist/cli/help.js +7 -0
  61. package/dist/cli/help.js.map +1 -1
  62. package/dist/cli/input.d.ts +1 -0
  63. package/dist/cli/input.js +23 -17
  64. package/dist/cli/input.js.map +1 -1
  65. package/dist/cli/main.js +1 -1
  66. package/dist/cli/main.js.map +1 -1
  67. package/dist/cli/output.js +17 -1
  68. package/dist/cli/output.js.map +1 -1
  69. package/dist/runtime/approval-registry.d.ts +27 -0
  70. package/dist/runtime/approval-registry.js +126 -0
  71. package/dist/runtime/approval-registry.js.map +1 -0
  72. package/dist/runtime/coordinator.d.ts +17 -1
  73. package/dist/runtime/coordinator.js +124 -6
  74. package/dist/runtime/coordinator.js.map +1 -1
  75. package/dist/runtime/dashboard.d.ts +42 -0
  76. package/dist/runtime/dashboard.js.map +1 -1
  77. package/dist/runtime/select-native.d.ts +2 -1
  78. package/dist/runtime/select-native.js +2 -2
  79. package/dist/runtime/select-native.js.map +1 -1
  80. package/dist/runtime/service.js +24 -1
  81. package/dist/runtime/service.js.map +1 -1
  82. package/dist/runtime/types.d.ts +9 -1
  83. package/dist/runtime/types.js.map +1 -1
  84. package/dist/runtime/worker-approvals.d.ts +21 -0
  85. package/dist/runtime/worker-approvals.js +51 -0
  86. package/dist/runtime/worker-approvals.js.map +1 -0
  87. package/dist/runtime/worker-client.js +35 -7
  88. package/dist/runtime/worker-client.js.map +1 -1
  89. package/dist/runtime/worker-server.d.ts +2 -0
  90. package/dist/runtime/worker-server.js +39 -10
  91. package/dist/runtime/worker-server.js.map +1 -1
  92. package/package.json +1 -1
  93. package/sdk/access-config.md +28 -0
  94. package/sdk/adapter-contract.md +2 -10
  95. package/sdk/agent-skill.md +6 -3
  96. package/sdk/approvals.md +118 -0
  97. package/sdk/cli/dashboard-design.md +38 -4
  98. package/sdk/cli/dashboard-inspection.md +25 -0
  99. package/sdk/cli/index.md +11 -5
  100. package/sdk/cli/output.md +7 -3
  101. package/sdk/completion-notifications.md +2 -0
  102. package/sdk/distribution.md +52 -0
  103. package/sdk/evals.md +9 -3
  104. package/sdk/fx.md +1 -1
  105. package/sdk/index.md +1 -0
  106. package/sdk/message-delivery.md +1 -1
  107. package/sdk/permissions.md +4 -4
  108. package/sdk/pr-integration.md +1 -1
  109. package/sdk/sessions.md +4 -1
  110. package/sdk/v1-runtime.md +3 -3
@@ -0,0 +1,70 @@
1
+ import { AgentError } from "../errors.js";
2
+ const invalid = () => new AgentError("INVALID_APPROVAL_RESPONSE", "The approval response does not match the requested schema.");
3
+ const unsupported = () => new AgentError("INPUT_REQUIRED", "The native permission request cannot be represented by a supported approval schema.");
4
+ function object(value) {
5
+ return typeof value === "object" && value !== null && !Array.isArray(value) && [Object.prototype, null].includes(Object.getPrototypeOf(value));
6
+ }
7
+ function keys(value, allowed) { return Object.keys(value).every(key => allowed.includes(key)); }
8
+ function strings(value) { return Array.isArray(value) && Object.keys(value).length === value.length && value.every(v => typeof v === "string") && new Set(value).size === value.length; }
9
+ function choices(value) {
10
+ return Array.isArray(value) && value.length > 0 && value.every(v => object(v) && keys(v, ["const", "title"]) && typeof v.const === "string" && typeof v.title === "string") && new Set(value.map(v => v.const)).size === value.length;
11
+ }
12
+ function bounds(field, lower, upper, integral = false) {
13
+ return [lower, upper].every(key => field[key] === undefined || (Number.isFinite(field[key]) && (!integral || (Number.isInteger(field[key]) && field[key] >= 0)))) && !(field[lower] !== undefined && field[upper] !== undefined && field[lower] > field[upper]);
14
+ }
15
+ function fieldValid(field) {
16
+ if (!object(field) || !["title", "description"].every(key => field[key] === undefined || typeof field[key] === "string"))
17
+ return false;
18
+ const common = ["type", "title", "description"];
19
+ switch (field.type) {
20
+ case "string": return keys(field, [...common, "enum", "oneOf", "minLength", "maxLength"]) && !(field.enum && field.oneOf)
21
+ && (field.enum === undefined || (strings(field.enum) && field.enum.length > 0)) && (field.oneOf === undefined || choices(field.oneOf)) && bounds(field, "minLength", "maxLength", true);
22
+ case "boolean": return keys(field, common);
23
+ case "number":
24
+ case "integer": return keys(field, [...common, "minimum", "maximum"]) && bounds(field, "minimum", "maximum");
25
+ case "array": return keys(field, [...common, "items", "minItems", "maxItems", "uniqueItems"]) && (field.uniqueItems === undefined || field.uniqueItems === true)
26
+ && bounds(field, "minItems", "maxItems", true) && object(field.items) && keys(field.items, ["type", "enum", "anyOf"]) && field.items.type === "string"
27
+ && ((field.items.enum !== undefined && field.items.anyOf === undefined && strings(field.items.enum) && field.items.enum.length > 0) || (field.items.enum === undefined && choices(field.items.anyOf)));
28
+ default: return false;
29
+ }
30
+ }
31
+ /** Reject unsupported schema constructs before publishing a native request. */
32
+ export function validateApprovalSchema(schema) {
33
+ if (!object(schema) || !keys(schema, ["type", "properties", "required", "additionalProperties"]) || schema.type !== "object" || !object(schema.properties)
34
+ || (schema.additionalProperties !== undefined && schema.additionalProperties !== false) || !Object.values(schema.properties).every(fieldValid)
35
+ || (schema.required !== undefined && (!strings(schema.required) || !schema.required.every((key) => Object.hasOwn(schema.properties, key)))))
36
+ throw unsupported();
37
+ }
38
+ export function validateApprovalContent(schema, content) {
39
+ validateApprovalSchema(schema);
40
+ if (!object(content) || !keys(content, Object.keys(schema.properties)) || schema.required?.some(key => !Object.hasOwn(content, key)))
41
+ throw invalid();
42
+ try {
43
+ if (Buffer.byteLength(JSON.stringify(content)) > 16 * 1024)
44
+ throw invalid();
45
+ }
46
+ catch {
47
+ throw invalid();
48
+ }
49
+ const result = {};
50
+ for (const [key, value] of Object.entries(content)) {
51
+ const field = schema.properties[key];
52
+ let valid = false;
53
+ if (field.type === "string")
54
+ valid = typeof value === "string" && (field.enum === undefined || field.enum.includes(value)) && (field.oneOf === undefined || field.oneOf.some(choice => choice.const === value))
55
+ && (field.minLength === undefined || [...value].length >= field.minLength) && (field.maxLength === undefined || [...value].length <= field.maxLength);
56
+ else if (field.type === "boolean")
57
+ valid = typeof value === "boolean";
58
+ else if (field.type === "number" || field.type === "integer")
59
+ valid = typeof value === "number" && Number.isFinite(value) && (field.type !== "integer" || Number.isInteger(value))
60
+ && (field.minimum === undefined || value >= field.minimum) && (field.maximum === undefined || value <= field.maximum);
61
+ else if (field.type === "array")
62
+ valid = strings(value) && value.every(item => field.items.enum?.includes(item) ?? field.items.anyOf.some(choice => choice.const === item))
63
+ && (field.minItems === undefined || value.length >= field.minItems) && (field.maxItems === undefined || value.length <= field.maxItems);
64
+ if (!valid)
65
+ throw invalid();
66
+ Object.defineProperty(result, key, { value: Array.isArray(value) ? [...value] : value, enumerable: true, writable: true, configurable: true });
67
+ }
68
+ return result;
69
+ }
70
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/approvals/schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { AgentError } from \"../errors.js\";\nimport type { ApprovalContent, ApprovalSchema } from \"./types.js\";\n\nconst invalid = () => new AgentError(\"INVALID_APPROVAL_RESPONSE\", \"The approval response does not match the requested schema.\");\nconst unsupported = () => new AgentError(\"INPUT_REQUIRED\", \"The native permission request cannot be represented by a supported approval schema.\");\nfunction object(value: unknown): value is Record<string, any> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value) && [Object.prototype, null].includes(Object.getPrototypeOf(value));\n}\nfunction keys(value: Record<string, any>, allowed: string[]): boolean { return Object.keys(value).every(key => allowed.includes(key)); }\nfunction strings(value: unknown): value is string[] { return Array.isArray(value) && Object.keys(value).length === value.length && value.every(v => typeof v === \"string\") && new Set(value).size === value.length; }\nfunction choices(value: unknown): value is {const: string; title: string}[] {\n return Array.isArray(value) && value.length > 0 && value.every(v => object(v) && keys(v, [\"const\", \"title\"]) && typeof v.const === \"string\" && typeof v.title === \"string\") && new Set(value.map(v => v.const)).size === value.length;\n}\nfunction bounds(field: Record<string, any>, lower: string, upper: string, integral = false): boolean {\n return [lower, upper].every(key => field[key] === undefined || (Number.isFinite(field[key]) && (!integral || (Number.isInteger(field[key]) && field[key] >= 0)))) && !(field[lower] !== undefined && field[upper] !== undefined && field[lower] > field[upper]);\n}\nfunction fieldValid(field: unknown): boolean {\n if (!object(field) || ![\"title\", \"description\"].every(key => field[key] === undefined || typeof field[key] === \"string\")) return false;\n const common = [\"type\", \"title\", \"description\"];\n switch (field.type) {\n case \"string\": return keys(field, [...common, \"enum\", \"oneOf\", \"minLength\", \"maxLength\"]) && !(field.enum && field.oneOf)\n && (field.enum === undefined || (strings(field.enum) && field.enum.length > 0)) && (field.oneOf === undefined || choices(field.oneOf)) && bounds(field, \"minLength\", \"maxLength\", true);\n case \"boolean\": return keys(field, common);\n case \"number\": case \"integer\": return keys(field, [...common, \"minimum\", \"maximum\"]) && bounds(field, \"minimum\", \"maximum\");\n case \"array\": return keys(field, [...common, \"items\", \"minItems\", \"maxItems\", \"uniqueItems\"]) && (field.uniqueItems === undefined || field.uniqueItems === true)\n && bounds(field, \"minItems\", \"maxItems\", true) && object(field.items) && keys(field.items, [\"type\", \"enum\", \"anyOf\"]) && field.items.type === \"string\"\n && ((field.items.enum !== undefined && field.items.anyOf === undefined && strings(field.items.enum) && field.items.enum.length > 0) || (field.items.enum === undefined && choices(field.items.anyOf)));\n default: return false;\n }\n}\n/** Reject unsupported schema constructs before publishing a native request. */\nexport function validateApprovalSchema(schema: unknown): asserts schema is ApprovalSchema {\n if (!object(schema) || !keys(schema, [\"type\", \"properties\", \"required\", \"additionalProperties\"]) || schema.type !== \"object\" || !object(schema.properties)\n || (schema.additionalProperties !== undefined && schema.additionalProperties !== false) || !Object.values(schema.properties).every(fieldValid)\n || (schema.required !== undefined && (!strings(schema.required) || !schema.required.every((key: string) => Object.hasOwn(schema.properties, key))))) throw unsupported();\n}\nexport function validateApprovalContent(schema: ApprovalSchema, content: unknown): ApprovalContent {\n validateApprovalSchema(schema);\n if (!object(content) || !keys(content, Object.keys(schema.properties)) || schema.required?.some(key => !Object.hasOwn(content, key))) throw invalid();\n try { if (Buffer.byteLength(JSON.stringify(content)) > 16 * 1024) throw invalid(); } catch { throw invalid(); }\n const result: ApprovalContent = {};\n for (const [key, value] of Object.entries(content)) {\n const field = schema.properties[key]!;\n let valid = false;\n if (field.type === \"string\") valid = typeof value === \"string\" && (field.enum === undefined || field.enum.includes(value)) && (field.oneOf === undefined || field.oneOf.some(choice => choice.const === value))\n && (field.minLength === undefined || [...value].length >= field.minLength) && (field.maxLength === undefined || [...value].length <= field.maxLength);\n else if (field.type === \"boolean\") valid = typeof value === \"boolean\";\n else if (field.type === \"number\" || field.type === \"integer\") valid = typeof value === \"number\" && Number.isFinite(value) && (field.type !== \"integer\" || Number.isInteger(value))\n && (field.minimum === undefined || value >= field.minimum) && (field.maximum === undefined || value <= field.maximum);\n else if (field.type === \"array\") valid = strings(value) && value.every(item => field.items.enum?.includes(item) ?? field.items.anyOf!.some(choice => choice.const === item))\n && (field.minItems === undefined || value.length >= field.minItems) && (field.maxItems === undefined || value.length <= field.maxItems);\n if (!valid) throw invalid();\n Object.defineProperty(result, key, { value: Array.isArray(value) ? [...value] : value, enumerable: true, writable: true, configurable: true });\n }\n return result;\n}\n"]}
@@ -0,0 +1,47 @@
1
+ export type ApprovalContent = Record<string, string | number | boolean | string[]>;
2
+ export interface ApprovalChoice {
3
+ const: string;
4
+ title: string;
5
+ }
6
+ interface FieldDescription {
7
+ title?: string;
8
+ description?: string;
9
+ }
10
+ export type ApprovalField = FieldDescription & ({
11
+ type: "string";
12
+ enum?: readonly string[];
13
+ oneOf?: readonly ApprovalChoice[];
14
+ minLength?: number;
15
+ maxLength?: number;
16
+ } | {
17
+ type: "boolean";
18
+ } | {
19
+ type: "number" | "integer";
20
+ minimum?: number;
21
+ maximum?: number;
22
+ } | {
23
+ type: "array";
24
+ items: {
25
+ type: "string";
26
+ enum?: readonly string[];
27
+ anyOf?: readonly ApprovalChoice[];
28
+ };
29
+ minItems?: number;
30
+ maxItems?: number;
31
+ uniqueItems?: true;
32
+ });
33
+ export interface ApprovalSchema {
34
+ type: "object";
35
+ properties: Record<string, ApprovalField>;
36
+ required?: readonly string[];
37
+ additionalProperties?: false;
38
+ }
39
+ export interface NativeApprovalRequest {
40
+ kind: "permission";
41
+ harness: "codex" | "claudeCode" | "fx";
42
+ message: string;
43
+ requestedSchema: ApprovalSchema;
44
+ context?: Record<string, unknown>;
45
+ }
46
+ export type ApprovalHandler = (request: NativeApprovalRequest, signal: AbortSignal) => Promise<ApprovalContent>;
47
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/approvals/types.ts"],"names":[],"mappings":"","sourcesContent":["export type ApprovalContent = Record<string, string | number | boolean | string[]>;\n\nexport interface ApprovalChoice {\n const: string;\n title: string;\n}\ninterface FieldDescription { title?: string; description?: string }\nexport type ApprovalField = FieldDescription & (\n | { type: \"string\"; enum?: readonly string[]; oneOf?: readonly ApprovalChoice[]; minLength?: number; maxLength?: number }\n | { type: \"boolean\" }\n | { type: \"number\" | \"integer\"; minimum?: number; maximum?: number }\n | { type: \"array\"; items: { type: \"string\"; enum?: readonly string[]; anyOf?: readonly ApprovalChoice[] }; minItems?: number; maxItems?: number; uniqueItems?: true }\n);\nexport interface ApprovalSchema {\n type: \"object\";\n properties: Record<string, ApprovalField>;\n required?: readonly string[];\n additionalProperties?: false;\n}\nexport interface NativeApprovalRequest {\n kind: \"permission\";\n harness: \"codex\" | \"claudeCode\" | \"fx\";\n message: string;\n requestedSchema: ApprovalSchema;\n context?: Record<string, unknown>;\n}\nexport type ApprovalHandler = (request: NativeApprovalRequest, signal: AbortSignal) => Promise<ApprovalContent>;\n"]}
@@ -1,5 +1,5 @@
1
1
  import { type PromptStream } from './input.js';
2
- export type Command = 'list' | 'dashboard' | 'check' | 'run' | 'send' | 'wait' | 'status' | 'queue' | 'cancel' | 'resume' | 'help' | 'version';
2
+ export type Command = 'list' | 'dashboard' | 'check' | 'run' | 'send' | 'wait' | 'status' | 'queue' | 'cancel' | 'resume' | 'respond' | 'help' | 'version';
3
3
  export interface Arguments {
4
4
  command: Command;
5
5
  id?: string;
@@ -14,6 +14,7 @@ export interface Arguments {
14
14
  model?: string;
15
15
  effort?: string;
16
16
  helpCommand?: 'run' | 'check';
17
+ content?: Record<string, unknown>;
17
18
  }
18
19
  export declare function parseArgs(argv: string[], cwd?: string, dependencies?: {
19
20
  stdin?: PromptStream;
package/dist/cli/args.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { resolve } from 'node:path';
2
2
  import { AgentError } from '../errors.js';
3
- import { MAX_PROMPT_BYTES, readPromptInput } from './input.js';
3
+ import { MAX_PROMPT_BYTES, readPromptInput, readApprovalInput } from './input.js';
4
4
  const options = {
5
5
  list: ['cwd'], dashboard: [], check: ['cwd', 'model', 'effort'], run: ['cwd', 'prompt', 'prompt-file', 'model', 'effort', 'detach'], send: ['delivery', 'prompt', 'prompt-file', 'detach'],
6
- wait: ['after'], status: ['full'], queue: [], cancel: [], resume: [],
6
+ wait: ['after'], status: ['full'], queue: [], cancel: [], resume: [], respond: ['content', 'content-file'],
7
7
  };
8
8
  const directTargets = { codex: 'codex', claude: 'claudeCode', fx: 'fx' };
9
9
  const claudeEfforts = new Set(['low', 'medium', 'high', 'xhigh', 'max']);
@@ -116,6 +116,24 @@ export async function parseArgs(argv, cwd = process.cwd(), dependencies = {}) {
116
116
  result.after = String(values.after);
117
117
  }
118
118
  }
119
+ if (command === 'respond') {
120
+ if (Number('content' in values) + Number('content-file' in values) !== 1)
121
+ fail('Supply exactly one approval response source: --content or --content-file.');
122
+ const text = 'content-file' in values
123
+ ? await readApprovalInput(String(values['content-file']), cwd, dependencies.stdin) : String(values.content);
124
+ if (Buffer.byteLength(text) > 16 * 1024)
125
+ fail('Approval content exceeds 16 KiB.');
126
+ let content;
127
+ try {
128
+ content = JSON.parse(text);
129
+ }
130
+ catch {
131
+ fail('Approval content must be valid JSON.');
132
+ }
133
+ if (!content || typeof content !== 'object' || Array.isArray(content))
134
+ fail('Approval content must be a JSON object.');
135
+ result.content = content;
136
+ }
119
137
  return result;
120
138
  }
121
139
  function defaults(command, cwd) {
@@ -1 +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' | 'dashboard' | 'check' | '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; detach: boolean;\n harness?: 'codex' | 'claudeCode' | 'fx'; model?: string; effort?: string;\n helpCommand?: 'run' | 'check';\n}\nconst options: Record<string, string[]> = {\n list: ['cwd'], dashboard: [], check: ['cwd','model','effort'], run: ['cwd','prompt','prompt-file','model','effort','detach'], send: ['delivery','prompt','prompt-file','detach'],\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' || command === 'dashboard') && 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' || name === 'detach') 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 (command === 'dashboard' && positionals.length) fail('Expected no identifier for dashboard.');\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' || command === 'check') && 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, helpCommand: command as 'run' | 'check'} : {})};\n }\n const promptCommand = command === 'run' || command === 'send';\n const identifierCount = command === 'list' || command === 'dashboard' ? 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 if (values.detach === true && delivery === 'steer') fail('--detach cannot be combined with --delivery steer.');\n const result = {...defaults(command as Command, cwd), id: positionals[0], format, delivery,\n cwd: resolve(cwd, String(values.cwd ?? '.')), full: values.full === true, detach: values.detach === true} as Arguments;\n if (command === 'run' || command === 'check') {\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 ('after' in values) {\n if (!values.after) fail('wait requires --after <response-id>.');\n result.after = String(values.after);\n }\n }\n return result;\n}\nfunction defaults(command: Command, cwd: string): Arguments {\n return {command,cwd,delivery:'queue',format:'text',full:false,detach:false};\n}\n"]}
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, readApprovalInput, type PromptStream } from './input.js';\n\nexport type Command = 'list' | 'dashboard' | 'check' | 'run' | 'send' | 'wait' | 'status' | 'queue' | 'cancel' | 'resume' | 'respond' | '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; detach: boolean;\n harness?: 'codex' | 'claudeCode' | 'fx'; model?: string; effort?: string;\n helpCommand?: 'run' | 'check';\n content?: Record<string,unknown>;\n}\nconst options: Record<string, string[]> = {\n list: ['cwd'], dashboard: [], check: ['cwd','model','effort'], run: ['cwd','prompt','prompt-file','model','effort','detach'], send: ['delivery','prompt','prompt-file','detach'],\n wait: ['after'], status: ['full'], queue: [], cancel: [], resume: [], respond:['content','content-file'],\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' || command === 'dashboard') && 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' || name === 'detach') 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 (command === 'dashboard' && positionals.length) fail('Expected no identifier for dashboard.');\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' || command === 'check') && 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, helpCommand: command as 'run' | 'check'} : {})};\n }\n const promptCommand = command === 'run' || command === 'send';\n const identifierCount = command === 'list' || command === 'dashboard' ? 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 if (values.detach === true && delivery === 'steer') fail('--detach cannot be combined with --delivery steer.');\n const result = {...defaults(command as Command, cwd), id: positionals[0], format, delivery,\n cwd: resolve(cwd, String(values.cwd ?? '.')), full: values.full === true, detach: values.detach === true} as Arguments;\n if (command === 'run' || command === 'check') {\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 ('after' in values) {\n if (!values.after) fail('wait requires --after <response-id>.');\n result.after = String(values.after);\n }\n }\n if (command === 'respond') {\n if (Number('content' in values) + Number('content-file' in values) !== 1)\n fail('Supply exactly one approval response source: --content or --content-file.');\n const text = 'content-file' in values\n ? await readApprovalInput(String(values['content-file']),cwd,dependencies.stdin) : String(values.content);\n if (Buffer.byteLength(text) > 16 * 1024) fail('Approval content exceeds 16 KiB.');\n let content: unknown;\n try { content = JSON.parse(text); } catch { fail('Approval content must be valid JSON.'); }\n if (!content || typeof content !== 'object' || Array.isArray(content)) fail('Approval content must be a JSON object.');\n result.content = content as Record<string,unknown>;\n }\n return result;\n}\nfunction defaults(command: Command, cwd: string): Arguments {\n return {command,cwd,delivery:'queue',format:'text',full:false,detach:false};\n}\n"]}
@@ -1,3 +1,7 @@
1
- import type { DashboardSnapshot } from '../runtime/dashboard.js';
1
+ import type { DashboardDetail, DashboardRelatedTask, DashboardSession, DashboardSnapshot } from '../runtime/dashboard.js';
2
2
  import type { Endpoint } from '../runtime/state.js';
3
+ export type DashboardRelatedRecord = DashboardRelatedTask;
4
+ export type DashboardDetailRecord = DashboardDetail;
5
+ export declare function fetchDashboardSession(endpoint: Endpoint, id: string, signal: AbortSignal, timeoutMs?: number): Promise<DashboardSession>;
3
6
  export declare function fetchDashboardSnapshot(endpoint: Endpoint, signal: AbortSignal, timeoutMs?: number): Promise<DashboardSnapshot>;
7
+ export declare function fetchDashboardDetail(endpoint: Endpoint, id: string, signal: AbortSignal, includePrompt?: boolean, knownResponseId?: string, timeoutMs?: number): Promise<DashboardDetailRecord>;
@@ -1,7 +1,7 @@
1
1
  import { isAbsolute } from 'node:path';
2
2
  import { AgentError } from '../errors.js';
3
3
  const harnesses = new Set(['codex', 'claude', 'fx', 'pending']);
4
- const states = new Set(['queued', 'running', 'waiting', 'completed', 'failed', 'cancelled', 'interrupted']);
4
+ const states = new Set(['queued', 'running', 'waiting', 'awaiting_approval', 'completed', 'failed', 'cancelled', 'interrupted']);
5
5
  const finishedStates = new Set(['completed', 'cancelled', 'interrupted']);
6
6
  const timestamp = (value) => value === undefined || (typeof value === 'number' && Number.isFinite(value) && value >= 0);
7
7
  function isWorkspace(value) {
@@ -11,6 +11,18 @@ function isWorkspace(value) {
11
11
  return typeof workspace.directory === 'string' && isAbsolute(workspace.directory)
12
12
  && (workspace.repository === undefined || (typeof workspace.repository === 'string' && isAbsolute(workspace.repository)));
13
13
  }
14
+ function isRow(value, grouping) {
15
+ if (!value || typeof value !== 'object')
16
+ return false;
17
+ const item = value;
18
+ return typeof item.sessionId === 'string' && typeof item.taskId === 'string'
19
+ && typeof item.harness === 'string' && harnesses.has(item.harness)
20
+ && typeof item.state === 'string' && states.has(item.state)
21
+ && typeof item.title === 'string' && [...item.title].length <= 120
22
+ && (!grouping || (isWorkspace(item.workspace) && item.updatedAt !== undefined && timestamp(item.updatedAt)))
23
+ && timestamp(item.dispatchedAt) && timestamp(item.failedAt) && timestamp(item.finishedAt)
24
+ && (!finishedStates.has(item.state) || item.finishedAt !== undefined);
25
+ }
14
26
  function isSnapshot(value) {
15
27
  if (!value || typeof value !== 'object')
16
28
  return false;
@@ -21,18 +33,54 @@ function isSnapshot(value) {
21
33
  return false;
22
34
  if ('grouping' in snapshot && typeof snapshot.grouping !== 'boolean')
23
35
  return false;
24
- return snapshot.sessions.every((row) => {
25
- if (!row || typeof row !== 'object')
36
+ return snapshot.sessions.every((row) => isRow(row, snapshot.grouping === true));
37
+ }
38
+ function isRelated(value) {
39
+ if (!value || typeof value !== 'object')
40
+ return false;
41
+ const task = value;
42
+ return typeof task.taskId === 'string' && typeof task.sessionId === 'string'
43
+ && typeof task.harness === 'string' && harnesses.has(task.harness)
44
+ && typeof task.title === 'string' && [...task.title].length <= 120
45
+ && typeof task.state === 'string' && states.has(task.state);
46
+ }
47
+ function isDetail(value, id, includePrompt, knownResponseId) {
48
+ if (!value || typeof value !== 'object')
49
+ return false;
50
+ const detail = value;
51
+ if (detail.version !== 1 || detail.type !== 'dashboard-detail'
52
+ || !isRow(detail.task, true) || detail.task.taskId !== id
53
+ || !Array.isArray(detail.children) || !detail.children.every(isRelated)
54
+ || !detail.queue || typeof detail.queue !== 'object'
55
+ || typeof detail.stopUnconfirmed !== 'boolean')
56
+ return false;
57
+ const queue = detail.queue;
58
+ if (typeof queue.paused !== 'boolean' || !Array.isArray(queue.tasks) || !queue.tasks.every(isRelated))
59
+ return false;
60
+ if (includePrompt) {
61
+ if (typeof detail.prompt !== 'string')
62
+ return false;
63
+ }
64
+ else if (Object.hasOwn(detail, 'prompt'))
65
+ return false;
66
+ if (Object.hasOwn(detail, 'error')) {
67
+ if (!detail.error || typeof detail.error !== 'object')
68
+ return false;
69
+ const error = detail.error;
70
+ if (typeof error.code !== 'string' || typeof error.message !== 'string')
26
71
  return false;
27
- const item = row;
28
- return typeof item.sessionId === 'string' && typeof item.taskId === 'string'
29
- && typeof item.harness === 'string' && harnesses.has(item.harness)
30
- && typeof item.state === 'string' && states.has(item.state)
31
- && typeof item.title === 'string' && [...item.title].length <= 120
32
- && (snapshot.grouping !== true || (isWorkspace(item.workspace) && item.updatedAt !== undefined && timestamp(item.updatedAt)))
33
- && timestamp(item.dispatchedAt) && timestamp(item.failedAt) && timestamp(item.finishedAt)
34
- && (!finishedStates.has(item.state) || item.finishedAt !== undefined);
35
- });
72
+ }
73
+ if (Object.hasOwn(detail, 'response')) {
74
+ if (!detail.response || typeof detail.response !== 'object')
75
+ return false;
76
+ const response = detail.response;
77
+ if (typeof response.responseId !== 'string')
78
+ return false;
79
+ const unchanged = knownResponseId !== undefined && response.responseId === knownResponseId;
80
+ if (unchanged ? Object.hasOwn(response, 'text') : typeof response.text !== 'string')
81
+ return false;
82
+ }
83
+ return true;
36
84
  }
37
85
  function isLegacyUnknownOperation(value) {
38
86
  if (!value || typeof value !== 'object')
@@ -45,8 +93,78 @@ function isLegacyUnknownOperation(value) {
45
93
  return Object.keys(error).length === 2
46
94
  && error.code === 'INVALID_ARGUMENT' && error.message === 'Unknown coordinator operation.';
47
95
  }
48
- function outdatedCoordinator(endpoint) {
49
- return new AgentError('COORDINATOR_OUTDATED', `The background coordinator (PID ${endpoint.pid}) does not support finished-run history and checkout grouping. Stop that coordinator after active work ends, then start a new run. Reopening the dashboard does not reload coordinator code. Restarting the coordinator discards retained in-memory history.`);
96
+ function isSession(value, id) {
97
+ if (!value || typeof value !== 'object')
98
+ return false;
99
+ const session = value;
100
+ if (session.version !== 1 || session.type !== 'dashboard-session' || session.taskId !== id
101
+ || !isRelated(session) || !session.sessionId || !isWorkspace(session.workspace)
102
+ || typeof session.queuePaused !== 'boolean' || !Array.isArray(session.requests) || !session.requests.length
103
+ || !Array.isArray(session.subagents))
104
+ return false;
105
+ const ids = new Set();
106
+ const ordinals = new Set();
107
+ let previous;
108
+ for (const row of session.requests) {
109
+ if (!isRow(row, true) || !row.taskId || row.sessionId !== session.sessionId || row.harness !== session.harness
110
+ || row.workspace.directory !== session.workspace.directory || row.workspace.repository !== session.workspace.repository
111
+ || !Number.isSafeInteger(row.ordinal) || row.ordinal < 1 || row.ordinal > session.requests.length
112
+ || ordinals.has(row.ordinal) || ids.has(row.taskId) || typeof row.stopUnconfirmed !== 'boolean'
113
+ || (row.stopUnconfirmed && row.state !== 'failed')
114
+ || (['running', 'waiting', 'awaiting_approval', 'completed'].includes(row.state) && row.dispatchedAt === undefined)
115
+ || (row.state === 'failed' && (row.failedAt === undefined || row.finishedAt === undefined))
116
+ || (row.state === 'queued' && (row.dispatchedAt !== undefined || row.finishedAt !== undefined || row.failedAt !== undefined))
117
+ // Failure time can precede the final state while descendant shutdown is pending.
118
+ || (['running', 'waiting', 'awaiting_approval'].includes(row.state) && row.finishedAt !== undefined))
119
+ return false;
120
+ if (previous && ((previous.state !== 'queued' && row.state === 'queued')
121
+ || ((previous.state === 'queued') === (row.state === 'queued') && previous.ordinal <= row.ordinal)))
122
+ return false;
123
+ ids.add(row.taskId);
124
+ ordinals.add(row.ordinal);
125
+ previous = row;
126
+ }
127
+ if (!ids.has(id))
128
+ return false;
129
+ const children = new Set();
130
+ for (const child of session.subagents) {
131
+ if (!isRelated(child) || !child.taskId || !child.sessionId || child.sessionId === session.sessionId
132
+ || ids.has(child.taskId) || children.has(child.sessionId))
133
+ return false;
134
+ ids.add(child.taskId);
135
+ children.add(child.sessionId);
136
+ }
137
+ return true;
138
+ }
139
+ function outdatedCoordinator(endpoint, capability = 'overview') {
140
+ const missing = capability === 'session' ? 'dashboard agent-session history' : capability === 'inspection'
141
+ ? 'dashboard task inspection'
142
+ : 'finished-run history and checkout grouping';
143
+ return new AgentError('COORDINATOR_OUTDATED', `The background coordinator (PID ${endpoint.pid}) does not support ${missing}. Stop that coordinator after active work ends, then start a new run. Reopening the dashboard does not reload coordinator code. Restarting the coordinator discards retained in-memory history.`);
144
+ }
145
+ export async function fetchDashboardSession(endpoint, id, signal, timeoutMs = 5_000) {
146
+ const bounded = AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]);
147
+ try {
148
+ const response = await fetch(endpoint.url, {
149
+ method: 'POST', headers: { authorization: `Bearer ${endpoint.token}`, 'content-type': 'application/json' },
150
+ body: JSON.stringify({ command: 'dashboard-session', id }), signal: bounded,
151
+ });
152
+ if (!response.ok) {
153
+ await response.body?.cancel();
154
+ throw new Error('Rejected session');
155
+ }
156
+ const session = JSON.parse(await response.text());
157
+ if (isLegacyUnknownOperation(session))
158
+ throw outdatedCoordinator(endpoint, 'session');
159
+ if (!isSession(session, id))
160
+ throw new Error('Invalid session');
161
+ return session;
162
+ }
163
+ catch (error) {
164
+ if (error instanceof AgentError)
165
+ throw error;
166
+ throw new AgentError('COORDINATOR_UNAVAILABLE', 'The dashboard lost its connection to the local coordinator or received invalid session history.');
167
+ }
50
168
  }
51
169
  export async function fetchDashboardSnapshot(endpoint, signal, timeoutMs = 5_000) {
52
170
  const bounded = AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]);
@@ -75,4 +193,33 @@ export async function fetchDashboardSnapshot(endpoint, signal, timeoutMs = 5_000
75
193
  throw new AgentError('COORDINATOR_UNAVAILABLE', 'The dashboard lost its connection to the local coordinator or received an invalid snapshot.');
76
194
  }
77
195
  }
196
+ export async function fetchDashboardDetail(endpoint, id, signal, includePrompt = true, knownResponseId, timeoutMs = 5_000) {
197
+ const bounded = AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]);
198
+ const request = { command: 'dashboard-detail', id };
199
+ if (!includePrompt)
200
+ request.includePrompt = false;
201
+ if (knownResponseId !== undefined)
202
+ request.knownResponseId = knownResponseId;
203
+ try {
204
+ const response = await fetch(endpoint.url, {
205
+ method: 'POST', headers: { authorization: `Bearer ${endpoint.token}`, 'content-type': 'application/json' },
206
+ body: JSON.stringify(request), signal: bounded,
207
+ });
208
+ if (!response.ok) {
209
+ await response.body?.cancel();
210
+ throw new Error('Rejected detail');
211
+ }
212
+ const detail = JSON.parse(await response.text());
213
+ if (isLegacyUnknownOperation(detail))
214
+ throw outdatedCoordinator(endpoint, 'inspection');
215
+ if (!isDetail(detail, id, includePrompt, knownResponseId))
216
+ throw new Error('Invalid detail');
217
+ return detail;
218
+ }
219
+ catch (error) {
220
+ if (error instanceof AgentError)
221
+ throw error;
222
+ throw new AgentError('COORDINATOR_UNAVAILABLE', 'The dashboard lost its connection to the local coordinator or received invalid task details.');
223
+ }
224
+ }
78
225
  //# sourceMappingURL=dashboard-client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-client.js","sourceRoot":"","sources":["../../src/cli/dashboard-client.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute } from 'node:path';\nimport { AgentError } from '../errors.js';\nimport type { DashboardSnapshot } from '../runtime/dashboard.js';\nimport type { Endpoint } from '../runtime/state.js';\n\nconst harnesses = new Set(['codex', 'claude', 'fx', 'pending']);\nconst states = new Set(['queued', 'running', 'waiting', 'completed', 'failed', 'cancelled', 'interrupted']);\nconst finishedStates = new Set(['completed', 'cancelled', 'interrupted']);\nconst timestamp = (value: unknown) => value === undefined || (typeof value === 'number' && Number.isFinite(value) && value >= 0);\n\nfunction isWorkspace(value: unknown): boolean {\n if (!value || typeof value !== 'object') return false;\n const workspace = value as Record<string, unknown>;\n return typeof workspace.directory === 'string' && isAbsolute(workspace.directory)\n && (workspace.repository === undefined || (typeof workspace.repository === 'string' && isAbsolute(workspace.repository)));\n}\n\ntype SnapshotResponse = Omit<DashboardSnapshot, 'history' | 'grouping'> & {history?: boolean; grouping?: boolean};\n\nfunction isSnapshot(value: unknown): value is SnapshotResponse {\n if (!value || typeof value !== 'object') return false;\n const snapshot = value as Record<string, unknown>;\n if (snapshot.version !== 1 || snapshot.type !== 'dashboard' || !Array.isArray(snapshot.sessions)) return false;\n if ('history' in snapshot && typeof snapshot.history !== 'boolean') return false;\n if ('grouping' in snapshot && typeof snapshot.grouping !== 'boolean') return false;\n return snapshot.sessions.every((row: unknown) => {\n if (!row || typeof row !== 'object') return false;\n const item = row as Record<string, unknown>;\n return typeof item.sessionId === 'string' && typeof item.taskId === 'string'\n && typeof item.harness === 'string' && harnesses.has(item.harness)\n && typeof item.state === 'string' && states.has(item.state)\n && typeof item.title === 'string' && [...item.title].length <= 120\n && (snapshot.grouping !== true || (isWorkspace(item.workspace) && item.updatedAt !== undefined && timestamp(item.updatedAt)))\n && timestamp(item.dispatchedAt) && timestamp(item.failedAt) && timestamp(item.finishedAt)\n && (!finishedStates.has(item.state) || item.finishedAt !== undefined);\n });\n}\n\nfunction isLegacyUnknownOperation(value: unknown): boolean {\n if (!value || typeof value !== 'object') return false;\n const response = value as Record<string, unknown>;\n if (Object.keys(response).length !== 3 || response.version !== 1 || response.type !== 'error'\n || !response.error || typeof response.error !== 'object') return false;\n const error = response.error as Record<string, unknown>;\n return Object.keys(error).length === 2\n && error.code === 'INVALID_ARGUMENT' && error.message === 'Unknown coordinator operation.';\n}\n\nfunction outdatedCoordinator(endpoint: Endpoint): AgentError {\n return new AgentError('COORDINATOR_OUTDATED', `The background coordinator (PID ${endpoint.pid}) does not support finished-run history and checkout grouping. Stop that coordinator after active work ends, then start a new run. Reopening the dashboard does not reload coordinator code. Restarting the coordinator discards retained in-memory history.`);\n}\n\nexport async function fetchDashboardSnapshot(endpoint: Endpoint, signal: AbortSignal, timeoutMs = 5_000): Promise<DashboardSnapshot> {\n const bounded = AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]);\n try {\n const response = await fetch(endpoint.url, {\n method: 'POST', headers: {authorization: `Bearer ${endpoint.token}`, 'content-type': 'application/json'},\n body: JSON.stringify({command: 'dashboard'}), signal: bounded,\n });\n if (!response.ok) { await response.body?.cancel(); throw new Error('Rejected snapshot'); }\n const snapshot: unknown = JSON.parse(await response.text());\n if (isLegacyUnknownOperation(snapshot)) throw outdatedCoordinator(endpoint);\n if (!isSnapshot(snapshot)) throw new Error('Invalid snapshot');\n if (snapshot.history !== true || snapshot.grouping !== true) {\n throw outdatedCoordinator(endpoint);\n }\n return {...snapshot, history: true, grouping: true};\n } catch (error) {\n if (error instanceof AgentError) throw error;\n throw new AgentError('COORDINATOR_UNAVAILABLE', 'The dashboard lost its connection to the local coordinator or received an invalid snapshot.');\n }\n}\n"]}
1
+ {"version":3,"file":"dashboard-client.js","sourceRoot":"","sources":["../../src/cli/dashboard-client.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute } from 'node:path';\nimport { AgentError } from '../errors.js';\nimport type {\n DashboardDetail,\n DashboardRelatedTask,\n DashboardRow,\n DashboardRequest,\n DashboardSession,\n DashboardSnapshot,\n} from '../runtime/dashboard.js';\nimport type { Endpoint } from '../runtime/state.js';\n\nconst harnesses = new Set(['codex', 'claude', 'fx', 'pending']);\nconst states = new Set(['queued', 'running', 'waiting', 'awaiting_approval', 'completed', 'failed', 'cancelled', 'interrupted']);\nconst finishedStates = new Set(['completed', 'cancelled', 'interrupted']);\nconst timestamp = (value: unknown) => value === undefined || (typeof value === 'number' && Number.isFinite(value) && value >= 0);\n\nfunction isWorkspace(value: unknown): boolean {\n if (!value || typeof value !== 'object') return false;\n const workspace = value as Record<string, unknown>;\n return typeof workspace.directory === 'string' && isAbsolute(workspace.directory)\n && (workspace.repository === undefined || (typeof workspace.repository === 'string' && isAbsolute(workspace.repository)));\n}\n\nfunction isRow(value: unknown, grouping: boolean): value is DashboardRow {\n if (!value || typeof value !== 'object') return false;\n const item = value as Record<string, unknown>;\n return typeof item.sessionId === 'string' && typeof item.taskId === 'string'\n && typeof item.harness === 'string' && harnesses.has(item.harness)\n && typeof item.state === 'string' && states.has(item.state)\n && typeof item.title === 'string' && [...item.title].length <= 120\n && (!grouping || (isWorkspace(item.workspace) && item.updatedAt !== undefined && timestamp(item.updatedAt)))\n && timestamp(item.dispatchedAt) && timestamp(item.failedAt) && timestamp(item.finishedAt)\n && (!finishedStates.has(item.state) || item.finishedAt !== undefined);\n}\n\ntype SnapshotResponse = Omit<DashboardSnapshot, 'history' | 'grouping'> & {history?: boolean; grouping?: boolean};\n\nfunction isSnapshot(value: unknown): value is SnapshotResponse {\n if (!value || typeof value !== 'object') return false;\n const snapshot = value as Record<string, unknown>;\n if (snapshot.version !== 1 || snapshot.type !== 'dashboard' || !Array.isArray(snapshot.sessions)) return false;\n if ('history' in snapshot && typeof snapshot.history !== 'boolean') return false;\n if ('grouping' in snapshot && typeof snapshot.grouping !== 'boolean') return false;\n return snapshot.sessions.every((row: unknown) => isRow(row, snapshot.grouping === true));\n}\n\nexport type DashboardRelatedRecord = DashboardRelatedTask;\nexport type DashboardDetailRecord = DashboardDetail;\n\nfunction isRelated(value: unknown): value is DashboardRelatedRecord {\n if (!value || typeof value !== 'object') return false;\n const task = value as Record<string, unknown>;\n return typeof task.taskId === 'string' && typeof task.sessionId === 'string'\n && typeof task.harness === 'string' && harnesses.has(task.harness)\n && typeof task.title === 'string' && [...task.title].length <= 120\n && typeof task.state === 'string' && states.has(task.state);\n}\n\nfunction isDetail(\n value: unknown,\n id: string,\n includePrompt: boolean,\n knownResponseId?: string,\n): value is DashboardDetailRecord {\n if (!value || typeof value !== 'object') return false;\n const detail = value as Record<string, unknown>;\n if (detail.version !== 1 || detail.type !== 'dashboard-detail'\n || !isRow(detail.task, true) || detail.task.taskId !== id\n || !Array.isArray(detail.children) || !detail.children.every(isRelated)\n || !detail.queue || typeof detail.queue !== 'object'\n || typeof detail.stopUnconfirmed !== 'boolean') return false;\n const queue = detail.queue as Record<string, unknown>;\n if (typeof queue.paused !== 'boolean' || !Array.isArray(queue.tasks) || !queue.tasks.every(isRelated)) return false;\n if (includePrompt) {\n if (typeof detail.prompt !== 'string') return false;\n } else if (Object.hasOwn(detail, 'prompt')) return false;\n if (Object.hasOwn(detail, 'error')) {\n if (!detail.error || typeof detail.error !== 'object') return false;\n const error = detail.error as Record<string, unknown>;\n if (typeof error.code !== 'string' || typeof error.message !== 'string') return false;\n }\n if (Object.hasOwn(detail, 'response')) {\n if (!detail.response || typeof detail.response !== 'object') return false;\n const response = detail.response as Record<string, unknown>;\n if (typeof response.responseId !== 'string') return false;\n const unchanged = knownResponseId !== undefined && response.responseId === knownResponseId;\n if (unchanged ? Object.hasOwn(response, 'text') : typeof response.text !== 'string') return false;\n }\n return true;\n}\n\nfunction isLegacyUnknownOperation(value: unknown): boolean {\n if (!value || typeof value !== 'object') return false;\n const response = value as Record<string, unknown>;\n if (Object.keys(response).length !== 3 || response.version !== 1 || response.type !== 'error'\n || !response.error || typeof response.error !== 'object') return false;\n const error = response.error as Record<string, unknown>;\n return Object.keys(error).length === 2\n && error.code === 'INVALID_ARGUMENT' && error.message === 'Unknown coordinator operation.';\n}\n\nfunction isSession(value: unknown, id: string): value is DashboardSession {\n if (!value || typeof value !== 'object') return false;\n const session = value as DashboardSession;\n if (session.version !== 1 || session.type !== 'dashboard-session' || session.taskId !== id\n || !isRelated(session) || !session.sessionId || !isWorkspace(session.workspace)\n || typeof session.queuePaused !== 'boolean' || !Array.isArray(session.requests) || !session.requests.length\n || !Array.isArray(session.subagents)) return false;\n const ids = new Set<string>();\n const ordinals = new Set<number>();\n let previous: DashboardRequest | undefined;\n for (const row of session.requests) {\n if (!isRow(row, true) || !row.taskId || row.sessionId !== session.sessionId || row.harness !== session.harness\n || row.workspace.directory !== session.workspace.directory || row.workspace.repository !== session.workspace.repository\n || !Number.isSafeInteger(row.ordinal) || row.ordinal < 1 || row.ordinal > session.requests.length\n || ordinals.has(row.ordinal) || ids.has(row.taskId) || typeof row.stopUnconfirmed !== 'boolean'\n || (row.stopUnconfirmed && row.state !== 'failed')\n || (['running', 'waiting', 'awaiting_approval', 'completed'].includes(row.state) && row.dispatchedAt === undefined)\n || (row.state === 'failed' && (row.failedAt === undefined || row.finishedAt === undefined))\n || (row.state === 'queued' && (row.dispatchedAt !== undefined || row.finishedAt !== undefined || row.failedAt !== undefined))\n // Failure time can precede the final state while descendant shutdown is pending.\n || (['running', 'waiting', 'awaiting_approval'].includes(row.state) && row.finishedAt !== undefined)) return false;\n if (previous && ((previous.state !== 'queued' && row.state === 'queued')\n || ((previous.state === 'queued') === (row.state === 'queued') && previous.ordinal <= row.ordinal))) return false;\n ids.add(row.taskId); ordinals.add(row.ordinal); previous = row;\n }\n if (!ids.has(id)) return false;\n const children = new Set<string>();\n for (const child of session.subagents) {\n if (!isRelated(child) || !child.taskId || !child.sessionId || child.sessionId === session.sessionId\n || ids.has(child.taskId) || children.has(child.sessionId)) return false;\n ids.add(child.taskId); children.add(child.sessionId);\n }\n return true;\n}\n\nfunction outdatedCoordinator(endpoint: Endpoint, capability: 'overview' | 'inspection' | 'session' = 'overview'): AgentError {\n const missing = capability === 'session' ? 'dashboard agent-session history' : capability === 'inspection'\n ? 'dashboard task inspection'\n : 'finished-run history and checkout grouping';\n return new AgentError('COORDINATOR_OUTDATED', `The background coordinator (PID ${endpoint.pid}) does not support ${missing}. Stop that coordinator after active work ends, then start a new run. Reopening the dashboard does not reload coordinator code. Restarting the coordinator discards retained in-memory history.`);\n}\n\nexport async function fetchDashboardSession(\n endpoint: Endpoint,\n id: string,\n signal: AbortSignal,\n timeoutMs = 5_000,\n): Promise<DashboardSession> {\n const bounded = AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]);\n try {\n const response = await fetch(endpoint.url, {\n method: 'POST', headers: {authorization: `Bearer ${endpoint.token}`, 'content-type': 'application/json'},\n body: JSON.stringify({command: 'dashboard-session', id}), signal: bounded,\n });\n if (!response.ok) { await response.body?.cancel(); throw new Error('Rejected session'); }\n const session: unknown = JSON.parse(await response.text());\n if (isLegacyUnknownOperation(session)) throw outdatedCoordinator(endpoint, 'session');\n if (!isSession(session, id)) throw new Error('Invalid session');\n return session;\n } catch (error) {\n if (error instanceof AgentError) throw error;\n throw new AgentError('COORDINATOR_UNAVAILABLE', 'The dashboard lost its connection to the local coordinator or received invalid session history.');\n }\n}\n\nexport async function fetchDashboardSnapshot(endpoint: Endpoint, signal: AbortSignal, timeoutMs = 5_000): Promise<DashboardSnapshot> {\n const bounded = AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]);\n try {\n const response = await fetch(endpoint.url, {\n method: 'POST', headers: {authorization: `Bearer ${endpoint.token}`, 'content-type': 'application/json'},\n body: JSON.stringify({command: 'dashboard'}), signal: bounded,\n });\n if (!response.ok) { await response.body?.cancel(); throw new Error('Rejected snapshot'); }\n const snapshot: unknown = JSON.parse(await response.text());\n if (isLegacyUnknownOperation(snapshot)) throw outdatedCoordinator(endpoint);\n if (!isSnapshot(snapshot)) throw new Error('Invalid snapshot');\n if (snapshot.history !== true || snapshot.grouping !== true) {\n throw outdatedCoordinator(endpoint);\n }\n return {...snapshot, history: true, grouping: true};\n } catch (error) {\n if (error instanceof AgentError) throw error;\n throw new AgentError('COORDINATOR_UNAVAILABLE', 'The dashboard lost its connection to the local coordinator or received an invalid snapshot.');\n }\n}\n\nexport async function fetchDashboardDetail(\n endpoint: Endpoint,\n id: string,\n signal: AbortSignal,\n includePrompt = true,\n knownResponseId?: string,\n timeoutMs = 5_000,\n): Promise<DashboardDetailRecord> {\n const bounded = AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]);\n const request: Record<string, unknown> = {command: 'dashboard-detail', id};\n if (!includePrompt) request.includePrompt = false;\n if (knownResponseId !== undefined) request.knownResponseId = knownResponseId;\n try {\n const response = await fetch(endpoint.url, {\n method: 'POST', headers: {authorization: `Bearer ${endpoint.token}`, 'content-type': 'application/json'},\n body: JSON.stringify(request), signal: bounded,\n });\n if (!response.ok) { await response.body?.cancel(); throw new Error('Rejected detail'); }\n const detail: unknown = JSON.parse(await response.text());\n if (isLegacyUnknownOperation(detail)) throw outdatedCoordinator(endpoint, 'inspection');\n if (!isDetail(detail, id, includePrompt, knownResponseId)) throw new Error('Invalid detail');\n return detail;\n } catch (error) {\n if (error instanceof AgentError) throw error;\n throw new AgentError('COORDINATOR_UNAVAILABLE', 'The dashboard lost its connection to the local coordinator or received invalid task details.');\n }\n}\n"]}
@@ -0,0 +1,16 @@
1
+ import type { DashboardDetailRecord } from './dashboard-client.js';
2
+ export declare function wrapDashboardText(text: string, columns: number): string[];
3
+ export declare class DashboardDetailView {
4
+ private detail;
5
+ private wrapped;
6
+ private usedWraps;
7
+ private contentCache?;
8
+ constructor(detail: DashboardDetailRecord);
9
+ get taskId(): string;
10
+ get responseId(): string | undefined;
11
+ get workspace(): import("../runtime/dashboard.js").DashboardWorkspace;
12
+ get cachedWrapCount(): number;
13
+ update(detail: DashboardDetailRecord): void;
14
+ private wrap;
15
+ contentLines(columns: number): string[];
16
+ }