@geminixiang/mikan 1.0.0-beta.45 → 1.0.0-beta.47
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 +47 -0
- package/README.md +12 -19
- package/dist/adapter.d.ts +1 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +6 -1
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +168 -144
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/discord/context.d.ts +2 -8
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +1 -1
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/discord/format.d.ts.map +1 -1
- package/dist/adapters/discord/format.js +2 -4
- package/dist/adapters/discord/format.js.map +1 -1
- package/dist/adapters/github/bot.d.ts +6 -1
- package/dist/adapters/github/bot.d.ts.map +1 -1
- package/dist/adapters/github/bot.js +57 -25
- package/dist/adapters/github/bot.js.map +1 -1
- package/dist/adapters/github/context.d.ts +2 -9
- package/dist/adapters/github/context.d.ts.map +1 -1
- package/dist/adapters/github/context.js.map +1 -1
- package/dist/adapters/github/github-ops.d.ts +4 -17
- package/dist/adapters/github/github-ops.d.ts.map +1 -1
- package/dist/adapters/github/github-ops.js +17 -86
- package/dist/adapters/github/github-ops.js.map +1 -1
- package/dist/adapters/github/tool-pack.d.ts.map +1 -1
- package/dist/adapters/github/tool-pack.js +0 -1
- package/dist/adapters/github/tool-pack.js.map +1 -1
- package/dist/adapters/github/tools/checks.d.ts +0 -1
- package/dist/adapters/github/tools/checks.d.ts.map +1 -1
- package/dist/adapters/github/tools/checks.js +3 -22
- package/dist/adapters/github/tools/checks.js.map +1 -1
- package/dist/adapters/github/types.d.ts +0 -33
- package/dist/adapters/github/types.d.ts.map +1 -1
- package/dist/adapters/github/types.js.map +1 -1
- package/dist/adapters/progressive-renderer.d.ts.map +1 -1
- package/dist/adapters/progressive-renderer.js +311 -318
- package/dist/adapters/progressive-renderer.js.map +1 -1
- package/dist/adapters/shared.d.ts +12 -1
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/shared.js +44 -1
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/slack/blocks.d.ts.map +1 -1
- package/dist/adapters/slack/blocks.js +1 -4
- package/dist/adapters/slack/blocks.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +15 -0
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +233 -206
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/context.d.ts +2 -8
- package/dist/adapters/slack/context.d.ts.map +1 -1
- package/dist/adapters/slack/context.js +1 -1
- 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 +135 -123
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/slack/stream-limits.d.ts +1 -1
- package/dist/adapters/slack/stream-limits.js +1 -1
- package/dist/adapters/slack/stream-limits.js.map +1 -1
- package/dist/adapters/slack/types.d.ts +4 -0
- 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 +3 -0
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +23 -7
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/adapters/telegram/context.d.ts +2 -8
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +1 -2
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/adapters/types.d.ts +11 -5
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js.map +1 -1
- package/dist/agent/catalog.d.ts +6 -18
- package/dist/agent/catalog.d.ts.map +1 -1
- package/dist/agent/catalog.js +24 -156
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/execution.d.ts +0 -7
- package/dist/agent/execution.d.ts.map +1 -1
- package/dist/agent/execution.js +23 -21
- package/dist/agent/execution.js.map +1 -1
- package/dist/agent/presenter.d.ts +7 -9
- package/dist/agent/presenter.d.ts.map +1 -1
- package/dist/agent/presenter.js +355 -357
- package/dist/agent/presenter.js.map +1 -1
- package/dist/agent/prompt.d.ts +5 -12
- package/dist/agent/prompt.d.ts.map +1 -1
- package/dist/agent/prompt.js +56 -81
- package/dist/agent/prompt.js.map +1 -1
- package/dist/agent/runner.d.ts +0 -7
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +335 -318
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/types.d.ts +21 -17
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js +0 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/cli/boot.d.ts.map +1 -1
- package/dist/cli/boot.js +7 -10
- package/dist/cli/boot.js.map +1 -1
- package/dist/cli/onboard.d.ts +10 -0
- package/dist/cli/onboard.d.ts.map +1 -0
- package/dist/cli/onboard.js +237 -0
- package/dist/cli/onboard.js.map +1 -0
- package/dist/cli/types.d.ts +8 -3
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/types.js.map +1 -1
- package/dist/commands/auto-reply.d.ts.map +1 -1
- package/dist/commands/auto-reply.js +5 -12
- package/dist/commands/auto-reply.js.map +1 -1
- package/dist/commands/manifest.d.ts.map +1 -1
- package/dist/commands/manifest.js +9 -16
- package/dist/commands/manifest.js.map +1 -1
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +15 -10
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +0 -2
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +89 -70
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/commands/session-view.js +9 -2
- package/dist/commands/session-view.js.map +1 -1
- package/dist/commands/types.d.ts +4 -3
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js.map +1 -1
- package/dist/config.d.ts +13 -17
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +39 -37
- package/dist/config.js.map +1 -1
- package/dist/dream/index.d.ts +20 -0
- package/dist/dream/index.d.ts.map +1 -0
- package/dist/dream/index.js +253 -0
- package/dist/dream/index.js.map +1 -0
- package/dist/dream/types.d.ts +30 -0
- package/dist/dream/types.d.ts.map +1 -0
- package/dist/dream/types.js.map +1 -0
- package/dist/env-manifest.d.ts.map +1 -1
- package/dist/env-manifest.js +12 -27
- package/dist/env-manifest.js.map +1 -1
- package/dist/execution-resolver.d.ts +9 -2
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +26 -27
- package/dist/execution-resolver.js.map +1 -1
- package/dist/harness/event-format.d.ts +1 -2
- package/dist/harness/event-format.d.ts.map +1 -1
- package/dist/harness/event-format.js +9 -15
- package/dist/harness/event-format.js.map +1 -1
- package/dist/harness/index.d.ts +1 -7
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +0 -4
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/models.d.ts.map +1 -1
- package/dist/harness/models.js +15 -35
- package/dist/harness/models.js.map +1 -1
- package/dist/harness/runner.d.ts +7 -16
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +13 -131
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session-store.d.ts +1 -1
- package/dist/harness/session-store.d.ts.map +1 -1
- package/dist/harness/session-store.js +1 -1
- package/dist/harness/session-store.js.map +1 -1
- package/dist/harness/subagent-runner.d.ts +2 -2
- package/dist/harness/subagent-runner.d.ts.map +1 -1
- package/dist/harness/subagent-runner.js +157 -162
- package/dist/harness/subagent-runner.js.map +1 -1
- package/dist/harness/types.d.ts +1 -13
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/index.d.ts +3 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -5
- package/dist/index.js.map +1 -1
- package/dist/main.js +103 -222
- package/dist/main.js.map +1 -1
- package/dist/mcp/catalog.d.ts +5 -0
- package/dist/mcp/catalog.d.ts.map +1 -0
- package/dist/mcp/catalog.js +156 -0
- package/dist/mcp/catalog.js.map +1 -0
- package/dist/mcp/loader.d.ts +3 -2
- package/dist/mcp/loader.d.ts.map +1 -1
- package/dist/mcp/loader.js +54 -23
- package/dist/mcp/loader.js.map +1 -1
- package/dist/mcp/open-connector.d.ts +14 -0
- package/dist/mcp/open-connector.d.ts.map +1 -0
- package/dist/mcp/open-connector.js +203 -0
- package/dist/mcp/open-connector.js.map +1 -0
- package/dist/mcp/types.d.ts +28 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/office/index.d.ts +136 -8
- package/dist/office/index.d.ts.map +1 -1
- package/dist/office/index.js +1050 -9
- package/dist/office/index.js.map +1 -1
- package/dist/office/types.d.ts +19 -1
- package/dist/office/types.d.ts.map +1 -1
- package/dist/office/types.js.map +1 -1
- package/dist/packages/index.d.ts +168 -5
- package/dist/packages/index.d.ts.map +1 -1
- package/dist/packages/index.js +720 -5
- package/dist/packages/index.js.map +1 -1
- package/dist/packages/types.d.ts +1 -5
- package/dist/packages/types.d.ts.map +1 -1
- package/dist/packages/types.js.map +1 -1
- package/dist/process-lifecycle.d.ts +19 -0
- package/dist/process-lifecycle.d.ts.map +1 -0
- package/dist/process-lifecycle.js +60 -0
- package/dist/process-lifecycle.js.map +1 -0
- package/dist/provisioner.d.ts +2 -9
- package/dist/provisioner.d.ts.map +1 -1
- package/dist/provisioner.js +3 -12
- package/dist/provisioner.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +124 -380
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/session-lifecycle.d.ts +34 -18
- package/dist/runtime/session-lifecycle.d.ts.map +1 -1
- package/dist/runtime/session-lifecycle.js +179 -46
- package/dist/runtime/session-lifecycle.js.map +1 -1
- package/dist/runtime/types.d.ts +8 -26
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +2 -3
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts +0 -1
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +2 -3
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +4 -2
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/identity.d.ts +10 -19
- package/dist/sandbox/identity.d.ts.map +1 -1
- package/dist/sandbox/identity.js +8 -8
- package/dist/sandbox/identity.js.map +1 -1
- package/dist/sandbox/index.d.ts +7 -10
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +45 -16
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +13 -45
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +5 -0
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +10 -0
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts +1 -3
- package/dist/sessions/chat-history-sync.d.ts.map +1 -1
- package/dist/sessions/chat-history-sync.js +58 -11
- package/dist/sessions/chat-history-sync.js.map +1 -1
- package/dist/sessions/migrate-v3.d.ts +2 -5
- package/dist/sessions/migrate-v3.d.ts.map +1 -1
- package/dist/sessions/migrate-v3.js +17 -1
- package/dist/sessions/migrate-v3.js.map +1 -1
- package/dist/sessions/store.d.ts +5 -6
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +62 -2
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +9 -0
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +2 -10
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/read.js +2 -2
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/sandbox.d.ts.map +1 -1
- package/dist/tools/sandbox.js +2 -3
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/tools/subagent.d.ts +1 -1
- package/dist/tools/subagent.js.map +1 -1
- package/dist/types.d.ts +54 -130
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/index.d.ts +9 -2
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +29 -5
- package/dist/vault/index.js.map +1 -1
- package/dist/web/admin/portal.d.ts +12 -1
- package/dist/web/admin/portal.d.ts.map +1 -1
- package/dist/web/admin/portal.js +437 -422
- package/dist/web/admin/portal.js.map +1 -1
- package/dist/web/admin/types.d.ts +2 -2
- package/dist/web/admin/types.d.ts.map +1 -1
- package/dist/web/admin/types.js.map +1 -1
- package/dist/web/login/portal.d.ts +7 -1
- package/dist/web/login/portal.d.ts.map +1 -1
- package/dist/web/login/portal.js +143 -78
- package/dist/web/login/portal.js.map +1 -1
- package/dist/web/portal-shell.d.ts +1 -0
- package/dist/web/portal-shell.d.ts.map +1 -1
- package/dist/web/portal-shell.js +12 -1
- package/dist/web/portal-shell.js.map +1 -1
- package/dist/web/server.d.ts +3 -3
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js.map +1 -1
- package/dist/web/session-view/portal.d.ts +8 -1
- package/dist/web/session-view/portal.d.ts.map +1 -1
- package/dist/web/session-view/portal.js +609 -132
- package/dist/web/session-view/portal.js.map +1 -1
- package/dist/web/session-view/types.d.ts +8 -0
- package/dist/web/session-view/types.d.ts.map +1 -1
- package/dist/web/session-view/types.js.map +1 -1
- package/dist/workspace-projection/index.d.ts +14 -2
- package/dist/workspace-projection/index.d.ts.map +1 -1
- package/dist/workspace-projection/index.js +102 -14
- package/dist/workspace-projection/index.js.map +1 -1
- package/dist/workspace-projection/types.d.ts +14 -1
- package/dist/workspace-projection/types.d.ts.map +1 -1
- package/dist/workspace-projection/types.js.map +1 -1
- package/package.json +3 -5
- package/dist/adapters/github/cloudbuild.d.ts +0 -19
- package/dist/adapters/github/cloudbuild.d.ts.map +0 -1
- package/dist/adapters/github/cloudbuild.js +0 -71
- package/dist/adapters/github/cloudbuild.js.map +0 -1
- package/dist/adapters/github/gcp-auth.d.ts +0 -28
- package/dist/adapters/github/gcp-auth.d.ts.map +0 -1
- package/dist/adapters/github/gcp-auth.js +0 -196
- package/dist/adapters/github/gcp-auth.js.map +0 -1
- package/dist/agent/index.d.ts +0 -9
- package/dist/agent/index.d.ts.map +0 -1
- package/dist/agent/index.js +0 -8
- package/dist/agent/index.js.map +0 -1
- package/dist/cli/ext-dev.d.ts +0 -2
- package/dist/cli/ext-dev.d.ts.map +0 -1
- package/dist/cli/ext-dev.js +0 -188
- package/dist/cli/ext-dev.js.map +0 -1
- package/dist/cli/ext.d.ts +0 -2
- package/dist/cli/ext.d.ts.map +0 -1
- package/dist/cli/ext.js +0 -324
- package/dist/cli/ext.js.map +0 -1
- package/dist/commands/extensions.d.ts +0 -26
- package/dist/commands/extensions.d.ts.map +0 -1
- package/dist/commands/extensions.js +0 -103
- package/dist/commands/extensions.js.map +0 -1
- package/dist/extension-schedules.d.ts +0 -31
- package/dist/extension-schedules.d.ts.map +0 -1
- package/dist/extension-schedules.js +0 -229
- package/dist/extension-schedules.js.map +0 -1
- package/dist/harness/auth.d.ts +0 -17
- package/dist/harness/auth.d.ts.map +0 -1
- package/dist/harness/auth.js +0 -92
- package/dist/harness/auth.js.map +0 -1
- package/dist/harness/extensions/loader.d.ts +0 -40
- package/dist/harness/extensions/loader.d.ts.map +0 -1
- package/dist/harness/extensions/loader.js +0 -723
- package/dist/harness/extensions/loader.js.map +0 -1
- package/dist/harness/extensions/registry.d.ts +0 -155
- package/dist/harness/extensions/registry.d.ts.map +0 -1
- package/dist/harness/extensions/registry.js +0 -420
- package/dist/harness/extensions/registry.js.map +0 -1
- package/dist/harness/extensions/types.d.ts +0 -665
- package/dist/harness/extensions/types.d.ts.map +0 -1
- package/dist/harness/extensions/types.js.map +0 -1
- package/dist/office/address.d.ts +0 -31
- package/dist/office/address.d.ts.map +0 -1
- package/dist/office/address.js +0 -113
- package/dist/office/address.js.map +0 -1
- package/dist/office/layout.d.ts +0 -27
- package/dist/office/layout.d.ts.map +0 -1
- package/dist/office/layout.js +0 -97
- package/dist/office/layout.js.map +0 -1
- package/dist/office/migration.d.ts +0 -44
- package/dist/office/migration.d.ts.map +0 -1
- package/dist/office/migration.js +0 -255
- package/dist/office/migration.js.map +0 -1
- package/dist/office/registry.d.ts +0 -75
- package/dist/office/registry.d.ts.map +0 -1
- package/dist/office/registry.js +0 -646
- package/dist/office/registry.js.map +0 -1
- package/dist/packages/admin.d.ts +0 -17
- package/dist/packages/admin.d.ts.map +0 -1
- package/dist/packages/admin.js +0 -98
- package/dist/packages/admin.js.map +0 -1
- package/dist/packages/inspect.d.ts +0 -11
- package/dist/packages/inspect.d.ts.map +0 -1
- package/dist/packages/inspect.js +0 -98
- package/dist/packages/inspect.js.map +0 -1
- package/dist/packages/materialize.d.ts +0 -40
- package/dist/packages/materialize.d.ts.map +0 -1
- package/dist/packages/materialize.js +0 -297
- package/dist/packages/materialize.js.map +0 -1
- package/dist/packages/resolve.d.ts +0 -25
- package/dist/packages/resolve.d.ts.map +0 -1
- package/dist/packages/resolve.js +0 -208
- package/dist/packages/resolve.js.map +0 -1
- package/dist/packages/source.d.ts +0 -39
- package/dist/packages/source.d.ts.map +0 -1
- package/dist/packages/source.js +0 -189
- package/dist/packages/source.js.map +0 -1
- package/dist/sandbox/errors.d.ts +0 -6
- package/dist/sandbox/errors.d.ts.map +0 -1
- package/dist/sandbox/errors.js +0 -11
- package/dist/sandbox/errors.js.map +0 -1
- package/dist/sandbox/firecracker.d.ts +0 -18
- package/dist/sandbox/firecracker.d.ts.map +0 -1
- package/dist/sandbox/firecracker.js +0 -223
- package/dist/sandbox/firecracker.js.map +0 -1
- package/dist/sandbox/gondolin.d.ts +0 -57
- package/dist/sandbox/gondolin.d.ts.map +0 -1
- package/dist/sandbox/gondolin.js +0 -764
- package/dist/sandbox/gondolin.js.map +0 -1
- package/dist/sandbox/image.d.ts +0 -3
- package/dist/sandbox/image.d.ts.map +0 -1
- package/dist/sandbox/image.js +0 -29
- package/dist/sandbox/image.js.map +0 -1
- package/dist/sessions/conversation-log.d.ts +0 -9
- package/dist/sessions/conversation-log.d.ts.map +0 -1
- package/dist/sessions/conversation-log.js +0 -50
- package/dist/sessions/conversation-log.js.map +0 -1
- package/dist/sessions/rotation.d.ts +0 -2
- package/dist/sessions/rotation.d.ts.map +0 -1
- package/dist/sessions/rotation.js +0 -41
- package/dist/sessions/rotation.js.map +0 -1
- package/dist/vault/disabled.d.ts +0 -9
- package/dist/vault/disabled.d.ts.map +0 -1
- package/dist/vault/disabled.js +0 -25
- package/dist/vault/disabled.js.map +0 -1
- package/dist/web/admin/store.d.ts +0 -13
- package/dist/web/admin/store.d.ts.map +0 -1
- package/dist/web/admin/store.js +0 -14
- package/dist/web/admin/store.js.map +0 -1
- package/dist/web/login/store.d.ts +0 -8
- package/dist/web/login/store.d.ts.map +0 -1
- package/dist/web/login/store.js +0 -15
- package/dist/web/login/store.js.map +0 -1
- package/dist/web/session-view/service.d.ts +0 -6
- package/dist/web/session-view/service.d.ts.map +0 -1
- package/dist/web/session-view/service.js +0 -517
- package/dist/web/session-view/service.js.map +0 -1
- package/dist/web/session-view/store.d.ts +0 -8
- package/dist/web/session-view/store.d.ts.map +0 -1
- package/dist/web/session-view/store.js +0 -15
- package/dist/web/session-view/store.js.map +0 -1
- /package/dist/{harness/extensions → dream}/types.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-v3.js","sourceRoot":"","sources":["../../src/sessions/migrate-v3.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One-time migration of legacy v3 session files to pi's v4 JSONL format.\n *\n * v3 is the entry family mikan wrote up to pi 0.83: a `{\"type\":\"session\"}`\n * header followed by tree entries with string ISO timestamps and compaction\n * entries that point at `firstKeptEntryId`. v4 (pi 0.84+) uses a\n * `{\"kind\":\"header\",\"version\":4}` header followed by mutation lines whose\n * entries carry numeric timestamps and a consecutive `seq`, with compaction\n * retention stored inline as `retainedTail`.\n *\n * The migration preserves entry ids, parent links, and timestamps, converts\n * `custom_message` entries into v4 `custom`-role messages, folds\n * `session_info` into the v4 name fact, `label` entries into label facts,\n * and rewrites each compaction's kept range into its inline `retainedTail`.\n * Every migrated file is verified before it replaces the original: the v4\n * file is re-opened with pi's reader and its built context must equal the\n * v3 context computed by the reference converter below. The original file\n * is kept beside the migrated one as `<name>.v3.bak`.\n */\nimport { existsSync, readdirSync, readFileSync, renameSync, rmSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n buildSessionContext,\n createCustomMessage,\n type AgentMessage,\n type Entry as PiEntry,\n type JsonlV4Header,\n} from \"@earendil-works/pi-agent-core\";\nimport { SessionStore } from \"../harness/session-store.js\";\nimport { atomicWritePrivateFile } from \"../utils/file-guards.js\";\n\n// ── v3 shapes ────────────────────────────────────────────────────────────────\n\ninterface V3EntryBase {\n type: string;\n id: string;\n parentId: string | null;\n timestamp: string;\n}\n\ntype V3Entry = V3EntryBase &\n (\n | { type: \"message\"; message: AgentMessage }\n | { type: \"thinking_level_change\"; thinkingLevel: string }\n | { type: \"model_change\"; provider: string; modelId: string }\n | { type: \"active_tools_change\"; activeToolNames: string[] }\n | {\n type: \"compaction\";\n summary: string;\n firstKeptEntryId?: string;\n tokensBefore: number;\n retainedTail?: AgentMessage[];\n details?: unknown;\n usage?: unknown;\n }\n | {\n type: \"branch_summary\";\n fromId: string;\n summary: string;\n details?: unknown;\n usage?: unknown;\n }\n | { type: \"custom\"; customType: string; data?: unknown }\n | {\n type: \"custom_message\";\n customType: string;\n content: Parameters<typeof createCustomMessage>[1];\n display: boolean;\n details?: unknown;\n }\n | { type: \"label\"; targetId: string; label: string | undefined }\n | { type: \"session_info\"; name?: string }\n | { type: \"leaf\"; targetId: string | null }\n );\n\ninterface V3SessionHeader {\n type: \"session\";\n version?: number;\n id: string;\n timestamp: string;\n cwd: string;\n parentSession?: string;\n parentSessionId?: string;\n [extra: string]: unknown;\n}\n\ninterface V3SessionFile {\n header: V3SessionHeader;\n entries: V3Entry[];\n}\n\n/** Whether a file's first non-empty line is a v3 session header. */\nexport function isV3SessionFile(filePath: string): boolean {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const firstLine = content.split(\"\\n\").find((line) => line.trim().length > 0);\n if (!firstLine) return false;\n const parsed = JSON.parse(firstLine) as { type?: unknown };\n return parsed.type === \"session\";\n } catch {\n return false;\n }\n}\n\n/** Read a v3 session file, ignoring a torn final line (crash tail). */\nfunction readV3SessionFile(filePath: string): V3SessionFile {\n const lines = readFileSync(filePath, \"utf-8\")\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n const records: Record<string, unknown>[] = [];\n for (const [index, line] of lines.entries()) {\n try {\n records.push(JSON.parse(line) as Record<string, unknown>);\n } catch (error) {\n if (index === lines.length - 1 && index > 0) continue;\n throw new Error(`Invalid JSON on line ${index + 1} of ${filePath}`, { cause: error });\n }\n }\n const header = records[0];\n if (!header || header.type !== \"session\" || typeof header.id !== \"string\") {\n throw new Error(`Not a v3 session file: ${filePath}`);\n }\n // Crash-era v3 files can contain duplicated lines (a retried append wrote\n // the header+entry pair twice). The v3 runtime read entries into a Map, so\n // duplicates were silently collapsed; v4 rejects duplicate mutation ids.\n // Reproduce the v3 semantics: keep one entry per id, drop stray repeated\n // session headers.\n const seen = new Set<string>();\n const entries: V3Entry[] = [];\n for (const record of records.slice(1)) {\n if (typeof record.type !== \"string\" || typeof record.id !== \"string\") continue;\n if (record.type === \"session\") continue;\n if (seen.has(record.id)) continue;\n seen.add(record.id);\n entries.push(record as unknown as V3Entry);\n }\n return { header: header as unknown as V3SessionHeader, entries };\n}\n\nfunction toEpochMillis(timestamp: string): number {\n const parsed = Date.parse(timestamp);\n return Number.isNaN(parsed) ? 0 : parsed;\n}\n\n/** Walk a v3 tree from an entry to the root; returns root-first path order. */\nfunction v3Branch(entries: V3Entry[], fromId: string | null): V3Entry[] {\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const path: V3Entry[] = [];\n let currentId = fromId;\n while (currentId) {\n const entry = byId.get(currentId);\n if (!entry) break;\n path.push(entry);\n currentId = entry.parentId;\n }\n return path.toReversed();\n}\n\nfunction v3LeafId(entries: V3Entry[]): string | null {\n let leafId: string | null = null;\n for (const entry of entries) {\n leafId = entry.type === \"leaf\" ? entry.targetId : entry.id;\n }\n return leafId;\n}\n\n/** Convert one tree-shaping v3 entry to its v4 counterpart (facts excluded). */\nfunction convertEntry(entry: V3Entry, entries: V3Entry[]): PiEntry | null {\n const base = {\n id: entry.id,\n seq: 0, // assigned at mutation-encoding time\n parentId: resolveV4Parent(entry, entries),\n timestamp: toEpochMillis(entry.timestamp),\n };\n switch (entry.type) {\n case \"message\":\n return { ...base, type: \"message\", message: entry.message };\n case \"custom_message\":\n return {\n ...base,\n type: \"message\",\n message: createCustomMessage(\n entry.customType,\n entry.content,\n entry.display,\n entry.details,\n toEpochMillis(entry.timestamp),\n ),\n };\n case \"thinking_level_change\":\n return { ...base, type: \"thinking_level_change\", thinkingLevel: entry.thinkingLevel };\n case \"model_change\":\n return { ...base, type: \"model_change\", provider: entry.provider, modelId: entry.modelId };\n case \"active_tools_change\":\n return { ...base, type: \"active_tools_change\", activeToolNames: entry.activeToolNames };\n case \"compaction\":\n return {\n ...base,\n type: \"compaction\",\n summary: entry.summary,\n retainedTail: entry.retainedTail ?? compactionKeptMessages(entry, entries),\n tokensBefore: entry.tokensBefore,\n ...(entry.details !== undefined ? { details: entry.details } : {}),\n ...(entry.usage !== undefined ? { usage: entry.usage as PiEntry & object } : {}),\n } as unknown as PiEntry;\n case \"branch_summary\":\n return {\n ...base,\n type: \"branch_summary\",\n fromId: entry.fromId,\n summary: entry.summary,\n ...(entry.details !== undefined ? { details: entry.details } : {}),\n ...(entry.usage !== undefined ? { usage: entry.usage } : {}),\n } as unknown as PiEntry;\n case \"custom\":\n return { ...base, type: \"custom\", customType: entry.customType, data: entry.data };\n default:\n // session_info / label / leaf become facts and the lane pointer.\n return null;\n }\n}\n\n/**\n * Skip fact-only ancestors (session_info/label/leaf) when re-linking the v4\n * tree: those entries disappear from the entry stream, so children re-attach\n * to the nearest surviving ancestor.\n */\nfunction resolveV4Parent(entry: V3Entry, entries: V3Entry[]): string | null {\n const byId = new Map(entries.map((item) => [item.id, item]));\n let parentId = entry.parentId;\n while (parentId !== null) {\n const parent = byId.get(parentId);\n if (!parent) return null;\n if (parent.type !== \"session_info\" && parent.type !== \"label\" && parent.type !== \"leaf\") {\n return parentId;\n }\n parentId = parent.parentId;\n }\n return null;\n}\n\n/**\n * Messages of the v3 kept range (`firstKeptEntryId` .. compaction parent),\n * which v4 stores inline on the compaction entry.\n */\nfunction compactionKeptMessages(\n compaction: Extract<V3Entry, { type: \"compaction\" }>,\n entries: V3Entry[],\n): AgentMessage[] {\n if (!compaction.firstKeptEntryId) return [];\n const ancestors = v3Branch(entries, compaction.parentId);\n const keptStart = ancestors.findIndex((entry) => entry.id === compaction.firstKeptEntryId);\n if (keptStart === -1) return [];\n const messages: AgentMessage[] = [];\n for (const entry of ancestors.slice(keptStart)) {\n if (entry.type === \"message\") messages.push(entry.message);\n else if (entry.type === \"custom_message\") {\n messages.push(\n createCustomMessage(\n entry.customType,\n entry.content,\n entry.display,\n entry.details,\n toEpochMillis(entry.timestamp),\n ),\n );\n }\n }\n return messages;\n}\n\n// ── reference converter (verification oracle) ───────────────────────────────\n\n/**\n * Convert a v3 branch to v4 entries with the pi-0.83 context semantics:\n * the last compaction is repositioned ahead of its kept range so pi's v4\n * transform reproduces the v3 context exactly. This mirrors what the\n * runtime shim did before mikan moved to native v4 files, and serves as\n * the verification oracle for migrated output.\n */\nfunction referenceContextEntries(branch: V3Entry[]): PiEntry[] {\n let lastCompactionIndex = -1;\n for (let i = branch.length - 1; i >= 0; i--) {\n if (branch[i]?.type === \"compaction\") {\n lastCompactionIndex = i;\n break;\n }\n }\n const lastCompaction = branch[lastCompactionIndex] as\n | Extract<V3Entry, { type: \"compaction\" }>\n | undefined;\n const firstKeptId =\n lastCompaction && !lastCompaction.retainedTail ? lastCompaction.firstKeptEntryId : undefined;\n const firstKeptIndex =\n firstKeptId === undefined ? -1 : branch.findIndex((entry) => entry.id === firstKeptId);\n\n const ordered: V3Entry[] = [];\n if (firstKeptIndex !== -1 && lastCompaction) {\n ordered.push(...branch.slice(0, firstKeptIndex));\n ordered.push(lastCompaction);\n for (const [index, entry] of branch.entries()) {\n if (index >= firstKeptIndex && index !== lastCompactionIndex) ordered.push(entry);\n }\n } else {\n ordered.push(...branch);\n }\n\n const converted: PiEntry[] = [];\n for (const entry of ordered) {\n if (entry.type === \"compaction\" && entry === lastCompaction && firstKeptIndex !== -1) {\n converted.push({\n type: \"compaction\",\n id: entry.id,\n seq: 0,\n parentId: null,\n timestamp: toEpochMillis(entry.timestamp),\n summary: entry.summary,\n retainedTail: [],\n tokensBefore: entry.tokensBefore,\n });\n continue;\n }\n const piEntry = convertEntry(entry, []);\n if (piEntry) converted.push(piEntry);\n }\n let previousId: string | null = null;\n for (const [index, entry] of converted.entries()) {\n entry.seq = index;\n entry.parentId = previousId;\n previousId = entry.id;\n }\n return converted;\n}\n\n// ── v4 encoding ─────────────────────────────────────────────────────────────\n\nfunction buildV4Header(header: V3SessionHeader): JsonlV4Header {\n const {\n type: _type,\n version: _version,\n id,\n timestamp,\n cwd,\n parentSession,\n parentSessionId,\n ...extras\n } = header;\n const metadata: Record<string, unknown> = { ...extras };\n if (parentSession !== undefined) metadata.parentSessionPath = parentSession;\n return {\n kind: \"header\",\n version: 4,\n id,\n createdAt: toEpochMillis(timestamp),\n cwd,\n ...(parentSessionId !== undefined ? { parentSessionId } : {}),\n ...(Object.keys(metadata).length > 0\n ? { metadata: metadata as JsonlV4Header[\"metadata\"] }\n : {}),\n };\n}\n\nfunction encodeV4File(file: V3SessionFile): string {\n const lines: string[] = [JSON.stringify(buildV4Header(file.header))];\n let seq = 0;\n const push = (mutation: Record<string, unknown>) => {\n lines.push(JSON.stringify(mutation));\n };\n\n let name: string | undefined;\n const labels: Array<{ targetId: string; label: string | undefined }> = [];\n for (const entry of file.entries) {\n if (entry.type === \"session_info\") {\n name = entry.name?.trim() || undefined;\n continue;\n }\n if (entry.type === \"label\") {\n labels.push({ targetId: entry.targetId, label: entry.label });\n continue;\n }\n if (entry.type === \"leaf\") continue;\n const converted = convertEntry(entry, file.entries);\n if (!converted) continue;\n converted.seq = ++seq;\n // Entry mutations are encoded flat: {kind:\"entry\", ...entry fields}.\n push({ kind: \"entry\", ...converted });\n }\n\n const leafId = v3LeafId(file.entries);\n push({ kind: \"lane\", seq: ++seq, lane: \"main\", leafId });\n if (name !== undefined) push({ kind: \"fact\", seq: ++seq, fact: \"name\", name });\n for (const { targetId, label } of labels) {\n push({ kind: \"fact\", seq: ++seq, fact: \"label\", targetId, label });\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\n// ── migration driver ────────────────────────────────────────────────────────\n\nexport interface MigrateResult {\n file: string;\n status: \"migrated\" | \"already-v4\" | \"skipped\";\n detail?: string;\n}\n\nasync function verifyMigratedFile(v4Path: string, source: V3SessionFile): Promise<void> {\n const store = await SessionStore.inspect(v4Path);\n const migratedContext = await store.buildSessionContext();\n const branch = v3Branch(source.entries, v3LeafId(source.entries));\n const referenceContext = buildSessionContext(referenceContextEntries(branch));\n const migrated = JSON.stringify(migratedContext.messages);\n const reference = JSON.stringify(referenceContext.messages);\n if (migrated !== reference) {\n throw new Error(\"migrated context does not match the v3 reference context\");\n }\n const migratedName = await store.getSessionName();\n const v3Name = [...source.entries]\n .toReversed()\n .find((entry) => entry.type === \"session_info\")\n ?.name?.trim();\n if ((migratedName ?? \"\") !== (v3Name || \"\")) {\n throw new Error(\"migrated session name does not match the v3 session name\");\n }\n}\n\n/**\n * Migrate one session file in place. The migrated file is verified against\n * the v3 reference semantics before it replaces the original; the original\n * is preserved as `<file>.v3.bak`.\n */\nexport async function migrateSessionFile(\n filePath: string,\n options?: { dryRun?: boolean },\n): Promise<MigrateResult> {\n if (!isV3SessionFile(filePath)) return { file: filePath, status: \"already-v4\" };\n const source = readV3SessionFile(filePath);\n if (options?.dryRun) return { file: filePath, status: \"migrated\", detail: \"dry run\" };\n\n const tempPath = `${filePath}.v4.tmp`;\n atomicWritePrivateFile(tempPath, encodeV4File(source));\n try {\n await verifyMigratedFile(tempPath, source);\n } catch (error) {\n rmSync(tempPath, { force: true });\n throw new Error(`Verification failed for ${filePath}`, { cause: error });\n }\n renameSync(filePath, `${filePath}.v3.bak`);\n renameSync(tempPath, filePath);\n return { file: filePath, status: \"migrated\" };\n}\n\n/** Recursively find candidate session files (.jsonl with a v3 header). */\nexport function findV3SessionFiles(root: string): string[] {\n if (!existsSync(root)) return [];\n const found: string[] = [];\n const walk = (dir: string) => {\n for (const name of readdirSync(dir)) {\n const path = join(dir, name);\n let stats;\n try {\n stats = statSync(path);\n } catch {\n continue;\n }\n if (stats.isDirectory()) {\n walk(path);\n } else if (name.endsWith(\".jsonl\") && isV3SessionFile(path)) {\n found.push(path);\n }\n }\n };\n walk(root);\n return found;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"migrate-v3.js","sourceRoot":"","sources":["../../src/sessions/migrate-v3.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9F,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GAIpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAgEjE,oEAAoE;AACpE,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAuB,CAAC;QAC3D,OAAO,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,uEAAuE;AACvE,SAAS,iBAAiB,CAAC,QAAgB;IACzC,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC;SAC1C,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,OAAO,GAA8B,EAAE,CAAC;IAC9C,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC;gBAAE,SAAS;YACtD,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,GAAG,CAAC,OAAO,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,yEAAyE;IACzE,mBAAmB;IACnB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ;YAAE,SAAS;QAC/E,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QACxC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAAE,SAAS;QAClC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,MAA4B,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,MAAoC,EAAE,OAAO,EAAE,CAAC;AACnE,CAAC;AAED,SAAS,aAAa,CAAC,SAAiB;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3C,CAAC;AAED,+EAA+E;AAC/E,SAAS,QAAQ,CAAC,OAAkB,EAAE,MAAqB;IACzD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,IAAI,GAAc,EAAE,CAAC;IAC3B,IAAI,SAAS,GAAG,MAAM,CAAC;IACvB,OAAO,SAAS,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,MAAM;QAClB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,QAAQ,CAAC,OAAkB;IAClC,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,GAAG,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;IAC7D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gFAAgF;AAChF,SAAS,YAAY,CAAC,KAAc,EAAE,OAAkB;IACtD,MAAM,IAAI,GAAG;QACX,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,GAAG,EAAE,CAAC,EAAE,qCAAqC;QAC7C,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC;QACzC,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC;KAC1C,CAAC;IACF,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,SAAS;YACZ,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAC9D,KAAK,gBAAgB;YACnB,OAAO;gBACL,GAAG,IAAI;gBACP,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,mBAAmB,CAC1B,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAC/B;aACF,CAAC;QACJ,KAAK,uBAAuB;YAC1B,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,uBAAuB,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC;QACxF,KAAK,cAAc;YACjB,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAC7F,KAAK,qBAAqB;YACxB,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,qBAAqB,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,CAAC;QAC1F,KAAK,YAAY;YACf,OAAO;gBACL,GAAG,IAAI;gBACP,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,sBAAsB,CAAC,KAAK,EAAE,OAAO,CAAC;gBAC1E,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClE,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAyB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3D,CAAC;QAC1B,KAAK,gBAAgB;YACnB,OAAO;gBACL,GAAG,IAAI;gBACP,IAAI,EAAE,gBAAgB;gBACtB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClE,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACvC,CAAC;QAC1B,KAAK,QAAQ;YACX,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;QACrF;YACE,iEAAiE;YACjE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,KAAc,EAAE,OAAkB;IACzD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7D,IAAI,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC9B,OAAO,QAAQ,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxF,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,sBAAsB,CAC7B,UAAoD,EACpD,OAAkB;IAElB,IAAI,CAAC,UAAU,CAAC,gBAAgB;QAAE,OAAO,EAAE,CAAC;IAC5C,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAC3F,IAAI,SAAS,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;aACtD,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YACzC,QAAQ,CAAC,IAAI,CACX,mBAAmB,CACjB,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAC/B,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,+EAA+E;AAE/E;;;;;;GAMG;AACH,SAAS,uBAAuB,CAAC,MAAiB;IAChD,IAAI,mBAAmB,GAAG,CAAC,CAAC,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;YACrC,mBAAmB,GAAG,CAAC,CAAC;YACxB,MAAM;QACR,CAAC;IACH,CAAC;IACD,MAAM,cAAc,GAAG,MAAM,CAAC,mBAAmB,CAEpC,CAAC;IACd,MAAM,WAAW,GACf,cAAc,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/F,MAAM,cAAc,GAClB,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;IAEzF,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,IAAI,cAAc,KAAK,CAAC,CAAC,IAAI,cAAc,EAAE,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7B,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;YAC9C,IAAI,KAAK,IAAI,cAAc,IAAI,KAAK,KAAK,mBAAmB;gBAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,SAAS,GAAc,EAAE,CAAC;IAChC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,KAAK,cAAc,IAAI,cAAc,KAAK,CAAC,CAAC,EAAE,CAAC;YACrF,SAAS,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,YAAY;gBAClB,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,GAAG,EAAE,CAAC;gBACN,QAAQ,EAAE,IAAI;gBACd,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC;gBACzC,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,YAAY,EAAE,EAAE;gBAChB,YAAY,EAAE,KAAK,CAAC,YAAY;aACjC,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACxC,IAAI,OAAO;YAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;QACjD,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC;QAClB,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC;QAC5B,UAAU,GAAG,KAAK,CAAC,EAAE,CAAC;IACxB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+EAA+E;AAE/E,SAAS,aAAa,CAAC,MAAuB;IAC5C,MAAM,EACJ,IAAI,EAAE,KAAK,EACX,OAAO,EAAE,QAAQ,EACjB,EAAE,EACF,SAAS,EACT,GAAG,EACH,aAAa,EACb,eAAe,EACf,GAAG,MAAM,EACV,GAAG,MAAM,CAAC;IACX,MAAM,QAAQ,GAA4B,EAAE,GAAG,MAAM,EAAE,CAAC;IACxD,IAAI,aAAa,KAAK,SAAS;QAAE,QAAQ,CAAC,iBAAiB,GAAG,aAAa,CAAC;IAC5E,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,CAAC;QACV,EAAE;QACF,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC;QACnC,GAAG;QACH,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC;YAClC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAqC,EAAE;YACrD,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,IAAmB;IACvC,MAAM,KAAK,GAAa,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACrE,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,MAAM,IAAI,GAAG,CAAC,QAAiC,EAAE,EAAE;QACjD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC;IAEF,IAAI,IAAwB,CAAC;IAC7B,MAAM,MAAM,GAA2D,EAAE,CAAC;IAC1E,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAClC,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;YACvC,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;YAC9D,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QACpC,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACpD,IAAI,CAAC,SAAS;YAAE,SAAS;QACzB,SAAS,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC;QACtB,qEAAqE;QACrE,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,uEAAuE;IACvE,2EAA2E;IAC3E,uCAAuC;IACvC,IAAI,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACrE,OAAO,MAAM,KAAK,IAAI,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,IAAI,CAAC;YACd,MAAM;QACR,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxF,MAAM;QACR,CAAC;QACD,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC3B,CAAC;IACD,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACzD,IAAI,IAAI,KAAK,SAAS;QAAE,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/E,KAAK,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,MAAM,EAAE,CAAC;QACzC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,+EAA+E;AAE/E,KAAK,UAAU,kBAAkB,CAAC,MAAc,EAAE,MAAqB;IACrE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,eAAe,GAAG,MAAM,KAAK,CAAC,mBAAmB,EAAE,CAAC;IAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAClE,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9E,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC5D,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,cAAc,EAAE,CAAC;IAClD,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC;SAC/B,UAAU,EAAE;SACZ,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC;QAC/C,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACjB,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAgB,EAChB,OAA8B;IAE9B,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAChF,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,OAAO,EAAE,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAEtF,MAAM,QAAQ,GAAG,GAAG,QAAQ,SAAS,CAAC;IACtC,sBAAsB,CAAC,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,MAAM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,UAAU,CAAC,QAAQ,EAAE,GAAG,QAAQ,SAAS,CAAC,CAAC;IAC3C,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,EAAE;QAC3B,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7B,IAAI,KAAK,CAAC;YACV,IAAI,CAAC;gBACH,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YACzB,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,IAAI,CAAC,CAAC;YACb,CAAC;iBAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,IAAI,CAAC,CAAC;IACX,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["/**\n * One-time migration of legacy v3 session files to pi's v4 JSONL format.\n *\n * v3 is the entry family mikan wrote up to pi 0.83: a `{\"type\":\"session\"}`\n * header followed by tree entries with string ISO timestamps and compaction\n * entries that point at `firstKeptEntryId`. v4 (pi 0.84+) uses a\n * `{\"kind\":\"header\",\"version\":4}` header followed by mutation lines whose\n * entries carry numeric timestamps and a consecutive `seq`, with compaction\n * retention stored inline as `retainedTail`.\n *\n * The migration preserves entry ids, parent links, and timestamps, converts\n * `custom_message` entries into v4 `custom`-role messages, folds\n * `session_info` into the v4 name fact, `label` entries into label facts,\n * and rewrites each compaction's kept range into its inline `retainedTail`.\n * Every migrated file is verified before it replaces the original: the v4\n * file is re-opened with pi's reader and its built context must equal the\n * v3 context computed by the reference converter below. The original file\n * is kept beside the migrated one as `<name>.v3.bak`.\n */\nimport { existsSync, readdirSync, readFileSync, renameSync, rmSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n buildSessionContext,\n createCustomMessage,\n type AgentMessage,\n type Entry as PiEntry,\n type JsonlV4Header,\n} from \"@earendil-works/pi-agent-core\";\nimport { SessionStore } from \"../harness/session-store.js\";\nimport { atomicWritePrivateFile } from \"../utils/file-guards.js\";\nimport type { MigrateResult } from \"./types.js\";\nexport type { MigrateResult } from \"./types.js\";\n\n// ── v3 shapes ────────────────────────────────────────────────────────────────\n\ninterface V3EntryBase {\n type: string;\n id: string;\n parentId: string | null;\n timestamp: string;\n}\n\ntype V3Entry = V3EntryBase &\n (\n | { type: \"message\"; message: AgentMessage }\n | { type: \"thinking_level_change\"; thinkingLevel: string }\n | { type: \"model_change\"; provider: string; modelId: string }\n | { type: \"active_tools_change\"; activeToolNames: string[] }\n | {\n type: \"compaction\";\n summary: string;\n firstKeptEntryId?: string;\n tokensBefore: number;\n retainedTail?: AgentMessage[];\n details?: unknown;\n usage?: unknown;\n }\n | {\n type: \"branch_summary\";\n fromId: string;\n summary: string;\n details?: unknown;\n usage?: unknown;\n }\n | { type: \"custom\"; customType: string; data?: unknown }\n | {\n type: \"custom_message\";\n customType: string;\n content: Parameters<typeof createCustomMessage>[1];\n display: boolean;\n details?: unknown;\n }\n | { type: \"label\"; targetId: string; label: string | undefined }\n | { type: \"session_info\"; name?: string }\n | { type: \"leaf\"; targetId: string | null }\n );\n\ninterface V3SessionHeader {\n type: \"session\";\n version?: number;\n id: string;\n timestamp: string;\n cwd: string;\n parentSession?: string;\n parentSessionId?: string;\n [extra: string]: unknown;\n}\n\ninterface V3SessionFile {\n header: V3SessionHeader;\n entries: V3Entry[];\n}\n\n/** Whether a file's first non-empty line is a v3 session header. */\nexport function isV3SessionFile(filePath: string): boolean {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const firstLine = content.split(\"\\n\").find((line) => line.trim().length > 0);\n if (!firstLine) return false;\n const parsed = JSON.parse(firstLine) as { type?: unknown };\n return parsed.type === \"session\";\n } catch {\n return false;\n }\n}\n\n/** Read a v3 session file, ignoring a torn final line (crash tail). */\nfunction readV3SessionFile(filePath: string): V3SessionFile {\n const lines = readFileSync(filePath, \"utf-8\")\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n const records: Record<string, unknown>[] = [];\n for (const [index, line] of lines.entries()) {\n try {\n records.push(JSON.parse(line) as Record<string, unknown>);\n } catch (error) {\n if (index === lines.length - 1 && index > 0) continue;\n throw new Error(`Invalid JSON on line ${index + 1} of ${filePath}`, { cause: error });\n }\n }\n const header = records[0];\n if (!header || header.type !== \"session\" || typeof header.id !== \"string\") {\n throw new Error(`Not a v3 session file: ${filePath}`);\n }\n // Crash-era v3 files can contain duplicated lines (a retried append wrote\n // the header+entry pair twice). The v3 runtime read entries into a Map, so\n // duplicates were silently collapsed; v4 rejects duplicate mutation ids.\n // Reproduce the v3 semantics: keep one entry per id, drop stray repeated\n // session headers.\n const seen = new Set<string>();\n const entries: V3Entry[] = [];\n for (const record of records.slice(1)) {\n if (typeof record.type !== \"string\" || typeof record.id !== \"string\") continue;\n if (record.type === \"session\") continue;\n if (seen.has(record.id)) continue;\n seen.add(record.id);\n entries.push(record as unknown as V3Entry);\n }\n return { header: header as unknown as V3SessionHeader, entries };\n}\n\nfunction toEpochMillis(timestamp: string): number {\n const parsed = Date.parse(timestamp);\n return Number.isNaN(parsed) ? 0 : parsed;\n}\n\n/** Walk a v3 tree from an entry to the root; returns root-first path order. */\nfunction v3Branch(entries: V3Entry[], fromId: string | null): V3Entry[] {\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const path: V3Entry[] = [];\n let currentId = fromId;\n while (currentId) {\n const entry = byId.get(currentId);\n if (!entry) break;\n path.push(entry);\n currentId = entry.parentId;\n }\n return path.toReversed();\n}\n\nfunction v3LeafId(entries: V3Entry[]): string | null {\n let leafId: string | null = null;\n for (const entry of entries) {\n leafId = entry.type === \"leaf\" ? entry.targetId : entry.id;\n }\n return leafId;\n}\n\n/** Convert one tree-shaping v3 entry to its v4 counterpart (facts excluded). */\nfunction convertEntry(entry: V3Entry, entries: V3Entry[]): PiEntry | null {\n const base = {\n id: entry.id,\n seq: 0, // assigned at mutation-encoding time\n parentId: resolveV4Parent(entry, entries),\n timestamp: toEpochMillis(entry.timestamp),\n };\n switch (entry.type) {\n case \"message\":\n return { ...base, type: \"message\", message: entry.message };\n case \"custom_message\":\n return {\n ...base,\n type: \"message\",\n message: createCustomMessage(\n entry.customType,\n entry.content,\n entry.display,\n entry.details,\n toEpochMillis(entry.timestamp),\n ),\n };\n case \"thinking_level_change\":\n return { ...base, type: \"thinking_level_change\", thinkingLevel: entry.thinkingLevel };\n case \"model_change\":\n return { ...base, type: \"model_change\", provider: entry.provider, modelId: entry.modelId };\n case \"active_tools_change\":\n return { ...base, type: \"active_tools_change\", activeToolNames: entry.activeToolNames };\n case \"compaction\":\n return {\n ...base,\n type: \"compaction\",\n summary: entry.summary,\n retainedTail: entry.retainedTail ?? compactionKeptMessages(entry, entries),\n tokensBefore: entry.tokensBefore,\n ...(entry.details !== undefined ? { details: entry.details } : {}),\n ...(entry.usage !== undefined ? { usage: entry.usage as PiEntry & object } : {}),\n } as unknown as PiEntry;\n case \"branch_summary\":\n return {\n ...base,\n type: \"branch_summary\",\n fromId: entry.fromId,\n summary: entry.summary,\n ...(entry.details !== undefined ? { details: entry.details } : {}),\n ...(entry.usage !== undefined ? { usage: entry.usage } : {}),\n } as unknown as PiEntry;\n case \"custom\":\n return { ...base, type: \"custom\", customType: entry.customType, data: entry.data };\n default:\n // session_info / label / leaf become facts and the lane pointer.\n return null;\n }\n}\n\n/**\n * Skip fact-only ancestors (session_info/label/leaf) when re-linking the v4\n * tree: those entries disappear from the entry stream, so children re-attach\n * to the nearest surviving ancestor.\n */\nfunction resolveV4Parent(entry: V3Entry, entries: V3Entry[]): string | null {\n const byId = new Map(entries.map((item) => [item.id, item]));\n let parentId = entry.parentId;\n while (parentId !== null) {\n const parent = byId.get(parentId);\n if (!parent) return null;\n if (parent.type !== \"session_info\" && parent.type !== \"label\" && parent.type !== \"leaf\") {\n return parentId;\n }\n parentId = parent.parentId;\n }\n return null;\n}\n\n/**\n * Messages of the v3 kept range (`firstKeptEntryId` .. compaction parent),\n * which v4 stores inline on the compaction entry.\n */\nfunction compactionKeptMessages(\n compaction: Extract<V3Entry, { type: \"compaction\" }>,\n entries: V3Entry[],\n): AgentMessage[] {\n if (!compaction.firstKeptEntryId) return [];\n const ancestors = v3Branch(entries, compaction.parentId);\n const keptStart = ancestors.findIndex((entry) => entry.id === compaction.firstKeptEntryId);\n if (keptStart === -1) return [];\n const messages: AgentMessage[] = [];\n for (const entry of ancestors.slice(keptStart)) {\n if (entry.type === \"message\") messages.push(entry.message);\n else if (entry.type === \"custom_message\") {\n messages.push(\n createCustomMessage(\n entry.customType,\n entry.content,\n entry.display,\n entry.details,\n toEpochMillis(entry.timestamp),\n ),\n );\n }\n }\n return messages;\n}\n\n// ── reference converter (verification oracle) ───────────────────────────────\n\n/**\n * Convert a v3 branch to v4 entries with the pi-0.83 context semantics:\n * the last compaction is repositioned ahead of its kept range so pi's v4\n * transform reproduces the v3 context exactly. This mirrors what the\n * runtime shim did before mikan moved to native v4 files, and serves as\n * the verification oracle for migrated output.\n */\nfunction referenceContextEntries(branch: V3Entry[]): PiEntry[] {\n let lastCompactionIndex = -1;\n for (let i = branch.length - 1; i >= 0; i--) {\n if (branch[i]?.type === \"compaction\") {\n lastCompactionIndex = i;\n break;\n }\n }\n const lastCompaction = branch[lastCompactionIndex] as\n | Extract<V3Entry, { type: \"compaction\" }>\n | undefined;\n const firstKeptId =\n lastCompaction && !lastCompaction.retainedTail ? lastCompaction.firstKeptEntryId : undefined;\n const firstKeptIndex =\n firstKeptId === undefined ? -1 : branch.findIndex((entry) => entry.id === firstKeptId);\n\n const ordered: V3Entry[] = [];\n if (firstKeptIndex !== -1 && lastCompaction) {\n ordered.push(...branch.slice(0, firstKeptIndex));\n ordered.push(lastCompaction);\n for (const [index, entry] of branch.entries()) {\n if (index >= firstKeptIndex && index !== lastCompactionIndex) ordered.push(entry);\n }\n } else {\n ordered.push(...branch);\n }\n\n const converted: PiEntry[] = [];\n for (const entry of ordered) {\n if (entry.type === \"compaction\" && entry === lastCompaction && firstKeptIndex !== -1) {\n converted.push({\n type: \"compaction\",\n id: entry.id,\n seq: 0,\n parentId: null,\n timestamp: toEpochMillis(entry.timestamp),\n summary: entry.summary,\n retainedTail: [],\n tokensBefore: entry.tokensBefore,\n });\n continue;\n }\n const piEntry = convertEntry(entry, []);\n if (piEntry) converted.push(piEntry);\n }\n let previousId: string | null = null;\n for (const [index, entry] of converted.entries()) {\n entry.seq = index;\n entry.parentId = previousId;\n previousId = entry.id;\n }\n return converted;\n}\n\n// ── v4 encoding ─────────────────────────────────────────────────────────────\n\nfunction buildV4Header(header: V3SessionHeader): JsonlV4Header {\n const {\n type: _type,\n version: _version,\n id,\n timestamp,\n cwd,\n parentSession,\n parentSessionId,\n ...extras\n } = header;\n const metadata: Record<string, unknown> = { ...extras };\n if (parentSession !== undefined) metadata.parentSessionPath = parentSession;\n return {\n kind: \"header\",\n version: 4,\n id,\n createdAt: toEpochMillis(timestamp),\n cwd,\n ...(parentSessionId !== undefined ? { parentSessionId } : {}),\n ...(Object.keys(metadata).length > 0\n ? { metadata: metadata as JsonlV4Header[\"metadata\"] }\n : {}),\n };\n}\n\nfunction encodeV4File(file: V3SessionFile): string {\n const lines: string[] = [JSON.stringify(buildV4Header(file.header))];\n let seq = 0;\n const push = (mutation: Record<string, unknown>) => {\n lines.push(JSON.stringify(mutation));\n };\n\n let name: string | undefined;\n const labels: Array<{ targetId: string; label: string | undefined }> = [];\n for (const entry of file.entries) {\n if (entry.type === \"session_info\") {\n name = entry.name?.trim() || undefined;\n continue;\n }\n if (entry.type === \"label\") {\n labels.push({ targetId: entry.targetId, label: entry.label });\n continue;\n }\n if (entry.type === \"leaf\") continue;\n const converted = convertEntry(entry, file.entries);\n if (!converted) continue;\n converted.seq = ++seq;\n // Entry mutations are encoded flat: {kind:\"entry\", ...entry fields}.\n push({ kind: \"entry\", ...converted });\n }\n\n // The v3 leaf may point at a fact-only entry (session_info/label) that\n // does not survive as a v4 entry; re-aim the lane at its nearest surviving\n // ancestor, mirroring resolveV4Parent.\n let leafId = v3LeafId(file.entries);\n const byId = new Map(file.entries.map((entry) => [entry.id, entry]));\n while (leafId !== null) {\n const target = byId.get(leafId);\n if (!target) {\n leafId = null;\n break;\n }\n if (target.type !== \"session_info\" && target.type !== \"label\" && target.type !== \"leaf\") {\n break;\n }\n leafId = target.parentId;\n }\n push({ kind: \"lane\", seq: ++seq, lane: \"main\", leafId });\n if (name !== undefined) push({ kind: \"fact\", seq: ++seq, fact: \"name\", name });\n for (const { targetId, label } of labels) {\n push({ kind: \"fact\", seq: ++seq, fact: \"label\", targetId, label });\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\n// ── migration driver ────────────────────────────────────────────────────────\n\nasync function verifyMigratedFile(v4Path: string, source: V3SessionFile): Promise<void> {\n const store = await SessionStore.inspect(v4Path);\n const migratedContext = await store.buildSessionContext();\n const branch = v3Branch(source.entries, v3LeafId(source.entries));\n const referenceContext = buildSessionContext(referenceContextEntries(branch));\n const migrated = JSON.stringify(migratedContext.messages);\n const reference = JSON.stringify(referenceContext.messages);\n if (migrated !== reference) {\n throw new Error(\"migrated context does not match the v3 reference context\");\n }\n const migratedName = await store.getSessionName();\n const v3Name = [...source.entries]\n .toReversed()\n .find((entry) => entry.type === \"session_info\")\n ?.name?.trim();\n if ((migratedName ?? \"\") !== (v3Name || \"\")) {\n throw new Error(\"migrated session name does not match the v3 session name\");\n }\n}\n\n/**\n * Migrate one session file in place. The migrated file is verified against\n * the v3 reference semantics before it replaces the original; the original\n * is preserved as `<file>.v3.bak`.\n */\nexport async function migrateSessionFile(\n filePath: string,\n options?: { dryRun?: boolean },\n): Promise<MigrateResult> {\n if (!isV3SessionFile(filePath)) return { file: filePath, status: \"already-v4\" };\n const source = readV3SessionFile(filePath);\n if (options?.dryRun) return { file: filePath, status: \"migrated\", detail: \"dry run\" };\n\n const tempPath = `${filePath}.v4.tmp`;\n atomicWritePrivateFile(tempPath, encodeV4File(source));\n try {\n await verifyMigratedFile(tempPath, source);\n } catch (error) {\n rmSync(tempPath, { force: true });\n throw new Error(`Verification failed for ${filePath}`, { cause: error });\n }\n renameSync(filePath, `${filePath}.v3.bak`);\n renameSync(tempPath, filePath);\n return { file: filePath, status: \"migrated\" };\n}\n\n/** Recursively find candidate session files (.jsonl with a v3 header). */\nexport function findV3SessionFiles(root: string): string[] {\n if (!existsSync(root)) return [];\n const found: string[] = [];\n const walk = (dir: string) => {\n for (const name of readdirSync(dir)) {\n const path = join(dir, name);\n let stats;\n try {\n stats = statSync(path);\n } catch {\n continue;\n }\n if (stats.isDirectory()) {\n walk(path);\n } else if (name.endsWith(\".jsonl\") && isV3SessionFile(path)) {\n found.push(path);\n }\n }\n };\n walk(root);\n return found;\n}\n"]}
|
package/dist/sessions/store.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SessionStore } from "../harness/index.js";
|
|
2
|
-
export type { ResolvedSessionScope, ThreadRootMessage } from "./types.js";
|
|
3
|
-
|
|
2
|
+
export type { MikanSessionHeader, ParentSessionRef, ResolvedSessionScope, ThreadRootMessage, } from "./types.js";
|
|
3
|
+
import type { ParentSessionRef } from "./types.js";
|
|
4
4
|
export declare function isPlatformHistorySession(sessionFile: string): boolean;
|
|
5
5
|
/**
|
|
6
6
|
* Resolves the current active session file for a session directory.
|
|
@@ -42,13 +42,11 @@ export declare function createManagedSessionFile(sessionDir: string, cwd: string
|
|
|
42
42
|
* This avoids SessionStore.open() falling back to process.cwd() for fresh sessions.
|
|
43
43
|
*/
|
|
44
44
|
export declare function openManagedSession(sessionFile: string, cwd: string): Promise<SessionStore>;
|
|
45
|
+
/** Preserve a fixed-path session before recreating that scope at the same path. */
|
|
46
|
+
export declare function archiveManagedSessionFile(sessionFile: string): string | null;
|
|
45
47
|
/**
|
|
46
48
|
* Creates or overwrites a fixed-path session file with a valid session header.
|
|
47
49
|
*/
|
|
48
|
-
export interface ParentSessionRef {
|
|
49
|
-
path: string;
|
|
50
|
-
id: string;
|
|
51
|
-
}
|
|
52
50
|
export declare function createManagedSessionFileAtPath(sessionFile: string, cwd: string, parent?: ParentSessionRef): string;
|
|
53
51
|
/**
|
|
54
52
|
* Returns the fixed session file path for a Slack thread.
|
|
@@ -77,4 +75,5 @@ export declare function resolveChannelSessionFile(channelDir: string): string |
|
|
|
77
75
|
* Returns both path and session UUID so callers can store a UUID-stable reference.
|
|
78
76
|
*/
|
|
79
77
|
export declare function resolveParentSessionForThread(channelDir: string, threadTs: string | undefined): ParentSessionRef | null;
|
|
78
|
+
export declare function shouldRotateTopLevelSession(sessionFile: string, now: Date): boolean;
|
|
80
79
|
//# sourceMappingURL=store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/sessions/store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AASnD,YAAY,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/sessions/store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AASnD,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEvE,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAQrE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAI7D;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIjF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE/D;AAiBD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAO/D;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAOhF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAM1F;AAOD,mFAAmF;AACnF,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa5E;AAQD;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,gBAAgB,GACxB,MAAM,CAGR;AAgBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAGnF;AA8DD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI1E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE1E;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE3E;AAKD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,gBAAgB,GAAG,IAAI,CAYzB;AA6CD,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAGnF"}
|
package/dist/sessions/store.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { existsSync, lstatSync, mkdirSync, readdirSync, rmSync } from "node:fs";
|
|
3
|
-
import { basename, join, relative, resolve, sep } from "node:path";
|
|
2
|
+
import { existsSync, lstatSync, mkdirSync, readdirSync, renameSync, rmSync } from "node:fs";
|
|
3
|
+
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import { SessionStore } from "../harness/index.js";
|
|
5
5
|
import { atomicWritePrivateFile, isRecord, parseJsonValue, readTextFileIfExists, } from "../utils/file-guards.js";
|
|
6
6
|
import { officeSessionsDir } from "../office/index.js";
|
|
@@ -106,11 +106,32 @@ function createSessionFilename(sessionId = randomUUID()) {
|
|
|
106
106
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
107
107
|
return `${timestamp}_${sessionId.slice(0, 8)}.jsonl`;
|
|
108
108
|
}
|
|
109
|
+
/** Preserve a fixed-path session before recreating that scope at the same path. */
|
|
110
|
+
export function archiveManagedSessionFile(sessionFile) {
|
|
111
|
+
if (!existsSync(sessionFile))
|
|
112
|
+
return null;
|
|
113
|
+
let archiveName;
|
|
114
|
+
try {
|
|
115
|
+
const sessionId = SessionStore.readHeader(sessionFile)?.id;
|
|
116
|
+
if (!sessionId)
|
|
117
|
+
throw new Error("missing header");
|
|
118
|
+
archiveName = `scoped-archive-${createSessionFilename(sessionId)}`;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
archiveName = `scoped-archive-${createSessionFilename()}.corrupt`;
|
|
122
|
+
}
|
|
123
|
+
const archive = join(dirname(sessionFile), archiveName);
|
|
124
|
+
renameSync(sessionFile, archive);
|
|
125
|
+
return archive;
|
|
126
|
+
}
|
|
109
127
|
function setCurrentPointer(sessionDir, sessionFilePath) {
|
|
110
128
|
const filename = sessionFilePath.split("/").pop();
|
|
111
129
|
mkdirSync(sessionDir, { recursive: true });
|
|
112
130
|
atomicWritePrivateFile(join(sessionDir, "current"), filename);
|
|
113
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Creates or overwrites a fixed-path session file with a valid session header.
|
|
134
|
+
*/
|
|
114
135
|
export function createManagedSessionFileAtPath(sessionFile, cwd, parent) {
|
|
115
136
|
writeSessionHeader(sessionFile, cwd, undefined, parent);
|
|
116
137
|
return sessionFile;
|
|
@@ -264,4 +285,43 @@ function readSessionHeaderSummary(filePath) {
|
|
|
264
285
|
return null;
|
|
265
286
|
}
|
|
266
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* Biweekly rotation clock for top-level shared sessions: a session file
|
|
290
|
+
* rotates when its header timestamp falls in a different two-week bucket
|
|
291
|
+
* (anchored to a fixed Sunday) than the given "now".
|
|
292
|
+
*/
|
|
293
|
+
const BIWEEKLY_ROTATION_ANCHOR = new Date(2026, 0, 4); // Sunday
|
|
294
|
+
const BIWEEKLY_MS = 14 * 24 * 60 * 60 * 1000;
|
|
295
|
+
export function shouldRotateTopLevelSession(sessionFile, now) {
|
|
296
|
+
const timestamp = readSessionTimestamp(sessionFile);
|
|
297
|
+
return timestamp !== null && biweeklyBucket(timestamp) !== biweeklyBucket(now);
|
|
298
|
+
}
|
|
299
|
+
function readSessionTimestamp(sessionFile) {
|
|
300
|
+
const raw = readTextFileIfExists(sessionFile);
|
|
301
|
+
if (raw === undefined)
|
|
302
|
+
return null;
|
|
303
|
+
const firstLine = raw.split("\n").find((line) => line.trim());
|
|
304
|
+
if (!firstLine)
|
|
305
|
+
return null;
|
|
306
|
+
try {
|
|
307
|
+
const header = parseJsonValue(firstLine, (value) => isRecord(value), (detail) => (detail === "unexpected JSON shape" ? "expected a JSON object" : detail));
|
|
308
|
+
// v4 headers carry a numeric createdAt; legacy v3 headers a string timestamp.
|
|
309
|
+
const value = typeof header.createdAt === "number" ? header.createdAt : header.timestamp;
|
|
310
|
+
if (typeof value !== "number" && typeof value !== "string")
|
|
311
|
+
return null;
|
|
312
|
+
const date = new Date(value);
|
|
313
|
+
return Number.isFinite(date.getTime()) ? date : null;
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function biweeklyBucket(date) {
|
|
320
|
+
const weekStart = sundayStart(date).getTime();
|
|
321
|
+
const anchor = sundayStart(BIWEEKLY_ROTATION_ANCHOR).getTime();
|
|
322
|
+
return Math.floor((weekStart - anchor) / BIWEEKLY_MS);
|
|
323
|
+
}
|
|
324
|
+
function sundayStart(date) {
|
|
325
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay());
|
|
326
|
+
}
|
|
267
327
|
//# sourceMappingURL=store.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/sessions/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { existsSync, lstatSync, mkdirSync, readdirSync, rmSync } from \"node:fs\";\nimport { basename, join, relative, resolve, sep } from \"node:path\";\nimport { SessionStore } from \"../harness/index.js\";\nimport {\n atomicWritePrivateFile,\n isRecord,\n parseJsonValue,\n readTextFileIfExists,\n} from \"../utils/file-guards.js\";\nimport { officeSessionsDir } from \"../office/index.js\";\nimport { assertSessionSuffix, threadSuffixOf } from \"./session-key.js\";\nexport type { ResolvedSessionScope, ThreadRootMessage } from \"./types.js\";\nexport type { MikanSessionHeader } from \"./types.js\";\nimport type { MikanSessionHeader } from \"./types.js\";\n\nexport function isPlatformHistorySession(sessionFile: string): boolean {\n try {\n const header = SessionStore.readHeader(sessionFile);\n const source = (header?.metadata as MikanSessionHeader | undefined)?.source;\n return source?.kind === \"platform-history\";\n } catch {\n return false;\n }\n}\n\n/**\n * Resolves the current active session file for a session directory.\n * Reads the \"current\" pointer file; creates a new session if none exists\n * or the pointed-to file is missing.\n */\nexport function resolveSessionFile(sessionDir: string): string {\n const existing = tryResolveCurrentSession(sessionDir);\n if (existing) return existing;\n return createNewSessionFile(sessionDir);\n}\n\n/**\n * Resolve the current active session file for a session directory.\n * Creates a fully initialized persistent session with the provided cwd when none exists.\n */\nexport function resolveManagedSessionFile(sessionDir: string, cwd: string): string {\n const existingPath = getCurrentSessionPath(sessionDir);\n if (existingPath && !isPlatformHistorySession(existingPath)) return existingPath;\n return createManagedSessionFile(sessionDir, cwd);\n}\n\n/**\n * Extracts the short UUID from a session file path.\n * e.g. \"2026-04-05T00-00_7b54cf90.jsonl\" → \"7b54cf90\"\n */\nexport function extractSessionUuid(sessionFile: string): string {\n return basename(sessionFile).replace(\".jsonl\", \"\").split(\"_\").pop()!;\n}\n\n/**\n * Extracts the thread/suffix part of a session key.\n * \"channelId:threadId\" → \"threadId\", \"channelId\" → \"channelId\"\n */\nexport function extractSessionSuffix(sessionKey: string): string {\n return assertSessionSuffix(threadSuffixOf(sessionKey) ?? sessionKey);\n}\n\n/**\n * Resolve one child path and prove it remains inside its owning directory.\n * Identity validation is the first guard; containment is defense in depth for\n * every session path derived from platform-controlled values.\n */\nfunction resolveChildPath(root: string, child: string): string {\n const resolvedRoot = resolve(root);\n const resolvedChild = resolve(resolvedRoot, child);\n const relation = relative(resolvedRoot, resolvedChild);\n if (!relation || relation === \"..\" || relation.startsWith(`..${sep}`)) {\n throw new Error(`Session path escapes its owning directory: ${JSON.stringify(child)}`);\n }\n return resolvedChild;\n}\n\n/**\n * Creates an empty timestamped file and updates the \"current\" pointer.\n * Used only by tests for placeholder-file scenarios.\n *\n * Order matters: write the session file first, then atomic-rename the pointer\n * last so a crash mid-create never leaves \"current\" pointing at a missing file.\n */\nexport function createNewSessionFile(sessionDir: string): string {\n mkdirSync(sessionDir, { recursive: true });\n const filename = createSessionFilename();\n const filePath = join(sessionDir, filename);\n atomicWritePrivateFile(filePath, \"\");\n atomicWritePrivateFile(join(sessionDir, \"current\"), filename);\n return filePath;\n}\n\n/**\n * Creates a new persistent session file with a proper SessionManager header and cwd.\n * Also updates the \"current\" pointer. Header is written before the pointer flips so a\n * partial create cannot leave \"current\" pointing at a missing file.\n */\nexport function createManagedSessionFile(sessionDir: string, cwd: string): string {\n mkdirSync(sessionDir, { recursive: true });\n const sessionId = randomUUID();\n const sessionFile = join(sessionDir, createSessionFilename(sessionId));\n writeSessionHeader(sessionFile, cwd, sessionId);\n setCurrentPointer(sessionDir, sessionFile);\n return sessionFile;\n}\n\n/**\n * Open a session file with an explicit cwd, even if the file does not exist yet.\n * This avoids SessionStore.open() falling back to process.cwd() for fresh sessions.\n */\nexport function openManagedSession(sessionFile: string, cwd: string): Promise<SessionStore> {\n if (shouldRecreatePreinitializedSession(sessionFile)) {\n rmSync(sessionFile, { force: true });\n }\n\n return SessionStore.open(sessionFile, cwd);\n}\n\nfunction createSessionFilename(sessionId = randomUUID()): string {\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n return `${timestamp}_${sessionId.slice(0, 8)}.jsonl`;\n}\n\nfunction setCurrentPointer(sessionDir: string, sessionFilePath: string): void {\n const filename = sessionFilePath.split(\"/\").pop()!;\n mkdirSync(sessionDir, { recursive: true });\n atomicWritePrivateFile(join(sessionDir, \"current\"), filename);\n}\n\n/**\n * Creates or overwrites a fixed-path session file with a valid session header.\n */\nexport interface ParentSessionRef {\n path: string;\n id: string;\n}\n\nexport function createManagedSessionFileAtPath(\n sessionFile: string,\n cwd: string,\n parent?: ParentSessionRef,\n): string {\n writeSessionHeader(sessionFile, cwd, undefined, parent);\n return sessionFile;\n}\n\nfunction writeSessionHeader(\n sessionFile: string,\n cwd: string,\n sessionId = randomUUID(),\n parent?: ParentSessionRef,\n): void {\n // The header format (and its version) is owned by the harness store; this\n // layer only decides the path and the id.\n SessionStore.writeHeaderFile(sessionFile, cwd, {\n id: sessionId,\n ...(parent ? { parentSession: parent.path, parentSessionId: parent.id } : {}),\n });\n}\n\n/**\n * Returns the fixed session file path for a Slack thread.\n */\nexport function getThreadSessionFile(channelDir: string, sessionKey: string): string {\n const sessionDir = officeSessionsDir(channelDir);\n return resolveChildPath(sessionDir, `${extractSessionSuffix(sessionKey)}.jsonl`);\n}\n\nfunction isRegularSessionFile(sessionFile: string): boolean {\n try {\n return lstatSync(sessionFile).isFile();\n } catch {\n return false;\n }\n}\n\nfunction hasSessionHeader(sessionFile: string): boolean {\n // readHeader returns null for missing/garbage files and throws ONLY for\n // legacy v3 files. Let that throw propagate: treating an unmigrated v3\n // session as \"no session\" would flip the current pointer to a fresh file\n // and silently orphan the conversation history.\n return SessionStore.readHeader(sessionFile) !== null;\n}\n\nfunction shouldRecreatePreinitializedSession(sessionFile: string): boolean {\n try {\n const raw = readTextFileIfExists(sessionFile);\n if (raw === undefined) return false;\n const entries = raw\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map(parseSessionEntry);\n\n if (entries.length !== 1) return false;\n const only = entries[0] as {\n kind?: unknown;\n parentSessionId?: unknown;\n metadata?: { parentSessionPath?: unknown };\n };\n if (only.kind !== \"header\") return false;\n // Sessions with lineage metadata are fully initialized — preserve them.\n if (only.parentSessionId || only.metadata?.parentSessionPath) return false;\n return true;\n } catch {\n return false;\n }\n}\n\nfunction parseSessionEntry(line: string): { type?: string; kind?: string } {\n return parseJsonValue(\n line,\n (value): value is { type?: string; kind?: string } => isRecord(value),\n (detail) => (detail === \"unexpected JSON shape\" ? \"expected a JSON object\" : detail),\n );\n}\n\nfunction getCurrentSessionPath(sessionDir: string): string | null {\n const pointerFile = join(sessionDir, \"current\");\n const filename = readTextFileIfExists(pointerFile)?.trim();\n if (!filename) return null;\n try {\n return resolveChildPath(sessionDir, filename);\n } catch {\n return null;\n }\n}\n\n/**\n * Try to resolve an existing current session file.\n * Returns null if no current pointer exists or the pointed file has no valid session header.\n */\nexport function tryResolveCurrentSession(sessionDir: string): string | null {\n const fullPath = getCurrentSessionPath(sessionDir);\n if (fullPath && isRegularSessionFile(fullPath) && hasSessionHeader(fullPath)) return fullPath;\n return null;\n}\n\n/**\n * Try to resolve an existing thread session file.\n * Returns the file path if found, or null if no valid thread session exists yet.\n */\nexport function tryResolveThreadSession(sessionFile: string): string | null {\n return isRegularSessionFile(sessionFile) && hasSessionHeader(sessionFile) ? sessionFile : null;\n}\n\n/**\n * Resolve the channel's current session file path.\n * Returns null if no channel session exists.\n */\nexport function resolveChannelSessionFile(channelDir: string): string | null {\n return tryResolveCurrentSession(officeSessionsDir(channelDir));\n}\n\n// Matches timestamped main session filenames; thread sessions use bare threadTs.\nconst MAIN_SESSION_FILENAME = /^\\d{4}-\\d{2}-\\d{2}T.+_[0-9a-f]{8}\\.jsonl$/i;\n\n/**\n * Resolve the main session file that was active when a thread was created.\n * Uses the thread's Slack timestamp to find the main session whose creation\n * time is the latest one at or before that moment — stable across rotations.\n * Falls back to resolveChannelSessionFile when threadTs is absent or unparseable.\n * Returns both path and session UUID so callers can store a UUID-stable reference.\n */\nexport function resolveParentSessionForThread(\n channelDir: string,\n threadTs: string | undefined,\n): ParentSessionRef | null {\n if (threadTs !== undefined) {\n const threadTimeMs = Number(threadTs) * 1000;\n if (Number.isFinite(threadTimeMs)) {\n const best = findMainSessionActiveAtTime(channelDir, threadTimeMs);\n if (best) return best;\n }\n }\n const path = resolveChannelSessionFile(channelDir);\n if (!path) return null;\n const id = readSessionHeaderSummary(path)?.id;\n return id ? { path, id } : null;\n}\n\nfunction findMainSessionActiveAtTime(\n channelDir: string,\n targetMs: number,\n): ParentSessionRef | null {\n const sessionDir = officeSessionsDir(channelDir);\n if (!existsSync(sessionDir)) return null;\n\n let best: ParentSessionRef | null = null;\n let bestCreatedMs = -Infinity;\n\n for (const name of readdirSync(sessionDir)) {\n if (!MAIN_SESSION_FILENAME.test(name)) continue;\n const filePath = join(sessionDir, name);\n const summary = readSessionHeaderSummary(filePath);\n if (!summary) continue;\n if (summary.timestampMs <= targetMs && summary.timestampMs > bestCreatedMs) {\n bestCreatedMs = summary.timestampMs;\n best = { path: filePath, id: summary.id };\n }\n }\n return best;\n}\n\nfunction readSessionHeaderSummary(filePath: string): { id: string; timestampMs: number } | null {\n try {\n const header = SessionStore.readHeader(filePath);\n if (!header) return null;\n const timestampMs = new Date(header.timestamp).getTime();\n return Number.isFinite(timestampMs) ? { id: header.id, timestampMs } : null;\n } catch {\n return null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/sessions/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { existsSync, lstatSync, mkdirSync, readdirSync, renameSync, rmSync } from \"node:fs\";\nimport { basename, dirname, join, relative, resolve, sep } from \"node:path\";\nimport { SessionStore } from \"../harness/index.js\";\nimport {\n atomicWritePrivateFile,\n isRecord,\n parseJsonValue,\n readTextFileIfExists,\n} from \"../utils/file-guards.js\";\nimport { officeSessionsDir } from \"../office/index.js\";\nimport { assertSessionSuffix, threadSuffixOf } from \"./session-key.js\";\nexport type {\n MikanSessionHeader,\n ParentSessionRef,\n ResolvedSessionScope,\n ThreadRootMessage,\n} from \"./types.js\";\nimport type { MikanSessionHeader, ParentSessionRef } from \"./types.js\";\n\nexport function isPlatformHistorySession(sessionFile: string): boolean {\n try {\n const header = SessionStore.readHeader(sessionFile);\n const source = (header?.metadata as MikanSessionHeader | undefined)?.source;\n return source?.kind === \"platform-history\";\n } catch {\n return false;\n }\n}\n\n/**\n * Resolves the current active session file for a session directory.\n * Reads the \"current\" pointer file; creates a new session if none exists\n * or the pointed-to file is missing.\n */\nexport function resolveSessionFile(sessionDir: string): string {\n const existing = tryResolveCurrentSession(sessionDir);\n if (existing) return existing;\n return createNewSessionFile(sessionDir);\n}\n\n/**\n * Resolve the current active session file for a session directory.\n * Creates a fully initialized persistent session with the provided cwd when none exists.\n */\nexport function resolveManagedSessionFile(sessionDir: string, cwd: string): string {\n const existingPath = getCurrentSessionPath(sessionDir);\n if (existingPath && !isPlatformHistorySession(existingPath)) return existingPath;\n return createManagedSessionFile(sessionDir, cwd);\n}\n\n/**\n * Extracts the short UUID from a session file path.\n * e.g. \"2026-04-05T00-00_7b54cf90.jsonl\" → \"7b54cf90\"\n */\nexport function extractSessionUuid(sessionFile: string): string {\n return basename(sessionFile).replace(\".jsonl\", \"\").split(\"_\").pop()!;\n}\n\n/**\n * Extracts the thread/suffix part of a session key.\n * \"channelId:threadId\" → \"threadId\", \"channelId\" → \"channelId\"\n */\nexport function extractSessionSuffix(sessionKey: string): string {\n return assertSessionSuffix(threadSuffixOf(sessionKey) ?? sessionKey);\n}\n\n/**\n * Resolve one child path and prove it remains inside its owning directory.\n * Identity validation is the first guard; containment is defense in depth for\n * every session path derived from platform-controlled values.\n */\nfunction resolveChildPath(root: string, child: string): string {\n const resolvedRoot = resolve(root);\n const resolvedChild = resolve(resolvedRoot, child);\n const relation = relative(resolvedRoot, resolvedChild);\n if (!relation || relation === \"..\" || relation.startsWith(`..${sep}`)) {\n throw new Error(`Session path escapes its owning directory: ${JSON.stringify(child)}`);\n }\n return resolvedChild;\n}\n\n/**\n * Creates an empty timestamped file and updates the \"current\" pointer.\n * Used only by tests for placeholder-file scenarios.\n *\n * Order matters: write the session file first, then atomic-rename the pointer\n * last so a crash mid-create never leaves \"current\" pointing at a missing file.\n */\nexport function createNewSessionFile(sessionDir: string): string {\n mkdirSync(sessionDir, { recursive: true });\n const filename = createSessionFilename();\n const filePath = join(sessionDir, filename);\n atomicWritePrivateFile(filePath, \"\");\n atomicWritePrivateFile(join(sessionDir, \"current\"), filename);\n return filePath;\n}\n\n/**\n * Creates a new persistent session file with a proper SessionManager header and cwd.\n * Also updates the \"current\" pointer. Header is written before the pointer flips so a\n * partial create cannot leave \"current\" pointing at a missing file.\n */\nexport function createManagedSessionFile(sessionDir: string, cwd: string): string {\n mkdirSync(sessionDir, { recursive: true });\n const sessionId = randomUUID();\n const sessionFile = join(sessionDir, createSessionFilename(sessionId));\n writeSessionHeader(sessionFile, cwd, sessionId);\n setCurrentPointer(sessionDir, sessionFile);\n return sessionFile;\n}\n\n/**\n * Open a session file with an explicit cwd, even if the file does not exist yet.\n * This avoids SessionStore.open() falling back to process.cwd() for fresh sessions.\n */\nexport function openManagedSession(sessionFile: string, cwd: string): Promise<SessionStore> {\n if (shouldRecreatePreinitializedSession(sessionFile)) {\n rmSync(sessionFile, { force: true });\n }\n\n return SessionStore.open(sessionFile, cwd);\n}\n\nfunction createSessionFilename(sessionId: string = randomUUID()): string {\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n return `${timestamp}_${sessionId.slice(0, 8)}.jsonl`;\n}\n\n/** Preserve a fixed-path session before recreating that scope at the same path. */\nexport function archiveManagedSessionFile(sessionFile: string): string | null {\n if (!existsSync(sessionFile)) return null;\n let archiveName: string;\n try {\n const sessionId = SessionStore.readHeader(sessionFile)?.id;\n if (!sessionId) throw new Error(\"missing header\");\n archiveName = `scoped-archive-${createSessionFilename(sessionId)}`;\n } catch {\n archiveName = `scoped-archive-${createSessionFilename()}.corrupt`;\n }\n const archive = join(dirname(sessionFile), archiveName);\n renameSync(sessionFile, archive);\n return archive;\n}\n\nfunction setCurrentPointer(sessionDir: string, sessionFilePath: string): void {\n const filename = sessionFilePath.split(\"/\").pop()!;\n mkdirSync(sessionDir, { recursive: true });\n atomicWritePrivateFile(join(sessionDir, \"current\"), filename);\n}\n\n/**\n * Creates or overwrites a fixed-path session file with a valid session header.\n */\nexport function createManagedSessionFileAtPath(\n sessionFile: string,\n cwd: string,\n parent?: ParentSessionRef,\n): string {\n writeSessionHeader(sessionFile, cwd, undefined, parent);\n return sessionFile;\n}\n\nfunction writeSessionHeader(\n sessionFile: string,\n cwd: string,\n sessionId = randomUUID(),\n parent?: ParentSessionRef,\n): void {\n // The header format (and its version) is owned by the harness store; this\n // layer only decides the path and the id.\n SessionStore.writeHeaderFile(sessionFile, cwd, {\n id: sessionId,\n ...(parent ? { parentSession: parent.path, parentSessionId: parent.id } : {}),\n });\n}\n\n/**\n * Returns the fixed session file path for a Slack thread.\n */\nexport function getThreadSessionFile(channelDir: string, sessionKey: string): string {\n const sessionDir = officeSessionsDir(channelDir);\n return resolveChildPath(sessionDir, `${extractSessionSuffix(sessionKey)}.jsonl`);\n}\n\nfunction isRegularSessionFile(sessionFile: string): boolean {\n try {\n return lstatSync(sessionFile).isFile();\n } catch {\n return false;\n }\n}\n\nfunction hasSessionHeader(sessionFile: string): boolean {\n // readHeader returns null for missing/garbage files and throws ONLY for\n // legacy v3 files. Let that throw propagate: treating an unmigrated v3\n // session as \"no session\" would flip the current pointer to a fresh file\n // and silently orphan the conversation history.\n return SessionStore.readHeader(sessionFile) !== null;\n}\n\nfunction shouldRecreatePreinitializedSession(sessionFile: string): boolean {\n try {\n const raw = readTextFileIfExists(sessionFile);\n if (raw === undefined) return false;\n const entries = raw\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map(parseSessionEntry);\n\n if (entries.length !== 1) return false;\n const only = entries[0] as {\n kind?: unknown;\n parentSessionId?: unknown;\n metadata?: { parentSessionPath?: unknown };\n };\n if (only.kind !== \"header\") return false;\n // Sessions with lineage metadata are fully initialized — preserve them.\n if (only.parentSessionId || only.metadata?.parentSessionPath) return false;\n return true;\n } catch {\n return false;\n }\n}\n\nfunction parseSessionEntry(line: string): { type?: string; kind?: string } {\n return parseJsonValue(\n line,\n (value): value is { type?: string; kind?: string } => isRecord(value),\n (detail) => (detail === \"unexpected JSON shape\" ? \"expected a JSON object\" : detail),\n );\n}\n\nfunction getCurrentSessionPath(sessionDir: string): string | null {\n const pointerFile = join(sessionDir, \"current\");\n const filename = readTextFileIfExists(pointerFile)?.trim();\n if (!filename) return null;\n try {\n return resolveChildPath(sessionDir, filename);\n } catch {\n return null;\n }\n}\n\n/**\n * Try to resolve an existing current session file.\n * Returns null if no current pointer exists or the pointed file has no valid session header.\n */\nexport function tryResolveCurrentSession(sessionDir: string): string | null {\n const fullPath = getCurrentSessionPath(sessionDir);\n if (fullPath && isRegularSessionFile(fullPath) && hasSessionHeader(fullPath)) return fullPath;\n return null;\n}\n\n/**\n * Try to resolve an existing thread session file.\n * Returns the file path if found, or null if no valid thread session exists yet.\n */\nexport function tryResolveThreadSession(sessionFile: string): string | null {\n return isRegularSessionFile(sessionFile) && hasSessionHeader(sessionFile) ? sessionFile : null;\n}\n\n/**\n * Resolve the channel's current session file path.\n * Returns null if no channel session exists.\n */\nexport function resolveChannelSessionFile(channelDir: string): string | null {\n return tryResolveCurrentSession(officeSessionsDir(channelDir));\n}\n\n// Matches timestamped main session filenames; thread sessions use bare threadTs.\nconst MAIN_SESSION_FILENAME = /^\\d{4}-\\d{2}-\\d{2}T.+_[0-9a-f]{8}\\.jsonl$/i;\n\n/**\n * Resolve the main session file that was active when a thread was created.\n * Uses the thread's Slack timestamp to find the main session whose creation\n * time is the latest one at or before that moment — stable across rotations.\n * Falls back to resolveChannelSessionFile when threadTs is absent or unparseable.\n * Returns both path and session UUID so callers can store a UUID-stable reference.\n */\nexport function resolveParentSessionForThread(\n channelDir: string,\n threadTs: string | undefined,\n): ParentSessionRef | null {\n if (threadTs !== undefined) {\n const threadTimeMs = Number(threadTs) * 1000;\n if (Number.isFinite(threadTimeMs)) {\n const best = findMainSessionActiveAtTime(channelDir, threadTimeMs);\n if (best) return best;\n }\n }\n const path = resolveChannelSessionFile(channelDir);\n if (!path) return null;\n const id = readSessionHeaderSummary(path)?.id;\n return id ? { path, id } : null;\n}\n\nfunction findMainSessionActiveAtTime(\n channelDir: string,\n targetMs: number,\n): ParentSessionRef | null {\n const sessionDir = officeSessionsDir(channelDir);\n if (!existsSync(sessionDir)) return null;\n\n let best: ParentSessionRef | null = null;\n let bestCreatedMs = -Infinity;\n\n for (const name of readdirSync(sessionDir)) {\n if (!MAIN_SESSION_FILENAME.test(name)) continue;\n const filePath = join(sessionDir, name);\n const summary = readSessionHeaderSummary(filePath);\n if (!summary) continue;\n if (summary.timestampMs <= targetMs && summary.timestampMs > bestCreatedMs) {\n bestCreatedMs = summary.timestampMs;\n best = { path: filePath, id: summary.id };\n }\n }\n return best;\n}\n\nfunction readSessionHeaderSummary(filePath: string): { id: string; timestampMs: number } | null {\n try {\n const header = SessionStore.readHeader(filePath);\n if (!header) return null;\n const timestampMs = new Date(header.timestamp).getTime();\n return Number.isFinite(timestampMs) ? { id: header.id, timestampMs } : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Biweekly rotation clock for top-level shared sessions: a session file\n * rotates when its header timestamp falls in a different two-week bucket\n * (anchored to a fixed Sunday) than the given \"now\".\n */\n\nconst BIWEEKLY_ROTATION_ANCHOR = new Date(2026, 0, 4); // Sunday\nconst BIWEEKLY_MS = 14 * 24 * 60 * 60 * 1000;\n\nexport function shouldRotateTopLevelSession(sessionFile: string, now: Date): boolean {\n const timestamp = readSessionTimestamp(sessionFile);\n return timestamp !== null && biweeklyBucket(timestamp) !== biweeklyBucket(now);\n}\n\nfunction readSessionTimestamp(sessionFile: string): Date | null {\n const raw = readTextFileIfExists(sessionFile);\n if (raw === undefined) return null;\n const firstLine = raw.split(\"\\n\").find((line) => line.trim());\n if (!firstLine) return null;\n try {\n const header = parseJsonValue(\n firstLine,\n (value): value is { timestamp?: unknown; createdAt?: unknown } => isRecord(value),\n (detail) => (detail === \"unexpected JSON shape\" ? \"expected a JSON object\" : detail),\n );\n // v4 headers carry a numeric createdAt; legacy v3 headers a string timestamp.\n const value = typeof header.createdAt === \"number\" ? header.createdAt : header.timestamp;\n if (typeof value !== \"number\" && typeof value !== \"string\") return null;\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date : null;\n } catch {\n return null;\n }\n}\n\nfunction biweeklyBucket(date: Date): number {\n const weekStart = sundayStart(date).getTime();\n const anchor = sundayStart(BIWEEKLY_ROTATION_ANCHOR).getTime();\n return Math.floor((weekStart - anchor) / BIWEEKLY_MS);\n}\n\nfunction sundayStart(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay());\n}\n"]}
|
package/dist/sessions/types.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ export interface ResolveSessionKeyOptions {
|
|
|
23
23
|
persistentTopLevel?: boolean;
|
|
24
24
|
scopeDirectThreads?: boolean;
|
|
25
25
|
}
|
|
26
|
+
export interface ParentSessionRef {
|
|
27
|
+
path: string;
|
|
28
|
+
id: string;
|
|
29
|
+
}
|
|
26
30
|
export interface ThreadRootMessage {
|
|
27
31
|
text?: string;
|
|
28
32
|
userName?: string;
|
|
@@ -88,4 +92,9 @@ export interface ThreadBootstrapWaitOptions {
|
|
|
88
92
|
sleep?: (ms: number) => Promise<void>;
|
|
89
93
|
pollMs?: number;
|
|
90
94
|
}
|
|
95
|
+
export interface MigrateResult {
|
|
96
|
+
file: string;
|
|
97
|
+
status: "migrated" | "already-v4" | "skipped";
|
|
98
|
+
detail?: string;
|
|
99
|
+
}
|
|
91
100
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAI1D,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAID,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAID,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC7C;AAED,+DAA+D;AAC/D,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,sBAAsB,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf;AAID,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,8BAA8B;IAC7C,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2GAA2G;IAC3G,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,YAAY,CAAC;IAC7B,wGAAwG;IACxG,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,4BAA4B;IAC3C,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,6BAA6B;IAC5C,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,OAAO,CAAC;IAChC,eAAe,EAAE,MAAM,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ConversationKind } from \"../adapter.js\";\nimport type { SessionStore } from \"../harness/index.js\";\nimport type { ConversationLogMessage } from \"../types.js\";\n\n// ── session metadata ─────────────────────────────────────────────────────────\n\nexport interface MikanSessionHeader {\n type?: string;\n version?: number;\n id?: string;\n timestamp?: string;\n cwd?: string;\n parentSession?: string;\n /** Legacy platform-history marker; preserved in v4 header metadata. */\n source?: {\n kind?: string;\n file?: string;\n recentDays?: number;\n };\n}\n\n// ── session policy ───────────────────────────────────────────────────────────\n\nexport interface ResolveSessionKeyOptions {\n conversationId: string;\n conversationKind: ConversationKind;\n messageId: string;\n threadTs?: string;\n persistentTopLevel?: boolean;\n scopeDirectThreads?: boolean;\n}\n\n// ── session store ────────────────────────────────────────────────────────────\n\nexport interface ThreadRootMessage {\n text?: string;\n userName?: string;\n user?: string;\n loggedAt?: number;\n isMessagingBot?: boolean;\n}\n\nexport interface ResolvedSessionScope {\n sessionDir: string;\n contextFile: string;\n threadRootMessage: ThreadRootMessage | null;\n}\n\n/** One parsed log.jsonl entry with its original line index. */\nexport interface LogRecord {\n message: ConversationLogMessage;\n index: number;\n}\n\n// ── chat history sync ────────────────────────────────────────────────────────\n\n/** What one sync pass actually did — the inspectable result of a sync. */\nexport interface ChatSyncReport {\n /** Log messages appended to the session in this pass. */\n appended: number;\n /** The log message id recorded as the new sync watermark. */\n lastMessageId?: string;\n}\n\nexport interface ChatHistorySyncOptions {\n recentDays?: number;\n maxTopLevelMessages?: number;\n now?: () => Date;\n}\n\nexport interface ResolveChatSessionScopeOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n /** The triggering platform message ID. History is capped before this turn to avoid future queued turns. */\n currentMessageId?: string;\n}\n\nexport interface SyncChatSessionOptions {\n conversationDir: string;\n sessionKey: string;\n sessionManager: SessionStore;\n /** The triggering platform message ID. Sync is capped before this turn to avoid future queued turns. */\n currentMessageId?: string;\n}\n\nexport interface ResetChatSessionOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n}\n\nexport interface RegisterThreadSessionOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n}\n\nexport interface HasMaterializedSessionOptions {\n conversationDir: string;\n sessionKey: string;\n}\n\nexport interface ThreadBootstrapWaitOptions {\n parentSessionKey: string;\n sessionKey: string;\n hasThreadSession: () => boolean;\n isParentRunning: () => boolean;\n sleep?: (ms: number) => Promise<void>;\n pollMs?: number;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ConversationKind } from \"../adapter.js\";\nimport type { SessionStore } from \"../harness/index.js\";\nimport type { ConversationLogMessage } from \"../types.js\";\n\n// ── session metadata ─────────────────────────────────────────────────────────\n\nexport interface MikanSessionHeader {\n type?: string;\n version?: number;\n id?: string;\n timestamp?: string;\n cwd?: string;\n parentSession?: string;\n /** Legacy platform-history marker; preserved in v4 header metadata. */\n source?: {\n kind?: string;\n file?: string;\n recentDays?: number;\n };\n}\n\n// ── session policy ───────────────────────────────────────────────────────────\n\nexport interface ResolveSessionKeyOptions {\n conversationId: string;\n conversationKind: ConversationKind;\n messageId: string;\n threadTs?: string;\n persistentTopLevel?: boolean;\n scopeDirectThreads?: boolean;\n}\n\n// ── session store ────────────────────────────────────────────────────────────\n\nexport interface ParentSessionRef {\n path: string;\n id: string;\n}\n\nexport interface ThreadRootMessage {\n text?: string;\n userName?: string;\n user?: string;\n loggedAt?: number;\n isMessagingBot?: boolean;\n}\n\nexport interface ResolvedSessionScope {\n sessionDir: string;\n contextFile: string;\n threadRootMessage: ThreadRootMessage | null;\n}\n\n/** One parsed log.jsonl entry with its original line index. */\nexport interface LogRecord {\n message: ConversationLogMessage;\n index: number;\n}\n\n// ── chat history sync ────────────────────────────────────────────────────────\n\n/** What one sync pass actually did — the inspectable result of a sync. */\nexport interface ChatSyncReport {\n /** Log messages appended to the session in this pass. */\n appended: number;\n /** The log message id recorded as the new sync watermark. */\n lastMessageId?: string;\n}\n\nexport interface ChatHistorySyncOptions {\n recentDays?: number;\n maxTopLevelMessages?: number;\n now?: () => Date;\n}\n\nexport interface ResolveChatSessionScopeOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n /** The triggering platform message ID. History is capped before this turn to avoid future queued turns. */\n currentMessageId?: string;\n}\n\nexport interface SyncChatSessionOptions {\n conversationDir: string;\n sessionKey: string;\n sessionManager: SessionStore;\n /** The triggering platform message ID. Sync is capped before this turn to avoid future queued turns. */\n currentMessageId?: string;\n}\n\nexport interface ResetChatSessionOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n}\n\nexport interface RegisterThreadSessionOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n}\n\nexport interface HasMaterializedSessionOptions {\n conversationDir: string;\n sessionKey: string;\n}\n\nexport interface ThreadBootstrapWaitOptions {\n parentSessionKey: string;\n sessionKey: string;\n hasThreadSession: () => boolean;\n isParentRunning: () => boolean;\n sleep?: (ms: number) => Promise<void>;\n pollMs?: number;\n}\n\n// ── v3 migration ─────────────────────────────────────────────────────────────\n\nexport interface MigrateResult {\n file: string;\n status: \"migrated\" | \"already-v4\" | \"skipped\";\n detail?: string;\n}\n"]}
|
package/dist/tools/bash.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AASpD,QAAA,MAAM,UAAU;;;;EAQd,CAAC;AAOH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,GACvC,SAAS,CAAC,OAAO,UAAU,CAAC,CAiF9B"}
|
package/dist/tools/bash.js
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { Type } from "@sinclair/typebox";
|
|
3
3
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateTail, } from "@earendil-works/pi-agent-core";
|
|
4
|
-
/**
|
|
5
|
-
* Spill path for oversized bash output, inside the runtime workspace so the
|
|
6
|
-
* model can actually read the file it is pointed at (a host tmpdir path is a
|
|
7
|
-
* dead pointer inside sandbox containers — see src/sandbox/README.md).
|
|
8
|
-
*/
|
|
9
|
-
function getSpillPath(runtimeWorkspaceRoot) {
|
|
10
|
-
const id = randomBytes(8).toString("hex");
|
|
11
|
-
return `${runtimeWorkspaceRoot.replace(/\/+$/, "")}/.mikan/bash-output/${id}.log`;
|
|
12
|
-
}
|
|
13
4
|
const bashSchema = Type.Object({
|
|
14
5
|
label: Type.String({
|
|
15
6
|
description: "Brief description of what this command does (shown to user)",
|
|
@@ -41,7 +32,8 @@ export function createBashTool(executor, options) {
|
|
|
41
32
|
// where the model's follow-up read/bash actually runs.
|
|
42
33
|
if (totalBytes > DEFAULT_MAX_BYTES) {
|
|
43
34
|
const runtimeRoot = executor.getPathContext(options?.hostWorkspaceRoot ?? process.cwd()).runtimeWorkspaceRoot;
|
|
44
|
-
const
|
|
35
|
+
const id = randomBytes(8).toString("hex");
|
|
36
|
+
const spillPath = `${runtimeRoot.replace(/\/+$/, "")}/.mikan/bash-output/${id}.log`;
|
|
45
37
|
try {
|
|
46
38
|
await executor.writeFile(spillPath, output, { signal });
|
|
47
39
|
tempFilePath = spillPath;
|
package/dist/tools/bash.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EAEV,YAAY,GACb,MAAM,+BAA+B,CAAC;AAEvC
|
|
1
|
+
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { Executor } from \"../sandbox/index.js\";\nimport {\n DEFAULT_MAX_BYTES,\n DEFAULT_MAX_LINES,\n formatSize,\n type TruncationResult,\n truncateTail,\n} from \"@earendil-works/pi-agent-core\";\n\nconst bashSchema = Type.Object({\n label: Type.String({\n description: \"Brief description of what this command does (shown to user)\",\n }),\n command: Type.String({ description: \"Bash command to execute\" }),\n timeout: Type.Optional(\n Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" }),\n ),\n});\n\ninterface BashToolDetails {\n truncation?: TruncationResult;\n fullOutputPath?: string;\n}\n\nexport function createBashTool(\n executor: Executor,\n options?: { hostWorkspaceRoot?: string },\n): AgentTool<typeof bashSchema> {\n return {\n name: \"bash\",\n label: \"bash\",\n executionMode: \"sequential\",\n description: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n parameters: bashSchema,\n execute: async (\n _toolCallId: string,\n { command, timeout }: { label: string; command: string; timeout?: number },\n signal?: AbortSignal,\n ) => {\n let tempFilePath: string | undefined;\n\n const result = await executor.exec(command, { timeout, signal });\n let output = \"\";\n if (result.stdout) output += result.stdout;\n if (result.stderr) {\n if (output) output += \"\\n\";\n output += result.stderr;\n }\n\n const totalBytes = Buffer.byteLength(output, \"utf-8\");\n\n // Spill the full output into the runtime workspace when it exceeds the\n // limit; the executor owns transport, so the advertised path is valid\n // where the model's follow-up read/bash actually runs.\n if (totalBytes > DEFAULT_MAX_BYTES) {\n const runtimeRoot = executor.getPathContext(\n options?.hostWorkspaceRoot ?? process.cwd(),\n ).runtimeWorkspaceRoot;\n const id = randomBytes(8).toString(\"hex\");\n const spillPath = `${runtimeRoot.replace(/\\/+$/, \"\")}/.mikan/bash-output/${id}.log`;\n try {\n await executor.writeFile(spillPath, output, { signal });\n tempFilePath = spillPath;\n } catch {\n tempFilePath = undefined;\n }\n }\n\n // Apply tail truncation\n const truncation = truncateTail(output);\n let outputText = truncation.content || \"(no output)\";\n\n // Build details with truncation info\n let details: BashToolDetails | undefined;\n\n if (truncation.truncated) {\n details = {\n truncation,\n fullOutputPath: tempFilePath,\n };\n\n // Build actionable notice\n const startLine = truncation.totalLines - truncation.outputLines + 1;\n const endLine = truncation.totalLines;\n const fullOutputNote = tempFilePath\n ? ` Full output: ${tempFilePath}`\n : \" Full output unavailable (spill failed).\";\n\n if (truncation.lastLinePartial) {\n // Edge case: last line alone > 50KB\n const lastLineSize = formatSize(\n Buffer.byteLength(output.split(\"\\n\").pop() || \"\", \"utf-8\"),\n );\n outputText += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}).${fullOutputNote}]`;\n } else if (truncation.truncatedBy === \"lines\") {\n outputText += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}.${fullOutputNote}]`;\n } else {\n outputText += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit).${fullOutputNote}]`;\n }\n }\n\n if (result.code !== 0) {\n throw new Error(`${outputText}\\n\\nCommand exited with code ${result.code}`.trim());\n }\n\n return { content: [{ type: \"text\", text: outputText }], details };\n },\n };\n}\n"]}
|
package/dist/tools/read.js
CHANGED
|
@@ -88,8 +88,8 @@ export function createReadTool(executor) {
|
|
|
88
88
|
let details;
|
|
89
89
|
if (truncation.firstLineExceedsLimit) {
|
|
90
90
|
// Serve the line in byte-addressed slices rather than pointing at
|
|
91
|
-
// another tool: the caller may not hold one
|
|
92
|
-
//
|
|
91
|
+
// another tool: the caller may not hold one, and a dead end there
|
|
92
|
+
// costs a whole run.
|
|
93
93
|
const lineBuffer = Buffer.from(selectedContent.split("\n")[0] ?? "", "utf-8");
|
|
94
94
|
const start = Math.max(0, Math.min(byteOffset ?? 0, lineBuffer.length));
|
|
95
95
|
const slice = trimToCharBoundary(lineBuffer.subarray(start, start + DEFAULT_MAX_BYTES));
|
package/dist/tools/read.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport { Type } from \"@sinclair/typebox\";\nimport { extname } from \"node:path\";\nimport type { Executor } from \"../sandbox/index.js\";\nimport {\n DEFAULT_MAX_BYTES,\n DEFAULT_MAX_LINES,\n formatSize,\n type TruncationResult,\n truncateHead,\n} from \"@earendil-works/pi-agent-core\";\n\n/**\n * Map of file extensions to MIME types for common image formats\n */\nconst IMAGE_MIME_TYPES: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n};\n\n/**\n * Check if a file is an image based on its extension\n */\nfunction isImageFile(filePath: string): string | null {\n const ext = extname(filePath).toLowerCase();\n return IMAGE_MIME_TYPES[ext] || null;\n}\n\nconst readSchema = Type.Object({\n label: Type.String({\n description: \"Brief description of what you're reading and why (shown to user)\",\n }),\n path: Type.String({ description: \"Path to the file to read (relative or absolute)\" }),\n offset: Type.Optional(\n Type.Number({ description: \"Line number to start reading from (1-indexed)\" }),\n ),\n limit: Type.Optional(Type.Number({ description: \"Maximum number of lines to read\" })),\n byteOffset: Type.Optional(\n Type.Number({\n description:\n \"Byte offset into the first selected line. Use to page through a line too large to return whole.\",\n }),\n ),\n});\n\n/**\n * Trim bytes that would split a multi-byte UTF-8 sequence at the slice end, so\n * paging through a long line never emits a replacement character at the seam.\n */\nfunction trimToCharBoundary(buffer: Buffer): Buffer {\n for (let back = 1; back <= Math.min(4, buffer.length); back++) {\n const byte = buffer[buffer.length - back];\n if (byte === undefined || (byte & 0xc0) === 0x80) continue; // continuation byte; keep walking back\n const needed = byte < 0x80 ? 1 : byte < 0xe0 ? 2 : byte < 0xf0 ? 3 : 4;\n return back === needed ? buffer : buffer.subarray(0, buffer.length - back);\n }\n return buffer;\n}\n\ninterface ReadToolDetails {\n truncation?: TruncationResult;\n}\n\nexport function createReadTool(executor: Executor): AgentTool<typeof readSchema> {\n return {\n name: \"read\",\n label: \"read\",\n description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files, and byteOffset to page through a single line larger than the byte limit.`,\n parameters: readSchema,\n execute: async (\n _toolCallId: string,\n {\n path,\n offset,\n limit,\n byteOffset,\n }: {\n label: string;\n path: string;\n offset?: number;\n limit?: number;\n byteOffset?: number;\n },\n signal?: AbortSignal,\n ): Promise<{\n content: (TextContent | ImageContent)[];\n details: ReadToolDetails | undefined;\n }> => {\n const mimeType = isImageFile(path);\n\n if (mimeType) {\n // Binary content rides the executor's own transport, never shell argv.\n const base64 = await executor.readFileBase64(path, { signal });\n\n return {\n content: [\n { type: \"text\", text: `Read image file [${mimeType}]` },\n { type: \"image\", data: base64, mimeType },\n ],\n details: undefined,\n };\n }\n\n // One transport read; line selection is plain code, not shell strings.\n const fileText = await executor.readFile(path, { signal });\n const fileLines = fileText.split(\"\\n\");\n const totalFileLines = fileLines.length;\n\n // Apply offset if specified (1-indexed)\n const startLine = offset ? Math.max(1, offset) : 1;\n const startLineDisplay = startLine;\n\n // Check if offset is out of bounds\n if (startLine > totalFileLines) {\n throw new Error(`Offset ${offset} is beyond end of file (${totalFileLines} lines total)`);\n }\n\n let selectedContent = startLine === 1 ? fileText : fileLines.slice(startLine - 1).join(\"\\n\");\n let userLimitedLines: number | undefined;\n\n // Apply user limit if specified\n if (limit !== undefined) {\n const lines = selectedContent.split(\"\\n\");\n const endLine = Math.min(limit, lines.length);\n selectedContent = lines.slice(0, endLine).join(\"\\n\");\n userLimitedLines = endLine;\n }\n\n // Apply truncation (respects both line and byte limits)\n const truncation = truncateHead(selectedContent);\n\n let outputText: string;\n let details: ReadToolDetails | undefined;\n\n if (truncation.firstLineExceedsLimit) {\n // Serve the line in byte-addressed slices rather than pointing at\n // another tool: the caller may not hold one (Session Dream grants only\n // read/edit/write), and a dead end there costs a whole run.\n const lineBuffer = Buffer.from(selectedContent.split(\"\\n\")[0] ?? \"\", \"utf-8\");\n const start = Math.max(0, Math.min(byteOffset ?? 0, lineBuffer.length));\n const slice = trimToCharBoundary(lineBuffer.subarray(start, start + DEFAULT_MAX_BYTES));\n const end = start + slice.length;\n\n outputText = slice.toString(\"utf-8\");\n outputText += `\\n\\n[Line ${startLineDisplay} is ${formatSize(lineBuffer.length)}; showing bytes ${start}-${end}.`;\n outputText +=\n end < lineBuffer.length ? ` Use byteOffset=${end} to continue]` : \" End of line reached]\";\n details = { truncation };\n } else if (truncation.truncated) {\n // Truncation occurred - build actionable notice\n const endLineDisplay = startLineDisplay + truncation.outputLines - 1;\n const nextOffset = endLineDisplay + 1;\n\n outputText = truncation.content;\n\n if (truncation.truncatedBy === \"lines\") {\n outputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue]`;\n } else {\n outputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue]`;\n }\n details = { truncation };\n } else if (userLimitedLines !== undefined) {\n // User specified limit, check if there's more content\n const linesFromStart = startLine - 1 + userLimitedLines;\n if (linesFromStart < totalFileLines) {\n const remaining = totalFileLines - linesFromStart;\n const nextOffset = startLine + userLimitedLines;\n\n outputText = truncation.content;\n outputText += `\\n\\n[${remaining} more lines in file. Use offset=${nextOffset} to continue]`;\n } else {\n outputText = truncation.content;\n }\n } else {\n // No truncation, no user limit exceeded\n outputText = truncation.content;\n }\n\n return {\n content: [{ type: \"text\", text: outputText }],\n details,\n };\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport { Type } from \"@sinclair/typebox\";\nimport { extname } from \"node:path\";\nimport type { Executor } from \"../sandbox/index.js\";\nimport {\n DEFAULT_MAX_BYTES,\n DEFAULT_MAX_LINES,\n formatSize,\n type TruncationResult,\n truncateHead,\n} from \"@earendil-works/pi-agent-core\";\n\n/**\n * Map of file extensions to MIME types for common image formats\n */\nconst IMAGE_MIME_TYPES: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n};\n\n/**\n * Check if a file is an image based on its extension\n */\nfunction isImageFile(filePath: string): string | null {\n const ext = extname(filePath).toLowerCase();\n return IMAGE_MIME_TYPES[ext] || null;\n}\n\nconst readSchema = Type.Object({\n label: Type.String({\n description: \"Brief description of what you're reading and why (shown to user)\",\n }),\n path: Type.String({ description: \"Path to the file to read (relative or absolute)\" }),\n offset: Type.Optional(\n Type.Number({ description: \"Line number to start reading from (1-indexed)\" }),\n ),\n limit: Type.Optional(Type.Number({ description: \"Maximum number of lines to read\" })),\n byteOffset: Type.Optional(\n Type.Number({\n description:\n \"Byte offset into the first selected line. Use to page through a line too large to return whole.\",\n }),\n ),\n});\n\n/**\n * Trim bytes that would split a multi-byte UTF-8 sequence at the slice end, so\n * paging through a long line never emits a replacement character at the seam.\n */\nfunction trimToCharBoundary(buffer: Buffer): Buffer {\n for (let back = 1; back <= Math.min(4, buffer.length); back++) {\n const byte = buffer[buffer.length - back];\n if (byte === undefined || (byte & 0xc0) === 0x80) continue; // continuation byte; keep walking back\n const needed = byte < 0x80 ? 1 : byte < 0xe0 ? 2 : byte < 0xf0 ? 3 : 4;\n return back === needed ? buffer : buffer.subarray(0, buffer.length - back);\n }\n return buffer;\n}\n\ninterface ReadToolDetails {\n truncation?: TruncationResult;\n}\n\nexport function createReadTool(executor: Executor): AgentTool<typeof readSchema> {\n return {\n name: \"read\",\n label: \"read\",\n description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files, and byteOffset to page through a single line larger than the byte limit.`,\n parameters: readSchema,\n execute: async (\n _toolCallId: string,\n {\n path,\n offset,\n limit,\n byteOffset,\n }: {\n label: string;\n path: string;\n offset?: number;\n limit?: number;\n byteOffset?: number;\n },\n signal?: AbortSignal,\n ): Promise<{\n content: (TextContent | ImageContent)[];\n details: ReadToolDetails | undefined;\n }> => {\n const mimeType = isImageFile(path);\n\n if (mimeType) {\n // Binary content rides the executor's own transport, never shell argv.\n const base64 = await executor.readFileBase64(path, { signal });\n\n return {\n content: [\n { type: \"text\", text: `Read image file [${mimeType}]` },\n { type: \"image\", data: base64, mimeType },\n ],\n details: undefined,\n };\n }\n\n // One transport read; line selection is plain code, not shell strings.\n const fileText = await executor.readFile(path, { signal });\n const fileLines = fileText.split(\"\\n\");\n const totalFileLines = fileLines.length;\n\n // Apply offset if specified (1-indexed)\n const startLine = offset ? Math.max(1, offset) : 1;\n const startLineDisplay = startLine;\n\n // Check if offset is out of bounds\n if (startLine > totalFileLines) {\n throw new Error(`Offset ${offset} is beyond end of file (${totalFileLines} lines total)`);\n }\n\n let selectedContent = startLine === 1 ? fileText : fileLines.slice(startLine - 1).join(\"\\n\");\n let userLimitedLines: number | undefined;\n\n // Apply user limit if specified\n if (limit !== undefined) {\n const lines = selectedContent.split(\"\\n\");\n const endLine = Math.min(limit, lines.length);\n selectedContent = lines.slice(0, endLine).join(\"\\n\");\n userLimitedLines = endLine;\n }\n\n // Apply truncation (respects both line and byte limits)\n const truncation = truncateHead(selectedContent);\n\n let outputText: string;\n let details: ReadToolDetails | undefined;\n\n if (truncation.firstLineExceedsLimit) {\n // Serve the line in byte-addressed slices rather than pointing at\n // another tool: the caller may not hold one, and a dead end there\n // costs a whole run.\n const lineBuffer = Buffer.from(selectedContent.split(\"\\n\")[0] ?? \"\", \"utf-8\");\n const start = Math.max(0, Math.min(byteOffset ?? 0, lineBuffer.length));\n const slice = trimToCharBoundary(lineBuffer.subarray(start, start + DEFAULT_MAX_BYTES));\n const end = start + slice.length;\n\n outputText = slice.toString(\"utf-8\");\n outputText += `\\n\\n[Line ${startLineDisplay} is ${formatSize(lineBuffer.length)}; showing bytes ${start}-${end}.`;\n outputText +=\n end < lineBuffer.length ? ` Use byteOffset=${end} to continue]` : \" End of line reached]\";\n details = { truncation };\n } else if (truncation.truncated) {\n // Truncation occurred - build actionable notice\n const endLineDisplay = startLineDisplay + truncation.outputLines - 1;\n const nextOffset = endLineDisplay + 1;\n\n outputText = truncation.content;\n\n if (truncation.truncatedBy === \"lines\") {\n outputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue]`;\n } else {\n outputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue]`;\n }\n details = { truncation };\n } else if (userLimitedLines !== undefined) {\n // User specified limit, check if there's more content\n const linesFromStart = startLine - 1 + userLimitedLines;\n if (linesFromStart < totalFileLines) {\n const remaining = totalFileLines - linesFromStart;\n const nextOffset = startLine + userLimitedLines;\n\n outputText = truncation.content;\n outputText += `\\n\\n[${remaining} more lines in file. Use offset=${nextOffset} to continue]`;\n } else {\n outputText = truncation.content;\n }\n } else {\n // No truncation, no user limit exceeded\n outputText = truncation.content;\n }\n\n return {\n content: [{ type: \"text\", text: outputText }],\n details,\n };\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/tools/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAkB,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAG5F,QAAA,MAAM,aAAa;;;;EAcjB,CAAC;AAQH,UAAU,kBAAkB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,UAAU,qBAAqB;IAC7B,OAAO,EAAE,aAAa,CAAC;IACvB,kBAAkB,CAAC,EAAE,IAAI,CAAC,yBAAyB,EAAE,gBAAgB,GAAG,WAAW,CAAC,CAAC;CACtF;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,qBAAqB,GAAG;IACpE,IAAI,EAAE,SAAS,CAAC,OAAO,aAAa,CAAC,CAAC;IACtC,iBAAiB,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC1D,
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/tools/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAkB,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAG5F,QAAA,MAAM,aAAa;;;;EAcjB,CAAC;AAQH,UAAU,kBAAkB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,UAAU,qBAAqB;IAC7B,OAAO,EAAE,aAAa,CAAC;IACvB,kBAAkB,CAAC,EAAE,IAAI,CAAC,yBAAyB,EAAE,gBAAgB,GAAG,WAAW,CAAC,CAAC;CACtF;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,qBAAqB,GAAG;IACpE,IAAI,EAAE,SAAS,CAAC,OAAO,aAAa,CAAC,CAAC;IACtC,iBAAiB,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC1D,CA+CA"}
|