@astralyn/pi 0.87.4 → 0.87.6
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 +33 -0
- package/dist/bundle/chunks/{chunk-CUDKRZ2V.js → chunk-4W4Q2H6W.js} +58 -57
- package/dist/bundle/chunks/{chunk-ANT4TSUE.js → chunk-IORR2FW4.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-Y2YZRMU3.js → virtual-modules-KUEIEAZN.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 +8 -24
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +54 -109
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/background/session.d.ts +11 -7
- package/dist/core/background/session.d.ts.map +1 -1
- package/dist/core/background/session.js +42 -16
- package/dist/core/background/session.js.map +1 -1
- package/dist/core/context-snapshot.d.ts +17 -4
- package/dist/core/context-snapshot.d.ts.map +1 -1
- package/dist/core/context-snapshot.js +48 -50
- package/dist/core/context-snapshot.js.map +1 -1
- package/dist/core/extensions/distribution-api.d.ts +0 -7
- package/dist/core/extensions/distribution-api.d.ts.map +1 -1
- package/dist/core/extensions/distribution-api.js +6 -6
- package/dist/core/extensions/distribution-api.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 +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +3 -2
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +1 -5
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +10 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +3 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +59 -7
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/tools/bash.d.ts +1 -3
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +0 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +0 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +0 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +0 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +0 -7
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +0 -11
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js +59 -5
- package/dist/core/tools/renderers/bash.js.map +1 -1
- package/dist/core/tools/renderers/edit.d.ts.map +1 -1
- package/dist/core/tools/renderers/edit.js +4 -22
- package/dist/core/tools/renderers/edit.js.map +1 -1
- package/dist/core/tools/renderers/find.d.ts.map +1 -1
- package/dist/core/tools/renderers/find.js +7 -6
- package/dist/core/tools/renderers/find.js.map +1 -1
- package/dist/core/tools/renderers/grep.d.ts.map +1 -1
- package/dist/core/tools/renderers/grep.js +8 -7
- package/dist/core/tools/renderers/grep.js.map +1 -1
- package/dist/core/tools/renderers/ls.d.ts.map +1 -1
- package/dist/core/tools/renderers/ls.js +3 -2
- package/dist/core/tools/renderers/ls.js.map +1 -1
- package/dist/core/tools/renderers/read.d.ts.map +1 -1
- package/dist/core/tools/renderers/read.js +7 -12
- package/dist/core/tools/renderers/read.js.map +1 -1
- package/dist/core/tools/renderers/write.d.ts.map +1 -1
- package/dist/core/tools/renderers/write.js +3 -2
- package/dist/core/tools/renderers/write.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts +2 -6
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +5 -4
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/extensions/background/completion-render.d.ts.map +1 -1
- package/dist/extensions/background/completion-render.js +3 -4
- package/dist/extensions/background/completion-render.js.map +1 -1
- package/dist/extensions/background/constants.d.ts +2 -0
- package/dist/extensions/background/constants.d.ts.map +1 -1
- package/dist/extensions/background/constants.js +2 -0
- package/dist/extensions/background/constants.js.map +1 -1
- package/dist/extensions/background/index.d.ts.map +1 -1
- package/dist/extensions/background/index.js +31 -5
- package/dist/extensions/background/index.js.map +1 -1
- package/dist/extensions/question/detail-pane.d.ts +12 -0
- package/dist/extensions/question/detail-pane.d.ts.map +1 -0
- package/dist/extensions/question/detail-pane.js +42 -0
- package/dist/extensions/question/detail-pane.js.map +1 -0
- package/dist/extensions/question/dialog.d.ts.map +1 -1
- package/dist/extensions/question/dialog.js +175 -105
- package/dist/extensions/question/dialog.js.map +1 -1
- package/dist/extensions/question/option-window.d.ts +26 -0
- package/dist/extensions/question/option-window.d.ts.map +1 -0
- package/dist/extensions/question/option-window.js +53 -0
- package/dist/extensions/question/option-window.js.map +1 -0
- package/dist/extensions/question/render-cache.d.ts +4 -4
- package/dist/extensions/question/render-cache.d.ts.map +1 -1
- package/dist/extensions/question/render-cache.js +10 -11
- package/dist/extensions/question/render-cache.js.map +1 -1
- package/dist/extensions/todo/constants.d.ts +1 -1
- package/dist/extensions/todo/constants.d.ts.map +1 -1
- package/dist/extensions/todo/constants.js +2 -2
- package/dist/extensions/todo/constants.js.map +1 -1
- package/dist/extensions/todo/index.d.ts.map +1 -1
- package/dist/extensions/todo/index.js +12 -8
- package/dist/extensions/todo/index.js.map +1 -1
- package/dist/extensions/todo/schema.d.ts +1 -0
- package/dist/extensions/todo/schema.d.ts.map +1 -1
- package/dist/extensions/todo/schema.js +1 -1
- package/dist/extensions/todo/schema.js.map +1 -1
- package/dist/extensions/todo/state.d.ts.map +1 -1
- package/dist/extensions/todo/state.js +15 -5
- package/dist/extensions/todo/state.js.map +1 -1
- package/dist/extensions/todo/view.d.ts +4 -4
- package/dist/extensions/todo/view.d.ts.map +1 -1
- package/dist/extensions/todo/view.js +11 -30
- package/dist/extensions/todo/view.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/status-marker.d.ts +2 -2
- package/dist/modes/interactive/components/status-marker.js +2 -2
- package/dist/modes/interactive/components/status-marker.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -10
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +2 -3
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/interactive/tool-view/chat.d.ts +20 -0
- package/dist/modes/interactive/tool-view/chat.d.ts.map +1 -0
- package/dist/modes/interactive/tool-view/chat.js +46 -0
- package/dist/modes/interactive/tool-view/chat.js.map +1 -0
- package/dist/modes/interactive/tool-view/fallback.d.ts +14 -0
- package/dist/modes/interactive/tool-view/fallback.d.ts.map +1 -0
- package/dist/modes/interactive/tool-view/fallback.js +52 -0
- package/dist/modes/interactive/tool-view/fallback.js.map +1 -0
- package/dist/modes/interactive/tool-view/style.d.ts +63 -0
- package/dist/modes/interactive/tool-view/style.d.ts.map +1 -0
- package/dist/modes/interactive/tool-view/style.js +83 -0
- package/dist/modes/interactive/tool-view/style.js.map +1 -0
- package/dist/modes/interactive/{components → tool-view}/tool-execution.d.ts +17 -24
- package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/{components → tool-view}/tool-execution.js +42 -116
- package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -0
- package/docs/bundled/README.md +1 -1
- package/docs/bundled/extensions/background.md +1 -1
- package/docs/bundled/extensions/question.md +6 -5
- package/docs/bundled/extensions/todo.md +5 -5
- package/docs/bundled/tool-presentation.md +41 -31
- package/docs/extensions.md +1 -4
- package/docs/keybindings.md +11 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/core/model-stream-options.d.ts +0 -6
- package/dist/core/model-stream-options.d.ts.map +0 -1
- package/dist/core/model-stream-options.js +0 -20
- package/dist/core/model-stream-options.js.map +0 -1
- package/dist/modes/interactive/components/tool-chrome.d.ts +0 -28
- package/dist/modes/interactive/components/tool-chrome.d.ts.map +0 -1
- package/dist/modes/interactive/components/tool-chrome.js +0 -84
- package/dist/modes/interactive/components/tool-chrome.js.map +0 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +0 -1
- package/dist/modes/interactive/components/tool-execution.js.map +0 -1
- package/dist/modes/interactive/components/tool-group.d.ts +0 -17
- package/dist/modes/interactive/components/tool-group.d.ts.map +0 -1
- package/dist/modes/interactive/components/tool-group.js +0 -78
- package/dist/modes/interactive/components/tool-group.js.map +0 -1
- package/dist/modes/interactive/tool-chat.d.ts +0 -21
- package/dist/modes/interactive/tool-chat.d.ts.map +0 -1
- package/dist/modes/interactive/tool-chat.js +0 -58
- package/dist/modes/interactive/tool-chat.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/todo/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAGN,4BAA4B,GAE5B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,kBAAkB,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAoB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAkB,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/todo/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * todo — Pi-native task tracking for multi-step work.\n *\n * State is conversation-backed: every tool result carries a full v3 snapshot\n * in `details`, and lifecycle handlers replay the current branch into the\n * closure store created by createTodoStore(). Resume, /reload, and /tree\n * navigation stay aligned with the conversation without a disk database or\n * any per-session global state.\n */\nimport { Text } from \"@earendil-works/pi-tui\";\nimport {\n\ttype AgentToolResult,\n\ttype ExtensionAPI,\n\tisStaleExtensionContextError,\n\ttype ToolExecutionMode,\n} from \"../../core/extensions/types.ts\";\nimport {\n\tTODO_PROMPT_GUIDELINES,\n\tTODO_PROMPT_SNIPPET,\n\tTODO_TOOL_DESCRIPTION,\n\tTODO_TOOL_LABEL,\n\tTODO_TOOL_NAME,\n\tTODOS_COMMAND_NAME,\n} from \"./constants.ts\";\nimport { type TodoDetails, TodoParamsSchema } from \"./schema.ts\";\nimport { createTodoStore, replayTodosFromBranch, type TodoStore } from \"./state.ts\";\nimport { formatCommandList, formatTodoCall, formatTodoContent, formatTodoSummary } from \"./view.ts\";\nimport { TodoWidget } from \"./widget.ts\";\n\ninterface TodoSessionCtx {\n\tsessionManager: { getBranch(): Iterable<unknown> };\n}\n\nfunction safeReplay(ctx: TodoSessionCtx, store: TodoStore): void {\n\t// Every ctx.sessionManager access stays inside the guard: a lifecycle event\n\t// can race session replacement (resume, /tree, /reload), and a stale ctx\n\t// just means another session took over — nothing left to replay for it.\n\ttry {\n\t\tstore.replaceState(replayTodosFromBranch(ctx));\n\t} catch (error) {\n\t\tif (!isStaleExtensionContextError(error)) throw error;\n\t}\n}\n\nexport default function todo(pi: ExtensionAPI): void {\n\tconst store = createTodoStore();\n\tlet widget: TodoWidget | undefined;\n\n\tpi.registerTool({\n\t\tname: TODO_TOOL_NAME,\n\t\tlabel: TODO_TOOL_LABEL,\n\t\tdescription: TODO_TOOL_DESCRIPTION,\n\t\tpromptSnippet: TODO_PROMPT_SNIPPET,\n\t\tpromptGuidelines: TODO_PROMPT_GUIDELINES,\n\t\tparameters: TodoParamsSchema,\n\t\tconstrainedSampling: { type: \"json_schema\", strict: \"prefer\" },\n\t\texecutionMode: \"sequential\" as ToolExecutionMode,\n\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate): Promise<AgentToolResult<TodoDetails>> {\n\t\t\t// Validation errors throw before any state mutation, so the store is\n\t\t\t// untouched on failure.\n\t\t\tconst details = store.execute(params);\n\t\t\tconst text = formatTodoContent(details.change, details.state);\n\t\t\treturn { content: [{ type: \"text\", text }], details };\n\t\t},\n\n\t\t// The widget already carries the live list, so a collapsed row is one\n\t\t// result-aware line and the result text appears only when expanded.\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(\n\t\t\t\tcontext.expanded\n\t\t\t\t\t? formatTodoCall(args, theme, true, context.result)\n\t\t\t\t\t: formatTodoSummary(args, theme, context),\n\t\t\t);\n\t\t\treturn text;\n\t\t},\n\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\tconst output = result.content.flatMap((block) => (block.type === \"text\" ? [block.text] : [])).join(\"\\n\");\n\t\t\ttext.setText(options.expanded ? theme.fg(\"toolOutput\", output) : \"\");\n\t\t\treturn text;\n\t\t},\n\t});\n\n\tpi.registerCommand(TODOS_COMMAND_NAME, {\n\t\tdescription: \"Show the complete todo list for the current conversation branch\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (!ctx.hasUI) {\n\t\t\t\tctx.ui.notify(\"/todos requires an interactive UI.\", \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tctx.ui.notify(formatCommandList(store.getState()), \"info\");\n\t\t},\n\t});\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tsafeReplay(ctx, store);\n\t\tif (ctx.hasUI) {\n\t\t\twidget ??= new TodoWidget(() => store.getState());\n\t\t\twidget.setUI(ctx.ui);\n\t\t\twidget.update();\n\t\t}\n\t});\n\n\tpi.on(\"session_tree\", async (_event, ctx) => {\n\t\tsafeReplay(ctx, store);\n\t\twidget?.update();\n\t});\n\n\tpi.on(\"session_shutdown\", async (_event, _ctx) => {\n\t\t// The store belongs to this extension runtime and is collected with it;\n\t\t// the next runtime restores its own store during session_start.\n\t\twidget?.dispose();\n\t\twidget = undefined;\n\t});\n\n\tpi.on(\"tool_execution_end\", async (event) => {\n\t\tif (event.toolName !== TODO_TOOL_NAME || event.isError) return;\n\t\twidget?.update();\n\t});\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/schema.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;AAEjE,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CACf;AAED,+DAA+D;AAC/D,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C;;;;GAIG;AACH,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAC;QAAC,EAAE,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IACjE,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC3B,aAAa,EAAE,OAAO,2BAA2B,CAAC;IAClD,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;CACjB;AA4CD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;EAsB5B,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEzD,eAAO,MAAM,gBAAgB,EAAE,SAAoC,CAAC"}
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/schema.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;AAEjE,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CACf;AAED,+DAA+D;AAC/D,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C;;;;GAIG;AACH,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sFAAsF;IACtF,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAC;QAAC,EAAE,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IACjE,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC3B,aAAa,EAAE,OAAO,2BAA2B,CAAC;IAClD,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;CACjB;AA4CD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;EAsB5B,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEzD,eAAO,MAAM,gBAAgB,EAAE,SAAoC,CAAC"}
|
|
@@ -12,7 +12,7 @@ import { TODO_MAX_BATCH_ITEMS, TODO_MAX_DESCRIPTION_LENGTH, TODO_MAX_SUBJECT_LEN
|
|
|
12
12
|
/** Current shape of snapshots written to todo tool results. */
|
|
13
13
|
export const TODO_DETAILS_SCHEMA_VERSION = 3;
|
|
14
14
|
const StatusSchema = StringEnum(["pending", "in_progress", "completed"], {
|
|
15
|
-
description: "Task status: pending for future work, in_progress for the single active task, completed for verified done work.
|
|
15
|
+
description: "Task status: pending for future work, in_progress for the single active task, completed for verified done work. At most one task may be in_progress; setting one demotes any other active task to pending.",
|
|
16
16
|
});
|
|
17
17
|
const TaskIdSchema = Type.Integer({ minimum: 1, description: "Positive task id." });
|
|
18
18
|
const CreateItemSchema = Type.Object({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/extensions/todo/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAgB5G,+DAA+D;AAC/D,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/extensions/todo/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAgB5G,+DAA+D;AAC/D,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAuB7C,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,CAAU,EAAE;IACjF,WAAW,EACV,4MAA4M;CAC7M,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAC,CAAC;AAEpF,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CACnC;IACC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC;QACpB,SAAS,EAAE,uBAAuB;QAClC,WAAW,EAAE,2DAA2D;KACxE,CAAC;IACF,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC;QACxB,SAAS,EAAE,2BAA2B;QACtC,WAAW,EAAE,4EAA4E;KACzF,CAAC;IACF,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;CACnC,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAC/B,CAAC;AAEF,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CACnC;IACC,EAAE,EAAE,YAAY;IAChB,OAAO,EAAE,IAAI,CAAC,QAAQ,CACrB,IAAI,CAAC,MAAM,CAAC;QACX,SAAS,EAAE,uBAAuB;QAClC,WAAW,EAAE,8DAA8D;KAC3E,CAAC,CACF;IACD,WAAW,EAAE,IAAI,CAAC,QAAQ,CACzB,IAAI,CAAC,MAAM,CAAC;QACX,SAAS,EAAE,2BAA2B;QACtC,WAAW,EAAE,oFAAoF;KACjG,CAAC,CACF;IACD,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;CACnC,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAC/B,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAC1C;IACC,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE;QAC5B,QAAQ,EAAE,oBAAoB;QAC9B,WAAW,EAAE,8EAA8E;KAC3F,CAAC,CACF;IACD,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE;QAC5B,QAAQ,EAAE,oBAAoB;QAC9B,WAAW,EAAE,sEAAsE;KACnF,CAAC,CACF;IACD,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE;QACxB,QAAQ,EAAE,oBAAoB;QAC9B,WAAW,EAAE,wFAAwF;KACrG,CAAC,CACF;CACD,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAC/B,CAAC;AAIF,MAAM,CAAC,MAAM,gBAAgB,GAAc,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC","sourcesContent":["/**\n * todo/schema.ts — v3 tool parameters, state shape, and operation model.\n *\n * One call is one patch: the three group fields (create, update, delete) are\n * applied together, there is no action discriminator. The shape is built for\n * strict constrained sampling: optional groups can be null or empty and every\n * filler value a strict sampler may emit ([], \"\", null) is a harmless no-op.\n */\nimport { StringEnum } from \"@earendil-works/pi-ai\";\nimport { type Static, Type } from \"typebox\";\nimport { TODO_MAX_BATCH_ITEMS, TODO_MAX_DESCRIPTION_LENGTH, TODO_MAX_SUBJECT_LENGTH } from \"./constants.ts\";\n\nexport type TodoStatus = \"pending\" | \"in_progress\" | \"completed\";\n\nexport interface TodoItem {\n\tid: number;\n\tsubject: string;\n\tdescription: string;\n\tstatus: TodoStatus;\n}\n\nexport interface TodoState {\n\titems: TodoItem[];\n\tnextId: number;\n}\n\n/** Current shape of snapshots written to todo tool results. */\nexport const TODO_DETAILS_SCHEMA_VERSION = 3;\n\n/**\n * What one call changed, as a flat patch record. Every list is empty for a\n * pure list call; `demotedId` is present only when an activation pushed the\n * previously active task back to pending.\n */\nexport interface TodoChange {\n\tcreated: number[];\n\t/** Explicitly updated tasks, from their prior status to the final snapshot status. */\n\tupdated: Array<{ id: number; from: TodoStatus; to: TodoStatus }>;\n\tdeleted: Array<{ id: number; subject: string }>;\n\tabsent: number[];\n\tevicted: Array<{ id: number; subject: string }>;\n\tdemotedId?: number;\n}\n\nexport interface TodoDetails {\n\tschemaVersion: typeof TODO_DETAILS_SCHEMA_VERSION;\n\tchange: TodoChange;\n\tstate: TodoState;\n}\n\nconst StatusSchema = StringEnum([\"pending\", \"in_progress\", \"completed\"] as const, {\n\tdescription:\n\t\t\"Task status: pending for future work, in_progress for the single active task, completed for verified done work. At most one task may be in_progress; setting one demotes any other active task to pending.\",\n});\n\nconst TaskIdSchema = Type.Integer({ minimum: 1, description: \"Positive task id.\" });\n\nconst CreateItemSchema = Type.Object(\n\t{\n\t\tsubject: Type.String({\n\t\t\tmaxLength: TODO_MAX_SUBJECT_LENGTH,\n\t\t\tdescription: \"Short imperative task subject; a reviewable unit of work.\",\n\t\t}),\n\t\tdescription: Type.String({\n\t\t\tmaxLength: TODO_MAX_DESCRIPTION_LENGTH,\n\t\t\tdescription: \"What done means for this task: acceptance criteria or verification detail.\",\n\t\t}),\n\t\tstatus: Type.Optional(StatusSchema),\n\t},\n\t{ additionalProperties: false },\n);\n\nconst UpdateItemSchema = Type.Object(\n\t{\n\t\tid: TaskIdSchema,\n\t\tsubject: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tmaxLength: TODO_MAX_SUBJECT_LENGTH,\n\t\t\t\tdescription: \"Replacement subject; blank or omitted keeps the current one.\",\n\t\t\t}),\n\t\t),\n\t\tdescription: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tmaxLength: TODO_MAX_DESCRIPTION_LENGTH,\n\t\t\t\tdescription: \"Replacement description (what done means); blank or omitted keeps the current one.\",\n\t\t\t}),\n\t\t),\n\t\tstatus: Type.Optional(StatusSchema),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const TodoParamsSchema = Type.Object(\n\t{\n\t\tcreate: Type.Optional(\n\t\t\tType.Array(CreateItemSchema, {\n\t\t\t\tmaxItems: TODO_MAX_BATCH_ITEMS,\n\t\t\t\tdescription: \"Tasks to add, created atomically in input order; status defaults to pending.\",\n\t\t\t}),\n\t\t),\n\t\tupdate: Type.Optional(\n\t\t\tType.Array(UpdateItemSchema, {\n\t\t\t\tmaxItems: TODO_MAX_BATCH_ITEMS,\n\t\t\t\tdescription: \"Task edits by id; blank or omitted fields keep their current values.\",\n\t\t\t}),\n\t\t),\n\t\tdelete: Type.Optional(\n\t\t\tType.Array(TaskIdSchema, {\n\t\t\t\tmaxItems: TODO_MAX_BATCH_ITEMS,\n\t\t\t\tdescription: \"Ids to remove from the current list; deleting an id that is already absent is a no-op.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type TodoParams = Static<typeof TodoParamsSchema>;\n\nexport const EMPTY_TODO_STATE: TodoState = { items: [], nextId: 1 };\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/state.ts"],"names":[],"mappings":"AAkBA,OAAO,EAGN,KAAK,UAAU,EACf,KAAK,WAAW,EAEhB,KAAK,UAAU,EACf,KAAK,SAAS,EAEd,MAAM,aAAa,CAAC;AAuJrB,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAE1D;AAED,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/state.ts"],"names":[],"mappings":"AAkBA,OAAO,EAGN,KAAK,UAAU,EACf,KAAK,WAAW,EAEhB,KAAK,UAAU,EACf,KAAK,SAAS,EAEd,MAAM,aAAa,CAAC;AAuJrB,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAE1D;AAED,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,CAoJ/E;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,GAAG,WAAW,CAElF;AAED,MAAM,WAAW,SAAS;IACzB,QAAQ,IAAI,SAAS,CAAC;IACtB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACrC,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,CAAC;CACzC;AAQD,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAgB9D;AAwCD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IAAE,cAAc,EAAE;QAAE,SAAS,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAA;KAAE,CAAA;CAAE,GAAG,SAAS,CAoB5G"}
|
|
@@ -185,7 +185,7 @@ export function applyTodoPatch(before, params) {
|
|
|
185
185
|
if (deleteSet.has(entry.id))
|
|
186
186
|
throw new Error(`#${entry.id} cannot be in both update and delete`);
|
|
187
187
|
}
|
|
188
|
-
//
|
|
188
|
+
// At most one activation per call: more than one is a real contradiction,
|
|
189
189
|
// since a single task can be in_progress at any time.
|
|
190
190
|
const activations = [];
|
|
191
191
|
createEntries.forEach((entry, index) => {
|
|
@@ -222,7 +222,6 @@ export function applyTodoPatch(before, params) {
|
|
|
222
222
|
}
|
|
223
223
|
let items = before.items.filter((item) => !deleteSet.has(item.id));
|
|
224
224
|
// --- Apply: update -------------------------------------------------------
|
|
225
|
-
const updated = [];
|
|
226
225
|
if (updateEntries.length > 0) {
|
|
227
226
|
const entriesById = new Map(updateEntries.map((entry) => [entry.id, entry]));
|
|
228
227
|
items = items.map((item) => {
|
|
@@ -235,7 +234,6 @@ export function applyTodoPatch(before, params) {
|
|
|
235
234
|
description: entry.description ?? item.description,
|
|
236
235
|
status: entry.status ?? item.status,
|
|
237
236
|
};
|
|
238
|
-
updated.push({ id: item.id, from: item.status, to: next.status });
|
|
239
237
|
return next;
|
|
240
238
|
});
|
|
241
239
|
}
|
|
@@ -294,10 +292,22 @@ export function applyTodoPatch(before, params) {
|
|
|
294
292
|
evicted.push({ id: item.id, subject: item.subject });
|
|
295
293
|
overflow--;
|
|
296
294
|
}
|
|
297
|
-
if (overflow > 0)
|
|
298
|
-
|
|
295
|
+
if (overflow > 0) {
|
|
296
|
+
const completedIds = before.items.filter((item) => item.status === "completed").map((item) => `#${item.id}`);
|
|
297
|
+
throw new Error(`at most ${TODO_MAX_ITEMS} tasks; complete or delete some first. Patch not applied. Tasks created or updated in this call are not reclaimed. ` +
|
|
298
|
+
`Delete existing tasks in the same patch to free space (remove those ids from update), or complete tasks in a separate call before creating more. ` +
|
|
299
|
+
`Completed ids before this call: ${completedIds.join(", ") || "none"}.`);
|
|
300
|
+
}
|
|
299
301
|
items = items.filter((item) => !evictIds.has(item.id));
|
|
300
302
|
}
|
|
303
|
+
// Report transitions only after activation and capacity have settled the snapshot.
|
|
304
|
+
const updated = items
|
|
305
|
+
.filter((item) => updatedIds.has(item.id))
|
|
306
|
+
.map((item) => ({
|
|
307
|
+
id: item.id,
|
|
308
|
+
from: byId.get(item.id).status,
|
|
309
|
+
to: item.status,
|
|
310
|
+
}));
|
|
301
311
|
const change = { created, updated, deleted, absent, evicted };
|
|
302
312
|
if (demotedId !== undefined)
|
|
303
313
|
change.demotedId = demotedId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/extensions/todo/state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * todo/state.ts — v3 pure state core: closure-scoped store, atomic patch\n * application (delete, then update, then create), snapshot cloning, and\n * branch replay. No session registry, metadata, dependency graph, tombstones,\n * filters, or legacy normalizers.\n *\n * The patch shape is designed so every value a strict sampler may fill in for\n * an unused field ([], \"\", null already stripped by validation) is a no-op:\n * empty groups do nothing, blank update text keeps the current value, and\n * deleting an absent id is recorded rather than rejected.\n */\nimport {\n\tTODO_MAX_BATCH_ITEMS,\n\tTODO_MAX_DESCRIPTION_LENGTH,\n\tTODO_MAX_ITEMS,\n\tTODO_MAX_SUBJECT_LENGTH,\n\tTODO_TOOL_NAME,\n} from \"./constants.ts\";\nimport {\n\tEMPTY_TODO_STATE,\n\tTODO_DETAILS_SCHEMA_VERSION,\n\ttype TodoChange,\n\ttype TodoDetails,\n\ttype TodoItem,\n\ttype TodoParams,\n\ttype TodoState,\n\ttype TodoStatus,\n} from \"./schema.ts\";\n\nconst TODO_STATUSES: ReadonlySet<TodoStatus> = new Set([\"pending\", \"in_progress\", \"completed\"]);\nconst GROUP_FIELDS: ReadonlySet<string> = new Set([\"create\", \"update\", \"delete\"]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isPositiveSafeInteger(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isSafeInteger(value) && value >= 1;\n}\n\nfunction isTodoStatus(value: unknown): value is TodoStatus {\n\treturn typeof value === \"string\" && TODO_STATUSES.has(value as TodoStatus);\n}\n\n/** De-duplicate ids preserving first-seen input order. */\nfunction dedupeIds(ids: number[]): number[] {\n\tconst seen: number[] = [];\n\tfor (const id of ids) {\n\t\tif (!seen.includes(id)) seen.push(id);\n\t}\n\treturn seen;\n}\n\n/** Trim and collapse every internal whitespace run to a single space. */\nfunction normalizeText(value: string): string {\n\treturn value.trim().replace(/\\s+/g, \" \");\n}\n\n/** Required text (create): normalized, non-empty, within the limit. */\nfunction validateRequiredText(value: unknown, label: string, maximum: number): string {\n\tif (typeof value !== \"string\") throw new Error(`${label} must be a string`);\n\tconst normalized = normalizeText(value);\n\tif (!normalized) throw new Error(`${label} cannot be empty`);\n\tif (normalized.length > maximum) throw new Error(`${label} exceeds ${maximum} characters`);\n\treturn normalized;\n}\n\n/**\n * Optional text (update): normalized and within the limit, where blank means\n * \"keep the current value\" (undefined) so strict-mode filler stays harmless.\n */\nfunction validateOptionalText(value: unknown, label: string, maximum: number): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\") throw new Error(`${label} must be a string`);\n\tconst normalized = normalizeText(value);\n\tif (!normalized) return undefined;\n\tif (normalized.length > maximum) throw new Error(`${label} exceeds ${maximum} characters`);\n\treturn normalized;\n}\n\nfunction validateOptionalStatus(value: unknown, label: string): TodoStatus | undefined {\n\tif (value === undefined) return undefined;\n\tif (!isTodoStatus(value)) throw new Error(`${label} is invalid`);\n\treturn value;\n}\n\ninterface CreateEntry {\n\tsubject: string;\n\tdescription: string;\n\tstatus?: TodoStatus;\n}\n\ninterface UpdateEntry {\n\tid: number;\n\tsubject?: string;\n\tdescription?: string;\n\tstatus?: TodoStatus;\n}\n\nfunction readCreateEntries(raw: unknown): CreateEntry[] {\n\tif (raw === undefined) return [];\n\tif (!Array.isArray(raw)) throw new Error(\"create must be an array\");\n\tif (raw.length > TODO_MAX_BATCH_ITEMS) throw new Error(`create exceeds ${TODO_MAX_BATCH_ITEMS} tasks`);\n\tconst entries: CreateEntry[] = [];\n\tfor (let index = 0; index < raw.length; index++) {\n\t\tconst item = raw[index];\n\t\tif (!isRecord(item)) throw new Error(`create[${index}] must be an object`);\n\t\tfor (const key of Object.keys(item)) {\n\t\t\tif (key !== \"subject\" && key !== \"description\" && key !== \"status\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`create[${index}].${key} is not a create field; valid fields: subject, description, status`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tconst entry: CreateEntry = {\n\t\t\tsubject: validateRequiredText(item.subject, `create[${index}].subject`, TODO_MAX_SUBJECT_LENGTH),\n\t\t\tdescription: validateRequiredText(\n\t\t\t\titem.description,\n\t\t\t\t`create[${index}].description`,\n\t\t\t\tTODO_MAX_DESCRIPTION_LENGTH,\n\t\t\t),\n\t\t};\n\t\tconst status = validateOptionalStatus(item.status, `create[${index}].status`);\n\t\tif (status !== undefined) entry.status = status;\n\t\tentries.push(entry);\n\t}\n\treturn entries;\n}\n\nfunction readUpdateEntries(raw: unknown): UpdateEntry[] {\n\tif (raw === undefined) return [];\n\tif (!Array.isArray(raw)) throw new Error(\"update must be an array\");\n\tif (raw.length > TODO_MAX_BATCH_ITEMS) throw new Error(`update exceeds ${TODO_MAX_BATCH_ITEMS} tasks`);\n\tconst entries: UpdateEntry[] = [];\n\tfor (let index = 0; index < raw.length; index++) {\n\t\tconst item = raw[index];\n\t\tif (!isRecord(item)) throw new Error(`update[${index}] must be an object`);\n\t\tfor (const key of Object.keys(item)) {\n\t\t\tif (key !== \"id\" && key !== \"subject\" && key !== \"description\" && key !== \"status\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`update[${index}].${key} is not an update field; valid fields: id, subject, description, status`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (!isPositiveSafeInteger(item.id)) throw new Error(`update[${index}].id must be a positive integer`);\n\t\tconst entry: UpdateEntry = { id: item.id };\n\t\tconst subject = validateOptionalText(item.subject, `update[${index}].subject`, TODO_MAX_SUBJECT_LENGTH);\n\t\tif (subject !== undefined) entry.subject = subject;\n\t\tconst description = validateOptionalText(\n\t\t\titem.description,\n\t\t\t`update[${index}].description`,\n\t\t\tTODO_MAX_DESCRIPTION_LENGTH,\n\t\t);\n\t\tif (description !== undefined) entry.description = description;\n\t\tconst status = validateOptionalStatus(item.status, `update[${index}].status`);\n\t\tif (status !== undefined) entry.status = status;\n\t\tentries.push(entry);\n\t}\n\treturn entries;\n}\n\nfunction readDeleteIds(raw: unknown): number[] {\n\tif (raw === undefined) return [];\n\tif (!Array.isArray(raw)) throw new Error(\"delete must be an array\");\n\tif (raw.length > TODO_MAX_BATCH_ITEMS) throw new Error(`delete exceeds ${TODO_MAX_BATCH_ITEMS} ids`);\n\tconst ids: number[] = [];\n\tfor (let index = 0; index < raw.length; index++) {\n\t\tif (!isPositiveSafeInteger(raw[index])) throw new Error(`delete[${index}] must be a positive integer id`);\n\t\tids.push(raw[index]);\n\t}\n\treturn ids;\n}\n\nfunction currentIdsLabel(state: TodoState): string {\n\tif (state.items.length === 0) return \"the list is empty\";\n\treturn `current ids: ${state.items.map((item) => `#${item.id}`).join(\", \")}`;\n}\n\n/** Snapshot clone: items are plain string/number records, so a shallow copy is safe. */\nexport function cloneTodoState(state: TodoState): TodoState {\n\treturn { items: state.items.map((item) => ({ ...item })), nextId: state.nextId };\n}\n\nexport interface TodoPatch {\n\tstate: TodoState;\n\tchange: TodoChange;\n}\n\n/**\n * Pure patch application: validates every runtime input (tool args can be\n * tampered after schema validation), throws on any invalid call, and never\n * mutates the input state. Application order is delete, then update, then\n * create, so a delete in the same call frees capacity for the create.\n */\nexport function applyTodoPatch(before: TodoState, params: TodoParams): TodoPatch {\n\tif (!isRecord(params)) throw new Error(\"todo params must be an object\");\n\tfor (const key of Object.keys(params)) {\n\t\tif (!GROUP_FIELDS.has(key)) throw new Error(`unknown todo field \"${key}\"; valid fields: create, update, delete`);\n\t}\n\n\t// Everything above the apply phase is validation: any throw leaves the\n\t// caller's state untouched.\n\tconst createEntries = readCreateEntries(params.create);\n\tconst updateEntries = readUpdateEntries(params.update);\n\tconst deleteIds = readDeleteIds(params.delete);\n\n\t// Conflicts: one edit per task per call, and a task cannot be both edited\n\t// and removed in the same call.\n\tconst updatedIds = new Set<number>();\n\tfor (const entry of updateEntries) {\n\t\tif (updatedIds.has(entry.id)) throw new Error(`#${entry.id} appears more than once in update`);\n\t\tupdatedIds.add(entry.id);\n\t}\n\tconst deleteSet = new Set(deleteIds);\n\tfor (const entry of updateEntries) {\n\t\tif (deleteSet.has(entry.id)) throw new Error(`#${entry.id} cannot be in both update and delete`);\n\t}\n\n\t// Exactly one activation per call: more than one is a real contradiction,\n\t// since a single task can be in_progress at any time.\n\tconst activations: string[] = [];\n\tcreateEntries.forEach((entry, index) => {\n\t\tif (entry.status === \"in_progress\") activations.push(`create[${index}]`);\n\t});\n\tfor (const entry of updateEntries) {\n\t\tif (entry.status === \"in_progress\") activations.push(`#${entry.id}`);\n\t}\n\tif (activations.length > 1) {\n\t\tthrow new Error(`at most one task may be set in_progress per call; got ${activations.join(\" and \")}`);\n\t}\n\n\tconst byId = new Map(before.items.map((item) => [item.id, item]));\n\tfor (const entry of updateEntries) {\n\t\tif (!byId.has(entry.id)) throw new Error(`#${entry.id} not found; ${currentIdsLabel(before)}`);\n\t}\n\n\tif (createEntries.length > 0) {\n\t\tif (!Number.isSafeInteger(before.nextId) || before.nextId < 1) throw new Error(\"next id is invalid\");\n\t\tif (before.nextId > Number.MAX_SAFE_INTEGER - createEntries.length) throw new Error(\"next id is exhausted\");\n\t}\n\n\t// --- Apply: delete -------------------------------------------------------\n\tconst deleted: Array<{ id: number; subject: string }> = [];\n\tconst absent: number[] = [];\n\tfor (const id of dedupeIds(deleteIds)) {\n\t\tconst item = byId.get(id);\n\t\tif (item) deleted.push({ id: item.id, subject: item.subject });\n\t\telse absent.push(id);\n\t}\n\tlet items = before.items.filter((item) => !deleteSet.has(item.id));\n\n\t// --- Apply: update -------------------------------------------------------\n\tconst updated: Array<{ id: number; from: TodoStatus; to: TodoStatus }> = [];\n\tif (updateEntries.length > 0) {\n\t\tconst entriesById = new Map(updateEntries.map((entry) => [entry.id, entry]));\n\t\titems = items.map((item) => {\n\t\t\tconst entry = entriesById.get(item.id);\n\t\t\tif (!entry) return item;\n\t\t\tconst next: TodoItem = {\n\t\t\t\tid: item.id,\n\t\t\t\tsubject: entry.subject ?? item.subject,\n\t\t\t\tdescription: entry.description ?? item.description,\n\t\t\t\tstatus: entry.status ?? item.status,\n\t\t\t};\n\t\t\tupdated.push({ id: item.id, from: item.status, to: next.status });\n\t\t\treturn next;\n\t\t});\n\t}\n\n\t// --- Apply: create -------------------------------------------------------\n\tconst created: number[] = [];\n\tif (createEntries.length > 0) {\n\t\tconst newItems = createEntries.map((entry, index) => {\n\t\t\tconst item: TodoItem = {\n\t\t\t\tid: before.nextId + index,\n\t\t\t\tsubject: entry.subject,\n\t\t\t\tdescription: entry.description,\n\t\t\t\tstatus: entry.status ?? \"pending\",\n\t\t\t};\n\t\t\treturn item;\n\t\t});\n\t\tfor (const item of newItems) created.push(item.id);\n\t\titems = [...items, ...newItems];\n\t}\n\n\t// --- Single in_progress: the one task this call activates demotes the rest.\n\tlet demotedId: number | undefined;\n\tlet activatedId: number | undefined;\n\tfor (const entry of updateEntries) {\n\t\tif (entry.status === \"in_progress\") activatedId = entry.id;\n\t}\n\tif (activatedId === undefined) {\n\t\tcreateEntries.forEach((entry, index) => {\n\t\t\tif (entry.status === \"in_progress\") activatedId = before.nextId + index;\n\t\t});\n\t}\n\tif (activatedId !== undefined) {\n\t\tconst demoted = items.find((item) => item.id !== activatedId && item.status === \"in_progress\");\n\t\tif (demoted) {\n\t\t\tdemotedId = demoted.id;\n\t\t\titems = items.map((item) => (item.id === demoted.id ? { ...item, status: \"pending\" as const } : item));\n\t\t}\n\t}\n\n\t// --- Capacity: completed tasks are reclaimed oldest-first before a call\n\t// may fail for space; only a list that stays over the cap is rejected.\n\t// Tasks this call created or updated are never reclaimed: silently dropping\n\t// a task would be confusing when the same result reports it as touched.\n\tconst evicted: Array<{ id: number; subject: string }> = [];\n\tif (items.length > TODO_MAX_ITEMS) {\n\t\tlet overflow = items.length - TODO_MAX_ITEMS;\n\t\tconst evictIds = new Set<number>();\n\t\tconst touched = new Set<number>([...created, ...updatedIds]);\n\t\tconst completedOldestFirst = items\n\t\t\t.filter((item) => item.status === \"completed\" && !touched.has(item.id))\n\t\t\t.sort((first, second) => first.id - second.id);\n\t\tfor (const item of completedOldestFirst) {\n\t\t\tif (overflow <= 0) break;\n\t\t\tevictIds.add(item.id);\n\t\t\tevicted.push({ id: item.id, subject: item.subject });\n\t\t\toverflow--;\n\t\t}\n\t\tif (overflow > 0) throw new Error(`at most ${TODO_MAX_ITEMS} tasks; complete or delete some first`);\n\t\titems = items.filter((item) => !evictIds.has(item.id));\n\t}\n\n\tconst change: TodoChange = { created, updated, deleted, absent, evicted };\n\tif (demotedId !== undefined) change.demotedId = demotedId;\n\treturn { state: { items, nextId: before.nextId + created.length }, change };\n}\n\nexport function buildTodoDetails(change: TodoChange, state: TodoState): TodoDetails {\n\treturn { schemaVersion: TODO_DETAILS_SCHEMA_VERSION, change, state: cloneTodoState(state) };\n}\n\nexport interface TodoStore {\n\tgetState(): TodoState;\n\treplaceState(state: TodoState): void;\n\texecute(params: TodoParams): TodoDetails;\n}\n\nfunction requireValidState(value: unknown): TodoState {\n\tconst state = normalizeSnapshotState(value);\n\tif (!state) throw new Error(\"todo state is invalid\");\n\treturn state;\n}\n\n/** Closure-scoped store: one list per store, no module-global session state. */\nexport function createTodoStore(initial?: TodoState): TodoStore {\n\tlet state = requireValidState(initial ?? EMPTY_TODO_STATE);\n\treturn {\n\t\tgetState() {\n\t\t\treturn cloneTodoState(state);\n\t\t},\n\t\treplaceState(next: TodoState) {\n\t\t\tstate = requireValidState(next);\n\t\t},\n\t\texecute(params: TodoParams): TodoDetails {\n\t\t\tconst patch = applyTodoPatch(state, params);\n\t\t\tconst details = buildTodoDetails(patch.change, patch.state);\n\t\t\tstate = patch.state;\n\t\t\treturn details;\n\t\t},\n\t};\n}\n\n/**\n * Validate an external v3 snapshot; returns undefined when malformed.\n *\n * Snapshot text must already be in normalizeText() form, which makes that\n * function's output part of the v3 persistence contract: relaxing or changing\n * it would silently invalidate every historical snapshot, falling back to an\n * earlier one or to the empty state with no diagnostic. Change normalizeText\n * only together with TODO_DETAILS_SCHEMA_VERSION.\n */\nfunction normalizeSnapshotState(value: unknown): TodoState | undefined {\n\tif (!isRecord(value) || !Array.isArray(value.items) || !isPositiveSafeInteger(value.nextId)) return undefined;\n\tif (value.items.length > TODO_MAX_ITEMS) return undefined;\n\tconst items: TodoItem[] = [];\n\tconst ids = new Set<number>();\n\tlet maxId = 0;\n\tlet activeCount = 0;\n\tfor (const rawItem of value.items) {\n\t\tif (!isRecord(rawItem)) return undefined;\n\t\tconst id = rawItem.id;\n\t\tif (!isPositiveSafeInteger(id) || ids.has(id)) return undefined;\n\t\tconst subject = rawItem.subject;\n\t\tconst description = rawItem.description;\n\t\tconst status = rawItem.status;\n\t\tif (typeof subject !== \"string\" || typeof description !== \"string\") return undefined;\n\t\tif (subject !== normalizeText(subject) || description !== normalizeText(description)) return undefined;\n\t\tif (!subject || subject.length > TODO_MAX_SUBJECT_LENGTH) return undefined;\n\t\tif (!description || description.length > TODO_MAX_DESCRIPTION_LENGTH) return undefined;\n\t\tif (!isTodoStatus(status)) return undefined;\n\t\tids.add(id);\n\t\tif (id > maxId) maxId = id;\n\t\tif (status === \"in_progress\") activeCount++;\n\t\titems.push({ id, subject, description, status });\n\t}\n\tif (activeCount > 1) return undefined;\n\tif (value.nextId <= maxId) return undefined;\n\treturn { items, nextId: value.nextId };\n}\n\n/**\n * Replay the newest valid v3 todo snapshot from a branch, scanning tail to\n * head so a malformed latest snapshot falls back to an earlier valid one.\n * Older schema versions (v1/v2) are ignored: restoring a session written\n * before v3 starts from an empty list.\n */\nexport function replayTodosFromBranch(ctx: { sessionManager: { getBranch(): Iterable<unknown> } }): TodoState {\n\tconst branch = Array.from(ctx.sessionManager.getBranch());\n\tfor (let index = branch.length - 1; index >= 0; index--) {\n\t\t// Session history is external input, so every field read stays inside the\n\t\t// guard: a hostile entry falls through to an earlier snapshot instead of\n\t\t// escaping to the lifecycle handler.\n\t\ttry {\n\t\t\tconst entry = branch[index];\n\t\t\tif (!isRecord(entry) || entry.type !== \"message\") continue;\n\t\t\tconst message = entry.message;\n\t\t\tif (!isRecord(message) || message.role !== \"toolResult\" || message.toolName !== TODO_TOOL_NAME) continue;\n\t\t\tconst details = message.details;\n\t\t\tif (!isRecord(details) || details.schemaVersion !== TODO_DETAILS_SCHEMA_VERSION) continue;\n\t\t\tconst state = normalizeSnapshotState(details.state);\n\t\t\tif (state) return state;\n\t\t} catch {\n\t\t\t// Keep scanning for an earlier valid v3 snapshot.\n\t\t}\n\t}\n\treturn cloneTodoState(EMPTY_TODO_STATE);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/extensions/todo/state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * todo/state.ts — v3 pure state core: closure-scoped store, atomic patch\n * application (delete, then update, then create), snapshot cloning, and\n * branch replay. No session registry, metadata, dependency graph, tombstones,\n * filters, or legacy normalizers.\n *\n * The patch shape is designed so every value a strict sampler may fill in for\n * an unused field ([], \"\", null already stripped by validation) is a no-op:\n * empty groups do nothing, blank update text keeps the current value, and\n * deleting an absent id is recorded rather than rejected.\n */\nimport {\n\tTODO_MAX_BATCH_ITEMS,\n\tTODO_MAX_DESCRIPTION_LENGTH,\n\tTODO_MAX_ITEMS,\n\tTODO_MAX_SUBJECT_LENGTH,\n\tTODO_TOOL_NAME,\n} from \"./constants.ts\";\nimport {\n\tEMPTY_TODO_STATE,\n\tTODO_DETAILS_SCHEMA_VERSION,\n\ttype TodoChange,\n\ttype TodoDetails,\n\ttype TodoItem,\n\ttype TodoParams,\n\ttype TodoState,\n\ttype TodoStatus,\n} from \"./schema.ts\";\n\nconst TODO_STATUSES: ReadonlySet<TodoStatus> = new Set([\"pending\", \"in_progress\", \"completed\"]);\nconst GROUP_FIELDS: ReadonlySet<string> = new Set([\"create\", \"update\", \"delete\"]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isPositiveSafeInteger(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isSafeInteger(value) && value >= 1;\n}\n\nfunction isTodoStatus(value: unknown): value is TodoStatus {\n\treturn typeof value === \"string\" && TODO_STATUSES.has(value as TodoStatus);\n}\n\n/** De-duplicate ids preserving first-seen input order. */\nfunction dedupeIds(ids: number[]): number[] {\n\tconst seen: number[] = [];\n\tfor (const id of ids) {\n\t\tif (!seen.includes(id)) seen.push(id);\n\t}\n\treturn seen;\n}\n\n/** Trim and collapse every internal whitespace run to a single space. */\nfunction normalizeText(value: string): string {\n\treturn value.trim().replace(/\\s+/g, \" \");\n}\n\n/** Required text (create): normalized, non-empty, within the limit. */\nfunction validateRequiredText(value: unknown, label: string, maximum: number): string {\n\tif (typeof value !== \"string\") throw new Error(`${label} must be a string`);\n\tconst normalized = normalizeText(value);\n\tif (!normalized) throw new Error(`${label} cannot be empty`);\n\tif (normalized.length > maximum) throw new Error(`${label} exceeds ${maximum} characters`);\n\treturn normalized;\n}\n\n/**\n * Optional text (update): normalized and within the limit, where blank means\n * \"keep the current value\" (undefined) so strict-mode filler stays harmless.\n */\nfunction validateOptionalText(value: unknown, label: string, maximum: number): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\") throw new Error(`${label} must be a string`);\n\tconst normalized = normalizeText(value);\n\tif (!normalized) return undefined;\n\tif (normalized.length > maximum) throw new Error(`${label} exceeds ${maximum} characters`);\n\treturn normalized;\n}\n\nfunction validateOptionalStatus(value: unknown, label: string): TodoStatus | undefined {\n\tif (value === undefined) return undefined;\n\tif (!isTodoStatus(value)) throw new Error(`${label} is invalid`);\n\treturn value;\n}\n\ninterface CreateEntry {\n\tsubject: string;\n\tdescription: string;\n\tstatus?: TodoStatus;\n}\n\ninterface UpdateEntry {\n\tid: number;\n\tsubject?: string;\n\tdescription?: string;\n\tstatus?: TodoStatus;\n}\n\nfunction readCreateEntries(raw: unknown): CreateEntry[] {\n\tif (raw === undefined) return [];\n\tif (!Array.isArray(raw)) throw new Error(\"create must be an array\");\n\tif (raw.length > TODO_MAX_BATCH_ITEMS) throw new Error(`create exceeds ${TODO_MAX_BATCH_ITEMS} tasks`);\n\tconst entries: CreateEntry[] = [];\n\tfor (let index = 0; index < raw.length; index++) {\n\t\tconst item = raw[index];\n\t\tif (!isRecord(item)) throw new Error(`create[${index}] must be an object`);\n\t\tfor (const key of Object.keys(item)) {\n\t\t\tif (key !== \"subject\" && key !== \"description\" && key !== \"status\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`create[${index}].${key} is not a create field; valid fields: subject, description, status`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tconst entry: CreateEntry = {\n\t\t\tsubject: validateRequiredText(item.subject, `create[${index}].subject`, TODO_MAX_SUBJECT_LENGTH),\n\t\t\tdescription: validateRequiredText(\n\t\t\t\titem.description,\n\t\t\t\t`create[${index}].description`,\n\t\t\t\tTODO_MAX_DESCRIPTION_LENGTH,\n\t\t\t),\n\t\t};\n\t\tconst status = validateOptionalStatus(item.status, `create[${index}].status`);\n\t\tif (status !== undefined) entry.status = status;\n\t\tentries.push(entry);\n\t}\n\treturn entries;\n}\n\nfunction readUpdateEntries(raw: unknown): UpdateEntry[] {\n\tif (raw === undefined) return [];\n\tif (!Array.isArray(raw)) throw new Error(\"update must be an array\");\n\tif (raw.length > TODO_MAX_BATCH_ITEMS) throw new Error(`update exceeds ${TODO_MAX_BATCH_ITEMS} tasks`);\n\tconst entries: UpdateEntry[] = [];\n\tfor (let index = 0; index < raw.length; index++) {\n\t\tconst item = raw[index];\n\t\tif (!isRecord(item)) throw new Error(`update[${index}] must be an object`);\n\t\tfor (const key of Object.keys(item)) {\n\t\t\tif (key !== \"id\" && key !== \"subject\" && key !== \"description\" && key !== \"status\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`update[${index}].${key} is not an update field; valid fields: id, subject, description, status`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (!isPositiveSafeInteger(item.id)) throw new Error(`update[${index}].id must be a positive integer`);\n\t\tconst entry: UpdateEntry = { id: item.id };\n\t\tconst subject = validateOptionalText(item.subject, `update[${index}].subject`, TODO_MAX_SUBJECT_LENGTH);\n\t\tif (subject !== undefined) entry.subject = subject;\n\t\tconst description = validateOptionalText(\n\t\t\titem.description,\n\t\t\t`update[${index}].description`,\n\t\t\tTODO_MAX_DESCRIPTION_LENGTH,\n\t\t);\n\t\tif (description !== undefined) entry.description = description;\n\t\tconst status = validateOptionalStatus(item.status, `update[${index}].status`);\n\t\tif (status !== undefined) entry.status = status;\n\t\tentries.push(entry);\n\t}\n\treturn entries;\n}\n\nfunction readDeleteIds(raw: unknown): number[] {\n\tif (raw === undefined) return [];\n\tif (!Array.isArray(raw)) throw new Error(\"delete must be an array\");\n\tif (raw.length > TODO_MAX_BATCH_ITEMS) throw new Error(`delete exceeds ${TODO_MAX_BATCH_ITEMS} ids`);\n\tconst ids: number[] = [];\n\tfor (let index = 0; index < raw.length; index++) {\n\t\tif (!isPositiveSafeInteger(raw[index])) throw new Error(`delete[${index}] must be a positive integer id`);\n\t\tids.push(raw[index]);\n\t}\n\treturn ids;\n}\n\nfunction currentIdsLabel(state: TodoState): string {\n\tif (state.items.length === 0) return \"the list is empty\";\n\treturn `current ids: ${state.items.map((item) => `#${item.id}`).join(\", \")}`;\n}\n\n/** Snapshot clone: items are plain string/number records, so a shallow copy is safe. */\nexport function cloneTodoState(state: TodoState): TodoState {\n\treturn { items: state.items.map((item) => ({ ...item })), nextId: state.nextId };\n}\n\nexport interface TodoPatch {\n\tstate: TodoState;\n\tchange: TodoChange;\n}\n\n/**\n * Pure patch application: validates every runtime input (tool args can be\n * tampered after schema validation), throws on any invalid call, and never\n * mutates the input state. Application order is delete, then update, then\n * create, so a delete in the same call frees capacity for the create.\n */\nexport function applyTodoPatch(before: TodoState, params: TodoParams): TodoPatch {\n\tif (!isRecord(params)) throw new Error(\"todo params must be an object\");\n\tfor (const key of Object.keys(params)) {\n\t\tif (!GROUP_FIELDS.has(key)) throw new Error(`unknown todo field \"${key}\"; valid fields: create, update, delete`);\n\t}\n\n\t// Everything above the apply phase is validation: any throw leaves the\n\t// caller's state untouched.\n\tconst createEntries = readCreateEntries(params.create);\n\tconst updateEntries = readUpdateEntries(params.update);\n\tconst deleteIds = readDeleteIds(params.delete);\n\n\t// Conflicts: one edit per task per call, and a task cannot be both edited\n\t// and removed in the same call.\n\tconst updatedIds = new Set<number>();\n\tfor (const entry of updateEntries) {\n\t\tif (updatedIds.has(entry.id)) throw new Error(`#${entry.id} appears more than once in update`);\n\t\tupdatedIds.add(entry.id);\n\t}\n\tconst deleteSet = new Set(deleteIds);\n\tfor (const entry of updateEntries) {\n\t\tif (deleteSet.has(entry.id)) throw new Error(`#${entry.id} cannot be in both update and delete`);\n\t}\n\n\t// At most one activation per call: more than one is a real contradiction,\n\t// since a single task can be in_progress at any time.\n\tconst activations: string[] = [];\n\tcreateEntries.forEach((entry, index) => {\n\t\tif (entry.status === \"in_progress\") activations.push(`create[${index}]`);\n\t});\n\tfor (const entry of updateEntries) {\n\t\tif (entry.status === \"in_progress\") activations.push(`#${entry.id}`);\n\t}\n\tif (activations.length > 1) {\n\t\tthrow new Error(`at most one task may be set in_progress per call; got ${activations.join(\" and \")}`);\n\t}\n\n\tconst byId = new Map(before.items.map((item) => [item.id, item]));\n\tfor (const entry of updateEntries) {\n\t\tif (!byId.has(entry.id)) throw new Error(`#${entry.id} not found; ${currentIdsLabel(before)}`);\n\t}\n\n\tif (createEntries.length > 0) {\n\t\tif (!Number.isSafeInteger(before.nextId) || before.nextId < 1) throw new Error(\"next id is invalid\");\n\t\tif (before.nextId > Number.MAX_SAFE_INTEGER - createEntries.length) throw new Error(\"next id is exhausted\");\n\t}\n\n\t// --- Apply: delete -------------------------------------------------------\n\tconst deleted: Array<{ id: number; subject: string }> = [];\n\tconst absent: number[] = [];\n\tfor (const id of dedupeIds(deleteIds)) {\n\t\tconst item = byId.get(id);\n\t\tif (item) deleted.push({ id: item.id, subject: item.subject });\n\t\telse absent.push(id);\n\t}\n\tlet items = before.items.filter((item) => !deleteSet.has(item.id));\n\n\t// --- Apply: update -------------------------------------------------------\n\tif (updateEntries.length > 0) {\n\t\tconst entriesById = new Map(updateEntries.map((entry) => [entry.id, entry]));\n\t\titems = items.map((item) => {\n\t\t\tconst entry = entriesById.get(item.id);\n\t\t\tif (!entry) return item;\n\t\t\tconst next: TodoItem = {\n\t\t\t\tid: item.id,\n\t\t\t\tsubject: entry.subject ?? item.subject,\n\t\t\t\tdescription: entry.description ?? item.description,\n\t\t\t\tstatus: entry.status ?? item.status,\n\t\t\t};\n\t\t\treturn next;\n\t\t});\n\t}\n\n\t// --- Apply: create -------------------------------------------------------\n\tconst created: number[] = [];\n\tif (createEntries.length > 0) {\n\t\tconst newItems = createEntries.map((entry, index) => {\n\t\t\tconst item: TodoItem = {\n\t\t\t\tid: before.nextId + index,\n\t\t\t\tsubject: entry.subject,\n\t\t\t\tdescription: entry.description,\n\t\t\t\tstatus: entry.status ?? \"pending\",\n\t\t\t};\n\t\t\treturn item;\n\t\t});\n\t\tfor (const item of newItems) created.push(item.id);\n\t\titems = [...items, ...newItems];\n\t}\n\n\t// --- Single in_progress: the one task this call activates demotes the rest.\n\tlet demotedId: number | undefined;\n\tlet activatedId: number | undefined;\n\tfor (const entry of updateEntries) {\n\t\tif (entry.status === \"in_progress\") activatedId = entry.id;\n\t}\n\tif (activatedId === undefined) {\n\t\tcreateEntries.forEach((entry, index) => {\n\t\t\tif (entry.status === \"in_progress\") activatedId = before.nextId + index;\n\t\t});\n\t}\n\tif (activatedId !== undefined) {\n\t\tconst demoted = items.find((item) => item.id !== activatedId && item.status === \"in_progress\");\n\t\tif (demoted) {\n\t\t\tdemotedId = demoted.id;\n\t\t\titems = items.map((item) => (item.id === demoted.id ? { ...item, status: \"pending\" as const } : item));\n\t\t}\n\t}\n\n\t// --- Capacity: completed tasks are reclaimed oldest-first before a call\n\t// may fail for space; only a list that stays over the cap is rejected.\n\t// Tasks this call created or updated are never reclaimed: silently dropping\n\t// a task would be confusing when the same result reports it as touched.\n\tconst evicted: Array<{ id: number; subject: string }> = [];\n\tif (items.length > TODO_MAX_ITEMS) {\n\t\tlet overflow = items.length - TODO_MAX_ITEMS;\n\t\tconst evictIds = new Set<number>();\n\t\tconst touched = new Set<number>([...created, ...updatedIds]);\n\t\tconst completedOldestFirst = items\n\t\t\t.filter((item) => item.status === \"completed\" && !touched.has(item.id))\n\t\t\t.sort((first, second) => first.id - second.id);\n\t\tfor (const item of completedOldestFirst) {\n\t\t\tif (overflow <= 0) break;\n\t\t\tevictIds.add(item.id);\n\t\t\tevicted.push({ id: item.id, subject: item.subject });\n\t\t\toverflow--;\n\t\t}\n\t\tif (overflow > 0) {\n\t\t\tconst completedIds = before.items.filter((item) => item.status === \"completed\").map((item) => `#${item.id}`);\n\t\t\tthrow new Error(\n\t\t\t\t`at most ${TODO_MAX_ITEMS} tasks; complete or delete some first. Patch not applied. Tasks created or updated in this call are not reclaimed. ` +\n\t\t\t\t\t`Delete existing tasks in the same patch to free space (remove those ids from update), or complete tasks in a separate call before creating more. ` +\n\t\t\t\t\t`Completed ids before this call: ${completedIds.join(\", \") || \"none\"}.`,\n\t\t\t);\n\t\t}\n\t\titems = items.filter((item) => !evictIds.has(item.id));\n\t}\n\n\t// Report transitions only after activation and capacity have settled the snapshot.\n\tconst updated = items\n\t\t.filter((item) => updatedIds.has(item.id))\n\t\t.map((item) => ({\n\t\t\tid: item.id,\n\t\t\tfrom: byId.get(item.id)!.status,\n\t\t\tto: item.status,\n\t\t}));\n\tconst change: TodoChange = { created, updated, deleted, absent, evicted };\n\tif (demotedId !== undefined) change.demotedId = demotedId;\n\treturn { state: { items, nextId: before.nextId + created.length }, change };\n}\n\nexport function buildTodoDetails(change: TodoChange, state: TodoState): TodoDetails {\n\treturn { schemaVersion: TODO_DETAILS_SCHEMA_VERSION, change, state: cloneTodoState(state) };\n}\n\nexport interface TodoStore {\n\tgetState(): TodoState;\n\treplaceState(state: TodoState): void;\n\texecute(params: TodoParams): TodoDetails;\n}\n\nfunction requireValidState(value: unknown): TodoState {\n\tconst state = normalizeSnapshotState(value);\n\tif (!state) throw new Error(\"todo state is invalid\");\n\treturn state;\n}\n\n/** Closure-scoped store: one list per store, no module-global session state. */\nexport function createTodoStore(initial?: TodoState): TodoStore {\n\tlet state = requireValidState(initial ?? EMPTY_TODO_STATE);\n\treturn {\n\t\tgetState() {\n\t\t\treturn cloneTodoState(state);\n\t\t},\n\t\treplaceState(next: TodoState) {\n\t\t\tstate = requireValidState(next);\n\t\t},\n\t\texecute(params: TodoParams): TodoDetails {\n\t\t\tconst patch = applyTodoPatch(state, params);\n\t\t\tconst details = buildTodoDetails(patch.change, patch.state);\n\t\t\tstate = patch.state;\n\t\t\treturn details;\n\t\t},\n\t};\n}\n\n/**\n * Validate an external v3 snapshot; returns undefined when malformed.\n *\n * Snapshot text must already be in normalizeText() form, which makes that\n * function's output part of the v3 persistence contract: relaxing or changing\n * it would silently invalidate every historical snapshot, falling back to an\n * earlier one or to the empty state with no diagnostic. Change normalizeText\n * only together with TODO_DETAILS_SCHEMA_VERSION.\n */\nfunction normalizeSnapshotState(value: unknown): TodoState | undefined {\n\tif (!isRecord(value) || !Array.isArray(value.items) || !isPositiveSafeInteger(value.nextId)) return undefined;\n\tif (value.items.length > TODO_MAX_ITEMS) return undefined;\n\tconst items: TodoItem[] = [];\n\tconst ids = new Set<number>();\n\tlet maxId = 0;\n\tlet activeCount = 0;\n\tfor (const rawItem of value.items) {\n\t\tif (!isRecord(rawItem)) return undefined;\n\t\tconst id = rawItem.id;\n\t\tif (!isPositiveSafeInteger(id) || ids.has(id)) return undefined;\n\t\tconst subject = rawItem.subject;\n\t\tconst description = rawItem.description;\n\t\tconst status = rawItem.status;\n\t\tif (typeof subject !== \"string\" || typeof description !== \"string\") return undefined;\n\t\tif (subject !== normalizeText(subject) || description !== normalizeText(description)) return undefined;\n\t\tif (!subject || subject.length > TODO_MAX_SUBJECT_LENGTH) return undefined;\n\t\tif (!description || description.length > TODO_MAX_DESCRIPTION_LENGTH) return undefined;\n\t\tif (!isTodoStatus(status)) return undefined;\n\t\tids.add(id);\n\t\tif (id > maxId) maxId = id;\n\t\tif (status === \"in_progress\") activeCount++;\n\t\titems.push({ id, subject, description, status });\n\t}\n\tif (activeCount > 1) return undefined;\n\tif (value.nextId <= maxId) return undefined;\n\treturn { items, nextId: value.nextId };\n}\n\n/**\n * Replay the newest valid v3 todo snapshot from a branch, scanning tail to\n * head so a malformed latest snapshot falls back to an earlier valid one.\n * Older schema versions (v1/v2) are ignored: restoring a session written\n * before v3 starts from an empty list.\n */\nexport function replayTodosFromBranch(ctx: { sessionManager: { getBranch(): Iterable<unknown> } }): TodoState {\n\tconst branch = Array.from(ctx.sessionManager.getBranch());\n\tfor (let index = branch.length - 1; index >= 0; index--) {\n\t\t// Session history is external input, so every field read stays inside the\n\t\t// guard: a hostile entry falls through to an earlier snapshot instead of\n\t\t// escaping to the lifecycle handler.\n\t\ttry {\n\t\t\tconst entry = branch[index];\n\t\t\tif (!isRecord(entry) || entry.type !== \"message\") continue;\n\t\t\tconst message = entry.message;\n\t\t\tif (!isRecord(message) || message.role !== \"toolResult\" || message.toolName !== TODO_TOOL_NAME) continue;\n\t\t\tconst details = message.details;\n\t\t\tif (!isRecord(details) || details.schemaVersion !== TODO_DETAILS_SCHEMA_VERSION) continue;\n\t\t\tconst state = normalizeSnapshotState(details.state);\n\t\t\tif (state) return state;\n\t\t} catch {\n\t\t\t// Keep scanning for an earlier valid v3 snapshot.\n\t\t}\n\t}\n\treturn cloneTodoState(EMPTY_TODO_STATE);\n}\n"]}
|
|
@@ -10,7 +10,7 @@ import { type TodoChange, type TodoParams, type TodoState, type TodoStatus } fro
|
|
|
10
10
|
export declare const STATUS_MARK: Record<TodoStatus, string>;
|
|
11
11
|
/** True while any open task exists; the widget is registered only in that case. */
|
|
12
12
|
export declare function hasOpenTodos(state: TodoState): boolean;
|
|
13
|
-
/** One-line widget: `Todos 2/6 · [>] #4 s [ ] #5 s +N more
|
|
13
|
+
/** One-line widget: `Todos 2/6 · [>] #4 s [ ] #5 s +N more`; only hidden open tasks count in the overflow. */
|
|
14
14
|
export declare function renderWidgetLine(state: TodoState, theme: Theme, width: number): string[];
|
|
15
15
|
/** `Todos: X in progress, Y pending, Z completed` header plus two-line tasks. */
|
|
16
16
|
declare function formatTodoList(state: TodoState): string;
|
|
@@ -25,12 +25,12 @@ export declare function formatTodoContent(change: TodoChange, state: TodoState):
|
|
|
25
25
|
type TodoCallArgs = Partial<Record<keyof TodoParams, unknown>>;
|
|
26
26
|
/** One-line call summary when collapsed; headline plus details when expanded. */
|
|
27
27
|
export declare function formatTodoCall(args: TodoCallArgs | undefined, theme: Theme, expanded: boolean, result?: AgentToolResult<unknown>): string;
|
|
28
|
-
export interface
|
|
28
|
+
export interface TodoSummaryContext {
|
|
29
29
|
isError: boolean;
|
|
30
30
|
isPartial: boolean;
|
|
31
31
|
result?: AgentToolResult<unknown>;
|
|
32
32
|
}
|
|
33
|
-
/** Compact result-aware summary
|
|
34
|
-
export declare function
|
|
33
|
+
/** Compact result-aware one-line summary of a collapsed todo row. */
|
|
34
|
+
export declare function formatTodoSummary(args: TodoCallArgs | undefined, theme: Theme, context: TodoSummaryContext): string;
|
|
35
35
|
export {};
|
|
36
36
|
//# sourceMappingURL=view.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/view.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAOpE,OAAO,EAEN,KAAK,UAAU,EAEf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,UAAU,EACf,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAIlD,CAAC;AAmBF,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAEtD;
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/view.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAOpE,OAAO,EAEN,KAAK,UAAU,EAEf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,UAAU,EACf,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAIlD,CAAC;AAmBF,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAEtD;AAsBD,gHAAgH;AAChH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAwDxF;AAID,iFAAiF;AACjF,iBAAS,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAYhD;AAED,yFAAyF;AACzF,eAAO,MAAM,iBAAiB,uBAAiB,CAAC;AAUhD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CA+B9E;AASD,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;AAkR/D,iFAAiF;AACjF,wBAAgB,cAAc,CAC7B,IAAI,EAAE,YAAY,GAAG,SAAS,EAC9B,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,OAAO,EACjB,MAAM,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,GAC/B,MAAM,CAGR;AAiID,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;CAClC;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAyBnH"}
|
|
@@ -49,16 +49,7 @@ function widgetLine(header, segments, overflow) {
|
|
|
49
49
|
const body = [...segments, ...(overflow ? [overflow] : [])].join(WIDGET_ITEM_SEPARATOR);
|
|
50
50
|
return body ? `${header}${WIDGET_HEADER_SEPARATOR}${body}` : header;
|
|
51
51
|
}
|
|
52
|
-
/**
|
|
53
|
-
function widgetOverflowLong(remaining, counts) {
|
|
54
|
-
const parts = [
|
|
55
|
-
counts.active > 0 ? `${counts.active} active` : "",
|
|
56
|
-
counts.pending > 0 ? `${counts.pending} pending` : "",
|
|
57
|
-
counts.completed > 0 ? `${counts.completed} completed` : "",
|
|
58
|
-
].filter(Boolean);
|
|
59
|
-
return `+${remaining} more${parts.length ? ` (${parts.join(", ")})` : ""}`;
|
|
60
|
-
}
|
|
61
|
-
/** One-line widget: `Todos 2/6 · [>] #4 s [ ] #5 s +N more (…)`; completed tasks are hidden but counted in the overflow. */
|
|
52
|
+
/** One-line widget: `Todos 2/6 · [>] #4 s [ ] #5 s +N more`; only hidden open tasks count in the overflow. */
|
|
62
53
|
export function renderWidgetLine(state, theme, width) {
|
|
63
54
|
const safeWidth = Math.max(1, width);
|
|
64
55
|
const items = state.items;
|
|
@@ -70,25 +61,14 @@ export function renderWidgetLine(state, theme, width) {
|
|
|
70
61
|
const total = items.length;
|
|
71
62
|
const completed = items.filter((item) => item.status === "completed").length;
|
|
72
63
|
const header = `${theme.fg("accent", "Todos")} ${theme.fg("dim", `${completed}/${total}`)}`;
|
|
73
|
-
const counts = widgetCounts(state);
|
|
74
64
|
const shown = [];
|
|
75
65
|
let overflow = "";
|
|
76
|
-
//
|
|
77
|
-
// the short `+N more` form otherwise, undefined when even that overflows.
|
|
66
|
+
// Count only open tasks not shown by the trial segments.
|
|
78
67
|
const bestOverflow = (trial) => {
|
|
79
|
-
const remaining =
|
|
68
|
+
const remaining = candidates.length - trial.length;
|
|
80
69
|
const segments = trial.map((entry) => widgetSegment(entry.item, entry.subject, theme));
|
|
81
|
-
const activeShown = trial.some((entry) => entry.item.status === "in_progress") ? 1 : 0;
|
|
82
|
-
const hidden = {
|
|
83
|
-
active: counts.active - activeShown,
|
|
84
|
-
pending: counts.pending - (trial.length - activeShown),
|
|
85
|
-
completed: counts.completed,
|
|
86
|
-
};
|
|
87
70
|
if (remaining <= 0)
|
|
88
71
|
return visibleWidth(widgetLine(header, segments, "")) <= safeWidth ? "" : undefined;
|
|
89
|
-
const long = theme.fg("dim", widgetOverflowLong(remaining, hidden));
|
|
90
|
-
if (visibleWidth(widgetLine(header, segments, long)) <= safeWidth)
|
|
91
|
-
return long;
|
|
92
72
|
const short = theme.fg("dim", `+${remaining} more`);
|
|
93
73
|
return visibleWidth(widgetLine(header, segments, short)) <= safeWidth ? short : undefined;
|
|
94
74
|
};
|
|
@@ -112,7 +92,7 @@ export function renderWidgetLine(state, theme, width) {
|
|
|
112
92
|
}
|
|
113
93
|
if (candidate.status !== "in_progress")
|
|
114
94
|
break;
|
|
115
|
-
const remaining =
|
|
95
|
+
const remaining = candidates.length - shown.length - 1;
|
|
116
96
|
const suffix = remaining > 0 ? `${WIDGET_ITEM_SEPARATOR}+${remaining} more` : "";
|
|
117
97
|
const prefix = `${header}${WIDGET_HEADER_SEPARATOR}${widgetSegment(candidate, "", theme)}${suffix}`;
|
|
118
98
|
const available = safeWidth - visibleWidth(prefix);
|
|
@@ -195,7 +175,7 @@ const CALL_ITEMS_MAX = TODO_MAX_BATCH_ITEMS;
|
|
|
195
175
|
const CALL_SUBJECT_PREVIEW_COUNT = 2;
|
|
196
176
|
const CALL_SUBJECT_PREVIEW_WIDTH = 72;
|
|
197
177
|
const CALL_DESCRIPTION_PREVIEW_LENGTH = 120;
|
|
198
|
-
const
|
|
178
|
+
const SUMMARY_FAILURE_MAX_LENGTH = 120;
|
|
199
179
|
/** Record-like read; proxies that throw on inspection are treated as absent. */
|
|
200
180
|
function safeRecord(value) {
|
|
201
181
|
try {
|
|
@@ -505,7 +485,7 @@ function updatedEntries(value) {
|
|
|
505
485
|
}
|
|
506
486
|
return entries;
|
|
507
487
|
}
|
|
508
|
-
function
|
|
488
|
+
function formatTodoSuccessSummary(args, theme, result) {
|
|
509
489
|
const parsed = todoDetails(result.details);
|
|
510
490
|
if (!parsed)
|
|
511
491
|
return undefined;
|
|
@@ -566,8 +546,8 @@ function formatTodoGroupSuccess(args, theme, result) {
|
|
|
566
546
|
void args;
|
|
567
547
|
return segments.join(theme.fg("dim", " ; "));
|
|
568
548
|
}
|
|
569
|
-
/** Compact result-aware summary
|
|
570
|
-
export function
|
|
549
|
+
/** Compact result-aware one-line summary of a collapsed todo row. */
|
|
550
|
+
export function formatTodoSummary(args, theme, context) {
|
|
571
551
|
if (context.isError) {
|
|
572
552
|
let reason = "tool failed";
|
|
573
553
|
try {
|
|
@@ -580,7 +560,8 @@ export function formatTodoGroupCall(args, theme, context) {
|
|
|
580
560
|
.trim();
|
|
581
561
|
if (!text)
|
|
582
562
|
continue;
|
|
583
|
-
reason =
|
|
563
|
+
reason =
|
|
564
|
+
text.length > SUMMARY_FAILURE_MAX_LENGTH ? `${text.slice(0, SUMMARY_FAILURE_MAX_LENGTH - 1)}…` : text;
|
|
584
565
|
break;
|
|
585
566
|
}
|
|
586
567
|
}
|
|
@@ -590,7 +571,7 @@ export function formatTodoGroupCall(args, theme, context) {
|
|
|
590
571
|
return `${formatTodoCall(args, theme, false)} ${theme.fg("error", `failed: ${reason}`)}`;
|
|
591
572
|
}
|
|
592
573
|
if (!context.isPartial && context.result) {
|
|
593
|
-
const summary =
|
|
574
|
+
const summary = formatTodoSuccessSummary(args, theme, context.result);
|
|
594
575
|
if (summary)
|
|
595
576
|
return summary;
|
|
596
577
|
}
|