@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
package/src/accounts/env.test.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { existsSync, lstatSync, linkSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, readlinkSync, symlinkSync, writeFileSync } from 'node:fs'
|
|
2
|
-
import { tmpdir } from 'node:os'
|
|
3
|
-
import { join } from 'node:path'
|
|
4
|
-
import { expect, test } from 'vitest'
|
|
5
|
-
|
|
6
|
-
import { configDir, ensureSharedDir, linkSharedEntries, sharedDir, type EntryLinker } from './env'
|
|
7
|
-
|
|
8
|
-
const temp = () => mkdtempSync(join(tmpdir(), 'harness-env-'))
|
|
9
|
-
const refused = (code = 'EPERM') => Object.assign(new Error(`${code}: operation not permitted, symlink`), { code })
|
|
10
|
-
const backups = (folder: string) => readdirSync(folder).filter((name) => name.includes('xagent-backup') || name.includes('agentx-backup'))
|
|
11
|
-
|
|
12
|
-
// A Windows account without the symlink privilege: file symlinks are refused, junctions and hard links work.
|
|
13
|
-
const windowsLike: EntryLinker = {
|
|
14
|
-
symlink: (target, path, isDir) => {
|
|
15
|
-
if (!isDir) throw refused()
|
|
16
|
-
symlinkSync(target, path)
|
|
17
|
-
},
|
|
18
|
-
hardLink: (target, path) => linkSync(target, path)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const refusesAll: EntryLinker = {
|
|
22
|
-
symlink: () => {
|
|
23
|
-
throw refused()
|
|
24
|
-
},
|
|
25
|
-
hardLink: () => {
|
|
26
|
-
throw refused()
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
test('without the symlink privilege, files are hard-linked and folders are junctioned', () => {
|
|
31
|
-
const dir = temp()
|
|
32
|
-
const home = configDir(dir, { id: 'acc1' })
|
|
33
|
-
mkdirSync(home, { recursive: true })
|
|
34
|
-
writeFileSync(join(home, 'settings.json'), '{"theme":"dark"}')
|
|
35
|
-
|
|
36
|
-
const first = linkSharedEntries(dir, { id: 'acc1' }, windowsLike)
|
|
37
|
-
const shared = join(sharedDir(dir), 'settings.json')
|
|
38
|
-
expect(first.entries.find((entry) => entry.name === 'settings.json')).toEqual({ name: 'settings.json', state: 'linked' })
|
|
39
|
-
expect(lstatSync(join(home, 'settings.json')).ino).toBe(lstatSync(shared).ino)
|
|
40
|
-
expect(lstatSync(join(home, 'settings.json')).isSymbolicLink()).toBe(false)
|
|
41
|
-
expect(lstatSync(join(home, 'skills')).isSymbolicLink()).toBe(true)
|
|
42
|
-
|
|
43
|
-
// Entries with no shared copy yet cannot be hard-linked, so they stay the account's own.
|
|
44
|
-
expect(first.entries.find((entry) => entry.name === 'AGENTS.md')).toMatchObject({ state: 'unshared' })
|
|
45
|
-
|
|
46
|
-
// A second launch finds the links in place and moves nothing aside.
|
|
47
|
-
const second = linkSharedEntries(dir, { id: 'acc1' }, windowsLike)
|
|
48
|
-
expect(second.entries.find((entry) => entry.name === 'settings.json')?.state).toBe('linked')
|
|
49
|
-
expect(second.entries.find((entry) => entry.name === 'skills')?.state).toBe('linked')
|
|
50
|
-
expect(backups(home)).toEqual([])
|
|
51
|
-
expect(backups(sharedDir(dir))).toEqual([])
|
|
52
|
-
expect(readFileSync(join(home, 'settings.json'), 'utf8')).toBe('{"theme":"dark"}')
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
test('when links are refused, the account keeps its own settings', () => {
|
|
56
|
-
const dir = temp()
|
|
57
|
-
const home = configDir(dir, { id: 'acc1' })
|
|
58
|
-
mkdirSync(home, { recursive: true })
|
|
59
|
-
writeFileSync(join(home, 'settings.json'), '{"mine":true}')
|
|
60
|
-
|
|
61
|
-
const { entries } = linkSharedEntries(dir, { id: 'acc1' }, refusesAll)
|
|
62
|
-
expect(entries.find((entry) => entry.name === 'settings.json')).toEqual({ name: 'settings.json', state: 'unshared', reason: 'EPERM' })
|
|
63
|
-
expect(readFileSync(join(home, 'settings.json'), 'utf8')).toBe('{"mine":true}')
|
|
64
|
-
expect(existsSync(join(sharedDir(dir), 'settings.json'))).toBe(false)
|
|
65
|
-
expect(backups(home)).toEqual([])
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
test('when links are refused, a shared file the account lacks is copied in and stays put', () => {
|
|
69
|
-
const dir = temp()
|
|
70
|
-
writeFileSync(join(ensureSharedDir(dir), 'settings.json'), '{"shared":true}')
|
|
71
|
-
const home = configDir(dir, { id: 'acc2' })
|
|
72
|
-
|
|
73
|
-
const first = linkSharedEntries(dir, { id: 'acc2' }, refusesAll)
|
|
74
|
-
expect(readFileSync(join(home, 'settings.json'), 'utf8')).toBe('{"shared":true}')
|
|
75
|
-
expect(first.entries.find((entry) => entry.name === 'settings.json')?.state).toBe('unshared')
|
|
76
|
-
|
|
77
|
-
const second = linkSharedEntries(dir, { id: 'acc2' }, refusesAll)
|
|
78
|
-
expect(second.entries.find((entry) => entry.name === 'settings.json')?.state).toBe('unshared')
|
|
79
|
-
expect(readFileSync(join(home, 'settings.json'), 'utf8')).toBe('{"shared":true}')
|
|
80
|
-
expect(backups(home)).toEqual([])
|
|
81
|
-
expect(backups(sharedDir(dir))).toEqual([])
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
test('a refused link leaves the account\'s existing link as it was', () => {
|
|
85
|
-
const dir = temp()
|
|
86
|
-
const home = configDir(dir, { id: 'acc3' })
|
|
87
|
-
mkdirSync(home, { recursive: true })
|
|
88
|
-
const elsewhere = join(temp(), 'skills')
|
|
89
|
-
mkdirSync(elsewhere)
|
|
90
|
-
symlinkSync(elsewhere, join(home, 'skills'))
|
|
91
|
-
|
|
92
|
-
const { entries } = linkSharedEntries(dir, { id: 'acc3' }, refusesAll)
|
|
93
|
-
expect(entries.find((entry) => entry.name === 'skills')?.state).toBe('unshared')
|
|
94
|
-
expect(readlinkSync(join(home, 'skills'))).toBe(elsewhere)
|
|
95
|
-
})
|
package/src/accounts/env.ts
DELETED
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
// Isolated launch environments. Every Pi session the harness starts gets its account's own
|
|
2
|
-
// agent folder (`PI_CODING_AGENT_DIR`) under the state directory, and inherited credential
|
|
3
|
-
// variables are removed. A launch that would fall back to `~/.pi` is refused.
|
|
4
|
-
//
|
|
5
|
-
// Settings, skills, prompts, and instructions are shared by every account: the account's agent
|
|
6
|
-
// folder links those entries to `_shared/pi/`. Where the system refuses a link (Windows without
|
|
7
|
-
// the symlink privilege), the entry stays the account's own, and a shared file is copied in so
|
|
8
|
-
// its settings still load. Credentials, sessions, and history stay in the account's own folder.
|
|
9
|
-
import { chmodSync, copyFileSync, linkSync, lstatSync, mkdirSync, readlinkSync, renameSync, rmdirSync, statSync, symlinkSync, unlinkSync, utimesSync } from 'node:fs'
|
|
10
|
-
import { homedir } from 'node:os'
|
|
11
|
-
import { basename, dirname, join, resolve, sep } from 'node:path'
|
|
12
|
-
|
|
13
|
-
import { HarnessError } from '../core/errors'
|
|
14
|
-
import type { Account } from './store'
|
|
15
|
-
|
|
16
|
-
// Config-directory variables the harness always sets itself, including those of other tools so
|
|
17
|
-
// a session can never inherit them.
|
|
18
|
-
const DIR_VARS = ['CODEX_HOME', 'CLAUDE_CONFIG_DIR', 'PI_CODING_AGENT_DIR']
|
|
19
|
-
|
|
20
|
-
/** Inherited variables that carry credentials; they would bypass the account's own sign-in. */
|
|
21
|
-
export function isCredentialVar(name: string): boolean {
|
|
22
|
-
const upper = name.toUpperCase()
|
|
23
|
-
return DIR_VARS.includes(upper) || ['_API_KEY', '_AUTH_TOKEN', '_OAUTH_TOKEN', '_ACCESS_TOKEN'].some((suffix) => upper.endsWith(suffix))
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Names of inherited variables to remove from a session's process. */
|
|
27
|
-
export function inheritedCredentialVars(env: NodeJS.ProcessEnv = process.env): string[] {
|
|
28
|
-
const names = Object.keys(env).filter(isCredentialVar)
|
|
29
|
-
for (const name of DIR_VARS) if (!names.includes(name)) names.push(name)
|
|
30
|
-
return names
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Makes this process safe to run Pi sessions in: credentials come only from an account's own
|
|
35
|
-
* store, so inherited credential variables are dropped, and Pi's fallback agent folder is an
|
|
36
|
-
* empty one under the state directory rather than `~/.pi`.
|
|
37
|
-
*/
|
|
38
|
-
export function isolateProcess(accountsDir: string, env: NodeJS.ProcessEnv = process.env): void {
|
|
39
|
-
for (const name of inheritedCredentialVars(env)) delete env[name]
|
|
40
|
-
const fallback = join(accountsDir, '.sidecar', 'pi')
|
|
41
|
-
mkdirSync(fallback, { recursive: true })
|
|
42
|
-
env.PI_CODING_AGENT_DIR = fallback
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const homeDir = (accountsDir: string, accountId: string): string => join(accountsDir, accountId, 'home')
|
|
46
|
-
/** Pi's agent folder for this account. */
|
|
47
|
-
export const configDir = (accountsDir: string, account: Pick<Account, 'id'>): string => join(homeDir(accountsDir, account.id), 'pi')
|
|
48
|
-
/** The agent-folder entries every account shares. */
|
|
49
|
-
export const sharedDir = (accountsDir: string): string => join(accountsDir, '_shared', 'pi')
|
|
50
|
-
|
|
51
|
-
function makePrivate(path: string): void {
|
|
52
|
-
mkdirSync(path, { recursive: true })
|
|
53
|
-
chmodSync(path, 0o700)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Entries every account shares, and whether each is a folder. Credentials (`auth.json`),
|
|
57
|
-
// sessions, and history are never listed.
|
|
58
|
-
const SHARED_ENTRIES: readonly (readonly [string, boolean])[] = [
|
|
59
|
-
['settings.json', false],
|
|
60
|
-
['models.json', false],
|
|
61
|
-
['AGENTS.md', false],
|
|
62
|
-
['SYSTEM.md', false],
|
|
63
|
-
['skills', true],
|
|
64
|
-
['prompts', true],
|
|
65
|
-
['extensions', true],
|
|
66
|
-
['themes', true],
|
|
67
|
-
// Where Pi keeps installed packages: one install serves every account.
|
|
68
|
-
['npm', true],
|
|
69
|
-
['git', true]
|
|
70
|
-
]
|
|
71
|
-
|
|
72
|
-
export interface NativeConfig {
|
|
73
|
-
provider: string
|
|
74
|
-
path: string
|
|
75
|
-
entries: { name: string; directory: boolean; present: boolean }[]
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const present = (path: string): boolean => {
|
|
79
|
-
try {
|
|
80
|
-
lstatSync(path)
|
|
81
|
-
return true
|
|
82
|
-
} catch {
|
|
83
|
-
return false
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/** What the accounts share, and which of it exists yet. Reads only; nothing is created. */
|
|
88
|
-
export function nativeConfig(accountsDir: string): NativeConfig {
|
|
89
|
-
const shared = sharedDir(accountsDir)
|
|
90
|
-
return { provider: 'pi', path: shared, entries: SHARED_ENTRIES.map(([name, directory]) => ({ name, directory, present: present(join(shared, name)) })) }
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/** The shared folder, created private if no account has linked it yet. */
|
|
94
|
-
export function ensureSharedDir(accountsDir: string): string {
|
|
95
|
-
const shared = sharedDir(accountsDir)
|
|
96
|
-
makePrivate(shared)
|
|
97
|
-
return shared
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const modified = (path: string): number => {
|
|
101
|
-
try {
|
|
102
|
-
return lstatSync(path).mtimeMs
|
|
103
|
-
} catch {
|
|
104
|
-
return -1
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/** Moves a real file or folder aside so the shared link can take its place; returns where it went. */
|
|
109
|
-
function backUp(path: string): string {
|
|
110
|
-
const backup = join(dirname(path), `${basename(path)}.xagent-backup-${Math.floor(Date.now() / 1000)}`)
|
|
111
|
-
renameSync(path, backup)
|
|
112
|
-
return backup
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* How one shared entry is linked into an account folder. Windows refuses a symbolic link to a
|
|
117
|
-
* user without the symlink privilege, so each kind has a fallback that needs none.
|
|
118
|
-
*/
|
|
119
|
-
export interface EntryLinker {
|
|
120
|
-
/** A symbolic link to a file, or a junction to a folder (junctions need no privilege on Windows). */
|
|
121
|
-
symlink(target: string, path: string, isDir: boolean): void
|
|
122
|
-
/** A hard link to a file on the same volume. */
|
|
123
|
-
hardLink(target: string, path: string): void
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const nodeLinker: EntryLinker = {
|
|
127
|
-
symlink: (target, path, isDir) => symlinkSync(resolve(target), path, isDir ? 'junction' : 'file'),
|
|
128
|
-
hardLink: (target, path) => linkSync(target, path)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const codeOf = (error: unknown): string => (error as NodeJS.ErrnoException).code ?? String(error)
|
|
132
|
-
const PRIVILEGE_CODES = ['EPERM', 'EACCES']
|
|
133
|
-
|
|
134
|
-
function createLink(target: string, path: string, isDir: boolean, linker: EntryLinker): void {
|
|
135
|
-
try {
|
|
136
|
-
linker.symlink(target, path, isDir)
|
|
137
|
-
} catch (error) {
|
|
138
|
-
// A file can still be hard-linked without the privilege; a folder has no such fallback.
|
|
139
|
-
if (isDir || !PRIVILEGE_CODES.includes(codeOf(error))) throw error
|
|
140
|
-
linker.hardLink(target, path)
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const isLink = (path: string): boolean => {
|
|
145
|
-
try {
|
|
146
|
-
return lstatSync(path).isSymbolicLink()
|
|
147
|
-
} catch {
|
|
148
|
-
return false
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Windows reports some link targets with the `\\?\` prefix.
|
|
153
|
-
const LONG_PREFIX = /^\\\\\?\\/
|
|
154
|
-
function samePath(a: string, b: string): boolean {
|
|
155
|
-
const normal = (path: string): string => {
|
|
156
|
-
const full = resolve(path.replace(LONG_PREFIX, ''))
|
|
157
|
-
return process.platform === 'win32' ? full.toLowerCase() : full
|
|
158
|
-
}
|
|
159
|
-
return normal(a) === normal(b)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/** A hard link is the same file on disk as its target, so it has the same device and inode. */
|
|
163
|
-
function sameFile(a: string, b: string): boolean {
|
|
164
|
-
try {
|
|
165
|
-
const left = lstatSync(a)
|
|
166
|
-
const right = lstatSync(b)
|
|
167
|
-
return left.ino !== 0 && left.dev === right.dev && left.ino === right.ino
|
|
168
|
-
} catch {
|
|
169
|
-
return false
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function isLinkTo(path: string, target: string, isDir: boolean): boolean {
|
|
174
|
-
try {
|
|
175
|
-
const meta = lstatSync(path)
|
|
176
|
-
if (meta.isSymbolicLink()) return samePath(readlinkSync(path), target)
|
|
177
|
-
return !isDir && meta.isFile() && sameFile(path, target)
|
|
178
|
-
} catch {
|
|
179
|
-
return false
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/** Removes a link without touching what it points to. A Windows junction needs `rmdir`. */
|
|
184
|
-
function removeLink(path: string, isDir: boolean): void {
|
|
185
|
-
try {
|
|
186
|
-
unlinkSync(path)
|
|
187
|
-
} catch (error) {
|
|
188
|
-
if (!isDir) throw error
|
|
189
|
-
rmdirSync(path)
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* A file the account does not have, for an entry whose link was refused: a copy of the shared one
|
|
195
|
-
* (with its time kept, so the newest-wins rule does not move it), so the account's settings load.
|
|
196
|
-
*/
|
|
197
|
-
function keepCopy(target: string, path: string, isDir: boolean): void {
|
|
198
|
-
if (isDir || present(path) || !present(target)) return
|
|
199
|
-
try {
|
|
200
|
-
copyFileSync(target, path)
|
|
201
|
-
const { atime, mtime } = statSync(target)
|
|
202
|
-
utimesSync(path, atime, mtime)
|
|
203
|
-
} catch {
|
|
204
|
-
// The account simply keeps no copy; its sign-in and its own files are not affected.
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/** What happened to one shared entry: linked to the shared copy, or left as the account's own. */
|
|
209
|
-
export interface SharedEntry {
|
|
210
|
-
name: string
|
|
211
|
-
state: 'linked' | 'unshared'
|
|
212
|
-
/** Why the link was refused, when it was. */
|
|
213
|
-
reason?: string
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Links one entry to its shared copy. A real entry found in the account folder (from before
|
|
218
|
-
* sharing, or a tool that replaced the link while saving) becomes the shared copy when there is
|
|
219
|
-
* none or it is newer; otherwise it is kept as a backup. If the link is then refused, every move
|
|
220
|
-
* is undone, so the account keeps what it had.
|
|
221
|
-
*/
|
|
222
|
-
function linkOne(name: string, target: string, path: string, isDir: boolean, linker: EntryLinker): SharedEntry {
|
|
223
|
-
if (isLinkTo(path, target, isDir)) {
|
|
224
|
-
if (isDir) mkdirSync(target, { recursive: true })
|
|
225
|
-
return { name, state: 'linked' }
|
|
226
|
-
}
|
|
227
|
-
const undo: (() => void)[] = []
|
|
228
|
-
try {
|
|
229
|
-
if (isLink(path)) {
|
|
230
|
-
const previous = readlinkSync(path)
|
|
231
|
-
removeLink(path, isDir)
|
|
232
|
-
undo.push(() => nodeLinker.symlink(previous, path, isDir))
|
|
233
|
-
} else if (present(path)) {
|
|
234
|
-
if (!present(target)) {
|
|
235
|
-
renameSync(path, target)
|
|
236
|
-
undo.push(() => renameSync(target, path))
|
|
237
|
-
} else if (!isDir && modified(path) > modified(target)) {
|
|
238
|
-
const backup = backUp(target)
|
|
239
|
-
undo.push(() => renameSync(backup, target))
|
|
240
|
-
renameSync(path, target)
|
|
241
|
-
undo.push(() => renameSync(target, path))
|
|
242
|
-
} else {
|
|
243
|
-
const backup = backUp(path)
|
|
244
|
-
undo.push(() => renameSync(backup, path))
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
if (isDir) mkdirSync(target, { recursive: true })
|
|
248
|
-
createLink(target, path, isDir, linker)
|
|
249
|
-
return { name, state: 'linked' }
|
|
250
|
-
} catch (error) {
|
|
251
|
-
for (const step of undo.reverse()) {
|
|
252
|
-
try {
|
|
253
|
-
step()
|
|
254
|
-
} catch {
|
|
255
|
-
// The entry stays where that step left it; nothing further can be restored safely.
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
keepCopy(target, path, isDir)
|
|
259
|
-
return { name, state: 'unshared', reason: codeOf(error) }
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Creates the account's runtime folder and links the shared entries into it. Never throws for a
|
|
265
|
-
* refused link: each entry is reported, and the account falls back to its own copy.
|
|
266
|
-
*/
|
|
267
|
-
export function linkSharedEntries(accountsDir: string, account: Pick<Account, 'id'>, linker: EntryLinker = nodeLinker): { dir: string; entries: SharedEntry[] } {
|
|
268
|
-
makePrivate(join(accountsDir, account.id))
|
|
269
|
-
makePrivate(homeDir(accountsDir, account.id))
|
|
270
|
-
const dir = configDir(accountsDir, account)
|
|
271
|
-
makePrivate(dir)
|
|
272
|
-
const shared = ensureSharedDir(accountsDir)
|
|
273
|
-
const entries = SHARED_ENTRIES.map(([name, isDir]) => linkOne(name, join(shared, name), join(dir, name), isDir, linker))
|
|
274
|
-
return { dir, entries }
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/** Creates the account's runtime folder and links the shared entries into it. */
|
|
278
|
-
export function ensureHome(accountsDir: string, account: Pick<Account, 'id'>): string {
|
|
279
|
-
return linkSharedEntries(accountsDir, account).dir
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const inside = (path: string, parent: string): boolean => path === parent || path.startsWith(parent.endsWith(sep) ? parent : `${parent}${sep}`)
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* Refuses an agent folder that is (or is inside) a default tool folder, or that is not inside
|
|
286
|
-
* the harness's own accounts folder.
|
|
287
|
-
*/
|
|
288
|
-
export function assertIsolated(accountsDir: string, dir: string): void {
|
|
289
|
-
const defaults = ['.codex', '.claude', '.pi'].map((name) => join(homedir() || '/', name))
|
|
290
|
-
if (defaults.some((folder) => inside(dir, folder)) || !inside(dir, accountsDir)) {
|
|
291
|
-
throw new HarnessError('account_required', 'A session cannot start outside its isolated account folder.')
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
function sessionEnv(dir: string, inherited: NodeJS.ProcessEnv): Record<string, string | null> {
|
|
296
|
-
const env: Record<string, string | null> = {}
|
|
297
|
-
for (const name of inheritedCredentialVars(inherited)) env[name] = null
|
|
298
|
-
env.PI_CODING_AGENT_DIR = dir
|
|
299
|
-
return env
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/** Variables to set, or remove (`null`), when launching a session for this account. */
|
|
303
|
-
export function launchEnv(accountsDir: string, account: Pick<Account, 'id'>, inherited: NodeJS.ProcessEnv = process.env): Record<string, string | null> {
|
|
304
|
-
const dir = ensureHome(accountsDir, account)
|
|
305
|
-
assertIsolated(accountsDir, dir)
|
|
306
|
-
return sessionEnv(dir, inherited)
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/** What a session needs to run for an account. */
|
|
310
|
-
export interface AccountContext {
|
|
311
|
-
id: string
|
|
312
|
-
provider: 'pi'
|
|
313
|
-
label: string
|
|
314
|
-
/** Variables to set; `null` removes an inherited one. */
|
|
315
|
-
env: Record<string, string | null>
|
|
316
|
-
/** The account's own agent folder. */
|
|
317
|
-
configDir: string
|
|
318
|
-
/** Which shared entries are linked, and which the account keeps as its own. */
|
|
319
|
-
sharing: SharedEntry[]
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
export function accountContext(accountsDir: string, account: Account): AccountContext {
|
|
323
|
-
const { dir, entries } = linkSharedEntries(accountsDir, account)
|
|
324
|
-
assertIsolated(accountsDir, dir)
|
|
325
|
-
return { id: account.id, provider: 'pi', label: account.label, env: sessionEnv(dir, process.env), configDir: dir, sharing: entries }
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/** The process environment for a `pi` process launched on behalf of this account. */
|
|
329
|
-
export function processEnv(account: AccountContext, inherited: NodeJS.ProcessEnv = process.env): Record<string, string> {
|
|
330
|
-
const env: Record<string, string> = {}
|
|
331
|
-
for (const [name, value] of Object.entries(inherited)) if (value !== undefined) env[name] = value
|
|
332
|
-
for (const [name, value] of Object.entries(account.env)) {
|
|
333
|
-
if (value === null) delete env[name]
|
|
334
|
-
else env[name] = value
|
|
335
|
-
}
|
|
336
|
-
return env
|
|
337
|
-
}
|
|
338
|
-
|
package/src/accounts/secrets.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
// Where credentials live. The harness never writes a secret to its own files: it asks the
|
|
2
|
-
// store the embedding application provides (a Keychain, an encrypted vault), by key.
|
|
3
|
-
import { chmodSync, mkdirSync } from 'node:fs'
|
|
4
|
-
import { dirname } from 'node:path'
|
|
5
|
-
|
|
6
|
-
import { atomicWrite, readJsonOr } from '../core/fs'
|
|
7
|
-
|
|
8
|
-
export interface SecretStore {
|
|
9
|
-
get(key: string): Promise<string | null>
|
|
10
|
-
set(key: string, value: string): Promise<void>
|
|
11
|
-
delete(key: string): Promise<void>
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/** `<account id>/<secret name>`: the key an account's secret is stored under. */
|
|
15
|
-
export const secretKey = (accountId: string, name: string): string => `${accountId}/${name}`
|
|
16
|
-
|
|
17
|
-
/** Secrets held only for the life of the process. For tests and throwaway runs. */
|
|
18
|
-
export function memorySecretStore(initial: Record<string, string> = {}): SecretStore & { values: Map<string, string> } {
|
|
19
|
-
const values = new Map(Object.entries(initial))
|
|
20
|
-
return {
|
|
21
|
-
values,
|
|
22
|
-
get: async (key) => values.get(key) ?? null,
|
|
23
|
-
set: async (key, value) => void values.set(key, value),
|
|
24
|
-
delete: async (key) => void values.delete(key)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Secrets in one owner-only JSON file. For a host with no Keychain to offer; anything that can
|
|
30
|
-
* read the file can read every secret in it.
|
|
31
|
-
*/
|
|
32
|
-
export function fileSecretStore(path: string): SecretStore {
|
|
33
|
-
const read = (): Record<string, string> => readJsonOr<Record<string, string>>(path, {})
|
|
34
|
-
const write = (values: Record<string, string>): void => {
|
|
35
|
-
mkdirSync(dirname(path), { recursive: true, mode: 0o700 })
|
|
36
|
-
atomicWrite(path, `${JSON.stringify(values, null, 2)}\n`)
|
|
37
|
-
chmodSync(path, 0o600)
|
|
38
|
-
}
|
|
39
|
-
return {
|
|
40
|
-
get: async (key) => read()[key] ?? null,
|
|
41
|
-
set: async (key, value) => write({ ...read(), [key]: value }),
|
|
42
|
-
delete: async (key) => {
|
|
43
|
-
const values = read()
|
|
44
|
-
if (key in values) {
|
|
45
|
-
delete values[key]
|
|
46
|
-
write(values)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|