@astralyn/pi 1.4.10 → 1.4.11
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 +15 -0
- package/dist/bundle/chunks/{chunk-MF3T3ETJ.js → chunk-NUQMVNKQ.js} +2 -2
- package/dist/bundle/chunks/{chunk-6GTUUUCJ.js → chunk-PUU43PDV.js} +14 -29
- package/dist/bundle/chunks/{chunk-UCH27AVQ.js → chunk-TH3QDDPD.js} +1 -1
- package/dist/bundle/chunks/{execute-FQKRO4XJ.js → execute-VLAIP26K.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-6IJ6V2CG.js → virtual-modules-63XNTSVN.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.map +1 -1
- package/dist/core/agent-session.js +0 -3
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +14 -7
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/tasks/delivery.d.ts +4 -20
- package/dist/core/tasks/delivery.d.ts.map +1 -1
- package/dist/core/tasks/delivery.js +5 -58
- package/dist/core/tasks/delivery.js.map +1 -1
- package/dist/core/tasks/limits.d.ts +3 -19
- package/dist/core/tasks/limits.d.ts.map +1 -1
- package/dist/core/tasks/limits.js +3 -24
- package/dist/core/tasks/limits.js.map +1 -1
- package/dist/core/tasks/runtime.d.ts +1 -12
- package/dist/core/tasks/runtime.d.ts.map +1 -1
- package/dist/core/tasks/runtime.js +1 -81
- package/dist/core/tasks/runtime.js.map +1 -1
- package/dist/core/tasks/session.d.ts +0 -3
- package/dist/core/tasks/session.d.ts.map +1 -1
- package/dist/core/tasks/session.js +0 -16
- package/dist/core/tasks/session.js.map +1 -1
- package/dist/core/tasks/types.d.ts +2 -74
- package/dist/core/tasks/types.d.ts.map +1 -1
- package/dist/core/tasks/types.js +2 -2
- package/dist/core/tasks/types.js.map +1 -1
- package/dist/core/tools/shell-tool.js +1 -1
- package/dist/core/tools/shell-tool.js.map +1 -1
- package/dist/extensions/cached-compaction/summary.d.ts +1 -1
- package/dist/extensions/cached-compaction/summary.d.ts.map +1 -1
- package/dist/extensions/cached-compaction/summary.js +13 -16
- package/dist/extensions/cached-compaction/summary.js.map +1 -1
- package/dist/extensions/tasks/tool/actions.d.ts +1 -2
- package/dist/extensions/tasks/tool/actions.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/actions.js +7 -79
- package/dist/extensions/tasks/tool/actions.js.map +1 -1
- package/dist/extensions/tasks/tool/constants.d.ts +1 -3
- package/dist/extensions/tasks/tool/constants.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/constants.js +1 -3
- package/dist/extensions/tasks/tool/constants.js.map +1 -1
- package/dist/extensions/tasks/tool/schema.d.ts +1 -2
- package/dist/extensions/tasks/tool/schema.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/schema.js +6 -14
- package/dist/extensions/tasks/tool/schema.js.map +1 -1
- package/dist/extensions/tasks/tool/types.d.ts +1 -19
- 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 +1 -2
- package/dist/extensions/tasks/tool.d.ts.map +1 -1
- package/dist/extensions/tasks/tool.js +2 -4
- package/dist/extensions/tasks/tool.js.map +1 -1
- package/dist/extensions/tasks/ui/render.d.ts +2 -16
- package/dist/extensions/tasks/ui/render.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/render.js +3 -79
- package/dist/extensions/tasks/ui/render.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +1 -0
- package/dist/modes/print-mode.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/docs/bundled/extensions/agent.md +2 -2
- package/docs/bundled/extensions/statusline.md +1 -1
- package/docs/bundled/tasks.md +10 -23
- package/docs/bundled/tool-presentation.md +1 -1
- package/docs/extensions.md +5 -7
- package/docs/models-configuration.md +1 -1
- package/docs/models.md +7 -85
- package/docs/sdk.md +3 -3
- package/docs/session-format.md +1 -1
- package/package.json +3 -4
- package/dist/core/tasks/wait.d.ts +0 -19
- package/dist/core/tasks/wait.d.ts.map +0 -1
- package/dist/core/tasks/wait.js +0 -45
- package/dist/core/tasks/wait.js.map +0 -1
- package/dist/modes/interactive/tool-view/tool-execution.d.ts +0 -14
- package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +0 -1
- package/dist/modes/interactive/tool-view/tool-execution.js +0 -13
- package/dist/modes/interactive/tool-view/tool-execution.js.map +0 -1
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/exy.png +0 -0
- package/npm-shrinkwrap.json +0 -4207
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/core/tasks/session.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AgentMessage, AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { CustomMessage } from \"../messages.ts\";\nimport { getTasksLateSidecarPath, type SessionEntry, type SessionManager } from \"../session-manager.ts\";\nimport { truncateHead } from \"../tools/truncate.ts\";\nimport { getTaskUsageRecord } from \"../usage-totals.ts\";\nimport { TASK_RECORD_TYPE, TASK_SNAPSHOT_VERSION } from \"./codec.ts\";\nimport { TaskDelivery } from \"./delivery.ts\";\nimport { TaskContextReminder } from \"./reminder.ts\";\nimport { TaskRuntime } from \"./runtime.ts\";\nimport { isTaskTerminal, type TaskSnapshot } from \"./types.ts\";\n\ninterface TaskSessionOptions {\n\tmanager: SessionManager;\n\tbackgroundAllowed?: boolean;\n\t/** The main session owns input queues, preflight and idle state. */\n\tcanDeliver(): boolean;\n\t/** Whether the model-facing management tool is active, which new background work requires. Omitted: no gate. */\n\tmanagementActive?(): boolean;\n\t/**\n\t * Start a completion turn, or enqueue the message and return waitForPersistence().\n\t * The host owns input routing; this adapter owns the queued delivery's lifetime.\n\t */\n\tdeliver(message: CustomMessage, waitForPersistence: () => Promise<void>): Promise<void>;\n\tonEntry(entry: SessionEntry): void;\n\tonError(event: string, message: string): void;\n}\n\nexport interface QuarantinedTaskSettlement {\n\tsessionId: string;\n\tgeneration: number;\n\ttask: TaskSnapshot;\n\tusage?: Usage;\n}\n\n/**\n * Session persistence and completion delivery; execution supervision stays in TaskRuntime.\n * A handed-off task that settles on the current service is persisted here and then enqueued in\n * TaskDelivery, which keeps it retained until the model has seen it.\n */\nexport class TaskSession {\n\tprivate readonly options: TaskSessionOptions;\n\tprivate _service: TaskRuntime;\n\tprivate enabled = false;\n\tprivate disposed = false;\n\tprivate generation = 0;\n\tprivate waitInterrupt = new AbortController();\n\tprivate readonly contextReminder = new TaskContextReminder();\n\treadonly delivery: TaskDelivery;\n\tprivate readonly quarantine: QuarantinedTaskSettlement[] = [];\n\tprivate readonly changeListeners = new Set<() => void>();\n\n\tconstructor(options: TaskSessionOptions) {\n\t\tthis.options = options;\n\t\tthis.delivery = new TaskDelivery({\n\t\t\tservice: () => this.service,\n\t\t\tcanDeliver: options.canDeliver,\n\t\t\tdeliver: options.deliver,\n\t\t\twarn: (event, message) => this.warn(event, message),\n\t\t});\n\t\tthis._service = this.createService();\n\t\tthis.delivery.subscribe(() => this.changed());\n\t}\n\n\t/** Called when background tasks, the runtime itself, or delivery state change. */\n\tsubscribe(listener: () => void): () => void {\n\t\tthis.changeListeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.changeListeners.delete(listener);\n\t\t};\n\t}\n\n\tprivate changed(): void {\n\t\tfor (const listener of [...this.changeListeners]) {\n\t\t\ttry {\n\t\t\t\tlistener();\n\t\t\t} catch {\n\t\t\t\t// Observers cannot interrupt task supervision or delivery.\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Handed-off tasks of the current runtime that have not settled. */\n\trunningBackground(): TaskSnapshot[] {\n\t\tconst service = this.service;\n\t\tif (this.disposed || service.closed) return [];\n\t\treturn service.list().filter((task) => task.mode === \"background\" && !isTaskTerminal(task.status));\n\t}\n\n\tget service(): TaskRuntime {\n\t\treturn this._service;\n\t}\n\n\t/** End only current task waits; the next wait observes a fresh signal. */\n\tinterruptWaits(): void {\n\t\tconst previous = this.waitInterrupt;\n\t\tthis.waitInterrupt = new AbortController();\n\t\tprevious.abort();\n\t}\n\n\t/** The active tools changed: availability of background detaching may have too. */\n\ttoolsChanged(): void {\n\t\tthis.service.refresh();\n\t}\n\n\tnoteCompaction(): void {\n\t\tthis.contextReminder.compacted();\n\t}\n\n\tprojectContextReminder(messages: AgentMessage[]): AgentMessage[] {\n\t\treturn this.contextReminder.project(this.service, messages);\n\t}\n\n\tnoteAssistantCompleted(): void {\n\t\tthis.contextReminder.assistantCompleted();\n\t}\n\n\tget quarantinedSettlements(): readonly QuarantinedTaskSettlement[] {\n\t\treturn structuredClone(this.quarantine);\n\t}\n\n\tsetEnabled(enabled: boolean): void {\n\t\tthis.enabled = enabled && this.options.backgroundAllowed !== false;\n\t\tthis.service.setEnabled(this.enabled);\n\t}\n\n\t/**\n\t * Running tasks that navigating to `targetId` would cancel, since results are saved on their\n\t * launch branch. Mirrors navigateTree's destination: selecting a user or custom message moves\n\t * the leaf to its parent.\n\t */\n\tstoppedByTreeNavigation(targetId: string, service = this.service): TaskSnapshot[] {\n\t\tconst target = this.options.manager.getEntry(targetId);\n\t\tif (!target) return [];\n\t\tconst leafId =\n\t\t\t(target.type === \"message\" && target.message.role === \"user\") || target.type === \"custom_message\"\n\t\t\t\t? target.parentId\n\t\t\t\t: targetId;\n\t\treturn service.activeOutsideBranch(this.branchIds(leafId));\n\t}\n\n\t/** Cancel running tasks launched outside the branch ending at `leafId`. */\n\tcancelOutsideBranch(leafId: string | null): Promise<void> {\n\t\treturn this.service.cancelOutsideBranch(this.branchIds(leafId));\n\t}\n\n\tprivate branchIds(leafId: string | null): Set<string> {\n\t\treturn new Set(leafId === null ? [] : this.options.manager.getBranch(leafId).map((entry) => entry.id));\n\t}\n\n\t/**\n\t * Close the current service, release the retention its undelivered completions hold, and\n\t * drain its executors within the grace period. Lifecycle operations pair this with replaceService().\n\t */\n\tshutdown(graceMs?: number): Promise<void> {\n\t\treturn this.service.shutdown(graceMs);\n\t}\n\n\t/** Called after the old service's bounded shutdown, while lifecycle delivery is paused. */\n\treplaceService(): void {\n\t\tthis.contextReminder.reset();\n\t\tthis.service.close();\n\t\tthis._service = this.createService();\n\t\tthis.delivery.retry();\n\t\tthis.changed();\n\t}\n\n\t/** Acknowledge that a task's completion reached its consumer by other means than automatic delivery. */\n\tacknowledgeDelivery(taskId: string): void {\n\t\tthis.delivery.acknowledge(taskId);\n\t}\n\n\tprivate createService(): TaskRuntime {\n\t\tconst { manager, backgroundAllowed } = this.options;\n\t\tconst generation = ++this.generation;\n\t\tconst sessionId = manager.getSessionId();\n\t\tconst sessionFile = manager.getSessionFile();\n\t\tconst interrupts = () => this.waitInterrupt.signal;\n\t\tconst service: TaskRuntime = new TaskRuntime({\n\t\t\tenabled: this.enabled,\n\t\t\tbackgroundAllowed,\n\t\t\tcanManageBackground: () => this.options.managementActive?.() ?? true,\n\t\t\tsession: {\n\t\t\t\tstoppedByTreeNavigation: (targetId): TaskSnapshot[] => this.stoppedByTreeNavigation(targetId, service),\n\t\t\t},\n\t\t\twaits: {\n\t\t\t\tget interruptSignal() {\n\t\t\t\t\treturn interrupts();\n\t\t\t\t},\n\t\t\t\thold: (taskIds) => this.delivery.hold(taskIds),\n\t\t\t\tbind: (toolCallId, taskId) => this.delivery.bindWait(toolCallId, taskId),\n\t\t\t},\n\t\t\tanchor: () => manager.getLeafId(),\n\t\t\tonCleanupError: (message) => this.warn(\"task_cleanup\", message),\n\t\t\tonClosed: () => this.delivery.discard(service),\n\t\t\tonSettled: (task, usage) => {\n\t\t\t\tconst current = !this.disposed && this.service === service;\n\t\t\t\tconst onBranch =\n\t\t\t\t\tmanager.getSessionId() === sessionId &&\n\t\t\t\t\t(task.anchorId === null || manager.getBranch().some((entry) => entry.id === task.anchorId));\n\t\t\t\ttry {\n\t\t\t\t\tif (current && onBranch) this.persistSettlement(task, usage);\n\t\t\t\t\telse this.quarantineSettlement({ sessionId, generation, task, usage }, sessionFile);\n\t\t\t\t} finally {\n\t\t\t\t\t// Delivery still follows a failed write, which the runtime reports. A completion hidden on\n\t\t\t\t\t// another branch waits for its branch; a replaced service delivers nothing.\n\t\t\t\t\tif (current && task.mode === \"background\") this.delivery.enqueue(service, task.id);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tthis.restoreHistory(service);\n\t\tservice.subscribe(() => {\n\t\t\tthis.delivery.schedule();\n\t\t\tthis.changed();\n\t\t});\n\t\treturn service;\n\t}\n\n\trestoreHistory(service = this.service): void {\n\t\tconst records: unknown[] = [];\n\t\tconst toolResults = new Map<string, AgentToolResult<unknown>[\"content\"]>();\n\t\tfor (const entry of this.options.manager.getBranch()) {\n\t\t\tif (entry.type === \"custom\" && entry.customType === TASK_RECORD_TYPE) records.push(entry.data);\n\t\t\telse if (entry.type === \"message\" && entry.message.role === \"toolResult\")\n\t\t\t\ttoolResults.set(entry.message.toolCallId, entry.message.content);\n\t\t}\n\t\tservice.restoreHistory(records, toolResults);\n\t}\n\n\tprivate quarantineSettlement(record: QuarantinedTaskSettlement, sessionFile: string | undefined): void {\n\t\t// Never move the active leaf to append late usage: JSONL's last entry also\n\t\t// selects its resumed branch. The sidecar is diagnostic evidence only.\n\t\tthis.quarantine.push(structuredClone(record));\n\t\tif (this.quarantine.length > 32) this.quarantine.shift();\n\t\tlet persistence =\n\t\t\t\"Not persisted: only the latest 32 snapshots are retained in quarantinedTaskSettlements; late usage is not accounted in session totals.\";\n\t\tif (sessionFile) {\n\t\t\ttry {\n\t\t\t\tmkdirSync(dirname(sessionFile), { recursive: true });\n\t\t\t\tconst sidecar = getTasksLateSidecarPath(sessionFile);\n\t\t\t\tappendFileSync(sidecar, `${JSON.stringify({ version: 1, ...record })}\\n`);\n\t\t\t\tpersistence = `Saved diagnostic sidecar: ${sidecar} (not included in normal session totals).`;\n\t\t\t} catch {\n\t\t\t\tpersistence = `Sidecar write failed. ${persistence}`;\n\t\t\t}\n\t\t}\n\t\tthis.warn(\n\t\t\t\"task_settlement_quarantined\",\n\t\t\t`Late background settlement ${record.task.id} was quarantined. ${persistence}`,\n\t\t);\n\t}\n\n\t/** One entry per settlement: the bounded terminal snapshot and its first usage settlement. */\n\tprivate persistSettlement(task: TaskSnapshot, usage: Usage | undefined): void {\n\t\tconst manager = this.options.manager;\n\t\tconst accounted = usage && manager.getEntries().some((entry) => getTaskUsageRecord(entry)?.taskId === task.id);\n\t\t// A foreground result is the tool result the transcript already saves; restoration reads it from there.\n\t\tconst { result: _result, ...metadata } = task;\n\t\tconst saved = task.mode === \"foreground\" ? metadata : task;\n\t\tconst data = JSON.parse(\n\t\t\tJSON.stringify({ version: TASK_SNAPSHOT_VERSION, task: saved, ...(usage && !accounted ? { usage } : {}) }),\n\t\t);\n\t\tconst entry = manager.getEntry(manager.appendCustomEntry(TASK_RECORD_TYPE, data));\n\t\tif (!entry) return;\n\t\ttry {\n\t\t\tthis.options.onEntry(entry);\n\t\t} catch {\n\t\t\t// Observers cannot interrupt settlement or result publication.\n\t\t}\n\t}\n\n\tprivate warn(event: string, message: string): void {\n\t\ttry {\n\t\t\tthis.options.onError(event, truncateHead(message, { maxBytes: 4096, maxLines: 32 }).content);\n\t\t} catch {\n\t\t\t// Diagnostics cannot reject settlement, cleanup or scheduled callbacks.\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tthis.contextReminder.reset();\n\t\tthis.interruptWaits();\n\t\tthis.service.close();\n\t\tthis.delivery.dispose();\n\t\tthis.changeListeners.clear();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/core/tasks/session.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AgentMessage, AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { CustomMessage } from \"../messages.ts\";\nimport { getTasksLateSidecarPath, type SessionEntry, type SessionManager } from \"../session-manager.ts\";\nimport { truncateHead } from \"../tools/truncate.ts\";\nimport { getTaskUsageRecord } from \"../usage-totals.ts\";\nimport { TASK_RECORD_TYPE, TASK_SNAPSHOT_VERSION } from \"./codec.ts\";\nimport { TaskDelivery } from \"./delivery.ts\";\nimport { TaskContextReminder } from \"./reminder.ts\";\nimport { TaskRuntime } from \"./runtime.ts\";\nimport { isTaskTerminal, type TaskSnapshot } from \"./types.ts\";\n\ninterface TaskSessionOptions {\n\tmanager: SessionManager;\n\tbackgroundAllowed?: boolean;\n\t/** The main session owns input queues, preflight and idle state. */\n\tcanDeliver(): boolean;\n\t/** Whether the model-facing management tool is active, which new background work requires. Omitted: no gate. */\n\tmanagementActive?(): boolean;\n\t/**\n\t * Start a completion turn, or enqueue the message and return waitForPersistence().\n\t * The host owns input routing; this adapter owns the queued delivery's lifetime.\n\t */\n\tdeliver(message: CustomMessage, waitForPersistence: () => Promise<void>): Promise<void>;\n\tonEntry(entry: SessionEntry): void;\n\tonError(event: string, message: string): void;\n}\n\nexport interface QuarantinedTaskSettlement {\n\tsessionId: string;\n\tgeneration: number;\n\ttask: TaskSnapshot;\n\tusage?: Usage;\n}\n\n/**\n * Session persistence and completion delivery; execution supervision stays in TaskRuntime.\n * A handed-off task that settles on the current service is persisted here and then enqueued in\n * TaskDelivery, which keeps it retained until the model has seen it.\n */\nexport class TaskSession {\n\tprivate readonly options: TaskSessionOptions;\n\tprivate _service: TaskRuntime;\n\tprivate enabled = false;\n\tprivate disposed = false;\n\tprivate generation = 0;\n\tprivate readonly contextReminder = new TaskContextReminder();\n\treadonly delivery: TaskDelivery;\n\tprivate readonly quarantine: QuarantinedTaskSettlement[] = [];\n\tprivate readonly changeListeners = new Set<() => void>();\n\n\tconstructor(options: TaskSessionOptions) {\n\t\tthis.options = options;\n\t\tthis.delivery = new TaskDelivery({\n\t\t\tservice: () => this.service,\n\t\t\tcanDeliver: options.canDeliver,\n\t\t\tdeliver: options.deliver,\n\t\t\twarn: (event, message) => this.warn(event, message),\n\t\t});\n\t\tthis._service = this.createService();\n\t\tthis.delivery.subscribe(() => this.changed());\n\t}\n\n\t/** Called when background tasks, the runtime itself, or delivery state change. */\n\tsubscribe(listener: () => void): () => void {\n\t\tthis.changeListeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.changeListeners.delete(listener);\n\t\t};\n\t}\n\n\tprivate changed(): void {\n\t\tfor (const listener of [...this.changeListeners]) {\n\t\t\ttry {\n\t\t\t\tlistener();\n\t\t\t} catch {\n\t\t\t\t// Observers cannot interrupt task supervision or delivery.\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Handed-off tasks of the current runtime that have not settled. */\n\trunningBackground(): TaskSnapshot[] {\n\t\tconst service = this.service;\n\t\tif (this.disposed || service.closed) return [];\n\t\treturn service.list().filter((task) => task.mode === \"background\" && !isTaskTerminal(task.status));\n\t}\n\n\tget service(): TaskRuntime {\n\t\treturn this._service;\n\t}\n\n\t/** The active tools changed: availability of background detaching may have too. */\n\ttoolsChanged(): void {\n\t\tthis.service.refresh();\n\t}\n\n\tnoteCompaction(): void {\n\t\tthis.contextReminder.compacted();\n\t}\n\n\tprojectContextReminder(messages: AgentMessage[]): AgentMessage[] {\n\t\treturn this.contextReminder.project(this.service, messages);\n\t}\n\n\tnoteAssistantCompleted(): void {\n\t\tthis.contextReminder.assistantCompleted();\n\t}\n\n\tget quarantinedSettlements(): readonly QuarantinedTaskSettlement[] {\n\t\treturn structuredClone(this.quarantine);\n\t}\n\n\tsetEnabled(enabled: boolean): void {\n\t\tthis.enabled = enabled && this.options.backgroundAllowed !== false;\n\t\tthis.service.setEnabled(this.enabled);\n\t}\n\n\t/**\n\t * Running tasks that navigating to `targetId` would cancel, since results are saved on their\n\t * launch branch. Mirrors navigateTree's destination: selecting a user or custom message moves\n\t * the leaf to its parent.\n\t */\n\tstoppedByTreeNavigation(targetId: string, service = this.service): TaskSnapshot[] {\n\t\tconst target = this.options.manager.getEntry(targetId);\n\t\tif (!target) return [];\n\t\tconst leafId =\n\t\t\t(target.type === \"message\" && target.message.role === \"user\") || target.type === \"custom_message\"\n\t\t\t\t? target.parentId\n\t\t\t\t: targetId;\n\t\treturn service.activeOutsideBranch(this.branchIds(leafId));\n\t}\n\n\t/** Cancel running tasks launched outside the branch ending at `leafId`. */\n\tcancelOutsideBranch(leafId: string | null): Promise<void> {\n\t\treturn this.service.cancelOutsideBranch(this.branchIds(leafId));\n\t}\n\n\tprivate branchIds(leafId: string | null): Set<string> {\n\t\treturn new Set(leafId === null ? [] : this.options.manager.getBranch(leafId).map((entry) => entry.id));\n\t}\n\n\t/**\n\t * Close the current service, release the retention its undelivered completions hold, and\n\t * drain its executors within the grace period. Lifecycle operations pair this with replaceService().\n\t */\n\tshutdown(graceMs?: number): Promise<void> {\n\t\treturn this.service.shutdown(graceMs);\n\t}\n\n\t/** Called after the old service's bounded shutdown, while lifecycle delivery is paused. */\n\treplaceService(): void {\n\t\tthis.contextReminder.reset();\n\t\tthis.service.close();\n\t\tthis._service = this.createService();\n\t\tthis.delivery.retry();\n\t\tthis.changed();\n\t}\n\n\t/** Acknowledge that a task's completion reached its consumer by other means than automatic delivery. */\n\tacknowledgeDelivery(taskId: string): void {\n\t\tthis.delivery.acknowledge(taskId);\n\t}\n\n\tprivate createService(): TaskRuntime {\n\t\tconst { manager, backgroundAllowed } = this.options;\n\t\tconst generation = ++this.generation;\n\t\tconst sessionId = manager.getSessionId();\n\t\tconst sessionFile = manager.getSessionFile();\n\t\tconst service: TaskRuntime = new TaskRuntime({\n\t\t\tenabled: this.enabled,\n\t\t\tbackgroundAllowed,\n\t\t\tcanManageBackground: () => this.options.managementActive?.() ?? true,\n\t\t\tsession: {\n\t\t\t\tstoppedByTreeNavigation: (targetId): TaskSnapshot[] => this.stoppedByTreeNavigation(targetId, service),\n\t\t\t},\n\t\t\tanchor: () => manager.getLeafId(),\n\t\t\tonCleanupError: (message) => this.warn(\"task_cleanup\", message),\n\t\t\tonClosed: () => this.delivery.discard(service),\n\t\t\tonSettled: (task, usage) => {\n\t\t\t\tconst current = !this.disposed && this.service === service;\n\t\t\t\tconst onBranch =\n\t\t\t\t\tmanager.getSessionId() === sessionId &&\n\t\t\t\t\t(task.anchorId === null || manager.getBranch().some((entry) => entry.id === task.anchorId));\n\t\t\t\ttry {\n\t\t\t\t\tif (current && onBranch) this.persistSettlement(task, usage);\n\t\t\t\t\telse this.quarantineSettlement({ sessionId, generation, task, usage }, sessionFile);\n\t\t\t\t} finally {\n\t\t\t\t\t// Delivery still follows a failed write, which the runtime reports. A completion hidden on\n\t\t\t\t\t// another branch waits for its branch; a replaced service delivers nothing.\n\t\t\t\t\tif (current && task.mode === \"background\") this.delivery.enqueue(service, task.id);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tthis.restoreHistory(service);\n\t\tservice.subscribe(() => {\n\t\t\tthis.delivery.schedule();\n\t\t\tthis.changed();\n\t\t});\n\t\treturn service;\n\t}\n\n\trestoreHistory(service = this.service): void {\n\t\tconst records: unknown[] = [];\n\t\tconst toolResults = new Map<string, AgentToolResult<unknown>[\"content\"]>();\n\t\tfor (const entry of this.options.manager.getBranch()) {\n\t\t\tif (entry.type === \"custom\" && entry.customType === TASK_RECORD_TYPE) records.push(entry.data);\n\t\t\telse if (entry.type === \"message\" && entry.message.role === \"toolResult\")\n\t\t\t\ttoolResults.set(entry.message.toolCallId, entry.message.content);\n\t\t}\n\t\tservice.restoreHistory(records, toolResults);\n\t}\n\n\tprivate quarantineSettlement(record: QuarantinedTaskSettlement, sessionFile: string | undefined): void {\n\t\t// Never move the active leaf to append late usage: JSONL's last entry also\n\t\t// selects its resumed branch. The sidecar is diagnostic evidence only.\n\t\tthis.quarantine.push(structuredClone(record));\n\t\tif (this.quarantine.length > 32) this.quarantine.shift();\n\t\tlet persistence =\n\t\t\t\"Not persisted: only the latest 32 snapshots are retained in quarantinedTaskSettlements; late usage is not accounted in session totals.\";\n\t\tif (sessionFile) {\n\t\t\ttry {\n\t\t\t\tmkdirSync(dirname(sessionFile), { recursive: true });\n\t\t\t\tconst sidecar = getTasksLateSidecarPath(sessionFile);\n\t\t\t\tappendFileSync(sidecar, `${JSON.stringify({ version: 1, ...record })}\\n`);\n\t\t\t\tpersistence = `Saved diagnostic sidecar: ${sidecar} (not included in normal session totals).`;\n\t\t\t} catch {\n\t\t\t\tpersistence = `Sidecar write failed. ${persistence}`;\n\t\t\t}\n\t\t}\n\t\tthis.warn(\n\t\t\t\"task_settlement_quarantined\",\n\t\t\t`Late background settlement ${record.task.id} was quarantined. ${persistence}`,\n\t\t);\n\t}\n\n\t/** One entry per settlement: the bounded terminal snapshot and its first usage settlement. */\n\tprivate persistSettlement(task: TaskSnapshot, usage: Usage | undefined): void {\n\t\tconst manager = this.options.manager;\n\t\tconst accounted = usage && manager.getEntries().some((entry) => getTaskUsageRecord(entry)?.taskId === task.id);\n\t\t// A foreground result is the tool result the transcript already saves; restoration reads it from there.\n\t\tconst { result: _result, ...metadata } = task;\n\t\tconst saved = task.mode === \"foreground\" ? metadata : task;\n\t\tconst data = JSON.parse(\n\t\t\tJSON.stringify({ version: TASK_SNAPSHOT_VERSION, task: saved, ...(usage && !accounted ? { usage } : {}) }),\n\t\t);\n\t\tconst entry = manager.getEntry(manager.appendCustomEntry(TASK_RECORD_TYPE, data));\n\t\tif (!entry) return;\n\t\ttry {\n\t\t\tthis.options.onEntry(entry);\n\t\t} catch {\n\t\t\t// Observers cannot interrupt settlement or result publication.\n\t\t}\n\t}\n\n\tprivate warn(event: string, message: string): void {\n\t\ttry {\n\t\t\tthis.options.onError(event, truncateHead(message, { maxBytes: 4096, maxLines: 32 }).content);\n\t\t} catch {\n\t\t\t// Diagnostics cannot reject settlement, cleanup or scheduled callbacks.\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tthis.contextReminder.reset();\n\t\tthis.service.close();\n\t\tthis.delivery.dispose();\n\t\tthis.changeListeners.clear();\n\t}\n}\n"]}
|
|
@@ -177,63 +177,6 @@ export interface TasksSessionContext {
|
|
|
177
177
|
/** Running tasks that navigating to `targetId` would cancel on this session branch. */
|
|
178
178
|
stoppedByTreeNavigation(targetId: string): TaskSnapshot[];
|
|
179
179
|
}
|
|
180
|
-
/** How a wait ended. `closed` means the host shut down, so execution state is unconfirmed. */
|
|
181
|
-
export type TaskWaitOutcome = "settled" | "interrupted" | "timed_out" | "closed";
|
|
182
|
-
interface TaskObservationOptions {
|
|
183
|
-
/** Defaults to 20 seconds and is bounded by the runtime. A timeout never cancels execution. */
|
|
184
|
-
timeoutMs?: number;
|
|
185
|
-
/** Rejects the wait with the signal's reason; execution continues. */
|
|
186
|
-
signal?: AbortSignal;
|
|
187
|
-
/**
|
|
188
|
-
* The tool call whose result carries this observation to the model. With a session host, a
|
|
189
|
-
* settled background task stays out of automatic notifications until that result is persisted.
|
|
190
|
-
* Without it, or in a standalone runtime, the wait is purely observational.
|
|
191
|
-
*/
|
|
192
|
-
toolCallId?: string;
|
|
193
|
-
}
|
|
194
|
-
export interface TaskWaitOptions extends TaskObservationOptions {
|
|
195
|
-
/** Read output while delivery is still held; skipped when steering interrupted the wait. */
|
|
196
|
-
read?: Pick<TaskReadOptions, "bytes" | "sinceBytes">;
|
|
197
|
-
}
|
|
198
|
-
export interface TaskWaitResult {
|
|
199
|
-
outcome: TaskWaitOutcome;
|
|
200
|
-
waitedMs: number;
|
|
201
|
-
/** The task when the wait ended, before `read` was taken. */
|
|
202
|
-
task: TaskSnapshot;
|
|
203
|
-
read?: TaskRead;
|
|
204
|
-
}
|
|
205
|
-
export interface TaskWaitAnyOptions extends TaskObservationOptions {
|
|
206
|
-
/** Read the settled task's output while delivery is still held. */
|
|
207
|
-
read?: Pick<TaskReadOptions, "bytes">;
|
|
208
|
-
}
|
|
209
|
-
export interface TaskWaitAnyResult {
|
|
210
|
-
/** `no_tasks`: no background task was running at call time, so nothing was observed. */
|
|
211
|
-
outcome: TaskWaitOutcome | "no_tasks";
|
|
212
|
-
waitedMs: number;
|
|
213
|
-
/** The first cohort member to settle; present only for `settled`. */
|
|
214
|
-
task?: TaskSnapshot;
|
|
215
|
-
read?: TaskRead;
|
|
216
|
-
/** Cohort members still running when the wait ended. */
|
|
217
|
-
running: TaskSnapshot[];
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Host hooks that make waits part of a durable session. TaskSession supplies them; products
|
|
221
|
-
* embedding a bare TaskRuntime omit them and keep waits observational.
|
|
222
|
-
*/
|
|
223
|
-
export interface TaskWaitHost {
|
|
224
|
-
/** Current steering signal. Aborting it ends management waits only, never execution. */
|
|
225
|
-
readonly interruptSignal: AbortSignal;
|
|
226
|
-
/**
|
|
227
|
-
* Keep `taskIds` out of automatic delivery until the returned release runs. The runtime holds
|
|
228
|
-
* the observed records for the whole observation: before waiting, until after `bind`.
|
|
229
|
-
*/
|
|
230
|
-
hold(taskIds: readonly string[]): () => void;
|
|
231
|
-
/**
|
|
232
|
-
* A wait observed a settled background task and its `toolCallId` is known. Called while the
|
|
233
|
-
* observation hold is still in place; the host takes over until that tool result persists.
|
|
234
|
-
*/
|
|
235
|
-
bind(toolCallId: string, taskId: string): void;
|
|
236
|
-
}
|
|
237
180
|
/** Session-bound public capability. Captured instances close on runtime replacement. */
|
|
238
181
|
export interface TasksContext {
|
|
239
182
|
readonly enabled: boolean;
|
|
@@ -249,18 +192,6 @@ export interface TasksContext {
|
|
|
249
192
|
* settled or presenter-less task, or when the presenter throws; callers then use the default view.
|
|
250
193
|
*/
|
|
251
194
|
presentOutput(id: string, width: number, theme: Theme): string[] | undefined;
|
|
252
|
-
/**
|
|
253
|
-
* Observe one task. With `toolCallId` in a session host, the whole observation (wait, read,
|
|
254
|
-
* receipt) is atomic with respect to automatic delivery; a standalone runtime never
|
|
255
|
-
* acknowledges delivery. Rejects with `TaskLookupError` for an unknown or ambiguous id.
|
|
256
|
-
*/
|
|
257
|
-
wait(id: string, options?: TaskWaitOptions): Promise<TaskWaitResult>;
|
|
258
|
-
/**
|
|
259
|
-
* Observe the first task running at call time to settle. Tasks started later are excluded,
|
|
260
|
-
* and `no_tasks` is returned for an empty cohort. Delivery holds cover the whole cohort until
|
|
261
|
-
* the observation completes; members other than the winner then resume ordinary notification.
|
|
262
|
-
*/
|
|
263
|
-
waitAny(options?: TaskWaitAnyOptions): Promise<TaskWaitAnyResult>;
|
|
264
195
|
kill(id: string): boolean;
|
|
265
196
|
/**
|
|
266
197
|
* Move running foreground executions to the background while background slots remain;
|
|
@@ -280,8 +211,6 @@ export interface TaskRuntimeOptions {
|
|
|
280
211
|
backgroundAllowed?: boolean;
|
|
281
212
|
/** Branch-impact queries for a durable host; standalone runtimes omit it. */
|
|
282
213
|
session?: TasksSessionContext;
|
|
283
|
-
/** Wait receipts and steering interruption for a durable host; standalone runtimes leave waits observational. */
|
|
284
|
-
waits?: TaskWaitHost;
|
|
285
214
|
anchor?: () => string | null;
|
|
286
215
|
/** Admission limit for unsettled background tasks; foreground work is bounded by its caller. */
|
|
287
216
|
maxBackground?: number;
|
|
@@ -301,11 +230,11 @@ export interface TaskRuntimeOptions {
|
|
|
301
230
|
}
|
|
302
231
|
/**
|
|
303
232
|
* The model-facing management tool, owned by the bundled `builtin:tasks` extension. Background
|
|
304
|
-
* work is admitted only while it is active, so the model can always read
|
|
233
|
+
* work is admitted only while it is active, so the model can always read and stop what
|
|
305
234
|
* it starts. Model-facing copy names it through this constant.
|
|
306
235
|
*/
|
|
307
236
|
export declare const TASKS_TOOL_NAME = "tasks";
|
|
308
|
-
export declare const TASK_MANAGEMENT_REJECTION = "Background execution needs the tasks tool to read
|
|
237
|
+
export declare const TASK_MANAGEMENT_REJECTION = "Background execution needs the tasks tool to read and stop the work, and it is not active. Activate the tasks tool or run in the foreground. No work was started.";
|
|
309
238
|
export declare const TASK_BACKGROUND_REJECTION = "Background execution is not permitted in this host. Run with background: false or omit background. No work was started.";
|
|
310
239
|
export declare function isTaskTerminal(status: TaskStatus): status is TaskTerminalStatus;
|
|
311
240
|
/**
|
|
@@ -319,5 +248,4 @@ export declare class TaskLookupError extends Error {
|
|
|
319
248
|
readonly matches: TaskSnapshot[];
|
|
320
249
|
constructor(kind: "unknown" | "ambiguous", matches: TaskSnapshot[]);
|
|
321
250
|
}
|
|
322
|
-
export {};
|
|
323
251
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/types.ts"],"names":[],"mappings":"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"}
|
package/dist/core/tasks/types.js
CHANGED
|
@@ -2,11 +2,11 @@ export const TASK_TERMINAL_STATUSES = ["completed", "partial", "failed", "cancel
|
|
|
2
2
|
export const TASK_KIND_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;
|
|
3
3
|
/**
|
|
4
4
|
* The model-facing management tool, owned by the bundled `builtin:tasks` extension. Background
|
|
5
|
-
* work is admitted only while it is active, so the model can always read
|
|
5
|
+
* work is admitted only while it is active, so the model can always read and stop what
|
|
6
6
|
* it starts. Model-facing copy names it through this constant.
|
|
7
7
|
*/
|
|
8
8
|
export const TASKS_TOOL_NAME = "tasks";
|
|
9
|
-
export const TASK_MANAGEMENT_REJECTION = `Background execution needs the ${TASKS_TOOL_NAME} tool to read
|
|
9
|
+
export const TASK_MANAGEMENT_REJECTION = `Background execution needs the ${TASKS_TOOL_NAME} tool to read and stop the work, and it is not active. Activate the ${TASKS_TOOL_NAME} tool or run in the foreground. No work was started.`;
|
|
10
10
|
export const TASK_BACKGROUND_REJECTION = "Background execution is not permitted in this host. Run with background: false or omit background. No work was started.";
|
|
11
11
|
export function isTaskTerminal(status) {
|
|
12
12
|
return TASK_TERMINAL_STATUSES.includes(status);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/tasks/types.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAU,CAAC;AAG1G,MAAM,CAAC,MAAM,iBAAiB,GAAG,wBAAwB,CAAC;AA6S1D;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAEvC,MAAM,CAAC,MAAM,yBAAyB,GAAG,kCAAkC,eAAe,iFAAiF,eAAe,sDAAsD,CAAC;AAEjP,MAAM,CAAC,MAAM,yBAAyB,GACrC,yHAAyH,CAAC;AAE3H,MAAM,UAAU,cAAc,CAAC,MAAkB;IAChD,OAAQ,sBAA4C,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACvE,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAGzC,YAAY,IAA6B,EAAE,OAAuB;QACjE,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD","sourcesContent":["import type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\n\n/** An executor-owned machine source: the task ID prefix, never a dispatch key for the runtime. */\nexport type TaskKind = string;\n/**\n * Where the task actually runs. `background` exactly when its caller was released with a\n * background outcome; a caller that is waiting, or was asked to leave but is still held while\n * the executor prepares, is `foreground`.\n */\nexport type TaskMode = \"foreground\" | \"background\";\nexport const TASK_TERMINAL_STATUSES = [\"completed\", \"partial\", \"failed\", \"cancelled\", \"timeout\"] as const;\nexport type TaskTerminalStatus = (typeof TASK_TERMINAL_STATUSES)[number];\nexport type TaskStatus = \"queued\" | \"running\" | \"stopping\" | TaskTerminalStatus;\nexport const TASK_KIND_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;\n\n/**\n * How a task's output is shaped, declared by its executor:\n * a `log` streams and carries its outcome at the end; a `report` is one finished document.\n */\nexport type TaskOutputKind = \"log\" | \"report\";\n\n/** A bounded snapshot; truncation is recorded at the source, never inferred from text. */\nexport interface TaskText {\n\ttext: string;\n\ttruncated: boolean;\n}\n\n/** What the task was asked to do, such as a shell command or a delegated briefing. */\nexport interface TaskInput extends TaskText {\n\t/** Human label for the input, such as \"Command\" or \"Prompt\". */\n\tlabel: string;\n\t/** Optional syntax-highlighting language. */\n\tlanguage?: string;\n}\n\n/** One labelled Details row, such as [\"Directory\", \"/repo\"] or [\"Exit\", \"1\"]. */\nexport type TaskFact = readonly [label: string, value: string];\n\n/** A read-only view of one task; the runtime returns frozen snapshots. */\nexport interface TaskSnapshot {\n\tid: string;\n\tkind: TaskKind;\n\t/** Human source name, such as \"Bash\" or \"Agent\". */\n\tlabel: string;\n\ttitle: string;\n\toutput: TaskOutputKind;\n\tinput?: TaskInput;\n\tfacts?: TaskFact[];\n\ttoolCallId: string;\n\tanchorId: string | null;\n\tmode: TaskMode;\n\tstatus: TaskStatus;\n\tstartedAt: number;\n\tendedAt?: number;\n\toutputPath?: string;\n\t/** Bounded model-readable result text. */\n\tresult?: TaskText;\n\t/**\n\t * The executor's human-only view. In /tasks it replaces the result as what a person reads;\n\t * model-facing reads always use `result`. A terminal snapshot has one only if the completion\n\t * supplied it: the last progress display does not survive settlement.\n\t */\n\tdisplay?: TaskText;\n\terror?: string;\n}\n\nexport interface TaskUpdate<T> {\n\t/** Model-readable progress; also forwarded to a foreground caller's onUpdate. */\n\tresult: AgentToolResult<T>;\n\t/** The live human-only view while running; replaces the result in /tasks and ends at settlement. */\n\tdisplay?: string;\n\t/** Cumulative usage so far, settled once if the execution ends without a final usage. */\n\tusage?: Usage;\n}\n\nexport interface TaskCompletion<T> {\n\tresult: AgentToolResult<T>;\n\t/** Defaults to completed, or cancelled when the task was already cancelled. */\n\tstatus?: TaskTerminalStatus;\n\t/**\n\t * The terminal human-only view. In /tasks it replaces the result as what a person reads; model-facing\n\t * reads and completion context always use `result`. Without it, the terminal snapshot has no display.\n\t */\n\tdisplay?: string;\n\t/** Terminal diagnostic, stored independently of log slices and bounded to 4096 bytes. */\n\terror?: string;\n\t/** Terminal Details rows; a label replaces the same label given at launch. */\n\tfacts?: TaskFact[];\n\t/** Authoritative cumulative usage; overrides the result's usage and the latest published usage. */\n\tusage?: Usage;\n}\n\nexport interface TaskControl<T> {\n\treadonly id: string;\n\treadonly signal: AbortSignal;\n\t/** Actual placement: `background` only once the caller was released. */\n\treadonly mode: TaskMode;\n\t/** Called once the caller is released and the mode becomes `background`. */\n\tonModeChange(listener: (mode: TaskMode) => void): () => void;\n\t/** The executor's own preflight passed; from now on the caller may be handed off to the background. */\n\taccept(): void;\n\tpublish(update: TaskUpdate<T>): void;\n\t/** Register once; cleanup must own only this exclusively-created file and close its writer first. */\n\tattachOutput(path: string, cleanup?: () => void | Promise<void>): void;\n\t/** Cancel this execution, for example when an executor policy limit is exceeded. */\n\tcancel(): void;\n}\n\n/**\n * Renders a live task's human Output in the Tasks panel: styled, already fitted lines of at most\n * `width` columns, or `undefined` to use the default view (the published `display`, else the\n * result). Called on every repaint while the task runs, so it must be cheap and synchronous.\n * It lives in memory with the running task: never persisted, absent from snapshots, and dropped\n * at settlement. The returned text is trusted extension output, not task text.\n */\nexport type TaskPresenter = (width: number, theme: Theme) => string[] | undefined;\n\nexport interface TaskExecution<T> {\n\tkind: TaskKind;\n\t/** Human source name; defaults to `kind`. */\n\tlabel?: string;\n\ttitle: string;\n\t/** Defaults to `log`. */\n\toutput?: TaskOutputKind;\n\tinput?: TaskInput;\n\tfacts?: TaskFact[];\n\ttoolCallId: string;\n\tbackground?: boolean;\n\t/**\n\t * At most `limit` executions sharing `key` run at once; lanes belong to one `kind`, so another\n\t * executor may reuse the key. Later ones wait as queued tasks whose `run` starts when a slot\n\t * frees; a queued task can be handed off or cancelled.\n\t */\n\tconcurrency?: { key: string; limit: number };\n\tsignal?: AbortSignal;\n\tonUpdate?: (result: AgentToolResult<T>) => void;\n\t/** Renders the running task's Output in /tasks; see {@link TaskPresenter}. Dropped at settlement. */\n\tpresent?: TaskPresenter;\n\trun(control: TaskControl<T>): Promise<TaskCompletion<T>>;\n}\n\n/**\n * How a tool call ends. A `background` outcome says why the caller was released: `submitted`\n * when it asked for background, `detached` when it was moved while the work ran.\n */\nexport type TaskToolOutcome<T> =\n\t| { kind: \"result\"; result: AgentToolResult<T>; status: TaskTerminalStatus; error?: string }\n\t| { kind: \"background\"; task: TaskSnapshot; reason: \"submitted\" | \"detached\" };\n\n/** Which slice of a task's output to read. Defaults to 8 KiB. */\nexport interface TaskReadOptions {\n\t/**\n\t * `head` reads the start of the output, `tail` its end. Without it a `report` is read from its\n\t * start and a `log` from its end.\n\t */\n\tmode?: \"head\" | \"tail\";\n\t/** Maximum bytes to return, bounded by the runtime. */\n\tbytes?: number;\n\t/**\n\t * First unread byte. `head` reads forward from this offset; `tail` returns the newest window\n\t * at or after it. Without it the output kind selects the default end.\n\t */\n\tsinceBytes?: number;\n}\n\nexport interface TaskRead {\n\ttask: TaskSnapshot;\n\ttext: string;\n\t/** Bounded log-read/expiry diagnostic, independent of text slicing and byte offsets. */\n\treadError?: string;\n\ttotalBytes: number;\n\ttruncated: boolean;\n\tfromByte?: number;\n\t/** Raw source-byte end supplied by the runtime; older/custom hosts may omit it. */\n\tendByte?: number;\n}\n\n/** Optional host integration for products built on the execution runtime. */\nexport interface TasksSessionContext {\n\t/** Running tasks that navigating to `targetId` would cancel on this session branch. */\n\tstoppedByTreeNavigation(targetId: string): TaskSnapshot[];\n}\n\n/** How a wait ended. `closed` means the host shut down, so execution state is unconfirmed. */\nexport type TaskWaitOutcome = \"settled\" | \"interrupted\" | \"timed_out\" | \"closed\";\n\ninterface TaskObservationOptions {\n\t/** Defaults to 20 seconds and is bounded by the runtime. A timeout never cancels execution. */\n\ttimeoutMs?: number;\n\t/** Rejects the wait with the signal's reason; execution continues. */\n\tsignal?: AbortSignal;\n\t/**\n\t * The tool call whose result carries this observation to the model. With a session host, a\n\t * settled background task stays out of automatic notifications until that result is persisted.\n\t * Without it, or in a standalone runtime, the wait is purely observational.\n\t */\n\ttoolCallId?: string;\n}\n\nexport interface TaskWaitOptions extends TaskObservationOptions {\n\t/** Read output while delivery is still held; skipped when steering interrupted the wait. */\n\tread?: Pick<TaskReadOptions, \"bytes\" | \"sinceBytes\">;\n}\n\nexport interface TaskWaitResult {\n\toutcome: TaskWaitOutcome;\n\twaitedMs: number;\n\t/** The task when the wait ended, before `read` was taken. */\n\ttask: TaskSnapshot;\n\tread?: TaskRead;\n}\n\nexport interface TaskWaitAnyOptions extends TaskObservationOptions {\n\t/** Read the settled task's output while delivery is still held. */\n\tread?: Pick<TaskReadOptions, \"bytes\">;\n}\n\nexport interface TaskWaitAnyResult {\n\t/** `no_tasks`: no background task was running at call time, so nothing was observed. */\n\toutcome: TaskWaitOutcome | \"no_tasks\";\n\twaitedMs: number;\n\t/** The first cohort member to settle; present only for `settled`. */\n\ttask?: TaskSnapshot;\n\tread?: TaskRead;\n\t/** Cohort members still running when the wait ended. */\n\trunning: TaskSnapshot[];\n}\n\n/**\n * Host hooks that make waits part of a durable session. TaskSession supplies them; products\n * embedding a bare TaskRuntime omit them and keep waits observational.\n */\nexport interface TaskWaitHost {\n\t/** Current steering signal. Aborting it ends management waits only, never execution. */\n\treadonly interruptSignal: AbortSignal;\n\t/**\n\t * Keep `taskIds` out of automatic delivery until the returned release runs. The runtime holds\n\t * the observed records for the whole observation: before waiting, until after `bind`.\n\t */\n\thold(taskIds: readonly string[]): () => void;\n\t/**\n\t * A wait observed a settled background task and its `toolCallId` is known. Called while the\n\t * observation hold is still in place; the host takes over until that tool result persists.\n\t */\n\tbind(toolCallId: string, taskId: string): void;\n}\n\n/** Session-bound public capability. Captured instances close on runtime replacement. */\nexport interface TasksContext {\n\treadonly enabled: boolean;\n\treadonly closed?: boolean;\n\t/** Present when the runtime is attached to Pi's durable session lifecycle. */\n\treadonly session?: TasksSessionContext;\n\texecute<T>(execution: TaskExecution<T>): Promise<TaskToolOutcome<T>>;\n\tlist(): TaskSnapshot[];\n\tget(id: string): TaskSnapshot;\n\tread(id: string, options?: TaskReadOptions): Promise<TaskRead>;\n\t/**\n\t * The running task's live Output from its executor's `present`, or `undefined` for an unknown,\n\t * settled or presenter-less task, or when the presenter throws; callers then use the default view.\n\t */\n\tpresentOutput(id: string, width: number, theme: Theme): string[] | undefined;\n\t/**\n\t * Observe one task. With `toolCallId` in a session host, the whole observation (wait, read,\n\t * receipt) is atomic with respect to automatic delivery; a standalone runtime never\n\t * acknowledges delivery. Rejects with `TaskLookupError` for an unknown or ambiguous id.\n\t */\n\twait(id: string, options?: TaskWaitOptions): Promise<TaskWaitResult>;\n\t/**\n\t * Observe the first task running at call time to settle. Tasks started later are excluded,\n\t * and `no_tasks` is returned for an empty cohort. Delivery holds cover the whole cohort until\n\t * the observation completes; members other than the winner then resume ordinary notification.\n\t */\n\twaitAny(options?: TaskWaitAnyOptions): Promise<TaskWaitAnyResult>;\n\tkill(id: string): boolean;\n\t/**\n\t * Move running foreground executions to the background while background slots remain;\n\t * returns how many moved. Throws when eligible work exists but every slot is taken.\n\t */\n\tdetachForeground(): number;\n\t/** Whether this execution can move now, including host policy and available background slots. */\n\tcanDetach(id: string): boolean;\n\t/** Returns false when the task cannot move; throws when every background slot is taken. */\n\tdetach(id: string): boolean;\n\tsubscribe(listener: () => void): () => void;\n\t/** Keep retained output available without delaying completion delivery. */\n\tretain(id: string): () => void;\n}\n\nexport interface TaskRuntimeOptions {\n\tenabled?: boolean;\n\tbackgroundAllowed?: boolean;\n\t/** Branch-impact queries for a durable host; standalone runtimes omit it. */\n\tsession?: TasksSessionContext;\n\t/** Wait receipts and steering interruption for a durable host; standalone runtimes leave waits observational. */\n\twaits?: TaskWaitHost;\n\tanchor?: () => string | null;\n\t/** Admission limit for unsettled background tasks; foreground work is bounded by its caller. */\n\tmaxBackground?: number;\n\t/** Per-history limit: foreground and background tasks each get this allowance. */\n\tmaxHistory?: number;\n\t/** Best-effort cleanup errors, bounded to 4096 bytes; no retries or execution failure. */\n\tonCleanupError?: (message: string) => void;\n\t/** Synchronous persistence before terminal observers or notifications. */\n\tonSettled?: (task: TaskSnapshot, usage: Usage | undefined) => void;\n\t/**\n\t * Whether the host can supervise new background work, such as its management tool being\n\t * active. Gates admission and detaching only; work already admitted is unaffected.\n\t */\n\tcanManageBackground?: () => boolean;\n\t/** The runtime closed: a host holding retention pins for it must release them so output cleanup runs. */\n\tonClosed?: () => void;\n}\n\n/**\n * The model-facing management tool, owned by the bundled `builtin:tasks` extension. Background\n * work is admitted only while it is active, so the model can always read, wait for and stop what\n * it starts. Model-facing copy names it through this constant.\n */\nexport const TASKS_TOOL_NAME = \"tasks\";\n\nexport const TASK_MANAGEMENT_REJECTION = `Background execution needs the ${TASKS_TOOL_NAME} tool to read, wait for and stop the work, and it is not active. Activate the ${TASKS_TOOL_NAME} tool or run in the foreground. No work was started.`;\n\nexport const TASK_BACKGROUND_REJECTION =\n\t\"Background execution is not permitted in this host. Run with background: false or omit background. No work was started.\";\n\nexport function isTaskTerminal(status: TaskStatus): status is TaskTerminalStatus {\n\treturn (TASK_TERMINAL_STATUSES as readonly string[]).includes(status);\n}\n\n/**\n * A failed id lookup, typed so hosts can enrich the message without matching\n * on message text. `matches` snapshots exactly the records the id or prefix\n * resolved against — including records outside the current branch, which\n * list() hides but prefix matching still collides with.\n */\nexport class TaskLookupError extends Error {\n\treadonly kind: \"unknown\" | \"ambiguous\";\n\treadonly matches: TaskSnapshot[];\n\tconstructor(kind: \"unknown\" | \"ambiguous\", matches: TaskSnapshot[]) {\n\t\tsuper(kind === \"ambiguous\" ? \"Ambiguous task ID\" : \"Unknown task ID\");\n\t\tthis.name = \"TaskLookupError\";\n\t\tthis.kind = kind;\n\t\tthis.matches = matches;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/tasks/types.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAU,CAAC;AAG1G,MAAM,CAAC,MAAM,iBAAiB,GAAG,wBAAwB,CAAC;AA+N1D;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAEvC,MAAM,CAAC,MAAM,yBAAyB,GAAG,kCAAkC,eAAe,uEAAuE,eAAe,sDAAsD,CAAC;AAEvO,MAAM,CAAC,MAAM,yBAAyB,GACrC,yHAAyH,CAAC;AAE3H,MAAM,UAAU,cAAc,CAAC,MAAkB;IAChD,OAAQ,sBAA4C,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACvE,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAGzC,YAAY,IAA6B,EAAE,OAAuB;QACjE,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD","sourcesContent":["import type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\n\n/** An executor-owned machine source: the task ID prefix, never a dispatch key for the runtime. */\nexport type TaskKind = string;\n/**\n * Where the task actually runs. `background` exactly when its caller was released with a\n * background outcome; a caller that is waiting, or was asked to leave but is still held while\n * the executor prepares, is `foreground`.\n */\nexport type TaskMode = \"foreground\" | \"background\";\nexport const TASK_TERMINAL_STATUSES = [\"completed\", \"partial\", \"failed\", \"cancelled\", \"timeout\"] as const;\nexport type TaskTerminalStatus = (typeof TASK_TERMINAL_STATUSES)[number];\nexport type TaskStatus = \"queued\" | \"running\" | \"stopping\" | TaskTerminalStatus;\nexport const TASK_KIND_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;\n\n/**\n * How a task's output is shaped, declared by its executor:\n * a `log` streams and carries its outcome at the end; a `report` is one finished document.\n */\nexport type TaskOutputKind = \"log\" | \"report\";\n\n/** A bounded snapshot; truncation is recorded at the source, never inferred from text. */\nexport interface TaskText {\n\ttext: string;\n\ttruncated: boolean;\n}\n\n/** What the task was asked to do, such as a shell command or a delegated briefing. */\nexport interface TaskInput extends TaskText {\n\t/** Human label for the input, such as \"Command\" or \"Prompt\". */\n\tlabel: string;\n\t/** Optional syntax-highlighting language. */\n\tlanguage?: string;\n}\n\n/** One labelled Details row, such as [\"Directory\", \"/repo\"] or [\"Exit\", \"1\"]. */\nexport type TaskFact = readonly [label: string, value: string];\n\n/** A read-only view of one task; the runtime returns frozen snapshots. */\nexport interface TaskSnapshot {\n\tid: string;\n\tkind: TaskKind;\n\t/** Human source name, such as \"Bash\" or \"Agent\". */\n\tlabel: string;\n\ttitle: string;\n\toutput: TaskOutputKind;\n\tinput?: TaskInput;\n\tfacts?: TaskFact[];\n\ttoolCallId: string;\n\tanchorId: string | null;\n\tmode: TaskMode;\n\tstatus: TaskStatus;\n\tstartedAt: number;\n\tendedAt?: number;\n\toutputPath?: string;\n\t/** Bounded model-readable result text. */\n\tresult?: TaskText;\n\t/**\n\t * The executor's human-only view. In /tasks it replaces the result as what a person reads;\n\t * model-facing reads always use `result`. A terminal snapshot has one only if the completion\n\t * supplied it: the last progress display does not survive settlement.\n\t */\n\tdisplay?: TaskText;\n\terror?: string;\n}\n\nexport interface TaskUpdate<T> {\n\t/** Model-readable progress; also forwarded to a foreground caller's onUpdate. */\n\tresult: AgentToolResult<T>;\n\t/** The live human-only view while running; replaces the result in /tasks and ends at settlement. */\n\tdisplay?: string;\n\t/** Cumulative usage so far, settled once if the execution ends without a final usage. */\n\tusage?: Usage;\n}\n\nexport interface TaskCompletion<T> {\n\tresult: AgentToolResult<T>;\n\t/** Defaults to completed, or cancelled when the task was already cancelled. */\n\tstatus?: TaskTerminalStatus;\n\t/**\n\t * The terminal human-only view. In /tasks it replaces the result as what a person reads; model-facing\n\t * reads and completion context always use `result`. Without it, the terminal snapshot has no display.\n\t */\n\tdisplay?: string;\n\t/** Terminal diagnostic, stored independently of log slices and bounded to 4096 bytes. */\n\terror?: string;\n\t/** Terminal Details rows; a label replaces the same label given at launch. */\n\tfacts?: TaskFact[];\n\t/** Authoritative cumulative usage; overrides the result's usage and the latest published usage. */\n\tusage?: Usage;\n}\n\nexport interface TaskControl<T> {\n\treadonly id: string;\n\treadonly signal: AbortSignal;\n\t/** Actual placement: `background` only once the caller was released. */\n\treadonly mode: TaskMode;\n\t/** Called once the caller is released and the mode becomes `background`. */\n\tonModeChange(listener: (mode: TaskMode) => void): () => void;\n\t/** The executor's own preflight passed; from now on the caller may be handed off to the background. */\n\taccept(): void;\n\tpublish(update: TaskUpdate<T>): void;\n\t/** Register once; cleanup must own only this exclusively-created file and close its writer first. */\n\tattachOutput(path: string, cleanup?: () => void | Promise<void>): void;\n\t/** Cancel this execution, for example when an executor policy limit is exceeded. */\n\tcancel(): void;\n}\n\n/**\n * Renders a live task's human Output in the Tasks panel: styled, already fitted lines of at most\n * `width` columns, or `undefined` to use the default view (the published `display`, else the\n * result). Called on every repaint while the task runs, so it must be cheap and synchronous.\n * It lives in memory with the running task: never persisted, absent from snapshots, and dropped\n * at settlement. The returned text is trusted extension output, not task text.\n */\nexport type TaskPresenter = (width: number, theme: Theme) => string[] | undefined;\n\nexport interface TaskExecution<T> {\n\tkind: TaskKind;\n\t/** Human source name; defaults to `kind`. */\n\tlabel?: string;\n\ttitle: string;\n\t/** Defaults to `log`. */\n\toutput?: TaskOutputKind;\n\tinput?: TaskInput;\n\tfacts?: TaskFact[];\n\ttoolCallId: string;\n\tbackground?: boolean;\n\t/**\n\t * At most `limit` executions sharing `key` run at once; lanes belong to one `kind`, so another\n\t * executor may reuse the key. Later ones wait as queued tasks whose `run` starts when a slot\n\t * frees; a queued task can be handed off or cancelled.\n\t */\n\tconcurrency?: { key: string; limit: number };\n\tsignal?: AbortSignal;\n\tonUpdate?: (result: AgentToolResult<T>) => void;\n\t/** Renders the running task's Output in /tasks; see {@link TaskPresenter}. Dropped at settlement. */\n\tpresent?: TaskPresenter;\n\trun(control: TaskControl<T>): Promise<TaskCompletion<T>>;\n}\n\n/**\n * How a tool call ends. A `background` outcome says why the caller was released: `submitted`\n * when it asked for background, `detached` when it was moved while the work ran.\n */\nexport type TaskToolOutcome<T> =\n\t| { kind: \"result\"; result: AgentToolResult<T>; status: TaskTerminalStatus; error?: string }\n\t| { kind: \"background\"; task: TaskSnapshot; reason: \"submitted\" | \"detached\" };\n\n/** Which slice of a task's output to read. Defaults to 8 KiB. */\nexport interface TaskReadOptions {\n\t/**\n\t * `head` reads the start of the output, `tail` its end. Without it a `report` is read from its\n\t * start and a `log` from its end.\n\t */\n\tmode?: \"head\" | \"tail\";\n\t/** Maximum bytes to return, bounded by the runtime. */\n\tbytes?: number;\n\t/**\n\t * First unread byte. `head` reads forward from this offset; `tail` returns the newest window\n\t * at or after it. Without it the output kind selects the default end.\n\t */\n\tsinceBytes?: number;\n}\n\nexport interface TaskRead {\n\ttask: TaskSnapshot;\n\ttext: string;\n\t/** Bounded log-read/expiry diagnostic, independent of text slicing and byte offsets. */\n\treadError?: string;\n\ttotalBytes: number;\n\ttruncated: boolean;\n\tfromByte?: number;\n\t/** Raw source-byte end supplied by the runtime; older/custom hosts may omit it. */\n\tendByte?: number;\n}\n\n/** Optional host integration for products built on the execution runtime. */\nexport interface TasksSessionContext {\n\t/** Running tasks that navigating to `targetId` would cancel on this session branch. */\n\tstoppedByTreeNavigation(targetId: string): TaskSnapshot[];\n}\n\n/** Session-bound public capability. Captured instances close on runtime replacement. */\nexport interface TasksContext {\n\treadonly enabled: boolean;\n\treadonly closed?: boolean;\n\t/** Present when the runtime is attached to Pi's durable session lifecycle. */\n\treadonly session?: TasksSessionContext;\n\texecute<T>(execution: TaskExecution<T>): Promise<TaskToolOutcome<T>>;\n\tlist(): TaskSnapshot[];\n\tget(id: string): TaskSnapshot;\n\tread(id: string, options?: TaskReadOptions): Promise<TaskRead>;\n\t/**\n\t * The running task's live Output from its executor's `present`, or `undefined` for an unknown,\n\t * settled or presenter-less task, or when the presenter throws; callers then use the default view.\n\t */\n\tpresentOutput(id: string, width: number, theme: Theme): string[] | undefined;\n\tkill(id: string): boolean;\n\t/**\n\t * Move running foreground executions to the background while background slots remain;\n\t * returns how many moved. Throws when eligible work exists but every slot is taken.\n\t */\n\tdetachForeground(): number;\n\t/** Whether this execution can move now, including host policy and available background slots. */\n\tcanDetach(id: string): boolean;\n\t/** Returns false when the task cannot move; throws when every background slot is taken. */\n\tdetach(id: string): boolean;\n\tsubscribe(listener: () => void): () => void;\n\t/** Keep retained output available without delaying completion delivery. */\n\tretain(id: string): () => void;\n}\n\nexport interface TaskRuntimeOptions {\n\tenabled?: boolean;\n\tbackgroundAllowed?: boolean;\n\t/** Branch-impact queries for a durable host; standalone runtimes omit it. */\n\tsession?: TasksSessionContext;\n\tanchor?: () => string | null;\n\t/** Admission limit for unsettled background tasks; foreground work is bounded by its caller. */\n\tmaxBackground?: number;\n\t/** Per-history limit: foreground and background tasks each get this allowance. */\n\tmaxHistory?: number;\n\t/** Best-effort cleanup errors, bounded to 4096 bytes; no retries or execution failure. */\n\tonCleanupError?: (message: string) => void;\n\t/** Synchronous persistence before terminal observers or notifications. */\n\tonSettled?: (task: TaskSnapshot, usage: Usage | undefined) => void;\n\t/**\n\t * Whether the host can supervise new background work, such as its management tool being\n\t * active. Gates admission and detaching only; work already admitted is unaffected.\n\t */\n\tcanManageBackground?: () => boolean;\n\t/** The runtime closed: a host holding retention pins for it must release them so output cleanup runs. */\n\tonClosed?: () => void;\n}\n\n/**\n * The model-facing management tool, owned by the bundled `builtin:tasks` extension. Background\n * work is admitted only while it is active, so the model can always read and stop what\n * it starts. Model-facing copy names it through this constant.\n */\nexport const TASKS_TOOL_NAME = \"tasks\";\n\nexport const TASK_MANAGEMENT_REJECTION = `Background execution needs the ${TASKS_TOOL_NAME} tool to read and stop the work, and it is not active. Activate the ${TASKS_TOOL_NAME} tool or run in the foreground. No work was started.`;\n\nexport const TASK_BACKGROUND_REJECTION =\n\t\"Background execution is not permitted in this host. Run with background: false or omit background. No work was started.\";\n\nexport function isTaskTerminal(status: TaskStatus): status is TaskTerminalStatus {\n\treturn (TASK_TERMINAL_STATUSES as readonly string[]).includes(status);\n}\n\n/**\n * A failed id lookup, typed so hosts can enrich the message without matching\n * on message text. `matches` snapshots exactly the records the id or prefix\n * resolved against — including records outside the current branch, which\n * list() hides but prefix matching still collides with.\n */\nexport class TaskLookupError extends Error {\n\treadonly kind: \"unknown\" | \"ambiguous\";\n\treadonly matches: TaskSnapshot[];\n\tconstructor(kind: \"unknown\" | \"ambiguous\", matches: TaskSnapshot[]) {\n\t\tsuper(kind === \"ambiguous\" ? \"Ambiguous task ID\" : \"Unknown task ID\");\n\t\tthis.name = \"TaskLookupError\";\n\t\tthis.kind = kind;\n\t\tthis.matches = matches;\n\t}\n}\n"]}
|
|
@@ -59,7 +59,7 @@ export function createShellToolDefinition(cwd, config, options) {
|
|
|
59
59
|
return {
|
|
60
60
|
name: config.name,
|
|
61
61
|
label: config.label,
|
|
62
|
-
description: `Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr, truncated to the last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first); the full output is saved to a temp file. Optionally provide a timeout in seconds (no default). Choose the mode per call: foreground (default) blocks until the command exits — use it when your next step needs the output; background: true returns immediately with a task ID — use it for long-running work (builds, servers, watchers, big test suites) or when you have independent work to continue. A handoff is not completion: the result arrives later as an automatic completion notification; meanwhile use ${TASKS_TOOL_NAME} read to inspect output
|
|
62
|
+
description: `Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr, truncated to the last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first); the full output is saved to a temp file. Optionally provide a timeout in seconds (no default). Choose the mode per call: foreground (default) blocks until the command exits — use it when your next step needs the output; background: true returns immediately with a task ID — use it for long-running work (builds, servers, watchers, big test suites) or when you have independent work to continue. A handoff is not completion: the result arrives later as an automatic completion notification; meanwhile use ${TASKS_TOOL_NAME} read to inspect output and ${TASKS_TOOL_NAME} kill to stop it. Background output is limited to 20 MiB.`,
|
|
63
63
|
promptSnippet: config.promptSnippet,
|
|
64
64
|
promptGuidelines: exposeSessionEnvironment && config.promptGuidelines ? [...config.promptGuidelines] : undefined,
|
|
65
65
|
parameters: bashSchema,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell-tool.js","sourceRoot":"","sources":["../../../src/core/tools/shell-tool.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\nimport { TaskRuntime } from \"../tasks/runtime.ts\";\nimport { TASKS_TOOL_NAME, type TaskCompletion, type TaskControl, type TaskToolOutcome } from \"../tasks/types.ts\";\nimport {\n\ttype BashOperations,\n\ttype BashToolOptions,\n\tresolveSpawnContext,\n\tresolveTimeoutMs,\n\ttype ShellToolConfig,\n} from \"./bash.ts\";\nimport { createShellRenderers } from \"./renderers/bash.ts\";\nimport { runShellCommand } from \"./shell-execution.ts\";\nimport { createLocalBashOperations } from \"./shell-operations.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, type TruncationResult } from \"./truncate.ts\";\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Shell command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n\tbackground: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription:\n\t\t\t\t\"true returns a managed task ID immediately and runs the command in the background, and you are notified when it completes — do not poll for its result; omit or false to block until exit\",\n\t\t}),\n\t),\n});\n\nexport const bashToolSystemPromptContribution = {\n\tsnippet: \"Execute bash commands, foreground or background\",\n\tguidelines: [\"You can inspect PI_* environment variables for current model and session details.\"],\n} as const;\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nconst bashOutputSchema = Type.Union([\n\tType.Object({\n\t\toutput: Type.String({\n\t\t\tdescription: \"Combined stdout and stderr, up to 1 MiB, keeping head and tail when truncated.\",\n\t\t}),\n\t\ttruncated: Type.Boolean(),\n\t\tfull_output_path: Type.Optional(Type.String()),\n\t\texit_code: Type.Number(),\n\t\twall_time_seconds: Type.Number(),\n\t}),\n\tType.Object({ task_id: Type.String(), status: Type.String() }),\n]);\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n\t/** Settled handoff snapshot, not a command completion or exit code. */\n\tbackground?: { kind: \"background\"; taskId: string };\n}\n\nexport type BashRenderState = {\n\tdispose?: () => void;\n};\n\n/**\n * Translate terminal shell failures to the native foreground tool contract once. A task result\n * holds the command's output only; the foreground text is that output followed by the failure.\n */\nfunction shellToolResult(completion: TaskCompletion<BashToolDetails | undefined>) {\n\tconst status = completion.status;\n\tconst output = completion.result.content\n\t\t.filter((part) => part.type === \"text\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\\n\");\n\tconst withError = (error: string) => (output ? `${output}\\n\\n${error}` : error);\n\tif (completion.result.structuredContent) {\n\t\tif (!completion.result.isError || !completion.error) return completion.result;\n\t\treturn { ...completion.result, content: [{ type: \"text\" as const, text: withError(completion.error) }] };\n\t}\n\tif (status === \"failed\" || status === \"timeout\" || status === \"cancelled\") {\n\t\tthrow new Error(\n\t\t\tcompletion.error ? withError(completion.error) : `${output ? `${output}\\n\\n` : \"\"}Command ${status}`,\n\t\t);\n\t}\n\treturn completion.result;\n}\n\nexport function createShellToolDefinition(\n\tcwd: string,\n\tconfig: ShellToolConfig,\n\toptions: BashToolOptions & { operations: BashOperations },\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst ops = options.operations;\n\tconst commandPrefix = options?.commandPrefix;\n\tconst exposeSessionEnvironment = options?.exposeSessionEnvironment ?? true;\n\tconst spawnHook = options?.spawnHook;\n\treturn {\n\t\tname: config.name,\n\t\tlabel: config.label,\n\t\tdescription: `Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr, truncated to the last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first); the full output is saved to a temp file. Optionally provide a timeout in seconds (no default). Choose the mode per call: foreground (default) blocks until the command exits — use it when your next step needs the output; background: true returns immediately with a task ID — use it for long-running work (builds, servers, watchers, big test suites) or when you have independent work to continue. A handoff is not completion: the result arrives later as an automatic completion notification; meanwhile use ${TASKS_TOOL_NAME} read to inspect output, ${TASKS_TOOL_NAME} wait with an ID for one task or without one for any running task, and ${TASKS_TOOL_NAME} kill to stop it. Steering interrupts only a wait, never execution. Background output is limited to 20 MiB; an expired ${TASKS_TOOL_NAME} wait window never stops the command.`,\n\t\tpromptSnippet: config.promptSnippet,\n\t\tpromptGuidelines: exposeSessionEnvironment && config.promptGuidelines ? [...config.promptGuidelines] : undefined,\n\t\tparameters: bashSchema,\n\t\toutputSchema: bashOutputSchema,\n\t\tconstrainedSampling: { type: \"json_schema\", strict: \"prefer\" },\n\t\tasync execute(\n\t\t\ttoolCallId,\n\t\t\t{ command, timeout, background }: BashToolInput,\n\t\t\tparentSignal?: AbortSignal,\n\t\t\toriginalUpdate?,\n\t\t\tctx?: ExtensionContext,\n\t\t) {\n\t\t\tconst sessionTasks = ctx?.tasks;\n\t\t\tif (sessionTasks?.closed) throw new Error(\"Task service is closed\");\n\t\t\tif (!sessionTasks && background)\n\t\t\t\tthrow new Error(\"Background execution is not available in this host. No command was started.\");\n\t\t\t// Without a session the command still runs as a task, on a throwaway runtime that never backgrounds.\n\t\t\tconst standalone = sessionTasks ? undefined : new TaskRuntime();\n\t\t\tconst run = async (\n\t\t\t\tcontrol: TaskControl<BashToolDetails | undefined>,\n\t\t\t): Promise<TaskCompletion<BashToolDetails | undefined>> => {\n\t\t\t\tif (control.signal.aborted) throw new Error(\"Command aborted\");\n\t\t\t\tresolveTimeoutMs(timeout);\n\t\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\t\tconst spawnContext = resolveSpawnContext(\n\t\t\t\t\tresolvedCommand,\n\t\t\t\t\tctx?.cwd || cwd,\n\t\t\t\t\tspawnHook,\n\t\t\t\t\texposeSessionEnvironment,\n\t\t\t\t\tctx,\n\t\t\t\t);\n\t\t\t\t// A setup throw settles the task as failed, or cancelled once its signal fired.\n\t\t\t\treturn await runShellCommand({\n\t\t\t\t\toperations: ops,\n\t\t\t\t\tcontext: spawnContext,\n\t\t\t\t\ttempFilePrefix: config.tempFilePrefix,\n\t\t\t\t\ttimeout,\n\t\t\t\t\tcontrol,\n\t\t\t\t\ttaskLog: sessionTasks !== undefined,\n\t\t\t\t});\n\t\t\t};\n\t\t\tlet outcome: TaskToolOutcome<BashToolDetails | undefined>;\n\t\t\ttry {\n\t\t\t\toutcome = await (sessionTasks ?? standalone!).execute<BashToolDetails | undefined>({\n\t\t\t\t\tkind: config.name,\n\t\t\t\t\tlabel: config.shellName[0]!.toUpperCase() + config.shellName.slice(1),\n\t\t\t\t\ttitle: command,\n\t\t\t\t\tinput: { label: \"Command\", text: command, truncated: false, language: config.name },\n\t\t\t\t\tfacts: [[\"Directory\", ctx?.cwd || cwd]],\n\t\t\t\t\ttoolCallId,\n\t\t\t\t\tbackground,\n\t\t\t\t\tsignal: parentSignal,\n\t\t\t\t\tonUpdate: originalUpdate,\n\t\t\t\t\trun,\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\tstandalone?.close();\n\t\t\t}\n\t\t\tif (outcome.kind === \"result\") return shellToolResult(outcome);\n\t\t\tconst tail = `Task ID: ${outcome.task.id}. Status: ${outcome.task.status}. Completion arrives and wakes you automatically — do not poll or wait on it; continue with other work, or end your turn and hand back to the user. If you would only wait for the result, prefer foreground next time. Use ${TASKS_TOOL_NAME} read to inspect output or ${TASKS_TOOL_NAME} kill to stop it.`;\n\t\t\t// Shell execution can become background work in two ways, and the model has to know which\n\t\t\t// one it got: a submitted background command starts from an empty log, while a detached\n\t\t\t// one already holds output and keeps its original timeout.\n\t\t\tconst handoff =\n\t\t\t\toutcome.reason === \"submitted\"\n\t\t\t\t\t? `Command handed to background. ${tail}`\n\t\t\t\t\t: `Command moved to the background while it was running, by the user. The execution continues unchanged — no restart, and a supplied timeout is still measured from command startup. Output produced so far is already in the log, so ${TASKS_TOOL_NAME} read now returns partial output, not a fresh start. ${tail}`;\n\t\t\treturn {\n\t\t\t\tstructuredContent: { task_id: outcome.task.id, status: outcome.task.status },\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `${handoff}${outcome.task.outputPath ? `\\nFull output: ${outcome.task.outputPath}` : \"\"}`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails: {\n\t\t\t\t\tbackground: { kind: \"background\", taskId: outcome.task.id },\n\t\t\t\t\tfullOutputPath: outcome.task.outputPath,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t...createShellRenderers(config),\n\t};\n}\n\nconst bashToolConfig: ShellToolConfig = {\n\tname: \"bash\",\n\tlabel: \"bash\",\n\tshellName: \"bash\",\n\tprompt: \"$\",\n\tpromptSnippet: bashToolSystemPromptContribution.snippet,\n\tpromptGuidelines: bashToolSystemPromptContribution.guidelines,\n\ttempFilePrefix: \"pi-bash\",\n};\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ReturnType<typeof createShellToolDefinition> {\n\treturn createShellToolDefinition(cwd, bashToolConfig, {\n\t\t...options,\n\t\toperations: options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath }),\n\t});\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions) {\n\tconst definition = createBashToolDefinition(cwd, options);\n\tconst tool = wrapToolDefinition(definition);\n\tObject.assign(tool, {\n\t\tpromptSnippet: definition.promptSnippet,\n\t\tpromptGuidelines: definition.promptGuidelines,\n\t});\n\treturn tool;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shell-tool.js","sourceRoot":"","sources":["../../../src/core/tools/shell-tool.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\nimport { TaskRuntime } from \"../tasks/runtime.ts\";\nimport { TASKS_TOOL_NAME, type TaskCompletion, type TaskControl, type TaskToolOutcome } from \"../tasks/types.ts\";\nimport {\n\ttype BashOperations,\n\ttype BashToolOptions,\n\tresolveSpawnContext,\n\tresolveTimeoutMs,\n\ttype ShellToolConfig,\n} from \"./bash.ts\";\nimport { createShellRenderers } from \"./renderers/bash.ts\";\nimport { runShellCommand } from \"./shell-execution.ts\";\nimport { createLocalBashOperations } from \"./shell-operations.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, type TruncationResult } from \"./truncate.ts\";\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Shell command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n\tbackground: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription:\n\t\t\t\t\"true returns a managed task ID immediately and runs the command in the background, and you are notified when it completes — do not poll for its result; omit or false to block until exit\",\n\t\t}),\n\t),\n});\n\nexport const bashToolSystemPromptContribution = {\n\tsnippet: \"Execute bash commands, foreground or background\",\n\tguidelines: [\"You can inspect PI_* environment variables for current model and session details.\"],\n} as const;\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nconst bashOutputSchema = Type.Union([\n\tType.Object({\n\t\toutput: Type.String({\n\t\t\tdescription: \"Combined stdout and stderr, up to 1 MiB, keeping head and tail when truncated.\",\n\t\t}),\n\t\ttruncated: Type.Boolean(),\n\t\tfull_output_path: Type.Optional(Type.String()),\n\t\texit_code: Type.Number(),\n\t\twall_time_seconds: Type.Number(),\n\t}),\n\tType.Object({ task_id: Type.String(), status: Type.String() }),\n]);\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n\t/** Settled handoff snapshot, not a command completion or exit code. */\n\tbackground?: { kind: \"background\"; taskId: string };\n}\n\nexport type BashRenderState = {\n\tdispose?: () => void;\n};\n\n/**\n * Translate terminal shell failures to the native foreground tool contract once. A task result\n * holds the command's output only; the foreground text is that output followed by the failure.\n */\nfunction shellToolResult(completion: TaskCompletion<BashToolDetails | undefined>) {\n\tconst status = completion.status;\n\tconst output = completion.result.content\n\t\t.filter((part) => part.type === \"text\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\\n\");\n\tconst withError = (error: string) => (output ? `${output}\\n\\n${error}` : error);\n\tif (completion.result.structuredContent) {\n\t\tif (!completion.result.isError || !completion.error) return completion.result;\n\t\treturn { ...completion.result, content: [{ type: \"text\" as const, text: withError(completion.error) }] };\n\t}\n\tif (status === \"failed\" || status === \"timeout\" || status === \"cancelled\") {\n\t\tthrow new Error(\n\t\t\tcompletion.error ? withError(completion.error) : `${output ? `${output}\\n\\n` : \"\"}Command ${status}`,\n\t\t);\n\t}\n\treturn completion.result;\n}\n\nexport function createShellToolDefinition(\n\tcwd: string,\n\tconfig: ShellToolConfig,\n\toptions: BashToolOptions & { operations: BashOperations },\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst ops = options.operations;\n\tconst commandPrefix = options?.commandPrefix;\n\tconst exposeSessionEnvironment = options?.exposeSessionEnvironment ?? true;\n\tconst spawnHook = options?.spawnHook;\n\treturn {\n\t\tname: config.name,\n\t\tlabel: config.label,\n\t\tdescription: `Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr, truncated to the last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first); the full output is saved to a temp file. Optionally provide a timeout in seconds (no default). Choose the mode per call: foreground (default) blocks until the command exits — use it when your next step needs the output; background: true returns immediately with a task ID — use it for long-running work (builds, servers, watchers, big test suites) or when you have independent work to continue. A handoff is not completion: the result arrives later as an automatic completion notification; meanwhile use ${TASKS_TOOL_NAME} read to inspect output and ${TASKS_TOOL_NAME} kill to stop it. Background output is limited to 20 MiB.`,\n\t\tpromptSnippet: config.promptSnippet,\n\t\tpromptGuidelines: exposeSessionEnvironment && config.promptGuidelines ? [...config.promptGuidelines] : undefined,\n\t\tparameters: bashSchema,\n\t\toutputSchema: bashOutputSchema,\n\t\tconstrainedSampling: { type: \"json_schema\", strict: \"prefer\" },\n\t\tasync execute(\n\t\t\ttoolCallId,\n\t\t\t{ command, timeout, background }: BashToolInput,\n\t\t\tparentSignal?: AbortSignal,\n\t\t\toriginalUpdate?,\n\t\t\tctx?: ExtensionContext,\n\t\t) {\n\t\t\tconst sessionTasks = ctx?.tasks;\n\t\t\tif (sessionTasks?.closed) throw new Error(\"Task service is closed\");\n\t\t\tif (!sessionTasks && background)\n\t\t\t\tthrow new Error(\"Background execution is not available in this host. No command was started.\");\n\t\t\t// Without a session the command still runs as a task, on a throwaway runtime that never backgrounds.\n\t\t\tconst standalone = sessionTasks ? undefined : new TaskRuntime();\n\t\t\tconst run = async (\n\t\t\t\tcontrol: TaskControl<BashToolDetails | undefined>,\n\t\t\t): Promise<TaskCompletion<BashToolDetails | undefined>> => {\n\t\t\t\tif (control.signal.aborted) throw new Error(\"Command aborted\");\n\t\t\t\tresolveTimeoutMs(timeout);\n\t\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\t\tconst spawnContext = resolveSpawnContext(\n\t\t\t\t\tresolvedCommand,\n\t\t\t\t\tctx?.cwd || cwd,\n\t\t\t\t\tspawnHook,\n\t\t\t\t\texposeSessionEnvironment,\n\t\t\t\t\tctx,\n\t\t\t\t);\n\t\t\t\t// A setup throw settles the task as failed, or cancelled once its signal fired.\n\t\t\t\treturn await runShellCommand({\n\t\t\t\t\toperations: ops,\n\t\t\t\t\tcontext: spawnContext,\n\t\t\t\t\ttempFilePrefix: config.tempFilePrefix,\n\t\t\t\t\ttimeout,\n\t\t\t\t\tcontrol,\n\t\t\t\t\ttaskLog: sessionTasks !== undefined,\n\t\t\t\t});\n\t\t\t};\n\t\t\tlet outcome: TaskToolOutcome<BashToolDetails | undefined>;\n\t\t\ttry {\n\t\t\t\toutcome = await (sessionTasks ?? standalone!).execute<BashToolDetails | undefined>({\n\t\t\t\t\tkind: config.name,\n\t\t\t\t\tlabel: config.shellName[0]!.toUpperCase() + config.shellName.slice(1),\n\t\t\t\t\ttitle: command,\n\t\t\t\t\tinput: { label: \"Command\", text: command, truncated: false, language: config.name },\n\t\t\t\t\tfacts: [[\"Directory\", ctx?.cwd || cwd]],\n\t\t\t\t\ttoolCallId,\n\t\t\t\t\tbackground,\n\t\t\t\t\tsignal: parentSignal,\n\t\t\t\t\tonUpdate: originalUpdate,\n\t\t\t\t\trun,\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\tstandalone?.close();\n\t\t\t}\n\t\t\tif (outcome.kind === \"result\") return shellToolResult(outcome);\n\t\t\tconst tail = `Task ID: ${outcome.task.id}. Status: ${outcome.task.status}. Completion arrives and wakes you automatically — do not poll or wait on it; continue with other work, or end your turn and hand back to the user. If you would only wait for the result, prefer foreground next time. Use ${TASKS_TOOL_NAME} read to inspect output or ${TASKS_TOOL_NAME} kill to stop it.`;\n\t\t\t// Shell execution can become background work in two ways, and the model has to know which\n\t\t\t// one it got: a submitted background command starts from an empty log, while a detached\n\t\t\t// one already holds output and keeps its original timeout.\n\t\t\tconst handoff =\n\t\t\t\toutcome.reason === \"submitted\"\n\t\t\t\t\t? `Command handed to background. ${tail}`\n\t\t\t\t\t: `Command moved to the background while it was running, by the user. The execution continues unchanged — no restart, and a supplied timeout is still measured from command startup. Output produced so far is already in the log, so ${TASKS_TOOL_NAME} read now returns partial output, not a fresh start. ${tail}`;\n\t\t\treturn {\n\t\t\t\tstructuredContent: { task_id: outcome.task.id, status: outcome.task.status },\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `${handoff}${outcome.task.outputPath ? `\\nFull output: ${outcome.task.outputPath}` : \"\"}`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails: {\n\t\t\t\t\tbackground: { kind: \"background\", taskId: outcome.task.id },\n\t\t\t\t\tfullOutputPath: outcome.task.outputPath,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t...createShellRenderers(config),\n\t};\n}\n\nconst bashToolConfig: ShellToolConfig = {\n\tname: \"bash\",\n\tlabel: \"bash\",\n\tshellName: \"bash\",\n\tprompt: \"$\",\n\tpromptSnippet: bashToolSystemPromptContribution.snippet,\n\tpromptGuidelines: bashToolSystemPromptContribution.guidelines,\n\ttempFilePrefix: \"pi-bash\",\n};\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ReturnType<typeof createShellToolDefinition> {\n\treturn createShellToolDefinition(cwd, bashToolConfig, {\n\t\t...options,\n\t\toperations: options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath }),\n\t});\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions) {\n\tconst definition = createBashToolDefinition(cwd, options);\n\tconst tool = wrapToolDefinition(definition);\n\tObject.assign(tool, {\n\t\tpromptSnippet: definition.promptSnippet,\n\t\tpromptGuidelines: definition.promptGuidelines,\n\t});\n\treturn tool;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Message } from "@earendil-works/pi-ai";
|
|
2
|
-
import type
|
|
2
|
+
import { type CompactionDetails, type FileOperations } from "../../core/compaction/index.ts";
|
|
3
3
|
import { type SessionEntry } from "../../core/session-manager.ts";
|
|
4
4
|
export interface KeptStart {
|
|
5
5
|
text: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/summary.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/summary.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EACN,KAAK,iBAAiB,EAEtB,KAAK,cAAc,EAEnB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAoD,KAAK,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAEpH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACd;AA2BD,wBAAgB,SAAS,CACxB,OAAO,EAAE,YAAY,EAAE,EACvB,gBAAgB,EAAE,MAAM,EACxB,YAAY,EAAE,OAAO,EAAE,GACrB,SAAS,GAAG,SAAS,CAevB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,kBAAkB,CAAC,EAAE,MAAM,GAAG,MAAM,CAoDvF;AAMD,wBAAgB,iBAAiB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,YAAY,EAAE,GACrB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,CAqBjD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { contentText } from "@earendil-works/pi-ai";
|
|
2
|
+
import { computeFileLists, formatFileOperations, } from "../../core/compaction/index.js";
|
|
2
3
|
import { convertToLlm } from "../../core/messages.js";
|
|
3
4
|
import { buildSessionProjection, getLatestCompactionEntry } from "../../core/session-manager.js";
|
|
4
5
|
function sameMessage(candidate, projected) {
|
|
@@ -99,33 +100,29 @@ function isPlainObject(value) {
|
|
|
99
100
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
100
101
|
}
|
|
101
102
|
export function checkpointSummary(text, fileOps, entries) {
|
|
102
|
-
const
|
|
103
|
-
|
|
103
|
+
const merged = {
|
|
104
|
+
read: new Set(fileOps.read),
|
|
105
|
+
written: new Set(fileOps.written),
|
|
106
|
+
edited: new Set(fileOps.edited),
|
|
107
|
+
};
|
|
104
108
|
const previousDetails = getLatestCompactionEntry(entries)?.details;
|
|
105
109
|
if (isPlainObject(previousDetails)) {
|
|
106
110
|
const { readFiles, modifiedFiles } = previousDetails;
|
|
107
111
|
if (Array.isArray(readFiles)) {
|
|
108
112
|
for (const file of readFiles)
|
|
109
113
|
if (typeof file === "string")
|
|
110
|
-
read.add(file);
|
|
114
|
+
merged.read.add(file);
|
|
111
115
|
}
|
|
112
116
|
if (Array.isArray(modifiedFiles)) {
|
|
113
117
|
for (const file of modifiedFiles)
|
|
114
118
|
if (typeof file === "string")
|
|
115
|
-
|
|
119
|
+
merged.edited.add(file);
|
|
116
120
|
}
|
|
117
121
|
}
|
|
118
|
-
const details =
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
text.replace(/<(read-files|modified-files)>[\s\S]*?<\/\1>/g, "").trim(),
|
|
124
|
-
details.readFiles.length > 0 ? `<read-files>\n${details.readFiles.join("\n")}\n</read-files>` : "",
|
|
125
|
-
details.modifiedFiles.length > 0
|
|
126
|
-
? `<modified-files>\n${details.modifiedFiles.join("\n")}\n</modified-files>`
|
|
127
|
-
: "",
|
|
128
|
-
];
|
|
129
|
-
return { summary: sections.filter(Boolean).join("\n\n"), details };
|
|
122
|
+
const details = computeFileLists(merged);
|
|
123
|
+
const body = text.replace(/<(read-files|modified-files)>[\s\S]*?<\/\1>/g, "").trim();
|
|
124
|
+
const operations = formatFileOperations(details.readFiles, details.modifiedFiles);
|
|
125
|
+
// The shared formatter prefixes a non-empty operation list; an empty summary body has no leading blank lines.
|
|
126
|
+
return { summary: body ? body + operations : operations.slice(2), details };
|
|
130
127
|
}
|
|
131
128
|
//# sourceMappingURL=summary.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summary.js","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/summary.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { contentText, type Message } from \"@earendil-works/pi-ai\";\nimport type { CompactionDetails, FileOperations } from \"../../core/compaction/index.ts\";\nimport { convertToLlm } from \"../../core/messages.ts\";\nimport { buildSessionProjection, getLatestCompactionEntry, type SessionEntry } from \"../../core/session-manager.ts\";\n\nexport interface KeptStart {\n\ttext: string;\n\tfromEnd: number;\n\tcount: number;\n}\n\nfunction sameMessage(candidate: Message, projected: AgentMessage): boolean {\n\tconst serialized = JSON.stringify(candidate);\n\treturn convertToLlm([projected]).some((message) => JSON.stringify(message) === serialized);\n}\n\nfunction messagePreview(message: Message): string | undefined {\n\tlet text: string | undefined;\n\tif (message.role === \"user\") {\n\t\ttext = contentText(message.content);\n\t} else if (message.role === \"assistant\") {\n\t\ttext = message.content\n\t\t\t.flatMap((block) =>\n\t\t\t\tblock.type === \"text\"\n\t\t\t\t\t? [block.text]\n\t\t\t\t\t: block.type === \"toolCall\"\n\t\t\t\t\t\t? [`[tool call: ${block.name} ${JSON.stringify(block.arguments)}]`]\n\t\t\t\t\t\t: [],\n\t\t\t)\n\t\t\t.join(\"\\n\");\n\t}\n\ttext = text?.trim();\n\tif (!text) return undefined;\n\treturn text.length > 400 ? `${text.slice(0, 400)}…` : text;\n}\n\nexport function keptStart(\n\tentries: SessionEntry[],\n\tfirstKeptEntryId: string,\n\tconversation: Message[],\n): KeptStart | undefined {\n\tconst projected = buildSessionProjection(entries).entries;\n\tconst start = projected.findIndex((entry) => entry.sourceEntry.id === firstKeptEntryId);\n\tif (start === -1) return undefined;\n\tlet at = -1;\n\tfor (const message of projected.slice(start).flatMap((entry) => entry.messages)) {\n\t\tat = conversation.findLastIndex((candidate) => sameMessage(candidate, message));\n\t\tif (at !== -1) break;\n\t}\n\tif (at === -1) return undefined;\n\tconst previews = conversation.slice(at).map(messagePreview);\n\tconst text = previews[0];\n\treturn text\n\t\t? { text, fromEnd: previews.filter((preview) => preview === text).length, count: previews.length }\n\t\t: undefined;\n}\n\nexport function summaryInstruction(kept: KeptStart, customInstructions?: string): string {\n\tconst repeated =\n\t\tkept.fromEnd > 1\n\t\t\t? ` Several retained messages begin with this text. The boundary is occurrence ${kept.fromEnd}, counting backward from the end of the conversation.`\n\t\t\t: \"\";\n\tconst toolCalls = kept.text.includes(\"[tool call: \")\n\t\t? \" Tool calls are written as [tool call: name arguments].\"\n\t\t: \"\";\n\tconst focus = customInstructions?.trim() ? `\\n\\nAdditional focus from the user:\\n${customInstructions.trim()}` : \"\";\n\treturn `Stop working on the current task. Do not call any tools.\n\nWrite a structured context checkpoint summary of the earlier part of this conversation. Another LLM will continue the task from your summary, followed by the last ${kept.count} messages, which will remain in context verbatim.\n\nThe retained messages begin with the message that starts with this text.${repeated}${toolCalls}\n\n<kept-start>\n${kept.text}\n</kept-start>\n\nSummarize only the messages before that boundary, as if the conversation had ended immediately before it. Work occurring at or after the boundary has not happened as far as this summary is concerned: do not list it as completed. If it was already planned, include it under Next Steps instead.\n\nIf the conversation contains an earlier checkpoint summary, fold its still-relevant facts into this summary and update its progress and next steps.\n\nUse exactly this structure:\n\n## Goal\n[What the user is trying to accomplish. Include multiple goals if applicable.]\n\n## Constraints & Preferences\n- [Requirements, preferences, and explicit constraints from the user]\n- [Use \"(none)\" when appropriate]\n\n## Progress\n### Done\n- [x] [Work completed before the boundary]\n\n### In Progress\n- [ ] [Work underway at the boundary]\n\n### Blocked\n- [Issues preventing progress, or \"(none)\"]\n\n## Key Decisions\n- **[Decision]**: [Rationale]\n\n## Next Steps\n1. [Ordered steps needed to continue]\n\n## Critical Context\n- [Exact information needed to continue: file paths, symbols, commands, important tool results, error messages, and relevant technical details]\n\nBe concise but preserve information required to continue without rereading the original conversation. Keep exact file paths, function names, commands, and error messages. Do not include file-operation lists; they will be added automatically. Return only the summary.${focus}`;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function checkpointSummary(\n\ttext: string,\n\tfileOps: FileOperations,\n\tentries: SessionEntry[],\n): { summary: string; details: CompactionDetails } {\n\tconst read = new Set(fileOps.read);\n\tconst modified = new Set([...fileOps.written, ...fileOps.edited]);\n\tconst previousDetails: unknown = getLatestCompactionEntry(entries)?.details;\n\tif (isPlainObject(previousDetails)) {\n\t\tconst { readFiles, modifiedFiles } = previousDetails;\n\t\tif (Array.isArray(readFiles)) {\n\t\t\tfor (const file of readFiles) if (typeof file === \"string\") read.add(file);\n\t\t}\n\t\tif (Array.isArray(modifiedFiles)) {\n\t\t\tfor (const file of modifiedFiles) if (typeof file === \"string\") modified.add(file);\n\t\t}\n\t}\n\tconst details = {\n\t\treadFiles: [...read].filter((file) => !modified.has(file)).sort(),\n\t\tmodifiedFiles: [...modified].sort(),\n\t};\n\tconst sections = [\n\t\ttext.replace(/<(read-files|modified-files)>[\\s\\S]*?<\\/\\1>/g, \"\").trim(),\n\t\tdetails.readFiles.length > 0 ? `<read-files>\\n${details.readFiles.join(\"\\n\")}\\n</read-files>` : \"\",\n\t\tdetails.modifiedFiles.length > 0\n\t\t\t? `<modified-files>\\n${details.modifiedFiles.join(\"\\n\")}\\n</modified-files>`\n\t\t\t: \"\",\n\t];\n\treturn { summary: sections.filter(Boolean).join(\"\\n\\n\"), details };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"summary.js","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/summary.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { contentText, type Message } from \"@earendil-works/pi-ai\";\nimport {\n\ttype CompactionDetails,\n\tcomputeFileLists,\n\ttype FileOperations,\n\tformatFileOperations,\n} from \"../../core/compaction/index.ts\";\nimport { convertToLlm } from \"../../core/messages.ts\";\nimport { buildSessionProjection, getLatestCompactionEntry, type SessionEntry } from \"../../core/session-manager.ts\";\n\nexport interface KeptStart {\n\ttext: string;\n\tfromEnd: number;\n\tcount: number;\n}\n\nfunction sameMessage(candidate: Message, projected: AgentMessage): boolean {\n\tconst serialized = JSON.stringify(candidate);\n\treturn convertToLlm([projected]).some((message) => JSON.stringify(message) === serialized);\n}\n\nfunction messagePreview(message: Message): string | undefined {\n\tlet text: string | undefined;\n\tif (message.role === \"user\") {\n\t\ttext = contentText(message.content);\n\t} else if (message.role === \"assistant\") {\n\t\ttext = message.content\n\t\t\t.flatMap((block) =>\n\t\t\t\tblock.type === \"text\"\n\t\t\t\t\t? [block.text]\n\t\t\t\t\t: block.type === \"toolCall\"\n\t\t\t\t\t\t? [`[tool call: ${block.name} ${JSON.stringify(block.arguments)}]`]\n\t\t\t\t\t\t: [],\n\t\t\t)\n\t\t\t.join(\"\\n\");\n\t}\n\ttext = text?.trim();\n\tif (!text) return undefined;\n\treturn text.length > 400 ? `${text.slice(0, 400)}…` : text;\n}\n\nexport function keptStart(\n\tentries: SessionEntry[],\n\tfirstKeptEntryId: string,\n\tconversation: Message[],\n): KeptStart | undefined {\n\tconst projected = buildSessionProjection(entries).entries;\n\tconst start = projected.findIndex((entry) => entry.sourceEntry.id === firstKeptEntryId);\n\tif (start === -1) return undefined;\n\tlet at = -1;\n\tfor (const message of projected.slice(start).flatMap((entry) => entry.messages)) {\n\t\tat = conversation.findLastIndex((candidate) => sameMessage(candidate, message));\n\t\tif (at !== -1) break;\n\t}\n\tif (at === -1) return undefined;\n\tconst previews = conversation.slice(at).map(messagePreview);\n\tconst text = previews[0];\n\treturn text\n\t\t? { text, fromEnd: previews.filter((preview) => preview === text).length, count: previews.length }\n\t\t: undefined;\n}\n\nexport function summaryInstruction(kept: KeptStart, customInstructions?: string): string {\n\tconst repeated =\n\t\tkept.fromEnd > 1\n\t\t\t? ` Several retained messages begin with this text. The boundary is occurrence ${kept.fromEnd}, counting backward from the end of the conversation.`\n\t\t\t: \"\";\n\tconst toolCalls = kept.text.includes(\"[tool call: \")\n\t\t? \" Tool calls are written as [tool call: name arguments].\"\n\t\t: \"\";\n\tconst focus = customInstructions?.trim() ? `\\n\\nAdditional focus from the user:\\n${customInstructions.trim()}` : \"\";\n\treturn `Stop working on the current task. Do not call any tools.\n\nWrite a structured context checkpoint summary of the earlier part of this conversation. Another LLM will continue the task from your summary, followed by the last ${kept.count} messages, which will remain in context verbatim.\n\nThe retained messages begin with the message that starts with this text.${repeated}${toolCalls}\n\n<kept-start>\n${kept.text}\n</kept-start>\n\nSummarize only the messages before that boundary, as if the conversation had ended immediately before it. Work occurring at or after the boundary has not happened as far as this summary is concerned: do not list it as completed. If it was already planned, include it under Next Steps instead.\n\nIf the conversation contains an earlier checkpoint summary, fold its still-relevant facts into this summary and update its progress and next steps.\n\nUse exactly this structure:\n\n## Goal\n[What the user is trying to accomplish. Include multiple goals if applicable.]\n\n## Constraints & Preferences\n- [Requirements, preferences, and explicit constraints from the user]\n- [Use \"(none)\" when appropriate]\n\n## Progress\n### Done\n- [x] [Work completed before the boundary]\n\n### In Progress\n- [ ] [Work underway at the boundary]\n\n### Blocked\n- [Issues preventing progress, or \"(none)\"]\n\n## Key Decisions\n- **[Decision]**: [Rationale]\n\n## Next Steps\n1. [Ordered steps needed to continue]\n\n## Critical Context\n- [Exact information needed to continue: file paths, symbols, commands, important tool results, error messages, and relevant technical details]\n\nBe concise but preserve information required to continue without rereading the original conversation. Keep exact file paths, function names, commands, and error messages. Do not include file-operation lists; they will be added automatically. Return only the summary.${focus}`;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function checkpointSummary(\n\ttext: string,\n\tfileOps: FileOperations,\n\tentries: SessionEntry[],\n): { summary: string; details: CompactionDetails } {\n\tconst merged: FileOperations = {\n\t\tread: new Set(fileOps.read),\n\t\twritten: new Set(fileOps.written),\n\t\tedited: new Set(fileOps.edited),\n\t};\n\tconst previousDetails: unknown = getLatestCompactionEntry(entries)?.details;\n\tif (isPlainObject(previousDetails)) {\n\t\tconst { readFiles, modifiedFiles } = previousDetails;\n\t\tif (Array.isArray(readFiles)) {\n\t\t\tfor (const file of readFiles) if (typeof file === \"string\") merged.read.add(file);\n\t\t}\n\t\tif (Array.isArray(modifiedFiles)) {\n\t\t\tfor (const file of modifiedFiles) if (typeof file === \"string\") merged.edited.add(file);\n\t\t}\n\t}\n\tconst details = computeFileLists(merged);\n\tconst body = text.replace(/<(read-files|modified-files)>[\\s\\S]*?<\\/\\1>/g, \"\").trim();\n\tconst operations = formatFileOperations(details.readFiles, details.modifiedFiles);\n\t// The shared formatter prefixes a non-empty operation list; an empty summary body has no leading blank lines.\n\treturn { summary: body ? body + operations : operations.slice(2), details };\n}\n"]}
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
import type { AgentToolResult } from "../../../core/extensions/types.ts";
|
|
3
3
|
import { type TaskSnapshot, type TasksContext } from "../../../core/tasks/types.ts";
|
|
4
4
|
import { type TasksInput } from "./schema.ts";
|
|
5
|
-
import type { TasksKillDetails, TasksListDetails, TasksReadDetails
|
|
5
|
+
import type { TasksKillDetails, TasksListDetails, TasksReadDetails } from "./types.ts";
|
|
6
6
|
export declare function boundedText(text: string): string;
|
|
7
7
|
export declare function describeTaskLine(task: TaskSnapshot, now?: number): string;
|
|
8
8
|
export declare function runRead(background: TasksContext, input: TasksInput): Promise<AgentToolResult<TasksReadDetails>>;
|
|
9
|
-
export declare function runWait(background: TasksContext, input: TasksInput, signal?: AbortSignal, toolCallId?: string): Promise<AgentToolResult<TasksWaitDetails>>;
|
|
10
9
|
export declare function runKill(background: TasksContext, input: TasksInput): AgentToolResult<TasksKillDetails>;
|
|
11
10
|
export declare function runList(background: TasksContext): AgentToolResult<TasksListDetails>;
|
|
12
11
|
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/tool/actions.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAElF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAIzE,OAAO,EAIN,KAAK,YAAY,EACjB,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/tool/actions.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAElF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAIzE,OAAO,EAIN,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,MAAM,8BAA8B,CAAC;AAItC,OAAO,EAAkC,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,KAAK,EAAgB,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErG,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAID,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,SAAa,GAAG,MAAM,CAE7E;AAuFD,wBAAsB,OAAO,CAAC,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,CAoBrH;AAED,wBAAgB,OAAO,CAAC,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,eAAe,CAAC,gBAAgB,CAAC,CAoBtG;AACD,wBAAgB,OAAO,CAAC,UAAU,EAAE,YAAY,GAAG,eAAe,CAAC,gBAAgB,CAAC,CAmBnF"}
|