@xingular/harness 0.1.7 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +97 -1
- package/LICENSE +202 -0
- package/NOTICE.md +22 -0
- package/README.md +187 -85
- package/THIRD_PARTY_LICENSES.md +942 -0
- package/dist/cli.js +13701 -13498
- package/dist/sdk/accounts/accounts.d.ts +165 -0
- package/dist/sdk/accounts/accounts.js +730 -0
- package/dist/sdk/accounts/choices.d.ts +23 -0
- package/dist/sdk/accounts/choices.js +62 -0
- package/dist/sdk/accounts/env.d.ts +78 -0
- package/dist/sdk/accounts/env.js +294 -0
- package/dist/sdk/accounts/secrets.d.ts +16 -0
- package/dist/sdk/accounts/secrets.js +40 -0
- package/dist/sdk/accounts/store.d.ts +114 -0
- package/dist/sdk/accounts/store.js +255 -0
- package/dist/sdk/browser/config.d.ts +16 -0
- package/dist/sdk/browser/config.js +22 -0
- package/dist/sdk/browser/diagnostics.d.ts +4 -0
- package/dist/sdk/browser/diagnostics.js +38 -0
- package/dist/sdk/browser/index.d.ts +17 -0
- package/dist/sdk/browser/index.js +65 -0
- package/dist/sdk/browser/network.d.ts +10 -0
- package/dist/sdk/browser/network.js +59 -0
- package/dist/sdk/browser/session.d.ts +84 -0
- package/dist/sdk/browser/session.js +192 -0
- package/dist/sdk/browser/tools.d.ts +8 -0
- package/dist/sdk/browser/tools.js +329 -0
- package/dist/sdk/capabilities/api.d.ts +22 -0
- package/dist/sdk/capabilities/api.js +54 -0
- package/dist/sdk/capabilities/runSnapshot.d.ts +18 -0
- package/dist/sdk/capabilities/runSnapshot.js +47 -0
- package/dist/sdk/capabilities/types.d.ts +29 -0
- package/dist/sdk/capabilities/types.js +1 -0
- package/dist/sdk/cli.d.ts +2 -0
- package/dist/sdk/cli.js +142 -0
- package/dist/sdk/core/bus.d.ts +23 -0
- package/dist/sdk/core/bus.js +76 -0
- package/dist/sdk/core/caller.d.ts +22 -0
- package/dist/sdk/core/caller.js +16 -0
- package/dist/sdk/core/changes.d.ts +15 -0
- package/dist/sdk/core/changes.js +15 -0
- package/dist/sdk/core/effort.d.ts +2 -0
- package/dist/sdk/core/effort.js +1 -0
- package/dist/sdk/core/env.d.ts +18 -0
- package/dist/sdk/core/env.js +8 -0
- package/dist/sdk/core/errors.d.ts +15 -0
- package/dist/sdk/core/errors.js +24 -0
- package/dist/sdk/core/frontmatter.d.ts +12 -0
- package/dist/sdk/core/frontmatter.js +50 -0
- package/dist/sdk/core/fs.d.ts +18 -0
- package/dist/sdk/core/fs.js +106 -0
- package/dist/sdk/core/index.d.ts +24 -0
- package/dist/sdk/core/index.js +187 -0
- package/dist/sdk/core/path.d.ts +7 -0
- package/dist/sdk/core/path.js +79 -0
- package/dist/sdk/core/projects.d.ts +18 -0
- package/dist/sdk/core/projects.js +67 -0
- package/dist/sdk/core/secrets.d.ts +2 -0
- package/dist/sdk/core/secrets.js +5 -0
- package/dist/sdk/core/text.d.ts +7 -0
- package/dist/sdk/core/text.js +40 -0
- package/dist/sdk/doctor/checks.d.ts +5 -0
- package/dist/sdk/doctor/checks.js +208 -0
- package/dist/sdk/doctor/probe.d.ts +4 -0
- package/dist/sdk/doctor/probe.js +92 -0
- package/dist/sdk/doctor/service.d.ts +23 -0
- package/dist/sdk/doctor/service.js +144 -0
- package/dist/sdk/doctor/types.d.ts +141 -0
- package/dist/sdk/doctor/types.js +29 -0
- package/dist/sdk/harness.d.ts +133 -0
- package/dist/sdk/harness.js +299 -0
- package/dist/sdk/history/lessonPrompt.d.ts +2 -0
- package/dist/sdk/history/lessonPrompt.js +15 -0
- package/dist/sdk/history/lessons.d.ts +52 -0
- package/dist/sdk/history/lessons.js +173 -0
- package/dist/sdk/history/recall.d.ts +68 -0
- package/dist/sdk/history/recall.js +199 -0
- package/dist/sdk/history/trajectory.d.ts +7 -0
- package/dist/sdk/history/trajectory.js +216 -0
- package/dist/sdk/hub/catalog.json +123 -0
- package/dist/sdk/hub/cli.d.ts +7 -0
- package/dist/sdk/hub/cli.js +81 -0
- package/dist/sdk/hub/hub.d.ts +74 -0
- package/dist/sdk/hub/hub.js +474 -0
- package/dist/sdk/hub/schema.d.ts +280 -0
- package/dist/sdk/hub/schema.js +78 -0
- package/dist/sdk/index.d.ts +63 -0
- package/dist/sdk/index.js +48 -0
- package/dist/sdk/mcp/connections.d.ts +83 -0
- package/dist/sdk/mcp/connections.js +669 -0
- package/dist/sdk/mcp/manager.d.ts +26 -0
- package/dist/sdk/mcp/manager.js +124 -0
- package/dist/sdk/mcp/oauth.d.ts +35 -0
- package/dist/sdk/mcp/oauth.js +171 -0
- package/dist/sdk/mcp/scopeMigration.d.ts +19 -0
- package/dist/sdk/mcp/scopeMigration.js +198 -0
- package/dist/sdk/mcp/service.d.ts +160 -0
- package/dist/sdk/mcp/service.js +510 -0
- package/dist/sdk/mcp/types.d.ts +131 -0
- package/dist/sdk/mcp/types.js +49 -0
- package/dist/sdk/pi/runtime.d.ts +13 -0
- package/dist/sdk/pi/runtime.js +31 -0
- package/dist/sdk/plugins/api.d.ts +66 -0
- package/dist/sdk/plugins/api.js +155 -0
- package/dist/sdk/plugins/attachments.d.ts +46 -0
- package/dist/sdk/plugins/attachments.js +111 -0
- package/dist/sdk/plugins/builtin.d.ts +6 -0
- package/dist/sdk/plugins/builtin.js +68 -0
- package/dist/sdk/plugins/catalogue.d.ts +29 -0
- package/dist/sdk/plugins/catalogue.js +196 -0
- package/dist/sdk/plugins/cli.d.ts +13 -0
- package/dist/sdk/plugins/cli.js +187 -0
- package/dist/sdk/plugins/discover.d.ts +42 -0
- package/dist/sdk/plugins/discover.js +115 -0
- package/dist/sdk/plugins/firstParty.d.ts +50 -0
- package/dist/sdk/plugins/firstParty.js +113 -0
- package/dist/sdk/plugins/hooks.d.ts +94 -0
- package/dist/sdk/plugins/hooks.js +162 -0
- package/dist/sdk/plugins/identity.d.ts +19 -0
- package/dist/sdk/plugins/identity.js +48 -0
- package/dist/sdk/plugins/install.d.ts +20 -0
- package/dist/sdk/plugins/install.js +110 -0
- package/dist/sdk/plugins/inventory.d.ts +22 -0
- package/dist/sdk/plugins/inventory.js +110 -0
- package/dist/sdk/plugins/manifest.d.ts +13 -0
- package/dist/sdk/plugins/manifest.js +56 -0
- package/dist/sdk/plugins/plugins.d.ts +104 -0
- package/dist/sdk/plugins/plugins.js +164 -0
- package/dist/sdk/plugins/runtime.d.ts +9 -0
- package/dist/sdk/plugins/runtime.js +95 -0
- package/dist/sdk/plugins/trust.d.ts +44 -0
- package/dist/sdk/plugins/trust.js +120 -0
- package/dist/sdk/plugins/types.d.ts +159 -0
- package/dist/sdk/plugins/types.js +7 -0
- package/dist/sdk/prompt/compile.d.ts +174 -0
- package/dist/sdk/prompt/compile.js +396 -0
- package/dist/sdk/refine/cli.d.ts +4 -0
- package/dist/sdk/refine/cli.js +186 -0
- package/dist/sdk/refine/demo.d.ts +21 -0
- package/dist/sdk/refine/demo.js +114 -0
- package/dist/sdk/refine/evidence.d.ts +55 -0
- package/dist/sdk/refine/evidence.js +330 -0
- package/dist/sdk/refine/host.d.ts +51 -0
- package/dist/sdk/refine/host.js +76 -0
- package/dist/sdk/refine/ledger.d.ts +48 -0
- package/dist/sdk/refine/ledger.js +76 -0
- package/dist/sdk/refine/library.d.ts +55 -0
- package/dist/sdk/refine/library.js +177 -0
- package/dist/sdk/refine/pi.d.ts +72 -0
- package/dist/sdk/refine/pi.js +248 -0
- package/dist/sdk/refine/prompts.d.ts +45 -0
- package/dist/sdk/refine/prompts.js +390 -0
- package/dist/sdk/refine/recursion.d.ts +113 -0
- package/dist/sdk/refine/recursion.js +258 -0
- package/dist/sdk/refine/runner.d.ts +81 -0
- package/dist/sdk/refine/runner.js +150 -0
- package/dist/sdk/refine/selection.d.ts +57 -0
- package/dist/sdk/refine/selection.js +251 -0
- package/dist/sdk/refine/service.d.ts +84 -0
- package/dist/sdk/refine/service.js +165 -0
- package/dist/sdk/refine/suite.d.ts +67 -0
- package/dist/sdk/refine/suite.js +174 -0
- package/dist/sdk/refine/trajectory.d.ts +9 -0
- package/dist/sdk/refine/trajectory.js +68 -0
- package/dist/sdk/refine/types.d.ts +77 -0
- package/dist/sdk/refine/types.js +10 -0
- package/dist/sdk/server/methods.d.ts +3 -0
- package/dist/sdk/server/methods.js +370 -0
- package/dist/sdk/server/remote.d.ts +19 -0
- package/dist/sdk/server/remote.js +84 -0
- package/dist/sdk/server/rpc.d.ts +20 -0
- package/dist/sdk/server/rpc.js +102 -0
- package/dist/sdk/server/serve.d.ts +10 -0
- package/dist/sdk/server/serve.js +18 -0
- package/dist/sdk/sessions/approvals.d.ts +47 -0
- package/dist/sdk/sessions/approvals.js +119 -0
- package/dist/sdk/sessions/continuation.d.ts +48 -0
- package/dist/sdk/sessions/continuation.js +85 -0
- package/dist/sdk/sessions/contracts.d.ts +534 -0
- package/dist/sdk/sessions/contracts.js +299 -0
- package/dist/sdk/sessions/extensionUi.d.ts +19 -0
- package/dist/sdk/sessions/extensionUi.js +64 -0
- package/dist/sdk/sessions/history.d.ts +16 -0
- package/dist/sdk/sessions/history.js +68 -0
- package/dist/sdk/sessions/lineageJoin.d.ts +2 -0
- package/dist/sdk/sessions/lineageJoin.js +61 -0
- package/dist/sdk/sessions/planMode.d.ts +36 -0
- package/dist/sdk/sessions/planMode.js +84 -0
- package/dist/sdk/sessions/policy.d.ts +43 -0
- package/dist/sdk/sessions/policy.js +1 -0
- package/dist/sdk/sessions/pricing.d.ts +34 -0
- package/dist/sdk/sessions/pricing.js +40 -0
- package/dist/sdk/sessions/reasoningSummaries.d.ts +11 -0
- package/dist/sdk/sessions/reasoningSummaries.js +61 -0
- package/dist/sdk/sessions/registry.d.ts +102 -0
- package/dist/sdk/sessions/registry.js +383 -0
- package/dist/sdk/sessions/runIndex.d.ts +21 -0
- package/dist/sdk/sessions/runIndex.js +65 -0
- package/dist/sdk/sessions/runStore.d.ts +66 -0
- package/dist/sdk/sessions/runStore.js +335 -0
- package/dist/sdk/sessions/runner.d.ts +213 -0
- package/dist/sdk/sessions/runner.js +589 -0
- package/dist/sdk/sessions/sessions.d.ts +140 -0
- package/dist/sdk/sessions/sessions.js +394 -0
- package/dist/sdk/sessions/subagentService.d.ts +41 -0
- package/dist/sdk/sessions/subagentService.js +247 -0
- package/dist/sdk/sessions/subagents.d.ts +50 -0
- package/dist/sdk/sessions/subagents.js +68 -0
- package/dist/sdk/terminal/accountsMenu.d.ts +46 -0
- package/dist/sdk/terminal/accountsMenu.js +392 -0
- package/dist/sdk/terminal/cli.d.ts +20 -0
- package/dist/sdk/terminal/cli.js +121 -0
- package/dist/sdk/terminal/client.d.ts +15 -0
- package/dist/sdk/terminal/client.js +126 -0
- package/dist/sdk/terminal/control.d.ts +4 -0
- package/dist/sdk/terminal/control.js +25 -0
- package/dist/sdk/terminal/controller.d.ts +72 -0
- package/dist/sdk/terminal/controller.js +351 -0
- package/dist/sdk/terminal/hubMenu.d.ts +10 -0
- package/dist/sdk/terminal/hubMenu.js +34 -0
- package/dist/sdk/terminal/launch.d.ts +5 -0
- package/dist/sdk/terminal/launch.js +27 -0
- package/dist/sdk/terminal/logs.d.ts +14 -0
- package/dist/sdk/terminal/logs.js +59 -0
- package/dist/sdk/terminal/piExtension.d.ts +6 -0
- package/dist/sdk/terminal/piExtension.js +392 -0
- package/dist/sdk/terminal/pluginMenu.d.ts +34 -0
- package/dist/sdk/terminal/pluginMenu.js +101 -0
- package/dist/sdk/terminal/socket.d.ts +70 -0
- package/dist/sdk/terminal/socket.js +256 -0
- package/dist/sdk/terminal/standalone.d.ts +18 -0
- package/dist/sdk/terminal/standalone.js +146 -0
- package/dist/sdk/terminal/terminals.d.ts +176 -0
- package/dist/sdk/terminal/terminals.js +767 -0
- package/dist/sdk/terminal/trajectory.d.ts +10 -0
- package/dist/sdk/terminal/trajectory.js +30 -0
- package/dist/sdk/terminal/tui/chrome.d.ts +64 -0
- package/dist/sdk/terminal/tui/chrome.js +169 -0
- package/dist/sdk/terminal/tui/clipboardFiles.d.ts +11 -0
- package/dist/sdk/terminal/tui/clipboardFiles.js +74 -0
- package/dist/sdk/terminal/tui/commandPages.d.ts +7 -0
- package/dist/sdk/terminal/tui/commandPages.js +63 -0
- package/dist/sdk/terminal/tui/commands.d.ts +42 -0
- package/dist/sdk/terminal/tui/commands.js +276 -0
- package/dist/sdk/terminal/tui/dialogGeometry.d.ts +27 -0
- package/dist/sdk/terminal/tui/dialogGeometry.js +50 -0
- package/dist/sdk/terminal/tui/dialogs.d.ts +75 -0
- package/dist/sdk/terminal/tui/dialogs.js +363 -0
- package/dist/sdk/terminal/tui/keybindings.d.ts +11 -0
- package/dist/sdk/terminal/tui/keybindings.js +49 -0
- package/dist/sdk/terminal/tui/list.d.ts +73 -0
- package/dist/sdk/terminal/tui/list.js +196 -0
- package/dist/sdk/terminal/tui/modeChoices.d.ts +42 -0
- package/dist/sdk/terminal/tui/modeChoices.js +70 -0
- package/dist/sdk/terminal/tui/modelPicker.d.ts +55 -0
- package/dist/sdk/terminal/tui/modelPicker.js +155 -0
- package/dist/sdk/terminal/tui/mouse.d.ts +3 -0
- package/dist/sdk/terminal/tui/mouse.js +3 -0
- package/dist/sdk/terminal/tui/page.d.ts +14 -0
- package/dist/sdk/terminal/tui/page.js +1 -0
- package/dist/sdk/terminal/tui/pageOverlay.d.ts +27 -0
- package/dist/sdk/terminal/tui/pageOverlay.js +145 -0
- package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +54 -0
- package/dist/sdk/terminal/tui/pages/accountsPage.js +181 -0
- package/dist/sdk/terminal/tui/pages/componentsPage.d.ts +47 -0
- package/dist/sdk/terminal/tui/pages/componentsPage.js +119 -0
- package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +37 -0
- package/dist/sdk/terminal/tui/pages/doctorPage.js +145 -0
- package/dist/sdk/terminal/tui/pages/hubPage.d.ts +39 -0
- package/dist/sdk/terminal/tui/pages/hubPage.js +128 -0
- package/dist/sdk/terminal/tui/pages/logPage.d.ts +38 -0
- package/dist/sdk/terminal/tui/pages/logPage.js +189 -0
- package/dist/sdk/terminal/tui/pages/permissionsPage.d.ts +44 -0
- package/dist/sdk/terminal/tui/pages/permissionsPage.js +124 -0
- package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +57 -0
- package/dist/sdk/terminal/tui/pages/pluginsPage.js +243 -0
- package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +55 -0
- package/dist/sdk/terminal/tui/pages/settingsPage.js +88 -0
- package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +58 -0
- package/dist/sdk/terminal/tui/pages/trajectoryPage.js +377 -0
- package/dist/sdk/terminal/tui/piAdapter.d.ts +18 -0
- package/dist/sdk/terminal/tui/piAdapter.js +48 -0
- package/dist/sdk/terminal/tui/planMode.d.ts +2 -0
- package/dist/sdk/terminal/tui/planMode.js +2 -0
- package/dist/sdk/terminal/tui/questionPicker.d.ts +20 -0
- package/dist/sdk/terminal/tui/questionPicker.js +150 -0
- package/dist/sdk/terminal/tui/questions.d.ts +19 -0
- package/dist/sdk/terminal/tui/questions.js +42 -0
- package/dist/sdk/terminal/tui/runtime.d.ts +114 -0
- package/dist/sdk/terminal/tui/runtime.js +441 -0
- package/dist/sdk/terminal/tui/search.d.ts +22 -0
- package/dist/sdk/terminal/tui/search.js +60 -0
- package/dist/sdk/terminal/tui/selection.d.ts +16 -0
- package/dist/sdk/terminal/tui/selection.js +16 -0
- package/dist/sdk/terminal/tui/sessionUi.d.ts +3 -0
- package/dist/sdk/terminal/tui/sessionUi.js +30 -0
- package/dist/sdk/terminal/tui/settingsModel.d.ts +12 -0
- package/dist/sdk/terminal/tui/settingsModel.js +84 -0
- package/dist/sdk/terminal/tui/sideQuestion.d.ts +53 -0
- package/dist/sdk/terminal/tui/sideQuestion.js +197 -0
- package/dist/sdk/terminal/tui/skillInvocation.d.ts +9 -0
- package/dist/sdk/terminal/tui/skillInvocation.js +43 -0
- package/dist/sdk/terminal/tui/status.d.ts +18 -0
- package/dist/sdk/terminal/tui/status.js +67 -0
- package/dist/sdk/terminal/tui/theme.d.ts +45 -0
- package/dist/sdk/terminal/tui/theme.js +176 -0
- package/dist/sdk/terminal/tui/treeModel.d.ts +79 -0
- package/dist/sdk/terminal/tui/treeModel.js +483 -0
- package/dist/sdk/terminal/tui/treePicker.d.ts +49 -0
- package/dist/sdk/terminal/tui/treePicker.js +251 -0
- package/dist/sdk/terminal/tui/ui.d.ts +47 -0
- package/dist/sdk/terminal/tui/ui.js +148 -0
- package/dist/sdk/terminal/tui/workingStatus.d.ts +9 -0
- package/dist/sdk/terminal/tui/workingStatus.js +229 -0
- package/dist/sdk/tools/askUser.d.ts +6 -0
- package/dist/sdk/tools/askUser.js +74 -0
- package/dist/sdk/tools/checklist.d.ts +9 -0
- package/dist/sdk/tools/checklist.js +54 -0
- package/dist/sdk/tools/definitions.d.ts +30 -0
- package/dist/sdk/tools/definitions.js +117 -0
- package/dist/sdk/tools/dispatch.d.ts +16 -0
- package/dist/sdk/tools/dispatch.js +67 -0
- package/dist/sdk/tools/harnessTools.d.ts +6 -0
- package/dist/sdk/tools/harnessTools.js +20 -0
- package/dist/sdk/tools/sessionName.d.ts +7 -0
- package/dist/sdk/tools/sessionName.js +31 -0
- package/dist/sdk/tools/spawnSubagent.d.ts +4 -0
- package/dist/sdk/tools/spawnSubagent.js +49 -0
- package/dist/sdk/tools/types.d.ts +48 -0
- package/dist/sdk/tools/types.js +1 -0
- package/dist/sdk/variant/components.d.ts +34 -0
- package/dist/sdk/variant/components.js +230 -0
- package/dist/sdk/variant/materialise.d.ts +66 -0
- package/dist/sdk/variant/materialise.js +81 -0
- package/dist/sdk/variant/migrate.d.ts +4 -0
- package/dist/sdk/variant/migrate.js +41 -0
- package/dist/sdk/variant/seed.d.ts +20 -0
- package/dist/sdk/variant/seed.js +116 -0
- package/dist/sdk/variant/store.d.ts +82 -0
- package/dist/sdk/variant/store.js +151 -0
- package/dist/sdk/variant/surface.d.ts +56 -0
- package/dist/sdk/variant/surface.js +81 -0
- package/dist/sdk/variant/trust.d.ts +27 -0
- package/dist/sdk/variant/trust.js +64 -0
- package/dist/sdk/variant/variant.d.ts +71 -0
- package/dist/sdk/variant/variant.js +331 -0
- package/dist/sdk/web/markdown.d.ts +10 -0
- package/dist/sdk/web/markdown.js +66 -0
- package/dist/sdk/web/safeRequest.d.ts +34 -0
- package/dist/sdk/web/safeRequest.js +175 -0
- package/dist/sdk/web/search.d.ts +53 -0
- package/dist/sdk/web/search.js +168 -0
- package/dist/sdk/web/text.d.ts +2 -0
- package/dist/sdk/web/text.js +7 -0
- package/dist/sdk/web/tools.d.ts +22 -0
- package/dist/sdk/web/tools.js +195 -0
- package/dist/sdk/web/turndown-plugin-gfm.d.ts +4 -0
- package/dist/sdk/wiki/notes.d.ts +68 -0
- package/dist/sdk/wiki/notes.js +297 -0
- package/dist/sdk/world/actions.d.ts +23 -0
- package/dist/sdk/world/actions.js +31 -0
- package/dist/sdk/world/cli.d.ts +12 -0
- package/dist/sdk/world/cli.js +166 -0
- package/dist/sdk/world/images.d.ts +20 -0
- package/dist/sdk/world/images.js +48 -0
- package/dist/sdk/world/untrusted.d.ts +12 -0
- package/dist/sdk/world/untrusted.js +20 -0
- package/dist/sdk/world/world.d.ts +65 -0
- package/dist/sdk/world/world.js +80 -0
- package/dist/terminal-opentui.js +13612 -0
- package/dist/terminal-pi.js +808 -151
- package/docs/README.md +22 -0
- package/docs/architecture/00-overview.md +159 -0
- package/docs/architecture/01-extension-points.md +78 -0
- package/docs/architecture/02-sessions-and-runs.md +146 -0
- package/docs/architecture/03-variants.md +95 -0
- package/docs/architecture/04-prompt.md +102 -0
- package/docs/architecture/05-refinement.md +107 -0
- package/docs/architecture/06-plugins-and-capabilities.md +93 -0
- package/docs/architecture/07-tools-and-gate.md +88 -0
- package/docs/architecture/08-memory-and-history.md +94 -0
- package/docs/architecture/09-accounts-and-connectors.md +90 -0
- package/docs/architecture/10-server-protocol.md +84 -0
- package/docs/architecture/11-terminal.md +81 -0
- package/docs/architecture/12-storage.md +61 -0
- package/docs/architecture/13-world-tools.md +23 -0
- package/docs/architecture/README.md +114 -0
- package/docs/architecture/proposals/PROP-0001-reporting-section.md +106 -0
- package/docs/architecture/proposals/PROP-0002-retain-rollout-workspaces.md +104 -0
- package/docs/architecture/proposals/PROP-0003-executor-settings.md +81 -0
- package/docs/architecture/proposals/PROP-0004-flexible-reporting-guidance.md +71 -0
- package/docs/architecture/proposals/PROP-0005-xharness-cli-name.md +78 -0
- package/docs/architecture/proposals/PROP-0006-run-checklist.md +68 -0
- package/docs/architecture/proposals/PROP-0007-run-continuation.md +80 -0
- package/docs/architecture/proposals/PROP-0008-lessons-from-runs.md +80 -0
- package/docs/architecture/proposals/PROP-0009-foundation-and-variants.md +78 -0
- package/docs/architecture/proposals/PROP-0010-session-names.md +73 -0
- package/docs/architecture/proposals/PROP-0011-doctor.md +63 -0
- package/docs/architecture/proposals/PROP-0012-release-baseline.md +56 -0
- package/docs/architecture/proposals/README.md +76 -0
- package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
- package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
- package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
- package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
- package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
- package/docs/decisions/ADR-0007-reporting-section.md +33 -0
- package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
- package/docs/decisions/ADR-0009-xharness-command.md +38 -0
- package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
- package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
- package/docs/decisions/ADR-0012-native-session-names.md +34 -0
- package/docs/decisions/ADR-0013-doctor.md +27 -0
- package/docs/decisions/ADR-0014-public-release-baseline.md +21 -0
- package/docs/doctor.md +74 -0
- package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
- package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
- package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
- package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
- package/docs/features/README.md +20 -0
- package/docs/features/automations/README.md +41 -0
- package/docs/features/cores/README.md +39 -0
- package/docs/features/google-harness2/README.md +52 -0
- package/docs/features/integrations/README.md +40 -0
- package/docs/features/interfaces/README.md +29 -0
- package/docs/features/memory/README.md +28 -0
- package/docs/releases/1.0.0.md +40 -0
- package/docs/releases/README.md +36 -0
- package/docs/study/00-index.md +78 -0
- package/docs/study/arms/00-matrix.md +20 -0
- package/docs/study/arms/01-system-prompt.md +211 -0
- package/docs/study/arms/02-tools.md +79 -0
- package/docs/study/arms/03-subagents.md +90 -0
- package/docs/study/arms/04-skills.md +75 -0
- package/docs/study/arms/05-context-management.md +90 -0
- package/docs/study/arms/06-memory.md +90 -0
- package/docs/study/arms/07-governance.md +71 -0
- package/docs/study/arms/08-execution.md +69 -0
- package/docs/study/arms/09-observability.md +60 -0
- package/docs/study/arms/10-refinement.md +110 -0
- package/docs/study/btw-comparison.md +37 -0
- package/docs/study/feature-gap-review.md +42 -0
- package/docs/study/insights.md +123 -0
- package/docs/study/roadmap.md +72 -0
- package/docs/study/sources/claude-code.md +44 -0
- package/docs/study/sources/deepseek-harness.md +102 -0
- package/docs/study/sources/harness2.md +50 -0
- package/docs/study/sources/kimi-cli.md +42 -0
- package/docs/study/sources/omp.md +93 -0
- package/docs/study/sources/opencode.md +43 -0
- package/docs/study/sources/openhands.md +46 -0
- package/docs/study/sources/smolagents.md +40 -0
- package/docs/study/sources/swe-agent.md +34 -0
- package/docs/system-prompt-design.md +196 -0
- package/docs/terminal-tui.md +473 -56
- package/package.json +43 -13
- package/docs/evidence/terminal-2026-10-17/120x40-completed-transcript.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/40x20-settings-interaction.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/40x20-settings-keyboard.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/40x20-welcome.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/80x24-approval-0.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/80x24-question.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17/verification.json +0 -130
- package/docs/evidence/terminal-2026-10-17-followup/120x40-completed-transcript.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-interaction.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-keyboard.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/40x20-welcome.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/80x24-approval-0.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/80x24-plugin-light.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/80x24-question-batch.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/80x24-question.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-approval-0.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-plugin-light.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question-batch.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/app-bundle/verification.json +0 -95
- package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-approval-0.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-plugin-light.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question-batch.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/global-install/README.md +0 -27
- package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command-80x24.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command.json +0 -18
- package/docs/evidence/terminal-2026-10-17-followup/global-install/verification.json +0 -95
- package/docs/evidence/terminal-2026-10-17-followup/harness-reference-80x24.json.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/harness-reference-final-80x24.json.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/harness-reference-scenario.json +0 -60
- package/docs/evidence/terminal-2026-10-17-followup/live-codex/README.md +0 -24
- package/docs/evidence/terminal-2026-10-17-followup/live-codex/complete-80x24.ansi.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/live-codex/verification.json +0 -57
- package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24-early.json.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24.json.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/omp-reference-scenario.json +0 -58
- package/docs/evidence/terminal-2026-10-17-followup/omp-supplemental-static.json.gz +0 -0
- package/docs/evidence/terminal-2026-10-17-followup/rea-artifacts.json +0 -320
- package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.json +0 -30
- package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.md +0 -133
- package/docs/evidence/terminal-2026-10-17-followup/reference-source-observations.json +0 -20
- package/docs/evidence/terminal-2026-10-17-followup/verification.json +0 -207
- package/src/accounts/accounts.test.ts +0 -333
- package/src/accounts/accounts.ts +0 -658
- package/src/accounts/env.test.ts +0 -95
- package/src/accounts/env.ts +0 -338
- package/src/accounts/secrets.ts +0 -50
- package/src/accounts/store.ts +0 -338
- package/src/capabilities/api.ts +0 -75
- package/src/capabilities/runSnapshot.ts +0 -59
- package/src/capabilities/types.ts +0 -34
- package/src/cli.ts +0 -118
- package/src/core/bus.ts +0 -34
- package/src/core/changes.ts +0 -33
- package/src/core/env.ts +0 -27
- package/src/core/errors.ts +0 -32
- package/src/core/frontmatter.ts +0 -47
- package/src/core/fs.test.ts +0 -38
- package/src/core/fs.ts +0 -92
- package/src/core/index.ts +0 -193
- package/src/core/path.test.ts +0 -14
- package/src/core/path.ts +0 -79
- package/src/core/projects.ts +0 -90
- package/src/core/text.ts +0 -39
- package/src/harness.ts +0 -312
- package/src/hub/catalog.json +0 -123
- package/src/hub/cli.ts +0 -59
- package/src/hub/hub.test.ts +0 -205
- package/src/hub/hub.ts +0 -256
- package/src/hub/schema.ts +0 -81
- package/src/index.ts +0 -75
- package/src/mcp/connections.ts +0 -614
- package/src/mcp/manager.ts +0 -130
- package/src/mcp/oauth.ts +0 -195
- package/src/mcp/scopeMigration.test.ts +0 -79
- package/src/mcp/scopeMigration.ts +0 -204
- package/src/mcp/service.test.ts +0 -376
- package/src/mcp/service.ts +0 -549
- package/src/mcp/types.ts +0 -108
- package/src/memory/api.test.ts +0 -82
- package/src/memory/api.ts +0 -303
- package/src/memory/blocks.test.ts +0 -78
- package/src/memory/blocks.ts +0 -408
- package/src/memory/caller.ts +0 -69
- package/src/memory/curation.test.ts +0 -163
- package/src/memory/curation.ts +0 -64
- package/src/memory/dispatch.ts +0 -59
- package/src/memory/facts.test.ts +0 -41
- package/src/memory/facts.ts +0 -248
- package/src/memory/graph.ts +0 -103
- package/src/memory/health.test.ts +0 -130
- package/src/memory/health.ts +0 -74
- package/src/memory/maintainer.ts +0 -272
- package/src/memory/maintenance.test.ts +0 -176
- package/src/memory/maintenance.ts +0 -518
- package/src/memory/migrate.ts +0 -79
- package/src/memory/operations.ts +0 -150
- package/src/memory/proposals.test.ts +0 -168
- package/src/memory/proposals.ts +0 -584
- package/src/memory/recall.test.ts +0 -115
- package/src/memory/recall.ts +0 -278
- package/src/memory/references.ts +0 -77
- package/src/memory/runContext.ts +0 -93
- package/src/memory/secrets.ts +0 -6
- package/src/memory/store.test.ts +0 -66
- package/src/memory/store.ts +0 -385
- package/src/memory/wiki.test.ts +0 -47
- package/src/memory/wiki.ts +0 -422
- package/src/memory/wikiIndex.test.ts +0 -88
- package/src/memory/wikiIndex.ts +0 -116
- package/src/plugins/api.ts +0 -181
- package/src/plugins/attachments.test.ts +0 -84
- package/src/plugins/attachments.ts +0 -141
- package/src/plugins/builtin.ts +0 -82
- package/src/plugins/catalogue.test.ts +0 -254
- package/src/plugins/catalogue.ts +0 -251
- package/src/plugins/cli.ts +0 -184
- package/src/plugins/discover.ts +0 -151
- package/src/plugins/firstParty.test.ts +0 -143
- package/src/plugins/firstParty.ts +0 -129
- package/src/plugins/hooks.test.ts +0 -250
- package/src/plugins/hooks.ts +0 -239
- package/src/plugins/identity.ts +0 -37
- package/src/plugins/install.test.ts +0 -107
- package/src/plugins/install.ts +0 -106
- package/src/plugins/inventory.ts +0 -123
- package/src/plugins/manifest.ts +0 -76
- package/src/plugins/plugins.test.ts +0 -205
- package/src/plugins/plugins.ts +0 -189
- package/src/plugins/proposal.ts +0 -121
- package/src/plugins/runtime.test.ts +0 -40
- package/src/plugins/runtime.ts +0 -82
- package/src/plugins/trust.ts +0 -142
- package/src/plugins/types.ts +0 -149
- package/src/prompt/compile.test.ts +0 -261
- package/src/prompt/compile.ts +0 -732
- package/src/server/methods.ts +0 -349
- package/src/server/remote.ts +0 -77
- package/src/server/rpc.ts +0 -116
- package/src/server/serve.ts +0 -28
- package/src/server/server.test.ts +0 -174
- package/src/sessions/approvals.ts +0 -118
- package/src/sessions/contracts.ts +0 -336
- package/src/sessions/conversation.test.ts +0 -177
- package/src/sessions/extensionSession.test.ts +0 -74
- package/src/sessions/extensionUi.test.ts +0 -65
- package/src/sessions/extensionUi.ts +0 -102
- package/src/sessions/history.ts +0 -51
- package/src/sessions/lineageJoin.ts +0 -75
- package/src/sessions/policy.ts +0 -36
- package/src/sessions/pricing.ts +0 -60
- package/src/sessions/questionBatches.test.ts +0 -110
- package/src/sessions/reasoningSummaries.ts +0 -59
- package/src/sessions/registry.ts +0 -381
- package/src/sessions/runIndex.ts +0 -99
- package/src/sessions/runStore.test.ts +0 -152
- package/src/sessions/runStore.ts +0 -332
- package/src/sessions/runner.ts +0 -604
- package/src/sessions/runtimeResources.test.ts +0 -61
- package/src/sessions/sessions.test.ts +0 -549
- package/src/sessions/sessions.ts +0 -339
- package/src/skills/registry.test.ts +0 -104
- package/src/skills/registry.ts +0 -413
- package/src/terminal/accountsMenu.test.ts +0 -225
- package/src/terminal/accountsMenu.ts +0 -382
- package/src/terminal/cli.ts +0 -149
- package/src/terminal/client.ts +0 -74
- package/src/terminal/control.test.ts +0 -23
- package/src/terminal/control.ts +0 -23
- package/src/terminal/controller.ts +0 -291
- package/src/terminal/hubMenu.ts +0 -24
- package/src/terminal/launch.test.ts +0 -25
- package/src/terminal/launch.ts +0 -48
- package/src/terminal/piExtension.lifecycle.test.ts +0 -55
- package/src/terminal/piExtension.ts +0 -259
- package/src/terminal/pluginControl.test.ts +0 -146
- package/src/terminal/pluginMenu.ts +0 -112
- package/src/terminal/socket.test.ts +0 -71
- package/src/terminal/socket.ts +0 -232
- package/src/terminal/standalone.test.ts +0 -167
- package/src/terminal/standalone.ts +0 -153
- package/src/terminal/terminal.test.ts +0 -399
- package/src/terminal/terminals.ts +0 -553
- package/src/terminal/tui/application.test.ts +0 -114
- package/src/terminal/tui/application.ts +0 -491
- package/src/terminal/tui/commands.test.ts +0 -218
- package/src/terminal/tui/commands.ts +0 -361
- package/src/terminal/tui/dialogs.ts +0 -301
- package/src/terminal/tui/editor.test.ts +0 -84
- package/src/terminal/tui/editor.ts +0 -79
- package/src/terminal/tui/keybindings.test.ts +0 -22
- package/src/terminal/tui/keybindings.ts +0 -50
- package/src/terminal/tui/piAdapter.ts +0 -62
- package/src/terminal/tui/presentation.test.ts +0 -79
- package/src/terminal/tui/questions.test.ts +0 -41
- package/src/terminal/tui/questions.ts +0 -47
- package/src/terminal/tui/runtime.socket.test.ts +0 -104
- package/src/terminal/tui/runtime.test.ts +0 -215
- package/src/terminal/tui/runtime.ts +0 -388
- package/src/terminal/tui/sessionUi.ts +0 -24
- package/src/terminal/tui/settings.test.ts +0 -150
- package/src/terminal/tui/settings.ts +0 -188
- package/src/terminal/tui/status.test.ts +0 -70
- package/src/terminal/tui/status.ts +0 -109
- package/src/terminal/tui/theme.ts +0 -174
- package/src/terminal/tui/tools.test.ts +0 -145
- package/src/terminal/tui/tools.ts +0 -142
- package/src/terminal/tui/transcript.test.ts +0 -25
- package/src/terminal/tui/transcript.ts +0 -124
- package/src/terminal/tui/ui.test.ts +0 -313
- package/src/terminal/tui/ui.ts +0 -166
- package/src/terminal/tui/welcome.ts +0 -102
- package/src/tools/askUser.test.ts +0 -69
- package/src/tools/askUser.ts +0 -59
- package/src/tools/definitions.ts +0 -187
- package/src/tools/maintenance.ts +0 -24
- package/src/tools/memoryTools.ts +0 -22
- package/src/tools/pluginPropose.ts +0 -41
- package/src/tools/registryWrite.test.ts +0 -101
- package/src/tools/registryWrite.ts +0 -182
- package/src/tools/spawnSubagent.ts +0 -92
- package/src/tools/types.ts +0 -39
- package/src/web/safeRequest.ts +0 -171
- package/src/web/text.ts +0 -53
- package/src/web/tools.ts +0 -134
- package/src/web/web.test.ts +0 -141
|
@@ -1,518 +0,0 @@
|
|
|
1
|
-
// The memory lifecycle. Imported sources and eligible settled runs become jobs; one job runs at
|
|
2
|
-
// a time, so the Wiki has a single writer. A job asks the maintainer session for proposals,
|
|
3
|
-
// checks every one against the evidence, applies the valid ones as one undoable operation, and
|
|
4
|
-
// sends the rest to the Inbox. When no job arrives for a while, memory blocks that are close to
|
|
5
|
-
// their limit are condensed.
|
|
6
|
-
import { readFileSync } from 'node:fs'
|
|
7
|
-
import { join } from 'node:path'
|
|
8
|
-
|
|
9
|
-
import type { Accounts } from '../accounts/accounts'
|
|
10
|
-
import { log, type Bus } from '../core/bus'
|
|
11
|
-
import type { HarnessEnv } from '../core/env'
|
|
12
|
-
import { newId, now, readJsonOr } from '../core/fs'
|
|
13
|
-
import { findProject } from '../core/projects'
|
|
14
|
-
import { charCount, takeChars } from '../core/text'
|
|
15
|
-
import type { RunEvent } from '../sessions/contracts'
|
|
16
|
-
import { findRun, readEvents } from '../sessions/runStore'
|
|
17
|
-
import { evidenceText, transcript } from './api'
|
|
18
|
-
import * as blocks from './blocks'
|
|
19
|
-
import { callerBlocks, type CallerContext } from './caller'
|
|
20
|
-
import * as facts from './facts'
|
|
21
|
-
import { piMaintainerFactory, runMaintenance, type ExistingBlock, type ExistingMemory, type ExistingPage, type MaintainerFactory, type MaintenanceRequest } from './maintainer'
|
|
22
|
-
import { inbox, undo } from './operations'
|
|
23
|
-
import { accept, apply, captureHashes, describeTrigger, parseProposalSet, writeIndex, type Evidence, type Trigger } from './proposals'
|
|
24
|
-
import { looksSecret } from './secrets'
|
|
25
|
-
import { enqueueCuration, listCuration, curationJob, saveCuration, requireCurator, type CurationJob } from './curation'
|
|
26
|
-
import * as registry from '../skills/registry'
|
|
27
|
-
import * as attachments from '../plugins/attachments'
|
|
28
|
-
import { parkPluginProposal, pluginProposalSchema } from '../plugins/proposal'
|
|
29
|
-
import { registryProposalSchema } from './proposals'
|
|
30
|
-
import { writeJson } from '../core/fs'
|
|
31
|
-
import { invalid } from '../core/errors'
|
|
32
|
-
import * as store from './store'
|
|
33
|
-
import { namespaces, searchEntries } from './wiki'
|
|
34
|
-
import { reindexQuietly } from './wikiIndex'
|
|
35
|
-
|
|
36
|
-
export type Job = { kind: 'ingest'; namespace: string; sourceId: string } | { kind: 'run'; runId: string; namespace?: string } | { kind: 'consolidate'; blockIds: string[] } | { kind: 'review'; requestId?: string; manual?: boolean }
|
|
37
|
-
|
|
38
|
-
const FULL_PAGES = 5
|
|
39
|
-
const FULL_PAGE_LIMIT = 6000
|
|
40
|
-
/** A block this full is condensed when nothing else is happening. */
|
|
41
|
-
const NEAR_LIMIT_PERCENT = 90
|
|
42
|
-
const IDLE_CHECK_MS = 600_000
|
|
43
|
-
|
|
44
|
-
/** Conversations belong to no project, so only this setting can pause them. Absent means on. */
|
|
45
|
-
export function chatUpdatesPaused(settings: unknown): boolean {
|
|
46
|
-
return (settings as { autoMaintenanceChat?: unknown } | null)?.autoMaintenanceChat === false
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Where a settled run's knowledge is filed and what the job reads of it; throws the reason it is not eligible. */
|
|
50
|
-
function runEvidence(root: string, runId: string): { namespace: string; transcript: string } {
|
|
51
|
-
const run = findRun(root, runId)
|
|
52
|
-
if (!run) throw new Error('Run was not found.')
|
|
53
|
-
const settings = readJsonOr<{ excludedSourceIds?: unknown } | null>(join(root, 'config/settings.json'), null)
|
|
54
|
-
if (Array.isArray(settings?.excludedSourceIds) && settings.excludedSourceIds.includes(runId)) throw new Error('run excluded in settings')
|
|
55
|
-
const projectId = run.mode === 'chat' || run.mode === 'code' ? run.projectId : null
|
|
56
|
-
let namespace: string
|
|
57
|
-
if (projectId) {
|
|
58
|
-
const project = findProject(root, projectId)
|
|
59
|
-
if (!project.autoMaintenance) throw new Error('automatic updates are paused for this project')
|
|
60
|
-
namespace = project.wikiNamespace
|
|
61
|
-
} else if (run.mode === 'chat') {
|
|
62
|
-
if (chatUpdatesPaused(settings)) throw new Error('automatic updates are paused for Chat')
|
|
63
|
-
namespace = store.LIBRARY_NAMESPACE
|
|
64
|
-
} else {
|
|
65
|
-
throw new Error('run has no project')
|
|
66
|
-
}
|
|
67
|
-
const text = transcript(run.goal ?? '', readEvents(root, runId))
|
|
68
|
-
if (!text.includes('Assistant:')) throw new Error('no recorded assistant output to use as evidence')
|
|
69
|
-
if (looksSecret(text)) throw new Error('the run contains text that looks like a credential')
|
|
70
|
-
return { namespace, transcript: text }
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* The blocks attached to a run, which its consolidation may rewrite: an agent's blocks for its
|
|
75
|
-
* own conversation, or the `user` block and the project's brief for a session in a project.
|
|
76
|
-
*/
|
|
77
|
-
function runBlocks(env: HarnessEnv, runId: string): blocks.Block[] {
|
|
78
|
-
const run = findRun(env.root, runId)
|
|
79
|
-
if (!run) return []
|
|
80
|
-
const chat = run.mode === 'chat'
|
|
81
|
-
// What the session was told it is when it started, when that was recorded.
|
|
82
|
-
const recorded = readJsonOr<CallerContext | null>(join(env.root, 'runs', run.id, 'caller.json'), null)
|
|
83
|
-
const context: CallerContext = recorded ?? {
|
|
84
|
-
runId: run.id,
|
|
85
|
-
sessionId: run.sessionId,
|
|
86
|
-
projectId: run.projectId,
|
|
87
|
-
// A conversation's run names its agent; older records rely on the session being the agent's own.
|
|
88
|
-
agentId: chat ? (run.agentId ?? (env.directory.agentName(run.sessionId) !== null ? run.sessionId : null)) : null,
|
|
89
|
-
actor: chat ? 'Chat' : 'Code'
|
|
90
|
-
}
|
|
91
|
-
let attached: blocks.Block[]
|
|
92
|
-
try {
|
|
93
|
-
attached = callerBlocks(env, context).attached
|
|
94
|
-
} catch {
|
|
95
|
-
// A run with no single agent has only the shared user block attached.
|
|
96
|
-
attached = [blocks.ensureUser(store.wikiDir(env.root))]
|
|
97
|
-
}
|
|
98
|
-
return attached.filter((block) => !block.front.readOnly)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* What the job sees of the Wiki: the target namespace's pages, entries relevant to the
|
|
103
|
-
* evidence from anywhere (the closest few in full), and the facts that apply.
|
|
104
|
-
*/
|
|
105
|
-
function maintainerContext(root: string, namespace: string, evidence: string): { pages: ExistingPage[]; memories: ExistingMemory[] } {
|
|
106
|
-
const wiki = store.wikiDir(root)
|
|
107
|
-
const pages = store.loadPages(wiki)
|
|
108
|
-
const query = evidence.split(/\s+/).filter((word) => Buffer.byteLength(word) > 4).slice(0, 12).join(' ')
|
|
109
|
-
const ranked = searchEntries(root, query, { kinds: ['page'], limit: 30 }).map((hit) => hit.id)
|
|
110
|
-
const inFull = new Set(ranked.slice(0, FULL_PAGES))
|
|
111
|
-
const small = pages.filter((page) => page.location.namespace === namespace).length <= FULL_PAGES
|
|
112
|
-
return {
|
|
113
|
-
pages: pages
|
|
114
|
-
.filter((page) => page.location.namespace === namespace || ranked.includes(page.frontmatter.id))
|
|
115
|
-
.slice(0, 150)
|
|
116
|
-
.map((page) => ({
|
|
117
|
-
id: page.frontmatter.id,
|
|
118
|
-
title: page.frontmatter.title,
|
|
119
|
-
type: page.frontmatter.type,
|
|
120
|
-
path: page.location.path,
|
|
121
|
-
summary: store.firstParagraph(page.body),
|
|
122
|
-
// An update replaces the whole body, so the job must see what the page says now.
|
|
123
|
-
...(inFull.has(page.frontmatter.id) || (page.location.namespace === namespace && small) ? { body: takeChars(page.body, FULL_PAGE_LIMIT) } : {})
|
|
124
|
-
})),
|
|
125
|
-
memories: facts
|
|
126
|
-
.loadMemories(wiki)
|
|
127
|
-
.filter((memory) => facts.appliesTo(memory.front, store.projectNamespaceOf(namespace)))
|
|
128
|
-
.slice(0, 60)
|
|
129
|
-
.map((memory) => ({ id: memory.front.id, title: memory.front.title, kind: memory.front.kind, namespace: memory.front.namespace, body: takeChars(memory.body, 300) }))
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/** Blocks at or over `NEAR_LIMIT_PERCENT` of their limit that have not been tried in this state. */
|
|
134
|
-
export function fullBlocks(wiki: string, tried: Set<string>): string[] {
|
|
135
|
-
return blocks
|
|
136
|
-
.loadAll(wiki)
|
|
137
|
-
.filter((block) => !block.front.readOnly && block.front.limit > 0 && charCount(block.body) * 100 >= block.front.limit * NEAR_LIMIT_PERCENT)
|
|
138
|
-
.filter((block) => {
|
|
139
|
-
const key = `${block.id}\u0000${store.currentRevision(wiki, block.id) ?? ''}`
|
|
140
|
-
return !tried.has(key) && Boolean(tried.add(key))
|
|
141
|
-
})
|
|
142
|
-
.map((block) => block.id)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const blockValues = (found: readonly blocks.Block[]): ExistingBlock[] => found.map((block) => ({ id: block.id, label: block.front.label, description: block.front.description, limit: block.front.limit, body: block.body }))
|
|
146
|
-
|
|
147
|
-
export interface MaintenanceOptions {
|
|
148
|
-
env: HarnessEnv
|
|
149
|
-
bus: Bus
|
|
150
|
-
accounts: Accounts
|
|
151
|
-
factory?: MaintainerFactory
|
|
152
|
-
/** How long the queue stays empty before full blocks are condensed. */
|
|
153
|
-
idleMs?: number
|
|
154
|
-
external?: boolean
|
|
155
|
-
excludedTriggers?: string[]
|
|
156
|
-
/** False: a settled run queues no consolidation of its own. */
|
|
157
|
-
runTrigger?: boolean
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export class Maintenance {
|
|
161
|
-
private chain: Promise<void> = Promise.resolve()
|
|
162
|
-
private idle: ReturnType<typeof setTimeout> | null = null
|
|
163
|
-
private readonly tried = new Set<string>()
|
|
164
|
-
private stopped = false
|
|
165
|
-
|
|
166
|
-
constructor(private readonly options: MaintenanceOptions) {}
|
|
167
|
-
|
|
168
|
-
/** Starts the idle check. Jobs can be queued whether or not it runs. */
|
|
169
|
-
start(): void {
|
|
170
|
-
this.stopped = false
|
|
171
|
-
if (this.options.external) {
|
|
172
|
-
for (const job of this.jobs().filter((job) => job.status === 'running')) {
|
|
173
|
-
job.status = 'failed'
|
|
174
|
-
job.reason = 'The previous process stopped before this request settled. Retry it explicitly.'
|
|
175
|
-
saveCuration(this.options.env.root, job)
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
this.rest()
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
stop(): void {
|
|
182
|
-
this.stopped = true
|
|
183
|
-
if (this.idle) clearTimeout(this.idle)
|
|
184
|
-
this.idle = null
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/** Resolves when every queued job has finished. */
|
|
188
|
-
settled(): Promise<void> {
|
|
189
|
-
return this.chain
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
private rest(): void {
|
|
193
|
-
if (this.idle) clearTimeout(this.idle)
|
|
194
|
-
if (this.stopped) return
|
|
195
|
-
this.idle = setTimeout(() => {
|
|
196
|
-
try {
|
|
197
|
-
const blockIds = fullBlocks(store.wikiDir(this.options.env.root), this.tried)
|
|
198
|
-
if (blockIds.length) this.enqueue({ kind: 'consolidate', blockIds })
|
|
199
|
-
else this.rest()
|
|
200
|
-
} catch {
|
|
201
|
-
this.rest()
|
|
202
|
-
}
|
|
203
|
-
}, this.options.idleMs ?? IDLE_CHECK_MS)
|
|
204
|
-
this.idle.unref?.()
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
enqueue(job: Job): void {
|
|
208
|
-
if (this.idle) clearTimeout(this.idle)
|
|
209
|
-
if (this.options.external) {
|
|
210
|
-
if (job.kind === 'run') {
|
|
211
|
-
try { runEvidence(this.options.env.root, job.runId) } catch (error) { log('maintenance source skipped', error instanceof Error ? error.message : String(error)); return }
|
|
212
|
-
const run = findRun(this.options.env.root, job.runId)
|
|
213
|
-
const namespace = run?.projectId ? findProject(this.options.env.root, run.projectId).wikiNamespace : store.LIBRARY_NAMESPACE
|
|
214
|
-
enqueueCuration(this.options.env.root, { ...job, namespace })
|
|
215
|
-
} else enqueueCuration(this.options.env.root, job)
|
|
216
|
-
this.options.bus.emit({ type: 'maintenance.queued' })
|
|
217
|
-
this.rest()
|
|
218
|
-
return
|
|
219
|
-
}
|
|
220
|
-
this.chain = this.chain
|
|
221
|
-
.then(() => this.process(job))
|
|
222
|
-
.catch((error) => log('maintenance', error instanceof Error ? error.message : String(error)))
|
|
223
|
-
.then(() => this.rest())
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/** A settled run is evidence; whether it is eligible is decided when its job runs. */
|
|
227
|
-
onRunEvent(event: RunEvent): void {
|
|
228
|
-
if (this.options.runTrigger === false) return
|
|
229
|
-
const caller = readJsonOr<CallerContext | null>(join(this.options.env.root, 'runs', event.runId, 'caller.json'), null)
|
|
230
|
-
if (caller?.vaultAccess === 'curator' || this.options.excludedTriggers?.includes(findRun(this.options.env.root, event.runId)?.trigger ?? '')) return
|
|
231
|
-
if (event.type === 'completed') this.enqueue({ kind: 'run', runId: event.runId })
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
jobs(): CurationJob[] { return listCuration(this.options.env.root) }
|
|
235
|
-
|
|
236
|
-
claim(context: CallerContext, id: string, prepare = true): CurationJob {
|
|
237
|
-
requireCurator(context)
|
|
238
|
-
const root = this.options.env.root
|
|
239
|
-
const job = curationJob(root, id)
|
|
240
|
-
if (job.status === 'completed' || job.status === 'rejected' || job.status === 'needs_user') return job
|
|
241
|
-
if (context.maintenanceJobIds !== undefined && !context.maintenanceJobIds.includes(id) && !('caller' in job.input && job.input.caller.runId === context.runId)) throw invalid('This request is not assigned to this run.')
|
|
242
|
-
if (job.runId && job.runId !== context.runId && job.status === 'running') throw invalid('Another run owns this request.')
|
|
243
|
-
job.runId = context.runId!
|
|
244
|
-
if (prepare && job.input.kind !== 'proposal' && job.input.kind !== 'registry' && job.input.kind !== 'plugin' && !job.prepared) {
|
|
245
|
-
let prepared: ReturnType<Maintenance['prepare']>
|
|
246
|
-
try { prepared = this.prepare(job.input) } catch (error) { job.status = 'failed'; job.reason = error instanceof Error ? error.message : String(error); saveCuration(root, job); throw error }
|
|
247
|
-
job.prepared = { request: prepared.request, evidence: prepared.evidence, namespace: prepared.namespace, trigger: prepared.trigger }
|
|
248
|
-
job.hashes = [...prepared.captured]
|
|
249
|
-
if (job.prepared.evidence.sourceText) job.prepared.evidence.sourceText = takeChars(job.prepared.evidence.sourceText, 60_000)
|
|
250
|
-
}
|
|
251
|
-
if (prepare && job.input.kind === 'proposal' && !job.prepared) {
|
|
252
|
-
const input = job.input
|
|
253
|
-
const origin = input.caller.runId
|
|
254
|
-
const attached = input.proposals.blocks.map((proposal) => blocks.find(store.wikiDir(root), proposal.block))
|
|
255
|
-
const evidence = origin && input.caller.vaultAccess !== 'curator' ? evidenceText(root, origin) : ''
|
|
256
|
-
const context = maintainerContext(root, input.namespace, evidence)
|
|
257
|
-
job.prepared = { request: { jobId: job.id, namespace: input.namespace, trigger: { kind: 'run', runId: origin ?? '', transcript: takeChars(evidence, 24_000) }, pages: context.pages, memories: context.memories, blocks: blockValues(attached), index: '' }, evidence: { runText: evidence, blocks: attached.map((block) => block.id) }, namespace: input.namespace, trigger: { kind: 'agent', runId: origin ?? null, actor: 'Curator' } }
|
|
258
|
-
}
|
|
259
|
-
job.status = 'running'
|
|
260
|
-
job.runId = context.runId!
|
|
261
|
-
return saveCuration(root, job)
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
readJob(context: CallerContext, id: string): unknown {
|
|
265
|
-
const job = this.claim(context, id)
|
|
266
|
-
return { id: job.id, status: job.status, input: job.input, context: job.prepared?.request ?? null, receipt: job.receipt }
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
decide(context: CallerContext, id: string, decision: 'reject' | 'needs_user', reason: string): CurationJob {
|
|
270
|
-
if (!reason.trim()) throw invalid('Explain the decision.')
|
|
271
|
-
const job = this.claim(context, id, false)
|
|
272
|
-
if (job.status === 'completed' || job.status === 'rejected' || job.status === 'needs_user') return job
|
|
273
|
-
job.status = decision === 'reject' ? 'rejected' : 'needs_user'
|
|
274
|
-
job.reason = reason.trim()
|
|
275
|
-
job.receipt = { operationId: null, notes: [job.reason], parked: decision === 'needs_user' ? 1 : 0, flagged: 0 }
|
|
276
|
-
if (decision === 'needs_user') {
|
|
277
|
-
const input = job.input
|
|
278
|
-
if (input.kind === 'registry') {
|
|
279
|
-
const proposal = input.proposal
|
|
280
|
-
inbox(store.wikiDir(this.options.env.root), 'proposed', `Review ${proposal.kind}: ${proposal.name}`, reason, [], null, { kind: proposal.kind, proposal, curationJobId: id })
|
|
281
|
-
} else if (input.kind === 'plugin') parkPluginProposal(store.wikiDir(this.options.env.root), `Curated request ${id}`, pluginProposalSchema.parse(input.proposal))
|
|
282
|
-
else inbox(store.wikiDir(this.options.env.root), 'unresolved', 'Maintenance needs your decision', reason, [])
|
|
283
|
-
}
|
|
284
|
-
this.options.bus.emit({ type: 'wiki.changed' })
|
|
285
|
-
return saveCuration(this.options.env.root, job)
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
applyJob(context: CallerContext, id: string, replacement?: unknown, reason = '', scope?: attachments.AttachScope): CurationJob {
|
|
289
|
-
if (!reason.trim()) throw invalid('Explain why this change should be applied.')
|
|
290
|
-
const root = this.options.env.root
|
|
291
|
-
const wiki = store.wikiDir(root)
|
|
292
|
-
const job = this.claim(context, id)
|
|
293
|
-
if (job.status === 'completed' || job.status === 'rejected' || job.status === 'needs_user') return job
|
|
294
|
-
const committed = readJsonOr<{ id: string } | null>(join(wiki, 'operations', `${job.id}.json`), null)
|
|
295
|
-
if (committed) {
|
|
296
|
-
job.status = 'completed'
|
|
297
|
-
job.receipt = { operationId: committed.id, notes: ['This request was already committed.'], parked: 0, flagged: 0 }
|
|
298
|
-
return saveCuration(root, job)
|
|
299
|
-
}
|
|
300
|
-
const input = job.input
|
|
301
|
-
if (input.kind === 'plugin') return this.decide(context, id, 'needs_user', reason || 'Plugin files require user review before activation; executable code also needs explicit trust.')
|
|
302
|
-
if (input.kind === 'registry') {
|
|
303
|
-
const proposal = registryProposalSchema.parse(input.proposal)
|
|
304
|
-
const itemId = `${proposal.kind}s/${store.slug(proposal.name)}`
|
|
305
|
-
if (!['skill', 'prompt', 'rule'].includes(proposal.kind) || !proposal.name.trim() || !proposal.body.trim() || looksSecret(proposal.body)) throw invalid('Invalid text resource proposal.')
|
|
306
|
-
const existing = registry.list(root).find((item) => item.id === itemId)
|
|
307
|
-
const current = captureHashes(wiki).get(itemId)
|
|
308
|
-
if (existing?.builtin || current !== new Map(job.hashes).get(itemId)) return this.decide(context, id, 'needs_user', 'The resource is built-in or changed since it was proposed. Review the current version.')
|
|
309
|
-
const target = scope ?? { agentId: input.caller.agentId ?? context.agentId }
|
|
310
|
-
if (target.agentId && target.projectId) throw invalid('Choose one attachment scope.')
|
|
311
|
-
if (target.agentId && target.agentId !== context.agentId && target.agentId !== input.caller.agentId && !this.options.env.directory.agentName(target.agentId)) throw invalid('Unknown attachment target.')
|
|
312
|
-
if (target.projectId) findProject(root, target.projectId)
|
|
313
|
-
const before = existing ? store.snapshot(wiki, itemId, readFileSync(existing.path, 'utf8'), 'Curator', `Before ${id}`).id : null
|
|
314
|
-
const beforeChoices = attachments.load(root)
|
|
315
|
-
registry.writeItem(root, proposal.kind, proposal.name, proposal.description, proposal.body, `Curated request ${id}: ${reason || proposal.reason}`, context.agentName ?? 'Curator')
|
|
316
|
-
const saved = registry.list(root).find((item) => item.id === itemId)!
|
|
317
|
-
const after = store.currentRevision(wiki, itemId)!
|
|
318
|
-
const choices = attachments.load(root)
|
|
319
|
-
attachments.set(choices, [itemId], target, true, false)
|
|
320
|
-
attachments.save(root, choices)
|
|
321
|
-
writeJson(join(wiki, 'operations', `${id}.json`), { id, createdAt: now(), trigger: `Curated request ${id}`, pages: [{ pageId: itemId, path: saved.path, beforeRevisionId: before, afterRevisionId: after }], undone: false, protected: true, attachmentsBefore: beforeChoices, attachmentsAfter: choices })
|
|
322
|
-
job.receipt = { operationId: id, notes: [`Saved ${itemId}; enabled for ${target.agentId ?? target.projectId ?? 'everyone'}. ${reason || proposal.reason}`], parked: 0, flagged: 0 }
|
|
323
|
-
this.options.bus.emit({ type: 'plugins.changed' })
|
|
324
|
-
} else {
|
|
325
|
-
const prepared = job.prepared
|
|
326
|
-
const proposalInput = input.kind === 'proposal' ? input : null
|
|
327
|
-
const proposals = parseProposalSet(replacement ?? proposalInput?.proposals)
|
|
328
|
-
const origin = proposalInput?.caller.runId ?? null
|
|
329
|
-
const trigger: Trigger = prepared?.trigger ?? { kind: 'agent', runId: origin, actor: context.agentName ?? 'Curator' }
|
|
330
|
-
const evidence: Evidence = input.kind === 'proposal' ? (prepared?.evidence ?? {}) : this.prepare(input).evidence
|
|
331
|
-
const originEvidence: Evidence = prepared?.evidence ?? { runText: origin ? evidenceText(root, origin) : null, blocks: proposals.blocks.map((block) => block.block) }
|
|
332
|
-
{
|
|
333
|
-
if (input.kind === 'proposal') Object.assign(evidence, originEvidence)
|
|
334
|
-
evidence.runs = {}
|
|
335
|
-
evidence.sources = {}
|
|
336
|
-
const refs = [...proposals.pages, ...proposals.memories, ...proposals.blocks].flatMap(proposal => proposal.sourceRefs).slice(0, 20)
|
|
337
|
-
for (const ref of refs) {
|
|
338
|
-
if (ref.kind === 'run' && findRun(root, ref.ref) && readJsonOr<CallerContext | null>(join(root, 'runs', ref.ref, 'caller.json'), null)?.vaultAccess !== 'curator') {
|
|
339
|
-
const excluded = readJsonOr<{ excludedSourceIds?: string[] }>(join(root, 'config/settings.json'), {}).excludedSourceIds ?? []
|
|
340
|
-
const text = evidenceText(root, ref.ref)
|
|
341
|
-
if (!excluded.includes(ref.ref) && !looksSecret(text)) evidence.runs[ref.ref] = takeChars(text, 60_000)
|
|
342
|
-
}
|
|
343
|
-
if (ref.kind === 'source') {
|
|
344
|
-
const source = store.listSources(wiki).find(source => source.id === ref.ref)
|
|
345
|
-
if (source) {
|
|
346
|
-
const text = readFileSync(join(wiki, 'raw', source.id, source.name), 'utf8')
|
|
347
|
-
if (!looksSecret(text)) evidence.sources[ref.ref] = takeChars(text, 60_000)
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
const outcome = apply(wiki, prepared?.namespace ?? proposalInput?.namespace ?? store.LIBRARY_NAMESPACE, trigger, proposals, new Map(job.hashes), evidence, id, context.agentName ?? 'Curator')
|
|
353
|
-
if (outcome.operation) writeJson(join(wiki, 'operations', `${outcome.operation.id}.json`), { ...outcome.operation, protected: true })
|
|
354
|
-
job.receipt = { operationId: outcome.operation?.id ?? null, notes: outcome.notes, parked: outcome.parked, flagged: outcome.flagged }
|
|
355
|
-
}
|
|
356
|
-
job.status = job.receipt.parked ? 'needs_user' : 'completed'
|
|
357
|
-
job.reason = reason
|
|
358
|
-
reindexQuietly(root)
|
|
359
|
-
this.options.bus.emit({ type: 'wiki.changed' })
|
|
360
|
-
return saveCuration(root, job)
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
finishRun(runId: string, failed: boolean): void {
|
|
364
|
-
for (const job of this.jobs().filter((job) => job.runId === runId && job.status === 'running')) {
|
|
365
|
-
job.status = failed ? 'failed' : 'completed'
|
|
366
|
-
job.reason = failed ? 'The run stopped before completing this request. Retry it explicitly.' : 'The review completed without applying a change.'
|
|
367
|
-
job.receipt ??= { operationId: null, notes: [job.reason], parked: 0, flagged: 0 }
|
|
368
|
-
saveCuration(this.options.env.root, job)
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
retry(id: string): CurationJob {
|
|
373
|
-
const job = curationJob(this.options.env.root, id)
|
|
374
|
-
if (job.status !== 'failed') throw invalid('Only a failed request can be retried.')
|
|
375
|
-
return saveCuration(this.options.env.root, { ...job, status: 'queued', runId: null, reason: '', receipt: null })
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
prepare(job: Job): { request: MaintenanceRequest; evidence: Evidence; captured: Map<string, string>; namespace: string; trigger: Trigger } {
|
|
379
|
-
const { env } = this.options
|
|
380
|
-
const root = env.root
|
|
381
|
-
const wiki = store.wikiDir(root)
|
|
382
|
-
const evidence: Evidence = {}
|
|
383
|
-
let attached: blocks.Block[] = []
|
|
384
|
-
let namespace: string
|
|
385
|
-
let trigger: Trigger
|
|
386
|
-
let request: MaintenanceRequest['trigger']
|
|
387
|
-
let shown = ''
|
|
388
|
-
if (job.kind === 'ingest') {
|
|
389
|
-
const directory = join(wiki, 'raw', job.sourceId)
|
|
390
|
-
const name = readJsonOr<{ name?: unknown } | null>(join(directory, 'meta.json'), null)?.name
|
|
391
|
-
const sourceName = typeof name === 'string' ? name : 'source'
|
|
392
|
-
let text: string | null = null
|
|
393
|
-
try {
|
|
394
|
-
text = new TextDecoder('utf-8', { fatal: true }).decode(readFileSync(join(directory, sourceName)))
|
|
395
|
-
} catch {
|
|
396
|
-
text = null
|
|
397
|
-
}
|
|
398
|
-
if (text === null) {
|
|
399
|
-
throw invalid('Only text sources can be synthesized automatically right now.')
|
|
400
|
-
}
|
|
401
|
-
shown = takeChars(text, 60_000)
|
|
402
|
-
evidence.sourceText = text
|
|
403
|
-
namespace = job.namespace
|
|
404
|
-
trigger = { kind: 'ingest', sourceId: job.sourceId, sourceName }
|
|
405
|
-
request = { kind: 'ingest', sourceId: job.sourceId, sourceName, text: shown }
|
|
406
|
-
} else if (job.kind === 'run') {
|
|
407
|
-
let found: ReturnType<typeof runEvidence>
|
|
408
|
-
try {
|
|
409
|
-
found = runEvidence(root, job.runId)
|
|
410
|
-
} catch (error) {
|
|
411
|
-
throw error
|
|
412
|
-
}
|
|
413
|
-
evidence.runText = evidenceText(root, job.runId)
|
|
414
|
-
attached = runBlocks(env, job.runId)
|
|
415
|
-
shown = found.transcript
|
|
416
|
-
namespace = found.namespace
|
|
417
|
-
trigger = { kind: 'run', runId: job.runId }
|
|
418
|
-
request = { kind: 'run', runId: job.runId, transcript: shown }
|
|
419
|
-
} else {
|
|
420
|
-
attached = (job.kind === 'review' ? blocks.loadAll(wiki).filter((block) => !block.front.readOnly).sort((a, b) => charCount(b.body) / b.front.limit - charCount(a.body) / a.front.limit).slice(0, 30).map((block) => block.id) : job.blockIds).flatMap((id) => {
|
|
421
|
-
try {
|
|
422
|
-
const block = blocks.find(wiki, id)
|
|
423
|
-
return block.front.readOnly ? [] : [block]
|
|
424
|
-
} catch {
|
|
425
|
-
return []
|
|
426
|
-
}
|
|
427
|
-
})
|
|
428
|
-
if (!attached.length && job.kind !== 'review') throw invalid('No writable blocks remain in this job.')
|
|
429
|
-
namespace = store.LIBRARY_NAMESPACE
|
|
430
|
-
trigger = { kind: 'consolidate' }
|
|
431
|
-
request = { kind: 'consolidate' }
|
|
432
|
-
}
|
|
433
|
-
evidence.blocks = attached.map((block) => block.id)
|
|
434
|
-
const captured = captureHashes(wiki)
|
|
435
|
-
const context = trigger.kind === 'consolidate' ? { pages: [], memories: [] } : maintainerContext(root, namespace, shown)
|
|
436
|
-
let index = ''
|
|
437
|
-
try {
|
|
438
|
-
index = takeChars(readFileSync(join(wiki, 'index.md'), 'utf8'), 8000)
|
|
439
|
-
} catch {
|
|
440
|
-
index = ''
|
|
441
|
-
}
|
|
442
|
-
return { request: { jobId: '', namespace, trigger: request, pages: context.pages, memories: context.memories, blocks: blockValues(attached), namespaces: namespaces(root), index }, evidence, captured, namespace, trigger }
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
private async process(job: Job): Promise<void> {
|
|
446
|
-
const { env, bus } = this.options
|
|
447
|
-
const root = env.root
|
|
448
|
-
const wiki = store.wikiDir(root)
|
|
449
|
-
let prepared: ReturnType<Maintenance['prepare']>
|
|
450
|
-
try { prepared = this.prepare(job) } catch (error) {
|
|
451
|
-
const message = error instanceof Error ? error.message : String(error)
|
|
452
|
-
if (job.kind === 'run') log(`maintenance skipped run ${job.runId}: ${message}`)
|
|
453
|
-
else if (job.kind === 'ingest') { inbox(wiki, 'unresolved', 'Source was imported but not summarized', message, []); bus.emit({ type: 'wiki.changed' }) }
|
|
454
|
-
return
|
|
455
|
-
}
|
|
456
|
-
const { namespace, trigger, evidence, captured } = prepared
|
|
457
|
-
const described = describeTrigger(trigger)
|
|
458
|
-
try {
|
|
459
|
-
// The job runs on the default account.
|
|
460
|
-
const account = this.options.accounts.context(this.options.accounts.resolve())
|
|
461
|
-
const proposed = await runMaintenance(
|
|
462
|
-
{ ...prepared.request, jobId: newId() },
|
|
463
|
-
{ cwd: wiki, product: env.productName, account, runtime: () => this.options.accounts.runtime(account) },
|
|
464
|
-
this.options.factory ?? piMaintainerFactory
|
|
465
|
-
)
|
|
466
|
-
const outcome = apply(wiki, namespace, trigger, parseProposalSet(proposed), captured, evidence)
|
|
467
|
-
reindexQuietly(root)
|
|
468
|
-
if (outcome.operation) {
|
|
469
|
-
const count = outcome.operation.pages.length
|
|
470
|
-
bus.emit({ type: 'wiki.maintenance', namespace, title: `Wiki updated ${count} entr${count === 1 ? 'y' : 'ies'}`, detail: `From ${described}. ${outcome.parked} parked, ${outcome.flagged} flagged for review.` })
|
|
471
|
-
}
|
|
472
|
-
} catch (error) {
|
|
473
|
-
const message = error instanceof Error ? error.message : String(error)
|
|
474
|
-
try {
|
|
475
|
-
inbox(wiki, 'blocked', `Consolidation for ${described} did not finish`, message, [])
|
|
476
|
-
store.log(wiki, `- ${now()} · Sleep-time · ${described} · failed: ${message}`)
|
|
477
|
-
} catch {
|
|
478
|
-
// The failure is still logged by the queue.
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
bus.emit({ type: 'wiki.changed' })
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// ---- What a person does from the Inbox -------------------------------------------------------
|
|
485
|
-
|
|
486
|
-
/** Reverts an applied operation through new revisions. */
|
|
487
|
-
undoOperation(operationId: string): void {
|
|
488
|
-
const { root } = this.options.env
|
|
489
|
-
const wiki = store.wikiDir(root)
|
|
490
|
-
const operation = undo(wiki, operationId)
|
|
491
|
-
writeIndex(wiki)
|
|
492
|
-
const count = operation.pages.length
|
|
493
|
-
inbox(wiki, 'applied', `Undid an update to ${count} entr${count === 1 ? 'y' : 'ies'}`, "Earlier content was restored as new revisions; created entries moved to the Wiki's trash folder.", operation.pages.map((page) => page.pageId))
|
|
494
|
-
reindexQuietly(root)
|
|
495
|
-
this.options.bus.emit({ type: 'wiki.changed' })
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
/** Accepts a parked proposal with the user as the authority. */
|
|
499
|
-
acceptInboxItem(itemId: string): string {
|
|
500
|
-
const { root } = this.options.env
|
|
501
|
-
const message = accept(root, itemId)
|
|
502
|
-
reindexQuietly(root)
|
|
503
|
-
this.options.bus.emit({ type: 'wiki.changed' })
|
|
504
|
-
return message
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
/** Imports a file as an immutable source and queues the job that reads it. */
|
|
508
|
-
ingest(name: string, bytes: Uint8Array, namespace: string = store.LIBRARY_NAMESPACE): store.WikiSource {
|
|
509
|
-
const { root } = this.options.env
|
|
510
|
-
const wiki = store.wikiDir(root)
|
|
511
|
-
store.namespaceDir(wiki, namespace)
|
|
512
|
-
const source = store.importSource(wiki, name.replace(/[/\\]/g, '_'), bytes)
|
|
513
|
-
reindexQuietly(root)
|
|
514
|
-
this.enqueue({ kind: 'ingest', namespace, sourceId: source.id })
|
|
515
|
-
return source
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
|
package/src/memory/migrate.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
// Storage migration to version 3: memory blocks, facts, and the Library.
|
|
2
|
-
//
|
|
3
|
-
// Version 3 starts from an empty Wiki. Whatever came before is kept whole as a backup and is
|
|
4
|
-
// not carried over: a version 2 `wiki/` becomes `wiki.pre-v3/`, and a version 1 `knowledge/`
|
|
5
|
-
// becomes `knowledge.pre-v2/`. The new tree is staged in `wiki.migrating/` before anything is
|
|
6
|
-
// renamed; on failure the staged tree is removed and the earlier Wiki is left in place.
|
|
7
|
-
import { existsSync, renameSync, rmSync } from 'node:fs'
|
|
8
|
-
import { join } from 'node:path'
|
|
9
|
-
|
|
10
|
-
import type { HarnessEnv } from '../core/env'
|
|
11
|
-
import { HarnessError } from '../core/errors'
|
|
12
|
-
import { now, readJsonOr, writeJson } from '../core/fs'
|
|
13
|
-
import { listProjects } from '../core/projects'
|
|
14
|
-
import * as registry from '../skills/registry'
|
|
15
|
-
import * as blocks from './blocks'
|
|
16
|
-
import { writeIndex } from './proposals'
|
|
17
|
-
import * as store from './store'
|
|
18
|
-
|
|
19
|
-
export const WIKI_VERSION = 3
|
|
20
|
-
|
|
21
|
-
const storagePath = (root: string): string => join(root, 'config/storage.json')
|
|
22
|
-
|
|
23
|
-
export function version(root: string): number {
|
|
24
|
-
const stored = readJsonOr<{ wikiVersion?: unknown } | null>(storagePath(root), null)?.wikiVersion
|
|
25
|
-
if (typeof stored === 'number' && Number.isInteger(stored) && stored >= 0) return stored
|
|
26
|
-
const wiki = store.wikiDir(root)
|
|
27
|
-
if (store.isDir(join(root, 'knowledge'))) return 1
|
|
28
|
-
// A version 2 Wiki whose marker is missing still has its old folders and no blocks.
|
|
29
|
-
if (!existsSync(join(wiki, 'blocks')) && (store.isDir(join(wiki, 'docs')) || store.isDir(join(wiki, 'memory')))) return 2
|
|
30
|
-
return WIKI_VERSION
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const stamp = (): string => now().replace(/[:.]/g, '-')
|
|
34
|
-
|
|
35
|
-
/** Moves `from` to `<name>` beside it, or `<name>-<time>` when that backup already exists. */
|
|
36
|
-
function backUp(root: string, from: string, name: string): void {
|
|
37
|
-
if (!existsSync(from)) return
|
|
38
|
-
renameSync(from, existsSync(join(root, name)) ? join(root, `${name}-${stamp()}`) : join(root, name))
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Brings a data root to the current Wiki layout. Safe to call on every start. `agentIds` are
|
|
43
|
-
* the agents that get their own blocks. Returns whether a migration happened.
|
|
44
|
-
*/
|
|
45
|
-
export function run(env: HarnessEnv, agentIds: readonly string[] = []): boolean {
|
|
46
|
-
const { root } = env
|
|
47
|
-
if (version(root) >= WIKI_VERSION) return false
|
|
48
|
-
const failed = (detail: string): HarnessError => new HarnessError('migration_failed', `The Wiki was not migrated to version 3; your Wiki is unchanged. ${detail}`)
|
|
49
|
-
const staging = join(root, 'wiki.migrating')
|
|
50
|
-
rmSync(staging, { recursive: true, force: true })
|
|
51
|
-
try {
|
|
52
|
-
store.ensureLayoutAt(staging, env.productName)
|
|
53
|
-
blocks.ensureUser(staging)
|
|
54
|
-
for (const agentId of agentIds) blocks.ensureAgent(staging, agentId)
|
|
55
|
-
for (const project of listProjects(root)) blocks.ensureProject(staging, project.slug, project.name)
|
|
56
|
-
store.log(staging, `- ${now()} · ${env.productName} · started storage version 3; the earlier Wiki is kept as a backup beside it`)
|
|
57
|
-
backUp(root, store.wikiDir(root), 'wiki.pre-v3')
|
|
58
|
-
} catch (error) {
|
|
59
|
-
rmSync(staging, { recursive: true, force: true })
|
|
60
|
-
throw failed(error instanceof Error ? error.message : String(error))
|
|
61
|
-
}
|
|
62
|
-
renameSync(staging, store.wikiDir(root))
|
|
63
|
-
backUp(root, join(root, 'knowledge'), 'knowledge.pre-v2')
|
|
64
|
-
|
|
65
|
-
store.ensureLayout(root, env.productName)
|
|
66
|
-
for (const project of listProjects(root)) store.ensureProjectNamespace(root, project.slug, project.name)
|
|
67
|
-
// Registry items that version 1 enabled for personal agents are enabled for everyone.
|
|
68
|
-
const enablement = registry.enablement(root)
|
|
69
|
-
if ('personal' in enablement) {
|
|
70
|
-
const ids = registry.enablementIds(enablement, registry.GLOBAL_KEY)
|
|
71
|
-
for (const id of registry.enablementIds(enablement, 'personal')) if (!ids.includes(id)) ids.push(id)
|
|
72
|
-
delete enablement.personal
|
|
73
|
-
enablement[registry.GLOBAL_KEY] = ids
|
|
74
|
-
writeJson(join(root, 'config/registry-enabled.json'), enablement)
|
|
75
|
-
}
|
|
76
|
-
writeIndex(store.wikiDir(root))
|
|
77
|
-
writeJson(storagePath(root), { wikiVersion: WIKI_VERSION, migratedAt: now() })
|
|
78
|
-
return true
|
|
79
|
-
}
|