@astralyn/pi 0.87.2 → 0.87.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.
- package/CHANGELOG.md +19 -0
- package/dist/bundle/chunks/{chunk-NBIUJDV6.js → chunk-ANT4TSUE.js} +1 -1
- package/dist/bundle/chunks/{chunk-RFLBIA5Z.js → chunk-CUDKRZ2V.js} +37 -24
- package/dist/bundle/chunks/{virtual-modules-GOHLE5JL.js → virtual-modules-Y2YZRMU3.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/background/service.d.ts.map +1 -1
- package/dist/core/background/service.js +4 -3
- package/dist/core/background/service.js.map +1 -1
- package/dist/core/background/types.d.ts +11 -0
- package/dist/core/background/types.d.ts.map +1 -1
- package/dist/core/background/types.js +14 -0
- package/dist/core/background/types.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +121 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/extensions/background/actions.d.ts.map +1 -1
- package/dist/extensions/background/actions.js +126 -67
- package/dist/extensions/background/actions.js.map +1 -1
- package/dist/extensions/background/index.js +3 -3
- package/dist/extensions/background/index.js.map +1 -1
- package/dist/extensions/question/index.d.ts.map +1 -1
- package/dist/extensions/question/index.js +3 -1
- package/dist/extensions/question/index.js.map +1 -1
- package/dist/extensions/question/schema.d.ts +18 -0
- package/dist/extensions/question/schema.d.ts.map +1 -1
- package/dist/extensions/question/schema.js +52 -0
- package/dist/extensions/question/schema.js.map +1 -1
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +3 -1
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent/resolve.d.ts +14 -1
- package/dist/extensions/subagent/resolve.d.ts.map +1 -1
- package/dist/extensions/subagent/resolve.js +32 -18
- package/dist/extensions/subagent/resolve.js.map +1 -1
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +4 -1
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/schema.d.ts +9 -0
- package/dist/extensions/subagent/schema.d.ts.map +1 -1
- package/dist/extensions/subagent/schema.js +30 -1
- package/dist/extensions/subagent/schema.js.map +1 -1
- package/dist/extensions/subagent/types.d.ts +2 -0
- package/dist/extensions/subagent/types.d.ts.map +1 -1
- package/dist/extensions/subagent/types.js.map +1 -1
- package/dist/extensions/todo/constants.d.ts +1 -1
- package/dist/extensions/todo/constants.d.ts.map +1 -1
- package/dist/extensions/todo/constants.js +8 -8
- package/dist/extensions/todo/constants.js.map +1 -1
- package/dist/extensions/todo/index.d.ts.map +1 -1
- package/dist/extensions/todo/index.js +2 -1
- package/dist/extensions/todo/index.js.map +1 -1
- package/dist/extensions/todo/schema.d.ts +30 -25
- package/dist/extensions/todo/schema.d.ts.map +1 -1
- package/dist/extensions/todo/schema.js +26 -20
- package/dist/extensions/todo/schema.js.map +1 -1
- package/dist/extensions/todo/state.d.ts +12 -8
- package/dist/extensions/todo/state.d.ts.map +1 -1
- package/dist/extensions/todo/state.js +257 -171
- package/dist/extensions/todo/state.js.map +1 -1
- package/dist/extensions/todo/view.d.ts +6 -2
- package/dist/extensions/todo/view.d.ts.map +1 -1
- package/dist/extensions/todo/view.js +234 -144
- package/dist/extensions/todo/view.js.map +1 -1
- package/docs/bundled/extensions/background.md +1 -1
- package/docs/bundled/extensions/question.md +1 -0
- package/docs/bundled/extensions/subagent.md +3 -1
- package/docs/bundled/extensions/todo.md +35 -23
- package/docs/extensions.md +2 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/extensions/question/schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { Type } from \"typebox\";\nimport { QUESTION_LIMITS } from \"./limits.ts\";\nimport type { Question, QuestionOption, QuestionToolError } from \"./types.ts\";\n\nconst MIN_OPTIONS = 2;\nconst MAX_OPTIONS = 4;\nconst MAX_QUESTIONS = 4;\nconst RESERVED_LABELS = [\"Other\", \"Type something\", \"Type something.\", \"Chat about this\"] as const;\n\nconst normalizeLabel = (text: string) => text.trim().toLowerCase();\nconst RESERVED_NORMALIZED = new Set(RESERVED_LABELS.map(normalizeLabel));\n\nconst OptionSchema = Type.Object({\n\tlabel: Type.String({\n\t\tminLength: 1,\n\t\tmaxLength: QUESTION_LIMITS.optionLabelChars,\n\t\tdescription:\n\t\t\t\"Short user-facing option label (1-5 words), distinct within the question. Reserved labels ('Other', 'Type something', 'Chat about this') are rejected — the UI adds the custom-answer path itself.\",\n\t}),\n\tdescription: Type.String({\n\t\tminLength: 1,\n\t\tmaxLength: QUESTION_LIMITS.optionDescriptionChars,\n\t\tdescription: \"One concise sentence explaining the option's meaning, consequence, or tradeoff.\",\n\t}),\n\tpreview: Type.Optional(\n\t\tType.String({\n\t\t\tminLength: 1,\n\t\t\tmaxLength: QUESTION_LIMITS.previewChars,\n\t\t\tdescription:\n\t\t\t\t\"Optional markdown preview shown only for focused single-select options; use for concrete snippets, layouts, copy, or config comparisons.\",\n\t\t}),\n\t),\n});\n\nconst QuestionSchema = Type.Object({\n\tquestion: Type.String({\n\t\tminLength: 1,\n\t\tmaxLength: QUESTION_LIMITS.questionChars,\n\t\tdescription:\n\t\t\t\"One clear, specific decision or preference question ending in a question mark. Ask only what is needed to proceed.\",\n\t}),\n\theader: Type.String({\n\t\tminLength: 1,\n\t\tmaxLength: QUESTION_LIMITS.headerChars,\n\t\tdescription: \"Very short decision label shown as a chip; aim for ~12 chars, max 32. E.g. 'Auth method'.\",\n\t}),\n\toptions: Type.Array(OptionSchema, {\n\t\tminItems: MIN_OPTIONS,\n\t\tmaxItems: MAX_OPTIONS,\n\t\tdescription: \"Mutually distinct options for this decision; do not include reserved custom-answer labels.\",\n\t}),\n\tmultiSelect: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription:\n\t\t\t\t\"Allow selecting multiple options only when choices can be combined. Defaults to false for mutually exclusive decisions.\",\n\t\t}),\n\t),\n});\n\nexport const QuestionParams = Type.Object({\n\tquestions: Type.Array(QuestionSchema, {\n\t\tminItems: 1,\n\t\tmaxItems: MAX_QUESTIONS,\n\t\tdescription: \"Related decisions to ask now (1-4); ask only what is needed to unblock progress.\",\n\t}),\n});\n\n/**\n * Checks visible non-whitespace text and cross-field rules the schema cannot\n * express. Length and count limits remain enforced by `QuestionParams` first.\n */\nexport function validateQuestions(\n\tquestions: Question[],\n): { ok: true } | { ok: false; error: QuestionToolError; message: string } {\n\tconst requireNonBlank = (\n\t\tvalue: unknown,\n\t\tpath: string,\n\t): { ok: false; error: QuestionToolError; message: string } | undefined => {\n\t\tif (typeof value === \"string\" && value.trim().length > 0) return undefined;\n\t\treturn { ok: false, error: \"blank_text\", message: `${path} must contain visible text` };\n\t};\n\n\tconst seenQuestions = new Set<string>();\n\tfor (let questionIndex = 0; questionIndex < questions.length; questionIndex++) {\n\t\tconst q = questions[questionIndex];\n\t\tconst questionError = requireNonBlank(q.question, `questions[${questionIndex}].question`);\n\t\tif (questionError) return questionError;\n\t\tconst headerError = requireNonBlank(q.header, `questions[${questionIndex}].header`);\n\t\tif (headerError) return headerError;\n\n\t\tconst questionKey = normalizeLabel(q.question);\n\t\tif (seenQuestions.has(questionKey)) {\n\t\t\treturn { ok: false, error: \"duplicate_question\", message: \"Question text must be unique\" };\n\t\t}\n\t\tseenQuestions.add(questionKey);\n\n\t\tconst seenLabels = new Set<string>();\n\t\tfor (let optionIndex = 0; optionIndex < q.options.length; optionIndex++) {\n\t\t\tconst option = q.options[optionIndex] as QuestionOption;\n\t\t\tconst optionPath = `questions[${questionIndex}].options[${optionIndex}]`;\n\t\t\tconst labelError = requireNonBlank(option.label, `${optionPath}.label`);\n\t\t\tif (labelError) return labelError;\n\t\t\tconst descriptionError = requireNonBlank(option.description, `${optionPath}.description`);\n\t\t\tif (descriptionError) return descriptionError;\n\t\t\tif (option.preview !== undefined) {\n\t\t\t\tconst previewError = requireNonBlank(option.preview, `${optionPath}.preview`);\n\t\t\t\tif (previewError) return previewError;\n\t\t\t}\n\n\t\t\tconst labelKey = normalizeLabel(option.label);\n\t\t\tif (RESERVED_NORMALIZED.has(labelKey)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: \"reserved_label\",\n\t\t\t\t\tmessage: `Option label is reserved (${RESERVED_LABELS.join(\", \")})`,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (seenLabels.has(labelKey)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: \"duplicate_option_label\",\n\t\t\t\t\tmessage: \"Option labels must be unique within a question\",\n\t\t\t\t};\n\t\t\t}\n\t\t\tseenLabels.add(labelKey);\n\t\t}\n\n\t\tif (q.multiSelect && q.options.some((option) => option.preview)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: \"preview_multiselect\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"Option previews are not supported on multiSelect questions; drop the previews or make the question single-select\",\n\t\t\t};\n\t\t}\n\t}\n\n\treturn { ok: true };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/extensions/question/schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { Type } from \"typebox\";\nimport { QUESTION_LIMITS } from \"./limits.ts\";\nimport type { Question, QuestionOption, QuestionToolError } from \"./types.ts\";\n\ntype QuestionArgs = { questions: Question[] };\n\nconst MIN_OPTIONS = 2;\nconst MAX_OPTIONS = 4;\nconst MAX_QUESTIONS = 4;\nconst RESERVED_LABELS = [\"Other\", \"Type something\", \"Type something.\", \"Chat about this\"] as const;\n\nconst normalizeLabel = (text: string) => text.trim().toLowerCase();\nconst RESERVED_NORMALIZED = new Set(RESERVED_LABELS.map(normalizeLabel));\n\nconst OptionSchema = Type.Object({\n\tlabel: Type.String({\n\t\tminLength: 1,\n\t\tmaxLength: QUESTION_LIMITS.optionLabelChars,\n\t\tdescription:\n\t\t\t\"Short user-facing option label (1-5 words), distinct within the question. Reserved labels ('Other', 'Type something', 'Chat about this') are rejected — the UI adds the custom-answer path itself.\",\n\t}),\n\tdescription: Type.String({\n\t\tminLength: 1,\n\t\tmaxLength: QUESTION_LIMITS.optionDescriptionChars,\n\t\tdescription: \"One concise sentence explaining the option's meaning, consequence, or tradeoff.\",\n\t}),\n\tpreview: Type.Optional(\n\t\tType.String({\n\t\t\tminLength: 1,\n\t\t\tmaxLength: QUESTION_LIMITS.previewChars,\n\t\t\tdescription:\n\t\t\t\t\"Optional markdown preview shown only for focused single-select options; use for concrete snippets, layouts, copy, or config comparisons.\",\n\t\t}),\n\t),\n});\n\nconst QuestionSchema = Type.Object({\n\tquestion: Type.String({\n\t\tminLength: 1,\n\t\tmaxLength: QUESTION_LIMITS.questionChars,\n\t\tdescription:\n\t\t\t\"One clear, specific decision or preference question ending in a question mark. Ask only what is needed to proceed.\",\n\t}),\n\theader: Type.String({\n\t\tminLength: 1,\n\t\tmaxLength: QUESTION_LIMITS.headerChars,\n\t\tdescription: \"Very short decision label shown as a chip; aim for ~12 chars, max 32. E.g. 'Auth method'.\",\n\t}),\n\toptions: Type.Array(OptionSchema, {\n\t\tminItems: MIN_OPTIONS,\n\t\tmaxItems: MAX_OPTIONS,\n\t\tdescription: \"Mutually distinct options for this decision; do not include reserved custom-answer labels.\",\n\t}),\n\tmultiSelect: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription:\n\t\t\t\t\"Allow selecting multiple options only when choices can be combined. Defaults to false for mutually exclusive decisions.\",\n\t\t}),\n\t),\n});\n\nexport const QuestionParams = Type.Object({\n\tquestions: Type.Array(QuestionSchema, {\n\t\tminItems: 1,\n\t\tmaxItems: MAX_QUESTIONS,\n\t\tdescription: \"Related decisions to ask now (1-4); ask only what is needed to unblock progress.\",\n\t}),\n});\n\n/**\n * Unambiguous argument normalizations applied before schema validation; the\n * schema itself stays a single object shape because strict constrained\n * sampling does not support object unions. Everything else is left for\n * validation to report.\n *\n * - a lone question written flat at the root ({question, header?, options,\n * multiSelect?} with no questions) wraps into questions[0];\n * - a root-level question string fills a questions[0] object that lost its\n * own question field to the root;\n * - a stringified questions array parses back into an array (a parse failure\n * stays for validation to reject).\n */\nexport function normalizeQuestionArguments(raw: unknown): QuestionArgs {\n\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) return raw as QuestionArgs;\n\tconst args: Record<string, unknown> = { ...(raw as Record<string, unknown>) };\n\n\tif (typeof args.questions === \"string\") {\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(args.questions);\n\t\t\tif (Array.isArray(parsed)) args.questions = parsed;\n\t\t} catch {\n\t\t\t// Leave the string for schema validation to reject.\n\t\t}\n\t}\n\n\tconst rootQuestion = typeof args.question === \"string\" ? args.question : undefined;\n\tconst onlyQuestion =\n\t\tArray.isArray(args.questions) && args.questions.length === 1 ? (args.questions[0] as unknown) : undefined;\n\tif (\n\t\trootQuestion !== undefined &&\n\t\tonlyQuestion !== null &&\n\t\ttypeof onlyQuestion === \"object\" &&\n\t\t!Array.isArray(onlyQuestion) &&\n\t\t(onlyQuestion as Record<string, unknown>).question === undefined\n\t) {\n\t\targs.questions = [{ ...(onlyQuestion as Record<string, unknown>), question: rootQuestion }];\n\t\tdelete args.question;\n\t\treturn args as QuestionArgs;\n\t}\n\n\tif (args.questions === undefined && rootQuestion !== undefined && args.options !== undefined) {\n\t\tconst question: Record<string, unknown> = { question: rootQuestion, options: args.options };\n\t\tif (args.header !== undefined) question.header = args.header;\n\t\tif (args.multiSelect !== undefined) question.multiSelect = args.multiSelect;\n\t\tdelete args.question;\n\t\tdelete args.options;\n\t\tdelete args.header;\n\t\tdelete args.multiSelect;\n\t\targs.questions = [question];\n\t}\n\treturn args as QuestionArgs;\n}\n\n/**\n * Checks visible non-whitespace text and cross-field rules the schema cannot\n * express. Length and count limits remain enforced by `QuestionParams` first.\n */\nexport function validateQuestions(\n\tquestions: Question[],\n): { ok: true } | { ok: false; error: QuestionToolError; message: string } {\n\tconst requireNonBlank = (\n\t\tvalue: unknown,\n\t\tpath: string,\n\t): { ok: false; error: QuestionToolError; message: string } | undefined => {\n\t\tif (typeof value === \"string\" && value.trim().length > 0) return undefined;\n\t\treturn { ok: false, error: \"blank_text\", message: `${path} must contain visible text` };\n\t};\n\n\tconst seenQuestions = new Set<string>();\n\tfor (let questionIndex = 0; questionIndex < questions.length; questionIndex++) {\n\t\tconst q = questions[questionIndex];\n\t\tconst questionError = requireNonBlank(q.question, `questions[${questionIndex}].question`);\n\t\tif (questionError) return questionError;\n\t\tconst headerError = requireNonBlank(q.header, `questions[${questionIndex}].header`);\n\t\tif (headerError) return headerError;\n\n\t\tconst questionKey = normalizeLabel(q.question);\n\t\tif (seenQuestions.has(questionKey)) {\n\t\t\treturn { ok: false, error: \"duplicate_question\", message: \"Question text must be unique\" };\n\t\t}\n\t\tseenQuestions.add(questionKey);\n\n\t\tconst seenLabels = new Set<string>();\n\t\tfor (let optionIndex = 0; optionIndex < q.options.length; optionIndex++) {\n\t\t\tconst option = q.options[optionIndex] as QuestionOption;\n\t\t\tconst optionPath = `questions[${questionIndex}].options[${optionIndex}]`;\n\t\t\tconst labelError = requireNonBlank(option.label, `${optionPath}.label`);\n\t\t\tif (labelError) return labelError;\n\t\t\tconst descriptionError = requireNonBlank(option.description, `${optionPath}.description`);\n\t\t\tif (descriptionError) return descriptionError;\n\t\t\tif (option.preview !== undefined) {\n\t\t\t\tconst previewError = requireNonBlank(option.preview, `${optionPath}.preview`);\n\t\t\t\tif (previewError) return previewError;\n\t\t\t}\n\n\t\t\tconst labelKey = normalizeLabel(option.label);\n\t\t\tif (RESERVED_NORMALIZED.has(labelKey)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: \"reserved_label\",\n\t\t\t\t\tmessage: `Option label is reserved (${RESERVED_LABELS.join(\", \")})`,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (seenLabels.has(labelKey)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: \"duplicate_option_label\",\n\t\t\t\t\tmessage: \"Option labels must be unique within a question\",\n\t\t\t\t};\n\t\t\t}\n\t\t\tseenLabels.add(labelKey);\n\t\t}\n\n\t\tif (q.multiSelect && q.options.some((option) => option.preview)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: \"preview_multiselect\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"Option previews are not supported on multiSelect questions; drop the previews or make the question single-select\",\n\t\t\t};\n\t\t}\n\t}\n\n\treturn { ok: true };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAYpF,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAYpF,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA0IvD"}
|
|
@@ -6,7 +6,7 @@ import { SUBAGENT_COMMAND_NAME, SUBAGENT_TOOL_LABEL, SUBAGENT_TOOL_NAME } from "
|
|
|
6
6
|
import { renderSubagentCall, renderSubagentResult, scheduleLiveRefresh } from "./render.js";
|
|
7
7
|
import { subagentGroupTitle } from "./resolve.js";
|
|
8
8
|
import { ConcurrencyGate, isSubagentError, runSubagentInvocation } from "./runner.js";
|
|
9
|
-
import { SubagentParamsSchema } from "./schema.js";
|
|
9
|
+
import { normalizeSubagentArguments, SubagentParamsSchema } from "./schema.js";
|
|
10
10
|
import { statusSummary } from "./state.js";
|
|
11
11
|
export default function subagent(pi) {
|
|
12
12
|
const gate = new ConcurrencyGate();
|
|
@@ -22,6 +22,8 @@ export default function subagent(pi) {
|
|
|
22
22
|
"Give every task a short `description` label; it is shown in the /bg list, live rows, and report headings.",
|
|
23
23
|
],
|
|
24
24
|
parameters: SubagentParamsSchema,
|
|
25
|
+
constrainedSampling: { type: "json_schema", strict: "prefer" },
|
|
26
|
+
prepareArguments: normalizeSubagentArguments,
|
|
25
27
|
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
26
28
|
const host = ctx.background;
|
|
27
29
|
if (host?.closed)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/subagent/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAgentDir } from \"../../config.ts\";\nimport type { BackgroundControl, BackgroundProjection, BackgroundTerminalStatus } from \"../../core/background/types.ts\";\nimport type { AgentToolResult, ExtensionAPI } from \"../../core/extensions/types.ts\";\nimport { emptyUsage } from \"./activity.ts\";\nimport { subagentToolDescription } from \"./agents.ts\";\nimport { showAgentsCommand } from \"./agents-command.ts\";\nimport { SUBAGENT_COMMAND_NAME, SUBAGENT_TOOL_LABEL, SUBAGENT_TOOL_NAME } from \"./constants.ts\";\nimport { renderSubagentCall, renderSubagentResult, type SubagentRenderState, scheduleLiveRefresh } from \"./render.ts\";\nimport { type ParentModelContext, subagentGroupTitle } from \"./resolve.ts\";\nimport { ConcurrencyGate, isSubagentError, runSubagentInvocation } from \"./runner.ts\";\nimport { SubagentParamsSchema } from \"./schema.ts\";\nimport { statusSummary } from \"./state.ts\";\nimport type { SubagentDetails } from \"./types.ts\";\n\nexport default function subagent(pi: ExtensionAPI): void {\n\tconst gate = new ConcurrencyGate();\n\tlet workerOrdinal = 0;\n\tconst activeAborters = new Set<() => Promise<void>>();\n\n\tpi.registerTool<typeof SubagentParamsSchema, SubagentDetails, SubagentRenderState>({\n\t\tname: SUBAGENT_TOOL_NAME,\n\t\tlabel: SUBAGENT_TOOL_LABEL,\n\t\tdescription: subagentToolDescription(),\n\t\tpromptSnippet: \"Delegate bounded work to isolated explorer or general workers\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use `subagent` for bounded work that benefits from isolated context or concurrent investigation; do not delegate a task you can finish with one or two direct tool calls.\",\n\t\t\t\"Give every task a short `description` label; it is shown in the /bg list, live rows, and report headings.\",\n\t\t],\n\t\tparameters: SubagentParamsSchema,\n\t\tasync execute(toolCallId, params, signal, onUpdate, ctx): Promise<AgentToolResult<SubagentDetails>> {\n\t\t\tconst host = ctx.background;\n\t\t\tif (host?.closed) throw new Error(\"Background service is closed\");\n\t\t\tconst managed = host?.enabled || params.background === true;\n\t\t\tif (managed && !host) throw new Error(\"Background execution requires an enabled Background host.\");\n\t\t\tlet latest: SubagentDetails = {\n\t\t\t\tstatus: \"running\",\n\t\t\t\truns: [],\n\t\t\t\tstartedAt: Date.now(),\n\t\t\t\tusage: emptyUsage(),\n\t\t\t};\n\t\t\tconst ordinals = new Map<string, number>();\n\t\t\tconst projection = (view: BackgroundProjection): BackgroundProjection => ({\n\t\t\t\t...view,\n\t\t\t\tworkers: view.workers?.map((worker) => {\n\t\t\t\t\tlet ordinal = ordinals.get(worker.id);\n\t\t\t\t\tif (ordinal === undefined) {\n\t\t\t\t\t\tordinal = ++workerOrdinal;\n\t\t\t\t\t\tordinals.set(worker.id, ordinal);\n\t\t\t\t\t}\n\t\t\t\t\treturn { ...worker, label: `#${ordinal} ${worker.profile}` };\n\t\t\t\t}),\n\t\t\t});\n\t\t\tconst run = async (\n\t\t\t\tcontrol?: BackgroundControl<SubagentDetails>,\n\t\t\t): Promise<AgentToolResult<SubagentDetails>> => {\n\t\t\t\tconst update = (details: SubagentDetails, view?: BackgroundProjection): void => {\n\t\t\t\t\tlatest = details;\n\t\t\t\t\tconst result: AgentToolResult<SubagentDetails> = {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: statusSummary(details) }],\n\t\t\t\t\t\tdetails,\n\t\t\t\t\t};\n\t\t\t\t\tif (control) control.publish(result, view ? projection(view) : undefined);\n\t\t\t\t\telse onUpdate?.(result);\n\t\t\t\t};\n\t\t\t\tupdate(latest);\n\t\t\t\tconst parent: ParentModelContext = {\n\t\t\t\t\tmodel: ctx.model,\n\t\t\t\t\tthinking: pi.getThinkingLevel(),\n\t\t\t\t\tmodelRegistry: ctx.modelRegistry,\n\t\t\t\t};\n\t\t\t\tconst execution = await runSubagentInvocation({\n\t\t\t\t\tparams,\n\t\t\t\t\tparentCwd: ctx.cwd,\n\t\t\t\t\tparent,\n\t\t\t\t\tmodelRuntime: ctx.modelRuntime,\n\t\t\t\t\tagentDir: getAgentDir(),\n\t\t\t\t\tprojectTrusted: ctx.isProjectTrusted(),\n\t\t\t\t\tsignal: control?.signal ?? signal,\n\t\t\t\t\tgate,\n\t\t\t\t\tbatchId: control?.id ?? toolCallId,\n\t\t\t\t\tonUpdate: update,\n\t\t\t\t\tonAccepted: control ? () => control.accept() : undefined,\n\t\t\t\t\tonConfigWarning: (message) => ctx.ui.notify(message, \"warning\"),\n\t\t\t\t\tregisterAbort: control\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: (abort) => {\n\t\t\t\t\t\t\t\tactiveAborters.add(abort);\n\t\t\t\t\t\t\t\treturn () => activeAborters.delete(abort);\n\t\t\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tconst result: AgentToolResult<SubagentDetails> = {\n\t\t\t\t\tcontent: [{ type: \"text\", text: execution.content }],\n\t\t\t\t\tdetails: execution.details,\n\t\t\t\t\tusage: execution.usage,\n\t\t\t\t};\n\t\t\t\tcontrol?.publish(result, projection(execution.projection));\n\t\t\t\treturn result;\n\t\t\t};\n\t\t\tif (!managed) return run();\n\t\t\tconst outcome = await host!.execute<SubagentDetails>({\n\t\t\t\tkind: \"subagent\",\n\t\t\t\ttitle: subagentGroupTitle(params.tasks),\n\t\t\t\ttoolCallId,\n\t\t\t\tbackground: params.background === true,\n\t\t\t\tsignal,\n\t\t\t\tonUpdate,\n\t\t\t\trun: async (control) => {\n\t\t\t\t\tconst result = await run(control);\n\t\t\t\t\tconst status = result.details!.status;\n\t\t\t\t\tconst terminal: BackgroundTerminalStatus =\n\t\t\t\t\t\tstatus === \"aborted\" ? \"cancelled\" : status === \"running\" ? \"failed\" : status;\n\t\t\t\t\treturn { result, status: terminal };\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (outcome.kind === \"result\") return outcome.result;\n\t\t\tconst submittedAt = Date.now();\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `Subagent group handed to background: ${outcome.task.id}. Completion arrives automatically as a notification — do not poll or immediately wait on it; continue with other work or hand back to the user. Use bg read to inspect progress, bg wait only when your next step is blocked on the result (prefer foreground next time in that case), or bg kill to stop the whole group.`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails: { ...latest, endedAt: submittedAt, background: { id: outcome.task.id, submittedAt } },\n\t\t\t};\n\t\t},\n\t\trenderCall(args, theme) {\n\t\t\treturn renderSubagentCall(args, theme);\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tscheduleLiveRefresh(context, options.isPartial && !result.details?.background);\n\t\t\treturn renderSubagentResult(result, options, theme, context.args, context.isError);\n\t\t},\n\t});\n\n\tpi.registerCommand(SUBAGENT_COMMAND_NAME, {\n\t\tdescription: \"Configure Subagent profiles, models, and thinking levels\",\n\t\thandler: async (_args, ctx) => showAgentsCommand(ctx, pi.getThinkingLevel()),\n\t});\n\n\tpi.on(\"tool_result\", async (event) => {\n\t\tif (event.toolName !== SUBAGENT_TOOL_NAME) return;\n\t\tconst details = event.details as SubagentDetails | undefined;\n\t\tif (details && !details.background && isSubagentError(details)) return { isError: true };\n\t});\n\n\tpi.on(\"session_shutdown\", async () => {\n\t\tawait Promise.allSettled([...activeAborters].map((abort) => abort()));\n\t\tactiveAborters.clear();\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/subagent/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAgentDir } from \"../../config.ts\";\nimport type { BackgroundControl, BackgroundProjection, BackgroundTerminalStatus } from \"../../core/background/types.ts\";\nimport type { AgentToolResult, ExtensionAPI } from \"../../core/extensions/types.ts\";\nimport { emptyUsage } from \"./activity.ts\";\nimport { subagentToolDescription } from \"./agents.ts\";\nimport { showAgentsCommand } from \"./agents-command.ts\";\nimport { SUBAGENT_COMMAND_NAME, SUBAGENT_TOOL_LABEL, SUBAGENT_TOOL_NAME } from \"./constants.ts\";\nimport { renderSubagentCall, renderSubagentResult, type SubagentRenderState, scheduleLiveRefresh } from \"./render.ts\";\nimport { type ParentModelContext, subagentGroupTitle } from \"./resolve.ts\";\nimport { ConcurrencyGate, isSubagentError, runSubagentInvocation } from \"./runner.ts\";\nimport { normalizeSubagentArguments, SubagentParamsSchema } from \"./schema.ts\";\nimport { statusSummary } from \"./state.ts\";\nimport type { SubagentDetails } from \"./types.ts\";\n\nexport default function subagent(pi: ExtensionAPI): void {\n\tconst gate = new ConcurrencyGate();\n\tlet workerOrdinal = 0;\n\tconst activeAborters = new Set<() => Promise<void>>();\n\n\tpi.registerTool<typeof SubagentParamsSchema, SubagentDetails, SubagentRenderState>({\n\t\tname: SUBAGENT_TOOL_NAME,\n\t\tlabel: SUBAGENT_TOOL_LABEL,\n\t\tdescription: subagentToolDescription(),\n\t\tpromptSnippet: \"Delegate bounded work to isolated explorer or general workers\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use `subagent` for bounded work that benefits from isolated context or concurrent investigation; do not delegate a task you can finish with one or two direct tool calls.\",\n\t\t\t\"Give every task a short `description` label; it is shown in the /bg list, live rows, and report headings.\",\n\t\t],\n\t\tparameters: SubagentParamsSchema,\n\t\tconstrainedSampling: { type: \"json_schema\", strict: \"prefer\" },\n\t\tprepareArguments: normalizeSubagentArguments,\n\t\tasync execute(toolCallId, params, signal, onUpdate, ctx): Promise<AgentToolResult<SubagentDetails>> {\n\t\t\tconst host = ctx.background;\n\t\t\tif (host?.closed) throw new Error(\"Background service is closed\");\n\t\t\tconst managed = host?.enabled || params.background === true;\n\t\t\tif (managed && !host) throw new Error(\"Background execution requires an enabled Background host.\");\n\t\t\tlet latest: SubagentDetails = {\n\t\t\t\tstatus: \"running\",\n\t\t\t\truns: [],\n\t\t\t\tstartedAt: Date.now(),\n\t\t\t\tusage: emptyUsage(),\n\t\t\t};\n\t\t\tconst ordinals = new Map<string, number>();\n\t\t\tconst projection = (view: BackgroundProjection): BackgroundProjection => ({\n\t\t\t\t...view,\n\t\t\t\tworkers: view.workers?.map((worker) => {\n\t\t\t\t\tlet ordinal = ordinals.get(worker.id);\n\t\t\t\t\tif (ordinal === undefined) {\n\t\t\t\t\t\tordinal = ++workerOrdinal;\n\t\t\t\t\t\tordinals.set(worker.id, ordinal);\n\t\t\t\t\t}\n\t\t\t\t\treturn { ...worker, label: `#${ordinal} ${worker.profile}` };\n\t\t\t\t}),\n\t\t\t});\n\t\t\tconst run = async (\n\t\t\t\tcontrol?: BackgroundControl<SubagentDetails>,\n\t\t\t): Promise<AgentToolResult<SubagentDetails>> => {\n\t\t\t\tconst update = (details: SubagentDetails, view?: BackgroundProjection): void => {\n\t\t\t\t\tlatest = details;\n\t\t\t\t\tconst result: AgentToolResult<SubagentDetails> = {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: statusSummary(details) }],\n\t\t\t\t\t\tdetails,\n\t\t\t\t\t};\n\t\t\t\t\tif (control) control.publish(result, view ? projection(view) : undefined);\n\t\t\t\t\telse onUpdate?.(result);\n\t\t\t\t};\n\t\t\t\tupdate(latest);\n\t\t\t\tconst parent: ParentModelContext = {\n\t\t\t\t\tmodel: ctx.model,\n\t\t\t\t\tthinking: pi.getThinkingLevel(),\n\t\t\t\t\tmodelRegistry: ctx.modelRegistry,\n\t\t\t\t};\n\t\t\t\tconst execution = await runSubagentInvocation({\n\t\t\t\t\tparams,\n\t\t\t\t\tparentCwd: ctx.cwd,\n\t\t\t\t\tparent,\n\t\t\t\t\tmodelRuntime: ctx.modelRuntime,\n\t\t\t\t\tagentDir: getAgentDir(),\n\t\t\t\t\tprojectTrusted: ctx.isProjectTrusted(),\n\t\t\t\t\tsignal: control?.signal ?? signal,\n\t\t\t\t\tgate,\n\t\t\t\t\tbatchId: control?.id ?? toolCallId,\n\t\t\t\t\tonUpdate: update,\n\t\t\t\t\tonAccepted: control ? () => control.accept() : undefined,\n\t\t\t\t\tonConfigWarning: (message) => ctx.ui.notify(message, \"warning\"),\n\t\t\t\t\tregisterAbort: control\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: (abort) => {\n\t\t\t\t\t\t\t\tactiveAborters.add(abort);\n\t\t\t\t\t\t\t\treturn () => activeAborters.delete(abort);\n\t\t\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tconst result: AgentToolResult<SubagentDetails> = {\n\t\t\t\t\tcontent: [{ type: \"text\", text: execution.content }],\n\t\t\t\t\tdetails: execution.details,\n\t\t\t\t\tusage: execution.usage,\n\t\t\t\t};\n\t\t\t\tcontrol?.publish(result, projection(execution.projection));\n\t\t\t\treturn result;\n\t\t\t};\n\t\t\tif (!managed) return run();\n\t\t\tconst outcome = await host!.execute<SubagentDetails>({\n\t\t\t\tkind: \"subagent\",\n\t\t\t\ttitle: subagentGroupTitle(params.tasks),\n\t\t\t\ttoolCallId,\n\t\t\t\tbackground: params.background === true,\n\t\t\t\tsignal,\n\t\t\t\tonUpdate,\n\t\t\t\trun: async (control) => {\n\t\t\t\t\tconst result = await run(control);\n\t\t\t\t\tconst status = result.details!.status;\n\t\t\t\t\tconst terminal: BackgroundTerminalStatus =\n\t\t\t\t\t\tstatus === \"aborted\" ? \"cancelled\" : status === \"running\" ? \"failed\" : status;\n\t\t\t\t\treturn { result, status: terminal };\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (outcome.kind === \"result\") return outcome.result;\n\t\t\tconst submittedAt = Date.now();\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `Subagent group handed to background: ${outcome.task.id}. Completion arrives automatically as a notification — do not poll or immediately wait on it; continue with other work or hand back to the user. Use bg read to inspect progress, bg wait only when your next step is blocked on the result (prefer foreground next time in that case), or bg kill to stop the whole group.`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails: { ...latest, endedAt: submittedAt, background: { id: outcome.task.id, submittedAt } },\n\t\t\t};\n\t\t},\n\t\trenderCall(args, theme) {\n\t\t\treturn renderSubagentCall(args, theme);\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tscheduleLiveRefresh(context, options.isPartial && !result.details?.background);\n\t\t\treturn renderSubagentResult(result, options, theme, context.args, context.isError);\n\t\t},\n\t});\n\n\tpi.registerCommand(SUBAGENT_COMMAND_NAME, {\n\t\tdescription: \"Configure Subagent profiles, models, and thinking levels\",\n\t\thandler: async (_args, ctx) => showAgentsCommand(ctx, pi.getThinkingLevel()),\n\t});\n\n\tpi.on(\"tool_result\", async (event) => {\n\t\tif (event.toolName !== SUBAGENT_TOOL_NAME) return;\n\t\tconst details = event.details as SubagentDetails | undefined;\n\t\tif (details && !details.background && isSubagentError(details)) return { isError: true };\n\t});\n\n\tpi.on(\"session_shutdown\", async () => {\n\t\tawait Promise.allSettled([...activeAborters].map((abort) => abort()));\n\t\tactiveAborters.clear();\n\t});\n}\n"]}
|
|
@@ -8,7 +8,20 @@ export interface ParentModelContext {
|
|
|
8
8
|
thinking: ThinkingLevel;
|
|
9
9
|
modelRegistry: Pick<ModelRegistry, "find" | "getAvailable" | "hasConfiguredAuth">;
|
|
10
10
|
}
|
|
11
|
-
export
|
|
11
|
+
export interface ResolvedTaskCwd {
|
|
12
|
+
cwd: string;
|
|
13
|
+
/** False for a directory outside the parent: the task runs untrusted there. */
|
|
14
|
+
insideParent: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the requested cwd against the parent working directory. A directory
|
|
18
|
+
* outside the parent is allowed but marked untrusted (the runner starts it
|
|
19
|
+
* without the parent project's trust, so its .pi settings are never loaded);
|
|
20
|
+
* only a missing or non-directory cwd fails. The inside/outside decision is
|
|
21
|
+
* always made on canonical paths, so a symlink that points outside the parent
|
|
22
|
+
* is treated as outside rather than rejected.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveTaskCwd(parentCwd: string, requestedCwd: string | undefined): ResolvedTaskCwd;
|
|
12
25
|
export declare function taskLabel(task: Pick<SubagentTask, "prompt"> & {
|
|
13
26
|
description?: string | null;
|
|
14
27
|
}): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,KAAK,GAAG,EAAsB,KAAK,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAExF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAGlE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAA2B,MAAM,YAAY,CAAC;AAEpG,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,GAAG,mBAAmB,CAAC,CAAC;CAClF;
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,KAAK,GAAG,EAAsB,KAAK,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAExF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAGlE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAA2B,MAAM,YAAY,CAAC;AAEpG,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,GAAG,mBAAmB,CAAC,CAAC;CAClF;AA8BD,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,+EAA+E;IAC/E,YAAY,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,eAAe,CAYnG;AAyBD,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,MAAM,CAItG;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAIzE;AAED,wBAAsB,mBAAmB,CACxC,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,kBAAkB,EAC1B,cAAc,SAAgB,EAC9B,eAAe,CAAC,EAAE,kBAAkB,GAClC,OAAO,CAAC,oBAAoB,CAAC,CAoB/B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
2
|
-
import { isAbsolute, relative, resolve } from "node:path";
|
|
2
|
+
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
3
3
|
import { clampThinkingLevel } from "@earendil-works/pi-ai/compat";
|
|
4
4
|
import { getAgentDir } from "../../config.js";
|
|
5
5
|
import { AGENT_PROFILES } from "./agents.js";
|
|
@@ -21,28 +21,40 @@ function isWithin(parent, child) {
|
|
|
21
21
|
return rest === "" || (rest !== ".." && !rest.startsWith(`..${PATH_SEP}`) && !isAbsolute(rest));
|
|
22
22
|
}
|
|
23
23
|
const PATH_SEP = process.platform === "win32" ? "\\" : "/";
|
|
24
|
+
/** Closest existing ancestor directory, for "does not exist" diagnostics. */
|
|
25
|
+
function nearestExistingParent(candidate) {
|
|
26
|
+
let current = candidate;
|
|
27
|
+
for (let depth = 0; depth < 64; depth++) {
|
|
28
|
+
const parent = dirname(current);
|
|
29
|
+
if (parent === current)
|
|
30
|
+
return current;
|
|
31
|
+
if (existsSync(parent))
|
|
32
|
+
return parent;
|
|
33
|
+
current = parent;
|
|
34
|
+
}
|
|
35
|
+
return current;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolve the requested cwd against the parent working directory. A directory
|
|
39
|
+
* outside the parent is allowed but marked untrusted (the runner starts it
|
|
40
|
+
* without the parent project's trust, so its .pi settings are never loaded);
|
|
41
|
+
* only a missing or non-directory cwd fails. The inside/outside decision is
|
|
42
|
+
* always made on canonical paths, so a symlink that points outside the parent
|
|
43
|
+
* is treated as outside rather than rejected.
|
|
44
|
+
*/
|
|
24
45
|
export function resolveTaskCwd(parentCwd, requestedCwd) {
|
|
25
46
|
const value = normalizeCwdInput(requestedCwd);
|
|
26
47
|
// Models routinely echo the parent working directory back as an absolute
|
|
27
|
-
// path; accept an absolute cwd
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// so their containment is decided by the canonical check below.
|
|
34
|
-
if (!absolute && !isWithin(resolve(parentCwd), candidate))
|
|
35
|
-
throw new Error(`Subagent cwd escapes the parent working directory: ${requestedCwd}`);
|
|
36
|
-
if (!existsSync(candidate) || !statSync(candidate).isDirectory())
|
|
48
|
+
// path; accept an absolute cwd instead of failing the task over path style.
|
|
49
|
+
const candidate = value !== undefined && isAbsolute(value) ? resolve(value) : resolve(parentCwd, value ?? ".");
|
|
50
|
+
if (!existsSync(candidate)) {
|
|
51
|
+
throw new Error(`${candidate} does not exist; nearest existing parent: ${nearestExistingParent(candidate)}`);
|
|
52
|
+
}
|
|
53
|
+
if (!statSync(candidate).isDirectory())
|
|
37
54
|
throw new Error(`Subagent cwd is not a directory: ${candidate}`);
|
|
38
55
|
const realParent = realpathSync(parentCwd);
|
|
39
56
|
const realCandidate = realpathSync(candidate);
|
|
40
|
-
|
|
41
|
-
if (absolute)
|
|
42
|
-
throw new Error("cwd must stay inside the parent working directory.");
|
|
43
|
-
throw new Error(`Subagent cwd escapes the parent working directory: ${requestedCwd}`);
|
|
44
|
-
}
|
|
45
|
-
return realCandidate;
|
|
57
|
+
return { cwd: realCandidate, insideParent: isWithin(realParent, realCandidate) };
|
|
46
58
|
}
|
|
47
59
|
// Exactly two layers: a /agents override wins, otherwise the subagent
|
|
48
60
|
// inherits the parent session. Callers and agent files cannot pick models.
|
|
@@ -85,11 +97,13 @@ export async function resolveSubagentTask(task, parentCwd, parent, configAgentDi
|
|
|
85
97
|
const config = preloadedConfig ?? (await loadSubagentConfig(configAgentDir));
|
|
86
98
|
const override = config.profiles[agent.name];
|
|
87
99
|
const model = resolveModel(override, parent);
|
|
100
|
+
const { cwd, insideParent } = resolveTaskCwd(parentCwd, task.cwd ?? undefined);
|
|
88
101
|
return {
|
|
89
102
|
agent,
|
|
90
103
|
description: taskLabel(task),
|
|
91
104
|
prompt: task.prompt,
|
|
92
|
-
cwd
|
|
105
|
+
cwd,
|
|
106
|
+
insideParent,
|
|
93
107
|
model,
|
|
94
108
|
thinking: resolveThinking(override, parent, model),
|
|
95
109
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/extensions/subagent/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, realpathSync, statSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { type Api, clampThinkingLevel, type Model } from \"@earendil-works/pi-ai/compat\";\nimport { getAgentDir } from \"../../config.ts\";\nimport type { ModelRegistry } from \"../../core/model-registry.ts\";\nimport { AGENT_PROFILES } from \"./agents.ts\";\nimport { findAvailableModel } from \"./model-selection.ts\";\nimport type { SubagentTask } from \"./schema.ts\";\nimport { loadSubagentConfig } from \"./settings.ts\";\nimport { firstPlainLine, truncate } from \"./text.ts\";\nimport type { ResolvedSubagentTask, SubagentConfigFile, SubagentProfileOverride } from \"./types.ts\";\n\nexport interface ParentModelContext {\n\tmodel: Model<Api> | undefined;\n\tthinking: ThinkingLevel;\n\tmodelRegistry: Pick<ModelRegistry, \"find\" | \"getAvailable\" | \"hasConfiguredAuth\">;\n}\n\nfunction normalizeCwdInput(value: string | undefined): string | undefined {\n\tif (value === undefined) return undefined;\n\tconst trimmed = value.trim();\n\tif (!trimmed) throw new Error(\"cwd must not be empty.\");\n\treturn trimmed.startsWith(\"@\") ? trimmed.slice(1) : trimmed;\n}\n\nfunction isWithin(parent: string, child: string): boolean {\n\tconst normalizedParent = process.platform === \"win32\" ? parent.toLowerCase() : parent;\n\tconst normalizedChild = process.platform === \"win32\" ? child.toLowerCase() : child;\n\tconst rest = relative(normalizedParent, normalizedChild);\n\treturn rest === \"\" || (rest !== \"..\" && !rest.startsWith(`..${PATH_SEP}`) && !isAbsolute(rest));\n}\n\nconst PATH_SEP = process.platform === \"win32\" ? \"\\\\\" : \"/\";\n\nexport function resolveTaskCwd(parentCwd: string, requestedCwd: string | undefined): string {\n\tconst value = normalizeCwdInput(requestedCwd);\n\t// Models routinely echo the parent working directory back as an absolute\n\t// path; accept an absolute cwd that stays inside the parent instead of\n\t// failing the whole task over path style.\n\tconst absolute = value !== undefined && isAbsolute(value);\n\tconst candidate = absolute ? resolve(value) : resolve(parentCwd, value ?? \".\");\n\t// Relative inputs get a lexical traversal check before touching the file\n\t// system. Absolute inputs may use the real spelling of a symlinked parent,\n\t// so their containment is decided by the canonical check below.\n\tif (!absolute && !isWithin(resolve(parentCwd), candidate))\n\t\tthrow new Error(`Subagent cwd escapes the parent working directory: ${requestedCwd}`);\n\tif (!existsSync(candidate) || !statSync(candidate).isDirectory())\n\t\tthrow new Error(`Subagent cwd is not a directory: ${candidate}`);\n\tconst realParent = realpathSync(parentCwd);\n\tconst realCandidate = realpathSync(candidate);\n\tif (!isWithin(realParent, realCandidate)) {\n\t\tif (absolute) throw new Error(\"cwd must stay inside the parent working directory.\");\n\t\tthrow new Error(`Subagent cwd escapes the parent working directory: ${requestedCwd}`);\n\t}\n\treturn realCandidate;\n}\n\n// Exactly two layers: a /agents override wins, otherwise the subagent\n// inherits the parent session. Callers and agent files cannot pick models.\nfunction resolveModel(override: SubagentProfileOverride | undefined, parent: ParentModelContext): Model<Api> {\n\tif (override?.model) return findAvailableModel(override.model, parent.modelRegistry);\n\tif (!parent.model) throw new Error(\"The parent session has no active model.\");\n\treturn parent.model;\n}\n\nfunction resolveThinking(\n\toverride: SubagentProfileOverride | undefined,\n\tparent: ParentModelContext,\n\tmodel: Model<Api>,\n): ThinkingLevel {\n\tconst requested = override?.thinking ?? parent.thinking;\n\treturn clampThinkingLevel(model, requested) as ThinkingLevel;\n}\n\n// The schema restricts task.agent to explorer|general; an omitted or null\n// agent resolves to the read-only explorer profile.\nconst DEFAULT_AGENT_NAME = \"explorer\";\n\n// An explicit short label wins; otherwise derive a bounded plain-text label from\n// the briefing's first meaningful line so UI rows and report headings stay readable.\nexport function taskLabel(task: Pick<SubagentTask, \"prompt\"> & { description?: string | null }): string {\n\tconst explicit = task.description?.trim();\n\tif (explicit) return explicit;\n\treturn truncate(firstPlainLine(task.prompt), 80);\n}\n\n/** Group title shown in the /bg list, status line, and completion notification. */\nexport function subagentGroupTitle(tasks: readonly SubagentTask[]): string {\n\tconst labels = tasks.map((task) => taskLabel(task));\n\tif (labels.length === 1) return truncate(`Subagent · ${labels[0]}`, 100);\n\treturn truncate(`Subagent · ${tasks.length} tasks: ${labels.join(\", \")}`, 100);\n}\n\nexport async function resolveSubagentTask(\n\ttask: SubagentTask,\n\tparentCwd: string,\n\tparent: ParentModelContext,\n\tconfigAgentDir = getAgentDir(),\n\tpreloadedConfig?: SubagentConfigFile,\n): Promise<ResolvedSubagentTask> {\n\tconst agentName = task.agent ?? DEFAULT_AGENT_NAME;\n\tconst agent = AGENT_PROFILES.find((candidate) => candidate.name === agentName);\n\tif (!agent) {\n\t\tconst available = AGENT_PROFILES.map((candidate) => candidate.name).join(\", \") || \"none\";\n\t\tthrow new Error(`Unknown agent \"${agentName}\". Available agents: ${available}.`);\n\t}\n\tconst config = preloadedConfig ?? (await loadSubagentConfig(configAgentDir));\n\tconst override = config.profiles[agent.name];\n\tconst model = resolveModel(override, parent);\n\treturn {\n\t\tagent,\n\t\tdescription: taskLabel(task),\n\t\tprompt: task.prompt,\n\t\tcwd: resolveTaskCwd(parentCwd, task.cwd ?? undefined),\n\t\tmodel,\n\t\tthinking: resolveThinking(override, parent, model),\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/extensions/subagent/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, realpathSync, statSync } from \"node:fs\";\nimport { dirname, isAbsolute, relative, resolve } from \"node:path\";\nimport type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { type Api, clampThinkingLevel, type Model } from \"@earendil-works/pi-ai/compat\";\nimport { getAgentDir } from \"../../config.ts\";\nimport type { ModelRegistry } from \"../../core/model-registry.ts\";\nimport { AGENT_PROFILES } from \"./agents.ts\";\nimport { findAvailableModel } from \"./model-selection.ts\";\nimport type { SubagentTask } from \"./schema.ts\";\nimport { loadSubagentConfig } from \"./settings.ts\";\nimport { firstPlainLine, truncate } from \"./text.ts\";\nimport type { ResolvedSubagentTask, SubagentConfigFile, SubagentProfileOverride } from \"./types.ts\";\n\nexport interface ParentModelContext {\n\tmodel: Model<Api> | undefined;\n\tthinking: ThinkingLevel;\n\tmodelRegistry: Pick<ModelRegistry, \"find\" | \"getAvailable\" | \"hasConfiguredAuth\">;\n}\n\nfunction normalizeCwdInput(value: string | undefined): string | undefined {\n\tif (value === undefined) return undefined;\n\tconst trimmed = value.trim();\n\tif (!trimmed) throw new Error(\"cwd must not be empty.\");\n\treturn trimmed.startsWith(\"@\") ? trimmed.slice(1) : trimmed;\n}\n\nfunction isWithin(parent: string, child: string): boolean {\n\tconst normalizedParent = process.platform === \"win32\" ? parent.toLowerCase() : parent;\n\tconst normalizedChild = process.platform === \"win32\" ? child.toLowerCase() : child;\n\tconst rest = relative(normalizedParent, normalizedChild);\n\treturn rest === \"\" || (rest !== \"..\" && !rest.startsWith(`..${PATH_SEP}`) && !isAbsolute(rest));\n}\n\nconst PATH_SEP = process.platform === \"win32\" ? \"\\\\\" : \"/\";\n\n/** Closest existing ancestor directory, for \"does not exist\" diagnostics. */\nfunction nearestExistingParent(candidate: string): string {\n\tlet current = candidate;\n\tfor (let depth = 0; depth < 64; depth++) {\n\t\tconst parent = dirname(current);\n\t\tif (parent === current) return current;\n\t\tif (existsSync(parent)) return parent;\n\t\tcurrent = parent;\n\t}\n\treturn current;\n}\n\nexport interface ResolvedTaskCwd {\n\tcwd: string;\n\t/** False for a directory outside the parent: the task runs untrusted there. */\n\tinsideParent: boolean;\n}\n\n/**\n * Resolve the requested cwd against the parent working directory. A directory\n * outside the parent is allowed but marked untrusted (the runner starts it\n * without the parent project's trust, so its .pi settings are never loaded);\n * only a missing or non-directory cwd fails. The inside/outside decision is\n * always made on canonical paths, so a symlink that points outside the parent\n * is treated as outside rather than rejected.\n */\nexport function resolveTaskCwd(parentCwd: string, requestedCwd: string | undefined): ResolvedTaskCwd {\n\tconst value = normalizeCwdInput(requestedCwd);\n\t// Models routinely echo the parent working directory back as an absolute\n\t// path; accept an absolute cwd instead of failing the task over path style.\n\tconst candidate = value !== undefined && isAbsolute(value) ? resolve(value) : resolve(parentCwd, value ?? \".\");\n\tif (!existsSync(candidate)) {\n\t\tthrow new Error(`${candidate} does not exist; nearest existing parent: ${nearestExistingParent(candidate)}`);\n\t}\n\tif (!statSync(candidate).isDirectory()) throw new Error(`Subagent cwd is not a directory: ${candidate}`);\n\tconst realParent = realpathSync(parentCwd);\n\tconst realCandidate = realpathSync(candidate);\n\treturn { cwd: realCandidate, insideParent: isWithin(realParent, realCandidate) };\n}\n\n// Exactly two layers: a /agents override wins, otherwise the subagent\n// inherits the parent session. Callers and agent files cannot pick models.\nfunction resolveModel(override: SubagentProfileOverride | undefined, parent: ParentModelContext): Model<Api> {\n\tif (override?.model) return findAvailableModel(override.model, parent.modelRegistry);\n\tif (!parent.model) throw new Error(\"The parent session has no active model.\");\n\treturn parent.model;\n}\n\nfunction resolveThinking(\n\toverride: SubagentProfileOverride | undefined,\n\tparent: ParentModelContext,\n\tmodel: Model<Api>,\n): ThinkingLevel {\n\tconst requested = override?.thinking ?? parent.thinking;\n\treturn clampThinkingLevel(model, requested) as ThinkingLevel;\n}\n\n// The schema restricts task.agent to explorer|general; an omitted or null\n// agent resolves to the read-only explorer profile.\nconst DEFAULT_AGENT_NAME = \"explorer\";\n\n// An explicit short label wins; otherwise derive a bounded plain-text label from\n// the briefing's first meaningful line so UI rows and report headings stay readable.\nexport function taskLabel(task: Pick<SubagentTask, \"prompt\"> & { description?: string | null }): string {\n\tconst explicit = task.description?.trim();\n\tif (explicit) return explicit;\n\treturn truncate(firstPlainLine(task.prompt), 80);\n}\n\n/** Group title shown in the /bg list, status line, and completion notification. */\nexport function subagentGroupTitle(tasks: readonly SubagentTask[]): string {\n\tconst labels = tasks.map((task) => taskLabel(task));\n\tif (labels.length === 1) return truncate(`Subagent · ${labels[0]}`, 100);\n\treturn truncate(`Subagent · ${tasks.length} tasks: ${labels.join(\", \")}`, 100);\n}\n\nexport async function resolveSubagentTask(\n\ttask: SubagentTask,\n\tparentCwd: string,\n\tparent: ParentModelContext,\n\tconfigAgentDir = getAgentDir(),\n\tpreloadedConfig?: SubagentConfigFile,\n): Promise<ResolvedSubagentTask> {\n\tconst agentName = task.agent ?? DEFAULT_AGENT_NAME;\n\tconst agent = AGENT_PROFILES.find((candidate) => candidate.name === agentName);\n\tif (!agent) {\n\t\tconst available = AGENT_PROFILES.map((candidate) => candidate.name).join(\", \") || \"none\";\n\t\tthrow new Error(`Unknown agent \"${agentName}\". Available agents: ${available}.`);\n\t}\n\tconst config = preloadedConfig ?? (await loadSubagentConfig(configAgentDir));\n\tconst override = config.profiles[agent.name];\n\tconst model = resolveModel(override, parent);\n\tconst { cwd, insideParent } = resolveTaskCwd(parentCwd, task.cwd ?? undefined);\n\treturn {\n\t\tagent,\n\t\tdescription: taskLabel(task),\n\t\tprompt: task.prompt,\n\t\tcwd,\n\t\tinsideParent,\n\t\tmodel,\n\t\tthinking: resolveThinking(override, parent, model),\n\t};\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAKhE,OAAO,EAAE,KAAK,kBAAkB,EAAuB,MAAM,cAAc,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,aAAa,CAAC;AAahE,OAAO,KAAK,EAAwB,eAAe,EAAE,uBAAuB,EAAiB,MAAM,YAAY,CAAC;AAUhH,qBAAa,eAAe;IAC3B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,KAAK,SAAkB;IAInC,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;IAsBlD,OAAO,CAAC,OAAO;CAYf;AAED,MAAM,WAAW,yBAAyB;IACzC,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAChF,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC;IAC3D,8DAA8D;IAC9D,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAKhE,OAAO,EAAE,KAAK,kBAAkB,EAAuB,MAAM,cAAc,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,aAAa,CAAC;AAahE,OAAO,KAAK,EAAwB,eAAe,EAAE,uBAAuB,EAAiB,MAAM,YAAY,CAAC;AAUhH,qBAAa,eAAe;IAC3B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,KAAK,SAAkB;IAInC,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;IAsBlD,OAAO,CAAC,OAAO;CAYf;AAED,MAAM,WAAW,yBAAyB;IACzC,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAChF,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC;IAC3D,8DAA8D;IAC9D,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAsKD,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CA0DhH;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -145,7 +145,10 @@ async function runWithGate(task, scope, options, dispatch, getState, onProgress)
|
|
|
145
145
|
dispatch,
|
|
146
146
|
modelRuntime: options.modelRuntime,
|
|
147
147
|
agentDir: options.agentDir,
|
|
148
|
-
|
|
148
|
+
// Trust follows the directory, not the parent session: a task that
|
|
149
|
+
// works outside the parent must never load that directory's project
|
|
150
|
+
// settings under the parent's trust conclusion.
|
|
151
|
+
projectTrusted: task.insideParent ? options.projectTrusted : false,
|
|
149
152
|
onProgress,
|
|
150
153
|
});
|
|
151
154
|
const state = getState();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/extensions/subagent/runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { isRetryableAssistantError } from \"@earendil-works/pi-ai/compat\";\nimport type { BackgroundProjection } from \"../../core/background/types.ts\";\nimport type { ModelRuntime } from \"../../core/model-runtime.ts\";\nimport { emptyUsage, mergeUsage, toNestedUsage } from \"./activity.ts\";\nimport { boundSubagentDetails, resultContent } from \"./budget.ts\";\nimport { abortableSleep, createRunCancellation, type RunCancellation } from \"./cancellation.ts\";\nimport { MAX_CONCURRENCY, MAX_TASKS, TASK_RETRY_BASE_DELAY_MS, TASK_RETRY_LIMIT } from \"./constants.ts\";\nimport { type ParentModelContext, resolveSubagentTask } from \"./resolve.ts\";\nimport type { SubagentParams, SubagentTask } from \"./schema.ts\";\nimport { runSdkTask } from \"./sdk-runner.ts\";\nimport { loadSubagentConfig } from \"./settings.ts\";\nimport {\n\tcreateRunState,\n\treduceRun,\n\ttype SubagentRunEvent,\n\ttype SubagentRunState,\n\tstatusOf,\n\tstatusSummary,\n\ttoRunDetails,\n\tversionSum,\n} from \"./state.ts\";\nimport type { ResolvedSubagentTask, SubagentDetails, SubagentExecutionResult, SubagentUsage } from \"./types.ts\";\n\ninterface Waiter {\n\tresolve: (release: () => void) => void;\n\treject: (error: Error) => void;\n\tsignal?: AbortSignal;\n\tabortListener?: () => void;\n\tsettled: boolean;\n}\n\nexport class ConcurrencyGate {\n\tprivate active = 0;\n\tprivate readonly waiters: Waiter[] = [];\n\tprivate readonly limit: number;\n\n\tconstructor(limit = MAX_CONCURRENCY) {\n\t\tthis.limit = limit;\n\t}\n\n\tacquire(signal?: AbortSignal): Promise<() => void> {\n\t\tif (signal?.aborted) return Promise.reject(new Error(\"Subagent was aborted while queued.\"));\n\t\tif (this.active < this.limit) {\n\t\t\tthis.active++;\n\t\t\treturn Promise.resolve(() => this.release());\n\t\t}\n\t\treturn new Promise<() => void>((resolve, reject) => {\n\t\t\tconst waiter: Waiter = { resolve, reject, signal, settled: false };\n\t\t\tif (signal) {\n\t\t\t\twaiter.abortListener = () => {\n\t\t\t\t\tif (waiter.settled) return;\n\t\t\t\t\twaiter.settled = true;\n\t\t\t\t\tconst index = this.waiters.indexOf(waiter);\n\t\t\t\t\tif (index >= 0) this.waiters.splice(index, 1);\n\t\t\t\t\treject(new Error(\"Subagent was aborted while queued.\"));\n\t\t\t\t};\n\t\t\t\tsignal.addEventListener(\"abort\", waiter.abortListener, { once: true });\n\t\t\t}\n\t\t\tthis.waiters.push(waiter);\n\t\t});\n\t}\n\n\tprivate release(): void {\n\t\tthis.active = Math.max(0, this.active - 1);\n\t\twhile (this.waiters.length > 0) {\n\t\t\tconst waiter = this.waiters.shift()!;\n\t\t\tif (waiter.settled || waiter.signal?.aborted) continue;\n\t\t\twaiter.settled = true;\n\t\t\twaiter.signal?.removeEventListener(\"abort\", waiter.abortListener!);\n\t\t\tthis.active++;\n\t\t\twaiter.resolve(() => this.release());\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nexport interface SubagentInvocationOptions {\n\tparams: SubagentParams;\n\tparentCwd: string;\n\tparent: ParentModelContext;\n\tmodelRuntime: ModelRuntime;\n\tagentDir: string;\n\tprojectTrusted: boolean;\n\tsignal?: AbortSignal;\n\tgate: ConcurrencyGate;\n\tonUpdate?: (details: SubagentDetails, projection: BackgroundProjection) => void;\n\t/** Whole-batch preflight and initial publication finished; no worker has started. */\n\tonAccepted?: () => void;\n\tonConfigWarning?: (message: string) => void;\n\tregisterAbort?: (abort: () => Promise<void>) => () => void;\n\t/** Test hook: overrides the task-retry backoff base delay. */\n\ttaskRetryBaseDelayMs?: number;\n\t/** Tool-call id of the invoking call; prefixes per-run ids for readability. */\n\tbatchId?: string;\n}\n\nfunction aggregateUsage(runs: readonly SubagentRunState[]): SubagentUsage {\n\tconst usage = emptyUsage();\n\tfor (const run of runs) mergeUsage(usage, run.usage);\n\treturn usage;\n}\n\n/** Capture report provenance before the tool-details budget can discard it. */\nfunction backgroundProjection(\n\truns: readonly SubagentRunState[],\n\ttasks: readonly ResolvedSubagentTask[],\n\tdetails: SubagentDetails,\n): BackgroundProjection {\n\treturn {\n\t\ttext: statusSummary(details),\n\t\tworkers: runs.map((run, index) => ({\n\t\t\tid: run.id,\n\t\t\tlabel: run.agent,\n\t\t\tprofile: run.agent,\n\t\t\tdescription: run.description,\n\t\t\tstatus: run.status,\n\t\t\tprompt: tasks[index]?.prompt ?? run.description,\n\t\t\tactivity:\n\t\t\t\trun.currentActivity ??\n\t\t\t\trun.activities\n\t\t\t\t\t.slice(-3)\n\t\t\t\t\t.map((item) => item.summary)\n\t\t\t\t\t.join(\"\\n\"),\n\t\t\treport: { text: run.report, truncated: run.reportTruncated },\n\t\t\terror: run.error,\n\t\t\tmodel: `${run.model} · ${run.thinking}`,\n\t\t\tusage: `${run.usage.totalTokens} tokens · $${run.usage.cost.toFixed(4)} · ${run.usage.toolUses} tool calls`,\n\t\t})),\n\t};\n}\n\nfunction emitDetails(\n\truns: SubagentRunState[],\n\ttasks: readonly ResolvedSubagentTask[],\n\tstartedAt: number,\n\tonUpdate: SubagentInvocationOptions[\"onUpdate\"],\n): SubagentDetails {\n\tconst details: SubagentDetails = {\n\t\tstatus: statusOf(runs),\n\t\truns: runs.map(toRunDetails),\n\t\tstartedAt,\n\t\tusage: aggregateUsage(runs),\n\t};\n\tonUpdate?.(boundSubagentDetails(details), backgroundProjection(runs, tasks, details));\n\treturn details;\n}\n\nfunction validateTaskCount(tasks: readonly SubagentTask[]): void {\n\tif (tasks.length === 0) throw new Error(\"Subagent task list must not be empty.\");\n\tif (tasks.length > MAX_TASKS) throw new Error(`Subagent task list is limited to ${MAX_TASKS} tasks.`);\n}\n\nasync function resolveTasks(\n\ttasks: readonly SubagentTask[],\n\toptions: SubagentInvocationOptions,\n): Promise<ResolvedSubagentTask[]> {\n\tvalidateTaskCount(tasks);\n\t// One config load and one resolution pass for the whole batch: every\n\t// task/profile/cwd/model is settled before any run is created or any\n\t// worker starts, so a failing task cannot strand half-initialized runs.\n\tconst config = await loadSubagentConfig(options.agentDir, options.onConfigWarning);\n\treturn Promise.all(\n\t\ttasks.map((task, index) =>\n\t\t\tresolveSubagentTask(task, options.parentCwd, options.parent, options.agentDir, config).catch((error) => {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tthrow new Error(`Subagent task tasks[${index}] failed to resolve: ${message}`);\n\t\t\t}),\n\t\t),\n\t);\n}\n\n// Reuses pi-ai's provider-error classification by wrapping the stored error\n// text in the assistant-message shape it inspects.\nfunction isRetryableRunError(error: string | undefined): boolean {\n\tif (!error) return false;\n\tconst probe = { role: \"assistant\", content: [], stopReason: \"error\", errorMessage: error };\n\treturn isRetryableAssistantError(probe as unknown as Parameters<typeof isRetryableAssistantError>[0]);\n}\n\n// Session-level auto-retry already covers errors that happen inside the agent\n// loop; this catches the paths that bypass it (preflight throws such as auth\n// checks). Only a run that produced nothing is retried, so partial work is\n// never discarded.\nfunction shouldRetryTask(run: SubagentRunState): boolean {\n\treturn (\n\t\trun.status === \"failed\" && run.usage.turns === 0 && run.usage.toolUses === 0 && isRetryableRunError(run.error)\n\t);\n}\n\n// The gate slot is held only while a worker session actually runs. Backoff\n// waits outside the slot (release, sleep, reacquire) so a retrying task\n// cannot starve queued tasks, and aborting during the wait settles the run\n// without occupying the gate.\nasync function runWithGate(\n\ttask: ResolvedSubagentTask,\n\tscope: RunCancellation,\n\toptions: SubagentInvocationOptions,\n\tdispatch: (event: SubagentRunEvent) => void,\n\tgetState: () => SubagentRunState,\n\tonProgress: () => void,\n): Promise<void> {\n\tconst baseDelayMs = options.taskRetryBaseDelayMs ?? TASK_RETRY_BASE_DELAY_MS;\n\tfor (let attempt = 0; ; attempt++) {\n\t\tdispatch({ type: \"retry_started\" });\n\t\tlet release: (() => void) | undefined;\n\t\tlet delayMs = 0;\n\t\ttry {\n\t\t\trelease = await options.gate.acquire(scope.signal);\n\t\t\tif (scope.signal.aborted) {\n\t\t\t\tdispatch({ type: \"abort_while_queued\", endedAt: Date.now() });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdispatch({ type: \"slot_acquired\", startedAt: Date.now() });\n\t\t\tawait runSdkTask({\n\t\t\t\ttask,\n\t\t\t\tscope,\n\t\t\t\tdispatch,\n\t\t\t\tmodelRuntime: options.modelRuntime,\n\t\t\t\tagentDir: options.agentDir,\n\t\t\t\tprojectTrusted: options.projectTrusted,\n\t\t\t\tonProgress,\n\t\t\t});\n\t\t\tconst state = getState();\n\t\t\tif (attempt >= TASK_RETRY_LIMIT || scope.signal.aborted || !shouldRetryTask(state)) return;\n\t\t\tdelayMs = baseDelayMs * 2 ** attempt;\n\t\t\tdispatch({\n\t\t\t\ttype: \"retry_scheduled\",\n\t\t\t\tattempt: attempt + 1,\n\t\t\t\tmaxAttempts: TASK_RETRY_LIMIT,\n\t\t\t\tdeadline: Date.now() + delayMs,\n\t\t\t\terror: state.error,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (scope.signal.aborted) {\n\t\t\t\tdispatch({ type: \"abort_while_queued\", endedAt: Date.now() });\n\t\t\t} else {\n\t\t\t\tdispatch({\n\t\t\t\t\ttype: \"settle\",\n\t\t\t\t\tverdict: \"failed\",\n\t\t\t\t\treport: \"\",\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\tendedAt: Date.now(),\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t} finally {\n\t\t\trelease?.();\n\t\t}\n\t\ttry {\n\t\t\tawait abortableSleep(delayMs, scope);\n\t\t} catch {\n\t\t\tdispatch({ type: \"abort_while_retrying\", endedAt: Date.now() });\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nexport async function runSubagentInvocation(options: SubagentInvocationOptions): Promise<SubagentExecutionResult> {\n\t// Register one invocation-level scope before the first await so shutdown can\n\t// never snapshot the active set between preflight and worker creation.\n\tconst invocationScope = createRunCancellation(options.signal);\n\tconst unregisterInvocation = options.registerAbort?.(invocationScope.abort);\n\ttry {\n\t\t// Defensive count check: the schema already enforces 1..MAX_TASKS, but\n\t\t// strict providers can bypass minItems, so validate before any work.\n\t\tconst tasks = options.params.tasks ?? [];\n\t\tconst resolved = await resolveTasks(tasks, options);\n\t\tconst runs = resolved.map((task, index) => createRunState(task, index, options.batchId, options.parentCwd));\n\t\tconst startedAt = Date.now();\n\t\tconst scopes = runs.map(() => createRunCancellation(invocationScope.signal));\n\t\tconst unregisterChildren = invocationScope.onAbort(async () => {\n\t\t\tawait Promise.allSettled(scopes.map((scope) => scope.abort()));\n\t\t});\n\t\tlet lastVersion = versionSum(runs);\n\t\tconst progress = (): void => {\n\t\t\tconst version = versionSum(runs);\n\t\t\tif (version === lastVersion) return;\n\t\t\tlastVersion = version;\n\t\t\temitDetails(runs, resolved, startedAt, options.onUpdate);\n\t\t};\n\t\tconst dispatch = (index: number, event: SubagentRunEvent): void => {\n\t\t\truns[index] = reduceRun(runs[index]!, event);\n\t\t\tprogress();\n\t\t};\n\t\tlet latestDetails = emitDetails(runs, resolved, startedAt, options.onUpdate);\n\n\t\t// Every task runs concurrently through the shared gate; Promise.all keeps\n\t\t// result order identical to input order. There is no single-task branch:\n\t\t// one task is just a batch of one.\n\t\ttry {\n\t\t\tif (!invocationScope.aborted) options.onAccepted?.();\n\t\t\tawait Promise.all(\n\t\t\t\tresolved.map((task, index) => {\n\t\t\t\t\tconst dispatchToRun = (event: SubagentRunEvent): void => dispatch(index, event);\n\t\t\t\t\treturn runWithGate(task, scopes[index]!, options, dispatchToRun, () => runs[index]!, progress);\n\t\t\t\t}),\n\t\t\t);\n\t\t} finally {\n\t\t\tunregisterChildren();\n\t\t\tfor (const scope of scopes) scope.dispose();\n\t\t}\n\t\tlatestDetails = emitDetails(runs, resolved, startedAt, undefined);\n\t\tlatestDetails.endedAt = Date.now();\n\t\t// Error classification lives in the tool_result handler (index.ts), the\n\t\t// only channel that reaches the session transcript and export.\n\t\treturn {\n\t\t\tcontent: resultContent(latestDetails),\n\t\t\tdetails: boundSubagentDetails(latestDetails),\n\t\t\tprojection: backgroundProjection(runs, resolved, latestDetails),\n\t\t\tusage: toNestedUsage(latestDetails.usage),\n\t\t};\n\t} finally {\n\t\tunregisterInvocation?.();\n\t\tinvocationScope.dispose();\n\t}\n}\n\nexport { isSubagentError } from \"./state.ts\";\n"]}
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/extensions/subagent/runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { isRetryableAssistantError } from \"@earendil-works/pi-ai/compat\";\nimport type { BackgroundProjection } from \"../../core/background/types.ts\";\nimport type { ModelRuntime } from \"../../core/model-runtime.ts\";\nimport { emptyUsage, mergeUsage, toNestedUsage } from \"./activity.ts\";\nimport { boundSubagentDetails, resultContent } from \"./budget.ts\";\nimport { abortableSleep, createRunCancellation, type RunCancellation } from \"./cancellation.ts\";\nimport { MAX_CONCURRENCY, MAX_TASKS, TASK_RETRY_BASE_DELAY_MS, TASK_RETRY_LIMIT } from \"./constants.ts\";\nimport { type ParentModelContext, resolveSubagentTask } from \"./resolve.ts\";\nimport type { SubagentParams, SubagentTask } from \"./schema.ts\";\nimport { runSdkTask } from \"./sdk-runner.ts\";\nimport { loadSubagentConfig } from \"./settings.ts\";\nimport {\n\tcreateRunState,\n\treduceRun,\n\ttype SubagentRunEvent,\n\ttype SubagentRunState,\n\tstatusOf,\n\tstatusSummary,\n\ttoRunDetails,\n\tversionSum,\n} from \"./state.ts\";\nimport type { ResolvedSubagentTask, SubagentDetails, SubagentExecutionResult, SubagentUsage } from \"./types.ts\";\n\ninterface Waiter {\n\tresolve: (release: () => void) => void;\n\treject: (error: Error) => void;\n\tsignal?: AbortSignal;\n\tabortListener?: () => void;\n\tsettled: boolean;\n}\n\nexport class ConcurrencyGate {\n\tprivate active = 0;\n\tprivate readonly waiters: Waiter[] = [];\n\tprivate readonly limit: number;\n\n\tconstructor(limit = MAX_CONCURRENCY) {\n\t\tthis.limit = limit;\n\t}\n\n\tacquire(signal?: AbortSignal): Promise<() => void> {\n\t\tif (signal?.aborted) return Promise.reject(new Error(\"Subagent was aborted while queued.\"));\n\t\tif (this.active < this.limit) {\n\t\t\tthis.active++;\n\t\t\treturn Promise.resolve(() => this.release());\n\t\t}\n\t\treturn new Promise<() => void>((resolve, reject) => {\n\t\t\tconst waiter: Waiter = { resolve, reject, signal, settled: false };\n\t\t\tif (signal) {\n\t\t\t\twaiter.abortListener = () => {\n\t\t\t\t\tif (waiter.settled) return;\n\t\t\t\t\twaiter.settled = true;\n\t\t\t\t\tconst index = this.waiters.indexOf(waiter);\n\t\t\t\t\tif (index >= 0) this.waiters.splice(index, 1);\n\t\t\t\t\treject(new Error(\"Subagent was aborted while queued.\"));\n\t\t\t\t};\n\t\t\t\tsignal.addEventListener(\"abort\", waiter.abortListener, { once: true });\n\t\t\t}\n\t\t\tthis.waiters.push(waiter);\n\t\t});\n\t}\n\n\tprivate release(): void {\n\t\tthis.active = Math.max(0, this.active - 1);\n\t\twhile (this.waiters.length > 0) {\n\t\t\tconst waiter = this.waiters.shift()!;\n\t\t\tif (waiter.settled || waiter.signal?.aborted) continue;\n\t\t\twaiter.settled = true;\n\t\t\twaiter.signal?.removeEventListener(\"abort\", waiter.abortListener!);\n\t\t\tthis.active++;\n\t\t\twaiter.resolve(() => this.release());\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nexport interface SubagentInvocationOptions {\n\tparams: SubagentParams;\n\tparentCwd: string;\n\tparent: ParentModelContext;\n\tmodelRuntime: ModelRuntime;\n\tagentDir: string;\n\tprojectTrusted: boolean;\n\tsignal?: AbortSignal;\n\tgate: ConcurrencyGate;\n\tonUpdate?: (details: SubagentDetails, projection: BackgroundProjection) => void;\n\t/** Whole-batch preflight and initial publication finished; no worker has started. */\n\tonAccepted?: () => void;\n\tonConfigWarning?: (message: string) => void;\n\tregisterAbort?: (abort: () => Promise<void>) => () => void;\n\t/** Test hook: overrides the task-retry backoff base delay. */\n\ttaskRetryBaseDelayMs?: number;\n\t/** Tool-call id of the invoking call; prefixes per-run ids for readability. */\n\tbatchId?: string;\n}\n\nfunction aggregateUsage(runs: readonly SubagentRunState[]): SubagentUsage {\n\tconst usage = emptyUsage();\n\tfor (const run of runs) mergeUsage(usage, run.usage);\n\treturn usage;\n}\n\n/** Capture report provenance before the tool-details budget can discard it. */\nfunction backgroundProjection(\n\truns: readonly SubagentRunState[],\n\ttasks: readonly ResolvedSubagentTask[],\n\tdetails: SubagentDetails,\n): BackgroundProjection {\n\treturn {\n\t\ttext: statusSummary(details),\n\t\tworkers: runs.map((run, index) => ({\n\t\t\tid: run.id,\n\t\t\tlabel: run.agent,\n\t\t\tprofile: run.agent,\n\t\t\tdescription: run.description,\n\t\t\tstatus: run.status,\n\t\t\tprompt: tasks[index]?.prompt ?? run.description,\n\t\t\tactivity:\n\t\t\t\trun.currentActivity ??\n\t\t\t\trun.activities\n\t\t\t\t\t.slice(-3)\n\t\t\t\t\t.map((item) => item.summary)\n\t\t\t\t\t.join(\"\\n\"),\n\t\t\treport: { text: run.report, truncated: run.reportTruncated },\n\t\t\terror: run.error,\n\t\t\tmodel: `${run.model} · ${run.thinking}`,\n\t\t\tusage: `${run.usage.totalTokens} tokens · $${run.usage.cost.toFixed(4)} · ${run.usage.toolUses} tool calls`,\n\t\t})),\n\t};\n}\n\nfunction emitDetails(\n\truns: SubagentRunState[],\n\ttasks: readonly ResolvedSubagentTask[],\n\tstartedAt: number,\n\tonUpdate: SubagentInvocationOptions[\"onUpdate\"],\n): SubagentDetails {\n\tconst details: SubagentDetails = {\n\t\tstatus: statusOf(runs),\n\t\truns: runs.map(toRunDetails),\n\t\tstartedAt,\n\t\tusage: aggregateUsage(runs),\n\t};\n\tonUpdate?.(boundSubagentDetails(details), backgroundProjection(runs, tasks, details));\n\treturn details;\n}\n\nfunction validateTaskCount(tasks: readonly SubagentTask[]): void {\n\tif (tasks.length === 0) throw new Error(\"Subagent task list must not be empty.\");\n\tif (tasks.length > MAX_TASKS) throw new Error(`Subagent task list is limited to ${MAX_TASKS} tasks.`);\n}\n\nasync function resolveTasks(\n\ttasks: readonly SubagentTask[],\n\toptions: SubagentInvocationOptions,\n): Promise<ResolvedSubagentTask[]> {\n\tvalidateTaskCount(tasks);\n\t// One config load and one resolution pass for the whole batch: every\n\t// task/profile/cwd/model is settled before any run is created or any\n\t// worker starts, so a failing task cannot strand half-initialized runs.\n\tconst config = await loadSubagentConfig(options.agentDir, options.onConfigWarning);\n\treturn Promise.all(\n\t\ttasks.map((task, index) =>\n\t\t\tresolveSubagentTask(task, options.parentCwd, options.parent, options.agentDir, config).catch((error) => {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tthrow new Error(`Subagent task tasks[${index}] failed to resolve: ${message}`);\n\t\t\t}),\n\t\t),\n\t);\n}\n\n// Reuses pi-ai's provider-error classification by wrapping the stored error\n// text in the assistant-message shape it inspects.\nfunction isRetryableRunError(error: string | undefined): boolean {\n\tif (!error) return false;\n\tconst probe = { role: \"assistant\", content: [], stopReason: \"error\", errorMessage: error };\n\treturn isRetryableAssistantError(probe as unknown as Parameters<typeof isRetryableAssistantError>[0]);\n}\n\n// Session-level auto-retry already covers errors that happen inside the agent\n// loop; this catches the paths that bypass it (preflight throws such as auth\n// checks). Only a run that produced nothing is retried, so partial work is\n// never discarded.\nfunction shouldRetryTask(run: SubagentRunState): boolean {\n\treturn (\n\t\trun.status === \"failed\" && run.usage.turns === 0 && run.usage.toolUses === 0 && isRetryableRunError(run.error)\n\t);\n}\n\n// The gate slot is held only while a worker session actually runs. Backoff\n// waits outside the slot (release, sleep, reacquire) so a retrying task\n// cannot starve queued tasks, and aborting during the wait settles the run\n// without occupying the gate.\nasync function runWithGate(\n\ttask: ResolvedSubagentTask,\n\tscope: RunCancellation,\n\toptions: SubagentInvocationOptions,\n\tdispatch: (event: SubagentRunEvent) => void,\n\tgetState: () => SubagentRunState,\n\tonProgress: () => void,\n): Promise<void> {\n\tconst baseDelayMs = options.taskRetryBaseDelayMs ?? TASK_RETRY_BASE_DELAY_MS;\n\tfor (let attempt = 0; ; attempt++) {\n\t\tdispatch({ type: \"retry_started\" });\n\t\tlet release: (() => void) | undefined;\n\t\tlet delayMs = 0;\n\t\ttry {\n\t\t\trelease = await options.gate.acquire(scope.signal);\n\t\t\tif (scope.signal.aborted) {\n\t\t\t\tdispatch({ type: \"abort_while_queued\", endedAt: Date.now() });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdispatch({ type: \"slot_acquired\", startedAt: Date.now() });\n\t\t\tawait runSdkTask({\n\t\t\t\ttask,\n\t\t\t\tscope,\n\t\t\t\tdispatch,\n\t\t\t\tmodelRuntime: options.modelRuntime,\n\t\t\t\tagentDir: options.agentDir,\n\t\t\t\t// Trust follows the directory, not the parent session: a task that\n\t\t\t\t// works outside the parent must never load that directory's project\n\t\t\t\t// settings under the parent's trust conclusion.\n\t\t\t\tprojectTrusted: task.insideParent ? options.projectTrusted : false,\n\t\t\t\tonProgress,\n\t\t\t});\n\t\t\tconst state = getState();\n\t\t\tif (attempt >= TASK_RETRY_LIMIT || scope.signal.aborted || !shouldRetryTask(state)) return;\n\t\t\tdelayMs = baseDelayMs * 2 ** attempt;\n\t\t\tdispatch({\n\t\t\t\ttype: \"retry_scheduled\",\n\t\t\t\tattempt: attempt + 1,\n\t\t\t\tmaxAttempts: TASK_RETRY_LIMIT,\n\t\t\t\tdeadline: Date.now() + delayMs,\n\t\t\t\terror: state.error,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (scope.signal.aborted) {\n\t\t\t\tdispatch({ type: \"abort_while_queued\", endedAt: Date.now() });\n\t\t\t} else {\n\t\t\t\tdispatch({\n\t\t\t\t\ttype: \"settle\",\n\t\t\t\t\tverdict: \"failed\",\n\t\t\t\t\treport: \"\",\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\tendedAt: Date.now(),\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t} finally {\n\t\t\trelease?.();\n\t\t}\n\t\ttry {\n\t\t\tawait abortableSleep(delayMs, scope);\n\t\t} catch {\n\t\t\tdispatch({ type: \"abort_while_retrying\", endedAt: Date.now() });\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nexport async function runSubagentInvocation(options: SubagentInvocationOptions): Promise<SubagentExecutionResult> {\n\t// Register one invocation-level scope before the first await so shutdown can\n\t// never snapshot the active set between preflight and worker creation.\n\tconst invocationScope = createRunCancellation(options.signal);\n\tconst unregisterInvocation = options.registerAbort?.(invocationScope.abort);\n\ttry {\n\t\t// Defensive count check: the schema already enforces 1..MAX_TASKS, but\n\t\t// strict providers can bypass minItems, so validate before any work.\n\t\tconst tasks = options.params.tasks ?? [];\n\t\tconst resolved = await resolveTasks(tasks, options);\n\t\tconst runs = resolved.map((task, index) => createRunState(task, index, options.batchId, options.parentCwd));\n\t\tconst startedAt = Date.now();\n\t\tconst scopes = runs.map(() => createRunCancellation(invocationScope.signal));\n\t\tconst unregisterChildren = invocationScope.onAbort(async () => {\n\t\t\tawait Promise.allSettled(scopes.map((scope) => scope.abort()));\n\t\t});\n\t\tlet lastVersion = versionSum(runs);\n\t\tconst progress = (): void => {\n\t\t\tconst version = versionSum(runs);\n\t\t\tif (version === lastVersion) return;\n\t\t\tlastVersion = version;\n\t\t\temitDetails(runs, resolved, startedAt, options.onUpdate);\n\t\t};\n\t\tconst dispatch = (index: number, event: SubagentRunEvent): void => {\n\t\t\truns[index] = reduceRun(runs[index]!, event);\n\t\t\tprogress();\n\t\t};\n\t\tlet latestDetails = emitDetails(runs, resolved, startedAt, options.onUpdate);\n\n\t\t// Every task runs concurrently through the shared gate; Promise.all keeps\n\t\t// result order identical to input order. There is no single-task branch:\n\t\t// one task is just a batch of one.\n\t\ttry {\n\t\t\tif (!invocationScope.aborted) options.onAccepted?.();\n\t\t\tawait Promise.all(\n\t\t\t\tresolved.map((task, index) => {\n\t\t\t\t\tconst dispatchToRun = (event: SubagentRunEvent): void => dispatch(index, event);\n\t\t\t\t\treturn runWithGate(task, scopes[index]!, options, dispatchToRun, () => runs[index]!, progress);\n\t\t\t\t}),\n\t\t\t);\n\t\t} finally {\n\t\t\tunregisterChildren();\n\t\t\tfor (const scope of scopes) scope.dispose();\n\t\t}\n\t\tlatestDetails = emitDetails(runs, resolved, startedAt, undefined);\n\t\tlatestDetails.endedAt = Date.now();\n\t\t// Error classification lives in the tool_result handler (index.ts), the\n\t\t// only channel that reaches the session transcript and export.\n\t\treturn {\n\t\t\tcontent: resultContent(latestDetails),\n\t\t\tdetails: boundSubagentDetails(latestDetails),\n\t\t\tprojection: backgroundProjection(runs, resolved, latestDetails),\n\t\t\tusage: toNestedUsage(latestDetails.usage),\n\t\t};\n\t} finally {\n\t\tunregisterInvocation?.();\n\t\tinvocationScope.dispose();\n\t}\n}\n\nexport { isSubagentError } from \"./state.ts\";\n"]}
|
|
@@ -16,4 +16,13 @@ export declare const SubagentParamsSchema: Type.TObject<{
|
|
|
16
16
|
}>;
|
|
17
17
|
export type SubagentParams = Static<typeof SubagentParamsSchema>;
|
|
18
18
|
export type SubagentTask = Static<typeof TaskSchema>;
|
|
19
|
+
/**
|
|
20
|
+
* Unambiguous argument normalizations applied before schema validation:
|
|
21
|
+
* a single task written at the root ({agent, prompt, ...} with no tasks)
|
|
22
|
+
* wraps into tasks[0] with background left at the root, and root-level null
|
|
23
|
+
* fields the schema does not declare are dropped as strict-mode leftovers.
|
|
24
|
+
* Non-null unknown fields are kept on purpose: validation names them instead
|
|
25
|
+
* of silently discarding what may be briefing content.
|
|
26
|
+
*/
|
|
27
|
+
export declare function normalizeSubagentArguments(raw: unknown): SubagentParams;
|
|
19
28
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAgB,IAAI,EAAE,MAAM,SAAS,CAAC;AAW1D,eAAO,MAAM,UAAU;;;;;EAqBtB,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;;;;;EAahC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAgB,IAAI,EAAE,MAAM,SAAS,CAAC;AAW1D,eAAO,MAAM,UAAU;;;;;EAqBtB,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;;;;;EAahC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAKrD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAevE"}
|
|
@@ -16,7 +16,7 @@ export const TaskSchema = Type.Object({
|
|
|
16
16
|
description: "Complete self-contained briefing; the worker cannot see the parent conversation",
|
|
17
17
|
}),
|
|
18
18
|
description: nullable(Type.String({ minLength: 1, maxLength: 80 }), "Short task label (3-5 words) shown in the /bg list, live rows, and report headings; null or omit to derive it from the prompt"),
|
|
19
|
-
cwd: nullable(Type.String({ minLength: 1, maxLength: 4_096 }), "
|
|
19
|
+
cwd: nullable(Type.String({ minLength: 1, maxLength: 4_096 }), "Worker directory; relative paths resolve against the parent directory. A directory outside the parent runs without that project's settings. Null or omit to inherit."),
|
|
20
20
|
}, { additionalProperties: false });
|
|
21
21
|
export const SubagentParamsSchema = Type.Object({
|
|
22
22
|
background: nullable(Type.Boolean(), "true runs all tasks as one managed background group and returns a group reference immediately; false, null or omit blocks until every worker finishes and returns their reports"),
|
|
@@ -26,4 +26,33 @@ export const SubagentParamsSchema = Type.Object({
|
|
|
26
26
|
description: `Independent tasks run concurrently: at most ${MAX_CONCURRENCY} active at once, excess tasks queue, and results preserve input order`,
|
|
27
27
|
}),
|
|
28
28
|
}, { additionalProperties: false });
|
|
29
|
+
const ROOT_FIELDS = new Set(["background", "tasks"]);
|
|
30
|
+
const TASK_FIELDS = ["agent", "prompt", "description", "cwd"];
|
|
31
|
+
/**
|
|
32
|
+
* Unambiguous argument normalizations applied before schema validation:
|
|
33
|
+
* a single task written at the root ({agent, prompt, ...} with no tasks)
|
|
34
|
+
* wraps into tasks[0] with background left at the root, and root-level null
|
|
35
|
+
* fields the schema does not declare are dropped as strict-mode leftovers.
|
|
36
|
+
* Non-null unknown fields are kept on purpose: validation names them instead
|
|
37
|
+
* of silently discarding what may be briefing content.
|
|
38
|
+
*/
|
|
39
|
+
export function normalizeSubagentArguments(raw) {
|
|
40
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw))
|
|
41
|
+
return raw;
|
|
42
|
+
const args = { ...raw };
|
|
43
|
+
for (const key of Object.keys(args)) {
|
|
44
|
+
if (args[key] === null && !ROOT_FIELDS.has(key))
|
|
45
|
+
delete args[key];
|
|
46
|
+
}
|
|
47
|
+
if (args.tasks === undefined && typeof args.prompt === "string") {
|
|
48
|
+
const task = {};
|
|
49
|
+
for (const key of TASK_FIELDS) {
|
|
50
|
+
if (args[key] !== undefined)
|
|
51
|
+
task[key] = args[key];
|
|
52
|
+
delete args[key];
|
|
53
|
+
}
|
|
54
|
+
args.tasks = [task];
|
|
55
|
+
}
|
|
56
|
+
return args;
|
|
57
|
+
}
|
|
29
58
|
//# sourceMappingURL=schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/extensions/subagent/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAA6B,IAAI,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAElF,yEAAyE;AACzE,mEAAmE;AACnE,yEAAyE;AACzE,qEAAqE;AACrE,SAAS,QAAQ,CAAoB,MAAS,EAAE,WAAmB;IAClE,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CACpC;IACC,KAAK,EAAE,QAAQ,CACd,UAAU,CAAC,oBAAoB,EAAE,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC,EAC1F,2DAA2D,CAC3D;IACD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QACnB,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,MAAM;QACjB,WAAW,EAAE,iFAAiF;KAC9F,CAAC;IACF,WAAW,EAAE,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,EAC5C,+HAA+H,CAC/H;IACD,GAAG,EAAE,QAAQ,CACZ,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAC/C,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/extensions/subagent/schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { StringEnum } from \"@earendil-works/pi-ai\";\nimport { type Static, type TSchema, Type } from \"typebox\";\nimport { MAX_CONCURRENCY, MAX_TASKS, SUBAGENT_AGENT_NAMES } from \"./constants.ts\";\n\n// Strict constrained-sampling providers treat every property as required\n// and reject bare unions at the top level, so the schema is a flat\n// `type: \"object\"` whose optional fields are also nullable: callers omit\n// a field when the grammar allows it and send null when it does not.\nfunction nullable<T extends TSchema>(schema: T, description: string) {\n\treturn Type.Optional(Type.Union([schema, Type.Null()], { description }));\n}\n\nexport const TaskSchema = Type.Object(\n\t{\n\t\tagent: nullable(\n\t\t\tStringEnum(SUBAGENT_AGENT_NAMES, { description: \"Which built-in profile runs this task\" }),\n\t\t\t\"Built-in profile; null or omit for explorer (the default)\",\n\t\t),\n\t\tprompt: Type.String({\n\t\t\tminLength: 1,\n\t\t\tmaxLength: 50_000,\n\t\t\tdescription: \"Complete self-contained briefing; the worker cannot see the parent conversation\",\n\t\t}),\n\t\tdescription: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 80 }),\n\t\t\t\"Short task label (3-5 words) shown in the /bg list, live rows, and report headings; null or omit to derive it from the prompt\",\n\t\t),\n\t\tcwd: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 4_096 }),\n\t\t\t\"Worker directory; relative paths resolve against the parent directory. A directory outside the parent runs without that project's settings. Null or omit to inherit.\",\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const SubagentParamsSchema = Type.Object(\n\t{\n\t\tbackground: nullable(\n\t\t\tType.Boolean(),\n\t\t\t\"true runs all tasks as one managed background group and returns a group reference immediately; false, null or omit blocks until every worker finishes and returns their reports\",\n\t\t),\n\t\ttasks: Type.Array(TaskSchema, {\n\t\t\tminItems: 1,\n\t\t\tmaxItems: MAX_TASKS,\n\t\t\tdescription: `Independent tasks run concurrently: at most ${MAX_CONCURRENCY} active at once, excess tasks queue, and results preserve input order`,\n\t\t}),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type SubagentParams = Static<typeof SubagentParamsSchema>;\nexport type SubagentTask = Static<typeof TaskSchema>;\n\nconst ROOT_FIELDS: ReadonlySet<string> = new Set([\"background\", \"tasks\"]);\nconst TASK_FIELDS = [\"agent\", \"prompt\", \"description\", \"cwd\"] as const;\n\n/**\n * Unambiguous argument normalizations applied before schema validation:\n * a single task written at the root ({agent, prompt, ...} with no tasks)\n * wraps into tasks[0] with background left at the root, and root-level null\n * fields the schema does not declare are dropped as strict-mode leftovers.\n * Non-null unknown fields are kept on purpose: validation names them instead\n * of silently discarding what may be briefing content.\n */\nexport function normalizeSubagentArguments(raw: unknown): SubagentParams {\n\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) return raw as SubagentParams;\n\tconst args: Record<string, unknown> = { ...(raw as Record<string, unknown>) };\n\tfor (const key of Object.keys(args)) {\n\t\tif (args[key] === null && !ROOT_FIELDS.has(key)) delete args[key];\n\t}\n\tif (args.tasks === undefined && typeof args.prompt === \"string\") {\n\t\tconst task: Record<string, unknown> = {};\n\t\tfor (const key of TASK_FIELDS) {\n\t\t\tif (args[key] !== undefined) task[key] = args[key];\n\t\t\tdelete args[key];\n\t\t}\n\t\targs.tasks = [task];\n\t}\n\treturn args as SubagentParams;\n}\n"]}
|
|
@@ -20,6 +20,8 @@ export interface ResolvedSubagentTask {
|
|
|
20
20
|
description: string;
|
|
21
21
|
prompt: string;
|
|
22
22
|
cwd: string;
|
|
23
|
+
/** False when cwd sits outside the parent directory: the run starts without the parent project's trust. */
|
|
24
|
+
insideParent: boolean;
|
|
23
25
|
model: Model<Api>;
|
|
24
26
|
thinking: ThinkingLevel;
|
|
25
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/extensions/subagent/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Model, Usage } from \"@earendil-works/pi-ai\";\nimport type { BackgroundProjection } from \"../../core/background/types.ts\";\nimport type { SubagentAgentName } from \"./constants.ts\";\n\n// Static built-in subagent profile; the only agents a task can select.\nexport interface AgentProfile {\n\tname: SubagentAgentName;\n\ttools: string[];\n\tsystemPrompt: string;\n}\n\nexport interface SubagentProfileOverride {\n\tmodel?: string;\n\tthinking?: ThinkingLevel;\n}\n\nexport interface SubagentConfigFile {\n\tversion: 1;\n\t// Absence means \"inherit the parent session\"; only the two built-in\n\t// profiles exist, so unknown keys are rejected by settings.ts.\n\tprofiles: Partial<Record<SubagentAgentName, SubagentProfileOverride>>;\n}\n\nexport interface ResolvedSubagentTask {\n\tagent: AgentProfile;\n\tdescription: string;\n\tprompt: string;\n\tcwd: string;\n\tmodel: Model<Api>;\n\tthinking: ThinkingLevel;\n}\n\nexport type SubagentRunStatus = \"queued\" | \"running\" | \"completed\" | \"failed\" | \"aborted\";\n/** Aggregate batch status; active runs beat every terminal verdict. */\nexport type SubagentBatchStatus = \"running\" | \"completed\" | \"partial\" | \"failed\" | \"aborted\";\nexport type ToolActivityStatus = \"running\" | \"succeeded\" | \"failed\";\n\nexport interface ToolActivity {\n\tid: string;\n\ttoolName: string;\n\tsummary: string;\n\tstatus: ToolActivityStatus;\n\tstartedAt: number;\n\tendedAt?: number;\n\tresultSummary?: string;\n}\n\n// Flat projection of pi-ai's Usage: the cost breakdown collapses to a\n// scalar total (renderers need one number; toNestedUsage rebuilds the nested\n// shape for the parent transcript), and turns/toolUses/contextTokens track\n// worker progress. The optional pi-ai fields (reasoning, cacheWrite1h) stay\n// optional here and are not aggregated.\nexport type SubagentUsage = Omit<Usage, \"cost\"> & {\n\tcost: number;\n\tturns: number;\n\ttoolUses: number;\n\t/** Context watermark: total tokens of the latest request, not a running sum. */\n\tcontextTokens?: number;\n};\n\nexport interface SubagentRetryDetails {\n\tattempt: number;\n\tmaxAttempts: number;\n\tdeadline: number;\n\terror: string;\n}\n\nexport interface SubagentRunDetails {\n\tid: string;\n\tagent: string;\n\tdescription: string;\n\tcwd: string;\n\tmodel: string;\n\tthinking: ThinkingLevel;\n\tstatus: SubagentRunStatus;\n\tstartedAt?: number;\n\tendedAt?: number;\n\tcurrentActivity?: string;\n\tretry?: SubagentRetryDetails;\n\tactivities: ToolActivity[];\n\t/** Final assistant report; empty until the worker settles. */\n\treport: string;\n\terror?: string;\n\tusage: SubagentUsage;\n}\n\nexport interface SubagentDetails {\n\t/** Settled submission snapshot; live state belongs to Background. */\n\tbackground?: { id: string; submittedAt: number };\n\tstatus: SubagentBatchStatus;\n\truns: SubagentRunDetails[];\n\tstartedAt: number;\n\tendedAt?: number;\n\tusage: SubagentUsage;\n}\n\nexport interface SubagentExecutionResult {\n\tcontent: string;\n\tdetails: SubagentDetails;\n\t/** Internal presentation output, separate from the tool result. */\n\tprojection: BackgroundProjection;\n\tusage?: Usage;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/extensions/subagent/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Model, Usage } from \"@earendil-works/pi-ai\";\nimport type { BackgroundProjection } from \"../../core/background/types.ts\";\nimport type { SubagentAgentName } from \"./constants.ts\";\n\n// Static built-in subagent profile; the only agents a task can select.\nexport interface AgentProfile {\n\tname: SubagentAgentName;\n\ttools: string[];\n\tsystemPrompt: string;\n}\n\nexport interface SubagentProfileOverride {\n\tmodel?: string;\n\tthinking?: ThinkingLevel;\n}\n\nexport interface SubagentConfigFile {\n\tversion: 1;\n\t// Absence means \"inherit the parent session\"; only the two built-in\n\t// profiles exist, so unknown keys are rejected by settings.ts.\n\tprofiles: Partial<Record<SubagentAgentName, SubagentProfileOverride>>;\n}\n\nexport interface ResolvedSubagentTask {\n\tagent: AgentProfile;\n\tdescription: string;\n\tprompt: string;\n\tcwd: string;\n\t/** False when cwd sits outside the parent directory: the run starts without the parent project's trust. */\n\tinsideParent: boolean;\n\tmodel: Model<Api>;\n\tthinking: ThinkingLevel;\n}\n\nexport type SubagentRunStatus = \"queued\" | \"running\" | \"completed\" | \"failed\" | \"aborted\";\n/** Aggregate batch status; active runs beat every terminal verdict. */\nexport type SubagentBatchStatus = \"running\" | \"completed\" | \"partial\" | \"failed\" | \"aborted\";\nexport type ToolActivityStatus = \"running\" | \"succeeded\" | \"failed\";\n\nexport interface ToolActivity {\n\tid: string;\n\ttoolName: string;\n\tsummary: string;\n\tstatus: ToolActivityStatus;\n\tstartedAt: number;\n\tendedAt?: number;\n\tresultSummary?: string;\n}\n\n// Flat projection of pi-ai's Usage: the cost breakdown collapses to a\n// scalar total (renderers need one number; toNestedUsage rebuilds the nested\n// shape for the parent transcript), and turns/toolUses/contextTokens track\n// worker progress. The optional pi-ai fields (reasoning, cacheWrite1h) stay\n// optional here and are not aggregated.\nexport type SubagentUsage = Omit<Usage, \"cost\"> & {\n\tcost: number;\n\tturns: number;\n\ttoolUses: number;\n\t/** Context watermark: total tokens of the latest request, not a running sum. */\n\tcontextTokens?: number;\n};\n\nexport interface SubagentRetryDetails {\n\tattempt: number;\n\tmaxAttempts: number;\n\tdeadline: number;\n\terror: string;\n}\n\nexport interface SubagentRunDetails {\n\tid: string;\n\tagent: string;\n\tdescription: string;\n\tcwd: string;\n\tmodel: string;\n\tthinking: ThinkingLevel;\n\tstatus: SubagentRunStatus;\n\tstartedAt?: number;\n\tendedAt?: number;\n\tcurrentActivity?: string;\n\tretry?: SubagentRetryDetails;\n\tactivities: ToolActivity[];\n\t/** Final assistant report; empty until the worker settles. */\n\treport: string;\n\terror?: string;\n\tusage: SubagentUsage;\n}\n\nexport interface SubagentDetails {\n\t/** Settled submission snapshot; live state belongs to Background. */\n\tbackground?: { id: string; submittedAt: number };\n\tstatus: SubagentBatchStatus;\n\truns: SubagentRunDetails[];\n\tstartedAt: number;\n\tendedAt?: number;\n\tusage: SubagentUsage;\n}\n\nexport interface SubagentExecutionResult {\n\tcontent: string;\n\tdetails: SubagentDetails;\n\t/** Internal presentation output, separate from the tool result. */\n\tprojection: BackgroundProjection;\n\tusage?: Usage;\n}\n"]}
|