@narumitw/pi-subagents 3.3.2 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -24
- package/dist/child-communication-bridge.ts +3 -2
- package/dist/child-communication-bridge.ts.map +1 -1
- package/dist/child-readiness-probe.ts +114 -17
- package/dist/child-readiness-probe.ts.map +2 -2
- package/dist/chunks/{chunk-FY5HIU6Y.ts → chunk-5OXDVXXO.ts} +1 -1
- package/dist/chunks/{chunk-FY5HIU6Y.ts.map → chunk-5OXDVXXO.ts.map} +1 -1
- package/dist/chunks/chunk-B3RWNGDX.ts +192 -0
- package/dist/chunks/chunk-B3RWNGDX.ts.map +7 -0
- package/dist/chunks/{chunk-ZOAFWLDJ.ts → chunk-PRIDTAJL.ts} +4 -16
- package/dist/chunks/chunk-PRIDTAJL.ts.map +7 -0
- package/dist/chunks/{chunk-YMVSJ5GE.ts → chunk-YV2P6XJX.ts} +46 -17
- package/dist/chunks/chunk-YV2P6XJX.ts.map +7 -0
- package/dist/chunks/{menu-KAIUEWL7.ts → menu-2UH4ICLL.ts} +74 -3
- package/dist/chunks/menu-2UH4ICLL.ts.map +7 -0
- package/dist/index.ts +553 -292
- package/dist/index.ts.map +3 -3
- package/docs/attachments.md +9 -3
- package/docs/design-principles.md +3 -1
- package/docs/tools.md +15 -1
- package/package.json +6 -6
- package/src/broker-credentials.ts +44 -13
- package/src/child-communication-tools.ts +2 -19
- package/src/child-readiness-probe.ts +144 -18
- package/src/child-readiness.ts +118 -0
- package/src/menu.ts +82 -3
- package/src/message-broker.ts +23 -10
- package/src/process.ts +59 -167
- package/src/resource-attachments.ts +1 -3
- package/src/rpc-line-decoder.ts +61 -0
- package/src/runtime.ts +21 -9
- package/src/settings.ts +2 -2
- package/src/subagents.ts +110 -18
- package/src/tools.ts +83 -37
- package/src/types.ts +1 -0
- package/src/widget-renderer.ts +119 -0
- package/src/widget.ts +245 -121
- package/dist/chunks/chunk-3FCHXUKZ.ts +0 -98
- package/dist/chunks/chunk-3FCHXUKZ.ts.map +0 -7
- package/dist/chunks/chunk-YMVSJ5GE.ts.map +0 -7
- package/dist/chunks/chunk-ZOAFWLDJ.ts.map +0 -7
- package/dist/chunks/menu-KAIUEWL7.ts.map +0 -7
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// @generated by scripts/build-runtime.mjs; do not edit.
|
|
2
|
+
// @ts-nocheck -- generated entries use .ts extensions for Pi's Jiti loader.
|
|
3
|
+
import {
|
|
4
|
+
MAX_READINESS_FRAME_BYTES,
|
|
5
|
+
sanitizeTerminalText
|
|
6
|
+
} from "./chunk-YV2P6XJX.ts";
|
|
7
|
+
|
|
8
|
+
// src/attachment-utils.ts
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
10
|
+
import { realpathSync } from "node:fs";
|
|
11
|
+
import { readFile, stat } from "node:fs/promises";
|
|
12
|
+
import * as path from "node:path";
|
|
13
|
+
var ATTACHMENT_IGNORE_FILE_NAMES = [".gitignore", ".ignore", ".fdignore"];
|
|
14
|
+
function throwInvalidAttachmentIgnoreFile() {
|
|
15
|
+
throw new Error("Subagent attachment ignore files must be regular files.");
|
|
16
|
+
}
|
|
17
|
+
function throwIfAttachmentAborted(signal) {
|
|
18
|
+
if (!signal?.aborted) return;
|
|
19
|
+
const error = new Error("Subagent attachment validation was cancelled.");
|
|
20
|
+
error.name = "AbortError";
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
function isAbortError(error) {
|
|
24
|
+
return error instanceof Error && error.name === "AbortError";
|
|
25
|
+
}
|
|
26
|
+
function prefixIgnorePattern(line, prefix) {
|
|
27
|
+
const trimmed = line.trim();
|
|
28
|
+
if (!trimmed || trimmed.startsWith("#") && !trimmed.startsWith("\\#")) return null;
|
|
29
|
+
let pattern = line;
|
|
30
|
+
let negated = false;
|
|
31
|
+
if (pattern.startsWith("!")) {
|
|
32
|
+
negated = true;
|
|
33
|
+
pattern = pattern.slice(1);
|
|
34
|
+
} else if (pattern.startsWith("\\!")) {
|
|
35
|
+
pattern = pattern.slice(1);
|
|
36
|
+
}
|
|
37
|
+
if (pattern.startsWith("/")) pattern = pattern.slice(1);
|
|
38
|
+
const prefixed = prefix ? `${prefix}${pattern}` : pattern;
|
|
39
|
+
return negated ? `!${prefixed}` : prefixed;
|
|
40
|
+
}
|
|
41
|
+
async function addAttachmentIgnoreRules(ignoreMatcher, directory, rootDirectory, signal, accountForFile) {
|
|
42
|
+
const relativeDirectory = path.relative(rootDirectory, directory);
|
|
43
|
+
const prefix = relativeDirectory ? `${toPosixPath(relativeDirectory)}/` : "";
|
|
44
|
+
for (const filename of ATTACHMENT_IGNORE_FILE_NAMES) {
|
|
45
|
+
throwIfAttachmentAborted(signal);
|
|
46
|
+
const ignorePath = path.join(directory, filename);
|
|
47
|
+
let ignoreStats;
|
|
48
|
+
try {
|
|
49
|
+
ignoreStats = await stat(ignorePath);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
if (isAbortError(error)) throw error;
|
|
52
|
+
throwIfAttachmentAborted(signal);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (!ignoreStats.isFile()) throwInvalidAttachmentIgnoreFile();
|
|
56
|
+
accountForFile(ignorePath, ignoreStats.size);
|
|
57
|
+
try {
|
|
58
|
+
const content = await readFile(ignorePath, { encoding: "utf8", signal });
|
|
59
|
+
throwIfAttachmentAborted(signal);
|
|
60
|
+
const patterns = content.split(/\r?\n/u).map((line) => prefixIgnorePattern(line, prefix)).filter((line) => line !== null);
|
|
61
|
+
if (patterns.length > 0) ignoreMatcher.add(patterns);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (isAbortError(error)) throw error;
|
|
64
|
+
throwIfAttachmentAborted(signal);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function toPosixPath(value) {
|
|
69
|
+
return value.split(path.sep).join("/");
|
|
70
|
+
}
|
|
71
|
+
function toolSourceId(value) {
|
|
72
|
+
return createHash("sha256").update(value).digest("hex");
|
|
73
|
+
}
|
|
74
|
+
function realpath(value, label) {
|
|
75
|
+
try {
|
|
76
|
+
return realpathSync(value);
|
|
77
|
+
} catch {
|
|
78
|
+
throw new Error(`${label} path does not exist: ${sanitizeTerminalText(value).slice(0, 512)}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function isWithin(root, candidate) {
|
|
82
|
+
const relative2 = path.relative(root, candidate);
|
|
83
|
+
return relative2 === "" || !relative2.startsWith(`..${path.sep}`) && relative2 !== ".." && !path.isAbsolute(relative2);
|
|
84
|
+
}
|
|
85
|
+
function isRecord(value) {
|
|
86
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/child-readiness.ts
|
|
90
|
+
import * as fs from "node:fs";
|
|
91
|
+
import * as path2 from "node:path";
|
|
92
|
+
function isChildModelPair(value) {
|
|
93
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
94
|
+
const model = value;
|
|
95
|
+
return [model.provider, model.id].every(
|
|
96
|
+
(part) => typeof part === "string" && part.trim().length > 0 && ![...part].some((character) => {
|
|
97
|
+
const code = character.codePointAt(0) ?? 0;
|
|
98
|
+
return code <= 31 || code >= 127 && code <= 159;
|
|
99
|
+
})
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
function assertChildModelPair(value, expected) {
|
|
103
|
+
if (!isChildModelPair(value)) throw new Error("Subagent child model attestation returned an invalid model.");
|
|
104
|
+
if (value.provider !== expected.provider || value.id !== expected.model) {
|
|
105
|
+
throw new Error("Subagent child model does not match the requested provider and model.");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function assertChildModelState(value, expected) {
|
|
109
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
110
|
+
throw new Error("Subagent child model attestation returned invalid state.");
|
|
111
|
+
}
|
|
112
|
+
assertChildModelPair(value.model, expected);
|
|
113
|
+
}
|
|
114
|
+
function parseReadinessFrame(buffer, expectedToolCount) {
|
|
115
|
+
if (buffer.byteLength > MAX_READINESS_FRAME_BYTES) {
|
|
116
|
+
throw new Error("Subagent readiness frame exceeded its size limit.");
|
|
117
|
+
}
|
|
118
|
+
if (buffer.byteLength === 0) throw new Error("Subagent readiness pipe closed without a result.");
|
|
119
|
+
let text;
|
|
120
|
+
try {
|
|
121
|
+
text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(buffer);
|
|
122
|
+
} catch {
|
|
123
|
+
throw new Error("Subagent readiness pipe returned invalid UTF-8.");
|
|
124
|
+
}
|
|
125
|
+
const newline = text.indexOf("\n");
|
|
126
|
+
if (newline < 0 || newline !== text.length - 1) {
|
|
127
|
+
throw new Error("Subagent readiness pipe returned an invalid frame.");
|
|
128
|
+
}
|
|
129
|
+
let value;
|
|
130
|
+
try {
|
|
131
|
+
value = JSON.parse(text.slice(0, newline));
|
|
132
|
+
} catch {
|
|
133
|
+
throw new Error("Subagent readiness pipe returned malformed JSON.");
|
|
134
|
+
}
|
|
135
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
136
|
+
throw new Error("Subagent readiness pipe returned an invalid result.");
|
|
137
|
+
}
|
|
138
|
+
const record = value;
|
|
139
|
+
if (record.ok === true && Object.keys(record).length === 3 && Array.isArray(record.sources) && record.sources.length === expectedToolCount && record.sources.every((source) => typeof source === "string" && /^[a-f0-9]{64}$/u.test(source)) && isChildModelPair(record.model) && Object.keys(record.model).length === 2) {
|
|
140
|
+
return { ok: true, sources: record.sources, model: record.model };
|
|
141
|
+
}
|
|
142
|
+
if (record.ok === false && Object.keys(record).length === 2 && typeof record.error === "string" && record.error.length > 0 && Buffer.byteLength(record.error, "utf8") <= 8 * 1024) {
|
|
143
|
+
return { ok: false, error: sanitizeTerminalText(record.error) };
|
|
144
|
+
}
|
|
145
|
+
throw new Error("Subagent readiness pipe returned an invalid result.");
|
|
146
|
+
}
|
|
147
|
+
function assertTrustedChildResources(value, cwd) {
|
|
148
|
+
const invalid = () => new Error("Subagent child resource attestation returned invalid commands.");
|
|
149
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw invalid();
|
|
150
|
+
const commands = value.commands;
|
|
151
|
+
if (!Array.isArray(commands)) throw invalid();
|
|
152
|
+
let canonicalCwd;
|
|
153
|
+
try {
|
|
154
|
+
canonicalCwd = fs.realpathSync(cwd);
|
|
155
|
+
} catch {
|
|
156
|
+
throw invalid();
|
|
157
|
+
}
|
|
158
|
+
for (const command of commands) {
|
|
159
|
+
if (!command || typeof command !== "object" || Array.isArray(command)) throw invalid();
|
|
160
|
+
const entry = command;
|
|
161
|
+
if (entry.source !== "skill" && entry.source !== "prompt") continue;
|
|
162
|
+
const resourcePath = entry.sourceInfo?.path;
|
|
163
|
+
if (typeof resourcePath !== "string" || !resourcePath) throw invalid();
|
|
164
|
+
const lexicalPath = path2.resolve(cwd, resourcePath);
|
|
165
|
+
let canonicalPath;
|
|
166
|
+
try {
|
|
167
|
+
canonicalPath = fs.realpathSync(lexicalPath);
|
|
168
|
+
} catch {
|
|
169
|
+
throw invalid();
|
|
170
|
+
}
|
|
171
|
+
if (isWithin(cwd, lexicalPath) || isWithin(canonicalCwd, canonicalPath)) {
|
|
172
|
+
throw new Error("Subagent child cannot load project resources because the project is not trusted.");
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export {
|
|
178
|
+
throwIfAttachmentAborted,
|
|
179
|
+
isAbortError,
|
|
180
|
+
addAttachmentIgnoreRules,
|
|
181
|
+
toPosixPath,
|
|
182
|
+
toolSourceId,
|
|
183
|
+
realpath,
|
|
184
|
+
isWithin,
|
|
185
|
+
isRecord,
|
|
186
|
+
isChildModelPair,
|
|
187
|
+
assertChildModelPair,
|
|
188
|
+
assertChildModelState,
|
|
189
|
+
parseReadinessFrame,
|
|
190
|
+
assertTrustedChildResources
|
|
191
|
+
};
|
|
192
|
+
//# sourceMappingURL=chunk-B3RWNGDX.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/attachment-utils.ts", "../../src/child-readiness.ts"],
|
|
4
|
+
"sourcesContent": ["import { createHash } from \"node:crypto\";\nimport { realpathSync } from \"node:fs\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport type ignore from \"ignore\";\nimport { sanitizeTerminalText } from \"./message-broker.js\";\n\nconst ATTACHMENT_IGNORE_FILE_NAMES = [\".gitignore\", \".ignore\", \".fdignore\"];\n\nexport type IgnoreMatcher = ReturnType<typeof ignore>;\n\nfunction throwInvalidAttachmentIgnoreFile(): never {\n throw new Error(\"Subagent attachment ignore files must be regular files.\");\n}\n\nexport function throwIfAttachmentAborted(signal: AbortSignal | undefined): void {\n if (!signal?.aborted) return;\n const error = new Error(\"Subagent attachment validation was cancelled.\");\n error.name = \"AbortError\";\n throw error;\n}\n\nexport function isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === \"AbortError\";\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n const trimmed = line.trim();\n if (!trimmed || (trimmed.startsWith(\"#\") && !trimmed.startsWith(\"\\\\#\"))) return null;\n let pattern = line;\n let negated = false;\n if (pattern.startsWith(\"!\")) {\n negated = true;\n pattern = pattern.slice(1);\n } else if (pattern.startsWith(\"\\\\!\")) {\n pattern = pattern.slice(1);\n }\n if (pattern.startsWith(\"/\")) pattern = pattern.slice(1);\n const prefixed = prefix ? `${prefix}${pattern}` : pattern;\n return negated ? `!${prefixed}` : prefixed;\n}\n\nexport async function addAttachmentIgnoreRules(\n ignoreMatcher: IgnoreMatcher,\n directory: string,\n rootDirectory: string,\n signal: AbortSignal | undefined,\n accountForFile: (ignorePath: string, bytes: number) => void,\n): Promise<void> {\n const relativeDirectory = path.relative(rootDirectory, directory);\n const prefix = relativeDirectory ? `${toPosixPath(relativeDirectory)}/` : \"\";\n for (const filename of ATTACHMENT_IGNORE_FILE_NAMES) {\n throwIfAttachmentAborted(signal);\n const ignorePath = path.join(directory, filename);\n let ignoreStats: Awaited<ReturnType<typeof stat>>;\n try {\n ignoreStats = await stat(ignorePath);\n } catch (error) {\n if (isAbortError(error)) throw error;\n throwIfAttachmentAborted(signal);\n continue;\n }\n if (!ignoreStats.isFile()) throwInvalidAttachmentIgnoreFile();\n accountForFile(ignorePath, ignoreStats.size);\n try {\n const content = await readFile(ignorePath, { encoding: \"utf8\", signal });\n throwIfAttachmentAborted(signal);\n const patterns = content\n .split(/\\r?\\n/u)\n .map((line) => prefixIgnorePattern(line, prefix))\n .filter((line): line is string => line !== null);\n if (patterns.length > 0) ignoreMatcher.add(patterns);\n } catch (error) {\n if (isAbortError(error)) throw error;\n throwIfAttachmentAborted(signal);\n // Pi ignores unreadable ignore files.\n }\n }\n}\n\nexport function toPosixPath(value: string): string {\n return value.split(path.sep).join(\"/\");\n}\n\nexport function toolSourceId(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nexport function realpath(value: string, label: string): string {\n try {\n return realpathSync(value);\n } catch {\n throw new Error(`${label} path does not exist: ${sanitizeTerminalText(value).slice(0, 512)}`);\n }\n}\n\nexport function isWithin(root: string, candidate: string): boolean {\n const relative = path.relative(root, candidate);\n return relative === \"\" || (!relative.startsWith(`..${path.sep}`) && relative !== \"..\" && !path.isAbsolute(relative));\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n", "import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { isWithin } from \"./attachment-utils.js\";\nimport { MAX_READINESS_FRAME_BYTES } from \"./broker-credentials.js\";\nimport { sanitizeTerminalText } from \"./message-broker.js\";\n\nexport interface ChildModelPair {\n provider: string;\n id: string;\n}\n\nexport type ChildReadinessFrame = { ok: true; sources: string[]; model: ChildModelPair } | { ok: false; error: string };\n\nexport function isChildModelPair(value: unknown): value is ChildModelPair {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n const model = value as Record<string, unknown>;\n return [model.provider, model.id].every(\n (part) =>\n typeof part === \"string\" &&\n part.trim().length > 0 &&\n ![...part].some((character) => {\n const code = character.codePointAt(0) ?? 0;\n return code <= 0x1f || (code >= 0x7f && code <= 0x9f);\n }),\n );\n}\n\nexport function assertChildModelPair(value: unknown, expected: { provider: string; model: string }): void {\n if (!isChildModelPair(value)) throw new Error(\"Subagent child model attestation returned an invalid model.\");\n if (value.provider !== expected.provider || value.id !== expected.model) {\n throw new Error(\"Subagent child model does not match the requested provider and model.\");\n }\n}\n\nexport function assertChildModelState(value: unknown, expected: { provider: string; model: string }): void {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\"Subagent child model attestation returned invalid state.\");\n }\n assertChildModelPair((value as { model?: unknown }).model, expected);\n}\n\nexport function parseReadinessFrame(buffer: Buffer, expectedToolCount: number): ChildReadinessFrame {\n if (buffer.byteLength > MAX_READINESS_FRAME_BYTES) {\n throw new Error(\"Subagent readiness frame exceeded its size limit.\");\n }\n if (buffer.byteLength === 0) throw new Error(\"Subagent readiness pipe closed without a result.\");\n let text: string;\n try {\n text = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(buffer);\n } catch {\n throw new Error(\"Subagent readiness pipe returned invalid UTF-8.\");\n }\n const newline = text.indexOf(\"\\n\");\n if (newline < 0 || newline !== text.length - 1) {\n throw new Error(\"Subagent readiness pipe returned an invalid frame.\");\n }\n let value: unknown;\n try {\n value = JSON.parse(text.slice(0, newline));\n } catch {\n throw new Error(\"Subagent readiness pipe returned malformed JSON.\");\n }\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\"Subagent readiness pipe returned an invalid result.\");\n }\n const record = value as Record<string, unknown>;\n if (\n record.ok === true &&\n Object.keys(record).length === 3 &&\n Array.isArray(record.sources) &&\n record.sources.length === expectedToolCount &&\n record.sources.every((source) => typeof source === \"string\" && /^[a-f0-9]{64}$/u.test(source)) &&\n isChildModelPair(record.model) &&\n Object.keys(record.model).length === 2\n ) {\n return { ok: true, sources: record.sources, model: record.model };\n }\n if (\n record.ok === false &&\n Object.keys(record).length === 2 &&\n typeof record.error === \"string\" &&\n record.error.length > 0 &&\n Buffer.byteLength(record.error, \"utf8\") <= 8 * 1024\n ) {\n return { ok: false, error: sanitizeTerminalText(record.error) };\n }\n throw new Error(\"Subagent readiness pipe returned an invalid result.\");\n}\n\nexport function assertTrustedChildResources(value: unknown, cwd: string): void {\n const invalid = () => new Error(\"Subagent child resource attestation returned invalid commands.\");\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalid();\n const commands = (value as { commands?: unknown }).commands;\n if (!Array.isArray(commands)) throw invalid();\n let canonicalCwd: string;\n try {\n canonicalCwd = fs.realpathSync(cwd);\n } catch {\n throw invalid();\n }\n for (const command of commands) {\n if (!command || typeof command !== \"object\" || Array.isArray(command)) throw invalid();\n const entry = command as { source?: unknown; sourceInfo?: { path?: unknown } };\n if (entry.source !== \"skill\" && entry.source !== \"prompt\") continue;\n const resourcePath = entry.sourceInfo?.path;\n if (typeof resourcePath !== \"string\" || !resourcePath) throw invalid();\n const lexicalPath = path.resolve(cwd, resourcePath);\n let canonicalPath: string;\n try {\n canonicalPath = fs.realpathSync(lexicalPath);\n } catch {\n throw invalid();\n }\n if (isWithin(cwd, lexicalPath) || isWithin(canonicalCwd, canonicalPath)) {\n throw new Error(\"Subagent child cannot load project resources because the project is not trusted.\");\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["relative", "path"]
|
|
7
|
+
}
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
import {
|
|
4
4
|
MAX_IDENTIFIER_LENGTH,
|
|
5
5
|
MAX_MESSAGE_BYTES,
|
|
6
|
+
optionalIdentifier,
|
|
7
|
+
requiredIdentifier,
|
|
6
8
|
sanitizeTerminalText,
|
|
7
9
|
validateMessage
|
|
8
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-YV2P6XJX.ts";
|
|
9
11
|
|
|
10
12
|
// src/child-communication-tools.ts
|
|
11
13
|
import { Type } from "typebox";
|
|
@@ -106,20 +108,6 @@ function createChildCommunicationExtension(client) {
|
|
|
106
108
|
function prepareWaitArguments(args) {
|
|
107
109
|
return prepareTimeoutArguments(args);
|
|
108
110
|
}
|
|
109
|
-
function optionalIdentifier(value, field) {
|
|
110
|
-
return value === void 0 ? void 0 : requiredIdentifier(value, field);
|
|
111
|
-
}
|
|
112
|
-
function requiredIdentifier(value, field) {
|
|
113
|
-
if (typeof value !== "string" || !value.trim()) throw new Error(`Subagent ${field} is required.`);
|
|
114
|
-
const identifier = value.trim();
|
|
115
|
-
if (identifier.length > MAX_IDENTIFIER_LENGTH || [...identifier].some((character) => {
|
|
116
|
-
const codePoint = character.codePointAt(0) ?? 0;
|
|
117
|
-
return codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
|
|
118
|
-
})) {
|
|
119
|
-
throw new Error(`Subagent ${field} is invalid.`);
|
|
120
|
-
}
|
|
121
|
-
return identifier;
|
|
122
|
-
}
|
|
123
111
|
|
|
124
112
|
export {
|
|
125
113
|
resolveTimeoutMs,
|
|
@@ -127,4 +115,4 @@ export {
|
|
|
127
115
|
CHILD_COMMUNICATION_TOOL_NAMES,
|
|
128
116
|
createChildCommunicationExtension
|
|
129
117
|
};
|
|
130
|
-
//# sourceMappingURL=chunk-
|
|
118
|
+
//# sourceMappingURL=chunk-PRIDTAJL.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/child-communication-tools.ts", "../../src/timeout.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ExtensionFactory } from \"@earendil-works/pi-coding-agent\";\nimport { type Static, Type } from \"typebox\";\nimport {\n type BrokerSendAcknowledgement,\n MAX_IDENTIFIER_LENGTH,\n MAX_MESSAGE_BYTES,\n optionalIdentifier,\n requiredIdentifier,\n sanitizeTerminalText,\n validateMessage,\n} from \"./message-broker.js\";\nimport { prepareTimeoutArguments, resolveTimeoutMs } from \"./timeout.js\";\n\nexport const CHILD_COMMUNICATION_TOOL_NAMES = [\"subagent_send\", \"subagent_wait\"] as const;\n\nconst SendParameters = Type.Object(\n {\n requestId: Type.Optional(\n Type.String({\n description: \"Pending main-agent request to answer. Omit when starting a new request.\",\n minLength: 1,\n maxLength: MAX_IDENTIFIER_LENGTH,\n }),\n ),\n message: Type.String({\n description: \"Plain-text request or response. Maximum 48 KiB of UTF-8 text and 1,992 lines.\",\n minLength: 1,\n maxLength: MAX_MESSAGE_BYTES,\n }),\n },\n { additionalProperties: false },\n);\n\nconst WaitParameters = Type.Object(\n {\n requestId: Type.String({\n description: \"Request ID returned by subagent_send.\",\n minLength: 1,\n maxLength: MAX_IDENTIFIER_LENGTH,\n }),\n timeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n },\n { additionalProperties: false },\n);\n\ntype ChildBrokerSendArguments = { recipient: \"main\"; message: string } | { requestId: string; message: string };\n\ntype WaitArguments = Static<typeof WaitParameters>;\n\nexport interface ChildCommunicationClient {\n send(params: ChildBrokerSendArguments, signal?: AbortSignal): Promise<BrokerSendAcknowledgement>;\n wait(requestId: string, timeoutMs: number | undefined, signal?: AbortSignal): Promise<string>;\n}\n\nexport function createChildCommunicationExtension(client: ChildCommunicationClient): ExtensionFactory {\n return (pi) => {\n pi.registerTool({\n name: \"subagent_send\",\n label: \"Subagent \u00B7 Send to Main\",\n description:\n \"Use subagent_send to send one request to the main agent or answer one pending main-agent request. Omit requestId to start a request. Provide requestId to answer that request.\",\n promptSnippet: \"Use subagent_send to send or answer one main-agent message\",\n parameters: SendParameters,\n async execute(_toolCallId, params, signal) {\n validateMessage(params.message, \"Subagent message\");\n const requestId = optionalIdentifier(params.requestId, \"requestId\");\n const acknowledgement = await client.send(\n requestId === undefined\n ? { recipient: \"main\", message: params.message }\n : { requestId, message: params.message },\n signal,\n );\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(acknowledgement) }],\n details: acknowledgement,\n };\n },\n });\n\n pi.registerTool({\n name: \"subagent_wait\",\n label: \"Subagent \u00B7 Wait for Main Agent\",\n description:\n \"Use subagent_wait with a request ID from subagent_send to wait for the main agent's plain-text response. A timeout, caller cancellation, or incoming main-agent request stops only this wait and does not cancel the original request. Retry the wait when its response is still needed.\",\n promptSnippet: \"Use subagent_wait to receive a requested main-agent response\",\n parameters: WaitParameters,\n prepareArguments: prepareWaitArguments,\n async execute(_toolCallId, params, signal) {\n const requestId = requiredIdentifier(params.requestId, \"requestId\");\n const response = await client.wait(requestId, resolveTimeoutMs(params.timeout), signal);\n return {\n content: [{ type: \"text\" as const, text: sanitizeTerminalText(response) }],\n details: { requestId },\n };\n },\n });\n };\n}\n\nfunction prepareWaitArguments(args: unknown): WaitArguments {\n return prepareTimeoutArguments(args) as WaitArguments;\n}\n", "const MAX_TIMEOUT_MS = 2_147_483_647;\nconst MAX_TIMEOUT_SECONDS = MAX_TIMEOUT_MS / 1000;\n\nexport function resolveTimeoutMs(timeout: number | undefined): number | undefined {\n if (timeout === undefined) return undefined;\n if (!Number.isFinite(timeout) || timeout <= 0) {\n throw new Error(\"Invalid timeout: must be a finite number of seconds\");\n }\n const timeoutMs = timeout * 1000;\n if (timeoutMs > MAX_TIMEOUT_MS) {\n throw new Error(`Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`);\n }\n return timeoutMs;\n}\n\nexport function prepareTimeoutArguments(args: unknown): Record<string, unknown> {\n if (!args || typeof args !== \"object\") return args as Record<string, unknown>;\n if (!Object.hasOwn(args, \"timeoutMs\")) return args as Record<string, unknown>;\n const record = args as Record<string, unknown>;\n if (typeof record.timeoutMs !== \"number\") return record;\n const { timeoutMs, ...prepared } = record;\n if (prepared.timeout === undefined) return { ...prepared, timeout: timeoutMs / 1000 };\n return prepared;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// @generated by scripts/build-runtime.mjs; do not edit.
|
|
2
2
|
// @ts-nocheck -- generated entries use .ts extensions for Pi's Jiti loader.
|
|
3
|
+
import {
|
|
4
|
+
SUBAGENT_THINKING_LEVELS
|
|
5
|
+
} from "./chunk-5OXDVXXO.ts";
|
|
3
6
|
|
|
4
7
|
// src/message-broker.ts
|
|
5
8
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
@@ -94,7 +97,7 @@ var MessageBroker = class {
|
|
|
94
97
|
throw new Error(`Subagent messaging credentials already exist for ${input.jobId}.`);
|
|
95
98
|
}
|
|
96
99
|
const token = randomBytes(32).toString("hex");
|
|
97
|
-
const record = { ...input
|
|
100
|
+
const record = { ...input };
|
|
98
101
|
this.jobsByToken.set(token, record);
|
|
99
102
|
this.tokenByJob.set(input.jobId, token);
|
|
100
103
|
return { host: BROKER_HOST, port: this.address?.port ?? 0, token };
|
|
@@ -202,10 +205,7 @@ var MessageBroker = class {
|
|
|
202
205
|
requestId: `req_${randomUUID()}`,
|
|
203
206
|
jobId: job.jobId,
|
|
204
207
|
generation: job.generation,
|
|
205
|
-
origin
|
|
206
|
-
expectedResponder: origin === "main" ? "child" : "main",
|
|
207
|
-
message,
|
|
208
|
-
createdAt: this.now()
|
|
208
|
+
origin
|
|
209
209
|
};
|
|
210
210
|
this.requests.set(request.requestId, request);
|
|
211
211
|
if (origin === "child") {
|
|
@@ -214,7 +214,7 @@ var MessageBroker = class {
|
|
|
214
214
|
kind: "request",
|
|
215
215
|
requestId: request.requestId,
|
|
216
216
|
jobId: request.jobId,
|
|
217
|
-
message
|
|
217
|
+
message
|
|
218
218
|
});
|
|
219
219
|
} catch (error) {
|
|
220
220
|
this.requests.delete(request.requestId);
|
|
@@ -227,7 +227,7 @@ var MessageBroker = class {
|
|
|
227
227
|
validateRequestId(requestId);
|
|
228
228
|
validateMessage(message, "Subagent response");
|
|
229
229
|
const request = this.requests.get(requestId);
|
|
230
|
-
if (!request || request.
|
|
230
|
+
if (!request || request.origin === responder || job && (request.jobId !== job.jobId || request.generation !== job.generation)) {
|
|
231
231
|
throw new Error("Unknown, expired, or unauthorized subagent request.");
|
|
232
232
|
}
|
|
233
233
|
if (request.response !== void 0) {
|
|
@@ -426,6 +426,20 @@ var MessageBroker = class {
|
|
|
426
426
|
this.address = void 0;
|
|
427
427
|
}
|
|
428
428
|
};
|
|
429
|
+
function optionalIdentifier(value, field) {
|
|
430
|
+
return value === void 0 ? void 0 : requiredIdentifier(value, field);
|
|
431
|
+
}
|
|
432
|
+
function requiredIdentifier(value, field) {
|
|
433
|
+
if (typeof value !== "string" || !value.trim()) throw new Error(`Subagent ${field} is required.`);
|
|
434
|
+
const identifier = value.trim();
|
|
435
|
+
if (identifier.length > MAX_IDENTIFIER_LENGTH || [...identifier].some((character) => {
|
|
436
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
437
|
+
return codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
|
|
438
|
+
})) {
|
|
439
|
+
throw new Error(`Subagent ${field} is invalid.`);
|
|
440
|
+
}
|
|
441
|
+
return identifier;
|
|
442
|
+
}
|
|
429
443
|
function validateMessage(message, label) {
|
|
430
444
|
if (!message.trim()) throw new Error(`${label} is required.`);
|
|
431
445
|
if (message.includes("\0")) throw new Error(`${label} must not contain NUL bytes.`);
|
|
@@ -492,13 +506,16 @@ function childBootstrapEnvironment(expectReadiness) {
|
|
|
492
506
|
function serializeChildBootstrap(bootstrap) {
|
|
493
507
|
return JSON.stringify(bootstrap);
|
|
494
508
|
}
|
|
495
|
-
function assertChildBootstrapCapacity(expectedTools) {
|
|
509
|
+
function assertChildBootstrapCapacity(expectedTools, selection) {
|
|
496
510
|
const serialized = serializeChildBootstrap({
|
|
497
511
|
communication: { host: "127.0.0.1", port: 65535, token: "f".repeat(64) },
|
|
498
|
-
expectedTools
|
|
512
|
+
expectedTools,
|
|
513
|
+
selection
|
|
499
514
|
});
|
|
500
515
|
if (Buffer.byteLength(serialized, "utf8") > MAX_BOOTSTRAP_BYTES) {
|
|
501
|
-
throw new Error(
|
|
516
|
+
throw new Error(
|
|
517
|
+
`Subagent tools and model selection exceed the ${MAX_BOOTSTRAP_BYTES}-byte child bootstrap size limit.`
|
|
518
|
+
);
|
|
502
519
|
}
|
|
503
520
|
}
|
|
504
521
|
function captureChildBootstrap(readBootstrap = readBootstrapPipe) {
|
|
@@ -534,8 +551,12 @@ function captureChildBootstrap(readBootstrap = readBootstrapPipe) {
|
|
|
534
551
|
if (readinessDescriptor !== String(CHILD_READINESS_FD)) {
|
|
535
552
|
throw new Error("Invalid pi-subagents readiness descriptor.");
|
|
536
553
|
}
|
|
537
|
-
setCapturedReadiness({
|
|
538
|
-
|
|
554
|
+
setCapturedReadiness({
|
|
555
|
+
fd: CHILD_READINESS_FD,
|
|
556
|
+
expectedTools: [...value.expectedTools],
|
|
557
|
+
selection: { ...value.selection }
|
|
558
|
+
});
|
|
559
|
+
return { ...value, selection: { ...value.selection }, readinessFd: CHILD_READINESS_FD };
|
|
539
560
|
}
|
|
540
561
|
if (readinessDescriptor !== void 0) throw new Error("Unexpected pi-subagents readiness descriptor.");
|
|
541
562
|
setCapturedReadiness(void 0);
|
|
@@ -545,7 +566,7 @@ function takeCapturedReadiness() {
|
|
|
545
566
|
const store = globalThis;
|
|
546
567
|
const readiness = store[READINESS_STATE_KEY];
|
|
547
568
|
delete store[READINESS_STATE_KEY];
|
|
548
|
-
return readiness ? { fd: readiness.fd, expectedTools: [...readiness.expectedTools] } : void 0;
|
|
569
|
+
return readiness ? { fd: readiness.fd, expectedTools: [...readiness.expectedTools], selection: { ...readiness.selection } } : void 0;
|
|
549
570
|
}
|
|
550
571
|
function setCapturedReadiness(readiness) {
|
|
551
572
|
const store = globalThis;
|
|
@@ -563,13 +584,19 @@ function readBootstrapPipe() {
|
|
|
563
584
|
}
|
|
564
585
|
}
|
|
565
586
|
function isChildBootstrap(value) {
|
|
566
|
-
if (!isRecord2(value) || Object.keys(value).length !==
|
|
567
|
-
if (!isBrokerCredentials(value.communication)) return false;
|
|
587
|
+
if (!isRecord2(value) || Object.keys(value).length !== 3) return false;
|
|
588
|
+
if (!isBrokerCredentials(value.communication) || !isChildSelection(value.selection)) return false;
|
|
568
589
|
if (!Array.isArray(value.expectedTools) || value.expectedTools.length > MAX_EXPECTED_TOOLS) return false;
|
|
569
590
|
return value.expectedTools.every(
|
|
570
591
|
(tool) => typeof tool === "string" && tool.length > 0 && tool.length <= MAX_TOOL_NAME_LENGTH && !tool.includes(",") && !hasControlCharacter(tool)
|
|
571
592
|
);
|
|
572
593
|
}
|
|
594
|
+
function isChildSelection(value) {
|
|
595
|
+
if (!isRecord2(value) || Object.keys(value).length !== 3) return false;
|
|
596
|
+
return [value.provider, value.model].every(
|
|
597
|
+
(id) => typeof id === "string" && id.trim().length > 0 && !hasControlCharacter(id)
|
|
598
|
+
) && SUBAGENT_THINKING_LEVELS.includes(value.thinkingLevel);
|
|
599
|
+
}
|
|
573
600
|
function isBrokerCredentials(value) {
|
|
574
601
|
if (!isRecord2(value) || Object.keys(value).length !== 3) return false;
|
|
575
602
|
return value.host === "127.0.0.1" && Number.isSafeInteger(value.port) && value.port >= 1 && value.port <= 65535 && typeof value.token === "string" && /^[a-f0-9]{64}$/u.test(value.token);
|
|
@@ -589,16 +616,18 @@ export {
|
|
|
589
616
|
MAX_FRAME_BYTES,
|
|
590
617
|
MAX_IDENTIFIER_LENGTH,
|
|
591
618
|
MessageBroker,
|
|
619
|
+
optionalIdentifier,
|
|
620
|
+
requiredIdentifier,
|
|
592
621
|
validateMessage,
|
|
593
622
|
sanitizeTerminalText,
|
|
594
623
|
BROKER_CREDENTIAL_FD,
|
|
595
624
|
CHILD_READINESS_FD,
|
|
596
|
-
CHILD_READINESS_FD_ENV,
|
|
597
625
|
MAX_READINESS_FRAME_BYTES,
|
|
626
|
+
MAX_BOOTSTRAP_BYTES,
|
|
598
627
|
childBootstrapEnvironment,
|
|
599
628
|
serializeChildBootstrap,
|
|
600
629
|
assertChildBootstrapCapacity,
|
|
601
630
|
captureChildBootstrap,
|
|
602
631
|
takeCapturedReadiness
|
|
603
632
|
};
|
|
604
|
-
//# sourceMappingURL=chunk-
|
|
633
|
+
//# sourceMappingURL=chunk-YV2P6XJX.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/message-broker.ts", "../../src/broker-credentials.ts"],
|
|
4
|
+
"sourcesContent": ["import { randomBytes, randomUUID } from \"node:crypto\";\nimport net, { type AddressInfo, type Server, type Socket } from \"node:net\";\nimport type { BrokerCredentials } from \"./types.js\";\n\nexport const BROKER_HOST = \"127.0.0.1\" as const;\nexport const MAX_MESSAGE_BYTES = 48 * 1024;\nexport const MAX_MESSAGE_LINES = 1_992;\nexport const MAX_FRAME_BYTES = 384 * 1024;\nexport const MAX_ERROR_BYTES = 8 * 1024;\nexport const MAX_OUTSTANDING_REQUESTS = 4;\nexport const MAX_IDENTIFIER_LENGTH = 128;\n\nconst MAX_CONNECTIONS = 32;\nconst REQUEST_FRAME_TIMEOUT_MS = 2_000;\nconst MAX_TIMEOUT_MS = 2_147_483_647;\nconst MAX_RETAINED_CONSUMED_REQUESTS = 4;\nconst CHILD_WAIT_INTERRUPTED_ERROR =\n \"Subagent wait was interrupted by an incoming main-agent request. The original request remains active.\";\n\nexport type BrokerRequestOrigin = \"main\" | \"child\";\n\nexport interface BrokerInboundMessage {\n kind: \"request\" | \"response\";\n requestId: string;\n jobId: string;\n message: string;\n}\n\nexport interface BrokerSendAcknowledgement {\n requestId: string;\n accepted: boolean;\n duplicate: boolean;\n}\n\nexport interface MessageBrokerOptions {\n onMessage(message: BrokerInboundMessage): void;\n createServer?: (listener: (socket: Socket) => void) => Server;\n now?: () => number;\n requestFrameTimeoutMs?: number;\n}\n\ninterface JobRecord {\n jobId: string;\n generation: number;\n}\n\ninterface RequestWaiter {\n socket: Socket;\n timer?: NodeJS.Timeout;\n}\n\ninterface RequestRecord {\n requestId: string;\n jobId: string;\n generation: number;\n origin: BrokerRequestOrigin;\n response?: string;\n consumedAt?: number;\n deliveryQueued?: boolean;\n waiter?: RequestWaiter;\n}\n\ntype BrokerRequest =\n | {\n type: \"send\";\n token: string;\n recipient?: string;\n requestId?: string;\n message: string;\n }\n | { type: \"wait\"; token: string; requestId: string; timeoutMs?: number };\n\n/** Session-scoped authenticated loopback transport for bidirectional requests and responses. */\nexport class MessageBroker {\n private server?: Server;\n private starting?: Promise<void>;\n private address?: { host: typeof BROKER_HOST; port: number };\n private failure?: string;\n private generation = 0;\n private readonly sockets = new Set<Socket>();\n private readonly jobsByToken = new Map<string, JobRecord>();\n private readonly tokenByJob = new Map<string, string>();\n private readonly requests = new Map<string, RequestRecord>();\n private readonly inboundMessageListeners = new Set<() => void>();\n private pendingInboundResponse = false;\n private readonly createServer: (listener: (socket: Socket) => void) => Server;\n private readonly now: () => number;\n private readonly requestFrameTimeoutMs: number;\n\n constructor(private readonly options: MessageBrokerOptions) {\n this.createServer = options.createServer ?? ((listener) => net.createServer(listener));\n this.now = options.now ?? Date.now;\n this.requestFrameTimeoutMs = options.requestFrameTimeoutMs ?? REQUEST_FRAME_TIMEOUT_MS;\n if (!Number.isFinite(this.requestFrameTimeoutMs) || this.requestFrameTimeoutMs <= 0) {\n throw new Error(\"Subagent broker frame timeout must be positive.\");\n }\n }\n\n async start(): Promise<void> {\n if (this.server && this.address && !this.failure) return;\n if (this.starting) return this.starting;\n const ownerGeneration = ++this.generation;\n this.failure = undefined;\n this.starting = new Promise<void>((resolve, reject) => {\n const server = this.createServer((socket) => this.accept(socket));\n server.maxConnections = MAX_CONNECTIONS;\n const onStartError = (error: Error) => {\n server.close(() => undefined);\n reject(error);\n };\n server.once(\"error\", onStartError);\n server.listen({ host: BROKER_HOST, port: 0 }, () => {\n server.off(\"error\", onStartError);\n if (ownerGeneration !== this.generation) {\n server.close(() => undefined);\n reject(new Error(\"Subagent message broker start was superseded.\"));\n return;\n }\n const address = server.address();\n if (!isLoopbackAddress(address)) {\n server.close(() => undefined);\n reject(new Error(\"Subagent message broker did not bind to loopback.\"));\n return;\n }\n this.server = server;\n this.address = { host: BROKER_HOST, port: address.port };\n server.on(\"error\", (error) => this.fail(error));\n server.unref();\n resolve();\n });\n })\n .catch((error) => {\n const message = truncateError(error instanceof Error ? error.message : String(error));\n this.failure = message;\n throw new Error(`Subagent message broker failed to start: ${message}`);\n })\n .finally(() => {\n this.starting = undefined;\n });\n return this.starting;\n }\n\n assertReady(): void {\n if (this.server && this.address && !this.failure) return;\n throw new Error(\n this.failure\n ? `Subagent messaging is unavailable: ${this.failure}`\n : \"Subagent messaging is unavailable because the session broker is not ready.\",\n );\n }\n\n issueCredentials(input: { jobId: string; generation: number }): BrokerCredentials {\n this.assertReady();\n if (this.tokenByJob.has(input.jobId)) {\n throw new Error(`Subagent messaging credentials already exist for ${input.jobId}.`);\n }\n const token = randomBytes(32).toString(\"hex\");\n const record: JobRecord = { ...input };\n this.jobsByToken.set(token, record);\n this.tokenByJob.set(input.jobId, token);\n return { host: BROKER_HOST, port: this.address?.port ?? 0, token };\n }\n\n createMainRequest(jobId: string, message: string): BrokerSendAcknowledgement {\n this.assertReady();\n const job = this.requireJob(jobId);\n return this.createRequest(job, \"main\", message);\n }\n\n replyFromMain(requestId: string, message: string): BrokerSendAcknowledgement {\n this.assertReady();\n return this.acceptResponse(\"main\", undefined, requestId, message);\n }\n\n rollbackMainRequest(requestId: string): void {\n const request = this.requests.get(requestId);\n if (request?.origin === \"main\" && request.response === undefined) {\n this.clearWaiter(request);\n this.requests.delete(requestId);\n }\n }\n\n revokeJob(jobId: string, reason = \"Subagent job is no longer active.\"): void {\n const token = this.tokenByJob.get(jobId);\n if (token) {\n this.tokenByJob.delete(jobId);\n this.jobsByToken.delete(token);\n }\n for (const request of [...this.requests.values()]) {\n if (request.jobId !== jobId) continue;\n if (request.waiter) this.respondError(request.waiter.socket, reason);\n this.clearWaiter(request);\n this.requests.delete(request.requestId);\n }\n }\n\n hasPendingMainRequest(): boolean {\n return [...this.requests.values()].some((request) => request.origin === \"child\" && request.response === undefined);\n }\n\n takePendingInboundResponse(): boolean {\n const pending = this.pendingInboundResponse;\n this.pendingInboundResponse = false;\n return pending;\n }\n\n markMainRequestQueued(requestId: string): boolean {\n const request = this.requests.get(requestId);\n if (request?.origin !== \"main\") {\n throw new Error(\"Unknown or expired main-agent subagent request.\");\n }\n request.deliveryQueued = true;\n return request.response === undefined;\n }\n\n interruptChildWaits(jobId: string): number {\n let interrupted = 0;\n for (const request of this.requests.values()) {\n if (request.jobId !== jobId || request.origin !== \"child\" || !request.waiter) continue;\n const socket = request.waiter.socket;\n this.clearWaiter(request);\n this.respondError(socket, CHILD_WAIT_INTERRUPTED_ERROR);\n interrupted++;\n }\n return interrupted;\n }\n\n subscribeInboundMessage(listener: () => void): () => void {\n this.inboundMessageListeners.add(listener);\n if (this.hasPendingMainRequest()) listener();\n return () => this.inboundMessageListeners.delete(listener);\n }\n\n async shutdown(): Promise<void> {\n ++this.generation;\n const starting = this.starting;\n if (starting) await starting.catch(() => undefined);\n for (const jobId of [...this.tokenByJob.keys()]) {\n this.revokeJob(jobId, \"Subagent session shut down.\");\n }\n this.requests.clear();\n this.inboundMessageListeners.clear();\n this.pendingInboundResponse = false;\n for (const socket of this.sockets) socket.destroy();\n this.sockets.clear();\n const server = this.server;\n this.server = undefined;\n this.address = undefined;\n this.failure = undefined;\n if (!server?.listening) return;\n await new Promise<void>((resolve) => server.close(() => resolve()));\n }\n\n private requireJob(jobId: string): JobRecord {\n const token = this.tokenByJob.get(jobId);\n const job = token ? this.jobsByToken.get(token) : undefined;\n if (!job) throw new Error(\"Unknown or inactive subagent job.\");\n return job;\n }\n\n private hasQueuedRequestForChild(jobId: string): boolean {\n return [...this.requests.values()].some(\n (request) =>\n request.jobId === jobId &&\n request.origin === \"main\" &&\n request.deliveryQueued === true &&\n request.response === undefined,\n );\n }\n\n private createRequest(job: JobRecord, origin: BrokerRequestOrigin, message: string): BrokerSendAcknowledgement {\n validateMessage(message, \"Subagent request\");\n const outstanding = [...this.requests.values()].filter(\n (request) => request.jobId === job.jobId && request.consumedAt === undefined,\n ).length;\n if (outstanding >= MAX_OUTSTANDING_REQUESTS) {\n throw new Error(`Subagent job may have at most ${MAX_OUTSTANDING_REQUESTS} outstanding requests.`);\n }\n const request: RequestRecord = {\n requestId: `req_${randomUUID()}`,\n jobId: job.jobId,\n generation: job.generation,\n origin,\n };\n this.requests.set(request.requestId, request);\n if (origin === \"child\") {\n try {\n this.deliverInbound({\n kind: \"request\",\n requestId: request.requestId,\n jobId: request.jobId,\n message,\n });\n } catch (error) {\n this.requests.delete(request.requestId);\n throw error;\n }\n }\n return { requestId: request.requestId, accepted: true, duplicate: false };\n }\n\n private acceptResponse(\n responder: BrokerRequestOrigin,\n job: JobRecord | undefined,\n requestId: string,\n message: string,\n ): BrokerSendAcknowledgement {\n validateRequestId(requestId);\n validateMessage(message, \"Subagent response\");\n const request = this.requests.get(requestId);\n if (\n !request ||\n request.origin === responder ||\n (job && (request.jobId !== job.jobId || request.generation !== job.generation))\n ) {\n throw new Error(\"Unknown, expired, or unauthorized subagent request.\");\n }\n if (request.response !== undefined) {\n return { requestId, accepted: false, duplicate: true };\n }\n request.response = message;\n if (responder === \"child\") {\n try {\n this.deliverInbound({\n kind: \"response\",\n requestId,\n jobId: request.jobId,\n message,\n });\n this.markConsumed(request);\n } catch (error) {\n request.response = undefined;\n throw error;\n }\n } else if (request.waiter) {\n const socket = request.waiter.socket;\n this.clearWaiter(request);\n this.respond(socket, { ok: true, response: message }, () => this.markConsumed(request));\n }\n return { requestId, accepted: true, duplicate: false };\n }\n\n private deliverInbound(message: BrokerInboundMessage): void {\n this.options.onMessage(message);\n if (message.kind === \"response\" && this.inboundMessageListeners.size === 0) {\n this.pendingInboundResponse = true;\n }\n for (const listener of [...this.inboundMessageListeners]) {\n try {\n listener();\n } catch {\n // Runtime wait observers cannot interrupt broker delivery.\n }\n }\n }\n\n private accept(socket: Socket): void {\n if (!this.server || this.failure || this.sockets.size >= MAX_CONNECTIONS) {\n socket.destroy();\n return;\n }\n this.sockets.add(socket);\n socket.setNoDelay(true);\n let frame = Buffer.alloc(0);\n let handled = false;\n const frameTimer = setTimeout(() => {\n if (handled) return;\n handled = true;\n this.respondError(socket, \"Subagent broker request frame timed out.\");\n }, this.requestFrameTimeoutMs);\n frameTimer.unref();\n const cleanup = () => {\n clearTimeout(frameTimer);\n this.sockets.delete(socket);\n for (const request of this.requests.values()) {\n if (request.waiter?.socket === socket) this.clearWaiter(request);\n }\n };\n socket.on(\"data\", (chunk: Buffer) => {\n if (handled) return;\n frame = Buffer.concat([frame, chunk]);\n if (frame.byteLength > MAX_FRAME_BYTES) {\n handled = true;\n clearTimeout(frameTimer);\n this.respondError(socket, \"Subagent broker request exceeded its size limit.\");\n return;\n }\n const newline = frame.indexOf(0x0a);\n if (newline < 0) return;\n handled = true;\n clearTimeout(frameTimer);\n socket.removeAllListeners(\"data\");\n const trailing = frame\n .subarray(newline + 1)\n .toString(\"utf8\")\n .trim();\n if (trailing) {\n this.respondError(socket, \"Subagent broker accepts one request per connection.\");\n return;\n }\n this.handleFrame(socket, frame.subarray(0, newline).toString(\"utf8\"));\n });\n socket.once(\"close\", cleanup);\n socket.once(\"error\", cleanup);\n }\n\n private handleFrame(socket: Socket, frame: string): void {\n let request: BrokerRequest;\n try {\n const parsed = JSON.parse(frame) as unknown;\n if (!isRecord(parsed)) throw new Error();\n request = parsed as BrokerRequest;\n } catch {\n this.respondError(socket, \"Malformed subagent broker request.\");\n return;\n }\n const job = typeof request.token === \"string\" ? this.jobsByToken.get(request.token) : undefined;\n if (!job) {\n this.respondError(socket, \"Unauthenticated subagent broker request.\");\n return;\n }\n try {\n if (request.type === \"send\") {\n this.handleSend(socket, job, request);\n return;\n }\n if (request.type === \"wait\") {\n this.handleWait(socket, job, request);\n return;\n }\n throw new Error(\"Unsupported subagent broker request.\");\n } catch (error) {\n this.respondError(socket, error instanceof Error ? error.message : String(error));\n }\n }\n\n private handleSend(socket: Socket, job: JobRecord, request: Extract<BrokerRequest, { type: \"send\" }>): void {\n if (typeof request.message !== \"string\") {\n throw new Error(\"subagent_send requires a message string.\");\n }\n const hasRecipient = typeof request.recipient === \"string\";\n const hasRequestId = typeof request.requestId === \"string\";\n if (hasRecipient === hasRequestId) {\n throw new Error(\"subagent_send requires exactly one of recipient or requestId.\");\n }\n const acknowledgement = hasRecipient\n ? request.recipient === \"main\"\n ? this.createRequest(job, \"child\", request.message)\n : (() => {\n throw new Error('A subagent may send new requests only to recipient \"main\".');\n })()\n : this.acceptResponse(\"child\", job, request.requestId ?? \"\", request.message);\n this.respond(socket, { ok: true, ...acknowledgement });\n }\n\n private handleWait(socket: Socket, job: JobRecord, request: Extract<BrokerRequest, { type: \"wait\" }>): void {\n if (typeof request.requestId !== \"string\") {\n throw new Error(\"Subagent wait requires a request ID.\");\n }\n validateRequestId(request.requestId);\n if (request.timeoutMs !== undefined) validateTimeout(request.timeoutMs);\n const record = this.requests.get(request.requestId);\n if (record?.origin !== \"child\" || record.jobId !== job.jobId || record.generation !== job.generation) {\n throw new Error(\"Unknown or expired subagent request.\");\n }\n if (record.consumedAt !== undefined && record.response !== undefined) {\n this.respond(socket, { ok: true, response: record.response });\n return;\n }\n if (record.response !== undefined) {\n this.respond(socket, { ok: true, response: record.response }, () => this.markConsumed(record));\n return;\n }\n if (this.hasQueuedRequestForChild(job.jobId)) {\n this.respondError(socket, CHILD_WAIT_INTERRUPTED_ERROR);\n return;\n }\n if (record.waiter) {\n throw new Error(`A wait is already active for subagent request ${request.requestId}.`);\n }\n const waiter: RequestWaiter = { socket };\n record.waiter = waiter;\n if (request.timeoutMs !== undefined) {\n waiter.timer = setTimeout(() => {\n if (record.waiter !== waiter) return;\n this.clearWaiter(record);\n this.respondError(socket, \"Subagent response wait timed out.\");\n }, request.timeoutMs);\n waiter.timer.unref();\n }\n }\n\n private markConsumed(request: RequestRecord): void {\n if (this.requests.get(request.requestId) !== request || request.response === undefined) return;\n request.consumedAt ??= this.now();\n const consumed = [...this.requests.values()]\n .filter((candidate) => candidate.jobId === request.jobId && candidate.consumedAt !== undefined)\n .sort((left, right) => (left.consumedAt ?? 0) - (right.consumedAt ?? 0));\n for (const expired of consumed.slice(0, Math.max(0, consumed.length - MAX_RETAINED_CONSUMED_REQUESTS))) {\n this.requests.delete(expired.requestId);\n }\n }\n\n private clearWaiter(request: RequestRecord): void {\n if (request.waiter?.timer) clearTimeout(request.waiter.timer);\n request.waiter = undefined;\n }\n\n private respondError(socket: Socket, error: string): void {\n this.respond(socket, { ok: false, error: truncateError(error) });\n }\n\n private respond(socket: Socket, value: Record<string, unknown>, onFlushed?: () => void): void {\n if (socket.destroyed) return;\n let content = `${JSON.stringify(value)}\\n`;\n if (Buffer.byteLength(content, \"utf8\") > MAX_FRAME_BYTES) {\n content = `${JSON.stringify({ ok: false, error: \"Subagent broker response exceeded its size limit.\" })}\\n`;\n }\n socket.end(content, onFlushed);\n }\n\n private fail(error: Error): void {\n this.failure = truncateError(error.message);\n for (const jobId of [...this.tokenByJob.keys()]) {\n this.revokeJob(jobId, \"Subagent message broker failed.\");\n }\n for (const socket of this.sockets) socket.destroy();\n this.sockets.clear();\n this.address = undefined;\n }\n}\n\nexport function optionalIdentifier(value: unknown, field: string): string | undefined {\n return value === undefined ? undefined : requiredIdentifier(value, field);\n}\n\n/** Tool arguments accept trimmed IDs; broker request IDs have a separate UUID check. */\nexport function requiredIdentifier(value: unknown, field: string): string {\n if (typeof value !== \"string\" || !value.trim()) throw new Error(`Subagent ${field} is required.`);\n const identifier = value.trim();\n if (\n identifier.length > MAX_IDENTIFIER_LENGTH ||\n [...identifier].some((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f);\n })\n ) {\n throw new Error(`Subagent ${field} is invalid.`);\n }\n return identifier;\n}\n\nexport function validateMessage(message: string, label: string): void {\n if (!message.trim()) throw new Error(`${label} is required.`);\n if (message.includes(\"\\0\")) throw new Error(`${label} must not contain NUL bytes.`);\n if (Buffer.byteLength(message, \"utf8\") > MAX_MESSAGE_BYTES) {\n throw new Error(`${label} must be at most ${MAX_MESSAGE_BYTES} UTF-8 bytes.`);\n }\n if (lineCount(message) > MAX_MESSAGE_LINES) {\n throw new Error(`${label} must contain at most ${MAX_MESSAGE_LINES} lines.`);\n }\n}\n\nexport function sanitizeTerminalText(value: string): string {\n return [...value]\n .filter((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n if (character === \"\\n\" || character === \"\\t\") return true;\n if (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f)) return false;\n return !((codePoint >= 0x202a && codePoint <= 0x202e) || (codePoint >= 0x2066 && codePoint <= 0x2069));\n })\n .join(\"\");\n}\n\nfunction validateRequestId(requestId: string): void {\n if (\n requestId.length > MAX_IDENTIFIER_LENGTH ||\n !/^req_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u.test(requestId)\n ) {\n throw new Error(\"Invalid subagent request ID.\");\n }\n}\n\nfunction validateTimeout(timeoutMs: number): void {\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > MAX_TIMEOUT_MS) {\n throw new Error(\"Subagent wait timeout is outside the supported range.\");\n }\n}\n\nfunction lineCount(value: string): number {\n let count = 1;\n for (const character of value) if (character === \"\\n\") count++;\n return count;\n}\n\nfunction truncateError(error: string): string {\n const bytes = Buffer.from(error, \"utf8\");\n if (bytes.length <= MAX_ERROR_BYTES) return error;\n return `${bytes\n .subarray(0, Math.max(0, MAX_ERROR_BYTES - 18))\n .toString(\"utf8\")\n .replace(/\uFFFD+$/gu, \"\")}\\n\u2026 [truncated]`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isLoopbackAddress(address: AddressInfo | string | null): address is AddressInfo {\n return Boolean(address && typeof address !== \"string\" && address.address === BROKER_HOST);\n}\n", "import * as fs from \"node:fs\";\nimport { type BrokerCredentials, SUBAGENT_THINKING_LEVELS, type SubagentThinkingLevel } from \"./types.js\";\n\nexport const BROKER_CREDENTIAL_FD = 3;\nexport const BROKER_CREDENTIAL_FD_ENV = \"PI_SUBAGENT_BROKER_FD\";\nexport const CHILD_READINESS_FD = 4;\nexport const CHILD_READINESS_FD_ENV = \"PI_SUBAGENT_READINESS_FD\";\nexport const MAX_READINESS_FRAME_BYTES = 16 * 1024;\n\nexport const MAX_BOOTSTRAP_BYTES = 16 * 1024;\nconst MAX_EXPECTED_TOOLS = 66;\nconst MAX_TOOL_NAME_LENGTH = 128;\nconst READINESS_STATE_KEY = Symbol.for(\"@narumitw/pi-subagents/child-readiness\");\n\nexport interface ChildSelection {\n provider: string;\n model: string;\n thinkingLevel: SubagentThinkingLevel;\n}\n\nexport interface ChildBootstrap {\n communication: BrokerCredentials;\n expectedTools: string[];\n selection: ChildSelection;\n}\n\ninterface CapturedReadiness {\n fd: number;\n expectedTools: string[];\n selection: ChildSelection;\n}\n\nexport interface CapturedChildBootstrap extends ChildBootstrap {\n readinessFd?: number;\n}\n\nexport function childBootstrapEnvironment(expectReadiness: boolean): NodeJS.ProcessEnv {\n return {\n [BROKER_CREDENTIAL_FD_ENV]: String(BROKER_CREDENTIAL_FD),\n ...(expectReadiness ? { [CHILD_READINESS_FD_ENV]: String(CHILD_READINESS_FD) } : {}),\n };\n}\n\nexport function serializeChildBootstrap(bootstrap: ChildBootstrap): string {\n return JSON.stringify(bootstrap);\n}\n\nexport function assertChildBootstrapCapacity(expectedTools: string[], selection: ChildSelection): void {\n const serialized = serializeChildBootstrap({\n communication: { host: \"127.0.0.1\", port: 65_535, token: \"f\".repeat(64) },\n expectedTools,\n selection,\n });\n if (Buffer.byteLength(serialized, \"utf8\") > MAX_BOOTSTRAP_BYTES) {\n throw new Error(\n `Subagent tools and model selection exceed the ${MAX_BOOTSTRAP_BYTES}-byte child bootstrap size limit.`,\n );\n }\n}\n\nexport function captureChildBootstrap(\n readBootstrap: () => string = readBootstrapPipe,\n): CapturedChildBootstrap | undefined {\n const credentialDescriptor = process.env[BROKER_CREDENTIAL_FD_ENV];\n const readinessDescriptor = process.env[CHILD_READINESS_FD_ENV];\n delete process.env[BROKER_CREDENTIAL_FD_ENV];\n delete process.env[CHILD_READINESS_FD_ENV];\n setCapturedReadiness(undefined);\n if (credentialDescriptor === undefined) {\n if (readinessDescriptor !== undefined) throw new Error(\"Unexpected pi-subagents readiness descriptor.\");\n return undefined;\n }\n if (credentialDescriptor !== String(BROKER_CREDENTIAL_FD)) {\n throw new Error(\"Invalid pi-subagents broker credential descriptor.\");\n }\n let serialized: string;\n try {\n serialized = readBootstrap();\n } catch {\n throw new Error(\"Unable to read pi-subagents child bootstrap.\");\n }\n if (Buffer.byteLength(serialized, \"utf8\") > MAX_BOOTSTRAP_BYTES) {\n throw new Error(\"Invalid pi-subagents child bootstrap.\");\n }\n let value: unknown;\n try {\n value = JSON.parse(serialized);\n } catch {\n throw new Error(\"Invalid pi-subagents child bootstrap.\");\n }\n if (!isChildBootstrap(value)) throw new Error(\"Invalid pi-subagents child bootstrap.\");\n\n if (value.expectedTools.length > 0) {\n if (readinessDescriptor !== String(CHILD_READINESS_FD)) {\n throw new Error(\"Invalid pi-subagents readiness descriptor.\");\n }\n setCapturedReadiness({\n fd: CHILD_READINESS_FD,\n expectedTools: [...value.expectedTools],\n selection: { ...value.selection },\n });\n return { ...value, selection: { ...value.selection }, readinessFd: CHILD_READINESS_FD };\n }\n if (readinessDescriptor !== undefined) throw new Error(\"Unexpected pi-subagents readiness descriptor.\");\n setCapturedReadiness(undefined);\n return value;\n}\n\nexport function takeCapturedReadiness(): CapturedReadiness | undefined {\n const store = globalThis as unknown as Record<symbol, CapturedReadiness | undefined>;\n const readiness = store[READINESS_STATE_KEY];\n delete store[READINESS_STATE_KEY];\n return readiness\n ? { fd: readiness.fd, expectedTools: [...readiness.expectedTools], selection: { ...readiness.selection } }\n : undefined;\n}\n\nfunction setCapturedReadiness(readiness: CapturedReadiness | undefined): void {\n const store = globalThis as unknown as Record<symbol, CapturedReadiness | undefined>;\n if (readiness) store[READINESS_STATE_KEY] = readiness;\n else delete store[READINESS_STATE_KEY];\n}\n\nfunction readBootstrapPipe(): string {\n try {\n return fs.readFileSync(BROKER_CREDENTIAL_FD, \"utf8\");\n } finally {\n try {\n fs.closeSync(BROKER_CREDENTIAL_FD);\n } catch {\n // The descriptor may already be closed after a failed read.\n }\n }\n}\n\nfunction isChildBootstrap(value: unknown): value is ChildBootstrap {\n if (!isRecord(value) || Object.keys(value).length !== 3) return false;\n if (!isBrokerCredentials(value.communication) || !isChildSelection(value.selection)) return false;\n if (!Array.isArray(value.expectedTools) || value.expectedTools.length > MAX_EXPECTED_TOOLS) return false;\n return value.expectedTools.every(\n (tool) =>\n typeof tool === \"string\" &&\n tool.length > 0 &&\n tool.length <= MAX_TOOL_NAME_LENGTH &&\n !tool.includes(\",\") &&\n !hasControlCharacter(tool),\n );\n}\n\nfunction isChildSelection(value: unknown): value is ChildSelection {\n if (!isRecord(value) || Object.keys(value).length !== 3) return false;\n return (\n [value.provider, value.model].every(\n (id) => typeof id === \"string\" && id.trim().length > 0 && !hasControlCharacter(id),\n ) && SUBAGENT_THINKING_LEVELS.includes(value.thinkingLevel as SubagentThinkingLevel)\n );\n}\n\nfunction isBrokerCredentials(value: unknown): value is BrokerCredentials {\n if (!isRecord(value) || Object.keys(value).length !== 3) return false;\n return (\n value.host === \"127.0.0.1\" &&\n Number.isSafeInteger(value.port) &&\n (value.port as number) >= 1 &&\n (value.port as number) <= 65_535 &&\n typeof value.token === \"string\" &&\n /^[a-f0-9]{64}$/u.test(value.token)\n );\n}\n\nfunction hasControlCharacter(value: string): boolean {\n return [...value].some((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f);\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["request", "isRecord"]
|
|
7
|
+
}
|