@xingular/harness 0.1.7 → 1.0.0
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 +97 -1
- package/LICENSE +202 -0
- package/NOTICE.md +22 -0
- package/README.md +187 -85
- package/THIRD_PARTY_LICENSES.md +942 -0
- package/dist/cli.js +13701 -13498
- package/dist/sdk/accounts/accounts.d.ts +165 -0
- package/dist/sdk/accounts/accounts.js +730 -0
- package/dist/sdk/accounts/choices.d.ts +23 -0
- package/dist/sdk/accounts/choices.js +62 -0
- package/dist/sdk/accounts/env.d.ts +78 -0
- package/dist/sdk/accounts/env.js +294 -0
- package/dist/sdk/accounts/secrets.d.ts +16 -0
- package/dist/sdk/accounts/secrets.js +40 -0
- package/dist/sdk/accounts/store.d.ts +114 -0
- package/dist/sdk/accounts/store.js +255 -0
- package/dist/sdk/browser/config.d.ts +16 -0
- package/dist/sdk/browser/config.js +22 -0
- package/dist/sdk/browser/diagnostics.d.ts +4 -0
- package/dist/sdk/browser/diagnostics.js +38 -0
- package/dist/sdk/browser/index.d.ts +17 -0
- package/dist/sdk/browser/index.js +65 -0
- package/dist/sdk/browser/network.d.ts +10 -0
- package/dist/sdk/browser/network.js +59 -0
- package/dist/sdk/browser/session.d.ts +84 -0
- package/dist/sdk/browser/session.js +192 -0
- package/dist/sdk/browser/tools.d.ts +8 -0
- package/dist/sdk/browser/tools.js +329 -0
- package/dist/sdk/capabilities/api.d.ts +22 -0
- package/dist/sdk/capabilities/api.js +54 -0
- package/dist/sdk/capabilities/runSnapshot.d.ts +18 -0
- package/dist/sdk/capabilities/runSnapshot.js +47 -0
- package/dist/sdk/capabilities/types.d.ts +29 -0
- package/dist/sdk/capabilities/types.js +1 -0
- package/dist/sdk/cli.d.ts +2 -0
- package/dist/sdk/cli.js +142 -0
- package/dist/sdk/core/bus.d.ts +23 -0
- package/dist/sdk/core/bus.js +76 -0
- package/dist/sdk/core/caller.d.ts +22 -0
- package/dist/sdk/core/caller.js +16 -0
- package/dist/sdk/core/changes.d.ts +15 -0
- package/dist/sdk/core/changes.js +15 -0
- package/dist/sdk/core/effort.d.ts +2 -0
- package/dist/sdk/core/effort.js +1 -0
- package/dist/sdk/core/env.d.ts +18 -0
- package/dist/sdk/core/env.js +8 -0
- package/dist/sdk/core/errors.d.ts +15 -0
- package/dist/sdk/core/errors.js +24 -0
- package/dist/sdk/core/frontmatter.d.ts +12 -0
- package/dist/sdk/core/frontmatter.js +50 -0
- package/dist/sdk/core/fs.d.ts +18 -0
- package/dist/sdk/core/fs.js +106 -0
- package/dist/sdk/core/index.d.ts +24 -0
- package/dist/sdk/core/index.js +187 -0
- package/dist/sdk/core/path.d.ts +7 -0
- package/dist/sdk/core/path.js +79 -0
- package/dist/sdk/core/projects.d.ts +18 -0
- package/dist/sdk/core/projects.js +67 -0
- package/dist/sdk/core/secrets.d.ts +2 -0
- package/dist/sdk/core/secrets.js +5 -0
- package/dist/sdk/core/text.d.ts +7 -0
- package/dist/sdk/core/text.js +40 -0
- package/dist/sdk/doctor/checks.d.ts +5 -0
- package/dist/sdk/doctor/checks.js +208 -0
- package/dist/sdk/doctor/probe.d.ts +4 -0
- package/dist/sdk/doctor/probe.js +92 -0
- package/dist/sdk/doctor/service.d.ts +23 -0
- package/dist/sdk/doctor/service.js +144 -0
- package/dist/sdk/doctor/types.d.ts +141 -0
- package/dist/sdk/doctor/types.js +29 -0
- package/dist/sdk/harness.d.ts +133 -0
- package/dist/sdk/harness.js +299 -0
- package/dist/sdk/history/lessonPrompt.d.ts +2 -0
- package/dist/sdk/history/lessonPrompt.js +15 -0
- package/dist/sdk/history/lessons.d.ts +52 -0
- package/dist/sdk/history/lessons.js +173 -0
- package/dist/sdk/history/recall.d.ts +68 -0
- package/dist/sdk/history/recall.js +199 -0
- package/dist/sdk/history/trajectory.d.ts +7 -0
- package/dist/sdk/history/trajectory.js +216 -0
- package/dist/sdk/hub/catalog.json +123 -0
- package/dist/sdk/hub/cli.d.ts +7 -0
- package/dist/sdk/hub/cli.js +81 -0
- package/dist/sdk/hub/hub.d.ts +74 -0
- package/dist/sdk/hub/hub.js +474 -0
- package/dist/sdk/hub/schema.d.ts +280 -0
- package/dist/sdk/hub/schema.js +78 -0
- package/dist/sdk/index.d.ts +63 -0
- package/dist/sdk/index.js +48 -0
- package/dist/sdk/mcp/connections.d.ts +83 -0
- package/dist/sdk/mcp/connections.js +669 -0
- package/dist/sdk/mcp/manager.d.ts +26 -0
- package/dist/sdk/mcp/manager.js +124 -0
- package/dist/sdk/mcp/oauth.d.ts +35 -0
- package/dist/sdk/mcp/oauth.js +171 -0
- package/dist/sdk/mcp/scopeMigration.d.ts +19 -0
- package/dist/sdk/mcp/scopeMigration.js +198 -0
- package/dist/sdk/mcp/service.d.ts +160 -0
- package/dist/sdk/mcp/service.js +510 -0
- package/dist/sdk/mcp/types.d.ts +131 -0
- package/dist/sdk/mcp/types.js +49 -0
- package/dist/sdk/pi/runtime.d.ts +13 -0
- package/dist/sdk/pi/runtime.js +31 -0
- package/dist/sdk/plugins/api.d.ts +66 -0
- package/dist/sdk/plugins/api.js +155 -0
- package/dist/sdk/plugins/attachments.d.ts +46 -0
- package/dist/sdk/plugins/attachments.js +111 -0
- package/dist/sdk/plugins/builtin.d.ts +6 -0
- package/dist/sdk/plugins/builtin.js +68 -0
- package/dist/sdk/plugins/catalogue.d.ts +29 -0
- package/dist/sdk/plugins/catalogue.js +196 -0
- package/dist/sdk/plugins/cli.d.ts +13 -0
- package/dist/sdk/plugins/cli.js +187 -0
- package/dist/sdk/plugins/discover.d.ts +42 -0
- package/dist/sdk/plugins/discover.js +115 -0
- package/dist/sdk/plugins/firstParty.d.ts +50 -0
- package/dist/sdk/plugins/firstParty.js +113 -0
- package/dist/sdk/plugins/hooks.d.ts +94 -0
- package/dist/sdk/plugins/hooks.js +162 -0
- package/dist/sdk/plugins/identity.d.ts +19 -0
- package/dist/sdk/plugins/identity.js +48 -0
- package/dist/sdk/plugins/install.d.ts +20 -0
- package/dist/sdk/plugins/install.js +110 -0
- package/dist/sdk/plugins/inventory.d.ts +22 -0
- package/dist/sdk/plugins/inventory.js +110 -0
- package/dist/sdk/plugins/manifest.d.ts +13 -0
- package/dist/sdk/plugins/manifest.js +56 -0
- package/dist/sdk/plugins/plugins.d.ts +104 -0
- package/dist/sdk/plugins/plugins.js +164 -0
- package/dist/sdk/plugins/runtime.d.ts +9 -0
- package/dist/sdk/plugins/runtime.js +95 -0
- package/dist/sdk/plugins/trust.d.ts +44 -0
- package/dist/sdk/plugins/trust.js +120 -0
- package/dist/sdk/plugins/types.d.ts +159 -0
- package/dist/sdk/plugins/types.js +7 -0
- package/dist/sdk/prompt/compile.d.ts +174 -0
- package/dist/sdk/prompt/compile.js +396 -0
- package/dist/sdk/refine/cli.d.ts +4 -0
- package/dist/sdk/refine/cli.js +186 -0
- package/dist/sdk/refine/demo.d.ts +21 -0
- package/dist/sdk/refine/demo.js +114 -0
- package/dist/sdk/refine/evidence.d.ts +55 -0
- package/dist/sdk/refine/evidence.js +330 -0
- package/dist/sdk/refine/host.d.ts +51 -0
- package/dist/sdk/refine/host.js +76 -0
- package/dist/sdk/refine/ledger.d.ts +48 -0
- package/dist/sdk/refine/ledger.js +76 -0
- package/dist/sdk/refine/library.d.ts +55 -0
- package/dist/sdk/refine/library.js +177 -0
- package/dist/sdk/refine/pi.d.ts +72 -0
- package/dist/sdk/refine/pi.js +248 -0
- package/dist/sdk/refine/prompts.d.ts +45 -0
- package/dist/sdk/refine/prompts.js +390 -0
- package/dist/sdk/refine/recursion.d.ts +113 -0
- package/dist/sdk/refine/recursion.js +258 -0
- package/dist/sdk/refine/runner.d.ts +81 -0
- package/dist/sdk/refine/runner.js +150 -0
- package/dist/sdk/refine/selection.d.ts +57 -0
- package/dist/sdk/refine/selection.js +251 -0
- package/dist/sdk/refine/service.d.ts +84 -0
- package/dist/sdk/refine/service.js +165 -0
- package/dist/sdk/refine/suite.d.ts +67 -0
- package/dist/sdk/refine/suite.js +174 -0
- package/dist/sdk/refine/trajectory.d.ts +9 -0
- package/dist/sdk/refine/trajectory.js +68 -0
- package/dist/sdk/refine/types.d.ts +77 -0
- package/dist/sdk/refine/types.js +10 -0
- package/dist/sdk/server/methods.d.ts +3 -0
- package/dist/sdk/server/methods.js +370 -0
- package/dist/sdk/server/remote.d.ts +19 -0
- package/dist/sdk/server/remote.js +84 -0
- package/dist/sdk/server/rpc.d.ts +20 -0
- package/dist/sdk/server/rpc.js +102 -0
- package/dist/sdk/server/serve.d.ts +10 -0
- package/dist/sdk/server/serve.js +18 -0
- package/dist/sdk/sessions/approvals.d.ts +47 -0
- package/dist/sdk/sessions/approvals.js +119 -0
- package/dist/sdk/sessions/continuation.d.ts +48 -0
- package/dist/sdk/sessions/continuation.js +85 -0
- package/dist/sdk/sessions/contracts.d.ts +534 -0
- package/dist/sdk/sessions/contracts.js +299 -0
- package/dist/sdk/sessions/extensionUi.d.ts +19 -0
- package/dist/sdk/sessions/extensionUi.js +64 -0
- package/dist/sdk/sessions/history.d.ts +16 -0
- package/dist/sdk/sessions/history.js +68 -0
- package/dist/sdk/sessions/lineageJoin.d.ts +2 -0
- package/dist/sdk/sessions/lineageJoin.js +61 -0
- package/dist/sdk/sessions/planMode.d.ts +36 -0
- package/dist/sdk/sessions/planMode.js +84 -0
- package/dist/sdk/sessions/policy.d.ts +43 -0
- package/dist/sdk/sessions/policy.js +1 -0
- package/dist/sdk/sessions/pricing.d.ts +34 -0
- package/dist/sdk/sessions/pricing.js +40 -0
- package/dist/sdk/sessions/reasoningSummaries.d.ts +11 -0
- package/dist/sdk/sessions/reasoningSummaries.js +61 -0
- package/dist/sdk/sessions/registry.d.ts +102 -0
- package/dist/sdk/sessions/registry.js +383 -0
- package/dist/sdk/sessions/runIndex.d.ts +21 -0
- package/dist/sdk/sessions/runIndex.js +65 -0
- package/dist/sdk/sessions/runStore.d.ts +66 -0
- package/dist/sdk/sessions/runStore.js +335 -0
- package/dist/sdk/sessions/runner.d.ts +213 -0
- package/dist/sdk/sessions/runner.js +589 -0
- package/dist/sdk/sessions/sessions.d.ts +140 -0
- package/dist/sdk/sessions/sessions.js +394 -0
- package/dist/sdk/sessions/subagentService.d.ts +41 -0
- package/dist/sdk/sessions/subagentService.js +247 -0
- package/dist/sdk/sessions/subagents.d.ts +50 -0
- package/dist/sdk/sessions/subagents.js +68 -0
- package/dist/sdk/terminal/accountsMenu.d.ts +46 -0
- package/dist/sdk/terminal/accountsMenu.js +392 -0
- package/dist/sdk/terminal/cli.d.ts +20 -0
- package/dist/sdk/terminal/cli.js +121 -0
- package/dist/sdk/terminal/client.d.ts +15 -0
- package/dist/sdk/terminal/client.js +126 -0
- package/dist/sdk/terminal/control.d.ts +4 -0
- package/dist/sdk/terminal/control.js +25 -0
- package/dist/sdk/terminal/controller.d.ts +72 -0
- package/dist/sdk/terminal/controller.js +351 -0
- package/dist/sdk/terminal/hubMenu.d.ts +10 -0
- package/dist/sdk/terminal/hubMenu.js +34 -0
- package/dist/sdk/terminal/launch.d.ts +5 -0
- package/dist/sdk/terminal/launch.js +27 -0
- package/dist/sdk/terminal/logs.d.ts +14 -0
- package/dist/sdk/terminal/logs.js +59 -0
- package/dist/sdk/terminal/piExtension.d.ts +6 -0
- package/dist/sdk/terminal/piExtension.js +392 -0
- package/dist/sdk/terminal/pluginMenu.d.ts +34 -0
- package/dist/sdk/terminal/pluginMenu.js +101 -0
- package/dist/sdk/terminal/socket.d.ts +70 -0
- package/dist/sdk/terminal/socket.js +256 -0
- package/dist/sdk/terminal/standalone.d.ts +18 -0
- package/dist/sdk/terminal/standalone.js +146 -0
- package/dist/sdk/terminal/terminals.d.ts +176 -0
- package/dist/sdk/terminal/terminals.js +767 -0
- package/dist/sdk/terminal/trajectory.d.ts +10 -0
- package/dist/sdk/terminal/trajectory.js +30 -0
- package/dist/sdk/terminal/tui/chrome.d.ts +64 -0
- package/dist/sdk/terminal/tui/chrome.js +169 -0
- package/dist/sdk/terminal/tui/clipboardFiles.d.ts +11 -0
- package/dist/sdk/terminal/tui/clipboardFiles.js +74 -0
- package/dist/sdk/terminal/tui/commandPages.d.ts +7 -0
- package/dist/sdk/terminal/tui/commandPages.js +63 -0
- package/dist/sdk/terminal/tui/commands.d.ts +42 -0
- package/dist/sdk/terminal/tui/commands.js +276 -0
- package/dist/sdk/terminal/tui/dialogGeometry.d.ts +27 -0
- package/dist/sdk/terminal/tui/dialogGeometry.js +50 -0
- package/dist/sdk/terminal/tui/dialogs.d.ts +75 -0
- package/dist/sdk/terminal/tui/dialogs.js +363 -0
- package/dist/sdk/terminal/tui/keybindings.d.ts +11 -0
- package/dist/sdk/terminal/tui/keybindings.js +49 -0
- package/dist/sdk/terminal/tui/list.d.ts +73 -0
- package/dist/sdk/terminal/tui/list.js +196 -0
- package/dist/sdk/terminal/tui/modeChoices.d.ts +42 -0
- package/dist/sdk/terminal/tui/modeChoices.js +70 -0
- package/dist/sdk/terminal/tui/modelPicker.d.ts +55 -0
- package/dist/sdk/terminal/tui/modelPicker.js +155 -0
- package/dist/sdk/terminal/tui/mouse.d.ts +3 -0
- package/dist/sdk/terminal/tui/mouse.js +3 -0
- package/dist/sdk/terminal/tui/page.d.ts +14 -0
- package/dist/sdk/terminal/tui/page.js +1 -0
- package/dist/sdk/terminal/tui/pageOverlay.d.ts +27 -0
- package/dist/sdk/terminal/tui/pageOverlay.js +145 -0
- package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +54 -0
- package/dist/sdk/terminal/tui/pages/accountsPage.js +181 -0
- package/dist/sdk/terminal/tui/pages/componentsPage.d.ts +47 -0
- package/dist/sdk/terminal/tui/pages/componentsPage.js +119 -0
- package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +37 -0
- package/dist/sdk/terminal/tui/pages/doctorPage.js +145 -0
- package/dist/sdk/terminal/tui/pages/hubPage.d.ts +39 -0
- package/dist/sdk/terminal/tui/pages/hubPage.js +128 -0
- package/dist/sdk/terminal/tui/pages/logPage.d.ts +38 -0
- package/dist/sdk/terminal/tui/pages/logPage.js +189 -0
- package/dist/sdk/terminal/tui/pages/permissionsPage.d.ts +44 -0
- package/dist/sdk/terminal/tui/pages/permissionsPage.js +124 -0
- package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +57 -0
- package/dist/sdk/terminal/tui/pages/pluginsPage.js +243 -0
- package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +55 -0
- package/dist/sdk/terminal/tui/pages/settingsPage.js +88 -0
- package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +58 -0
- package/dist/sdk/terminal/tui/pages/trajectoryPage.js +377 -0
- package/dist/sdk/terminal/tui/piAdapter.d.ts +18 -0
- package/dist/sdk/terminal/tui/piAdapter.js +48 -0
- package/dist/sdk/terminal/tui/planMode.d.ts +2 -0
- package/dist/sdk/terminal/tui/planMode.js +2 -0
- package/dist/sdk/terminal/tui/questionPicker.d.ts +20 -0
- package/dist/sdk/terminal/tui/questionPicker.js +150 -0
- package/dist/sdk/terminal/tui/questions.d.ts +19 -0
- package/dist/sdk/terminal/tui/questions.js +42 -0
- package/dist/sdk/terminal/tui/runtime.d.ts +114 -0
- package/dist/sdk/terminal/tui/runtime.js +441 -0
- package/dist/sdk/terminal/tui/search.d.ts +22 -0
- package/dist/sdk/terminal/tui/search.js +60 -0
- package/dist/sdk/terminal/tui/selection.d.ts +16 -0
- package/dist/sdk/terminal/tui/selection.js +16 -0
- package/dist/sdk/terminal/tui/sessionUi.d.ts +3 -0
- package/dist/sdk/terminal/tui/sessionUi.js +30 -0
- package/dist/sdk/terminal/tui/settingsModel.d.ts +12 -0
- package/dist/sdk/terminal/tui/settingsModel.js +84 -0
- package/dist/sdk/terminal/tui/sideQuestion.d.ts +53 -0
- package/dist/sdk/terminal/tui/sideQuestion.js +197 -0
- package/dist/sdk/terminal/tui/skillInvocation.d.ts +9 -0
- package/dist/sdk/terminal/tui/skillInvocation.js +43 -0
- package/dist/sdk/terminal/tui/status.d.ts +18 -0
- package/dist/sdk/terminal/tui/status.js +67 -0
- package/dist/sdk/terminal/tui/theme.d.ts +45 -0
- package/dist/sdk/terminal/tui/theme.js +176 -0
- package/dist/sdk/terminal/tui/treeModel.d.ts +79 -0
- package/dist/sdk/terminal/tui/treeModel.js +483 -0
- package/dist/sdk/terminal/tui/treePicker.d.ts +49 -0
- package/dist/sdk/terminal/tui/treePicker.js +251 -0
- package/dist/sdk/terminal/tui/ui.d.ts +47 -0
- package/dist/sdk/terminal/tui/ui.js +148 -0
- package/dist/sdk/terminal/tui/workingStatus.d.ts +9 -0
- package/dist/sdk/terminal/tui/workingStatus.js +229 -0
- package/dist/sdk/tools/askUser.d.ts +6 -0
- package/dist/sdk/tools/askUser.js +74 -0
- package/dist/sdk/tools/checklist.d.ts +9 -0
- package/dist/sdk/tools/checklist.js +54 -0
- package/dist/sdk/tools/definitions.d.ts +30 -0
- package/dist/sdk/tools/definitions.js +117 -0
- package/dist/sdk/tools/dispatch.d.ts +16 -0
- package/dist/sdk/tools/dispatch.js +67 -0
- package/dist/sdk/tools/harnessTools.d.ts +6 -0
- package/dist/sdk/tools/harnessTools.js +20 -0
- package/dist/sdk/tools/sessionName.d.ts +7 -0
- package/dist/sdk/tools/sessionName.js +31 -0
- package/dist/sdk/tools/spawnSubagent.d.ts +4 -0
- package/dist/sdk/tools/spawnSubagent.js +49 -0
- package/dist/sdk/tools/types.d.ts +48 -0
- package/dist/sdk/tools/types.js +1 -0
- package/dist/sdk/variant/components.d.ts +34 -0
- package/dist/sdk/variant/components.js +230 -0
- package/dist/sdk/variant/materialise.d.ts +66 -0
- package/dist/sdk/variant/materialise.js +81 -0
- package/dist/sdk/variant/migrate.d.ts +4 -0
- package/dist/sdk/variant/migrate.js +41 -0
- package/dist/sdk/variant/seed.d.ts +20 -0
- package/dist/sdk/variant/seed.js +116 -0
- package/dist/sdk/variant/store.d.ts +82 -0
- package/dist/sdk/variant/store.js +151 -0
- package/dist/sdk/variant/surface.d.ts +56 -0
- package/dist/sdk/variant/surface.js +81 -0
- package/dist/sdk/variant/trust.d.ts +27 -0
- package/dist/sdk/variant/trust.js +64 -0
- package/dist/sdk/variant/variant.d.ts +71 -0
- package/dist/sdk/variant/variant.js +331 -0
- package/dist/sdk/web/markdown.d.ts +10 -0
- package/dist/sdk/web/markdown.js +66 -0
- package/dist/sdk/web/safeRequest.d.ts +34 -0
- package/dist/sdk/web/safeRequest.js +175 -0
- package/dist/sdk/web/search.d.ts +53 -0
- package/dist/sdk/web/search.js +168 -0
- package/dist/sdk/web/text.d.ts +2 -0
- package/dist/sdk/web/text.js +7 -0
- package/dist/sdk/web/tools.d.ts +22 -0
- package/dist/sdk/web/tools.js +195 -0
- package/dist/sdk/web/turndown-plugin-gfm.d.ts +4 -0
- package/dist/sdk/wiki/notes.d.ts +68 -0
- package/dist/sdk/wiki/notes.js +297 -0
- package/dist/sdk/world/actions.d.ts +23 -0
- package/dist/sdk/world/actions.js +31 -0
- package/dist/sdk/world/cli.d.ts +12 -0
- package/dist/sdk/world/cli.js +166 -0
- package/dist/sdk/world/images.d.ts +20 -0
- package/dist/sdk/world/images.js +48 -0
- package/dist/sdk/world/untrusted.d.ts +12 -0
- package/dist/sdk/world/untrusted.js +20 -0
- package/dist/sdk/world/world.d.ts +65 -0
- package/dist/sdk/world/world.js +80 -0
- package/dist/terminal-opentui.js +13612 -0
- package/dist/terminal-pi.js +808 -151
- package/docs/README.md +22 -0
- package/docs/architecture/00-overview.md +159 -0
- package/docs/architecture/01-extension-points.md +78 -0
- package/docs/architecture/02-sessions-and-runs.md +146 -0
- package/docs/architecture/03-variants.md +95 -0
- package/docs/architecture/04-prompt.md +102 -0
- package/docs/architecture/05-refinement.md +107 -0
- package/docs/architecture/06-plugins-and-capabilities.md +93 -0
- package/docs/architecture/07-tools-and-gate.md +88 -0
- package/docs/architecture/08-memory-and-history.md +94 -0
- package/docs/architecture/09-accounts-and-connectors.md +90 -0
- package/docs/architecture/10-server-protocol.md +84 -0
- package/docs/architecture/11-terminal.md +81 -0
- package/docs/architecture/12-storage.md +61 -0
- package/docs/architecture/13-world-tools.md +23 -0
- package/docs/architecture/README.md +114 -0
- package/docs/architecture/proposals/PROP-0001-reporting-section.md +106 -0
- package/docs/architecture/proposals/PROP-0002-retain-rollout-workspaces.md +104 -0
- package/docs/architecture/proposals/PROP-0003-executor-settings.md +81 -0
- package/docs/architecture/proposals/PROP-0004-flexible-reporting-guidance.md +71 -0
- package/docs/architecture/proposals/PROP-0005-xharness-cli-name.md +78 -0
- package/docs/architecture/proposals/PROP-0006-run-checklist.md +68 -0
- package/docs/architecture/proposals/PROP-0007-run-continuation.md +80 -0
- package/docs/architecture/proposals/PROP-0008-lessons-from-runs.md +80 -0
- package/docs/architecture/proposals/PROP-0009-foundation-and-variants.md +78 -0
- package/docs/architecture/proposals/PROP-0010-session-names.md +73 -0
- package/docs/architecture/proposals/PROP-0011-doctor.md +63 -0
- package/docs/architecture/proposals/PROP-0012-release-baseline.md +56 -0
- package/docs/architecture/proposals/README.md +76 -0
- package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
- package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
- package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
- package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
- package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
- package/docs/decisions/ADR-0007-reporting-section.md +33 -0
- package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
- package/docs/decisions/ADR-0009-xharness-command.md +38 -0
- package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
- package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
- package/docs/decisions/ADR-0012-native-session-names.md +34 -0
- package/docs/decisions/ADR-0013-doctor.md +27 -0
- package/docs/decisions/ADR-0014-public-release-baseline.md +21 -0
- package/docs/doctor.md +74 -0
- package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
- package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
- package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
- package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
- package/docs/features/README.md +20 -0
- package/docs/features/automations/README.md +41 -0
- package/docs/features/cores/README.md +39 -0
- package/docs/features/google-harness2/README.md +52 -0
- package/docs/features/integrations/README.md +40 -0
- package/docs/features/interfaces/README.md +29 -0
- package/docs/features/memory/README.md +28 -0
- package/docs/releases/1.0.0.md +40 -0
- package/docs/releases/README.md +36 -0
- package/docs/study/00-index.md +78 -0
- package/docs/study/arms/00-matrix.md +20 -0
- package/docs/study/arms/01-system-prompt.md +211 -0
- package/docs/study/arms/02-tools.md +79 -0
- package/docs/study/arms/03-subagents.md +90 -0
- package/docs/study/arms/04-skills.md +75 -0
- package/docs/study/arms/05-context-management.md +90 -0
- package/docs/study/arms/06-memory.md +90 -0
- package/docs/study/arms/07-governance.md +71 -0
- package/docs/study/arms/08-execution.md +69 -0
- package/docs/study/arms/09-observability.md +60 -0
- package/docs/study/arms/10-refinement.md +110 -0
- package/docs/study/btw-comparison.md +37 -0
- package/docs/study/feature-gap-review.md +42 -0
- package/docs/study/insights.md +123 -0
- package/docs/study/roadmap.md +72 -0
- package/docs/study/sources/claude-code.md +44 -0
- package/docs/study/sources/deepseek-harness.md +102 -0
- package/docs/study/sources/harness2.md +50 -0
- package/docs/study/sources/kimi-cli.md +42 -0
- package/docs/study/sources/omp.md +93 -0
- package/docs/study/sources/opencode.md +43 -0
- package/docs/study/sources/openhands.md +46 -0
- package/docs/study/sources/smolagents.md +40 -0
- package/docs/study/sources/swe-agent.md +34 -0
- package/docs/system-prompt-design.md +196 -0
- package/docs/terminal-tui.md +473 -56
- package/package.json +43 -13
- package/docs/evidence/terminal-2026-10-17/120x40-completed-transcript.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/40x20-settings-interaction.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/40x20-settings-keyboard.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/40x20-welcome.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/80x24-approval-0.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/80x24-question.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/verification.json +0 -130
- package/docs/evidence/terminal-2026-10-17-followup/120x40-completed-transcript.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-interaction.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-keyboard.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/40x20-welcome.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/80x24-approval-0.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/80x24-plugin-light.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/80x24-question-batch.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/80x24-question.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-approval-0.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-plugin-light.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question-batch.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/app-bundle/verification.json +0 -95
- package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-approval-0.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-plugin-light.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question-batch.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/global-install/README.md +0 -27
- package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command-80x24.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command.json +0 -18
- package/docs/evidence/terminal-2026-10-17-followup/global-install/verification.json +0 -95
- package/docs/evidence/terminal-2026-10-17-followup/harness-reference-80x24.json.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/harness-reference-final-80x24.json.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/harness-reference-scenario.json +0 -60
- package/docs/evidence/terminal-2026-10-17-followup/live-codex/README.md +0 -24
- package/docs/evidence/terminal-2026-10-17-followup/live-codex/complete-80x24.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/live-codex/verification.json +0 -57
- package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24-early.json.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24.json.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/omp-reference-scenario.json +0 -58
- package/docs/evidence/terminal-2026-10-17-followup/omp-supplemental-static.json.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/rea-artifacts.json +0 -320
- package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.json +0 -30
- package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.md +0 -133
- package/docs/evidence/terminal-2026-10-17-followup/reference-source-observations.json +0 -20
- package/docs/evidence/terminal-2026-10-17-followup/verification.json +0 -207
- package/src/accounts/accounts.test.ts +0 -333
- package/src/accounts/accounts.ts +0 -658
- package/src/accounts/env.test.ts +0 -95
- package/src/accounts/env.ts +0 -338
- package/src/accounts/secrets.ts +0 -50
- package/src/accounts/store.ts +0 -338
- package/src/capabilities/api.ts +0 -75
- package/src/capabilities/runSnapshot.ts +0 -59
- package/src/capabilities/types.ts +0 -34
- package/src/cli.ts +0 -118
- package/src/core/bus.ts +0 -34
- package/src/core/changes.ts +0 -33
- package/src/core/env.ts +0 -27
- package/src/core/errors.ts +0 -32
- package/src/core/frontmatter.ts +0 -47
- package/src/core/fs.test.ts +0 -38
- package/src/core/fs.ts +0 -92
- package/src/core/index.ts +0 -193
- package/src/core/path.test.ts +0 -14
- package/src/core/path.ts +0 -79
- package/src/core/projects.ts +0 -90
- package/src/core/text.ts +0 -39
- package/src/harness.ts +0 -312
- package/src/hub/catalog.json +0 -123
- package/src/hub/cli.ts +0 -59
- package/src/hub/hub.test.ts +0 -205
- package/src/hub/hub.ts +0 -256
- package/src/hub/schema.ts +0 -81
- package/src/index.ts +0 -75
- package/src/mcp/connections.ts +0 -614
- package/src/mcp/manager.ts +0 -130
- package/src/mcp/oauth.ts +0 -195
- package/src/mcp/scopeMigration.test.ts +0 -79
- package/src/mcp/scopeMigration.ts +0 -204
- package/src/mcp/service.test.ts +0 -376
- package/src/mcp/service.ts +0 -549
- package/src/mcp/types.ts +0 -108
- package/src/memory/api.test.ts +0 -82
- package/src/memory/api.ts +0 -303
- package/src/memory/blocks.test.ts +0 -78
- package/src/memory/blocks.ts +0 -408
- package/src/memory/caller.ts +0 -69
- package/src/memory/curation.test.ts +0 -163
- package/src/memory/curation.ts +0 -64
- package/src/memory/dispatch.ts +0 -59
- package/src/memory/facts.test.ts +0 -41
- package/src/memory/facts.ts +0 -248
- package/src/memory/graph.ts +0 -103
- package/src/memory/health.test.ts +0 -130
- package/src/memory/health.ts +0 -74
- package/src/memory/maintainer.ts +0 -272
- package/src/memory/maintenance.test.ts +0 -176
- package/src/memory/maintenance.ts +0 -518
- package/src/memory/migrate.ts +0 -79
- package/src/memory/operations.ts +0 -150
- package/src/memory/proposals.test.ts +0 -168
- package/src/memory/proposals.ts +0 -584
- package/src/memory/recall.test.ts +0 -115
- package/src/memory/recall.ts +0 -278
- package/src/memory/references.ts +0 -77
- package/src/memory/runContext.ts +0 -93
- package/src/memory/secrets.ts +0 -6
- package/src/memory/store.test.ts +0 -66
- package/src/memory/store.ts +0 -385
- package/src/memory/wiki.test.ts +0 -47
- package/src/memory/wiki.ts +0 -422
- package/src/memory/wikiIndex.test.ts +0 -88
- package/src/memory/wikiIndex.ts +0 -116
- package/src/plugins/api.ts +0 -181
- package/src/plugins/attachments.test.ts +0 -84
- package/src/plugins/attachments.ts +0 -141
- package/src/plugins/builtin.ts +0 -82
- package/src/plugins/catalogue.test.ts +0 -254
- package/src/plugins/catalogue.ts +0 -251
- package/src/plugins/cli.ts +0 -184
- package/src/plugins/discover.ts +0 -151
- package/src/plugins/firstParty.test.ts +0 -143
- package/src/plugins/firstParty.ts +0 -129
- package/src/plugins/hooks.test.ts +0 -250
- package/src/plugins/hooks.ts +0 -239
- package/src/plugins/identity.ts +0 -37
- package/src/plugins/install.test.ts +0 -107
- package/src/plugins/install.ts +0 -106
- package/src/plugins/inventory.ts +0 -123
- package/src/plugins/manifest.ts +0 -76
- package/src/plugins/plugins.test.ts +0 -205
- package/src/plugins/plugins.ts +0 -189
- package/src/plugins/proposal.ts +0 -121
- package/src/plugins/runtime.test.ts +0 -40
- package/src/plugins/runtime.ts +0 -82
- package/src/plugins/trust.ts +0 -142
- package/src/plugins/types.ts +0 -149
- package/src/prompt/compile.test.ts +0 -261
- package/src/prompt/compile.ts +0 -732
- package/src/server/methods.ts +0 -349
- package/src/server/remote.ts +0 -77
- package/src/server/rpc.ts +0 -116
- package/src/server/serve.ts +0 -28
- package/src/server/server.test.ts +0 -174
- package/src/sessions/approvals.ts +0 -118
- package/src/sessions/contracts.ts +0 -336
- package/src/sessions/conversation.test.ts +0 -177
- package/src/sessions/extensionSession.test.ts +0 -74
- package/src/sessions/extensionUi.test.ts +0 -65
- package/src/sessions/extensionUi.ts +0 -102
- package/src/sessions/history.ts +0 -51
- package/src/sessions/lineageJoin.ts +0 -75
- package/src/sessions/policy.ts +0 -36
- package/src/sessions/pricing.ts +0 -60
- package/src/sessions/questionBatches.test.ts +0 -110
- package/src/sessions/reasoningSummaries.ts +0 -59
- package/src/sessions/registry.ts +0 -381
- package/src/sessions/runIndex.ts +0 -99
- package/src/sessions/runStore.test.ts +0 -152
- package/src/sessions/runStore.ts +0 -332
- package/src/sessions/runner.ts +0 -604
- package/src/sessions/runtimeResources.test.ts +0 -61
- package/src/sessions/sessions.test.ts +0 -549
- package/src/sessions/sessions.ts +0 -339
- package/src/skills/registry.test.ts +0 -104
- package/src/skills/registry.ts +0 -413
- package/src/terminal/accountsMenu.test.ts +0 -225
- package/src/terminal/accountsMenu.ts +0 -382
- package/src/terminal/cli.ts +0 -149
- package/src/terminal/client.ts +0 -74
- package/src/terminal/control.test.ts +0 -23
- package/src/terminal/control.ts +0 -23
- package/src/terminal/controller.ts +0 -291
- package/src/terminal/hubMenu.ts +0 -24
- package/src/terminal/launch.test.ts +0 -25
- package/src/terminal/launch.ts +0 -48
- package/src/terminal/piExtension.lifecycle.test.ts +0 -55
- package/src/terminal/piExtension.ts +0 -259
- package/src/terminal/pluginControl.test.ts +0 -146
- package/src/terminal/pluginMenu.ts +0 -112
- package/src/terminal/socket.test.ts +0 -71
- package/src/terminal/socket.ts +0 -232
- package/src/terminal/standalone.test.ts +0 -167
- package/src/terminal/standalone.ts +0 -153
- package/src/terminal/terminal.test.ts +0 -399
- package/src/terminal/terminals.ts +0 -553
- package/src/terminal/tui/application.test.ts +0 -114
- package/src/terminal/tui/application.ts +0 -491
- package/src/terminal/tui/commands.test.ts +0 -218
- package/src/terminal/tui/commands.ts +0 -361
- package/src/terminal/tui/dialogs.ts +0 -301
- package/src/terminal/tui/editor.test.ts +0 -84
- package/src/terminal/tui/editor.ts +0 -79
- package/src/terminal/tui/keybindings.test.ts +0 -22
- package/src/terminal/tui/keybindings.ts +0 -50
- package/src/terminal/tui/piAdapter.ts +0 -62
- package/src/terminal/tui/presentation.test.ts +0 -79
- package/src/terminal/tui/questions.test.ts +0 -41
- package/src/terminal/tui/questions.ts +0 -47
- package/src/terminal/tui/runtime.socket.test.ts +0 -104
- package/src/terminal/tui/runtime.test.ts +0 -215
- package/src/terminal/tui/runtime.ts +0 -388
- package/src/terminal/tui/sessionUi.ts +0 -24
- package/src/terminal/tui/settings.test.ts +0 -150
- package/src/terminal/tui/settings.ts +0 -188
- package/src/terminal/tui/status.test.ts +0 -70
- package/src/terminal/tui/status.ts +0 -109
- package/src/terminal/tui/theme.ts +0 -174
- package/src/terminal/tui/tools.test.ts +0 -145
- package/src/terminal/tui/tools.ts +0 -142
- package/src/terminal/tui/transcript.test.ts +0 -25
- package/src/terminal/tui/transcript.ts +0 -124
- package/src/terminal/tui/ui.test.ts +0 -313
- package/src/terminal/tui/ui.ts +0 -166
- package/src/terminal/tui/welcome.ts +0 -102
- package/src/tools/askUser.test.ts +0 -69
- package/src/tools/askUser.ts +0 -59
- package/src/tools/definitions.ts +0 -187
- package/src/tools/maintenance.ts +0 -24
- package/src/tools/memoryTools.ts +0 -22
- package/src/tools/pluginPropose.ts +0 -41
- package/src/tools/registryWrite.test.ts +0 -101
- package/src/tools/registryWrite.ts +0 -182
- package/src/tools/spawnSubagent.ts +0 -92
- package/src/tools/types.ts +0 -39
- package/src/web/safeRequest.ts +0 -171
- package/src/web/text.ts +0 -53
- package/src/web/tools.ts +0 -134
- package/src/web/web.test.ts +0 -141
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
/** The same words the app shows for each health state (`App/src/modes/accounts/accountModel.ts`). */
|
|
2
|
+
export const HEALTH = {
|
|
3
|
+
ok: 'Ready',
|
|
4
|
+
limited: 'Limit reached',
|
|
5
|
+
auth_expired: 'Sign in again',
|
|
6
|
+
signed_out: 'Signed out',
|
|
7
|
+
error: 'Needs attention',
|
|
8
|
+
unknown: 'Not checked'
|
|
9
|
+
};
|
|
10
|
+
const ADD = 'Add account';
|
|
11
|
+
const POOLS = 'Pools';
|
|
12
|
+
const CHECK_ALL = 'Check all accounts';
|
|
13
|
+
const DONE = 'Done';
|
|
14
|
+
const BACK = 'Back';
|
|
15
|
+
const USE_HERE = 'Use for this session (restarts it)';
|
|
16
|
+
const MAKE_DEFAULT = 'Make default for new sessions';
|
|
17
|
+
const RENAME = 'Rename';
|
|
18
|
+
const CHECK = 'Check';
|
|
19
|
+
const DETAILS = 'Details';
|
|
20
|
+
const ACTIVITY = 'Activity';
|
|
21
|
+
const SIGN_IN = 'Sign in';
|
|
22
|
+
const REMOVE_PROVIDER = 'Remove a provider';
|
|
23
|
+
const SIGN_OUT = 'Sign out';
|
|
24
|
+
const REMOVE = 'Remove account';
|
|
25
|
+
const NEW_POOL = 'New pool';
|
|
26
|
+
const EDIT = 'Edit';
|
|
27
|
+
const DELETE = 'Delete';
|
|
28
|
+
const SAVE_POOL = 'Save pool';
|
|
29
|
+
const CANCEL = 'Cancel';
|
|
30
|
+
const START_OVER = 'Start over';
|
|
31
|
+
const REMOVE_LAST = 'Remove the last one';
|
|
32
|
+
const CANCEL_SIGN_IN = 'Cancel sign-in';
|
|
33
|
+
const CHECK_STATUS = 'Check status';
|
|
34
|
+
const LOGIN_TIMEOUT_MS = 10 * 60_000;
|
|
35
|
+
const POLL_MS = 1000;
|
|
36
|
+
const message = (error) => (error instanceof Error ? error.message : String(error));
|
|
37
|
+
/** Runs one call, reports a failure through the menu, and says whether it worked. */
|
|
38
|
+
async function attempt(ui, action) {
|
|
39
|
+
try {
|
|
40
|
+
await action();
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
ui.notify(message(error), 'error');
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** A short "in 2h 5m" from an ISO time, or the time itself when it has passed. */
|
|
49
|
+
export function resetIn(resetsAt, now = Date.now()) {
|
|
50
|
+
const minutes = Math.round((Date.parse(resetsAt) - now) / 60_000);
|
|
51
|
+
if (Number.isNaN(minutes))
|
|
52
|
+
return resetsAt;
|
|
53
|
+
if (minutes <= 0)
|
|
54
|
+
return 'now';
|
|
55
|
+
if (minutes < 60)
|
|
56
|
+
return `in ${minutes}m`;
|
|
57
|
+
if (minutes < 60 * 24)
|
|
58
|
+
return `in ${Math.floor(minutes / 60)}h ${minutes % 60}m`;
|
|
59
|
+
return `in ${Math.floor(minutes / (60 * 24))}d`;
|
|
60
|
+
}
|
|
61
|
+
/** One line per account, numbered so two accounts with the same name stay distinct in the menu. */
|
|
62
|
+
export function accountRows(overview, session) {
|
|
63
|
+
return overview.accounts.map((account, index) => {
|
|
64
|
+
const mark = account.isDefault ? '●' : '○';
|
|
65
|
+
const here = session?.accountId === account.id ? ' · this session' : '';
|
|
66
|
+
return { account, label: `${index + 1}. ${mark} ${account.label} · ${HEALTH[account.state.health] ?? HEALTH.unknown}${here}` };
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const limitLine = (limit) => `${limit.label}: ${limit.usedPercent ?? '?'}% used${limit.resetsAt ? `, resets ${resetIn(limit.resetsAt)}` : ''}`;
|
|
70
|
+
/** What `Details` shows for one account. */
|
|
71
|
+
export function accountDetails(account) {
|
|
72
|
+
const state = account.state;
|
|
73
|
+
const lines = [
|
|
74
|
+
account.label,
|
|
75
|
+
`Health: ${HEALTH[state.health] ?? HEALTH.unknown}`,
|
|
76
|
+
`Default for new sessions: ${account.isDefault ? 'yes' : 'no'}`,
|
|
77
|
+
`Signed in: ${state.signedIn === null ? 'not checked' : state.signedIn ? 'yes' : 'no'}`,
|
|
78
|
+
`Providers: ${state.piProviders.length ? state.piProviders.join(', ') : 'none'}`,
|
|
79
|
+
state.plan ? `Plan: ${state.plan}` : null,
|
|
80
|
+
state.identity ? `Identity: ${state.identity}` : null,
|
|
81
|
+
`Last checked: ${state.lastCheckedAt ? new Date(state.lastCheckedAt).toLocaleString() : 'never'}`,
|
|
82
|
+
state.lastError ? `Last error: ${state.lastError.message}${state.lastError.resetsAt ? ` (resets ${resetIn(state.lastError.resetsAt)})` : ''}` : null,
|
|
83
|
+
...state.limits.map(limitLine),
|
|
84
|
+
state.limits.length ? null : 'Usage limits: Pi providers do not report them.',
|
|
85
|
+
state.capabilities.length ? `Detected: ${state.capabilities.join(', ')}` : null
|
|
86
|
+
];
|
|
87
|
+
return lines.filter((line) => line !== null).join('\n');
|
|
88
|
+
}
|
|
89
|
+
/** The text shown while a sign-in waits for the person: a link, or a code to enter. */
|
|
90
|
+
function loginStep(step) {
|
|
91
|
+
if (step.type === 'auth_url' && typeof step.url === 'string')
|
|
92
|
+
return `Open this link to sign in:\n${step.url}${typeof step.instructions === 'string' ? `\n${step.instructions}` : ''}`;
|
|
93
|
+
if (step.type === 'device_code' && typeof step.userCode === 'string')
|
|
94
|
+
return `Enter the code ${step.userCode} at ${String(step.verificationUri ?? '')}`;
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
/** The whole `/accounts` conversation. Returns `'relaunch'` when the person chose to switch this session's account. */
|
|
98
|
+
export async function runAccountsMenu(ui, call, session) {
|
|
99
|
+
for (;;) {
|
|
100
|
+
const overview = await call('accounts.list');
|
|
101
|
+
const rows = accountRows(overview, session);
|
|
102
|
+
const options = [...rows.map((row) => row.label), ADD, POOLS, CHECK_ALL, DONE];
|
|
103
|
+
const picked = await ui.select('Accounts', options);
|
|
104
|
+
if (!picked || picked === DONE)
|
|
105
|
+
return;
|
|
106
|
+
if (picked === ADD) {
|
|
107
|
+
await addAccount(ui, call);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (picked === POOLS) {
|
|
111
|
+
await poolsMenu(ui, call);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (picked === CHECK_ALL) {
|
|
115
|
+
await attempt(ui, () => call('accounts.refresh'));
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const row = rows[options.indexOf(picked)];
|
|
119
|
+
if (!row)
|
|
120
|
+
continue;
|
|
121
|
+
if ((await accountMenu(ui, call, session, row.account.id)) === 'relaunch')
|
|
122
|
+
return 'relaunch';
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
export async function addAccount(ui, call) {
|
|
126
|
+
const label = await ui.input('Name for the new account', 'Work, Personal, …');
|
|
127
|
+
if (!label?.trim())
|
|
128
|
+
return;
|
|
129
|
+
if (await attempt(ui, () => call('accounts.create', { label: label.trim(), authKind: 'subscription' })))
|
|
130
|
+
ui.notify('Account added. Sign in to use it.', 'info');
|
|
131
|
+
}
|
|
132
|
+
/** What can be done with one account; `details` is left out where the screen already shows them. */
|
|
133
|
+
export function accountActions(account, isSession, details = true) {
|
|
134
|
+
return [
|
|
135
|
+
...(isSession ? [] : [USE_HERE]),
|
|
136
|
+
...(account.isDefault ? [] : [MAKE_DEFAULT]),
|
|
137
|
+
RENAME,
|
|
138
|
+
CHECK,
|
|
139
|
+
...(details ? [DETAILS] : []),
|
|
140
|
+
ACTIVITY,
|
|
141
|
+
SIGN_IN,
|
|
142
|
+
...(account.state.piProviders.length ? [REMOVE_PROVIDER] : []),
|
|
143
|
+
SIGN_OUT,
|
|
144
|
+
// The session's own account is in use, so it cannot be removed from inside the session.
|
|
145
|
+
...(isSession ? [] : [REMOVE])
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Runs one chosen action. `'relaunch'` means the session is switching to this account; `'gone'` that the
|
|
150
|
+
* account was removed. Anything the person declines or that fails leaves everything as it was.
|
|
151
|
+
*/
|
|
152
|
+
export async function runAccountAction(ui, call, overview, account, action) {
|
|
153
|
+
const accountId = account.id;
|
|
154
|
+
if (action === USE_HERE) {
|
|
155
|
+
if (!(await ui.confirm('Switch this session?', `This ends the terminal's Pi process and resumes the conversation on ${account.label}. Work in progress stops.`)))
|
|
156
|
+
return;
|
|
157
|
+
if (await attempt(ui, () => call('accounts.relaunch', { accountId }))) {
|
|
158
|
+
ui.notify(`Switching to ${account.label}.`, 'info');
|
|
159
|
+
return 'relaunch';
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else if (action === MAKE_DEFAULT) {
|
|
163
|
+
if (await attempt(ui, () => call('accounts.setDefault', { accountId })))
|
|
164
|
+
ui.notify(`${account.label} is the default for new sessions.`, 'info');
|
|
165
|
+
}
|
|
166
|
+
else if (action === RENAME) {
|
|
167
|
+
const label = await ui.input('New name', account.label);
|
|
168
|
+
if (label?.trim())
|
|
169
|
+
await attempt(ui, () => call('accounts.rename', { accountId, label: label.trim() }));
|
|
170
|
+
}
|
|
171
|
+
else if (action === CHECK) {
|
|
172
|
+
if (await attempt(ui, () => call('accounts.refresh', { accountId })))
|
|
173
|
+
ui.notify('Checked.', 'info');
|
|
174
|
+
}
|
|
175
|
+
else if (action === DETAILS) {
|
|
176
|
+
await ui.select(accountDetails(account), [BACK]);
|
|
177
|
+
}
|
|
178
|
+
else if (action === ACTIVITY) {
|
|
179
|
+
await showActivity(ui, call, accountId, account.label);
|
|
180
|
+
}
|
|
181
|
+
else if (action === SIGN_IN) {
|
|
182
|
+
await signIn(ui, call, account);
|
|
183
|
+
}
|
|
184
|
+
else if (action === REMOVE_PROVIDER) {
|
|
185
|
+
const provider = await ui.select('Remove which provider?', [...account.state.piProviders, BACK]);
|
|
186
|
+
if (!provider || provider === BACK)
|
|
187
|
+
return;
|
|
188
|
+
if (await ui.confirm(`Remove ${provider}?`, `The stored ${provider} sign-in for ${account.label} is deleted from this device.`))
|
|
189
|
+
await attempt(ui, () => call('accounts.removeProvider', { accountId, provider }));
|
|
190
|
+
}
|
|
191
|
+
else if (action === SIGN_OUT) {
|
|
192
|
+
if (await ui.confirm(`Sign out of ${account.label}?`, 'Stored sign-ins are deleted. The account stays, so you can sign in again.'))
|
|
193
|
+
await attempt(ui, () => call('accounts.signOut', { accountId }));
|
|
194
|
+
}
|
|
195
|
+
else if (action === REMOVE) {
|
|
196
|
+
const last = overview.accounts.length === 1;
|
|
197
|
+
const consequence = last
|
|
198
|
+
? 'This is the only account. New sessions will ask you to add one.'
|
|
199
|
+
: account.isDefault
|
|
200
|
+
? 'New sessions will use another account.'
|
|
201
|
+
: 'Sessions pinned to it will ask for another account next time they start.';
|
|
202
|
+
if (!(await ui.confirm(`Remove ${account.label}?`, `Its stored sign-in and its runtime folder are deleted. ${consequence}`)))
|
|
203
|
+
return;
|
|
204
|
+
if (await attempt(ui, () => call('accounts.remove', { accountId }))) {
|
|
205
|
+
ui.notify(`${account.label} was removed.`, 'info');
|
|
206
|
+
return 'gone';
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async function accountMenu(ui, call, session, accountId) {
|
|
211
|
+
const isSession = session.accountId === accountId;
|
|
212
|
+
for (;;) {
|
|
213
|
+
const overview = await call('accounts.list');
|
|
214
|
+
const account = overview.accounts.find((candidate) => candidate.id === accountId);
|
|
215
|
+
if (!account)
|
|
216
|
+
return;
|
|
217
|
+
const action = await ui.select(`${account.label} · ${HEALTH[account.state.health] ?? HEALTH.unknown}`, [...accountActions(account, isSession), BACK]);
|
|
218
|
+
if (!action || action === BACK)
|
|
219
|
+
return;
|
|
220
|
+
const outcome = await runAccountAction(ui, call, overview, account, action);
|
|
221
|
+
if (outcome === 'relaunch')
|
|
222
|
+
return 'relaunch';
|
|
223
|
+
if (outcome === 'gone')
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
async function showActivity(ui, call, accountId, label) {
|
|
228
|
+
const entries = await call('accounts.audit', { accountId, limit: 30 });
|
|
229
|
+
const lines = entries.map((entry) => `${new Date(entry.at).toLocaleString()} · ${entry.action} · ${entry.detail}`);
|
|
230
|
+
await ui.select(`${label}: activity\n${lines.join('\n') || 'Nothing has happened here yet.'}`, [BACK]);
|
|
231
|
+
}
|
|
232
|
+
async function signIn(ui, call, account) {
|
|
233
|
+
const providers = await call('accounts.providers');
|
|
234
|
+
if (!providers.length) {
|
|
235
|
+
ui.notify('No provider here can be signed in to.', 'warning');
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const labels = providers.map((provider, index) => `${index + 1}. ${provider.name}${account.state.piProviders.includes(provider.id) ? ' · signed in' : ''}`);
|
|
239
|
+
const pickedLabel = await ui.select(`Sign in ${account.label} to which provider?`, [...labels, BACK]);
|
|
240
|
+
const index = labels.indexOf(pickedLabel ?? '');
|
|
241
|
+
const provider = providers[index];
|
|
242
|
+
if (!provider)
|
|
243
|
+
return;
|
|
244
|
+
const methods = [...(provider.oauth ? [provider.oauthLabel ?? 'Sign in with the browser'] : []), ...(provider.apiKey ? ['Enter an API key'] : [])];
|
|
245
|
+
if (!methods.length) {
|
|
246
|
+
ui.notify(`${provider.name} has no sign-in from a terminal.`, 'warning');
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const method = methods.length === 1 ? methods[0] : await ui.select(`${provider.name}: how to sign in`, [...methods, BACK]);
|
|
250
|
+
if (!method || method === BACK)
|
|
251
|
+
return;
|
|
252
|
+
if (method === 'Enter an API key') {
|
|
253
|
+
const key = await ui.input(`API key for ${provider.name}`, 'Paste the key');
|
|
254
|
+
if (!key?.trim())
|
|
255
|
+
return;
|
|
256
|
+
if (await attempt(ui, () => call('accounts.setApiKey', { accountId: account.id, provider: provider.id, key: key.trim() })))
|
|
257
|
+
ui.notify(`Key saved for ${provider.name}.`, 'info');
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
await runLogin(ui, call, account.id, provider.id);
|
|
261
|
+
}
|
|
262
|
+
/** Starts a provider sign-in and follows it until it ends: shows the link or code, answers prompts, and stops on a timeout. */
|
|
263
|
+
async function runLogin(ui, call, accountId, provider) {
|
|
264
|
+
let loginId;
|
|
265
|
+
try {
|
|
266
|
+
loginId = (await call('accounts.loginStart', { accountId, provider })).loginId;
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
ui.notify(message(error), 'error');
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
return followLogin(ui, call, accountId, loginId);
|
|
273
|
+
}
|
|
274
|
+
async function followLogin(ui, call, accountId, loginId) {
|
|
275
|
+
const deadline = Date.now() + LOGIN_TIMEOUT_MS;
|
|
276
|
+
let shownRevision = -1;
|
|
277
|
+
for (;;) {
|
|
278
|
+
const snapshot = await call('accounts.loginStatus', { accountId });
|
|
279
|
+
// A newer sign-in on this account replaced ours; there is nothing left to follow.
|
|
280
|
+
if (!snapshot || snapshot.loginId !== loginId)
|
|
281
|
+
return;
|
|
282
|
+
if (snapshot.status !== 'running')
|
|
283
|
+
return reportLogin(ui, snapshot);
|
|
284
|
+
if (snapshot.prompt) {
|
|
285
|
+
await answerPrompt(ui, call, loginId, snapshot.prompt);
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const step = [...snapshot.events].reverse().map(loginStep).find((text) => text !== null);
|
|
289
|
+
if (step && snapshot.revision !== shownRevision) {
|
|
290
|
+
shownRevision = snapshot.revision;
|
|
291
|
+
const choice = await ui.select(`${step}\n\nFinish in your browser, then choose Check status.`, [CHECK_STATUS, CANCEL_SIGN_IN]);
|
|
292
|
+
if (choice === CANCEL_SIGN_IN) {
|
|
293
|
+
await call('accounts.loginCancel', { accountId, loginId });
|
|
294
|
+
ui.notify('Sign-in cancelled.', 'warning');
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (Date.now() > deadline) {
|
|
300
|
+
await call('accounts.loginCancel', { accountId, loginId });
|
|
301
|
+
ui.notify('Sign-in timed out and was cancelled.', 'error');
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_MS));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function reportLogin(ui, snapshot) {
|
|
308
|
+
if (snapshot.status === 'completed')
|
|
309
|
+
ui.notify('Signed in.', 'info');
|
|
310
|
+
else if (snapshot.status === 'cancelled')
|
|
311
|
+
ui.notify('Sign-in was cancelled.', 'warning');
|
|
312
|
+
else
|
|
313
|
+
ui.notify(snapshot.error ?? 'Sign-in failed.', 'error');
|
|
314
|
+
}
|
|
315
|
+
async function answerPrompt(ui, call, loginId, prompt) {
|
|
316
|
+
const promptId = String(prompt.promptId ?? '');
|
|
317
|
+
const detail = (prompt.prompt ?? {});
|
|
318
|
+
const text = detail.message ?? 'Sign-in needs an answer.';
|
|
319
|
+
// A secret is typed with `input` like any other answer: it is never echoed or logged here.
|
|
320
|
+
let value;
|
|
321
|
+
if (detail.type === 'select' && Array.isArray(detail.options)) {
|
|
322
|
+
if (detail.options.every((option) => typeof option === 'string')) {
|
|
323
|
+
value = await ui.select(text, detail.options);
|
|
324
|
+
}
|
|
325
|
+
else if (detail.options.every((option) => typeof option === 'object' && option !== null && 'id' in option && typeof option.id === 'string' && 'label' in option && typeof option.label === 'string')) {
|
|
326
|
+
const options = detail.options;
|
|
327
|
+
const selected = await ui.select(text, options.map((option) => option.label));
|
|
328
|
+
value = options.find((option) => option.label === selected)?.id;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
value = await ui.input(text, detail.placeholder ?? undefined);
|
|
333
|
+
}
|
|
334
|
+
await call('accounts.loginRespond', { loginId, promptId, value: value ?? null });
|
|
335
|
+
}
|
|
336
|
+
async function poolsMenu(ui, call) {
|
|
337
|
+
for (;;) {
|
|
338
|
+
const overview = await call('accounts.list');
|
|
339
|
+
const names = new Map(overview.accounts.map((account) => [account.id, account.label]));
|
|
340
|
+
const labels = overview.pools.map((pool, index) => `${index + 1}. ${pool.label} · ${pool.accountIds.map((id) => names.get(id) ?? 'removed account').join(' → ')}`);
|
|
341
|
+
const options = [NEW_POOL, ...labels, BACK];
|
|
342
|
+
const picked = await ui.select('Pools: new sessions use the first ready account in a pool, in this order', options);
|
|
343
|
+
if (!picked || picked === BACK)
|
|
344
|
+
return;
|
|
345
|
+
if (picked === NEW_POOL) {
|
|
346
|
+
await editPool(ui, call, overview, null);
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
const pool = overview.pools[options.indexOf(picked) - 1];
|
|
350
|
+
if (!pool)
|
|
351
|
+
continue;
|
|
352
|
+
const action = await ui.select(pool.label, [EDIT, DELETE, BACK]);
|
|
353
|
+
if (action === EDIT)
|
|
354
|
+
await editPool(ui, call, overview, pool);
|
|
355
|
+
else if (action === DELETE && (await ui.confirm(`Delete ${pool.label}?`, 'The accounts stay. Only the pool is removed.')))
|
|
356
|
+
await attempt(ui, () => call('accounts.removePool', { poolId: pool.id }));
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
export async function editPool(ui, call, overview, pool) {
|
|
360
|
+
const label = await ui.input('Pool name', pool?.label);
|
|
361
|
+
if (!label?.trim())
|
|
362
|
+
return;
|
|
363
|
+
const names = new Map(overview.accounts.map((account) => [account.id, account.label]));
|
|
364
|
+
const order = [...(pool?.accountIds ?? [])];
|
|
365
|
+
for (;;) {
|
|
366
|
+
const ordered = order.map((id, index) => `${index + 1}. ${names.get(id) ?? 'removed account'}`).join(' ');
|
|
367
|
+
const free = overview.accounts.filter((account) => !order.includes(account.id));
|
|
368
|
+
const addOptions = free.map((account) => `Add ${account.label}`);
|
|
369
|
+
const options = [...addOptions, ...(order.length ? [REMOVE_LAST, START_OVER] : []), SAVE_POOL, CANCEL];
|
|
370
|
+
const picked = await ui.select(`${label.trim()}: ${ordered || 'no accounts yet'}`, options);
|
|
371
|
+
if (!picked || picked === CANCEL)
|
|
372
|
+
return;
|
|
373
|
+
if (picked === SAVE_POOL) {
|
|
374
|
+
if (!order.length) {
|
|
375
|
+
ui.notify('A pool needs at least one account.', 'error');
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
if (await attempt(ui, () => call('accounts.savePool', { pool: { id: pool?.id, label: label.trim(), accountIds: order } })))
|
|
379
|
+
ui.notify('Pool saved.', 'info');
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (picked === START_OVER)
|
|
383
|
+
order.length = 0;
|
|
384
|
+
else if (picked === REMOVE_LAST)
|
|
385
|
+
order.pop();
|
|
386
|
+
else {
|
|
387
|
+
const account = free[addOptions.indexOf(picked)];
|
|
388
|
+
if (account)
|
|
389
|
+
order.push(account.id);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HarnessCall } from "../tools/definitions.js";
|
|
2
|
+
export declare const WIKI_COMMAND = "xagent-wiki";
|
|
3
|
+
export declare const APPS_COMMAND = "xagent-mcp";
|
|
4
|
+
export declare const USAGE = "Usage: xagent-wiki <command> [arguments]\n\n search <query> [--project SLUG] Search the Wiki's project notes\n read <path> Read one note, e.g. projects/<slug>/decisions\n list [project slug | library] List notes\n write <path> <text | -> Save a note (when this session may write the Wiki)\n skill [name] Load one of your skills, or list them\n history <query> [--scope all] [--since YYYY-MM-DD]\n Search earlier conversations and runs (also: recall)\n history-read <run id> Read one earlier run (also: recall-read)\n";
|
|
5
|
+
export declare const APPS_USAGE = "Usage: xagent-mcp <command>\n\n list The app and connected-app tools this session may use\n call <tool-name> '<JSON arguments>'\n Use one of them\n";
|
|
6
|
+
export type CliCommand = {
|
|
7
|
+
kind: 'call';
|
|
8
|
+
call: HarnessCall;
|
|
9
|
+
params: Record<string, unknown>;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'help';
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'stdin-write';
|
|
14
|
+
path: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function parseCli(argv: string[]): CliCommand;
|
|
17
|
+
/** Runs `xagent-wiki <argv>`; returns the exit code. */
|
|
18
|
+
export declare function runWikiCli(argv: string[]): Promise<number>;
|
|
19
|
+
/** Runs `xagent-mcp <argv>`; returns the exit code. */
|
|
20
|
+
export declare function runAppsCli(argv: string[]): Promise<number>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { connectionFromEnv, socketCall } from "./client.js";
|
|
2
|
+
export const WIKI_COMMAND = 'xagent-wiki';
|
|
3
|
+
export const APPS_COMMAND = 'xagent-mcp';
|
|
4
|
+
export const USAGE = `Usage: ${WIKI_COMMAND} <command> [arguments]
|
|
5
|
+
|
|
6
|
+
search <query> [--project SLUG] Search the Wiki's project notes
|
|
7
|
+
read <path> Read one note, e.g. projects/<slug>/decisions
|
|
8
|
+
list [project slug | library] List notes
|
|
9
|
+
write <path> <text | -> Save a note (when this session may write the Wiki)
|
|
10
|
+
skill [name] Load one of your skills, or list them
|
|
11
|
+
history <query> [--scope all] [--since YYYY-MM-DD]
|
|
12
|
+
Search earlier conversations and runs (also: recall)
|
|
13
|
+
history-read <run id> Read one earlier run (also: recall-read)
|
|
14
|
+
`;
|
|
15
|
+
export const APPS_USAGE = `Usage: ${APPS_COMMAND} <command>
|
|
16
|
+
|
|
17
|
+
list The app and connected-app tools this session may use
|
|
18
|
+
call <tool-name> '<JSON arguments>'
|
|
19
|
+
Use one of them
|
|
20
|
+
`;
|
|
21
|
+
function options(args) {
|
|
22
|
+
const positional = [];
|
|
23
|
+
const flags = {};
|
|
24
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
25
|
+
const arg = args[index];
|
|
26
|
+
if (arg.startsWith('--') && index + 1 < args.length) {
|
|
27
|
+
flags[arg.slice(2)] = args[index + 1];
|
|
28
|
+
index += 1;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
positional.push(arg);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return { positional, flags };
|
|
35
|
+
}
|
|
36
|
+
export function parseCli(argv) {
|
|
37
|
+
const [command, ...rest] = argv;
|
|
38
|
+
const { positional, flags } = options(rest);
|
|
39
|
+
const joined = positional.join(' ').trim();
|
|
40
|
+
switch (command) {
|
|
41
|
+
case 'search':
|
|
42
|
+
if (!joined)
|
|
43
|
+
return { kind: 'help' };
|
|
44
|
+
return { kind: 'call', call: 'wiki.search', params: { query: joined, ...(flags.project ? { project: flags.project } : {}) } };
|
|
45
|
+
case 'read':
|
|
46
|
+
if (!joined)
|
|
47
|
+
return { kind: 'help' };
|
|
48
|
+
return { kind: 'call', call: 'wiki.read', params: { path: joined } };
|
|
49
|
+
case 'list':
|
|
50
|
+
return { kind: 'call', call: 'wiki.list', params: joined ? { project: joined } : {} };
|
|
51
|
+
case 'write': {
|
|
52
|
+
const [path, ...words] = positional;
|
|
53
|
+
if (!path)
|
|
54
|
+
return { kind: 'help' };
|
|
55
|
+
if (words.join(' ').trim() === '-')
|
|
56
|
+
return { kind: 'stdin-write', path };
|
|
57
|
+
if (!words.length)
|
|
58
|
+
return { kind: 'help' };
|
|
59
|
+
return { kind: 'call', call: 'wiki.write', params: { path, text: words.join(' ') } };
|
|
60
|
+
}
|
|
61
|
+
case 'skill':
|
|
62
|
+
return { kind: 'call', call: 'skill.load', params: joined ? { name: joined } : {} };
|
|
63
|
+
case 'history':
|
|
64
|
+
case 'recall':
|
|
65
|
+
if (!joined)
|
|
66
|
+
return { kind: 'help' };
|
|
67
|
+
return { kind: 'call', call: 'recall.search', params: { query: joined, ...(flags.scope ? { scope: flags.scope } : {}), ...(flags.since ? { since: flags.since } : {}) } };
|
|
68
|
+
case 'history-read':
|
|
69
|
+
case 'recall-read':
|
|
70
|
+
if (!joined)
|
|
71
|
+
return { kind: 'help' };
|
|
72
|
+
return { kind: 'call', call: 'recall.read', params: { run: joined } };
|
|
73
|
+
default:
|
|
74
|
+
return { kind: 'help' };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function readStdin() {
|
|
78
|
+
let text = '';
|
|
79
|
+
for await (const chunk of process.stdin)
|
|
80
|
+
text += chunk.toString();
|
|
81
|
+
return text;
|
|
82
|
+
}
|
|
83
|
+
const errorText = (error) => (error instanceof Error ? error.message : String(error));
|
|
84
|
+
/** Runs `xagent-wiki <argv>`; returns the exit code. */
|
|
85
|
+
export async function runWikiCli(argv) {
|
|
86
|
+
const command = parseCli(argv);
|
|
87
|
+
if (command.kind === 'help') {
|
|
88
|
+
process.stdout.write(USAGE);
|
|
89
|
+
return argv.length ? 2 : 0;
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
const connection = connectionFromEnv();
|
|
93
|
+
const result = command.kind === 'stdin-write'
|
|
94
|
+
? await socketCall(connection, 'wiki.write', { path: command.path, text: await readStdin() })
|
|
95
|
+
: await socketCall(connection, command.call, command.params);
|
|
96
|
+
process.stdout.write(`${typeof result === 'string' ? result : JSON.stringify(result)}\n`);
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
process.stderr.write(`${errorText(error)}\n`);
|
|
101
|
+
return 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Runs `xagent-mcp <argv>`; returns the exit code. */
|
|
105
|
+
export async function runAppsCli(argv) {
|
|
106
|
+
const [command, name, args] = argv;
|
|
107
|
+
if (command !== 'list' && !(command === 'call' && name)) {
|
|
108
|
+
process.stdout.write(APPS_USAGE);
|
|
109
|
+
return argv.length ? 2 : 0;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const connection = connectionFromEnv();
|
|
113
|
+
const result = command === 'list' ? await socketCall(connection, 'mcp.list', {}, 90_000) : await socketCall(connection, 'mcp.call', { name, args: JSON.parse(args ?? '{}') }, 1_230_000);
|
|
114
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
115
|
+
return 0;
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
process.stderr.write(`${errorText(error)}\n`);
|
|
119
|
+
return 1;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const SOCKET_ENV = "XINGULAR_HARNESS_SOCKET";
|
|
2
|
+
export declare const TOKEN_ENV = "XINGULAR_HARNESS_TOKEN";
|
|
3
|
+
export declare class SocketError extends Error {
|
|
4
|
+
readonly code: string;
|
|
5
|
+
constructor(code: string, message: string);
|
|
6
|
+
}
|
|
7
|
+
export interface SocketConnection {
|
|
8
|
+
socket: string;
|
|
9
|
+
token: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function connectionFromEnv(env?: NodeJS.ProcessEnv): SocketConnection;
|
|
12
|
+
/** A memory, Wiki, recall, or connected-app call made on behalf of the session that owns the token. */
|
|
13
|
+
export declare function socketCall<T = unknown>(connection: SocketConnection, call: string, params?: Record<string, unknown>, timeoutMs?: number, control?: string): Promise<T>;
|
|
14
|
+
/** Telemetry and decisions from the native `pi` process. Approvals may wait on a person, so the default wait is long. */
|
|
15
|
+
export declare function terminalCall<T = Record<string, unknown>>(event: string, data?: Record<string, unknown>, timeoutMs?: number): Promise<T>;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// How a process outside the harness (the `pi` command's extension, the `xagent-wiki` and
|
|
2
|
+
// `xagent-mcp` commands) reaches it: newline-delimited JSON requests and replies on the session
|
|
3
|
+
// socket, authorized by the token the harness put in its environment. A reply leaves its connection
|
|
4
|
+
// open for the next request, so the terminal's frequent small calls do not each open a socket.
|
|
5
|
+
import { createConnection } from 'node:net';
|
|
6
|
+
export const SOCKET_ENV = 'XINGULAR_HARNESS_SOCKET';
|
|
7
|
+
export const TOKEN_ENV = 'XINGULAR_HARNESS_TOKEN';
|
|
8
|
+
export class SocketError extends Error {
|
|
9
|
+
code;
|
|
10
|
+
constructor(code, message) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.code = code;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function connectionFromEnv(env = process.env) {
|
|
16
|
+
const socket = env[SOCKET_ENV];
|
|
17
|
+
const token = env[TOKEN_ENV];
|
|
18
|
+
if (!socket || !token)
|
|
19
|
+
throw new SocketError('not_configured', `This command only works inside a terminal session the harness started (${SOCKET_ENV} and ${TOKEN_ENV} are not set).`);
|
|
20
|
+
return { socket, token };
|
|
21
|
+
}
|
|
22
|
+
const MAX_IDLE_PER_SOCKET = 4;
|
|
23
|
+
/** Open connections waiting for their next request, per socket path. Idle ones never keep a process alive. */
|
|
24
|
+
const idle = new Map();
|
|
25
|
+
function takeIdle(path) {
|
|
26
|
+
const entries = idle.get(path);
|
|
27
|
+
const entry = entries?.values().next().value;
|
|
28
|
+
if (!entries || !entry)
|
|
29
|
+
return undefined;
|
|
30
|
+
entries.delete(entry);
|
|
31
|
+
entry.stream.off('close', entry.drop);
|
|
32
|
+
entry.stream.off('error', entry.drop);
|
|
33
|
+
entry.stream.ref();
|
|
34
|
+
return entry.stream;
|
|
35
|
+
}
|
|
36
|
+
function putIdle(path, stream) {
|
|
37
|
+
const entries = idle.get(path) ?? new Set();
|
|
38
|
+
if (stream.destroyed || entries.size >= MAX_IDLE_PER_SOCKET) {
|
|
39
|
+
stream.end();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const entry = { stream, drop: () => { entries.delete(entry); stream.destroy(); } };
|
|
43
|
+
stream.once('close', entry.drop);
|
|
44
|
+
stream.on('error', entry.drop);
|
|
45
|
+
stream.unref();
|
|
46
|
+
entries.add(entry);
|
|
47
|
+
idle.set(path, entries);
|
|
48
|
+
}
|
|
49
|
+
function request(connection, body, what, timeoutMs) {
|
|
50
|
+
const reused = takeIdle(connection.socket);
|
|
51
|
+
return attempt(connection, body, what, timeoutMs, reused).catch((error) => {
|
|
52
|
+
// An idle connection the harness had already closed fails before any reply; one fresh retry.
|
|
53
|
+
if (reused && error instanceof StaleConnection)
|
|
54
|
+
return attempt(connection, body, what, timeoutMs, undefined);
|
|
55
|
+
throw error;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
class StaleConnection extends Error {
|
|
59
|
+
}
|
|
60
|
+
function attempt(connection, body, what, timeoutMs, reused) {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
const stream = reused ?? createConnection(connection.socket);
|
|
63
|
+
let buffer = '';
|
|
64
|
+
let replied = false;
|
|
65
|
+
let settled = false;
|
|
66
|
+
const send = () => stream.write(`${JSON.stringify({ token: connection.token, ...body, keep: true })}\n`);
|
|
67
|
+
const onData = (chunk) => {
|
|
68
|
+
replied = true;
|
|
69
|
+
buffer += chunk.toString('utf8');
|
|
70
|
+
const newline = buffer.indexOf('\n');
|
|
71
|
+
if (newline < 0)
|
|
72
|
+
return;
|
|
73
|
+
const rest = buffer.slice(newline + 1);
|
|
74
|
+
try {
|
|
75
|
+
const reply = JSON.parse(buffer.slice(0, newline));
|
|
76
|
+
if (reply.error) {
|
|
77
|
+
const error = typeof reply.error === 'string' ? { message: reply.error } : reply.error;
|
|
78
|
+
finish(() => reject(new SocketError(error.code ?? 'error', error.message ?? `${what} failed.`)), !rest);
|
|
79
|
+
}
|
|
80
|
+
else
|
|
81
|
+
finish(() => resolve(reply.result), !rest);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
finish(() => reject(new SocketError('invalid_reply', 'The harness sent an unreadable reply.')));
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const onError = (error) => finish(() => reject(reused && !replied ? new StaleConnection(error.message) : new SocketError('unavailable', `The harness is not reachable: ${error.message}.`)));
|
|
88
|
+
const onClose = () => finish(() => reject(reused && !replied ? new StaleConnection('closed') : new SocketError('unavailable', 'The harness closed the connection.')));
|
|
89
|
+
const finish = (action, keep = false) => {
|
|
90
|
+
if (settled)
|
|
91
|
+
return;
|
|
92
|
+
settled = true;
|
|
93
|
+
clearTimeout(timer);
|
|
94
|
+
stream.off('connect', send);
|
|
95
|
+
stream.off('data', onData);
|
|
96
|
+
stream.off('error', onError);
|
|
97
|
+
stream.off('close', onClose);
|
|
98
|
+
if (keep)
|
|
99
|
+
putIdle(connection.socket, stream);
|
|
100
|
+
else {
|
|
101
|
+
stream.on('error', () => { });
|
|
102
|
+
stream.end();
|
|
103
|
+
}
|
|
104
|
+
action();
|
|
105
|
+
};
|
|
106
|
+
const timer = setTimeout(() => {
|
|
107
|
+
stream.destroy();
|
|
108
|
+
finish(() => reject(new SocketError('timeout', `The harness did not answer ${what}.`)));
|
|
109
|
+
}, timeoutMs);
|
|
110
|
+
stream.on('data', onData);
|
|
111
|
+
stream.on('error', onError);
|
|
112
|
+
stream.on('close', onClose);
|
|
113
|
+
if (reused)
|
|
114
|
+
send();
|
|
115
|
+
else
|
|
116
|
+
stream.on('connect', send);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/** A memory, Wiki, recall, or connected-app call made on behalf of the session that owns the token. */
|
|
120
|
+
export function socketCall(connection, call, params = {}, timeoutMs = 120_000, control) {
|
|
121
|
+
return request(connection, { call, params, ...(control ? { control } : {}) }, call, timeoutMs);
|
|
122
|
+
}
|
|
123
|
+
/** Telemetry and decisions from the native `pi` process. Approvals may wait on a person, so the default wait is long. */
|
|
124
|
+
export function terminalCall(event, data = {}, timeoutMs = 600_000) {
|
|
125
|
+
return request(connectionFromEnv(), { event, data }, event, timeoutMs);
|
|
126
|
+
}
|