@geminixiang/mikan 0.3.2 → 0.4.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/adapter.d.ts +1 -138
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +1 -4
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +25 -33
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +28 -0
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/discord/types.d.ts +6 -0
- package/dist/adapters/discord/types.d.ts.map +1 -0
- package/dist/adapters/discord/types.js +2 -0
- package/dist/adapters/discord/types.js.map +1 -0
- package/dist/adapters/intake.d.ts +11 -0
- package/dist/adapters/intake.d.ts.map +1 -0
- package/dist/adapters/intake.js +42 -0
- package/dist/adapters/intake.js.map +1 -0
- package/dist/adapters/shared.d.ts +7 -31
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/shared.js +18 -2
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +14 -33
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +148 -116
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/context.d.ts +3 -4
- package/dist/adapters/slack/context.d.ts.map +1 -1
- package/dist/adapters/slack/context.js +97 -14
- package/dist/adapters/slack/context.js.map +1 -1
- package/dist/adapters/slack/session.d.ts +5 -20
- package/dist/adapters/slack/session.d.ts.map +1 -1
- package/dist/adapters/slack/session.js.map +1 -1
- package/dist/adapters/slack/types.d.ts +84 -0
- package/dist/adapters/slack/types.d.ts.map +1 -0
- package/dist/adapters/slack/types.js +2 -0
- package/dist/adapters/slack/types.js.map +1 -0
- package/dist/adapters/streaming.d.ts +18 -0
- package/dist/adapters/streaming.d.ts.map +1 -0
- package/dist/adapters/streaming.js +44 -0
- package/dist/adapters/streaming.js.map +1 -0
- package/dist/adapters/telegram/bot.d.ts +1 -4
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +32 -39
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +33 -0
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/adapters/telegram/types.d.ts +6 -0
- package/dist/adapters/telegram/types.d.ts.map +1 -0
- package/dist/adapters/telegram/types.js +2 -0
- package/dist/adapters/telegram/types.js.map +1 -0
- package/dist/adapters/types.d.ts +58 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/agent.d.ts +4 -16
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +27 -20
- package/dist/agent.js.map +1 -1
- package/dist/commands/admin.d.ts.map +1 -1
- package/dist/commands/admin.js +1 -1
- package/dist/commands/admin.js.map +1 -1
- package/dist/commands/auto-reply.d.ts.map +1 -1
- package/dist/commands/auto-reply.js +1 -8
- package/dist/commands/auto-reply.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +3 -3
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/model.d.ts +5 -8
- package/dist/commands/model.d.ts.map +1 -1
- package/dist/commands/model.js +15 -20
- package/dist/commands/model.js.map +1 -1
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +5 -10
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/parse.d.ts.map +1 -1
- package/dist/commands/parse.js +1 -4
- package/dist/commands/parse.js.map +1 -1
- package/dist/commands/registry.d.ts +1 -0
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +23 -0
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/sandbox.d.ts +2 -5
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +11 -16
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/commands/session-view.d.ts.map +1 -1
- package/dist/commands/session-view.js +10 -15
- package/dist/commands/session-view.js.map +1 -1
- package/dist/commands/types.d.ts +11 -2
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js.map +1 -1
- package/dist/config.d.ts +6 -28
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +43 -41
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +1 -15
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js.map +1 -1
- package/dist/events.d.ts +3 -44
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +2 -9
- package/dist/events.js.map +1 -1
- package/dist/execution-resolver.d.ts +3 -7
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +8 -8
- package/dist/execution-resolver.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/log.d.ts +2 -6
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +1 -37
- package/dist/log.js.map +1 -1
- package/dist/main.d.ts +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +16 -16
- package/dist/main.js.map +1 -1
- package/dist/observability/instrument.d.ts.map +1 -0
- package/dist/{instrument.js → observability/instrument.js} +2 -2
- package/dist/observability/instrument.js.map +1 -0
- package/dist/{sentry.d.ts → observability/sentry.d.ts} +2 -30
- package/dist/observability/sentry.d.ts.map +1 -0
- package/dist/observability/sentry.js.map +1 -0
- package/dist/observability/types.d.ts +31 -0
- package/dist/observability/types.d.ts.map +1 -0
- package/dist/observability/types.js +2 -0
- package/dist/observability/types.js.map +1 -0
- package/dist/{ui-copy.d.ts → platform-messages.d.ts} +1 -1
- package/dist/platform-messages.d.ts.map +1 -0
- package/dist/{ui-copy.js → platform-messages.js} +1 -1
- package/dist/platform-messages.js.map +1 -0
- package/dist/portal-shell.d.ts +2 -28
- package/dist/portal-shell.d.ts.map +1 -1
- package/dist/portal-shell.js +2 -2
- package/dist/portal-shell.js.map +1 -1
- package/dist/provisioner.d.ts +2 -23
- package/dist/provisioner.d.ts.map +1 -1
- package/dist/provisioner.js +1 -1
- package/dist/provisioner.js.map +1 -1
- package/dist/runtime/conversation-orchestrator.d.ts +4 -19
- package/dist/runtime/conversation-orchestrator.d.ts.map +1 -1
- package/dist/runtime/conversation-orchestrator.js +3 -3
- package/dist/runtime/conversation-orchestrator.js.map +1 -1
- package/dist/runtime/session-runtime.d.ts +2 -23
- package/dist/runtime/session-runtime.d.ts.map +1 -1
- package/dist/runtime/session-runtime.js +7 -9
- package/dist/runtime/session-runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +35 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +1 -1
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +1 -4
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sessions/chat-session-manager.d.ts +2 -46
- package/dist/sessions/chat-session-manager.d.ts.map +1 -1
- package/dist/sessions/chat-session-manager.js +12 -40
- package/dist/sessions/chat-session-manager.js.map +1 -1
- package/dist/sessions/metadata.d.ts +1 -13
- package/dist/sessions/metadata.d.ts.map +1 -1
- package/dist/sessions/metadata.js.map +1 -1
- package/dist/sessions/policy.d.ts +3 -10
- package/dist/sessions/policy.d.ts.map +1 -1
- package/dist/sessions/policy.js.map +1 -1
- package/dist/sessions/store.d.ts +1 -12
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +4 -7
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +76 -0
- package/dist/sessions/types.d.ts.map +1 -0
- package/dist/sessions/types.js +2 -0
- package/dist/sessions/types.js.map +1 -0
- package/dist/store.d.ts +2 -19
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +1 -1
- package/dist/store.js.map +1 -1
- package/dist/tools/event.d.ts +30 -36
- package/dist/tools/event.d.ts.map +1 -1
- package/dist/tools/event.js +207 -26
- package/dist/tools/event.js.map +1 -1
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/sandbox.d.ts.map +1 -1
- package/dist/tools/sandbox.js +1 -1
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/tools/truncate.d.ts +2 -26
- package/dist/tools/truncate.d.ts.map +1 -1
- package/dist/tools/truncate.js.map +1 -1
- package/dist/tools/types.d.ts +54 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/trigger.d.ts +2 -13
- package/dist/trigger.d.ts.map +1 -1
- package/dist/trigger.js.map +1 -1
- package/dist/types.d.ts +307 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/date.d.ts +10 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +23 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/file-guards.d.ts.map +1 -0
- package/dist/utils/file-guards.js.map +1 -0
- package/dist/utils/fs-atomic.d.ts.map +1 -0
- package/dist/utils/fs-atomic.js.map +1 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/http-body.d.ts +10 -0
- package/dist/utils/http-body.d.ts.map +1 -0
- package/dist/utils/http-body.js +34 -0
- package/dist/utils/http-body.js.map +1 -0
- package/dist/vault/index.d.ts +34 -0
- package/dist/vault/index.d.ts.map +1 -0
- package/dist/{vault.js → vault/index.js} +4 -4
- package/dist/vault/index.js.map +1 -0
- package/dist/{vault-routing.d.ts → vault/routing.d.ts} +2 -2
- package/dist/vault/routing.d.ts.map +1 -0
- package/dist/{vault-routing.js → vault/routing.js} +2 -2
- package/dist/vault/routing.js.map +1 -0
- package/dist/{vault.d.ts → vault/types.d.ts} +3 -34
- package/dist/vault/types.d.ts.map +1 -0
- package/dist/vault/types.js +2 -0
- package/dist/vault/types.js.map +1 -0
- package/dist/web/admin/portal.d.ts +5 -0
- package/dist/web/admin/portal.d.ts.map +1 -0
- package/dist/{admin → web/admin}/portal.js +140 -52
- package/dist/web/admin/portal.js.map +1 -0
- package/dist/web/admin/store.d.ts +13 -0
- package/dist/web/admin/store.d.ts.map +1 -0
- package/dist/web/admin/store.js +23 -0
- package/dist/web/admin/store.js.map +1 -0
- package/dist/web/admin/types.d.ts +28 -0
- package/dist/web/admin/types.d.ts.map +1 -0
- package/dist/web/admin/types.js +2 -0
- package/dist/web/admin/types.js.map +1 -0
- package/dist/web/login/oauth.d.ts +6 -0
- package/dist/web/login/oauth.d.ts.map +1 -0
- package/dist/{login/index.js → web/login/oauth.js} +33 -30
- package/dist/web/login/oauth.js.map +1 -0
- package/dist/{login → web/login}/portal.d.ts +5 -5
- package/dist/web/login/portal.d.ts.map +1 -0
- package/dist/{login → web/login}/portal.js +16 -35
- package/dist/web/login/portal.js.map +1 -0
- package/dist/web/login/store.d.ts +12 -0
- package/dist/web/login/store.d.ts.map +1 -0
- package/dist/web/login/store.js +28 -0
- package/dist/web/login/store.js.map +1 -0
- package/dist/web/login/types.d.ts +50 -0
- package/dist/web/login/types.d.ts.map +1 -0
- package/dist/web/login/types.js +2 -0
- package/dist/web/login/types.js.map +1 -0
- package/dist/web/session-view/command.d.ts +4 -0
- package/dist/web/session-view/command.d.ts.map +1 -0
- package/dist/{session-view → web/session-view}/command.js +1 -1
- package/dist/web/session-view/command.js.map +1 -0
- package/dist/{session-view → web/session-view}/portal.d.ts +2 -5
- package/dist/web/session-view/portal.d.ts.map +1 -0
- package/dist/{session-view → web/session-view}/portal.js +5 -5
- package/dist/web/session-view/portal.js.map +1 -0
- package/dist/web/session-view/service.d.ts +6 -0
- package/dist/web/session-view/service.d.ts.map +1 -0
- package/dist/{session-view → web/session-view}/service.js +6 -36
- package/dist/web/session-view/service.js.map +1 -0
- package/dist/web/session-view/store.d.ts +8 -0
- package/dist/web/session-view/store.d.ts.map +1 -0
- package/dist/web/session-view/store.js +20 -0
- package/dist/web/session-view/store.js.map +1 -0
- package/dist/{session-view/service.d.ts → web/session-view/types.d.ts} +20 -4
- package/dist/web/session-view/types.d.ts.map +1 -0
- package/dist/web/session-view/types.js +2 -0
- package/dist/web/session-view/types.js.map +1 -0
- package/dist/web/token-store.d.ts +19 -0
- package/dist/web/token-store.d.ts.map +1 -0
- package/dist/web/token-store.js +45 -0
- package/dist/web/token-store.js.map +1 -0
- package/dist/web/types.d.ts +5 -0
- package/dist/web/types.d.ts.map +1 -0
- package/dist/web/types.js +2 -0
- package/dist/web/types.js.map +1 -0
- package/package.json +1 -1
- package/dist/adapters/discord/index.d.ts +0 -3
- package/dist/adapters/discord/index.d.ts.map +0 -1
- package/dist/adapters/discord/index.js +0 -3
- package/dist/adapters/discord/index.js.map +0 -1
- package/dist/adapters/slack/index.d.ts +0 -3
- package/dist/adapters/slack/index.d.ts.map +0 -1
- package/dist/adapters/slack/index.js +0 -3
- package/dist/adapters/slack/index.js.map +0 -1
- package/dist/adapters/slack/thread-manager.d.ts +0 -19
- package/dist/adapters/slack/thread-manager.d.ts.map +0 -1
- package/dist/adapters/slack/thread-manager.js +0 -11
- package/dist/adapters/slack/thread-manager.js.map +0 -1
- package/dist/adapters/telegram/index.d.ts +0 -3
- package/dist/adapters/telegram/index.d.ts.map +0 -1
- package/dist/adapters/telegram/index.js +0 -3
- package/dist/adapters/telegram/index.js.map +0 -1
- package/dist/admin/portal.d.ts +0 -27
- package/dist/admin/portal.d.ts.map +0 -1
- package/dist/admin/portal.js.map +0 -1
- package/dist/admin/store.d.ts +0 -22
- package/dist/admin/store.d.ts.map +0 -1
- package/dist/admin/store.js +0 -39
- package/dist/admin/store.js.map +0 -1
- package/dist/commands/index.d.ts +0 -5
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/index.js +0 -20
- package/dist/commands/index.js.map +0 -1
- package/dist/env.d.ts.map +0 -1
- package/dist/env.js.map +0 -1
- package/dist/file-guards.d.ts.map +0 -1
- package/dist/file-guards.js.map +0 -1
- package/dist/fs-atomic.d.ts.map +0 -1
- package/dist/fs-atomic.js.map +0 -1
- package/dist/html.d.ts.map +0 -1
- package/dist/html.js.map +0 -1
- package/dist/instrument.d.ts.map +0 -1
- package/dist/instrument.js.map +0 -1
- package/dist/login/index.d.ts +0 -43
- package/dist/login/index.d.ts.map +0 -1
- package/dist/login/index.js.map +0 -1
- package/dist/login/portal.d.ts.map +0 -1
- package/dist/login/portal.js.map +0 -1
- package/dist/login/store.d.ts +0 -26
- package/dist/login/store.d.ts.map +0 -1
- package/dist/login/store.js +0 -56
- package/dist/login/store.js.map +0 -1
- package/dist/runtime/index.d.ts +0 -2
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js +0 -2
- package/dist/runtime/index.js.map +0 -1
- package/dist/sentry.d.ts.map +0 -1
- package/dist/sentry.js.map +0 -1
- package/dist/session-view/command.d.ts +0 -5
- package/dist/session-view/command.d.ts.map +0 -1
- package/dist/session-view/command.js.map +0 -1
- package/dist/session-view/portal.d.ts.map +0 -1
- package/dist/session-view/portal.js.map +0 -1
- package/dist/session-view/service.d.ts.map +0 -1
- package/dist/session-view/service.js.map +0 -1
- package/dist/session-view/store.d.ts +0 -18
- package/dist/session-view/store.d.ts.map +0 -1
- package/dist/session-view/store.js +0 -36
- package/dist/session-view/store.js.map +0 -1
- package/dist/ui-copy.d.ts.map +0 -1
- package/dist/ui-copy.js.map +0 -1
- package/dist/vault-routing.d.ts.map +0 -1
- package/dist/vault-routing.js.map +0 -1
- package/dist/vault.d.ts.map +0 -1
- package/dist/vault.js.map +0 -1
- /package/dist/{instrument.d.ts → observability/instrument.d.ts} +0 -0
- /package/dist/{sentry.js → observability/sentry.js} +0 -0
- /package/dist/{env.d.ts → utils/env.d.ts} +0 -0
- /package/dist/{env.js → utils/env.js} +0 -0
- /package/dist/{file-guards.d.ts → utils/file-guards.d.ts} +0 -0
- /package/dist/{file-guards.js → utils/file-guards.js} +0 -0
- /package/dist/{fs-atomic.d.ts → utils/fs-atomic.d.ts} +0 -0
- /package/dist/{fs-atomic.js → utils/fs-atomic.js} +0 -0
- /package/dist/{html.d.ts → utils/html.d.ts} +0 -0
- /package/dist/{html.js → utils/html.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-resolver.d.ts","sourceRoot":"","sources":["../src/execution-resolver.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,sBAAsB,EAAuB,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAkB,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEvF,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"execution-resolver.d.ts","sourceRoot":"","sources":["../src/execution-resolver.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,sBAAsB,EAAuB,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAkB,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEvF,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGnG,YAAY,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAExE,wBAAgB,kCAAkC,CAChD,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,cAAc,EAAE,MAAM,GACrB,uBAAuB,CAczB;AAyBD,qBAAa,sBAAsB;IAI/B,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,WAAW,CAAC;IACpB,OAAO,CAAC,YAAY,CAAC;IANvB,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAqB;IAE7D,YACU,UAAU,EAAE,aAAa,EACzB,YAAY,EAAE,YAAY,EAC1B,WAAW,CAAC,EAAE,sBAAsB,YAAA,EACpC,YAAY,CAAC,EAAE,MAAM,YAAA,EAC3B;IAEE,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAatD;IAED,OAAO,CAAC,wBAAwB;IAehC,OAAO,CAAC,oBAAoB;IAgB5B,OAAO,CAAC,wBAAwB;IA4ChC,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,uBAAuB;CAsBhC","sourcesContent":["import { existsSync } from \"fs\";\nimport { join } from \"path\";\nimport { loadGlobalSettings, resolveConversationSettings } from \"./config.js\";\nimport { ensureDirExists, isRecord, readJsonFileIfExists } from \"./utils/file-guards.js\";\nimport { DockerContainerManager, type ContainerMount } from \"./provisioner.js\";\nimport { createExecutor, type Executor, type SandboxConfig } from \"./sandbox/index.js\";\nimport { reportUserFacingError } from \"./observability/sentry.js\";\nimport { normalizeSharedVaultName, type ResolvedVault, type VaultManager } from \"./vault/index.js\";\nimport { resolveActorVaultKey } from \"./vault/routing.js\";\n\nexport type { ActorContext, ImageWorkspaceMountMode } from \"./types.js\";\nimport type { ActorContext, ImageWorkspaceMountMode } from \"./types.js\";\n\nexport function readConversationWorkspaceMountMode(\n workspaceDir: string | undefined,\n conversationId: string,\n): ImageWorkspaceMountMode {\n const globalDefault = readGlobalWorkspaceMountMode();\n if (!workspaceDir) {\n return globalDefault;\n }\n\n const conversationDir = join(workspaceDir, conversationId);\n try {\n return resolveConversationSettings(conversationDir).sandboxImageWorkspaceMount ?? globalDefault;\n } catch {\n const conversationSettingsPath = join(conversationDir, \"settings.json\");\n const raw = readConversationSettingsFallback(conversationSettingsPath);\n return raw?.sandbox?.image?.workspaceMount ?? globalDefault;\n }\n}\n\nfunction readGlobalWorkspaceMountMode(): ImageWorkspaceMountMode {\n try {\n return loadGlobalSettings().sandboxImageWorkspaceMount ?? \"private\";\n } catch {\n return \"private\";\n }\n}\n\nfunction readConversationSettingsFallback(\n settingsPath: string,\n): { sandbox?: { image?: { workspaceMount?: ImageWorkspaceMountMode } } } | undefined {\n try {\n return readJsonFileIfExists(\n settingsPath,\n (value): value is { sandbox?: { image?: { workspaceMount?: ImageWorkspaceMountMode } } } =>\n isRecord(value),\n () => \"Ignoring malformed conversation settings file while resolving workspace mount\",\n );\n } catch {\n return undefined;\n }\n}\n\nexport class ActorExecutionResolver {\n private readonly ensuredConversationDirs = new Set<string>();\n\n constructor(\n private baseConfig: SandboxConfig,\n private vaultManager: VaultManager,\n private provisioner?: DockerContainerManager,\n private workspaceDir?: string,\n ) {}\n\n async resolve(context: ActorContext): Promise<Executor> {\n const vaultKey = resolveActorVaultKey(this.baseConfig, context.userId, context.conversationId);\n this.ensureDefaultSharedVault(vaultKey);\n\n const vault = this.vaultManager.resolve(vaultKey);\n const config = this.resolveSandboxConfig(vaultKey);\n const env =\n config.type !== \"host\" && vault && Object.keys(vault.env).length > 0 ? vault.env : undefined;\n return createExecutor(\n config,\n env,\n this.buildEnsureReadyCallback(vaultKey, context.conversationId, config, vault),\n );\n }\n\n private ensureDefaultSharedVault(vaultKey: string): void {\n if (this.baseConfig.type !== \"image\" && this.baseConfig.type !== \"cloudflare\") return;\n if (this.vaultManager.hasEntry(vaultKey)) return;\n\n let profile: string | undefined;\n try {\n profile = loadGlobalSettings().defaultSharedVault;\n } catch {\n return;\n }\n if (!profile || normalizeSharedVaultName(profile) !== profile) return;\n\n this.vaultManager.copySharedVaultTo(profile, vaultKey);\n }\n\n private resolveSandboxConfig(vaultKey: string): SandboxConfig {\n const config = this.vaultManager.getSandboxConfig(vaultKey, this.baseConfig);\n if (this.baseConfig.type !== \"image\") {\n return config;\n }\n\n if (config.type === \"container\") {\n return config;\n }\n\n return {\n type: \"container\",\n container: DockerContainerManager.containerName(vaultKey),\n };\n }\n\n private buildEnsureReadyCallback(\n vaultKey: string,\n conversationId: string,\n config: SandboxConfig,\n vault?: ResolvedVault,\n ): (() => Promise<void>) | undefined {\n if (this.baseConfig.type !== \"image\" || config.type !== \"container\") {\n return undefined;\n }\n\n return async () => {\n const expected = config.container || DockerContainerManager.containerName(vaultKey);\n let actual: string | undefined;\n try {\n actual = await this.provisioner?.provision(vaultKey, {\n containerName: expected,\n mounts: this.resolveMounts(conversationId, vault),\n conversationId,\n });\n } catch (err) {\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"sandbox_provision\",\n operation: \"ensure_image_container_ready\",\n severity: \"error\",\n context: {\n sandboxType: \"image\",\n resolvedSandboxType: config.type,\n conversationId,\n vaultKey,\n expectedContainer: expected,\n hasVault: Boolean(vault),\n },\n });\n throw err;\n }\n if (actual && actual !== expected) {\n throw new Error(\n `Provisioner returned container \"${actual}\" for container key \"${vaultKey}\", expected \"${expected}\"`,\n );\n }\n };\n }\n\n private resolveMounts(conversationId: string, vault?: ResolvedVault): ContainerMount[] {\n const mountsByTarget = new Map<string, ContainerMount>();\n for (const mount of this.buildImageSandboxMounts(conversationId)) {\n mountsByTarget.set(mount.target, mount);\n }\n for (const mount of vault?.mounts ?? []) {\n if (!existsSync(mount.source)) {\n reportUserFacingError(new Error(\"Vault mount source is missing\"), {\n domain: \"sandbox\",\n surface: \"vault_injection\",\n operation: \"resolve_mounts\",\n severity: \"warning\",\n context: {\n sandboxType: \"image\",\n conversationId,\n target: mount.target,\n hasVault: Boolean(vault),\n },\n });\n continue;\n }\n mountsByTarget.set(mount.target, { source: mount.source, target: mount.target });\n }\n return [...mountsByTarget.values()];\n }\n\n private buildImageSandboxMounts(conversationId: string): ContainerMount[] {\n if (!this.workspaceDir) {\n return [];\n }\n\n if (readConversationWorkspaceMountMode(this.workspaceDir, conversationId) === \"full\") {\n return [{ source: this.workspaceDir, target: \"/workspace\" }];\n }\n\n const conversationDir = join(this.workspaceDir, conversationId);\n if (!this.ensuredConversationDirs.has(conversationId)) {\n ensureDirExists(conversationDir);\n this.ensuredConversationDirs.add(conversationId);\n }\n\n return [\n { source: join(this.workspaceDir, \"MEMORY.md\"), target: \"/workspace/MEMORY.md\" },\n { source: join(this.workspaceDir, \"skills\"), target: \"/workspace/skills\" },\n { source: join(this.workspaceDir, \"events\"), target: \"/workspace/events\" },\n { source: conversationDir, target: `/workspace/${conversationId}` },\n ];\n }\n}\n"]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { existsSync } from "fs";
|
|
2
2
|
import { join } from "path";
|
|
3
|
-
import {
|
|
4
|
-
import { ensureDirExists, isRecord, readJsonFileIfExists } from "./file-guards.js";
|
|
3
|
+
import { loadGlobalSettings, resolveConversationSettings } from "./config.js";
|
|
4
|
+
import { ensureDirExists, isRecord, readJsonFileIfExists } from "./utils/file-guards.js";
|
|
5
5
|
import { DockerContainerManager } from "./provisioner.js";
|
|
6
6
|
import { createExecutor } from "./sandbox/index.js";
|
|
7
|
-
import { reportUserFacingError } from "./sentry.js";
|
|
8
|
-
import { normalizeSharedVaultName } from "./vault.js";
|
|
9
|
-
import { resolveActorVaultKey } from "./vault
|
|
7
|
+
import { reportUserFacingError } from "./observability/sentry.js";
|
|
8
|
+
import { normalizeSharedVaultName } from "./vault/index.js";
|
|
9
|
+
import { resolveActorVaultKey } from "./vault/routing.js";
|
|
10
10
|
export function readConversationWorkspaceMountMode(workspaceDir, conversationId) {
|
|
11
11
|
const globalDefault = readGlobalWorkspaceMountMode();
|
|
12
12
|
if (!workspaceDir) {
|
|
@@ -14,7 +14,7 @@ export function readConversationWorkspaceMountMode(workspaceDir, conversationId)
|
|
|
14
14
|
}
|
|
15
15
|
const conversationDir = join(workspaceDir, conversationId);
|
|
16
16
|
try {
|
|
17
|
-
return (
|
|
17
|
+
return resolveConversationSettings(conversationDir).sandboxImageWorkspaceMount ?? globalDefault;
|
|
18
18
|
}
|
|
19
19
|
catch {
|
|
20
20
|
const conversationSettingsPath = join(conversationDir, "settings.json");
|
|
@@ -24,7 +24,7 @@ export function readConversationWorkspaceMountMode(workspaceDir, conversationId)
|
|
|
24
24
|
}
|
|
25
25
|
function readGlobalWorkspaceMountMode() {
|
|
26
26
|
try {
|
|
27
|
-
return
|
|
27
|
+
return loadGlobalSettings().sandboxImageWorkspaceMount ?? "private";
|
|
28
28
|
}
|
|
29
29
|
catch {
|
|
30
30
|
return "private";
|
|
@@ -61,7 +61,7 @@ export class ActorExecutionResolver {
|
|
|
61
61
|
return;
|
|
62
62
|
let profile;
|
|
63
63
|
try {
|
|
64
|
-
profile =
|
|
64
|
+
profile = loadGlobalSettings().defaultSharedVault;
|
|
65
65
|
}
|
|
66
66
|
catch {
|
|
67
67
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-resolver.js","sourceRoot":"","sources":["../src/execution-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"fs\";\nimport { join } from \"path\";\nimport { loadAgentConfig, loadAgentConfigForConversation } from \"./config.js\";\nimport { ensureDirExists, isRecord, readJsonFileIfExists } from \"./file-guards.js\";\nimport { DockerContainerManager, type ContainerMount } from \"./provisioner.js\";\nimport { createExecutor, type Executor, type SandboxConfig } from \"./sandbox/index.js\";\nimport { reportUserFacingError } from \"./sentry.js\";\nimport { normalizeSharedVaultName, type ResolvedVault, type VaultManager } from \"./vault.js\";\nimport { resolveActorVaultKey } from \"./vault-routing.js\";\n\nexport interface ActorContext {\n platform: string;\n userId: string;\n conversationId: string;\n}\n\nexport type ImageWorkspaceMountMode = \"private\" | \"full\";\n\nexport function readConversationWorkspaceMountMode(\n workspaceDir: string | undefined,\n conversationId: string,\n): ImageWorkspaceMountMode {\n const globalDefault = readGlobalWorkspaceMountMode();\n if (!workspaceDir) {\n return globalDefault;\n }\n\n const conversationDir = join(workspaceDir, conversationId);\n try {\n return (\n loadAgentConfigForConversation(conversationDir).sandboxImageWorkspaceMount ?? globalDefault\n );\n } catch {\n const conversationSettingsPath = join(conversationDir, \"settings.json\");\n const raw = readConversationSettingsFallback(conversationSettingsPath);\n return raw?.sandbox?.image?.workspaceMount ?? globalDefault;\n }\n}\n\nfunction readGlobalWorkspaceMountMode(): ImageWorkspaceMountMode {\n try {\n return loadAgentConfig().sandboxImageWorkspaceMount ?? \"private\";\n } catch {\n return \"private\";\n }\n}\n\nfunction readConversationSettingsFallback(\n settingsPath: string,\n): { sandbox?: { image?: { workspaceMount?: ImageWorkspaceMountMode } } } | undefined {\n try {\n return readJsonFileIfExists(\n settingsPath,\n (value): value is { sandbox?: { image?: { workspaceMount?: ImageWorkspaceMountMode } } } =>\n isRecord(value),\n () => \"Ignoring malformed conversation settings file while resolving workspace mount\",\n );\n } catch {\n return undefined;\n }\n}\n\nexport class ActorExecutionResolver {\n private readonly ensuredConversationDirs = new Set<string>();\n\n constructor(\n private baseConfig: SandboxConfig,\n private vaultManager: VaultManager,\n private provisioner?: DockerContainerManager,\n private workspaceDir?: string,\n ) {}\n\n async resolve(context: ActorContext): Promise<Executor> {\n const vaultKey = resolveActorVaultKey(this.baseConfig, context.userId, context.conversationId);\n this.ensureDefaultSharedVault(vaultKey);\n\n const vault = this.vaultManager.resolve(vaultKey);\n const config = this.resolveSandboxConfig(vaultKey);\n const env =\n config.type !== \"host\" && vault && Object.keys(vault.env).length > 0 ? vault.env : undefined;\n return createExecutor(\n config,\n env,\n this.buildEnsureReadyCallback(vaultKey, context.conversationId, config, vault),\n );\n }\n\n private ensureDefaultSharedVault(vaultKey: string): void {\n if (this.baseConfig.type !== \"image\" && this.baseConfig.type !== \"cloudflare\") return;\n if (this.vaultManager.hasEntry(vaultKey)) return;\n\n let profile: string | undefined;\n try {\n profile = loadAgentConfig().defaultSharedVault;\n } catch {\n return;\n }\n if (!profile || normalizeSharedVaultName(profile) !== profile) return;\n\n this.vaultManager.copySharedVaultTo(profile, vaultKey);\n }\n\n private resolveSandboxConfig(vaultKey: string): SandboxConfig {\n const config = this.vaultManager.getSandboxConfig(vaultKey, this.baseConfig);\n if (this.baseConfig.type !== \"image\") {\n return config;\n }\n\n if (config.type === \"container\") {\n return config;\n }\n\n return {\n type: \"container\",\n container: DockerContainerManager.containerName(vaultKey),\n };\n }\n\n private buildEnsureReadyCallback(\n vaultKey: string,\n conversationId: string,\n config: SandboxConfig,\n vault?: ResolvedVault,\n ): (() => Promise<void>) | undefined {\n if (this.baseConfig.type !== \"image\" || config.type !== \"container\") {\n return undefined;\n }\n\n return async () => {\n const expected = config.container || DockerContainerManager.containerName(vaultKey);\n let actual: string | undefined;\n try {\n actual = await this.provisioner?.provision(vaultKey, {\n containerName: expected,\n mounts: this.resolveMounts(conversationId, vault),\n conversationId,\n });\n } catch (err) {\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"sandbox_provision\",\n operation: \"ensure_image_container_ready\",\n severity: \"error\",\n context: {\n sandboxType: \"image\",\n resolvedSandboxType: config.type,\n conversationId,\n vaultKey,\n expectedContainer: expected,\n hasVault: Boolean(vault),\n },\n });\n throw err;\n }\n if (actual && actual !== expected) {\n throw new Error(\n `Provisioner returned container \"${actual}\" for container key \"${vaultKey}\", expected \"${expected}\"`,\n );\n }\n };\n }\n\n private resolveMounts(conversationId: string, vault?: ResolvedVault): ContainerMount[] {\n const mountsByTarget = new Map<string, ContainerMount>();\n for (const mount of this.buildImageSandboxMounts(conversationId)) {\n mountsByTarget.set(mount.target, mount);\n }\n for (const mount of vault?.mounts ?? []) {\n if (!existsSync(mount.source)) {\n reportUserFacingError(new Error(\"Vault mount source is missing\"), {\n domain: \"sandbox\",\n surface: \"vault_injection\",\n operation: \"resolve_mounts\",\n severity: \"warning\",\n context: {\n sandboxType: \"image\",\n conversationId,\n target: mount.target,\n hasVault: Boolean(vault),\n },\n });\n continue;\n }\n mountsByTarget.set(mount.target, { source: mount.source, target: mount.target });\n }\n return [...mountsByTarget.values()];\n }\n\n private buildImageSandboxMounts(conversationId: string): ContainerMount[] {\n if (!this.workspaceDir) {\n return [];\n }\n\n if (readConversationWorkspaceMountMode(this.workspaceDir, conversationId) === \"full\") {\n return [{ source: this.workspaceDir, target: \"/workspace\" }];\n }\n\n const conversationDir = join(this.workspaceDir, conversationId);\n if (!this.ensuredConversationDirs.has(conversationId)) {\n ensureDirExists(conversationDir);\n this.ensuredConversationDirs.add(conversationId);\n }\n\n return [\n { source: join(this.workspaceDir, \"MEMORY.md\"), target: \"/workspace/MEMORY.md\" },\n { source: join(this.workspaceDir, \"skills\"), target: \"/workspace/skills\" },\n { source: join(this.workspaceDir, \"events\"), target: \"/workspace/events\" },\n { source: conversationDir, target: `/workspace/${conversationId}` },\n ];\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"execution-resolver.js","sourceRoot":"","sources":["../src/execution-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"fs\";\nimport { join } from \"path\";\nimport { loadGlobalSettings, resolveConversationSettings } from \"./config.js\";\nimport { ensureDirExists, isRecord, readJsonFileIfExists } from \"./utils/file-guards.js\";\nimport { DockerContainerManager, type ContainerMount } from \"./provisioner.js\";\nimport { createExecutor, type Executor, type SandboxConfig } from \"./sandbox/index.js\";\nimport { reportUserFacingError } from \"./observability/sentry.js\";\nimport { normalizeSharedVaultName, type ResolvedVault, type VaultManager } from \"./vault/index.js\";\nimport { resolveActorVaultKey } from \"./vault/routing.js\";\n\nexport type { ActorContext, ImageWorkspaceMountMode } from \"./types.js\";\nimport type { ActorContext, ImageWorkspaceMountMode } from \"./types.js\";\n\nexport function readConversationWorkspaceMountMode(\n workspaceDir: string | undefined,\n conversationId: string,\n): ImageWorkspaceMountMode {\n const globalDefault = readGlobalWorkspaceMountMode();\n if (!workspaceDir) {\n return globalDefault;\n }\n\n const conversationDir = join(workspaceDir, conversationId);\n try {\n return resolveConversationSettings(conversationDir).sandboxImageWorkspaceMount ?? globalDefault;\n } catch {\n const conversationSettingsPath = join(conversationDir, \"settings.json\");\n const raw = readConversationSettingsFallback(conversationSettingsPath);\n return raw?.sandbox?.image?.workspaceMount ?? globalDefault;\n }\n}\n\nfunction readGlobalWorkspaceMountMode(): ImageWorkspaceMountMode {\n try {\n return loadGlobalSettings().sandboxImageWorkspaceMount ?? \"private\";\n } catch {\n return \"private\";\n }\n}\n\nfunction readConversationSettingsFallback(\n settingsPath: string,\n): { sandbox?: { image?: { workspaceMount?: ImageWorkspaceMountMode } } } | undefined {\n try {\n return readJsonFileIfExists(\n settingsPath,\n (value): value is { sandbox?: { image?: { workspaceMount?: ImageWorkspaceMountMode } } } =>\n isRecord(value),\n () => \"Ignoring malformed conversation settings file while resolving workspace mount\",\n );\n } catch {\n return undefined;\n }\n}\n\nexport class ActorExecutionResolver {\n private readonly ensuredConversationDirs = new Set<string>();\n\n constructor(\n private baseConfig: SandboxConfig,\n private vaultManager: VaultManager,\n private provisioner?: DockerContainerManager,\n private workspaceDir?: string,\n ) {}\n\n async resolve(context: ActorContext): Promise<Executor> {\n const vaultKey = resolveActorVaultKey(this.baseConfig, context.userId, context.conversationId);\n this.ensureDefaultSharedVault(vaultKey);\n\n const vault = this.vaultManager.resolve(vaultKey);\n const config = this.resolveSandboxConfig(vaultKey);\n const env =\n config.type !== \"host\" && vault && Object.keys(vault.env).length > 0 ? vault.env : undefined;\n return createExecutor(\n config,\n env,\n this.buildEnsureReadyCallback(vaultKey, context.conversationId, config, vault),\n );\n }\n\n private ensureDefaultSharedVault(vaultKey: string): void {\n if (this.baseConfig.type !== \"image\" && this.baseConfig.type !== \"cloudflare\") return;\n if (this.vaultManager.hasEntry(vaultKey)) return;\n\n let profile: string | undefined;\n try {\n profile = loadGlobalSettings().defaultSharedVault;\n } catch {\n return;\n }\n if (!profile || normalizeSharedVaultName(profile) !== profile) return;\n\n this.vaultManager.copySharedVaultTo(profile, vaultKey);\n }\n\n private resolveSandboxConfig(vaultKey: string): SandboxConfig {\n const config = this.vaultManager.getSandboxConfig(vaultKey, this.baseConfig);\n if (this.baseConfig.type !== \"image\") {\n return config;\n }\n\n if (config.type === \"container\") {\n return config;\n }\n\n return {\n type: \"container\",\n container: DockerContainerManager.containerName(vaultKey),\n };\n }\n\n private buildEnsureReadyCallback(\n vaultKey: string,\n conversationId: string,\n config: SandboxConfig,\n vault?: ResolvedVault,\n ): (() => Promise<void>) | undefined {\n if (this.baseConfig.type !== \"image\" || config.type !== \"container\") {\n return undefined;\n }\n\n return async () => {\n const expected = config.container || DockerContainerManager.containerName(vaultKey);\n let actual: string | undefined;\n try {\n actual = await this.provisioner?.provision(vaultKey, {\n containerName: expected,\n mounts: this.resolveMounts(conversationId, vault),\n conversationId,\n });\n } catch (err) {\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"sandbox_provision\",\n operation: \"ensure_image_container_ready\",\n severity: \"error\",\n context: {\n sandboxType: \"image\",\n resolvedSandboxType: config.type,\n conversationId,\n vaultKey,\n expectedContainer: expected,\n hasVault: Boolean(vault),\n },\n });\n throw err;\n }\n if (actual && actual !== expected) {\n throw new Error(\n `Provisioner returned container \"${actual}\" for container key \"${vaultKey}\", expected \"${expected}\"`,\n );\n }\n };\n }\n\n private resolveMounts(conversationId: string, vault?: ResolvedVault): ContainerMount[] {\n const mountsByTarget = new Map<string, ContainerMount>();\n for (const mount of this.buildImageSandboxMounts(conversationId)) {\n mountsByTarget.set(mount.target, mount);\n }\n for (const mount of vault?.mounts ?? []) {\n if (!existsSync(mount.source)) {\n reportUserFacingError(new Error(\"Vault mount source is missing\"), {\n domain: \"sandbox\",\n surface: \"vault_injection\",\n operation: \"resolve_mounts\",\n severity: \"warning\",\n context: {\n sandboxType: \"image\",\n conversationId,\n target: mount.target,\n hasVault: Boolean(vault),\n },\n });\n continue;\n }\n mountsByTarget.set(mount.target, { source: mount.source, target: mount.target });\n }\n return [...mountsByTarget.values()];\n }\n\n private buildImageSandboxMounts(conversationId: string): ContainerMount[] {\n if (!this.workspaceDir) {\n return [];\n }\n\n if (readConversationWorkspaceMountMode(this.workspaceDir, conversationId) === \"full\") {\n return [{ source: this.workspaceDir, target: \"/workspace\" }];\n }\n\n const conversationDir = join(this.workspaceDir, conversationId);\n if (!this.ensuredConversationDirs.has(conversationId)) {\n ensureDirExists(conversationDir);\n this.ensuredConversationDirs.add(conversationId);\n }\n\n return [\n { source: join(this.workspaceDir, \"MEMORY.md\"), target: \"/workspace/MEMORY.md\" },\n { source: join(this.workspaceDir, \"skills\"), target: \"/workspace/skills\" },\n { source: join(this.workspaceDir, \"events\"), target: \"/workspace/events\" },\n { source: conversationDir, target: `/workspace/${conversationId}` },\n ];\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { defaultCommandHandlers, dispatchCommand } from "./commands/
|
|
2
|
-
export type { CommandContext, CommandHandler, CommandServices } from "./commands/
|
|
1
|
+
export { defaultCommandHandlers, dispatchCommand } from "./commands/registry.js";
|
|
2
|
+
export type { CommandContext, CommandHandler, CommandServices } from "./commands/types.js";
|
|
3
3
|
export * from "./sessions/chat-session-manager.js";
|
|
4
4
|
export * from "./sessions/metadata.js";
|
|
5
5
|
export * from "./sessions/policy.js";
|
|
6
6
|
export * from "./sessions/store.js";
|
|
7
|
-
export { createSessionRuntime, type CreateSessionSandboxOptions, type RunSessionOptions, type SessionRuntime, type SessionRuntimeOptions, } from "./runtime/
|
|
7
|
+
export { createSessionRuntime, type CreateSessionSandboxOptions, type RunSessionOptions, type SessionRuntime, type SessionRuntimeOptions, } from "./runtime/session-runtime.js";
|
|
8
8
|
export type { Bot, BotAdapters, BotEvent, BotHandler, ChatAdapter, ChatMessage, ChatResponseContext, ChatToolResult, ConversationKind, PlatformInfo, RunningSession, } from "./adapter.js";
|
|
9
9
|
export { SandboxError, createExecutor, getSandboxAdapters, parseSandboxArg, validateSandbox, } from "./sandbox/index.js";
|
|
10
10
|
export type { CloudflareSandboxConfig, ExecOptions, ExecResult, Executor, SandboxAdapter, SandboxConfig, } from "./sandbox/index.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACjF,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3F,cAAc,oCAAoC,CAAC;AACnD,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,qBAAqB,GAC3B,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,GAAG,EACH,WAAW,EACX,QAAQ,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,uBAAuB,EACvB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,cAAc,EACd,aAAa,GACd,MAAM,oBAAoB,CAAC","sourcesContent":["export { defaultCommandHandlers, dispatchCommand } from \"./commands/registry.js\";\nexport type { CommandContext, CommandHandler, CommandServices } from \"./commands/types.js\";\nexport * from \"./sessions/chat-session-manager.js\";\nexport * from \"./sessions/metadata.js\";\nexport * from \"./sessions/policy.js\";\nexport * from \"./sessions/store.js\";\nexport {\n createSessionRuntime,\n type CreateSessionSandboxOptions,\n type RunSessionOptions,\n type SessionRuntime,\n type SessionRuntimeOptions,\n} from \"./runtime/session-runtime.js\";\nexport type {\n Bot,\n BotAdapters,\n BotEvent,\n BotHandler,\n ChatAdapter,\n ChatMessage,\n ChatResponseContext,\n ChatToolResult,\n ConversationKind,\n PlatformInfo,\n RunningSession,\n} from \"./adapter.js\";\nexport {\n SandboxError,\n createExecutor,\n getSandboxAdapters,\n parseSandboxArg,\n validateSandbox,\n} from \"./sandbox/index.js\";\nexport type {\n CloudflareSandboxConfig,\n ExecOptions,\n ExecResult,\n Executor,\n SandboxAdapter,\n SandboxConfig,\n} from \"./sandbox/index.js\";\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { defaultCommandHandlers, dispatchCommand } from "./commands/
|
|
1
|
+
export { defaultCommandHandlers, dispatchCommand } from "./commands/registry.js";
|
|
2
2
|
export * from "./sessions/chat-session-manager.js";
|
|
3
3
|
export * from "./sessions/metadata.js";
|
|
4
4
|
export * from "./sessions/policy.js";
|
|
5
5
|
export * from "./sessions/store.js";
|
|
6
|
-
export { createSessionRuntime, } from "./runtime/
|
|
6
|
+
export { createSessionRuntime, } from "./runtime/session-runtime.js";
|
|
7
7
|
export { SandboxError, createExecutor, getSandboxAdapters, parseSandboxArg, validateSandbox, } from "./sandbox/index.js";
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEjF,cAAc,oCAAoC,CAAC;AACnD,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,oBAAoB,GAKrB,MAAM,8BAA8B,CAAC;AActC,OAAO,EACL,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,eAAe,GAChB,MAAM,oBAAoB,CAAC","sourcesContent":["export { defaultCommandHandlers, dispatchCommand } from \"./commands/registry.js\";\nexport type { CommandContext, CommandHandler, CommandServices } from \"./commands/types.js\";\nexport * from \"./sessions/chat-session-manager.js\";\nexport * from \"./sessions/metadata.js\";\nexport * from \"./sessions/policy.js\";\nexport * from \"./sessions/store.js\";\nexport {\n createSessionRuntime,\n type CreateSessionSandboxOptions,\n type RunSessionOptions,\n type SessionRuntime,\n type SessionRuntimeOptions,\n} from \"./runtime/session-runtime.js\";\nexport type {\n Bot,\n BotAdapters,\n BotEvent,\n BotHandler,\n ChatAdapter,\n ChatMessage,\n ChatResponseContext,\n ChatToolResult,\n ConversationKind,\n PlatformInfo,\n RunningSession,\n} from \"./adapter.js\";\nexport {\n SandboxError,\n createExecutor,\n getSandboxAdapters,\n parseSandboxArg,\n validateSandbox,\n} from \"./sandbox/index.js\";\nexport type {\n CloudflareSandboxConfig,\n ExecOptions,\n ExecResult,\n Executor,\n SandboxAdapter,\n SandboxConfig,\n} from \"./sandbox/index.js\";\n"]}
|
package/dist/log.d.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
userName?: string;
|
|
4
|
-
conversationName?: string;
|
|
5
|
-
sessionId?: string;
|
|
6
|
-
}
|
|
1
|
+
export type { LogContext } from "./types.js";
|
|
2
|
+
import type { LogContext } from "./types.js";
|
|
7
3
|
export declare function logUserMessage(ctx: LogContext, text: string): void;
|
|
8
4
|
export declare function logToolStart(ctx: LogContext, toolName: string, label: string, args: Record<string, unknown>): void;
|
|
9
5
|
export declare function logToolSuccess(ctx: LogContext, toolName: string, durationMs: number, result: string): void;
|
package/dist/log.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoED,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAElE;AAGD,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,IAAI,CAWN;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,IAAI,CAYN;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GACZ,IAAI,CAUN;AAGD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAEtD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAQnE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAQ/D;AAGD,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CASlE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAQ7E;AAUD,wBAAgB,eAAe,CAC7B,GAAG,EAAE,UAAU,EACf,KAAK,EAAE;IACL,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/F,EACD,aAAa,CAAC,EAAE,MAAM,EACtB,aAAa,CAAC,EAAE,MAAM,GACrB,MAAM,CAqCR;AAGD,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAIpE;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAGnD;AAED,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAGD,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAElF;AAED,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAOnF","sourcesContent":["import chalk from \"chalk\";\n\nexport interface LogContext {\n conversationId: string;\n userName?: string;\n conversationName?: string; // For display like #dev-team vs C16HET4EQ\n sessionId?: string;\n}\n\nfunction timestamp(): string {\n const now = new Date();\n const hh = String(now.getHours()).padStart(2, \"0\");\n const mm = String(now.getMinutes()).padStart(2, \"0\");\n const ss = String(now.getSeconds()).padStart(2, \"0\");\n return `[${hh}:${mm}:${ss}]`;\n}\n\nfunction formatContext(ctx: LogContext): string {\n const session = ctx.sessionId ? `:${ctx.sessionId}` : \"\";\n if (ctx.conversationId.startsWith(\"D\")) {\n return `[DM:${ctx.userName || ctx.conversationId}${session}]`;\n }\n const conversation = ctx.conversationName || ctx.conversationId;\n const user = ctx.userName || \"unknown\";\n return `[${conversation.startsWith(\"#\") ? conversation : `#${conversation}`}:${user}${session}]`;\n}\n\n// Keep stdout/stderr lines manageable when echoing tool/agent output. Long bodies\n// flow through Sentry and session storage; the console stream just needs a preview.\nconst LOG_PREVIEW_MAX = 1000;\n\nfunction truncate(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return `${text.substring(0, maxLen)}\\n(truncated at ${maxLen} chars)`;\n}\n\nfunction formatToolArgs(args: Record<string, unknown>): string {\n const lines: string[] = [];\n\n for (const [key, value] of Object.entries(args)) {\n // Skip the label - it's already shown in the tool name\n if (key === \"label\") continue;\n\n // For read tool, format path with offset/limit\n if (key === \"path\" && typeof value === \"string\") {\n const offset = args.offset as number | undefined;\n const limit = args.limit as number | undefined;\n if (offset !== undefined && limit !== undefined) {\n lines.push(`${value}:${offset}-${offset + limit}`);\n } else {\n lines.push(value);\n }\n continue;\n }\n\n // Skip offset/limit since we already handled them\n if (key === \"offset\" || key === \"limit\") continue;\n\n // For other values, format them\n if (typeof value === \"string\") {\n // Multi-line strings get indented\n if (value.includes(\"\\n\")) {\n lines.push(value);\n } else {\n lines.push(value);\n }\n } else {\n lines.push(JSON.stringify(value));\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n// User messages\nexport function logUserMessage(ctx: LogContext, text: string): void {\n console.log(chalk.green(`${timestamp()} ${formatContext(ctx)} ${text}`));\n}\n\n// Tool execution\nexport function logToolStart(\n ctx: LogContext,\n toolName: string,\n label: string,\n args: Record<string, unknown>,\n): void {\n const formattedArgs = formatToolArgs(args);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ↳ ${toolName}: ${label}`));\n if (formattedArgs) {\n // Indent the args\n const indented = formattedArgs\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logToolSuccess(\n ctx: LogContext,\n toolName: string,\n durationMs: number,\n result: string,\n): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ✓ ${toolName} (${duration}s)`));\n\n const truncated = truncate(result, LOG_PREVIEW_MAX);\n if (truncated) {\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logToolError(\n ctx: LogContext,\n toolName: string,\n durationMs: number,\n error: string,\n): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ✗ ${toolName} (${duration}s)`));\n\n const truncated = truncate(error, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\n// Response streaming\nexport function logResponseStart(ctx: LogContext): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} → Streaming response...`));\n}\n\nexport function logThinking(ctx: LogContext, thinking: string): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💭 Thinking`));\n const truncated = truncate(thinking, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\nexport function logResponse(ctx: LogContext, text: string): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💬 Response`));\n const truncated = truncate(text, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\n// System\nexport function logInfo(message: string): void {\n console.log(chalk.blue(`${timestamp()} [system] ${message}`));\n}\n\nexport function logWarning(message: string, details?: string): void {\n console.log(chalk.yellow(`${timestamp()} [system] ⚠ ${message}`));\n if (details) {\n const indented = details\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logAgentError(ctx: LogContext | \"system\", error: string): void {\n const context = ctx === \"system\" ? \"[system]\" : formatContext(ctx);\n console.log(chalk.yellow(`${timestamp()} ${context} ✗ Agent error`));\n const indented = error\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\nfunction formatTokenCount(count: number): string {\n if (count < 1000) return count.toString();\n if (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n if (count < 1000000) return `${Math.round(count / 1000)}k`;\n return `${(count / 1000000).toFixed(1)}M`;\n}\n\n// Usage summary\nexport function logUsageSummary(\n ctx: LogContext,\n usage: {\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n cost: { input: number; output: number; cacheRead: number; cacheWrite: number; total: number };\n },\n contextTokens?: number,\n contextWindow?: number,\n): string {\n const lines: string[] = [];\n lines.push(\"_Usage Summary_\");\n lines.push(`Tokens: ${usage.input.toLocaleString()} in, ${usage.output.toLocaleString()} out`);\n if (usage.cacheRead > 0 || usage.cacheWrite > 0) {\n lines.push(\n `Cache: ${usage.cacheRead.toLocaleString()} read, ${usage.cacheWrite.toLocaleString()} write`,\n );\n }\n if (contextTokens && contextWindow) {\n const contextPercent = ((contextTokens / contextWindow) * 100).toFixed(1);\n lines.push(\n `Context: ${formatTokenCount(contextTokens)} / ${formatTokenCount(contextWindow)} (${contextPercent}%)`,\n );\n }\n lines.push(\n `Cost: $${usage.cost.input.toFixed(4)} in, $${usage.cost.output.toFixed(4)} out` +\n (usage.cacheRead > 0 || usage.cacheWrite > 0\n ? `, $${usage.cost.cacheRead.toFixed(4)} cache read, $${usage.cost.cacheWrite.toFixed(4)} cache write`\n : \"\"),\n );\n lines.push(`*Total: $${usage.cost.total.toFixed(4)}*`);\n\n const summary = lines.join(\"\\n\");\n\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💰 Usage`));\n console.log(\n chalk.dim(\n ` ${usage.input.toLocaleString()} in + ${usage.output.toLocaleString()} out` +\n (usage.cacheRead > 0 || usage.cacheWrite > 0\n ? ` (${usage.cacheRead.toLocaleString()} cache read, ${usage.cacheWrite.toLocaleString()} cache write)`\n : \"\") +\n ` = $${usage.cost.total.toFixed(4)}`,\n ),\n );\n\n return summary;\n}\n\n// Startup (no context needed)\nexport function logStartup(workingDir: string, sandbox: string): void {\n console.log(\"Starting mikan...\");\n console.log(` Working directory: ${workingDir}`);\n console.log(` Sandbox: ${sandbox}`);\n}\n\nexport function logConnected(platform: string): void {\n console.log(`⚡️ Mikan connected to ${platform} and listening!`);\n console.log(\"\");\n}\n\nexport function logDisconnected(): void {\n console.log(\"Mikan disconnected.\");\n}\n\n// Backfill\nexport function logBackfillStart(channelCount: number): void {\n console.log(chalk.blue(`${timestamp()} [system] Backfilling ${channelCount} channels...`));\n}\n\nexport function logBackfillChannel(channelName: string, messageCount: number): void {\n console.log(chalk.blue(`${timestamp()} [system] #${channelName}: ${messageCount} messages`));\n}\n\nexport function logBackfillComplete(totalMessages: number, durationMs: number): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(\n chalk.blue(\n `${timestamp()} [system] Backfill complete: ${totalMessages} messages in ${duration}s`,\n ),\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA8B7C,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAElE;AAGD,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,IAAI,CAWN;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,IAAI,CAYN;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GACZ,IAAI,CAUN;AAGD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAEtD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAQnE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAQ/D;AAGD,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CASlE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAQ7E;AAUD,wBAAgB,eAAe,CAC7B,GAAG,EAAE,UAAU,EACf,KAAK,EAAE;IACL,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/F,EACD,aAAa,CAAC,EAAE,MAAM,EACtB,aAAa,CAAC,EAAE,MAAM,GACrB,MAAM,CAqCR;AAGD,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAIpE;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAGnD;AAED,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAGD,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAElF;AAED,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAOnF","sourcesContent":["import chalk from \"chalk\";\nimport { formatToolArgs } from \"./adapters/shared.js\";\n\nexport type { LogContext } from \"./types.js\";\nimport type { LogContext } from \"./types.js\";\n\nfunction timestamp(): string {\n const now = new Date();\n const hh = String(now.getHours()).padStart(2, \"0\");\n const mm = String(now.getMinutes()).padStart(2, \"0\");\n const ss = String(now.getSeconds()).padStart(2, \"0\");\n return `[${hh}:${mm}:${ss}]`;\n}\n\nfunction formatContext(ctx: LogContext): string {\n const session = ctx.sessionId ? `:${ctx.sessionId}` : \"\";\n if (ctx.conversationId.startsWith(\"D\")) {\n return `[DM:${ctx.userName || ctx.conversationId}${session}]`;\n }\n const conversation = ctx.conversationName || ctx.conversationId;\n const user = ctx.userName || \"unknown\";\n return `[${conversation.startsWith(\"#\") ? conversation : `#${conversation}`}:${user}${session}]`;\n}\n\n// Keep stdout/stderr lines manageable when echoing tool/agent output. Long bodies\n// flow through Sentry and session storage; the console stream just needs a preview.\nconst LOG_PREVIEW_MAX = 1000;\n\nfunction truncate(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return `${text.substring(0, maxLen)}\\n(truncated at ${maxLen} chars)`;\n}\n\n// User messages\nexport function logUserMessage(ctx: LogContext, text: string): void {\n console.log(chalk.green(`${timestamp()} ${formatContext(ctx)} ${text}`));\n}\n\n// Tool execution\nexport function logToolStart(\n ctx: LogContext,\n toolName: string,\n label: string,\n args: Record<string, unknown>,\n): void {\n const formattedArgs = formatToolArgs(args);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ↳ ${toolName}: ${label}`));\n if (formattedArgs) {\n // Indent the args\n const indented = formattedArgs\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logToolSuccess(\n ctx: LogContext,\n toolName: string,\n durationMs: number,\n result: string,\n): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ✓ ${toolName} (${duration}s)`));\n\n const truncated = truncate(result, LOG_PREVIEW_MAX);\n if (truncated) {\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logToolError(\n ctx: LogContext,\n toolName: string,\n durationMs: number,\n error: string,\n): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ✗ ${toolName} (${duration}s)`));\n\n const truncated = truncate(error, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\n// Response streaming\nexport function logResponseStart(ctx: LogContext): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} → Streaming response...`));\n}\n\nexport function logThinking(ctx: LogContext, thinking: string): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💭 Thinking`));\n const truncated = truncate(thinking, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\nexport function logResponse(ctx: LogContext, text: string): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💬 Response`));\n const truncated = truncate(text, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\n// System\nexport function logInfo(message: string): void {\n console.log(chalk.blue(`${timestamp()} [system] ${message}`));\n}\n\nexport function logWarning(message: string, details?: string): void {\n console.log(chalk.yellow(`${timestamp()} [system] ⚠ ${message}`));\n if (details) {\n const indented = details\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logAgentError(ctx: LogContext | \"system\", error: string): void {\n const context = ctx === \"system\" ? \"[system]\" : formatContext(ctx);\n console.log(chalk.yellow(`${timestamp()} ${context} ✗ Agent error`));\n const indented = error\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\nfunction formatTokenCount(count: number): string {\n if (count < 1000) return count.toString();\n if (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n if (count < 1000000) return `${Math.round(count / 1000)}k`;\n return `${(count / 1000000).toFixed(1)}M`;\n}\n\n// Usage summary\nexport function logUsageSummary(\n ctx: LogContext,\n usage: {\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n cost: { input: number; output: number; cacheRead: number; cacheWrite: number; total: number };\n },\n contextTokens?: number,\n contextWindow?: number,\n): string {\n const lines: string[] = [];\n lines.push(\"_Usage Summary_\");\n lines.push(`Tokens: ${usage.input.toLocaleString()} in, ${usage.output.toLocaleString()} out`);\n if (usage.cacheRead > 0 || usage.cacheWrite > 0) {\n lines.push(\n `Cache: ${usage.cacheRead.toLocaleString()} read, ${usage.cacheWrite.toLocaleString()} write`,\n );\n }\n if (contextTokens && contextWindow) {\n const contextPercent = ((contextTokens / contextWindow) * 100).toFixed(1);\n lines.push(\n `Context: ${formatTokenCount(contextTokens)} / ${formatTokenCount(contextWindow)} (${contextPercent}%)`,\n );\n }\n lines.push(\n `Cost: $${usage.cost.input.toFixed(4)} in, $${usage.cost.output.toFixed(4)} out` +\n (usage.cacheRead > 0 || usage.cacheWrite > 0\n ? `, $${usage.cost.cacheRead.toFixed(4)} cache read, $${usage.cost.cacheWrite.toFixed(4)} cache write`\n : \"\"),\n );\n lines.push(`*Total: $${usage.cost.total.toFixed(4)}*`);\n\n const summary = lines.join(\"\\n\");\n\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💰 Usage`));\n console.log(\n chalk.dim(\n ` ${usage.input.toLocaleString()} in + ${usage.output.toLocaleString()} out` +\n (usage.cacheRead > 0 || usage.cacheWrite > 0\n ? ` (${usage.cacheRead.toLocaleString()} cache read, ${usage.cacheWrite.toLocaleString()} cache write)`\n : \"\") +\n ` = $${usage.cost.total.toFixed(4)}`,\n ),\n );\n\n return summary;\n}\n\n// Startup (no context needed)\nexport function logStartup(workingDir: string, sandbox: string): void {\n console.log(\"Starting mikan...\");\n console.log(` Working directory: ${workingDir}`);\n console.log(` Sandbox: ${sandbox}`);\n}\n\nexport function logConnected(platform: string): void {\n console.log(`⚡️ Mikan connected to ${platform} and listening!`);\n console.log(\"\");\n}\n\nexport function logDisconnected(): void {\n console.log(\"Mikan disconnected.\");\n}\n\n// Backfill\nexport function logBackfillStart(channelCount: number): void {\n console.log(chalk.blue(`${timestamp()} [system] Backfilling ${channelCount} channels...`));\n}\n\nexport function logBackfillChannel(channelName: string, messageCount: number): void {\n console.log(chalk.blue(`${timestamp()} [system] #${channelName}: ${messageCount} messages`));\n}\n\nexport function logBackfillComplete(totalMessages: number, durationMs: number): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(\n chalk.blue(\n `${timestamp()} [system] Backfill complete: ${totalMessages} messages in ${duration}s`,\n ),\n );\n}\n"]}
|
package/dist/log.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
+
import { formatToolArgs } from "./adapters/shared.js";
|
|
2
3
|
function timestamp() {
|
|
3
4
|
const now = new Date();
|
|
4
5
|
const hh = String(now.getHours()).padStart(2, "0");
|
|
@@ -23,43 +24,6 @@ function truncate(text, maxLen) {
|
|
|
23
24
|
return text;
|
|
24
25
|
return `${text.substring(0, maxLen)}\n(truncated at ${maxLen} chars)`;
|
|
25
26
|
}
|
|
26
|
-
function formatToolArgs(args) {
|
|
27
|
-
const lines = [];
|
|
28
|
-
for (const [key, value] of Object.entries(args)) {
|
|
29
|
-
// Skip the label - it's already shown in the tool name
|
|
30
|
-
if (key === "label")
|
|
31
|
-
continue;
|
|
32
|
-
// For read tool, format path with offset/limit
|
|
33
|
-
if (key === "path" && typeof value === "string") {
|
|
34
|
-
const offset = args.offset;
|
|
35
|
-
const limit = args.limit;
|
|
36
|
-
if (offset !== undefined && limit !== undefined) {
|
|
37
|
-
lines.push(`${value}:${offset}-${offset + limit}`);
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
lines.push(value);
|
|
41
|
-
}
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
// Skip offset/limit since we already handled them
|
|
45
|
-
if (key === "offset" || key === "limit")
|
|
46
|
-
continue;
|
|
47
|
-
// For other values, format them
|
|
48
|
-
if (typeof value === "string") {
|
|
49
|
-
// Multi-line strings get indented
|
|
50
|
-
if (value.includes("\n")) {
|
|
51
|
-
lines.push(value);
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
lines.push(value);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
lines.push(JSON.stringify(value));
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return lines.join("\n");
|
|
62
|
-
}
|
|
63
27
|
// User messages
|
|
64
28
|
export function logUserMessage(ctx, text) {
|
|
65
29
|
console.log(chalk.green(`${timestamp()} ${formatContext(ctx)} ${text}`));
|
package/dist/log.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from \"chalk\";\n\nexport interface LogContext {\n conversationId: string;\n userName?: string;\n conversationName?: string; // For display like #dev-team vs C16HET4EQ\n sessionId?: string;\n}\n\nfunction timestamp(): string {\n const now = new Date();\n const hh = String(now.getHours()).padStart(2, \"0\");\n const mm = String(now.getMinutes()).padStart(2, \"0\");\n const ss = String(now.getSeconds()).padStart(2, \"0\");\n return `[${hh}:${mm}:${ss}]`;\n}\n\nfunction formatContext(ctx: LogContext): string {\n const session = ctx.sessionId ? `:${ctx.sessionId}` : \"\";\n if (ctx.conversationId.startsWith(\"D\")) {\n return `[DM:${ctx.userName || ctx.conversationId}${session}]`;\n }\n const conversation = ctx.conversationName || ctx.conversationId;\n const user = ctx.userName || \"unknown\";\n return `[${conversation.startsWith(\"#\") ? conversation : `#${conversation}`}:${user}${session}]`;\n}\n\n// Keep stdout/stderr lines manageable when echoing tool/agent output. Long bodies\n// flow through Sentry and session storage; the console stream just needs a preview.\nconst LOG_PREVIEW_MAX = 1000;\n\nfunction truncate(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return `${text.substring(0, maxLen)}\\n(truncated at ${maxLen} chars)`;\n}\n\nfunction formatToolArgs(args: Record<string, unknown>): string {\n const lines: string[] = [];\n\n for (const [key, value] of Object.entries(args)) {\n // Skip the label - it's already shown in the tool name\n if (key === \"label\") continue;\n\n // For read tool, format path with offset/limit\n if (key === \"path\" && typeof value === \"string\") {\n const offset = args.offset as number | undefined;\n const limit = args.limit as number | undefined;\n if (offset !== undefined && limit !== undefined) {\n lines.push(`${value}:${offset}-${offset + limit}`);\n } else {\n lines.push(value);\n }\n continue;\n }\n\n // Skip offset/limit since we already handled them\n if (key === \"offset\" || key === \"limit\") continue;\n\n // For other values, format them\n if (typeof value === \"string\") {\n // Multi-line strings get indented\n if (value.includes(\"\\n\")) {\n lines.push(value);\n } else {\n lines.push(value);\n }\n } else {\n lines.push(JSON.stringify(value));\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n// User messages\nexport function logUserMessage(ctx: LogContext, text: string): void {\n console.log(chalk.green(`${timestamp()} ${formatContext(ctx)} ${text}`));\n}\n\n// Tool execution\nexport function logToolStart(\n ctx: LogContext,\n toolName: string,\n label: string,\n args: Record<string, unknown>,\n): void {\n const formattedArgs = formatToolArgs(args);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ↳ ${toolName}: ${label}`));\n if (formattedArgs) {\n // Indent the args\n const indented = formattedArgs\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logToolSuccess(\n ctx: LogContext,\n toolName: string,\n durationMs: number,\n result: string,\n): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ✓ ${toolName} (${duration}s)`));\n\n const truncated = truncate(result, LOG_PREVIEW_MAX);\n if (truncated) {\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logToolError(\n ctx: LogContext,\n toolName: string,\n durationMs: number,\n error: string,\n): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ✗ ${toolName} (${duration}s)`));\n\n const truncated = truncate(error, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\n// Response streaming\nexport function logResponseStart(ctx: LogContext): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} → Streaming response...`));\n}\n\nexport function logThinking(ctx: LogContext, thinking: string): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💭 Thinking`));\n const truncated = truncate(thinking, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\nexport function logResponse(ctx: LogContext, text: string): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💬 Response`));\n const truncated = truncate(text, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\n// System\nexport function logInfo(message: string): void {\n console.log(chalk.blue(`${timestamp()} [system] ${message}`));\n}\n\nexport function logWarning(message: string, details?: string): void {\n console.log(chalk.yellow(`${timestamp()} [system] ⚠ ${message}`));\n if (details) {\n const indented = details\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logAgentError(ctx: LogContext | \"system\", error: string): void {\n const context = ctx === \"system\" ? \"[system]\" : formatContext(ctx);\n console.log(chalk.yellow(`${timestamp()} ${context} ✗ Agent error`));\n const indented = error\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\nfunction formatTokenCount(count: number): string {\n if (count < 1000) return count.toString();\n if (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n if (count < 1000000) return `${Math.round(count / 1000)}k`;\n return `${(count / 1000000).toFixed(1)}M`;\n}\n\n// Usage summary\nexport function logUsageSummary(\n ctx: LogContext,\n usage: {\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n cost: { input: number; output: number; cacheRead: number; cacheWrite: number; total: number };\n },\n contextTokens?: number,\n contextWindow?: number,\n): string {\n const lines: string[] = [];\n lines.push(\"_Usage Summary_\");\n lines.push(`Tokens: ${usage.input.toLocaleString()} in, ${usage.output.toLocaleString()} out`);\n if (usage.cacheRead > 0 || usage.cacheWrite > 0) {\n lines.push(\n `Cache: ${usage.cacheRead.toLocaleString()} read, ${usage.cacheWrite.toLocaleString()} write`,\n );\n }\n if (contextTokens && contextWindow) {\n const contextPercent = ((contextTokens / contextWindow) * 100).toFixed(1);\n lines.push(\n `Context: ${formatTokenCount(contextTokens)} / ${formatTokenCount(contextWindow)} (${contextPercent}%)`,\n );\n }\n lines.push(\n `Cost: $${usage.cost.input.toFixed(4)} in, $${usage.cost.output.toFixed(4)} out` +\n (usage.cacheRead > 0 || usage.cacheWrite > 0\n ? `, $${usage.cost.cacheRead.toFixed(4)} cache read, $${usage.cost.cacheWrite.toFixed(4)} cache write`\n : \"\"),\n );\n lines.push(`*Total: $${usage.cost.total.toFixed(4)}*`);\n\n const summary = lines.join(\"\\n\");\n\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💰 Usage`));\n console.log(\n chalk.dim(\n ` ${usage.input.toLocaleString()} in + ${usage.output.toLocaleString()} out` +\n (usage.cacheRead > 0 || usage.cacheWrite > 0\n ? ` (${usage.cacheRead.toLocaleString()} cache read, ${usage.cacheWrite.toLocaleString()} cache write)`\n : \"\") +\n ` = $${usage.cost.total.toFixed(4)}`,\n ),\n );\n\n return summary;\n}\n\n// Startup (no context needed)\nexport function logStartup(workingDir: string, sandbox: string): void {\n console.log(\"Starting mikan...\");\n console.log(` Working directory: ${workingDir}`);\n console.log(` Sandbox: ${sandbox}`);\n}\n\nexport function logConnected(platform: string): void {\n console.log(`⚡️ Mikan connected to ${platform} and listening!`);\n console.log(\"\");\n}\n\nexport function logDisconnected(): void {\n console.log(\"Mikan disconnected.\");\n}\n\n// Backfill\nexport function logBackfillStart(channelCount: number): void {\n console.log(chalk.blue(`${timestamp()} [system] Backfilling ${channelCount} channels...`));\n}\n\nexport function logBackfillChannel(channelName: string, messageCount: number): void {\n console.log(chalk.blue(`${timestamp()} [system] #${channelName}: ${messageCount} messages`));\n}\n\nexport function logBackfillComplete(totalMessages: number, durationMs: number): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(\n chalk.blue(\n `${timestamp()} [system] Backfill complete: ${totalMessages} messages in ${duration}s`,\n ),\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from \"chalk\";\nimport { formatToolArgs } from \"./adapters/shared.js\";\n\nexport type { LogContext } from \"./types.js\";\nimport type { LogContext } from \"./types.js\";\n\nfunction timestamp(): string {\n const now = new Date();\n const hh = String(now.getHours()).padStart(2, \"0\");\n const mm = String(now.getMinutes()).padStart(2, \"0\");\n const ss = String(now.getSeconds()).padStart(2, \"0\");\n return `[${hh}:${mm}:${ss}]`;\n}\n\nfunction formatContext(ctx: LogContext): string {\n const session = ctx.sessionId ? `:${ctx.sessionId}` : \"\";\n if (ctx.conversationId.startsWith(\"D\")) {\n return `[DM:${ctx.userName || ctx.conversationId}${session}]`;\n }\n const conversation = ctx.conversationName || ctx.conversationId;\n const user = ctx.userName || \"unknown\";\n return `[${conversation.startsWith(\"#\") ? conversation : `#${conversation}`}:${user}${session}]`;\n}\n\n// Keep stdout/stderr lines manageable when echoing tool/agent output. Long bodies\n// flow through Sentry and session storage; the console stream just needs a preview.\nconst LOG_PREVIEW_MAX = 1000;\n\nfunction truncate(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return `${text.substring(0, maxLen)}\\n(truncated at ${maxLen} chars)`;\n}\n\n// User messages\nexport function logUserMessage(ctx: LogContext, text: string): void {\n console.log(chalk.green(`${timestamp()} ${formatContext(ctx)} ${text}`));\n}\n\n// Tool execution\nexport function logToolStart(\n ctx: LogContext,\n toolName: string,\n label: string,\n args: Record<string, unknown>,\n): void {\n const formattedArgs = formatToolArgs(args);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ↳ ${toolName}: ${label}`));\n if (formattedArgs) {\n // Indent the args\n const indented = formattedArgs\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logToolSuccess(\n ctx: LogContext,\n toolName: string,\n durationMs: number,\n result: string,\n): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ✓ ${toolName} (${duration}s)`));\n\n const truncated = truncate(result, LOG_PREVIEW_MAX);\n if (truncated) {\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logToolError(\n ctx: LogContext,\n toolName: string,\n durationMs: number,\n error: string,\n): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} ✗ ${toolName} (${duration}s)`));\n\n const truncated = truncate(error, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\n// Response streaming\nexport function logResponseStart(ctx: LogContext): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} → Streaming response...`));\n}\n\nexport function logThinking(ctx: LogContext, thinking: string): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💭 Thinking`));\n const truncated = truncate(thinking, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\nexport function logResponse(ctx: LogContext, text: string): void {\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💬 Response`));\n const truncated = truncate(text, LOG_PREVIEW_MAX);\n const indented = truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\n// System\nexport function logInfo(message: string): void {\n console.log(chalk.blue(`${timestamp()} [system] ${message}`));\n}\n\nexport function logWarning(message: string, details?: string): void {\n console.log(chalk.yellow(`${timestamp()} [system] ⚠ ${message}`));\n if (details) {\n const indented = details\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n }\n}\n\nexport function logAgentError(ctx: LogContext | \"system\", error: string): void {\n const context = ctx === \"system\" ? \"[system]\" : formatContext(ctx);\n console.log(chalk.yellow(`${timestamp()} ${context} ✗ Agent error`));\n const indented = error\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\");\n console.log(chalk.dim(indented));\n}\n\nfunction formatTokenCount(count: number): string {\n if (count < 1000) return count.toString();\n if (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n if (count < 1000000) return `${Math.round(count / 1000)}k`;\n return `${(count / 1000000).toFixed(1)}M`;\n}\n\n// Usage summary\nexport function logUsageSummary(\n ctx: LogContext,\n usage: {\n input: number;\n output: number;\n cacheRead: number;\n cacheWrite: number;\n cost: { input: number; output: number; cacheRead: number; cacheWrite: number; total: number };\n },\n contextTokens?: number,\n contextWindow?: number,\n): string {\n const lines: string[] = [];\n lines.push(\"_Usage Summary_\");\n lines.push(`Tokens: ${usage.input.toLocaleString()} in, ${usage.output.toLocaleString()} out`);\n if (usage.cacheRead > 0 || usage.cacheWrite > 0) {\n lines.push(\n `Cache: ${usage.cacheRead.toLocaleString()} read, ${usage.cacheWrite.toLocaleString()} write`,\n );\n }\n if (contextTokens && contextWindow) {\n const contextPercent = ((contextTokens / contextWindow) * 100).toFixed(1);\n lines.push(\n `Context: ${formatTokenCount(contextTokens)} / ${formatTokenCount(contextWindow)} (${contextPercent}%)`,\n );\n }\n lines.push(\n `Cost: $${usage.cost.input.toFixed(4)} in, $${usage.cost.output.toFixed(4)} out` +\n (usage.cacheRead > 0 || usage.cacheWrite > 0\n ? `, $${usage.cost.cacheRead.toFixed(4)} cache read, $${usage.cost.cacheWrite.toFixed(4)} cache write`\n : \"\"),\n );\n lines.push(`*Total: $${usage.cost.total.toFixed(4)}*`);\n\n const summary = lines.join(\"\\n\");\n\n console.log(chalk.yellow(`${timestamp()} ${formatContext(ctx)} 💰 Usage`));\n console.log(\n chalk.dim(\n ` ${usage.input.toLocaleString()} in + ${usage.output.toLocaleString()} out` +\n (usage.cacheRead > 0 || usage.cacheWrite > 0\n ? ` (${usage.cacheRead.toLocaleString()} cache read, ${usage.cacheWrite.toLocaleString()} cache write)`\n : \"\") +\n ` = $${usage.cost.total.toFixed(4)}`,\n ),\n );\n\n return summary;\n}\n\n// Startup (no context needed)\nexport function logStartup(workingDir: string, sandbox: string): void {\n console.log(\"Starting mikan...\");\n console.log(` Working directory: ${workingDir}`);\n console.log(` Sandbox: ${sandbox}`);\n}\n\nexport function logConnected(platform: string): void {\n console.log(`⚡️ Mikan connected to ${platform} and listening!`);\n console.log(\"\");\n}\n\nexport function logDisconnected(): void {\n console.log(\"Mikan disconnected.\");\n}\n\n// Backfill\nexport function logBackfillStart(channelCount: number): void {\n console.log(chalk.blue(`${timestamp()} [system] Backfilling ${channelCount} channels...`));\n}\n\nexport function logBackfillChannel(channelName: string, messageCount: number): void {\n console.log(chalk.blue(`${timestamp()} [system] #${channelName}: ${messageCount} messages`));\n}\n\nexport function logBackfillComplete(totalMessages: number, durationMs: number): void {\n const duration = (durationMs / 1000).toFixed(1);\n console.log(\n chalk.blue(\n `${timestamp()} [system] Backfill complete: ${totalMessages} messages in ${duration}s`,\n ),\n );\n}\n"]}
|
package/dist/main.d.ts
CHANGED
package/dist/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAEA,OAAO,iBAAiB,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport \"./instrument.js\";\n\nimport { join, resolve } from \"path\";\nimport { mkdirSync, statSync, writeFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { fileURLToPath } from \"url\";\nimport { dirname, join as pathJoin } from \"path\";\nimport type { Bot } from \"./adapter.js\";\nimport { DiscordBot } from \"./adapters/discord/index.js\";\nimport { TelegramBot } from \"./adapters/telegram/index.js\";\nimport { SlackBot as SlackBotClass } from \"./adapters/slack/index.js\";\nimport { downloadChannel } from \"./download.js\";\nimport { createEventsWatcher } from \"./events.js\";\nimport * as log from \"./log.js\";\nimport { startLinkServer } from \"./login/portal.js\";\nimport { InMemoryAdminTokenStore } from \"./admin/store.js\";\nimport { InMemoryLinkTokenStore } from \"./login/store.js\";\nimport { InMemorySessionViewTokenStore } from \"./session-view/store.js\";\nimport { DockerContainerManager } from \"./provisioner.js\";\nimport { createGlobalSettingsFile, loadAgentConfig, MissingGlobalSettingsError } from \"./config.js\";\nimport { readEnv, setEnvAliases } from \"./env.js\";\nimport { ensureDirExists, isRecord, readJsonFileIfExists } from \"./file-guards.js\";\nimport {\n SandboxError,\n parseSandboxArg,\n type SandboxConfig,\n validateSandbox,\n} from \"./sandbox/index.js\";\nimport { FileVaultManager } from \"./vault.js\";\nimport { createSessionRuntime } from \"./runtime/index.js\";\nimport { ChannelStore } from \"./store.js\";\nimport * as Sentry from \"@sentry/node\";\n\nfunction getVersion(): string {\n // Try to find package.json in the dist directory or parent\n const possiblePaths = [\n pathJoin(dirname(fileURLToPath(import.meta.url)), \"package.json\"),\n pathJoin(dirname(fileURLToPath(import.meta.url)), \"..\", \"package.json\"),\n pathJoin(process.cwd(), \"package.json\"),\n ];\n\n for (const pkgPath of possiblePaths) {\n const pkg = readJsonFileIfExists(\n pkgPath,\n (value): value is { version?: unknown } => isRecord(value),\n () => \"Ignoring package.json while resolving version\",\n );\n if (typeof pkg?.version === \"string\" && pkg.version) return pkg.version;\n }\n return \"unknown\";\n}\n\nconst SLACK_APP_TOKEN = readEnv(\"SLACK_APP_TOKEN\");\nconst SLACK_BOT_TOKEN = readEnv(\"SLACK_BOT_TOKEN\");\nconst TELEGRAM_BOT_TOKEN = readEnv(\"TELEGRAM_BOT_TOKEN\");\nconst DISCORD_BOT_TOKEN = readEnv(\"DISCORD_BOT_TOKEN\");\nconst LINK_URL = readEnv(\"LINK_URL\");\nconst LINK_PORT = readEnv(\"LINK_PORT\")\n ? parseInt(readEnv(\"LINK_PORT\") ?? \"\", 10)\n : LINK_URL\n ? 8181\n : undefined;\n\ninterface ParsedArgs {\n workingDir?: string;\n stateDir?: string;\n sandbox: SandboxConfig;\n downloadChannel?: string;\n showOnboard?: boolean;\n showVersion?: boolean;\n}\n\nfunction parseArgs(): ParsedArgs {\n const args = process.argv.slice(2);\n let sandbox: SandboxConfig = { type: \"host\" };\n let workingDir: string | undefined;\n let stateDirArg: string | undefined;\n let downloadChannelId: string | undefined;\n let showOnboard = false;\n let showVersion = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"--version\" || arg === \"-v\" || arg === \"-V\") {\n showVersion = true;\n } else if (arg === \"--onboard\") {\n showOnboard = true;\n } else if (arg.startsWith(\"--sandbox=\")) {\n sandbox = parseSandboxArg(arg.slice(\"--sandbox=\".length));\n } else if (arg === \"--sandbox\") {\n sandbox = parseSandboxArg(args[++i] || \"\");\n } else if (arg.startsWith(\"--state-dir=\")) {\n stateDirArg = arg.slice(\"--state-dir=\".length);\n } else if (arg === \"--state-dir\") {\n stateDirArg = args[++i];\n } else if (arg.startsWith(\"--download=\")) {\n downloadChannelId = arg.slice(\"--download=\".length);\n } else if (arg === \"--download\") {\n downloadChannelId = args[++i];\n } else if (!arg.startsWith(\"-\")) {\n workingDir = arg;\n }\n }\n\n return {\n workingDir: workingDir ? resolve(workingDir) : undefined,\n stateDir: stateDirArg ? resolve(stateDirArg) : undefined,\n sandbox,\n downloadChannel: downloadChannelId,\n showOnboard,\n showVersion,\n };\n}\n\nconst WORLD_WRITABLE_MODE = 0o002;\n\nfunction ensureSecureStateDir(path: string): void {\n let stat;\n try {\n stat = statSync(path);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n mkdirSync(path, { recursive: true, mode: 0o700 });\n return;\n }\n console.error(`Error: cannot access --state-dir ${path}: ${(err as Error).message}`);\n process.exit(1);\n }\n\n if (!stat.isDirectory()) {\n console.error(`Error: --state-dir ${path} exists but is not a directory`);\n process.exit(1);\n }\n\n if (stat.mode & WORLD_WRITABLE_MODE) {\n console.error(\n `Error: --state-dir ${path} is world-writable (mode ${(stat.mode & 0o777).toString(8)}). ` +\n `Credentials stored there would be exposed to other local users. ` +\n `Fix with: chmod 0700 ${path}`,\n );\n process.exit(1);\n }\n\n const euid = typeof process.geteuid === \"function\" ? process.geteuid() : undefined;\n if (euid !== undefined && stat.uid !== euid) {\n console.error(\n `Error: --state-dir ${path} is owned by uid ${stat.uid} but mikan is running as uid ${euid}. ` +\n `Run mikan as the directory owner or point --state-dir at a directory you own.`,\n );\n process.exit(1);\n }\n}\n\nfunction handleStartupError(error: unknown): never {\n if (error instanceof SandboxError) {\n for (const line of error.formatForCli()) {\n console.error(line);\n }\n process.exit(1);\n }\n if (error instanceof MissingGlobalSettingsError) {\n console.error(`Missing global settings: ${error.settingsPath}`);\n console.error(\"\");\n console.error(\"Run onboarding to create it:\");\n console.error(` mikan --onboard --state-dir ${stateDir}`);\n console.error(\"\");\n console.error(\"Then review the generated settings.json and start mikan again.\");\n process.exit(1);\n }\n if (error instanceof Error) {\n console.error(`Error: ${error.message}`);\n process.exit(1);\n }\n console.error(String(error));\n process.exit(1);\n}\n\nlet parsedArgs: ParsedArgs;\ntry {\n parsedArgs = parseArgs();\n} catch (error) {\n handleStartupError(error);\n}\n\n// Handle --version\nif (parsedArgs.showVersion) {\n console.log(getVersion());\n process.exit(0);\n}\n\n// Handle --onboard mode\nif (parsedArgs.showOnboard) {\n const stateDir = parsedArgs.stateDir ?? join(homedir(), \".mikan\");\n setEnvAliases(\"STATE_DIR\", stateDir);\n ensureSecureStateDir(stateDir);\n try {\n const settingsPath = createGlobalSettingsFile(stateDir);\n console.log(`Created global settings at ${settingsPath}`);\n console.log(\"Review the file, then start mikan with your working directory.\");\n process.exit(0);\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n}\n\n// Handle --download mode (Slack only)\nif (parsedArgs.downloadChannel) {\n if (!SLACK_BOT_TOKEN) {\n console.error(\"Missing env: SLACK_BOT_TOKEN\");\n process.exit(1);\n }\n await downloadChannel(parsedArgs.downloadChannel, SLACK_BOT_TOKEN);\n process.exit(0);\n}\n\n// Normal bot mode - require working dir\nif (!parsedArgs.workingDir) {\n console.error(\n \"Usage: mikan [--state-dir=<dir>] [--sandbox=host|container:<name>|image:<image>|firecracker:<vm-id>:<host-path>|cloudflare:<sandbox-id>] <working-directory>\",\n );\n console.error(\" mikan --onboard [--state-dir=<dir>]\");\n console.error(\" mikan --download <channel-id>\");\n process.exit(1);\n}\n\nconst { workingDir, sandbox } = { workingDir: parsedArgs.workingDir, sandbox: parsedArgs.sandbox };\nconst stateDir = parsedArgs.stateDir ?? join(homedir(), \".mikan\");\nsetEnvAliases(\"STATE_DIR\", stateDir);\nensureSecureStateDir(stateDir);\n\n// Validate platform tokens\nconst hasSlack = !!(SLACK_APP_TOKEN && SLACK_BOT_TOKEN);\nconst hasTelegram = !!TELEGRAM_BOT_TOKEN;\nconst hasDiscord = !!DISCORD_BOT_TOKEN;\n\nif (!hasSlack && !hasTelegram && !hasDiscord) {\n console.error(\n \"No platform tokens found. Set one of:\\n\" +\n \" Slack: SLACK_APP_TOKEN + SLACK_BOT_TOKEN\\n\" +\n \" Telegram: TELEGRAM_BOT_TOKEN\\n\" +\n \" Discord: DISCORD_BOT_TOKEN\",\n );\n process.exit(1);\n}\n\ntry {\n await validateSandbox(sandbox);\n} catch (error) {\n handleStartupError(error);\n}\n\nconst vaultManager = new FileVaultManager(stateDir);\nif (vaultManager.isEnabled()) {\n console.log(\n sandbox.type === \"container\"\n ? \" Vault system enabled. Container vault active.\"\n : sandbox.type === \"image\" || sandbox.type === \"firecracker\" || sandbox.type === \"cloudflare\"\n ? \" Vault system enabled. Conversation-scoped credential routing active.\"\n : \" Vault system enabled. Host mode will not inject vault env.\",\n );\n}\n\nconst startupConfig = (() => {\n try {\n return loadAgentConfig();\n } catch (error) {\n handleStartupError(error);\n }\n})();\nconst sandboxLimits =\n startupConfig.sandboxCpus || startupConfig.sandboxMemory\n ? { cpus: startupConfig.sandboxCpus, memory: startupConfig.sandboxMemory }\n : undefined;\nconst sandboxBoostLimits =\n startupConfig.sandboxBoostCpus || startupConfig.sandboxBoostMemory\n ? { cpus: startupConfig.sandboxBoostCpus, memory: startupConfig.sandboxBoostMemory }\n : undefined;\n\nconst provisioner =\n sandbox.type === \"image\"\n ? new DockerContainerManager(sandbox.image, {\n limits: sandboxLimits,\n boostLimits: sandboxBoostLimits,\n })\n : undefined;\n\nif (sandbox.type === \"image\") {\n ensureDirExists(join(workingDir, \"skills\"));\n ensureDirExists(join(workingDir, \"events\"));\n try {\n writeFileSync(join(workingDir, \"MEMORY.md\"), \"\", { flag: \"wx\" });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") throw err;\n }\n}\n\nconst linkTokenStore = new InMemoryLinkTokenStore();\nconst sessionViewTokenStore = new InMemorySessionViewTokenStore();\nconst adminTokenStore = new InMemoryAdminTokenStore();\nsetInterval(() => linkTokenStore.purge(), 5 * 60 * 1000).unref();\nsetInterval(() => sessionViewTokenStore.purge(), 5 * 60 * 1000).unref();\nsetInterval(() => adminTokenStore.purge(), 5 * 60 * 1000).unref();\n\nfunction portalBaseUrl(): string | undefined {\n if (LINK_URL) return LINK_URL.replace(/\\/+$/, \"\");\n if (LINK_PORT) return `http://localhost:${LINK_PORT}`;\n return undefined;\n}\n/** Idle timeout for managed image containers (10 minutes) */\nconst IMAGE_IDLE_TIMEOUT_MS = 10 * 60 * 1000;\n\nif (provisioner) {\n await provisioner.reconcile();\n await provisioner.stopIdle(IMAGE_IDLE_TIMEOUT_MS);\n setInterval(() => provisioner.stopIdle(IMAGE_IDLE_TIMEOUT_MS), IMAGE_IDLE_TIMEOUT_MS).unref();\n}\nconst handler = createSessionRuntime({\n workingDir,\n sandbox,\n vaultManager,\n provisioner,\n linkTokenStore,\n sessionViewTokenStore,\n adminTokenStore,\n portalBaseUrl: portalBaseUrl(),\n});\n\nconst sandboxDesc =\n sandbox.type === \"host\"\n ? \"host\"\n : sandbox.type === \"container\"\n ? `container:${sandbox.container}`\n : sandbox.type === \"image\"\n ? `image:${sandbox.image}`\n : sandbox.type === \"firecracker\"\n ? `firecracker:${sandbox.vmId}`\n : `cloudflare:${sandbox.sandboxId}`;\nlog.logStartup(workingDir, sandboxDesc);\n\nconst bots: Bot[] = [];\nconst botsByPlatform: Record<string, Bot> = {};\n\nif (hasSlack) {\n const slackBotToken = SLACK_BOT_TOKEN;\n const slackAppToken = SLACK_APP_TOKEN;\n if (!slackBotToken || !slackAppToken) {\n throw new Error(\"Slack startup requires both SLACK_APP_TOKEN and SLACK_BOT_TOKEN\");\n }\n const sharedStore = new ChannelStore({ workingDir, botToken: slackBotToken });\n const slackBot = new SlackBotClass(handler, {\n appToken: slackAppToken,\n botToken: slackBotToken,\n workingDir,\n store: sharedStore,\n });\n bots.push(slackBot);\n botsByPlatform.slack = slackBot;\n log.logInfo(\"Platform: Slack\");\n}\nif (hasTelegram) {\n const telegramToken = TELEGRAM_BOT_TOKEN;\n if (!telegramToken) {\n throw new Error(\"Telegram startup requires TELEGRAM_BOT_TOKEN\");\n }\n const telegramBot = new TelegramBot(handler, {\n token: telegramToken,\n workingDir,\n });\n bots.push(telegramBot);\n botsByPlatform.telegram = telegramBot;\n log.logInfo(\"Platform: Telegram\");\n}\nif (hasDiscord) {\n const discordToken = DISCORD_BOT_TOKEN;\n if (!discordToken) {\n throw new Error(\"Discord startup requires DISCORD_BOT_TOKEN\");\n }\n const discordBot = new DiscordBot(handler, {\n token: discordToken,\n workingDir,\n });\n bots.push(discordBot);\n botsByPlatform.discord = discordBot;\n log.logInfo(\"Platform: Discord\");\n}\n\nif (LINK_PORT) {\n startLinkServer(\n LINK_PORT,\n linkTokenStore,\n vaultManager,\n async (platform, conversationId, message) => {\n const bot = botsByPlatform[platform];\n if (bot) await bot.postMessage(conversationId, message);\n },\n sessionViewTokenStore,\n { handler, botsByPlatform },\n { adminTokenStore, workingDir, runtime: handler, sandbox, botsByPlatform },\n );\n}\n\n// Start events watcher with explicit platform routing\nconst eventsWatcher = createEventsWatcher(workingDir, botsByPlatform);\nconst slackBot = botsByPlatform.slack as SlackBotClass | undefined;\nif (slackBot) {\n slackBot.setEventsWatcher(eventsWatcher);\n}\neventsWatcher.start();\n\n// Handle shutdown\nasync function shutdown(): Promise<void> {\n await handler.shutdown();\n eventsWatcher.stop();\n await Sentry.close(5000);\n process.exit(0);\n}\n\nprocess.on(\"SIGINT\", shutdown);\nprocess.on(\"SIGTERM\", shutdown);\n\n// Start all bots\nawait Promise.all(\n bots.map((bot) =>\n bot.start().catch((err) => {\n log.logWarning(\"Failed to start bot\", err instanceof Error ? err.message : String(err));\n process.exit(1);\n }),\n ),\n);\n"]}
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAEA,OAAO,+BAA+B,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport \"./observability/instrument.js\";\n\nimport { join, resolve } from \"path\";\nimport { mkdirSync, statSync, writeFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { fileURLToPath } from \"url\";\nimport { dirname, join as pathJoin } from \"path\";\nimport type { Bot } from \"./adapter.js\";\nimport { DiscordBot } from \"./adapters/discord/bot.js\";\nimport { TelegramBot } from \"./adapters/telegram/bot.js\";\nimport { SlackBot as SlackBotClass } from \"./adapters/slack/bot.js\";\nimport { downloadChannel } from \"./download.js\";\nimport { EventsWatcher } from \"./events.js\";\nimport * as log from \"./log.js\";\nimport { startLinkServer } from \"./web/login/portal.js\";\nimport { InMemoryAdminTokenStore } from \"./web/admin/store.js\";\nimport { InMemoryLinkTokenStore } from \"./web/login/store.js\";\nimport { InMemorySessionViewTokenStore } from \"./web/session-view/store.js\";\nimport { DockerContainerManager } from \"./provisioner.js\";\nimport {\n createGlobalSettingsFile,\n loadGlobalSettings,\n MissingGlobalSettingsError,\n} from \"./config.js\";\nimport { readEnv, setEnvAliases } from \"./utils/env.js\";\nimport { ensureDirExists, isRecord, readJsonFileIfExists } from \"./utils/file-guards.js\";\nimport {\n SandboxError,\n parseSandboxArg,\n type SandboxConfig,\n validateSandbox,\n} from \"./sandbox/index.js\";\nimport { FileVaultManager } from \"./vault/index.js\";\nimport { createSessionRuntime } from \"./runtime/session-runtime.js\";\nimport { ChannelStore } from \"./store.js\";\nimport * as Sentry from \"@sentry/node\";\n\nfunction getVersion(): string {\n // Try to find package.json in the dist directory or parent\n const possiblePaths = [\n pathJoin(dirname(fileURLToPath(import.meta.url)), \"package.json\"),\n pathJoin(dirname(fileURLToPath(import.meta.url)), \"..\", \"package.json\"),\n pathJoin(process.cwd(), \"package.json\"),\n ];\n\n for (const pkgPath of possiblePaths) {\n const pkg = readJsonFileIfExists(\n pkgPath,\n (value): value is { version?: unknown } => isRecord(value),\n () => \"Ignoring package.json while resolving version\",\n );\n if (typeof pkg?.version === \"string\" && pkg.version) return pkg.version;\n }\n return \"unknown\";\n}\n\nconst SLACK_APP_TOKEN = readEnv(\"SLACK_APP_TOKEN\");\nconst SLACK_BOT_TOKEN = readEnv(\"SLACK_BOT_TOKEN\");\nconst TELEGRAM_BOT_TOKEN = readEnv(\"TELEGRAM_BOT_TOKEN\");\nconst DISCORD_BOT_TOKEN = readEnv(\"DISCORD_BOT_TOKEN\");\nconst LINK_URL = readEnv(\"LINK_URL\");\nconst LINK_PORT = readEnv(\"LINK_PORT\")\n ? parseInt(readEnv(\"LINK_PORT\") ?? \"\", 10)\n : LINK_URL\n ? 8181\n : undefined;\n\ninterface ParsedArgs {\n workingDir?: string;\n stateDir?: string;\n sandbox: SandboxConfig;\n downloadChannel?: string;\n showOnboard?: boolean;\n showVersion?: boolean;\n}\n\nfunction parseArgs(): ParsedArgs {\n const args = process.argv.slice(2);\n let sandbox: SandboxConfig = { type: \"host\" };\n let workingDir: string | undefined;\n let stateDirArg: string | undefined;\n let downloadChannelId: string | undefined;\n let showOnboard = false;\n let showVersion = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"--version\" || arg === \"-v\" || arg === \"-V\") {\n showVersion = true;\n } else if (arg === \"--onboard\") {\n showOnboard = true;\n } else if (arg.startsWith(\"--sandbox=\")) {\n sandbox = parseSandboxArg(arg.slice(\"--sandbox=\".length));\n } else if (arg === \"--sandbox\") {\n sandbox = parseSandboxArg(args[++i] || \"\");\n } else if (arg.startsWith(\"--state-dir=\")) {\n stateDirArg = arg.slice(\"--state-dir=\".length);\n } else if (arg === \"--state-dir\") {\n stateDirArg = args[++i];\n } else if (arg.startsWith(\"--download=\")) {\n downloadChannelId = arg.slice(\"--download=\".length);\n } else if (arg === \"--download\") {\n downloadChannelId = args[++i];\n } else if (!arg.startsWith(\"-\")) {\n workingDir = arg;\n }\n }\n\n return {\n workingDir: workingDir ? resolve(workingDir) : undefined,\n stateDir: stateDirArg ? resolve(stateDirArg) : undefined,\n sandbox,\n downloadChannel: downloadChannelId,\n showOnboard,\n showVersion,\n };\n}\n\nconst WORLD_WRITABLE_MODE = 0o002;\n\nfunction ensureSecureStateDir(path: string): void {\n let stat;\n try {\n stat = statSync(path);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n mkdirSync(path, { recursive: true, mode: 0o700 });\n return;\n }\n console.error(`Error: cannot access --state-dir ${path}: ${(err as Error).message}`);\n process.exit(1);\n }\n\n if (!stat.isDirectory()) {\n console.error(`Error: --state-dir ${path} exists but is not a directory`);\n process.exit(1);\n }\n\n if (stat.mode & WORLD_WRITABLE_MODE) {\n console.error(\n `Error: --state-dir ${path} is world-writable (mode ${(stat.mode & 0o777).toString(8)}). ` +\n `Credentials stored there would be exposed to other local users. ` +\n `Fix with: chmod 0700 ${path}`,\n );\n process.exit(1);\n }\n\n const euid = typeof process.geteuid === \"function\" ? process.geteuid() : undefined;\n if (euid !== undefined && stat.uid !== euid) {\n console.error(\n `Error: --state-dir ${path} is owned by uid ${stat.uid} but mikan is running as uid ${euid}. ` +\n `Run mikan as the directory owner or point --state-dir at a directory you own.`,\n );\n process.exit(1);\n }\n}\n\nfunction handleStartupError(error: unknown): never {\n if (error instanceof SandboxError) {\n for (const line of error.formatForCli()) {\n console.error(line);\n }\n process.exit(1);\n }\n if (error instanceof MissingGlobalSettingsError) {\n console.error(`Missing global settings: ${error.settingsPath}`);\n console.error(\"\");\n console.error(\"Run onboarding to create it:\");\n console.error(` mikan --onboard --state-dir ${stateDir}`);\n console.error(\"\");\n console.error(\"Then review the generated settings.json and start mikan again.\");\n process.exit(1);\n }\n if (error instanceof Error) {\n console.error(`Error: ${error.message}`);\n process.exit(1);\n }\n console.error(String(error));\n process.exit(1);\n}\n\nlet parsedArgs: ParsedArgs;\ntry {\n parsedArgs = parseArgs();\n} catch (error) {\n handleStartupError(error);\n}\n\n// Handle --version\nif (parsedArgs.showVersion) {\n console.log(getVersion());\n process.exit(0);\n}\n\n// Handle --onboard mode\nif (parsedArgs.showOnboard) {\n const stateDir = parsedArgs.stateDir ?? join(homedir(), \".mikan\");\n setEnvAliases(\"STATE_DIR\", stateDir);\n ensureSecureStateDir(stateDir);\n try {\n const settingsPath = createGlobalSettingsFile(stateDir);\n console.log(`Created global settings at ${settingsPath}`);\n console.log(\"Review the file, then start mikan with your working directory.\");\n process.exit(0);\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n}\n\n// Handle --download mode (Slack only)\nif (parsedArgs.downloadChannel) {\n if (!SLACK_BOT_TOKEN) {\n console.error(\"Missing env: SLACK_BOT_TOKEN\");\n process.exit(1);\n }\n await downloadChannel(parsedArgs.downloadChannel, SLACK_BOT_TOKEN);\n process.exit(0);\n}\n\n// Normal bot mode - require working dir\nif (!parsedArgs.workingDir) {\n console.error(\n \"Usage: mikan [--state-dir=<dir>] [--sandbox=host|container:<name>|image:<image>|firecracker:<vm-id>:<host-path>|cloudflare:<sandbox-id>] <working-directory>\",\n );\n console.error(\" mikan --onboard [--state-dir=<dir>]\");\n console.error(\" mikan --download <channel-id>\");\n process.exit(1);\n}\n\nconst { workingDir, sandbox } = { workingDir: parsedArgs.workingDir, sandbox: parsedArgs.sandbox };\nconst stateDir = parsedArgs.stateDir ?? join(homedir(), \".mikan\");\nsetEnvAliases(\"STATE_DIR\", stateDir);\nensureSecureStateDir(stateDir);\n\n// Validate platform tokens\nconst hasSlack = !!(SLACK_APP_TOKEN && SLACK_BOT_TOKEN);\nconst hasTelegram = !!TELEGRAM_BOT_TOKEN;\nconst hasDiscord = !!DISCORD_BOT_TOKEN;\n\nif (!hasSlack && !hasTelegram && !hasDiscord) {\n console.error(\n \"No platform tokens found. Set one of:\\n\" +\n \" Slack: SLACK_APP_TOKEN + SLACK_BOT_TOKEN\\n\" +\n \" Telegram: TELEGRAM_BOT_TOKEN\\n\" +\n \" Discord: DISCORD_BOT_TOKEN\",\n );\n process.exit(1);\n}\n\ntry {\n await validateSandbox(sandbox);\n} catch (error) {\n handleStartupError(error);\n}\n\nconst vaultManager = new FileVaultManager(stateDir);\nif (vaultManager.isEnabled()) {\n console.log(\n sandbox.type === \"container\"\n ? \" Vault system enabled. Container vault active.\"\n : sandbox.type === \"image\" || sandbox.type === \"firecracker\" || sandbox.type === \"cloudflare\"\n ? \" Vault system enabled. Conversation-scoped credential routing active.\"\n : \" Vault system enabled. Host mode will not inject vault env.\",\n );\n}\n\nconst startupConfig = (() => {\n try {\n return loadGlobalSettings();\n } catch (error) {\n handleStartupError(error);\n }\n})();\nconst sandboxLimits =\n startupConfig.sandboxCpus || startupConfig.sandboxMemory\n ? { cpus: startupConfig.sandboxCpus, memory: startupConfig.sandboxMemory }\n : undefined;\nconst sandboxBoostLimits =\n startupConfig.sandboxBoostCpus || startupConfig.sandboxBoostMemory\n ? { cpus: startupConfig.sandboxBoostCpus, memory: startupConfig.sandboxBoostMemory }\n : undefined;\n\nconst provisioner =\n sandbox.type === \"image\"\n ? new DockerContainerManager(sandbox.image, {\n limits: sandboxLimits,\n boostLimits: sandboxBoostLimits,\n })\n : undefined;\n\nif (sandbox.type === \"image\") {\n ensureDirExists(join(workingDir, \"skills\"));\n ensureDirExists(join(workingDir, \"events\"));\n try {\n writeFileSync(join(workingDir, \"MEMORY.md\"), \"\", { flag: \"wx\" });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") throw err;\n }\n}\n\nconst linkTokenStore = new InMemoryLinkTokenStore();\nconst sessionViewTokenStore = new InMemorySessionViewTokenStore();\nconst adminTokenStore = new InMemoryAdminTokenStore();\nsetInterval(() => linkTokenStore.purge(), 5 * 60 * 1000).unref();\nsetInterval(() => sessionViewTokenStore.purge(), 5 * 60 * 1000).unref();\nsetInterval(() => adminTokenStore.purge(), 5 * 60 * 1000).unref();\n\nfunction portalBaseUrl(): string | undefined {\n if (LINK_URL) return LINK_URL.replace(/\\/+$/, \"\");\n if (LINK_PORT) return `http://localhost:${LINK_PORT}`;\n return undefined;\n}\n/** Idle timeout for managed image containers (10 minutes) */\nconst IMAGE_IDLE_TIMEOUT_MS = 10 * 60 * 1000;\n\nif (provisioner) {\n await provisioner.reconcile();\n await provisioner.stopIdle(IMAGE_IDLE_TIMEOUT_MS);\n setInterval(() => provisioner.stopIdle(IMAGE_IDLE_TIMEOUT_MS), IMAGE_IDLE_TIMEOUT_MS).unref();\n}\nconst handler = createSessionRuntime({\n workingDir,\n sandbox,\n vaultManager,\n provisioner,\n linkTokenStore,\n sessionViewTokenStore,\n adminTokenStore,\n portalBaseUrl: portalBaseUrl(),\n});\n\nconst sandboxDesc =\n sandbox.type === \"host\"\n ? \"host\"\n : sandbox.type === \"container\"\n ? `container:${sandbox.container}`\n : sandbox.type === \"image\"\n ? `image:${sandbox.image}`\n : sandbox.type === \"firecracker\"\n ? `firecracker:${sandbox.vmId}`\n : `cloudflare:${sandbox.sandboxId}`;\nlog.logStartup(workingDir, sandboxDesc);\n\nconst bots: Bot[] = [];\nconst botsByPlatform: Record<string, Bot> = {};\n\nif (hasSlack) {\n const slackBotToken = SLACK_BOT_TOKEN;\n const slackAppToken = SLACK_APP_TOKEN;\n if (!slackBotToken || !slackAppToken) {\n throw new Error(\"Slack startup requires both SLACK_APP_TOKEN and SLACK_BOT_TOKEN\");\n }\n const sharedStore = new ChannelStore({ workingDir, botToken: slackBotToken });\n const slackBot = new SlackBotClass(handler, {\n appToken: slackAppToken,\n botToken: slackBotToken,\n workingDir,\n store: sharedStore,\n });\n bots.push(slackBot);\n botsByPlatform.slack = slackBot;\n log.logInfo(\"Platform: Slack\");\n}\nif (hasTelegram) {\n const telegramToken = TELEGRAM_BOT_TOKEN;\n if (!telegramToken) {\n throw new Error(\"Telegram startup requires TELEGRAM_BOT_TOKEN\");\n }\n const telegramBot = new TelegramBot(handler, {\n token: telegramToken,\n workingDir,\n });\n bots.push(telegramBot);\n botsByPlatform.telegram = telegramBot;\n log.logInfo(\"Platform: Telegram\");\n}\nif (hasDiscord) {\n const discordToken = DISCORD_BOT_TOKEN;\n if (!discordToken) {\n throw new Error(\"Discord startup requires DISCORD_BOT_TOKEN\");\n }\n const discordBot = new DiscordBot(handler, {\n token: discordToken,\n workingDir,\n });\n bots.push(discordBot);\n botsByPlatform.discord = discordBot;\n log.logInfo(\"Platform: Discord\");\n}\n\nif (LINK_PORT) {\n startLinkServer(\n LINK_PORT,\n linkTokenStore,\n vaultManager,\n async (platform, conversationId, message) => {\n const bot = botsByPlatform[platform];\n if (bot) await bot.postMessage(conversationId, message);\n },\n sessionViewTokenStore,\n { handler, botsByPlatform },\n { adminTokenStore, workingDir, runtime: handler, sandbox, botsByPlatform },\n );\n}\n\n// Start events watcher with explicit platform routing\nconst eventsWatcher = new EventsWatcher(join(workingDir, \"events\"), botsByPlatform);\nconst slackBot = botsByPlatform.slack as SlackBotClass | undefined;\nif (slackBot) {\n slackBot.setEventsWatcher(eventsWatcher);\n}\neventsWatcher.start();\n\n// Handle shutdown\nasync function shutdown(): Promise<void> {\n await handler.shutdown();\n eventsWatcher.stop();\n await Sentry.close(5000);\n process.exit(0);\n}\n\nprocess.on(\"SIGINT\", shutdown);\nprocess.on(\"SIGTERM\", shutdown);\n\n// Start all bots\nawait Promise.all(\n bots.map((bot) =>\n bot.start().catch((err) => {\n log.logWarning(\"Failed to start bot\", err instanceof Error ? err.message : String(err));\n process.exit(1);\n }),\n ),\n);\n"]}
|
package/dist/main.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./instrument.js";
|
|
2
|
+
import "./observability/instrument.js";
|
|
3
3
|
import { join, resolve } from "path";
|
|
4
4
|
import { mkdirSync, statSync, writeFileSync } from "fs";
|
|
5
5
|
import { homedir } from "os";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { dirname, join as pathJoin } from "path";
|
|
8
|
-
import { DiscordBot } from "./adapters/discord/
|
|
9
|
-
import { TelegramBot } from "./adapters/telegram/
|
|
10
|
-
import { SlackBot as SlackBotClass } from "./adapters/slack/
|
|
8
|
+
import { DiscordBot } from "./adapters/discord/bot.js";
|
|
9
|
+
import { TelegramBot } from "./adapters/telegram/bot.js";
|
|
10
|
+
import { SlackBot as SlackBotClass } from "./adapters/slack/bot.js";
|
|
11
11
|
import { downloadChannel } from "./download.js";
|
|
12
|
-
import {
|
|
12
|
+
import { EventsWatcher } from "./events.js";
|
|
13
13
|
import * as log from "./log.js";
|
|
14
|
-
import { startLinkServer } from "./login/portal.js";
|
|
15
|
-
import { InMemoryAdminTokenStore } from "./admin/store.js";
|
|
16
|
-
import { InMemoryLinkTokenStore } from "./login/store.js";
|
|
17
|
-
import { InMemorySessionViewTokenStore } from "./session-view/store.js";
|
|
14
|
+
import { startLinkServer } from "./web/login/portal.js";
|
|
15
|
+
import { InMemoryAdminTokenStore } from "./web/admin/store.js";
|
|
16
|
+
import { InMemoryLinkTokenStore } from "./web/login/store.js";
|
|
17
|
+
import { InMemorySessionViewTokenStore } from "./web/session-view/store.js";
|
|
18
18
|
import { DockerContainerManager } from "./provisioner.js";
|
|
19
|
-
import { createGlobalSettingsFile,
|
|
20
|
-
import { readEnv, setEnvAliases } from "./env.js";
|
|
21
|
-
import { ensureDirExists, isRecord, readJsonFileIfExists } from "./file-guards.js";
|
|
19
|
+
import { createGlobalSettingsFile, loadGlobalSettings, MissingGlobalSettingsError, } from "./config.js";
|
|
20
|
+
import { readEnv, setEnvAliases } from "./utils/env.js";
|
|
21
|
+
import { ensureDirExists, isRecord, readJsonFileIfExists } from "./utils/file-guards.js";
|
|
22
22
|
import { SandboxError, parseSandboxArg, validateSandbox, } from "./sandbox/index.js";
|
|
23
|
-
import { FileVaultManager } from "./vault.js";
|
|
24
|
-
import { createSessionRuntime } from "./runtime/
|
|
23
|
+
import { FileVaultManager } from "./vault/index.js";
|
|
24
|
+
import { createSessionRuntime } from "./runtime/session-runtime.js";
|
|
25
25
|
import { ChannelStore } from "./store.js";
|
|
26
26
|
import * as Sentry from "@sentry/node";
|
|
27
27
|
function getVersion() {
|
|
@@ -225,7 +225,7 @@ if (vaultManager.isEnabled()) {
|
|
|
225
225
|
}
|
|
226
226
|
const startupConfig = (() => {
|
|
227
227
|
try {
|
|
228
|
-
return
|
|
228
|
+
return loadGlobalSettings();
|
|
229
229
|
}
|
|
230
230
|
catch (error) {
|
|
231
231
|
handleStartupError(error);
|
|
@@ -347,7 +347,7 @@ if (LINK_PORT) {
|
|
|
347
347
|
}, sessionViewTokenStore, { handler, botsByPlatform }, { adminTokenStore, workingDir, runtime: handler, sandbox, botsByPlatform });
|
|
348
348
|
}
|
|
349
349
|
// Start events watcher with explicit platform routing
|
|
350
|
-
const eventsWatcher =
|
|
350
|
+
const eventsWatcher = new EventsWatcher(join(workingDir, "events"), botsByPlatform);
|
|
351
351
|
const slackBot = botsByPlatform.slack;
|
|
352
352
|
if (slackBot) {
|
|
353
353
|
slackBot.setEventsWatcher(eventsWatcher);
|