@geminixiang/mikan 1.0.0-beta.2 → 1.0.0-beta.20
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 +354 -0
- package/README.md +42 -16
- package/dist/adapter.d.ts +1 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +1 -0
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +36 -67
- 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 +17 -42
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/github/bot.d.ts +148 -0
- package/dist/adapters/github/bot.d.ts.map +1 -0
- package/dist/adapters/github/bot.js +1031 -0
- package/dist/adapters/github/bot.js.map +1 -0
- package/dist/adapters/github/client.d.ts +118 -0
- package/dist/adapters/github/client.d.ts.map +1 -0
- package/dist/adapters/github/client.js +309 -0
- package/dist/adapters/github/client.js.map +1 -0
- package/dist/adapters/github/cloudbuild.d.ts +24 -0
- package/dist/adapters/github/cloudbuild.d.ts.map +1 -0
- package/dist/adapters/github/cloudbuild.js +71 -0
- package/dist/adapters/github/cloudbuild.js.map +1 -0
- package/dist/adapters/github/context.d.ts +9 -0
- package/dist/adapters/github/context.d.ts.map +1 -0
- package/dist/adapters/github/context.js +175 -0
- package/dist/adapters/github/context.js.map +1 -0
- package/dist/adapters/github/gcp-auth.d.ts +31 -0
- package/dist/adapters/github/gcp-auth.d.ts.map +1 -0
- package/dist/adapters/github/gcp-auth.js +196 -0
- package/dist/adapters/github/gcp-auth.js.map +1 -0
- package/dist/adapters/github/ids.d.ts +34 -0
- package/dist/adapters/github/ids.d.ts.map +1 -0
- package/dist/adapters/github/ids.js +53 -0
- package/dist/adapters/github/ids.js.map +1 -0
- package/dist/adapters/github/repo.d.ts +30 -0
- package/dist/adapters/github/repo.d.ts.map +1 -0
- package/dist/adapters/github/repo.js +136 -0
- package/dist/adapters/github/repo.js.map +1 -0
- package/dist/adapters/github/tool-pack.d.ts +14 -0
- package/dist/adapters/github/tool-pack.d.ts.map +1 -0
- package/dist/adapters/github/tool-pack.js +56 -0
- package/dist/adapters/github/tool-pack.js.map +1 -0
- package/dist/adapters/github/tools/checks.d.ts +24 -0
- package/dist/adapters/github/tools/checks.d.ts.map +1 -0
- package/dist/adapters/github/tools/checks.js +116 -0
- package/dist/adapters/github/tools/checks.js.map +1 -0
- package/dist/adapters/github/tools/issue.d.ts +22 -0
- package/dist/adapters/github/tools/issue.d.ts.map +1 -0
- package/dist/adapters/github/tools/issue.js +59 -0
- package/dist/adapters/github/tools/issue.js.map +1 -0
- package/dist/adapters/github/tools/pr.d.ts +22 -0
- package/dist/adapters/github/tools/pr.d.ts.map +1 -0
- package/dist/adapters/github/tools/pr.js +59 -0
- package/dist/adapters/github/tools/pr.js.map +1 -0
- package/dist/adapters/github/tools/read.d.ts +22 -0
- package/dist/adapters/github/tools/read.d.ts.map +1 -0
- package/dist/adapters/github/tools/read.js +152 -0
- package/dist/adapters/github/tools/read.js.map +1 -0
- package/dist/adapters/github/tools/review-reply.d.ts +19 -0
- package/dist/adapters/github/tools/review-reply.d.ts.map +1 -0
- package/dist/adapters/github/tools/review-reply.js +49 -0
- package/dist/adapters/github/tools/review-reply.js.map +1 -0
- package/dist/adapters/github/tools/sync.d.ts +17 -0
- package/dist/adapters/github/tools/sync.d.ts.map +1 -0
- package/dist/adapters/github/tools/sync.js +45 -0
- package/dist/adapters/github/tools/sync.js.map +1 -0
- package/dist/adapters/github/types.d.ts +350 -0
- package/dist/adapters/github/types.d.ts.map +1 -0
- package/dist/adapters/github/types.js +2 -0
- package/dist/adapters/github/types.js.map +1 -0
- package/dist/adapters/intake.d.ts +16 -5
- package/dist/adapters/intake.d.ts.map +1 -1
- package/dist/adapters/intake.js +79 -22
- package/dist/adapters/intake.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +8 -6
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +81 -133
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/context.d.ts.map +1 -1
- package/dist/adapters/slack/context.js +3 -14
- package/dist/adapters/slack/context.js.map +1 -1
- package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
- package/dist/adapters/slack/response-lifecycle.js +14 -17
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/slack/session.d.ts.map +1 -1
- package/dist/adapters/slack/session.js +5 -8
- package/dist/adapters/slack/session.js.map +1 -1
- package/dist/adapters/streaming.d.ts +4 -0
- package/dist/adapters/streaming.d.ts.map +1 -1
- package/dist/adapters/streaming.js +11 -0
- package/dist/adapters/streaming.js.map +1 -1
- package/dist/adapters/telegram/bot.d.ts +1 -2
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +27 -62
- 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 +8 -27
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/adapters/types.d.ts +28 -2
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js.map +1 -1
- package/dist/agent.d.ts +38 -14
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +358 -224
- package/dist/agent.js.map +1 -1
- package/dist/cli/download.d.ts.map +1 -0
- package/dist/cli/download.js.map +1 -0
- package/dist/cli/ext-git.d.ts +22 -0
- package/dist/cli/ext-git.d.ts.map +1 -0
- package/dist/cli/ext-git.js +76 -0
- package/dist/cli/ext-git.js.map +1 -0
- package/dist/cli/ext.d.ts +2 -0
- package/dist/cli/ext.d.ts.map +1 -0
- package/dist/cli/ext.js +217 -0
- package/dist/cli/ext.js.map +1 -0
- package/dist/commands/admin.d.ts.map +1 -1
- package/dist/commands/admin.js +2 -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 +2 -6
- package/dist/commands/auto-reply.js.map +1 -1
- package/dist/commands/extensions.d.ts.map +1 -1
- package/dist/commands/extensions.js +16 -6
- package/dist/commands/extensions.js.map +1 -1
- package/dist/commands/login.d.ts +2 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +30 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/manifest.d.ts +72 -0
- package/dist/commands/manifest.d.ts.map +1 -0
- package/dist/commands/manifest.js +121 -0
- package/dist/commands/manifest.js.map +1 -0
- package/dist/commands/model.d.ts.map +1 -1
- package/dist/commands/model.js +3 -1
- package/dist/commands/model.js.map +1 -1
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +2 -1
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +16 -12
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/commands/text.d.ts +2 -0
- package/dist/commands/text.d.ts.map +1 -0
- package/dist/commands/text.js +16 -0
- package/dist/commands/text.js.map +1 -0
- package/dist/commands/types.d.ts +14 -1
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +90 -54
- package/dist/config.js.map +1 -1
- package/dist/events.d.ts +10 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +14 -5
- package/dist/events.js.map +1 -1
- package/dist/execution-resolver.d.ts +3 -2
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +28 -12
- package/dist/execution-resolver.js.map +1 -1
- package/dist/harness/extensions/loader.d.ts +39 -9
- package/dist/harness/extensions/loader.d.ts.map +1 -1
- package/dist/harness/extensions/loader.js +258 -54
- package/dist/harness/extensions/loader.js.map +1 -1
- package/dist/harness/extensions/registry.d.ts +48 -1
- package/dist/harness/extensions/registry.d.ts.map +1 -1
- package/dist/harness/extensions/registry.js +146 -0
- package/dist/harness/extensions/registry.js.map +1 -1
- package/dist/harness/extensions/types.d.ts +161 -14
- package/dist/harness/extensions/types.d.ts.map +1 -1
- package/dist/harness/extensions/types.js.map +1 -1
- package/dist/harness/index.d.ts +5 -5
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +2 -2
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/models.d.ts +5 -0
- package/dist/harness/models.d.ts.map +1 -1
- package/dist/harness/models.js +10 -0
- package/dist/harness/models.js.map +1 -1
- package/dist/harness/runner.d.ts +21 -2
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +80 -22
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session-store.d.ts +4 -1
- package/dist/harness/session-store.d.ts.map +1 -1
- package/dist/harness/session-store.js +11 -2
- package/dist/harness/session-store.js.map +1 -1
- package/dist/harness/subagent-runner.d.ts +17 -0
- package/dist/harness/subagent-runner.d.ts.map +1 -0
- package/dist/harness/subagent-runner.js +307 -0
- package/dist/harness/subagent-runner.js.map +1 -0
- package/dist/harness/types.d.ts +53 -0
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.js +232 -29
- package/dist/main.js.map +1 -1
- package/dist/provisioner.d.ts.map +1 -1
- package/dist/provisioner.js +2 -5
- package/dist/provisioner.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +264 -41
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +32 -5
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/cloudflare.d.ts +2 -0
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +7 -0
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts +3 -0
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +8 -2
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/firecracker.d.ts +2 -0
- package/dist/sandbox/firecracker.d.ts.map +1 -1
- package/dist/sandbox/firecracker.js +7 -1
- package/dist/sandbox/firecracker.js.map +1 -1
- package/dist/sandbox/gondolin-fleet.d.ts +104 -0
- package/dist/sandbox/gondolin-fleet.d.ts.map +1 -0
- package/dist/sandbox/gondolin-fleet.js +330 -0
- package/dist/sandbox/gondolin-fleet.js.map +1 -0
- package/dist/sandbox/gondolin-gateway.d.ts +85 -0
- package/dist/sandbox/gondolin-gateway.d.ts.map +1 -0
- package/dist/sandbox/gondolin-gateway.js +400 -0
- package/dist/sandbox/gondolin-gateway.js.map +1 -0
- package/dist/sandbox/gondolin-inventory.d.ts +89 -0
- package/dist/sandbox/gondolin-inventory.d.ts.map +1 -0
- package/dist/sandbox/gondolin-inventory.js +267 -0
- package/dist/sandbox/gondolin-inventory.js.map +1 -0
- package/dist/sandbox/gondolin-join.d.ts +62 -0
- package/dist/sandbox/gondolin-join.d.ts.map +1 -0
- package/dist/sandbox/gondolin-join.js +261 -0
- package/dist/sandbox/gondolin-join.js.map +1 -0
- package/dist/sandbox/gondolin-nfs-advisory.d.ts +15 -0
- package/dist/sandbox/gondolin-nfs-advisory.d.ts.map +1 -0
- package/dist/sandbox/gondolin-nfs-advisory.js +60 -0
- package/dist/sandbox/gondolin-nfs-advisory.js.map +1 -0
- package/dist/sandbox/gondolin-placement.d.ts +32 -0
- package/dist/sandbox/gondolin-placement.d.ts.map +1 -0
- package/dist/sandbox/gondolin-placement.js +83 -0
- package/dist/sandbox/gondolin-placement.js.map +1 -0
- package/dist/sandbox/gondolin-remote.d.ts +73 -0
- package/dist/sandbox/gondolin-remote.d.ts.map +1 -0
- package/dist/sandbox/gondolin-remote.js +352 -0
- package/dist/sandbox/gondolin-remote.js.map +1 -0
- package/dist/sandbox/gondolin-worker-client.d.ts +139 -0
- package/dist/sandbox/gondolin-worker-client.d.ts.map +1 -0
- package/dist/sandbox/gondolin-worker-client.js +325 -0
- package/dist/sandbox/gondolin-worker-client.js.map +1 -0
- package/dist/sandbox/gondolin-worker-main.d.ts +2 -0
- package/dist/sandbox/gondolin-worker-main.d.ts.map +1 -0
- package/dist/sandbox/gondolin-worker-main.js +22 -0
- package/dist/sandbox/gondolin-worker-main.js.map +1 -0
- package/dist/sandbox/gondolin-worker.d.ts +55 -0
- package/dist/sandbox/gondolin-worker.d.ts.map +1 -0
- package/dist/sandbox/gondolin-worker.js +201 -0
- package/dist/sandbox/gondolin-worker.js.map +1 -0
- package/dist/sandbox/gondolin.d.ts +52 -0
- package/dist/sandbox/gondolin.d.ts.map +1 -0
- package/dist/sandbox/gondolin.js +425 -0
- package/dist/sandbox/gondolin.js.map +1 -0
- package/dist/sandbox/host.d.ts +2 -0
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +11 -0
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/identity.d.ts +21 -0
- package/dist/sandbox/identity.d.ts.map +1 -0
- package/dist/sandbox/identity.js +36 -0
- package/dist/sandbox/identity.js.map +1 -0
- package/dist/sandbox/index.d.ts +4 -3
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +5 -3
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +26 -1
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +11 -0
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +35 -0
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/sessions/agent-memory-file-manager.d.ts.map +1 -1
- package/dist/sessions/agent-memory-file-manager.js +16 -30
- package/dist/sessions/agent-memory-file-manager.js.map +1 -1
- package/dist/sessions/history-line.d.ts +20 -0
- package/dist/sessions/history-line.d.ts.map +1 -0
- package/dist/sessions/history-line.js +24 -0
- package/dist/sessions/history-line.js.map +1 -0
- package/dist/sessions/policy.d.ts.map +1 -1
- package/dist/sessions/policy.js +5 -3
- package/dist/sessions/policy.js.map +1 -1
- package/dist/sessions/session-key.d.ts +31 -0
- package/dist/sessions/session-key.d.ts.map +1 -0
- package/dist/sessions/session-key.js +44 -0
- package/dist/sessions/session-key.js.map +1 -0
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +2 -2
- package/dist/sessions/store.js.map +1 -1
- package/dist/tools/bash.d.ts +3 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +24 -17
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +9 -12
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/event.d.ts +1 -1
- package/dist/tools/event.d.ts.map +1 -1
- package/dist/tools/event.js +33 -4
- package/dist/tools/event.js.map +1 -1
- package/dist/tools/generate-image.d.ts +17 -0
- package/dist/tools/generate-image.d.ts.map +1 -0
- package/dist/tools/generate-image.js +63 -0
- package/dist/tools/generate-image.js.map +1 -0
- package/dist/tools/index.d.ts +16 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +27 -3
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/react.d.ts +15 -0
- package/dist/tools/react.d.ts.map +1 -0
- package/dist/tools/react.js +40 -0
- package/dist/tools/react.js.map +1 -0
- package/dist/tools/sandbox.d.ts +2 -2
- package/dist/tools/sandbox.d.ts.map +1 -1
- package/dist/tools/sandbox.js +8 -7
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/tools/subagent.d.ts +69 -0
- package/dist/tools/subagent.d.ts.map +1 -0
- package/dist/tools/subagent.js +286 -0
- package/dist/tools/subagent.js.map +1 -0
- package/dist/tools/types.d.ts +34 -1
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +1 -8
- package/dist/tools/write.js.map +1 -1
- package/dist/trigger.d.ts.map +1 -1
- package/dist/trigger.js +1 -2
- package/dist/trigger.js.map +1 -1
- package/dist/types.d.ts +139 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/disabled.d.ts +9 -0
- package/dist/vault/disabled.d.ts.map +1 -0
- package/dist/vault/disabled.js +23 -0
- package/dist/vault/disabled.js.map +1 -0
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +3 -24
- package/dist/vault/index.js.map +1 -1
- package/dist/vault/policy.d.ts +20 -0
- package/dist/vault/policy.d.ts.map +1 -0
- package/dist/vault/policy.js +20 -0
- package/dist/vault/policy.js.map +1 -0
- package/dist/vault/routing.d.ts +1 -0
- package/dist/vault/routing.d.ts.map +1 -1
- package/dist/vault/routing.js +3 -10
- package/dist/vault/routing.js.map +1 -1
- package/dist/web/admin/portal.d.ts +27 -0
- package/dist/web/admin/portal.d.ts.map +1 -1
- package/dist/web/admin/portal.js +91 -130
- package/dist/web/admin/portal.js.map +1 -1
- package/dist/web/admin/types.d.ts +3 -0
- package/dist/web/admin/types.d.ts.map +1 -1
- package/dist/web/admin/types.js.map +1 -1
- package/dist/web/login/oauth.d.ts +2 -3
- package/dist/web/login/oauth.d.ts.map +1 -1
- package/dist/web/login/oauth.js +0 -31
- package/dist/web/login/oauth.js.map +1 -1
- package/dist/web/login/portal.js +1 -1
- package/dist/web/login/portal.js.map +1 -1
- package/dist/web/login/types.d.ts +0 -11
- package/dist/web/login/types.d.ts.map +1 -1
- package/dist/web/login/types.js.map +1 -1
- package/dist/web/portal-shell.d.ts +4 -0
- package/dist/web/portal-shell.d.ts.map +1 -0
- package/dist/{portal-shell.js → web/portal-shell.js} +2 -2
- package/dist/web/portal-shell.js.map +1 -0
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +7 -0
- package/dist/web/server.js.map +1 -1
- package/dist/web/session-view/command.d.ts.map +1 -1
- package/dist/web/session-view/command.js +4 -1
- package/dist/web/session-view/command.js.map +1 -1
- package/dist/web/session-view/portal.d.ts.map +1 -1
- package/dist/web/session-view/portal.js +4 -3
- package/dist/web/session-view/portal.js.map +1 -1
- package/dist/web/session-view/service.d.ts.map +1 -1
- package/dist/web/session-view/service.js +2 -1
- package/dist/web/session-view/service.js.map +1 -1
- package/dist/web/session-view/types.d.ts +2 -1
- package/dist/web/session-view/types.d.ts.map +1 -1
- package/dist/web/session-view/types.js.map +1 -1
- package/package.json +7 -4
- package/dist/download.d.ts.map +0 -1
- package/dist/download.js.map +0 -1
- package/dist/model-registry.d.ts +0 -4
- package/dist/model-registry.d.ts.map +0 -1
- package/dist/model-registry.js +0 -7
- package/dist/model-registry.js.map +0 -1
- package/dist/portal-shell.d.ts +0 -4
- package/dist/portal-shell.d.ts.map +0 -1
- package/dist/portal-shell.js.map +0 -1
- package/dist/runtime/agent-run-controller.d.ts +0 -31
- package/dist/runtime/agent-run-controller.d.ts.map +0 -1
- package/dist/runtime/agent-run-controller.js +0 -195
- package/dist/runtime/agent-run-controller.js.map +0 -1
- /package/dist/{download.d.ts → cli/download.d.ts} +0 -0
- /package/dist/{download.js → cli/download.js} +0 -0
package/dist/agent.js
CHANGED
|
@@ -1,24 +1,43 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Agent runner: prompt construction, path translation, run lifecycle, and createRunner.
|
|
3
|
+
* Single module — do not split helpers that only this file uses.
|
|
4
|
+
*/
|
|
5
|
+
import { DEFAULT_EVENT_BUDGET, defaultExtensionDirs, formatSkillsForPrompt, loadExtensions, loadSkillsFromDir, MikanAgentSession, MikanModels, parseCommandInput, } from "./harness/index.js";
|
|
6
|
+
import { runSubagent } from "./harness/subagent-runner.js";
|
|
2
7
|
import { createHash } from "crypto";
|
|
3
8
|
import { existsSync, readFileSync } from "fs";
|
|
4
|
-
import { mkdir, readFile
|
|
9
|
+
import { mkdir, readFile } from "fs/promises";
|
|
5
10
|
import { join, posix } from "path";
|
|
6
11
|
import { resolveConversationSettings } from "./config.js";
|
|
7
12
|
import { readEnv } from "./utils/env.js";
|
|
8
13
|
import { ActorExecutionResolver } from "./execution-resolver.js";
|
|
9
14
|
import * as log from "./log.js";
|
|
10
|
-
import { reportUserFacingError } from "./observability/sentry.js";
|
|
11
15
|
import { createExecutor, } from "./sandbox/index.js";
|
|
12
16
|
import { createMountedRuntimePathContext } from "./sandbox/path-context.js";
|
|
13
|
-
import { addLifecycleBreadcrumb, metricAttributes, updateActiveSpanAttribution, } from "./observability/sentry.js";
|
|
17
|
+
import { addLifecycleBreadcrumb, metricAttributes, reportUserFacingError, updateActiveSpanAttribution, } from "./observability/sentry.js";
|
|
14
18
|
import { AgentMemoryFileManager } from "./sessions/agent-memory-file-manager.js";
|
|
19
|
+
import { formatHistoryLine } from "./sessions/history-line.js";
|
|
20
|
+
import { conversationIdOf, isThreadSessionKey } from "./sessions/session-key.js";
|
|
15
21
|
import { extractSessionUuid, openManagedSession, } from "./sessions/store.js";
|
|
16
22
|
import { HostEventStore } from "./tools/event.js";
|
|
17
|
-
import { createMikanTools } from "./tools/index.js";
|
|
23
|
+
import { createMikanTools, createSubagentTool } from "./tools/index.js";
|
|
18
24
|
import * as Sentry from "@sentry/node";
|
|
19
|
-
import { formatLocalTimestamp } from "./utils/date.js";
|
|
20
|
-
import { resolveConfiguredModel } from "./model-registry.js";
|
|
21
25
|
import { emitAgentEvent } from "./agent-events.js";
|
|
26
|
+
export function getUnresolvedSandboxPathContext(sandboxConfig, hostWorkspaceRoot) {
|
|
27
|
+
if (sandboxConfig.type === "image") {
|
|
28
|
+
return createMountedRuntimePathContext(hostWorkspaceRoot, "/workspace");
|
|
29
|
+
}
|
|
30
|
+
return createExecutor(sandboxConfig).getPathContext(hostWorkspaceRoot);
|
|
31
|
+
}
|
|
32
|
+
export function translateRuntimePathToHost(runtimePath, pathContext) {
|
|
33
|
+
return pathContext.runtimeToHostPath?.(runtimePath) ?? runtimePath;
|
|
34
|
+
}
|
|
35
|
+
export function translateAttachPathToHost(filePath, pathContext) {
|
|
36
|
+
const runtimePath = posix.isAbsolute(filePath)
|
|
37
|
+
? filePath
|
|
38
|
+
: posix.join(pathContext.runtimeWorkspaceRoot, filePath);
|
|
39
|
+
return translateRuntimePathToHost(runtimePath, pathContext);
|
|
40
|
+
}
|
|
22
41
|
const IMAGE_MIME_TYPES = {
|
|
23
42
|
jpg: "image/jpeg",
|
|
24
43
|
jpeg: "image/jpeg",
|
|
@@ -29,12 +48,46 @@ const IMAGE_MIME_TYPES = {
|
|
|
29
48
|
function getImageMimeType(filename) {
|
|
30
49
|
return IMAGE_MIME_TYPES[filename.toLowerCase().split(".").pop() || ""];
|
|
31
50
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
function formatTimestampedUserMessage(message) {
|
|
52
|
+
return formatHistoryLine({
|
|
53
|
+
date: new Date(),
|
|
54
|
+
userName: message.userName,
|
|
55
|
+
threadTs: message.threadTs,
|
|
56
|
+
text: message.text,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function collectMessageAttachments(message, workspacePath, pathContext) {
|
|
60
|
+
const imageAttachments = [];
|
|
61
|
+
const nonImagePaths = [];
|
|
62
|
+
for (const attachment of message.attachments || []) {
|
|
63
|
+
const runtimePath = `${workspacePath}/${attachment.localPath}`;
|
|
64
|
+
const hostPath = pathContext?.runtimeToHostPath?.(runtimePath) ?? runtimePath;
|
|
65
|
+
const mimeType = getImageMimeType(attachment.localPath);
|
|
66
|
+
if (mimeType && existsSync(hostPath)) {
|
|
67
|
+
try {
|
|
68
|
+
imageAttachments.push({
|
|
69
|
+
type: "image",
|
|
70
|
+
mimeType,
|
|
71
|
+
data: readFileSync(hostPath).toString("base64"),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
nonImagePaths.push(runtimePath);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
nonImagePaths.push(runtimePath);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { imageAttachments, nonImagePaths };
|
|
83
|
+
}
|
|
84
|
+
export function buildPromptPayload(message, workspacePath, pathContext) {
|
|
85
|
+
let userMessage = formatTimestampedUserMessage(message);
|
|
86
|
+
const { imageAttachments, nonImagePaths } = collectMessageAttachments(message, workspacePath, pathContext);
|
|
87
|
+
if (nonImagePaths.length > 0) {
|
|
88
|
+
userMessage += `\n\n<slack_attachments>\n${nonImagePaths.join("\n")}\n</slack_attachments>`;
|
|
89
|
+
}
|
|
90
|
+
return { userMessage, imageAttachments };
|
|
38
91
|
}
|
|
39
92
|
async function getMemory(conversationDir) {
|
|
40
93
|
const parts = [];
|
|
@@ -329,81 +382,21 @@ Do not add this to \`[SILENT]\` responses.`);
|
|
|
329
382
|
}
|
|
330
383
|
return parts.join("\n\n");
|
|
331
384
|
}
|
|
332
|
-
export function
|
|
333
|
-
if (
|
|
334
|
-
return
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
: createExecutor(sandboxConfig);
|
|
347
|
-
const executor = {
|
|
348
|
-
exec(command, options) {
|
|
349
|
-
return activeExecutor.exec(command, options);
|
|
350
|
-
},
|
|
351
|
-
getWorkspacePath(hostPath) {
|
|
352
|
-
return activeExecutor.getWorkspacePath(hostPath);
|
|
353
|
-
},
|
|
354
|
-
getSandboxConfig() {
|
|
355
|
-
return activeExecutor.getSandboxConfig();
|
|
356
|
-
},
|
|
357
|
-
getPathContext(hostWorkspaceRoot) {
|
|
358
|
-
return activeExecutor.getPathContext(hostWorkspaceRoot);
|
|
359
|
-
},
|
|
360
|
-
};
|
|
361
|
-
return {
|
|
362
|
-
executionResolver,
|
|
363
|
-
executor,
|
|
364
|
-
getPathContext: () => executor.getPathContext(hostWorkspacePath),
|
|
365
|
-
async resolveExecutorForRun(context) {
|
|
366
|
-
if (!executionResolver)
|
|
367
|
-
return;
|
|
368
|
-
activeExecutor = await executionResolver.resolve(context);
|
|
369
|
-
},
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
/**
|
|
373
|
-
* Extension host services over mikan's runtime infrastructure: schedules
|
|
374
|
-
* become event files under `<workspaceDir>/events` (picked up live by
|
|
375
|
-
* EventsWatcher), secrets come from `vaults/extensions/<slug>/env`, and
|
|
376
|
-
* notify posts through the platform bots when main.ts provides a notifier.
|
|
377
|
-
*/
|
|
378
|
-
function buildExtensionHostServices(params) {
|
|
379
|
-
const { workspaceDir, vaultManager, platformNotifier } = params;
|
|
380
|
-
const eventStore = HostEventStore.fromWorkspaceDir(workspaceDir);
|
|
381
|
-
return {
|
|
382
|
-
stateDir: readEnv("STATE_DIR"),
|
|
383
|
-
scheduleStore: {
|
|
384
|
-
write: async (filename, payload) => {
|
|
385
|
-
// Event files tolerate a missing platform (single-platform default),
|
|
386
|
-
// so the harness payload is a valid event payload as written.
|
|
387
|
-
await eventStore.write(filename, payload);
|
|
388
|
-
},
|
|
389
|
-
delete: async (filename) => (await eventStore.delete(filename)).deleted,
|
|
390
|
-
list: async () => (await eventStore.list()).map((entry) => ({
|
|
391
|
-
filename: entry.filename,
|
|
392
|
-
payload: entry.payload,
|
|
393
|
-
})),
|
|
394
|
-
},
|
|
395
|
-
...(platformNotifier ? { postMessage: platformNotifier } : {}),
|
|
396
|
-
...(vaultManager
|
|
397
|
-
? {
|
|
398
|
-
resolveSecrets: (slug) => vaultManager.resolve(`extensions/${slug}`)?.env ?? {},
|
|
399
|
-
}
|
|
400
|
-
: {}),
|
|
401
|
-
};
|
|
385
|
+
export function appendTriggerAttribution(text, triggerAttribution, sessionLink) {
|
|
386
|
+
if (!triggerAttribution)
|
|
387
|
+
return text;
|
|
388
|
+
const trimmed = text.trimEnd();
|
|
389
|
+
const legacySuffix = `_Triggered by ${triggerAttribution}_`;
|
|
390
|
+
// Slack mrkdwn italics cannot span a URL — a `_..._` wrapping a link renders
|
|
391
|
+
// the underscores literally. Keep the session link outside the italic span.
|
|
392
|
+
const suffix = sessionLink ? `${legacySuffix} · session: ${sessionLink}` : legacySuffix;
|
|
393
|
+
if (trimmed.endsWith(suffix))
|
|
394
|
+
return text;
|
|
395
|
+
const body = trimmed.endsWith(legacySuffix)
|
|
396
|
+
? trimmed.slice(0, -legacySuffix.length).trimEnd()
|
|
397
|
+
: trimmed;
|
|
398
|
+
return `${body}\n\n${suffix}`;
|
|
402
399
|
}
|
|
403
|
-
/**
|
|
404
|
-
* Local (workspace/conversation) skills override extension skills on name
|
|
405
|
-
* collision: an admin's on-disk skill always beats an extension's.
|
|
406
|
-
*/
|
|
407
400
|
function mergeExtensionSkills(local, extension) {
|
|
408
401
|
if (extension.length === 0)
|
|
409
402
|
return local;
|
|
@@ -414,37 +407,6 @@ function mergeExtensionSkills(local, extension) {
|
|
|
414
407
|
byName.set(skill.name, skill);
|
|
415
408
|
return [...byName.values()];
|
|
416
409
|
}
|
|
417
|
-
async function createConfiguredAgentSession(params) {
|
|
418
|
-
const { conversationId, workspaceDir, systemPrompt, model, thinkingLevel, tools, sessionStore, models, vaultManager, platformNotifier, } = params;
|
|
419
|
-
// Host-only dirs under the state dir: extension code runs in the mikan
|
|
420
|
-
// process, so it must never load from workspace paths — those are mounted
|
|
421
|
-
// into sandbox containers and agent-writable (sandbox escape otherwise).
|
|
422
|
-
const extensionsResult = await loadExtensions({
|
|
423
|
-
dirs: defaultExtensionDirs(conversationId, readEnv("STATE_DIR")),
|
|
424
|
-
context: { conversationId, workspaceDir, model, thinkingLevel },
|
|
425
|
-
services: buildExtensionHostServices({ workspaceDir, vaultManager, platformNotifier }),
|
|
426
|
-
});
|
|
427
|
-
for (const err of extensionsResult.errors) {
|
|
428
|
-
log.logWarning(`[${conversationId}] Extension load error: ${err.path}`, err.error);
|
|
429
|
-
}
|
|
430
|
-
if (extensionsResult.extensions.length > 0) {
|
|
431
|
-
log.logInfo(`[${conversationId}] Loaded ${extensionsResult.extensions.length} extension(s): ${extensionsResult.extensions.map((extension) => extension.name).join(", ")}`);
|
|
432
|
-
}
|
|
433
|
-
const session = new MikanAgentSession({
|
|
434
|
-
systemPrompt,
|
|
435
|
-
model,
|
|
436
|
-
thinkingLevel,
|
|
437
|
-
tools,
|
|
438
|
-
models,
|
|
439
|
-
sessionStore,
|
|
440
|
-
extensions: extensionsResult.registry,
|
|
441
|
-
});
|
|
442
|
-
const reloaded = session.reloadFromSession();
|
|
443
|
-
if (reloaded > 0) {
|
|
444
|
-
log.logInfo(`[${conversationId}] Reloaded ${reloaded} messages from session context`);
|
|
445
|
-
}
|
|
446
|
-
return { session, extensionSkills: extensionsResult.skills };
|
|
447
|
-
}
|
|
448
410
|
function createEmptyUsageTotals() {
|
|
449
411
|
return {
|
|
450
412
|
input: 0,
|
|
@@ -461,6 +423,7 @@ function createRunState() {
|
|
|
461
423
|
queue: null,
|
|
462
424
|
pendingTools: new Map(),
|
|
463
425
|
toolProgress: new Map(),
|
|
426
|
+
toolProgressTimer: undefined,
|
|
464
427
|
totalUsage: createEmptyUsageTotals(),
|
|
465
428
|
llmCallCount: 0,
|
|
466
429
|
stopReason: "stop",
|
|
@@ -480,6 +443,9 @@ function resetRunState(runState, responder, sessionConversation, userName, sessi
|
|
|
480
443
|
};
|
|
481
444
|
runState.pendingTools.clear();
|
|
482
445
|
runState.toolProgress.clear();
|
|
446
|
+
if (runState.toolProgressTimer)
|
|
447
|
+
clearTimeout(runState.toolProgressTimer);
|
|
448
|
+
runState.toolProgressTimer = undefined;
|
|
483
449
|
runState.totalUsage = createEmptyUsageTotals();
|
|
484
450
|
runState.llmCallCount = 0;
|
|
485
451
|
runState.stopReason = "stop";
|
|
@@ -515,53 +481,6 @@ function createRunQueue(responder, runState) {
|
|
|
515
481
|
wait: () => queueChain,
|
|
516
482
|
};
|
|
517
483
|
}
|
|
518
|
-
function formatTimestampedUserMessage(message) {
|
|
519
|
-
const timestamp = formatLocalTimestamp(new Date());
|
|
520
|
-
const threadContext = message.threadTs ? ` [in-thread:${message.threadTs}]` : "";
|
|
521
|
-
return `[${timestamp}] [${message.userName || "unknown"}]${threadContext}: ${message.text}`;
|
|
522
|
-
}
|
|
523
|
-
function collectMessageAttachments(message, workspacePath, pathContext) {
|
|
524
|
-
const imageAttachments = [];
|
|
525
|
-
const nonImagePaths = [];
|
|
526
|
-
for (const attachment of message.attachments || []) {
|
|
527
|
-
const runtimePath = `${workspacePath}/${attachment.localPath}`;
|
|
528
|
-
const hostPath = pathContext?.runtimeToHostPath?.(runtimePath) ?? runtimePath;
|
|
529
|
-
const mimeType = getImageMimeType(attachment.localPath);
|
|
530
|
-
if (mimeType && existsSync(hostPath)) {
|
|
531
|
-
try {
|
|
532
|
-
imageAttachments.push({
|
|
533
|
-
type: "image",
|
|
534
|
-
mimeType,
|
|
535
|
-
data: readFileSync(hostPath).toString("base64"),
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
catch {
|
|
539
|
-
nonImagePaths.push(runtimePath);
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
else {
|
|
543
|
-
nonImagePaths.push(runtimePath);
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
return { imageAttachments, nonImagePaths };
|
|
547
|
-
}
|
|
548
|
-
export function buildPromptPayload(message, workspacePath, pathContext) {
|
|
549
|
-
let userMessage = formatTimestampedUserMessage(message);
|
|
550
|
-
const { imageAttachments, nonImagePaths } = collectMessageAttachments(message, workspacePath, pathContext);
|
|
551
|
-
if (nonImagePaths.length > 0) {
|
|
552
|
-
userMessage += `\n\n<slack_attachments>\n${nonImagePaths.join("\n")}\n</slack_attachments>`;
|
|
553
|
-
}
|
|
554
|
-
return { userMessage, imageAttachments };
|
|
555
|
-
}
|
|
556
|
-
async function writePromptDebugContext(conversationDir, systemPrompt, session, userMessage, imageAttachmentCount) {
|
|
557
|
-
const debugContext = {
|
|
558
|
-
systemPrompt,
|
|
559
|
-
messages: session.messages,
|
|
560
|
-
newUserMessage: userMessage,
|
|
561
|
-
imageAttachmentCount,
|
|
562
|
-
};
|
|
563
|
-
await writeFile(join(conversationDir, "last_prompt.jsonl"), JSON.stringify(debugContext, null, 2));
|
|
564
|
-
}
|
|
565
484
|
function getFinalAssistantText(session) {
|
|
566
485
|
const lastAssistant = session.messages.findLast((message) => message.role === "assistant");
|
|
567
486
|
return (lastAssistant?.content
|
|
@@ -569,21 +488,6 @@ function getFinalAssistantText(session) {
|
|
|
569
488
|
.map((content) => content.text)
|
|
570
489
|
.join("\n") || "");
|
|
571
490
|
}
|
|
572
|
-
export function appendTriggerAttribution(text, triggerAttribution, sessionLink) {
|
|
573
|
-
if (!triggerAttribution)
|
|
574
|
-
return text;
|
|
575
|
-
const trimmed = text.trimEnd();
|
|
576
|
-
const legacySuffix = `_Triggered by ${triggerAttribution}_`;
|
|
577
|
-
const suffix = sessionLink
|
|
578
|
-
? `_Triggered by ${triggerAttribution} · session: ${sessionLink}_`
|
|
579
|
-
: legacySuffix;
|
|
580
|
-
if (trimmed.endsWith(suffix))
|
|
581
|
-
return text;
|
|
582
|
-
const body = trimmed.endsWith(legacySuffix)
|
|
583
|
-
? trimmed.slice(0, -legacySuffix.length).trimEnd()
|
|
584
|
-
: trimmed;
|
|
585
|
-
return `${body}\n\n${suffix}`;
|
|
586
|
-
}
|
|
587
491
|
function isEventTriggerAttribution(triggerAttribution) {
|
|
588
492
|
return triggerAttribution?.startsWith("[event:") === true;
|
|
589
493
|
}
|
|
@@ -609,6 +513,31 @@ async function replaceResponseWithToolProgress(responder, runState) {
|
|
|
609
513
|
if (progress)
|
|
610
514
|
await responder.replaceResponse(progress);
|
|
611
515
|
}
|
|
516
|
+
const TOOL_PROGRESS_DEBOUNCE_MS = 500;
|
|
517
|
+
function scheduleToolProgressUpdate(responder, runState) {
|
|
518
|
+
if (runState.toolProgressTimer)
|
|
519
|
+
return;
|
|
520
|
+
runState.toolProgressTimer = setTimeout(() => {
|
|
521
|
+
runState.toolProgressTimer = undefined;
|
|
522
|
+
runState.queue?.enqueue(() => replaceResponseWithToolProgress(responder, runState), "tool progress update");
|
|
523
|
+
}, TOOL_PROGRESS_DEBOUNCE_MS);
|
|
524
|
+
runState.toolProgressTimer.unref();
|
|
525
|
+
}
|
|
526
|
+
function flushToolProgressUpdate(responder, runState) {
|
|
527
|
+
if (runState.toolProgressTimer)
|
|
528
|
+
clearTimeout(runState.toolProgressTimer);
|
|
529
|
+
runState.toolProgressTimer = undefined;
|
|
530
|
+
runState.queue?.enqueue(() => replaceResponseWithToolProgress(responder, runState), "tool progress update");
|
|
531
|
+
}
|
|
532
|
+
function extractToolProgressLabel(partialResult) {
|
|
533
|
+
if (!partialResult || typeof partialResult !== "object")
|
|
534
|
+
return undefined;
|
|
535
|
+
const details = partialResult.details;
|
|
536
|
+
if (!details || typeof details !== "object")
|
|
537
|
+
return undefined;
|
|
538
|
+
const label = details.progressLabel;
|
|
539
|
+
return typeof label === "string" && label.trim() ? label.trim().slice(0, 1000) : undefined;
|
|
540
|
+
}
|
|
612
541
|
async function finalizeRunResponse(responder, session, runState, options) {
|
|
613
542
|
if (runState.stopReason === "error" && runState.errorMessage) {
|
|
614
543
|
if (!runState.reportedLlmError) {
|
|
@@ -739,6 +668,170 @@ async function reportUsageSummary(ctx) {
|
|
|
739
668
|
await waitForQueue();
|
|
740
669
|
}
|
|
741
670
|
}
|
|
671
|
+
function extractToolResultText(result) {
|
|
672
|
+
if (typeof result === "string") {
|
|
673
|
+
return result;
|
|
674
|
+
}
|
|
675
|
+
if (result &&
|
|
676
|
+
typeof result === "object" &&
|
|
677
|
+
"content" in result &&
|
|
678
|
+
Array.isArray(result.content)) {
|
|
679
|
+
const content = result.content;
|
|
680
|
+
const textParts = [];
|
|
681
|
+
for (const part of content) {
|
|
682
|
+
if (part.type === "text" && part.text) {
|
|
683
|
+
textParts.push(part.text);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
if (textParts.length > 0) {
|
|
687
|
+
return textParts.join("\n");
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
return JSON.stringify(result);
|
|
691
|
+
}
|
|
692
|
+
function buildThreadSessionName(message) {
|
|
693
|
+
const text = message?.text?.trim();
|
|
694
|
+
if (!text)
|
|
695
|
+
return undefined;
|
|
696
|
+
const userLabel = message?.userName || message?.user || "unknown";
|
|
697
|
+
return `[${userLabel}]: ${text}`;
|
|
698
|
+
}
|
|
699
|
+
function createRunnerExecutionContext(sandboxConfig, vaultManager, provisioner, workspaceDir, hostWorkspacePath) {
|
|
700
|
+
const executionResolver = vaultManager && sandboxConfig.type !== "host"
|
|
701
|
+
? new ActorExecutionResolver(sandboxConfig, vaultManager, provisioner, workspaceDir, hostWorkspacePath)
|
|
702
|
+
: undefined;
|
|
703
|
+
// activeExecutor is replaced at the start of each run() call when executionResolver
|
|
704
|
+
// is present, so the stable `executor` wrapper always delegates to the latest resolved value.
|
|
705
|
+
let activeExecutor = executionResolver !== undefined
|
|
706
|
+
? createExecutor({ type: "host" })
|
|
707
|
+
: createExecutor(sandboxConfig);
|
|
708
|
+
const executor = {
|
|
709
|
+
exec(command, options) {
|
|
710
|
+
return activeExecutor.exec(command, options);
|
|
711
|
+
},
|
|
712
|
+
readFile(path, options) {
|
|
713
|
+
return activeExecutor.readFile(path, options);
|
|
714
|
+
},
|
|
715
|
+
writeFile(path, content, options) {
|
|
716
|
+
return activeExecutor.writeFile(path, content, options);
|
|
717
|
+
},
|
|
718
|
+
getWorkspacePath(hostPath) {
|
|
719
|
+
return activeExecutor.getWorkspacePath(hostPath);
|
|
720
|
+
},
|
|
721
|
+
getSandboxConfig() {
|
|
722
|
+
return activeExecutor.getSandboxConfig();
|
|
723
|
+
},
|
|
724
|
+
getPathContext(hostWorkspaceRoot) {
|
|
725
|
+
return activeExecutor.getPathContext(hostWorkspaceRoot);
|
|
726
|
+
},
|
|
727
|
+
};
|
|
728
|
+
return {
|
|
729
|
+
executionResolver,
|
|
730
|
+
executor,
|
|
731
|
+
getPathContext: () => executor.getPathContext(hostWorkspacePath),
|
|
732
|
+
async resolveExecutorForRun(context) {
|
|
733
|
+
if (!executionResolver)
|
|
734
|
+
return;
|
|
735
|
+
activeExecutor = await executionResolver.resolve(context);
|
|
736
|
+
},
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Extension host services over mikan's runtime infrastructure: schedules
|
|
741
|
+
* become event files under `<workspaceDir>/events` (picked up live by
|
|
742
|
+
* EventsWatcher), secrets come from `vaults/extensions/<slug>/env`, and
|
|
743
|
+
* notify posts through the platform bots when main.ts provides a notifier.
|
|
744
|
+
*/
|
|
745
|
+
function buildExtensionHostServices(params) {
|
|
746
|
+
const { workspaceDir, vaultManager, platformNotifier, platformReactor, platformUploader, runSubagentService, } = params;
|
|
747
|
+
const eventStore = HostEventStore.fromWorkspaceDir(workspaceDir);
|
|
748
|
+
return {
|
|
749
|
+
stateDir: readEnv("STATE_DIR"),
|
|
750
|
+
scheduleStore: {
|
|
751
|
+
write: async (filename, payload) => {
|
|
752
|
+
// Event files tolerate a missing platform (single-platform default),
|
|
753
|
+
// so the harness payload is a valid event payload as written.
|
|
754
|
+
await eventStore.write(filename, payload);
|
|
755
|
+
},
|
|
756
|
+
delete: async (filename) => (await eventStore.delete(filename)).deleted,
|
|
757
|
+
list: async () => (await eventStore.list())
|
|
758
|
+
.filter((entry) => entry.payload !== null)
|
|
759
|
+
.map((entry) => ({
|
|
760
|
+
filename: entry.filename,
|
|
761
|
+
payload: entry.payload,
|
|
762
|
+
})),
|
|
763
|
+
},
|
|
764
|
+
...(platformNotifier ? { postMessage: platformNotifier } : {}),
|
|
765
|
+
...(platformReactor ? { addReaction: platformReactor } : {}),
|
|
766
|
+
...(platformUploader ? { uploadFile: platformUploader } : {}),
|
|
767
|
+
...(runSubagentService ? { runSubagent: runSubagentService } : {}),
|
|
768
|
+
...(vaultManager
|
|
769
|
+
? {
|
|
770
|
+
resolveSecrets: (slug) => vaultManager.resolve(`extensions/${slug}`)?.env ?? {},
|
|
771
|
+
}
|
|
772
|
+
: {}),
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
async function createConfiguredAgentSession(params) {
|
|
776
|
+
const { conversationId, workspaceDir, systemPrompt, model, thinkingLevel, tools, sessionStore, models, vaultManager, platformNotifier, platformReactor, platformUploader, } = params;
|
|
777
|
+
// Host-only dirs under the state dir: extension code runs in the mikan
|
|
778
|
+
// process, so it must never load from workspace paths — those are mounted
|
|
779
|
+
// into sandbox containers and agent-writable (sandbox escape otherwise).
|
|
780
|
+
let contributedTools = [];
|
|
781
|
+
const subagentTool = createSubagentTool((request) => runSubagent({
|
|
782
|
+
request,
|
|
783
|
+
defaultModel: model,
|
|
784
|
+
thinkingLevel,
|
|
785
|
+
models,
|
|
786
|
+
workspaceDir,
|
|
787
|
+
availableTools: [...tools, ...contributedTools],
|
|
788
|
+
}));
|
|
789
|
+
const extensionsResult = await loadExtensions({
|
|
790
|
+
dirs: defaultExtensionDirs(conversationId, readEnv("STATE_DIR")),
|
|
791
|
+
context: { conversationId, workspaceDir, model, thinkingLevel },
|
|
792
|
+
services: buildExtensionHostServices({
|
|
793
|
+
workspaceDir,
|
|
794
|
+
vaultManager,
|
|
795
|
+
platformNotifier,
|
|
796
|
+
platformReactor,
|
|
797
|
+
platformUploader,
|
|
798
|
+
runSubagentService: (request, extensionTools) => runSubagent({
|
|
799
|
+
request,
|
|
800
|
+
defaultModel: model,
|
|
801
|
+
thinkingLevel,
|
|
802
|
+
models,
|
|
803
|
+
workspaceDir,
|
|
804
|
+
availableTools: [...tools, ...extensionTools],
|
|
805
|
+
}),
|
|
806
|
+
}),
|
|
807
|
+
});
|
|
808
|
+
contributedTools = extensionsResult.registry.getContributedTools();
|
|
809
|
+
for (const err of extensionsResult.errors) {
|
|
810
|
+
log.logWarning(`[${conversationId}] Extension load error: ${err.path}`, err.error);
|
|
811
|
+
}
|
|
812
|
+
if (extensionsResult.extensions.length > 0) {
|
|
813
|
+
log.logInfo(`[${conversationId}] Loaded ${extensionsResult.extensions.length} extension(s): ${extensionsResult.extensions.map((extension) => extension.name).join(", ")}`);
|
|
814
|
+
}
|
|
815
|
+
const session = new MikanAgentSession({
|
|
816
|
+
systemPrompt,
|
|
817
|
+
model,
|
|
818
|
+
thinkingLevel,
|
|
819
|
+
tools: [...tools, subagentTool],
|
|
820
|
+
models,
|
|
821
|
+
sessionStore,
|
|
822
|
+
extensions: extensionsResult.registry,
|
|
823
|
+
});
|
|
824
|
+
const reloaded = session.reloadFromSession();
|
|
825
|
+
if (reloaded > 0) {
|
|
826
|
+
log.logInfo(`[${conversationId}] Reloaded ${reloaded} messages from session context`);
|
|
827
|
+
}
|
|
828
|
+
return {
|
|
829
|
+
session,
|
|
830
|
+
extensionSkills: extensionsResult.skills,
|
|
831
|
+
extensionRegistry: extensionsResult.registry,
|
|
832
|
+
disposeExtensions: extensionsResult.dispose,
|
|
833
|
+
};
|
|
834
|
+
}
|
|
742
835
|
function reloadSessionMessages(session, conversationId) {
|
|
743
836
|
const reloaded = session.reloadFromSession();
|
|
744
837
|
if (reloaded > 0) {
|
|
@@ -746,15 +839,16 @@ function reloadSessionMessages(session, conversationId) {
|
|
|
746
839
|
}
|
|
747
840
|
}
|
|
748
841
|
async function prepareRunContext(params) {
|
|
749
|
-
const { message, responder, platform, conversationId, conversationDir, sessionUuid, runState, executor, executionResolver, resolveExecutorForRun, getPathContext, session, setEventContext, setSandboxContext, setUploadFunction, } = params;
|
|
842
|
+
const { message, responder, platform, conversationId, conversationDir, sessionUuid, runState, executor, executionResolver, resolveExecutorForRun, getPathContext, session, setEventContext, setSandboxContext, setUploadFunction, setReactFunction, bindPlatformToolPacks, } = params;
|
|
750
843
|
let pathContext = params.pathContext;
|
|
751
|
-
const sessionConversation = message.sessionKey
|
|
844
|
+
const sessionConversation = conversationIdOf(message.sessionKey);
|
|
752
845
|
await mkdir(join(conversationDir, "scratch"), { recursive: true });
|
|
753
846
|
if (executionResolver) {
|
|
754
847
|
await resolveExecutorForRun({
|
|
755
848
|
platform: platform.name,
|
|
756
849
|
userId: message.userId,
|
|
757
850
|
conversationId,
|
|
851
|
+
trustModel: platform.trustModel,
|
|
758
852
|
});
|
|
759
853
|
pathContext = getPathContext();
|
|
760
854
|
}
|
|
@@ -768,9 +862,11 @@ async function prepareRunContext(params) {
|
|
|
768
862
|
// provider prompt caching. If this hash changes between turns of one
|
|
769
863
|
// conversation, something turn-varying leaked into the prompt; if it is
|
|
770
864
|
// stable and cacheRead stays 0, the miss is provider-side (e.g. OpenRouter
|
|
771
|
-
// routing the model across upstream hosts).
|
|
865
|
+
// routing the model across upstream hosts). This is the base prompt mikan
|
|
866
|
+
// builds; a `before_agent_start` extension may still rewrite it per turn
|
|
867
|
+
// (logged separately by the runner).
|
|
772
868
|
const promptHash = createHash("sha256").update(systemPrompt).digest("hex").slice(0, 8);
|
|
773
|
-
log.logInfo(`[${conversationId}] System prompt: ${systemPrompt.length} chars, sha ${promptHash}`);
|
|
869
|
+
log.logInfo(`[${conversationId}] System prompt (base): ${systemPrompt.length} chars, sha ${promptHash}`);
|
|
774
870
|
setEventContext({
|
|
775
871
|
platform: platform.name,
|
|
776
872
|
conversationId,
|
|
@@ -782,6 +878,13 @@ async function prepareRunContext(params) {
|
|
|
782
878
|
const hostPath = translateAttachPathToHost(filePath, pathContext);
|
|
783
879
|
await responder.uploadFile(hostPath, title);
|
|
784
880
|
});
|
|
881
|
+
// The react tool is available only when the responder supports reactions
|
|
882
|
+
// (interactive turns on platforms with reaction support); otherwise unset
|
|
883
|
+
// so the tool reports it is unavailable rather than silently no-op'ing.
|
|
884
|
+
setReactFunction(responder.react ? async (emoji) => responder.react(emoji) : null);
|
|
885
|
+
// Platform capability packs (e.g. GitHub PR/CI) enable themselves per run;
|
|
886
|
+
// core does not branch on platform name here.
|
|
887
|
+
bindPlatformToolPacks({ conversationId, platformName: platform.name });
|
|
785
888
|
resetRunState(runState, responder, sessionConversation, message.userName, sessionUuid, triggerAttribution);
|
|
786
889
|
const runQueue = createRunQueue(responder, runState);
|
|
787
890
|
runState.queue = runQueue.queue;
|
|
@@ -790,7 +893,6 @@ async function prepareRunContext(params) {
|
|
|
790
893
|
const { userMessage, imageAttachments } = buildPromptPayload(message, pathContext.runtimeWorkspaceRoot, pathContext);
|
|
791
894
|
const turnInstructions = buildTurnInstructions(message.id.startsWith("event:"), triggerAttribution, platform.name);
|
|
792
895
|
const finalUserMessage = turnInstructions ? `${turnInstructions}\n\n${userMessage}` : userMessage;
|
|
793
|
-
await writePromptDebugContext(conversationDir, systemPrompt, session, finalUserMessage, imageAttachments.length);
|
|
794
896
|
return {
|
|
795
897
|
sessionConversation,
|
|
796
898
|
runQueue,
|
|
@@ -845,6 +947,15 @@ function attachSessionEventHandlers(params) {
|
|
|
845
947
|
log.logToolStart(logCtx, event.toolName, label, event.args);
|
|
846
948
|
return;
|
|
847
949
|
}
|
|
950
|
+
if (event.type === "tool_execution_update") {
|
|
951
|
+
const label = extractToolProgressLabel(event.partialResult);
|
|
952
|
+
const progress = runState.toolProgress.get(event.toolCallId);
|
|
953
|
+
if (label && progress) {
|
|
954
|
+
progress.label = label;
|
|
955
|
+
scheduleToolProgressUpdate(responder, runState);
|
|
956
|
+
}
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
848
959
|
if (event.type === "tool_execution_end") {
|
|
849
960
|
const resultStr = extractToolResultText(event.result);
|
|
850
961
|
const pending = pendingTools.get(event.toolCallId);
|
|
@@ -856,7 +967,7 @@ function attachSessionEventHandlers(params) {
|
|
|
856
967
|
const progress = runState.toolProgress.get(event.toolCallId);
|
|
857
968
|
if (progress)
|
|
858
969
|
progress.status = event.isError ? "error" : "done";
|
|
859
|
-
|
|
970
|
+
flushToolProgressUpdate(responder, runState);
|
|
860
971
|
pendingTools.delete(event.toolCallId);
|
|
861
972
|
const durationMs = pending ? Date.now() - pending.startTime : 0;
|
|
862
973
|
Sentry.metrics.count("agent.tool.calls", 1, {
|
|
@@ -1069,27 +1180,6 @@ function attachSessionEventHandlers(params) {
|
|
|
1069
1180
|
}
|
|
1070
1181
|
});
|
|
1071
1182
|
}
|
|
1072
|
-
function extractToolResultText(result) {
|
|
1073
|
-
if (typeof result === "string") {
|
|
1074
|
-
return result;
|
|
1075
|
-
}
|
|
1076
|
-
if (result &&
|
|
1077
|
-
typeof result === "object" &&
|
|
1078
|
-
"content" in result &&
|
|
1079
|
-
Array.isArray(result.content)) {
|
|
1080
|
-
const content = result.content;
|
|
1081
|
-
const textParts = [];
|
|
1082
|
-
for (const part of content) {
|
|
1083
|
-
if (part.type === "text" && part.text) {
|
|
1084
|
-
textParts.push(part.text);
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
if (textParts.length > 0) {
|
|
1088
|
-
return textParts.join("\n");
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
return JSON.stringify(result);
|
|
1092
|
-
}
|
|
1093
1183
|
/**
|
|
1094
1184
|
* Create a new PiAgentWrapper for a channel.
|
|
1095
1185
|
* Sets up the session and subscribes to events once.
|
|
@@ -1097,18 +1187,22 @@ function extractToolResultText(result) {
|
|
|
1097
1187
|
* Runner caching is handled by the caller (channelStates in main.ts).
|
|
1098
1188
|
* This is a stateless factory function.
|
|
1099
1189
|
*/
|
|
1100
|
-
export async function createRunner(
|
|
1190
|
+
export async function createRunner(options) {
|
|
1191
|
+
const { sandboxConfig, sessionKey, conversationId, conversationDir, workspaceDir, sessionScope, vaultManager, provisioner, resourceController, sessionView, platformNotifier, platformReactor, platformUploader, platformToolPackFactories, } = options;
|
|
1101
1192
|
const agentConfig = resolveConversationSettings(conversationDir);
|
|
1102
1193
|
const workspaceBase = join(conversationDir, "..");
|
|
1103
1194
|
const { executionResolver, executor, getPathContext, resolveExecutorForRun } = createRunnerExecutionContext(sandboxConfig, vaultManager, provisioner, workspaceDir, workspaceBase);
|
|
1104
1195
|
let pathContext = getUnresolvedSandboxPathContext(sandboxConfig, workspaceBase);
|
|
1105
|
-
|
|
1106
|
-
const { tools, setUploadFunction, setEventContext, setSandboxContext } = createMikanTools(executor, workspaceDir, { sandbox: sandboxConfig, provisioner });
|
|
1107
|
-
const modelRegistry = MikanModels.create();
|
|
1196
|
+
const modelRegistry = options.models ?? MikanModels.create();
|
|
1108
1197
|
if (modelRegistry.getError()) {
|
|
1109
1198
|
log.logWarning("models.json load error", modelRegistry.getError());
|
|
1110
1199
|
}
|
|
1111
|
-
const model =
|
|
1200
|
+
const model = modelRegistry.resolve(agentConfig.provider, agentConfig.model);
|
|
1201
|
+
// Create tools (per-runner, with per-runner upload function setter)
|
|
1202
|
+
const { tools, setUploadFunction, setReactFunction, bindPlatformToolPacks, setEventContext, setSandboxContext, } = createMikanTools(executor, workspaceDir, { sandbox: sandboxConfig, resourceController: resourceController ?? provisioner }, platformToolPackFactories ?? [], {
|
|
1203
|
+
model,
|
|
1204
|
+
getApiKey: () => modelRegistry.getApiKeyForProvider(model.provider),
|
|
1205
|
+
});
|
|
1112
1206
|
// Initial system prompt (will be updated each run with fresh memory/channels/users/skills)
|
|
1113
1207
|
const memory = await getMemory(conversationDir);
|
|
1114
1208
|
const skills = loadMikanSkills(conversationDir, pathContext.runtimeWorkspaceRoot);
|
|
@@ -1117,12 +1211,13 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
|
|
|
1117
1211
|
formattingGuide: "",
|
|
1118
1212
|
channels: [],
|
|
1119
1213
|
users: [],
|
|
1214
|
+
trustModel: "membership",
|
|
1120
1215
|
};
|
|
1121
1216
|
const systemPrompt = buildSystemPrompt(pathContext.runtimeWorkspaceRoot, conversationId, "shared", undefined, memory, sandboxConfig, emptyPlatform, skills);
|
|
1122
1217
|
// Create session manager and settings manager. Top-level/private sessions
|
|
1123
1218
|
// use the conversation's current pointer; scoped sessions use fixed files.
|
|
1124
1219
|
// Platform-specific scope behavior is resolved before runner creation.
|
|
1125
|
-
const isThread = sessionKey
|
|
1220
|
+
const isThread = isThreadSessionKey(sessionKey);
|
|
1126
1221
|
const { contextFile, threadRootMessage } = sessionScope;
|
|
1127
1222
|
const sessionManager = openManagedSession(contextFile, pathContext.runtimeWorkspaceRoot);
|
|
1128
1223
|
const threadSessionName = buildThreadSessionName(threadRootMessage);
|
|
@@ -1131,7 +1226,7 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
|
|
|
1131
1226
|
}
|
|
1132
1227
|
const sessionUuid = extractSessionUuid(contextFile);
|
|
1133
1228
|
const chatSessionManager = new AgentMemoryFileManager();
|
|
1134
|
-
const { session, extensionSkills } = await createConfiguredAgentSession({
|
|
1229
|
+
const { session, extensionSkills, extensionRegistry, disposeExtensions } = await createConfiguredAgentSession({
|
|
1135
1230
|
conversationId,
|
|
1136
1231
|
workspaceDir,
|
|
1137
1232
|
systemPrompt,
|
|
@@ -1142,6 +1237,8 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
|
|
|
1142
1237
|
models: modelRegistry,
|
|
1143
1238
|
vaultManager,
|
|
1144
1239
|
platformNotifier,
|
|
1240
|
+
platformReactor,
|
|
1241
|
+
platformUploader,
|
|
1145
1242
|
});
|
|
1146
1243
|
// Mutable per-run state - event handler references this
|
|
1147
1244
|
const runState = createRunState();
|
|
@@ -1173,6 +1270,8 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
|
|
|
1173
1270
|
setEventContext,
|
|
1174
1271
|
setSandboxContext,
|
|
1175
1272
|
setUploadFunction,
|
|
1273
|
+
setReactFunction,
|
|
1274
|
+
bindPlatformToolPacks,
|
|
1176
1275
|
pathContext,
|
|
1177
1276
|
});
|
|
1178
1277
|
pathContext = prepared.pathContext;
|
|
@@ -1201,10 +1300,39 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
|
|
|
1201
1300
|
// Autonomous (event/trigger) runs get an explicit resource ceiling since
|
|
1202
1301
|
// no human is watching the loop; interactive turns stay human-gated.
|
|
1203
1302
|
const isEventRun = message.id.startsWith("event:");
|
|
1204
|
-
|
|
1303
|
+
// Event runs have no triggering platform message, so identity fields
|
|
1304
|
+
// stay unset and extensions must null-check them.
|
|
1305
|
+
const origin = isEventRun
|
|
1306
|
+
? { kind: "event", platform: platform.name }
|
|
1307
|
+
: {
|
|
1308
|
+
kind: "interactive",
|
|
1309
|
+
platform: platform.name,
|
|
1310
|
+
messageTs: message.id,
|
|
1311
|
+
userId: message.userId,
|
|
1312
|
+
userName: message.userName,
|
|
1313
|
+
threadTs: message.threadTs,
|
|
1314
|
+
attachments: message.attachments,
|
|
1315
|
+
};
|
|
1316
|
+
const outcome = await session.prompt(prepared.userMessage, {
|
|
1317
|
+
origin,
|
|
1205
1318
|
...(prepared.imageAttachments.length > 0 ? { images: prepared.imageAttachments } : {}),
|
|
1206
1319
|
...(isEventRun ? { budget: DEFAULT_EVENT_BUDGET } : {}),
|
|
1207
1320
|
});
|
|
1321
|
+
if (outcome?.blocked) {
|
|
1322
|
+
const text = outcome.reason
|
|
1323
|
+
? `_Turn blocked by an extension: ${outcome.reason}_`
|
|
1324
|
+
: "_Turn blocked by an extension._";
|
|
1325
|
+
sendAgentEvent({
|
|
1326
|
+
sessionId: sessionUuid,
|
|
1327
|
+
actorName: formatAgentActorName(message.userName, prepared.sessionConversation),
|
|
1328
|
+
event: { kind: "diagnostic", text },
|
|
1329
|
+
});
|
|
1330
|
+
await responder.respondDiagnostic(text, { style: "muted" });
|
|
1331
|
+
runState.responder = null;
|
|
1332
|
+
runState.logCtx = null;
|
|
1333
|
+
runState.queue = null;
|
|
1334
|
+
return { stopReason: "blocked" };
|
|
1335
|
+
}
|
|
1208
1336
|
// Wait for queued messages
|
|
1209
1337
|
await prepared.runQueue.wait();
|
|
1210
1338
|
const sessionViewTokenStore = sessionView?.tokenStore;
|
|
@@ -1250,6 +1378,21 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
|
|
|
1250
1378
|
abort() {
|
|
1251
1379
|
session.abort();
|
|
1252
1380
|
},
|
|
1381
|
+
async tryExtensionCommand(message, responder) {
|
|
1382
|
+
const parsed = parseCommandInput(message.text);
|
|
1383
|
+
if (!parsed)
|
|
1384
|
+
return false;
|
|
1385
|
+
return extensionRegistry.dispatchCommand(parsed.name, {
|
|
1386
|
+
args: parsed.args,
|
|
1387
|
+
conversationId,
|
|
1388
|
+
userId: message.userId,
|
|
1389
|
+
userName: message.userName,
|
|
1390
|
+
respond: (text) => responder.respond(text),
|
|
1391
|
+
});
|
|
1392
|
+
},
|
|
1393
|
+
async dispose() {
|
|
1394
|
+
await disposeExtensions();
|
|
1395
|
+
},
|
|
1253
1396
|
getCurrentStep() {
|
|
1254
1397
|
const pending = runState.pendingTools;
|
|
1255
1398
|
if (pending.size === 0)
|
|
@@ -1265,13 +1408,4 @@ export async function createRunner(sandboxConfig, sessionKey, conversationId, co
|
|
|
1265
1408
|
},
|
|
1266
1409
|
};
|
|
1267
1410
|
}
|
|
1268
|
-
export function translateRuntimePathToHost(runtimePath, pathContext) {
|
|
1269
|
-
return pathContext.runtimeToHostPath?.(runtimePath) ?? runtimePath;
|
|
1270
|
-
}
|
|
1271
|
-
export function translateAttachPathToHost(filePath, pathContext) {
|
|
1272
|
-
const runtimePath = posix.isAbsolute(filePath)
|
|
1273
|
-
? filePath
|
|
1274
|
-
: posix.join(pathContext.runtimeWorkspaceRoot, filePath);
|
|
1275
|
-
return translateRuntimePathToHost(runtimePath, pathContext);
|
|
1276
|
-
}
|
|
1277
1411
|
//# sourceMappingURL=agent.js.map
|