@astralyn/pi 0.82.6 → 0.82.7
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 +27 -0
- package/README.md +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +11 -13
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/core/extensions/types.d.ts +4 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +2 -2
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/tools/bash.d.ts +1 -5
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +16 -41
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +42 -11
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +6 -7
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +17 -8
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +3 -3
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +4 -4
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +7 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +11 -0
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +2 -3
- package/dist/core/tools/write.js.map +1 -1
- package/dist/extensions/deepwiki/render.d.ts.map +1 -1
- package/dist/extensions/deepwiki/render.js +34 -22
- package/dist/extensions/deepwiki/render.js.map +1 -1
- package/dist/extensions/plan/constants.d.ts +32 -4
- package/dist/extensions/plan/constants.d.ts.map +1 -1
- package/dist/extensions/plan/constants.js +37 -6
- package/dist/extensions/plan/constants.js.map +1 -1
- package/dist/extensions/plan/index.d.ts +27 -0
- package/dist/extensions/plan/index.d.ts.map +1 -1
- package/dist/extensions/plan/index.js +150 -44
- package/dist/extensions/plan/index.js.map +1 -1
- package/dist/extensions/plan/schema.d.ts +5 -0
- package/dist/extensions/plan/schema.d.ts.map +1 -1
- package/dist/extensions/plan/schema.js.map +1 -1
- package/dist/extensions/plan/state.d.ts +11 -2
- package/dist/extensions/plan/state.d.ts.map +1 -1
- package/dist/extensions/plan/state.js +31 -9
- package/dist/extensions/plan/state.js.map +1 -1
- package/dist/extensions/plan/storage.d.ts +11 -3
- package/dist/extensions/plan/storage.d.ts.map +1 -1
- package/dist/extensions/plan/storage.js +45 -20
- package/dist/extensions/plan/storage.js.map +1 -1
- package/dist/extensions/plan/view.d.ts +15 -7
- package/dist/extensions/plan/view.d.ts.map +1 -1
- package/dist/extensions/plan/view.js +91 -16
- package/dist/extensions/plan/view.js.map +1 -1
- package/dist/extensions/question/dialog.d.ts.map +1 -1
- package/dist/extensions/question/dialog.js +29 -10
- package/dist/extensions/question/dialog.js.map +1 -1
- package/dist/extensions/question/index.d.ts.map +1 -1
- package/dist/extensions/question/index.js +7 -2
- package/dist/extensions/question/index.js.map +1 -1
- package/dist/extensions/question/render.d.ts +4 -8
- package/dist/extensions/question/render.d.ts.map +1 -1
- package/dist/extensions/question/render.js +202 -29
- package/dist/extensions/question/render.js.map +1 -1
- package/dist/extensions/question/results.d.ts.map +1 -1
- package/dist/extensions/question/results.js +1 -0
- package/dist/extensions/question/results.js.map +1 -1
- package/dist/extensions/question/schema.d.ts.map +1 -1
- package/dist/extensions/question/schema.js +2 -2
- package/dist/extensions/question/schema.js.map +1 -1
- package/dist/extensions/question/types.d.ts +1 -0
- package/dist/extensions/question/types.d.ts.map +1 -1
- package/dist/extensions/question/types.js +1 -1
- package/dist/extensions/question/types.js.map +1 -1
- package/dist/extensions/router/stream.d.ts +1 -0
- package/dist/extensions/router/stream.d.ts.map +1 -1
- package/dist/extensions/router/stream.js +44 -13
- package/dist/extensions/router/stream.js.map +1 -1
- package/dist/extensions/subagent/constants.d.ts +1 -0
- package/dist/extensions/subagent/constants.d.ts.map +1 -1
- package/dist/extensions/subagent/constants.js +1 -0
- package/dist/extensions/subagent/constants.js.map +1 -1
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +2 -0
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +121 -48
- package/dist/extensions/subagent/render.js.map +1 -1
- package/dist/extensions/subagent/retry.d.ts +17 -0
- package/dist/extensions/subagent/retry.d.ts.map +1 -0
- package/dist/extensions/subagent/retry.js +41 -0
- package/dist/extensions/subagent/retry.js.map +1 -0
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +33 -5
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/sdk-runner.d.ts +6 -0
- package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
- package/dist/extensions/subagent/sdk-runner.js +46 -24
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/types.d.ts +7 -0
- package/dist/extensions/subagent/types.d.ts.map +1 -1
- package/dist/extensions/subagent/types.js.map +1 -1
- package/dist/extensions/todo/index.d.ts.map +1 -1
- package/dist/extensions/todo/index.js +1 -1
- package/dist/extensions/todo/index.js.map +1 -1
- package/dist/extensions/todo/state.d.ts.map +1 -1
- package/dist/extensions/todo/state.js +10 -2
- package/dist/extensions/todo/state.js.map +1 -1
- package/dist/extensions/todo/view.d.ts +1 -1
- package/dist/extensions/todo/view.d.ts.map +1 -1
- package/dist/extensions/todo/view.js +179 -34
- package/dist/extensions/todo/view.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +2 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js +5 -0
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +1 -0
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +4 -2
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts +13 -6
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +54 -17
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +10 -6
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts +11 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +56 -0
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +3 -0
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +52 -2
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +10 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +133 -18
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-group.d.ts +1 -0
- package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-group.js +5 -0
- package/dist/modes/interactive/components/tool-group.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +10 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +55 -2
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +5 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +72 -18
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +3 -2
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/utils/paths.d.ts +6 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +8 -0
- package/dist/utils/paths.js.map +1 -1
- package/docs/bundled/README.md +1 -0
- package/docs/bundled/extensions/deepwiki.md +1 -1
- package/docs/bundled/extensions/plan.md +10 -9
- package/docs/bundled/extensions/question.md +7 -5
- package/docs/bundled/extensions/router.md +3 -4
- package/docs/bundled/extensions/statusline.md +0 -1
- package/docs/bundled/extensions/subagent.md +4 -3
- package/docs/bundled/extensions/todo.md +1 -1
- package/docs/bundled/tool-presentation.md +17 -16
- package/docs/extensions.md +20 -5
- package/docs/rpc.md +1 -1
- package/docs/usage.md +1 -1
- package/npm-shrinkwrap.json +6 -6
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/extensions/question/render.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { answerScalar } from \"./results.ts\";\nimport type { Question, QuestionToolDetails } from \"./types.ts\";\n\ntype RenderOptions = { expanded: boolean };\n\ntype ResultLike = {\n\tcontent: Array<{ type: string; text?: string }>;\n\tdetails?: QuestionToolDetails;\n};\n\nfunction questionsFromArgs(args: unknown): Question[] {\n\tif (!args || typeof args !== \"object\" || !(\"questions\" in args) || !Array.isArray(args.questions)) return [];\n\treturn args.questions.filter(\n\t\t(question): question is Question =>\n\t\t\tBoolean(question) &&\n\t\t\ttypeof question === \"object\" &&\n\t\t\t\"header\" in question &&\n\t\t\ttypeof question.header === \"string\",\n\t);\n}\n\nfunction resultFallback(result: ResultLike): string {\n\treturn result.content\n\t\t.filter(\n\t\t\t(block): block is { type: string; text: string } => block.type === \"text\" && typeof block.text === \"string\",\n\t\t)\n\t\t.map((block) => block.text)\n\t\t.join(\"\\n\");\n}\n\nexport function renderQuestionCall(args: unknown, theme: Theme): Text {\n\tconst questions = questionsFromArgs(args);\n\tconst headers = questions.map((question) => question.header).join(\", \");\n\tconst count = `${questions.length} decision${questions.length === 1 ? \"\" : \"s\"}`;\n\tconst summary = questions.length === 0 ? \"asking for a decision\" : headers ? `${count}: ${headers}` : count;\n\treturn new Text(`${theme.fg(\"toolTitle\", theme.bold(\"question\"))} ${theme.fg(\"muted\", summary)}`, 0, 0);\n}\n\nexport function renderQuestionResult(result: ResultLike, options: RenderOptions, theme: Theme): Text {\n\tconst details = result.details;\n\tif (!details) return new Text(resultFallback(result), 0, 0);\n\n\tif (details.outcome === \"cancelled\") return new Text(theme.fg(\"warning\", \"Cancelled\"), 0, 0);\n\tif (details.outcome === \"needs_clarification\") {\n\t\treturn new Text(theme.fg(\"warning\", \"Wants to discuss the choices before answering\"), 0, 0);\n\t}\n\tif (details.outcome === \"error\") {\n\t\treturn new Text(theme.fg(\"error\", `Question error: ${details.error ?? \"unknown error\"}`), 0, 0);\n\t}\n\n\tconst title = theme.fg(\n\t\t\"success\",\n\t\t`✓ Answered ${details.answers.length} decision${details.answers.length === 1 ? \"\" : \"s\"}`,\n\t);\n\tif (!options.expanded) return new Text(title, 0, 0);\n\n\tconst answers = details.answers.map((answer) => {\n\t\tconst notes = answer.notes?.length\n\t\t\t? `\\n${answer.notes.map((note) => theme.fg(\"muted\", ` Note for ${note.option}: ${note.text}`)).join(\"\\n\")}`\n\t\t\t: \"\";\n\t\treturn `${theme.fg(\"accent\", answer.header)}: ${theme.fg(\"text\", answerScalar(answer))}${notes}`;\n\t});\n\treturn new Text(`${title}\\n${answers.join(\"\\n\")}`, 0, 0);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/extensions/question/render.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport { keyLabel } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { QUESTION_LIMITS } from \"./limits.ts\";\nimport { answerScalar } from \"./results.ts\";\nimport type { QuestionAnswer, QuestionOutcome } from \"./types.ts\";\n\ntype RenderOptions = { expanded: boolean };\n\ntype ResultLike = {\n\tcontent?: unknown;\n\tdetails?: unknown;\n};\n\ninterface RenderQuestion {\n\theader: string;\n\tquestion: string;\n\tmultiSelect: boolean;\n}\n\ninterface RenderDetails {\n\tanswers: QuestionAnswer[];\n\toutcome: QuestionOutcome;\n\tmessage?: string;\n}\n\nconst MAX_RENDERED_QUESTIONS = 4;\nconst MAX_RENDERED_ANSWERS = 4;\nconst MAX_RENDERED_SELECTIONS = 5;\nconst MAX_RENDERED_ANSWER_CHARS = 400;\nconst MAX_RENDERED_NOTE_CHARS = 400;\nconst MAX_RENDERED_ERROR_CHARS = 400;\nconst MAX_RENDERED_VALIDATION_SUMMARY_CHARS = 240;\nconst MAX_RENDERED_FALLBACK_CHARS = 1_000;\n\nfunction safeRecord(value: unknown): Record<string, unknown> | undefined {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value)\n\t\t? (value as Record<string, unknown>)\n\t\t: undefined;\n}\n\nfunction safeValue(record: Record<string, unknown>, key: string): unknown {\n\ttry {\n\t\treturn record[key];\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction truncate(text: string, limit: number): string {\n\treturn text.length > limit ? `${text.slice(0, Math.max(0, limit - 1))}…` : text;\n}\n\nfunction oneLine(value: unknown, limit: number): string {\n\treturn typeof value === \"string\" ? truncate(value.replace(/\\s+/gu, \" \").trim(), limit) : \"\";\n}\n\nfunction questionsFromArgs(args: unknown): RenderQuestion[] {\n\tconst record = safeRecord(args);\n\tif (!record) return [];\n\tconst rawQuestions = safeValue(record, \"questions\");\n\tif (!Array.isArray(rawQuestions)) return [];\n\tconst questions: RenderQuestion[] = [];\n\tfor (const rawQuestion of rawQuestions.slice(0, MAX_RENDERED_QUESTIONS)) {\n\t\tconst question = safeRecord(rawQuestion);\n\t\tif (!question) continue;\n\t\tconst rawHeader = safeValue(question, \"header\");\n\t\tif (typeof rawHeader !== \"string\") continue;\n\t\tconst header = oneLine(rawHeader, QUESTION_LIMITS.headerChars) || `Decision ${questions.length + 1}`;\n\t\tquestions.push({\n\t\t\theader,\n\t\t\tquestion: oneLine(safeValue(question, \"question\"), QUESTION_LIMITS.questionChars),\n\t\t\tmultiSelect: safeValue(question, \"multiSelect\") === true,\n\t\t});\n\t}\n\treturn questions;\n}\n\nfunction resultFallback(result: ResultLike): string {\n\tif (!Array.isArray(result.content)) return \"\";\n\tconst blocks: string[] = [];\n\tfor (const rawBlock of result.content.slice(0, 8)) {\n\t\tconst block = safeRecord(rawBlock);\n\t\tif (!block || safeValue(block, \"type\") !== \"text\") continue;\n\t\tconst text = safeValue(block, \"text\");\n\t\tif (typeof text === \"string\") blocks.push(text);\n\t}\n\treturn truncate(blocks.join(\"\\n\"), MAX_RENDERED_FALLBACK_CHARS);\n}\n\nfunction validationSummary(text: string): { summary: string; hiddenErrors: number } | undefined {\n\tconst match = /^Validation failed for tool\\s+\"question\":\\s*([\\s\\S]*?)(?:\\r?\\n\\s*\\r?\\nReceived arguments:|$)/u.exec(\n\t\ttext.trim(),\n\t);\n\tif (!match) return undefined;\n\tconst errors = match[1]\n\t\t.split(/\\r?\\n/u)\n\t\t.map((line) => line.trim().replace(/^-\\s*/u, \"\"))\n\t\t.filter(Boolean);\n\tconst firstError = oneLine(errors[0], MAX_RENDERED_VALIDATION_SUMMARY_CHARS) || \"schema validation failed\";\n\treturn {\n\t\tsummary: `Invalid arguments · ${firstError}`,\n\t\thiddenErrors: Math.max(0, errors.length - 1),\n\t};\n}\n\nfunction renderFallbackResult(result: ResultLike, expanded: boolean, theme: Theme): Text {\n\tconst fallback = resultFallback(result);\n\tif (!fallback) return new Text(\"Question result unavailable\", 0, 0);\n\tconst validation = validationSummary(fallback);\n\tif (!validation || expanded) return new Text(fallback, 0, 0);\n\n\tconst moreErrors = validation.hiddenErrors > 0 ? ` · +${validation.hiddenErrors} more` : \"\";\n\tconst expandKey = keyLabel(\"app.tools.expand\");\n\tconst hint = theme.fg(\"muted\", expandKey ? ` (${expandKey} to expand)` : \" (more details available)\");\n\treturn new Text(`${theme.fg(\"error\", validation.summary)}${theme.fg(\"muted\", moreErrors)}${hint}`, 0, 0);\n}\n\nfunction normalizeAnswer(value: unknown, index: number): QuestionAnswer | undefined {\n\tconst raw = safeRecord(value);\n\tif (!raw) return undefined;\n\tconst rawHeader = safeValue(raw, \"header\");\n\tif (typeof rawHeader !== \"string\") return undefined;\n\tconst header = oneLine(rawHeader, QUESTION_LIMITS.headerChars) || `Decision ${index + 1}`;\n\tconst kindValue = safeValue(raw, \"kind\");\n\tconst kind = kindValue === \"multi\" || kindValue === \"custom\" ? kindValue : \"option\";\n\tconst rawIndex = safeValue(raw, \"questionIndex\");\n\tconst questionIndex =\n\t\ttypeof rawIndex === \"number\" && Number.isSafeInteger(rawIndex) && rawIndex >= 0 ? rawIndex : index;\n\tconst question = oneLine(safeValue(raw, \"question\"), QUESTION_LIMITS.questionChars);\n\tconst answer = oneLine(safeValue(raw, \"answer\"), MAX_RENDERED_ANSWER_CHARS);\n\n\tconst rawSelected = safeValue(raw, \"selected\");\n\tconst selected = Array.isArray(rawSelected)\n\t\t? rawSelected\n\t\t\t\t.slice(0, MAX_RENDERED_SELECTIONS)\n\t\t\t\t.map((entry, selectedIndex) => {\n\t\t\t\t\tif (typeof entry !== \"string\") return \"\";\n\t\t\t\t\treturn oneLine(entry, MAX_RENDERED_ANSWER_CHARS) || `Option ${selectedIndex + 1}`;\n\t\t\t\t})\n\t\t\t\t.filter(Boolean)\n\t\t: undefined;\n\tconst rawNotes = safeValue(raw, \"notes\");\n\tconst notes = Array.isArray(rawNotes)\n\t\t? rawNotes\n\t\t\t\t.slice(0, MAX_RENDERED_ANSWERS)\n\t\t\t\t.map((entry) => {\n\t\t\t\t\tconst note = safeRecord(entry);\n\t\t\t\t\tif (!note) return undefined;\n\t\t\t\t\tconst option = oneLine(safeValue(note, \"option\"), QUESTION_LIMITS.optionLabelChars);\n\t\t\t\t\tconst text = oneLine(safeValue(note, \"text\"), MAX_RENDERED_NOTE_CHARS);\n\t\t\t\t\treturn option && text ? { option, text } : undefined;\n\t\t\t\t})\n\t\t\t\t.filter((note): note is { option: string; text: string } => note !== undefined)\n\t\t: undefined;\n\n\treturn {\n\t\tquestionIndex,\n\t\tquestion,\n\t\theader,\n\t\tkind,\n\t\tanswer: answer || null,\n\t\t...(kind === \"multi\" && selected?.length ? { selected } : {}),\n\t\t...(notes?.length ? { notes } : {}),\n\t};\n}\n\nfunction normalizeDetails(value: unknown): RenderDetails | undefined {\n\tconst raw = safeRecord(value);\n\tif (!raw) return undefined;\n\tconst outcome = safeValue(raw, \"outcome\");\n\tif (outcome !== \"answered\" && outcome !== \"cancelled\" && outcome !== \"needs_clarification\" && outcome !== \"error\") {\n\t\treturn undefined;\n\t}\n\tconst rawAnswers = safeValue(raw, \"answers\");\n\tconst answers = Array.isArray(rawAnswers)\n\t\t? rawAnswers\n\t\t\t\t.slice(0, MAX_RENDERED_ANSWERS)\n\t\t\t\t.map((answer, index) => normalizeAnswer(answer, index))\n\t\t\t\t.filter((answer): answer is QuestionAnswer => answer !== undefined)\n\t\t: [];\n\tconst message = oneLine(safeValue(raw, \"message\"), MAX_RENDERED_ERROR_CHARS);\n\treturn { answers, outcome, ...(message ? { message } : {}) };\n}\n\nfunction errorMessage(result: ResultLike, details: RenderDetails): string {\n\tif (details.message) return details.message;\n\tconst fallback = resultFallback(result).trim();\n\tconst match = /^Question tool error \\([^)]*\\):\\s*([\\s\\S]+)$/u.exec(fallback);\n\treturn truncate(match?.[1]?.trim() || \"The question tool could not continue\", MAX_RENDERED_ERROR_CHARS);\n}\n\nfunction answerLines(answers: QuestionAnswer[], theme: Theme): string[] {\n\treturn answers.map((answer) => {\n\t\tconst notes = answer.notes?.length\n\t\t\t? `\\n${answer.notes.map((note) => theme.fg(\"muted\", ` Note for ${note.option}: ${note.text}`)).join(\"\\n\")}`\n\t\t\t: \"\";\n\t\treturn `${theme.fg(\"accent\", answer.header)}: ${theme.fg(\"text\", answerScalar(answer))}${notes}`;\n\t});\n}\n\nfunction renderOutcome(title: string, details: RenderDetails, expanded: boolean, theme: Theme): Text {\n\tif (!expanded || details.answers.length === 0) return new Text(title, 0, 0);\n\treturn new Text(`${title}\\n${answerLines(details.answers, theme).join(\"\\n\")}`, 0, 0);\n}\n\nfunction answerProgress(details: RenderDetails, args: unknown): string {\n\tconst total = questionsFromArgs(args).length;\n\treturn total > 0 ? `answered ${details.answers.length} of ${total}` : `answered ${details.answers.length}`;\n}\n\nexport function renderQuestionCall(args: unknown, theme: Theme, expanded: boolean): Text {\n\tconst questions = questionsFromArgs(args);\n\tconst headers = questions.map((question) => question.header).join(\", \");\n\tconst count = `${questions.length} decision${questions.length === 1 ? \"\" : \"s\"}`;\n\tconst summary = questions.length === 0 ? \"asking for a decision\" : headers ? `${count}: ${headers}` : count;\n\tconst title = `${theme.fg(\"toolTitle\", theme.bold(\"question\"))} ${theme.fg(\"muted\", summary)}`;\n\tif (!expanded || questions.length === 0) return new Text(title, 0, 0);\n\tconst detailLines = questions.map((question) => {\n\t\tconst multi = question.multiSelect ? \" (multi-select)\" : \"\";\n\t\tconst body = question.question ? `: ${question.question}` : \"\";\n\t\treturn theme.fg(\"dim\", `${question.header}${multi}${body}`);\n\t});\n\treturn new Text(`${title}\\n${detailLines.join(\"\\n\")}`, 0, 0);\n}\n\nexport function renderQuestionResult(result: ResultLike, options: RenderOptions, theme: Theme, args?: unknown): Text {\n\tconst details = normalizeDetails(result.details);\n\tif (!details) return renderFallbackResult(result, options.expanded, theme);\n\n\tif (details.outcome === \"error\") {\n\t\treturn new Text(theme.fg(\"error\", `Question error: ${errorMessage(result, details)}`), 0, 0);\n\t}\n\tif (details.outcome === \"cancelled\") {\n\t\tconst title = theme.fg(\"warning\", `Cancelled · ${answerProgress(details, args)}`);\n\t\treturn renderOutcome(title, details, options.expanded, theme);\n\t}\n\tif (details.outcome === \"needs_clarification\") {\n\t\tconst title = theme.fg(\"warning\", `Wants to discuss · ${answerProgress(details, args)}`);\n\t\treturn renderOutcome(title, details, options.expanded, theme);\n\t}\n\n\tconst title = theme.fg(\n\t\t\"success\",\n\t\t`✓ Answered ${details.answers.length} decision${details.answers.length === 1 ? \"\" : \"s\"}`,\n\t);\n\treturn renderOutcome(title, details, options.expanded, theme);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"results.d.ts","sourceRoot":"","sources":["../../../src/extensions/question/results.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAoBzF,wBAAgB,WAAW,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,CAAC,mBAAmB,CAAC,
|
|
1
|
+
{"version":3,"file":"results.d.ts","sourceRoot":"","sources":["../../../src/extensions/question/results.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAoBzF,wBAAgB,WAAW,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,CAAC,mBAAmB,CAAC,CAQ3G;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAG3D;AAiBD,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,eAAe,CAAC,mBAAmB,CAAC,CAS7F;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,cAAc,EAAO,GAAG,eAAe,CAAC,mBAAmB,CAAC,CAOjG;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,cAAc,EAAO,GAAG,eAAe,CAAC,mBAAmB,CAAC,CAYxG","sourcesContent":["import type { AgentToolResult } from \"../../core/extensions/types.ts\";\nimport { QUESTION_LIMITS, TRUNCATION_FOLLOW_UP } from \"./limits.ts\";\nimport type { QuestionAnswer, QuestionToolDetails, QuestionToolError } from \"./types.ts\";\n\nconst DECLINE_MESSAGE = \"User declined to answer the questions.\";\nconst CLARIFICATION_MESSAGE = \"The user wants to discuss these questions before choosing an answer.\";\nconst ENVELOPE_PREFIX = \"User decisions:\";\nconst ENVELOPE_SUFFIX = \"Continue with these decisions in mind.\";\n\nfunction buildToolResult(text: string, details: QuestionToolDetails): AgentToolResult<QuestionToolDetails> {\n\treturn {\n\t\tcontent: [{ type: \"text\", text }],\n\t\tdetails,\n\t};\n}\n\nfunction boundedText(text: string): string {\n\tif (text.length <= QUESTION_LIMITS.modelResultChars) return text;\n\tconst suffix = `\\n\\n[Question result truncated. ${TRUNCATION_FOLLOW_UP}]`;\n\treturn `${text.slice(0, Math.max(0, QUESTION_LIMITS.modelResultChars - suffix.length))}${suffix}`;\n}\n\nexport function errorResult(error: QuestionToolError, message: string): AgentToolResult<QuestionToolDetails> {\n\treturn buildToolResult(`Question tool error (${error}): ${message}`, {\n\t\tanswers: [],\n\t\toutcome: \"error\",\n\t\tcancelled: false,\n\t\terror,\n\t\tmessage,\n\t});\n}\n\nexport function answerScalar(answer: QuestionAnswer): string {\n\tif (answer.kind === \"multi\") return answer.selected?.length ? answer.selected.join(\", \") : \"(no input)\";\n\treturn answer.answer && answer.answer.length > 0 ? answer.answer : \"(no input)\";\n}\n\nfunction answerKindLabel(answer: QuestionAnswer): string {\n\tif (answer.kind === \"multi\") return \"Selections\";\n\treturn answer.kind === \"custom\" ? \"Custom answer\" : \"Selected option\";\n}\n\nfunction answerSegment(answer: QuestionAnswer): string {\n\tconst lines = [\n\t\t`${answer.questionIndex + 1}. [${answer.header}] ${answer.question}`,\n\t\t` ${answerKindLabel(answer)}: ${answerScalar(answer)}`,\n\t];\n\tif (answer.preview) lines.push(\" Preview: selected (kept in tool details)\");\n\tfor (const note of answer.notes ?? []) lines.push(` Note for ${note.option}: ${note.text}`);\n\treturn lines.join(\"\\n\");\n}\n\nexport function successResult(answers: QuestionAnswer[]): AgentToolResult<QuestionToolDetails> {\n\tconst text = answers.length\n\t\t? boundedText(`${ENVELOPE_PREFIX}\\n${answers.map(answerSegment).join(\"\\n\\n\")}\\n\\n${ENVELOPE_SUFFIX}`)\n\t\t: DECLINE_MESSAGE;\n\treturn buildToolResult(text, {\n\t\tanswers,\n\t\toutcome: answers.length ? \"answered\" : \"cancelled\",\n\t\tcancelled: answers.length === 0,\n\t});\n}\n\nexport function cancelResult(answers: QuestionAnswer[] = []): AgentToolResult<QuestionToolDetails> {\n\tconst answered = answers.length ? `\\n\\nPartial answers so far:\\n${answers.map(answerSegment).join(\"\\n\\n\")}` : \"\";\n\treturn buildToolResult(boundedText(`${DECLINE_MESSAGE}${answered}`), {\n\t\tanswers,\n\t\toutcome: \"cancelled\",\n\t\tcancelled: true,\n\t});\n}\n\nexport function clarificationResult(answers: QuestionAnswer[] = []): AgentToolResult<QuestionToolDetails> {\n\tconst answered = answers.length ? ` Partial answers so far:\\n${answers.map(answerSegment).join(\"\\n\\n\")}` : \"\";\n\treturn buildToolResult(\n\t\tboundedText(\n\t\t\t`${CLARIFICATION_MESSAGE}${answered}\\n\\nExplain the trade-offs or ask what the user would like clarified.`,\n\t\t),\n\t\t{\n\t\t\tanswers,\n\t\t\toutcome: \"needs_clarification\",\n\t\t\tcancelled: false,\n\t\t},\n\t);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"results.js","sourceRoot":"","sources":["../../../src/extensions/question/results.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGpE,MAAM,eAAe,GAAG,wCAAwC,CAAC;AACjE,MAAM,qBAAqB,GAAG,sEAAsE,CAAC;AACrG,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAC1C,MAAM,eAAe,GAAG,wCAAwC,CAAC;AAEjE,SAAS,eAAe,CAAC,IAAY,EAAE,OAA4B,EAAwC;IAC1G,OAAO;QACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACjC,OAAO;KACP,CAAC;AAAA,CACF;AAED,SAAS,WAAW,CAAC,IAAY,EAAU;IAC1C,IAAI,IAAI,CAAC,MAAM,IAAI,eAAe,CAAC,gBAAgB;QAAE,OAAO,IAAI,CAAC;IACjE,MAAM,MAAM,GAAG,mCAAmC,oBAAoB,GAAG,CAAC;IAC1E,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,CAAC,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC;AAAA,CAClG;AAED,MAAM,UAAU,WAAW,CAAC,KAAwB,EAAE,OAAe,EAAwC;IAC5G,OAAO,eAAe,CAAC,wBAAwB,KAAK,MAAM,OAAO,EAAE,EAAE;QACpE,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,KAAK;QAChB,KAAK;
|
|
1
|
+
{"version":3,"file":"results.js","sourceRoot":"","sources":["../../../src/extensions/question/results.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentToolResult } from \"../../core/extensions/types.ts\";\nimport { QUESTION_LIMITS, TRUNCATION_FOLLOW_UP } from \"./limits.ts\";\nimport type { QuestionAnswer, QuestionToolDetails, QuestionToolError } from \"./types.ts\";\n\nconst DECLINE_MESSAGE = \"User declined to answer the questions.\";\nconst CLARIFICATION_MESSAGE = \"The user wants to discuss these questions before choosing an answer.\";\nconst ENVELOPE_PREFIX = \"User decisions:\";\nconst ENVELOPE_SUFFIX = \"Continue with these decisions in mind.\";\n\nfunction buildToolResult(text: string, details: QuestionToolDetails): AgentToolResult<QuestionToolDetails> {\n\treturn {\n\t\tcontent: [{ type: \"text\", text }],\n\t\tdetails,\n\t};\n}\n\nfunction boundedText(text: string): string {\n\tif (text.length <= QUESTION_LIMITS.modelResultChars) return text;\n\tconst suffix = `\\n\\n[Question result truncated. ${TRUNCATION_FOLLOW_UP}]`;\n\treturn `${text.slice(0, Math.max(0, QUESTION_LIMITS.modelResultChars - suffix.length))}${suffix}`;\n}\n\nexport function errorResult(error: QuestionToolError, message: string): AgentToolResult<QuestionToolDetails> {\n\treturn buildToolResult(`Question tool error (${error}): ${message}`, {\n\t\tanswers: [],\n\t\toutcome: \"error\",\n\t\tcancelled: false,\n\t\terror,\n\t\tmessage,\n\t});\n}\n\nexport function answerScalar(answer: QuestionAnswer): string {\n\tif (answer.kind === \"multi\") return answer.selected?.length ? answer.selected.join(\", \") : \"(no input)\";\n\treturn answer.answer && answer.answer.length > 0 ? answer.answer : \"(no input)\";\n}\n\nfunction answerKindLabel(answer: QuestionAnswer): string {\n\tif (answer.kind === \"multi\") return \"Selections\";\n\treturn answer.kind === \"custom\" ? \"Custom answer\" : \"Selected option\";\n}\n\nfunction answerSegment(answer: QuestionAnswer): string {\n\tconst lines = [\n\t\t`${answer.questionIndex + 1}. [${answer.header}] ${answer.question}`,\n\t\t` ${answerKindLabel(answer)}: ${answerScalar(answer)}`,\n\t];\n\tif (answer.preview) lines.push(\" Preview: selected (kept in tool details)\");\n\tfor (const note of answer.notes ?? []) lines.push(` Note for ${note.option}: ${note.text}`);\n\treturn lines.join(\"\\n\");\n}\n\nexport function successResult(answers: QuestionAnswer[]): AgentToolResult<QuestionToolDetails> {\n\tconst text = answers.length\n\t\t? boundedText(`${ENVELOPE_PREFIX}\\n${answers.map(answerSegment).join(\"\\n\\n\")}\\n\\n${ENVELOPE_SUFFIX}`)\n\t\t: DECLINE_MESSAGE;\n\treturn buildToolResult(text, {\n\t\tanswers,\n\t\toutcome: answers.length ? \"answered\" : \"cancelled\",\n\t\tcancelled: answers.length === 0,\n\t});\n}\n\nexport function cancelResult(answers: QuestionAnswer[] = []): AgentToolResult<QuestionToolDetails> {\n\tconst answered = answers.length ? `\\n\\nPartial answers so far:\\n${answers.map(answerSegment).join(\"\\n\\n\")}` : \"\";\n\treturn buildToolResult(boundedText(`${DECLINE_MESSAGE}${answered}`), {\n\t\tanswers,\n\t\toutcome: \"cancelled\",\n\t\tcancelled: true,\n\t});\n}\n\nexport function clarificationResult(answers: QuestionAnswer[] = []): AgentToolResult<QuestionToolDetails> {\n\tconst answered = answers.length ? ` Partial answers so far:\\n${answers.map(answerSegment).join(\"\\n\\n\")}` : \"\";\n\treturn buildToolResult(\n\t\tboundedText(\n\t\t\t`${CLARIFICATION_MESSAGE}${answered}\\n\\nExplain the trade-offs or ask what the user would like clarified.`,\n\t\t),\n\t\t{\n\t\t\tanswers,\n\t\t\toutcome: \"needs_clarification\",\n\t\t\tcancelled: false,\n\t\t},\n\t);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/extensions/question/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,OAAO,KAAK,EAAE,QAAQ,EAAkB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAoD9E,eAAO,MAAM,cAAc;;;;;;;;;;;EAMzB,CAAC;AAEH;;;GAGG;AACH,wBAAgB,iBAAiB,CAChC,SAAS,EAAE,QAAQ,EAAE,GACnB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAwCzE","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.\", \"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\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
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/extensions/question/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,OAAO,KAAK,EAAE,QAAQ,EAAkB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAoD9E,eAAO,MAAM,cAAc;;;;;;;;;;;EAMzB,CAAC;AAEH;;;GAGG;AACH,wBAAgB,iBAAiB,CAChC,SAAS,EAAE,QAAQ,EAAE,GACnB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAwCzE","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\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\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\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\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\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 the schema cannot express. Length and count limits are omitted:\n * the agent core validates params against `QuestionParams` before execute runs.\n */\nexport function validateQuestions(\n\tquestions: Question[],\n): { ok: true } | { ok: false; error: QuestionToolError; message: string } {\n\tconst seenQuestions = new Set<string>();\n\tfor (const q of questions) {\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\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\n\t\tconst seenLabels = new Set<string>();\n\t\tfor (const option of q.options as QuestionOption[]) {\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\t}\n\n\treturn { ok: true };\n}\n"]}
|
|
@@ -3,13 +3,13 @@ import { QUESTION_LIMITS } from "./limits.js";
|
|
|
3
3
|
const MIN_OPTIONS = 2;
|
|
4
4
|
const MAX_OPTIONS = 4;
|
|
5
5
|
const MAX_QUESTIONS = 4;
|
|
6
|
-
const RESERVED_LABELS = ["Other", "Type something.", "Chat about this"];
|
|
6
|
+
const RESERVED_LABELS = ["Other", "Type something", "Type something.", "Chat about this"];
|
|
7
7
|
const normalizeLabel = (text) => text.trim().toLowerCase();
|
|
8
8
|
const RESERVED_NORMALIZED = new Set(RESERVED_LABELS.map(normalizeLabel));
|
|
9
9
|
const OptionSchema = Type.Object({
|
|
10
10
|
label: Type.String({
|
|
11
11
|
maxLength: QUESTION_LIMITS.optionLabelChars,
|
|
12
|
-
description: "Short user-facing option label (1-5 words), distinct within the question. Reserved labels ('Other', 'Type something
|
|
12
|
+
description: "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.",
|
|
13
13
|
}),
|
|
14
14
|
description: Type.String({
|
|
15
15
|
maxLength: QUESTION_LIMITS.optionDescriptionChars,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/extensions/question/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,CAAU,CAAC;
|
|
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\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\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\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\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\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 the schema cannot express. Length and count limits are omitted:\n * the agent core validates params against `QuestionParams` before execute runs.\n */\nexport function validateQuestions(\n\tquestions: Question[],\n): { ok: true } | { ok: false; error: QuestionToolError; message: string } {\n\tconst seenQuestions = new Set<string>();\n\tfor (const q of questions) {\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\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\n\t\tconst seenLabels = new Set<string>();\n\t\tfor (const option of q.options as QuestionOption[]) {\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\t}\n\n\treturn { ok: true };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/extensions/question/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAC1B,OAAO,GACP,oBAAoB,GACpB,wBAAwB,GACxB,gBAAgB,GAChB,qBAAqB,CAAC;AAEzB,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,WAAW,GAAG,qBAAqB,GAAG,OAAO,CAAC;AAEzF,MAAM,WAAW,mBAAmB;IACnC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/extensions/question/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAC1B,OAAO,GACP,oBAAoB,GACpB,wBAAwB,GACxB,gBAAgB,GAChB,qBAAqB,CAAC;AAEzB,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,WAAW,GAAG,qBAAqB,GAAG,OAAO,CAAC;AAEzF,MAAM,WAAW,mBAAmB;IACnC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,MAAM,aAAa,GACtB,CAAC,cAAc,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,GAC1D;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC;AAEnD,eAAO,MAAM,YAAY,EAAE,aAAyE,CAAC","sourcesContent":["export interface QuestionOption {\n\tlabel: string;\n\tdescription: string;\n\tpreview?: string;\n}\n\nexport interface Question {\n\tquestion: string;\n\theader: string;\n\toptions: QuestionOption[];\n\tmultiSelect?: boolean;\n}\n\nexport type InputMode = \"custom\" | \"notes\" | undefined;\n\nexport type QuestionToolError =\n\t| \"no_ui\"\n\t| \"duplicate_question\"\n\t| \"duplicate_option_label\"\n\t| \"reserved_label\"\n\t| \"preview_multiselect\";\n\nexport interface AnswerNote {\n\toption: string;\n\ttext: string;\n}\n\nexport interface QuestionAnswer {\n\tquestionIndex: number;\n\tquestion: string;\n\theader: string;\n\tkind: \"option\" | \"custom\" | \"multi\";\n\tanswer: string | null;\n\tselected?: string[];\n\tnotes?: AnswerNote[];\n\tpreview?: string;\n}\n\nexport type QuestionOutcome = \"answered\" | \"cancelled\" | \"needs_clarification\" | \"error\";\n\nexport interface QuestionToolDetails {\n\tanswers: QuestionAnswer[];\n\toutcome: QuestionOutcome;\n\tcancelled: boolean;\n\terror?: QuestionToolError;\n\tmessage?: string;\n}\n\nexport interface CustomAnswer {\n\ttext: string;\n\tselected: boolean;\n}\n\nexport interface QuestionState {\n\toptionIndex: number;\n\tsingleAnswer?: QuestionAnswer;\n\tmultiSelected: Set<number>;\n\tcustomAnswer?: CustomAnswer;\n\tnotesByOption: Map<string, string>;\n\twarning?: string;\n}\n\nexport interface DialogResult {\n\tanswers: QuestionAnswer[];\n\toutcome: QuestionOutcome;\n}\n\nexport type DisplayOption =\n\t| (QuestionOption & { kind: \"option\"; optionIndex: number })\n\t| { kind: \"other\"; label: string; isOther: true };\n\nexport const OTHER_OPTION: DisplayOption = { kind: \"other\", label: \"Type something\", isOther: true };\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const OTHER_OPTION = { kind: "other", label: "Type something
|
|
1
|
+
export const OTHER_OPTION = { kind: "other", label: "Type something", isOther: true };
|
|
2
2
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/extensions/question/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/extensions/question/types.ts"],"names":[],"mappings":"AAuEA,MAAM,CAAC,MAAM,YAAY,GAAkB,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC","sourcesContent":["export interface QuestionOption {\n\tlabel: string;\n\tdescription: string;\n\tpreview?: string;\n}\n\nexport interface Question {\n\tquestion: string;\n\theader: string;\n\toptions: QuestionOption[];\n\tmultiSelect?: boolean;\n}\n\nexport type InputMode = \"custom\" | \"notes\" | undefined;\n\nexport type QuestionToolError =\n\t| \"no_ui\"\n\t| \"duplicate_question\"\n\t| \"duplicate_option_label\"\n\t| \"reserved_label\"\n\t| \"preview_multiselect\";\n\nexport interface AnswerNote {\n\toption: string;\n\ttext: string;\n}\n\nexport interface QuestionAnswer {\n\tquestionIndex: number;\n\tquestion: string;\n\theader: string;\n\tkind: \"option\" | \"custom\" | \"multi\";\n\tanswer: string | null;\n\tselected?: string[];\n\tnotes?: AnswerNote[];\n\tpreview?: string;\n}\n\nexport type QuestionOutcome = \"answered\" | \"cancelled\" | \"needs_clarification\" | \"error\";\n\nexport interface QuestionToolDetails {\n\tanswers: QuestionAnswer[];\n\toutcome: QuestionOutcome;\n\tcancelled: boolean;\n\terror?: QuestionToolError;\n\tmessage?: string;\n}\n\nexport interface CustomAnswer {\n\ttext: string;\n\tselected: boolean;\n}\n\nexport interface QuestionState {\n\toptionIndex: number;\n\tsingleAnswer?: QuestionAnswer;\n\tmultiSelected: Set<number>;\n\tcustomAnswer?: CustomAnswer;\n\tnotesByOption: Map<string, string>;\n\twarning?: string;\n}\n\nexport interface DialogResult {\n\tanswers: QuestionAnswer[];\n\toutcome: QuestionOutcome;\n}\n\nexport type DisplayOption =\n\t| (QuestionOption & { kind: \"option\"; optionIndex: number })\n\t| { kind: \"other\"; label: string; isOther: true };\n\nexport const OTHER_OPTION: DisplayOption = { kind: \"other\", label: \"Type something\", isOther: true };\n"]}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { type Api, type Context, createAssistantMessageEventStream, type Model, type SimpleStreamOptions } from "@earendil-works/pi-ai/compat";
|
|
13
13
|
export declare function streamRouterCodex(model: Model<Api>, context: Context, options?: SimpleStreamOptions): ReturnType<typeof createAssistantMessageEventStream>;
|
|
14
|
+
export declare function sanitizeInputItemsForCodex(input: unknown): void;
|
|
14
15
|
export declare function resolveResponsesUrl(baseUrl: string): string;
|
|
15
16
|
export declare function isRouterApi(api: string): boolean;
|
|
16
17
|
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../src/extensions/router/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACN,KAAK,GAAG,EACR,KAAK,OAAO,EACZ,iCAAiC,EACjC,KAAK,KAAK,EAEV,KAAK,mBAAmB,EACxB,MAAM,8BAA8B,CAAC;AAMtC,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,UAAU,CAAC,OAAO,iCAAiC,CAAC,CA0EtD;AA2KD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD","sourcesContent":["/**\n * Codex-oriented Responses client for API relays.\n *\n * Follows Pi's documented custom-provider pattern (see coding-agent docs\n * providers.md / custom-provider.md and examples/custom-provider-gitlab-duo):\n * wrap a built-in pi-ai stream API from `@earendil-works/pi-ai/compat` instead of\n * reimplementing SSE or deep-importing internal modules.\n *\n * We use openAIResponsesApi (works with relay sk- keys) and reshape the request\n * payload toward Codex CLI style so transparent gateways receive a friendlier body.\n */\n\nimport {\n\ttype Api,\n\ttype Context,\n\tcreateAssistantMessageEventStream,\n\ttype Model,\n\topenAIResponsesApi,\n\ttype SimpleStreamOptions,\n} from \"@earendil-works/pi-ai/compat\";\n\nimport { DEFAULTS, formatError, ROUTER_API } from \"./constants.ts\";\n\nconst responsesApi = openAIResponsesApi();\n\nexport function streamRouterCodex(\n\tmodel: Model<Api>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): ReturnType<typeof createAssistantMessageEventStream> {\n\tconst stream = createAssistantMessageEventStream();\n\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey;\n\t\t\tif (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);\n\n\t\t\t// Built-in Responses stream expects api \"openai-responses\" on the model object.\n\t\t\tconst requestModel = {\n\t\t\t\t...model,\n\t\t\t\tapi: \"openai-responses\" as const,\n\t\t\t\tcompat: {\n\t\t\t\t\tsupportsDeveloperRole: true,\n\t\t\t\t\t// Avoid underscore session_id header that strict proxies reject.\n\t\t\t\t\tsessionAffinityFormat: \"openai-nosession\" as const,\n\t\t\t\t\t// Codex-style upstreams reject prompt_cache_retention: \"24h\".\n\t\t\t\t\tsupportsLongCacheRetention: false,\n\t\t\t\t\t...(model.compat ?? {}),\n\t\t\t\t},\n\t\t\t} as Model<\"openai-responses\">;\n\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\toriginator: DEFAULTS.originator,\n\t\t\t\t...(options?.headers as Record<string, string> | undefined),\n\t\t\t};\n\n\t\t\t// Prefer hyphenated Codex-style session affinity when we have a session id.\n\t\t\tconst sessionId = clampCacheKey(options?.sessionId);\n\t\t\tif (sessionId) {\n\t\t\t\tif (!headers[\"session-id\"]) headers[\"session-id\"] = sessionId;\n\t\t\t\tif (!headers[\"x-client-request-id\"]) headers[\"x-client-request-id\"] = sessionId;\n\t\t\t}\n\n\t\t\tconst inner = responsesApi.streamSimple(requestModel, context, {\n\t\t\t\t...options,\n\t\t\t\tapiKey,\n\t\t\t\theaders,\n\t\t\t\tonPayload: (payload) => reshapePayloadForRelay(payload, context, options?.onPayload, requestModel),\n\t\t\t});\n\n\t\t\tfor await (const event of inner) {\n\t\t\t\tstream.push(event);\n\t\t\t}\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\t// Match examples/custom-provider-gitlab-duo error event shape.\n\t\t\tstream.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\treason: options?.signal?.aborted ? \"aborted\" : \"error\",\n\t\t\t\terror: {\n\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\tcontent: [],\n\t\t\t\t\tapi: model.api,\n\t\t\t\t\tprovider: model.provider,\n\t\t\t\t\tmodel: model.id,\n\t\t\t\t\tusage: {\n\t\t\t\t\t\tinput: 0,\n\t\t\t\t\t\toutput: 0,\n\t\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t},\n\t\t\t\t\tstopReason: options?.signal?.aborted ? \"aborted\" : \"error\",\n\t\t\t\t\terrorMessage: formatError(error),\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t});\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n}\n\n/**\n * Nudge the OpenAI Responses payload toward Codex CLI request shape for\n * transparent relays: instructions + input, store:false, no max_output_tokens /\n * prompt_cache_retention, verbosity + parallel_tool_calls.\n */\nasync function reshapePayloadForRelay(\n\tpayload: unknown,\n\tcontext: Context,\n\tuserOnPayload: SimpleStreamOptions[\"onPayload\"],\n\tmodel: Model<\"openai-responses\">,\n): Promise<unknown> {\n\tconst base =\n\t\tpayload && typeof payload === \"object\" && !Array.isArray(payload)\n\t\t\t? { ...(payload as Record<string, unknown>) }\n\t\t\t: ({} as Record<string, unknown>);\n\n\t// Always safe for ChatGPT/Codex-style backends.\n\tbase.store = false;\n\tbase.stream = true;\n\n\t// Codex CLI sends system prompt as `instructions`, not as a role message in input.\n\tconst { instructions, input } = extractInstructions(base.input, context.systemPrompt);\n\tif (instructions) base.instructions = instructions;\n\tif (input !== undefined) base.input = input;\n\n\t// Codex CLI's ResponseItem serialization never emits `status` on replayed\n\t// message/function_call/function_call_output/reasoning items (only\n\t// local_shell_call has it), and output_text content has no `annotations`.\n\t// Strict Codex-schema gateways 400 on both (e.g. \"input[i].status:\n\t// unknown_parameter\"), while pi-ai emits them per the Platform schema.\n\tsanitizeInputItemsForCodex(base.input);\n\n\t// Fields common on Codex CLI / rejected by many transparent Codex upstreams.\n\tif (!base.text || typeof base.text !== \"object\") {\n\t\tbase.text = { verbosity: \"low\" };\n\t}\n\tif (base.tool_choice === undefined) base.tool_choice = \"auto\";\n\tif (base.parallel_tool_calls === undefined) base.parallel_tool_calls = true;\n\n\t// Prefer encrypted reasoning content for multi-turn store:false sessions.\n\tconst include = Array.isArray(base.include) ? [...(base.include as unknown[])] : [];\n\tif (!include.includes(\"reasoning.encrypted_content\")) {\n\t\tinclude.push(\"reasoning.encrypted_content\");\n\t}\n\tbase.include = include;\n\n\t// Drop Platform-only fields that Codex OAuth endpoints often 400 on.\n\tdelete base.prompt_cache_retention;\n\tdelete base.prompt_cache_options;\n\tdelete base.max_output_tokens;\n\tdelete base.temperature;\n\tdelete base.top_p;\n\tdelete base.user;\n\tdelete base.metadata;\n\tdelete base.service_tier;\n\tdelete base.truncation;\n\tdelete base.context_management;\n\tdelete base.safety_identifier;\n\tdelete base.stream_options;\n\n\tif (userOnPayload) {\n\t\tconst next = await userOnPayload(base, model);\n\t\tif (next !== undefined) return next;\n\t}\n\treturn base;\n}\n\n/**\n * Item types where Codex CLI's ResponseItem serialization has NO `status`\n * field (codex-rs/protocol/src/models.rs): Message, Reasoning, FunctionCall,\n * FunctionCallOutput, CustomToolCallOutput. Other item types either require\n * `status` (local_shell_call, tool_search_output, image_generation_call) or\n * accept it optionally (tool_search_call, custom_tool_call, web_search_call),\n * so we must not strip it there.\n */\nconst STATUS_LESS_ITEM_TYPES = new Set([\n\t\"message\",\n\t\"reasoning\",\n\t\"function_call\",\n\t\"function_call_output\",\n\t\"custom_tool_call_output\",\n]);\n\nfunction sanitizeInputItemsForCodex(input: unknown): void {\n\tif (!Array.isArray(input)) return;\n\tfor (const item of input) {\n\t\tif (!item || typeof item !== \"object\" || Array.isArray(item)) continue;\n\t\tconst record = item as Record<string, unknown>;\n\t\tif (typeof record.type === \"string\" && STATUS_LESS_ITEM_TYPES.has(record.type) && \"status\" in record) {\n\t\t\tdelete record.status;\n\t\t}\n\t\tif (Array.isArray(record.content)) {\n\t\t\tfor (const part of record.content) {\n\t\t\t\tif (\n\t\t\t\t\tpart &&\n\t\t\t\t\ttypeof part === \"object\" &&\n\t\t\t\t\t(part as { type?: string }).type === \"output_text\" &&\n\t\t\t\t\t\"annotations\" in part\n\t\t\t\t) {\n\t\t\t\t\tdelete (part as Record<string, unknown>).annotations;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction extractInstructions(\n\tinput: unknown,\n\tsystemPrompt: string | undefined,\n): { instructions?: string; input: unknown } {\n\t// Prefer context.systemPrompt (matches Codex stream path).\n\tif (systemPrompt && systemPrompt.length > 0) {\n\t\tconst stripped = stripLeadingSystemRoles(input);\n\t\treturn { instructions: systemPrompt, input: stripped ?? input };\n\t}\n\n\tif (!Array.isArray(input) || input.length === 0) {\n\t\treturn { input };\n\t}\n\n\tconst first = input[0];\n\tif (\n\t\tfirst &&\n\t\ttypeof first === \"object\" &&\n\t\t!Array.isArray(first) &&\n\t\t\"role\" in first &&\n\t\t((first as { role?: string }).role === \"system\" || (first as { role?: string }).role === \"developer\")\n\t) {\n\t\tconst content = (first as { content?: unknown }).content;\n\t\tconst text =\n\t\t\ttypeof content === \"string\"\n\t\t\t\t? content\n\t\t\t\t: Array.isArray(content)\n\t\t\t\t\t? content\n\t\t\t\t\t\t\t.map((part) =>\n\t\t\t\t\t\t\t\tpart && typeof part === \"object\" && \"text\" in part\n\t\t\t\t\t\t\t\t\t? String((part as { text: unknown }).text)\n\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join(\"\")\n\t\t\t\t\t: \"\";\n\t\treturn {\n\t\t\tinstructions: text || undefined,\n\t\t\tinput: input.slice(1),\n\t\t};\n\t}\n\n\treturn { input };\n}\n\nfunction stripLeadingSystemRoles(input: unknown): unknown {\n\tif (!Array.isArray(input) || input.length === 0) return input;\n\tconst first = input[0];\n\tif (\n\t\tfirst &&\n\t\ttypeof first === \"object\" &&\n\t\t!Array.isArray(first) &&\n\t\t((first as { role?: string }).role === \"system\" || (first as { role?: string }).role === \"developer\")\n\t) {\n\t\treturn input.slice(1);\n\t}\n\treturn input;\n}\n\nfunction clampCacheKey(sessionId: string | undefined): string | undefined {\n\tif (!sessionId) return undefined;\n\treturn sessionId.length <= 64 ? sessionId : sessionId.slice(0, 64);\n}\n\nexport function resolveResponsesUrl(baseUrl: string): string {\n\tconst normalized = baseUrl.trim().replace(/\\/+$/, \"\");\n\tif (!normalized) throw new Error(\"Model baseUrl is empty.\");\n\tif (normalized.endsWith(\"/responses\")) return normalized;\n\treturn `${normalized}/responses`;\n}\n\nexport function isRouterApi(api: string): boolean {\n\treturn api === ROUTER_API;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../src/extensions/router/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACN,KAAK,GAAG,EACR,KAAK,OAAO,EACZ,iCAAiC,EACjC,KAAK,KAAK,EAEV,KAAK,mBAAmB,EACxB,MAAM,8BAA8B,CAAC;AAMtC,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,UAAU,CAAC,OAAO,iCAAiC,CAAC,CA0EtD;AAiHD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAyB/D;AAiED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD","sourcesContent":["/**\n * Codex-oriented Responses client for API relays.\n *\n * Follows Pi's documented custom-provider pattern (see coding-agent docs\n * providers.md / custom-provider.md and examples/custom-provider-gitlab-duo):\n * wrap a built-in pi-ai stream API from `@earendil-works/pi-ai/compat` instead of\n * reimplementing SSE or deep-importing internal modules.\n *\n * We use openAIResponsesApi (works with relay sk- keys) and reshape the request\n * payload toward Codex CLI style so transparent gateways receive a friendlier body.\n */\n\nimport {\n\ttype Api,\n\ttype Context,\n\tcreateAssistantMessageEventStream,\n\ttype Model,\n\topenAIResponsesApi,\n\ttype SimpleStreamOptions,\n} from \"@earendil-works/pi-ai/compat\";\n\nimport { DEFAULTS, formatError, ROUTER_API } from \"./constants.ts\";\n\nconst responsesApi = openAIResponsesApi();\n\nexport function streamRouterCodex(\n\tmodel: Model<Api>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): ReturnType<typeof createAssistantMessageEventStream> {\n\tconst stream = createAssistantMessageEventStream();\n\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey;\n\t\t\tif (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);\n\n\t\t\t// Built-in Responses stream expects api \"openai-responses\" on the model object.\n\t\t\tconst requestModel = {\n\t\t\t\t...model,\n\t\t\t\tapi: \"openai-responses\" as const,\n\t\t\t\tcompat: {\n\t\t\t\t\tsupportsDeveloperRole: true,\n\t\t\t\t\t// Avoid underscore session_id header that strict proxies reject.\n\t\t\t\t\tsessionAffinityFormat: \"openai-nosession\" as const,\n\t\t\t\t\t// Codex-style upstreams reject prompt_cache_retention: \"24h\".\n\t\t\t\t\tsupportsLongCacheRetention: false,\n\t\t\t\t\t...(model.compat ?? {}),\n\t\t\t\t},\n\t\t\t} as Model<\"openai-responses\">;\n\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\toriginator: DEFAULTS.originator,\n\t\t\t\t...(options?.headers as Record<string, string> | undefined),\n\t\t\t};\n\n\t\t\t// Prefer hyphenated Codex-style session affinity when we have a session id.\n\t\t\tconst sessionId = clampCacheKey(options?.sessionId);\n\t\t\tif (sessionId) {\n\t\t\t\tif (!headers[\"session-id\"]) headers[\"session-id\"] = sessionId;\n\t\t\t\tif (!headers[\"x-client-request-id\"]) headers[\"x-client-request-id\"] = sessionId;\n\t\t\t}\n\n\t\t\tconst inner = responsesApi.streamSimple(requestModel, context, {\n\t\t\t\t...options,\n\t\t\t\tapiKey,\n\t\t\t\theaders,\n\t\t\t\tonPayload: (payload) => reshapePayloadForRelay(payload, context, options?.onPayload, requestModel),\n\t\t\t});\n\n\t\t\tfor await (const event of inner) {\n\t\t\t\tstream.push(event);\n\t\t\t}\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\t// Match examples/custom-provider-gitlab-duo error event shape.\n\t\t\tstream.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\treason: options?.signal?.aborted ? \"aborted\" : \"error\",\n\t\t\t\terror: {\n\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\tcontent: [],\n\t\t\t\t\tapi: model.api,\n\t\t\t\t\tprovider: model.provider,\n\t\t\t\t\tmodel: model.id,\n\t\t\t\t\tusage: {\n\t\t\t\t\t\tinput: 0,\n\t\t\t\t\t\toutput: 0,\n\t\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t},\n\t\t\t\t\tstopReason: options?.signal?.aborted ? \"aborted\" : \"error\",\n\t\t\t\t\terrorMessage: formatError(error),\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t});\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n}\n\n/**\n * Nudge the OpenAI Responses payload toward Codex CLI request shape for\n * transparent relays: instructions + input, store:false, no max_output_tokens /\n * prompt_cache_retention, verbosity + parallel_tool_calls.\n */\nasync function reshapePayloadForRelay(\n\tpayload: unknown,\n\tcontext: Context,\n\tuserOnPayload: SimpleStreamOptions[\"onPayload\"],\n\tmodel: Model<\"openai-responses\">,\n): Promise<unknown> {\n\tconst base =\n\t\tpayload && typeof payload === \"object\" && !Array.isArray(payload)\n\t\t\t? { ...(payload as Record<string, unknown>) }\n\t\t\t: ({} as Record<string, unknown>);\n\n\t// Always safe for ChatGPT/Codex-style backends.\n\tbase.store = false;\n\tbase.stream = true;\n\n\t// Codex CLI sends system prompt as `instructions`, not as a role message in input.\n\tconst { instructions, input } = extractInstructions(base.input, context.systemPrompt);\n\tif (instructions) base.instructions = instructions;\n\tif (input !== undefined) base.input = input;\n\n\t// Released Codex CLI defaults omit replayed ResponseItem ids from store:false\n\t// requests. It also never emits `status` on the item types below, and its\n\t// output_text content has no `annotations`.\n\tsanitizeInputItemsForCodex(base.input);\n\n\t// Fields common on Codex CLI / rejected by many transparent Codex upstreams.\n\tif (!base.text || typeof base.text !== \"object\") {\n\t\tbase.text = { verbosity: \"low\" };\n\t}\n\tif (base.tool_choice === undefined) base.tool_choice = \"auto\";\n\tif (base.parallel_tool_calls === undefined) base.parallel_tool_calls = true;\n\n\t// Prefer encrypted reasoning content for multi-turn store:false sessions.\n\tconst include = Array.isArray(base.include) ? [...(base.include as unknown[])] : [];\n\tif (!include.includes(\"reasoning.encrypted_content\")) {\n\t\tinclude.push(\"reasoning.encrypted_content\");\n\t}\n\tbase.include = include;\n\n\t// Drop Platform-only fields that Codex OAuth endpoints often 400 on.\n\tdelete base.prompt_cache_retention;\n\tdelete base.prompt_cache_options;\n\tdelete base.max_output_tokens;\n\tdelete base.temperature;\n\tdelete base.top_p;\n\tdelete base.user;\n\tdelete base.metadata;\n\tdelete base.service_tier;\n\tdelete base.truncation;\n\tdelete base.context_management;\n\tdelete base.safety_identifier;\n\tdelete base.stream_options;\n\n\tif (userOnPayload) {\n\t\tconst next = await userOnPayload(base, model);\n\t\tif (next !== undefined) return next;\n\t}\n\treturn base;\n}\n\n/**\n * Match the released Codex CLI's default stateless request preparation:\n * optional ResponseItem identity ids are omitted from store:false requests,\n * while semantic ids, call_id, and encrypted_content remain available for\n * reference, tool, and reasoning continuity.\n *\n * These are the tagged variants handled by ResponseItem::set_id in Codex CLI\n * 0.145. Unknown input variants must retain `id`: for example,\n * item_reference.id and local_shell_call_output.id are required references,\n * not optional ResponseItem identities.\n */\nconst RESPONSE_ITEM_ID_TYPES = new Set([\n\t\"additional_tools\",\n\t\"message\",\n\t\"agent_message\",\n\t\"reasoning\",\n\t\"local_shell_call\",\n\t\"function_call\",\n\t\"tool_search_call\",\n\t\"function_call_output\",\n\t\"custom_tool_call\",\n\t\"custom_tool_call_output\",\n\t\"tool_search_output\",\n\t\"web_search_call\",\n\t\"image_generation_call\",\n\t\"compaction\",\n\t\"compaction_summary\",\n\t\"context_compaction\",\n]);\n\n/**\n * Codex ResponseItem serialization has NO `status` field on Message,\n * Reasoning, FunctionCall, FunctionCallOutput, or CustomToolCallOutput\n * (codex-rs/protocol/src/models.rs). Other item types either require `status`\n * (local_shell_call, tool_search_output, image_generation_call) or accept it\n * optionally (tool_search_call, custom_tool_call, web_search_call), so we must\n * not strip it there.\n */\nconst STATUS_LESS_ITEM_TYPES = new Set([\n\t\"message\",\n\t\"reasoning\",\n\t\"function_call\",\n\t\"function_call_output\",\n\t\"custom_tool_call_output\",\n]);\n\nexport function sanitizeInputItemsForCodex(input: unknown): void {\n\tif (!Array.isArray(input)) return;\n\tfor (const item of input) {\n\t\tif (!item || typeof item !== \"object\" || Array.isArray(item)) continue;\n\t\tconst record = item as Record<string, unknown>;\n\t\tconst type = typeof record.type === \"string\" ? record.type : undefined;\n\t\tif (type && RESPONSE_ITEM_ID_TYPES.has(type)) {\n\t\t\tdelete record.id;\n\t\t}\n\t\tif (type && STATUS_LESS_ITEM_TYPES.has(type) && \"status\" in record) {\n\t\t\tdelete record.status;\n\t\t}\n\t\tif (Array.isArray(record.content)) {\n\t\t\tfor (const part of record.content) {\n\t\t\t\tif (\n\t\t\t\t\tpart &&\n\t\t\t\t\ttypeof part === \"object\" &&\n\t\t\t\t\t(part as { type?: string }).type === \"output_text\" &&\n\t\t\t\t\t\"annotations\" in part\n\t\t\t\t) {\n\t\t\t\t\tdelete (part as Record<string, unknown>).annotations;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction extractInstructions(\n\tinput: unknown,\n\tsystemPrompt: string | undefined,\n): { instructions?: string; input: unknown } {\n\t// Prefer context.systemPrompt (matches Codex stream path).\n\tif (systemPrompt && systemPrompt.length > 0) {\n\t\tconst stripped = stripLeadingSystemRoles(input);\n\t\treturn { instructions: systemPrompt, input: stripped ?? input };\n\t}\n\n\tif (!Array.isArray(input) || input.length === 0) {\n\t\treturn { input };\n\t}\n\n\tconst first = input[0];\n\tif (\n\t\tfirst &&\n\t\ttypeof first === \"object\" &&\n\t\t!Array.isArray(first) &&\n\t\t\"role\" in first &&\n\t\t((first as { role?: string }).role === \"system\" || (first as { role?: string }).role === \"developer\")\n\t) {\n\t\tconst content = (first as { content?: unknown }).content;\n\t\tconst text =\n\t\t\ttypeof content === \"string\"\n\t\t\t\t? content\n\t\t\t\t: Array.isArray(content)\n\t\t\t\t\t? content\n\t\t\t\t\t\t\t.map((part) =>\n\t\t\t\t\t\t\t\tpart && typeof part === \"object\" && \"text\" in part\n\t\t\t\t\t\t\t\t\t? String((part as { text: unknown }).text)\n\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join(\"\")\n\t\t\t\t\t: \"\";\n\t\treturn {\n\t\t\tinstructions: text || undefined,\n\t\t\tinput: input.slice(1),\n\t\t};\n\t}\n\n\treturn { input };\n}\n\nfunction stripLeadingSystemRoles(input: unknown): unknown {\n\tif (!Array.isArray(input) || input.length === 0) return input;\n\tconst first = input[0];\n\tif (\n\t\tfirst &&\n\t\ttypeof first === \"object\" &&\n\t\t!Array.isArray(first) &&\n\t\t((first as { role?: string }).role === \"system\" || (first as { role?: string }).role === \"developer\")\n\t) {\n\t\treturn input.slice(1);\n\t}\n\treturn input;\n}\n\nfunction clampCacheKey(sessionId: string | undefined): string | undefined {\n\tif (!sessionId) return undefined;\n\treturn sessionId.length <= 64 ? sessionId : sessionId.slice(0, 64);\n}\n\nexport function resolveResponsesUrl(baseUrl: string): string {\n\tconst normalized = baseUrl.trim().replace(/\\/+$/, \"\");\n\tif (!normalized) throw new Error(\"Model baseUrl is empty.\");\n\tif (normalized.endsWith(\"/responses\")) return normalized;\n\treturn `${normalized}/responses`;\n}\n\nexport function isRouterApi(api: string): boolean {\n\treturn api === ROUTER_API;\n}\n"]}
|
|
@@ -102,11 +102,9 @@ async function reshapePayloadForRelay(payload, context, userOnPayload, model) {
|
|
|
102
102
|
base.instructions = instructions;
|
|
103
103
|
if (input !== undefined)
|
|
104
104
|
base.input = input;
|
|
105
|
-
// Codex CLI
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
// Strict Codex-schema gateways 400 on both (e.g. "input[i].status:
|
|
109
|
-
// unknown_parameter"), while pi-ai emits them per the Platform schema.
|
|
105
|
+
// Released Codex CLI defaults omit replayed ResponseItem ids from store:false
|
|
106
|
+
// requests. It also never emits `status` on the item types below, and its
|
|
107
|
+
// output_text content has no `annotations`.
|
|
110
108
|
sanitizeInputItemsForCodex(base.input);
|
|
111
109
|
// Fields common on Codex CLI / rejected by many transparent Codex upstreams.
|
|
112
110
|
if (!base.text || typeof base.text !== "object") {
|
|
@@ -143,12 +141,41 @@ async function reshapePayloadForRelay(payload, context, userOnPayload, model) {
|
|
|
143
141
|
return base;
|
|
144
142
|
}
|
|
145
143
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
144
|
+
* Match the released Codex CLI's default stateless request preparation:
|
|
145
|
+
* optional ResponseItem identity ids are omitted from store:false requests,
|
|
146
|
+
* while semantic ids, call_id, and encrypted_content remain available for
|
|
147
|
+
* reference, tool, and reasoning continuity.
|
|
148
|
+
*
|
|
149
|
+
* These are the tagged variants handled by ResponseItem::set_id in Codex CLI
|
|
150
|
+
* 0.145. Unknown input variants must retain `id`: for example,
|
|
151
|
+
* item_reference.id and local_shell_call_output.id are required references,
|
|
152
|
+
* not optional ResponseItem identities.
|
|
153
|
+
*/
|
|
154
|
+
const RESPONSE_ITEM_ID_TYPES = new Set([
|
|
155
|
+
"additional_tools",
|
|
156
|
+
"message",
|
|
157
|
+
"agent_message",
|
|
158
|
+
"reasoning",
|
|
159
|
+
"local_shell_call",
|
|
160
|
+
"function_call",
|
|
161
|
+
"tool_search_call",
|
|
162
|
+
"function_call_output",
|
|
163
|
+
"custom_tool_call",
|
|
164
|
+
"custom_tool_call_output",
|
|
165
|
+
"tool_search_output",
|
|
166
|
+
"web_search_call",
|
|
167
|
+
"image_generation_call",
|
|
168
|
+
"compaction",
|
|
169
|
+
"compaction_summary",
|
|
170
|
+
"context_compaction",
|
|
171
|
+
]);
|
|
172
|
+
/**
|
|
173
|
+
* Codex ResponseItem serialization has NO `status` field on Message,
|
|
174
|
+
* Reasoning, FunctionCall, FunctionCallOutput, or CustomToolCallOutput
|
|
175
|
+
* (codex-rs/protocol/src/models.rs). Other item types either require `status`
|
|
176
|
+
* (local_shell_call, tool_search_output, image_generation_call) or accept it
|
|
177
|
+
* optionally (tool_search_call, custom_tool_call, web_search_call), so we must
|
|
178
|
+
* not strip it there.
|
|
152
179
|
*/
|
|
153
180
|
const STATUS_LESS_ITEM_TYPES = new Set([
|
|
154
181
|
"message",
|
|
@@ -157,14 +184,18 @@ const STATUS_LESS_ITEM_TYPES = new Set([
|
|
|
157
184
|
"function_call_output",
|
|
158
185
|
"custom_tool_call_output",
|
|
159
186
|
]);
|
|
160
|
-
function sanitizeInputItemsForCodex(input) {
|
|
187
|
+
export function sanitizeInputItemsForCodex(input) {
|
|
161
188
|
if (!Array.isArray(input))
|
|
162
189
|
return;
|
|
163
190
|
for (const item of input) {
|
|
164
191
|
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
165
192
|
continue;
|
|
166
193
|
const record = item;
|
|
167
|
-
|
|
194
|
+
const type = typeof record.type === "string" ? record.type : undefined;
|
|
195
|
+
if (type && RESPONSE_ITEM_ID_TYPES.has(type)) {
|
|
196
|
+
delete record.id;
|
|
197
|
+
}
|
|
198
|
+
if (type && STATUS_LESS_ITEM_TYPES.has(type) && "status" in record) {
|
|
168
199
|
delete record.status;
|
|
169
200
|
}
|
|
170
201
|
if (Array.isArray(record.content)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../../src/extensions/router/stream.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Codex-oriented Responses client for API relays.\n *\n * Follows Pi's documented custom-provider pattern (see coding-agent docs\n * providers.md / custom-provider.md and examples/custom-provider-gitlab-duo):\n * wrap a built-in pi-ai stream API from `@earendil-works/pi-ai/compat` instead of\n * reimplementing SSE or deep-importing internal modules.\n *\n * We use openAIResponsesApi (works with relay sk- keys) and reshape the request\n * payload toward Codex CLI style so transparent gateways receive a friendlier body.\n */\n\nimport {\n\ttype Api,\n\ttype Context,\n\tcreateAssistantMessageEventStream,\n\ttype Model,\n\topenAIResponsesApi,\n\ttype SimpleStreamOptions,\n} from \"@earendil-works/pi-ai/compat\";\n\nimport { DEFAULTS, formatError, ROUTER_API } from \"./constants.ts\";\n\nconst responsesApi = openAIResponsesApi();\n\nexport function streamRouterCodex(\n\tmodel: Model<Api>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): ReturnType<typeof createAssistantMessageEventStream> {\n\tconst stream = createAssistantMessageEventStream();\n\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey;\n\t\t\tif (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);\n\n\t\t\t// Built-in Responses stream expects api \"openai-responses\" on the model object.\n\t\t\tconst requestModel = {\n\t\t\t\t...model,\n\t\t\t\tapi: \"openai-responses\" as const,\n\t\t\t\tcompat: {\n\t\t\t\t\tsupportsDeveloperRole: true,\n\t\t\t\t\t// Avoid underscore session_id header that strict proxies reject.\n\t\t\t\t\tsessionAffinityFormat: \"openai-nosession\" as const,\n\t\t\t\t\t// Codex-style upstreams reject prompt_cache_retention: \"24h\".\n\t\t\t\t\tsupportsLongCacheRetention: false,\n\t\t\t\t\t...(model.compat ?? {}),\n\t\t\t\t},\n\t\t\t} as Model<\"openai-responses\">;\n\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\toriginator: DEFAULTS.originator,\n\t\t\t\t...(options?.headers as Record<string, string> | undefined),\n\t\t\t};\n\n\t\t\t// Prefer hyphenated Codex-style session affinity when we have a session id.\n\t\t\tconst sessionId = clampCacheKey(options?.sessionId);\n\t\t\tif (sessionId) {\n\t\t\t\tif (!headers[\"session-id\"]) headers[\"session-id\"] = sessionId;\n\t\t\t\tif (!headers[\"x-client-request-id\"]) headers[\"x-client-request-id\"] = sessionId;\n\t\t\t}\n\n\t\t\tconst inner = responsesApi.streamSimple(requestModel, context, {\n\t\t\t\t...options,\n\t\t\t\tapiKey,\n\t\t\t\theaders,\n\t\t\t\tonPayload: (payload) => reshapePayloadForRelay(payload, context, options?.onPayload, requestModel),\n\t\t\t});\n\n\t\t\tfor await (const event of inner) {\n\t\t\t\tstream.push(event);\n\t\t\t}\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\t// Match examples/custom-provider-gitlab-duo error event shape.\n\t\t\tstream.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\treason: options?.signal?.aborted ? \"aborted\" : \"error\",\n\t\t\t\terror: {\n\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\tcontent: [],\n\t\t\t\t\tapi: model.api,\n\t\t\t\t\tprovider: model.provider,\n\t\t\t\t\tmodel: model.id,\n\t\t\t\t\tusage: {\n\t\t\t\t\t\tinput: 0,\n\t\t\t\t\t\toutput: 0,\n\t\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t},\n\t\t\t\t\tstopReason: options?.signal?.aborted ? \"aborted\" : \"error\",\n\t\t\t\t\terrorMessage: formatError(error),\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t});\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n}\n\n/**\n * Nudge the OpenAI Responses payload toward Codex CLI request shape for\n * transparent relays: instructions + input, store:false, no max_output_tokens /\n * prompt_cache_retention, verbosity + parallel_tool_calls.\n */\nasync function reshapePayloadForRelay(\n\tpayload: unknown,\n\tcontext: Context,\n\tuserOnPayload: SimpleStreamOptions[\"onPayload\"],\n\tmodel: Model<\"openai-responses\">,\n): Promise<unknown> {\n\tconst base =\n\t\tpayload && typeof payload === \"object\" && !Array.isArray(payload)\n\t\t\t? { ...(payload as Record<string, unknown>) }\n\t\t\t: ({} as Record<string, unknown>);\n\n\t// Always safe for ChatGPT/Codex-style backends.\n\tbase.store = false;\n\tbase.stream = true;\n\n\t// Codex CLI sends system prompt as `instructions`, not as a role message in input.\n\tconst { instructions, input } = extractInstructions(base.input, context.systemPrompt);\n\tif (instructions) base.instructions = instructions;\n\tif (input !== undefined) base.input = input;\n\n\t// Codex CLI's ResponseItem serialization never emits `status` on replayed\n\t// message/function_call/function_call_output/reasoning items (only\n\t// local_shell_call has it), and output_text content has no `annotations`.\n\t// Strict Codex-schema gateways 400 on both (e.g. \"input[i].status:\n\t// unknown_parameter\"), while pi-ai emits them per the Platform schema.\n\tsanitizeInputItemsForCodex(base.input);\n\n\t// Fields common on Codex CLI / rejected by many transparent Codex upstreams.\n\tif (!base.text || typeof base.text !== \"object\") {\n\t\tbase.text = { verbosity: \"low\" };\n\t}\n\tif (base.tool_choice === undefined) base.tool_choice = \"auto\";\n\tif (base.parallel_tool_calls === undefined) base.parallel_tool_calls = true;\n\n\t// Prefer encrypted reasoning content for multi-turn store:false sessions.\n\tconst include = Array.isArray(base.include) ? [...(base.include as unknown[])] : [];\n\tif (!include.includes(\"reasoning.encrypted_content\")) {\n\t\tinclude.push(\"reasoning.encrypted_content\");\n\t}\n\tbase.include = include;\n\n\t// Drop Platform-only fields that Codex OAuth endpoints often 400 on.\n\tdelete base.prompt_cache_retention;\n\tdelete base.prompt_cache_options;\n\tdelete base.max_output_tokens;\n\tdelete base.temperature;\n\tdelete base.top_p;\n\tdelete base.user;\n\tdelete base.metadata;\n\tdelete base.service_tier;\n\tdelete base.truncation;\n\tdelete base.context_management;\n\tdelete base.safety_identifier;\n\tdelete base.stream_options;\n\n\tif (userOnPayload) {\n\t\tconst next = await userOnPayload(base, model);\n\t\tif (next !== undefined) return next;\n\t}\n\treturn base;\n}\n\n/**\n * Item types where Codex CLI's ResponseItem serialization has NO `status`\n * field (codex-rs/protocol/src/models.rs): Message, Reasoning, FunctionCall,\n * FunctionCallOutput, CustomToolCallOutput. Other item types either require\n * `status` (local_shell_call, tool_search_output, image_generation_call) or\n * accept it optionally (tool_search_call, custom_tool_call, web_search_call),\n * so we must not strip it there.\n */\nconst STATUS_LESS_ITEM_TYPES = new Set([\n\t\"message\",\n\t\"reasoning\",\n\t\"function_call\",\n\t\"function_call_output\",\n\t\"custom_tool_call_output\",\n]);\n\nfunction sanitizeInputItemsForCodex(input: unknown): void {\n\tif (!Array.isArray(input)) return;\n\tfor (const item of input) {\n\t\tif (!item || typeof item !== \"object\" || Array.isArray(item)) continue;\n\t\tconst record = item as Record<string, unknown>;\n\t\tif (typeof record.type === \"string\" && STATUS_LESS_ITEM_TYPES.has(record.type) && \"status\" in record) {\n\t\t\tdelete record.status;\n\t\t}\n\t\tif (Array.isArray(record.content)) {\n\t\t\tfor (const part of record.content) {\n\t\t\t\tif (\n\t\t\t\t\tpart &&\n\t\t\t\t\ttypeof part === \"object\" &&\n\t\t\t\t\t(part as { type?: string }).type === \"output_text\" &&\n\t\t\t\t\t\"annotations\" in part\n\t\t\t\t) {\n\t\t\t\t\tdelete (part as Record<string, unknown>).annotations;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction extractInstructions(\n\tinput: unknown,\n\tsystemPrompt: string | undefined,\n): { instructions?: string; input: unknown } {\n\t// Prefer context.systemPrompt (matches Codex stream path).\n\tif (systemPrompt && systemPrompt.length > 0) {\n\t\tconst stripped = stripLeadingSystemRoles(input);\n\t\treturn { instructions: systemPrompt, input: stripped ?? input };\n\t}\n\n\tif (!Array.isArray(input) || input.length === 0) {\n\t\treturn { input };\n\t}\n\n\tconst first = input[0];\n\tif (\n\t\tfirst &&\n\t\ttypeof first === \"object\" &&\n\t\t!Array.isArray(first) &&\n\t\t\"role\" in first &&\n\t\t((first as { role?: string }).role === \"system\" || (first as { role?: string }).role === \"developer\")\n\t) {\n\t\tconst content = (first as { content?: unknown }).content;\n\t\tconst text =\n\t\t\ttypeof content === \"string\"\n\t\t\t\t? content\n\t\t\t\t: Array.isArray(content)\n\t\t\t\t\t? content\n\t\t\t\t\t\t\t.map((part) =>\n\t\t\t\t\t\t\t\tpart && typeof part === \"object\" && \"text\" in part\n\t\t\t\t\t\t\t\t\t? String((part as { text: unknown }).text)\n\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join(\"\")\n\t\t\t\t\t: \"\";\n\t\treturn {\n\t\t\tinstructions: text || undefined,\n\t\t\tinput: input.slice(1),\n\t\t};\n\t}\n\n\treturn { input };\n}\n\nfunction stripLeadingSystemRoles(input: unknown): unknown {\n\tif (!Array.isArray(input) || input.length === 0) return input;\n\tconst first = input[0];\n\tif (\n\t\tfirst &&\n\t\ttypeof first === \"object\" &&\n\t\t!Array.isArray(first) &&\n\t\t((first as { role?: string }).role === \"system\" || (first as { role?: string }).role === \"developer\")\n\t) {\n\t\treturn input.slice(1);\n\t}\n\treturn input;\n}\n\nfunction clampCacheKey(sessionId: string | undefined): string | undefined {\n\tif (!sessionId) return undefined;\n\treturn sessionId.length <= 64 ? sessionId : sessionId.slice(0, 64);\n}\n\nexport function resolveResponsesUrl(baseUrl: string): string {\n\tconst normalized = baseUrl.trim().replace(/\\/+$/, \"\");\n\tif (!normalized) throw new Error(\"Model baseUrl is empty.\");\n\tif (normalized.endsWith(\"/responses\")) return normalized;\n\treturn `${normalized}/responses`;\n}\n\nexport function isRouterApi(api: string): boolean {\n\treturn api === ROUTER_API;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../../src/extensions/router/stream.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Codex-oriented Responses client for API relays.\n *\n * Follows Pi's documented custom-provider pattern (see coding-agent docs\n * providers.md / custom-provider.md and examples/custom-provider-gitlab-duo):\n * wrap a built-in pi-ai stream API from `@earendil-works/pi-ai/compat` instead of\n * reimplementing SSE or deep-importing internal modules.\n *\n * We use openAIResponsesApi (works with relay sk- keys) and reshape the request\n * payload toward Codex CLI style so transparent gateways receive a friendlier body.\n */\n\nimport {\n\ttype Api,\n\ttype Context,\n\tcreateAssistantMessageEventStream,\n\ttype Model,\n\topenAIResponsesApi,\n\ttype SimpleStreamOptions,\n} from \"@earendil-works/pi-ai/compat\";\n\nimport { DEFAULTS, formatError, ROUTER_API } from \"./constants.ts\";\n\nconst responsesApi = openAIResponsesApi();\n\nexport function streamRouterCodex(\n\tmodel: Model<Api>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): ReturnType<typeof createAssistantMessageEventStream> {\n\tconst stream = createAssistantMessageEventStream();\n\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey;\n\t\t\tif (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);\n\n\t\t\t// Built-in Responses stream expects api \"openai-responses\" on the model object.\n\t\t\tconst requestModel = {\n\t\t\t\t...model,\n\t\t\t\tapi: \"openai-responses\" as const,\n\t\t\t\tcompat: {\n\t\t\t\t\tsupportsDeveloperRole: true,\n\t\t\t\t\t// Avoid underscore session_id header that strict proxies reject.\n\t\t\t\t\tsessionAffinityFormat: \"openai-nosession\" as const,\n\t\t\t\t\t// Codex-style upstreams reject prompt_cache_retention: \"24h\".\n\t\t\t\t\tsupportsLongCacheRetention: false,\n\t\t\t\t\t...(model.compat ?? {}),\n\t\t\t\t},\n\t\t\t} as Model<\"openai-responses\">;\n\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\toriginator: DEFAULTS.originator,\n\t\t\t\t...(options?.headers as Record<string, string> | undefined),\n\t\t\t};\n\n\t\t\t// Prefer hyphenated Codex-style session affinity when we have a session id.\n\t\t\tconst sessionId = clampCacheKey(options?.sessionId);\n\t\t\tif (sessionId) {\n\t\t\t\tif (!headers[\"session-id\"]) headers[\"session-id\"] = sessionId;\n\t\t\t\tif (!headers[\"x-client-request-id\"]) headers[\"x-client-request-id\"] = sessionId;\n\t\t\t}\n\n\t\t\tconst inner = responsesApi.streamSimple(requestModel, context, {\n\t\t\t\t...options,\n\t\t\t\tapiKey,\n\t\t\t\theaders,\n\t\t\t\tonPayload: (payload) => reshapePayloadForRelay(payload, context, options?.onPayload, requestModel),\n\t\t\t});\n\n\t\t\tfor await (const event of inner) {\n\t\t\t\tstream.push(event);\n\t\t\t}\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\t// Match examples/custom-provider-gitlab-duo error event shape.\n\t\t\tstream.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\treason: options?.signal?.aborted ? \"aborted\" : \"error\",\n\t\t\t\terror: {\n\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\tcontent: [],\n\t\t\t\t\tapi: model.api,\n\t\t\t\t\tprovider: model.provider,\n\t\t\t\t\tmodel: model.id,\n\t\t\t\t\tusage: {\n\t\t\t\t\t\tinput: 0,\n\t\t\t\t\t\toutput: 0,\n\t\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\ttotalTokens: 0,\n\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t},\n\t\t\t\t\tstopReason: options?.signal?.aborted ? \"aborted\" : \"error\",\n\t\t\t\t\terrorMessage: formatError(error),\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t});\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n}\n\n/**\n * Nudge the OpenAI Responses payload toward Codex CLI request shape for\n * transparent relays: instructions + input, store:false, no max_output_tokens /\n * prompt_cache_retention, verbosity + parallel_tool_calls.\n */\nasync function reshapePayloadForRelay(\n\tpayload: unknown,\n\tcontext: Context,\n\tuserOnPayload: SimpleStreamOptions[\"onPayload\"],\n\tmodel: Model<\"openai-responses\">,\n): Promise<unknown> {\n\tconst base =\n\t\tpayload && typeof payload === \"object\" && !Array.isArray(payload)\n\t\t\t? { ...(payload as Record<string, unknown>) }\n\t\t\t: ({} as Record<string, unknown>);\n\n\t// Always safe for ChatGPT/Codex-style backends.\n\tbase.store = false;\n\tbase.stream = true;\n\n\t// Codex CLI sends system prompt as `instructions`, not as a role message in input.\n\tconst { instructions, input } = extractInstructions(base.input, context.systemPrompt);\n\tif (instructions) base.instructions = instructions;\n\tif (input !== undefined) base.input = input;\n\n\t// Released Codex CLI defaults omit replayed ResponseItem ids from store:false\n\t// requests. It also never emits `status` on the item types below, and its\n\t// output_text content has no `annotations`.\n\tsanitizeInputItemsForCodex(base.input);\n\n\t// Fields common on Codex CLI / rejected by many transparent Codex upstreams.\n\tif (!base.text || typeof base.text !== \"object\") {\n\t\tbase.text = { verbosity: \"low\" };\n\t}\n\tif (base.tool_choice === undefined) base.tool_choice = \"auto\";\n\tif (base.parallel_tool_calls === undefined) base.parallel_tool_calls = true;\n\n\t// Prefer encrypted reasoning content for multi-turn store:false sessions.\n\tconst include = Array.isArray(base.include) ? [...(base.include as unknown[])] : [];\n\tif (!include.includes(\"reasoning.encrypted_content\")) {\n\t\tinclude.push(\"reasoning.encrypted_content\");\n\t}\n\tbase.include = include;\n\n\t// Drop Platform-only fields that Codex OAuth endpoints often 400 on.\n\tdelete base.prompt_cache_retention;\n\tdelete base.prompt_cache_options;\n\tdelete base.max_output_tokens;\n\tdelete base.temperature;\n\tdelete base.top_p;\n\tdelete base.user;\n\tdelete base.metadata;\n\tdelete base.service_tier;\n\tdelete base.truncation;\n\tdelete base.context_management;\n\tdelete base.safety_identifier;\n\tdelete base.stream_options;\n\n\tif (userOnPayload) {\n\t\tconst next = await userOnPayload(base, model);\n\t\tif (next !== undefined) return next;\n\t}\n\treturn base;\n}\n\n/**\n * Match the released Codex CLI's default stateless request preparation:\n * optional ResponseItem identity ids are omitted from store:false requests,\n * while semantic ids, call_id, and encrypted_content remain available for\n * reference, tool, and reasoning continuity.\n *\n * These are the tagged variants handled by ResponseItem::set_id in Codex CLI\n * 0.145. Unknown input variants must retain `id`: for example,\n * item_reference.id and local_shell_call_output.id are required references,\n * not optional ResponseItem identities.\n */\nconst RESPONSE_ITEM_ID_TYPES = new Set([\n\t\"additional_tools\",\n\t\"message\",\n\t\"agent_message\",\n\t\"reasoning\",\n\t\"local_shell_call\",\n\t\"function_call\",\n\t\"tool_search_call\",\n\t\"function_call_output\",\n\t\"custom_tool_call\",\n\t\"custom_tool_call_output\",\n\t\"tool_search_output\",\n\t\"web_search_call\",\n\t\"image_generation_call\",\n\t\"compaction\",\n\t\"compaction_summary\",\n\t\"context_compaction\",\n]);\n\n/**\n * Codex ResponseItem serialization has NO `status` field on Message,\n * Reasoning, FunctionCall, FunctionCallOutput, or CustomToolCallOutput\n * (codex-rs/protocol/src/models.rs). Other item types either require `status`\n * (local_shell_call, tool_search_output, image_generation_call) or accept it\n * optionally (tool_search_call, custom_tool_call, web_search_call), so we must\n * not strip it there.\n */\nconst STATUS_LESS_ITEM_TYPES = new Set([\n\t\"message\",\n\t\"reasoning\",\n\t\"function_call\",\n\t\"function_call_output\",\n\t\"custom_tool_call_output\",\n]);\n\nexport function sanitizeInputItemsForCodex(input: unknown): void {\n\tif (!Array.isArray(input)) return;\n\tfor (const item of input) {\n\t\tif (!item || typeof item !== \"object\" || Array.isArray(item)) continue;\n\t\tconst record = item as Record<string, unknown>;\n\t\tconst type = typeof record.type === \"string\" ? record.type : undefined;\n\t\tif (type && RESPONSE_ITEM_ID_TYPES.has(type)) {\n\t\t\tdelete record.id;\n\t\t}\n\t\tif (type && STATUS_LESS_ITEM_TYPES.has(type) && \"status\" in record) {\n\t\t\tdelete record.status;\n\t\t}\n\t\tif (Array.isArray(record.content)) {\n\t\t\tfor (const part of record.content) {\n\t\t\t\tif (\n\t\t\t\t\tpart &&\n\t\t\t\t\ttypeof part === \"object\" &&\n\t\t\t\t\t(part as { type?: string }).type === \"output_text\" &&\n\t\t\t\t\t\"annotations\" in part\n\t\t\t\t) {\n\t\t\t\t\tdelete (part as Record<string, unknown>).annotations;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction extractInstructions(\n\tinput: unknown,\n\tsystemPrompt: string | undefined,\n): { instructions?: string; input: unknown } {\n\t// Prefer context.systemPrompt (matches Codex stream path).\n\tif (systemPrompt && systemPrompt.length > 0) {\n\t\tconst stripped = stripLeadingSystemRoles(input);\n\t\treturn { instructions: systemPrompt, input: stripped ?? input };\n\t}\n\n\tif (!Array.isArray(input) || input.length === 0) {\n\t\treturn { input };\n\t}\n\n\tconst first = input[0];\n\tif (\n\t\tfirst &&\n\t\ttypeof first === \"object\" &&\n\t\t!Array.isArray(first) &&\n\t\t\"role\" in first &&\n\t\t((first as { role?: string }).role === \"system\" || (first as { role?: string }).role === \"developer\")\n\t) {\n\t\tconst content = (first as { content?: unknown }).content;\n\t\tconst text =\n\t\t\ttypeof content === \"string\"\n\t\t\t\t? content\n\t\t\t\t: Array.isArray(content)\n\t\t\t\t\t? content\n\t\t\t\t\t\t\t.map((part) =>\n\t\t\t\t\t\t\t\tpart && typeof part === \"object\" && \"text\" in part\n\t\t\t\t\t\t\t\t\t? String((part as { text: unknown }).text)\n\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join(\"\")\n\t\t\t\t\t: \"\";\n\t\treturn {\n\t\t\tinstructions: text || undefined,\n\t\t\tinput: input.slice(1),\n\t\t};\n\t}\n\n\treturn { input };\n}\n\nfunction stripLeadingSystemRoles(input: unknown): unknown {\n\tif (!Array.isArray(input) || input.length === 0) return input;\n\tconst first = input[0];\n\tif (\n\t\tfirst &&\n\t\ttypeof first === \"object\" &&\n\t\t!Array.isArray(first) &&\n\t\t((first as { role?: string }).role === \"system\" || (first as { role?: string }).role === \"developer\")\n\t) {\n\t\treturn input.slice(1);\n\t}\n\treturn input;\n}\n\nfunction clampCacheKey(sessionId: string | undefined): string | undefined {\n\tif (!sessionId) return undefined;\n\treturn sessionId.length <= 64 ? sessionId : sessionId.slice(0, 64);\n}\n\nexport function resolveResponsesUrl(baseUrl: string): string {\n\tconst normalized = baseUrl.trim().replace(/\\/+$/, \"\");\n\tif (!normalized) throw new Error(\"Model baseUrl is empty.\");\n\tif (normalized.endsWith(\"/responses\")) return normalized;\n\treturn `${normalized}/responses`;\n}\n\nexport function isRouterApi(api: string): boolean {\n\treturn api === ROUTER_API;\n}\n"]}
|
|
@@ -18,6 +18,7 @@ export declare const SINGLE_OUTPUT_LIMIT: number;
|
|
|
18
18
|
export declare const PARALLEL_TASK_OUTPUT_LIMIT: number;
|
|
19
19
|
export declare const PARALLEL_OUTPUT_LIMIT: number;
|
|
20
20
|
export declare const ERROR_TEXT_LIMIT: number;
|
|
21
|
+
export declare const RETRY_ERROR_TEXT_LIMIT = 160;
|
|
21
22
|
export declare const DETAILS_OUTPUT_LIMIT: number;
|
|
22
23
|
export declare const DETAILS_ACTIVITY_LIMIT = 12;
|
|
23
24
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAC7C,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAC9C,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AAEpD,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,eAAO,MAAM,eAAe,IAAI,CAAC;AAKjC,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,wBAAwB,OAAQ,CAAC;AAE9C,eAAO,MAAM,kBAAkB,kEAAmE,CAAC;AAEnG,eAAO,MAAM,mBAAmB,4CAA6C,CAAC;AAG9E,eAAO,MAAM,cAAc,iDAAkD,CAAC;AAE9E,eAAO,MAAM,eAAe,sEAQiB,CAAC;AAE9C,eAAO,MAAM,eAAe,QAAW,CAAC;AACxC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAC7C,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAC7C,eAAO,MAAM,0BAA0B,QAAY,CAAC;AACpD,eAAO,MAAM,qBAAqB,QAAY,CAAC;AAC/C,eAAO,MAAM,gBAAgB,QAAW,CAAC;AACzC,eAAO,MAAM,oBAAoB,QAAa,CAAC;AAG/C,eAAO,MAAM,sBAAsB,KAAK,CAAC","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\n\nexport const SUBAGENT_TOOL_NAME = \"subagent\";\nexport const SUBAGENT_TOOL_LABEL = \"Subagent\";\nexport const SUBAGENT_COMMAND_NAME = \"agents\";\nexport const SUBAGENT_CONFIG_VERSION = 1;\nexport const SUBAGENT_CONFIG_FILE = \"subagent.json\";\n\nexport const MAX_TASKS = 8;\nexport const MAX_CONCURRENCY = 5;\n\n// Task-level retry for failures that bypass the session's own auto-retry\n// (preflight throws such as auth checks). Only runs that produced nothing\n// are retried, so a retry never discards partial work.\nexport const TASK_RETRY_LIMIT = 2;\nexport const TASK_RETRY_BASE_DELAY_MS = 1_000;\n\nexport const BUILTIN_TOOL_NAMES = [\"read\", \"bash\", \"edit\", \"write\", \"grep\", \"find\", \"ls\"] as const;\n// Matches the parent session's default toolset; bash covers search needs.\nexport const DEFAULT_AGENT_TOOLS = [\"read\", \"bash\", \"edit\", \"write\"] as const;\n// Read-only agents get the standalone search tools plus bash for read-only\n// inspection (git history, counting); the system prompt constrains bash.\nexport const EXPLORER_TOOLS = [\"read\", \"grep\", \"find\", \"ls\", \"bash\"] as const;\n\nexport const THINKING_LEVELS = [\n\t\"off\",\n\t\"minimal\",\n\t\"low\",\n\t\"medium\",\n\t\"high\",\n\t\"xhigh\",\n\t\"max\",\n] as const satisfies readonly ThinkingLevel[];\n\nexport const LIVE_TEXT_LIMIT = 8 * 1024;\nexport const ACTIVITY_LIMIT = 80;\nexport const ACTIVITY_TEXT_LIMIT = 24 * 1024;\nexport const SINGLE_OUTPUT_LIMIT = 32 * 1024;\nexport const PARALLEL_TASK_OUTPUT_LIMIT = 12 * 1024;\nexport const PARALLEL_OUTPUT_LIMIT = 48 * 1024;\nexport const ERROR_TEXT_LIMIT = 8 * 1024;\nexport const DETAILS_OUTPUT_LIMIT = 120 * 1024;\n// Bounded per run inside DETAILS_OUTPUT_LIMIT; each activity costs up to\n// ~600 bytes, so 12 keeps an 8-run parallel batch from starving outputs.\nexport const DETAILS_ACTIVITY_LIMIT = 12;\n"]}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAC7C,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAC9C,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AAEpD,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,eAAO,MAAM,eAAe,IAAI,CAAC;AAKjC,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,wBAAwB,OAAQ,CAAC;AAE9C,eAAO,MAAM,kBAAkB,kEAAmE,CAAC;AAEnG,eAAO,MAAM,mBAAmB,4CAA6C,CAAC;AAG9E,eAAO,MAAM,cAAc,iDAAkD,CAAC;AAE9E,eAAO,MAAM,eAAe,sEAQiB,CAAC;AAE9C,eAAO,MAAM,eAAe,QAAW,CAAC;AACxC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAC7C,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAC7C,eAAO,MAAM,0BAA0B,QAAY,CAAC;AACpD,eAAO,MAAM,qBAAqB,QAAY,CAAC;AAC/C,eAAO,MAAM,gBAAgB,QAAW,CAAC;AACzC,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,oBAAoB,QAAa,CAAC;AAG/C,eAAO,MAAM,sBAAsB,KAAK,CAAC","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\n\nexport const SUBAGENT_TOOL_NAME = \"subagent\";\nexport const SUBAGENT_TOOL_LABEL = \"Subagent\";\nexport const SUBAGENT_COMMAND_NAME = \"agents\";\nexport const SUBAGENT_CONFIG_VERSION = 1;\nexport const SUBAGENT_CONFIG_FILE = \"subagent.json\";\n\nexport const MAX_TASKS = 8;\nexport const MAX_CONCURRENCY = 5;\n\n// Task-level retry for failures that bypass the session's own auto-retry\n// (preflight throws such as auth checks). Only runs that produced nothing\n// are retried, so a retry never discards partial work.\nexport const TASK_RETRY_LIMIT = 2;\nexport const TASK_RETRY_BASE_DELAY_MS = 1_000;\n\nexport const BUILTIN_TOOL_NAMES = [\"read\", \"bash\", \"edit\", \"write\", \"grep\", \"find\", \"ls\"] as const;\n// Matches the parent session's default toolset; bash covers search needs.\nexport const DEFAULT_AGENT_TOOLS = [\"read\", \"bash\", \"edit\", \"write\"] as const;\n// Read-only agents get the standalone search tools plus bash for read-only\n// inspection (git history, counting); the system prompt constrains bash.\nexport const EXPLORER_TOOLS = [\"read\", \"grep\", \"find\", \"ls\", \"bash\"] as const;\n\nexport const THINKING_LEVELS = [\n\t\"off\",\n\t\"minimal\",\n\t\"low\",\n\t\"medium\",\n\t\"high\",\n\t\"xhigh\",\n\t\"max\",\n] as const satisfies readonly ThinkingLevel[];\n\nexport const LIVE_TEXT_LIMIT = 8 * 1024;\nexport const ACTIVITY_LIMIT = 80;\nexport const ACTIVITY_TEXT_LIMIT = 24 * 1024;\nexport const SINGLE_OUTPUT_LIMIT = 32 * 1024;\nexport const PARALLEL_TASK_OUTPUT_LIMIT = 12 * 1024;\nexport const PARALLEL_OUTPUT_LIMIT = 48 * 1024;\nexport const ERROR_TEXT_LIMIT = 8 * 1024;\nexport const RETRY_ERROR_TEXT_LIMIT = 160;\nexport const DETAILS_OUTPUT_LIMIT = 120 * 1024;\n// Bounded per run inside DETAILS_OUTPUT_LIMIT; each activity costs up to\n// ~600 bytes, so 12 keeps an 8-run parallel batch from starving outputs.\nexport const DETAILS_ACTIVITY_LIMIT = 12;\n"]}
|
|
@@ -32,6 +32,7 @@ export const SINGLE_OUTPUT_LIMIT = 32 * 1024;
|
|
|
32
32
|
export const PARALLEL_TASK_OUTPUT_LIMIT = 12 * 1024;
|
|
33
33
|
export const PARALLEL_OUTPUT_LIMIT = 48 * 1024;
|
|
34
34
|
export const ERROR_TEXT_LIMIT = 8 * 1024;
|
|
35
|
+
export const RETRY_ERROR_TEXT_LIMIT = 160;
|
|
35
36
|
export const DETAILS_OUTPUT_LIMIT = 120 * 1024;
|
|
36
37
|
// Bounded per run inside DETAILS_OUTPUT_LIMIT; each activity costs up to
|
|
37
38
|
// ~600 bytes, so 12 keeps an 8-run parallel batch from starving outputs.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/extensions/subagent/constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAC9C,MAAM,CAAC,MAAM,qBAAqB,GAAG,QAAQ,CAAC;AAC9C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAEpD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC,yEAAyE;AACzE,0EAA0E;AAC1E,uDAAuD;AACvD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAClC,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAE9C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAU,CAAC;AACnG,0EAA0E;AAC1E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;AAC9E,2EAA2E;AAC3E,yEAAyE;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAU,CAAC;AAE9E,MAAM,CAAC,MAAM,eAAe,GAAG;IAC9B,KAAK;IACL,SAAS;IACT,KAAK;IACL,QAAQ;IACR,MAAM;IACN,OAAO;IACP,KAAK;CACuC,CAAC;AAE9C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,CAAC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAC;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAC;AAC7C,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,IAAI,CAAC;AACpD,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,GAAG,IAAI,CAAC;AAC/C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,CAAC;AACzC,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,GAAG,IAAI,CAAC;AAC/C,yEAAyE;AACzE,yEAAyE;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\n\nexport const SUBAGENT_TOOL_NAME = \"subagent\";\nexport const SUBAGENT_TOOL_LABEL = \"Subagent\";\nexport const SUBAGENT_COMMAND_NAME = \"agents\";\nexport const SUBAGENT_CONFIG_VERSION = 1;\nexport const SUBAGENT_CONFIG_FILE = \"subagent.json\";\n\nexport const MAX_TASKS = 8;\nexport const MAX_CONCURRENCY = 5;\n\n// Task-level retry for failures that bypass the session's own auto-retry\n// (preflight throws such as auth checks). Only runs that produced nothing\n// are retried, so a retry never discards partial work.\nexport const TASK_RETRY_LIMIT = 2;\nexport const TASK_RETRY_BASE_DELAY_MS = 1_000;\n\nexport const BUILTIN_TOOL_NAMES = [\"read\", \"bash\", \"edit\", \"write\", \"grep\", \"find\", \"ls\"] as const;\n// Matches the parent session's default toolset; bash covers search needs.\nexport const DEFAULT_AGENT_TOOLS = [\"read\", \"bash\", \"edit\", \"write\"] as const;\n// Read-only agents get the standalone search tools plus bash for read-only\n// inspection (git history, counting); the system prompt constrains bash.\nexport const EXPLORER_TOOLS = [\"read\", \"grep\", \"find\", \"ls\", \"bash\"] as const;\n\nexport const THINKING_LEVELS = [\n\t\"off\",\n\t\"minimal\",\n\t\"low\",\n\t\"medium\",\n\t\"high\",\n\t\"xhigh\",\n\t\"max\",\n] as const satisfies readonly ThinkingLevel[];\n\nexport const LIVE_TEXT_LIMIT = 8 * 1024;\nexport const ACTIVITY_LIMIT = 80;\nexport const ACTIVITY_TEXT_LIMIT = 24 * 1024;\nexport const SINGLE_OUTPUT_LIMIT = 32 * 1024;\nexport const PARALLEL_TASK_OUTPUT_LIMIT = 12 * 1024;\nexport const PARALLEL_OUTPUT_LIMIT = 48 * 1024;\nexport const ERROR_TEXT_LIMIT = 8 * 1024;\nexport const DETAILS_OUTPUT_LIMIT = 120 * 1024;\n// Bounded per run inside DETAILS_OUTPUT_LIMIT; each activity costs up to\n// ~600 bytes, so 12 keeps an 8-run parallel batch from starving outputs.\nexport const DETAILS_ACTIVITY_LIMIT = 12;\n"]}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/extensions/subagent/constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAC9C,MAAM,CAAC,MAAM,qBAAqB,GAAG,QAAQ,CAAC;AAC9C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAEpD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC,yEAAyE;AACzE,0EAA0E;AAC1E,uDAAuD;AACvD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAClC,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAE9C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAU,CAAC;AACnG,0EAA0E;AAC1E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;AAC9E,2EAA2E;AAC3E,yEAAyE;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAU,CAAC;AAE9E,MAAM,CAAC,MAAM,eAAe,GAAG;IAC9B,KAAK;IACL,SAAS;IACT,KAAK;IACL,QAAQ;IACR,MAAM;IACN,OAAO;IACP,KAAK;CACuC,CAAC;AAE9C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,CAAC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAC;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAC;AAC7C,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,IAAI,CAAC;AACpD,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,GAAG,IAAI,CAAC;AAC/C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,CAAC;AACzC,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAC1C,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,GAAG,IAAI,CAAC;AAC/C,yEAAyE;AACzE,yEAAyE;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\n\nexport const SUBAGENT_TOOL_NAME = \"subagent\";\nexport const SUBAGENT_TOOL_LABEL = \"Subagent\";\nexport const SUBAGENT_COMMAND_NAME = \"agents\";\nexport const SUBAGENT_CONFIG_VERSION = 1;\nexport const SUBAGENT_CONFIG_FILE = \"subagent.json\";\n\nexport const MAX_TASKS = 8;\nexport const MAX_CONCURRENCY = 5;\n\n// Task-level retry for failures that bypass the session's own auto-retry\n// (preflight throws such as auth checks). Only runs that produced nothing\n// are retried, so a retry never discards partial work.\nexport const TASK_RETRY_LIMIT = 2;\nexport const TASK_RETRY_BASE_DELAY_MS = 1_000;\n\nexport const BUILTIN_TOOL_NAMES = [\"read\", \"bash\", \"edit\", \"write\", \"grep\", \"find\", \"ls\"] as const;\n// Matches the parent session's default toolset; bash covers search needs.\nexport const DEFAULT_AGENT_TOOLS = [\"read\", \"bash\", \"edit\", \"write\"] as const;\n// Read-only agents get the standalone search tools plus bash for read-only\n// inspection (git history, counting); the system prompt constrains bash.\nexport const EXPLORER_TOOLS = [\"read\", \"grep\", \"find\", \"ls\", \"bash\"] as const;\n\nexport const THINKING_LEVELS = [\n\t\"off\",\n\t\"minimal\",\n\t\"low\",\n\t\"medium\",\n\t\"high\",\n\t\"xhigh\",\n\t\"max\",\n] as const satisfies readonly ThinkingLevel[];\n\nexport const LIVE_TEXT_LIMIT = 8 * 1024;\nexport const ACTIVITY_LIMIT = 80;\nexport const ACTIVITY_TEXT_LIMIT = 24 * 1024;\nexport const SINGLE_OUTPUT_LIMIT = 32 * 1024;\nexport const PARALLEL_TASK_OUTPUT_LIMIT = 12 * 1024;\nexport const PARALLEL_OUTPUT_LIMIT = 48 * 1024;\nexport const ERROR_TEXT_LIMIT = 8 * 1024;\nexport const RETRY_ERROR_TEXT_LIMIT = 160;\nexport const DETAILS_OUTPUT_LIMIT = 120 * 1024;\n// Bounded per run inside DETAILS_OUTPUT_LIMIT; each activity costs up to\n// ~600 bytes, so 12 keeps an 8-run parallel batch from starving outputs.\nexport const DETAILS_ACTIVITY_LIMIT = 12;\n"]}
|