@astralyn/pi 1.4.8 → 1.4.10
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 +68 -0
- package/dist/bundle/chunks/{chunk-I2COK45I.js → chunk-6GTUUUCJ.js} +128 -128
- package/dist/bundle/chunks/{chunk-PU2IWWXV.js → chunk-DLVLAQEG.js} +1 -1
- package/dist/bundle/chunks/{chunk-MG5XDTXV.js → chunk-LPF7HQ3S.js} +1 -1
- package/dist/bundle/chunks/{chunk-FODCTZXW.js → chunk-MF3T3ETJ.js} +4 -4
- package/dist/bundle/chunks/{chunk-RO2VH6UZ.js → chunk-R267VV5T.js} +1 -1
- package/dist/bundle/chunks/{chunk-RLNMABLM.js → chunk-RVKT7OUB.js} +1 -1
- package/dist/bundle/chunks/{chunk-5VIOGR76.js → chunk-UCH27AVQ.js} +1 -1
- package/dist/bundle/chunks/{cli-MEL7SGJD.js → cli-MBFCFGI2.js} +1 -1
- package/dist/bundle/chunks/{execute-4CWRNHPO.js → execute-FQKRO4XJ.js} +1 -1
- package/dist/bundle/chunks/{runtime-R3X67XMR.js → runtime-3RPOJS5T.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-BBLD7YLS.js → virtual-modules-6IJ6V2CG.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session.d.ts +34 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +99 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/isolated-session.d.ts +7 -2
- package/dist/core/isolated-session.d.ts.map +1 -1
- package/dist/core/isolated-session.js +7 -3
- package/dist/core/isolated-session.js.map +1 -1
- package/dist/core/session-manager.d.ts +17 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +29 -0
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/tasks/delivery.d.ts +42 -7
- package/dist/core/tasks/delivery.d.ts.map +1 -1
- package/dist/core/tasks/delivery.js +129 -15
- package/dist/core/tasks/delivery.js.map +1 -1
- package/dist/core/tasks/execution.d.ts +27 -14
- package/dist/core/tasks/execution.d.ts.map +1 -1
- package/dist/core/tasks/execution.js +90 -86
- package/dist/core/tasks/execution.js.map +1 -1
- package/dist/core/tasks/limits.d.ts +13 -1
- package/dist/core/tasks/limits.d.ts.map +1 -1
- package/dist/core/tasks/limits.js +14 -1
- package/dist/core/tasks/limits.js.map +1 -1
- package/dist/core/tasks/output.d.ts +9 -1
- package/dist/core/tasks/output.d.ts.map +1 -1
- package/dist/core/tasks/output.js +23 -10
- package/dist/core/tasks/output.js.map +1 -1
- package/dist/core/tasks/presentation.d.ts +1 -1
- package/dist/core/tasks/presentation.d.ts.map +1 -1
- package/dist/core/tasks/presentation.js +6 -4
- package/dist/core/tasks/presentation.js.map +1 -1
- package/dist/core/tasks/record.d.ts +41 -29
- package/dist/core/tasks/record.d.ts.map +1 -1
- package/dist/core/tasks/record.js +82 -37
- package/dist/core/tasks/record.js.map +1 -1
- package/dist/core/tasks/reminder.js +2 -2
- package/dist/core/tasks/reminder.js.map +1 -1
- package/dist/core/tasks/runtime.d.ts +17 -14
- package/dist/core/tasks/runtime.d.ts.map +1 -1
- package/dist/core/tasks/runtime.js +68 -116
- package/dist/core/tasks/runtime.js.map +1 -1
- package/dist/core/tasks/scheduler.d.ts +3 -1
- package/dist/core/tasks/scheduler.d.ts.map +1 -1
- package/dist/core/tasks/scheduler.js +16 -12
- package/dist/core/tasks/scheduler.js.map +1 -1
- package/dist/core/tasks/session.d.ts +24 -3
- package/dist/core/tasks/session.d.ts.map +1 -1
- package/dist/core/tasks/session.js +73 -9
- package/dist/core/tasks/session.js.map +1 -1
- package/dist/core/tasks/store.d.ts +17 -4
- package/dist/core/tasks/store.d.ts.map +1 -1
- package/dist/core/tasks/store.js +45 -48
- package/dist/core/tasks/store.js.map +1 -1
- package/dist/core/tasks/types.d.ts +72 -29
- package/dist/core/tasks/types.d.ts.map +1 -1
- package/dist/core/tasks/types.js +7 -0
- package/dist/core/tasks/types.js.map +1 -1
- package/dist/core/tasks/wait.d.ts +19 -0
- package/dist/core/tasks/wait.d.ts.map +1 -0
- package/dist/core/tasks/wait.js +45 -0
- package/dist/core/tasks/wait.js.map +1 -0
- package/dist/core/tools/shell-execution.d.ts.map +1 -1
- package/dist/core/tools/shell-execution.js +2 -1
- package/dist/core/tools/shell-execution.js.map +1 -1
- package/dist/core/tools/shell-tool.d.ts.map +1 -1
- package/dist/core/tools/shell-tool.js +20 -13
- package/dist/core/tools/shell-tool.js.map +1 -1
- package/dist/extensions/agent/activity-lines.d.ts +10 -0
- package/dist/extensions/agent/activity-lines.d.ts.map +1 -0
- package/dist/extensions/agent/activity-lines.js +76 -0
- package/dist/extensions/agent/activity-lines.js.map +1 -0
- package/dist/extensions/agent/activity.d.ts +25 -4
- package/dist/extensions/agent/activity.d.ts.map +1 -1
- package/dist/extensions/agent/activity.js +76 -21
- package/dist/extensions/agent/activity.js.map +1 -1
- package/dist/extensions/agent/artifacts.d.ts +15 -0
- package/dist/extensions/agent/artifacts.d.ts.map +1 -0
- package/dist/extensions/agent/artifacts.js +44 -0
- package/dist/extensions/agent/artifacts.js.map +1 -0
- package/dist/extensions/agent/progress.d.ts +30 -4
- package/dist/extensions/agent/progress.d.ts.map +1 -1
- package/dist/extensions/agent/progress.js +84 -11
- package/dist/extensions/agent/progress.js.map +1 -1
- package/dist/extensions/agent/render.d.ts.map +1 -1
- package/dist/extensions/agent/render.js +8 -24
- package/dist/extensions/agent/render.js.map +1 -1
- package/dist/extensions/agent/report.d.ts +11 -3
- package/dist/extensions/agent/report.d.ts.map +1 -1
- package/dist/extensions/agent/report.js +32 -7
- package/dist/extensions/agent/report.js.map +1 -1
- package/dist/extensions/agent/tool.d.ts.map +1 -1
- package/dist/extensions/agent/tool.js +20 -5
- package/dist/extensions/agent/tool.js.map +1 -1
- package/dist/extensions/agent/types.d.ts +2 -0
- package/dist/extensions/agent/types.d.ts.map +1 -1
- package/dist/extensions/agent/types.js.map +1 -1
- package/dist/extensions/agent/worker.d.ts +7 -0
- package/dist/extensions/agent/worker.d.ts.map +1 -1
- package/dist/extensions/agent/worker.js +9 -3
- package/dist/extensions/agent/worker.js.map +1 -1
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +2 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/search/index.d.ts.map +1 -1
- package/dist/extensions/search/index.js +6 -7
- package/dist/extensions/search/index.js.map +1 -1
- package/dist/extensions/shell-paths/index.d.ts +8 -0
- package/dist/extensions/shell-paths/index.d.ts.map +1 -0
- package/dist/extensions/shell-paths/index.js +74 -0
- package/dist/extensions/shell-paths/index.js.map +1 -0
- package/dist/extensions/tasks/tool/actions.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/actions.js +15 -11
- package/dist/extensions/tasks/tool/actions.js.map +1 -1
- package/dist/extensions/tasks/tool/schema.d.ts +1 -1
- package/dist/extensions/tasks/tool/schema.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/schema.js +5 -5
- package/dist/extensions/tasks/tool/schema.js.map +1 -1
- package/dist/extensions/tasks/tool/types.d.ts +2 -0
- package/dist/extensions/tasks/tool/types.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/types.js.map +1 -1
- package/dist/extensions/tasks/tool.d.ts.map +1 -1
- package/dist/extensions/tasks/tool.js +3 -2
- package/dist/extensions/tasks/tool.js.map +1 -1
- package/dist/extensions/tasks/ui/completion-render.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/completion-render.js +2 -2
- package/dist/extensions/tasks/ui/completion-render.js.map +1 -1
- package/dist/extensions/tasks/ui/footer.d.ts +37 -0
- package/dist/extensions/tasks/ui/footer.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/footer.js +129 -0
- package/dist/extensions/tasks/ui/footer.js.map +1 -0
- package/dist/extensions/tasks/ui/frame.d.ts +36 -0
- package/dist/extensions/tasks/ui/frame.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/frame.js +33 -0
- package/dist/extensions/tasks/ui/frame.js.map +1 -0
- package/dist/extensions/tasks/ui/help.d.ts +6 -0
- package/dist/extensions/tasks/ui/help.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/help.js +53 -0
- package/dist/extensions/tasks/ui/help.js.map +1 -0
- package/dist/extensions/tasks/ui/inspector.d.ts +4 -3
- package/dist/extensions/tasks/ui/inspector.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/inspector.js +25 -6
- package/dist/extensions/tasks/ui/inspector.js.map +1 -1
- package/dist/extensions/tasks/ui/layout.d.ts +15 -18
- package/dist/extensions/tasks/ui/layout.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/layout.js +162 -255
- package/dist/extensions/tasks/ui/layout.js.map +1 -1
- package/dist/extensions/tasks/ui/list.d.ts +3 -1
- package/dist/extensions/tasks/ui/list.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/list.js +19 -14
- package/dist/extensions/tasks/ui/list.js.map +1 -1
- package/dist/extensions/tasks/ui/manager.d.ts +17 -5
- package/dist/extensions/tasks/ui/manager.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/manager.js +147 -90
- package/dist/extensions/tasks/ui/manager.js.map +1 -1
- package/dist/extensions/tasks/ui/model.d.ts +32 -5
- package/dist/extensions/tasks/ui/model.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/model.js +7 -7
- package/dist/extensions/tasks/ui/model.js.map +1 -1
- package/dist/extensions/tasks/ui/panes.d.ts +40 -0
- package/dist/extensions/tasks/ui/panes.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/panes.js +144 -0
- package/dist/extensions/tasks/ui/panes.js.map +1 -0
- package/dist/extensions/tasks/ui/render.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/render.js +11 -7
- package/dist/extensions/tasks/ui/render.js.map +1 -1
- package/dist/extensions/tasks/ui/viewport.d.ts +12 -4
- package/dist/extensions/tasks/ui/viewport.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/viewport.js +23 -7
- package/dist/extensions/tasks/ui/viewport.js.map +1 -1
- package/dist/extensions/tasks/ui/views.d.ts +12 -6
- package/dist/extensions/tasks/ui/views.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/views.js +39 -32
- package/dist/extensions/tasks/ui/views.js.map +1 -1
- package/dist/modes/interactive/chat-viewport.d.ts +5 -2
- package/dist/modes/interactive/chat-viewport.d.ts.map +1 -1
- package/dist/modes/interactive/chat-viewport.js +72 -12
- package/dist/modes/interactive/chat-viewport.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +11 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +43 -17
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/sticky-user-message.d.ts +23 -0
- package/dist/modes/interactive/components/sticky-user-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/sticky-user-message.js +58 -0
- package/dist/modes/interactive/components/sticky-user-message.js.map +1 -0
- package/dist/modes/interactive/components/user-message.d.ts +9 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +51 -10
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +4 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tool-view/chat.d.ts +3 -2
- package/dist/modes/interactive/tool-view/chat.d.ts.map +1 -1
- package/dist/modes/interactive/tool-view/chat.js +3 -3
- package/dist/modes/interactive/tool-view/chat.js.map +1 -1
- package/dist/modes/interactive/transcript-layout.d.ts +23 -0
- package/dist/modes/interactive/transcript-layout.d.ts.map +1 -0
- package/dist/modes/interactive/transcript-layout.js +29 -0
- package/dist/modes/interactive/transcript-layout.js.map +1 -0
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +37 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +11 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +48 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +1 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +2 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/bundled/README.md +1 -0
- package/docs/bundled/extensions/agent.md +39 -7
- package/docs/bundled/extensions/shell-paths.md +17 -0
- package/docs/bundled/tasks.md +25 -21
- package/docs/docs.json +4 -0
- package/docs/extensions.md +14 -10
- package/docs/json.md +3 -0
- package/docs/rpc.md +14 -0
- package/docs/sdk.md +11 -1
- package/docs/session-format.md +10 -4
- package/docs/sessions.md +1 -1
- package/docs/usage.md +3 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -20,6 +20,6 @@ export type TasksInput = Static<typeof tasksSchema>;
|
|
|
20
20
|
export declare function requireTaskId(input: TasksInput): string;
|
|
21
21
|
export declare function clampSinceBytes(sinceBytes: number | undefined): number | undefined;
|
|
22
22
|
export declare const TASKS_TOOL_DESCRIPTION: string;
|
|
23
|
-
export declare const TASKS_PROMPT_SNIPPET = "
|
|
23
|
+
export declare const TASKS_PROMPT_SNIPPET = "List, read, or stop background tasks; their results arrive automatically";
|
|
24
24
|
export declare const TASKS_PROMPT_GUIDELINES: string[];
|
|
25
25
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/tool/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAM5C,eAAO,MAAM,WAAW;;;;;;;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/tool/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAM5C,eAAO,MAAM,WAAW;;;;;;;EAkCtB,CAAC;AAEH,uFAAuF;AACvF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAOpD,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAMvD;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAElF;AAED,eAAO,MAAM,sBAAsB,QAOmS,CAAC;AACvU,eAAO,MAAM,oBAAoB,6EAA6E,CAAC;AAC/G,eAAO,MAAM,uBAAuB,UAInC,CAAC"}
|
|
@@ -22,7 +22,7 @@ export const tasksSchema = Type.Object({
|
|
|
22
22
|
})),
|
|
23
23
|
// — read —
|
|
24
24
|
mode: Type.Optional(StringEnum(["tail", "head"], {
|
|
25
|
-
description: "
|
|
25
|
+
description: "Which end of the output to read (read). Defaults to the start of a report, such as an Agent's, and the end of a log, such as a command's",
|
|
26
26
|
})),
|
|
27
27
|
bytes: Type.Optional(Type.Number({
|
|
28
28
|
description: `Max bytes to return (read, default ${formatSize(TASK_READ_BYTES)}, max ${formatSize(TASK_RESULT_BYTES)})`,
|
|
@@ -50,16 +50,16 @@ export function clampSinceBytes(sinceBytes) {
|
|
|
50
50
|
return sinceBytes === undefined || !Number.isFinite(sinceBytes) ? undefined : Math.max(0, Math.floor(sinceBytes));
|
|
51
51
|
}
|
|
52
52
|
export const TASKS_TOOL_DESCRIPTION = "Inspect and control background tasks started by native tools or extensions. " +
|
|
53
|
-
"Completion is delivered to you automatically
|
|
53
|
+
"Completion is delivered to you automatically and starts a new turn if yours has ended — never poll; end your turn instead of waiting. " +
|
|
54
54
|
"list: bounded activity/history listing; find task IDs here. " +
|
|
55
|
-
"read: bounded model-readable output or report slice (head/tail); tool-call activity stays in /tasks. " +
|
|
55
|
+
"read: bounded model-readable output or report slice (head/tail, by default a report from its start and a log from its end); tool-call activity stays in /tasks. " +
|
|
56
56
|
"wait: observe one task, or any task running at call time, for up to waitMs; no running tasks returns immediately. New steering input ends only the wait with outcome interrupted; it never stops the task. " +
|
|
57
57
|
"kill: request cancellation of a whole task. " +
|
|
58
58
|
"tasks cannot start work; submit background work through its owning tool. A wait ends as settled, interrupted, timed_out, or no_tasks. Timeout or cancellation ends only the wait, never execution. Reads and settled waits report byte ranges; use next sinceBytes only with that task's ID. Output is capped at 50KB per response.";
|
|
59
|
-
export const TASKS_PROMPT_SNIPPET = "
|
|
59
|
+
export const TASKS_PROMPT_SNIPPET = "List, read, or stop background tasks; their results arrive automatically";
|
|
60
60
|
export const TASKS_PROMPT_GUIDELINES = [
|
|
61
61
|
"Start background work through its owning tool with background: true; continue independent work while it runs.",
|
|
62
|
-
"
|
|
62
|
+
"Ending your turn is the normal way to wait for a background task: when it finishes, its result starts a new turn for you automatically. Do not use tasks wait to get a result; use it only when the user explicitly asks you to block on a task, with taskId for one task or without it for any task running at call time. Never poll with repeated waits or reads.",
|
|
63
63
|
"A new steering message interrupts only an active tasks wait so you can read the new input; it does not cancel execution. A wait timeout is not a task failure.",
|
|
64
64
|
];
|
|
65
65
|
//# sourceMappingURL=schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/tool/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IACtC,MAAM,EAAE,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAU,EAAE;QAC7D,WAAW,EAAE,iCAAiC;KAC9C,CAAC;IACF,yBAAyB;IACzB,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,8FAA8F;KAC3G,CAAC,CACF;IACD,WAAW;IACX,IAAI,EAAE,IAAI,CAAC,QAAQ,CAClB,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,CAAU,EAAE;QACrC,WAAW,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/tool/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IACtC,MAAM,EAAE,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAU,EAAE;QAC7D,WAAW,EAAE,iCAAiC;KAC9C,CAAC;IACF,yBAAyB;IACzB,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,8FAA8F;KAC3G,CAAC,CACF;IACD,WAAW;IACX,IAAI,EAAE,IAAI,CAAC,QAAQ,CAClB,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,CAAU,EAAE;QACrC,WAAW,EACV,0IAA0I;KAC3I,CAAC,CACF;IACD,KAAK,EAAE,IAAI,CAAC,QAAQ,CACnB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,sCAAsC,UAAU,CAAC,eAAe,CAAC,SAAS,UAAU,CAAC,iBAAiB,CAAC,GAAG;KACvH,CAAC,CACF;IACD,WAAW;IACX,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,sCAAsC,cAAc,CAAC,qBAAqB,CAAC,SAAS,cAAc,CAAC,iBAAiB,CAAC,wDAAwD;KAC1L,CAAC,CACF;IACD,UAAU,EAAE,IAAI,CAAC,QAAQ,CACxB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EACV,0IAA0I;KAC3I,CAAC,CACF;CACD,CAAC,CAAC;AAKH,6EAA6E;AAC7E,2EAA2E;AAC3E,yEAAyE;AACzE,6CAA6C;AAE7C,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,CAAC,MAAM,iEAAiE,CAAC,CAAC;IAC3G,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,UAA8B;IAC7D,OAAO,UAAU,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;AACnH,CAAC;AAED,MAAM,CAAC,MAAM,sBAAsB,GAClC,8EAA8E;IAC9E,wIAAwI;IACxI,8DAA8D;IAC9D,kKAAkK;IAClK,6MAA6M;IAC7M,8CAA8C;IAC9C,qUAAqU,CAAC;AACvU,MAAM,CAAC,MAAM,oBAAoB,GAAG,0EAA0E,CAAC;AAC/G,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACtC,+GAA+G;IAC/G,qWAAqW;IACrW,gKAAgK;CAChK,CAAC","sourcesContent":["/**\n * The `tasks` tool's wire contract: one flat schema whose `action`\n * selects which of the remaining fields apply, plus the model-facing copy.\n *\n * The schema stays flat deliberately: a single tool keeps the model's tool list\n * short. Execution creation belongs to the native tools. Narrowing happens\n * inside actions.ts, not here.\n */\n\nimport { StringEnum } from \"@earendil-works/pi-ai\";\nimport { type Static, Type } from \"typebox\";\nimport { TASKS_WAIT_DEFAULT_MS, TASKS_WAIT_MAX_MS } from \"../../../core/tasks/limits.ts\";\nimport { TASK_READ_BYTES, TASK_RESULT_BYTES } from \"../../../core/tasks/output.ts\";\nimport { formatSize } from \"../../../core/tools/truncate.ts\";\nimport { formatDuration } from \"../../../utils/duration.ts\";\n\nexport const tasksSchema = Type.Object({\n\taction: StringEnum([\"read\", \"wait\", \"kill\", \"list\"] as const, {\n\t\tdescription: \"Which task operation to perform\",\n\t}),\n\t// — read / wait / kill —\n\ttaskId: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Task execution id (read/wait/kill). Omit for wait to wait for any task running at call time.\",\n\t\t}),\n\t),\n\t// — read —\n\tmode: Type.Optional(\n\t\tStringEnum([\"tail\", \"head\"] as const, {\n\t\t\tdescription:\n\t\t\t\t\"Which end of the output to read (read). Defaults to the start of a report, such as an Agent's, and the end of a log, such as a command's\",\n\t\t}),\n\t),\n\tbytes: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Max bytes to return (read, default ${formatSize(TASK_READ_BYTES)}, max ${formatSize(TASK_RESULT_BYTES)})`,\n\t\t}),\n\t),\n\t// — wait —\n\twaitMs: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Maximum wait window in ms (default ${formatDuration(TASKS_WAIT_DEFAULT_MS)}, max ${formatDuration(TASKS_WAIT_MAX_MS)}). Only the wait ends on timeout; execution continues.`,\n\t\t}),\n\t),\n\tsinceBytes: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription:\n\t\t\t\t\"Only return output written after this byte offset — use the 'next sinceBytes' value from a previous read or wait (wait with taskId only)\",\n\t\t}),\n\t),\n});\n\n/** Raw tool arguments. Every per-action field is optional here; actions.ts narrows. */\nexport type TasksInput = Static<typeof tasksSchema>;\n\n// ── reading the contract ──────────────────────────────────────────────────\n// One place per field: required fields throw a message that names the next\n// step, optional ones clamp to their documented range. Callers get plain\n// values, so no action handler needs a cast.\n\nexport function requireTaskId(input: TasksInput): string {\n\tconst taskId = input.taskId;\n\tif (!taskId || taskId.trim().length === 0) {\n\t\tthrow new Error(`action '${input.action}' requires 'taskId' — use action list to find the execution id.`);\n\t}\n\treturn taskId;\n}\n\nexport function clampSinceBytes(sinceBytes: number | undefined): number | undefined {\n\treturn sinceBytes === undefined || !Number.isFinite(sinceBytes) ? undefined : Math.max(0, Math.floor(sinceBytes));\n}\n\nexport const TASKS_TOOL_DESCRIPTION =\n\t\"Inspect and control background tasks started by native tools or extensions. \" +\n\t\"Completion is delivered to you automatically and starts a new turn if yours has ended — never poll; end your turn instead of waiting. \" +\n\t\"list: bounded activity/history listing; find task IDs here. \" +\n\t\"read: bounded model-readable output or report slice (head/tail, by default a report from its start and a log from its end); tool-call activity stays in /tasks. \" +\n\t\"wait: observe one task, or any task running at call time, for up to waitMs; no running tasks returns immediately. New steering input ends only the wait with outcome interrupted; it never stops the task. \" +\n\t\"kill: request cancellation of a whole task. \" +\n\t\"tasks cannot start work; submit background work through its owning tool. A wait ends as settled, interrupted, timed_out, or no_tasks. Timeout or cancellation ends only the wait, never execution. Reads and settled waits report byte ranges; use next sinceBytes only with that task's ID. Output is capped at 50KB per response.\";\nexport const TASKS_PROMPT_SNIPPET = \"List, read, or stop background tasks; their results arrive automatically\";\nexport const TASKS_PROMPT_GUIDELINES = [\n\t\"Start background work through its owning tool with background: true; continue independent work while it runs.\",\n\t\"Ending your turn is the normal way to wait for a background task: when it finishes, its result starts a new turn for you automatically. Do not use tasks wait to get a result; use it only when the user explicitly asks you to block on a task, with taskId for one task or without it for any task running at call time. Never poll with repeated waits or reads.\",\n\t\"A new steering message interrupts only an active tasks wait so you can read the new input; it does not cancel execution. A wait timeout is not a task failure.\",\n];\n"]}
|
|
@@ -29,6 +29,8 @@ export interface TasksWaitDetails {
|
|
|
29
29
|
deltaBytes: number;
|
|
30
30
|
totalBytes: number;
|
|
31
31
|
deltaTruncated: boolean;
|
|
32
|
+
/** Actual read direction when output was returned; absent in older persisted results. */
|
|
33
|
+
mode?: "head" | "tail";
|
|
32
34
|
outputPath: string;
|
|
33
35
|
/** Initial waitAny cohort members still running when the wait ended. */
|
|
34
36
|
running?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/tool/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,UAAU,CAAC;AAEpF,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,CAAC;IAC1B,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/tool/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,UAAU,CAAC;AAEpF,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,CAAC;IAC1B,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,yFAAyF;IACzF,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/tool/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG","sourcesContent":["/**\n * The `tasks` tool's structured `details` payloads.\n *\n * Every shape here is JSON-serialized verbatim into the session file and read back\n * by the renderers on `/reload`, `/tree`, and session resume. Adding an optional\n * field is free; renaming or repurposing an existing one degrades historical\n * transcripts.\n */\n\nimport type { TaskKind, TaskStatus } from \"../../../core/tasks/types.ts\";\n\nexport interface TasksReadDetails {\n\tkind?: TaskKind;\n\tstatus?: TaskStatus;\n\taction: \"read\";\n\ttaskId: string;\n\tmode: \"head\" | \"tail\";\n\tsliceBytes: number;\n\ttotalBytes: number;\n\toutputPath: string;\n}\n\nexport type TasksWaitOutcome = \"settled\" | \"interrupted\" | \"timed_out\" | \"no_tasks\";\n\nexport interface TasksWaitDetails {\n\tkind?: TaskKind;\n\taction: \"wait\";\n\toutcome: TasksWaitOutcome;\n\t/** Undefined for waitAny with no selected task, or when no tasks were running. */\n\ttaskId?: string;\n\tstatus?: TaskStatus;\n\twaitedMs: number;\n\tdeltaBytes: number;\n\ttotalBytes: number;\n\tdeltaTruncated: boolean;\n\toutputPath: string;\n\t/** Initial waitAny cohort members still running when the wait ended. */\n\trunning?: number;\n}\n\nexport interface TasksKillDetails {\n\trequested?: boolean;\n\tstatus?: TaskStatus;\n\taction: \"kill\";\n\ttaskId: string;\n\ttitle: string;\n}\n\nexport interface TasksListDetails {\n\taction: \"list\";\n\trunning: number;\n\tfinished: number;\n\tshown: number;\n\thidden: number;\n\t/** Foreground executions omitted from the listing; they deliver inline in the transcript. */\n\tforegroundOmitted?: number;\n}\n\nexport type TasksDetails = TasksReadDetails | TasksKillDetails | TasksListDetails | TasksWaitDetails;\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/tool/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG","sourcesContent":["/**\n * The `tasks` tool's structured `details` payloads.\n *\n * Every shape here is JSON-serialized verbatim into the session file and read back\n * by the renderers on `/reload`, `/tree`, and session resume. Adding an optional\n * field is free; renaming or repurposing an existing one degrades historical\n * transcripts.\n */\n\nimport type { TaskKind, TaskStatus } from \"../../../core/tasks/types.ts\";\n\nexport interface TasksReadDetails {\n\tkind?: TaskKind;\n\tstatus?: TaskStatus;\n\taction: \"read\";\n\ttaskId: string;\n\tmode: \"head\" | \"tail\";\n\tsliceBytes: number;\n\ttotalBytes: number;\n\toutputPath: string;\n}\n\nexport type TasksWaitOutcome = \"settled\" | \"interrupted\" | \"timed_out\" | \"no_tasks\";\n\nexport interface TasksWaitDetails {\n\tkind?: TaskKind;\n\taction: \"wait\";\n\toutcome: TasksWaitOutcome;\n\t/** Undefined for waitAny with no selected task, or when no tasks were running. */\n\ttaskId?: string;\n\tstatus?: TaskStatus;\n\twaitedMs: number;\n\tdeltaBytes: number;\n\ttotalBytes: number;\n\tdeltaTruncated: boolean;\n\t/** Actual read direction when output was returned; absent in older persisted results. */\n\tmode?: \"head\" | \"tail\";\n\toutputPath: string;\n\t/** Initial waitAny cohort members still running when the wait ended. */\n\trunning?: number;\n}\n\nexport interface TasksKillDetails {\n\trequested?: boolean;\n\tstatus?: TaskStatus;\n\taction: \"kill\";\n\ttaskId: string;\n\ttitle: string;\n}\n\nexport interface TasksListDetails {\n\taction: \"list\";\n\trunning: number;\n\tfinished: number;\n\tshown: number;\n\thidden: number;\n\t/** Foreground executions omitted from the listing; they deliver inline in the transcript. */\n\tforegroundOmitted?: number;\n}\n\nexport type TasksDetails = TasksReadDetails | TasksKillDetails | TasksListDetails | TasksWaitDetails;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../../src/extensions/tasks/tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../../src/extensions/tasks/tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGrE,OAAO,EAAyE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACtH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAsC,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAE3F,wBAAgB,yBAAyB,IAAI,cAAc,CAAC,OAAO,WAAW,EAAE,YAAY,EAAE,gBAAgB,CAAC,CA8B9G"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { TASKS_TOOL_NAME } from "../../core/tasks/types.js";
|
|
1
2
|
import { boundedText, runKill, runList, runRead, runWait } from "./tool/actions.js";
|
|
2
3
|
import { TASKS_PROMPT_GUIDELINES, TASKS_PROMPT_SNIPPET, TASKS_TOOL_DESCRIPTION, tasksSchema } from "./tool/schema.js";
|
|
3
4
|
import { renderTasksCall, renderTasksResult } from "./ui/render.js";
|
|
4
5
|
export function createTasksToolDefinition() {
|
|
5
6
|
return {
|
|
6
|
-
name:
|
|
7
|
-
label:
|
|
7
|
+
name: TASKS_TOOL_NAME,
|
|
8
|
+
label: TASKS_TOOL_NAME,
|
|
8
9
|
description: TASKS_TOOL_DESCRIPTION,
|
|
9
10
|
promptSnippet: TASKS_PROMPT_SNIPPET,
|
|
10
11
|
promptGuidelines: TASKS_PROMPT_GUIDELINES,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../../src/extensions/tasks/tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEtH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAyB,MAAM,gBAAgB,CAAC;AAE3F,MAAM,UAAU,yBAAyB;IACxC,OAAO;QACN,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../../src/extensions/tasks/tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEtH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAyB,MAAM,gBAAgB,CAAC;AAE3F,MAAM,UAAU,yBAAyB;IACxC,OAAO;QACN,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,sBAAsB;QACnC,aAAa,EAAE,oBAAoB;QACnC,gBAAgB,EAAE,uBAAuB;QACzC,UAAU,EAAE,WAAW;QACvB,mBAAmB,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE;QAC9D,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG;YACvD,IAAI,CAAC;gBACJ,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;oBACvB,KAAK,MAAM;wBACV,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;oBACzC,KAAK,MAAM;wBACV,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;oBAC7D,KAAK,MAAM;wBACV,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;oBACnC,KAAK,MAAM;wBACV,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAC5B,CAAC;YACF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,uEAAuE;gBACvE,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;YACvC,CAAC;QACF,CAAC;QACD,UAAU,EAAE,eAAe;QAC3B,YAAY,EAAE,iBAAiB;KAC/B,CAAC;AACH,CAAC","sourcesContent":["import type { ToolDefinition } from \"../../core/extensions/types.ts\";\nimport { TASKS_TOOL_NAME } from \"../../core/tasks/types.ts\";\nimport { boundedText, runKill, runList, runRead, runWait } from \"./tool/actions.ts\";\nimport { TASKS_PROMPT_GUIDELINES, TASKS_PROMPT_SNIPPET, TASKS_TOOL_DESCRIPTION, tasksSchema } from \"./tool/schema.ts\";\nimport type { TasksDetails } from \"./tool/types.ts\";\nimport { renderTasksCall, renderTasksResult, type TasksRenderState } from \"./ui/render.ts\";\n\nexport function createTasksToolDefinition(): ToolDefinition<typeof tasksSchema, TasksDetails, TasksRenderState> {\n\treturn {\n\t\tname: TASKS_TOOL_NAME,\n\t\tlabel: TASKS_TOOL_NAME,\n\t\tdescription: TASKS_TOOL_DESCRIPTION,\n\t\tpromptSnippet: TASKS_PROMPT_SNIPPET,\n\t\tpromptGuidelines: TASKS_PROMPT_GUIDELINES,\n\t\tparameters: tasksSchema,\n\t\tconstrainedSampling: { type: \"json_schema\", strict: \"prefer\" },\n\t\tasync execute(toolCallId, params, signal, _onUpdate, ctx) {\n\t\t\ttry {\n\t\t\t\tswitch (params.action) {\n\t\t\t\t\tcase \"read\":\n\t\t\t\t\t\treturn await runRead(ctx.tasks, params);\n\t\t\t\t\tcase \"wait\":\n\t\t\t\t\t\treturn await runWait(ctx.tasks, params, signal, toolCallId);\n\t\t\t\t\tcase \"kill\":\n\t\t\t\t\t\treturn runKill(ctx.tasks, params);\n\t\t\t\t\tcase \"list\":\n\t\t\t\t\t\treturn runList(ctx.tasks);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// Lookup failures already carry the current task list from actions.ts.\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tthrow new Error(boundedText(message));\n\t\t\t}\n\t\t},\n\t\trenderCall: renderTasksCall,\n\t\trenderResult: renderTasksResult,\n\t};\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completion-render.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/completion-render.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,OAAO,EAAE,KAAK,SAAS,EAAqC,MAAM,wBAAwB,CAAC;AAC3F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAI/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"completion-render.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/completion-render.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,OAAO,EAAE,KAAK,SAAS,EAAqC,MAAM,wBAAwB,CAAC;AAC3F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAI/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AAmLvE,gGAAgG;AAChG,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,EAC/B,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,KAAK,GACV,SAAS,CAYX"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { truncateToWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
3
3
|
import { readVersionedTask } from "../../../core/tasks/codec.js";
|
|
4
4
|
import { runtimeLabel } from "../../../core/tasks/format.js";
|
|
5
|
+
import { TASKS_TOOL_NAME } from "../../../core/tasks/types.js";
|
|
5
6
|
import { FramedComponent } from "../../../modes/interactive/tool-view/style.js";
|
|
6
7
|
import { statusName, statusView } from "./status.js";
|
|
7
8
|
import { cleanTaskText } from "./text.js";
|
|
@@ -141,12 +142,11 @@ class CompletionCard {
|
|
|
141
142
|
if (id) {
|
|
142
143
|
lines.push("", ...wrapTextWithAnsi(`Task ID: ${id}`, inner).map((line) => theme.fg("dim", line)));
|
|
143
144
|
}
|
|
144
|
-
lines.push(theme.fg("dim", "Preview of the saved result."));
|
|
145
145
|
}
|
|
146
146
|
const bounded = lines.length > CARD_ROWS
|
|
147
147
|
? [
|
|
148
148
|
...lines.slice(0, CARD_ROWS - 1),
|
|
149
|
-
theme.fg("dim",
|
|
149
|
+
theme.fg("dim", `… card shortened; use ${TASKS_TOOL_NAME} read for retained output`),
|
|
150
150
|
]
|
|
151
151
|
: lines;
|
|
152
152
|
return bounded.map((line) => " ".repeat(padding) + truncateToWidth(line, inner, "…") + " ".repeat(padding));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completion-render.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/completion-render.ts"],"names":[],"mappings":"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","sourcesContent":["/** Human-facing completion cards. The persisted context message remains untouched. */\nimport { type Component, truncateToWidth, wrapTextWithAnsi } from \"@earendil-works/pi-tui\";\nimport type { MessageRenderOptions } from \"../../../core/extensions/types.ts\";\nimport type { CustomMessage } from \"../../../core/messages.ts\";\nimport { readVersionedTask } from \"../../../core/tasks/codec.ts\";\nimport { runtimeLabel } from \"../../../core/tasks/format.ts\";\nimport type { TaskFact, TaskStatus } from \"../../../core/tasks/types.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport { FramedComponent } from \"../../../modes/interactive/tool-view/style.ts\";\nimport { statusName, statusView } from \"./status.ts\";\nimport { cleanTaskText } from \"./text.ts\";\n\nconst SOURCE_LIMIT = 64 * 1024;\nconst CARD_ROWS = 128;\nconst OUTPUT_ROWS = 20;\n/** A persisted task completion, or the saved text of a message that is unreadable or from an older format. */\ntype CompletionView =\n\t| {\n\t\t\tkind: \"task\";\n\t\t\tlabel: string;\n\t\t\ttitle: string;\n\t\t\tduration: string;\n\t\t\tstatus: TaskStatus;\n\t\t\tid: string;\n\t\t\tinput?: { label: string; text: string };\n\t\t\tfacts: TaskFact[];\n\t\t\tpath?: string;\n\t\t\tdiagnostic?: string;\n\t\t\toutput: string;\n\t\t\t/** A report previews its beginning; a log previews its end. */\n\t\t\treport: boolean;\n\t\t\ttruncated: boolean;\n\t }\n\t| { kind: \"saved\"; body: string; truncated: boolean };\n\nfunction savedText(message: CustomMessage<unknown>): { text: string; clipped: boolean } {\n\t// 64K is a UTF-16 code-unit display budget, not a UTF-8 byte promise; the block\n\t// cap bounds iteration itself so many empty/non-text blocks cannot spin here.\n\tconst MAX_SOURCE_BLOCKS = 256;\n\tconst content = message.content;\n\tlet text = \"\";\n\tlet clipped = false;\n\tif (typeof content === \"string\") {\n\t\ttext = content.slice(0, SOURCE_LIMIT);\n\t\tclipped = content.length > SOURCE_LIMIT;\n\t} else if (Array.isArray(content)) {\n\t\tlet visited = 0;\n\t\tfor (const block of content) {\n\t\t\tif (++visited > MAX_SOURCE_BLOCKS) {\n\t\t\t\tclipped = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!block || block.type !== \"text\" || typeof block.text !== \"string\") continue;\n\t\t\tconst next = `${text ? \"\\n\" : \"\"}${block.text.slice(0, SOURCE_LIMIT + 1)}`;\n\t\t\tconst remaining = SOURCE_LIMIT - text.length;\n\t\t\ttext += next.slice(0, remaining);\n\t\t\tif (next.length > remaining || block.text.length > SOURCE_LIMIT) {\n\t\t\t\tclipped = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn { text: cleanTaskText(text), clipped };\n}\n\nfunction completionView(message: CustomMessage<unknown>): CompletionView {\n\tconst task = readVersionedTask(message.details);\n\tif (!task) {\n\t\tconst { text, clipped } = savedText(message);\n\t\treturn { kind: \"saved\", body: text, truncated: clipped };\n\t}\n\treturn {\n\t\tkind: \"task\",\n\t\tlabel: cleanTaskText(task.label),\n\t\ttitle: cleanTaskText(task.title),\n\t\tduration: runtimeLabel(task),\n\t\tstatus: task.status,\n\t\tid: cleanTaskText(task.id),\n\t\tinput: task.input && { label: cleanTaskText(task.input.label), text: cleanTaskText(task.input.text) },\n\t\tfacts: (task.facts ?? []).map(([label, value]) => [cleanTaskText(label), cleanTaskText(value)]),\n\t\tpath: task.outputPath === undefined ? undefined : cleanTaskText(task.outputPath),\n\t\tdiagnostic: task.error === undefined ? undefined : cleanTaskText(task.error),\n\t\toutput: cleanTaskText(task.result?.text ?? \"\"),\n\t\treport: task.output === \"report\",\n\t\ttruncated: task.result?.truncated === true || task.input?.truncated === true,\n\t};\n}\n\nfunction shortId(id: string): string {\n\treturn id.replace(/^(.+)-([0-9a-f]{8})-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, \"$1-$2\");\n}\n\nclass CompletionCard implements Component {\n\tprivate readonly view: CompletionView;\n\tprivate readonly options: MessageRenderOptions;\n\tprivate readonly theme: Theme;\n\tconstructor(view: CompletionView, options: MessageRenderOptions, theme: Theme) {\n\t\tthis.view = view;\n\t\tthis.options = options;\n\t\tthis.theme = theme;\n\t}\n\tinvalidate(): void {}\n\trender(width: number): string[] {\n\t\tif (width < 1) return [];\n\t\tconst chrome = new FramedComponent(\n\t\t\t{ render: (contentWidth) => this.renderContent(contentWidth), invalidate() {} },\n\t\t\t\"header\",\n\t\t\t() => (this.view.kind === \"task\" ? statusView(this.view.status).color : \"muted\"),\n\t\t);\n\t\t// The gutter reserves its own cells; clip defensively for one-cell terminals.\n\t\treturn chrome.render(width).map((line) => truncateToWidth(line, width, \"\"));\n\t}\n\tprivate renderContent(width: number): string[] {\n\t\t// The chrome clamps to ≥1 already; keep the padding arithmetic safe regardless.\n\t\tif (!Number.isFinite(width) || width < 1) return [];\n\t\tconst view = this.view;\n\t\tconst theme = this.theme;\n\t\tconst options = this.options;\n\t\t// The native dot/rail replaces the default one-cell custom-message inset.\n\t\t// Additional configured padding stays inside the chrome, never shifting the dot.\n\t\tconst padding = Math.min(Math.max(0, Math.floor(options.outputPad || 0) - 1), Math.floor((width - 1) / 2));\n\t\tconst inner = width - padding * 2;\n\t\tconst indent = inner >= 3 ? \" \" : \"\";\n\t\tconst bodyWidth = Math.max(1, inner - indent.length);\n\t\tconst lines: string[] = [];\n\t\tconst status = view.kind === \"task\" ? statusName(view.status) : \"Result received\";\n\t\tconst label = view.kind === \"task\" ? view.label : \"Notification\";\n\t\tconst duration = view.kind === \"task\" && view.duration ? ` · ${view.duration}` : \"\";\n\t\tconst id = view.kind === \"task\" ? view.id : \"\";\n\t\tlines.push(\n\t\t\t`${theme.fg(\"toolTitle\", theme.bold(label))}${theme.fg(\"muted\", ` · Background ${status.toLowerCase()}${duration}`)}${id ? theme.fg(\"dim\", ` · ${shortId(id)}`) : \"\"}`,\n\t\t);\n\t\tif (!options.expanded) {\n\t\t\tif (view.kind === \"task\") {\n\t\t\t\tconst summary = view.title.split(\"\\n\").find((line) => line.trim()) ?? view.title;\n\t\t\t\tif (summary) lines.push(theme.fg(\"toolOutput\", summary));\n\t\t\t\tif (view.diagnostic) lines.push(theme.fg(statusView(view.status).color, view.diagnostic));\n\t\t\t}\n\t\t} else {\n\t\t\tif (view.truncated) {\n\t\t\t\tlines.push(theme.fg(\"warning\", \"The saved result is truncated; this is not the complete original output.\"));\n\t\t\t}\n\t\t\tconst section = (title: string, text: string, limit: number, tail = false, error = false) => {\n\t\t\t\tlines.push(\"\", theme.fg(\"muted\", theme.bold(title)));\n\t\t\t\tconst rendered = wrapTextWithAnsi(text, bodyWidth).map((line) =>\n\t\t\t\t\ttheme.fg(error ? \"error\" : \"toolOutput\", line),\n\t\t\t\t);\n\t\t\t\tconst omitted = Math.max(0, rendered.length - limit);\n\t\t\t\tconst selected = tail ? rendered.slice(-limit) : rendered.slice(0, limit);\n\t\t\t\tif (tail && omitted) lines.push(theme.fg(\"dim\", `${indent}… ${omitted} earlier display lines omitted`));\n\t\t\t\tfor (const line of selected) lines.push(indent + line);\n\t\t\t\tif (!tail && omitted) lines.push(theme.fg(\"dim\", `${indent}… ${omitted} more display lines omitted`));\n\t\t\t};\n\t\t\tif (view.kind === \"saved\") section(\"Details\", view.body || \"No text result.\", 36);\n\t\t\telse {\n\t\t\t\tif (view.input) section(view.input.label, view.input.text, 8);\n\t\t\t\telse if (view.title) section(\"Task\", view.title, 4);\n\t\t\t\tif (view.facts.length) {\n\t\t\t\t\tconst width = Math.max(...view.facts.map(([label]) => label.length)) + 1;\n\t\t\t\t\tsection(\"Details\", view.facts.map(([label, value]) => `${label.padEnd(width)}${value}`).join(\"\\n\"), 8);\n\t\t\t\t}\n\t\t\t\tsection(\n\t\t\t\t\tview.status === \"failed\" || view.status === \"timeout\" ? \"Error\" : \"Result\",\n\t\t\t\t\tview.diagnostic ?? status,\n\t\t\t\t\t4,\n\t\t\t\t\tfalse,\n\t\t\t\t\tview.status === \"failed\",\n\t\t\t\t);\n\t\t\t\tsection(\"Output\", !view.output.trim() ? \"No output.\" : view.output, OUTPUT_ROWS, !view.report);\n\t\t\t\tif (view.path) section(\"Log\", view.path, 4);\n\t\t\t}\n\t\t\tif (id) {\n\t\t\t\tlines.push(\"\", ...wrapTextWithAnsi(`Task ID: ${id}`, inner).map((line) => theme.fg(\"dim\", line)));\n\t\t\t}\n\t\t\tlines.push(theme.fg(\"dim\", \"Preview of the saved result.\"));\n\t\t}\n\t\tconst bounded =\n\t\t\tlines.length > CARD_ROWS\n\t\t\t\t? [\n\t\t\t\t\t\t...lines.slice(0, CARD_ROWS - 1),\n\t\t\t\t\t\ttheme.fg(\"dim\", \"… card shortened; use tasks read for retained output\"),\n\t\t\t\t\t]\n\t\t\t\t: lines;\n\t\treturn bounded.map((line) => \" \".repeat(padding) + truncateToWidth(line, inner, \"…\") + \" \".repeat(padding));\n\t}\n}\n\n/** Always return a compact, replay-safe component, including for unknown historical formats. */\nexport function renderTaskCompletion(\n\tmessage: CustomMessage<unknown>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n): Component {\n\tlet view: CompletionView;\n\ttry {\n\t\tview = completionView(message);\n\t} catch {\n\t\tview = {\n\t\t\tkind: \"saved\",\n\t\t\tbody: \"The saved notification could not be interpreted. Its original message remains in session history.\",\n\t\t\ttruncated: false,\n\t\t};\n\t}\n\treturn new CompletionCard(view, options, theme);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"completion-render.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/completion-render.ts"],"names":[],"mappings":"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","sourcesContent":["/** Human-facing completion cards. The persisted context message remains untouched. */\nimport { type Component, truncateToWidth, wrapTextWithAnsi } from \"@earendil-works/pi-tui\";\nimport type { MessageRenderOptions } from \"../../../core/extensions/types.ts\";\nimport type { CustomMessage } from \"../../../core/messages.ts\";\nimport { readVersionedTask } from \"../../../core/tasks/codec.ts\";\nimport { runtimeLabel } from \"../../../core/tasks/format.ts\";\nimport { TASKS_TOOL_NAME, type TaskFact, type TaskStatus } from \"../../../core/tasks/types.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport { FramedComponent } from \"../../../modes/interactive/tool-view/style.ts\";\nimport { statusName, statusView } from \"./status.ts\";\nimport { cleanTaskText } from \"./text.ts\";\n\nconst SOURCE_LIMIT = 64 * 1024;\nconst CARD_ROWS = 128;\nconst OUTPUT_ROWS = 20;\n/** A persisted task completion, or the saved text of a message that is unreadable or from an older format. */\ntype CompletionView =\n\t| {\n\t\t\tkind: \"task\";\n\t\t\tlabel: string;\n\t\t\ttitle: string;\n\t\t\tduration: string;\n\t\t\tstatus: TaskStatus;\n\t\t\tid: string;\n\t\t\tinput?: { label: string; text: string };\n\t\t\tfacts: TaskFact[];\n\t\t\tpath?: string;\n\t\t\tdiagnostic?: string;\n\t\t\toutput: string;\n\t\t\t/** A report previews its beginning; a log previews its end. */\n\t\t\treport: boolean;\n\t\t\ttruncated: boolean;\n\t }\n\t| { kind: \"saved\"; body: string; truncated: boolean };\n\nfunction savedText(message: CustomMessage<unknown>): { text: string; clipped: boolean } {\n\t// 64K is a UTF-16 code-unit display budget, not a UTF-8 byte promise; the block\n\t// cap bounds iteration itself so many empty/non-text blocks cannot spin here.\n\tconst MAX_SOURCE_BLOCKS = 256;\n\tconst content = message.content;\n\tlet text = \"\";\n\tlet clipped = false;\n\tif (typeof content === \"string\") {\n\t\ttext = content.slice(0, SOURCE_LIMIT);\n\t\tclipped = content.length > SOURCE_LIMIT;\n\t} else if (Array.isArray(content)) {\n\t\tlet visited = 0;\n\t\tfor (const block of content) {\n\t\t\tif (++visited > MAX_SOURCE_BLOCKS) {\n\t\t\t\tclipped = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!block || block.type !== \"text\" || typeof block.text !== \"string\") continue;\n\t\t\tconst next = `${text ? \"\\n\" : \"\"}${block.text.slice(0, SOURCE_LIMIT + 1)}`;\n\t\t\tconst remaining = SOURCE_LIMIT - text.length;\n\t\t\ttext += next.slice(0, remaining);\n\t\t\tif (next.length > remaining || block.text.length > SOURCE_LIMIT) {\n\t\t\t\tclipped = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn { text: cleanTaskText(text), clipped };\n}\n\nfunction completionView(message: CustomMessage<unknown>): CompletionView {\n\tconst task = readVersionedTask(message.details);\n\tif (!task) {\n\t\tconst { text, clipped } = savedText(message);\n\t\treturn { kind: \"saved\", body: text, truncated: clipped };\n\t}\n\treturn {\n\t\tkind: \"task\",\n\t\tlabel: cleanTaskText(task.label),\n\t\ttitle: cleanTaskText(task.title),\n\t\tduration: runtimeLabel(task),\n\t\tstatus: task.status,\n\t\tid: cleanTaskText(task.id),\n\t\tinput: task.input && { label: cleanTaskText(task.input.label), text: cleanTaskText(task.input.text) },\n\t\tfacts: (task.facts ?? []).map(([label, value]) => [cleanTaskText(label), cleanTaskText(value)]),\n\t\tpath: task.outputPath === undefined ? undefined : cleanTaskText(task.outputPath),\n\t\tdiagnostic: task.error === undefined ? undefined : cleanTaskText(task.error),\n\t\toutput: cleanTaskText(task.result?.text ?? \"\"),\n\t\treport: task.output === \"report\",\n\t\ttruncated: task.result?.truncated === true || task.input?.truncated === true,\n\t};\n}\n\nfunction shortId(id: string): string {\n\treturn id.replace(/^(.+)-([0-9a-f]{8})-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, \"$1-$2\");\n}\n\nclass CompletionCard implements Component {\n\tprivate readonly view: CompletionView;\n\tprivate readonly options: MessageRenderOptions;\n\tprivate readonly theme: Theme;\n\tconstructor(view: CompletionView, options: MessageRenderOptions, theme: Theme) {\n\t\tthis.view = view;\n\t\tthis.options = options;\n\t\tthis.theme = theme;\n\t}\n\tinvalidate(): void {}\n\trender(width: number): string[] {\n\t\tif (width < 1) return [];\n\t\tconst chrome = new FramedComponent(\n\t\t\t{ render: (contentWidth) => this.renderContent(contentWidth), invalidate() {} },\n\t\t\t\"header\",\n\t\t\t() => (this.view.kind === \"task\" ? statusView(this.view.status).color : \"muted\"),\n\t\t);\n\t\t// The gutter reserves its own cells; clip defensively for one-cell terminals.\n\t\treturn chrome.render(width).map((line) => truncateToWidth(line, width, \"\"));\n\t}\n\tprivate renderContent(width: number): string[] {\n\t\t// The chrome clamps to ≥1 already; keep the padding arithmetic safe regardless.\n\t\tif (!Number.isFinite(width) || width < 1) return [];\n\t\tconst view = this.view;\n\t\tconst theme = this.theme;\n\t\tconst options = this.options;\n\t\t// The native dot/rail replaces the default one-cell custom-message inset.\n\t\t// Additional configured padding stays inside the chrome, never shifting the dot.\n\t\tconst padding = Math.min(Math.max(0, Math.floor(options.outputPad || 0) - 1), Math.floor((width - 1) / 2));\n\t\tconst inner = width - padding * 2;\n\t\tconst indent = inner >= 3 ? \" \" : \"\";\n\t\tconst bodyWidth = Math.max(1, inner - indent.length);\n\t\tconst lines: string[] = [];\n\t\tconst status = view.kind === \"task\" ? statusName(view.status) : \"Result received\";\n\t\tconst label = view.kind === \"task\" ? view.label : \"Notification\";\n\t\tconst duration = view.kind === \"task\" && view.duration ? ` · ${view.duration}` : \"\";\n\t\tconst id = view.kind === \"task\" ? view.id : \"\";\n\t\tlines.push(\n\t\t\t`${theme.fg(\"toolTitle\", theme.bold(label))}${theme.fg(\"muted\", ` · Background ${status.toLowerCase()}${duration}`)}${id ? theme.fg(\"dim\", ` · ${shortId(id)}`) : \"\"}`,\n\t\t);\n\t\tif (!options.expanded) {\n\t\t\tif (view.kind === \"task\") {\n\t\t\t\tconst summary = view.title.split(\"\\n\").find((line) => line.trim()) ?? view.title;\n\t\t\t\tif (summary) lines.push(theme.fg(\"toolOutput\", summary));\n\t\t\t\tif (view.diagnostic) lines.push(theme.fg(statusView(view.status).color, view.diagnostic));\n\t\t\t}\n\t\t} else {\n\t\t\tif (view.truncated) {\n\t\t\t\tlines.push(theme.fg(\"warning\", \"The saved result is truncated; this is not the complete original output.\"));\n\t\t\t}\n\t\t\tconst section = (title: string, text: string, limit: number, tail = false, error = false) => {\n\t\t\t\tlines.push(\"\", theme.fg(\"muted\", theme.bold(title)));\n\t\t\t\tconst rendered = wrapTextWithAnsi(text, bodyWidth).map((line) =>\n\t\t\t\t\ttheme.fg(error ? \"error\" : \"toolOutput\", line),\n\t\t\t\t);\n\t\t\t\tconst omitted = Math.max(0, rendered.length - limit);\n\t\t\t\tconst selected = tail ? rendered.slice(-limit) : rendered.slice(0, limit);\n\t\t\t\tif (tail && omitted) lines.push(theme.fg(\"dim\", `${indent}… ${omitted} earlier display lines omitted`));\n\t\t\t\tfor (const line of selected) lines.push(indent + line);\n\t\t\t\tif (!tail && omitted) lines.push(theme.fg(\"dim\", `${indent}… ${omitted} more display lines omitted`));\n\t\t\t};\n\t\t\tif (view.kind === \"saved\") section(\"Details\", view.body || \"No text result.\", 36);\n\t\t\telse {\n\t\t\t\tif (view.input) section(view.input.label, view.input.text, 8);\n\t\t\t\telse if (view.title) section(\"Task\", view.title, 4);\n\t\t\t\tif (view.facts.length) {\n\t\t\t\t\tconst width = Math.max(...view.facts.map(([label]) => label.length)) + 1;\n\t\t\t\t\tsection(\"Details\", view.facts.map(([label, value]) => `${label.padEnd(width)}${value}`).join(\"\\n\"), 8);\n\t\t\t\t}\n\t\t\t\tsection(\n\t\t\t\t\tview.status === \"failed\" || view.status === \"timeout\" ? \"Error\" : \"Result\",\n\t\t\t\t\tview.diagnostic ?? status,\n\t\t\t\t\t4,\n\t\t\t\t\tfalse,\n\t\t\t\t\tview.status === \"failed\",\n\t\t\t\t);\n\t\t\t\tsection(\"Output\", !view.output.trim() ? \"No output.\" : view.output, OUTPUT_ROWS, !view.report);\n\t\t\t\tif (view.path) section(\"Log\", view.path, 4);\n\t\t\t}\n\t\t\tif (id) {\n\t\t\t\tlines.push(\"\", ...wrapTextWithAnsi(`Task ID: ${id}`, inner).map((line) => theme.fg(\"dim\", line)));\n\t\t\t}\n\t\t}\n\t\tconst bounded =\n\t\t\tlines.length > CARD_ROWS\n\t\t\t\t? [\n\t\t\t\t\t\t...lines.slice(0, CARD_ROWS - 1),\n\t\t\t\t\t\ttheme.fg(\"dim\", `… card shortened; use ${TASKS_TOOL_NAME} read for retained output`),\n\t\t\t\t\t]\n\t\t\t\t: lines;\n\t\treturn bounded.map((line) => \" \".repeat(padding) + truncateToWidth(line, inner, \"…\") + \" \".repeat(padding));\n\t}\n}\n\n/** Always return a compact, replay-safe component, including for unknown historical formats. */\nexport function renderTaskCompletion(\n\tmessage: CustomMessage<unknown>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n): Component {\n\tlet view: CompletionView;\n\ttry {\n\t\tview = completionView(message);\n\t} catch {\n\t\tview = {\n\t\t\tkind: \"saved\",\n\t\t\tbody: \"The saved notification could not be interpreted. Its original message remains in session history.\",\n\t\t\ttruncated: false,\n\t\t};\n\t}\n\treturn new CompletionCard(view, options, theme);\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Keybinding } from "../../../core/keybindings.ts";
|
|
2
|
+
import type { Theme } from "../../../modes/interactive/theme/theme.ts";
|
|
3
|
+
import type { PanelFocus, TaskHit } from "./model.ts";
|
|
4
|
+
/** An outcome the panel does not already show: the action did not do what was asked. */
|
|
5
|
+
export interface Feedback {
|
|
6
|
+
tone: "warning" | "error";
|
|
7
|
+
text: string;
|
|
8
|
+
}
|
|
9
|
+
export interface FooterEnv {
|
|
10
|
+
width: number;
|
|
11
|
+
/** The footer's screen row. */
|
|
12
|
+
y: number;
|
|
13
|
+
theme: Theme;
|
|
14
|
+
hint: (key: Keybinding) => string;
|
|
15
|
+
feedback?: Feedback;
|
|
16
|
+
}
|
|
17
|
+
export interface Footer {
|
|
18
|
+
line: string;
|
|
19
|
+
hits: TaskHit[];
|
|
20
|
+
}
|
|
21
|
+
export declare function browseFooter(env: FooterEnv, view: {
|
|
22
|
+
focus: PanelFocus;
|
|
23
|
+
split: boolean;
|
|
24
|
+
stoppable: boolean;
|
|
25
|
+
detachable: boolean;
|
|
26
|
+
}): Footer;
|
|
27
|
+
export declare function searchFooter(env: FooterEnv): Footer;
|
|
28
|
+
export declare function helpFooter(env: FooterEnv): Footer;
|
|
29
|
+
/**
|
|
30
|
+
* The stop question borrows only the footer row, so the task stays in view while confirming;
|
|
31
|
+
* `source` and `title` name the target, and the title gives way first on narrow widths.
|
|
32
|
+
*/
|
|
33
|
+
export declare function confirmStopFooter(env: FooterEnv, target: {
|
|
34
|
+
source: string;
|
|
35
|
+
title: string;
|
|
36
|
+
}): Footer;
|
|
37
|
+
//# sourceMappingURL=footer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/footer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAc,MAAM,2CAA2C,CAAC;AACnF,OAAO,KAAK,EAAE,UAAU,EAAc,OAAO,EAAE,MAAM,YAAY,CAAC;AAElE,wFAAwF;AACxF,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACb;AAqBD,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,MAAM,CAAC;IAClC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,WAAW,MAAM;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,EAAE,CAAC;CAChB;AA4CD,wBAAgB,YAAY,CAC3B,GAAG,EAAE,SAAS,EACd,IAAI,EAAE;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,GAClF,MAAM,CA4BR;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAYnD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CASjD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAkBnG"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The footer row, one builder per panel mode. Context hints sit on the left, the Escape action is
|
|
3
|
+
* pinned to the right edge, and transient feedback temporarily replaces the hints.
|
|
4
|
+
*/
|
|
5
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
6
|
+
const FEEDBACK_GLYPH = { warning: "!", error: "×" };
|
|
7
|
+
/** Cells kept between the left content and the pinned Escape action. */
|
|
8
|
+
const GAP = 3;
|
|
9
|
+
/** Drops the lowest-priority items, the later of equals first, until the rest fit. */
|
|
10
|
+
function dropToFit(items, room, separator) {
|
|
11
|
+
const kept = [...items];
|
|
12
|
+
const width = () => kept.reduce((sum, item) => sum + visibleWidth(item.text), 0) + visibleWidth(separator) * (kept.length - 1);
|
|
13
|
+
while (kept.length > 1 && width() > room) {
|
|
14
|
+
let drop = 0;
|
|
15
|
+
for (const [index, item] of kept.entries())
|
|
16
|
+
if (item.priority >= kept[drop].priority)
|
|
17
|
+
drop = index;
|
|
18
|
+
kept.splice(drop, 1);
|
|
19
|
+
}
|
|
20
|
+
return kept;
|
|
21
|
+
}
|
|
22
|
+
function compose(env, spec) {
|
|
23
|
+
const { width, y, theme } = env;
|
|
24
|
+
const hits = [];
|
|
25
|
+
const escapeWidth = visibleWidth(spec.escape.text);
|
|
26
|
+
const room = Math.max(0, width - escapeWidth - GAP);
|
|
27
|
+
let showEscape = true;
|
|
28
|
+
let left;
|
|
29
|
+
if (spec.feedback) {
|
|
30
|
+
const message = `${FEEDBACK_GLYPH[spec.feedback.tone]} ${spec.feedback.text}`;
|
|
31
|
+
// A long message is worth more than the Escape hint while it lasts.
|
|
32
|
+
showEscape = visibleWidth(message) <= room;
|
|
33
|
+
left = theme.fg(spec.feedback.tone, truncateToWidth(message, showEscape ? room : width, "…"));
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
let x = 0;
|
|
37
|
+
const kept = dropToFit(spec.items, room, spec.separator);
|
|
38
|
+
for (const item of kept) {
|
|
39
|
+
if (item.action)
|
|
40
|
+
hits.push({ x, y, width: visibleWidth(item.text), action: item.action });
|
|
41
|
+
x += visibleWidth(item.text) + visibleWidth(spec.separator);
|
|
42
|
+
}
|
|
43
|
+
left = theme.fg(spec.tone, truncateToWidth(kept.map((item) => item.text).join(spec.separator), room, "…"));
|
|
44
|
+
}
|
|
45
|
+
const gap = Math.max(0, width - visibleWidth(left) - (showEscape ? escapeWidth : 0));
|
|
46
|
+
if (showEscape && spec.escape.action)
|
|
47
|
+
hits.push({ x: width - escapeWidth, y, width: escapeWidth, action: spec.escape.action });
|
|
48
|
+
return { line: left + " ".repeat(gap) + (showEscape ? theme.fg(spec.tone, spec.escape.text) : ""), hits };
|
|
49
|
+
}
|
|
50
|
+
const BACK = { kind: "back" };
|
|
51
|
+
export function browseFooter(env, view) {
|
|
52
|
+
const { hint } = env;
|
|
53
|
+
const items = [];
|
|
54
|
+
const add = (text, priority, action) => items.push({ text, priority, action });
|
|
55
|
+
const arrows = `${hint("tui.select.up")} / ${hint("tui.select.down")}`;
|
|
56
|
+
if (view.focus === "list") {
|
|
57
|
+
add(`${arrows} tasks`, 5);
|
|
58
|
+
add(`${hint("tui.select.confirm")} open`, 4, { kind: "open" });
|
|
59
|
+
add(`${hint("app.tasks.search")} find`, 3, { kind: "key", key: "app.tasks.search" });
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
add(`${arrows} scroll`, 5);
|
|
63
|
+
// Without the list beside it, Escape is the way back.
|
|
64
|
+
if (view.split)
|
|
65
|
+
add(`${hint("app.tasks.nextFocus")} tasks`, 6, { kind: "key", key: "app.tasks.nextFocus" });
|
|
66
|
+
add(`${hint("app.tasks.previousTab")} output`, 6, { kind: "tab", tab: "output" });
|
|
67
|
+
add(`${hint("app.tasks.nextTab")} details`, 6, { kind: "tab", tab: "info" });
|
|
68
|
+
}
|
|
69
|
+
if (view.stoppable)
|
|
70
|
+
add(`${hint("app.tasks.kill")} stop`, 2, { kind: "key", key: "app.tasks.kill" });
|
|
71
|
+
if (view.detachable)
|
|
72
|
+
add(`${hint("app.tasks.detachSelected")} background`, 2, { kind: "key", key: "app.tasks.detachSelected" });
|
|
73
|
+
add(`${hint("app.tasks.help")} keys`, 1, { kind: "key", key: "app.tasks.help" });
|
|
74
|
+
const back = !view.split && view.focus === "inspector";
|
|
75
|
+
return compose(env, {
|
|
76
|
+
items,
|
|
77
|
+
separator: " · ",
|
|
78
|
+
escape: { text: `${hint("tui.select.cancel")} ${back ? "back" : "close"}`, priority: 0, action: BACK },
|
|
79
|
+
tone: "dim",
|
|
80
|
+
feedback: env.feedback,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
export function searchFooter(env) {
|
|
84
|
+
const { hint } = env;
|
|
85
|
+
return compose(env, {
|
|
86
|
+
items: [
|
|
87
|
+
{ text: `${hint("tui.select.up")} / ${hint("tui.select.down")} choose`, priority: 2 },
|
|
88
|
+
{ text: `${hint("tui.select.confirm")} locate`, priority: 1 },
|
|
89
|
+
],
|
|
90
|
+
separator: " · ",
|
|
91
|
+
escape: { text: `${hint("tui.select.cancel")} cancel`, priority: 0, action: BACK },
|
|
92
|
+
tone: "dim",
|
|
93
|
+
feedback: env.feedback,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
export function helpFooter(env) {
|
|
97
|
+
const { hint } = env;
|
|
98
|
+
return compose(env, {
|
|
99
|
+
items: [{ text: `${hint("tui.select.up")} / ${hint("tui.select.down")} scroll`, priority: 1 }],
|
|
100
|
+
separator: " · ",
|
|
101
|
+
escape: { text: `${hint("tui.select.cancel")} back`, priority: 0, action: BACK },
|
|
102
|
+
tone: "dim",
|
|
103
|
+
feedback: env.feedback,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The stop question borrows only the footer row, so the task stays in view while confirming;
|
|
108
|
+
* `source` and `title` name the target, and the title gives way first on narrow widths.
|
|
109
|
+
*/
|
|
110
|
+
export function confirmStopFooter(env, target) {
|
|
111
|
+
const { hint, width } = env;
|
|
112
|
+
const confirm = `${hint("app.tasks.confirmStop")} stop`;
|
|
113
|
+
const cancel = `${hint("tui.select.cancel")} cancel`;
|
|
114
|
+
const separator = " ";
|
|
115
|
+
const room = width - visibleWidth(cancel) - GAP - visibleWidth(separator + confirm);
|
|
116
|
+
const bare = `Stop ${target.source}?`;
|
|
117
|
+
const spare = room - visibleWidth(`Stop ${target.source} ""?`);
|
|
118
|
+
const question = spare >= 4 ? `Stop ${target.source} "${truncateToWidth(target.title, spare, "…")}"?` : bare;
|
|
119
|
+
return compose(env, {
|
|
120
|
+
items: [
|
|
121
|
+
{ text: question, priority: 0 },
|
|
122
|
+
{ text: confirm, priority: 0, action: { kind: "key", key: "app.tasks.confirmStop" } },
|
|
123
|
+
],
|
|
124
|
+
separator,
|
|
125
|
+
escape: { text: cancel, priority: 0, action: BACK },
|
|
126
|
+
tone: "warning",
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=footer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/footer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The footer row, one builder per panel mode. Context hints sit on the left, the Escape action is\n * pinned to the right edge, and transient feedback temporarily replaces the hints.\n */\nimport { truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport type { Keybinding } from \"../../../core/keybindings.ts\";\nimport type { Theme, ThemeColor } from \"../../../modes/interactive/theme/theme.ts\";\nimport type { PanelFocus, TaskAction, TaskHit } from \"./model.ts\";\n\n/** An outcome the panel does not already show: the action did not do what was asked. */\nexport interface Feedback {\n\ttone: \"warning\" | \"error\";\n\ttext: string;\n}\n\nconst FEEDBACK_GLYPH: Record<Feedback[\"tone\"], string> = { warning: \"!\", error: \"×\" };\n/** Cells kept between the left content and the pinned Escape action. */\nconst GAP = 3;\n\ninterface FooterItem {\n\ttext: string;\n\t/** Higher numbers are dropped first when the row is too narrow. */\n\tpriority: number;\n\taction?: TaskAction;\n}\n\ninterface FooterSpec {\n\titems: FooterItem[];\n\tseparator: string;\n\tescape: FooterItem;\n\ttone: ThemeColor;\n\tfeedback?: Feedback;\n}\n\nexport interface FooterEnv {\n\twidth: number;\n\t/** The footer's screen row. */\n\ty: number;\n\ttheme: Theme;\n\thint: (key: Keybinding) => string;\n\tfeedback?: Feedback;\n}\n\nexport interface Footer {\n\tline: string;\n\thits: TaskHit[];\n}\n\n/** Drops the lowest-priority items, the later of equals first, until the rest fit. */\nfunction dropToFit(items: FooterItem[], room: number, separator: string): FooterItem[] {\n\tconst kept = [...items];\n\tconst width = () =>\n\t\tkept.reduce((sum, item) => sum + visibleWidth(item.text), 0) + visibleWidth(separator) * (kept.length - 1);\n\twhile (kept.length > 1 && width() > room) {\n\t\tlet drop = 0;\n\t\tfor (const [index, item] of kept.entries()) if (item.priority >= kept[drop]!.priority) drop = index;\n\t\tkept.splice(drop, 1);\n\t}\n\treturn kept;\n}\n\nfunction compose(env: FooterEnv, spec: FooterSpec): Footer {\n\tconst { width, y, theme } = env;\n\tconst hits: TaskHit[] = [];\n\tconst escapeWidth = visibleWidth(spec.escape.text);\n\tconst room = Math.max(0, width - escapeWidth - GAP);\n\tlet showEscape = true;\n\tlet left: string;\n\tif (spec.feedback) {\n\t\tconst message = `${FEEDBACK_GLYPH[spec.feedback.tone]} ${spec.feedback.text}`;\n\t\t// A long message is worth more than the Escape hint while it lasts.\n\t\tshowEscape = visibleWidth(message) <= room;\n\t\tleft = theme.fg(spec.feedback.tone, truncateToWidth(message, showEscape ? room : width, \"…\"));\n\t} else {\n\t\tlet x = 0;\n\t\tconst kept = dropToFit(spec.items, room, spec.separator);\n\t\tfor (const item of kept) {\n\t\t\tif (item.action) hits.push({ x, y, width: visibleWidth(item.text), action: item.action });\n\t\t\tx += visibleWidth(item.text) + visibleWidth(spec.separator);\n\t\t}\n\t\tleft = theme.fg(spec.tone, truncateToWidth(kept.map((item) => item.text).join(spec.separator), room, \"…\"));\n\t}\n\tconst gap = Math.max(0, width - visibleWidth(left) - (showEscape ? escapeWidth : 0));\n\tif (showEscape && spec.escape.action)\n\t\thits.push({ x: width - escapeWidth, y, width: escapeWidth, action: spec.escape.action });\n\treturn { line: left + \" \".repeat(gap) + (showEscape ? theme.fg(spec.tone, spec.escape.text) : \"\"), hits };\n}\n\nconst BACK: TaskAction = { kind: \"back\" };\n\nexport function browseFooter(\n\tenv: FooterEnv,\n\tview: { focus: PanelFocus; split: boolean; stoppable: boolean; detachable: boolean },\n): Footer {\n\tconst { hint } = env;\n\tconst items: FooterItem[] = [];\n\tconst add = (text: string, priority: number, action?: TaskAction) => items.push({ text, priority, action });\n\tconst arrows = `${hint(\"tui.select.up\")} / ${hint(\"tui.select.down\")}`;\n\tif (view.focus === \"list\") {\n\t\tadd(`${arrows} tasks`, 5);\n\t\tadd(`${hint(\"tui.select.confirm\")} open`, 4, { kind: \"open\" });\n\t\tadd(`${hint(\"app.tasks.search\")} find`, 3, { kind: \"key\", key: \"app.tasks.search\" });\n\t} else {\n\t\tadd(`${arrows} scroll`, 5);\n\t\t// Without the list beside it, Escape is the way back.\n\t\tif (view.split) add(`${hint(\"app.tasks.nextFocus\")} tasks`, 6, { kind: \"key\", key: \"app.tasks.nextFocus\" });\n\t\tadd(`${hint(\"app.tasks.previousTab\")} output`, 6, { kind: \"tab\", tab: \"output\" });\n\t\tadd(`${hint(\"app.tasks.nextTab\")} details`, 6, { kind: \"tab\", tab: \"info\" });\n\t}\n\tif (view.stoppable) add(`${hint(\"app.tasks.kill\")} stop`, 2, { kind: \"key\", key: \"app.tasks.kill\" });\n\tif (view.detachable)\n\t\tadd(`${hint(\"app.tasks.detachSelected\")} background`, 2, { kind: \"key\", key: \"app.tasks.detachSelected\" });\n\tadd(`${hint(\"app.tasks.help\")} keys`, 1, { kind: \"key\", key: \"app.tasks.help\" });\n\tconst back = !view.split && view.focus === \"inspector\";\n\treturn compose(env, {\n\t\titems,\n\t\tseparator: \" · \",\n\t\tescape: { text: `${hint(\"tui.select.cancel\")} ${back ? \"back\" : \"close\"}`, priority: 0, action: BACK },\n\t\ttone: \"dim\",\n\t\tfeedback: env.feedback,\n\t});\n}\n\nexport function searchFooter(env: FooterEnv): Footer {\n\tconst { hint } = env;\n\treturn compose(env, {\n\t\titems: [\n\t\t\t{ text: `${hint(\"tui.select.up\")} / ${hint(\"tui.select.down\")} choose`, priority: 2 },\n\t\t\t{ text: `${hint(\"tui.select.confirm\")} locate`, priority: 1 },\n\t\t],\n\t\tseparator: \" · \",\n\t\tescape: { text: `${hint(\"tui.select.cancel\")} cancel`, priority: 0, action: BACK },\n\t\ttone: \"dim\",\n\t\tfeedback: env.feedback,\n\t});\n}\n\nexport function helpFooter(env: FooterEnv): Footer {\n\tconst { hint } = env;\n\treturn compose(env, {\n\t\titems: [{ text: `${hint(\"tui.select.up\")} / ${hint(\"tui.select.down\")} scroll`, priority: 1 }],\n\t\tseparator: \" · \",\n\t\tescape: { text: `${hint(\"tui.select.cancel\")} back`, priority: 0, action: BACK },\n\t\ttone: \"dim\",\n\t\tfeedback: env.feedback,\n\t});\n}\n\n/**\n * The stop question borrows only the footer row, so the task stays in view while confirming;\n * `source` and `title` name the target, and the title gives way first on narrow widths.\n */\nexport function confirmStopFooter(env: FooterEnv, target: { source: string; title: string }): Footer {\n\tconst { hint, width } = env;\n\tconst confirm = `${hint(\"app.tasks.confirmStop\")} stop`;\n\tconst cancel = `${hint(\"tui.select.cancel\")} cancel`;\n\tconst separator = \" \";\n\tconst room = width - visibleWidth(cancel) - GAP - visibleWidth(separator + confirm);\n\tconst bare = `Stop ${target.source}?`;\n\tconst spare = room - visibleWidth(`Stop ${target.source} \"\"?`);\n\tconst question = spare >= 4 ? `Stop ${target.source} \"${truncateToWidth(target.title, spare, \"…\")}\"?` : bare;\n\treturn compose(env, {\n\t\titems: [\n\t\t\t{ text: question, priority: 0 },\n\t\t\t{ text: confirm, priority: 0, action: { kind: \"key\", key: \"app.tasks.confirmStop\" } },\n\t\t],\n\t\tseparator,\n\t\tescape: { text: cancel, priority: 0, action: BACK },\n\t\ttone: \"warning\",\n\t});\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Theme } from "../../../modes/interactive/theme/theme.ts";
|
|
2
|
+
export interface Rect {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}
|
|
8
|
+
/** Columns from a pane's left edge to its title: the corner, one rule cell and a space. */
|
|
9
|
+
export declare const TITLE_INDENT = 3;
|
|
10
|
+
interface FrameOptions {
|
|
11
|
+
width: number;
|
|
12
|
+
theme: Theme;
|
|
13
|
+
/** The focused pane's border is accented. */
|
|
14
|
+
accent: boolean;
|
|
15
|
+
/** Styled title for the top border. */
|
|
16
|
+
title?: string;
|
|
17
|
+
/** Styled text right-aligned in the bottom border, such as a scroll range. */
|
|
18
|
+
status?: string;
|
|
19
|
+
/** Content rows, clipped or padded to the inner width. */
|
|
20
|
+
rows: string[];
|
|
21
|
+
/** Index of the content row drawn as a `├──┤` rule joined to the frame; that row's text is ignored. */
|
|
22
|
+
divider?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface Frame {
|
|
25
|
+
lines: string[];
|
|
26
|
+
/** Where the bottom-border status starts (pane-relative) and how many cells it occupies. */
|
|
27
|
+
status: {
|
|
28
|
+
x: number;
|
|
29
|
+
width: number;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** Pads or clips one content row to exactly `width` cells. */
|
|
33
|
+
export declare const fitCell: (text: string, width: number) => string;
|
|
34
|
+
export declare function framePane(options: FrameOptions): Frame;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=frame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/frame.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AAEvE,MAAM,WAAW,IAAI;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAED,2FAA2F;AAC3F,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,UAAU,YAAY;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,6CAA6C;IAC7C,MAAM,EAAE,OAAO,CAAC;IAChB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,uGAAuG;IACvG,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAK;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4FAA4F;IAC5F,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACrC;AAED,8DAA8D;AAC9D,eAAO,MAAM,OAAO,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,KAAG,MAA8D,CAAC;AAErH,wBAAgB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,KAAK,CA2BtD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Bordered pane chrome: the title sits in the top border and a status in the bottom one. */
|
|
2
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
|
+
/** Columns from a pane's left edge to its title: the corner, one rule cell and a space. */
|
|
4
|
+
export const TITLE_INDENT = 3;
|
|
5
|
+
/** Pads or clips one content row to exactly `width` cells. */
|
|
6
|
+
export const fitCell = (text, width) => truncateToWidth(text, Math.max(1, width), "…", true);
|
|
7
|
+
export function framePane(options) {
|
|
8
|
+
const { width, theme, rows } = options;
|
|
9
|
+
const border = (text) => theme.fg(options.accent ? "borderAccent" : "borderMuted", text);
|
|
10
|
+
const inner = Math.max(1, width - 2);
|
|
11
|
+
// `┌─ title ──┐` and `└── status ─┘`: three cells of corner, rule and space frame the text.
|
|
12
|
+
const room = Math.max(0, width - 5);
|
|
13
|
+
const title = options.title && room > 0 ? truncateToWidth(options.title, room, "…") : "";
|
|
14
|
+
const status = options.status && room > 0 ? truncateToWidth(options.status, room, "…") : "";
|
|
15
|
+
const top = title
|
|
16
|
+
? border("┌─ ") + title + border(` ${"─".repeat(Math.max(0, width - 5 - visibleWidth(title)))}┐`)
|
|
17
|
+
: border(`┌${"─".repeat(Math.max(0, width - 2))}┐`);
|
|
18
|
+
const statusWidth = visibleWidth(status);
|
|
19
|
+
const bottom = status
|
|
20
|
+
? border(`└${"─".repeat(Math.max(0, width - 5 - statusWidth))} `) + status + border(" ─┘")
|
|
21
|
+
: border(`└${"─".repeat(Math.max(0, width - 2))}┘`);
|
|
22
|
+
return {
|
|
23
|
+
lines: [
|
|
24
|
+
top,
|
|
25
|
+
...rows.map((row, index) => index === options.divider
|
|
26
|
+
? border(`├${"─".repeat(Math.max(0, width - 2))}┤`)
|
|
27
|
+
: border("│") + fitCell(row, inner) + border("│")),
|
|
28
|
+
bottom,
|
|
29
|
+
],
|
|
30
|
+
status: { x: Math.max(0, width - 3 - statusWidth), width: statusWidth },
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/frame.ts"],"names":[],"mappings":"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","sourcesContent":["/** Bordered pane chrome: the title sits in the top border and a status in the bottom one. */\nimport { truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\n\nexport interface Rect {\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n}\n\n/** Columns from a pane's left edge to its title: the corner, one rule cell and a space. */\nexport const TITLE_INDENT = 3;\n\ninterface FrameOptions {\n\twidth: number;\n\ttheme: Theme;\n\t/** The focused pane's border is accented. */\n\taccent: boolean;\n\t/** Styled title for the top border. */\n\ttitle?: string;\n\t/** Styled text right-aligned in the bottom border, such as a scroll range. */\n\tstatus?: string;\n\t/** Content rows, clipped or padded to the inner width. */\n\trows: string[];\n\t/** Index of the content row drawn as a `├──┤` rule joined to the frame; that row's text is ignored. */\n\tdivider?: number;\n}\n\nexport interface Frame {\n\tlines: string[];\n\t/** Where the bottom-border status starts (pane-relative) and how many cells it occupies. */\n\tstatus: { x: number; width: number };\n}\n\n/** Pads or clips one content row to exactly `width` cells. */\nexport const fitCell = (text: string, width: number): string => truncateToWidth(text, Math.max(1, width), \"…\", true);\n\nexport function framePane(options: FrameOptions): Frame {\n\tconst { width, theme, rows } = options;\n\tconst border = (text: string) => theme.fg(options.accent ? \"borderAccent\" : \"borderMuted\", text);\n\tconst inner = Math.max(1, width - 2);\n\t// `┌─ title ──┐` and `└── status ─┘`: three cells of corner, rule and space frame the text.\n\tconst room = Math.max(0, width - 5);\n\tconst title = options.title && room > 0 ? truncateToWidth(options.title, room, \"…\") : \"\";\n\tconst status = options.status && room > 0 ? truncateToWidth(options.status, room, \"…\") : \"\";\n\tconst top = title\n\t\t? border(\"┌─ \") + title + border(` ${\"─\".repeat(Math.max(0, width - 5 - visibleWidth(title)))}┐`)\n\t\t: border(`┌${\"─\".repeat(Math.max(0, width - 2))}┐`);\n\tconst statusWidth = visibleWidth(status);\n\tconst bottom = status\n\t\t? border(`└${\"─\".repeat(Math.max(0, width - 5 - statusWidth))} `) + status + border(\" ─┘\")\n\t\t: border(`└${\"─\".repeat(Math.max(0, width - 2))}┘`);\n\treturn {\n\t\tlines: [\n\t\t\ttop,\n\t\t\t...rows.map((row, index) =>\n\t\t\t\tindex === options.divider\n\t\t\t\t\t? border(`├${\"─\".repeat(Math.max(0, width - 2))}┤`)\n\t\t\t\t\t: border(\"│\") + fitCell(row, inner) + border(\"│\"),\n\t\t\t),\n\t\t\tbottom,\n\t\t],\n\t\tstatus: { x: Math.max(0, width - 3 - statusWidth), width: statusWidth },\n\t};\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** The `?` controls page: every binding grouped by purpose, with the user's current keys. */
|
|
2
|
+
import type { Keybinding } from "../../../core/keybindings.ts";
|
|
3
|
+
import type { Theme } from "../../../modes/interactive/theme/theme.ts";
|
|
4
|
+
/** Controls grouped by purpose; actions sharing a key, such as list and inspector paging, share a row. */
|
|
5
|
+
export declare function helpRows(hint: (key: Keybinding) => string, theme: Theme): string[];
|
|
6
|
+
//# sourceMappingURL=help.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/help.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAG7F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AAEvE,0GAA0G;AAC1G,wBAAgB,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,CAiDlF"}
|