@code-yeongyu/senpi 2026.9.19 → 2026.9.20
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 +67 -0
- package/dist/bundle/chunks/{app-server-command-QK7Q6XK5.js → app-server-command-B35FQUTE.js} +1 -1
- package/dist/bundle/chunks/{bun-extension-importer-JQZRPNJH.js → bun-extension-importer-HHH4TV4B.js} +3 -3
- package/dist/bundle/chunks/{chunk-YRN3PCTM.js → chunk-DQZB4GVV.js} +4 -4
- package/dist/bundle/chunks/{chunk-KKDSBABY.js → chunk-E5R67F7G.js} +38 -38
- package/dist/bundle/chunks/{chunk-NARL7XFO.js → chunk-TWGC3TBR.js} +2 -2
- package/dist/bundle/chunks/{chunk-RLRLQRI2.js → chunk-V2ZB62DG.js} +1 -1
- package/dist/bundle/chunks/{chunk-3FRTRCR6.js → chunk-YXQG2SUX.js} +2 -2
- package/dist/bundle/chunks/{chunk-PLZK7ABD.js → chunk-Z4LHCTJ6.js} +1 -1
- package/dist/bundle/chunks/{chunk-3Q4WGKFA.js → chunk-ZMFHNH6U.js} +1 -1
- package/dist/bundle/chunks/{cli-main-7SG3K4K3.js → cli-main-USVT7JMN.js} +1 -1
- package/dist/bundle/chunks/{interactive-host-runtime-AITXUDCT.js → interactive-host-runtime-ELBAZ4LN.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-7MN6GGCG.js → interactive-mode-R6225BKI.js} +1 -1
- package/dist/bundle/chunks/{list-tips-KTDNGQUK.js → list-tips-Z7T2ACVU.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-WKX34SOP.js → multi-session-host-QNEBJW2P.js} +3 -3
- package/dist/bundle/chunks/{package-manager-cli-CB2X57TD.js → package-manager-cli-4MVJ3JSE.js} +1 -1
- package/dist/bundle/chunks/{rpc-mode-CI6V2SBW.js → rpc-mode-CXVDRIBU.js} +1 -1
- package/dist/bundle/chunks/{session-picker-DXCITGLS.js → session-picker-6N666KQZ.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +67 -67
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +14 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +49 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +290 -44
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/builtin/ask-user/extension.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ask-user/extension.js +16 -5
- package/dist/core/extensions/builtin/ask-user/extension.js.map +1 -1
- package/dist/core/extensions/builtin/ask-user/format.d.ts +5 -0
- package/dist/core/extensions/builtin/ask-user/format.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ask-user/format.js +4 -0
- package/dist/core/extensions/builtin/ask-user/format.js.map +1 -1
- package/dist/core/extensions/builtin/ask-user/notify.d.ts +2 -0
- package/dist/core/extensions/builtin/ask-user/notify.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ask-user/notify.js +2 -0
- package/dist/core/extensions/builtin/ask-user/notify.js.map +1 -1
- package/dist/core/extensions/builtin/ask-user/registry.d.ts +15 -2
- package/dist/core/extensions/builtin/ask-user/registry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ask-user/registry.js +13 -0
- package/dist/core/extensions/builtin/ask-user/registry.js.map +1 -1
- package/dist/core/extensions/builtin/ask-user/render.d.ts +6 -0
- package/dist/core/extensions/builtin/ask-user/render.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ask-user/render.js +9 -0
- package/dist/core/extensions/builtin/ask-user/render.js.map +1 -1
- package/dist/core/extensions/builtin/ask-user/resume.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ask-user/resume.js +59 -24
- package/dist/core/extensions/builtin/ask-user/resume.js.map +1 -1
- package/dist/core/extensions/builtin/ask-user/tool.d.ts +1 -1
- package/dist/core/extensions/builtin/ask-user/tool.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ask-user/tool.js +98 -17
- package/dist/core/extensions/builtin/ask-user/tool.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts +18 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/model-usability-budget.js +16 -8
- package/dist/core/extensions/builtin/compaction/model-usability-budget.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/switch-admission.d.ts +23 -0
- package/dist/core/extensions/builtin/compaction/switch-admission.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/switch-admission.js +19 -0
- package/dist/core/extensions/builtin/compaction/switch-admission.js.map +1 -0
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +10 -0
- package/dist/core/extensions/builtin/goal/index.js.map +1 -1
- package/dist/core/extensions/bun-extension-commonjs.d.ts +1 -1
- package/dist/core/extensions/bun-extension-commonjs.d.ts.map +1 -1
- package/dist/core/extensions/bun-extension-commonjs.js +3 -3
- package/dist/core/extensions/bun-extension-commonjs.js.map +1 -1
- package/dist/core/extensions/bun-extension-importer.d.ts.map +1 -1
- package/dist/core/extensions/bun-extension-importer.js +4 -1
- package/dist/core/extensions/bun-extension-importer.js.map +1 -1
- package/dist/core/extensions/bun-extension-registry.d.ts.map +1 -1
- package/dist/core/extensions/bun-extension-registry.js +5 -9
- package/dist/core/extensions/bun-extension-registry.js.map +1 -1
- package/dist/core/resolved-paths-memo.d.ts +31 -0
- package/dist/core/resolved-paths-memo.d.ts.map +1 -0
- package/dist/core/resolved-paths-memo.js +57 -0
- package/dist/core/resolved-paths-memo.js.map +1 -0
- package/dist/core/resource-loader.d.ts +4 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +25 -12
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/retry-fallback/settings.d.ts +10 -2
- package/dist/core/retry-fallback/settings.d.ts.map +1 -1
- package/dist/core/retry-fallback/settings.js +28 -6
- package/dist/core/retry-fallback/settings.js.map +1 -1
- package/dist/core/skill-discovery.d.ts.map +1 -1
- package/dist/core/skill-discovery.js +11 -1
- package/dist/core/skill-discovery.js.map +1 -1
- package/dist/main.d.ts +10 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +19 -2
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/ask-user-answer-chip.d.ts +2 -5
- package/dist/modes/interactive/components/ask-user-answer-chip.d.ts.map +1 -1
- package/dist/modes/interactive/components/ask-user-answer-chip.js +1 -4
- package/dist/modes/interactive/components/ask-user-answer-chip.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +2 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +8 -0
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/assistant-render-descriptors.d.ts +1 -0
- package/dist/modes/interactive/components/assistant-render-descriptors.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-render-descriptors.js +4 -0
- package/dist/modes/interactive/components/assistant-render-descriptors.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +15 -2
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +81 -6
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/provider-error-presentation.d.ts +18 -0
- package/dist/modes/interactive/provider-error-presentation.d.ts.map +1 -0
- package/dist/modes/interactive/provider-error-presentation.js +100 -0
- package/dist/modes/interactive/provider-error-presentation.js.map +1 -0
- package/dist/modes/rpc/rpc-types.d.ts +18 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +14 -0
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +9 -1
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +21 -0
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +9 -2
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/dist/modes/rpc/session-worker-requests.d.ts +10 -1
- package/dist/modes/rpc/session-worker-requests.d.ts.map +1 -1
- package/dist/modes/rpc/session-worker-requests.js +8 -2
- package/dist/modes/rpc/session-worker-requests.js.map +1 -1
- package/dist/modes/rpc/session-worker-requests.test.d.ts +2 -0
- package/dist/modes/rpc/session-worker-requests.test.d.ts.map +1 -0
- package/dist/modes/rpc/session-worker-requests.test.js +44 -0
- package/dist/modes/rpc/session-worker-requests.test.js.map +1 -0
- package/docs/rpc.md +7 -0
- package/docs/settings.md +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/native-module-path.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/native-module-path.js +26 -3
- package/node_modules/@earendil-works/pi-tui/dist/native-module-path.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.js +13 -6
- package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui-main-screen.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui-main-screen.js +11 -3
- package/node_modules/@earendil-works/pi-tui/dist/tui-main-screen.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +15 -2
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js +45 -2
- package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/extension.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAMrE,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/extension.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAMrE,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA8D/D"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { APP_NAME } from "../../../../config.js";
|
|
2
2
|
import { pickVariant, TOOL_NAMES } from "./family.js";
|
|
3
|
-
import { getPendingQuestions } from "./registry.js";
|
|
3
|
+
import { deliverQueuedQuestionOutcomes, getPendingQuestions } from "./registry.js";
|
|
4
4
|
import { resumeDanglingQuestion } from "./resume.js";
|
|
5
5
|
import { createAskUserTool } from "./tool.js";
|
|
6
6
|
export default function askUserExtension(pi) {
|
|
@@ -21,14 +21,14 @@ export default function askUserExtension(pi) {
|
|
|
21
21
|
});
|
|
22
22
|
const state = { timedOut: false, unavailable: false };
|
|
23
23
|
let registered = false;
|
|
24
|
-
const cancelPending = (ctx, message) => {
|
|
24
|
+
const cancelPending = (ctx, message, reportDetachedLoss = false) => {
|
|
25
25
|
for (const entry of getPendingQuestions(ctx.sessionManager.getSessionId()))
|
|
26
|
-
entry.cancel(message);
|
|
26
|
+
entry.cancel(message, reportDetachedLoss);
|
|
27
27
|
};
|
|
28
28
|
const sync = (ctx, model = ctx.model) => {
|
|
29
29
|
const rest = pi.getActiveTools().filter((name) => !Object.values(TOOL_NAMES).includes(name));
|
|
30
30
|
if (ctx.getAskUserSettings?.().enabled === false || pi.getFlag("no-ask-user") === true) {
|
|
31
|
-
cancelPending(ctx, "The pending question was cancelled because ask-user is disabled.");
|
|
31
|
+
cancelPending(ctx, "The pending question was cancelled because ask-user is disabled.", true);
|
|
32
32
|
pi.setActiveTools(rest);
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
@@ -42,7 +42,13 @@ export default function askUserExtension(pi) {
|
|
|
42
42
|
pi.on("session_start", async (event, ctx) => {
|
|
43
43
|
state.timedOut = false;
|
|
44
44
|
state.unavailable = false;
|
|
45
|
+
const sessionId = ctx.sessionManager.getSessionId();
|
|
46
|
+
for (const entry of getPendingQuestions(sessionId))
|
|
47
|
+
entry.rebind(pi, ctx, state);
|
|
48
|
+
deliverQueuedQuestionOutcomes(sessionId, pi, ctx);
|
|
45
49
|
sync(ctx);
|
|
50
|
+
for (const entry of getPendingQuestions(sessionId))
|
|
51
|
+
entry.reattach();
|
|
46
52
|
void resumeDanglingQuestion(pi, event, ctx);
|
|
47
53
|
});
|
|
48
54
|
pi.on("model_select", async (event, ctx) => {
|
|
@@ -51,7 +57,12 @@ export default function askUserExtension(pi) {
|
|
|
51
57
|
pi.on("agent_end", async () => {
|
|
52
58
|
state.timedOut = false;
|
|
53
59
|
});
|
|
54
|
-
pi.on("session_shutdown", async (
|
|
60
|
+
pi.on("session_shutdown", async (event, ctx) => {
|
|
61
|
+
if (event.reason === "reload") {
|
|
62
|
+
for (const entry of getPendingQuestions(ctx.sessionManager.getSessionId()))
|
|
63
|
+
entry.detach();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
55
66
|
cancelPending(ctx, "The pending question was cancelled because the session closed.");
|
|
56
67
|
});
|
|
57
68
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/extension.ts"],"names":[],"mappings":"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","sourcesContent":["import { APP_NAME } from \"../../../../config.ts\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { pickVariant, TOOL_NAMES } from \"./family.ts\";\nimport { deliverQueuedQuestionOutcomes, getPendingQuestions } from \"./registry.ts\";\nimport { resumeDanglingQuestion } from \"./resume.ts\";\nimport { type AskUserState, createAskUserTool } from \"./tool.ts\";\n\nexport default function askUserExtension(pi: ExtensionAPI): void {\n\tpi.registerFlag(\"no-ask-user\", {\n\t\tdescription: \"Disable the built-in question tool.\",\n\t\ttype: \"boolean\",\n\t\tdefault: false,\n\t});\n\tpi.registerCommand(\"answer\", {\n\t\tdescription: \"Open the pending question\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`/answer opens the pending question in the TUI; run ${APP_NAME} in TUI mode to use it.`,\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// In TUI mode interactive-mode's text dispatch handles /answer first.\n\t\t},\n\t});\n\tconst state: AskUserState = { timedOut: false, unavailable: false };\n\tlet registered = false;\n\tconst cancelPending = (ctx: ExtensionContext, message: string, reportDetachedLoss = false) => {\n\t\tfor (const entry of getPendingQuestions(ctx.sessionManager.getSessionId()))\n\t\t\tentry.cancel(message, reportDetachedLoss);\n\t};\n\tconst sync = (ctx: ExtensionContext, model = ctx.model) => {\n\t\tconst rest = pi.getActiveTools().filter((name) => !Object.values(TOOL_NAMES).includes(name));\n\t\tif (ctx.getAskUserSettings?.().enabled === false || pi.getFlag(\"no-ask-user\") === true) {\n\t\t\tcancelPending(ctx, \"The pending question was cancelled because ask-user is disabled.\", true);\n\t\t\tpi.setActiveTools(rest);\n\t\t\treturn;\n\t\t}\n\t\tif (!registered) {\n\t\t\tpi.registerTool(createAskUserTool(\"codex\", pi, state));\n\t\t\tpi.registerTool(createAskUserTool(\"claude\", pi, state));\n\t\t\tregistered = true;\n\t\t}\n\t\tpi.setActiveTools(state.unavailable ? rest : [...rest, TOOL_NAMES[pickVariant(model)]]);\n\t};\n\tpi.on(\"session_start\", async (event, ctx) => {\n\t\tstate.timedOut = false;\n\t\tstate.unavailable = false;\n\t\tconst sessionId = ctx.sessionManager.getSessionId();\n\t\tfor (const entry of getPendingQuestions(sessionId)) entry.rebind(pi, ctx, state);\n\t\tdeliverQueuedQuestionOutcomes(sessionId, pi, ctx);\n\t\tsync(ctx);\n\t\tfor (const entry of getPendingQuestions(sessionId)) entry.reattach();\n\t\tvoid resumeDanglingQuestion(pi, event, ctx);\n\t});\n\tpi.on(\"model_select\", async (event, ctx) => {\n\t\tsync(ctx, event.model);\n\t});\n\tpi.on(\"agent_end\", async () => {\n\t\tstate.timedOut = false;\n\t});\n\tpi.on(\"session_shutdown\", async (event, ctx) => {\n\t\tif (event.reason === \"reload\") {\n\t\t\tfor (const entry of getPendingQuestions(ctx.sessionManager.getSessionId())) entry.detach();\n\t\t\treturn;\n\t\t}\n\t\tcancelPending(ctx, \"The pending question was cancelled because the session closed.\");\n\t});\n}\n"]}
|
|
@@ -17,6 +17,11 @@ export type ClaudeResultDetails = {
|
|
|
17
17
|
type Questions = QuestionRequest["questions"];
|
|
18
18
|
export declare function formatResultText(_variant: AskUserVariant, response: QuestionResponse, questions?: Questions): string;
|
|
19
19
|
export declare function formatUserMessage(response: QuestionResponse, requestId: string, questions?: Questions): string;
|
|
20
|
+
export interface AskUserAnswerFrame {
|
|
21
|
+
readonly requestId: string;
|
|
22
|
+
readonly body: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function parseAskUserAnswerFrame(text: string): AskUserAnswerFrame | undefined;
|
|
20
25
|
export declare function formatResultDetails(variant: AskUserVariant, response: QuestionResponse, questions?: Questions): CodexResultDetails | ClaudeResultDetails;
|
|
21
26
|
export {};
|
|
22
27
|
//# sourceMappingURL=format.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/format.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,cAAc,EAEnB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,kBAAkB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,SAAS,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;CACnC,CAAC;AAEF,KAAK,SAAS,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;AAsE9C,wBAAgB,gBAAgB,CAC/B,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,GAAE,SAAc,GACvB,MAAM,CAER;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,GAAE,SAAc,GAAG,MAAM,CAElH;AAQD,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,GAAE,SAAc,GACvB,kBAAkB,GAAG,mBAAmB,CA2B1C"}
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/format.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,cAAc,EAEnB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,kBAAkB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,SAAS,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;CACnC,CAAC;AAEF,KAAK,SAAS,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;AAsE9C,wBAAgB,gBAAgB,CAC/B,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,GAAE,SAAc,GACvB,MAAM,CAER;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,GAAE,SAAc,GAAG,MAAM,CAElH;AAED,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAGpF;AAQD,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,GAAE,SAAc,GACvB,kBAAkB,GAAG,mBAAmB,CA2B1C"}
|
|
@@ -74,6 +74,10 @@ export function formatResultText(_variant, response, questions = []) {
|
|
|
74
74
|
export function formatUserMessage(response, requestId, questions = []) {
|
|
75
75
|
return `[Answer to question ${requestId}]\n${formatBody(response, questions)}`;
|
|
76
76
|
}
|
|
77
|
+
export function parseAskUserAnswerFrame(text) {
|
|
78
|
+
const match = /^\[Answer to question ([^\]\r\n]+)\]\r?\n([\s\S]*)$/.exec(text);
|
|
79
|
+
return match ? { requestId: match[1], body: match[2] } : undefined;
|
|
80
|
+
}
|
|
77
81
|
function selectedAnswers(answer) {
|
|
78
82
|
if (answer.selected.length > 0)
|
|
79
83
|
return answer.selected;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/format.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype AskUserVariant,\n\tDEFAULT_ASK_USER_TIMEOUT_MS,\n\ttype QuestionRequest,\n\ttype QuestionResponse,\n} from \"./schema.ts\";\n\nexport type CodexResultDetails = {\n\tanswers: Record<string, { answers: string[] }>;\n\tcomment?: string;\n\tunanswered: string[];\n\tstatus: QuestionResponse[\"status\"];\n};\n\nexport type ClaudeResultDetails = {\n\tquestions: QuestionRequest[\"questions\"];\n\tanswers: Record<string, string>;\n\tfreeText?: string;\n\tunanswered: string[];\n\tstatus: QuestionResponse[\"status\"];\n};\n\ntype Questions = QuestionRequest[\"questions\"];\n\nfunction headerFor(id: string, questions: Questions): string {\n\treturn questions.find((question) => question.id === id)?.header ?? id;\n}\n\nfunction questionTextFor(id: string, questions: Questions): string {\n\treturn questions.find((question) => question.id === id)?.question ?? id;\n}\n\nfunction answerBody(answer: { selected: string[]; text?: string } | undefined): string | undefined {\n\tif (!answer) return undefined;\n\tif (answer.selected.length > 0) return answer.selected.join(\", \");\n\tconst text = answer.text?.trim();\n\treturn text === undefined || text.length === 0 ? undefined : text;\n}\n\nfunction answeredLines(response: QuestionResponse, questions: Questions): string[] {\n\tconst lines: string[] = [];\n\tconst seen = new Set<string>();\n\tfor (const question of questions) {\n\t\tconst body = answerBody(response.answers[question.id]);\n\t\tif (body !== undefined) {\n\t\t\tlines.push(`${question.header}: ${body}`);\n\t\t\tseen.add(question.id);\n\t\t}\n\t}\n\tfor (const [id, answer] of Object.entries(response.answers)) {\n\t\tif (seen.has(id)) continue;\n\t\tconst body = answerBody(answer);\n\t\tif (body !== undefined) lines.push(`${headerFor(id, questions)}: ${body}`);\n\t}\n\treturn lines;\n}\n\nfunction formatBody(response: QuestionResponse, questions: Questions): string {\n\tswitch (response.status) {\n\t\tcase \"answered\": {\n\t\t\tconst lines = answeredLines(response, questions);\n\t\t\tconst unanswered = response.unanswered.map((id) => headerFor(id, questions));\n\t\t\tif (unanswered.length > 0) lines.push(`Unanswered: ${unanswered.join(\", \")}`);\n\t\t\treturn lines.join(\"\\n\");\n\t\t}\n\t\tcase \"comment-submitted\": {\n\t\t\tconst lines = [`The user responded: ${response.comment?.trim() ?? \"\"}`, ...answeredLines(response, questions)];\n\t\t\tconst unanswered = response.unanswered.map((id) => headerFor(id, questions));\n\t\t\tif (unanswered.length > 0) lines.push(`Unanswered: ${unanswered.join(\", \")}`);\n\t\t\treturn lines.join(\"\\n\");\n\t\t}\n\t\tcase \"timed_out\": {\n\t\t\tconst minutes = Math.round((response.autoResolvedAfterMs ?? DEFAULT_ASK_USER_TIMEOUT_MS) / 60_000);\n\t\t\tconst lines = [\n\t\t\t\t`The user did not answer within ${minutes} minutes. (사용자가 답변을 안하고 timeout 으로 종료됨)`,\n\t\t\t];\n\t\t\tconst selected = answeredLines(response, questions);\n\t\t\tif (selected.length > 0) {\n\t\t\t\tlines.push(`Before going idle the user had selected: ${selected.join(\"; \")}`);\n\t\t\t}\n\t\t\tlines.push(\"Continue the work to completion on your best judgment; do not ask this question again this turn.\");\n\t\t\treturn lines.join(\"\\n\");\n\t\t}\n\t\tcase \"cancelled\":\n\t\t\treturn \"The user dismissed the question.\";\n\t\tcase \"orphaned-after-restart\":\n\t\t\treturn \"The pending question could not be resumed after a restart; continue on best judgment.\";\n\t\tcase \"unavailable\":\n\t\t\treturn \"This session has no user attached (subagent or headless); decide on best judgment.\";\n\t}\n}\n\nexport function formatResultText(\n\t_variant: AskUserVariant,\n\tresponse: QuestionResponse,\n\tquestions: Questions = [],\n): string {\n\treturn formatBody(response, questions);\n}\n\nexport function formatUserMessage(response: QuestionResponse, requestId: string, questions: Questions = []): string {\n\treturn `[Answer to question ${requestId}]\\n${formatBody(response, questions)}`;\n}\n\nfunction selectedAnswers(answer: { selected: string[]; text?: string }): string[] {\n\tif (answer.selected.length > 0) return answer.selected;\n\tconst text = answer.text?.trim();\n\treturn text === undefined || text.length === 0 ? [] : [text];\n}\n\nexport function formatResultDetails(\n\tvariant: AskUserVariant,\n\tresponse: QuestionResponse,\n\tquestions: Questions = [],\n): CodexResultDetails | ClaudeResultDetails {\n\tif (variant === \"codex\") {\n\t\tconst answers: CodexResultDetails[\"answers\"] = {};\n\t\tfor (const [id, answer] of Object.entries(response.answers)) {\n\t\t\tanswers[id] = { answers: selectedAnswers(answer) };\n\t\t}\n\t\tconst details: CodexResultDetails = {\n\t\t\tanswers,\n\t\t\tunanswered: response.unanswered,\n\t\t\tstatus: response.status,\n\t\t};\n\t\tif (response.comment !== undefined) details.comment = response.comment;\n\t\treturn details;\n\t}\n\tconst answers: Record<string, string> = {};\n\tfor (const [id, answer] of Object.entries(response.answers)) {\n\t\tconst body = answerBody(answer);\n\t\tif (body !== undefined) answers[questionTextFor(id, questions)] = body;\n\t}\n\tconst details: ClaudeResultDetails = {\n\t\tquestions,\n\t\tanswers,\n\t\tunanswered: response.unanswered.map((id) => questionTextFor(id, questions)),\n\t\tstatus: response.status,\n\t};\n\tif (response.comment !== undefined) details.freeText = response.comment;\n\treturn details;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/format.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype AskUserVariant,\n\tDEFAULT_ASK_USER_TIMEOUT_MS,\n\ttype QuestionRequest,\n\ttype QuestionResponse,\n} from \"./schema.ts\";\n\nexport type CodexResultDetails = {\n\tanswers: Record<string, { answers: string[] }>;\n\tcomment?: string;\n\tunanswered: string[];\n\tstatus: QuestionResponse[\"status\"];\n};\n\nexport type ClaudeResultDetails = {\n\tquestions: QuestionRequest[\"questions\"];\n\tanswers: Record<string, string>;\n\tfreeText?: string;\n\tunanswered: string[];\n\tstatus: QuestionResponse[\"status\"];\n};\n\ntype Questions = QuestionRequest[\"questions\"];\n\nfunction headerFor(id: string, questions: Questions): string {\n\treturn questions.find((question) => question.id === id)?.header ?? id;\n}\n\nfunction questionTextFor(id: string, questions: Questions): string {\n\treturn questions.find((question) => question.id === id)?.question ?? id;\n}\n\nfunction answerBody(answer: { selected: string[]; text?: string } | undefined): string | undefined {\n\tif (!answer) return undefined;\n\tif (answer.selected.length > 0) return answer.selected.join(\", \");\n\tconst text = answer.text?.trim();\n\treturn text === undefined || text.length === 0 ? undefined : text;\n}\n\nfunction answeredLines(response: QuestionResponse, questions: Questions): string[] {\n\tconst lines: string[] = [];\n\tconst seen = new Set<string>();\n\tfor (const question of questions) {\n\t\tconst body = answerBody(response.answers[question.id]);\n\t\tif (body !== undefined) {\n\t\t\tlines.push(`${question.header}: ${body}`);\n\t\t\tseen.add(question.id);\n\t\t}\n\t}\n\tfor (const [id, answer] of Object.entries(response.answers)) {\n\t\tif (seen.has(id)) continue;\n\t\tconst body = answerBody(answer);\n\t\tif (body !== undefined) lines.push(`${headerFor(id, questions)}: ${body}`);\n\t}\n\treturn lines;\n}\n\nfunction formatBody(response: QuestionResponse, questions: Questions): string {\n\tswitch (response.status) {\n\t\tcase \"answered\": {\n\t\t\tconst lines = answeredLines(response, questions);\n\t\t\tconst unanswered = response.unanswered.map((id) => headerFor(id, questions));\n\t\t\tif (unanswered.length > 0) lines.push(`Unanswered: ${unanswered.join(\", \")}`);\n\t\t\treturn lines.join(\"\\n\");\n\t\t}\n\t\tcase \"comment-submitted\": {\n\t\t\tconst lines = [`The user responded: ${response.comment?.trim() ?? \"\"}`, ...answeredLines(response, questions)];\n\t\t\tconst unanswered = response.unanswered.map((id) => headerFor(id, questions));\n\t\t\tif (unanswered.length > 0) lines.push(`Unanswered: ${unanswered.join(\", \")}`);\n\t\t\treturn lines.join(\"\\n\");\n\t\t}\n\t\tcase \"timed_out\": {\n\t\t\tconst minutes = Math.round((response.autoResolvedAfterMs ?? DEFAULT_ASK_USER_TIMEOUT_MS) / 60_000);\n\t\t\tconst lines = [\n\t\t\t\t`The user did not answer within ${minutes} minutes. (사용자가 답변을 안하고 timeout 으로 종료됨)`,\n\t\t\t];\n\t\t\tconst selected = answeredLines(response, questions);\n\t\t\tif (selected.length > 0) {\n\t\t\t\tlines.push(`Before going idle the user had selected: ${selected.join(\"; \")}`);\n\t\t\t}\n\t\t\tlines.push(\"Continue the work to completion on your best judgment; do not ask this question again this turn.\");\n\t\t\treturn lines.join(\"\\n\");\n\t\t}\n\t\tcase \"cancelled\":\n\t\t\treturn \"The user dismissed the question.\";\n\t\tcase \"orphaned-after-restart\":\n\t\t\treturn \"The pending question could not be resumed after a restart; continue on best judgment.\";\n\t\tcase \"unavailable\":\n\t\t\treturn \"This session has no user attached (subagent or headless); decide on best judgment.\";\n\t}\n}\n\nexport function formatResultText(\n\t_variant: AskUserVariant,\n\tresponse: QuestionResponse,\n\tquestions: Questions = [],\n): string {\n\treturn formatBody(response, questions);\n}\n\nexport function formatUserMessage(response: QuestionResponse, requestId: string, questions: Questions = []): string {\n\treturn `[Answer to question ${requestId}]\\n${formatBody(response, questions)}`;\n}\n\nexport interface AskUserAnswerFrame {\n\treadonly requestId: string;\n\treadonly body: string;\n}\n\nexport function parseAskUserAnswerFrame(text: string): AskUserAnswerFrame | undefined {\n\tconst match = /^\\[Answer to question ([^\\]\\r\\n]+)\\]\\r?\\n([\\s\\S]*)$/.exec(text);\n\treturn match ? { requestId: match[1], body: match[2] } : undefined;\n}\n\nfunction selectedAnswers(answer: { selected: string[]; text?: string }): string[] {\n\tif (answer.selected.length > 0) return answer.selected;\n\tconst text = answer.text?.trim();\n\treturn text === undefined || text.length === 0 ? [] : [text];\n}\n\nexport function formatResultDetails(\n\tvariant: AskUserVariant,\n\tresponse: QuestionResponse,\n\tquestions: Questions = [],\n): CodexResultDetails | ClaudeResultDetails {\n\tif (variant === \"codex\") {\n\t\tconst answers: CodexResultDetails[\"answers\"] = {};\n\t\tfor (const [id, answer] of Object.entries(response.answers)) {\n\t\t\tanswers[id] = { answers: selectedAnswers(answer) };\n\t\t}\n\t\tconst details: CodexResultDetails = {\n\t\t\tanswers,\n\t\t\tunanswered: response.unanswered,\n\t\t\tstatus: response.status,\n\t\t};\n\t\tif (response.comment !== undefined) details.comment = response.comment;\n\t\treturn details;\n\t}\n\tconst answers: Record<string, string> = {};\n\tfor (const [id, answer] of Object.entries(response.answers)) {\n\t\tconst body = answerBody(answer);\n\t\tif (body !== undefined) answers[questionTextFor(id, questions)] = body;\n\t}\n\tconst details: ClaudeResultDetails = {\n\t\tquestions,\n\t\tanswers,\n\t\tunanswered: response.unanswered.map((id) => questionTextFor(id, questions)),\n\t\tstatus: response.status,\n\t};\n\tif (response.comment !== undefined) details.freeText = response.comment;\n\treturn details;\n}\n"]}
|
|
@@ -4,6 +4,8 @@ export declare const ASK_USER_SETTLED_EVENT = "ask-user:settled";
|
|
|
4
4
|
export declare const ASK_USER_ASKED_EVENT = "ask-user:asked";
|
|
5
5
|
/** UI-only session metadata; never included in the model-facing answer frame. */
|
|
6
6
|
export declare const ASK_USER_QUESTION_ENTRY = "ask-user:question";
|
|
7
|
+
/** Durable terminal outcome, including silent cancellation, for restart recovery. */
|
|
8
|
+
export declare const ASK_USER_SETTLEMENT_ENTRY = "ask-user:settlement";
|
|
7
9
|
export interface AskUserQuestionEntry {
|
|
8
10
|
readonly requestId: string;
|
|
9
11
|
readonly headers: readonly string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAErF,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AACrD,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAC3D,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;CACjC,CAAC;AAEF,qFAAqF;AACrF,wBAAgB,uBAAuB,CACtC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAChC,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,cAAc,GACrB,IAAI,CAGN"}
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAErF,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AACrD,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAC3D,qFAAqF;AACrF,eAAO,MAAM,yBAAyB,wBAAwB,CAAC;AAC/D,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;CACjC,CAAC;AAEF,qFAAqF;AACrF,wBAAgB,uBAAuB,CACtC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAChC,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,cAAc,GACrB,IAAI,CAGN"}
|
|
@@ -2,6 +2,8 @@ export const ASK_USER_SETTLED_EVENT = "ask-user:settled";
|
|
|
2
2
|
export const ASK_USER_ASKED_EVENT = "ask-user:asked";
|
|
3
3
|
/** UI-only session metadata; never included in the model-facing answer frame. */
|
|
4
4
|
export const ASK_USER_QUESTION_ENTRY = "ask-user:question";
|
|
5
|
+
/** Durable terminal outcome, including silent cancellation, for restart recovery. */
|
|
6
|
+
export const ASK_USER_SETTLEMENT_ENTRY = "ask-user:settlement";
|
|
5
7
|
/** Publish only; the active hooks builtin owns preparation and command execution. */
|
|
6
8
|
export function emitAskUserNotification(pi, ctx, request, response, variant) {
|
|
7
9
|
if (response.status === "cancelled")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/notify.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AACrD,iFAAiF;AACjF,MAAM,CAAC,MAAM,uBAAuB,GAAG,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/notify.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AACrD,iFAAiF;AACjF,MAAM,CAAC,MAAM,uBAAuB,GAAG,mBAAmB,CAAC;AAC3D,qFAAqF;AACrF,MAAM,CAAC,MAAM,yBAAyB,GAAG,qBAAqB,CAAC;AAmB/D,qFAAqF;AACrF,MAAM,UAAU,uBAAuB,CACtC,EAAgC,EAChC,GAAqB,EACrB,OAAwB,EACxB,QAA0B,EAC1B,OAAuB;IAEvB,IAAI,QAAQ,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO;IAC5C,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAgC,CAAC,CAAC;AAC3G,CAAC","sourcesContent":["import type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport type { AskUserVariant, QuestionRequest, QuestionResponse } from \"./schema.ts\";\n\nexport const ASK_USER_SETTLED_EVENT = \"ask-user:settled\";\nexport const ASK_USER_ASKED_EVENT = \"ask-user:asked\";\n/** UI-only session metadata; never included in the model-facing answer frame. */\nexport const ASK_USER_QUESTION_ENTRY = \"ask-user:question\";\n/** Durable terminal outcome, including silent cancellation, for restart recovery. */\nexport const ASK_USER_SETTLEMENT_ENTRY = \"ask-user:settlement\";\nexport interface AskUserQuestionEntry {\n\treadonly requestId: string;\n\treadonly headers: readonly string[];\n}\n\nexport type AskUserAskedEvent = {\n\treadonly ctx: ExtensionContext;\n\treadonly request: QuestionRequest;\n\treadonly variant: AskUserVariant;\n};\n\nexport type AskUserSettledEvent = {\n\treadonly ctx: ExtensionContext;\n\treadonly request: QuestionRequest;\n\treadonly response: QuestionResponse;\n\treadonly variant: AskUserVariant;\n};\n\n/** Publish only; the active hooks builtin owns preparation and command execution. */\nexport function emitAskUserNotification(\n\tpi: Pick<ExtensionAPI, \"events\">,\n\tctx: ExtensionContext,\n\trequest: QuestionRequest,\n\tresponse: QuestionResponse,\n\tvariant: AskUserVariant,\n): void {\n\tif (response.status === \"cancelled\") return;\n\tpi.events.emit(ASK_USER_SETTLED_EVENT, { ctx, request, response, variant } satisfies AskUserSettledEvent);\n}\n"]}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import type { ExtensionUIDialogOptions } from "../../types.ts";
|
|
1
|
+
import type { ExtensionAPI, ExtensionContext, ExtensionUIDialogOptions } from "../../types.ts";
|
|
2
2
|
import type { PendingQuestion } from "./pending.ts";
|
|
3
3
|
import type { QuestionRequest, QuestionResponse } from "./schema.ts";
|
|
4
|
+
import type { AskUserState } from "./tool.ts";
|
|
4
5
|
/** Additive options consumed by question-capable UI bridges. Delivery belongs to the UI. */
|
|
5
6
|
export interface QuestionDialogOptions extends ExtensionUIDialogOptions {
|
|
6
7
|
deliver: "tool-result" | "user-message";
|
|
7
8
|
hardDeadlineAtMs: number;
|
|
8
9
|
/** Live absolute idle deadline; question UI countdowns are display-only when supplied. */
|
|
9
10
|
getDeadlineAtMs?: () => number;
|
|
11
|
+
initialDraft?: {
|
|
12
|
+
answers: QuestionResponse["answers"];
|
|
13
|
+
comment?: string;
|
|
14
|
+
};
|
|
10
15
|
onProgress: (draft: {
|
|
11
16
|
answers?: QuestionResponse["answers"];
|
|
12
17
|
comment?: string;
|
|
@@ -16,8 +21,16 @@ export interface PendingQuestionEntry {
|
|
|
16
21
|
request: QuestionRequest;
|
|
17
22
|
pending: PendingQuestion;
|
|
18
23
|
completion: Promise<QuestionResponse>;
|
|
19
|
-
cancel(message?: string): void;
|
|
24
|
+
cancel(message?: string, reportDetachedLoss?: boolean): void;
|
|
25
|
+
detach(): void;
|
|
26
|
+
rebind(pi: ExtensionAPI, ctx: ExtensionContext, state: AskUserState): void;
|
|
27
|
+
reattach(): void;
|
|
20
28
|
}
|
|
29
|
+
type QueuedOutcome = (pi: ExtensionAPI, ctx: ExtensionContext) => void;
|
|
30
|
+
/** A terminal request awaiting a live runner is no longer a pending question. */
|
|
31
|
+
export declare function queueQuestionOutcome(sessionId: string, outcome: QueuedOutcome): void;
|
|
32
|
+
export declare function deliverQueuedQuestionOutcomes(sessionId: string, pi: ExtensionAPI, ctx: ExtensionContext): void;
|
|
21
33
|
export declare function getPendingQuestions(sessionId: string): readonly PendingQuestionEntry[];
|
|
22
34
|
export declare function registerPendingQuestion(sessionId: string, entry: PendingQuestionEntry): () => void;
|
|
35
|
+
export {};
|
|
23
36
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC/
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,4FAA4F;AAC5F,MAAM,WAAW,qBAAsB,SAAQ,wBAAwB;IACtE,OAAO,EAAE,aAAa,GAAG,cAAc,CAAC;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,0FAA0F;IAC1F,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE;QAAE,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1E,UAAU,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,CAAC,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACzF;AACD,MAAM,WAAW,oBAAoB;IACpC,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,eAAe,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACtC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,kBAAkB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7D,MAAM,IAAI,IAAI,CAAC;IACf,MAAM,CAAC,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,gBAAgB,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3E,QAAQ,IAAI,IAAI,CAAC;CACjB;AAED,KAAK,aAAa,GAAG,CAAC,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAGvE,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAIpF;AAED,wBAAgB,6BAA6B,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAI9G;AACD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,oBAAoB,EAAE,CAEtF;AACD,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,oBAAoB,GAAG,MAAM,IAAI,CAYlG"}
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
const sessions = new Map();
|
|
2
|
+
const outcomes = new Map();
|
|
3
|
+
/** A terminal request awaiting a live runner is no longer a pending question. */
|
|
4
|
+
export function queueQuestionOutcome(sessionId, outcome) {
|
|
5
|
+
const queued = outcomes.get(sessionId) ?? [];
|
|
6
|
+
queued.push(outcome);
|
|
7
|
+
outcomes.set(sessionId, queued);
|
|
8
|
+
}
|
|
9
|
+
export function deliverQueuedQuestionOutcomes(sessionId, pi, ctx) {
|
|
10
|
+
const queued = outcomes.get(sessionId) ?? [];
|
|
11
|
+
outcomes.delete(sessionId);
|
|
12
|
+
for (const outcome of queued)
|
|
13
|
+
outcome(pi, ctx);
|
|
14
|
+
}
|
|
2
15
|
export function getPendingQuestions(sessionId) {
|
|
3
16
|
return [...(sessions.get(sessionId)?.values() ?? [])];
|
|
4
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/registry.ts"],"names":[],"mappings":"AAuBA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA6C,CAAC;AAEtE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEpD,iFAAiF;AACjF,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,OAAsB;IAC7E,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,SAAiB,EAAE,EAAgB,EAAE,GAAqB;IACvG,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IAC7C,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3B,KAAK,MAAM,OAAO,IAAI,MAAM;QAAE,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AAChD,CAAC;AACD,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACpD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvD,CAAC;AACD,MAAM,UAAU,uBAAuB,CAAC,SAAiB,EAAE,KAA2B;IACrF,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QACpB,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC5C,OAAO,GAAG,EAAE;QACX,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,KAAK;YAAE,OAAO;QAC3D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;YAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC,CAAC;AACH,CAAC","sourcesContent":["import type { ExtensionAPI, ExtensionContext, ExtensionUIDialogOptions } from \"../../types.ts\";\nimport type { PendingQuestion } from \"./pending.ts\";\nimport type { QuestionRequest, QuestionResponse } from \"./schema.ts\";\nimport type { AskUserState } from \"./tool.ts\";\n\n/** Additive options consumed by question-capable UI bridges. Delivery belongs to the UI. */\nexport interface QuestionDialogOptions extends ExtensionUIDialogOptions {\n\tdeliver: \"tool-result\" | \"user-message\";\n\thardDeadlineAtMs: number;\n\t/** Live absolute idle deadline; question UI countdowns are display-only when supplied. */\n\tgetDeadlineAtMs?: () => number;\n\tinitialDraft?: { answers: QuestionResponse[\"answers\"]; comment?: string };\n\tonProgress: (draft: { answers?: QuestionResponse[\"answers\"]; comment?: string }) => void;\n}\nexport interface PendingQuestionEntry {\n\trequest: QuestionRequest;\n\tpending: PendingQuestion;\n\tcompletion: Promise<QuestionResponse>;\n\tcancel(message?: string, reportDetachedLoss?: boolean): void;\n\tdetach(): void;\n\trebind(pi: ExtensionAPI, ctx: ExtensionContext, state: AskUserState): void;\n\treattach(): void;\n}\nconst sessions = new Map<string, Map<string, PendingQuestionEntry>>();\ntype QueuedOutcome = (pi: ExtensionAPI, ctx: ExtensionContext) => void;\nconst outcomes = new Map<string, QueuedOutcome[]>();\n\n/** A terminal request awaiting a live runner is no longer a pending question. */\nexport function queueQuestionOutcome(sessionId: string, outcome: QueuedOutcome): void {\n\tconst queued = outcomes.get(sessionId) ?? [];\n\tqueued.push(outcome);\n\toutcomes.set(sessionId, queued);\n}\n\nexport function deliverQueuedQuestionOutcomes(sessionId: string, pi: ExtensionAPI, ctx: ExtensionContext): void {\n\tconst queued = outcomes.get(sessionId) ?? [];\n\toutcomes.delete(sessionId);\n\tfor (const outcome of queued) outcome(pi, ctx);\n}\nexport function getPendingQuestions(sessionId: string): readonly PendingQuestionEntry[] {\n\treturn [...(sessions.get(sessionId)?.values() ?? [])];\n}\nexport function registerPendingQuestion(sessionId: string, entry: PendingQuestionEntry): () => void {\n\tlet entries = sessions.get(sessionId);\n\tif (!entries) {\n\t\tentries = new Map();\n\t\tsessions.set(sessionId, entries);\n\t}\n\tentries.set(entry.request.requestId, entry);\n\treturn () => {\n\t\tif (entries.get(entry.request.requestId) !== entry) return;\n\t\tentries.delete(entry.request.requestId);\n\t\tif (entries.size === 0) sessions.delete(sessionId);\n\t};\n}\n"]}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { ToolDefinition } from "../../types.ts";
|
|
2
2
|
export declare const renderCall: NonNullable<ToolDefinition["renderCall"]>;
|
|
3
3
|
export declare const renderResult: NonNullable<ToolDefinition["renderResult"]>;
|
|
4
|
+
/**
|
|
5
|
+
* Renderers for a question card whose tool definition is not resolvable: the tools are registered
|
|
6
|
+
* when the session synchronizes them, so a card streamed while a reload is in flight - or replayed
|
|
7
|
+
* in a session where ask-user is disabled - would otherwise fall back to a raw argument dump.
|
|
8
|
+
*/
|
|
9
|
+
export declare function askUserRenderers(toolName: string): Pick<ToolDefinition, "renderCall" | "renderResult"> | undefined;
|
|
4
10
|
//# sourceMappingURL=render.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC,cAAc,CAAC,YAAY,CAAC,CAchE,CAAC;AACF,eAAO,MAAM,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,cAAc,CAAC,CAepE,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,YAAY,GAAG,cAAc,CAAC,GAAG,SAAS,CAElH"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Text } from "@earendil-works/pi-tui";
|
|
2
|
+
import { TOOL_NAMES } from "./family.js";
|
|
2
3
|
export const renderCall = (args, theme) => {
|
|
3
4
|
const values = typeof args === "object" && args !== null ? args : {};
|
|
4
5
|
const headers = "questions" in values && Array.isArray(values.questions)
|
|
@@ -22,4 +23,12 @@ export const renderResult = (result) => {
|
|
|
22
23
|
}
|
|
23
24
|
return new Text([summary, ...result.content.flatMap((c) => (c.type === "text" ? [c.text] : []))].filter(Boolean).join("\n"), 0, 0);
|
|
24
25
|
};
|
|
26
|
+
/**
|
|
27
|
+
* Renderers for a question card whose tool definition is not resolvable: the tools are registered
|
|
28
|
+
* when the session synchronizes them, so a card streamed while a reload is in flight - or replayed
|
|
29
|
+
* in a session where ask-user is disabled - would otherwise fall back to a raw argument dump.
|
|
30
|
+
*/
|
|
31
|
+
export function askUserRenderers(toolName) {
|
|
32
|
+
return Object.values(TOOL_NAMES).includes(toolName) ? { renderCall, renderResult } : undefined;
|
|
33
|
+
}
|
|
25
34
|
//# sourceMappingURL=render.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,CAAC,MAAM,UAAU,GAA8C,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;IACpF,MAAM,MAAM,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,MAAM,OAAO,GACZ,WAAW,IAAI,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;QACvD,CAAC,CAAC,MAAM,CAAC,SAAS;aACf,GAAG,CAAC,CAAC,CAAU,EAAE,EAAE,CACnB,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY,CACrF;aACA,IAAI,CAAC,GAAG,CAAC;QACZ,CAAC,CAAC,UAAU,CAAC;IACf,MAAM,IAAI,GACT,CAAC,eAAe,IAAI,MAAM,IAAI,MAAM,CAAC,aAAa,KAAK,IAAI,CAAC;QAC5D,CAAC,iBAAiB,IAAI,MAAM,IAAI,MAAM,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC;IAClE,OAAO,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACzG,CAAC,CAAC;AACF,MAAM,CAAC,MAAM,YAAY,GAAgD,CAAC,MAAM,EAAE,EAAE;IACnF,MAAM,OAAO,GAAY,MAAM,CAAC,OAAO,CAAC;IACxC,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC5E,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,SAAS,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI;YAC1F,OAAO,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,WAAW,CAAC;QAChE,IAAI,YAAY,IAAI,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC;YAC/D,OAAO,IAAI,KAAK,OAAO,CAAC,UAAU,CAAC,MAAM,aAAa,CAAC;IACzD,CAAC;IACD,OAAO,IAAI,IAAI,CACd,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAC3G,CAAC,EACD,CAAC,CACD,CAAC;AACH,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAChD,OAAO,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAChG,CAAC","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport type { ToolDefinition } from \"../../types.ts\";\nimport { TOOL_NAMES } from \"./family.ts\";\n\nexport const renderCall: NonNullable<ToolDefinition[\"renderCall\"]> = (args, theme) => {\n\tconst values = typeof args === \"object\" && args !== null ? args : {};\n\tconst headers =\n\t\t\"questions\" in values && Array.isArray(values.questions)\n\t\t\t? values.questions\n\t\t\t\t\t.map((q: unknown) =>\n\t\t\t\t\t\ttypeof q === \"object\" && q !== null && \"header\" in q ? `[${q.header}]` : \"[Question]\",\n\t\t\t\t\t)\n\t\t\t\t\t.join(\" \")\n\t\t\t: \"Question\";\n\tconst wait =\n\t\t(\"waitForAnswer\" in values && values.waitForAnswer === true) ||\n\t\t(\"wait_for_answer\" in values && values.wait_for_answer === true);\n\treturn new Text(`${theme.fg(\"toolTitle\", headers)} ${wait ? \"wait for answer\" : \"answer later\"}`, 0, 0);\n};\nexport const renderResult: NonNullable<ToolDefinition[\"renderResult\"]> = (result) => {\n\tconst details: unknown = result.details;\n\tlet summary = \"\";\n\tif (typeof details === \"object\" && details !== null && \"status\" in details) {\n\t\tsummary = String(details.status);\n\t\tif (\"answers\" in details && typeof details.answers === \"object\" && details.answers !== null)\n\t\t\tsummary += `; ${Object.keys(details.answers).length} answered`;\n\t\tif (\"unanswered\" in details && Array.isArray(details.unanswered))\n\t\t\tsummary += `; ${details.unanswered.length} unanswered`;\n\t}\n\treturn new Text(\n\t\t[summary, ...result.content.flatMap((c) => (c.type === \"text\" ? [c.text] : []))].filter(Boolean).join(\"\\n\"),\n\t\t0,\n\t\t0,\n\t);\n};\n\n/**\n * Renderers for a question card whose tool definition is not resolvable: the tools are registered\n * when the session synchronizes them, so a card streamed while a reload is in flight - or replayed\n * in a session where ask-user is disabled - would otherwise fall back to a raw argument dump.\n */\nexport function askUserRenderers(toolName: string): Pick<ToolDefinition, \"renderCall\" | \"renderResult\"> | undefined {\n\treturn Object.values(TOOL_NAMES).includes(toolName) ? { renderCall, renderResult } : undefined;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/resume.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/resume.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAQxF,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AA0FzD,wBAAsB,sBAAsB,CAC3C,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,aAAa,GAAG,iBAAiB,GAAG,QAAQ,CAAC,EACpE,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,EACxC,GAAG,EAAE,gBAAgB,GACnB,OAAO,CAAC,IAAI,CAAC,CAgBf"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { TOOL_NAMES } from "./family.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { parseAskUserAnswerFrame } from "./format.js";
|
|
3
|
+
import { ASK_USER_SETTLEMENT_ENTRY } from "./notify.js";
|
|
4
|
+
import { getPendingQuestions } from "./registry.js";
|
|
5
|
+
import { DEFAULT_ASK_USER_TIMEOUT_MS, toCanonical } from "./schema.js";
|
|
5
6
|
import { startQuestion } from "./tool.js";
|
|
6
7
|
export const ASK_USER_RESUMED_ENTRY = "ask-user:resumed";
|
|
7
8
|
function isRecord(value) {
|
|
@@ -14,10 +15,23 @@ function variantFor(name) {
|
|
|
14
15
|
return "codex";
|
|
15
16
|
return undefined;
|
|
16
17
|
}
|
|
17
|
-
function
|
|
18
|
+
function findDanglingQuestions(entries) {
|
|
18
19
|
const results = new Set();
|
|
20
|
+
const accepted = new Set();
|
|
19
21
|
const resumed = new Set();
|
|
22
|
+
const settled = new Set();
|
|
20
23
|
for (const entry of entries) {
|
|
24
|
+
if (entry.type === "message" && entry.message.role === "user") {
|
|
25
|
+
const content = entry.message.content;
|
|
26
|
+
const texts = typeof content === "string"
|
|
27
|
+
? [content]
|
|
28
|
+
: content.flatMap((part) => (part.type === "text" ? [part.text] : []));
|
|
29
|
+
for (const text of texts) {
|
|
30
|
+
const frame = parseAskUserAnswerFrame(text);
|
|
31
|
+
if (frame)
|
|
32
|
+
settled.add(frame.requestId);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
21
35
|
if (entry.type === "custom" && entry.customType === ASK_USER_RESUMED_ENTRY && isRecord(entry.data)) {
|
|
22
36
|
const toolCallId = entry.data.toolCallId;
|
|
23
37
|
if (typeof toolCallId === "string")
|
|
@@ -25,8 +39,18 @@ function findDanglingQuestion(entries) {
|
|
|
25
39
|
}
|
|
26
40
|
if (entry.type === "message" && entry.message.role === "toolResult") {
|
|
27
41
|
results.add(entry.message.toolCallId);
|
|
42
|
+
const details = entry.message.details;
|
|
43
|
+
if (!entry.message.isError && isRecord(details) && details.accepted === true && details.status === "pending") {
|
|
44
|
+
accepted.add(entry.message.toolCallId);
|
|
45
|
+
}
|
|
28
46
|
}
|
|
47
|
+
if (entry.type === "custom" &&
|
|
48
|
+
entry.customType === ASK_USER_SETTLEMENT_ENTRY &&
|
|
49
|
+
isRecord(entry.data) &&
|
|
50
|
+
typeof entry.data.requestId === "string")
|
|
51
|
+
settled.add(entry.data.requestId);
|
|
29
52
|
}
|
|
53
|
+
const dangling = [];
|
|
30
54
|
for (let index = entries.length - 1; index >= 0; index--) {
|
|
31
55
|
const entry = entries[index];
|
|
32
56
|
if (entry?.type !== "message" || entry.message.role !== "assistant")
|
|
@@ -37,39 +61,50 @@ function findDanglingQuestion(entries) {
|
|
|
37
61
|
if (block?.type !== "toolCall" || block.incomplete === true)
|
|
38
62
|
continue;
|
|
39
63
|
const variant = variantFor(block.name);
|
|
40
|
-
if (!variant ||
|
|
64
|
+
if (!variant || settled.has(block.id))
|
|
65
|
+
continue;
|
|
66
|
+
const call = { toolCallId: block.id, variant, args: block.arguments };
|
|
67
|
+
const request = requestFromCall(call, DEFAULT_ASK_USER_TIMEOUT_MS);
|
|
68
|
+
if (results.has(block.id) && (request.waitForAnswer || !accepted.has(block.id)))
|
|
69
|
+
continue;
|
|
70
|
+
if (resumed.has(block.id))
|
|
41
71
|
continue;
|
|
42
|
-
|
|
72
|
+
dangling.push(call);
|
|
43
73
|
}
|
|
44
74
|
}
|
|
45
|
-
return
|
|
75
|
+
return dangling;
|
|
46
76
|
}
|
|
47
77
|
function requestFromCall(dangling, timeoutMs) {
|
|
48
78
|
try {
|
|
49
|
-
return toCanonical(dangling.variant, dangling.args, {
|
|
79
|
+
return toCanonical(dangling.variant, dangling.args, {
|
|
80
|
+
requestId: dangling.toolCallId,
|
|
81
|
+
timeoutMs,
|
|
82
|
+
});
|
|
50
83
|
}
|
|
51
84
|
catch {
|
|
52
|
-
return {
|
|
85
|
+
return {
|
|
86
|
+
requestId: dangling.toolCallId,
|
|
87
|
+
questions: [],
|
|
88
|
+
waitForAnswer: false,
|
|
89
|
+
timeoutMs,
|
|
90
|
+
};
|
|
53
91
|
}
|
|
54
92
|
}
|
|
55
|
-
function deliver(pi, ctx, request, response, variant) {
|
|
56
|
-
if (response.status === "cancelled")
|
|
57
|
-
return;
|
|
58
|
-
pi.sendUserMessage(formatUserMessage(response, request.requestId, request.questions));
|
|
59
|
-
emitAskUserNotification(pi, ctx, request, response, variant);
|
|
60
|
-
}
|
|
61
93
|
export async function resumeDanglingQuestion(pi, event, ctx) {
|
|
62
94
|
if (event.reason !== "resume" && event.reason !== "reload")
|
|
63
95
|
return;
|
|
64
|
-
const
|
|
65
|
-
if (!dangling)
|
|
66
|
-
return;
|
|
67
|
-
pi.appendEntry(ASK_USER_RESUMED_ENTRY, { toolCallId: dangling.toolCallId });
|
|
96
|
+
const pending = new Set(getPendingQuestions(ctx.sessionManager.getSessionId()).map((entry) => entry.request.requestId));
|
|
68
97
|
const timeoutMs = (ctx.getAskUserSettings?.().timeoutMinutes ?? DEFAULT_ASK_USER_TIMEOUT_MS / 60_000) * 60_000;
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
98
|
+
for (const dangling of findDanglingQuestions(ctx.sessionManager.getBranch())) {
|
|
99
|
+
if (pending.has(dangling.toolCallId))
|
|
100
|
+
continue;
|
|
101
|
+
pending.add(dangling.toolCallId);
|
|
102
|
+
pi.appendEntry(ASK_USER_RESUMED_ENTRY, { toolCallId: dangling.toolCallId });
|
|
103
|
+
const request = requestFromCall(dangling, timeoutMs);
|
|
104
|
+
// The runtime registration owns delivery, including after another reload.
|
|
105
|
+
void startQuestion(pi, ctx, request, ctx.signal, { timedOut: false, unavailable: false }, dangling.variant, {
|
|
106
|
+
resuming: true,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
74
109
|
}
|
|
75
110
|
//# sourceMappingURL=resume.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/resume.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/resume.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SessionEntry } from \"../../../session-manager.ts\";\nimport type { ExtensionAPI, ExtensionContext, SessionStartEvent } from \"../../types.ts\";\nimport { TOOL_NAMES } from \"./family.ts\";\nimport { parseAskUserAnswerFrame } from \"./format.ts\";\nimport { ASK_USER_SETTLEMENT_ENTRY } from \"./notify.ts\";\nimport { getPendingQuestions } from \"./registry.ts\";\nimport { type AskUserVariant, DEFAULT_ASK_USER_TIMEOUT_MS, type QuestionRequest, toCanonical } from \"./schema.ts\";\nimport { startQuestion } from \"./tool.ts\";\n\nexport const ASK_USER_RESUMED_ENTRY = \"ask-user:resumed\";\n\ntype DanglingQuestion = {\n\ttoolCallId: string;\n\tvariant: AskUserVariant;\n\targs: unknown;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction variantFor(name: string): AskUserVariant | undefined {\n\tif (name === TOOL_NAMES.claude) return \"claude\";\n\tif (name === TOOL_NAMES.codex) return \"codex\";\n\treturn undefined;\n}\n\nfunction findDanglingQuestions(entries: readonly SessionEntry[]): DanglingQuestion[] {\n\tconst results = new Set<string>();\n\tconst accepted = new Set<string>();\n\tconst resumed = new Set<string>();\n\tconst settled = new Set<string>();\n\tfor (const entry of entries) {\n\t\tif (entry.type === \"message\" && entry.message.role === \"user\") {\n\t\t\tconst content = entry.message.content;\n\t\t\tconst texts =\n\t\t\t\ttypeof content === \"string\"\n\t\t\t\t\t? [content]\n\t\t\t\t\t: content.flatMap((part) => (part.type === \"text\" ? [part.text] : []));\n\t\t\tfor (const text of texts) {\n\t\t\t\tconst frame = parseAskUserAnswerFrame(text);\n\t\t\t\tif (frame) settled.add(frame.requestId);\n\t\t\t}\n\t\t}\n\t\tif (entry.type === \"custom\" && entry.customType === ASK_USER_RESUMED_ENTRY && isRecord(entry.data)) {\n\t\t\tconst toolCallId = entry.data.toolCallId;\n\t\t\tif (typeof toolCallId === \"string\") resumed.add(toolCallId);\n\t\t}\n\t\tif (entry.type === \"message\" && entry.message.role === \"toolResult\") {\n\t\t\tresults.add(entry.message.toolCallId);\n\t\t\tconst details = entry.message.details;\n\t\t\tif (!entry.message.isError && isRecord(details) && details.accepted === true && details.status === \"pending\") {\n\t\t\t\taccepted.add(entry.message.toolCallId);\n\t\t\t}\n\t\t}\n\t\tif (\n\t\t\tentry.type === \"custom\" &&\n\t\t\tentry.customType === ASK_USER_SETTLEMENT_ENTRY &&\n\t\t\tisRecord(entry.data) &&\n\t\t\ttypeof entry.data.requestId === \"string\"\n\t\t)\n\t\t\tsettled.add(entry.data.requestId);\n\t}\n\tconst dangling: DanglingQuestion[] = [];\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry?.type !== \"message\" || entry.message.role !== \"assistant\") continue;\n\t\tconst content = entry.message.content;\n\t\tfor (let blockIndex = content.length - 1; blockIndex >= 0; blockIndex--) {\n\t\t\tconst block = content[blockIndex];\n\t\t\tif (block?.type !== \"toolCall\" || block.incomplete === true) continue;\n\t\t\tconst variant = variantFor(block.name);\n\t\t\tif (!variant || settled.has(block.id)) continue;\n\t\t\tconst call = { toolCallId: block.id, variant, args: block.arguments };\n\t\t\tconst request = requestFromCall(call, DEFAULT_ASK_USER_TIMEOUT_MS);\n\t\t\tif (results.has(block.id) && (request.waitForAnswer || !accepted.has(block.id))) continue;\n\t\t\tif (resumed.has(block.id)) continue;\n\t\t\tdangling.push(call);\n\t\t}\n\t}\n\treturn dangling;\n}\n\nfunction requestFromCall(dangling: DanglingQuestion, timeoutMs: number): QuestionRequest {\n\ttry {\n\t\treturn toCanonical(dangling.variant, dangling.args, {\n\t\t\trequestId: dangling.toolCallId,\n\t\t\ttimeoutMs,\n\t\t});\n\t} catch {\n\t\treturn {\n\t\t\trequestId: dangling.toolCallId,\n\t\t\tquestions: [],\n\t\t\twaitForAnswer: false,\n\t\t\ttimeoutMs,\n\t\t};\n\t}\n}\n\nexport async function resumeDanglingQuestion(\n\tpi: Pick<ExtensionAPI, \"appendEntry\" | \"sendUserMessage\" | \"events\">,\n\tevent: Pick<SessionStartEvent, \"reason\">,\n\tctx: ExtensionContext,\n): Promise<void> {\n\tif (event.reason !== \"resume\" && event.reason !== \"reload\") return;\n\tconst pending = new Set(\n\t\tgetPendingQuestions(ctx.sessionManager.getSessionId()).map((entry) => entry.request.requestId),\n\t);\n\tconst timeoutMs = (ctx.getAskUserSettings?.().timeoutMinutes ?? DEFAULT_ASK_USER_TIMEOUT_MS / 60_000) * 60_000;\n\tfor (const dangling of findDanglingQuestions(ctx.sessionManager.getBranch())) {\n\t\tif (pending.has(dangling.toolCallId)) continue;\n\t\tpending.add(dangling.toolCallId);\n\t\tpi.appendEntry(ASK_USER_RESUMED_ENTRY, { toolCallId: dangling.toolCallId });\n\t\tconst request = requestFromCall(dangling, timeoutMs);\n\t\t// The runtime registration owns delivery, including after another reload.\n\t\tvoid startQuestion(pi, ctx, request, ctx.signal, { timedOut: false, unavailable: false }, dangling.variant, {\n\t\t\tresuming: true,\n\t\t});\n\t}\n}\n"]}
|
|
@@ -4,7 +4,7 @@ export interface AskUserState {
|
|
|
4
4
|
timedOut: boolean;
|
|
5
5
|
unavailable: boolean;
|
|
6
6
|
}
|
|
7
|
-
export declare function startQuestion(
|
|
7
|
+
export declare function startQuestion(initialPi: Pick<ExtensionAPI, "sendUserMessage" | "events" | "appendEntry">, initialCtx: ExtensionContext, request: QuestionRequest, signal: AbortSignal | undefined, initialState: AskUserState, variant: "codex" | "claude", { resuming }?: {
|
|
8
8
|
resuming?: boolean;
|
|
9
9
|
}): Promise<QuestionResponse>;
|
|
10
10
|
export declare function createAskUserTool(variant: AskUserVariant, pi: ExtensionAPI, state: AskUserState): ToolDefinition;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/ask-user/tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAoBrF,OAAO,EAEN,KAAK,cAAc,EAGnB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EAErB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,YAAY;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACrB;AA+CD,wBAAgB,aAAa,CAC5B,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,QAAQ,GAAG,aAAa,CAAC,EAC3E,UAAU,EAAE,gBAAgB,EAC5B,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,OAAO,GAAG,QAAQ,EAC3B,EAAE,QAAgB,EAAE,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,6BA8LjD;AACD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,cAAc,CAmEhH"}
|