@code-yeongyu/senpi 2026.6.6-3 → 2026.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +113 -111
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/project-trust.d.ts +10 -0
- package/dist/cli/project-trust.d.ts.map +1 -0
- package/dist/cli/project-trust.js +48 -0
- package/dist/cli/project-trust.js.map +1 -0
- package/dist/cli/startup-ui.d.ts +7 -0
- package/dist/cli/startup-ui.d.ts.map +1 -0
- package/dist/cli/startup-ui.js +59 -0
- package/dist/cli/startup-ui.js.map +1 -0
- package/dist/cli.js +10 -1
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +3 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +4 -1
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +2 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +2 -2
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +6 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +1 -1
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/experimental.d.ts +2 -0
- package/dist/core/experimental.d.ts.map +1 -0
- package/dist/core/experimental.js +4 -0
- package/dist/core/experimental.js.map +1 -0
- package/dist/core/extensions/builtin/todotools/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/index.js +0 -2
- package/dist/core/extensions/builtin/todotools/index.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/prompt.d.ts +1 -1
- package/dist/core/extensions/builtin/todotools/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/prompt.js +0 -2
- package/dist/core/extensions/builtin/todotools/prompt.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 +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +4 -4
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +7 -2
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +34 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +21 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/model-registry.d.ts +3 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +22 -3
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/project-trust.d.ts +15 -0
- package/dist/core/project-trust.d.ts.map +1 -0
- package/dist/core/project-trust.js +58 -0
- package/dist/core/project-trust.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +2 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +24 -26
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/resource-loader.d.ts +14 -3
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +128 -58
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +34 -17
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-resident-store.d.ts +16 -0
- package/dist/core/session-resident-store.d.ts.map +1 -0
- package/dist/core/session-resident-store.js +48 -0
- package/dist/core/session-resident-store.js.map +1 -0
- package/dist/core/settings-manager.d.ts +4 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +9 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/trust-manager.d.ts +22 -0
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +75 -22
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +92 -129
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +39 -34
- package/dist/migrations.js.map +1 -1
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +1 -0
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +7 -1
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +20 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +26 -4
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts +6 -3
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/trust-selector.js +22 -18
- package/dist/modes/interactive/components/trust-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +15 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +158 -19
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/working-status.d.ts +2 -0
- package/dist/modes/interactive/working-status.d.ts.map +1 -1
- package/dist/modes/interactive/working-status.js +34 -0
- package/dist/modes/interactive/working-status.js.map +1 -1
- package/dist/package-manager-cli.d.ts +6 -2
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +58 -11
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/senpi +10 -1
- package/dist/utils/changelog.d.ts +1 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +78 -0
- package/dist/utils/changelog.js.map +1 -1
- package/docs/docs.json +4 -0
- package/docs/extensions.md +30 -1
- package/docs/index.md +1 -0
- package/docs/models.md +6 -39
- package/docs/packages.md +0 -2
- package/docs/prompt-templates.md +8 -1
- package/docs/sdk.md +5 -0
- package/docs/security.md +55 -0
- package/docs/settings.md +7 -4
- package/docs/terminal-setup.md +36 -2
- package/docs/tmux.md +4 -2
- package/docs/usage.md +12 -7
- package/examples/extensions/README.md +1 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/project-trust.ts +64 -0
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +125 -77
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.d.ts +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +6 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/README.md +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +6 -6
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +373 -116
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +353 -202
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +15 -7
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +17 -7
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +4 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +5 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/autocomplete.d.ts +2 -0
- package/node_modules/@earendil-works/pi-tui/dist/autocomplete.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/autocomplete.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts +6 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +89 -39
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/loader.d.ts +5 -0
- package/node_modules/@earendil-works/pi-tui/dist/components/loader.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/loader.js +18 -4
- package/node_modules/@earendil-works/pi-tui/dist/components/loader.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/fuzzy.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/fuzzy.js +131 -61
- package/node_modules/@earendil-works/pi-tui/dist/fuzzy.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +4 -7
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js +38 -76
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js +14 -4
- package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.js +43 -15
- package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -8
- package/dist/core/extensions/builtin/todotools/continuation/config.d.ts +0 -10
- package/dist/core/extensions/builtin/todotools/continuation/config.d.ts.map +0 -1
- package/dist/core/extensions/builtin/todotools/continuation/config.js +0 -33
- package/dist/core/extensions/builtin/todotools/continuation/config.js.map +0 -1
- package/dist/core/extensions/builtin/todotools/continuation/index.d.ts +0 -2
- package/dist/core/extensions/builtin/todotools/continuation/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/todotools/continuation/index.js +0 -2
- package/dist/core/extensions/builtin/todotools/continuation/index.js.map +0 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts +0 -5
- package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts.map +0 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.js +0 -34
- package/dist/core/extensions/builtin/todotools/continuation/prompt.js.map +0 -1
- package/dist/core/extensions/builtin/todotools/continuation/runtime.d.ts +0 -11
- package/dist/core/extensions/builtin/todotools/continuation/runtime.d.ts.map +0 -1
- package/dist/core/extensions/builtin/todotools/continuation/runtime.js +0 -201
- package/dist/core/extensions/builtin/todotools/continuation/runtime.js.map +0 -1
- package/dist/core/extensions/builtin/todotools/settings.d.ts +0 -6
- package/dist/core/extensions/builtin/todotools/settings.d.ts.map +0 -1
- package/dist/core/extensions/builtin/todotools/settings.js +0 -58
- package/dist/core/extensions/builtin/todotools/settings.js.map +0 -1
- package/dist/core/extensions/builtin/todotools/system-messages.d.ts +0 -34
- package/dist/core/extensions/builtin/todotools/system-messages.d.ts.map +0 -1
- package/dist/core/extensions/builtin/todotools/system-messages.js +0 -82
- package/dist/core/extensions/builtin/todotools/system-messages.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/todotools/continuation/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEhF,eAAO,MAAM,sBAAsB,y3BAUmN,CAAC;AAEvP,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAEzD;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAmBjE"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { isIncompleteTodo, sanitizeTodoText } from "../state.js";
|
|
2
|
-
export const CONTINUATION_DIRECTIVE = `[SYSTEM DIRECTIVE: SENPI - TODO CONTINUATION]
|
|
3
|
-
|
|
4
|
-
Incomplete tasks remain in your todo list. Continue working on the next pending task.
|
|
5
|
-
|
|
6
|
-
- FIRST: Continue the first actionable remaining task now. If an in-progress task is already done, verify it and mark it completed before moving on
|
|
7
|
-
- Proceed without asking for permission
|
|
8
|
-
- Mark each task complete immediately when finished
|
|
9
|
-
- Do not stop until all tasks are done
|
|
10
|
-
- Do not reply with refusal, deferral, or a summary-only response
|
|
11
|
-
- If a task is already complete, no longer needed, or blocked, verify that and update the todo list to a terminal state instead of leaving it pending
|
|
12
|
-
- If you believe all work is already complete, the system is questioning your completion claim. Critically re-examine each todo item from a skeptical perspective, verify the work was actually done correctly, and update the todo list accordingly.`;
|
|
13
|
-
export function countIncomplete(todos) {
|
|
14
|
-
return todos.filter(isIncompleteTodo).length;
|
|
15
|
-
}
|
|
16
|
-
export function buildContinuationPrompt(todos) {
|
|
17
|
-
if (todos.length === 0) {
|
|
18
|
-
return "";
|
|
19
|
-
}
|
|
20
|
-
const completedCount = todos.filter((todo) => todo.status === "completed").length;
|
|
21
|
-
const remainingTodos = todos.filter(isIncompleteTodo);
|
|
22
|
-
const activeTotal = completedCount + remainingTodos.length;
|
|
23
|
-
const remainingLines = remainingTodos
|
|
24
|
-
.map((todo) => `- [${todo.status}] ${sanitizeTodoText(todo.content)}`)
|
|
25
|
-
.join("\n");
|
|
26
|
-
return `${CONTINUATION_DIRECTIVE}
|
|
27
|
-
|
|
28
|
-
[Status: ${completedCount}/${activeTotal} completed, ${remainingTodos.length} remaining]
|
|
29
|
-
|
|
30
|
-
Remaining tasks:
|
|
31
|
-
${remainingLines}
|
|
32
|
-
`;
|
|
33
|
-
}
|
|
34
|
-
//# sourceMappingURL=prompt.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/todotools/continuation/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAiB,MAAM,aAAa,CAAC;AAEhF,MAAM,CAAC,MAAM,sBAAsB,GAAG;;;;;;;;;;sPAUgN,CAAC;AAEvP,MAAM,UAAU,eAAe,CAAC,KAAiB;IAChD,OAAO,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAiB;IACxD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACX,CAAC;IAED,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM,CAAC;IAClF,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC;IAC3D,MAAM,cAAc,GAAG,cAAc;SACnC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,IAAI,CAAC,MAAM,KAAK,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;SACrE,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO,GAAG,sBAAsB;;WAEtB,cAAc,IAAI,WAAW,eAAe,cAAc,CAAC,MAAM;;;EAG1E,cAAc;CACf,CAAC;AACF,CAAC","sourcesContent":["import { isIncompleteTodo, sanitizeTodoText, type TodoItem } from \"../state.ts\";\n\nexport const CONTINUATION_DIRECTIVE = `[SYSTEM DIRECTIVE: SENPI - TODO CONTINUATION]\n\nIncomplete tasks remain in your todo list. Continue working on the next pending task.\n\n- FIRST: Continue the first actionable remaining task now. If an in-progress task is already done, verify it and mark it completed before moving on\n- Proceed without asking for permission\n- Mark each task complete immediately when finished\n- Do not stop until all tasks are done\n- Do not reply with refusal, deferral, or a summary-only response\n- If a task is already complete, no longer needed, or blocked, verify that and update the todo list to a terminal state instead of leaving it pending\n- If you believe all work is already complete, the system is questioning your completion claim. Critically re-examine each todo item from a skeptical perspective, verify the work was actually done correctly, and update the todo list accordingly.`;\n\nexport function countIncomplete(todos: TodoItem[]): number {\n\treturn todos.filter(isIncompleteTodo).length;\n}\n\nexport function buildContinuationPrompt(todos: TodoItem[]): string {\n\tif (todos.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst completedCount = todos.filter((todo) => todo.status === \"completed\").length;\n\tconst remainingTodos = todos.filter(isIncompleteTodo);\n\tconst activeTotal = completedCount + remainingTodos.length;\n\tconst remainingLines = remainingTodos\n\t\t.map((todo) => `- [${todo.status}] ${sanitizeTodoText(todo.content)}`)\n\t\t.join(\"\\n\");\n\n\treturn `${CONTINUATION_DIRECTIVE}\n\n[Status: ${completedCount}/${activeTotal} completed, ${remainingTodos.length} remaining]\n\nRemaining tasks:\n${remainingLines}\n`;\n}\n"]}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "../../../types.ts";
|
|
2
|
-
import type { TodoItem } from "../state.ts";
|
|
3
|
-
type ContinuationDeps = {
|
|
4
|
-
getCurrentTodos: () => TodoItem[];
|
|
5
|
-
};
|
|
6
|
-
export declare const CONTINUATION_CHAIN_CAP = 10;
|
|
7
|
-
export declare function isContinuationFollowUpPrompt(prompt: string): boolean;
|
|
8
|
-
export declare function isCleanStopReason(stopReason: string | undefined): boolean;
|
|
9
|
-
export declare function installContinuation(pi: ExtensionAPI, deps: ContinuationDeps): void;
|
|
10
|
-
export {};
|
|
11
|
-
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/todotools/continuation/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAuC,MAAM,mBAAmB,CAAC;AAE3F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAW5C,KAAK,gBAAgB,GAAG;IACvB,eAAe,EAAE,MAAM,QAAQ,EAAE,CAAC;CAClC,CAAC;AAGF,eAAO,MAAM,sBAAsB,KAAK,CAAC;AA0BzC,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEzE;AAqGD,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAkGlF"}
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import { readTodoSettings } from "../settings.js";
|
|
2
|
-
import { emitTodoSystemMessageFailure, sendTodoUserMessage } from "../system-messages.js";
|
|
3
|
-
import { resolveContinuationConfig } from "./config.js";
|
|
4
|
-
import { buildContinuationPrompt, CONTINUATION_DIRECTIVE, countIncomplete } from "./prompt.js";
|
|
5
|
-
const CLEAN_STOP_REASONS = new Set(["stop", "toolUse", "endTurn", "end_turn"]);
|
|
6
|
-
export const CONTINUATION_CHAIN_CAP = 10;
|
|
7
|
-
const IDLE_POLL_INTERVAL_MS = 50;
|
|
8
|
-
const IDLE_WAIT_TIMEOUT_MS = 10_000;
|
|
9
|
-
function isAssistantMessage(message) {
|
|
10
|
-
if (!message || typeof message !== "object") {
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
const role = message.role;
|
|
14
|
-
return role === "assistant";
|
|
15
|
-
}
|
|
16
|
-
function getLastAssistantStopReason(messages) {
|
|
17
|
-
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
18
|
-
const message = messages[index];
|
|
19
|
-
if (!isAssistantMessage(message)) {
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
return message.stopReason;
|
|
23
|
-
}
|
|
24
|
-
return undefined;
|
|
25
|
-
}
|
|
26
|
-
export function isContinuationFollowUpPrompt(prompt) {
|
|
27
|
-
return prompt.includes(CONTINUATION_DIRECTIVE);
|
|
28
|
-
}
|
|
29
|
-
export function isCleanStopReason(stopReason) {
|
|
30
|
-
return typeof stopReason === "string" && CLEAN_STOP_REASONS.has(stopReason);
|
|
31
|
-
}
|
|
32
|
-
function createInitialState() {
|
|
33
|
-
return {
|
|
34
|
-
reEntryFlag: false,
|
|
35
|
-
chainCount: 0,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function abortPendingDispatch(state) {
|
|
39
|
-
state.pendingDispatchAbortController?.abort();
|
|
40
|
-
state.pendingDispatchAbortController = undefined;
|
|
41
|
-
}
|
|
42
|
-
function getSessionState(sessionStates, sessionId) {
|
|
43
|
-
const existingState = sessionStates.get(sessionId);
|
|
44
|
-
if (existingState) {
|
|
45
|
-
return existingState;
|
|
46
|
-
}
|
|
47
|
-
const nextState = createInitialState();
|
|
48
|
-
sessionStates.set(sessionId, nextState);
|
|
49
|
-
return nextState;
|
|
50
|
-
}
|
|
51
|
-
function getSessionId(ctx) {
|
|
52
|
-
return ctx.sessionManager.getSessionId();
|
|
53
|
-
}
|
|
54
|
-
function isNonInteractiveContext(ctx) {
|
|
55
|
-
return !ctx.hasUI;
|
|
56
|
-
}
|
|
57
|
-
function shouldResetForSessionStart(event) {
|
|
58
|
-
const reason = event.reason;
|
|
59
|
-
return reason === "reload" || reason === "resume" || reason === "compact";
|
|
60
|
-
}
|
|
61
|
-
function reportContinuationError(pi, ctx, error, prompt) {
|
|
62
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
63
|
-
emitTodoSystemMessageFailure(pi, {
|
|
64
|
-
route: "todotools.continuation",
|
|
65
|
-
sessionId: getSessionId(ctx),
|
|
66
|
-
content: prompt ?? "",
|
|
67
|
-
errorMessage: message,
|
|
68
|
-
});
|
|
69
|
-
pi.events.emit("todotools:continuation_error", {
|
|
70
|
-
sessionId: getSessionId(ctx),
|
|
71
|
-
message,
|
|
72
|
-
});
|
|
73
|
-
if (ctx.hasUI) {
|
|
74
|
-
ctx.ui.notify(`Todo continuation failed: ${message}`, "error");
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
process.stderr.write(`[todotools continuation] ${message}\n`);
|
|
78
|
-
}
|
|
79
|
-
function wait(ms) {
|
|
80
|
-
return new Promise((resolve) => {
|
|
81
|
-
setTimeout(resolve, ms);
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
async function dispatchContinuationWhenIdle(pi, ctx, prompt, signal) {
|
|
85
|
-
const startedAt = Date.now();
|
|
86
|
-
if (signal.aborted) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
while (Date.now() - startedAt < IDLE_WAIT_TIMEOUT_MS) {
|
|
90
|
-
if (signal.aborted) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
if (ctx.isIdle()) {
|
|
94
|
-
if (signal.aborted) {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
sendTodoUserMessage(pi, "todotools.continuation", prompt, {
|
|
98
|
-
sessionId: getSessionId(ctx),
|
|
99
|
-
});
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
await wait(IDLE_POLL_INTERVAL_MS);
|
|
103
|
-
if (signal.aborted) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
console.warn("[todotools continuation] Timed out waiting for idle state; skipping auto-dispatch.");
|
|
108
|
-
}
|
|
109
|
-
export function installContinuation(pi, deps) {
|
|
110
|
-
const sessionStates = new Map();
|
|
111
|
-
pi.registerFlag("disable-todo-continuation", {
|
|
112
|
-
type: "boolean",
|
|
113
|
-
default: false,
|
|
114
|
-
description: "Disable todo continuation — automatic follow-up when incomplete todos remain in the list",
|
|
115
|
-
});
|
|
116
|
-
pi.on("before_agent_start", async (event, ctx) => {
|
|
117
|
-
const sessionState = getSessionState(sessionStates, getSessionId(ctx));
|
|
118
|
-
sessionState.reEntryFlag = false;
|
|
119
|
-
if (!isContinuationFollowUpPrompt(event.prompt)) {
|
|
120
|
-
sessionState.chainCount = 0;
|
|
121
|
-
abortPendingDispatch(sessionState);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
pi.on("session_start", async (event, ctx) => {
|
|
125
|
-
if (!shouldResetForSessionStart(event)) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
const sessionId = getSessionId(ctx);
|
|
129
|
-
const existingState = sessionStates.get(sessionId);
|
|
130
|
-
if (existingState) {
|
|
131
|
-
abortPendingDispatch(existingState);
|
|
132
|
-
}
|
|
133
|
-
sessionStates.set(sessionId, createInitialState());
|
|
134
|
-
});
|
|
135
|
-
pi.on("session_shutdown", async (_event, ctx) => {
|
|
136
|
-
const sessionId = getSessionId(ctx);
|
|
137
|
-
const existingState = sessionStates.get(sessionId);
|
|
138
|
-
if (existingState) {
|
|
139
|
-
abortPendingDispatch(existingState);
|
|
140
|
-
}
|
|
141
|
-
sessionStates.delete(sessionId);
|
|
142
|
-
});
|
|
143
|
-
pi.on("agent_end", async (event, ctx) => {
|
|
144
|
-
try {
|
|
145
|
-
if (isNonInteractiveContext(ctx)) {
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
const stopReason = getLastAssistantStopReason(event.messages);
|
|
149
|
-
if (!isCleanStopReason(stopReason)) {
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
const settings = readTodoSettings(ctx.cwd);
|
|
153
|
-
const config = resolveContinuationConfig({
|
|
154
|
-
globalSettings: settings.globalSettings,
|
|
155
|
-
projectSettings: settings.projectSettings,
|
|
156
|
-
cliFlag: pi.getFlag("disable-todo-continuation"),
|
|
157
|
-
});
|
|
158
|
-
if (!config.enabled) {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
const todos = deps.getCurrentTodos();
|
|
162
|
-
if (countIncomplete(todos) === 0) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
const sessionId = getSessionId(ctx);
|
|
166
|
-
const sessionState = getSessionState(sessionStates, sessionId);
|
|
167
|
-
if (sessionState.reEntryFlag) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
if (sessionState.chainCount >= CONTINUATION_CHAIN_CAP) {
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
const prompt = buildContinuationPrompt(todos);
|
|
174
|
-
abortPendingDispatch(sessionState);
|
|
175
|
-
const pendingDispatchAbortController = new AbortController();
|
|
176
|
-
sessionState.pendingDispatchAbortController = pendingDispatchAbortController;
|
|
177
|
-
sessionState.reEntryFlag = true;
|
|
178
|
-
sessionState.chainCount += 1;
|
|
179
|
-
setTimeout(() => {
|
|
180
|
-
void (async () => {
|
|
181
|
-
try {
|
|
182
|
-
await dispatchContinuationWhenIdle(pi, ctx, prompt, pendingDispatchAbortController.signal);
|
|
183
|
-
}
|
|
184
|
-
catch (error) {
|
|
185
|
-
reportContinuationError(pi, ctx, error, prompt);
|
|
186
|
-
}
|
|
187
|
-
finally {
|
|
188
|
-
const currentState = sessionStates.get(sessionId);
|
|
189
|
-
if (currentState?.pendingDispatchAbortController === pendingDispatchAbortController) {
|
|
190
|
-
currentState.pendingDispatchAbortController = undefined;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
})();
|
|
194
|
-
}, 0);
|
|
195
|
-
}
|
|
196
|
-
catch (error) {
|
|
197
|
-
reportContinuationError(pi, ctx, error);
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
//# sourceMappingURL=runtime.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/todotools/continuation/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI, ExtensionContext, SessionStartEvent } from \"../../../types.ts\";\nimport { readTodoSettings } from \"../settings.ts\";\nimport type { TodoItem } from \"../state.ts\";\nimport { emitTodoSystemMessageFailure, sendTodoUserMessage } from \"../system-messages.ts\";\nimport { resolveContinuationConfig } from \"./config.ts\";\nimport { buildContinuationPrompt, CONTINUATION_DIRECTIVE, countIncomplete } from \"./prompt.ts\";\n\ntype ContinuationState = {\n\treEntryFlag: boolean;\n\tchainCount: number;\n\tpendingDispatchAbortController?: AbortController;\n};\n\ntype ContinuationDeps = {\n\tgetCurrentTodos: () => TodoItem[];\n};\n\nconst CLEAN_STOP_REASONS = new Set([\"stop\", \"toolUse\", \"endTurn\", \"end_turn\"]);\nexport const CONTINUATION_CHAIN_CAP = 10;\nconst IDLE_POLL_INTERVAL_MS = 50;\nconst IDLE_WAIT_TIMEOUT_MS = 10_000;\n\nfunction isAssistantMessage(message: unknown): message is AssistantMessage {\n\tif (!message || typeof message !== \"object\") {\n\t\treturn false;\n\t}\n\n\tconst role = (message as { role?: unknown }).role;\n\treturn role === \"assistant\";\n}\n\nfunction getLastAssistantStopReason(messages: unknown[]): string | undefined {\n\tfor (let index = messages.length - 1; index >= 0; index -= 1) {\n\t\tconst message = messages[index];\n\t\tif (!isAssistantMessage(message)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn message.stopReason;\n\t}\n\n\treturn undefined;\n}\n\nexport function isContinuationFollowUpPrompt(prompt: string): boolean {\n\treturn prompt.includes(CONTINUATION_DIRECTIVE);\n}\n\nexport function isCleanStopReason(stopReason: string | undefined): boolean {\n\treturn typeof stopReason === \"string\" && CLEAN_STOP_REASONS.has(stopReason);\n}\n\nfunction createInitialState(): ContinuationState {\n\treturn {\n\t\treEntryFlag: false,\n\t\tchainCount: 0,\n\t};\n}\n\nfunction abortPendingDispatch(state: ContinuationState): void {\n\tstate.pendingDispatchAbortController?.abort();\n\tstate.pendingDispatchAbortController = undefined;\n}\n\nfunction getSessionState(sessionStates: Map<string, ContinuationState>, sessionId: string): ContinuationState {\n\tconst existingState = sessionStates.get(sessionId);\n\tif (existingState) {\n\t\treturn existingState;\n\t}\n\n\tconst nextState = createInitialState();\n\tsessionStates.set(sessionId, nextState);\n\treturn nextState;\n}\n\nfunction getSessionId(ctx: ExtensionContext): string {\n\treturn ctx.sessionManager.getSessionId();\n}\n\nfunction isNonInteractiveContext(ctx: ExtensionContext): boolean {\n\treturn !ctx.hasUI;\n}\n\nfunction shouldResetForSessionStart(event: SessionStartEvent): boolean {\n\tconst reason = event.reason as string;\n\treturn reason === \"reload\" || reason === \"resume\" || reason === \"compact\";\n}\n\nfunction reportContinuationError(pi: ExtensionAPI, ctx: ExtensionContext, error: unknown, prompt?: string): void {\n\tconst message = error instanceof Error ? error.message : String(error);\n\temitTodoSystemMessageFailure(pi, {\n\t\troute: \"todotools.continuation\",\n\t\tsessionId: getSessionId(ctx),\n\t\tcontent: prompt ?? \"\",\n\t\terrorMessage: message,\n\t});\n\tpi.events.emit(\"todotools:continuation_error\", {\n\t\tsessionId: getSessionId(ctx),\n\t\tmessage,\n\t});\n\tif (ctx.hasUI) {\n\t\tctx.ui.notify(`Todo continuation failed: ${message}`, \"error\");\n\t\treturn;\n\t}\n\tprocess.stderr.write(`[todotools continuation] ${message}\\n`);\n}\n\nfunction wait(ms: number): Promise<void> {\n\treturn new Promise((resolve) => {\n\t\tsetTimeout(resolve, ms);\n\t});\n}\n\nasync function dispatchContinuationWhenIdle(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tprompt: string,\n\tsignal: AbortSignal,\n): Promise<void> {\n\tconst startedAt = Date.now();\n\n\tif (signal.aborted) {\n\t\treturn;\n\t}\n\n\twhile (Date.now() - startedAt < IDLE_WAIT_TIMEOUT_MS) {\n\t\tif (signal.aborted) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (ctx.isIdle()) {\n\t\t\tif (signal.aborted) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsendTodoUserMessage(pi, \"todotools.continuation\", prompt, {\n\t\t\t\tsessionId: getSessionId(ctx),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tawait wait(IDLE_POLL_INTERVAL_MS);\n\n\t\tif (signal.aborted) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tconsole.warn(\"[todotools continuation] Timed out waiting for idle state; skipping auto-dispatch.\");\n}\n\nexport function installContinuation(pi: ExtensionAPI, deps: ContinuationDeps): void {\n\tconst sessionStates = new Map<string, ContinuationState>();\n\n\tpi.registerFlag(\"disable-todo-continuation\", {\n\t\ttype: \"boolean\",\n\t\tdefault: false,\n\t\tdescription: \"Disable todo continuation — automatic follow-up when incomplete todos remain in the list\",\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tconst sessionState = getSessionState(sessionStates, getSessionId(ctx));\n\t\tsessionState.reEntryFlag = false;\n\t\tif (!isContinuationFollowUpPrompt(event.prompt)) {\n\t\t\tsessionState.chainCount = 0;\n\t\t\tabortPendingDispatch(sessionState);\n\t\t}\n\t});\n\n\tpi.on(\"session_start\", async (event, ctx) => {\n\t\tif (!shouldResetForSessionStart(event)) {\n\t\t\treturn;\n\t\t}\n\t\tconst sessionId = getSessionId(ctx);\n\t\tconst existingState = sessionStates.get(sessionId);\n\t\tif (existingState) {\n\t\t\tabortPendingDispatch(existingState);\n\t\t}\n\t\tsessionStates.set(sessionId, createInitialState());\n\t});\n\n\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\tconst sessionId = getSessionId(ctx);\n\t\tconst existingState = sessionStates.get(sessionId);\n\t\tif (existingState) {\n\t\t\tabortPendingDispatch(existingState);\n\t\t}\n\t\tsessionStates.delete(sessionId);\n\t});\n\n\tpi.on(\"agent_end\", async (event, ctx) => {\n\t\ttry {\n\t\t\tif (isNonInteractiveContext(ctx)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst stopReason = getLastAssistantStopReason(event.messages);\n\t\t\tif (!isCleanStopReason(stopReason)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst settings = readTodoSettings(ctx.cwd);\n\t\t\tconst config = resolveContinuationConfig({\n\t\t\t\tglobalSettings: settings.globalSettings,\n\t\t\t\tprojectSettings: settings.projectSettings,\n\t\t\t\tcliFlag: pi.getFlag(\"disable-todo-continuation\"),\n\t\t\t});\n\t\t\tif (!config.enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst todos = deps.getCurrentTodos();\n\t\t\tif (countIncomplete(todos) === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst sessionId = getSessionId(ctx);\n\t\t\tconst sessionState = getSessionState(sessionStates, sessionId);\n\t\t\tif (sessionState.reEntryFlag) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (sessionState.chainCount >= CONTINUATION_CHAIN_CAP) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst prompt = buildContinuationPrompt(todos);\n\t\t\tabortPendingDispatch(sessionState);\n\t\t\tconst pendingDispatchAbortController = new AbortController();\n\t\t\tsessionState.pendingDispatchAbortController = pendingDispatchAbortController;\n\t\t\tsessionState.reEntryFlag = true;\n\t\t\tsessionState.chainCount += 1;\n\t\t\tsetTimeout(() => {\n\t\t\t\tvoid (async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait dispatchContinuationWhenIdle(pi, ctx, prompt, pendingDispatchAbortController.signal);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\treportContinuationError(pi, ctx, error, prompt);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tconst currentState = sessionStates.get(sessionId);\n\t\t\t\t\t\tif (currentState?.pendingDispatchAbortController === pendingDispatchAbortController) {\n\t\t\t\t\t\t\tcurrentState.pendingDispatchAbortController = undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}, 0);\n\t\t} catch (error) {\n\t\t\treportContinuationError(pi, ctx, error);\n\t\t}\n\t});\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/todotools/settings.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAChC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAuDD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAK9D"}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
function isRecord(value) {
|
|
5
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
|
-
}
|
|
7
|
-
function readJsonObject(path) {
|
|
8
|
-
if (!existsSync(path)) {
|
|
9
|
-
return {};
|
|
10
|
-
}
|
|
11
|
-
try {
|
|
12
|
-
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
13
|
-
return isRecord(parsed) ? parsed : {};
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return {};
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function mergeSettings(base, override) {
|
|
20
|
-
const merged = { ...base };
|
|
21
|
-
for (const [key, value] of Object.entries(override)) {
|
|
22
|
-
const current = merged[key];
|
|
23
|
-
if (isRecord(current) && isRecord(value)) {
|
|
24
|
-
merged[key] = mergeSettings(current, value);
|
|
25
|
-
continue;
|
|
26
|
-
}
|
|
27
|
-
merged[key] = value;
|
|
28
|
-
}
|
|
29
|
-
return merged;
|
|
30
|
-
}
|
|
31
|
-
function unique(paths) {
|
|
32
|
-
return [...new Set(paths)];
|
|
33
|
-
}
|
|
34
|
-
function getGlobalSettingsPaths() {
|
|
35
|
-
const paths = [];
|
|
36
|
-
const piAgentDir = process.env.PI_CODING_AGENT_DIR;
|
|
37
|
-
const senpiAgentDir = process.env.SENPI_CODING_AGENT_DIR;
|
|
38
|
-
if (piAgentDir)
|
|
39
|
-
paths.push(join(piAgentDir, "settings.json"));
|
|
40
|
-
if (senpiAgentDir)
|
|
41
|
-
paths.push(join(senpiAgentDir, "settings.json"));
|
|
42
|
-
paths.push(join(homedir(), ".pi", "agent", "settings.json"));
|
|
43
|
-
paths.push(join(homedir(), ".senpi", "agent", "settings.json"));
|
|
44
|
-
return unique(paths);
|
|
45
|
-
}
|
|
46
|
-
function getProjectSettingsPaths(cwd) {
|
|
47
|
-
return [join(cwd, ".pi", "settings.json"), join(cwd, ".senpi", "settings.json")];
|
|
48
|
-
}
|
|
49
|
-
function readMergedSettings(paths) {
|
|
50
|
-
return paths.reduce((settings, path) => mergeSettings(settings, readJsonObject(path)), {});
|
|
51
|
-
}
|
|
52
|
-
export function readTodoSettings(cwd) {
|
|
53
|
-
return {
|
|
54
|
-
globalSettings: readMergedSettings(getGlobalSettingsPaths()),
|
|
55
|
-
projectSettings: readMergedSettings(getProjectSettingsPaths(cwd)),
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
//# sourceMappingURL=settings.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/todotools/settings.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface TodoSettingsPair {\n\tglobalSettings: Record<string, unknown>;\n\tprojectSettings: Record<string, unknown>;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction readJsonObject(path: string): Record<string, unknown> {\n\tif (!existsSync(path)) {\n\t\treturn {};\n\t}\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(path, \"utf-8\"));\n\t\treturn isRecord(parsed) ? parsed : {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction mergeSettings(base: Record<string, unknown>, override: Record<string, unknown>): Record<string, unknown> {\n\tconst merged: Record<string, unknown> = { ...base };\n\tfor (const [key, value] of Object.entries(override)) {\n\t\tconst current = merged[key];\n\t\tif (isRecord(current) && isRecord(value)) {\n\t\t\tmerged[key] = mergeSettings(current, value);\n\t\t\tcontinue;\n\t\t}\n\t\tmerged[key] = value;\n\t}\n\treturn merged;\n}\n\nfunction unique(paths: string[]): string[] {\n\treturn [...new Set(paths)];\n}\n\nfunction getGlobalSettingsPaths(): string[] {\n\tconst paths: string[] = [];\n\tconst piAgentDir = process.env.PI_CODING_AGENT_DIR;\n\tconst senpiAgentDir = process.env.SENPI_CODING_AGENT_DIR;\n\tif (piAgentDir) paths.push(join(piAgentDir, \"settings.json\"));\n\tif (senpiAgentDir) paths.push(join(senpiAgentDir, \"settings.json\"));\n\tpaths.push(join(homedir(), \".pi\", \"agent\", \"settings.json\"));\n\tpaths.push(join(homedir(), \".senpi\", \"agent\", \"settings.json\"));\n\treturn unique(paths);\n}\n\nfunction getProjectSettingsPaths(cwd: string): string[] {\n\treturn [join(cwd, \".pi\", \"settings.json\"), join(cwd, \".senpi\", \"settings.json\")];\n}\n\nfunction readMergedSettings(paths: string[]): Record<string, unknown> {\n\treturn paths.reduce<Record<string, unknown>>((settings, path) => mergeSettings(settings, readJsonObject(path)), {});\n}\n\nexport function readTodoSettings(cwd: string): TodoSettingsPair {\n\treturn {\n\t\tglobalSettings: readMergedSettings(getGlobalSettingsPaths()),\n\t\tprojectSettings: readMergedSettings(getProjectSettingsPaths(cwd)),\n\t};\n}\n"]}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { ImageContent, TextContent } from "@earendil-works/pi-ai";
|
|
2
|
-
import type { ExtensionAPI } from "../../types.ts";
|
|
3
|
-
export declare const SENPI_SYSTEM_PREFIX = "[system:senpi]";
|
|
4
|
-
export declare const SENPI_CONVERSATION_EVENT = "senpi:conversation";
|
|
5
|
-
export type TodoSystemMessageRoute = "todotools.continuation";
|
|
6
|
-
export type TodoConversationAction = "injected" | "failed";
|
|
7
|
-
export interface TodoConversationEvent {
|
|
8
|
-
version: 1;
|
|
9
|
-
source: "builtin";
|
|
10
|
-
action: TodoConversationAction;
|
|
11
|
-
route: TodoSystemMessageRoute;
|
|
12
|
-
sessionId?: string;
|
|
13
|
-
timestamp: number;
|
|
14
|
-
conversation: {
|
|
15
|
-
prefix: typeof SENPI_SYSTEM_PREFIX;
|
|
16
|
-
kind: "user_message";
|
|
17
|
-
deliverAs?: "steer" | "followUp";
|
|
18
|
-
};
|
|
19
|
-
text: string;
|
|
20
|
-
errorMessage?: string;
|
|
21
|
-
}
|
|
22
|
-
export interface TodoUserMessageOptions {
|
|
23
|
-
sessionId?: string;
|
|
24
|
-
deliverAs?: "steer" | "followUp";
|
|
25
|
-
}
|
|
26
|
-
export declare function sendTodoUserMessage(pi: ExtensionAPI, route: TodoSystemMessageRoute, content: string | (TextContent | ImageContent)[], options?: TodoUserMessageOptions): void;
|
|
27
|
-
export declare function emitTodoSystemMessageFailure(pi: ExtensionAPI, args: {
|
|
28
|
-
route: TodoSystemMessageRoute;
|
|
29
|
-
sessionId?: string;
|
|
30
|
-
content: string | (TextContent | ImageContent)[];
|
|
31
|
-
deliverAs?: "steer" | "followUp";
|
|
32
|
-
errorMessage: string;
|
|
33
|
-
}): void;
|
|
34
|
-
//# sourceMappingURL=system-messages.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"system-messages.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/todotools/system-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AACpD,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAE7D,MAAM,MAAM,sBAAsB,GAAG,wBAAwB,CAAC;AAC9D,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE3D,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,sBAAsB,CAAC;IAC/B,KAAK,EAAE,sBAAsB,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE;QACb,MAAM,EAAE,OAAO,mBAAmB,CAAC;QACnC,IAAI,EAAE,cAAc,CAAC;QACrB,SAAS,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;KACjC,CAAC;IACF,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;CACjC;AA0ED,wBAAgB,mBAAmB,CAClC,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,sBAAsB,EAC7B,OAAO,EAAE,MAAM,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,EAChD,OAAO,CAAC,EAAE,sBAAsB,GAC9B,IAAI,CAoBN;AAED,wBAAgB,4BAA4B,CAC3C,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE;IACL,KAAK,EAAE,sBAAsB,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAAC;IACjD,SAAS,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;CACrB,GACC,IAAI,CAcN"}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
export const SENPI_SYSTEM_PREFIX = "[system:senpi]";
|
|
2
|
-
export const SENPI_CONVERSATION_EVENT = "senpi:conversation";
|
|
3
|
-
function prefixText(text) {
|
|
4
|
-
return text.startsWith(SENPI_SYSTEM_PREFIX) ? text : `${SENPI_SYSTEM_PREFIX}\n${text}`;
|
|
5
|
-
}
|
|
6
|
-
function prefixContent(content) {
|
|
7
|
-
if (typeof content === "string") {
|
|
8
|
-
return prefixText(content);
|
|
9
|
-
}
|
|
10
|
-
const firstTextIndex = content.findIndex((part) => part.type === "text");
|
|
11
|
-
if (firstTextIndex === -1) {
|
|
12
|
-
return [{ type: "text", text: SENPI_SYSTEM_PREFIX }, ...content];
|
|
13
|
-
}
|
|
14
|
-
return content.map((part, index) => {
|
|
15
|
-
if (part.type !== "text" || index !== firstTextIndex) {
|
|
16
|
-
return part;
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
...part,
|
|
20
|
-
text: prefixText(part.text),
|
|
21
|
-
};
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
function extractText(content) {
|
|
25
|
-
if (typeof content === "string") {
|
|
26
|
-
return content;
|
|
27
|
-
}
|
|
28
|
-
return content
|
|
29
|
-
.filter((part) => part.type === "text")
|
|
30
|
-
.map((part) => part.text)
|
|
31
|
-
.join("\n");
|
|
32
|
-
}
|
|
33
|
-
function emitTodoConversationEvent(pi, event) {
|
|
34
|
-
pi.events.emit(SENPI_CONVERSATION_EVENT, event);
|
|
35
|
-
}
|
|
36
|
-
function createBaseEvent(args) {
|
|
37
|
-
return {
|
|
38
|
-
version: 1,
|
|
39
|
-
source: "builtin",
|
|
40
|
-
action: args.action,
|
|
41
|
-
route: args.route,
|
|
42
|
-
sessionId: args.sessionId,
|
|
43
|
-
timestamp: Date.now(),
|
|
44
|
-
conversation: {
|
|
45
|
-
prefix: SENPI_SYSTEM_PREFIX,
|
|
46
|
-
kind: "user_message",
|
|
47
|
-
deliverAs: args.deliverAs,
|
|
48
|
-
},
|
|
49
|
-
text: args.text,
|
|
50
|
-
errorMessage: args.errorMessage,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function hasUserMessageOptions(options) {
|
|
54
|
-
return options?.deliverAs !== undefined;
|
|
55
|
-
}
|
|
56
|
-
export function sendTodoUserMessage(pi, route, content, options) {
|
|
57
|
-
const prefixedContent = prefixContent(content);
|
|
58
|
-
emitTodoConversationEvent(pi, createBaseEvent({
|
|
59
|
-
action: "injected",
|
|
60
|
-
route,
|
|
61
|
-
sessionId: options?.sessionId,
|
|
62
|
-
text: extractText(prefixedContent),
|
|
63
|
-
deliverAs: options?.deliverAs,
|
|
64
|
-
}));
|
|
65
|
-
if (hasUserMessageOptions(options)) {
|
|
66
|
-
pi.sendUserMessage(prefixedContent, { deliverAs: options.deliverAs });
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
pi.sendUserMessage(prefixedContent);
|
|
70
|
-
}
|
|
71
|
-
export function emitTodoSystemMessageFailure(pi, args) {
|
|
72
|
-
const prefixedContent = prefixContent(args.content);
|
|
73
|
-
emitTodoConversationEvent(pi, createBaseEvent({
|
|
74
|
-
action: "failed",
|
|
75
|
-
route: args.route,
|
|
76
|
-
sessionId: args.sessionId,
|
|
77
|
-
text: extractText(prefixedContent),
|
|
78
|
-
deliverAs: args.deliverAs,
|
|
79
|
-
errorMessage: args.errorMessage,
|
|
80
|
-
}));
|
|
81
|
-
}
|
|
82
|
-
//# sourceMappingURL=system-messages.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"system-messages.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/todotools/system-messages.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../types.ts\";\n\nexport const SENPI_SYSTEM_PREFIX = \"[system:senpi]\";\nexport const SENPI_CONVERSATION_EVENT = \"senpi:conversation\";\n\nexport type TodoSystemMessageRoute = \"todotools.continuation\";\nexport type TodoConversationAction = \"injected\" | \"failed\";\n\nexport interface TodoConversationEvent {\n\tversion: 1;\n\tsource: \"builtin\";\n\taction: TodoConversationAction;\n\troute: TodoSystemMessageRoute;\n\tsessionId?: string;\n\ttimestamp: number;\n\tconversation: {\n\t\tprefix: typeof SENPI_SYSTEM_PREFIX;\n\t\tkind: \"user_message\";\n\t\tdeliverAs?: \"steer\" | \"followUp\";\n\t};\n\ttext: string;\n\terrorMessage?: string;\n}\n\nexport interface TodoUserMessageOptions {\n\tsessionId?: string;\n\tdeliverAs?: \"steer\" | \"followUp\";\n}\n\nfunction prefixText(text: string): string {\n\treturn text.startsWith(SENPI_SYSTEM_PREFIX) ? text : `${SENPI_SYSTEM_PREFIX}\\n${text}`;\n}\n\nfunction prefixContent(content: string | (TextContent | ImageContent)[]): string | (TextContent | ImageContent)[] {\n\tif (typeof content === \"string\") {\n\t\treturn prefixText(content);\n\t}\n\n\tconst firstTextIndex = content.findIndex((part) => part.type === \"text\");\n\tif (firstTextIndex === -1) {\n\t\treturn [{ type: \"text\", text: SENPI_SYSTEM_PREFIX }, ...content];\n\t}\n\n\treturn content.map((part, index) => {\n\t\tif (part.type !== \"text\" || index !== firstTextIndex) {\n\t\t\treturn part;\n\t\t}\n\n\t\treturn {\n\t\t\t...part,\n\t\t\ttext: prefixText(part.text),\n\t\t};\n\t});\n}\n\nfunction extractText(content: string | (TextContent | ImageContent)[]): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\n\treturn content\n\t\t.filter((part): part is TextContent => part.type === \"text\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\\n\");\n}\n\nfunction emitTodoConversationEvent(pi: ExtensionAPI, event: TodoConversationEvent): void {\n\tpi.events.emit(SENPI_CONVERSATION_EVENT, event);\n}\n\nfunction createBaseEvent(args: {\n\taction: TodoConversationAction;\n\troute: TodoSystemMessageRoute;\n\tsessionId?: string;\n\tdeliverAs?: \"steer\" | \"followUp\";\n\ttext: string;\n\terrorMessage?: string;\n}): TodoConversationEvent {\n\treturn {\n\t\tversion: 1,\n\t\tsource: \"builtin\",\n\t\taction: args.action,\n\t\troute: args.route,\n\t\tsessionId: args.sessionId,\n\t\ttimestamp: Date.now(),\n\t\tconversation: {\n\t\t\tprefix: SENPI_SYSTEM_PREFIX,\n\t\t\tkind: \"user_message\",\n\t\t\tdeliverAs: args.deliverAs,\n\t\t},\n\t\ttext: args.text,\n\t\terrorMessage: args.errorMessage,\n\t};\n}\n\nfunction hasUserMessageOptions(\n\toptions: TodoUserMessageOptions | undefined,\n): options is TodoUserMessageOptions & { deliverAs: \"steer\" | \"followUp\" } {\n\treturn options?.deliverAs !== undefined;\n}\n\nexport function sendTodoUserMessage(\n\tpi: ExtensionAPI,\n\troute: TodoSystemMessageRoute,\n\tcontent: string | (TextContent | ImageContent)[],\n\toptions?: TodoUserMessageOptions,\n): void {\n\tconst prefixedContent = prefixContent(content);\n\n\temitTodoConversationEvent(\n\t\tpi,\n\t\tcreateBaseEvent({\n\t\t\taction: \"injected\",\n\t\t\troute,\n\t\t\tsessionId: options?.sessionId,\n\t\t\ttext: extractText(prefixedContent),\n\t\t\tdeliverAs: options?.deliverAs,\n\t\t}),\n\t);\n\n\tif (hasUserMessageOptions(options)) {\n\t\tpi.sendUserMessage(prefixedContent, { deliverAs: options.deliverAs });\n\t\treturn;\n\t}\n\n\tpi.sendUserMessage(prefixedContent);\n}\n\nexport function emitTodoSystemMessageFailure(\n\tpi: ExtensionAPI,\n\targs: {\n\t\troute: TodoSystemMessageRoute;\n\t\tsessionId?: string;\n\t\tcontent: string | (TextContent | ImageContent)[];\n\t\tdeliverAs?: \"steer\" | \"followUp\";\n\t\terrorMessage: string;\n\t},\n): void {\n\tconst prefixedContent = prefixContent(args.content);\n\n\temitTodoConversationEvent(\n\t\tpi,\n\t\tcreateBaseEvent({\n\t\t\taction: \"failed\",\n\t\t\troute: args.route,\n\t\t\tsessionId: args.sessionId,\n\t\t\ttext: extractText(prefixedContent),\n\t\t\tdeliverAs: args.deliverAs,\n\t\t\terrorMessage: args.errorMessage,\n\t\t}),\n\t);\n}\n"]}
|