@xingular/harness 0.1.6 → 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 +107 -0
- package/LICENSE +202 -0
- package/NOTICE.md +60 -0
- package/README.md +265 -71
- package/THIRD_PARTY_LICENSES.md +942 -0
- package/dist/cli.js +14842 -9445
- 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 +1170 -62
- package/docs/README.md +34 -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-0001-owned-terminal.md +87 -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 +671 -0
- package/package.json +48 -12
- package/src/accounts/accounts.test.ts +0 -223
- package/src/accounts/accounts.ts +0 -522
- 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 -114
- 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 -299
- package/src/index.ts +0 -70
- 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 -289
- package/src/memory/blocks.test.ts +0 -78
- package/src/memory/blocks.ts +0 -406
- package/src/memory/caller.ts +0 -57
- 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 -330
- package/src/memory/migrate.ts +0 -79
- package/src/memory/operations.ts +0 -138
- package/src/memory/proposals.test.ts +0 -168
- package/src/memory/proposals.ts +0 -576
- package/src/memory/recall.test.ts +0 -104
- package/src/memory/recall.ts +0 -271
- 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 -314
- 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 -310
- package/src/sessions/conversation.test.ts +0 -150
- 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 -32
- package/src/sessions/pricing.ts +0 -60
- package/src/sessions/reasoningSummaries.ts +0 -59
- package/src/sessions/registry.ts +0 -294
- 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 -569
- package/src/sessions/runtimeResources.test.ts +0 -61
- package/src/sessions/sessions.test.ts +0 -455
- package/src/sessions/sessions.ts +0 -295
- package/src/skills/registry.test.ts +0 -104
- package/src/skills/registry.ts +0 -407
- package/src/terminal/cli.ts +0 -149
- package/src/terminal/client.ts +0 -74
- package/src/terminal/controller.ts +0 -227
- package/src/terminal/launch.test.ts +0 -34
- package/src/terminal/launch.ts +0 -88
- package/src/terminal/piExtension.ts +0 -210
- 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 -221
- package/src/terminal/standalone.test.ts +0 -130
- package/src/terminal/standalone.ts +0 -144
- package/src/terminal/terminal.test.ts +0 -330
- package/src/terminal/terminals.ts +0 -443
- package/src/tools/askUser.ts +0 -45
- package/src/tools/definitions.ts +0 -187
- package/src/tools/memoryTools.ts +0 -22
- package/src/tools/pluginPropose.ts +0 -41
- 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/plugins/install.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
// Installing, updating and removing a package. Pi's own package manager does the work, against
|
|
2
|
-
// the settings every account shares, so the `pi` command and the harness agree on what is
|
|
3
|
-
// installed. Fetching runs none of a package's code, and what was installed is switched off and
|
|
4
|
-
// untrusted until a person has looked at it.
|
|
5
|
-
import { existsSync, mkdirSync, renameSync, statSync } from 'node:fs'
|
|
6
|
-
import { homedir } from 'node:os'
|
|
7
|
-
import { basename, isAbsolute, join, resolve } from 'node:path'
|
|
8
|
-
|
|
9
|
-
import { ensureSharedDir } from '../accounts/env'
|
|
10
|
-
import { invalid, notFound } from '../core/errors'
|
|
11
|
-
import { now } from '../core/fs'
|
|
12
|
-
import type { Harness } from '../harness'
|
|
13
|
-
import { ensureAdopted, list, type PluginScope } from './api'
|
|
14
|
-
import * as attachments from './attachments'
|
|
15
|
-
import { withoutInstallScripts } from './discover'
|
|
16
|
-
import type { Plugin } from './types'
|
|
17
|
-
|
|
18
|
-
/** A folder on this machine, or a package as Pi's settings name it. A bare name is an npm package. */
|
|
19
|
-
export function normalizeSource(input: string): string {
|
|
20
|
-
const source = input.trim()
|
|
21
|
-
if (!source) throw invalid('Name a package: a folder, an npm name, or a git address.')
|
|
22
|
-
if (source.startsWith('~/')) return join(process.env.HOME || homedir(), source.slice(2))
|
|
23
|
-
if (isAbsolute(source)) return resolve(source)
|
|
24
|
-
if (source.startsWith('./') || source.startsWith('../')) throw invalid('Give the whole path of the folder.')
|
|
25
|
-
return /^(npm:|git:|https?:\/\/|ssh:\/\/|git@)/.test(source) ? source : `npm:${source}`
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function manager(harness: Harness) {
|
|
29
|
-
const pi = await import('@earendil-works/pi-coding-agent')
|
|
30
|
-
// The shared folder is where `settings.json` really is; an account's own is a link to it.
|
|
31
|
-
const agentDir = ensureSharedDir(harness.accounts.dir)
|
|
32
|
-
const settings = pi.SettingsManager.create(harness.stateDir, agentDir)
|
|
33
|
-
return { settings, packages: new pi.DefaultPackageManager({ cwd: harness.stateDir, agentDir, settingsManager: settings }) }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const changed = (harness: Harness): void => harness.bus.emit({ type: 'plugins.changed' })
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Installs a package for every account. It arrives switched off, and if it brings code, not
|
|
40
|
-
* trusted: nothing of it reaches a session until a person switches it on and trusts it.
|
|
41
|
-
*/
|
|
42
|
-
export async function install(harness: Harness, params: PluginScope & { source: string }): Promise<Plugin[]> {
|
|
43
|
-
const source = normalizeSource(params.source)
|
|
44
|
-
if (isAbsolute(source) && !(existsSync(source) && statSync(source).isDirectory())) throw invalid('That folder does not exist.')
|
|
45
|
-
// What was already there is taken over as trusted before anything new arrives, never after.
|
|
46
|
-
await ensureAdopted(harness)
|
|
47
|
-
const before = new Set((await list(harness, params)).map((plugin) => plugin.id))
|
|
48
|
-
const { settings, packages } = await manager(harness)
|
|
49
|
-
if (isAbsolute(source)) {
|
|
50
|
-
// Pi would save a folder as a path relative to the settings file, and each account reads
|
|
51
|
-
// that file through a link in its own folder, where a relative path points somewhere else.
|
|
52
|
-
const named = settings.getGlobalSettings().packages ?? []
|
|
53
|
-
if (!named.some((entry) => (typeof entry === 'string' ? entry : entry.source) === source)) settings.setPackages([...named, source])
|
|
54
|
-
await settings.flush()
|
|
55
|
-
} else {
|
|
56
|
-
await withoutInstallScripts(() => packages.installAndPersist(source))
|
|
57
|
-
}
|
|
58
|
-
const after = await list(harness, params)
|
|
59
|
-
const added = after.filter((plugin) => plugin.install && !before.has(plugin.id))
|
|
60
|
-
if (added.length) {
|
|
61
|
-
const choices = attachments.load(harness.env.root)
|
|
62
|
-
for (const plugin of added) attachments.set(choices, [plugin.id], {}, false, true)
|
|
63
|
-
attachments.save(harness.env.root, choices)
|
|
64
|
-
}
|
|
65
|
-
changed(harness)
|
|
66
|
-
return added.length ? list(harness, params) : after
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function installed(plugins: readonly Plugin[], pluginId: string): Plugin & { install: NonNullable<Plugin['install']> } {
|
|
70
|
-
const plugin = plugins.find((candidate) => candidate.id === pluginId)
|
|
71
|
-
if (!plugin) throw notFound('Plugin')
|
|
72
|
-
if (!plugin.install) throw invalid(`${plugin.title} was not installed as a package, so it cannot be removed or updated here.`)
|
|
73
|
-
return plugin as Plugin & { install: NonNullable<Plugin['install']> }
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** Removes an installed package. One kept as a folder beside a person's data is moved to the trash there. */
|
|
77
|
-
export async function remove(harness: Harness, params: PluginScope & { pluginId: string }): Promise<Plugin[]> {
|
|
78
|
-
const plugin = installed(await list(harness, params), params.pluginId)
|
|
79
|
-
if (plugin.install.kind === 'folder') {
|
|
80
|
-
const trash = join(harness.env.root, 'trash', 'plugins')
|
|
81
|
-
mkdirSync(trash, { recursive: true })
|
|
82
|
-
renameSync(plugin.install.source, join(trash, `${basename(plugin.install.source)}-${now().replace(/[:.]/g, '-')}`))
|
|
83
|
-
} else {
|
|
84
|
-
await (await manager(harness)).packages.removeAndPersist(plugin.install.source)
|
|
85
|
-
}
|
|
86
|
-
const choices = attachments.load(harness.env.root)
|
|
87
|
-
for (const scope of [choices.global, ...Object.values(choices.agents), ...Object.values(choices.projects)]) {
|
|
88
|
-
scope.on = scope.on.filter((id) => id !== plugin.id && !id.startsWith(`${plugin.id}/`))
|
|
89
|
-
scope.off = scope.off.filter((id) => id !== plugin.id && !id.startsWith(`${plugin.id}/`))
|
|
90
|
-
}
|
|
91
|
-
delete choices.settings[plugin.id]
|
|
92
|
-
attachments.save(harness.env.root, choices)
|
|
93
|
-
if (plugin.code) harness.plugins.trust.revoke(plugin.code.hash)
|
|
94
|
-
changed(harness)
|
|
95
|
-
return list(harness, params)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/** Fetches a newer version of one installed package, or of all of them. Changed code waits for trust again. */
|
|
99
|
-
export async function update(harness: Harness, params: PluginScope & { pluginId?: string | null }): Promise<Plugin[]> {
|
|
100
|
-
const plugin = params.pluginId ? installed(await list(harness, params), params.pluginId) : null
|
|
101
|
-
if (plugin?.install.kind === 'folder') throw invalid(`${plugin.title} is a folder on this machine. Change its files to update it.`)
|
|
102
|
-
const { packages } = await manager(harness)
|
|
103
|
-
await withoutInstallScripts(() => packages.update(plugin?.install.source))
|
|
104
|
-
changed(harness)
|
|
105
|
-
return list(harness, params)
|
|
106
|
-
}
|
package/src/plugins/inventory.ts
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
// What reaches one caller: every prompt section, tool, skill, connection and extension, each
|
|
2
|
-
// attributed to the plugin it comes from. Anything no plugin accounts for is reported, so a new
|
|
3
|
-
// source of model-visible text cannot appear without showing up here.
|
|
4
|
-
import { readFileSync } from 'node:fs'
|
|
5
|
-
|
|
6
|
-
import type { HarnessEnv } from '../core/env'
|
|
7
|
-
import { charCount } from '../core/text'
|
|
8
|
-
import { allowed } from '../mcp/connections'
|
|
9
|
-
import type { Connection } from '../mcp/types'
|
|
10
|
-
import type { CallerContext } from '../memory/caller'
|
|
11
|
-
import { BUILT_IN_DYNAMIC, compile, toolGroups, type Launch } from '../prompt/compile'
|
|
12
|
-
import * as registry from '../skills/registry'
|
|
13
|
-
import { ASK_USER } from '../tools/askUser'
|
|
14
|
-
import { PLUGIN_PROPOSE } from '../tools/pluginPropose'
|
|
15
|
-
import { WIKI_TOOL_NAMES } from '../tools/definitions'
|
|
16
|
-
import { INCLUDED_PLUGIN, YOURS_PLUGIN } from './builtin'
|
|
17
|
-
import type { Contribution, Inventory, InventoryItem, Plugin, PluginDescriptor } from './types'
|
|
18
|
-
|
|
19
|
-
export interface InventoryInput {
|
|
20
|
-
env: HarnessEnv
|
|
21
|
-
context: CallerContext
|
|
22
|
-
/** What the application adds to the prompt for this caller, as it would for a session. */
|
|
23
|
-
launch: Launch
|
|
24
|
-
/** The tools the caller has switched on, as a session's `allow` list. */
|
|
25
|
-
tools: readonly string[]
|
|
26
|
-
/** Whether the caller gets the connected-apps tools. */
|
|
27
|
-
connections: boolean
|
|
28
|
-
plugins: readonly Plugin[]
|
|
29
|
-
descriptors: readonly PluginDescriptor[]
|
|
30
|
-
saved: readonly Connection[]
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const size = (path: string | null): number | null => {
|
|
34
|
-
if (!path) return null
|
|
35
|
-
try {
|
|
36
|
-
return charCount(readFileSync(path, 'utf8'))
|
|
37
|
-
} catch {
|
|
38
|
-
return null
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function inventory(input: InventoryInput): Inventory {
|
|
43
|
-
const { env, context, launch, descriptors } = input
|
|
44
|
-
const items: InventoryItem[] = []
|
|
45
|
-
const unattributed: Inventory['unattributed'] = []
|
|
46
|
-
const item = (pluginId: string, kind: InventoryItem['kind'], name: string, delivery: InventoryItem['delivery'], chars: number | null, rest: Partial<InventoryItem> = {}): void => {
|
|
47
|
-
items.push({ pluginId, contributionId: null, kind, name, delivery, chars, cut: false, ...rest })
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const pack = compile(env, context, launch)
|
|
51
|
-
const dynamic = new Set([...BUILT_IN_DYNAMIC.map((entry) => entry.id), ...(launch.sections ?? []).filter((section) => section.dynamic).map((section) => section.id)])
|
|
52
|
-
const active = registry.enabledFor(env.root, context.projectId ?? null, context.agentId ?? null)
|
|
53
|
-
const owner = (entry: registry.RegistryItem): string => (entry.builtin ? INCLUDED_PLUGIN.id : YOURS_PLUGIN.id)
|
|
54
|
-
let systemChars = 0
|
|
55
|
-
let contextChars = 0
|
|
56
|
-
|
|
57
|
-
for (const section of pack.sections) {
|
|
58
|
-
const delivery = dynamic.has(section.id) ? 'context' : 'system'
|
|
59
|
-
if (delivery === 'context') contextChars += section.size
|
|
60
|
-
else systemChars += section.size
|
|
61
|
-
if (section.id === 'tools') {
|
|
62
|
-
// One paragraph per tool group; each belongs to the plugin that provides the group.
|
|
63
|
-
for (const group of toolGroups(context, launch)) {
|
|
64
|
-
if (!group.guidance) continue
|
|
65
|
-
const plugin = descriptors.find((descriptor) => descriptor.toolGroups?.includes(group.group))
|
|
66
|
-
if (!plugin) unattributed.push({ kind: 'toolGroup', id: group.group })
|
|
67
|
-
item(plugin?.id ?? '', 'instruction', `Tool guidance: ${group.group}`, delivery, charCount(group.guidance), { cut: section.cut })
|
|
68
|
-
}
|
|
69
|
-
continue
|
|
70
|
-
}
|
|
71
|
-
if (section.id === 'rules') {
|
|
72
|
-
for (const rule of active.filter((entry) => entry.kind === 'rules')) {
|
|
73
|
-
item(owner(rule), 'instruction', rule.name, delivery, charCount(`### ${rule.name} (${rule.id})\n\n${registry.itemBody(rule).trim()}`), { contributionId: `${owner(rule)}/${rule.id}`, cut: section.cut })
|
|
74
|
-
}
|
|
75
|
-
continue
|
|
76
|
-
}
|
|
77
|
-
const plugin = descriptors.find((descriptor) => descriptor.sections?.some((declared) => declared.id === section.id))
|
|
78
|
-
if (!plugin) unattributed.push({ kind: 'section', id: section.id })
|
|
79
|
-
const name = plugin?.sections?.find((declared) => declared.id === section.id)?.name ?? section.title
|
|
80
|
-
item(plugin?.id ?? '', 'instruction', name, delivery, section.size, { contributionId: plugin ? `${plugin.id}/instruction/${name}` : null, cut: section.cut })
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// A skill's or a prompt's own text is loaded only when it is used.
|
|
84
|
-
for (const entry of active.filter((candidate) => candidate.kind === 'skills' || candidate.kind === 'prompts')) {
|
|
85
|
-
item(owner(entry), entry.kind === 'skills' ? 'skill' : 'command', entry.name, 'on-demand', size(entry.path), { contributionId: `${owner(entry)}/${entry.id}` })
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const names = [...input.tools]
|
|
89
|
-
const extensionToolNames = new Set(input.plugins.filter((plugin) => ['project', 'package', 'shared', 'home'].includes(plugin.source)).flatMap((plugin) => plugin.contributions.filter((entry) => entry.kind === 'tool' && entry.state === 'on').map((entry) => entry.name)))
|
|
90
|
-
for (const name of [ASK_USER, PLUGIN_PROPOSE, ...WIKI_TOOL_NAMES, ...(input.connections ? ['mcp_list_tools', 'mcp_call_tool'] : [])]) if (!names.includes(name)) names.push(name)
|
|
91
|
-
for (const name of names) {
|
|
92
|
-
if (extensionToolNames.has(name)) continue
|
|
93
|
-
const plugin = descriptors.find((descriptor) => descriptor.tools?.some((tool) => tool.name === name))
|
|
94
|
-
if (!plugin) unattributed.push({ kind: 'tool', id: name })
|
|
95
|
-
item(plugin?.id ?? '', 'tool', name, 'tool', null, { contributionId: plugin ? `${plugin.id}/tool/${name}` : null })
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (input.connections) {
|
|
99
|
-
for (const connection of input.saved.filter((candidate) => allowed(candidate, { agentId: context.agentId ?? null, projectId: context.projectId ?? null }))) {
|
|
100
|
-
item('connected-apps', 'connection', connection.name || connection.id, 'tool', null, { contributionId: `connected-apps/connection/${connection.id}` })
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// What the harness found on disk and lets load. Pi's command's own extensions exist only in a terminal.
|
|
105
|
-
const delivered: Record<Contribution['kind'], InventoryItem['delivery']> = { code: 'code', skill: 'on-demand', command: 'on-demand', instruction: 'system', theme: 'code', tool: 'tool', connection: 'tool' }
|
|
106
|
-
const terminal = context.surface === 'cli'
|
|
107
|
-
for (const plugin of input.plugins) {
|
|
108
|
-
if (!['project', 'package', 'shared', 'home', 'pi'].includes(plugin.source)) continue
|
|
109
|
-
for (const found of plugin.contributions) {
|
|
110
|
-
if (found.state !== 'on' || (plugin.source === 'pi' && (found.kind !== 'code' || !terminal)) || (found.kind === 'theme' && !terminal)) continue
|
|
111
|
-
item(plugin.id, found.kind, found.name, found.background ? 'background' : delivered[found.kind], ['instruction', 'skill', 'command'].includes(found.kind) ? size(found.path) : null, { contributionId: found.id })
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
// The harness's own switched-on extensions.
|
|
115
|
-
for (const plugin of input.plugins) {
|
|
116
|
-
if (plugin.source !== 'builtin') continue
|
|
117
|
-
for (const own of plugin.contributions) if (own.kind === 'code' && own.state === 'on') item(plugin.id, 'code', own.name, 'code', null, { contributionId: own.id })
|
|
118
|
-
}
|
|
119
|
-
item('pi', 'instruction', 'Base prompt', 'system', null)
|
|
120
|
-
|
|
121
|
-
const used = new Set(items.map((entry) => entry.pluginId))
|
|
122
|
-
return { plugins: input.plugins.filter((plugin) => used.has(plugin.id)), others: input.plugins.filter((plugin) => !used.has(plugin.id)), items, unattributed, systemChars, contextChars }
|
|
123
|
-
}
|
package/src/plugins/manifest.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
// What a package says about itself in its `package.json`: Pi's own fields, and under `harness`
|
|
2
|
-
// which part of the harness it extends and the file of hooks the harness runs for it.
|
|
3
|
-
import { basename, join } from 'node:path'
|
|
4
|
-
import { z } from 'zod'
|
|
5
|
-
|
|
6
|
-
import { readJsonOr, safeRelative } from '../core/fs'
|
|
7
|
-
import type { ConnectorTemplate } from './types'
|
|
8
|
-
|
|
9
|
-
export interface PackageManifest {
|
|
10
|
-
name: string
|
|
11
|
-
description: string
|
|
12
|
-
version: string | null
|
|
13
|
-
/** The parts it adds to, by id: `memory`, `wiki`, `history`. */
|
|
14
|
-
extends: string[]
|
|
15
|
-
/** The hooks file, inside the package, or `null` when it has none. */
|
|
16
|
-
hooks: string | null
|
|
17
|
-
/** Data-only remote connector forms. Invalid templates are ignored; none can carry credentials. */
|
|
18
|
-
connectorTemplates: ConnectorTemplate[]
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface Raw {
|
|
22
|
-
name?: unknown
|
|
23
|
-
description?: unknown
|
|
24
|
-
version?: unknown
|
|
25
|
-
harness?: unknown
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const connectorTemplateSchema = z.object({
|
|
29
|
-
id: z.string().regex(/^[a-z0-9-]+$/),
|
|
30
|
-
name: z.string().min(1).max(120),
|
|
31
|
-
description: z.string().max(500),
|
|
32
|
-
url: z.string().url().startsWith('https://'),
|
|
33
|
-
auth: z.enum(['none', 'headers', 'oauth']),
|
|
34
|
-
oauthClient: z.enum(['dynamic', 'user']).nullable(),
|
|
35
|
-
oauthScopes: z.array(z.string().max(500)).max(30),
|
|
36
|
-
docsUrl: z.string().url().startsWith('https://').nullable(),
|
|
37
|
-
fields: z.array(z.object({
|
|
38
|
-
header: z.string().regex(/^[A-Za-z0-9_-]+$/),
|
|
39
|
-
label: z.string().min(1).max(120),
|
|
40
|
-
prefix: z.string().max(100),
|
|
41
|
-
help: z.string().max(500)
|
|
42
|
-
}).strict()).max(12),
|
|
43
|
-
setup: z.array(z.string().max(1000)).max(20),
|
|
44
|
-
notice: z.string().max(1000).nullable()
|
|
45
|
-
}).strict().superRefine((template, context) => {
|
|
46
|
-
const oauth = template.auth === 'oauth'
|
|
47
|
-
const headers = template.auth === 'headers'
|
|
48
|
-
if (oauth !== (template.oauthClient !== null)) context.addIssue({ code: 'custom', message: 'OAuth templates must state a client type and other templates must not.', path: ['oauthClient'] })
|
|
49
|
-
if (headers !== (template.fields.length > 0)) context.addIssue({ code: 'custom', message: 'Header templates must declare input fields and other templates must not.', path: ['fields'] })
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
/** A path inside the package, or `null` for one that is missing, absolute, or climbs out of it. */
|
|
53
|
-
function inside(path: unknown): string | null {
|
|
54
|
-
if (typeof path !== 'string' || !path.trim()) return null
|
|
55
|
-
try {
|
|
56
|
-
return safeRelative(path.replace(/^\.\//, ''))
|
|
57
|
-
} catch {
|
|
58
|
-
return null
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function packageManifest(packageRoot: string): PackageManifest {
|
|
63
|
-
const manifest = readJsonOr<Raw>(join(packageRoot, 'package.json'), {})
|
|
64
|
-
const own = (manifest.harness && typeof manifest.harness === 'object' && !Array.isArray(manifest.harness) ? manifest.harness : {}) as { extends?: unknown; hooks?: unknown; connectors?: unknown }
|
|
65
|
-
return {
|
|
66
|
-
name: typeof manifest.name === 'string' && manifest.name ? manifest.name : basename(packageRoot),
|
|
67
|
-
description: typeof manifest.description === 'string' ? manifest.description : '',
|
|
68
|
-
version: typeof manifest.version === 'string' ? manifest.version : null,
|
|
69
|
-
extends: (Array.isArray(own.extends) ? own.extends : typeof own.extends === 'string' ? [own.extends] : []).filter((id): id is string => typeof id === 'string' && !!id),
|
|
70
|
-
hooks: inside(own.hooks),
|
|
71
|
-
connectorTemplates: (Array.isArray(own.connectors) ? own.connectors : []).flatMap((value) => {
|
|
72
|
-
const parsed = connectorTemplateSchema.safeParse(value)
|
|
73
|
-
return parsed.success ? [parsed.data] : []
|
|
74
|
-
})
|
|
75
|
-
}
|
|
76
|
-
}
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, mkdtempSync, symlinkSync, writeFileSync } from 'node:fs'
|
|
2
|
-
import { tmpdir } from 'node:os'
|
|
3
|
-
import { join } from 'node:path'
|
|
4
|
-
import { describe, expect, it } from 'vitest'
|
|
5
|
-
|
|
6
|
-
import { Bus } from '../core/bus'
|
|
7
|
-
import type { Attachments } from './attachments'
|
|
8
|
-
import { loadResources, type TurnParams } from '../sessions/runner'
|
|
9
|
-
import { piResolver, type Found } from './discover'
|
|
10
|
-
import { Plugins } from './plugins'
|
|
11
|
-
import { projectCode } from './trust'
|
|
12
|
-
|
|
13
|
-
const temp = (prefix: string): string => mkdtempSync(join(tmpdir(), prefix))
|
|
14
|
-
|
|
15
|
-
function write(path: string, text: string): void {
|
|
16
|
-
mkdirSync(join(path, '..'), { recursive: true })
|
|
17
|
-
writeFileSync(path, text)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** An extension that leaves a file behind when Pi loads it, and registers a command and a hook. */
|
|
21
|
-
const extension = (marker: string, command: string): string =>
|
|
22
|
-
`import { writeFileSync } from 'node:fs'\nwriteFileSync(${JSON.stringify(marker)}, 'ran')\nexport default function (pi) {\n pi.registerCommand('${command}', { description: 'A test command', handler: async () => {} })\n pi.on('tool_call', async () => undefined)\n}\n`
|
|
23
|
-
|
|
24
|
-
function workspace() {
|
|
25
|
-
const base = temp('harness-plugins-')
|
|
26
|
-
const agentDir = join(base, 'agent')
|
|
27
|
-
const cwd = join(base, 'project')
|
|
28
|
-
const markers = { shared: join(base, 'ran-shared'), project: join(base, 'ran-project'), packaged: join(base, 'ran-packaged') }
|
|
29
|
-
write(join(agentDir, 'extensions/shared.ts'), extension(markers.shared, 'shared'))
|
|
30
|
-
write(join(agentDir, 'skills/alpha/SKILL.md'), '---\nname: alpha\ndescription: Alpha skill\n---\nAlpha.\n')
|
|
31
|
-
write(join(agentDir, 'prompts/review.md'), 'Review this.\n')
|
|
32
|
-
write(join(cwd, '.pi/extensions/project.ts'), extension(markers.project, 'project'))
|
|
33
|
-
write(join(cwd, '.pi/skills/beta/SKILL.md'), '---\nname: beta\ndescription: Beta skill\n---\nBeta.\n')
|
|
34
|
-
write(join(base, 'package/package.json'), JSON.stringify({ name: 'local-package', description: 'A local package', version: '0.1.0', keywords: ['pi-package'] }))
|
|
35
|
-
write(join(base, 'package/extensions/packaged.ts'), extension(markers.packaged, 'packaged'))
|
|
36
|
-
write(join(base, 'package/skills/gamma/SKILL.md'), '---\nname: gamma\ndescription: Gamma skill\n---\nGamma.\n')
|
|
37
|
-
write(join(agentDir, 'settings.json'), JSON.stringify({ packages: [join(base, 'package')], extensions: ['-builtin:llama.cpp'] }))
|
|
38
|
-
const stateDir = join(base, 'state')
|
|
39
|
-
mkdirSync(stateDir)
|
|
40
|
-
const notices: string[] = []
|
|
41
|
-
const bus = new Bus()
|
|
42
|
-
bus.on((notice) => void notices.push(notice.type))
|
|
43
|
-
return { base, agentDir, cwd, markers, notices, plugins: new Plugins({ stateDir, bus }) }
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const ran = (markers: Record<string, string>): Record<string, boolean> => Object.fromEntries(Object.entries(markers).map(([name, path]) => [name, existsSync(path)]))
|
|
47
|
-
|
|
48
|
-
describe('what Pi would load', () => {
|
|
49
|
-
it('is found without running any of it, with where each item comes from', async () => {
|
|
50
|
-
const { agentDir, cwd, markers, base } = workspace()
|
|
51
|
-
const found = await piResolver({ cwd, agentDir })
|
|
52
|
-
const of = (kind: Found['kind']) => found.filter((item) => item.kind === kind).map((item) => [item.origin, item.path.replace(`${base}/`, ''), item.enabled])
|
|
53
|
-
expect(of('extension')).toEqual([
|
|
54
|
-
['project', 'project/.pi/extensions/project.ts', true],
|
|
55
|
-
['shared', 'agent/extensions/shared.ts', true],
|
|
56
|
-
['package', 'package/extensions/packaged.ts', true],
|
|
57
|
-
['builtin', 'builtin:llama.cpp', false],
|
|
58
|
-
['builtin', 'builtin:codemode', true],
|
|
59
|
-
['builtin', 'builtin:tool-search', true],
|
|
60
|
-
['builtin', 'builtin:mcp', true]
|
|
61
|
-
])
|
|
62
|
-
expect(of('skill')).toEqual([
|
|
63
|
-
['project', 'project/.pi/skills/beta/SKILL.md', true],
|
|
64
|
-
['shared', 'agent/skills/alpha/SKILL.md', true],
|
|
65
|
-
['package', 'package/skills/gamma/SKILL.md', true]
|
|
66
|
-
])
|
|
67
|
-
expect(found.find((item) => item.origin === 'package')).toMatchObject({ packageRoot: join(base, 'package'), source: join(base, 'package'), project: false })
|
|
68
|
-
expect(ran(markers)).toEqual({ shared: false, project: false, packaged: false })
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('names a package nobody installed, and installs nothing when only listing', async () => {
|
|
72
|
-
const { agentDir, cwd } = workspace()
|
|
73
|
-
writeFileSync(join(agentDir, 'settings.json'), JSON.stringify({ packages: ['npm:@no-such-scope/never-installed'] }))
|
|
74
|
-
const found = await piResolver({ cwd, agentDir })
|
|
75
|
-
expect(found.some((item) => item.origin === 'package')).toBe(false)
|
|
76
|
-
expect(existsSync(join(agentDir, 'npm'))).toBe(false)
|
|
77
|
-
})
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
describe('what a session loads', () => {
|
|
81
|
-
it("leaves a working folder's code out until a person trusts it", async () => {
|
|
82
|
-
const { agentDir, cwd, plugins, base, notices } = workspace()
|
|
83
|
-
const before = await plugins.loading({ cwd, agentDir })
|
|
84
|
-
const short = (paths: string[]) => paths.map((path) => path.replace(`${base}/`, ''))
|
|
85
|
-
expect(short(before.extensionPaths)).toEqual(['agent/extensions/shared.ts', 'package/extensions/packaged.ts'])
|
|
86
|
-
expect(short(before.skillPaths)).toEqual(['project/.pi/skills/beta/SKILL.md', 'agent/skills/alpha/SKILL.md', 'package/skills/gamma/SKILL.md'])
|
|
87
|
-
expect(before.builtins).toEqual(['builtin:codemode', 'builtin:tool-search', 'builtin:mcp'])
|
|
88
|
-
expect(before.projectCode).toMatchObject({ trusted: false, files: ['.pi/extensions/project.ts'] })
|
|
89
|
-
|
|
90
|
-
plugins.trust.grant(before.projectCode!, cwd)
|
|
91
|
-
expect(notices).toContain('plugins.changed')
|
|
92
|
-
const trusted = await plugins.loading({ cwd, agentDir })
|
|
93
|
-
expect(short(trusted.extensionPaths)).toEqual(['project/.pi/extensions/project.ts', 'agent/extensions/shared.ts', 'package/extensions/packaged.ts'])
|
|
94
|
-
|
|
95
|
-
// A changed file is different code: it asks again.
|
|
96
|
-
writeFileSync(join(cwd, '.pi/extensions/project.ts'), 'export default function () {}\n')
|
|
97
|
-
const changed = await plugins.loading({ cwd, agentDir })
|
|
98
|
-
expect(changed.projectCode?.trusted).toBe(false)
|
|
99
|
-
expect(changed.projectCode?.hash).not.toBe(before.projectCode?.hash)
|
|
100
|
-
expect(short(changed.extensionPaths)).toEqual(['agent/extensions/shared.ts', 'package/extensions/packaged.ts'])
|
|
101
|
-
|
|
102
|
-
plugins.trust.revoke(before.projectCode!.hash)
|
|
103
|
-
// What is left is the package that was there when trust was first asked per package.
|
|
104
|
-
expect(plugins.trust.list().map((record) => record.folder)).toEqual([join(base, 'package')])
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
it('takes over the packages present once, then makes a new or changed package wait', async () => {
|
|
108
|
-
const { agentDir, cwd, plugins, base } = workspace()
|
|
109
|
-
const packaged = join(base, 'package/extensions/packaged.ts')
|
|
110
|
-
const first = await plugins.loading({ cwd, agentDir })
|
|
111
|
-
expect(first.packageCode[join(base, 'package')]).toMatchObject({ trusted: true, files: ['extensions/packaged.ts', 'package.json', 'skills/gamma/SKILL.md'] })
|
|
112
|
-
expect(first.extensionPaths).toContain(packaged)
|
|
113
|
-
|
|
114
|
-
// An update changes the code: it does not load until a person trusts it again.
|
|
115
|
-
writeFileSync(packaged, 'export default function () {}\n')
|
|
116
|
-
const changed = await plugins.loading({ cwd, agentDir })
|
|
117
|
-
expect(changed.packageCode[join(base, 'package')].trusted).toBe(false)
|
|
118
|
-
expect(changed.extensionPaths).not.toContain(packaged)
|
|
119
|
-
// Its text still loads: a skill runs nothing by itself.
|
|
120
|
-
expect(changed.skillPaths).toContain(join(base, 'package/skills/gamma/SKILL.md'))
|
|
121
|
-
plugins.trust.grant(changed.packageCode[join(base, 'package')], join(base, 'package'))
|
|
122
|
-
expect((await plugins.loading({ cwd, agentDir })).extensionPaths).toContain(packaged)
|
|
123
|
-
|
|
124
|
-
// A package added after the first start was never taken over.
|
|
125
|
-
write(join(base, 'second/package.json'), JSON.stringify({ name: 'second', version: '1.0.0' }))
|
|
126
|
-
write(join(base, 'second/extensions/later.ts'), 'export default function () {}\n')
|
|
127
|
-
write(join(agentDir, 'settings.json'), JSON.stringify({ packages: [join(base, 'package'), join(base, 'second')] }))
|
|
128
|
-
const later = await plugins.loading({ cwd, agentDir })
|
|
129
|
-
expect(later.packageCode[join(base, 'second')].trusted).toBe(false)
|
|
130
|
-
expect(later.extensionPaths).not.toContain(join(base, 'second/extensions/later.ts'))
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
it('trusts the same code in another folder, and names files from the folder they are in', () => {
|
|
134
|
-
const one = temp('harness-code-')
|
|
135
|
-
const two = temp('harness-code-')
|
|
136
|
-
for (const cwd of [one, two]) write(join(cwd, '.pi/extensions/tool/index.ts'), 'export default function () {}\n')
|
|
137
|
-
const item = (cwd: string): Found => ({ kind: 'extension', path: join(cwd, '.pi/extensions/tool/index.ts'), origin: 'project', project: true, packageRoot: null, source: null, enabled: true })
|
|
138
|
-
write(join(one, '.pi/extensions/tool/node_modules/dep/index.js'), 'ignored')
|
|
139
|
-
expect(projectCode([item(one)], one)).toEqual(projectCode([item(two)], two))
|
|
140
|
-
expect(projectCode([item(one)], one)?.files).toEqual(['.pi/extensions/tool/index.ts'])
|
|
141
|
-
// A helper beside `index.ts` is part of the same extension.
|
|
142
|
-
write(join(two, '.pi/extensions/tool/helper.ts'), 'export const x = 1\n')
|
|
143
|
-
expect(projectCode([item(two)], two)?.hash).not.toBe(projectCode([item(one)], one)?.hash)
|
|
144
|
-
expect(projectCode([{ ...item(one), project: false }], one)).toBeNull()
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
it('removes the skill links an earlier version kept in the shared folder', async () => {
|
|
148
|
-
const { agentDir, cwd, plugins, base } = workspace()
|
|
149
|
-
symlinkSync(join(agentDir, 'skills/alpha'), join(agentDir, 'skills/agentx-old'))
|
|
150
|
-
const loading = await plugins.loading({ cwd, agentDir })
|
|
151
|
-
expect(existsSync(join(agentDir, 'skills/agentx-old'))).toBe(false)
|
|
152
|
-
expect(loading.skillPaths.filter((path) => path.startsWith(join(base, 'agent')))).toEqual([join(agentDir, 'skills/alpha/SKILL.md')])
|
|
153
|
-
})
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
describe('a Pi session loader', () => {
|
|
157
|
-
const params = (cwd: string, agentDir: string, plugins: Plugins, extra: Partial<TurnParams> = {}) =>
|
|
158
|
-
({
|
|
159
|
-
cwd,
|
|
160
|
-
account: { configDir: agentDir } as TurnParams['account'],
|
|
161
|
-
system: '',
|
|
162
|
-
plugins: { loading: () => plugins.loading({ cwd, agentDir }), loaded: (extensions) => plugins.loaded(extensions) },
|
|
163
|
-
...extra
|
|
164
|
-
}) satisfies Parameters<typeof loadResources>[1]
|
|
165
|
-
|
|
166
|
-
it('runs only what the harness chose, and records what each extension registered', async () => {
|
|
167
|
-
const { agentDir, cwd, plugins, markers } = workspace()
|
|
168
|
-
const pi = await import('@earendil-works/pi-coding-agent')
|
|
169
|
-
const loader = await loadResources(pi, params(cwd, agentDir, plugins), () => undefined)
|
|
170
|
-
expect(ran(markers)).toEqual({ shared: true, project: false, packaged: true })
|
|
171
|
-
expect(loader.getSkills().skills.map((skill) => skill.name).sort()).toEqual(['alpha', 'beta', 'gamma'])
|
|
172
|
-
expect(loader.getPrompts().prompts.map((prompt) => prompt.name)).toEqual(['review'])
|
|
173
|
-
expect(Object.values(plugins.registered()).map((entry) => [entry.commands, entry.hooks])).toEqual([
|
|
174
|
-
[['shared'], ['tool_call']],
|
|
175
|
-
[['packaged'], ['tool_call']]
|
|
176
|
-
])
|
|
177
|
-
|
|
178
|
-
const code = (await plugins.loading({ cwd, agentDir })).projectCode!
|
|
179
|
-
plugins.trust.grant(code, cwd)
|
|
180
|
-
await loadResources(pi, params(cwd, agentDir, plugins), () => undefined)
|
|
181
|
-
expect(ran(markers).project).toBe(true)
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
it('does not run an extension a person switched off for the caller', async () => {
|
|
185
|
-
const { agentDir, cwd, markers, base } = workspace()
|
|
186
|
-
const choices: Attachments = { version: 1, global: { on: [], off: [] }, agents: { a1: { on: [], off: ['shared/code/shared.ts'] } }, projects: {}, settings: {} }
|
|
187
|
-
const plugins = new Plugins({ stateDir: join(base, 'state'), bus: new Bus(), attachments: () => choices })
|
|
188
|
-
const pi = await import('@earendil-works/pi-coding-agent')
|
|
189
|
-
const forAgent = (agentId: string) => ({ ...params(cwd, agentDir, plugins), plugins: { loading: () => plugins.loading({ cwd, agentDir, caller: { agentId } }), loaded: () => undefined } })
|
|
190
|
-
const loader = await loadResources(pi, forAgent('a1'), () => undefined)
|
|
191
|
-
expect(ran(markers)).toEqual({ shared: false, project: false, packaged: true })
|
|
192
|
-
// Its skills are a different contribution and still load.
|
|
193
|
-
expect(loader.getSkills().skills.map((skill) => skill.name).sort()).toEqual(['alpha', 'beta', 'gamma'])
|
|
194
|
-
await loadResources(pi, forAgent('a2'), () => undefined)
|
|
195
|
-
expect(ran(markers).shared).toBe(true)
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
it('loads no extension at all for an unattended run', async () => {
|
|
199
|
-
const { agentDir, cwd, plugins, markers } = workspace()
|
|
200
|
-
const pi = await import('@earendil-works/pi-coding-agent')
|
|
201
|
-
const settings = pi.SettingsManager.inMemory({})
|
|
202
|
-
await loadResources(pi, params(cwd, agentDir, plugins, { automatic: true }), () => undefined, settings)
|
|
203
|
-
expect(ran(markers)).toEqual({ shared: false, project: false, packaged: false })
|
|
204
|
-
})
|
|
205
|
-
})
|