p-spore 0.1.3 → 0.1.42
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/README.md +110 -15
- package/dist/agents/agent-manager.d.ts +3 -3
- package/dist/agents/agent-manager.d.ts.map +1 -1
- package/dist/agents/agent-manager.js +3 -2
- package/dist/agents/agent-manager.js.map +1 -1
- package/dist/application/agent-application.d.ts +29 -5
- package/dist/application/agent-application.d.ts.map +1 -1
- package/dist/application/agent-application.js +444 -14
- package/dist/application/agent-application.js.map +1 -1
- package/dist/articles/diff.d.ts +70 -0
- package/dist/articles/diff.d.ts.map +1 -0
- package/dist/articles/diff.js +330 -0
- package/dist/articles/diff.js.map +1 -0
- package/dist/articles/docx.d.ts +10 -0
- package/dist/articles/docx.d.ts.map +1 -0
- package/dist/articles/docx.js +219 -0
- package/dist/articles/docx.js.map +1 -0
- package/dist/articles/draft.d.ts +18 -0
- package/dist/articles/draft.d.ts.map +1 -0
- package/dist/articles/draft.js +88 -0
- package/dist/articles/draft.js.map +1 -0
- package/dist/articles/edits.d.ts +24 -0
- package/dist/articles/edits.d.ts.map +1 -0
- package/dist/articles/edits.js +54 -0
- package/dist/articles/edits.js.map +1 -0
- package/dist/articles/html.d.ts +10 -0
- package/dist/articles/html.d.ts.map +1 -0
- package/dist/articles/html.js +122 -0
- package/dist/articles/html.js.map +1 -0
- package/dist/articles/plain.d.ts +8 -0
- package/dist/articles/plain.d.ts.map +1 -0
- package/dist/articles/plain.js +69 -0
- package/dist/articles/plain.js.map +1 -0
- package/dist/articles/preview.d.ts +43 -0
- package/dist/articles/preview.d.ts.map +1 -0
- package/dist/articles/preview.js +90 -0
- package/dist/articles/preview.js.map +1 -0
- package/dist/articles/publish.d.ts +10 -0
- package/dist/articles/publish.d.ts.map +1 -0
- package/dist/articles/publish.js +54 -0
- package/dist/articles/publish.js.map +1 -0
- package/dist/articles/receipt.d.ts +16 -0
- package/dist/articles/receipt.d.ts.map +1 -0
- package/dist/articles/receipt.js +27 -0
- package/dist/articles/receipt.js.map +1 -0
- package/dist/articles/store.d.ts +78 -0
- package/dist/articles/store.d.ts.map +1 -0
- package/dist/articles/store.js +308 -0
- package/dist/articles/store.js.map +1 -0
- package/dist/articles/tool.d.ts +14 -0
- package/dist/articles/tool.d.ts.map +1 -0
- package/dist/articles/tool.js +175 -0
- package/dist/articles/tool.js.map +1 -0
- package/dist/articles/writer-context.d.ts +5 -0
- package/dist/articles/writer-context.d.ts.map +1 -0
- package/dist/articles/writer-context.js +56 -0
- package/dist/articles/writer-context.js.map +1 -0
- package/dist/articles/writer.d.ts +18 -0
- package/dist/articles/writer.d.ts.map +1 -0
- package/dist/articles/writer.js +79 -0
- package/dist/articles/writer.js.map +1 -0
- package/dist/articles/zip-write.d.ts +11 -0
- package/dist/articles/zip-write.d.ts.map +1 -0
- package/dist/articles/zip-write.js +63 -0
- package/dist/articles/zip-write.js.map +1 -0
- package/dist/bundled-skills/README.md +17 -0
- package/dist/bundled-skills/aegis-search/SKILL.md +59 -0
- package/dist/bundled-skills/aegis-search/bin/.gitkeep +0 -0
- package/dist/bundled-skills/article-canvas/SKILL.md +28 -0
- package/dist/bundled-skills/binaries.json +23 -0
- package/dist/bundled-skills/doc-extract/SKILL.md +56 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +407 -54
- package/dist/cli/main.js.map +1 -1
- package/dist/config/config.d.ts +43 -0
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +150 -6
- package/dist/config/config.js.map +1 -1
- package/dist/daemon/daemon.d.ts.map +1 -1
- package/dist/daemon/daemon.js +80 -11
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/desktop/application.d.ts +4 -0
- package/dist/desktop/application.d.ts.map +1 -0
- package/dist/desktop/application.js +1688 -0
- package/dist/desktop/application.js.map +1 -0
- package/dist/desktop/article-export.d.ts +12 -0
- package/dist/desktop/article-export.d.ts.map +1 -0
- package/dist/desktop/article-export.js +87 -0
- package/dist/desktop/article-export.js.map +1 -0
- package/dist/desktop/assets/pspore.png +0 -0
- package/dist/desktop/assets/pspore.svg +24 -0
- package/dist/desktop/conversation-smoke.d.ts +5 -0
- package/dist/desktop/conversation-smoke.d.ts.map +1 -0
- package/dist/desktop/conversation-smoke.js +93 -0
- package/dist/desktop/conversation-smoke.js.map +1 -0
- package/dist/desktop/daemon-bridge.d.ts.map +1 -1
- package/dist/desktop/daemon-bridge.js +62 -17
- package/dist/desktop/daemon-bridge.js.map +1 -1
- package/dist/desktop/ipc-contract.d.ts +124 -0
- package/dist/desktop/ipc-contract.d.ts.map +1 -1
- package/dist/desktop/ipc-contract.js +191 -12
- package/dist/desktop/ipc-contract.js.map +1 -1
- package/dist/desktop/local-path.d.ts +15 -0
- package/dist/desktop/local-path.d.ts.map +1 -0
- package/dist/desktop/local-path.js +59 -0
- package/dist/desktop/local-path.js.map +1 -0
- package/dist/desktop/main.d.ts +10 -1
- package/dist/desktop/main.d.ts.map +1 -1
- package/dist/desktop/main.js +122 -530
- package/dist/desktop/main.js.map +1 -1
- package/dist/desktop/native-startup.d.ts +4 -0
- package/dist/desktop/native-startup.d.ts.map +1 -0
- package/dist/desktop/native-startup.js +57 -0
- package/dist/desktop/native-startup.js.map +1 -0
- package/dist/desktop/preload.cjs +28 -1
- package/dist/desktop/renderer/article-panel.d.ts +45 -0
- package/dist/desktop/renderer/article-panel.d.ts.map +1 -0
- package/dist/desktop/renderer/article-panel.js +1126 -0
- package/dist/desktop/renderer/article-panel.js.map +1 -0
- package/dist/desktop/renderer/article-split.d.ts +32 -0
- package/dist/desktop/renderer/article-split.d.ts.map +1 -0
- package/dist/desktop/renderer/article-split.js +48 -0
- package/dist/desktop/renderer/article-split.js.map +1 -0
- package/dist/desktop/renderer/composer-file-references.d.ts +23 -0
- package/dist/desktop/renderer/composer-file-references.d.ts.map +1 -0
- package/dist/desktop/renderer/composer-file-references.js +51 -0
- package/dist/desktop/renderer/composer-file-references.js.map +1 -0
- package/dist/desktop/renderer/conversation.d.ts +23 -0
- package/dist/desktop/renderer/conversation.d.ts.map +1 -0
- package/dist/desktop/renderer/conversation.js +66 -0
- package/dist/desktop/renderer/conversation.js.map +1 -0
- package/dist/desktop/renderer/dom-reconcile.d.ts +15 -0
- package/dist/desktop/renderer/dom-reconcile.d.ts.map +1 -0
- package/dist/desktop/renderer/dom-reconcile.js +33 -0
- package/dist/desktop/renderer/dom-reconcile.js.map +1 -0
- package/dist/desktop/renderer/index.html +211 -34
- package/dist/desktop/renderer/indexing-view.d.ts +22 -0
- package/dist/desktop/renderer/indexing-view.d.ts.map +1 -0
- package/dist/desktop/renderer/indexing-view.js +115 -0
- package/dist/desktop/renderer/indexing-view.js.map +1 -0
- package/dist/desktop/renderer/markdown-view.d.ts +23 -0
- package/dist/desktop/renderer/markdown-view.d.ts.map +1 -0
- package/dist/desktop/renderer/markdown-view.js +436 -0
- package/dist/desktop/renderer/markdown-view.js.map +1 -0
- package/dist/desktop/renderer/motion.d.ts +67 -0
- package/dist/desktop/renderer/motion.d.ts.map +1 -0
- package/dist/desktop/renderer/motion.js +296 -0
- package/dist/desktop/renderer/motion.js.map +1 -0
- package/dist/desktop/renderer/renderer.js +1793 -155
- package/dist/desktop/renderer/renderer.js.map +1 -1
- package/dist/desktop/renderer/session-find.d.ts +18 -0
- package/dist/desktop/renderer/session-find.d.ts.map +1 -0
- package/dist/desktop/renderer/session-find.js +29 -0
- package/dist/desktop/renderer/session-find.js.map +1 -0
- package/dist/desktop/renderer/session-search.d.ts +30 -0
- package/dist/desktop/renderer/session-search.d.ts.map +1 -0
- package/dist/desktop/renderer/session-search.js +296 -0
- package/dist/desktop/renderer/session-search.js.map +1 -0
- package/dist/desktop/renderer/store.d.ts +35 -8
- package/dist/desktop/renderer/store.d.ts.map +1 -1
- package/dist/desktop/renderer/store.js +95 -78
- package/dist/desktop/renderer/store.js.map +1 -1
- package/dist/desktop/renderer/styles.css +910 -268
- package/dist/desktop/renderer/vendor/gsap.min.js +11 -0
- package/dist/desktop/renderer-diagnostics.d.ts +5 -0
- package/dist/desktop/renderer-diagnostics.d.ts.map +1 -0
- package/dist/desktop/renderer-diagnostics.js +47 -0
- package/dist/desktop/renderer-diagnostics.js.map +1 -0
- package/dist/desktop/security.d.ts +26 -1
- package/dist/desktop/security.d.ts.map +1 -1
- package/dist/desktop/security.js +26 -6
- package/dist/desktop/security.js.map +1 -1
- package/dist/desktop/smoke-fixture.d.ts.map +1 -1
- package/dist/desktop/smoke-fixture.js +77 -3
- package/dist/desktop/smoke-fixture.js.map +1 -1
- package/dist/desktop/splash/index.html +25 -0
- package/dist/desktop/splash/splash.d.ts +2 -0
- package/dist/desktop/splash/splash.d.ts.map +1 -0
- package/dist/desktop/splash/splash.js +8 -0
- package/dist/desktop/splash/splash.js.map +1 -0
- package/dist/desktop/splash/styles.css +24 -0
- package/dist/desktop/system-open.d.ts +16 -0
- package/dist/desktop/system-open.d.ts.map +1 -0
- package/dist/desktop/system-open.js +90 -0
- package/dist/desktop/system-open.js.map +1 -0
- package/dist/desktop/validation.d.ts.map +1 -1
- package/dist/desktop/validation.js +99 -21
- package/dist/desktop/validation.js.map +1 -1
- package/dist/desktop/window-security.d.ts +4 -0
- package/dist/desktop/window-security.d.ts.map +1 -0
- package/dist/desktop/window-security.js +26 -0
- package/dist/desktop/window-security.js.map +1 -0
- package/dist/documents/errors.d.ts +12 -0
- package/dist/documents/errors.d.ts.map +1 -0
- package/dist/documents/errors.js +12 -0
- package/dist/documents/errors.js.map +1 -0
- package/dist/documents/extract.d.ts +37 -0
- package/dist/documents/extract.d.ts.map +1 -0
- package/dist/documents/extract.js +90 -0
- package/dist/documents/extract.js.map +1 -0
- package/dist/documents/legacy-office.d.ts +23 -0
- package/dist/documents/legacy-office.d.ts.map +1 -0
- package/dist/documents/legacy-office.js +439 -0
- package/dist/documents/legacy-office.js.map +1 -0
- package/dist/documents/ole.d.ts +20 -0
- package/dist/documents/ole.d.ts.map +1 -0
- package/dist/documents/ole.js +189 -0
- package/dist/documents/ole.js.map +1 -0
- package/dist/documents/ooxml.d.ts +23 -0
- package/dist/documents/ooxml.d.ts.map +1 -0
- package/dist/documents/ooxml.js +197 -0
- package/dist/documents/ooxml.js.map +1 -0
- package/dist/documents/pdf.d.ts +20 -0
- package/dist/documents/pdf.d.ts.map +1 -0
- package/dist/documents/pdf.js +95 -0
- package/dist/documents/pdf.js.map +1 -0
- package/dist/documents/plain-text.d.ts +22 -0
- package/dist/documents/plain-text.d.ts.map +1 -0
- package/dist/documents/plain-text.js +57 -0
- package/dist/documents/plain-text.js.map +1 -0
- package/dist/documents/zip.d.ts +15 -0
- package/dist/documents/zip.d.ts.map +1 -0
- package/dist/documents/zip.js +137 -0
- package/dist/documents/zip.js.map +1 -0
- package/dist/domain/indexing.d.ts +60 -0
- package/dist/domain/indexing.d.ts.map +1 -0
- package/dist/domain/indexing.js +13 -0
- package/dist/domain/indexing.js.map +1 -0
- package/dist/domain/runtime.d.ts +133 -5
- package/dist/domain/runtime.d.ts.map +1 -1
- package/dist/gateway/local-gateway.d.ts +8 -0
- package/dist/gateway/local-gateway.d.ts.map +1 -1
- package/dist/gateway/local-gateway.js +105 -21
- package/dist/gateway/local-gateway.js.map +1 -1
- package/dist/indexing/index-service.d.ts +56 -0
- package/dist/indexing/index-service.d.ts.map +1 -0
- package/dist/indexing/index-service.js +262 -0
- package/dist/indexing/index-service.js.map +1 -0
- package/dist/kernel/loop.d.ts +10 -0
- package/dist/kernel/loop.d.ts.map +1 -1
- package/dist/kernel/loop.js +6 -2
- package/dist/kernel/loop.js.map +1 -1
- package/dist/kernel/reducer.d.ts.map +1 -1
- package/dist/kernel/reducer.js +17 -1
- package/dist/kernel/reducer.js.map +1 -1
- package/dist/kernel/state.d.ts +17 -4
- package/dist/kernel/state.d.ts.map +1 -1
- package/dist/kernel/state.js +2 -0
- package/dist/kernel/state.js.map +1 -1
- package/dist/memory/memory-tools.d.ts.map +1 -1
- package/dist/memory/memory-tools.js +25 -5
- package/dist/memory/memory-tools.js.map +1 -1
- package/dist/pi/context-budget.d.ts +8 -0
- package/dist/pi/context-budget.d.ts.map +1 -0
- package/dist/pi/context-budget.js +62 -0
- package/dist/pi/context-budget.js.map +1 -0
- package/dist/pi/pi-runtime-adapter.d.ts +38 -3
- package/dist/pi/pi-runtime-adapter.d.ts.map +1 -1
- package/dist/pi/pi-runtime-adapter.js +551 -56
- package/dist/pi/pi-runtime-adapter.js.map +1 -1
- package/dist/plugins/bundled-skills.d.ts +56 -0
- package/dist/plugins/bundled-skills.d.ts.map +1 -0
- package/dist/plugins/bundled-skills.js +243 -0
- package/dist/plugins/bundled-skills.js.map +1 -0
- package/dist/plugins/extension-manager.d.ts +23 -1
- package/dist/plugins/extension-manager.d.ts.map +1 -1
- package/dist/plugins/extension-manager.js +117 -0
- package/dist/plugins/extension-manager.js.map +1 -1
- package/dist/plugins/types.d.ts +29 -0
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/plugins/workspace-skills.d.ts +36 -0
- package/dist/plugins/workspace-skills.d.ts.map +1 -0
- package/dist/plugins/workspace-skills.js +309 -0
- package/dist/plugins/workspace-skills.js.map +1 -0
- package/dist/policy/policy.d.ts.map +1 -1
- package/dist/policy/policy.js +26 -4
- package/dist/policy/policy.js.map +1 -1
- package/dist/protocol/client.d.ts +1 -0
- package/dist/protocol/client.d.ts.map +1 -1
- package/dist/protocol/client.js +49 -24
- package/dist/protocol/client.js.map +1 -1
- package/dist/protocol/limits.d.ts +69 -0
- package/dist/protocol/limits.d.ts.map +1 -0
- package/dist/protocol/limits.js +166 -0
- package/dist/protocol/limits.js.map +1 -0
- package/dist/protocol/schema.d.ts +6 -0
- package/dist/protocol/schema.d.ts.map +1 -1
- package/dist/protocol/schema.js.map +1 -1
- package/dist/protocol/server-frame-codec.d.ts +18 -0
- package/dist/protocol/server-frame-codec.d.ts.map +1 -0
- package/dist/protocol/server-frame-codec.js +211 -0
- package/dist/protocol/server-frame-codec.js.map +1 -0
- package/dist/service/legacy-daemon.d.ts +6 -0
- package/dist/service/legacy-daemon.d.ts.map +1 -0
- package/dist/service/legacy-daemon.js +42 -0
- package/dist/service/legacy-daemon.js.map +1 -0
- package/dist/service/service-launch.d.ts +10 -0
- package/dist/service/service-launch.d.ts.map +1 -0
- package/dist/service/service-launch.js +56 -0
- package/dist/service/service-launch.js.map +1 -0
- package/dist/service/system-service.d.ts +57 -0
- package/dist/service/system-service.d.ts.map +1 -0
- package/dist/service/system-service.js +263 -0
- package/dist/service/system-service.js.map +1 -0
- package/dist/sessions/session-catalog.d.ts +45 -0
- package/dist/sessions/session-catalog.d.ts.map +1 -0
- package/dist/sessions/session-catalog.js +270 -0
- package/dist/sessions/session-catalog.js.map +1 -0
- package/dist/sessions/session-file.d.ts +12 -0
- package/dist/sessions/session-file.d.ts.map +1 -0
- package/dist/sessions/session-file.js +47 -0
- package/dist/sessions/session-file.js.map +1 -0
- package/dist/settings/compaction-settings.d.ts +10 -0
- package/dist/settings/compaction-settings.d.ts.map +1 -0
- package/dist/settings/compaction-settings.js +8 -0
- package/dist/settings/compaction-settings.js.map +1 -0
- package/dist/settings/indexing-settings-service.d.ts +16 -0
- package/dist/settings/indexing-settings-service.d.ts.map +1 -0
- package/dist/settings/indexing-settings-service.js +57 -0
- package/dist/settings/indexing-settings-service.js.map +1 -0
- package/dist/settings/indexing-settings.d.ts +30 -0
- package/dist/settings/indexing-settings.d.ts.map +1 -0
- package/dist/settings/indexing-settings.js +58 -0
- package/dist/settings/indexing-settings.js.map +1 -0
- package/dist/settings/llm-settings-service.d.ts +6 -0
- package/dist/settings/llm-settings-service.d.ts.map +1 -1
- package/dist/settings/llm-settings-service.js +137 -12
- package/dist/settings/llm-settings-service.js.map +1 -1
- package/dist/settings/llm-settings.d.ts +68 -2
- package/dist/settings/llm-settings.d.ts.map +1 -1
- package/dist/settings/llm-settings.js +119 -17
- package/dist/settings/llm-settings.js.map +1 -1
- package/dist/settings/model-api.d.ts +10 -0
- package/dist/settings/model-api.d.ts.map +1 -0
- package/dist/settings/model-api.js +10 -0
- package/dist/settings/model-api.js.map +1 -0
- package/dist/storage/home.d.ts +1 -0
- package/dist/storage/home.d.ts.map +1 -1
- package/dist/storage/home.js +37 -2
- package/dist/storage/home.js.map +1 -1
- package/dist/tools/core-tools.d.ts +2 -0
- package/dist/tools/core-tools.d.ts.map +1 -1
- package/dist/tools/core-tools.js +91 -1
- package/dist/tools/core-tools.js.map +1 -1
- package/dist/ui/shared/activity.d.ts +27 -0
- package/dist/ui/shared/activity.d.ts.map +1 -0
- package/dist/ui/shared/activity.js +384 -0
- package/dist/ui/shared/activity.js.map +1 -0
- package/dist/ui/shared/full-message.d.ts +22 -0
- package/dist/ui/shared/full-message.d.ts.map +1 -0
- package/dist/ui/shared/full-message.js +40 -0
- package/dist/ui/shared/full-message.js.map +1 -0
- package/dist/ui/shared/local-links.d.ts +7 -0
- package/dist/ui/shared/local-links.d.ts.map +1 -0
- package/dist/ui/shared/local-links.js +24 -0
- package/dist/ui/shared/local-links.js.map +1 -0
- package/dist/ui/shared/markdown-stream.d.ts +25 -0
- package/dist/ui/shared/markdown-stream.d.ts.map +1 -0
- package/dist/ui/shared/markdown-stream.js +35 -0
- package/dist/ui/shared/markdown-stream.js.map +1 -0
- package/dist/ui/shared/markdown.d.ts +70 -0
- package/dist/ui/shared/markdown.d.ts.map +1 -0
- package/dist/ui/shared/markdown.js +434 -0
- package/dist/ui/shared/markdown.js.map +1 -0
- package/dist/ui/shared/presentation.d.ts +10 -2
- package/dist/ui/shared/presentation.d.ts.map +1 -1
- package/dist/ui/shared/presentation.js +83 -22
- package/dist/ui/shared/presentation.js.map +1 -1
- package/dist/ui/shared/protocol-state.d.ts +19 -0
- package/dist/ui/shared/protocol-state.d.ts.map +1 -1
- package/dist/ui/shared/protocol-state.js +188 -26
- package/dist/ui/shared/protocol-state.js.map +1 -1
- package/dist/ui/shared/virtual-list.d.ts +34 -0
- package/dist/ui/shared/virtual-list.d.ts.map +1 -0
- package/dist/ui/shared/virtual-list.js +143 -0
- package/dist/ui/shared/virtual-list.js.map +1 -0
- package/dist/ui/tui/commands.d.ts +1 -1
- package/dist/ui/tui/commands.d.ts.map +1 -1
- package/dist/ui/tui/commands.js +9 -3
- package/dist/ui/tui/commands.js.map +1 -1
- package/dist/ui/tui/store.d.ts +26 -0
- package/dist/ui/tui/store.d.ts.map +1 -1
- package/dist/ui/tui/store.js +67 -3
- package/dist/ui/tui/store.js.map +1 -1
- package/dist/ui/tui/tui-app.d.ts.map +1 -1
- package/dist/ui/tui/tui-app.js +316 -38
- package/dist/ui/tui/tui-app.js.map +1 -1
- package/dist/ui/tui/view.d.ts +10 -0
- package/dist/ui/tui/view.d.ts.map +1 -1
- package/dist/ui/tui/view.js +253 -49
- package/dist/ui/tui/view.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +13 -2
package/dist/ui/tui/tui-app.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { ProcessTerminal, TuiAltScreen } from "@earendil-works/pi-tui";
|
|
3
3
|
import { ProtocolClient } from "../../protocol/client.js";
|
|
4
|
-
import { decodeLlmSettingsUpdate, defaultModelFor, MODEL_APIS, PROVIDER_OPTIONS, THINKING_LEVELS, } from "../../settings/llm-settings.js";
|
|
4
|
+
import { BYPASS_PERMISSION_MODE, decodeLlmSettingsUpdate, defaultModelFor, MODEL_APIS, PERMISSION_MODES, permissionModeSummary, PROVIDER_OPTIONS, THINKING_LEVELS, } from "../../settings/llm-settings.js";
|
|
5
5
|
import { TuiStore } from "./store.js";
|
|
6
6
|
import { TUI_HELP_LINES } from "./commands.js";
|
|
7
7
|
import { PsporeTuiView } from "./view.js";
|
|
8
|
+
import { activityDetailLines } from "../shared/activity.js";
|
|
8
9
|
import { conversationIntent, selectedAgent } from "../shared/presentation.js";
|
|
9
10
|
export const MODEL_SETUP_OFFER_PROMPT = "Run the model setup wizard now? [Y/n]";
|
|
10
11
|
export const MODEL_SETUP_OFFER_LINES = [
|
|
11
12
|
"No model is configured yet, so prompts would fail with model_not_configured.",
|
|
12
13
|
"",
|
|
13
|
-
"The wizard walks through provider, model, thinking
|
|
14
|
-
"The key
|
|
14
|
+
"The wizard walks through provider, model, thinking, API key and optional proxy cookie.",
|
|
15
|
+
"The key and cookie are stored in private 0600 files and are never shown in the TUI.",
|
|
15
16
|
"",
|
|
16
17
|
"Answer n to skip; you can run /config wizard at any time.",
|
|
17
18
|
];
|
|
@@ -22,6 +23,8 @@ export function acceptsModelSetupOffer(answer) {
|
|
|
22
23
|
const normalized = answer.trim().toLowerCase();
|
|
23
24
|
return normalized === "" || normalized === "y" || normalized === "yes";
|
|
24
25
|
}
|
|
26
|
+
/** How many older messages one scrollback request asks for. */
|
|
27
|
+
const HISTORY_PAGE_SIZE = 200;
|
|
25
28
|
export class PsporeTuiApp {
|
|
26
29
|
#options;
|
|
27
30
|
#store = new TuiStore();
|
|
@@ -31,8 +34,10 @@ export class PsporeTuiApp {
|
|
|
31
34
|
#client;
|
|
32
35
|
#stopping = false;
|
|
33
36
|
#retryTimer;
|
|
37
|
+
#settleTimer;
|
|
34
38
|
#retryMs = 250;
|
|
35
39
|
#lastInterruptAt = 0;
|
|
40
|
+
#loadingHistory = false;
|
|
36
41
|
#resolveExit;
|
|
37
42
|
#view;
|
|
38
43
|
constructor(options) {
|
|
@@ -47,12 +52,14 @@ export class PsporeTuiApp {
|
|
|
47
52
|
onSubmit: (input) => void this.#submit(input),
|
|
48
53
|
onInterrupt: () => void this.#interrupt(),
|
|
49
54
|
onBack: () => this.#store.clearPanel(),
|
|
55
|
+
onScrollBack: () => void this.#loadOlderHistory(),
|
|
50
56
|
});
|
|
51
57
|
this.#view = view;
|
|
52
58
|
this.#tui.setLayoutRoot(view);
|
|
53
59
|
this.#tui.setFocus(view);
|
|
54
60
|
this.#tui.start();
|
|
55
61
|
void this.#connect();
|
|
62
|
+
void this.#refreshConfiguredModel();
|
|
56
63
|
void this.#offerModelSetup();
|
|
57
64
|
try {
|
|
58
65
|
await new Promise((resolve) => {
|
|
@@ -63,7 +70,10 @@ export class PsporeTuiApp {
|
|
|
63
70
|
this.#stopping = true;
|
|
64
71
|
if (this.#retryTimer)
|
|
65
72
|
clearTimeout(this.#retryTimer);
|
|
73
|
+
if (this.#settleTimer)
|
|
74
|
+
clearTimeout(this.#settleTimer);
|
|
66
75
|
await this.#client?.close().catch(() => undefined);
|
|
76
|
+
this.#view?.dispose();
|
|
67
77
|
this.#tui.stop();
|
|
68
78
|
this.#view = undefined;
|
|
69
79
|
await this.#terminal.drainInput(250, 25);
|
|
@@ -90,6 +100,7 @@ export class PsporeTuiApp {
|
|
|
90
100
|
if (connected)
|
|
91
101
|
return;
|
|
92
102
|
this.#store.disconnected(error?.message ?? "Disconnected");
|
|
103
|
+
this.#scheduleSettle();
|
|
93
104
|
this.#tui.requestRender();
|
|
94
105
|
this.#scheduleReconnect();
|
|
95
106
|
});
|
|
@@ -105,10 +116,50 @@ export class PsporeTuiApp {
|
|
|
105
116
|
}
|
|
106
117
|
catch (error) {
|
|
107
118
|
this.#store.disconnected(`Daemon unavailable: ${toError(error).message}`);
|
|
119
|
+
this.#scheduleSettle();
|
|
108
120
|
this.#tui.requestRender();
|
|
109
121
|
this.#scheduleReconnect();
|
|
110
122
|
}
|
|
111
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Fetches the page of history before the oldest message this client holds.
|
|
126
|
+
* The daemon broadcasts only a bounded tail, so scrollback is a request.
|
|
127
|
+
*/
|
|
128
|
+
async #loadOlderHistory() {
|
|
129
|
+
if (this.#loadingHistory)
|
|
130
|
+
return;
|
|
131
|
+
const state = this.#store.snapshot();
|
|
132
|
+
const sessionId = state.selectedSessionId;
|
|
133
|
+
const session = state.kernel.sessions[sessionId];
|
|
134
|
+
if (!session || session.messageOffset === 0)
|
|
135
|
+
return;
|
|
136
|
+
const from = Math.max(0, session.messageOffset - HISTORY_PAGE_SIZE);
|
|
137
|
+
this.#loadingHistory = true;
|
|
138
|
+
try {
|
|
139
|
+
const page = await this.#command("session.transcript", { from, limit: session.messageOffset - from }, sessionId);
|
|
140
|
+
if (this.#store.applyTranscriptPage(page))
|
|
141
|
+
this.#tui.requestRender();
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
this.#store.setNotice(`Could not load older history: ${toError(error).message}`);
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
this.#loadingHistory = false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Surfaces a genuine outage once the store's masking window expires. */
|
|
151
|
+
#scheduleSettle() {
|
|
152
|
+
if (this.#stopping || this.#settleTimer)
|
|
153
|
+
return;
|
|
154
|
+
this.#settleTimer = setTimeout(() => {
|
|
155
|
+
this.#settleTimer = undefined;
|
|
156
|
+
if (this.#store.settleConnection())
|
|
157
|
+
this.#tui.requestRender();
|
|
158
|
+
else if (this.#store.snapshot().reconnecting)
|
|
159
|
+
this.#scheduleSettle();
|
|
160
|
+
}, 250);
|
|
161
|
+
this.#settleTimer.unref();
|
|
162
|
+
}
|
|
112
163
|
#scheduleReconnect() {
|
|
113
164
|
if (this.#stopping || this.#retryTimer)
|
|
114
165
|
return;
|
|
@@ -130,6 +181,10 @@ export class PsporeTuiApp {
|
|
|
130
181
|
this.#store.setPanel("Command palette", TUI_HELP_LINES);
|
|
131
182
|
return;
|
|
132
183
|
}
|
|
184
|
+
if (input === "/work" || input.startsWith("/work ")) {
|
|
185
|
+
this.#showWork(input.slice(5).trim());
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
133
188
|
if (input === "/back") {
|
|
134
189
|
this.#store.clearPanel();
|
|
135
190
|
return;
|
|
@@ -138,22 +193,54 @@ export class PsporeTuiApp {
|
|
|
138
193
|
await this.#config(input);
|
|
139
194
|
return;
|
|
140
195
|
}
|
|
196
|
+
if (input === "/new" || input.startsWith("/new ")) {
|
|
197
|
+
const title = input.slice(4).trim();
|
|
198
|
+
const session = await this.#command("session.create", title ? { title } : {});
|
|
199
|
+
this.#store.selectSession(session.sessionId);
|
|
200
|
+
this.#store.setNotice(`New session ${session.sessionId}`);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (input === "/delete" || input.startsWith("/delete ")) {
|
|
204
|
+
const requested = input.slice(7).trim();
|
|
205
|
+
const sessionId = requested || this.#store.snapshot().selectedSessionId;
|
|
206
|
+
if (this.#selectedAgent() && !requested) {
|
|
207
|
+
throw new Error("Only a root session can be deleted; use /agent-cancel for a child agent");
|
|
208
|
+
}
|
|
209
|
+
// Deleting also removes the transcript, so the id is echoed back rather
|
|
210
|
+
// than silently acting on whatever happened to be selected.
|
|
211
|
+
const deleted = await this.#command("session.delete", {}, sessionId);
|
|
212
|
+
this.#store.setNotice(`Deleted session ${deleted.sessionId}${deleted.title ? ` (${deleted.title})` : ""}`
|
|
213
|
+
+ `${deleted.transcriptRemoved ? " and its transcript" : ""}`);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
141
216
|
if (input === "/abort") {
|
|
217
|
+
const selectedSessionId = this.#store.snapshot().selectedSessionId;
|
|
142
218
|
const child = this.#selectedAgent();
|
|
143
219
|
if (child)
|
|
144
220
|
await this.#command("agent.cancel", { agentId: child.id, reason: "cancelled from TUI" });
|
|
145
221
|
else
|
|
146
|
-
await this.#command("session.abort", { reason: "TUI user requested abort" },
|
|
222
|
+
await this.#command("session.abort", { reason: "TUI user requested abort" }, selectedSessionId);
|
|
147
223
|
this.#store.setNotice(child ? `Agent ${child.id} cancelled` : "Abort requested");
|
|
148
224
|
return;
|
|
149
225
|
}
|
|
150
226
|
if (input === "/compact") {
|
|
151
227
|
if (this.#selectedAgent())
|
|
152
|
-
throw new Error("Compaction is available only for
|
|
153
|
-
await this.#command("session.compact", {},
|
|
228
|
+
throw new Error("Compaction is available only for a root session");
|
|
229
|
+
await this.#command("session.compact", {}, this.#store.snapshot().selectedSessionId);
|
|
154
230
|
this.#store.setNotice("Compaction requested");
|
|
155
231
|
return;
|
|
156
232
|
}
|
|
233
|
+
if (input.startsWith("/send-now ")) {
|
|
234
|
+
if (this.#selectedAgent())
|
|
235
|
+
throw new Error("Queued root-session messages are unavailable for a child agent");
|
|
236
|
+
const displayIndex = Number(input.slice(10).trim());
|
|
237
|
+
if (!Number.isSafeInteger(displayIndex) || displayIndex < 1)
|
|
238
|
+
throw new Error("Usage: /send-now QUEUE_NUMBER");
|
|
239
|
+
const sessionId = this.#store.snapshot().selectedSessionId;
|
|
240
|
+
await this.#command("session.queue.send-now", { index: displayIndex - 1 }, sessionId);
|
|
241
|
+
this.#store.setNotice("直接发送消息");
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
157
244
|
if (input === "/jobs") {
|
|
158
245
|
const jobs = await this.#command("jobs.list", {});
|
|
159
246
|
this.#store.setPanel("Automation jobs", jobs.map((job) => (`• ${job.id} · ${job.enabled ? "enabled" : "disabled"}${job.schedule?.cron ? ` · ${job.schedule.cron} ${job.schedule.timezone ?? ""}` : ""}`)));
|
|
@@ -204,10 +291,18 @@ export class PsporeTuiApp {
|
|
|
204
291
|
]);
|
|
205
292
|
return;
|
|
206
293
|
}
|
|
207
|
-
if (input === "/
|
|
208
|
-
const
|
|
294
|
+
if (input === "/skills") {
|
|
295
|
+
const skills = await this.#command("skills.catalog", {});
|
|
296
|
+
this.#store.setPanel("Skills", skills.length === 0 ? ["No skills found"] : skills.flatMap((skill) => [
|
|
297
|
+
`• ${skill.name} · ${skill.source} · ${skill.status}`,
|
|
298
|
+
...(skill.message ? [` ${skill.message}`] : []),
|
|
299
|
+
]));
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (input === "/resources" || input === "/plugins") {
|
|
303
|
+
const command = input === "/plugins" ? "plugins.list" : "resources.list";
|
|
209
304
|
const resources = await this.#command(command, {});
|
|
210
|
-
this.#store.setPanel(input === "/
|
|
305
|
+
this.#store.setPanel(input === "/plugins" ? "Host plugins" : "Trusted resources", resources.map((resource) => (`• ${resource.record.kind} · ${resource.record.name} · ${resource.health.status}`)));
|
|
211
306
|
return;
|
|
212
307
|
}
|
|
213
308
|
if (input.startsWith("/resource-inspect ")) {
|
|
@@ -252,8 +347,10 @@ export class PsporeTuiApp {
|
|
|
252
347
|
const objective = input.slice(13).trim();
|
|
253
348
|
if (!objective)
|
|
254
349
|
throw new Error("Usage: /agent-spawn OBJECTIVE");
|
|
350
|
+
const snapshot = this.#store.snapshot();
|
|
351
|
+
const parentId = selectedAgent(snapshot.kernel, snapshot.selectedSessionId)?.rootId ?? snapshot.selectedSessionId;
|
|
255
352
|
const agent = await this.#command("agent.spawn", {
|
|
256
|
-
parentId
|
|
353
|
+
parentId,
|
|
257
354
|
objective,
|
|
258
355
|
workspaceMode: "shared-read",
|
|
259
356
|
budget: {
|
|
@@ -314,13 +411,7 @@ export class PsporeTuiApp {
|
|
|
314
411
|
await this.#approval(input);
|
|
315
412
|
return;
|
|
316
413
|
}
|
|
317
|
-
|
|
318
|
-
const main = this.#store.snapshot().kernel.sessions["main"];
|
|
319
|
-
if (!child && main?.status === "running") {
|
|
320
|
-
this.#store.setNotice("Session is running; use /steer TEXT or /follow TEXT explicitly");
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
await this.#prompt(input, "prompt");
|
|
414
|
+
await this.#prompt(input, "auto");
|
|
324
415
|
}
|
|
325
416
|
catch (error) {
|
|
326
417
|
this.#store.setNotice(`Error: ${toError(error).message}`);
|
|
@@ -342,7 +433,8 @@ export class PsporeTuiApp {
|
|
|
342
433
|
return;
|
|
343
434
|
}
|
|
344
435
|
await this.#command("session.prompt", { text: intent.text, mode: intent.mode }, intent.sessionId);
|
|
345
|
-
this.#store.
|
|
436
|
+
const queued = this.#store.snapshot().kernel.sessions[intent.sessionId]?.status === "running" && mode === "auto";
|
|
437
|
+
this.#store.setNotice(queued ? "继续排队" : `Message accepted for ${intent.sessionId}`);
|
|
346
438
|
}
|
|
347
439
|
async #approval(input) {
|
|
348
440
|
const parts = input.split(/\s+/);
|
|
@@ -446,6 +538,38 @@ export class PsporeTuiApp {
|
|
|
446
538
|
await this.#saveSettings(updateFrom(current, { thinking: parseThinking(parts[2]) }));
|
|
447
539
|
return;
|
|
448
540
|
}
|
|
541
|
+
if (action === "permissions") {
|
|
542
|
+
if (parts.length !== 3)
|
|
543
|
+
throw new Error(`Usage: /config permissions ${PERMISSION_MODES.join("|")}|bypass`);
|
|
544
|
+
const permissionMode = parsePermissionMode(parts[2]);
|
|
545
|
+
await this.#saveSettings(updateFrom(current, { permissionMode }));
|
|
546
|
+
if (permissionMode === BYPASS_PERMISSION_MODE) {
|
|
547
|
+
this.#store.setNotice("Permissions bypassed: tools now run with your own privileges and no confirmation");
|
|
548
|
+
}
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
if (action === "compact") {
|
|
552
|
+
if (parts.length < 3 || parts.length > 6) {
|
|
553
|
+
throw new Error("Usage: /config compact on|off [RESERVE_TOKENS] [KEEP_RECENT_TOKENS] [TRIGGER_TOKENS]");
|
|
554
|
+
}
|
|
555
|
+
const enabled = parseOnOff(parts[2], "/config compact");
|
|
556
|
+
const reserveTokens = parts[3] === undefined
|
|
557
|
+
? current.autoCompactionReserveTokens
|
|
558
|
+
: parseCompactionTokens(parts[3], "reserve tokens");
|
|
559
|
+
const keepRecentTokens = parts[4] === undefined
|
|
560
|
+
? current.autoCompactionKeepRecentTokens
|
|
561
|
+
: parseCompactionTokens(parts[4], "keep recent tokens");
|
|
562
|
+
const triggerTokens = parts[5] === undefined
|
|
563
|
+
? current.autoCompactionTriggerTokens
|
|
564
|
+
: parseCompactionTokens(parts[5], "trigger tokens");
|
|
565
|
+
await this.#saveSettings(updateFrom(current, {
|
|
566
|
+
autoCompactionEnabled: enabled,
|
|
567
|
+
autoCompactionTriggerTokens: triggerTokens,
|
|
568
|
+
autoCompactionReserveTokens: reserveTokens,
|
|
569
|
+
autoCompactionKeepRecentTokens: keepRecentTokens,
|
|
570
|
+
}));
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
449
573
|
if (action === "key") {
|
|
450
574
|
if (parts.length !== 2)
|
|
451
575
|
throw new Error("API keys are never accepted as command arguments; use /config key");
|
|
@@ -465,6 +589,25 @@ export class PsporeTuiApp {
|
|
|
465
589
|
await this.#saveSettings(updateFrom(current, { clearApiKey: true }));
|
|
466
590
|
return;
|
|
467
591
|
}
|
|
592
|
+
if (action === "cookie") {
|
|
593
|
+
if (parts.length !== 2)
|
|
594
|
+
throw new Error("Cookies are never accepted as command arguments; use /config cookie");
|
|
595
|
+
const cookie = await this.#view?.requestValue("Cookie (hidden; Esc cancels)", { secret: true });
|
|
596
|
+
if (cookie === undefined) {
|
|
597
|
+
this.#store.setNotice("Cookie update cancelled");
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
if (!cookie)
|
|
601
|
+
throw new Error("Cookie cannot be empty");
|
|
602
|
+
await this.#saveSettings(updateFrom(current, { cookie }));
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
if (action === "clear-cookie") {
|
|
606
|
+
if (parts.length !== 2)
|
|
607
|
+
throw new Error("Usage: /config clear-cookie");
|
|
608
|
+
await this.#saveSettings(updateFrom(current, { clearCookie: true }));
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
468
611
|
throw new Error("Unknown config action; use /config, /config wizard, or /help");
|
|
469
612
|
}
|
|
470
613
|
/**
|
|
@@ -505,44 +648,61 @@ export class PsporeTuiApp {
|
|
|
505
648
|
if (!settingsPort || !view)
|
|
506
649
|
throw new Error("Settings wizard is unavailable");
|
|
507
650
|
const current = await settingsPort.get();
|
|
508
|
-
this.#
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
"4 Thinking level",
|
|
513
|
-
"5 API key action",
|
|
514
|
-
"6 Review and apply",
|
|
515
|
-
"",
|
|
516
|
-
"Press Esc at any prompt to cancel without saving.",
|
|
651
|
+
this.#showWizardStep(1, "Choose a provider", [
|
|
652
|
+
`1 DeepSeek ${current.provider === "deepseek" ? "← current" : ""}`,
|
|
653
|
+
`2 OpenAI ${current.provider === "openai" ? "← current" : ""}`,
|
|
654
|
+
`3 Custom OpenAI ${current.provider === "custom-openai" ? "← current" : ""}`,
|
|
517
655
|
]);
|
|
518
|
-
const providerValue = await view.requestValue(`1/
|
|
656
|
+
const providerValue = await view.requestValue(`1/7 provider [${current.provider}] (1 deepseek · 2 openai · 3 custom)`);
|
|
519
657
|
if (providerValue === undefined)
|
|
520
658
|
return this.#cancelWizard();
|
|
521
659
|
const provider = providerValue.trim() ? parseProvider(providerValue) : current.provider;
|
|
522
660
|
const suggestedModel = provider === current.provider ? current.model : defaultModelFor(provider);
|
|
523
|
-
|
|
661
|
+
this.#showWizardStep(2, "Choose a model", [
|
|
662
|
+
`Provider ${provider}`,
|
|
663
|
+
`Suggested ${suggestedModel}`,
|
|
664
|
+
"Press Enter to accept the suggestion, or type another model ID.",
|
|
665
|
+
]);
|
|
666
|
+
const modelValue = await view.requestValue(`2/7 model [${suggestedModel}]`);
|
|
524
667
|
if (modelValue === undefined)
|
|
525
668
|
return this.#cancelWizard();
|
|
526
669
|
const model = modelValue.trim() || suggestedModel;
|
|
527
670
|
let baseUrl = "";
|
|
528
671
|
let api = "provider-default";
|
|
529
672
|
if (provider === "custom-openai") {
|
|
530
|
-
|
|
673
|
+
this.#showWizardStep(3, "Connect an OpenAI-compatible endpoint", [
|
|
674
|
+
`Current URL ${current.provider === provider ? current.baseUrl || "not set" : "not set"}`,
|
|
675
|
+
"The URL must use HTTP(S) and cannot contain credentials.",
|
|
676
|
+
"API compatibility can be Chat Completions or Responses.",
|
|
677
|
+
]);
|
|
678
|
+
const baseUrlValue = await view.requestValue(`3/7 Base URL [${current.provider === provider ? current.baseUrl : "required"}]`);
|
|
531
679
|
if (baseUrlValue === undefined)
|
|
532
680
|
return this.#cancelWizard();
|
|
533
681
|
baseUrl = baseUrlValue.trim() || (current.provider === provider ? current.baseUrl : "");
|
|
534
682
|
if (!baseUrl)
|
|
535
683
|
throw new Error("A Base URL is required for custom OpenAI");
|
|
536
|
-
const apiValue = await view.requestValue("3/
|
|
684
|
+
const apiValue = await view.requestValue("3/7 API [chat] (chat · responses)");
|
|
537
685
|
if (apiValue === undefined)
|
|
538
686
|
return this.#cancelWizard();
|
|
539
687
|
api = parseOpenAiApi(apiValue.trim() || (current.provider === provider ? current.api : "chat"));
|
|
540
688
|
}
|
|
541
|
-
|
|
689
|
+
this.#showWizardStep(4, "Choose thinking effort", [
|
|
690
|
+
`Current ${current.thinking}`,
|
|
691
|
+
`Options ${THINKING_LEVELS.join(" · ")}`,
|
|
692
|
+
"Higher effort can increase latency and token use when the provider supports it.",
|
|
693
|
+
]);
|
|
694
|
+
const thinkingValue = await view.requestValue(`4/7 thinking [${current.thinking}] (${THINKING_LEVELS.join(" · ")})`);
|
|
542
695
|
if (thinkingValue === undefined)
|
|
543
696
|
return this.#cancelWizard();
|
|
544
697
|
const thinking = parseThinking(thinkingValue.trim() || current.thinking);
|
|
545
|
-
|
|
698
|
+
this.#showWizardStep(5, "Manage the API key", [
|
|
699
|
+
`Status ${current.hasApiKey ? "configured (hidden)" : "not configured"}`,
|
|
700
|
+
`File ${current.apiKeyPath}`,
|
|
701
|
+
"keep Leave the managed key unchanged",
|
|
702
|
+
"set Enter a new key through hidden input",
|
|
703
|
+
"clear Remove the managed key",
|
|
704
|
+
]);
|
|
705
|
+
const keyActionValue = await view.requestValue(`5/7 key [keep] (keep · set · clear)`);
|
|
546
706
|
if (keyActionValue === undefined)
|
|
547
707
|
return this.#cancelWizard();
|
|
548
708
|
const keyAction = keyActionValue.trim().toLowerCase() || "keep";
|
|
@@ -551,23 +711,46 @@ export class PsporeTuiApp {
|
|
|
551
711
|
}
|
|
552
712
|
let apiKey;
|
|
553
713
|
if (keyAction === "set") {
|
|
554
|
-
apiKey = await view.requestValue("5/
|
|
714
|
+
apiKey = await view.requestValue("5/7 API key (hidden; Esc cancels)", { secret: true });
|
|
555
715
|
if (apiKey === undefined)
|
|
556
716
|
return this.#cancelWizard();
|
|
557
717
|
if (!apiKey)
|
|
558
718
|
throw new Error("API key cannot be empty");
|
|
559
719
|
}
|
|
560
|
-
this.#
|
|
720
|
+
this.#showWizardStep(6, "Optional LLM proxy cookie", [
|
|
721
|
+
`Status ${current.hasCookie ? "configured (hidden)" : "not configured"}`,
|
|
722
|
+
`File ${current.cookiePath}`,
|
|
723
|
+
"keep Leave the managed cookie unchanged",
|
|
724
|
+
"set Enter a Cookie header through hidden input",
|
|
725
|
+
"clear Remove the managed cookie",
|
|
726
|
+
]);
|
|
727
|
+
const cookieActionValue = await view.requestValue(`6/7 cookie [keep] (keep · set · clear)`);
|
|
728
|
+
if (cookieActionValue === undefined)
|
|
729
|
+
return this.#cancelWizard();
|
|
730
|
+
const cookieAction = cookieActionValue.trim().toLowerCase() || "keep";
|
|
731
|
+
if (!["keep", "set", "clear"].includes(cookieAction)) {
|
|
732
|
+
throw new Error("Cookie action must be keep, set, or clear");
|
|
733
|
+
}
|
|
734
|
+
let cookie;
|
|
735
|
+
if (cookieAction === "set") {
|
|
736
|
+
cookie = await view.requestValue("6/7 Cookie (hidden; Esc cancels)", { secret: true });
|
|
737
|
+
if (cookie === undefined)
|
|
738
|
+
return this.#cancelWizard();
|
|
739
|
+
if (!cookie)
|
|
740
|
+
throw new Error("Cookie cannot be empty");
|
|
741
|
+
}
|
|
742
|
+
this.#showWizardStep(7, "Review and apply", [
|
|
561
743
|
`Provider ${provider}`,
|
|
562
744
|
`Model ${model}`,
|
|
563
745
|
`Base URL ${baseUrl || "provider default"}`,
|
|
564
746
|
`API ${api}`,
|
|
565
747
|
`Thinking ${thinking}`,
|
|
566
748
|
`API key ${keyAction === "keep" ? current.hasApiKey ? "keep configured key" : "not configured" : keyAction}`,
|
|
749
|
+
`Cookie ${cookieAction === "keep" ? current.hasCookie ? "keep configured cookie" : "not configured" : cookieAction}`,
|
|
567
750
|
"",
|
|
568
|
-
"The key
|
|
751
|
+
"The key and cookie values are never displayed or stored in the TUI state.",
|
|
569
752
|
]);
|
|
570
|
-
const confirmation = await view.requestValue("
|
|
753
|
+
const confirmation = await view.requestValue("7/7 save and apply? [y/N]");
|
|
571
754
|
if (confirmation === undefined || !/^(y|yes)$/i.test(confirmation.trim()))
|
|
572
755
|
return this.#cancelWizard();
|
|
573
756
|
await this.#saveSettings(updateFrom(current, {
|
|
@@ -578,7 +761,9 @@ export class PsporeTuiApp {
|
|
|
578
761
|
thinking,
|
|
579
762
|
customModel: provider === "custom-openai",
|
|
580
763
|
...(apiKey ? { apiKey } : {}),
|
|
764
|
+
...(cookie ? { cookie } : {}),
|
|
581
765
|
clearApiKey: keyAction === "clear",
|
|
766
|
+
clearCookie: cookieAction === "clear",
|
|
582
767
|
}));
|
|
583
768
|
}
|
|
584
769
|
async #saveSettings(update) {
|
|
@@ -587,6 +772,7 @@ export class PsporeTuiApp {
|
|
|
587
772
|
throw new Error("Model settings are unavailable");
|
|
588
773
|
this.#store.setNotice("Validating model settings…");
|
|
589
774
|
const saved = await settingsPort.save(decodeLlmSettingsUpdate(update, "TUI LLM settings"));
|
|
775
|
+
this.#store.setConfiguredModel({ provider: saved.provider, model: saved.model });
|
|
590
776
|
const applied = await this.#options.onSettingsSaved?.();
|
|
591
777
|
this.#showSettings(saved, applied?.message ?? "Settings saved; restart the daemon to apply them");
|
|
592
778
|
}
|
|
@@ -594,6 +780,60 @@ export class PsporeTuiApp {
|
|
|
594
780
|
this.#store.setPanel("Model settings", settingsLines(settings));
|
|
595
781
|
this.#store.setNotice(message);
|
|
596
782
|
}
|
|
783
|
+
#showWizardStep(step, title, lines) {
|
|
784
|
+
const progress = Array.from({ length: 7 }, (_, index) => index + 1 < step ? "●" : index + 1 === step ? "◉" : "○").join("─");
|
|
785
|
+
this.#store.setPanel(`Model setup · ${step}/7`, [
|
|
786
|
+
`${progress} ${title}`,
|
|
787
|
+
"",
|
|
788
|
+
...lines,
|
|
789
|
+
"",
|
|
790
|
+
"Esc cancels without saving.",
|
|
791
|
+
]);
|
|
792
|
+
}
|
|
793
|
+
#showWork(query) {
|
|
794
|
+
const activities = this.#store.snapshot().activities;
|
|
795
|
+
if (!query) {
|
|
796
|
+
this.#store.setPanel("Work history", activities.length === 0
|
|
797
|
+
? ["No work steps have been recorded in this daemon session yet."]
|
|
798
|
+
: activities.slice(-30).map((activity) => {
|
|
799
|
+
const status = activity.status === "running" ? "RUN" : activity.status === "failed" ? "FAIL" : "DONE";
|
|
800
|
+
const result = activity.resultSummary ? ` · ${activity.resultSummary}` : "";
|
|
801
|
+
return `${status.padEnd(4)} ${activity.id.slice(0, 8)} · ${activity.label} · ${activity.summary}${result}`;
|
|
802
|
+
}));
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
const matches = activities.filter((activity) => activity.id === query || activity.id.startsWith(query));
|
|
806
|
+
if (matches.length === 0)
|
|
807
|
+
throw new Error(`No work step matches ${query}`);
|
|
808
|
+
if (matches.length > 1)
|
|
809
|
+
throw new Error(`Work step ID is ambiguous: ${query}`);
|
|
810
|
+
const activity = matches[0];
|
|
811
|
+
if (!activity)
|
|
812
|
+
throw new Error(`No work step matches ${query}`);
|
|
813
|
+
this.#store.setPanel(`Work step ${activity.id.slice(0, 8)}`, activityDetailLines(activity));
|
|
814
|
+
}
|
|
815
|
+
async #refreshConfiguredModel() {
|
|
816
|
+
const settings = this.#options.settings;
|
|
817
|
+
if (!settings)
|
|
818
|
+
return;
|
|
819
|
+
try {
|
|
820
|
+
const configured = settings.isModelConfigured ? await settings.isModelConfigured() : true;
|
|
821
|
+
if (!configured || this.#stopping) {
|
|
822
|
+
this.#store.setConfiguredModel(undefined);
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
const value = await settings.get();
|
|
826
|
+
if (!this.#stopping)
|
|
827
|
+
this.#store.setConfiguredModel({ provider: value.provider, model: value.model });
|
|
828
|
+
}
|
|
829
|
+
catch {
|
|
830
|
+
// The settings panel reports actionable errors on demand; header refresh stays non-blocking.
|
|
831
|
+
}
|
|
832
|
+
finally {
|
|
833
|
+
if (!this.#stopping)
|
|
834
|
+
this.#tui.requestRender();
|
|
835
|
+
}
|
|
836
|
+
}
|
|
597
837
|
#cancelWizard() {
|
|
598
838
|
this.#store.clearPanel();
|
|
599
839
|
this.#store.setNotice("Settings wizard cancelled; nothing was changed");
|
|
@@ -609,7 +849,8 @@ export class PsporeTuiApp {
|
|
|
609
849
|
return client.command(type, payload, sessionId === undefined ? {} : { sessionId });
|
|
610
850
|
}
|
|
611
851
|
async #interrupt() {
|
|
612
|
-
const
|
|
852
|
+
const snapshot = this.#store.snapshot();
|
|
853
|
+
const running = snapshot.kernel.sessions[snapshot.selectedSessionId]?.status === "running";
|
|
613
854
|
if (running) {
|
|
614
855
|
await this.#submit("/abort");
|
|
615
856
|
this.#lastInterruptAt = Date.now();
|
|
@@ -650,6 +891,15 @@ function parseProvider(value) {
|
|
|
650
891
|
}
|
|
651
892
|
return provider;
|
|
652
893
|
}
|
|
894
|
+
function parsePermissionMode(value) {
|
|
895
|
+
const normalized = value?.trim().toLowerCase();
|
|
896
|
+
// `bypass` is the name users reach for; it maps onto the existing allow_all policy.
|
|
897
|
+
const mode = normalized === "bypass" ? "allow_all" : normalized;
|
|
898
|
+
if (!mode || !PERMISSION_MODES.includes(mode)) {
|
|
899
|
+
throw new Error(`Permission mode must be one of: ${PERMISSION_MODES.join(", ")} (or bypass)`);
|
|
900
|
+
}
|
|
901
|
+
return mode;
|
|
902
|
+
}
|
|
653
903
|
function parseThinking(value) {
|
|
654
904
|
const normalized = value?.trim().toLowerCase();
|
|
655
905
|
if (!normalized || !THINKING_LEVELS.includes(normalized)) {
|
|
@@ -673,8 +923,15 @@ function updateFrom(settings, changes) {
|
|
|
673
923
|
api: changes.api ?? settings.api,
|
|
674
924
|
thinking: changes.thinking ?? settings.thinking,
|
|
675
925
|
customModel: changes.customModel ?? settings.customModel,
|
|
926
|
+
permissionMode: changes.permissionMode ?? settings.permissionMode,
|
|
927
|
+
autoCompactionEnabled: changes.autoCompactionEnabled ?? settings.autoCompactionEnabled,
|
|
928
|
+
autoCompactionTriggerTokens: changes.autoCompactionTriggerTokens ?? settings.autoCompactionTriggerTokens,
|
|
929
|
+
autoCompactionReserveTokens: changes.autoCompactionReserveTokens ?? settings.autoCompactionReserveTokens,
|
|
930
|
+
autoCompactionKeepRecentTokens: changes.autoCompactionKeepRecentTokens ?? settings.autoCompactionKeepRecentTokens,
|
|
676
931
|
...(changes.apiKey ? { apiKey: changes.apiKey } : {}),
|
|
932
|
+
...(changes.cookie ? { cookie: changes.cookie } : {}),
|
|
677
933
|
clearApiKey: changes.clearApiKey ?? false,
|
|
934
|
+
clearCookie: changes.clearCookie ?? false,
|
|
678
935
|
};
|
|
679
936
|
}
|
|
680
937
|
function settingsLines(settings) {
|
|
@@ -684,9 +941,30 @@ function settingsLines(settings) {
|
|
|
684
941
|
`Base URL ${settings.baseUrl || "provider default"}`,
|
|
685
942
|
`API ${settings.api}`,
|
|
686
943
|
`Thinking ${settings.thinking}`,
|
|
944
|
+
`Approvals ${settings.permissionMode} — ${permissionModeSummary(settings.permissionMode)}`,
|
|
945
|
+
`Compact ${settings.autoCompactionEnabled ? "on" : "off"} · trigger ${settings.autoCompactionTriggerTokens} · reserve ${settings.autoCompactionReserveTokens} · keep ${settings.autoCompactionKeepRecentTokens}`,
|
|
687
946
|
`API key ${settings.hasApiKey ? "configured (hidden)" : "not configured"}`,
|
|
947
|
+
` file ${settings.apiKeyPath}`,
|
|
948
|
+
`Cookie ${settings.hasCookie ? "configured (hidden)" : "not configured"}`,
|
|
949
|
+
` file ${settings.cookiePath}`,
|
|
950
|
+
`Config ${settings.configPath}`,
|
|
951
|
+
`Catalog ${settings.modelsPath}`,
|
|
688
952
|
"",
|
|
689
953
|
"Use /config wizard for guided setup, or /help for direct commands.",
|
|
690
954
|
];
|
|
691
955
|
}
|
|
956
|
+
function parseOnOff(value, label) {
|
|
957
|
+
if (value === "on")
|
|
958
|
+
return true;
|
|
959
|
+
if (value === "off")
|
|
960
|
+
return false;
|
|
961
|
+
throw new Error(`${label} expects on or off`);
|
|
962
|
+
}
|
|
963
|
+
function parseCompactionTokens(value, label) {
|
|
964
|
+
const parsed = Number(value);
|
|
965
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0 || parsed > 1_000_000) {
|
|
966
|
+
throw new Error(`${label} must be an integer from 1 to 1000000`);
|
|
967
|
+
}
|
|
968
|
+
return parsed;
|
|
969
|
+
}
|
|
692
970
|
//# sourceMappingURL=tui-app.js.map
|