@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
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"passed": true,
|
|
3
|
-
"implementation": "production standalone CLI + real Pi SDK + loopback OpenAI SSE transport",
|
|
4
|
-
"cli": "/Users/tanny/Documents/Projects/Xingular/Xingular Agent/Harness/dist/cli.js",
|
|
5
|
-
"cliSha256": "2f5df943661a1e89440d0e81d59cd4a5bdb7aaf087a2a930e232b6743d5db093",
|
|
6
|
-
"verifierSha256": "6b7652f0093b12a37bd975fcffa7accc0f34d627022397b7e45923be270abc85",
|
|
7
|
-
"provider": "controlled loopback OpenAI-compatible streaming transport; no external model requests or user credentials",
|
|
8
|
-
"requestCount": 39,
|
|
9
|
-
"profiles": [
|
|
10
|
-
{
|
|
11
|
-
"size": "40x20",
|
|
12
|
-
"checks": [
|
|
13
|
-
"welcome and real configured model",
|
|
14
|
-
"actual settings tabs, section focus, keyboard search/control and Escape return",
|
|
15
|
-
"command autocomplete and real accounts selector",
|
|
16
|
-
"suspend/resume restores cooked/raw terminal modes and command input",
|
|
17
|
-
"Unicode, real streaming/thinking/read/bash/approval/question, expansion, resizing and scrolling",
|
|
18
|
-
"trusted plugin custom overlay, widget, status and disposal",
|
|
19
|
-
"grouped question progress and atomic choice/text answers through real registry",
|
|
20
|
-
"approval deny and Escape cancellation prevent actual tool execution",
|
|
21
|
-
"question Escape cancellation settles pending tools and interrupts run",
|
|
22
|
-
"new session, explicit scoped resume and session naming",
|
|
23
|
-
"actual stream cancellation and interrupted run record",
|
|
24
|
-
"explicit account switching, process restart and real run on newly pinned account",
|
|
25
|
-
"fatal asynchronous plugin failure exits 1 and restores terminal modes",
|
|
26
|
-
"plugin startup failure exits 1 and restores terminal modes"
|
|
27
|
-
],
|
|
28
|
-
"persistedRunCount": 7,
|
|
29
|
-
"exitCode": 0,
|
|
30
|
-
"termiosRestored": true,
|
|
31
|
-
"bracketedPasteDisabled": true,
|
|
32
|
-
"cursorShown": true,
|
|
33
|
-
"fatalCleanup": {
|
|
34
|
-
"exitCode": 1,
|
|
35
|
-
"termiosRestored": true,
|
|
36
|
-
"bracketedPasteDisabled": true,
|
|
37
|
-
"cursorShown": true
|
|
38
|
-
},
|
|
39
|
-
"startupCleanup": {
|
|
40
|
-
"exitCode": 1,
|
|
41
|
-
"termiosRestored": true,
|
|
42
|
-
"bracketedPasteDisabled": true,
|
|
43
|
-
"cursorShown": true
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
"size": "80x24",
|
|
48
|
-
"checks": [
|
|
49
|
-
"welcome and real configured model",
|
|
50
|
-
"actual settings tabs, section focus, keyboard search/control and Escape return",
|
|
51
|
-
"command autocomplete and real accounts selector",
|
|
52
|
-
"suspend/resume restores cooked/raw terminal modes and command input",
|
|
53
|
-
"Unicode, real streaming/thinking/read/bash/approval/question, expansion, resizing and scrolling",
|
|
54
|
-
"trusted plugin custom overlay, widget, status and disposal",
|
|
55
|
-
"grouped question progress and atomic choice/text answers through real registry",
|
|
56
|
-
"approval deny and Escape cancellation prevent actual tool execution",
|
|
57
|
-
"question Escape cancellation settles pending tools and interrupts run",
|
|
58
|
-
"new session, explicit scoped resume and session naming",
|
|
59
|
-
"actual stream cancellation and interrupted run record",
|
|
60
|
-
"explicit account switching, process restart and real run on newly pinned account",
|
|
61
|
-
"fatal asynchronous plugin failure exits 1 and restores terminal modes",
|
|
62
|
-
"plugin startup failure exits 1 and restores terminal modes"
|
|
63
|
-
],
|
|
64
|
-
"persistedRunCount": 7,
|
|
65
|
-
"exitCode": 0,
|
|
66
|
-
"termiosRestored": true,
|
|
67
|
-
"bracketedPasteDisabled": true,
|
|
68
|
-
"cursorShown": true,
|
|
69
|
-
"fatalCleanup": {
|
|
70
|
-
"exitCode": 1,
|
|
71
|
-
"termiosRestored": true,
|
|
72
|
-
"bracketedPasteDisabled": true,
|
|
73
|
-
"cursorShown": true
|
|
74
|
-
},
|
|
75
|
-
"startupCleanup": {
|
|
76
|
-
"exitCode": 1,
|
|
77
|
-
"termiosRestored": true,
|
|
78
|
-
"bracketedPasteDisabled": true,
|
|
79
|
-
"cursorShown": true
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
"size": "120x40",
|
|
84
|
-
"checks": [
|
|
85
|
-
"welcome and real configured model",
|
|
86
|
-
"actual settings tabs, section focus, keyboard search/control and Escape return",
|
|
87
|
-
"command autocomplete and real accounts selector",
|
|
88
|
-
"suspend/resume restores cooked/raw terminal modes and command input",
|
|
89
|
-
"Unicode, real streaming/thinking/read/bash/approval/question, expansion, resizing and scrolling",
|
|
90
|
-
"trusted plugin custom overlay, widget, status and disposal",
|
|
91
|
-
"grouped question progress and atomic choice/text answers through real registry",
|
|
92
|
-
"approval deny and Escape cancellation prevent actual tool execution",
|
|
93
|
-
"question Escape cancellation settles pending tools and interrupts run",
|
|
94
|
-
"new session, explicit scoped resume and session naming",
|
|
95
|
-
"actual stream cancellation and interrupted run record",
|
|
96
|
-
"explicit account switching, process restart and real run on newly pinned account",
|
|
97
|
-
"fatal asynchronous plugin failure exits 1 and restores terminal modes",
|
|
98
|
-
"plugin startup failure exits 1 and restores terminal modes"
|
|
99
|
-
],
|
|
100
|
-
"persistedRunCount": 7,
|
|
101
|
-
"exitCode": 0,
|
|
102
|
-
"termiosRestored": true,
|
|
103
|
-
"bracketedPasteDisabled": true,
|
|
104
|
-
"cursorShown": true,
|
|
105
|
-
"fatalCleanup": {
|
|
106
|
-
"exitCode": 1,
|
|
107
|
-
"termiosRestored": true,
|
|
108
|
-
"bracketedPasteDisabled": true,
|
|
109
|
-
"cursorShown": true
|
|
110
|
-
},
|
|
111
|
-
"startupCleanup": {
|
|
112
|
-
"exitCode": 1,
|
|
113
|
-
"termiosRestored": true,
|
|
114
|
-
"bracketedPasteDisabled": true,
|
|
115
|
-
"cursorShown": true
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
],
|
|
119
|
-
"captures": [
|
|
120
|
-
{
|
|
121
|
-
"file": "40x20-welcome.ansi.gz",
|
|
122
|
-
"kind": "actual PTY cumulative raw ANSI stream",
|
|
123
|
-
"columns": 40,
|
|
124
|
-
"rows": 20,
|
|
125
|
-
"rawBytes": 3085,
|
|
126
|
-
"rawSha256": "5ad9d6b7743730c00331865a713ade17a96d8a82254073eff8f7123f78ba0dfd",
|
|
127
|
-
"archiveBytes": 647,
|
|
128
|
-
"archiveSha256": "4e1d09e9e2b8ab6dd716c27342cb427e6d327b4517b2d5a1f9d6abe507ae6150"
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
"file": "40x20-settings-interaction.ansi.gz",
|
|
132
|
-
"kind": "actual PTY cumulative raw ANSI stream",
|
|
133
|
-
"columns": 40,
|
|
134
|
-
"rows": 20,
|
|
135
|
-
"rawBytes": 10579,
|
|
136
|
-
"rawSha256": "6e8cb197fd6444abd5b34500d14d36def96d945f6ffe75b70c107511a2fc6f92",
|
|
137
|
-
"archiveBytes": 1250,
|
|
138
|
-
"archiveSha256": "33227bf1354591624311e69f016862cea964aeb0d2cf6af0274bc8c49b6aa39c"
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
"file": "40x20-settings-keyboard.ansi.gz",
|
|
142
|
-
"kind": "actual PTY cumulative raw ANSI stream",
|
|
143
|
-
"columns": 40,
|
|
144
|
-
"rows": 20,
|
|
145
|
-
"rawBytes": 12779,
|
|
146
|
-
"rawSha256": "6071b778e316c86fdc6976ac024faffcf75221ba1043dfbd524e32cfcdff5e79",
|
|
147
|
-
"archiveBytes": 1387,
|
|
148
|
-
"archiveSha256": "722b555638b343520b7896527fb9287c71a2a9ba55e9a2f7c1ea573058db3a22"
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
"file": "80x24-approval-0.ansi.gz",
|
|
152
|
-
"kind": "actual PTY cumulative raw ANSI stream",
|
|
153
|
-
"columns": 80,
|
|
154
|
-
"rows": 24,
|
|
155
|
-
"rawBytes": 63082,
|
|
156
|
-
"rawSha256": "d182c53020bc8f9dae3b3f910ab78bbccae229b41fb927983b26b9352e13c7d1",
|
|
157
|
-
"archiveBytes": 5420,
|
|
158
|
-
"archiveSha256": "c00dd2d226ff8d0d8455311b903791dff1a4fc2b9fc4921ffc08837290570c99"
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
"file": "80x24-question.ansi.gz",
|
|
162
|
-
"kind": "actual PTY cumulative raw ANSI stream",
|
|
163
|
-
"columns": 80,
|
|
164
|
-
"rows": 24,
|
|
165
|
-
"rawBytes": 73627,
|
|
166
|
-
"rawSha256": "50c7fc4da8748ddcd2868007cf944e2294a9d55d035c60ad30cbe8820068682e",
|
|
167
|
-
"archiveBytes": 5834,
|
|
168
|
-
"archiveSha256": "d5371974389a6f99758d3d4e3bc820a69a48aa05fe344b3d0f4d3143cdd44298"
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
"file": "80x24-plugin-light.ansi.gz",
|
|
172
|
-
"kind": "actual PTY cumulative raw ANSI stream",
|
|
173
|
-
"columns": 120,
|
|
174
|
-
"rows": 30,
|
|
175
|
-
"rawBytes": 118891,
|
|
176
|
-
"rawSha256": "089d74da63cf763e1a06faf0264966d5b8d788518eda880ed91fb556fe844ab5",
|
|
177
|
-
"archiveBytes": 7618,
|
|
178
|
-
"archiveSha256": "55fe9f7742387b7e10692711daef697fe1f55af76486554c40290eb039c4a1fa"
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
"file": "80x24-question-batch.ansi.gz",
|
|
182
|
-
"kind": "actual PTY cumulative raw ANSI stream",
|
|
183
|
-
"columns": 120,
|
|
184
|
-
"rows": 30,
|
|
185
|
-
"rawBytes": 169983,
|
|
186
|
-
"rawSha256": "aee0560c4fb6bb878d187827ab8c40ceee81dda1022a98f663f8bb079e9bc2f6",
|
|
187
|
-
"archiveBytes": 8742,
|
|
188
|
-
"archiveSha256": "11ae7c4c7b3991014dbef17d126608104661c0776198e51e519ba35ad557dd35"
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
"file": "120x40-completed-transcript.ansi.gz",
|
|
192
|
-
"kind": "actual PTY cumulative raw ANSI stream",
|
|
193
|
-
"columns": 120,
|
|
194
|
-
"rows": 40,
|
|
195
|
-
"rawBytes": 140149,
|
|
196
|
-
"rawSha256": "abdbba2e7db4a94d25b82826539e1acbb9e59be7bb9d15167eeeee8f3838644d",
|
|
197
|
-
"archiveBytes": 7935,
|
|
198
|
-
"archiveSha256": "2f79e0637ed13a1fbf69d237eb2e644939fd4e3bb5cb257e5b6910fb19981012"
|
|
199
|
-
}
|
|
200
|
-
],
|
|
201
|
-
"limits": [
|
|
202
|
-
"The AgentSession, frontend, native tools, authorization and run writer are production code.",
|
|
203
|
-
"The controlled local transport supplies deterministic model responses and usage fixtures.",
|
|
204
|
-
"These functional checks do not establish external provider OAuth/service availability or visual equivalence to OMP.",
|
|
205
|
-
"Each compressed capture is a cumulative actual ANSI stream from PTY startup through the named interaction. Replay at its recorded dimensions."
|
|
206
|
-
]
|
|
207
|
-
}
|
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
import { existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, readlinkSync, rmdirSync, statSync, writeFileSync } from 'node:fs'
|
|
2
|
-
import { homedir, tmpdir } from 'node:os'
|
|
3
|
-
import { join } from 'node:path'
|
|
4
|
-
import { expect, test } from 'vitest'
|
|
5
|
-
import type { ModelRuntime } from '@earendil-works/pi-coding-agent'
|
|
6
|
-
|
|
7
|
-
import { Bus, type Notice } from '../core/bus'
|
|
8
|
-
import { Accounts, classifyMessage } from './accounts'
|
|
9
|
-
import { assertIsolated, configDir, ensureHome, ensureSharedDir, launchEnv, nativeConfig, sharedDir } from './env'
|
|
10
|
-
import { fileSecretStore, memorySecretStore } from './secrets'
|
|
11
|
-
import { addAccount, audit, deriveHealth, emptyState, loadRegistry, loadState, resolve, saveRegistry, updateState, type Issue } from './store'
|
|
12
|
-
|
|
13
|
-
const temp = () => mkdtempSync(join(tmpdir(), 'harness-accounts-'))
|
|
14
|
-
const ago = (ms: number): string => new Date(Date.now() - ms).toISOString()
|
|
15
|
-
const HOUR = 3_600_000
|
|
16
|
-
|
|
17
|
-
function service(dir = temp()) {
|
|
18
|
-
const secrets = memorySecretStore()
|
|
19
|
-
const notices: Notice[] = []
|
|
20
|
-
const bus = new Bus()
|
|
21
|
-
bus.on((notice) => void notices.push(notice))
|
|
22
|
-
return { dir, secrets, notices, accounts: new Accounts({ dir, secrets, bus }) }
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function loginService(login: (interaction: {
|
|
26
|
-
signal: AbortSignal
|
|
27
|
-
notify: (notification: Record<string, unknown>) => void
|
|
28
|
-
prompt: (prompt: { type: string; message: string; placeholder?: string; options?: unknown; signal?: AbortSignal }) => Promise<string>
|
|
29
|
-
}) => Promise<void>) {
|
|
30
|
-
const dir = temp()
|
|
31
|
-
const secrets = memorySecretStore()
|
|
32
|
-
const notices: Notice[] = []
|
|
33
|
-
const bus = new Bus()
|
|
34
|
-
bus.on((notice) => void notices.push(notice))
|
|
35
|
-
let loginOptions: { getDeviceId?: () => string } | undefined
|
|
36
|
-
let loginCalls = 0
|
|
37
|
-
const runtime = {
|
|
38
|
-
login: (_provider: string, _method: string, interaction: Parameters<typeof login>[0], options?: { getDeviceId?: () => string }) => {
|
|
39
|
-
loginCalls += 1
|
|
40
|
-
loginOptions = options
|
|
41
|
-
return login(interaction)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
class LoginAccounts extends Accounts {
|
|
45
|
-
override runtime(account: Parameters<Accounts['runtime']>[0]): Promise<ModelRuntime> {
|
|
46
|
-
void account
|
|
47
|
-
return Promise.resolve(runtime as unknown as ModelRuntime)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
const accounts = new LoginAccounts({ dir, secrets, bus })
|
|
51
|
-
const account = accounts.create('Login test', 'subscription').accounts[0]
|
|
52
|
-
return { accounts, account, notices, loginOptions: () => loginOptions, loginCalls: () => loginCalls }
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async function waitFor(predicate: () => boolean): Promise<void> {
|
|
56
|
-
for (let attempt = 0; attempt < 100; attempt++) {
|
|
57
|
-
if (predicate()) return
|
|
58
|
-
await new Promise((resolve) => setTimeout(resolve, 5))
|
|
59
|
-
}
|
|
60
|
-
throw new Error('Timed out waiting for the account operation.')
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
test('OpenAI login uses one persisted Harness installation device ID across accounts', async () => {
|
|
64
|
-
const { accounts, account, loginOptions, loginCalls } = loginService(async () => {})
|
|
65
|
-
const deviceId = await accounts.installationDeviceId()
|
|
66
|
-
const second = accounts.create('Second account', 'subscription').accounts.find((item) => item.id !== account.id)!
|
|
67
|
-
|
|
68
|
-
await accounts.loginStart(account.id, 'openai', 'oauth')
|
|
69
|
-
await waitFor(() => loginCalls() === 1)
|
|
70
|
-
expect(loginOptions()?.getDeviceId?.()).toBe(deviceId)
|
|
71
|
-
|
|
72
|
-
await accounts.loginStart(second.id, 'openai', 'oauth')
|
|
73
|
-
await waitFor(() => loginCalls() === 2)
|
|
74
|
-
expect(loginOptions()?.getDeviceId?.()).toBe(deviceId)
|
|
75
|
-
expect(JSON.parse(readFileSync(join(sharedDir(accounts.dir), 'settings.json'), 'utf8')).deviceId).toBe(deviceId)
|
|
76
|
-
expect(deviceId).toMatch(/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i)
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
test('device-code sign-in progress survives listener detachment and is available from status', async () => {
|
|
80
|
-
const { accounts, account, notices } = loginService((interaction) => new Promise<void>((_resolve, reject) => {
|
|
81
|
-
interaction.notify({ type: 'device_code', userCode: 'ABCD-EFGH', verificationUri: 'https://example.test/device' })
|
|
82
|
-
interaction.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true })
|
|
83
|
-
}))
|
|
84
|
-
|
|
85
|
-
const { loginId } = await accounts.loginStart(account.id, 'openai-codex', 'oauth')
|
|
86
|
-
await waitFor(() => (accounts.loginStatus(account.id)?.events.length ?? 0) > 0)
|
|
87
|
-
const detached = accounts.loginStatus(account.id)
|
|
88
|
-
expect(detached).toMatchObject({ loginId, status: 'running', events: [{ type: 'device_code', userCode: 'ABCD-EFGH' }] })
|
|
89
|
-
expect(notices.find((notice) => notice.type === 'accounts.loginEvent')).toMatchObject({ revision: 1, loginId })
|
|
90
|
-
|
|
91
|
-
// Asking again models a renderer returning to Accounts while the Harness stays alive.
|
|
92
|
-
expect(accounts.loginStatus(account.id)).toEqual(detached)
|
|
93
|
-
accounts.loginCancel(account.id, loginId)
|
|
94
|
-
await waitFor(() => accounts.loginStatus(account.id)?.status === 'cancelled')
|
|
95
|
-
const ended = accounts.loginStatus(account.id)
|
|
96
|
-
expect(ended).toMatchObject({ loginId, status: 'cancelled', events: [], prompt: null, success: false })
|
|
97
|
-
expect(JSON.stringify(ended)).not.toContain('ABCD-EFGH')
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
test('login status exposes the active prompt but never retains its response after completion', async () => {
|
|
101
|
-
const { accounts, account, notices } = loginService(async (interaction) => {
|
|
102
|
-
const value = await interaction.prompt({ type: 'secret', message: 'Enter the one-time value' })
|
|
103
|
-
expect(value).toBe('private-response')
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
const { loginId } = await accounts.loginStart(account.id, 'provider-with-prompt', 'oauth')
|
|
107
|
-
await waitFor(() => accounts.loginStatus(account.id)?.prompt !== null)
|
|
108
|
-
const waiting = accounts.loginStatus(account.id)
|
|
109
|
-
expect(waiting).toMatchObject({ loginId, status: 'running', prompt: { type: 'prompt', prompt: { type: 'secret' } } })
|
|
110
|
-
const promptId = String(waiting?.prompt?.promptId)
|
|
111
|
-
accounts.loginRespond(loginId, promptId, 'private-response')
|
|
112
|
-
await waitFor(() => accounts.loginStatus(account.id)?.status === 'completed')
|
|
113
|
-
const ended = accounts.loginStatus(account.id)
|
|
114
|
-
expect(ended).toMatchObject({ loginId, status: 'completed', success: true, events: [], prompt: null })
|
|
115
|
-
expect(JSON.stringify(ended)).not.toContain('private-response')
|
|
116
|
-
expect(notices.filter((notice) => notice.type === 'accounts.loginEvent' || notice.type === 'accounts.login').map((notice) => notice.revision)).toEqual([1, 2, 3])
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
test('health reflects sign-in, errors and limits', () => {
|
|
120
|
-
const state = { ...emptyState(), signedIn: true }
|
|
121
|
-
expect(deriveHealth(state)).toBe('ok')
|
|
122
|
-
state.limits.push({ id: '5h', label: '', usedPercent: 100, resetsAt: ago(-HOUR) })
|
|
123
|
-
expect(deriveHealth(state)).toBe('limited')
|
|
124
|
-
state.limits[0].resetsAt = ago(HOUR)
|
|
125
|
-
expect(deriveHealth(state)).toBe('ok')
|
|
126
|
-
state.lastError = { category: 'auth_expired', message: '', at: '', resetsAt: null }
|
|
127
|
-
expect(deriveHealth(state)).toBe('auth_expired')
|
|
128
|
-
state.lastError = null
|
|
129
|
-
state.signedIn = false
|
|
130
|
-
expect(deriveHealth(state)).toBe('signed_out')
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
test('a limit error without a reset time expires', () => {
|
|
134
|
-
const issue = (at: number, resetsAt: number | null): Issue => ({ category: 'quota', message: 'usage limit', at: ago(at), resetsAt: resetsAt === null ? null : ago(-resetsAt) })
|
|
135
|
-
const state = { ...emptyState(), signedIn: true }
|
|
136
|
-
expect(deriveHealth({ ...state, lastError: issue(5 * 60_000, null) })).toBe('limited')
|
|
137
|
-
expect(deriveHealth({ ...state, lastError: issue(96 * HOUR, null) })).toBe('ok')
|
|
138
|
-
expect(deriveHealth({ ...state, lastError: issue(96 * HOUR, HOUR) })).toBe('limited')
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
test('resolve prefers explicit, then pool, then default, and never skips silently', () => {
|
|
142
|
-
const dir = temp()
|
|
143
|
-
expect(() => resolve(dir)).toThrow('Add a Pi account first.')
|
|
144
|
-
const first = addAccount(dir, 'A', 'subscription')
|
|
145
|
-
const second = addAccount(dir, 'B', 'subscription')
|
|
146
|
-
expect(resolve(dir).id).toBe(first.id)
|
|
147
|
-
expect(resolve(dir, second.id).id).toBe(second.id)
|
|
148
|
-
// An account of a provider the harness no longer runs is kept in the file and never chosen.
|
|
149
|
-
const registry = loadRegistry(dir)
|
|
150
|
-
registry.accounts.push({ id: 'legacy', provider: 'codex', label: 'Old', authKind: 'subscription', createdAt: '' })
|
|
151
|
-
registry.pools.push({ id: 'p', provider: 'pi', label: 'Work', accountIds: [first.id, second.id] })
|
|
152
|
-
saveRegistry(dir, registry)
|
|
153
|
-
expect(() => resolve(dir, 'legacy')).toThrow('another provider')
|
|
154
|
-
expect(loadRegistry(dir).accounts).toHaveLength(3)
|
|
155
|
-
|
|
156
|
-
updateState(dir, first.id, (state) => void (state.signedIn = false))
|
|
157
|
-
expect(resolve(dir, null, 'p').id).toBe(second.id)
|
|
158
|
-
updateState(dir, second.id, (state) => void (state.lastError = { category: 'auth_expired', message: '', at: '', resetsAt: null }))
|
|
159
|
-
expect(() => resolve(dir, null, 'p')).toThrow('Every account in Work is unavailable.')
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
function walk(dir: string): string[] {
|
|
163
|
-
return readdirSync(dir).flatMap((name) => (statSync(join(dir, name)).isDirectory() ? walk(join(dir, name)) : [join(dir, name)]))
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
test('audit and state never hold secrets', async () => {
|
|
167
|
-
const { dir, accounts } = service()
|
|
168
|
-
audit(dir, 'a', 'login.failed', 'token sk-ant-api03-abcdefghijklmnopqrstuvwxyz0123456789 rejected')
|
|
169
|
-
const text = readFileSync(join(dir, 'audit.jsonl'), 'utf8')
|
|
170
|
-
expect(text).not.toContain('abcdefghijklmnop')
|
|
171
|
-
expect(text).toContain('[redacted]')
|
|
172
|
-
|
|
173
|
-
const account = addAccount(dir, 'A', 'apiKey')
|
|
174
|
-
await accounts.writeCredential(account.id, 'anthropic', { type: 'api_key', key: 'sk-secret-value' })
|
|
175
|
-
expect((await accounts.readCredential(account.id, 'anthropic'))?.key).toBe('sk-secret-value')
|
|
176
|
-
for (const file of walk(dir)) expect(readFileSync(file, 'utf8')).not.toContain('sk-secret-value')
|
|
177
|
-
expect((await accounts.listCredentials(account.id))[0].type).toBe('api_key')
|
|
178
|
-
await expect(accounts.writeCredential(account.id, '../x', null)).rejects.toThrow('Invalid provider name.')
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
test('a failed terminal credential launch can retry without a stale reference count', async () => {
|
|
182
|
-
const { dir, accounts } = service()
|
|
183
|
-
const account = addAccount(dir, 'A', 'apiKey')
|
|
184
|
-
ensureHome(dir, account)
|
|
185
|
-
await accounts.writeCredential(account.id, 'openai', { type: 'api_key', key: 'probe' })
|
|
186
|
-
const auth = join(configDir(dir, account), 'auth.json')
|
|
187
|
-
mkdirSync(auth)
|
|
188
|
-
await expect(accounts.terminalBegin(account)).rejects.toThrow()
|
|
189
|
-
rmdirSync(auth)
|
|
190
|
-
await accounts.terminalBegin(account)
|
|
191
|
-
expect(statSync(auth).isFile()).toBe(true)
|
|
192
|
-
expect(statSync(auth).mode & 0o777).toBe(0o600)
|
|
193
|
-
await accounts.terminalEnd(account)
|
|
194
|
-
expect(existsSync(auth)).toBe(false)
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
test('a terminal round-trips credentials through auth.json', async () => {
|
|
198
|
-
const { dir, accounts } = service()
|
|
199
|
-
const account = addAccount(dir, 'A', 'apiKey')
|
|
200
|
-
ensureHome(dir, account)
|
|
201
|
-
await accounts.writeCredential(account.id, 'openai', { type: 'api_key', key: 'k1' })
|
|
202
|
-
await accounts.terminalBegin(account)
|
|
203
|
-
const auth = join(configDir(dir, account), 'auth.json')
|
|
204
|
-
expect(readFileSync(auth, 'utf8')).toContain('k1')
|
|
205
|
-
writeFileSync(auth, JSON.stringify({ anthropic: { type: 'oauth', access: 'a', refresh: 'r', expires: 1 } }))
|
|
206
|
-
await accounts.terminalEnd(account)
|
|
207
|
-
expect(existsSync(auth)).toBe(false)
|
|
208
|
-
expect(loadState(dir, account.id).piProviders).toEqual(['anthropic'])
|
|
209
|
-
expect((await accounts.readCredential(account.id, 'anthropic'))?.refresh).toBe('r')
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
test('creating, renaming and removing an account is audited and announced', async () => {
|
|
213
|
-
const { dir, accounts, secrets, notices } = service()
|
|
214
|
-
const created = accounts.create(' Work ', 'apiKey').accounts[0]
|
|
215
|
-
expect([created.label, created.isDefault, created.state.health]).toEqual(['Work', true, 'unknown'])
|
|
216
|
-
expect(lstatSync(join(configDir(dir, created), 'skills')).isSymbolicLink()).toBe(true)
|
|
217
|
-
await accounts.writeCredential(created.id, 'openai', { type: 'api_key', key: 'k' })
|
|
218
|
-
expect(() => accounts.create('', 'apiKey')).toThrow()
|
|
219
|
-
expect(() => accounts.create('x', 'password')).toThrow('Unknown sign-in type.')
|
|
220
|
-
accounts.rename(created.id, 'Home')
|
|
221
|
-
await accounts.remove(created.id)
|
|
222
|
-
expect(accounts.overview().accounts).toEqual([])
|
|
223
|
-
expect(existsSync(join(dir, created.id))).toBe(false)
|
|
224
|
-
expect(secrets.values.size).toBe(0)
|
|
225
|
-
expect(notices.filter((notice) => notice.type === 'accounts.changed').length).toBeGreaterThanOrEqual(3)
|
|
226
|
-
expect(readFileSync(join(dir, 'audit.jsonl'), 'utf8')).toContain('account.deleted')
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
test('run events move an account between healthy and limited', () => {
|
|
230
|
-
const { dir, accounts, notices } = service()
|
|
231
|
-
const account = addAccount(dir, 'A', 'subscription')
|
|
232
|
-
const event = (type: string, payload: unknown) => ({ id: 'e', runId: 'r', sessionId: 's', sequence: 0, timestamp: '', type: type as never, payload })
|
|
233
|
-
accounts.onRunEvent(event('account.status', { accountId: account.id, category: 'quota', message: 'usage limit reached for sk-abcdefghijklmnopqrstuvwxyz012345' }), null)
|
|
234
|
-
const limited = loadState(dir, account.id)
|
|
235
|
-
expect(limited.health).toBe('limited')
|
|
236
|
-
expect(limited.lastError?.message).toContain('[redacted]')
|
|
237
|
-
expect(notices.at(-1)).toMatchObject({ type: 'accounts.changed', health: 'limited', previous: 'unknown' })
|
|
238
|
-
// A finished run proves the sign-in works, but a limit error stays until it resets.
|
|
239
|
-
accounts.onRunEvent(event('completed', {}), { accountId: account.id } as never)
|
|
240
|
-
expect(loadState(dir, account.id)).toMatchObject({ signedIn: true, health: 'limited' })
|
|
241
|
-
accounts.onRunEvent(event('account.status', { accountId: account.id, category: 'auth_expired', message: '401' }), null)
|
|
242
|
-
expect(loadState(dir, account.id)).toMatchObject({ signedIn: false, health: 'auth_expired' })
|
|
243
|
-
accounts.onRunEvent(event('completed', {}), { accountId: account.id } as never)
|
|
244
|
-
expect(loadState(dir, account.id).health).toBe('ok')
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
test('provider errors are classified', () => {
|
|
248
|
-
expect(classifyMessage('401 Unauthorized')).toBe('auth_expired')
|
|
249
|
-
expect(classifyMessage('You have hit your usage limit')).toBe('quota')
|
|
250
|
-
expect(classifyMessage('429 Too Many Requests')).toBe('rate_limited')
|
|
251
|
-
expect(classifyMessage('fetch failed')).toBe('network')
|
|
252
|
-
expect(classifyMessage('the model said no')).toBeNull()
|
|
253
|
-
})
|
|
254
|
-
|
|
255
|
-
test('a rejected OAuth refresh requests reauthentication and keeps the credential', async () => {
|
|
256
|
-
const { dir, accounts } = service()
|
|
257
|
-
const account = accounts.create('OpenAI', 'subscription').accounts[0]
|
|
258
|
-
await accounts.writeCredential(account.id, 'openai', { type: 'oauth', access: 'old-access', refresh: 'old-refresh', expires: 0 })
|
|
259
|
-
accounts.runtime = async () => ({
|
|
260
|
-
listCredentials: async () => [{ providerId: 'openai', type: 'oauth' }],
|
|
261
|
-
getAvailable: async () => { throw new Error('OAuth refresh failed for openai: OpenAI OAuth token request failed (400): {"error":"invalid_grant"}') }
|
|
262
|
-
} as unknown as ModelRuntime)
|
|
263
|
-
|
|
264
|
-
await accounts.refreshOne(account)
|
|
265
|
-
|
|
266
|
-
expect(loadState(dir, account.id)).toMatchObject({ health: 'auth_expired', lastError: { category: 'auth_expired' } })
|
|
267
|
-
expect(await accounts.readCredential(account.id, 'openai')).toMatchObject({ refresh: 'old-refresh' })
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
test('native config lists what is shared and what exists', () => {
|
|
271
|
-
const dir = temp()
|
|
272
|
-
const before = nativeConfig(dir)
|
|
273
|
-
expect(before.entries.some((entry) => entry.name === 'extensions' && entry.directory)).toBe(true)
|
|
274
|
-
expect(before.entries.every((entry) => !entry.present)).toBe(true)
|
|
275
|
-
expect(existsSync(before.path)).toBe(false)
|
|
276
|
-
writeFileSync(join(ensureSharedDir(dir), 'AGENTS.md'), 'x')
|
|
277
|
-
expect(nativeConfig(dir).entries.find((entry) => entry.name === 'AGENTS.md')?.present).toBe(true)
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
test('launch env isolates and strips inherited credentials', () => {
|
|
281
|
-
const dir = temp()
|
|
282
|
-
const env = launchEnv(dir, { id: 'acc1' }, { SOMEVENDOR_API_KEY: 'leak', PATH: '/bin' })
|
|
283
|
-
expect(env.PI_CODING_AGENT_DIR?.startsWith(dir)).toBe(true)
|
|
284
|
-
expect(env).toMatchObject({ SOMEVENDOR_API_KEY: null, CLAUDE_CONFIG_DIR: null, CODEX_HOME: null })
|
|
285
|
-
expect('PATH' in env).toBe(false)
|
|
286
|
-
})
|
|
287
|
-
|
|
288
|
-
test('accounts share config but not credentials', () => {
|
|
289
|
-
const dir = temp()
|
|
290
|
-
const first = ensureHome(dir, { id: 'acc1' })
|
|
291
|
-
const second = ensureHome(dir, { id: 'acc2' })
|
|
292
|
-
writeFileSync(join(first, 'settings.json'), '{"theme":"dark"}\n')
|
|
293
|
-
mkdirSync(join(first, 'skills/review'), { recursive: true })
|
|
294
|
-
writeFileSync(join(first, 'auth.json'), '{}')
|
|
295
|
-
expect(readFileSync(join(second, 'settings.json'), 'utf8')).toBe('{"theme":"dark"}\n')
|
|
296
|
-
expect(statSync(join(second, 'skills/review')).isDirectory()).toBe(true)
|
|
297
|
-
expect(existsSync(join(second, 'auth.json'))).toBe(false)
|
|
298
|
-
expect(lstatSync(join(first, 'auth.json')).isSymbolicLink()).toBe(false)
|
|
299
|
-
expect(readlinkSync(join(first, 'skills'))).toBe(join(sharedDir(dir), 'skills'))
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
test('existing account config moves into the shared folder, newest wins', async () => {
|
|
303
|
-
const dir = temp()
|
|
304
|
-
for (const id of ['acc1', 'acc2']) {
|
|
305
|
-
mkdirSync(configDir(dir, { id }), { recursive: true })
|
|
306
|
-
writeFileSync(join(configDir(dir, { id }), 'settings.json'), `{"from":"${id}"}`)
|
|
307
|
-
await new Promise((resolve) => setTimeout(resolve, 20))
|
|
308
|
-
}
|
|
309
|
-
ensureHome(dir, { id: 'acc1' })
|
|
310
|
-
// acc2's settings are newer than the shared copy acc1 just moved in, so they win.
|
|
311
|
-
const second = ensureHome(dir, { id: 'acc2' })
|
|
312
|
-
expect(readFileSync(join(sharedDir(dir), 'settings.json'), 'utf8')).toBe('{"from":"acc2"}')
|
|
313
|
-
expect(readdirSync(sharedDir(dir)).some((name) => name.startsWith('settings.json.xagent-backup-'))).toBe(true)
|
|
314
|
-
expect(lstatSync(join(second, 'settings.json')).isSymbolicLink()).toBe(true)
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
test('refuses default tool directories', () => {
|
|
318
|
-
const dir = temp()
|
|
319
|
-
for (const name of ['.codex', '.claude', '.pi/agent']) expect(() => assertIsolated(dir, join(homedir(), name))).toThrow()
|
|
320
|
-
expect(() => assertIsolated(dir, '/tmp/elsewhere')).toThrow()
|
|
321
|
-
expect(() => assertIsolated(dir, join(dir, 'a/home/pi'))).not.toThrow()
|
|
322
|
-
})
|
|
323
|
-
|
|
324
|
-
test('a file secret store keeps secrets owner-only', async () => {
|
|
325
|
-
const path = join(temp(), 'nested/secrets.json')
|
|
326
|
-
const secrets = fileSecretStore(path)
|
|
327
|
-
expect(await secrets.get('a/b')).toBeNull()
|
|
328
|
-
await secrets.set('a/b', 'value')
|
|
329
|
-
expect(await secrets.get('a/b')).toBe('value')
|
|
330
|
-
expect(statSync(path).mode & 0o777).toBe(0o600)
|
|
331
|
-
await secrets.delete('a/b')
|
|
332
|
-
expect(await secrets.get('a/b')).toBeNull()
|
|
333
|
-
})
|