@geminixiang/mikan 1.0.0-beta.76 → 1.0.0-beta.78
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 +39 -0
- package/dist/adapters/commands/login.d.ts.map +1 -1
- package/dist/adapters/commands/login.js +0 -9
- package/dist/adapters/commands/login.js.map +1 -1
- package/dist/adapters/commands/manifest.d.ts +0 -19
- package/dist/adapters/commands/manifest.d.ts.map +1 -1
- package/dist/adapters/commands/manifest.js +0 -34
- package/dist/adapters/commands/manifest.js.map +1 -1
- package/dist/adapters/commands/model.d.ts +0 -5
- package/dist/adapters/commands/model.d.ts.map +1 -1
- package/dist/adapters/commands/model.js +0 -5
- package/dist/adapters/commands/model.js.map +1 -1
- package/dist/adapters/commands/new.d.ts.map +1 -1
- package/dist/adapters/commands/new.js +0 -2
- package/dist/adapters/commands/new.js.map +1 -1
- package/dist/adapters/commands/registry.d.ts +0 -1
- package/dist/adapters/commands/registry.d.ts.map +1 -1
- package/dist/adapters/commands/registry.js +0 -8
- package/dist/adapters/commands/registry.js.map +1 -1
- package/dist/adapters/commands/session-view.d.ts.map +1 -1
- package/dist/adapters/commands/session-view.js +0 -2
- package/dist/adapters/commands/session-view.js.map +1 -1
- package/dist/adapters/commands/types.d.ts +0 -29
- package/dist/adapters/commands/types.d.ts.map +1 -1
- package/dist/adapters/commands/types.js.map +1 -1
- package/dist/adapters/commands/utils.d.ts +0 -3
- package/dist/adapters/commands/utils.d.ts.map +1 -1
- package/dist/adapters/commands/utils.js +0 -3
- package/dist/adapters/commands/utils.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +0 -4
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +5 -41
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/discord/components.d.ts +0 -23
- package/dist/adapters/discord/components.d.ts.map +1 -1
- package/dist/adapters/discord/components.js +0 -23
- package/dist/adapters/discord/components.js.map +1 -1
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +1 -11
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/discord/format.d.ts +0 -1
- package/dist/adapters/discord/format.d.ts.map +1 -1
- package/dist/adapters/discord/format.js +0 -37
- package/dist/adapters/discord/format.js.map +1 -1
- package/dist/adapters/github/bot.d.ts +0 -44
- package/dist/adapters/github/bot.d.ts.map +1 -1
- package/dist/adapters/github/bot.js +1 -120
- package/dist/adapters/github/bot.js.map +1 -1
- package/dist/adapters/github/client.d.ts +0 -57
- package/dist/adapters/github/client.d.ts.map +1 -1
- package/dist/adapters/github/client.js +0 -59
- package/dist/adapters/github/client.js.map +1 -1
- package/dist/adapters/github/context.d.ts.map +1 -1
- package/dist/adapters/github/context.js +1 -8
- package/dist/adapters/github/context.js.map +1 -1
- package/dist/adapters/github/github-ops.d.ts +0 -55
- package/dist/adapters/github/github-ops.d.ts.map +1 -1
- package/dist/adapters/github/github-ops.js +0 -59
- package/dist/adapters/github/github-ops.js.map +1 -1
- package/dist/adapters/github/ids.d.ts +0 -27
- package/dist/adapters/github/ids.d.ts.map +1 -1
- package/dist/adapters/github/ids.js +0 -29
- package/dist/adapters/github/ids.js.map +1 -1
- package/dist/adapters/github/repo.d.ts +0 -25
- package/dist/adapters/github/repo.d.ts.map +1 -1
- package/dist/adapters/github/repo.js +0 -49
- package/dist/adapters/github/repo.js.map +1 -1
- package/dist/adapters/github/tool-pack.d.ts +0 -10
- package/dist/adapters/github/tool-pack.d.ts.map +1 -1
- package/dist/adapters/github/tool-pack.js +0 -10
- package/dist/adapters/github/tool-pack.js.map +1 -1
- package/dist/adapters/github/tools/checks.d.ts +0 -6
- package/dist/adapters/github/tools/checks.d.ts.map +1 -1
- package/dist/adapters/github/tools/checks.js +0 -7
- package/dist/adapters/github/tools/checks.js.map +1 -1
- package/dist/adapters/github/tools/issue.d.ts +0 -5
- package/dist/adapters/github/tools/issue.d.ts.map +1 -1
- package/dist/adapters/github/tools/issue.js +0 -5
- package/dist/adapters/github/tools/issue.js.map +1 -1
- package/dist/adapters/github/tools/pr.d.ts +0 -7
- package/dist/adapters/github/tools/pr.d.ts.map +1 -1
- package/dist/adapters/github/tools/pr.js +0 -7
- package/dist/adapters/github/tools/pr.js.map +1 -1
- package/dist/adapters/github/tools/read.d.ts +0 -6
- package/dist/adapters/github/tools/read.d.ts.map +1 -1
- package/dist/adapters/github/tools/read.js +0 -8
- package/dist/adapters/github/tools/read.js.map +1 -1
- package/dist/adapters/github/tools/review-reply.d.ts +0 -5
- package/dist/adapters/github/tools/review-reply.d.ts.map +1 -1
- package/dist/adapters/github/tools/review-reply.js +0 -5
- package/dist/adapters/github/tools/review-reply.js.map +1 -1
- package/dist/adapters/github/tools/sync.d.ts +0 -6
- package/dist/adapters/github/tools/sync.d.ts.map +1 -1
- package/dist/adapters/github/tools/sync.js +0 -6
- package/dist/adapters/github/tools/sync.js.map +1 -1
- package/dist/adapters/github/types.d.ts +0 -88
- package/dist/adapters/github/types.d.ts.map +1 -1
- package/dist/adapters/github/types.js.map +1 -1
- package/dist/adapters/github/webhook.d.ts +0 -13
- package/dist/adapters/github/webhook.d.ts.map +1 -1
- package/dist/adapters/github/webhook.js +0 -16
- package/dist/adapters/github/webhook.js.map +1 -1
- package/dist/adapters/index.d.ts +3 -4
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/intake.d.ts +0 -17
- package/dist/adapters/intake.d.ts.map +1 -1
- package/dist/adapters/intake.js +6 -32
- package/dist/adapters/intake.js.map +1 -1
- package/dist/adapters/markdown-tables.d.ts +0 -10
- package/dist/adapters/markdown-tables.d.ts.map +1 -1
- package/dist/adapters/markdown-tables.js +1 -42
- package/dist/adapters/markdown-tables.js.map +1 -1
- package/dist/adapters/progressive-renderer.d.ts.map +1 -1
- package/dist/adapters/progressive-renderer.js +3 -25
- package/dist/adapters/progressive-renderer.js.map +1 -1
- package/dist/adapters/shared.d.ts +0 -57
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/shared.js +0 -71
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/slack/assistant.d.ts +0 -49
- package/dist/adapters/slack/assistant.d.ts.map +1 -1
- package/dist/adapters/slack/assistant.js +0 -97
- package/dist/adapters/slack/assistant.js.map +1 -1
- package/dist/adapters/slack/auto-reply-context.d.ts +0 -7
- package/dist/adapters/slack/auto-reply-context.d.ts.map +1 -1
- package/dist/adapters/slack/auto-reply-context.js +0 -7
- package/dist/adapters/slack/auto-reply-context.js.map +1 -1
- package/dist/adapters/slack/blocks.d.ts +0 -9
- package/dist/adapters/slack/blocks.d.ts.map +1 -1
- package/dist/adapters/slack/blocks.js +0 -20
- package/dist/adapters/slack/blocks.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +0 -116
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +7 -231
- 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 +1 -3
- package/dist/adapters/slack/context.js.map +1 -1
- package/dist/adapters/slack/jev-context.d.ts +0 -13
- package/dist/adapters/slack/jev-context.d.ts.map +1 -1
- package/dist/adapters/slack/jev-context.js +0 -12
- package/dist/adapters/slack/jev-context.js.map +1 -1
- package/dist/adapters/slack/markdown.d.ts +0 -1
- package/dist/adapters/slack/markdown.d.ts.map +1 -1
- package/dist/adapters/slack/markdown.js +0 -5
- package/dist/adapters/slack/markdown.js.map +1 -1
- package/dist/adapters/slack/persona.d.ts +0 -9
- package/dist/adapters/slack/persona.d.ts.map +1 -1
- package/dist/adapters/slack/persona.js +0 -9
- package/dist/adapters/slack/persona.js.map +1 -1
- package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
- package/dist/adapters/slack/response-lifecycle.js +1 -45
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/slack/session.d.ts +2 -1
- package/dist/adapters/slack/session.d.ts.map +1 -1
- package/dist/adapters/slack/session.js +2 -2
- package/dist/adapters/slack/session.js.map +1 -1
- package/dist/adapters/slack/stream-limits.d.ts +0 -25
- package/dist/adapters/slack/stream-limits.d.ts.map +1 -1
- package/dist/adapters/slack/stream-limits.js +0 -34
- package/dist/adapters/slack/stream-limits.js.map +1 -1
- package/dist/adapters/slack/task-intent.d.ts +0 -13
- package/dist/adapters/slack/task-intent.d.ts.map +1 -1
- package/dist/adapters/slack/task-intent.js +0 -7
- package/dist/adapters/slack/task-intent.js.map +1 -1
- package/dist/adapters/slack/task-status.d.ts +0 -1
- package/dist/adapters/slack/task-status.d.ts.map +1 -1
- package/dist/adapters/slack/task-status.js +1 -9
- package/dist/adapters/slack/task-status.js.map +1 -1
- package/dist/adapters/slack/tool-pack.d.ts +0 -6
- package/dist/adapters/slack/tool-pack.d.ts.map +1 -1
- package/dist/adapters/slack/tool-pack.js +0 -6
- package/dist/adapters/slack/tool-pack.js.map +1 -1
- package/dist/adapters/slack/tools/blockkit.d.ts.map +1 -1
- package/dist/adapters/slack/tools/blockkit.js +0 -11
- package/dist/adapters/slack/tools/blockkit.js.map +1 -1
- package/dist/adapters/slack/types.d.ts +0 -19
- package/dist/adapters/slack/types.d.ts.map +1 -1
- package/dist/adapters/slack/types.js.map +1 -1
- package/dist/adapters/slack/update-diagnostics.d.ts +0 -1
- package/dist/adapters/slack/update-diagnostics.d.ts.map +1 -1
- package/dist/adapters/slack/update-diagnostics.js +1 -7
- package/dist/adapters/slack/update-diagnostics.js.map +1 -1
- package/dist/adapters/telegram/bot.d.ts +0 -6
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +1 -50
- 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 +1 -8
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/adapters/types.d.ts +0 -57
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js.map +1 -1
- package/dist/adapters/web/admin/client-assets.d.ts +4 -0
- package/dist/adapters/web/admin/client-assets.d.ts.map +1 -0
- package/dist/adapters/web/admin/client-assets.js +1765 -0
- package/dist/adapters/web/admin/client-assets.js.map +1 -0
- package/dist/adapters/web/admin/portal.d.ts +0 -10
- package/dist/adapters/web/admin/portal.d.ts.map +1 -1
- package/dist/adapters/web/admin/portal.js +6 -1909
- package/dist/adapters/web/admin/portal.js.map +1 -1
- package/dist/adapters/web/admin/types.d.ts +0 -3
- package/dist/adapters/web/admin/types.d.ts.map +1 -1
- package/dist/adapters/web/admin/types.js.map +1 -1
- package/dist/adapters/web/login/oauth.d.ts.map +1 -1
- package/dist/adapters/web/login/oauth.js +3 -7
- package/dist/adapters/web/login/oauth.js.map +1 -1
- package/dist/adapters/web/login/portal.d.ts +0 -10
- package/dist/adapters/web/login/portal.d.ts.map +1 -1
- package/dist/adapters/web/login/portal.js +4 -37
- package/dist/adapters/web/login/portal.js.map +1 -1
- package/dist/adapters/web/login/types.d.ts +0 -5
- package/dist/adapters/web/login/types.d.ts.map +1 -1
- package/dist/adapters/web/login/types.js.map +1 -1
- package/dist/adapters/web/portal-shell.d.ts +0 -12
- package/dist/adapters/web/portal-shell.d.ts.map +1 -1
- package/dist/adapters/web/portal-shell.js +8 -25
- package/dist/adapters/web/portal-shell.js.map +1 -1
- package/dist/adapters/web/server.d.ts +0 -1
- package/dist/adapters/web/server.d.ts.map +1 -1
- package/dist/adapters/web/server.js +0 -2
- package/dist/adapters/web/server.js.map +1 -1
- package/dist/adapters/web/session-view/portal.d.ts.map +1 -1
- package/dist/adapters/web/session-view/portal.js +13 -24
- package/dist/adapters/web/session-view/portal.js.map +1 -1
- package/dist/adapters/web/session-view/types.d.ts.map +1 -1
- package/dist/adapters/web/session-view/types.js.map +1 -1
- package/dist/adapters/web/token-store.d.ts +0 -2
- package/dist/adapters/web/token-store.d.ts.map +1 -1
- package/dist/adapters/web/token-store.js +0 -2
- package/dist/adapters/web/token-store.js.map +1 -1
- package/dist/cli/arg-grammar.d.ts +0 -3
- package/dist/cli/arg-grammar.d.ts.map +1 -1
- package/dist/cli/arg-grammar.js +0 -3
- package/dist/cli/arg-grammar.js.map +1 -1
- package/dist/cli/boot.d.ts.map +1 -1
- package/dist/cli/boot.js +3 -12
- package/dist/cli/boot.js.map +1 -1
- package/dist/cli/download.d.ts.map +1 -1
- package/dist/cli/download.js +2 -6
- package/dist/cli/download.js.map +1 -1
- package/dist/cli/office.d.ts.map +1 -1
- package/dist/cli/office.js +0 -31
- package/dist/cli/office.js.map +1 -1
- package/dist/cli/onboard.d.ts +0 -2
- package/dist/cli/onboard.d.ts.map +1 -1
- package/dist/cli/onboard.js +0 -30
- package/dist/cli/onboard.js.map +1 -1
- package/dist/cli/process-lifecycle.d.ts +0 -5
- package/dist/cli/process-lifecycle.d.ts.map +1 -1
- package/dist/cli/process-lifecycle.js +0 -6
- package/dist/cli/process-lifecycle.js.map +1 -1
- package/dist/cli/sandbox.d.ts +3 -0
- package/dist/cli/sandbox.d.ts.map +1 -0
- package/dist/cli/sandbox.js +79 -0
- package/dist/cli/sandbox.js.map +1 -0
- package/dist/cli/sessions.d.ts.map +1 -1
- package/dist/cli/sessions.js +0 -11
- package/dist/cli/sessions.js.map +1 -1
- package/dist/cli/types.d.ts +2 -6
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/types.js.map +1 -1
- package/dist/env-manifest.d.ts +0 -21
- package/dist/env-manifest.d.ts.map +1 -1
- package/dist/env-manifest.js +0 -11
- package/dist/env-manifest.js.map +1 -1
- package/dist/events/index.d.ts +0 -51
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +0 -42
- package/dist/events/index.js.map +1 -1
- package/dist/events/scheduler.d.ts +0 -8
- package/dist/events/scheduler.d.ts.map +1 -1
- package/dist/events/scheduler.js +0 -8
- package/dist/events/scheduler.js.map +1 -1
- package/dist/file-guards.d.ts +0 -15
- package/dist/file-guards.d.ts.map +1 -1
- package/dist/file-guards.js +2 -26
- package/dist/file-guards.js.map +1 -1
- package/dist/harness/execution-env.d.ts +0 -15
- package/dist/harness/execution-env.d.ts.map +1 -1
- package/dist/harness/execution-env.js +4 -55
- package/dist/harness/execution-env.js.map +1 -1
- package/dist/harness/http.d.ts +0 -12
- package/dist/harness/http.d.ts.map +1 -1
- package/dist/harness/http.js +0 -34
- package/dist/harness/http.js.map +1 -1
- package/dist/harness/index.d.ts +4 -7
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +4 -7
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/jev.d.ts +0 -28
- package/dist/harness/jev.d.ts.map +1 -1
- package/dist/harness/jev.js +0 -45
- package/dist/harness/jev.js.map +1 -1
- package/dist/harness/mcp-result.d.ts +20 -0
- package/dist/harness/mcp-result.d.ts.map +1 -0
- package/dist/harness/mcp-result.js +171 -0
- package/dist/harness/mcp-result.js.map +1 -0
- package/dist/harness/mcp.d.ts +0 -19
- package/dist/harness/mcp.d.ts.map +1 -1
- package/dist/harness/mcp.js +7 -66
- package/dist/harness/mcp.js.map +1 -1
- package/dist/harness/models.d.ts +0 -19
- package/dist/harness/models.d.ts.map +1 -1
- package/dist/harness/models.js +0 -52
- package/dist/harness/models.js.map +1 -1
- package/dist/harness/open-connector.d.ts +0 -12
- package/dist/harness/open-connector.d.ts.map +1 -1
- package/dist/harness/open-connector.js +0 -22
- package/dist/harness/open-connector.js.map +1 -1
- package/dist/harness/presenter.d.ts +1 -0
- package/dist/harness/presenter.d.ts.map +1 -1
- package/dist/harness/presenter.js +16 -66
- package/dist/harness/presenter.js.map +1 -1
- package/dist/harness/prompt.d.ts +0 -11
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +1 -18
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +8 -28
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session.d.ts +11 -28
- package/dist/harness/session.d.ts.map +1 -1
- package/dist/harness/session.js +100 -38
- package/dist/harness/session.js.map +1 -1
- package/dist/harness/skills.d.ts +0 -22
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +0 -20
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/subagent-profiles.d.ts +0 -4
- package/dist/harness/subagent-profiles.d.ts.map +1 -1
- package/dist/harness/subagent-profiles.js +0 -29
- package/dist/harness/subagent-profiles.js.map +1 -1
- package/dist/harness/subagent.d.ts +0 -25
- package/dist/harness/subagent.d.ts.map +1 -1
- package/dist/harness/subagent.js +1 -70
- package/dist/harness/subagent.js.map +1 -1
- package/dist/harness/tools/event.d.ts.map +1 -1
- package/dist/harness/tools/event.js +0 -9
- package/dist/harness/tools/event.js.map +1 -1
- package/dist/harness/tools/generate-image.d.ts +0 -6
- package/dist/harness/tools/generate-image.d.ts.map +1 -1
- package/dist/harness/tools/generate-image.js.map +1 -1
- package/dist/harness/tools/host-fn-tool.d.ts +0 -17
- package/dist/harness/tools/host-fn-tool.d.ts.map +1 -1
- package/dist/harness/tools/host-fn-tool.js +0 -16
- package/dist/harness/tools/host-fn-tool.js.map +1 -1
- package/dist/harness/tools/index.d.ts +1 -7
- package/dist/harness/tools/index.d.ts.map +1 -1
- package/dist/harness/tools/index.js +3 -14
- package/dist/harness/tools/index.js.map +1 -1
- package/dist/harness/tools/jev-browser.d.ts +4 -94
- package/dist/harness/tools/jev-browser.d.ts.map +1 -1
- package/dist/harness/tools/jev-browser.js +203 -92
- package/dist/harness/tools/jev-browser.js.map +1 -1
- package/dist/harness/tools/jev.d.ts +0 -8
- package/dist/harness/tools/jev.d.ts.map +1 -1
- package/dist/harness/tools/jev.js +0 -11
- package/dist/harness/tools/jev.js.map +1 -1
- package/dist/harness/tools/pi-tools.d.ts +1 -11
- package/dist/harness/tools/pi-tools.d.ts.map +1 -1
- package/dist/harness/tools/pi-tools.js +1 -30
- package/dist/harness/tools/pi-tools.js.map +1 -1
- package/dist/harness/tools/react.d.ts +0 -5
- package/dist/harness/tools/react.d.ts.map +1 -1
- package/dist/harness/tools/react.js +0 -5
- package/dist/harness/tools/react.js.map +1 -1
- package/dist/harness/tools/secret-redaction.d.ts +0 -25
- package/dist/harness/tools/secret-redaction.d.ts.map +1 -1
- package/dist/harness/tools/secret-redaction.js +3 -36
- package/dist/harness/tools/secret-redaction.js.map +1 -1
- package/dist/harness/tools/subagent.d.ts +0 -34
- package/dist/harness/tools/subagent.d.ts.map +1 -1
- package/dist/harness/tools/subagent.js +0 -92
- package/dist/harness/tools/subagent.js.map +1 -1
- package/dist/harness/tools/task.d.ts +0 -1
- package/dist/harness/tools/task.d.ts.map +1 -1
- package/dist/harness/tools/task.js +0 -1
- package/dist/harness/tools/task.js.map +1 -1
- package/dist/harness/tools/types.d.ts +0 -16
- package/dist/harness/tools/types.d.ts.map +1 -1
- package/dist/harness/tools/types.js.map +1 -1
- package/dist/harness/types.d.ts +1 -77
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +0 -13
- package/dist/log.js.map +1 -1
- package/dist/main.js +7 -52
- package/dist/main.js.map +1 -1
- package/dist/memory-capture/index.d.ts +16 -0
- package/dist/memory-capture/index.d.ts.map +1 -0
- package/dist/memory-capture/index.js +194 -0
- package/dist/memory-capture/index.js.map +1 -0
- package/dist/memory-capture/types.d.ts +27 -0
- package/dist/memory-capture/types.d.ts.map +1 -0
- package/dist/memory-capture/types.js.map +1 -0
- package/dist/observability/index.d.ts +0 -9
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +0 -9
- package/dist/observability/index.js.map +1 -1
- package/dist/observability/instrument.js +0 -5
- package/dist/observability/instrument.js.map +1 -1
- package/dist/observability/otel.js +0 -1
- package/dist/observability/otel.js.map +1 -1
- package/dist/observability/sentry.d.ts +0 -18
- package/dist/observability/sentry.d.ts.map +1 -1
- package/dist/observability/sentry.js +0 -36
- package/dist/observability/sentry.js.map +1 -1
- package/dist/observability/types.d.ts +1 -10
- package/dist/observability/types.d.ts.map +1 -1
- package/dist/observability/types.js.map +1 -1
- package/dist/office/index.d.ts +0 -76
- package/dist/office/index.d.ts.map +1 -1
- package/dist/office/index.js +4 -154
- package/dist/office/index.js.map +1 -1
- package/dist/office/projection.d.ts +0 -29
- package/dist/office/projection.d.ts.map +1 -1
- package/dist/office/projection.js +5 -41
- package/dist/office/projection.js.map +1 -1
- package/dist/office/types.d.ts +0 -66
- package/dist/office/types.d.ts.map +1 -1
- package/dist/office/types.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +22 -83
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/session-lifecycle.d.ts +0 -10
- package/dist/runtime/session-lifecycle.d.ts.map +1 -1
- package/dist/runtime/session-lifecycle.js +0 -12
- package/dist/runtime/session-lifecycle.js.map +1 -1
- package/dist/runtime/types.d.ts +2 -29
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +2 -1
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +21 -15
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +0 -2
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/identity.d.ts +0 -28
- package/dist/sandbox/identity.d.ts.map +1 -1
- package/dist/sandbox/identity.js +0 -28
- package/dist/sandbox/identity.js.map +1 -1
- package/dist/sandbox/index.d.ts +0 -18
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +2 -19
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/layout.d.ts +7 -0
- package/dist/sandbox/layout.d.ts.map +1 -0
- package/dist/sandbox/layout.js +13 -0
- package/dist/sandbox/layout.js.map +1 -0
- package/dist/sandbox/provisioner.d.ts +24 -65
- package/dist/sandbox/provisioner.d.ts.map +1 -1
- package/dist/sandbox/provisioner.js +213 -125
- package/dist/sandbox/provisioner.js.map +1 -1
- package/dist/sandbox/types.d.ts +0 -39
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +2 -5
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +31 -31
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts +0 -6
- package/dist/sessions/chat-history-sync.d.ts.map +1 -1
- package/dist/sessions/chat-history-sync.js +1 -33
- package/dist/sessions/chat-history-sync.js.map +1 -1
- package/dist/sessions/history-line.d.ts +0 -20
- package/dist/sessions/history-line.d.ts.map +1 -1
- package/dist/sessions/history-line.js +0 -20
- package/dist/sessions/history-line.js.map +1 -1
- package/dist/sessions/migrate-common.d.ts +0 -15
- package/dist/sessions/migrate-common.d.ts.map +1 -1
- package/dist/sessions/migrate-common.js +0 -19
- package/dist/sessions/migrate-common.js.map +1 -1
- package/dist/sessions/migrate-pi-084.d.ts.map +1 -1
- package/dist/sessions/migrate-pi-084.js +0 -7
- package/dist/sessions/migrate-pi-084.js.map +1 -1
- package/dist/sessions/migrate-v3.d.ts +0 -7
- package/dist/sessions/migrate-v3.d.ts.map +1 -1
- package/dist/sessions/migrate-v3.js +1 -67
- package/dist/sessions/migrate-v3.js.map +1 -1
- package/dist/sessions/session-key.d.ts +3 -17
- package/dist/sessions/session-key.d.ts.map +1 -1
- package/dist/sessions/session-key.js +8 -35
- package/dist/sessions/session-key.js.map +1 -1
- package/dist/sessions/session-store.d.ts +1 -7
- package/dist/sessions/session-store.d.ts.map +1 -1
- package/dist/sessions/session-store.js +8 -50
- package/dist/sessions/session-store.js.map +1 -1
- package/dist/sessions/store.d.ts +0 -60
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +0 -113
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +0 -17
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/settings/apply.d.ts +0 -6
- package/dist/settings/apply.d.ts.map +1 -1
- package/dist/settings/apply.js +0 -29
- package/dist/settings/apply.js.map +1 -1
- package/dist/settings/index.d.ts +0 -53
- package/dist/settings/index.d.ts.map +1 -1
- package/dist/settings/index.js +0 -77
- package/dist/settings/index.js.map +1 -1
- package/dist/settings/migrate.d.ts +0 -5
- package/dist/settings/migrate.d.ts.map +1 -1
- package/dist/settings/migrate.js +0 -17
- package/dist/settings/migrate.js.map +1 -1
- package/dist/types.d.ts +9 -159
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/index.d.ts +2 -36
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +135 -65
- package/dist/vault/index.js.map +1 -1
- package/dist/vault/types.d.ts +0 -15
- package/dist/vault/types.d.ts.map +1 -1
- package/dist/vault/types.js.map +1 -1
- package/package.json +1 -1
- package/dist/dream/index.d.ts +0 -20
- package/dist/dream/index.d.ts.map +0 -1
- package/dist/dream/index.js +0 -264
- package/dist/dream/index.js.map +0 -1
- package/dist/dream/types.d.ts +0 -30
- package/dist/dream/types.d.ts.map +0 -1
- package/dist/dream/types.js.map +0 -1
- /package/dist/{dream → memory-capture}/types.js +0 -0
package/dist/harness/jev.js
CHANGED
|
@@ -1,33 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Jev (typesafe/jev) client, backed by `@geminixiang/jev`.
|
|
3
|
-
*
|
|
4
|
-
* Jev is a "System One" evaluation model: it scores a shared `state`
|
|
5
|
-
* against typed questions (a yes/no probability, a multiple choice, or a
|
|
6
|
-
* position on an ordered scale) and returns calibrated probabilities. It
|
|
7
|
-
* does not generate text or tool calls, so it cannot be driven through
|
|
8
|
-
* pi-ai's `Provider`/`Model`/`stream()` contract the way every model
|
|
9
|
-
* `models.ts` catalogs is — that contract is chat/completion shaped
|
|
10
|
-
* (system prompt + messages in, streamed text/tool-call events out), and
|
|
11
|
-
* Jev's typed-decision shape does not fit it. Jev is therefore not a
|
|
12
|
-
* selectable chat provider: callers import `evaluateWithJev` directly at
|
|
13
|
-
* whatever call site wants a fast, cheap, type-safe decision (e.g.
|
|
14
|
-
* classification, routing, guardrails), and interpret the returned
|
|
15
|
-
* probabilities themselves.
|
|
16
|
-
*
|
|
17
|
-
* `@geminixiang/jev` owns the wire protocol, provider catalog, and auth
|
|
18
|
-
* resolution for four backends (TypeSafe, OpenRouter, Vercel AI Gateway,
|
|
19
|
-
* Cloudflare Workers AI); this module picks OpenRouter (the same key
|
|
20
|
-
* pi-ai's `openrouter` chat provider reads) and adapts its typed
|
|
21
|
-
* request/answer shapes to the caller-facing contract mikan's call sites
|
|
22
|
-
* already depend on, so this file is the only one that needs to know a
|
|
23
|
-
* dependency swap happened.
|
|
24
|
-
*/
|
|
25
1
|
import { createBuiltinJevModels, JevAPIError, JevAuthError, JevConfigError, JevConnectionError, JevResponseError, JevTimeoutError, } from "@geminixiang/jev";
|
|
26
2
|
import { readEnv } from "../env-manifest.js";
|
|
27
3
|
import { recordJevOutcome } from "../observability/index.js";
|
|
28
|
-
/** The current public Jev model id on OpenRouter. */
|
|
29
4
|
export const JEV_MODEL_ID = "~typesafe/jev-latest";
|
|
30
|
-
/** Thrown when no Jev backend has a usable credential. Callers fail closed on this. */
|
|
31
5
|
export class JevNotConfiguredError extends Error {
|
|
32
6
|
constructor() {
|
|
33
7
|
super("Jev requires OPENROUTER_API_KEY (an OpenRouter API key). Set it in the environment before calling evaluateWithJev().");
|
|
@@ -41,12 +15,6 @@ export class JevRequestError extends Error {
|
|
|
41
15
|
this.name = "JevRequestError";
|
|
42
16
|
}
|
|
43
17
|
}
|
|
44
|
-
// ── @geminixiang/jev wiring ──────────────────────────────────────────────
|
|
45
|
-
/**
|
|
46
|
-
* Routes env reads through `readEnv` so `MIKAN_OPENROUTER_API_KEY` resolves
|
|
47
|
-
* the same as every other mikan-aliased credential, instead of the
|
|
48
|
-
* package's default `process.env`-only context.
|
|
49
|
-
*/
|
|
50
18
|
const mikanAuthContext = {
|
|
51
19
|
async env(name) {
|
|
52
20
|
return readEnv(name);
|
|
@@ -63,9 +31,6 @@ function models() {
|
|
|
63
31
|
function toGeminixiangQuestion(question) {
|
|
64
32
|
const instructions = question.instructions;
|
|
65
33
|
if (question.type === "boolean") {
|
|
66
|
-
// `@geminixiang/jev` leaves noul criteria optional; mikan has always sent
|
|
67
|
-
// an explicit Yes/No default so the wire payload (and anything tuned
|
|
68
|
-
// against it, e.g. the auto-reply gate) does not change under this swap.
|
|
69
34
|
return {
|
|
70
35
|
type: "noul",
|
|
71
36
|
instructions,
|
|
@@ -108,20 +73,10 @@ function fromGeminixiangAnswer(answer) {
|
|
|
108
73
|
confidence: answer.confidence,
|
|
109
74
|
};
|
|
110
75
|
}
|
|
111
|
-
/**
|
|
112
|
-
* Evaluate one or more typed questions against a shared `state` using Jev,
|
|
113
|
-
* reached through OpenRouter's decisions API by way of `@geminixiang/jev`.
|
|
114
|
-
* Every question is scored independently against the same state in a
|
|
115
|
-
* single request; batching questions here is cheap (they share the input)
|
|
116
|
-
* and is preferred over separate calls per question.
|
|
117
|
-
*/
|
|
118
76
|
export async function evaluateWithJev(state, questions, options) {
|
|
119
77
|
const catalogModel = models().getModel("openrouter", "jev-latest");
|
|
120
78
|
if (!catalogModel)
|
|
121
79
|
throw new JevNotConfiguredError();
|
|
122
|
-
// `options.model` is the wire model id callers already pass (e.g. from
|
|
123
|
-
// JEV_MODEL_ID); override the catalog slug directly rather than adding a
|
|
124
|
-
// second catalog entry per possible override.
|
|
125
80
|
const model = options.model ? { ...catalogModel, slug: options.model } : catalogModel;
|
|
126
81
|
const wireQuestions = {};
|
|
127
82
|
for (const [id, question] of Object.entries(questions)) {
|
package/dist/harness/jev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jev.js","sourceRoot":"","sources":["../../src/harness/jev.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Jev (typesafe/jev) client, backed by `@geminixiang/jev`.\n *\n * Jev is a \"System One\" evaluation model: it scores a shared `state`\n * against typed questions (a yes/no probability, a multiple choice, or a\n * position on an ordered scale) and returns calibrated probabilities. It\n * does not generate text or tool calls, so it cannot be driven through\n * pi-ai's `Provider`/`Model`/`stream()` contract the way every model\n * `models.ts` catalogs is — that contract is chat/completion shaped\n * (system prompt + messages in, streamed text/tool-call events out), and\n * Jev's typed-decision shape does not fit it. Jev is therefore not a\n * selectable chat provider: callers import `evaluateWithJev` directly at\n * whatever call site wants a fast, cheap, type-safe decision (e.g.\n * classification, routing, guardrails), and interpret the returned\n * probabilities themselves.\n *\n * `@geminixiang/jev` owns the wire protocol, provider catalog, and auth\n * resolution for four backends (TypeSafe, OpenRouter, Vercel AI Gateway,\n * Cloudflare Workers AI); this module picks OpenRouter (the same key\n * pi-ai's `openrouter` chat provider reads) and adapts its typed\n * request/answer shapes to the caller-facing contract mikan's call sites\n * already depend on, so this file is the only one that needs to know a\n * dependency swap happened.\n */\nimport {\n createBuiltinJevModels,\n JevAPIError,\n JevAuthError,\n JevConfigError,\n JevConnectionError,\n JevResponseError,\n JevTimeoutError,\n type AnswerFor as GeminixiangAnswerFor,\n type Entry as GeminixiangEntry,\n type Question as GeminixiangQuestion,\n} from \"@geminixiang/jev\";\nimport type { AuthContext } from \"@earendil-works/pi-ai\";\nimport { readEnv } from \"../env-manifest.js\";\nimport { recordJevOutcome, type JevCaller } from \"../observability/index.js\";\n\n/** The current public Jev model id on OpenRouter. */\nexport const JEV_MODEL_ID = \"~typesafe/jev-latest\";\n\n/**\n * Any value Jev accepts as text-bearing structure: a string, a JSON object,\n * an array, or `null`. State, instructions, and criteria descriptions all\n * take this shape; Jev is trained to read the structure, so objects with\n * labelled keys are preferred over string templates.\n */\nexport type JevEntry = string | number | boolean | null | JevEntry[] | { [key: string]: JevEntry };\n\n/** A shared caller-facing question shape; translated to `@geminixiang/jev`'s shape below. */\nexport type JevQuestion =\n | {\n type: \"boolean\";\n instructions: JevEntry;\n /** Optional descriptions of the yes / no outcomes. */\n criteria?: { true?: JevEntry; false?: JevEntry };\n }\n | { type: \"choice\"; instructions: JevEntry; criteria: Record<string, JevEntry> }\n | { type: \"score\"; instructions: JevEntry; criteria: readonly JevEntry[] };\n\nexport type JevQuestions = Record<string, JevQuestion>;\n\nexport type JevAnswer<QUESTION extends JevQuestion> = QUESTION extends { type: \"choice\" }\n ? {\n type: \"choice\";\n choice: string;\n probabilities?: Record<string, number>;\n /** 0-1 statistic over `probabilities`; low means no option clearly fits. */\n confidence?: number;\n }\n : QUESTION extends { type: \"score\" }\n ? {\n type: \"score\";\n /** Expected level index; fractional between levels. */\n score: number;\n probabilities?: Record<string, number>;\n /** Level index -> criterion text, as echoed by Jev. */\n legend?: Record<string, string>;\n confidence?: number;\n }\n : { type: \"boolean\"; probability: number };\n\nexport interface JevResult<QUESTIONS extends JevQuestions> {\n readonly answers: { [ID in keyof QUESTIONS]: JevAnswer<QUESTIONS[ID]> };\n readonly usage: {\n inputTokens: number | undefined;\n outputTokens: number | undefined;\n cost: number | undefined;\n };\n readonly model: string;\n}\n\n/** Thrown when no Jev backend has a usable credential. Callers fail closed on this. */\nexport class JevNotConfiguredError extends Error {\n constructor() {\n super(\n \"Jev requires OPENROUTER_API_KEY (an OpenRouter API key). Set it in the environment before calling evaluateWithJev().\",\n );\n this.name = \"JevNotConfiguredError\";\n }\n}\n\nexport class JevRequestError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n ) {\n super(message);\n this.name = \"JevRequestError\";\n }\n}\n\nexport interface EvaluateWithJevOptions {\n /** Evaluation model id; defaults to the current public Jev model. */\n model?: string;\n abortSignal?: AbortSignal;\n headers?: Record<string, string>;\n /**\n * Which call site is asking, so Jev spend is attributable in Sentry/OTel\n * (`agent.jev.cost`, tagged `caller`) without any judged content leaving\n * this function. Required rather than defaulted so a new call site must\n * consciously pick an attribution instead of spend silently landing in a\n * generic bucket.\n */\n caller: JevCaller;\n}\n\n// ── @geminixiang/jev wiring ──────────────────────────────────────────────\n\n/**\n * Routes env reads through `readEnv` so `MIKAN_OPENROUTER_API_KEY` resolves\n * the same as every other mikan-aliased credential, instead of the\n * package's default `process.env`-only context.\n */\nconst mikanAuthContext: AuthContext = {\n async env(name) {\n return readEnv(name);\n },\n async fileExists() {\n return false;\n },\n};\n\nlet cachedModels: ReturnType<typeof createBuiltinJevModels> | undefined;\n\nfunction models() {\n cachedModels ??= createBuiltinJevModels({ authContext: mikanAuthContext });\n return cachedModels;\n}\n\nfunction toGeminixiangQuestion(question: JevQuestion): GeminixiangQuestion {\n const instructions = question.instructions as GeminixiangEntry;\n if (question.type === \"boolean\") {\n // `@geminixiang/jev` leaves noul criteria optional; mikan has always sent\n // an explicit Yes/No default so the wire payload (and anything tuned\n // against it, e.g. the auto-reply gate) does not change under this swap.\n return {\n type: \"noul\",\n instructions,\n criteria: {\n true: (question.criteria?.true as GeminixiangEntry) ?? \"Yes\",\n false: (question.criteria?.false as GeminixiangEntry) ?? \"No\",\n },\n };\n }\n if (question.type === \"choice\") {\n return {\n type: \"choice\",\n instructions,\n criteria: question.criteria as Record<string, GeminixiangEntry>,\n };\n }\n const [first, second, ...rest] = question.criteria as GeminixiangEntry[];\n if (first === undefined || second === undefined) {\n throw new Error(\"score questions need at least two levels\");\n }\n return { type: \"score\", instructions, criteria: [first, second, ...rest] };\n}\n\nfunction fromGeminixiangAnswer(\n answer: GeminixiangAnswerFor<GeminixiangQuestion>,\n): JevAnswer<JevQuestion> {\n if (answer.type === \"noul\") {\n return { type: \"boolean\", probability: answer.noul };\n }\n if (answer.type === \"choice\") {\n return {\n type: \"choice\",\n choice: answer.choice,\n probabilities: answer.probabilities as Record<string, number>,\n confidence: answer.confidence,\n };\n }\n return {\n type: \"score\",\n score: answer.score,\n probabilities: answer.probabilities,\n legend: answer.legend as Record<string, string> | undefined,\n confidence: answer.confidence,\n };\n}\n\n/**\n * Evaluate one or more typed questions against a shared `state` using Jev,\n * reached through OpenRouter's decisions API by way of `@geminixiang/jev`.\n * Every question is scored independently against the same state in a\n * single request; batching questions here is cheap (they share the input)\n * and is preferred over separate calls per question.\n */\nexport async function evaluateWithJev<const QUESTIONS extends JevQuestions>(\n state: JevEntry,\n questions: QUESTIONS,\n options: EvaluateWithJevOptions,\n): Promise<JevResult<QUESTIONS>> {\n const catalogModel = models().getModel(\"openrouter\", \"jev-latest\");\n if (!catalogModel) throw new JevNotConfiguredError();\n // `options.model` is the wire model id callers already pass (e.g. from\n // JEV_MODEL_ID); override the catalog slug directly rather than adding a\n // second catalog entry per possible override.\n const model = options.model ? { ...catalogModel, slug: options.model } : catalogModel;\n\n const wireQuestions: Record<string, GeminixiangQuestion> = {};\n for (const [id, question] of Object.entries(questions)) {\n wireQuestions[id] = toGeminixiangQuestion(question);\n }\n\n const startedAt = Date.now();\n let result;\n try {\n result = await models().evaluate(\n model,\n { state: state as GeminixiangEntry, questions: wireQuestions },\n {\n ...(options.headers ? { headers: options.headers } : {}),\n ...(options.abortSignal ? { signal: options.abortSignal } : {}),\n },\n );\n } catch (error) {\n recordJevOutcome({\n caller: options.caller,\n status: \"error\",\n errorType: error instanceof Error ? error.name : \"Error\",\n durationMs: Date.now() - startedAt,\n });\n if (error instanceof JevAuthError || error instanceof JevConfigError) {\n throw new JevNotConfiguredError();\n }\n if (error instanceof JevAPIError) {\n throw new JevRequestError(error.message, error.status);\n }\n if (\n error instanceof JevResponseError ||\n error instanceof JevConnectionError ||\n error instanceof JevTimeoutError\n ) {\n throw new JevRequestError(error.message, 502);\n }\n throw error;\n }\n recordJevOutcome({\n caller: options.caller,\n status: \"ok\",\n inputTokens: result.usage.input,\n outputTokens: result.usage.output,\n costUsd: result.usage.cost.total,\n durationMs: Date.now() - startedAt,\n });\n\n const answers = {} as { [ID in keyof QUESTIONS]: JevAnswer<QUESTIONS[ID]> };\n for (const id of Object.keys(questions)) {\n const answer = result.answers[id];\n if (!answer) throw new JevRequestError(`Jev response missing answer for \"${id}\"`, 502);\n (answers as Record<string, JevAnswer<JevQuestion>>)[id] = fromGeminixiangAnswer(answer);\n }\n\n return {\n answers,\n usage: {\n inputTokens: result.usage.input,\n outputTokens: result.usage.output,\n cost: result.usage.cost.total,\n },\n model: result.model,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"jev.js","sourceRoot":"","sources":["../../src/harness/jev.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createBuiltinJevModels,\n JevAPIError,\n JevAuthError,\n JevConfigError,\n JevConnectionError,\n JevResponseError,\n JevTimeoutError,\n type AnswerFor as GeminixiangAnswerFor,\n type Entry as GeminixiangEntry,\n type Question as GeminixiangQuestion,\n} from \"@geminixiang/jev\";\nimport type { AuthContext } from \"@earendil-works/pi-ai\";\nimport { readEnv } from \"../env-manifest.js\";\nimport { recordJevOutcome, type JevCaller } from \"../observability/index.js\";\n\nexport const JEV_MODEL_ID = \"~typesafe/jev-latest\";\n\nexport type JevEntry = string | number | boolean | null | JevEntry[] | { [key: string]: JevEntry };\n\nexport type JevQuestion =\n | {\n type: \"boolean\";\n instructions: JevEntry;\n criteria?: { true?: JevEntry; false?: JevEntry };\n }\n | { type: \"choice\"; instructions: JevEntry; criteria: Record<string, JevEntry> }\n | { type: \"score\"; instructions: JevEntry; criteria: readonly JevEntry[] };\n\nexport type JevQuestions = Record<string, JevQuestion>;\n\nexport type JevAnswer<QUESTION extends JevQuestion> = QUESTION extends { type: \"choice\" }\n ? {\n type: \"choice\";\n choice: string;\n probabilities?: Record<string, number>;\n confidence?: number;\n }\n : QUESTION extends { type: \"score\" }\n ? {\n type: \"score\";\n score: number;\n probabilities?: Record<string, number>;\n legend?: Record<string, string>;\n confidence?: number;\n }\n : { type: \"boolean\"; probability: number };\n\nexport interface JevResult<QUESTIONS extends JevQuestions> {\n readonly answers: { [ID in keyof QUESTIONS]: JevAnswer<QUESTIONS[ID]> };\n readonly usage: {\n inputTokens: number | undefined;\n outputTokens: number | undefined;\n cost: number | undefined;\n };\n readonly model: string;\n}\n\nexport class JevNotConfiguredError extends Error {\n constructor() {\n super(\n \"Jev requires OPENROUTER_API_KEY (an OpenRouter API key). Set it in the environment before calling evaluateWithJev().\",\n );\n this.name = \"JevNotConfiguredError\";\n }\n}\n\nexport class JevRequestError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n ) {\n super(message);\n this.name = \"JevRequestError\";\n }\n}\n\nexport interface EvaluateWithJevOptions {\n model?: string;\n abortSignal?: AbortSignal;\n headers?: Record<string, string>;\n caller: JevCaller;\n}\n\nconst mikanAuthContext: AuthContext = {\n async env(name) {\n return readEnv(name);\n },\n async fileExists() {\n return false;\n },\n};\n\nlet cachedModels: ReturnType<typeof createBuiltinJevModels> | undefined;\n\nfunction models() {\n cachedModels ??= createBuiltinJevModels({ authContext: mikanAuthContext });\n return cachedModels;\n}\n\nfunction toGeminixiangQuestion(question: JevQuestion): GeminixiangQuestion {\n const instructions = question.instructions as GeminixiangEntry;\n if (question.type === \"boolean\") {\n return {\n type: \"noul\",\n instructions,\n criteria: {\n true: (question.criteria?.true as GeminixiangEntry) ?? \"Yes\",\n false: (question.criteria?.false as GeminixiangEntry) ?? \"No\",\n },\n };\n }\n if (question.type === \"choice\") {\n return {\n type: \"choice\",\n instructions,\n criteria: question.criteria as Record<string, GeminixiangEntry>,\n };\n }\n const [first, second, ...rest] = question.criteria as GeminixiangEntry[];\n if (first === undefined || second === undefined) {\n throw new Error(\"score questions need at least two levels\");\n }\n return { type: \"score\", instructions, criteria: [first, second, ...rest] };\n}\n\nfunction fromGeminixiangAnswer(\n answer: GeminixiangAnswerFor<GeminixiangQuestion>,\n): JevAnswer<JevQuestion> {\n if (answer.type === \"noul\") {\n return { type: \"boolean\", probability: answer.noul };\n }\n if (answer.type === \"choice\") {\n return {\n type: \"choice\",\n choice: answer.choice,\n probabilities: answer.probabilities as Record<string, number>,\n confidence: answer.confidence,\n };\n }\n return {\n type: \"score\",\n score: answer.score,\n probabilities: answer.probabilities,\n legend: answer.legend as Record<string, string> | undefined,\n confidence: answer.confidence,\n };\n}\n\nexport async function evaluateWithJev<const QUESTIONS extends JevQuestions>(\n state: JevEntry,\n questions: QUESTIONS,\n options: EvaluateWithJevOptions,\n): Promise<JevResult<QUESTIONS>> {\n const catalogModel = models().getModel(\"openrouter\", \"jev-latest\");\n if (!catalogModel) throw new JevNotConfiguredError();\n const model = options.model ? { ...catalogModel, slug: options.model } : catalogModel;\n\n const wireQuestions: Record<string, GeminixiangQuestion> = {};\n for (const [id, question] of Object.entries(questions)) {\n wireQuestions[id] = toGeminixiangQuestion(question);\n }\n\n const startedAt = Date.now();\n let result;\n try {\n result = await models().evaluate(\n model,\n { state: state as GeminixiangEntry, questions: wireQuestions },\n {\n ...(options.headers ? { headers: options.headers } : {}),\n ...(options.abortSignal ? { signal: options.abortSignal } : {}),\n },\n );\n } catch (error) {\n recordJevOutcome({\n caller: options.caller,\n status: \"error\",\n errorType: error instanceof Error ? error.name : \"Error\",\n durationMs: Date.now() - startedAt,\n });\n if (error instanceof JevAuthError || error instanceof JevConfigError) {\n throw new JevNotConfiguredError();\n }\n if (error instanceof JevAPIError) {\n throw new JevRequestError(error.message, error.status);\n }\n if (\n error instanceof JevResponseError ||\n error instanceof JevConnectionError ||\n error instanceof JevTimeoutError\n ) {\n throw new JevRequestError(error.message, 502);\n }\n throw error;\n }\n recordJevOutcome({\n caller: options.caller,\n status: \"ok\",\n inputTokens: result.usage.input,\n outputTokens: result.usage.output,\n costUsd: result.usage.cost.total,\n durationMs: Date.now() - startedAt,\n });\n\n const answers = {} as { [ID in keyof QUESTIONS]: JevAnswer<QUESTIONS[ID]> };\n for (const id of Object.keys(questions)) {\n const answer = result.answers[id];\n if (!answer) throw new JevRequestError(`Jev response missing answer for \"${id}\"`, 502);\n (answers as Record<string, JevAnswer<JevQuestion>>)[id] = fromGeminixiangAnswer(answer);\n }\n\n return {\n answers,\n usage: {\n inputTokens: result.usage.input,\n outputTokens: result.usage.output,\n cost: result.usage.cost.total,\n },\n model: result.model,\n };\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ImageContent, TextContent } from "@earendil-works/pi-ai";
|
|
2
|
+
import { type AgentToolResult, type Context, type ExecutionEnv } from "@earendil-works/pi-agent-core";
|
|
3
|
+
export interface McpTextLimits {
|
|
4
|
+
maxBytes: number;
|
|
5
|
+
maxLines: number;
|
|
6
|
+
}
|
|
7
|
+
export interface BoundedMcpText {
|
|
8
|
+
text: string;
|
|
9
|
+
truncated: boolean;
|
|
10
|
+
digest?: true;
|
|
11
|
+
}
|
|
12
|
+
export interface McpCallResult {
|
|
13
|
+
content?: unknown;
|
|
14
|
+
structuredContent?: unknown;
|
|
15
|
+
isError?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function mcpResultContent(result: McpCallResult): (TextContent | ImageContent)[];
|
|
18
|
+
export declare function boundMcpText(text: string, limits: McpTextLimits): BoundedMcpText;
|
|
19
|
+
export declare function guardMcpToolResult(result: McpCallResult, env: ExecutionEnv, context: Context): Promise<AgentToolResult<undefined>>;
|
|
20
|
+
//# sourceMappingURL=mcp-result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-result.d.ts","sourceRoot":"","sources":["../../src/harness/mcp-result.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,YAAY,EAClB,MAAM,+BAA+B,CAAC;AAGvC,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,IAAI,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAiED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAStF;AAsDD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,cAAc,CAehF;AAoCD,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAkBrC"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead, } from "@earendil-works/pi-agent-core";
|
|
3
|
+
import { redactSecrets } from "./tools/secret-redaction.js";
|
|
4
|
+
const SPILL_DIR = [".mikan", "mcp-output"];
|
|
5
|
+
const NOTICE_RESERVE_BYTES = 640;
|
|
6
|
+
const NOTICE_RESERVE_LINES = 4;
|
|
7
|
+
const RESULT_LIMITS = {
|
|
8
|
+
maxBytes: DEFAULT_MAX_BYTES - NOTICE_RESERVE_BYTES,
|
|
9
|
+
maxLines: DEFAULT_MAX_LINES - NOTICE_RESERVE_LINES,
|
|
10
|
+
};
|
|
11
|
+
const DIGEST_LEVELS = [
|
|
12
|
+
{ stringChars: 200, arrayItems: 3, depth: 6 },
|
|
13
|
+
{ stringChars: 80, arrayItems: 2, depth: 4 },
|
|
14
|
+
{ stringChars: 40, arrayItems: 1, depth: 3 },
|
|
15
|
+
{ stringChars: 16, arrayItems: 1, depth: 2 },
|
|
16
|
+
];
|
|
17
|
+
function isRecord(value) {
|
|
18
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19
|
+
}
|
|
20
|
+
function stringField(block, key) {
|
|
21
|
+
const value = block[key];
|
|
22
|
+
return typeof value === "string" ? value : undefined;
|
|
23
|
+
}
|
|
24
|
+
function describeResource(resource) {
|
|
25
|
+
const uri = stringField(resource, "uri") ?? "(no URI)";
|
|
26
|
+
const text = stringField(resource, "text");
|
|
27
|
+
if (text !== undefined)
|
|
28
|
+
return `[Resource: ${uri}]\n${text}`;
|
|
29
|
+
const blob = stringField(resource, "blob");
|
|
30
|
+
const mimeType = stringField(resource, "mimeType") ?? "unknown type";
|
|
31
|
+
const size = blob === undefined ? "no content" : `${Buffer.byteLength(blob, "base64")} bytes`;
|
|
32
|
+
return `[Resource: ${uri} (${mimeType}, ${size}, binary content omitted)]`;
|
|
33
|
+
}
|
|
34
|
+
function blockContent(block) {
|
|
35
|
+
const text = stringField(block, "text");
|
|
36
|
+
if (block.type === "text" && text !== undefined)
|
|
37
|
+
return { type: "text", text };
|
|
38
|
+
const data = stringField(block, "data");
|
|
39
|
+
const mimeType = stringField(block, "mimeType");
|
|
40
|
+
if (block.type === "image" && data !== undefined && mimeType !== undefined) {
|
|
41
|
+
return { type: "image", data, mimeType };
|
|
42
|
+
}
|
|
43
|
+
if (block.type === "resource" && isRecord(block.resource)) {
|
|
44
|
+
return { type: "text", text: describeResource(block.resource) };
|
|
45
|
+
}
|
|
46
|
+
if (block.type === "resource_link") {
|
|
47
|
+
const uri = stringField(block, "uri") ?? "(no URI)";
|
|
48
|
+
return { type: "text", text: `[Resource link: ${stringField(block, "name") ?? uri}] ${uri}` };
|
|
49
|
+
}
|
|
50
|
+
if (block.type === "audio") {
|
|
51
|
+
return { type: "text", text: `[Audio content omitted: ${mimeType ?? "audio/*"}]` };
|
|
52
|
+
}
|
|
53
|
+
return { type: "text", text: JSON.stringify(block) };
|
|
54
|
+
}
|
|
55
|
+
export function mcpResultContent(result) {
|
|
56
|
+
const blocks = (Array.isArray(result.content) ? result.content : [])
|
|
57
|
+
.filter(isRecord)
|
|
58
|
+
.map(blockContent);
|
|
59
|
+
if (blocks.length > 0)
|
|
60
|
+
return blocks;
|
|
61
|
+
if (result.structuredContent !== undefined && result.structuredContent !== null) {
|
|
62
|
+
return [{ type: "text", text: JSON.stringify(result.structuredContent) }];
|
|
63
|
+
}
|
|
64
|
+
return [{ type: "text", text: "(empty result)" }];
|
|
65
|
+
}
|
|
66
|
+
function parseJson(text) {
|
|
67
|
+
const trimmed = text.trimStart();
|
|
68
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("["))
|
|
69
|
+
return undefined;
|
|
70
|
+
try {
|
|
71
|
+
return { value: JSON.parse(text) };
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function digest(value, level, depth = 0) {
|
|
78
|
+
if (typeof value === "string") {
|
|
79
|
+
return value.length <= level.stringChars
|
|
80
|
+
? value
|
|
81
|
+
: `${value.slice(0, level.stringChars)}…[+${value.length - level.stringChars} chars]`;
|
|
82
|
+
}
|
|
83
|
+
if (Array.isArray(value)) {
|
|
84
|
+
if (depth >= level.depth)
|
|
85
|
+
return `[…${value.length} items]`;
|
|
86
|
+
const kept = value.slice(0, level.arrayItems).map((item) => digest(item, level, depth + 1));
|
|
87
|
+
const hidden = value.length - kept.length;
|
|
88
|
+
return hidden > 0 ? [...kept, `…[+${hidden} more items]`] : kept;
|
|
89
|
+
}
|
|
90
|
+
if (isRecord(value)) {
|
|
91
|
+
if (depth >= level.depth)
|
|
92
|
+
return `{…${Object.keys(value).length} keys}`;
|
|
93
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, digest(item, level, depth + 1)]));
|
|
94
|
+
}
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
function fits(text, limits) {
|
|
98
|
+
return (Buffer.byteLength(text, "utf8") <= limits.maxBytes && text.split("\n").length <= limits.maxLines);
|
|
99
|
+
}
|
|
100
|
+
function sliceToBytes(text, maxBytes) {
|
|
101
|
+
const buffer = Buffer.from(text, "utf8");
|
|
102
|
+
if (buffer.length <= maxBytes)
|
|
103
|
+
return text;
|
|
104
|
+
let end = Math.max(0, maxBytes);
|
|
105
|
+
while (end > 0 && (buffer[end] & 0xc0) === 0x80)
|
|
106
|
+
end--;
|
|
107
|
+
return buffer.subarray(0, end).toString("utf8");
|
|
108
|
+
}
|
|
109
|
+
function headTruncate(text, limits) {
|
|
110
|
+
const truncation = truncateHead(text, limits);
|
|
111
|
+
return truncation.firstLineExceedsLimit
|
|
112
|
+
? sliceToBytes(text, limits.maxBytes)
|
|
113
|
+
: truncation.content;
|
|
114
|
+
}
|
|
115
|
+
export function boundMcpText(text, limits) {
|
|
116
|
+
const parsed = parseJson(text);
|
|
117
|
+
if (!parsed) {
|
|
118
|
+
return fits(text, limits)
|
|
119
|
+
? { text, truncated: false }
|
|
120
|
+
: { text: headTruncate(text, limits), truncated: true };
|
|
121
|
+
}
|
|
122
|
+
const compact = JSON.stringify(parsed.value);
|
|
123
|
+
if (fits(compact, limits))
|
|
124
|
+
return { text: compact, truncated: false };
|
|
125
|
+
for (const level of DIGEST_LEVELS) {
|
|
126
|
+
const digested = JSON.stringify(digest(parsed.value, level));
|
|
127
|
+
if (fits(digested, limits))
|
|
128
|
+
return { text: digested, truncated: true, digest: true };
|
|
129
|
+
}
|
|
130
|
+
const smallest = JSON.stringify(digest(parsed.value, DIGEST_LEVELS.at(-1)));
|
|
131
|
+
return { text: sliceToBytes(smallest, limits.maxBytes), truncated: true, digest: true };
|
|
132
|
+
}
|
|
133
|
+
function compactMcpText(text) {
|
|
134
|
+
const parsed = parseJson(text);
|
|
135
|
+
return parsed ? JSON.stringify(parsed.value) : text;
|
|
136
|
+
}
|
|
137
|
+
async function spillFullResult(env, text, extension, context) {
|
|
138
|
+
const path = await env.joinPath([env.cwd, ...SPILL_DIR, `${randomBytes(8).toString("hex")}.${extension}`], context);
|
|
139
|
+
if (!path.ok)
|
|
140
|
+
return undefined;
|
|
141
|
+
const written = await env.writeFile(path.value, redactSecrets(text), context);
|
|
142
|
+
return written.ok ? path.value : undefined;
|
|
143
|
+
}
|
|
144
|
+
function truncationNotice(bounded, totalBytes, spillPath) {
|
|
145
|
+
const view = bounded.digest
|
|
146
|
+
? `an abbreviated view of ${formatSize(totalBytes)}: long strings, arrays, and deep nesting are shortened; keys, counts, and pagination fields are kept`
|
|
147
|
+
: `the beginning of ${formatSize(totalBytes)}`;
|
|
148
|
+
const full = spillPath
|
|
149
|
+
? `Full result: ${spillPath} — use read with offset/limit or grep to inspect it`
|
|
150
|
+
: "The full result could not be saved";
|
|
151
|
+
return `[MCP result truncated: showing ${view}. ${full}, or re-query with filters or smaller pages.]`;
|
|
152
|
+
}
|
|
153
|
+
export async function guardMcpToolResult(result, env, context) {
|
|
154
|
+
const blocks = mcpResultContent(result).map((block) => block.type === "text" ? Object.assign(block, { text: compactMcpText(block.text) }) : block);
|
|
155
|
+
const texts = blocks.filter((block) => block.type === "text");
|
|
156
|
+
const images = blocks.filter((block) => block.type === "image");
|
|
157
|
+
const combined = texts.map((block) => block.text).join("\n");
|
|
158
|
+
if (result.isError) {
|
|
159
|
+
throw new Error(boundMcpText(combined, RESULT_LIMITS).text || "MCP tool call failed");
|
|
160
|
+
}
|
|
161
|
+
if (fits(combined, RESULT_LIMITS))
|
|
162
|
+
return { content: blocks, details: undefined };
|
|
163
|
+
const bounded = boundMcpText(combined, RESULT_LIMITS);
|
|
164
|
+
const spillPath = await spillFullResult(env, combined, bounded.digest ? "json" : "txt", context);
|
|
165
|
+
const notice = truncationNotice(bounded, Buffer.byteLength(combined, "utf8"), spillPath);
|
|
166
|
+
return {
|
|
167
|
+
content: [{ type: "text", text: `${bounded.text}\n\n${notice}` }, ...images],
|
|
168
|
+
details: undefined,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=mcp-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-result.js","sourceRoot":"","sources":["../../src/harness/mcp-result.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport {\n DEFAULT_MAX_BYTES,\n DEFAULT_MAX_LINES,\n formatSize,\n truncateHead,\n type AgentToolResult,\n type Context,\n type ExecutionEnv,\n} from \"@earendil-works/pi-agent-core\";\nimport { redactSecrets } from \"./tools/secret-redaction.js\";\n\nexport interface McpTextLimits {\n maxBytes: number;\n maxLines: number;\n}\n\nexport interface BoundedMcpText {\n text: string;\n truncated: boolean;\n digest?: true;\n}\n\nexport interface McpCallResult {\n content?: unknown;\n structuredContent?: unknown;\n isError?: boolean;\n}\n\nconst SPILL_DIR = [\".mikan\", \"mcp-output\"];\nconst NOTICE_RESERVE_BYTES = 640;\nconst NOTICE_RESERVE_LINES = 4;\nconst RESULT_LIMITS: McpTextLimits = {\n maxBytes: DEFAULT_MAX_BYTES - NOTICE_RESERVE_BYTES,\n maxLines: DEFAULT_MAX_LINES - NOTICE_RESERVE_LINES,\n};\n\ninterface DigestLevel {\n stringChars: number;\n arrayItems: number;\n depth: number;\n}\n\nconst DIGEST_LEVELS: readonly DigestLevel[] = [\n { stringChars: 200, arrayItems: 3, depth: 6 },\n { stringChars: 80, arrayItems: 2, depth: 4 },\n { stringChars: 40, arrayItems: 1, depth: 3 },\n { stringChars: 16, arrayItems: 1, depth: 2 },\n];\n\ntype RawBlock = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is RawBlock {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stringField(block: RawBlock, key: string): string | undefined {\n const value = block[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction describeResource(resource: RawBlock): string {\n const uri = stringField(resource, \"uri\") ?? \"(no URI)\";\n const text = stringField(resource, \"text\");\n if (text !== undefined) return `[Resource: ${uri}]\\n${text}`;\n const blob = stringField(resource, \"blob\");\n const mimeType = stringField(resource, \"mimeType\") ?? \"unknown type\";\n const size = blob === undefined ? \"no content\" : `${Buffer.byteLength(blob, \"base64\")} bytes`;\n return `[Resource: ${uri} (${mimeType}, ${size}, binary content omitted)]`;\n}\n\nfunction blockContent(block: RawBlock): TextContent | ImageContent {\n const text = stringField(block, \"text\");\n if (block.type === \"text\" && text !== undefined) return { type: \"text\", text };\n const data = stringField(block, \"data\");\n const mimeType = stringField(block, \"mimeType\");\n if (block.type === \"image\" && data !== undefined && mimeType !== undefined) {\n return { type: \"image\", data, mimeType };\n }\n if (block.type === \"resource\" && isRecord(block.resource)) {\n return { type: \"text\", text: describeResource(block.resource) };\n }\n if (block.type === \"resource_link\") {\n const uri = stringField(block, \"uri\") ?? \"(no URI)\";\n return { type: \"text\", text: `[Resource link: ${stringField(block, \"name\") ?? uri}] ${uri}` };\n }\n if (block.type === \"audio\") {\n return { type: \"text\", text: `[Audio content omitted: ${mimeType ?? \"audio/*\"}]` };\n }\n return { type: \"text\", text: JSON.stringify(block) };\n}\n\nexport function mcpResultContent(result: McpCallResult): (TextContent | ImageContent)[] {\n const blocks = (Array.isArray(result.content) ? result.content : [])\n .filter(isRecord)\n .map(blockContent);\n if (blocks.length > 0) return blocks;\n if (result.structuredContent !== undefined && result.structuredContent !== null) {\n return [{ type: \"text\", text: JSON.stringify(result.structuredContent) }];\n }\n return [{ type: \"text\", text: \"(empty result)\" }];\n}\n\nfunction parseJson(text: string): { value: unknown } | undefined {\n const trimmed = text.trimStart();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) return undefined;\n try {\n return { value: JSON.parse(text) };\n } catch {\n return undefined;\n }\n}\n\nfunction digest(value: unknown, level: DigestLevel, depth = 0): unknown {\n if (typeof value === \"string\") {\n return value.length <= level.stringChars\n ? value\n : `${value.slice(0, level.stringChars)}…[+${value.length - level.stringChars} chars]`;\n }\n if (Array.isArray(value)) {\n if (depth >= level.depth) return `[…${value.length} items]`;\n const kept = value.slice(0, level.arrayItems).map((item) => digest(item, level, depth + 1));\n const hidden = value.length - kept.length;\n return hidden > 0 ? [...kept, `…[+${hidden} more items]`] : kept;\n }\n if (isRecord(value)) {\n if (depth >= level.depth) return `{…${Object.keys(value).length} keys}`;\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, digest(item, level, depth + 1)]),\n );\n }\n return value;\n}\n\nfunction fits(text: string, limits: McpTextLimits): boolean {\n return (\n Buffer.byteLength(text, \"utf8\") <= limits.maxBytes && text.split(\"\\n\").length <= limits.maxLines\n );\n}\n\nfunction sliceToBytes(text: string, maxBytes: number): string {\n const buffer = Buffer.from(text, \"utf8\");\n if (buffer.length <= maxBytes) return text;\n let end = Math.max(0, maxBytes);\n while (end > 0 && (buffer[end]! & 0xc0) === 0x80) end--;\n return buffer.subarray(0, end).toString(\"utf8\");\n}\n\nfunction headTruncate(text: string, limits: McpTextLimits): string {\n const truncation = truncateHead(text, limits);\n return truncation.firstLineExceedsLimit\n ? sliceToBytes(text, limits.maxBytes)\n : truncation.content;\n}\n\nexport function boundMcpText(text: string, limits: McpTextLimits): BoundedMcpText {\n const parsed = parseJson(text);\n if (!parsed) {\n return fits(text, limits)\n ? { text, truncated: false }\n : { text: headTruncate(text, limits), truncated: true };\n }\n const compact = JSON.stringify(parsed.value);\n if (fits(compact, limits)) return { text: compact, truncated: false };\n for (const level of DIGEST_LEVELS) {\n const digested = JSON.stringify(digest(parsed.value, level));\n if (fits(digested, limits)) return { text: digested, truncated: true, digest: true };\n }\n const smallest = JSON.stringify(digest(parsed.value, DIGEST_LEVELS.at(-1)!));\n return { text: sliceToBytes(smallest, limits.maxBytes), truncated: true, digest: true };\n}\n\nfunction compactMcpText(text: string): string {\n const parsed = parseJson(text);\n return parsed ? JSON.stringify(parsed.value) : text;\n}\n\nasync function spillFullResult(\n env: ExecutionEnv,\n text: string,\n extension: \"json\" | \"txt\",\n context: Context,\n): Promise<string | undefined> {\n const path = await env.joinPath(\n [env.cwd, ...SPILL_DIR, `${randomBytes(8).toString(\"hex\")}.${extension}`],\n context,\n );\n if (!path.ok) return undefined;\n const written = await env.writeFile(path.value, redactSecrets(text), context);\n return written.ok ? path.value : undefined;\n}\n\nfunction truncationNotice(\n bounded: BoundedMcpText,\n totalBytes: number,\n spillPath: string | undefined,\n): string {\n const view = bounded.digest\n ? `an abbreviated view of ${formatSize(totalBytes)}: long strings, arrays, and deep nesting are shortened; keys, counts, and pagination fields are kept`\n : `the beginning of ${formatSize(totalBytes)}`;\n const full = spillPath\n ? `Full result: ${spillPath} — use read with offset/limit or grep to inspect it`\n : \"The full result could not be saved\";\n return `[MCP result truncated: showing ${view}. ${full}, or re-query with filters or smaller pages.]`;\n}\n\nexport async function guardMcpToolResult(\n result: McpCallResult,\n env: ExecutionEnv,\n context: Context,\n): Promise<AgentToolResult<undefined>> {\n const blocks = mcpResultContent(result).map((block) =>\n block.type === \"text\" ? Object.assign(block, { text: compactMcpText(block.text) }) : block,\n );\n const texts = blocks.filter((block): block is TextContent => block.type === \"text\");\n const images = blocks.filter((block): block is ImageContent => block.type === \"image\");\n const combined = texts.map((block) => block.text).join(\"\\n\");\n if (result.isError) {\n throw new Error(boundMcpText(combined, RESULT_LIMITS).text || \"MCP tool call failed\");\n }\n if (fits(combined, RESULT_LIMITS)) return { content: blocks, details: undefined };\n const bounded = boundMcpText(combined, RESULT_LIMITS);\n const spillPath = await spillFullResult(env, combined, bounded.digest ? \"json\" : \"txt\", context);\n const notice = truncationNotice(bounded, Buffer.byteLength(combined, \"utf8\"), spillPath);\n return {\n content: [{ type: \"text\", text: `${bounded.text}\\n\\n${notice}` }, ...images],\n details: undefined,\n };\n}\n"]}
|
package/dist/harness/mcp.d.ts
CHANGED
|
@@ -7,19 +7,7 @@ export type StandardMcpParseResult = {
|
|
|
7
7
|
servers?: undefined;
|
|
8
8
|
error: string;
|
|
9
9
|
};
|
|
10
|
-
/**
|
|
11
|
-
* Accept the `mcpServers` JSON every MCP server's setup page hands out
|
|
12
|
-
* (`{ "mcpServers": { name: entry } }`, or the bare `{ name: entry }` map).
|
|
13
|
-
* Entries are stored as pasted — `command`/`args`/`env` or `url`/`headers`,
|
|
14
|
-
* values untouched — and the official SDK client does the rest at connect
|
|
15
|
-
* time. mikan only keeps the config and its enabled state per scope.
|
|
16
|
-
*/
|
|
17
10
|
export declare function parseStandardMcpServers(text: string): StandardMcpParseResult;
|
|
18
|
-
/**
|
|
19
|
-
* Hide query-string values: `?token=…` is a legitimate MCP auth channel
|
|
20
|
-
* (browserless, Claude.ai connectors), so a URL is a credential carrier and
|
|
21
|
-
* must never be echoed to a browser or a log line verbatim.
|
|
22
|
-
*/
|
|
23
11
|
export declare function redactMcpUrl(url: string): string;
|
|
24
12
|
export declare function listMcpPresets(): readonly McpPreset[];
|
|
25
13
|
export declare function findMcpPreset(id: string): McpPreset | undefined;
|
|
@@ -27,12 +15,5 @@ export declare function materializeMcpPreset(preset: McpPreset, values: Record<s
|
|
|
27
15
|
export type { McpServerConfig } from "./types.js";
|
|
28
16
|
export type { McpToolsResult } from "./types.js";
|
|
29
17
|
export declare function formatMcpServerInstructions(instructions: McpServerInstruction[]): string;
|
|
30
|
-
/**
|
|
31
|
-
* Connect to every enabled MCP server and wrap their tools as mikan
|
|
32
|
-
* {@link AgentTool}s. Failures are per-server: one unreachable server
|
|
33
|
-
* reports an error and the rest still load. Callers own the returned
|
|
34
|
-
* `dispose` and must call it when the runner is disposed, or stdio child
|
|
35
|
-
* processes leak.
|
|
36
|
-
*/
|
|
37
18
|
export declare function loadMcpTools(servers: Record<string, McpServerConfig>, signal?: AbortSignal): Promise<McpToolsResult>;
|
|
38
19
|
//# sourceMappingURL=mcp.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/harness/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EAEf,oBAAoB,EACpB,cAAc,EACf,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/harness/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EAEf,oBAAoB,EACpB,cAAc,EACf,MAAM,YAAY,CAAC;AAgBpB,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,MAAM,MAAM,sBAAsB,GAC9B;IAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,GAC/D;IAAE,OAAO,CAAC,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAM3C,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,CAwC5E;AAMD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOhD;AAmCD,wBAAgB,cAAc,IAAI,SAAS,SAAS,EAAE,CAErD;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAE/D;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,eAAe,CA2BjB;AACD,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAuEjD,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,oBAAoB,EAAE,GAAG,MAAM,CAOxF;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,EACxC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CA2CzB"}
|
package/dist/harness/mcp.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
2
|
import { StdioClientTransport, getDefaultEnvironment, } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3
3
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
4
|
+
import { guardMcpToolResult } from "./mcp-result.js";
|
|
5
|
+
import { tagHarnessTool } from "./tools/pi-tools.js";
|
|
4
6
|
import * as log from "../log.js";
|
|
5
|
-
/** Server names become tool-name segments (`mcp__<server>__<tool>`); keep them
|
|
6
|
-
* to a safe charset so a settings typo cannot produce an unparseable or
|
|
7
|
-
* provider-rejected tool name. Shared by the loader and the portal. */
|
|
8
7
|
const SERVER_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;
|
|
9
8
|
export function isValidMcpServerName(name) {
|
|
10
9
|
return SERVER_NAME_RE.test(name);
|
|
@@ -12,13 +11,6 @@ export function isValidMcpServerName(name) {
|
|
|
12
11
|
function isRecord(value) {
|
|
13
12
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14
13
|
}
|
|
15
|
-
/**
|
|
16
|
-
* Accept the `mcpServers` JSON every MCP server's setup page hands out
|
|
17
|
-
* (`{ "mcpServers": { name: entry } }`, or the bare `{ name: entry }` map).
|
|
18
|
-
* Entries are stored as pasted — `command`/`args`/`env` or `url`/`headers`,
|
|
19
|
-
* values untouched — and the official SDK client does the rest at connect
|
|
20
|
-
* time. mikan only keeps the config and its enabled state per scope.
|
|
21
|
-
*/
|
|
22
14
|
export function parseStandardMcpServers(text) {
|
|
23
15
|
let parsed;
|
|
24
16
|
try {
|
|
@@ -45,12 +37,9 @@ export function parseStandardMcpServers(text) {
|
|
|
45
37
|
return { error: `"${name}" must be an object` };
|
|
46
38
|
const hasCommand = typeof entry.command === "string" && entry.command.trim() !== "";
|
|
47
39
|
const hasUrl = typeof entry.url === "string";
|
|
48
|
-
// A broken url is named before the transport count, so a paste carrying
|
|
49
|
-
// both keys and a bad URL reports the URL rather than the ambiguity.
|
|
50
40
|
if (hasUrl && !URL.canParse(entry.url)) {
|
|
51
41
|
return { error: `"${name}": url is not a valid URL` };
|
|
52
42
|
}
|
|
53
|
-
// Exactly one transport: equal flags mean both were set, or neither was.
|
|
54
43
|
if (hasCommand === hasUrl) {
|
|
55
44
|
const detail = hasCommand
|
|
56
45
|
? "set only one of command / url"
|
|
@@ -71,11 +60,6 @@ export function parseStandardMcpServers(text) {
|
|
|
71
60
|
function stringValues(map) {
|
|
72
61
|
return Object.fromEntries(Object.entries(map).map(([k, v]) => [k, String(v)]));
|
|
73
62
|
}
|
|
74
|
-
/**
|
|
75
|
-
* Hide query-string values: `?token=…` is a legitimate MCP auth channel
|
|
76
|
-
* (browserless, Claude.ai connectors), so a URL is a credential carrier and
|
|
77
|
-
* must never be echoed to a browser or a log line verbatim.
|
|
78
|
-
*/
|
|
79
63
|
export function redactMcpUrl(url) {
|
|
80
64
|
if (!URL.canParse(url))
|
|
81
65
|
return url.replace(/([?&][^=&]+=)[^&]*/g, "$1<redacted>");
|
|
@@ -164,9 +148,6 @@ function buildTransport(name, config) {
|
|
|
164
148
|
return new StdioClientTransport({
|
|
165
149
|
command: config.command,
|
|
166
150
|
args: config.args ?? [],
|
|
167
|
-
// The SDK's default env is a minimal safe allowlist (PATH, HOME…);
|
|
168
|
-
// entries from settings are merged over it. Credentials for the MCP
|
|
169
|
-
// server belong here — on the host, out of the model's reach.
|
|
170
151
|
env: { ...getDefaultEnvironment(), ...config.env },
|
|
171
152
|
stderr: "ignore",
|
|
172
153
|
});
|
|
@@ -178,36 +159,6 @@ function buildTransport(name, config) {
|
|
|
178
159
|
}
|
|
179
160
|
throw new Error(`server "${name}" sets neither command nor url`);
|
|
180
161
|
}
|
|
181
|
-
function toAgentToolResult(result) {
|
|
182
|
-
const parts = Array.isArray(result.content) ? result.content : [];
|
|
183
|
-
const content = [];
|
|
184
|
-
for (const part of parts) {
|
|
185
|
-
if (part && typeof part === "object" && "type" in part) {
|
|
186
|
-
if (part.type === "text" && typeof part.text === "string") {
|
|
187
|
-
content.push({ type: "text", text: part.text });
|
|
188
|
-
continue;
|
|
189
|
-
}
|
|
190
|
-
if (part.type === "image" &&
|
|
191
|
-
typeof part.data === "string" &&
|
|
192
|
-
typeof part.mimeType === "string") {
|
|
193
|
-
const image = part;
|
|
194
|
-
content.push({ type: "image", data: image.data, mimeType: image.mimeType });
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
// resource/audio/other parts: surface as JSON text rather than dropping.
|
|
198
|
-
content.push({ type: "text", text: JSON.stringify(part) });
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
if (content.length === 0) {
|
|
202
|
-
content.push({ type: "text", text: "(empty result)" });
|
|
203
|
-
}
|
|
204
|
-
const text = content.map((c) => (c.type === "text" ? c.text : "")).join("\n");
|
|
205
|
-
if (result.isError) {
|
|
206
|
-
// AgentTool contract: throw on failure instead of encoding errors in content.
|
|
207
|
-
throw new Error(text || "MCP tool call failed");
|
|
208
|
-
}
|
|
209
|
-
return { content, details: undefined };
|
|
210
|
-
}
|
|
211
162
|
async function connectServer(name, config, signal) {
|
|
212
163
|
const client = new Client({ name: "mikan", version: "1.0.0" });
|
|
213
164
|
const transport = buildTransport(name, config);
|
|
@@ -220,18 +171,15 @@ async function connectServer(name, config, signal) {
|
|
|
220
171
|
timeout: CONNECT_TIMEOUT_MS,
|
|
221
172
|
...(signal ? { signal } : {}),
|
|
222
173
|
});
|
|
223
|
-
const tools = listed.tools.map((mcpTool) => ({
|
|
224
|
-
// Server prefix keeps names collision-free and visibly foreign next to
|
|
225
|
-
// mikan's own tools: `mcp__github__create_issue`.
|
|
174
|
+
const tools = listed.tools.map((mcpTool) => tagHarnessTool({
|
|
226
175
|
name: `mcp__${name}__${mcpTool.name}`,
|
|
227
176
|
label: `${name}: ${mcpTool.name}`,
|
|
228
177
|
description: mcpTool.description ?? `${mcpTool.name} (MCP server "${name}")`,
|
|
229
|
-
// MCP inputSchema is JSON Schema with `"type": "object"` at the root —
|
|
230
|
-
// structurally a valid TSchema; the provider sees the same JSON either way.
|
|
231
178
|
parameters: mcpTool.inputSchema,
|
|
232
|
-
execute: async (
|
|
233
|
-
const
|
|
234
|
-
|
|
179
|
+
execute: async (...args) => {
|
|
180
|
+
const [, params, , toolContext, , context] = args;
|
|
181
|
+
const result = await client.callTool({ name: mcpTool.name, arguments: params }, undefined, { timeout: CALL_TIMEOUT_MS, signal: context.abortSignal });
|
|
182
|
+
return guardMcpToolResult(result, toolContext.env, context);
|
|
235
183
|
},
|
|
236
184
|
}));
|
|
237
185
|
const instructions = client.getInstructions()?.trim();
|
|
@@ -256,13 +204,6 @@ The following admin-approved host-side servers supplied operating guidance. Appl
|
|
|
256
204
|
|
|
257
205
|
${sections.join("\n\n")}`;
|
|
258
206
|
}
|
|
259
|
-
/**
|
|
260
|
-
* Connect to every enabled MCP server and wrap their tools as mikan
|
|
261
|
-
* {@link AgentTool}s. Failures are per-server: one unreachable server
|
|
262
|
-
* reports an error and the rest still load. Callers own the returned
|
|
263
|
-
* `dispose` and must call it when the runner is disposed, or stdio child
|
|
264
|
-
* processes leak.
|
|
265
|
-
*/
|
|
266
207
|
export async function loadMcpTools(servers, signal) {
|
|
267
208
|
const clients = [];
|
|
268
209
|
const tools = [];
|