@geminixiang/mikan 1.0.0-beta.4 → 1.0.0-beta.40
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 +688 -0
- package/README.md +99 -36
- package/dist/adapter.d.ts +11 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +18 -1
- package/dist/adapter.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +6 -7
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +82 -117
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/discord/context.d.ts +3 -1
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +54 -215
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/github/bot.d.ts +89 -0
- package/dist/adapters/github/bot.d.ts.map +1 -0
- package/dist/adapters/github/bot.js +653 -0
- package/dist/adapters/github/bot.js.map +1 -0
- package/dist/adapters/github/client.d.ts +122 -0
- package/dist/adapters/github/client.d.ts.map +1 -0
- package/dist/adapters/github/client.js +314 -0
- package/dist/adapters/github/client.js.map +1 -0
- package/dist/adapters/github/cloudbuild.d.ts +19 -0
- package/dist/adapters/github/cloudbuild.d.ts.map +1 -0
- package/dist/adapters/github/cloudbuild.js +71 -0
- package/dist/adapters/github/cloudbuild.js.map +1 -0
- package/dist/adapters/github/context.d.ts +12 -0
- package/dist/adapters/github/context.d.ts.map +1 -0
- package/dist/adapters/github/context.js +101 -0
- package/dist/adapters/github/context.js.map +1 -0
- package/dist/adapters/github/gcp-auth.d.ts +28 -0
- package/dist/adapters/github/gcp-auth.d.ts.map +1 -0
- package/dist/adapters/github/gcp-auth.js +196 -0
- package/dist/adapters/github/gcp-auth.js.map +1 -0
- package/dist/adapters/github/github-ops.d.ts +91 -0
- package/dist/adapters/github/github-ops.d.ts.map +1 -0
- package/dist/adapters/github/github-ops.js +406 -0
- package/dist/adapters/github/github-ops.js.map +1 -0
- package/dist/adapters/github/ids.d.ts +34 -0
- package/dist/adapters/github/ids.d.ts.map +1 -0
- package/dist/adapters/github/ids.js +57 -0
- package/dist/adapters/github/ids.js.map +1 -0
- package/dist/adapters/github/repo.d.ts +33 -0
- package/dist/adapters/github/repo.d.ts.map +1 -0
- package/dist/adapters/github/repo.js +141 -0
- package/dist/adapters/github/repo.js.map +1 -0
- package/dist/adapters/github/tool-pack.d.ts +14 -0
- package/dist/adapters/github/tool-pack.d.ts.map +1 -0
- package/dist/adapters/github/tool-pack.js +56 -0
- package/dist/adapters/github/tool-pack.js.map +1 -0
- package/dist/adapters/github/tools/checks.d.ts +19 -0
- package/dist/adapters/github/tools/checks.d.ts.map +1 -0
- package/dist/adapters/github/tools/checks.js +105 -0
- package/dist/adapters/github/tools/checks.js.map +1 -0
- package/dist/adapters/github/tools/issue.d.ts +21 -0
- package/dist/adapters/github/tools/issue.d.ts.map +1 -0
- package/dist/adapters/github/tools/issue.js +48 -0
- package/dist/adapters/github/tools/issue.js.map +1 -0
- package/dist/adapters/github/tools/pr.d.ts +22 -0
- package/dist/adapters/github/tools/pr.d.ts.map +1 -0
- package/dist/adapters/github/tools/pr.js +48 -0
- package/dist/adapters/github/tools/pr.js.map +1 -0
- package/dist/adapters/github/tools/read.d.ts +21 -0
- package/dist/adapters/github/tools/read.d.ts.map +1 -0
- package/dist/adapters/github/tools/read.js +141 -0
- package/dist/adapters/github/tools/read.js.map +1 -0
- package/dist/adapters/github/tools/review-reply.d.ts +17 -0
- package/dist/adapters/github/tools/review-reply.d.ts.map +1 -0
- package/dist/adapters/github/tools/review-reply.js +38 -0
- package/dist/adapters/github/tools/review-reply.js.map +1 -0
- package/dist/adapters/github/tools/sync.d.ts +17 -0
- package/dist/adapters/github/tools/sync.d.ts.map +1 -0
- package/dist/adapters/github/tools/sync.js +34 -0
- package/dist/adapters/github/tools/sync.js.map +1 -0
- package/dist/adapters/github/types.d.ts +373 -0
- package/dist/adapters/github/types.d.ts.map +1 -0
- package/dist/adapters/github/types.js +2 -0
- package/dist/adapters/github/types.js.map +1 -0
- package/dist/adapters/intake.d.ts +16 -5
- package/dist/adapters/intake.d.ts.map +1 -1
- package/dist/adapters/intake.js +86 -23
- package/dist/adapters/intake.js.map +1 -1
- package/dist/adapters/progressive-renderer.d.ts +7 -0
- package/dist/adapters/progressive-renderer.d.ts.map +1 -0
- package/dist/adapters/progressive-renderer.js +383 -0
- package/dist/adapters/progressive-renderer.js.map +1 -0
- package/dist/adapters/shared.d.ts +23 -10
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/shared.js +60 -22
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/slack/blocks.d.ts +14 -0
- package/dist/adapters/slack/blocks.d.ts.map +1 -1
- package/dist/adapters/slack/blocks.js +147 -111
- package/dist/adapters/slack/blocks.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +43 -13
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +385 -207
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/context.d.ts +3 -1
- package/dist/adapters/slack/context.d.ts.map +1 -1
- package/dist/adapters/slack/context.js +11 -17
- package/dist/adapters/slack/context.js.map +1 -1
- package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
- package/dist/adapters/slack/response-lifecycle.js +126 -323
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/slack/session.d.ts.map +1 -1
- package/dist/adapters/slack/session.js +7 -11
- package/dist/adapters/slack/session.js.map +1 -1
- package/dist/adapters/slack/tool-pack.d.ts +11 -0
- package/dist/adapters/slack/tool-pack.d.ts.map +1 -0
- package/dist/adapters/slack/tool-pack.js +45 -0
- package/dist/adapters/slack/tool-pack.js.map +1 -0
- package/dist/adapters/slack/tools/attach.js +1 -1
- package/dist/adapters/slack/tools/attach.js.map +1 -1
- package/dist/adapters/slack/tools/blockkit.d.ts +14 -0
- package/dist/adapters/slack/tools/blockkit.d.ts.map +1 -0
- package/dist/adapters/slack/tools/blockkit.js +106 -0
- package/dist/adapters/slack/tools/blockkit.js.map +1 -0
- package/dist/adapters/slack/types.d.ts +40 -2
- package/dist/adapters/slack/types.d.ts.map +1 -1
- package/dist/adapters/slack/types.js.map +1 -1
- package/dist/adapters/telegram/bot.d.ts +8 -9
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +90 -117
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/adapters/telegram/context.d.ts +2 -0
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +61 -184
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/adapters/telegram/html.d.ts.map +1 -1
- package/dist/adapters/telegram/html.js +10 -7
- package/dist/adapters/telegram/html.js.map +1 -1
- package/dist/adapters/types.d.ts +109 -12
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js.map +1 -1
- package/dist/agent-events.d.ts +3 -2
- package/dist/agent-events.d.ts.map +1 -1
- package/dist/agent-events.js +19 -1
- package/dist/agent-events.js.map +1 -1
- package/dist/agent.d.ts +14 -19
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +840 -298
- package/dist/agent.js.map +1 -1
- package/dist/cli/arg-grammar.d.ts +25 -0
- package/dist/cli/arg-grammar.d.ts.map +1 -0
- package/dist/cli/arg-grammar.js +61 -0
- package/dist/cli/arg-grammar.js.map +1 -0
- package/dist/cli/boot.d.ts +5 -0
- package/dist/cli/boot.d.ts.map +1 -0
- package/dist/cli/boot.js +117 -0
- package/dist/cli/boot.js.map +1 -0
- package/dist/cli/download.d.ts.map +1 -0
- package/dist/{download.js → cli/download.js} +2 -0
- package/dist/cli/download.js.map +1 -0
- package/dist/cli/ext-dev.d.ts +2 -0
- package/dist/cli/ext-dev.d.ts.map +1 -0
- package/dist/cli/ext-dev.js +188 -0
- package/dist/cli/ext-dev.js.map +1 -0
- package/dist/cli/ext.d.ts +2 -0
- package/dist/cli/ext.d.ts.map +1 -0
- package/dist/cli/ext.js +324 -0
- package/dist/cli/ext.js.map +1 -0
- package/dist/cli/office.d.ts +2 -0
- package/dist/cli/office.d.ts.map +1 -0
- package/dist/cli/office.js +91 -0
- package/dist/cli/office.js.map +1 -0
- package/dist/cli/types.d.ts +16 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/commands/admin.d.ts.map +1 -1
- package/dist/commands/admin.js +3 -2
- package/dist/commands/admin.js.map +1 -1
- package/dist/commands/auto-reply.d.ts.map +1 -1
- package/dist/commands/auto-reply.js +5 -9
- package/dist/commands/auto-reply.js.map +1 -1
- package/dist/commands/extensions.d.ts.map +1 -1
- package/dist/commands/extensions.js +9 -6
- package/dist/commands/extensions.js.map +1 -1
- package/dist/commands/login.d.ts +2 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +40 -5
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/manifest.d.ts +37 -0
- package/dist/commands/manifest.d.ts.map +1 -0
- package/dist/commands/manifest.js +151 -0
- package/dist/commands/manifest.js.map +1 -0
- package/dist/commands/model.d.ts +2 -3
- package/dist/commands/model.d.ts.map +1 -1
- package/dist/commands/model.js +63 -24
- package/dist/commands/model.js.map +1 -1
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +15 -3
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/registry.d.ts +2 -2
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +1 -2
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +83 -33
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/commands/session-view.d.ts.map +1 -1
- package/dist/commands/session-view.js +6 -3
- package/dist/commands/session-view.js.map +1 -1
- package/dist/commands/types.d.ts +79 -7
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js.map +1 -1
- package/dist/config.d.ts +23 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +222 -135
- package/dist/config.js.map +1 -1
- package/dist/env-manifest.d.ts +30 -0
- package/dist/env-manifest.d.ts.map +1 -0
- package/dist/env-manifest.js +229 -0
- package/dist/env-manifest.js.map +1 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +20 -81
- package/dist/events.js.map +1 -1
- package/dist/execution-resolver.d.ts +7 -8
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +106 -110
- package/dist/execution-resolver.js.map +1 -1
- package/dist/extension-schedules.d.ts +31 -0
- package/dist/extension-schedules.d.ts.map +1 -0
- package/dist/extension-schedules.js +229 -0
- package/dist/extension-schedules.js.map +1 -0
- package/dist/harness/auth.d.ts +2 -1
- package/dist/harness/auth.d.ts.map +1 -1
- package/dist/harness/auth.js +11 -5
- package/dist/harness/auth.js.map +1 -1
- package/dist/harness/event-format.d.ts +27 -0
- package/dist/harness/event-format.d.ts.map +1 -0
- package/dist/harness/event-format.js +160 -0
- package/dist/harness/event-format.js.map +1 -0
- package/dist/harness/extensions/loader.d.ts +27 -49
- package/dist/harness/extensions/loader.d.ts.map +1 -1
- package/dist/harness/extensions/loader.js +486 -130
- package/dist/harness/extensions/loader.js.map +1 -1
- package/dist/harness/extensions/registry.d.ts +107 -2
- package/dist/harness/extensions/registry.d.ts.map +1 -1
- package/dist/harness/extensions/registry.js +316 -0
- package/dist/harness/extensions/registry.js.map +1 -1
- package/dist/harness/extensions/types.d.ts +482 -42
- package/dist/harness/extensions/types.d.ts.map +1 -1
- package/dist/harness/extensions/types.js.map +1 -1
- package/dist/harness/index.d.ts +18 -8
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +7 -4
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/models.d.ts +7 -4
- package/dist/harness/models.d.ts.map +1 -1
- package/dist/harness/models.js +46 -24
- package/dist/harness/models.js.map +1 -1
- package/dist/harness/runner.d.ts +50 -54
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +232 -46
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session-store.d.ts +11 -5
- package/dist/harness/session-store.d.ts.map +1 -1
- package/dist/harness/session-store.js +141 -36
- package/dist/harness/session-store.js.map +1 -1
- package/dist/harness/settings.d.ts +2 -20
- package/dist/harness/settings.d.ts.map +1 -1
- package/dist/harness/settings.js +12 -1
- package/dist/harness/settings.js.map +1 -1
- package/dist/harness/skills.d.ts +10 -29
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +48 -6
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/subagent-profiles.d.ts +8 -0
- package/dist/harness/subagent-profiles.d.ts.map +1 -0
- package/dist/harness/subagent-profiles.js +299 -0
- package/dist/harness/subagent-profiles.js.map +1 -0
- package/dist/harness/subagent-runner.d.ts +39 -0
- package/dist/harness/subagent-runner.d.ts.map +1 -0
- package/dist/harness/subagent-runner.js +617 -0
- package/dist/harness/subagent-runner.js.map +1 -0
- package/dist/harness/types.d.ts +267 -1
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/usage.d.ts +6 -0
- package/dist/harness/usage.d.ts.map +1 -0
- package/dist/harness/usage.js +32 -0
- package/dist/harness/usage.js.map +1 -0
- package/dist/index.d.ts +36 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -6
- package/dist/index.js.map +1 -1
- package/dist/main.js +391 -127
- package/dist/main.js.map +1 -1
- package/dist/observability/instrument.js +7 -5
- package/dist/observability/instrument.js.map +1 -1
- package/dist/observability/sentry.d.ts +2 -0
- package/dist/observability/sentry.d.ts.map +1 -1
- package/dist/observability/sentry.js +10 -2
- package/dist/observability/sentry.js.map +1 -1
- package/dist/office/address.d.ts +31 -0
- package/dist/office/address.d.ts.map +1 -0
- package/dist/office/address.js +113 -0
- package/dist/office/address.js.map +1 -0
- package/dist/office/index.d.ts +11 -0
- package/dist/office/index.d.ts.map +1 -0
- package/dist/office/index.js +11 -0
- package/dist/office/index.js.map +1 -0
- package/dist/office/layout.d.ts +27 -0
- package/dist/office/layout.d.ts.map +1 -0
- package/dist/office/layout.js +97 -0
- package/dist/office/layout.js.map +1 -0
- package/dist/office/migration.d.ts +44 -0
- package/dist/office/migration.d.ts.map +1 -0
- package/dist/office/migration.js +255 -0
- package/dist/office/migration.js.map +1 -0
- package/dist/office/registry.d.ts +75 -0
- package/dist/office/registry.d.ts.map +1 -0
- package/dist/office/registry.js +646 -0
- package/dist/office/registry.js.map +1 -0
- package/dist/office/types.d.ts +71 -0
- package/dist/office/types.d.ts.map +1 -0
- package/dist/office/types.js +2 -0
- package/dist/office/types.js.map +1 -0
- package/dist/packages/admin.d.ts +17 -0
- package/dist/packages/admin.d.ts.map +1 -0
- package/dist/packages/admin.js +98 -0
- package/dist/packages/admin.js.map +1 -0
- package/dist/packages/index.d.ts +6 -0
- package/dist/packages/index.d.ts.map +1 -0
- package/dist/packages/index.js +6 -0
- package/dist/packages/index.js.map +1 -0
- package/dist/packages/inspect.d.ts +11 -0
- package/dist/packages/inspect.d.ts.map +1 -0
- package/dist/packages/inspect.js +98 -0
- package/dist/packages/inspect.js.map +1 -0
- package/dist/packages/materialize.d.ts +40 -0
- package/dist/packages/materialize.d.ts.map +1 -0
- package/dist/packages/materialize.js +297 -0
- package/dist/packages/materialize.js.map +1 -0
- package/dist/packages/resolve.d.ts +25 -0
- package/dist/packages/resolve.d.ts.map +1 -0
- package/dist/packages/resolve.js +208 -0
- package/dist/packages/resolve.js.map +1 -0
- package/dist/packages/source.d.ts +39 -0
- package/dist/packages/source.d.ts.map +1 -0
- package/dist/packages/source.js +189 -0
- package/dist/packages/source.js.map +1 -0
- package/dist/packages/types.d.ts +104 -0
- package/dist/packages/types.d.ts.map +1 -0
- package/dist/packages/types.js +2 -0
- package/dist/packages/types.js.map +1 -0
- package/dist/provisioner.d.ts +66 -0
- package/dist/provisioner.d.ts.map +1 -1
- package/dist/provisioner.js +335 -13
- package/dist/provisioner.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +562 -118
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/session-lifecycle.d.ts +38 -0
- package/dist/runtime/session-lifecycle.d.ts.map +1 -0
- package/dist/runtime/session-lifecycle.js +193 -0
- package/dist/runtime/session-lifecycle.js.map +1 -0
- package/dist/runtime/types.d.ts +66 -7
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/cloudflare.d.ts +3 -0
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +13 -1
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts +4 -0
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +13 -3
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/firecracker.d.ts +3 -0
- package/dist/sandbox/firecracker.d.ts.map +1 -1
- package/dist/sandbox/firecracker.js +13 -2
- package/dist/sandbox/firecracker.js.map +1 -1
- package/dist/sandbox/gondolin.d.ts +57 -0
- package/dist/sandbox/gondolin.d.ts.map +1 -0
- package/dist/sandbox/gondolin.js +764 -0
- package/dist/sandbox/gondolin.js.map +1 -0
- package/dist/sandbox/host.d.ts +3 -0
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +18 -3
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/identity.d.ts +44 -0
- package/dist/sandbox/identity.d.ts.map +1 -0
- package/dist/sandbox/identity.js +68 -0
- package/dist/sandbox/identity.js.map +1 -0
- package/dist/sandbox/image.d.ts.map +1 -1
- package/dist/sandbox/image.js +2 -0
- package/dist/sandbox/image.js.map +1 -1
- package/dist/sandbox/index.d.ts +17 -4
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +37 -3
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +65 -1
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +14 -0
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +68 -1
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts +25 -0
- package/dist/sessions/chat-history-sync.d.ts.map +1 -0
- package/dist/sessions/{agent-memory-file-manager.js → chat-history-sync.js} +135 -131
- package/dist/sessions/chat-history-sync.js.map +1 -0
- package/dist/sessions/conversation-log.d.ts +9 -0
- package/dist/sessions/conversation-log.d.ts.map +1 -0
- package/dist/sessions/conversation-log.js +50 -0
- package/dist/sessions/conversation-log.js.map +1 -0
- package/dist/sessions/history-line.d.ts +29 -0
- package/dist/sessions/history-line.d.ts.map +1 -0
- package/dist/sessions/history-line.js +45 -0
- package/dist/sessions/history-line.js.map +1 -0
- package/dist/sessions/rotation.d.ts +2 -0
- package/dist/sessions/rotation.d.ts.map +1 -0
- package/dist/sessions/rotation.js +39 -0
- package/dist/sessions/rotation.js.map +1 -0
- package/dist/sessions/session-key.d.ts +33 -0
- package/dist/sessions/session-key.d.ts.map +1 -0
- package/dist/sessions/session-key.js +115 -0
- package/dist/sessions/session-key.js.map +1 -0
- package/dist/sessions/store.d.ts +15 -7
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +127 -36
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +19 -5
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/settings-mutation.d.ts +40 -0
- package/dist/settings-mutation.d.ts.map +1 -0
- package/dist/settings-mutation.js +61 -0
- package/dist/settings-mutation.js.map +1 -0
- package/dist/subagent-progress.d.ts +43 -0
- package/dist/subagent-progress.d.ts.map +1 -0
- package/dist/subagent-progress.js +220 -0
- package/dist/subagent-progress.js.map +1 -0
- package/dist/tools/bash.d.ts +3 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +26 -18
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +14 -13
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/event.d.ts +1 -1
- package/dist/tools/event.d.ts.map +1 -1
- package/dist/tools/event.js +58 -45
- package/dist/tools/event.js.map +1 -1
- package/dist/tools/generate-image.d.ts +23 -0
- package/dist/tools/generate-image.d.ts.map +1 -0
- package/dist/tools/generate-image.js +65 -0
- package/dist/tools/generate-image.js.map +1 -0
- package/dist/tools/host-fn-tool.d.ts +21 -0
- package/dist/tools/host-fn-tool.d.ts.map +1 -0
- package/dist/tools/host-fn-tool.js +32 -0
- package/dist/tools/host-fn-tool.js.map +1 -0
- package/dist/tools/index.d.ts +19 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +25 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/react.d.ts +15 -0
- package/dist/tools/react.d.ts.map +1 -0
- package/dist/tools/react.js +29 -0
- package/dist/tools/react.js.map +1 -0
- package/dist/tools/read.d.ts +1 -0
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +39 -33
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/sandbox.d.ts +2 -2
- package/dist/tools/sandbox.d.ts.map +1 -1
- package/dist/tools/sandbox.js +14 -9
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/tools/subagent-slots.d.ts +28 -0
- package/dist/tools/subagent-slots.d.ts.map +1 -0
- package/dist/tools/subagent-slots.js +72 -0
- package/dist/tools/subagent-slots.js.map +1 -0
- package/dist/tools/subagent.d.ts +54 -0
- package/dist/tools/subagent.d.ts.map +1 -0
- package/dist/tools/subagent.js +411 -0
- package/dist/tools/subagent.js.map +1 -0
- package/dist/tools/types.d.ts +40 -32
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +2 -8
- package/dist/tools/write.js.map +1 -1
- package/dist/trigger.d.ts +2 -1
- package/dist/trigger.d.ts.map +1 -1
- package/dist/trigger.js +6 -9
- package/dist/trigger.js.map +1 -1
- package/dist/types.d.ts +403 -59
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -2
- package/dist/types.js.map +1 -1
- package/dist/utils/file-guards.d.ts +9 -0
- package/dist/utils/file-guards.d.ts.map +1 -1
- package/dist/utils/file-guards.js +44 -1
- package/dist/utils/file-guards.js.map +1 -1
- package/dist/vault/disabled.d.ts +9 -0
- package/dist/vault/disabled.d.ts.map +1 -0
- package/dist/vault/disabled.js +25 -0
- package/dist/vault/disabled.js.map +1 -0
- package/dist/vault/index.d.ts +45 -2
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +127 -36
- package/dist/vault/index.js.map +1 -1
- package/dist/vault/types.d.ts +6 -2
- package/dist/vault/types.d.ts.map +1 -1
- package/dist/vault/types.js.map +1 -1
- package/dist/web/admin/portal.d.ts +31 -3
- package/dist/web/admin/portal.d.ts.map +1 -1
- package/dist/web/admin/portal.js +846 -345
- package/dist/web/admin/portal.js.map +1 -1
- package/dist/web/admin/provider-models.js +1 -1
- package/dist/web/admin/provider-models.js.map +1 -1
- package/dist/web/admin/types.d.ts +23 -3
- package/dist/web/admin/types.d.ts.map +1 -1
- package/dist/web/admin/types.js.map +1 -1
- package/dist/web/login/oauth.d.ts +2 -3
- package/dist/web/login/oauth.d.ts.map +1 -1
- package/dist/web/login/oauth.js +1 -32
- package/dist/web/login/oauth.js.map +1 -1
- package/dist/web/login/portal.d.ts +1 -1
- package/dist/web/login/portal.d.ts.map +1 -1
- package/dist/web/login/portal.js +13 -36
- package/dist/web/login/portal.js.map +1 -1
- package/dist/web/login/types.d.ts +0 -11
- package/dist/web/login/types.d.ts.map +1 -1
- package/dist/web/login/types.js.map +1 -1
- package/dist/web/portal-shell.d.ts +21 -0
- package/dist/web/portal-shell.d.ts.map +1 -0
- package/dist/{portal-shell.js → web/portal-shell.js} +67 -2
- package/dist/web/portal-shell.js.map +1 -0
- package/dist/web/server.d.ts +3 -2
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +11 -4
- package/dist/web/server.js.map +1 -1
- package/dist/web/session-view/portal.d.ts +1 -1
- package/dist/web/session-view/portal.d.ts.map +1 -1
- package/dist/web/session-view/portal.js +37 -28
- package/dist/web/session-view/portal.js.map +1 -1
- package/dist/web/session-view/service.d.ts +1 -1
- package/dist/web/session-view/service.d.ts.map +1 -1
- package/dist/web/session-view/service.js +61 -18
- package/dist/web/session-view/service.js.map +1 -1
- package/dist/web/session-view/types.d.ts +0 -3
- package/dist/web/session-view/types.d.ts.map +1 -1
- package/dist/web/session-view/types.js.map +1 -1
- package/dist/web/token-store.js +1 -1
- package/dist/web/token-store.js.map +1 -1
- package/dist/workspace-projection/index.d.ts +10 -0
- package/dist/workspace-projection/index.d.ts.map +1 -0
- package/dist/workspace-projection/index.js +120 -0
- package/dist/workspace-projection/index.js.map +1 -0
- package/dist/workspace-projection/types.d.ts +16 -0
- package/dist/workspace-projection/types.d.ts.map +1 -0
- package/dist/workspace-projection/types.js +2 -0
- package/dist/workspace-projection/types.js.map +1 -0
- package/package.json +67 -37
- package/dist/adapters/streaming.d.ts +0 -18
- package/dist/adapters/streaming.d.ts.map +0 -1
- package/dist/adapters/streaming.js +0 -44
- package/dist/adapters/streaming.js.map +0 -1
- package/dist/commands/parse.d.ts +0 -7
- package/dist/commands/parse.d.ts.map +0 -1
- package/dist/commands/parse.js +0 -14
- package/dist/commands/parse.js.map +0 -1
- package/dist/download.d.ts.map +0 -1
- package/dist/download.js.map +0 -1
- package/dist/model-registry.d.ts +0 -4
- package/dist/model-registry.d.ts.map +0 -1
- package/dist/model-registry.js +0 -7
- package/dist/model-registry.js.map +0 -1
- package/dist/portal-shell.d.ts +0 -4
- package/dist/portal-shell.d.ts.map +0 -1
- package/dist/portal-shell.js.map +0 -1
- package/dist/runtime/agent-run-controller.d.ts +0 -31
- package/dist/runtime/agent-run-controller.d.ts.map +0 -1
- package/dist/runtime/agent-run-controller.js +0 -195
- package/dist/runtime/agent-run-controller.js.map +0 -1
- package/dist/sandbox/path-context.d.ts +0 -3
- package/dist/sandbox/path-context.d.ts.map +0 -1
- package/dist/sandbox/path-context.js +0 -20
- package/dist/sandbox/path-context.js.map +0 -1
- package/dist/sessions/agent-memory-file-manager.d.ts +0 -19
- package/dist/sessions/agent-memory-file-manager.d.ts.map +0 -1
- package/dist/sessions/agent-memory-file-manager.js.map +0 -1
- package/dist/sessions/metadata.d.ts +0 -3
- package/dist/sessions/metadata.d.ts.map +0 -1
- package/dist/sessions/metadata.js +0 -11
- package/dist/sessions/metadata.js.map +0 -1
- package/dist/sessions/policy.d.ts +0 -6
- package/dist/sessions/policy.d.ts.map +0 -1
- package/dist/sessions/policy.js +0 -23
- package/dist/sessions/policy.js.map +0 -1
- package/dist/store.d.ts +0 -46
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -177
- package/dist/store.js.map +0 -1
- package/dist/tools/truncate.d.ts +0 -33
- package/dist/tools/truncate.d.ts.map +0 -1
- package/dist/tools/truncate.js +0 -184
- package/dist/tools/truncate.js.map +0 -1
- package/dist/utils/date.d.ts +0 -10
- package/dist/utils/date.d.ts.map +0 -1
- package/dist/utils/date.js +0 -23
- package/dist/utils/date.js.map +0 -1
- package/dist/utils/env.d.ts +0 -3
- package/dist/utils/env.d.ts.map +0 -1
- package/dist/utils/env.js +0 -12
- package/dist/utils/env.js.map +0 -1
- package/dist/utils/fs-atomic.d.ts +0 -10
- package/dist/utils/fs-atomic.d.ts.map +0 -1
- package/dist/utils/fs-atomic.js +0 -45
- package/dist/utils/fs-atomic.js.map +0 -1
- package/dist/utils/html.d.ts +0 -2
- package/dist/utils/html.d.ts.map +0 -1
- package/dist/utils/html.js +0 -4
- package/dist/utils/html.js.map +0 -1
- package/dist/utils/http-body.d.ts +0 -10
- package/dist/utils/http-body.d.ts.map +0 -1
- package/dist/utils/http-body.js +0 -34
- package/dist/utils/http-body.js.map +0 -1
- package/dist/vault/routing.d.ts +0 -3
- package/dist/vault/routing.d.ts.map +0 -1
- package/dist/vault/routing.js +0 -13
- package/dist/vault/routing.js.map +0 -1
- package/dist/web/agent-events/portal.d.ts +0 -3
- package/dist/web/agent-events/portal.d.ts.map +0 -1
- package/dist/web/agent-events/portal.js +0 -18
- package/dist/web/agent-events/portal.js.map +0 -1
- package/dist/web/request.d.ts +0 -3
- package/dist/web/request.d.ts.map +0 -1
- package/dist/web/request.js +0 -13
- package/dist/web/request.js.map +0 -1
- package/dist/web/session-view/command.d.ts +0 -4
- package/dist/web/session-view/command.d.ts.map +0 -1
- package/dist/web/session-view/command.js +0 -7
- package/dist/web/session-view/command.js.map +0 -1
- /package/dist/{download.d.ts → cli/download.d.ts} +0 -0
|
@@ -0,0 +1,646 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { lstatSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { officeDir, officeKey, assertConversationId, assertPlatformName, validateOfficeAddress, } from "./address.js";
|
|
5
|
+
import { parseGithubConversationId } from "../adapters/github/ids.js";
|
|
6
|
+
import { isRecord, readTextFileIfExists } from "../utils/file-guards.js";
|
|
7
|
+
import { atomicWritePrivateFile } from "../utils/file-guards.js";
|
|
8
|
+
const REGISTRY_VERSION = 1;
|
|
9
|
+
const REGISTRY_FILENAME = "office-registry.json";
|
|
10
|
+
const MIGRATION_STATUSES = new Set([
|
|
11
|
+
"needs-owner",
|
|
12
|
+
"prepared",
|
|
13
|
+
"moving",
|
|
14
|
+
"committed",
|
|
15
|
+
"failed",
|
|
16
|
+
]);
|
|
17
|
+
const REGISTRY_LOCK_FILENAME = ".office-registry.lock";
|
|
18
|
+
const REGISTRY_LOCK_RETRY_MS = 25;
|
|
19
|
+
const REGISTRY_LOCK_TIMEOUT_MS = 5_000;
|
|
20
|
+
const REGISTRY_LOCK_STALE_MS = 60_000;
|
|
21
|
+
export class OfficeRegistry {
|
|
22
|
+
constructor(stateDir, options = {}) {
|
|
23
|
+
this.stateDir = resolve(stateDir);
|
|
24
|
+
mkdirSync(this.stateDir, { recursive: true, mode: 0o700 });
|
|
25
|
+
assertRegularDirectory(this.stateDir, "State directory");
|
|
26
|
+
this.registryPath = resolve(this.stateDir, REGISTRY_FILENAME);
|
|
27
|
+
this.lockPath = join(this.stateDir, REGISTRY_LOCK_FILENAME);
|
|
28
|
+
this.writeState = options.writeState ?? atomicWritePrivateFile;
|
|
29
|
+
this.lockTimeoutMs = options.lockTimeoutMs ?? REGISTRY_LOCK_TIMEOUT_MS;
|
|
30
|
+
this.state = this.readState();
|
|
31
|
+
}
|
|
32
|
+
/** Reload the atomic registry file after another host process changed it. */
|
|
33
|
+
reload() {
|
|
34
|
+
this.state = this.readState();
|
|
35
|
+
return this.state;
|
|
36
|
+
}
|
|
37
|
+
getState() {
|
|
38
|
+
return this.state;
|
|
39
|
+
}
|
|
40
|
+
getMigration(rawConversationId) {
|
|
41
|
+
assertConversationId(rawConversationId);
|
|
42
|
+
return this.state.migrations.find((record) => record.rawConversationId === rawConversationId);
|
|
43
|
+
}
|
|
44
|
+
enablePlatform(platform) {
|
|
45
|
+
const validPlatform = assertPlatformName(platform);
|
|
46
|
+
return this.withExclusiveLease(() => {
|
|
47
|
+
if (this.state.enabledPlatforms.includes(validPlatform))
|
|
48
|
+
return this.state;
|
|
49
|
+
const enabledPlatforms = [...this.state.enabledPlatforms, validPlatform].toSorted();
|
|
50
|
+
this.replaceState(enabledPlatforms, this.state.offices, this.state.migrations);
|
|
51
|
+
return this.state;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Record that an office exists. Idempotent: re-recording a known office is
|
|
56
|
+
* a lock-free cache hit for callers that materialize directories per
|
|
57
|
+
* message, so this sits safely on hot write paths.
|
|
58
|
+
*/
|
|
59
|
+
recordOffice(address) {
|
|
60
|
+
const normalized = validateOfficeAddress(address);
|
|
61
|
+
const existing = this.findOffice(normalized);
|
|
62
|
+
if (existing)
|
|
63
|
+
return existing;
|
|
64
|
+
return this.withExclusiveLease(() => {
|
|
65
|
+
const found = this.findOffice(normalized);
|
|
66
|
+
if (found)
|
|
67
|
+
return found;
|
|
68
|
+
const record = Object.freeze({
|
|
69
|
+
platform: normalized.platform,
|
|
70
|
+
conversationId: normalized.conversationId,
|
|
71
|
+
recordedAt: new Date().toISOString(),
|
|
72
|
+
});
|
|
73
|
+
this.replaceState(this.state.enabledPlatforms, [...this.state.offices, record], this.state.migrations);
|
|
74
|
+
return record;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
getOffices() {
|
|
78
|
+
return this.state.offices;
|
|
79
|
+
}
|
|
80
|
+
findOffice(address) {
|
|
81
|
+
return this.state.offices.find((record) => record.platform === address.platform && record.conversationId === address.conversationId);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Validate and record a legacy directory. With exactly one enabled platform,
|
|
85
|
+
* ownership is safe to infer. With zero or multiple platforms, the record
|
|
86
|
+
* remains explicit `needs-owner` unless the caller supplies an owner.
|
|
87
|
+
*/
|
|
88
|
+
prepareLegacyMigration(options) {
|
|
89
|
+
const rawConversationId = assertConversationId(options.rawConversationId);
|
|
90
|
+
const sourceDir = resolve(options.sourceDir);
|
|
91
|
+
const workspaceRoot = resolve(options.workspaceRoot);
|
|
92
|
+
return this.withExclusiveLease(() => {
|
|
93
|
+
const existing = this.getMigration(rawConversationId);
|
|
94
|
+
assertCanonicalSource(sourceDir, workspaceRoot, rawConversationId);
|
|
95
|
+
if (existing) {
|
|
96
|
+
assertSameMigrationInputs(existing, sourceDir, workspaceRoot);
|
|
97
|
+
if (existing.status !== "needs-owner")
|
|
98
|
+
return existing;
|
|
99
|
+
}
|
|
100
|
+
assertRegularDirectory(sourceDir, "Legacy office source");
|
|
101
|
+
const ownerPlatform = this.resolveOwner(options.ownerPlatform, rawConversationId);
|
|
102
|
+
if (!ownerPlatform) {
|
|
103
|
+
const record = makeRecord({
|
|
104
|
+
rawConversationId,
|
|
105
|
+
sourceDir,
|
|
106
|
+
workspaceRoot,
|
|
107
|
+
status: "needs-owner",
|
|
108
|
+
});
|
|
109
|
+
this.replaceMigration(existing, record);
|
|
110
|
+
return record;
|
|
111
|
+
}
|
|
112
|
+
const targetDir = officeDir(workspaceRoot, {
|
|
113
|
+
platform: ownerPlatform,
|
|
114
|
+
conversationId: rawConversationId,
|
|
115
|
+
});
|
|
116
|
+
if (pathExists(targetDir)) {
|
|
117
|
+
const failed = makeRecord({
|
|
118
|
+
rawConversationId,
|
|
119
|
+
sourceDir,
|
|
120
|
+
workspaceRoot,
|
|
121
|
+
ownerPlatform,
|
|
122
|
+
targetDir,
|
|
123
|
+
status: "failed",
|
|
124
|
+
error: "Target office directory already exists",
|
|
125
|
+
});
|
|
126
|
+
this.replaceMigration(existing, failed);
|
|
127
|
+
throw new Error(`${failed.error}: ${targetDir}`);
|
|
128
|
+
}
|
|
129
|
+
const prepared = makeRecord({
|
|
130
|
+
rawConversationId,
|
|
131
|
+
sourceDir,
|
|
132
|
+
workspaceRoot,
|
|
133
|
+
ownerPlatform,
|
|
134
|
+
targetDir,
|
|
135
|
+
status: "prepared",
|
|
136
|
+
});
|
|
137
|
+
this.replaceMigration(existing, prepared);
|
|
138
|
+
return prepared;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
markMoving(rawConversationId) {
|
|
142
|
+
return this.withExclusiveLease(() => {
|
|
143
|
+
const record = this.requireMigration(rawConversationId);
|
|
144
|
+
if (record.status === "moving" ||
|
|
145
|
+
record.status === "committed" ||
|
|
146
|
+
record.status === "failed") {
|
|
147
|
+
return record;
|
|
148
|
+
}
|
|
149
|
+
if (record.status === "needs-owner") {
|
|
150
|
+
throw new Error(`Legacy office ${JSON.stringify(rawConversationId)} still needs an owner`);
|
|
151
|
+
}
|
|
152
|
+
assertRegularDirectory(record.sourceDir, "Legacy office source");
|
|
153
|
+
const targetDir = migrationTarget(record);
|
|
154
|
+
if (!targetDir)
|
|
155
|
+
throw new Error("Prepared office migration has no target directory");
|
|
156
|
+
if (pathExists(targetDir)) {
|
|
157
|
+
const failed = this.failRecord(record, "Target office directory appeared before moving");
|
|
158
|
+
throw new Error(`${failed.error}: ${targetDir}`);
|
|
159
|
+
}
|
|
160
|
+
const moving = transitionRecord(record, "moving");
|
|
161
|
+
this.replaceMigration(record, moving);
|
|
162
|
+
return moving;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
markCommitted(rawConversationId) {
|
|
166
|
+
return this.withExclusiveLease(() => {
|
|
167
|
+
const record = this.requireMigration(rawConversationId);
|
|
168
|
+
if (record.status === "committed" || record.status === "failed")
|
|
169
|
+
return record;
|
|
170
|
+
if (record.status !== "moving") {
|
|
171
|
+
throw new Error(`Cannot commit office migration from ${record.status}`);
|
|
172
|
+
}
|
|
173
|
+
const targetDir = migrationTarget(record);
|
|
174
|
+
if (!targetDir)
|
|
175
|
+
throw new Error("Moving office migration has no target directory");
|
|
176
|
+
assertRegularDirectory(targetDir, "Migrated office target");
|
|
177
|
+
assertPathAbsent(record.sourceDir, "Legacy office source");
|
|
178
|
+
const committed = transitionRecord(record, "committed");
|
|
179
|
+
this.replaceMigration(record, committed);
|
|
180
|
+
return committed;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
markFailed(rawConversationId, error) {
|
|
184
|
+
return this.withExclusiveLease(() => {
|
|
185
|
+
const record = this.requireMigration(rawConversationId);
|
|
186
|
+
if (record.status === "committed") {
|
|
187
|
+
throw new Error("A committed office migration cannot be marked failed");
|
|
188
|
+
}
|
|
189
|
+
if (record.status === "failed")
|
|
190
|
+
return record;
|
|
191
|
+
return this.failRecord(record, error);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
resolveOwner(ownerPlatform, rawConversationId) {
|
|
195
|
+
if (ownerPlatform !== undefined) {
|
|
196
|
+
const validPlatform = assertPlatformName(ownerPlatform);
|
|
197
|
+
if (!this.state.enabledPlatforms.includes(validPlatform)) {
|
|
198
|
+
throw new Error(`Owner platform ${validPlatform} is not enabled`);
|
|
199
|
+
}
|
|
200
|
+
return validPlatform;
|
|
201
|
+
}
|
|
202
|
+
const candidates = platformsMatchingConversationIdFormat(rawConversationId, this.state.enabledPlatforms);
|
|
203
|
+
return candidates.length === 1 ? candidates[0] : undefined;
|
|
204
|
+
}
|
|
205
|
+
requireMigration(rawConversationId) {
|
|
206
|
+
assertConversationId(rawConversationId);
|
|
207
|
+
const record = this.getMigration(rawConversationId);
|
|
208
|
+
if (!record)
|
|
209
|
+
throw new Error(`No office migration registered for ${rawConversationId}`);
|
|
210
|
+
return record;
|
|
211
|
+
}
|
|
212
|
+
failRecord(record, error) {
|
|
213
|
+
const message = error.trim();
|
|
214
|
+
if (!message)
|
|
215
|
+
throw new Error("Office migration failure reason must not be empty");
|
|
216
|
+
const failed = transitionRecord(record, "failed", message);
|
|
217
|
+
this.replaceMigration(record, failed);
|
|
218
|
+
return failed;
|
|
219
|
+
}
|
|
220
|
+
replaceMigration(previous, next) {
|
|
221
|
+
const migrations = [...this.state.migrations];
|
|
222
|
+
const index = previous
|
|
223
|
+
? migrations.findIndex((record) => record.rawConversationId === previous.rawConversationId)
|
|
224
|
+
: -1;
|
|
225
|
+
if (index === -1)
|
|
226
|
+
migrations.push(next);
|
|
227
|
+
else
|
|
228
|
+
migrations[index] = next;
|
|
229
|
+
this.replaceState(this.state.enabledPlatforms, this.state.offices, migrations);
|
|
230
|
+
}
|
|
231
|
+
replaceState(enabledPlatforms, offices, migrations) {
|
|
232
|
+
const candidate = freezeState({ enabledPlatforms, offices, migrations });
|
|
233
|
+
this.writeState(this.registryPath, `${JSON.stringify(candidate, null, 2)}\n`);
|
|
234
|
+
this.state = candidate;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Acquire the domain lease, reload while holding it, then perform one
|
|
238
|
+
* read-modify-write. A future move transaction can retain the same lease
|
|
239
|
+
* across its filesystem operation instead of splitting the transition.
|
|
240
|
+
*/
|
|
241
|
+
withExclusiveLease(operation) {
|
|
242
|
+
const release = acquireRegistryLease(this.lockPath, this.lockTimeoutMs);
|
|
243
|
+
try {
|
|
244
|
+
this.state = this.readState();
|
|
245
|
+
return operation();
|
|
246
|
+
}
|
|
247
|
+
finally {
|
|
248
|
+
release();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
readState() {
|
|
252
|
+
assertRegistryFileSafe(this.registryPath);
|
|
253
|
+
const raw = readTextFileIfExists(this.registryPath);
|
|
254
|
+
if (raw === undefined) {
|
|
255
|
+
return freezeState({ enabledPlatforms: [], offices: [], migrations: [] });
|
|
256
|
+
}
|
|
257
|
+
let value;
|
|
258
|
+
try {
|
|
259
|
+
value = JSON.parse(raw);
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
throw new Error(`Invalid office registry JSON at ${this.registryPath}`, { cause: error });
|
|
263
|
+
}
|
|
264
|
+
return parseState(value, this.registryPath);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function makeRecord(fields) {
|
|
268
|
+
const record = {
|
|
269
|
+
rawConversationId: fields.rawConversationId,
|
|
270
|
+
sourceDir: fields.sourceDir,
|
|
271
|
+
workspaceRoot: fields.workspaceRoot,
|
|
272
|
+
...(fields.ownerPlatform ? { ownerPlatform: fields.ownerPlatform } : {}),
|
|
273
|
+
...(fields.targetDir ? { targetDir: fields.targetDir } : {}),
|
|
274
|
+
status: fields.status,
|
|
275
|
+
...(fields.error ? { error: fields.error } : {}),
|
|
276
|
+
updatedAt: fields.updatedAt ?? new Date().toISOString(),
|
|
277
|
+
};
|
|
278
|
+
return Object.freeze(record);
|
|
279
|
+
}
|
|
280
|
+
function transitionRecord(record, status, error) {
|
|
281
|
+
const targetDir = migrationTarget(record);
|
|
282
|
+
return makeRecord({
|
|
283
|
+
rawConversationId: record.rawConversationId,
|
|
284
|
+
sourceDir: record.sourceDir,
|
|
285
|
+
workspaceRoot: record.workspaceRoot,
|
|
286
|
+
...(record.ownerPlatform ? { ownerPlatform: record.ownerPlatform } : {}),
|
|
287
|
+
...(targetDir ? { targetDir } : {}),
|
|
288
|
+
status,
|
|
289
|
+
...(error ? { error } : {}),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
function migrationTarget(record) {
|
|
293
|
+
return record.ownerPlatform
|
|
294
|
+
? officeDir(record.workspaceRoot, {
|
|
295
|
+
platform: record.ownerPlatform,
|
|
296
|
+
conversationId: record.rawConversationId,
|
|
297
|
+
})
|
|
298
|
+
: undefined;
|
|
299
|
+
}
|
|
300
|
+
function freezeState(input) {
|
|
301
|
+
return Object.freeze({
|
|
302
|
+
version: REGISTRY_VERSION,
|
|
303
|
+
enabledPlatforms: Object.freeze([...input.enabledPlatforms]),
|
|
304
|
+
offices: Object.freeze(input.offices.map((record) => Object.freeze({ ...record }))),
|
|
305
|
+
migrations: Object.freeze(input.migrations.map((record) => Object.freeze({ ...record }))),
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
function parseState(value, path) {
|
|
309
|
+
if (!isRecord(value) || value.version !== REGISTRY_VERSION) {
|
|
310
|
+
throw new Error(`Invalid office registry version at ${path}`);
|
|
311
|
+
}
|
|
312
|
+
if (!Array.isArray(value.enabledPlatforms) || !Array.isArray(value.migrations)) {
|
|
313
|
+
throw new Error(`Invalid office registry shape at ${path}`);
|
|
314
|
+
}
|
|
315
|
+
const enabledPlatforms = value.enabledPlatforms.map((platform) => {
|
|
316
|
+
if (typeof platform !== "string")
|
|
317
|
+
throw new Error(`Invalid enabled platform in ${path}`);
|
|
318
|
+
return assertPlatformName(platform);
|
|
319
|
+
});
|
|
320
|
+
if (new Set(enabledPlatforms).size !== enabledPlatforms.length) {
|
|
321
|
+
throw new Error(`Duplicate enabled platform in ${path}`);
|
|
322
|
+
}
|
|
323
|
+
// Files written before office records existed simply have no offices yet.
|
|
324
|
+
const offices = (Array.isArray(value.offices) ? value.offices : []).map((entry) => parseOfficeRecord(entry, path));
|
|
325
|
+
if (new Set(offices.map((record) => officeKey(record))).size !== offices.length) {
|
|
326
|
+
throw new Error(`Duplicate office record in ${path}`);
|
|
327
|
+
}
|
|
328
|
+
const migrations = value.migrations.map((entry) => parseRecord(entry, path, enabledPlatforms));
|
|
329
|
+
if (new Set(migrations.map((record) => record.rawConversationId)).size !== migrations.length) {
|
|
330
|
+
throw new Error(`Duplicate office migration in ${path}`);
|
|
331
|
+
}
|
|
332
|
+
return freezeState({ enabledPlatforms, offices, migrations });
|
|
333
|
+
}
|
|
334
|
+
function parseOfficeRecord(value, path) {
|
|
335
|
+
if (!isRecord(value))
|
|
336
|
+
throw new Error(`Invalid office record in ${path}`);
|
|
337
|
+
if (typeof value.platform !== "string" ||
|
|
338
|
+
typeof value.conversationId !== "string" ||
|
|
339
|
+
typeof value.recordedAt !== "string") {
|
|
340
|
+
throw new Error(`Invalid office record fields in ${path}`);
|
|
341
|
+
}
|
|
342
|
+
return Object.freeze({
|
|
343
|
+
platform: assertPlatformName(value.platform),
|
|
344
|
+
conversationId: assertConversationId(value.conversationId),
|
|
345
|
+
recordedAt: value.recordedAt,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
function parseRecord(value, path, enabledPlatforms) {
|
|
349
|
+
if (!isRecord(value))
|
|
350
|
+
throw new Error(`Invalid office migration record in ${path}`);
|
|
351
|
+
if (typeof value.rawConversationId !== "string" ||
|
|
352
|
+
typeof value.sourceDir !== "string" ||
|
|
353
|
+
typeof value.workspaceRoot !== "string" ||
|
|
354
|
+
typeof value.status !== "string" ||
|
|
355
|
+
typeof value.updatedAt !== "string") {
|
|
356
|
+
throw new Error(`Invalid office migration fields in ${path}`);
|
|
357
|
+
}
|
|
358
|
+
assertConversationId(value.rawConversationId);
|
|
359
|
+
if (!isAbsolute(value.sourceDir) || !isAbsolute(value.workspaceRoot)) {
|
|
360
|
+
throw new Error(`Office migration paths must be absolute in ${path}`);
|
|
361
|
+
}
|
|
362
|
+
assertCanonicalSource(value.sourceDir, value.workspaceRoot, value.rawConversationId);
|
|
363
|
+
if (!MIGRATION_STATUSES.has(value.status)) {
|
|
364
|
+
throw new Error(`Invalid office migration status in ${path}`);
|
|
365
|
+
}
|
|
366
|
+
const ownerPlatform = optionalPlatform(value.ownerPlatform);
|
|
367
|
+
const targetDir = optionalString(value.targetDir);
|
|
368
|
+
const error = optionalString(value.error);
|
|
369
|
+
if (ownerPlatform !== undefined && !enabledPlatforms.includes(ownerPlatform)) {
|
|
370
|
+
throw new Error(`Office migration owner is not enabled in ${path}`);
|
|
371
|
+
}
|
|
372
|
+
if (value.status === "needs-owner" && (ownerPlatform !== undefined || targetDir !== undefined)) {
|
|
373
|
+
throw new Error(`Needs-owner migration cannot have an owner or target in ${path}`);
|
|
374
|
+
}
|
|
375
|
+
if (value.status !== "needs-owner" &&
|
|
376
|
+
value.status !== "failed" &&
|
|
377
|
+
(ownerPlatform === undefined || targetDir === undefined)) {
|
|
378
|
+
throw new Error(`Prepared office migration is missing ownership in ${path}`);
|
|
379
|
+
}
|
|
380
|
+
if (ownerPlatform === undefined && targetDir !== undefined) {
|
|
381
|
+
throw new Error(`Office migration target has no owner in ${path}`);
|
|
382
|
+
}
|
|
383
|
+
const expectedTargetDir = ownerPlatform
|
|
384
|
+
? officeDir(value.workspaceRoot, {
|
|
385
|
+
platform: ownerPlatform,
|
|
386
|
+
conversationId: value.rawConversationId,
|
|
387
|
+
})
|
|
388
|
+
: undefined;
|
|
389
|
+
if (targetDir !== expectedTargetDir) {
|
|
390
|
+
throw new Error(`Office migration target does not match its office address in ${path}`);
|
|
391
|
+
}
|
|
392
|
+
if (value.status === "failed" && !error) {
|
|
393
|
+
throw new Error(`Failed office migration is missing an error in ${path}`);
|
|
394
|
+
}
|
|
395
|
+
return makeRecord({
|
|
396
|
+
rawConversationId: value.rawConversationId,
|
|
397
|
+
sourceDir: value.sourceDir,
|
|
398
|
+
workspaceRoot: value.workspaceRoot,
|
|
399
|
+
...(ownerPlatform ? { ownerPlatform } : {}),
|
|
400
|
+
...(expectedTargetDir ? { targetDir: expectedTargetDir } : {}),
|
|
401
|
+
status: value.status,
|
|
402
|
+
...(error ? { error } : {}),
|
|
403
|
+
updatedAt: value.updatedAt,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
function optionalPlatform(value) {
|
|
407
|
+
return value === undefined
|
|
408
|
+
? undefined
|
|
409
|
+
: typeof value === "string"
|
|
410
|
+
? assertPlatformName(value)
|
|
411
|
+
: failOptional("platform");
|
|
412
|
+
}
|
|
413
|
+
function optionalString(value) {
|
|
414
|
+
return value === undefined
|
|
415
|
+
? undefined
|
|
416
|
+
: typeof value === "string"
|
|
417
|
+
? value
|
|
418
|
+
: failOptional("string");
|
|
419
|
+
}
|
|
420
|
+
function failOptional(label) {
|
|
421
|
+
throw new Error(`Invalid optional ${label} in office registry`);
|
|
422
|
+
}
|
|
423
|
+
function assertSameMigrationInputs(existing, sourceDir, workspaceRoot) {
|
|
424
|
+
if (existing.sourceDir !== sourceDir || existing.workspaceRoot !== workspaceRoot) {
|
|
425
|
+
throw new Error(`Legacy office migration inputs changed for ${existing.rawConversationId}`);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
function assertCanonicalSource(sourceDir, workspaceRoot, rawConversationId) {
|
|
429
|
+
const expectedSourceDir = resolve(workspaceRoot, rawConversationId);
|
|
430
|
+
if (sourceDir !== expectedSourceDir) {
|
|
431
|
+
throw new Error(`Legacy office source must be ${expectedSourceDir}`);
|
|
432
|
+
}
|
|
433
|
+
assertRegularDirectory(workspaceRoot, "Workspace root");
|
|
434
|
+
assertPathIfPresent(sourceDir, "Legacy office source");
|
|
435
|
+
}
|
|
436
|
+
function assertRegularDirectory(path, label) {
|
|
437
|
+
let stat;
|
|
438
|
+
try {
|
|
439
|
+
stat = lstatSync(path);
|
|
440
|
+
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
throw new Error(`${label} does not exist: ${path}`, { cause: error });
|
|
443
|
+
}
|
|
444
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
445
|
+
throw new Error(`${label} must be a regular directory: ${path}`);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
function assertRegistryFileSafe(path) {
|
|
449
|
+
try {
|
|
450
|
+
const stat = lstatSync(path);
|
|
451
|
+
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
452
|
+
throw new Error(`Office registry must be a regular file: ${path}`);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
catch (error) {
|
|
456
|
+
if (isErrno(error, "ENOENT"))
|
|
457
|
+
return;
|
|
458
|
+
throw error;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
function assertPathIfPresent(path, label) {
|
|
462
|
+
try {
|
|
463
|
+
const stat = lstatSync(path);
|
|
464
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
465
|
+
throw new Error(`${label} must be a regular directory: ${path}`);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
catch (error) {
|
|
469
|
+
if (isErrno(error, "ENOENT"))
|
|
470
|
+
return;
|
|
471
|
+
throw error;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
function assertPathAbsent(path, label) {
|
|
475
|
+
try {
|
|
476
|
+
lstatSync(path);
|
|
477
|
+
}
|
|
478
|
+
catch (error) {
|
|
479
|
+
if (isErrno(error, "ENOENT"))
|
|
480
|
+
return;
|
|
481
|
+
throw error;
|
|
482
|
+
}
|
|
483
|
+
throw new Error(`${label} must be absent: ${path}`);
|
|
484
|
+
}
|
|
485
|
+
function pathExists(path) {
|
|
486
|
+
try {
|
|
487
|
+
lstatSync(path);
|
|
488
|
+
return true;
|
|
489
|
+
}
|
|
490
|
+
catch (error) {
|
|
491
|
+
if (isErrno(error, "ENOENT"))
|
|
492
|
+
return false;
|
|
493
|
+
throw error;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function acquireRegistryLease(lockPath, timeoutMs) {
|
|
497
|
+
const deadline = Date.now() + timeoutMs;
|
|
498
|
+
const token = `${process.pid}:${randomBytes(8).toString("hex")}`;
|
|
499
|
+
for (;;) {
|
|
500
|
+
try {
|
|
501
|
+
mkdirSync(lockPath, { mode: 0o700 });
|
|
502
|
+
try {
|
|
503
|
+
writeFileSync(join(lockPath, "owner"), `${token}\n`, { mode: 0o600 });
|
|
504
|
+
}
|
|
505
|
+
catch (error) {
|
|
506
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
507
|
+
throw error;
|
|
508
|
+
}
|
|
509
|
+
return () => releaseRegistryLease(lockPath, token);
|
|
510
|
+
}
|
|
511
|
+
catch (error) {
|
|
512
|
+
if (!isErrno(error, "EEXIST"))
|
|
513
|
+
throw error;
|
|
514
|
+
if (registryLockIsStale(lockPath)) {
|
|
515
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
if (Date.now() >= deadline) {
|
|
519
|
+
throw new Error(`Timed out acquiring office registry lock: ${lockPath}`, { cause: error });
|
|
520
|
+
}
|
|
521
|
+
sleepSync(REGISTRY_LOCK_RETRY_MS);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
function releaseRegistryLease(lockPath, token) {
|
|
526
|
+
try {
|
|
527
|
+
if (readFileSync(join(lockPath, "owner"), "utf8").trim() === token) {
|
|
528
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
catch (error) {
|
|
532
|
+
if (!isErrno(error, "ENOENT"))
|
|
533
|
+
throw error;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
function registryLockIsStale(lockPath) {
|
|
537
|
+
let ownerKnown = false;
|
|
538
|
+
let ownerAlive = false;
|
|
539
|
+
try {
|
|
540
|
+
const owner = readFileSync(join(lockPath, "owner"), "utf8").trim();
|
|
541
|
+
const pid = Number(owner.split(":", 1)[0]);
|
|
542
|
+
if (Number.isInteger(pid) && pid > 0) {
|
|
543
|
+
ownerKnown = true;
|
|
544
|
+
try {
|
|
545
|
+
process.kill(pid, 0);
|
|
546
|
+
ownerAlive = true;
|
|
547
|
+
}
|
|
548
|
+
catch (error) {
|
|
549
|
+
if (isErrno(error, "EPERM"))
|
|
550
|
+
ownerAlive = true;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
catch {
|
|
555
|
+
// The owner file may not have been written before its process died.
|
|
556
|
+
}
|
|
557
|
+
try {
|
|
558
|
+
const oldEnough = Date.now() - statSync(lockPath).mtimeMs >= REGISTRY_LOCK_STALE_MS;
|
|
559
|
+
return ownerKnown ? !ownerAlive : oldEnough;
|
|
560
|
+
}
|
|
561
|
+
catch {
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
function sleepSync(milliseconds) {
|
|
566
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);
|
|
567
|
+
}
|
|
568
|
+
// ── raw-id lookups (cold paths: CLI, Admin enumeration) ──────────────────────
|
|
569
|
+
/**
|
|
570
|
+
* Resolve the office behind a raw conversation id for surfaces that name
|
|
571
|
+
* offices by raw id (CLI operators). The registry is the only authority:
|
|
572
|
+
* office records first, then a committed migration's owner, then the sole
|
|
573
|
+
* enabled platform. Two platforms sharing the raw id make the scope
|
|
574
|
+
* genuinely ambiguous, and an unknown id has no office to resolve — both
|
|
575
|
+
* fail loudly rather than guessing a directory.
|
|
576
|
+
*
|
|
577
|
+
* Constructs a registry per call, which re-reads the journal from disk; this
|
|
578
|
+
* is a one-shot CLI/Admin surface, never a per-message path (those go
|
|
579
|
+
* through the Workspace value's cached registry in `layout.ts`).
|
|
580
|
+
*/
|
|
581
|
+
export function resolveOwnedOfficeAddress(rawConversationId, stateDir) {
|
|
582
|
+
assertConversationId(rawConversationId);
|
|
583
|
+
const registry = new OfficeRegistry(stateDir);
|
|
584
|
+
const matches = registry
|
|
585
|
+
.getState()
|
|
586
|
+
.offices.filter((record) => record.conversationId === rawConversationId);
|
|
587
|
+
const single = matches.length === 1 ? matches[0] : undefined;
|
|
588
|
+
if (single !== undefined) {
|
|
589
|
+
return { platform: single.platform, conversationId: rawConversationId };
|
|
590
|
+
}
|
|
591
|
+
if (matches.length > 1) {
|
|
592
|
+
throw new Error(`Conversation id ${JSON.stringify(rawConversationId)} names offices on several platforms; ` +
|
|
593
|
+
"use a platform-scoped surface instead");
|
|
594
|
+
}
|
|
595
|
+
const migration = registry.getMigration(rawConversationId);
|
|
596
|
+
if (migration?.ownerPlatform) {
|
|
597
|
+
return { platform: migration.ownerPlatform, conversationId: rawConversationId };
|
|
598
|
+
}
|
|
599
|
+
const { enabledPlatforms } = registry.getState();
|
|
600
|
+
const onlyPlatform = enabledPlatforms.length === 1 ? enabledPlatforms[0] : undefined;
|
|
601
|
+
if (onlyPlatform !== undefined) {
|
|
602
|
+
return { platform: onlyPlatform, conversationId: rawConversationId };
|
|
603
|
+
}
|
|
604
|
+
throw new Error(`No office is registered for conversation id ${JSON.stringify(rawConversationId)}`);
|
|
605
|
+
}
|
|
606
|
+
/** Current office inventory, read fresh from disk for cross-process freshness. */
|
|
607
|
+
export function listRegisteredOffices(stateDir) {
|
|
608
|
+
return new OfficeRegistry(stateDir).getOffices();
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Enabled platforms whose id format could have produced this raw
|
|
612
|
+
* conversation id. Auto-claiming uses this as verification, not guessing:
|
|
613
|
+
* every format below is one mikan itself writes (GitHub ids are mikan-derived
|
|
614
|
+
* slugs; Slack/Telegram/Discord ids are the platforms' own grammars), and a
|
|
615
|
+
* directory is only claimed when exactly one enabled platform's format
|
|
616
|
+
* matches. Bare digits stay ambiguous while both Telegram and Discord are
|
|
617
|
+
* enabled (negative ids are Telegram-only); anything matching no enabled
|
|
618
|
+
* format fails closed to needs-owner.
|
|
619
|
+
*/
|
|
620
|
+
function platformsMatchingConversationIdFormat(rawConversationId, enabledPlatforms) {
|
|
621
|
+
return enabledPlatforms.filter((platform) => {
|
|
622
|
+
switch (platform) {
|
|
623
|
+
case "github":
|
|
624
|
+
return isGithubConversationId(rawConversationId);
|
|
625
|
+
case "telegram":
|
|
626
|
+
return /^-?\d+$/.test(rawConversationId);
|
|
627
|
+
case "discord":
|
|
628
|
+
return /^\d+$/.test(rawConversationId);
|
|
629
|
+
case "slack":
|
|
630
|
+
return /^[A-Z][A-Z0-9]*$/.test(rawConversationId);
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
function isGithubConversationId(rawConversationId) {
|
|
635
|
+
try {
|
|
636
|
+
parseGithubConversationId(rawConversationId);
|
|
637
|
+
return true;
|
|
638
|
+
}
|
|
639
|
+
catch {
|
|
640
|
+
return false;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
function isErrno(error, code) {
|
|
644
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
645
|
+
}
|
|
646
|
+
//# sourceMappingURL=registry.js.map
|