@xingular/harness 0.1.7 → 1.1.1
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 +125 -1
- package/LICENSE +202 -0
- package/NOTICE.md +22 -0
- package/README.md +239 -86
- package/THIRD_PARTY_LICENSES.md +942 -0
- package/dist/cli.js +17853 -13114
- 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/agents/builtin.d.ts +2 -0
- package/dist/sdk/agents/builtin.js +34 -0
- package/dist/sdk/agents/narrow.d.ts +13 -0
- package/dist/sdk/agents/narrow.js +29 -0
- package/dist/sdk/agents/profiles.d.ts +80 -0
- package/dist/sdk/agents/profiles.js +221 -0
- package/dist/sdk/annotations/bridge.d.ts +42 -0
- package/dist/sdk/annotations/bridge.js +264 -0
- package/dist/sdk/annotations/capture.d.ts +116 -0
- package/dist/sdk/annotations/capture.js +308 -0
- package/dist/sdk/annotations/delivery.d.ts +72 -0
- package/dist/sdk/annotations/delivery.js +130 -0
- package/dist/sdk/annotations/inspect.d.ts +10 -0
- package/dist/sdk/annotations/inspect.js +33 -0
- package/dist/sdk/annotations/isolated.d.ts +6 -0
- package/dist/sdk/annotations/isolated.js +51 -0
- package/dist/sdk/annotations/pageScript.d.ts +28 -0
- package/dist/sdk/annotations/pageScript.js +570 -0
- package/dist/sdk/annotations/part.d.ts +10 -0
- package/dist/sdk/annotations/part.js +144 -0
- package/dist/sdk/annotations/queue.d.ts +4 -0
- package/dist/sdk/annotations/queue.js +40 -0
- package/dist/sdk/annotations/serverMethods.d.ts +3 -0
- package/dist/sdk/annotations/serverMethods.js +62 -0
- package/dist/sdk/annotations/store.d.ts +160 -0
- package/dist/sdk/annotations/store.js +386 -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 +28 -0
- package/dist/sdk/browser/index.js +72 -0
- package/dist/sdk/browser/network.d.ts +10 -0
- package/dist/sdk/browser/network.js +59 -0
- package/dist/sdk/browser/serverMethods.d.ts +3 -0
- package/dist/sdk/browser/serverMethods.js +7 -0
- package/dist/sdk/browser/session.d.ts +85 -0
- package/dist/sdk/browser/session.js +228 -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 +150 -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/serverMethods.d.ts +3 -0
- package/dist/sdk/doctor/serverMethods.js +8 -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 +148 -0
- package/dist/sdk/harness.js +338 -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/serverMethods.d.ts +3 -0
- package/dist/sdk/history/serverMethods.js +8 -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/hub/serverMethods.d.ts +3 -0
- package/dist/sdk/hub/serverMethods.js +11 -0
- package/dist/sdk/index.d.ts +73 -0
- package/dist/sdk/index.js +55 -0
- package/dist/sdk/mcp/connections.d.ts +83 -0
- package/dist/sdk/mcp/connections.js +676 -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/serverMethods.d.ts +3 -0
- package/dist/sdk/mcp/serverMethods.js +22 -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 +7 -0
- package/dist/sdk/plugins/builtin.js +163 -0
- package/dist/sdk/plugins/builtinRegistry.d.ts +53 -0
- package/dist/sdk/plugins/builtinRegistry.js +49 -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 +188 -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 +177 -0
- package/dist/sdk/prompt/compile.js +413 -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/serverMethods.d.ts +3 -0
- package/dist/sdk/refine/serverMethods.js +20 -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 +293 -0
- package/dist/sdk/server/params.d.ts +4 -0
- package/dist/sdk/server/params.js +11 -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 +551 -0
- package/dist/sdk/sessions/contracts.js +338 -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 +39 -0
- package/dist/sdk/sessions/planMode.js +93 -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 +103 -0
- package/dist/sdk/sessions/registry.js +386 -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 +337 -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 +152 -0
- package/dist/sdk/sessions/sessions.js +461 -0
- package/dist/sdk/sessions/sideQuestionServerMethods.d.ts +3 -0
- package/dist/sdk/sessions/sideQuestionServerMethods.js +19 -0
- package/dist/sdk/sessions/sideQuestions.d.ts +66 -0
- package/dist/sdk/sessions/sideQuestions.js +290 -0
- package/dist/sdk/sessions/subagentServerMethods.d.ts +3 -0
- package/dist/sdk/sessions/subagentServerMethods.js +41 -0
- package/dist/sdk/sessions/subagentService.d.ts +52 -0
- package/dist/sdk/sessions/subagentService.js +265 -0
- package/dist/sdk/sessions/subagents.d.ts +58 -0
- package/dist/sdk/sessions/subagents.js +87 -0
- package/dist/sdk/terminal/accountsMenu.d.ts +46 -0
- package/dist/sdk/terminal/accountsMenu.js +392 -0
- package/dist/sdk/terminal/browser.d.ts +62 -0
- package/dist/sdk/terminal/browser.js +41 -0
- package/dist/sdk/terminal/browserControl.d.ts +29 -0
- package/dist/sdk/terminal/browserControl.js +186 -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/commandHelp.d.ts +17 -0
- package/dist/sdk/terminal/commandHelp.js +20 -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 +78 -0
- package/dist/sdk/terminal/controller.js +383 -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/opentui/subagentsWidget.d.ts +28 -0
- package/dist/sdk/terminal/opentui/subagentsWidget.js +52 -0
- package/dist/sdk/terminal/piExtension.d.ts +6 -0
- package/dist/sdk/terminal/piExtension.js +377 -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 +73 -0
- package/dist/sdk/terminal/socket.js +287 -0
- package/dist/sdk/terminal/standalone.d.ts +20 -0
- package/dist/sdk/terminal/standalone.js +186 -0
- package/dist/sdk/terminal/subagentMonitor.d.ts +38 -0
- package/dist/sdk/terminal/subagentMonitor.js +121 -0
- package/dist/sdk/terminal/terminals.d.ts +212 -0
- package/dist/sdk/terminal/terminals.js +1108 -0
- package/dist/sdk/terminal/trajectory.d.ts +10 -0
- package/dist/sdk/terminal/trajectory.js +30 -0
- package/dist/sdk/terminal/tui/annotateCommand.d.ts +3 -0
- package/dist/sdk/terminal/tui/annotateCommand.js +22 -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 +11 -0
- package/dist/sdk/terminal/tui/commandPages.js +111 -0
- package/dist/sdk/terminal/tui/commands.d.ts +46 -0
- package/dist/sdk/terminal/tui/commands.js +399 -0
- package/dist/sdk/terminal/tui/dialogGeometry.d.ts +27 -0
- package/dist/sdk/terminal/tui/dialogGeometry.js +52 -0
- package/dist/sdk/terminal/tui/dialogs.d.ts +80 -0
- package/dist/sdk/terminal/tui/dialogs.js +370 -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 +150 -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 +17 -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 +156 -0
- package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +76 -0
- package/dist/sdk/terminal/tui/pages/accountsPage.js +409 -0
- package/dist/sdk/terminal/tui/pages/agentsPage.d.ts +74 -0
- package/dist/sdk/terminal/tui/pages/agentsPage.js +190 -0
- package/dist/sdk/terminal/tui/pages/annotatePage.d.ts +94 -0
- package/dist/sdk/terminal/tui/pages/annotatePage.js +341 -0
- package/dist/sdk/terminal/tui/pages/browserPage.d.ts +87 -0
- package/dist/sdk/terminal/tui/pages/browserPage.js +738 -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 +39 -0
- package/dist/sdk/terminal/tui/pages/doctorPage.js +233 -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/notesPage.d.ts +75 -0
- package/dist/sdk/terminal/tui/pages/notesPage.js +201 -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 +63 -0
- package/dist/sdk/terminal/tui/pages/settingsPage.js +103 -0
- package/dist/sdk/terminal/tui/pages/subagentsPage.d.ts +23 -0
- package/dist/sdk/terminal/tui/pages/subagentsPage.js +70 -0
- package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +65 -0
- package/dist/sdk/terminal/tui/pages/trajectoryPage.js +450 -0
- package/dist/sdk/terminal/tui/pages/worktreesPage.d.ts +72 -0
- package/dist/sdk/terminal/tui/pages/worktreesPage.js +203 -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/pluginCommands.d.ts +14 -0
- package/dist/sdk/terminal/tui/pluginCommands.js +27 -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 +21 -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 +443 -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 +14 -0
- package/dist/sdk/terminal/tui/settingsModel.js +114 -0
- package/dist/sdk/terminal/tui/sideQuestion.d.ts +53 -0
- package/dist/sdk/terminal/tui/sideQuestion.js +230 -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 +49 -0
- package/dist/sdk/terminal/tui/ui.js +149 -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 +92 -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 +8 -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 +58 -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/part.d.ts +10 -0
- package/dist/sdk/web/part.js +6 -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/serverMethods.d.ts +3 -0
- package/dist/sdk/web/serverMethods.js +7 -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/wiki/serverMethods.d.ts +3 -0
- package/dist/sdk/wiki/serverMethods.js +26 -0
- package/dist/sdk/worktrees/cli.d.ts +11 -0
- package/dist/sdk/worktrees/cli.js +146 -0
- package/dist/sdk/worktrees/copy.d.ts +9 -0
- package/dist/sdk/worktrees/copy.js +111 -0
- package/dist/sdk/worktrees/git.d.ts +16 -0
- package/dist/sdk/worktrees/git.js +81 -0
- package/dist/sdk/worktrees/serverMethods.d.ts +3 -0
- package/dist/sdk/worktrees/serverMethods.js +30 -0
- package/dist/sdk/worktrees/service.d.ts +73 -0
- package/dist/sdk/worktrees/service.js +483 -0
- package/dist/sdk/worktrees/setup.d.ts +23 -0
- package/dist/sdk/worktrees/setup.js +65 -0
- package/dist/sdk/worktrees/types.d.ts +91 -0
- package/dist/sdk/worktrees/types.js +1 -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 +67 -0
- package/dist/sdk/world/world.js +79 -0
- package/dist/terminal-opentui.js +20778 -0
- package/dist/terminal-pi.js +794 -518
- package/docs/README.md +42 -0
- package/docs/architecture/00-overview.md +171 -0
- package/docs/architecture/01-extension-points.md +78 -0
- package/docs/architecture/02-sessions-and-runs.md +203 -0
- package/docs/architecture/03-variants.md +103 -0
- package/docs/architecture/04-prompt.md +122 -0
- package/docs/architecture/05-refinement.md +107 -0
- package/docs/architecture/06-plugins-and-capabilities.md +129 -0
- package/docs/architecture/07-tools-and-gate.md +103 -0
- package/docs/architecture/08-memory-and-history.md +94 -0
- package/docs/architecture/09-accounts-and-connectors.md +98 -0
- package/docs/architecture/10-server-protocol.md +193 -0
- package/docs/architecture/11-terminal.md +261 -0
- package/docs/architecture/12-storage.md +75 -0
- package/docs/architecture/13-world-tools.md +45 -0
- package/docs/architecture/14-surfaces-and-parity.md +89 -0
- package/docs/architecture/README.md +125 -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 +70 -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/PROP-0013-resource-browser.md +58 -0
- package/docs/architecture/proposals/PROP-0014-fullscreen-browser-tabs.md +58 -0
- package/docs/architecture/proposals/PROP-0015-one-capability-surface.md +88 -0
- package/docs/architecture/proposals/PROP-0016-managed-worktrees.md +156 -0
- package/docs/architecture/proposals/PROP-0017-page-annotations.md +127 -0
- package/docs/architecture/proposals/PROP-0018-annotation-queue-and-app-targets.md +179 -0
- package/docs/architecture/proposals/PROP-0019-contextual-side-questions.md +122 -0
- package/docs/architecture/proposals/PROP-0020-builtin-feature-plugins.md +105 -0
- package/docs/architecture/proposals/PROP-0021-command-namespaces-and-duplicates.md +99 -0
- package/docs/architecture/proposals/PROP-0022-plan-only-questions.md +102 -0
- package/docs/architecture/proposals/PROP-0023-xagent-cli-name.md +61 -0
- package/docs/architecture/proposals/PROP-0024-question-sketch-previews.md +130 -0
- package/docs/architecture/proposals/PROP-0025-contextual-question-wireframes.md +49 -0
- package/docs/architecture/proposals/PROP-0026-connected-sketch-display.md +94 -0
- package/docs/architecture/proposals/PROP-0027-xingular-agent-product-identity.md +60 -0
- package/docs/architecture/proposals/PROP-0028-normalize-question-wireframes.md +55 -0
- package/docs/architecture/proposals/PROP-0029-agent-profiles.md +124 -0
- package/docs/architecture/proposals/PROP-0030-subagent-title.md +86 -0
- package/docs/architecture/proposals/README.md +101 -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 +39 -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 +22 -0
- package/docs/decisions/ADR-0015-resource-browser.md +28 -0
- package/docs/decisions/ADR-0016-fullscreen-browser-tabs.md +31 -0
- package/docs/decisions/ADR-0017-one-capability-surface.md +34 -0
- package/docs/decisions/ADR-0018-builtin-feature-plugins.md +35 -0
- package/docs/decisions/ADR-0019-managed-git-worktrees.md +31 -0
- package/docs/decisions/ADR-0020-page-annotations.md +37 -0
- package/docs/decisions/ADR-0021-required-command-namespaces.md +40 -0
- package/docs/decisions/ADR-0022-plan-only-question-tools.md +34 -0
- package/docs/decisions/ADR-0023-contextual-side-question-runs.md +35 -0
- package/docs/decisions/ADR-0024-xagent-command.md +40 -0
- package/docs/decisions/ADR-0025-question-choice-sketches.md +49 -0
- package/docs/decisions/ADR-0026-contextual-question-wireframes.md +58 -0
- package/docs/decisions/ADR-0027-connected-sketch-display.md +60 -0
- package/docs/decisions/ADR-0028-xingular-agent-product-identity.md +56 -0
- package/docs/decisions/ADR-0029-normalized-question-wireframe-borders.md +33 -0
- package/docs/decisions/ADR-0030-agent-profiles.md +43 -0
- package/docs/doctor.md +80 -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 +46 -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/future-work.md +48 -0
- package/docs/parity.md +78 -0
- package/docs/releases/1.0.0.md +40 -0
- package/docs/releases/4.0.0.md +46 -0
- package/docs/releases/README.md +41 -0
- package/docs/study/00-index.md +83 -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/autonomous-engineering-sources.md +277 -0
- package/docs/study/autonomy-sources.md +147 -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/proactive-autonomy.md +408 -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/study/tui-resource-browser.md +78 -0
- package/docs/system-prompt-design.md +196 -0
- package/docs/terminal-tui.md +707 -58
- 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/skills/registry.ts
DELETED
|
@@ -1,413 +0,0 @@
|
|
|
1
|
-
// Canonical skills, prompts, and rules under `<data root>/registry/`. Each item is a Markdown
|
|
2
|
-
// file (a skill may also be a folder with `SKILL.md`) with optional `name`/`description`
|
|
3
|
-
// frontmatter. These files are the single source of truth. Items are enabled globally and per
|
|
4
|
-
// project; enabled items are loaded automatically, and any item can be retrieved on demand.
|
|
5
|
-
//
|
|
6
|
-
// Built-in items ship with the harness or the application that embeds it, in folders laid out
|
|
7
|
-
// like `registry/`. They are read-only and on everywhere until a person switches one off; an
|
|
8
|
-
// item of the same id in the data root replaces the built-in one.
|
|
9
|
-
import { lstatSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, renameSync, rmSync, unlinkSync, writeFileSync } from 'node:fs'
|
|
10
|
-
import { basename, dirname, join } from 'node:path'
|
|
11
|
-
|
|
12
|
-
import { invalid } from '../core/errors'
|
|
13
|
-
import * as frontmatter from '../core/frontmatter'
|
|
14
|
-
import { atomicWrite, now, readJsonOr, safeRelative } from '../core/fs'
|
|
15
|
-
import { findProject } from '../core/projects'
|
|
16
|
-
import { compareText, lines, takeChars } from '../core/text'
|
|
17
|
-
import * as store from '../memory/store'
|
|
18
|
-
import * as attachments from '../plugins/attachments'
|
|
19
|
-
|
|
20
|
-
export const KINDS = ['skills', 'prompts', 'rules'] as const
|
|
21
|
-
export type RegistryKind = (typeof KINDS)[number]
|
|
22
|
-
|
|
23
|
-
export interface RegistryItem {
|
|
24
|
-
/** `<kind>/<name>`, stable across edits. */
|
|
25
|
-
id: string
|
|
26
|
-
kind: string
|
|
27
|
-
name: string
|
|
28
|
-
description: string
|
|
29
|
-
path: string
|
|
30
|
-
/** Set on an item that ships with the harness or the application, not on a person's own. */
|
|
31
|
-
builtin?: true
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** The capability id used when this registry item is shown in the plugin catalogue. */
|
|
35
|
-
export function contributionId(item: Pick<RegistryItem, 'id' | 'builtin'>): string {
|
|
36
|
-
return `${item.builtin ? 'included' : 'yours'}/${item.id}`
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Limits registry items to the contributions frozen for a run. `undefined` means no limit. */
|
|
40
|
-
export function limitToContributions(items: readonly RegistryItem[], contributions?: readonly string[]): RegistryItem[] {
|
|
41
|
-
if (contributions === undefined) return [...items]
|
|
42
|
-
const allowed = new Set(contributions)
|
|
43
|
-
return items.filter((item) => allowed.has(contributionId(item)))
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface SkillBundleInput {
|
|
47
|
-
name: string
|
|
48
|
-
files: { path: string; content: string; encoding: 'utf8' | 'base64' }[]
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const MAX_SKILL_BUNDLES = 20
|
|
52
|
-
const MAX_SKILL_FILES = 100
|
|
53
|
-
const MAX_SKILL_IMPORT_BYTES = 10 * 1024 * 1024
|
|
54
|
-
|
|
55
|
-
let builtinDirs: string[] = []
|
|
56
|
-
|
|
57
|
-
/** The folders built-in items are read from, each laid out like `registry/`. Later folders win. */
|
|
58
|
-
export function configureBuiltins(directories: readonly string[]): void {
|
|
59
|
-
builtinDirs = [...directories]
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function itemFrom(kind: string, stem: string, file: string): RegistryItem | null {
|
|
63
|
-
let text: string
|
|
64
|
-
try {
|
|
65
|
-
text = readFileSync(file, 'utf8')
|
|
66
|
-
} catch {
|
|
67
|
-
return null
|
|
68
|
-
}
|
|
69
|
-
const parsed = frontmatter.parse(text)
|
|
70
|
-
const name = parsed?.front.name
|
|
71
|
-
const description = parsed?.front.description
|
|
72
|
-
// A frontmatter block whose name or description is not text is treated as no frontmatter.
|
|
73
|
-
const usable = parsed !== null && (name === undefined || name === null || typeof name === 'string') && (description === undefined || description === null || typeof description === 'string')
|
|
74
|
-
const body = usable ? parsed.body : text
|
|
75
|
-
return {
|
|
76
|
-
id: `${kind}/${stem}`,
|
|
77
|
-
kind,
|
|
78
|
-
name: usable && typeof name === 'string' ? name : stem.replace(/[-_]/g, ' '),
|
|
79
|
-
description: usable && typeof description === 'string' ? description : takeChars(lines(body).find((line) => line.trim() && !line.startsWith('#')) ?? '', 160),
|
|
80
|
-
path: file
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const stemOf = (name: string): string => (name.lastIndexOf('.') > 0 ? name.slice(0, name.lastIndexOf('.')) : name)
|
|
85
|
-
|
|
86
|
-
/** The name and description of a skill or prompt file anywhere on disk, read the way a registry item is. */
|
|
87
|
-
export function describeFile(file: string): { name: string; description: string } | null {
|
|
88
|
-
const stem = basename(file) === 'SKILL.md' ? basename(dirname(file)) : stemOf(basename(file))
|
|
89
|
-
const item = itemFrom('', stem, file)
|
|
90
|
-
return item && { name: item.name, description: item.description }
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function itemsIn(directory: string): RegistryItem[] {
|
|
94
|
-
const items: RegistryItem[] = []
|
|
95
|
-
for (const kind of KINDS) {
|
|
96
|
-
let names: string[]
|
|
97
|
-
try {
|
|
98
|
-
names = readdirSync(join(directory, kind))
|
|
99
|
-
} catch {
|
|
100
|
-
continue
|
|
101
|
-
}
|
|
102
|
-
for (const name of names) {
|
|
103
|
-
const path = join(directory, kind, name)
|
|
104
|
-
const stem = stemOf(name)
|
|
105
|
-
if (stem.startsWith('.')) continue
|
|
106
|
-
const file = store.isDir(path) ? join(path, 'SKILL.md') : name.endsWith('.md') ? path : null
|
|
107
|
-
const item = file && itemFrom(kind, stem, file)
|
|
108
|
-
if (item) items.push(item)
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return items
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function list(root: string): RegistryItem[] {
|
|
115
|
-
const items = new Map<string, RegistryItem>()
|
|
116
|
-
for (const directory of builtinDirs) for (const item of itemsIn(directory)) items.set(item.id, { ...item, builtin: true })
|
|
117
|
-
for (const item of itemsIn(join(root, 'registry'))) items.set(item.id, item)
|
|
118
|
-
return [...items.values()].sort((left, right) => compareText(left.id, right.id))
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function enablementPath(root: string): string {
|
|
122
|
-
return join(root, 'config/registry-enabled.json')
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/** Key for items enabled everywhere. Older data roots used `personal`, which is read the same way. */
|
|
126
|
-
export const GLOBAL_KEY = 'global'
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* The registry's earlier enablement file as it is on disk: ids keyed by project id, or `global`
|
|
130
|
-
* for everyone. The choices now live with every other plugin's (`plugins/attachments.ts`), which
|
|
131
|
-
* reads this file until the first change is saved.
|
|
132
|
-
*/
|
|
133
|
-
export function enablement(root: string): Record<string, unknown> {
|
|
134
|
-
const map = readJsonOr<unknown>(enablementPath(root), {})
|
|
135
|
-
return map && typeof map === 'object' && !Array.isArray(map) ? (map as Record<string, unknown>) : {}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export function enablementIds(map: Record<string, unknown>, key: string): string[] {
|
|
139
|
-
const ids = map[key]
|
|
140
|
-
return Array.isArray(ids) ? ids.filter((id): id is string => typeof id === 'string') : []
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/** Built-in items a person switched off. Everything else built in is on everywhere. */
|
|
144
|
-
export const BUILTIN_OFF_KEY = 'builtinOff'
|
|
145
|
-
|
|
146
|
-
/** Whether an id names a registry item, as `<kind>/<name>`. */
|
|
147
|
-
export const isItemId = (id: string): boolean => KINDS.some((kind) => id.startsWith(`${kind}/`))
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Items active for a caller. A built-in is on until it is switched off; a person's own is off
|
|
151
|
-
* until it is switched on, everywhere, for the caller's project, or for the calling agent.
|
|
152
|
-
*/
|
|
153
|
-
export function enabledFor(root: string, projectId: string | null, agentId: string | null = null, contributions?: readonly string[]): RegistryItem[] {
|
|
154
|
-
if (contributions !== undefined) return limitToContributions(list(root), contributions)
|
|
155
|
-
const choices = attachments.load(root)
|
|
156
|
-
return list(root).filter((item) => attachments.attached(choices, [item.id], { agentId, projectId }, !!item.builtin))
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/** An item's Markdown body without frontmatter. */
|
|
160
|
-
export function itemBody(item: RegistryItem): string {
|
|
161
|
-
try {
|
|
162
|
-
const text = readFileSync(item.path, 'utf8')
|
|
163
|
-
return frontmatter.split(text)?.body ?? text
|
|
164
|
-
} catch {
|
|
165
|
-
return ''
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export interface RegistryResources {
|
|
170
|
-
ids: string[]
|
|
171
|
-
skillPaths: string[]
|
|
172
|
-
promptPaths: string[]
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/** What a Pi session needs to load enabled items natively. Rule text reaches the model through the compiled prompt. */
|
|
176
|
-
export function resources(root: string, projectId: string | null, agentId: string | null = null, contributions?: readonly string[]): RegistryResources {
|
|
177
|
-
const items = enabledFor(root, projectId, agentId, contributions)
|
|
178
|
-
return {
|
|
179
|
-
ids: items.map((item) => item.id),
|
|
180
|
-
skillPaths: items.filter((item) => item.kind === 'skills').map((item) => item.path),
|
|
181
|
-
promptPaths: items.filter((item) => item.kind === 'prompts').map((item) => item.path)
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Prefix of the entries an earlier version of the harness linked into a Pi agent folder's `skills/`.
|
|
186
|
-
const LINKED_SKILL_PREFIX = 'agentx-'
|
|
187
|
-
|
|
188
|
-
function isLinkedSkill(path: string): boolean {
|
|
189
|
-
let meta
|
|
190
|
-
try {
|
|
191
|
-
meta = lstatSync(path)
|
|
192
|
-
} catch {
|
|
193
|
-
return false
|
|
194
|
-
}
|
|
195
|
-
if (meta.isSymbolicLink()) return true
|
|
196
|
-
if (!meta.isDirectory()) return false
|
|
197
|
-
// A single-file skill was linked as `agentx-<name>/SKILL.md` inside a folder the harness made.
|
|
198
|
-
try {
|
|
199
|
-
const entries = readdirSync(path)
|
|
200
|
-
return entries.length === 1 && entries[0] === 'SKILL.md' && lstatSync(join(path, 'SKILL.md')).isSymbolicLink()
|
|
201
|
-
} catch {
|
|
202
|
-
return false
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Removes the `agentx-<name>` links an earlier version kept in a terminal session's `skills/`
|
|
208
|
-
* folder, leaving the user's own skills alone. Enabled skills now reach a session as paths.
|
|
209
|
-
*/
|
|
210
|
-
export function removeLinkedSkills(skillsDir: string): void {
|
|
211
|
-
let names: string[]
|
|
212
|
-
try {
|
|
213
|
-
names = readdirSync(skillsDir)
|
|
214
|
-
} catch {
|
|
215
|
-
return
|
|
216
|
-
}
|
|
217
|
-
for (const name of names) {
|
|
218
|
-
const path = join(skillsDir, name)
|
|
219
|
-
if (!name.startsWith(LINKED_SKILL_PREFIX) || !isLinkedSkill(path)) continue
|
|
220
|
-
if (lstatSync(path).isSymbolicLink()) unlinkSync(path)
|
|
221
|
-
else rmSync(path, { recursive: true, force: true })
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
export interface RegistryState {
|
|
226
|
-
items: RegistryItem[]
|
|
227
|
-
enabled: Record<string, unknown>
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Enablement as a person sees it, in the earlier file's shape: ids keyed by project id, `global`
|
|
232
|
-
* for everyone (built-ins that are on count as enabled everywhere), and the built-ins switched off.
|
|
233
|
-
*/
|
|
234
|
-
function shown(items: readonly RegistryItem[], choices: attachments.Attachments): Record<string, unknown> {
|
|
235
|
-
const builtin = items.filter((item) => item.builtin).map((item) => item.id)
|
|
236
|
-
const off = choices.global.off.filter((id) => builtin.includes(id))
|
|
237
|
-
const global = choices.global.on.filter((id) => isItemId(id) && !builtin.includes(id))
|
|
238
|
-
const map: Record<string, unknown> = { [GLOBAL_KEY]: [...global, ...builtin.filter((id) => !off.includes(id))] }
|
|
239
|
-
for (const [projectId, entries] of Object.entries(choices.projects)) map[projectId] = entries.on.filter(isItemId)
|
|
240
|
-
if (off.length) map[BUILTIN_OFF_KEY] = off
|
|
241
|
-
return map
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export function state(root: string): RegistryState {
|
|
245
|
-
const items = list(root)
|
|
246
|
-
return { items, enabled: shown(items, attachments.load(root)) }
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/** Sets enabled items for a project, or globally when `projectId` is `null`. */
|
|
250
|
-
export function setEnabled(root: string, projectId: string | null, ids: string[]): RegistryState {
|
|
251
|
-
if (projectId) findProject(root, projectId)
|
|
252
|
-
const items = list(root)
|
|
253
|
-
const unknown = ids.find((id) => !items.some((item) => item.id === id))
|
|
254
|
-
if (unknown !== undefined) throw invalid(`Unknown registry item ${unknown}.`)
|
|
255
|
-
const builtin = items.filter((item) => item.builtin).map((item) => item.id)
|
|
256
|
-
const choices = attachments.load(root)
|
|
257
|
-
const entries = projectId ? (choices.projects[projectId] ??= { on: [], off: [] }) : choices.global
|
|
258
|
-
// Only the registry's own ids are replaced; other plugins' choices in the same scope stay.
|
|
259
|
-
entries.on = [...entries.on.filter((id) => !isItemId(id)), ...ids.filter((id) => !builtin.includes(id))]
|
|
260
|
-
entries.off = entries.off.filter((id) => !isItemId(id) || (!ids.includes(id) && !(!projectId && builtin.includes(id))))
|
|
261
|
-
// A built-in left out of the global list was switched off.
|
|
262
|
-
if (!projectId) entries.off.push(...builtin.filter((id) => !ids.includes(id)))
|
|
263
|
-
attachments.save(root, choices)
|
|
264
|
-
return { items, enabled: shown(items, choices) }
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
function kindDir(root: string, kind: string): string {
|
|
268
|
-
if (!(KINDS as readonly string[]).includes(kind)) throw invalid('Unknown registry kind.')
|
|
269
|
-
return join(root, 'registry', kind)
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/** Creates a starter item from a name: a Markdown file, or a skill folder with `SKILL.md`. */
|
|
273
|
-
export function create(root: string, kind: string, rawName: string): RegistryState {
|
|
274
|
-
const directory = kindDir(root, kind)
|
|
275
|
-
const name = rawName.trim()
|
|
276
|
-
const slug = Array.from(name.toLowerCase(), (character) => (/^[a-z0-9]$/.test(character) ? character : '-')).join('').split('-').filter(Boolean).join('-')
|
|
277
|
-
if (!slug || slug.length > 64) throw invalid('Use a short name with letters or numbers.')
|
|
278
|
-
const description = 'Describe when to use this.'
|
|
279
|
-
const target = kind === 'skills' ? join(directory, slug) : join(directory, `${slug}.md`)
|
|
280
|
-
let exists = true
|
|
281
|
-
try {
|
|
282
|
-
lstatSync(target)
|
|
283
|
-
} catch {
|
|
284
|
-
exists = false
|
|
285
|
-
}
|
|
286
|
-
if (exists) throw invalid('An item with that name already exists.')
|
|
287
|
-
if (kind === 'skills') atomicWrite(join(target, 'SKILL.md'), `---\nname: ${slug}\ndescription: ${description}\n---\n\n# ${name}\n\nSteps the agent should follow.\n`)
|
|
288
|
-
else atomicWrite(target, `---\nname: ${name}\ndescription: ${description}\n---\n\n`)
|
|
289
|
-
return state(root)
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/** Imports complete user-owned skill folders without replacing existing or built-in items. */
|
|
293
|
-
export function importSkills(root: string, bundles: SkillBundleInput[]): RegistryState {
|
|
294
|
-
return importItems(root, 'skills', bundles)
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/** Imports inert registry resources. Prompts and rules are single UTF-8 Markdown documents. */
|
|
298
|
-
export function importItems(root: string, kind: RegistryKind, bundles: SkillBundleInput[]): RegistryState {
|
|
299
|
-
if (!Array.isArray(bundles) || bundles.length === 0 || bundles.length > MAX_SKILL_BUNDLES) {
|
|
300
|
-
throw invalid(`Import between 1 and ${MAX_SKILL_BUNDLES} skills at a time.`)
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
const directory = kindDir(root, kind)
|
|
304
|
-
mkdirSync(directory, { recursive: true })
|
|
305
|
-
const existing = new Set(list(root).map((item) => item.id))
|
|
306
|
-
const seen = new Set<string>()
|
|
307
|
-
let totalBytes = 0
|
|
308
|
-
const prepared = bundles.map((bundle) => {
|
|
309
|
-
if (!bundle || typeof bundle.name !== 'string' || !Array.isArray(bundle.files) || bundle.files.length === 0 || bundle.files.length > MAX_SKILL_FILES) {
|
|
310
|
-
throw invalid('Each skill needs a name and a bounded list of files.')
|
|
311
|
-
}
|
|
312
|
-
const name = bundle.name.trim()
|
|
313
|
-
if (name.length > 64) throw invalid('Use a skill name with at most 64 letters or numbers.')
|
|
314
|
-
const slug = Array.from(name.toLowerCase(), (character) => (/^[a-z0-9]$/.test(character) ? character : '-')).join('').split('-').filter(Boolean).join('-')
|
|
315
|
-
if (!slug || slug.length > 64) throw invalid('Use a skill name with at most 64 letters or numbers.')
|
|
316
|
-
const id = `${kind}/${slug}`
|
|
317
|
-
if (existing.has(id) || seen.has(id)) throw invalid(`The skill “${name}” already exists.`)
|
|
318
|
-
try {
|
|
319
|
-
lstatSync(join(directory, kind === 'skills' ? slug : `${slug}.md`))
|
|
320
|
-
throw invalid(`The skill “${name}” already exists.`)
|
|
321
|
-
} catch (error) {
|
|
322
|
-
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error
|
|
323
|
-
}
|
|
324
|
-
seen.add(id)
|
|
325
|
-
|
|
326
|
-
const files = new Map<string, Uint8Array>()
|
|
327
|
-
for (const file of bundle.files) {
|
|
328
|
-
if (!file || typeof file.path !== 'string' || file.path.length > 240 || typeof file.content !== 'string' || !['utf8', 'base64'].includes(file.encoding)) {
|
|
329
|
-
throw invalid(`The skill “${name}” contains an invalid file.`)
|
|
330
|
-
}
|
|
331
|
-
let relative: string
|
|
332
|
-
try {
|
|
333
|
-
relative = safeRelative(file.path)
|
|
334
|
-
} catch {
|
|
335
|
-
throw invalid(`The skill “${name}” contains a path outside its folder.`)
|
|
336
|
-
}
|
|
337
|
-
if (relative.includes('\0') || relative.split('/').some((part) => part.startsWith('.') || part.includes(':'))) {
|
|
338
|
-
throw invalid(`The skill “${name}” contains an unsupported file path.`)
|
|
339
|
-
}
|
|
340
|
-
const portablePath = relative.normalize('NFC').toLowerCase()
|
|
341
|
-
if ([...files.keys()].some((path) => path.normalize('NFC').toLowerCase() === portablePath)) throw invalid(`The skill “${name}” contains a duplicate file path.`)
|
|
342
|
-
let byteLength: number
|
|
343
|
-
if (file.encoding === 'base64') {
|
|
344
|
-
if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(file.content)) {
|
|
345
|
-
throw invalid(`The file “${relative}” is not valid base64.`)
|
|
346
|
-
}
|
|
347
|
-
if (file.content.length > Math.ceil(MAX_SKILL_IMPORT_BYTES / 3) * 4) throw invalid('The skill import is larger than 10 MiB.')
|
|
348
|
-
byteLength = Math.floor(file.content.length * 3 / 4) - (file.content.endsWith('==') ? 2 : file.content.endsWith('=') ? 1 : 0)
|
|
349
|
-
} else {
|
|
350
|
-
byteLength = Buffer.byteLength(file.content, 'utf8')
|
|
351
|
-
}
|
|
352
|
-
totalBytes += byteLength
|
|
353
|
-
if (totalBytes > MAX_SKILL_IMPORT_BYTES) throw invalid('The skill import is larger than 10 MiB.')
|
|
354
|
-
const bytes = file.encoding === 'base64' ? Buffer.from(file.content, 'base64') : Buffer.from(file.content, 'utf8')
|
|
355
|
-
if (file.encoding === 'base64' && bytes.toString('base64') !== file.content) throw invalid(`The file “${relative}” is not valid base64.`)
|
|
356
|
-
files.set(relative, bytes)
|
|
357
|
-
}
|
|
358
|
-
if (kind === 'skills' && !files.has('SKILL.md')) throw invalid(`The skill “${name}” must include SKILL.md at its root.`)
|
|
359
|
-
if (kind !== 'skills' && (bundle.files.length !== 1 || bundle.files[0].encoding !== 'utf8' || bundle.files[0].path !== 'CONTENT.md')) throw invalid('A prompt or rule must contain one UTF-8 CONTENT.md file.')
|
|
360
|
-
return { name, slug, files }
|
|
361
|
-
})
|
|
362
|
-
|
|
363
|
-
const staging = mkdtempSync(join(directory, '.agent-template-import-'))
|
|
364
|
-
const installed: string[] = []
|
|
365
|
-
try {
|
|
366
|
-
for (const bundle of prepared) {
|
|
367
|
-
const target = join(staging, bundle.slug)
|
|
368
|
-
for (const [relative, bytes] of bundle.files) {
|
|
369
|
-
const path = join(target, ...relative.split('/'))
|
|
370
|
-
mkdirSync(dirname(path), { recursive: true })
|
|
371
|
-
writeFileSync(path, bytes, { flag: 'wx' })
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
for (const bundle of prepared) {
|
|
375
|
-
const target = join(directory, kind === 'skills' ? bundle.slug : `${bundle.slug}.md`)
|
|
376
|
-
renameSync(kind === 'skills' ? join(staging, bundle.slug) : join(staging, bundle.slug, 'CONTENT.md'), target)
|
|
377
|
-
installed.push(target)
|
|
378
|
-
}
|
|
379
|
-
} catch (error) {
|
|
380
|
-
for (const target of installed) rmSync(target, { recursive: true, force: true })
|
|
381
|
-
throw error
|
|
382
|
-
} finally {
|
|
383
|
-
rmSync(staging, { recursive: true, force: true })
|
|
384
|
-
}
|
|
385
|
-
return state(root)
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* Writes a skill, prompt, or rule (an accepted proposal), keeping an existing item's location.
|
|
390
|
-
* The previous content and the new content are recorded as Wiki revisions of the item.
|
|
391
|
-
*/
|
|
392
|
-
export function writeItem(root: string, kind: string, name: string, description: string, body: string, reason: string, actor = 'user'): string {
|
|
393
|
-
const plural = kind === 'skill' ? 'skills' : kind === 'prompt' ? 'prompts' : kind === 'rule' ? 'rules' : null
|
|
394
|
-
if (!plural) throw invalid('Only skills, prompts, and rules can be written.')
|
|
395
|
-
const stem = store.slug(name)
|
|
396
|
-
const id = `${plural}/${stem}`
|
|
397
|
-
const existing = list(root).find((item) => item.id === id)
|
|
398
|
-
// A built-in is never edited in place: the accepted text becomes the person's own item.
|
|
399
|
-
const path = existing && !existing.builtin ? existing.path : plural === 'skills' ? join(kindDir(root, plural), stem, 'SKILL.md') : join(kindDir(root, plural), `${stem}.md`)
|
|
400
|
-
const text = frontmatter.serialize({ name: plural === 'skills' ? stem : name.trim(), ...(description.trim() ? { description: description.trim() } : {}) }, body)
|
|
401
|
-
const wiki = store.wikiDir(root)
|
|
402
|
-
if (existing) {
|
|
403
|
-
try {
|
|
404
|
-
store.snapshot(wiki, id, readFileSync(existing.path, 'utf8'), actor, 'Before accepted proposal')
|
|
405
|
-
} catch {
|
|
406
|
-
// Nothing readable to keep.
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
atomicWrite(path, text)
|
|
410
|
-
store.snapshot(wiki, id, text, actor, reason)
|
|
411
|
-
store.log(wiki, `- ${now()} · ${actor} · ${existing ? 'updated' : 'created'} \`${id}\` · ${reason}`)
|
|
412
|
-
return id
|
|
413
|
-
}
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import { mkdtempSync } from 'node:fs'
|
|
2
|
-
import { tmpdir } from 'node:os'
|
|
3
|
-
import { join } from 'node:path'
|
|
4
|
-
import { afterEach, describe, expect, it } from 'vitest'
|
|
5
|
-
|
|
6
|
-
import type { AccountsOverview, AccountView } from '../accounts/store'
|
|
7
|
-
import { memorySecretStore } from '../accounts/secrets'
|
|
8
|
-
import { createHarness, type Harness } from '../harness'
|
|
9
|
-
import { rootWithProject, writeFile } from '../../tests/helpers'
|
|
10
|
-
import { SOCKET_ENV, TOKEN_ENV, socketCall, type SocketConnection } from './client'
|
|
11
|
-
import { accountDetails, accountRows, resetIn, runAccountsMenu, type AccountsCall, type AccountsUi, type SessionAccount } from './accountsMenu'
|
|
12
|
-
|
|
13
|
-
const open: Harness[] = []
|
|
14
|
-
afterEach(async () => {
|
|
15
|
-
for (const harness of open.splice(0)) await harness.close()
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* A person at the terminal. Each answer picks the first option that contains it (select), or
|
|
20
|
-
* is the typed text (input), or is the yes/no (confirm). A select with no matching option fails
|
|
21
|
-
* the test, so a changed menu label shows up here.
|
|
22
|
-
*/
|
|
23
|
-
function person(answers: (string | boolean | undefined)[]) {
|
|
24
|
-
const shown: string[] = []
|
|
25
|
-
const said: { message: string; level?: string }[] = []
|
|
26
|
-
const next = () => answers.shift()
|
|
27
|
-
const ui: AccountsUi = {
|
|
28
|
-
select: async (title, options) => {
|
|
29
|
-
shown.push(title)
|
|
30
|
-
const answer = next()
|
|
31
|
-
if (answer === undefined) return undefined
|
|
32
|
-
const found = options.find((option) => option.includes(String(answer)))
|
|
33
|
-
if (!found) throw new Error(`No option containing "${answer}" in: ${options.join(' | ')}`)
|
|
34
|
-
return found
|
|
35
|
-
},
|
|
36
|
-
confirm: async (title) => {
|
|
37
|
-
shown.push(title)
|
|
38
|
-
return next() === true
|
|
39
|
-
},
|
|
40
|
-
input: async (title) => {
|
|
41
|
-
shown.push(title)
|
|
42
|
-
const answer = next()
|
|
43
|
-
return typeof answer === 'string' ? answer : undefined
|
|
44
|
-
},
|
|
45
|
-
notify: (message, level) => void said.push({ message, level })
|
|
46
|
-
}
|
|
47
|
-
return { ui, shown, said, remaining: () => answers.length }
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function view(id: string, label: string, overrides: Partial<AccountView> = {}): AccountView {
|
|
51
|
-
return {
|
|
52
|
-
id,
|
|
53
|
-
provider: 'pi',
|
|
54
|
-
label,
|
|
55
|
-
authKind: 'subscription',
|
|
56
|
-
createdAt: '2026-10-01T00:00:00.000Z',
|
|
57
|
-
isDefault: false,
|
|
58
|
-
state: { health: 'unknown', signedIn: null, authMethod: null, plan: null, identity: null, limits: [], lastError: null, lastCheckedAt: null, cliVersion: null, capabilities: [], piProviders: [] },
|
|
59
|
-
...overrides
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
describe('the accounts menu, without a terminal', () => {
|
|
64
|
-
it('numbers each account, marks the default and this session, and shows its health', () => {
|
|
65
|
-
const overview: AccountsOverview = {
|
|
66
|
-
accounts: [view('a1', 'Main', { isDefault: true, state: { ...view('a1', 'Main').state, health: 'limited' } }), view('a2', 'Spare')],
|
|
67
|
-
pools: [],
|
|
68
|
-
defaults: { pi: 'a1' }
|
|
69
|
-
}
|
|
70
|
-
const rows = accountRows(overview, { accountId: 'a2', label: 'Spare' } satisfies SessionAccount)
|
|
71
|
-
expect(rows.map((row) => row.label)).toEqual(['1. ● Main · Limit reached', '2. ○ Spare · Not checked · this session'])
|
|
72
|
-
expect(rows[1].account.id).toBe('a2')
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('says what the account can do and that providers do not report usage when none is reported', () => {
|
|
76
|
-
const text = accountDetails(view('a1', 'Main', { state: { ...view('a1', 'Main').state, health: 'auth_expired', piProviders: ['anthropic'], lastError: { category: 'rate_limited', message: 'Slow down.', at: '2026-10-01T00:00:00.000Z', resetsAt: null } } }))
|
|
77
|
-
expect(text).toContain('Health: Sign in again')
|
|
78
|
-
expect(text).toContain('Providers: anthropic')
|
|
79
|
-
expect(text).toContain('Last error: Slow down.')
|
|
80
|
-
expect(text).toContain('Pi providers do not report them.')
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('formats a reset time as a short countdown', () => {
|
|
84
|
-
const now = Date.parse('2026-10-01T00:00:00.000Z')
|
|
85
|
-
expect(resetIn('2026-10-01T00:05:00.000Z', now)).toBe('in 5m')
|
|
86
|
-
expect(resetIn('2026-10-01T02:30:00.000Z', now)).toBe('in 2h 30m')
|
|
87
|
-
expect(resetIn('2026-10-03T00:00:00.000Z', now)).toBe('in 2d')
|
|
88
|
-
expect(resetIn('2026-09-30T00:00:00.000Z', now)).toBe('now')
|
|
89
|
-
})
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
async function session() {
|
|
93
|
-
const root = rootWithProject()
|
|
94
|
-
const base = mkdtempSync(join(tmpdir(), 'accounts-menu-'))
|
|
95
|
-
writeFile(join(root, 'registry/rules/tests.md'), '---\nname: Run tests\ndescription: Always test.\n---\nAlways run the tests.\n')
|
|
96
|
-
const harness = createHarness({ dataRoot: root, stateDir: join(base, 'state'), secrets: memorySecretStore(), piProgram: () => '/opt/pi/bin/pi', assets: { node: '/opt/node', cli: '/opt/harness/cli.js', piExtension: '/opt/harness/terminal-pi.js' } })
|
|
97
|
-
open.push(harness)
|
|
98
|
-
const main = harness.accounts.create('Main', 'apiKey').accounts[0]
|
|
99
|
-
const spare = harness.accounts.create('Spare', 'apiKey').accounts.find((account) => account.label === 'Spare')!
|
|
100
|
-
const launch = await harness.terminals.prepare({ sessionId: 'term-1', accountId: main.id, cwd: base, sessionFolder: join(root, 'sessions', 'term-1') })
|
|
101
|
-
const connection: SocketConnection = { socket: String(launch.env[SOCKET_ENV]), token: String(launch.env[TOKEN_ENV]) }
|
|
102
|
-
// The extension claims the key before the model runs; the menu uses it for every change.
|
|
103
|
-
const { key } = await socketCall<{ key: string }>(connection, 'control.claim')
|
|
104
|
-
const call: AccountsCall = (method, params) => socketCall(connection, method, params ?? {}, 5_000, key)
|
|
105
|
-
return { harness, main, spare, connection, key, call }
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
describe('the accounts menu, over the session socket', () => {
|
|
109
|
-
it('refuses account calls from the shell token, and serves them to the extension with its key', async () => {
|
|
110
|
-
const { connection, key, main, harness } = await session()
|
|
111
|
-
await expect(socketCall(connection, 'accounts.list')).rejects.toMatchObject({ code: 'unauthorized' })
|
|
112
|
-
await expect(socketCall(connection, 'accounts.list', {}, 5_000, 'guessed')).rejects.toMatchObject({ code: 'unauthorized' })
|
|
113
|
-
await expect(socketCall(connection, 'accounts.deviceId')).rejects.toMatchObject({ code: 'unauthorized' })
|
|
114
|
-
const listed = await socketCall<AccountsOverview>(connection, 'accounts.list', {}, 5_000, key)
|
|
115
|
-
expect(listed.accounts.map((account) => account.id)).toContain(main.id)
|
|
116
|
-
expect(await socketCall<{ accountId: string; label: string }>(connection, 'accounts.session', {}, 5_000, key)).toEqual({ accountId: main.id, label: 'Main' })
|
|
117
|
-
expect(await socketCall(connection, 'accounts.deviceId', {}, 5_000, key)).toBe(await harness.accounts.installationDeviceId())
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
it('will not remove an account a running terminal is using, this session included', async () => {
|
|
121
|
-
const { call, main, spare, harness } = await session()
|
|
122
|
-
await expect(call('accounts.remove', { accountId: main.id })).rejects.toMatchObject({ code: 'account_in_use' })
|
|
123
|
-
expect(harness.accounts.find(main.id).id).toBe(main.id)
|
|
124
|
-
// An account with no terminal on it is removed as usual.
|
|
125
|
-
await call('accounts.remove', { accountId: spare.id })
|
|
126
|
-
expect(() => harness.accounts.find(spare.id)).toThrow()
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
it('makes an account the default from the menu', async () => {
|
|
130
|
-
const { call, harness, spare, main } = await session()
|
|
131
|
-
const { ui, said } = person(['Spare', 'Make default', 'Back', 'Done'])
|
|
132
|
-
expect(await runAccountsMenu(ui, call, { accountId: main.id, label: 'Main' })).toBeUndefined()
|
|
133
|
-
expect(harness.accounts.overview().defaults.pi).toBe(spare.id)
|
|
134
|
-
expect(said.map((entry) => entry.message)).toContain('Spare is the default for new sessions.')
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
it('switches this session to another account by ending Pi, and leaves the choice for the launcher', async () => {
|
|
138
|
-
const { call, harness, spare, main } = await session()
|
|
139
|
-
const { ui } = person(['Spare', 'Use for this session', true])
|
|
140
|
-
const outcome = await runAccountsMenu(ui, call, { accountId: main.id, label: 'Main' })
|
|
141
|
-
expect(outcome).toBe('relaunch')
|
|
142
|
-
expect(harness.terminals.takeRelaunch('term-1')).toEqual({ accountId: spare.id, nativeSessionId: null })
|
|
143
|
-
// Taken once: a second read finds nothing.
|
|
144
|
-
expect(harness.terminals.takeRelaunch('term-1')).toBeNull()
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
it('does not switch when the person declines the confirmation', async () => {
|
|
148
|
-
const { call, harness, spare, main } = await session()
|
|
149
|
-
const { ui } = person(['Spare', 'Use for this session', false, 'Back', 'Done'])
|
|
150
|
-
expect(await runAccountsMenu(ui, call, { accountId: main.id, label: 'Main' })).toBeUndefined()
|
|
151
|
-
expect(harness.terminals.takeRelaunch('term-1')).toBeNull()
|
|
152
|
-
expect(harness.accounts.find(spare.id).id).toBe(spare.id)
|
|
153
|
-
})
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
describe('signing in from the accounts menu', () => {
|
|
157
|
-
it('shows structured OAuth choices and returns the selected provider choice ID', async () => {
|
|
158
|
-
const overview: AccountsOverview = { accounts: [view('a1', 'Main')], pools: [], defaults: { pi: 'a1' } }
|
|
159
|
-
const answered: Record<string, unknown>[] = []
|
|
160
|
-
const statuses = [
|
|
161
|
-
{ loginId: 'L2', revision: 1, status: 'running', events: [], prompt: { type: 'prompt', promptId: 'P2', prompt: { type: 'select', message: 'Select OpenAI Codex login method:', options: [{ id: 'device_code', label: 'Device code login' }, { id: 'browser', label: 'Browser login' }] } }, success: null, error: null, accountId: 'a1', provider: 'openai-codex', method: 'oauth' },
|
|
162
|
-
{ loginId: 'L2', revision: 2, status: 'completed', events: [], prompt: null, success: true, error: null, accountId: 'a1', provider: 'openai-codex', method: 'oauth' }
|
|
163
|
-
]
|
|
164
|
-
const call = (async (method: string, params?: Record<string, unknown>) => {
|
|
165
|
-
switch (method) {
|
|
166
|
-
case 'accounts.list':
|
|
167
|
-
return overview
|
|
168
|
-
case 'accounts.providers':
|
|
169
|
-
return [{ id: 'openai-codex', name: 'OpenAI Codex', oauth: true, oauthLabel: 'Sign in with ChatGPT', apiKey: false }]
|
|
170
|
-
case 'accounts.loginStart':
|
|
171
|
-
return { loginId: 'L2' }
|
|
172
|
-
case 'accounts.loginStatus':
|
|
173
|
-
return statuses.shift()
|
|
174
|
-
case 'accounts.loginRespond':
|
|
175
|
-
answered.push(params!)
|
|
176
|
-
return {}
|
|
177
|
-
default:
|
|
178
|
-
throw new Error(`unexpected ${method}`)
|
|
179
|
-
}
|
|
180
|
-
}) as unknown as AccountsCall
|
|
181
|
-
const script = person(['Main', 'Sign in', 'OpenAI Codex', 'Device code login', 'Back', 'Done'])
|
|
182
|
-
|
|
183
|
-
expect(await runAccountsMenu(script.ui, call, { accountId: 'a1', label: 'Main' })).toBeUndefined()
|
|
184
|
-
|
|
185
|
-
expect(answered).toEqual([{ loginId: 'L2', promptId: 'P2', value: 'device_code' }])
|
|
186
|
-
expect(script.shown).toContain('Select OpenAI Codex login method:')
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
it('follows a browser sign-in, answers its prompt, and reports the result', async () => {
|
|
190
|
-
const overview: AccountsOverview = { accounts: [view('a1', 'Main')], pools: [], defaults: { pi: 'a1' } }
|
|
191
|
-
const answered: Record<string, unknown>[] = []
|
|
192
|
-
const statuses = [
|
|
193
|
-
{ loginId: 'L1', revision: 1, status: 'running', events: [{ type: 'auth_url', url: 'https://auth.example/start' }], prompt: null, success: null, error: null, accountId: 'a1', provider: 'anthropic', method: 'oauth' },
|
|
194
|
-
{ loginId: 'L1', revision: 2, status: 'running', events: [], prompt: { type: 'prompt', promptId: 'P1', prompt: { type: 'secret', message: 'Paste the code', placeholder: null, options: null } }, success: null, error: null, accountId: 'a1', provider: 'anthropic', method: 'oauth' },
|
|
195
|
-
{ loginId: 'L1', revision: 3, status: 'completed', events: [], prompt: null, success: true, error: null, accountId: 'a1', provider: 'anthropic', method: 'oauth' }
|
|
196
|
-
]
|
|
197
|
-
const call = (async (method: string, params?: Record<string, unknown>) => {
|
|
198
|
-
switch (method) {
|
|
199
|
-
case 'accounts.list':
|
|
200
|
-
return overview
|
|
201
|
-
case 'accounts.session':
|
|
202
|
-
return { accountId: 'a1', label: 'Main' }
|
|
203
|
-
case 'accounts.providers':
|
|
204
|
-
return [{ id: 'anthropic', name: 'Anthropic', oauth: true, oauthLabel: 'Claude', apiKey: false }]
|
|
205
|
-
case 'accounts.loginStart':
|
|
206
|
-
expect(params).toEqual({ accountId: 'a1', provider: 'anthropic' })
|
|
207
|
-
return { loginId: 'L1' }
|
|
208
|
-
case 'accounts.loginStatus':
|
|
209
|
-
return statuses.shift()
|
|
210
|
-
case 'accounts.loginRespond':
|
|
211
|
-
answered.push(params!)
|
|
212
|
-
return {}
|
|
213
|
-
default:
|
|
214
|
-
throw new Error(`unexpected ${method}`)
|
|
215
|
-
}
|
|
216
|
-
}) as unknown as AccountsCall
|
|
217
|
-
// Account, then Sign in, then the provider; one sign-in method means no second pick. The
|
|
218
|
-
// browser step is answered with "Check status", and the prompt is typed as '123'.
|
|
219
|
-
const script = person(['Main', 'Sign in', 'Anthropic', 'Check status', '123', 'Back', 'Done'])
|
|
220
|
-
expect(await runAccountsMenu(script.ui, call, { accountId: 'a1', label: 'Main' })).toBeUndefined()
|
|
221
|
-
expect(answered).toEqual([{ loginId: 'L1', promptId: 'P1', value: '123' }])
|
|
222
|
-
expect(script.said.map((entry) => entry.message)).toContain('Signed in.')
|
|
223
|
-
expect(script.remaining()).toBe(0)
|
|
224
|
-
})
|
|
225
|
-
})
|