@geminixiang/mikan 1.0.0-beta.4 → 1.0.0-beta.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +688 -0
- package/README.md +99 -36
- package/dist/adapter.d.ts +11 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +18 -1
- package/dist/adapter.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +6 -7
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +82 -117
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/discord/context.d.ts +3 -1
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +54 -215
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/github/bot.d.ts +89 -0
- package/dist/adapters/github/bot.d.ts.map +1 -0
- package/dist/adapters/github/bot.js +653 -0
- package/dist/adapters/github/bot.js.map +1 -0
- package/dist/adapters/github/client.d.ts +122 -0
- package/dist/adapters/github/client.d.ts.map +1 -0
- package/dist/adapters/github/client.js +314 -0
- package/dist/adapters/github/client.js.map +1 -0
- package/dist/adapters/github/cloudbuild.d.ts +19 -0
- package/dist/adapters/github/cloudbuild.d.ts.map +1 -0
- package/dist/adapters/github/cloudbuild.js +71 -0
- package/dist/adapters/github/cloudbuild.js.map +1 -0
- package/dist/adapters/github/context.d.ts +12 -0
- package/dist/adapters/github/context.d.ts.map +1 -0
- package/dist/adapters/github/context.js +101 -0
- package/dist/adapters/github/context.js.map +1 -0
- package/dist/adapters/github/gcp-auth.d.ts +28 -0
- package/dist/adapters/github/gcp-auth.d.ts.map +1 -0
- package/dist/adapters/github/gcp-auth.js +196 -0
- package/dist/adapters/github/gcp-auth.js.map +1 -0
- package/dist/adapters/github/github-ops.d.ts +91 -0
- package/dist/adapters/github/github-ops.d.ts.map +1 -0
- package/dist/adapters/github/github-ops.js +406 -0
- package/dist/adapters/github/github-ops.js.map +1 -0
- package/dist/adapters/github/ids.d.ts +34 -0
- package/dist/adapters/github/ids.d.ts.map +1 -0
- package/dist/adapters/github/ids.js +57 -0
- package/dist/adapters/github/ids.js.map +1 -0
- package/dist/adapters/github/repo.d.ts +33 -0
- package/dist/adapters/github/repo.d.ts.map +1 -0
- package/dist/adapters/github/repo.js +141 -0
- package/dist/adapters/github/repo.js.map +1 -0
- package/dist/adapters/github/tool-pack.d.ts +14 -0
- package/dist/adapters/github/tool-pack.d.ts.map +1 -0
- package/dist/adapters/github/tool-pack.js +56 -0
- package/dist/adapters/github/tool-pack.js.map +1 -0
- package/dist/adapters/github/tools/checks.d.ts +19 -0
- package/dist/adapters/github/tools/checks.d.ts.map +1 -0
- package/dist/adapters/github/tools/checks.js +105 -0
- package/dist/adapters/github/tools/checks.js.map +1 -0
- package/dist/adapters/github/tools/issue.d.ts +21 -0
- package/dist/adapters/github/tools/issue.d.ts.map +1 -0
- package/dist/adapters/github/tools/issue.js +48 -0
- package/dist/adapters/github/tools/issue.js.map +1 -0
- package/dist/adapters/github/tools/pr.d.ts +22 -0
- package/dist/adapters/github/tools/pr.d.ts.map +1 -0
- package/dist/adapters/github/tools/pr.js +48 -0
- package/dist/adapters/github/tools/pr.js.map +1 -0
- package/dist/adapters/github/tools/read.d.ts +21 -0
- package/dist/adapters/github/tools/read.d.ts.map +1 -0
- package/dist/adapters/github/tools/read.js +141 -0
- package/dist/adapters/github/tools/read.js.map +1 -0
- package/dist/adapters/github/tools/review-reply.d.ts +17 -0
- package/dist/adapters/github/tools/review-reply.d.ts.map +1 -0
- package/dist/adapters/github/tools/review-reply.js +38 -0
- package/dist/adapters/github/tools/review-reply.js.map +1 -0
- package/dist/adapters/github/tools/sync.d.ts +17 -0
- package/dist/adapters/github/tools/sync.d.ts.map +1 -0
- package/dist/adapters/github/tools/sync.js +34 -0
- package/dist/adapters/github/tools/sync.js.map +1 -0
- package/dist/adapters/github/types.d.ts +373 -0
- package/dist/adapters/github/types.d.ts.map +1 -0
- package/dist/adapters/github/types.js +2 -0
- package/dist/adapters/github/types.js.map +1 -0
- package/dist/adapters/intake.d.ts +16 -5
- package/dist/adapters/intake.d.ts.map +1 -1
- package/dist/adapters/intake.js +86 -23
- package/dist/adapters/intake.js.map +1 -1
- package/dist/adapters/progressive-renderer.d.ts +7 -0
- package/dist/adapters/progressive-renderer.d.ts.map +1 -0
- package/dist/adapters/progressive-renderer.js +383 -0
- package/dist/adapters/progressive-renderer.js.map +1 -0
- package/dist/adapters/shared.d.ts +23 -10
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/shared.js +60 -22
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/slack/blocks.d.ts +14 -0
- package/dist/adapters/slack/blocks.d.ts.map +1 -1
- package/dist/adapters/slack/blocks.js +147 -111
- package/dist/adapters/slack/blocks.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +43 -13
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +385 -207
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/context.d.ts +3 -1
- package/dist/adapters/slack/context.d.ts.map +1 -1
- package/dist/adapters/slack/context.js +11 -17
- package/dist/adapters/slack/context.js.map +1 -1
- package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
- package/dist/adapters/slack/response-lifecycle.js +126 -323
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/slack/session.d.ts.map +1 -1
- package/dist/adapters/slack/session.js +7 -11
- package/dist/adapters/slack/session.js.map +1 -1
- package/dist/adapters/slack/tool-pack.d.ts +11 -0
- package/dist/adapters/slack/tool-pack.d.ts.map +1 -0
- package/dist/adapters/slack/tool-pack.js +45 -0
- package/dist/adapters/slack/tool-pack.js.map +1 -0
- package/dist/adapters/slack/tools/attach.js +1 -1
- package/dist/adapters/slack/tools/attach.js.map +1 -1
- package/dist/adapters/slack/tools/blockkit.d.ts +14 -0
- package/dist/adapters/slack/tools/blockkit.d.ts.map +1 -0
- package/dist/adapters/slack/tools/blockkit.js +106 -0
- package/dist/adapters/slack/tools/blockkit.js.map +1 -0
- package/dist/adapters/slack/types.d.ts +40 -2
- package/dist/adapters/slack/types.d.ts.map +1 -1
- package/dist/adapters/slack/types.js.map +1 -1
- package/dist/adapters/telegram/bot.d.ts +8 -9
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +90 -117
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/adapters/telegram/context.d.ts +2 -0
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +61 -184
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/adapters/telegram/html.d.ts.map +1 -1
- package/dist/adapters/telegram/html.js +10 -7
- package/dist/adapters/telegram/html.js.map +1 -1
- package/dist/adapters/types.d.ts +109 -12
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js.map +1 -1
- package/dist/agent-events.d.ts +3 -2
- package/dist/agent-events.d.ts.map +1 -1
- package/dist/agent-events.js +19 -1
- package/dist/agent-events.js.map +1 -1
- package/dist/agent.d.ts +14 -19
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +840 -298
- package/dist/agent.js.map +1 -1
- package/dist/cli/arg-grammar.d.ts +25 -0
- package/dist/cli/arg-grammar.d.ts.map +1 -0
- package/dist/cli/arg-grammar.js +61 -0
- package/dist/cli/arg-grammar.js.map +1 -0
- package/dist/cli/boot.d.ts +5 -0
- package/dist/cli/boot.d.ts.map +1 -0
- package/dist/cli/boot.js +117 -0
- package/dist/cli/boot.js.map +1 -0
- package/dist/cli/download.d.ts.map +1 -0
- package/dist/{download.js → cli/download.js} +2 -0
- package/dist/cli/download.js.map +1 -0
- package/dist/cli/ext-dev.d.ts +2 -0
- package/dist/cli/ext-dev.d.ts.map +1 -0
- package/dist/cli/ext-dev.js +188 -0
- package/dist/cli/ext-dev.js.map +1 -0
- package/dist/cli/ext.d.ts +2 -0
- package/dist/cli/ext.d.ts.map +1 -0
- package/dist/cli/ext.js +324 -0
- package/dist/cli/ext.js.map +1 -0
- package/dist/cli/office.d.ts +2 -0
- package/dist/cli/office.d.ts.map +1 -0
- package/dist/cli/office.js +91 -0
- package/dist/cli/office.js.map +1 -0
- package/dist/cli/types.d.ts +16 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/commands/admin.d.ts.map +1 -1
- package/dist/commands/admin.js +3 -2
- package/dist/commands/admin.js.map +1 -1
- package/dist/commands/auto-reply.d.ts.map +1 -1
- package/dist/commands/auto-reply.js +5 -9
- package/dist/commands/auto-reply.js.map +1 -1
- package/dist/commands/extensions.d.ts.map +1 -1
- package/dist/commands/extensions.js +9 -6
- package/dist/commands/extensions.js.map +1 -1
- package/dist/commands/login.d.ts +2 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +40 -5
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/manifest.d.ts +37 -0
- package/dist/commands/manifest.d.ts.map +1 -0
- package/dist/commands/manifest.js +151 -0
- package/dist/commands/manifest.js.map +1 -0
- package/dist/commands/model.d.ts +2 -3
- package/dist/commands/model.d.ts.map +1 -1
- package/dist/commands/model.js +63 -24
- package/dist/commands/model.js.map +1 -1
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +15 -3
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/registry.d.ts +2 -2
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +1 -2
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +83 -33
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/commands/session-view.d.ts.map +1 -1
- package/dist/commands/session-view.js +6 -3
- package/dist/commands/session-view.js.map +1 -1
- package/dist/commands/types.d.ts +79 -7
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js.map +1 -1
- package/dist/config.d.ts +23 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +222 -135
- package/dist/config.js.map +1 -1
- package/dist/env-manifest.d.ts +30 -0
- package/dist/env-manifest.d.ts.map +1 -0
- package/dist/env-manifest.js +229 -0
- package/dist/env-manifest.js.map +1 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +20 -81
- package/dist/events.js.map +1 -1
- package/dist/execution-resolver.d.ts +7 -8
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +106 -110
- package/dist/execution-resolver.js.map +1 -1
- package/dist/extension-schedules.d.ts +31 -0
- package/dist/extension-schedules.d.ts.map +1 -0
- package/dist/extension-schedules.js +229 -0
- package/dist/extension-schedules.js.map +1 -0
- package/dist/harness/auth.d.ts +2 -1
- package/dist/harness/auth.d.ts.map +1 -1
- package/dist/harness/auth.js +11 -5
- package/dist/harness/auth.js.map +1 -1
- package/dist/harness/event-format.d.ts +27 -0
- package/dist/harness/event-format.d.ts.map +1 -0
- package/dist/harness/event-format.js +160 -0
- package/dist/harness/event-format.js.map +1 -0
- package/dist/harness/extensions/loader.d.ts +27 -49
- package/dist/harness/extensions/loader.d.ts.map +1 -1
- package/dist/harness/extensions/loader.js +486 -130
- package/dist/harness/extensions/loader.js.map +1 -1
- package/dist/harness/extensions/registry.d.ts +107 -2
- package/dist/harness/extensions/registry.d.ts.map +1 -1
- package/dist/harness/extensions/registry.js +316 -0
- package/dist/harness/extensions/registry.js.map +1 -1
- package/dist/harness/extensions/types.d.ts +482 -42
- package/dist/harness/extensions/types.d.ts.map +1 -1
- package/dist/harness/extensions/types.js.map +1 -1
- package/dist/harness/index.d.ts +18 -8
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +7 -4
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/models.d.ts +7 -4
- package/dist/harness/models.d.ts.map +1 -1
- package/dist/harness/models.js +46 -24
- package/dist/harness/models.js.map +1 -1
- package/dist/harness/runner.d.ts +50 -54
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +232 -46
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session-store.d.ts +11 -5
- package/dist/harness/session-store.d.ts.map +1 -1
- package/dist/harness/session-store.js +141 -36
- package/dist/harness/session-store.js.map +1 -1
- package/dist/harness/settings.d.ts +2 -20
- package/dist/harness/settings.d.ts.map +1 -1
- package/dist/harness/settings.js +12 -1
- package/dist/harness/settings.js.map +1 -1
- package/dist/harness/skills.d.ts +10 -29
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +48 -6
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/subagent-profiles.d.ts +8 -0
- package/dist/harness/subagent-profiles.d.ts.map +1 -0
- package/dist/harness/subagent-profiles.js +299 -0
- package/dist/harness/subagent-profiles.js.map +1 -0
- package/dist/harness/subagent-runner.d.ts +39 -0
- package/dist/harness/subagent-runner.d.ts.map +1 -0
- package/dist/harness/subagent-runner.js +617 -0
- package/dist/harness/subagent-runner.js.map +1 -0
- package/dist/harness/types.d.ts +267 -1
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/usage.d.ts +6 -0
- package/dist/harness/usage.d.ts.map +1 -0
- package/dist/harness/usage.js +32 -0
- package/dist/harness/usage.js.map +1 -0
- package/dist/index.d.ts +36 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -6
- package/dist/index.js.map +1 -1
- package/dist/main.js +391 -127
- package/dist/main.js.map +1 -1
- package/dist/observability/instrument.js +7 -5
- package/dist/observability/instrument.js.map +1 -1
- package/dist/observability/sentry.d.ts +2 -0
- package/dist/observability/sentry.d.ts.map +1 -1
- package/dist/observability/sentry.js +10 -2
- package/dist/observability/sentry.js.map +1 -1
- package/dist/office/address.d.ts +31 -0
- package/dist/office/address.d.ts.map +1 -0
- package/dist/office/address.js +113 -0
- package/dist/office/address.js.map +1 -0
- package/dist/office/index.d.ts +11 -0
- package/dist/office/index.d.ts.map +1 -0
- package/dist/office/index.js +11 -0
- package/dist/office/index.js.map +1 -0
- package/dist/office/layout.d.ts +27 -0
- package/dist/office/layout.d.ts.map +1 -0
- package/dist/office/layout.js +97 -0
- package/dist/office/layout.js.map +1 -0
- package/dist/office/migration.d.ts +44 -0
- package/dist/office/migration.d.ts.map +1 -0
- package/dist/office/migration.js +255 -0
- package/dist/office/migration.js.map +1 -0
- package/dist/office/registry.d.ts +75 -0
- package/dist/office/registry.d.ts.map +1 -0
- package/dist/office/registry.js +646 -0
- package/dist/office/registry.js.map +1 -0
- package/dist/office/types.d.ts +71 -0
- package/dist/office/types.d.ts.map +1 -0
- package/dist/office/types.js +2 -0
- package/dist/office/types.js.map +1 -0
- package/dist/packages/admin.d.ts +17 -0
- package/dist/packages/admin.d.ts.map +1 -0
- package/dist/packages/admin.js +98 -0
- package/dist/packages/admin.js.map +1 -0
- package/dist/packages/index.d.ts +6 -0
- package/dist/packages/index.d.ts.map +1 -0
- package/dist/packages/index.js +6 -0
- package/dist/packages/index.js.map +1 -0
- package/dist/packages/inspect.d.ts +11 -0
- package/dist/packages/inspect.d.ts.map +1 -0
- package/dist/packages/inspect.js +98 -0
- package/dist/packages/inspect.js.map +1 -0
- package/dist/packages/materialize.d.ts +40 -0
- package/dist/packages/materialize.d.ts.map +1 -0
- package/dist/packages/materialize.js +297 -0
- package/dist/packages/materialize.js.map +1 -0
- package/dist/packages/resolve.d.ts +25 -0
- package/dist/packages/resolve.d.ts.map +1 -0
- package/dist/packages/resolve.js +208 -0
- package/dist/packages/resolve.js.map +1 -0
- package/dist/packages/source.d.ts +39 -0
- package/dist/packages/source.d.ts.map +1 -0
- package/dist/packages/source.js +189 -0
- package/dist/packages/source.js.map +1 -0
- package/dist/packages/types.d.ts +104 -0
- package/dist/packages/types.d.ts.map +1 -0
- package/dist/packages/types.js +2 -0
- package/dist/packages/types.js.map +1 -0
- package/dist/provisioner.d.ts +66 -0
- package/dist/provisioner.d.ts.map +1 -1
- package/dist/provisioner.js +335 -13
- package/dist/provisioner.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +562 -118
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/session-lifecycle.d.ts +38 -0
- package/dist/runtime/session-lifecycle.d.ts.map +1 -0
- package/dist/runtime/session-lifecycle.js +193 -0
- package/dist/runtime/session-lifecycle.js.map +1 -0
- package/dist/runtime/types.d.ts +66 -7
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/cloudflare.d.ts +3 -0
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +13 -1
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts +4 -0
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +13 -3
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/firecracker.d.ts +3 -0
- package/dist/sandbox/firecracker.d.ts.map +1 -1
- package/dist/sandbox/firecracker.js +13 -2
- package/dist/sandbox/firecracker.js.map +1 -1
- package/dist/sandbox/gondolin.d.ts +57 -0
- package/dist/sandbox/gondolin.d.ts.map +1 -0
- package/dist/sandbox/gondolin.js +764 -0
- package/dist/sandbox/gondolin.js.map +1 -0
- package/dist/sandbox/host.d.ts +3 -0
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +18 -3
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/identity.d.ts +44 -0
- package/dist/sandbox/identity.d.ts.map +1 -0
- package/dist/sandbox/identity.js +68 -0
- package/dist/sandbox/identity.js.map +1 -0
- package/dist/sandbox/image.d.ts.map +1 -1
- package/dist/sandbox/image.js +2 -0
- package/dist/sandbox/image.js.map +1 -1
- package/dist/sandbox/index.d.ts +17 -4
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +37 -3
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +65 -1
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +14 -0
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +68 -1
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts +25 -0
- package/dist/sessions/chat-history-sync.d.ts.map +1 -0
- package/dist/sessions/{agent-memory-file-manager.js → chat-history-sync.js} +135 -131
- package/dist/sessions/chat-history-sync.js.map +1 -0
- package/dist/sessions/conversation-log.d.ts +9 -0
- package/dist/sessions/conversation-log.d.ts.map +1 -0
- package/dist/sessions/conversation-log.js +50 -0
- package/dist/sessions/conversation-log.js.map +1 -0
- package/dist/sessions/history-line.d.ts +29 -0
- package/dist/sessions/history-line.d.ts.map +1 -0
- package/dist/sessions/history-line.js +45 -0
- package/dist/sessions/history-line.js.map +1 -0
- package/dist/sessions/rotation.d.ts +2 -0
- package/dist/sessions/rotation.d.ts.map +1 -0
- package/dist/sessions/rotation.js +39 -0
- package/dist/sessions/rotation.js.map +1 -0
- package/dist/sessions/session-key.d.ts +33 -0
- package/dist/sessions/session-key.d.ts.map +1 -0
- package/dist/sessions/session-key.js +115 -0
- package/dist/sessions/session-key.js.map +1 -0
- package/dist/sessions/store.d.ts +15 -7
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +127 -36
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +19 -5
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/settings-mutation.d.ts +40 -0
- package/dist/settings-mutation.d.ts.map +1 -0
- package/dist/settings-mutation.js +61 -0
- package/dist/settings-mutation.js.map +1 -0
- package/dist/subagent-progress.d.ts +43 -0
- package/dist/subagent-progress.d.ts.map +1 -0
- package/dist/subagent-progress.js +220 -0
- package/dist/subagent-progress.js.map +1 -0
- package/dist/tools/bash.d.ts +3 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +26 -18
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +14 -13
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/event.d.ts +1 -1
- package/dist/tools/event.d.ts.map +1 -1
- package/dist/tools/event.js +58 -45
- package/dist/tools/event.js.map +1 -1
- package/dist/tools/generate-image.d.ts +23 -0
- package/dist/tools/generate-image.d.ts.map +1 -0
- package/dist/tools/generate-image.js +65 -0
- package/dist/tools/generate-image.js.map +1 -0
- package/dist/tools/host-fn-tool.d.ts +21 -0
- package/dist/tools/host-fn-tool.d.ts.map +1 -0
- package/dist/tools/host-fn-tool.js +32 -0
- package/dist/tools/host-fn-tool.js.map +1 -0
- package/dist/tools/index.d.ts +19 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +25 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/react.d.ts +15 -0
- package/dist/tools/react.d.ts.map +1 -0
- package/dist/tools/react.js +29 -0
- package/dist/tools/react.js.map +1 -0
- package/dist/tools/read.d.ts +1 -0
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +39 -33
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/sandbox.d.ts +2 -2
- package/dist/tools/sandbox.d.ts.map +1 -1
- package/dist/tools/sandbox.js +14 -9
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/tools/subagent-slots.d.ts +28 -0
- package/dist/tools/subagent-slots.d.ts.map +1 -0
- package/dist/tools/subagent-slots.js +72 -0
- package/dist/tools/subagent-slots.js.map +1 -0
- package/dist/tools/subagent.d.ts +54 -0
- package/dist/tools/subagent.d.ts.map +1 -0
- package/dist/tools/subagent.js +411 -0
- package/dist/tools/subagent.js.map +1 -0
- package/dist/tools/types.d.ts +40 -32
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +2 -8
- package/dist/tools/write.js.map +1 -1
- package/dist/trigger.d.ts +2 -1
- package/dist/trigger.d.ts.map +1 -1
- package/dist/trigger.js +6 -9
- package/dist/trigger.js.map +1 -1
- package/dist/types.d.ts +403 -59
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -2
- package/dist/types.js.map +1 -1
- package/dist/utils/file-guards.d.ts +9 -0
- package/dist/utils/file-guards.d.ts.map +1 -1
- package/dist/utils/file-guards.js +44 -1
- package/dist/utils/file-guards.js.map +1 -1
- package/dist/vault/disabled.d.ts +9 -0
- package/dist/vault/disabled.d.ts.map +1 -0
- package/dist/vault/disabled.js +25 -0
- package/dist/vault/disabled.js.map +1 -0
- package/dist/vault/index.d.ts +45 -2
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +127 -36
- package/dist/vault/index.js.map +1 -1
- package/dist/vault/types.d.ts +6 -2
- package/dist/vault/types.d.ts.map +1 -1
- package/dist/vault/types.js.map +1 -1
- package/dist/web/admin/portal.d.ts +31 -3
- package/dist/web/admin/portal.d.ts.map +1 -1
- package/dist/web/admin/portal.js +846 -345
- package/dist/web/admin/portal.js.map +1 -1
- package/dist/web/admin/provider-models.js +1 -1
- package/dist/web/admin/provider-models.js.map +1 -1
- package/dist/web/admin/types.d.ts +23 -3
- package/dist/web/admin/types.d.ts.map +1 -1
- package/dist/web/admin/types.js.map +1 -1
- package/dist/web/login/oauth.d.ts +2 -3
- package/dist/web/login/oauth.d.ts.map +1 -1
- package/dist/web/login/oauth.js +1 -32
- package/dist/web/login/oauth.js.map +1 -1
- package/dist/web/login/portal.d.ts +1 -1
- package/dist/web/login/portal.d.ts.map +1 -1
- package/dist/web/login/portal.js +13 -36
- package/dist/web/login/portal.js.map +1 -1
- package/dist/web/login/types.d.ts +0 -11
- package/dist/web/login/types.d.ts.map +1 -1
- package/dist/web/login/types.js.map +1 -1
- package/dist/web/portal-shell.d.ts +21 -0
- package/dist/web/portal-shell.d.ts.map +1 -0
- package/dist/{portal-shell.js → web/portal-shell.js} +67 -2
- package/dist/web/portal-shell.js.map +1 -0
- package/dist/web/server.d.ts +3 -2
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +11 -4
- package/dist/web/server.js.map +1 -1
- package/dist/web/session-view/portal.d.ts +1 -1
- package/dist/web/session-view/portal.d.ts.map +1 -1
- package/dist/web/session-view/portal.js +37 -28
- package/dist/web/session-view/portal.js.map +1 -1
- package/dist/web/session-view/service.d.ts +1 -1
- package/dist/web/session-view/service.d.ts.map +1 -1
- package/dist/web/session-view/service.js +61 -18
- package/dist/web/session-view/service.js.map +1 -1
- package/dist/web/session-view/types.d.ts +0 -3
- package/dist/web/session-view/types.d.ts.map +1 -1
- package/dist/web/session-view/types.js.map +1 -1
- package/dist/web/token-store.js +1 -1
- package/dist/web/token-store.js.map +1 -1
- package/dist/workspace-projection/index.d.ts +10 -0
- package/dist/workspace-projection/index.d.ts.map +1 -0
- package/dist/workspace-projection/index.js +120 -0
- package/dist/workspace-projection/index.js.map +1 -0
- package/dist/workspace-projection/types.d.ts +16 -0
- package/dist/workspace-projection/types.d.ts.map +1 -0
- package/dist/workspace-projection/types.js +2 -0
- package/dist/workspace-projection/types.js.map +1 -0
- package/package.json +67 -37
- package/dist/adapters/streaming.d.ts +0 -18
- package/dist/adapters/streaming.d.ts.map +0 -1
- package/dist/adapters/streaming.js +0 -44
- package/dist/adapters/streaming.js.map +0 -1
- package/dist/commands/parse.d.ts +0 -7
- package/dist/commands/parse.d.ts.map +0 -1
- package/dist/commands/parse.js +0 -14
- package/dist/commands/parse.js.map +0 -1
- package/dist/download.d.ts.map +0 -1
- package/dist/download.js.map +0 -1
- package/dist/model-registry.d.ts +0 -4
- package/dist/model-registry.d.ts.map +0 -1
- package/dist/model-registry.js +0 -7
- package/dist/model-registry.js.map +0 -1
- package/dist/portal-shell.d.ts +0 -4
- package/dist/portal-shell.d.ts.map +0 -1
- package/dist/portal-shell.js.map +0 -1
- package/dist/runtime/agent-run-controller.d.ts +0 -31
- package/dist/runtime/agent-run-controller.d.ts.map +0 -1
- package/dist/runtime/agent-run-controller.js +0 -195
- package/dist/runtime/agent-run-controller.js.map +0 -1
- package/dist/sandbox/path-context.d.ts +0 -3
- package/dist/sandbox/path-context.d.ts.map +0 -1
- package/dist/sandbox/path-context.js +0 -20
- package/dist/sandbox/path-context.js.map +0 -1
- package/dist/sessions/agent-memory-file-manager.d.ts +0 -19
- package/dist/sessions/agent-memory-file-manager.d.ts.map +0 -1
- package/dist/sessions/agent-memory-file-manager.js.map +0 -1
- package/dist/sessions/metadata.d.ts +0 -3
- package/dist/sessions/metadata.d.ts.map +0 -1
- package/dist/sessions/metadata.js +0 -11
- package/dist/sessions/metadata.js.map +0 -1
- package/dist/sessions/policy.d.ts +0 -6
- package/dist/sessions/policy.d.ts.map +0 -1
- package/dist/sessions/policy.js +0 -23
- package/dist/sessions/policy.js.map +0 -1
- package/dist/store.d.ts +0 -46
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -177
- package/dist/store.js.map +0 -1
- package/dist/tools/truncate.d.ts +0 -33
- package/dist/tools/truncate.d.ts.map +0 -1
- package/dist/tools/truncate.js +0 -184
- package/dist/tools/truncate.js.map +0 -1
- package/dist/utils/date.d.ts +0 -10
- package/dist/utils/date.d.ts.map +0 -1
- package/dist/utils/date.js +0 -23
- package/dist/utils/date.js.map +0 -1
- package/dist/utils/env.d.ts +0 -3
- package/dist/utils/env.d.ts.map +0 -1
- package/dist/utils/env.js +0 -12
- package/dist/utils/env.js.map +0 -1
- package/dist/utils/fs-atomic.d.ts +0 -10
- package/dist/utils/fs-atomic.d.ts.map +0 -1
- package/dist/utils/fs-atomic.js +0 -45
- package/dist/utils/fs-atomic.js.map +0 -1
- package/dist/utils/html.d.ts +0 -2
- package/dist/utils/html.d.ts.map +0 -1
- package/dist/utils/html.js +0 -4
- package/dist/utils/html.js.map +0 -1
- package/dist/utils/http-body.d.ts +0 -10
- package/dist/utils/http-body.d.ts.map +0 -1
- package/dist/utils/http-body.js +0 -34
- package/dist/utils/http-body.js.map +0 -1
- package/dist/vault/routing.d.ts +0 -3
- package/dist/vault/routing.d.ts.map +0 -1
- package/dist/vault/routing.js +0 -13
- package/dist/vault/routing.js.map +0 -1
- package/dist/web/agent-events/portal.d.ts +0 -3
- package/dist/web/agent-events/portal.d.ts.map +0 -1
- package/dist/web/agent-events/portal.js +0 -18
- package/dist/web/agent-events/portal.js.map +0 -1
- package/dist/web/request.d.ts +0 -3
- package/dist/web/request.d.ts.map +0 -1
- package/dist/web/request.js +0 -13
- package/dist/web/request.js.map +0 -1
- package/dist/web/session-view/command.d.ts +0 -4
- package/dist/web/session-view/command.d.ts.map +0 -1
- package/dist/web/session-view/command.js +0 -7
- package/dist/web/session-view/command.js.map +0 -1
- /package/dist/{download.d.ts → cli/download.d.ts} +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
const schema = Type.Object({
|
|
6
|
+
prompt: Type.String({ description: "Description of the image to generate" }),
|
|
7
|
+
size: Type.Optional(Type.String({ description: "Requested image size, for example 1024x1024" })),
|
|
8
|
+
quality: Type.Optional(Type.String({ description: "Requested image quality, for example low, medium, or high" })),
|
|
9
|
+
});
|
|
10
|
+
export function createGenerateImageTool(options) {
|
|
11
|
+
let uploadFn = null;
|
|
12
|
+
return {
|
|
13
|
+
tool: {
|
|
14
|
+
name: "generate_image",
|
|
15
|
+
label: "generate image",
|
|
16
|
+
description: "Generate an image with the configured model provider and attach it to the response.",
|
|
17
|
+
parameters: schema,
|
|
18
|
+
execute: async (_toolCallId, params, signal) => {
|
|
19
|
+
if (!uploadFn)
|
|
20
|
+
throw new Error("Upload function not configured");
|
|
21
|
+
if (!options.model.baseUrl)
|
|
22
|
+
throw new Error("Image generation requires a configured model baseUrl");
|
|
23
|
+
const apiKey = await options.getApiKey();
|
|
24
|
+
if (!apiKey)
|
|
25
|
+
throw new Error(`No API key configured for ${options.model.provider}`);
|
|
26
|
+
const response = await fetch(`${options.model.baseUrl.replace(/\/$/, "")}/images/generations`, {
|
|
27
|
+
method: "POST",
|
|
28
|
+
signal,
|
|
29
|
+
headers: {
|
|
30
|
+
...options.model.headers,
|
|
31
|
+
Authorization: `Bearer ${apiKey}`,
|
|
32
|
+
"Content-Type": "application/json",
|
|
33
|
+
},
|
|
34
|
+
body: JSON.stringify({
|
|
35
|
+
model: options.model.id,
|
|
36
|
+
prompt: params.prompt,
|
|
37
|
+
...(params.size ? { size: params.size } : {}),
|
|
38
|
+
...(params.quality ? { quality: params.quality } : {}),
|
|
39
|
+
response_format: "b64_json",
|
|
40
|
+
}),
|
|
41
|
+
});
|
|
42
|
+
const body = (await response.json());
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
throw new Error(`Image generation with model "${options.model.id}" failed: ` +
|
|
45
|
+
(body.error?.message ?? `HTTP ${response.status}`));
|
|
46
|
+
}
|
|
47
|
+
const encoded = body.data?.[0]?.b64_json;
|
|
48
|
+
if (!encoded)
|
|
49
|
+
throw new Error("Image generation response contained no image");
|
|
50
|
+
const fileName = `generated-${randomUUID()}.png`;
|
|
51
|
+
const filePath = join(options.outputDir, fileName);
|
|
52
|
+
await writeFile(filePath, Buffer.from(encoded, "base64"));
|
|
53
|
+
await uploadFn(filePath, fileName);
|
|
54
|
+
return {
|
|
55
|
+
content: [{ type: "text", text: `Generated and attached image: ${fileName}` }],
|
|
56
|
+
details: { fileName },
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
setUploadFunction: (fn) => {
|
|
61
|
+
uploadFn = fn;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=generate-image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-image.js","sourceRoot":"","sources":["../../src/tools/generate-image.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Model } from \"@earendil-works/pi-ai\";\nimport { Type } from \"@sinclair/typebox\";\nimport { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\n\nconst schema = Type.Object({\n prompt: Type.String({ description: \"Description of the image to generate\" }),\n size: Type.Optional(Type.String({ description: \"Requested image size, for example 1024x1024\" })),\n quality: Type.Optional(\n Type.String({ description: \"Requested image quality, for example low, medium, or high\" }),\n ),\n});\n\ninterface ImageResponse {\n data?: Array<{ b64_json?: string }>;\n error?: { message?: string };\n}\n\nexport function createGenerateImageTool(options: {\n model: Model<Api>;\n getApiKey: () => Promise<string | undefined>;\n /** Host directory the generated image is written into. Must be the\n * conversation's own office dir so the agent can also reach the file\n * from inside the sandbox; the workspace base is NOT guest-visible. */\n outputDir: string;\n}): {\n tool: AgentTool<typeof schema>;\n /** The callback receives the HOST path of the generated file. The image is\n * written host-side, so upload must not stage it through the sandbox the\n * way the attach tool does — the file may not be mounted there. */\n setUploadFunction: (fn: (hostPath: string, title?: string) => Promise<void>) => void;\n} {\n let uploadFn: ((hostPath: string, title?: string) => Promise<void>) | null = null;\n\n return {\n tool: {\n name: \"generate_image\",\n label: \"generate image\",\n description:\n \"Generate an image with the configured model provider and attach it to the response.\",\n parameters: schema,\n execute: async (_toolCallId, params, signal) => {\n if (!uploadFn) throw new Error(\"Upload function not configured\");\n if (!options.model.baseUrl)\n throw new Error(\"Image generation requires a configured model baseUrl\");\n const apiKey = await options.getApiKey();\n if (!apiKey) throw new Error(`No API key configured for ${options.model.provider}`);\n\n const response = await fetch(\n `${options.model.baseUrl.replace(/\\/$/, \"\")}/images/generations`,\n {\n method: \"POST\",\n signal,\n headers: {\n ...options.model.headers,\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n model: options.model.id,\n prompt: params.prompt,\n ...(params.size ? { size: params.size } : {}),\n ...(params.quality ? { quality: params.quality } : {}),\n response_format: \"b64_json\",\n }),\n },\n );\n const body = (await response.json()) as ImageResponse;\n if (!response.ok) {\n throw new Error(\n `Image generation with model \"${options.model.id}\" failed: ` +\n (body.error?.message ?? `HTTP ${response.status}`),\n );\n }\n const encoded = body.data?.[0]?.b64_json;\n if (!encoded) throw new Error(\"Image generation response contained no image\");\n\n const fileName = `generated-${randomUUID()}.png`;\n const filePath = join(options.outputDir, fileName);\n await writeFile(filePath, Buffer.from(encoded, \"base64\"));\n await uploadFn(filePath, fileName);\n\n return {\n content: [{ type: \"text\" as const, text: `Generated and attached image: ${fileName}` }],\n details: { fileName },\n };\n },\n },\n setUploadFunction: (fn) => {\n uploadFn = fn;\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import type { Static, TSchema } from "@sinclair/typebox";
|
|
3
|
+
/**
|
|
4
|
+
* A host-backed tool whose implementation is injected per run: a pack's
|
|
5
|
+
* bindRun binds the function for the current conversation (or null to
|
|
6
|
+
* disable the tool). Owns the choreography every such tool used to repeat
|
|
7
|
+
* by hand — the holder + setter pair, the disabled-tool error, and the
|
|
8
|
+
* abort guard — so a tool module only states its schema and its run body.
|
|
9
|
+
*/
|
|
10
|
+
export declare function defineHostFnTool<TFn, TParams extends TSchema>(definition: {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
parameters: TParams;
|
|
14
|
+
/** Error thrown when the tool executes with no bound implementation. */
|
|
15
|
+
unavailable: string;
|
|
16
|
+
run: (fn: TFn, args: Static<TParams>, signal?: AbortSignal) => ReturnType<AgentTool<TParams>["execute"]>;
|
|
17
|
+
}): {
|
|
18
|
+
tool: AgentTool<TParams>;
|
|
19
|
+
setFn: (fn: TFn | null) => void;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=host-fn-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-fn-tool.d.ts","sourceRoot":"","sources":["../../src/tools/host-fn-tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,SAAS,OAAO,EAAE,UAAU,EAAE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,CACH,EAAE,EAAE,GAAG,EACP,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EACrB,MAAM,CAAC,EAAE,WAAW,KACjB,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;CAChD,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAAC,KAAK,EAAE,CAAC,EAAE,EAAE,GAAG,GAAG,IAAI,KAAK,IAAI,CAAA;CAAE,CAyBhE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A host-backed tool whose implementation is injected per run: a pack's
|
|
3
|
+
* bindRun binds the function for the current conversation (or null to
|
|
4
|
+
* disable the tool). Owns the choreography every such tool used to repeat
|
|
5
|
+
* by hand — the holder + setter pair, the disabled-tool error, and the
|
|
6
|
+
* abort guard — so a tool module only states its schema and its run body.
|
|
7
|
+
*/
|
|
8
|
+
export function defineHostFnTool(definition) {
|
|
9
|
+
let bound = null;
|
|
10
|
+
const tool = {
|
|
11
|
+
name: definition.name,
|
|
12
|
+
label: definition.name,
|
|
13
|
+
description: definition.description,
|
|
14
|
+
parameters: definition.parameters,
|
|
15
|
+
execute: async (_toolCallId, args, signal) => {
|
|
16
|
+
if (!bound) {
|
|
17
|
+
throw new Error(definition.unavailable);
|
|
18
|
+
}
|
|
19
|
+
if (signal?.aborted) {
|
|
20
|
+
throw new Error("Operation aborted");
|
|
21
|
+
}
|
|
22
|
+
return definition.run(bound, args, signal);
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
tool,
|
|
27
|
+
setFn: (fn) => {
|
|
28
|
+
bound = fn;
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=host-fn-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-fn-tool.js","sourceRoot":"","sources":["../../src/tools/host-fn-tool.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAA+B,UAW9D;IACC,IAAI,KAAK,GAAe,IAAI,CAAC;IAE7B,MAAM,IAAI,GAAuB;QAC/B,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,KAAK,EAAE,UAAU,CAAC,IAAI;QACtB,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;YAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YAC1C,CAAC;YACD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YACD,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,IAAuB,EAAE,MAAM,CAAC,CAAC;QAChE,CAAC;KACF,CAAC;IAEF,OAAO;QACL,IAAI;QACJ,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;YACZ,KAAK,GAAG,EAAE,CAAC;QACb,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { Static, TSchema } from \"@sinclair/typebox\";\n\n/**\n * A host-backed tool whose implementation is injected per run: a pack's\n * bindRun binds the function for the current conversation (or null to\n * disable the tool). Owns the choreography every such tool used to repeat\n * by hand — the holder + setter pair, the disabled-tool error, and the\n * abort guard — so a tool module only states its schema and its run body.\n */\nexport function defineHostFnTool<TFn, TParams extends TSchema>(definition: {\n name: string;\n description: string;\n parameters: TParams;\n /** Error thrown when the tool executes with no bound implementation. */\n unavailable: string;\n run: (\n fn: TFn,\n args: Static<TParams>,\n signal?: AbortSignal,\n ) => ReturnType<AgentTool<TParams>[\"execute\"]>;\n}): { tool: AgentTool<TParams>; setFn: (fn: TFn | null) => void } {\n let bound: TFn | null = null;\n\n const tool: AgentTool<TParams> = {\n name: definition.name,\n label: definition.name,\n description: definition.description,\n parameters: definition.parameters,\n execute: async (_toolCallId, args, signal) => {\n if (!bound) {\n throw new Error(definition.unavailable);\n }\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n return definition.run(bound, args as Static<TParams>, signal);\n },\n };\n\n return {\n tool,\n setFn: (fn) => {\n bound = fn;\n },\n };\n}\n"]}
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
2
3
|
import type { TSchema } from "@sinclair/typebox";
|
|
3
4
|
import type { ConversationKind } from "../adapter.js";
|
|
4
|
-
import type { DockerContainerManager } from "../provisioner.js";
|
|
5
5
|
import type { Executor, SandboxConfig } from "../sandbox/index.js";
|
|
6
|
+
import type { SandboxResourceController } from "../types.js";
|
|
7
|
+
import type { PlatformToolPackFactory, PlatformToolRunContext } from "./types.js";
|
|
8
|
+
export { createSubagentTool } from "./subagent.js";
|
|
9
|
+
export { DEFAULT_GLOBAL_SUBAGENT_SLOTS, SubagentSlotPool } from "./subagent-slots.js";
|
|
6
10
|
export declare function createMikanTools(executor: Executor, workspaceDir: string, sandboxController?: {
|
|
7
11
|
sandbox: SandboxConfig;
|
|
8
|
-
|
|
12
|
+
resourceController?: Pick<SandboxResourceController, "getLimitStatus" | "setLimits">;
|
|
13
|
+
},
|
|
14
|
+
/** Platform capability pack factories (e.g. GitHub PR/CI); instantiated
|
|
15
|
+
* here so each runner owns its packs' bind state. Not core tools. */
|
|
16
|
+
platformToolPackFactories?: readonly PlatformToolPackFactory[], imageGeneration?: {
|
|
17
|
+
model: Model<Api>;
|
|
18
|
+
getApiKey: () => Promise<string | undefined>;
|
|
19
|
+
outputDir: string;
|
|
9
20
|
}): {
|
|
10
21
|
tools: AgentTool<TSchema>[];
|
|
11
22
|
setUploadFunction: (fn: (filePath: string, title?: string) => Promise<void>) => void;
|
|
23
|
+
/** Upload for generate_image. Receives the file's HOST path — the tool
|
|
24
|
+
* writes host-side, so this must not stage through the sandbox like the
|
|
25
|
+
* attach upload does. No-op when image generation is not configured. */
|
|
26
|
+
setImageUploadFunction: (fn: (hostPath: string, title?: string) => Promise<void>) => void;
|
|
27
|
+
setReactFunction: (fn: ((emoji: string) => Promise<void>) | null) => void;
|
|
28
|
+
bindPlatformToolPacks: (ctx: PlatformToolRunContext) => void;
|
|
12
29
|
setEventContext: (context: {
|
|
13
30
|
platform: string;
|
|
14
31
|
conversationId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAQ7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGlF,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,6BAA6B,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEtF,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,MAAM,EACpB,iBAAiB,CAAC,EAAE;IAClB,OAAO,EAAE,aAAa,CAAC;IACvB,kBAAkB,CAAC,EAAE,IAAI,CAAC,yBAAyB,EAAE,gBAAgB,GAAG,WAAW,CAAC,CAAC;CACtF;AACD;sEACsE;AACtE,yBAAyB,GAAE,SAAS,uBAAuB,EAAO,EAClE,eAAe,CAAC,EAAE;IAChB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,SAAS,EAAE,MAAM,CAAC;CACnB,GACA;IACD,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;IAC5B,iBAAiB,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IACrF;;6EAEyE;IACzE,sBAAsB,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IAC1F,gBAAgB,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IAC1E,qBAAqB,EAAE,CAAC,GAAG,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAC7D,eAAe,EAAE,CAAC,OAAO,EAAE;QACzB,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,EAAE,MAAM,CAAC;QACvB,gBAAgB,EAAE,gBAAgB,CAAC;QACnC,MAAM,EAAE,MAAM,CAAC;KAChB,KAAK,IAAI,CAAC;IACX,iBAAiB,EAAE,CAAC,OAAO,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAClF,CAsCA"}
|
package/dist/tools/index.js
CHANGED
|
@@ -2,24 +2,47 @@ import { createAttachTool } from "../adapters/slack/tools/attach.js";
|
|
|
2
2
|
import { createBashTool } from "./bash.js";
|
|
3
3
|
import { createEditTool } from "./edit.js";
|
|
4
4
|
import { createEventTool, HostEventStore } from "./event.js";
|
|
5
|
+
import { createGenerateImageTool } from "./generate-image.js";
|
|
6
|
+
import { createReactTool } from "./react.js";
|
|
5
7
|
import { createReadTool } from "./read.js";
|
|
6
8
|
import { createSandboxTool } from "./sandbox.js";
|
|
7
9
|
import { createWriteTool } from "./write.js";
|
|
8
|
-
export
|
|
10
|
+
export { createSubagentTool } from "./subagent.js";
|
|
11
|
+
export { DEFAULT_GLOBAL_SUBAGENT_SLOTS, SubagentSlotPool } from "./subagent-slots.js";
|
|
12
|
+
export function createMikanTools(executor, workspaceDir, sandboxController,
|
|
13
|
+
/** Platform capability pack factories (e.g. GitHub PR/CI); instantiated
|
|
14
|
+
* here so each runner owns its packs' bind state. Not core tools. */
|
|
15
|
+
platformToolPackFactories = [], imageGeneration) {
|
|
9
16
|
const { tool: attachTool, setUploadFunction } = createAttachTool();
|
|
17
|
+
const imageTool = imageGeneration ? createGenerateImageTool(imageGeneration) : undefined;
|
|
18
|
+
const { tool: reactTool, setReactFunction } = createReactTool();
|
|
10
19
|
const { tool: eventTool, setEventContext } = createEventTool(HostEventStore.fromWorkspaceDir(workspaceDir));
|
|
11
20
|
const { tool: sandboxTool, setSandboxContext } = createSandboxTool(sandboxController ?? { sandbox: executor.getSandboxConfig() });
|
|
21
|
+
const platformToolPacks = platformToolPackFactories.map((createPack) => createPack());
|
|
22
|
+
const packTools = platformToolPacks.flatMap((pack) => pack.tools);
|
|
12
23
|
return {
|
|
13
24
|
tools: [
|
|
14
25
|
createReadTool(executor),
|
|
15
|
-
createBashTool(executor),
|
|
26
|
+
createBashTool(executor, { hostWorkspaceRoot: workspaceDir }),
|
|
16
27
|
createEditTool(executor),
|
|
17
28
|
createWriteTool(executor),
|
|
18
29
|
eventTool,
|
|
19
30
|
sandboxTool,
|
|
20
31
|
attachTool,
|
|
32
|
+
...(imageTool ? [imageTool.tool] : []),
|
|
33
|
+
reactTool,
|
|
34
|
+
...packTools,
|
|
21
35
|
],
|
|
22
36
|
setUploadFunction,
|
|
37
|
+
setImageUploadFunction: (fn) => {
|
|
38
|
+
imageTool?.setUploadFunction(fn);
|
|
39
|
+
},
|
|
40
|
+
setReactFunction,
|
|
41
|
+
bindPlatformToolPacks: (ctx) => {
|
|
42
|
+
for (const pack of platformToolPacks) {
|
|
43
|
+
pack.bindRun(ctx);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
23
46
|
setEventContext,
|
|
24
47
|
setSandboxContext,
|
|
25
48
|
};
|
package/dist/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAGrE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,6BAA6B,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEtF,MAAM,UAAU,gBAAgB,CAC9B,QAAkB,EAClB,YAAoB,EACpB,iBAGC;AACD;sEACsE;AACtE,yBAAyB,GAAuC,EAAE,EAClE,eAIC;IAkBD,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,iBAAiB,EAAE,GAAG,gBAAgB,EAAE,CAAC;IACnE,MAAM,SAAS,GAAG,eAAe,CAAC,CAAC,CAAC,uBAAuB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzF,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,GAAG,eAAe,EAAE,CAAC;IAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,eAAe,CAC1D,cAAc,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAC9C,CAAC;IACF,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,CAChE,iBAAiB,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,gBAAgB,EAAE,EAAE,CAC9D,CAAC;IACF,MAAM,iBAAiB,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC;IACtF,MAAM,SAAS,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClE,OAAO;QACL,KAAK,EAAE;YACL,cAAc,CAAC,QAAQ,CAAC;YACxB,cAAc,CAAC,QAAQ,EAAE,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAC;YAC7D,cAAc,CAAC,QAAQ,CAAC;YACxB,eAAe,CAAC,QAAQ,CAAC;YACzB,SAAS;YACT,WAAW;YACX,UAAU;YACV,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACtC,SAAS;YACT,GAAG,SAAS;SACb;QACD,iBAAiB;QACjB,sBAAsB,EAAE,CAAC,EAAE,EAAE,EAAE;YAC7B,SAAS,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC;QACD,gBAAgB;QAChB,qBAAqB,EAAE,CAAC,GAAG,EAAE,EAAE;YAC7B,KAAK,MAAM,IAAI,IAAI,iBAAiB,EAAE,CAAC;gBACrC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;QACD,eAAe;QACf,iBAAiB;KAClB,CAAC;AACJ,CAAC","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Model } from \"@earendil-works/pi-ai\";\nimport type { TSchema } from \"@sinclair/typebox\";\nimport type { ConversationKind } from \"../adapter.js\";\nimport { createAttachTool } from \"../adapters/slack/tools/attach.js\";\nimport type { Executor, SandboxConfig } from \"../sandbox/index.js\";\nimport type { SandboxResourceController } from \"../types.js\";\nimport { createBashTool } from \"./bash.js\";\nimport { createEditTool } from \"./edit.js\";\nimport { createEventTool, HostEventStore } from \"./event.js\";\nimport { createGenerateImageTool } from \"./generate-image.js\";\nimport { createReactTool } from \"./react.js\";\nimport { createReadTool } from \"./read.js\";\nimport { createSandboxTool } from \"./sandbox.js\";\nimport type { PlatformToolPackFactory, PlatformToolRunContext } from \"./types.js\";\nimport { createWriteTool } from \"./write.js\";\n\nexport { createSubagentTool } from \"./subagent.js\";\nexport { DEFAULT_GLOBAL_SUBAGENT_SLOTS, SubagentSlotPool } from \"./subagent-slots.js\";\n\nexport function createMikanTools(\n executor: Executor,\n workspaceDir: string,\n sandboxController?: {\n sandbox: SandboxConfig;\n resourceController?: Pick<SandboxResourceController, \"getLimitStatus\" | \"setLimits\">;\n },\n /** Platform capability pack factories (e.g. GitHub PR/CI); instantiated\n * here so each runner owns its packs' bind state. Not core tools. */\n platformToolPackFactories: readonly PlatformToolPackFactory[] = [],\n imageGeneration?: {\n model: Model<Api>;\n getApiKey: () => Promise<string | undefined>;\n outputDir: string;\n },\n): {\n tools: AgentTool<TSchema>[];\n setUploadFunction: (fn: (filePath: string, title?: string) => Promise<void>) => void;\n /** Upload for generate_image. Receives the file's HOST path — the tool\n * writes host-side, so this must not stage through the sandbox like the\n * attach upload does. No-op when image generation is not configured. */\n setImageUploadFunction: (fn: (hostPath: string, title?: string) => Promise<void>) => void;\n setReactFunction: (fn: ((emoji: string) => Promise<void>) | null) => void;\n bindPlatformToolPacks: (ctx: PlatformToolRunContext) => void;\n setEventContext: (context: {\n platform: string;\n conversationId: string;\n conversationKind: ConversationKind;\n userId: string;\n }) => void;\n setSandboxContext: (context: { conversationId: string; userId: string }) => void;\n} {\n const { tool: attachTool, setUploadFunction } = createAttachTool();\n const imageTool = imageGeneration ? createGenerateImageTool(imageGeneration) : undefined;\n const { tool: reactTool, setReactFunction } = createReactTool();\n const { tool: eventTool, setEventContext } = createEventTool(\n HostEventStore.fromWorkspaceDir(workspaceDir),\n );\n const { tool: sandboxTool, setSandboxContext } = createSandboxTool(\n sandboxController ?? { sandbox: executor.getSandboxConfig() },\n );\n const platformToolPacks = platformToolPackFactories.map((createPack) => createPack());\n const packTools = platformToolPacks.flatMap((pack) => pack.tools);\n return {\n tools: [\n createReadTool(executor),\n createBashTool(executor, { hostWorkspaceRoot: workspaceDir }),\n createEditTool(executor),\n createWriteTool(executor),\n eventTool,\n sandboxTool,\n attachTool,\n ...(imageTool ? [imageTool.tool] : []),\n reactTool,\n ...packTools,\n ],\n setUploadFunction,\n setImageUploadFunction: (fn) => {\n imageTool?.setUploadFunction(fn);\n },\n setReactFunction,\n bindPlatformToolPacks: (ctx) => {\n for (const pack of platformToolPacks) {\n pack.bindRun(ctx);\n }\n },\n setEventContext,\n setSandboxContext,\n };\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
2
|
+
declare const reactSchema: import("@sinclair/typebox").TObject<{
|
|
3
|
+
emoji: import("@sinclair/typebox").TString;
|
|
4
|
+
}>;
|
|
5
|
+
/**
|
|
6
|
+
* The `react` tool adds an emoji reaction to the message that triggered the
|
|
7
|
+
* current run. The channel and message timestamp are captured per run via
|
|
8
|
+
* {@link createReactTool}'s setter; the model only supplies the emoji.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createReactTool(): {
|
|
11
|
+
tool: AgentTool<typeof reactSchema>;
|
|
12
|
+
setReactFunction: (fn: ((emoji: string) => Promise<void>) | null) => void;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/tools/react.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAI/D,QAAA,MAAM,WAAW;;EAKf,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,eAAe,IAAI;IACjC,IAAI,EAAE,SAAS,CAAC,OAAO,WAAW,CAAC,CAAC;IACpC,gBAAgB,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3E,CAiBA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { defineHostFnTool } from "./host-fn-tool.js";
|
|
3
|
+
const reactSchema = Type.Object({
|
|
4
|
+
emoji: Type.String({
|
|
5
|
+
description: "Emoji to react with. Use a short name without colons (e.g. eyes, white_check_mark, +1) on Slack, or a Unicode emoji on Discord/Telegram.",
|
|
6
|
+
}),
|
|
7
|
+
});
|
|
8
|
+
/**
|
|
9
|
+
* The `react` tool adds an emoji reaction to the message that triggered the
|
|
10
|
+
* current run. The channel and message timestamp are captured per run via
|
|
11
|
+
* {@link createReactTool}'s setter; the model only supplies the emoji.
|
|
12
|
+
*/
|
|
13
|
+
export function createReactTool() {
|
|
14
|
+
const { tool, setFn } = defineHostFnTool({
|
|
15
|
+
name: "react",
|
|
16
|
+
description: "Add an emoji reaction to the message you are responding to. Useful for a lightweight acknowledgement (e.g. eyes to show you saw a request, white_check_mark when done) instead of a full reply.",
|
|
17
|
+
parameters: reactSchema,
|
|
18
|
+
unavailable: "Reactions are not supported in this conversation.",
|
|
19
|
+
run: async (reactFn, { emoji }) => {
|
|
20
|
+
await reactFn(emoji);
|
|
21
|
+
return {
|
|
22
|
+
content: [{ type: "text", text: `Reacted with :${emoji.replace(/^:|:$/g, "")}:` }],
|
|
23
|
+
details: undefined,
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
return { tool, setReactFunction: setFn };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/tools/react.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;QACjB,WAAW,EACT,0IAA0I;KAC7I,CAAC;CACH,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAI7B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAuD;QAC7F,IAAI,EAAE,OAAO;QACb,WAAW,EACT,iMAAiM;QACnM,UAAU,EAAE,WAAW;QACvB,WAAW,EAAE,mDAAmD;QAChE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;YAChC,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;YACrB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,iBAAiB,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC;gBAC3F,OAAO,EAAE,SAAS;aACnB,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC;AAC3C,CAAC","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nimport { defineHostFnTool } from \"./host-fn-tool.js\";\n\nconst reactSchema = Type.Object({\n emoji: Type.String({\n description:\n \"Emoji to react with. Use a short name without colons (e.g. eyes, white_check_mark, +1) on Slack, or a Unicode emoji on Discord/Telegram.\",\n }),\n});\n\n/**\n * The `react` tool adds an emoji reaction to the message that triggered the\n * current run. The channel and message timestamp are captured per run via\n * {@link createReactTool}'s setter; the model only supplies the emoji.\n */\nexport function createReactTool(): {\n tool: AgentTool<typeof reactSchema>;\n setReactFunction: (fn: ((emoji: string) => Promise<void>) | null) => void;\n} {\n const { tool, setFn } = defineHostFnTool<(emoji: string) => Promise<void>, typeof reactSchema>({\n name: \"react\",\n description:\n \"Add an emoji reaction to the message you are responding to. Useful for a lightweight acknowledgement (e.g. eyes to show you saw a request, white_check_mark when done) instead of a full reply.\",\n parameters: reactSchema,\n unavailable: \"Reactions are not supported in this conversation.\",\n run: async (reactFn, { emoji }) => {\n await reactFn(emoji);\n return {\n content: [{ type: \"text\" as const, text: `Reacted with :${emoji.replace(/^:|:$/g, \"\")}:` }],\n details: undefined,\n };\n },\n });\n\n return { tool, setReactFunction: setFn };\n}\n"]}
|
package/dist/tools/read.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ declare const readSchema: import("@sinclair/typebox").TObject<{
|
|
|
5
5
|
path: import("@sinclair/typebox").TString;
|
|
6
6
|
offset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
7
7
|
limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
8
|
+
byteOffset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
8
9
|
}>;
|
|
9
10
|
export declare function createReadTool(executor: Executor): AgentTool<typeof readSchema>;
|
|
10
11
|
export {};
|
package/dist/tools/read.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAI/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAI/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AA4BpD,QAAA,MAAM,UAAU;;;;;;EAed,CAAC;AAoBH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAyH/E"}
|
package/dist/tools/read.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
|
-
import { extname } from "path";
|
|
3
|
-
import {
|
|
4
|
-
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead, } from "./truncate.js";
|
|
2
|
+
import { extname } from "node:path";
|
|
3
|
+
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead, } from "@earendil-works/pi-agent-core";
|
|
5
4
|
/**
|
|
6
5
|
* Map of file extensions to MIME types for common image formats
|
|
7
6
|
*/
|
|
@@ -26,22 +25,35 @@ const readSchema = Type.Object({
|
|
|
26
25
|
path: Type.String({ description: "Path to the file to read (relative or absolute)" }),
|
|
27
26
|
offset: Type.Optional(Type.Number({ description: "Line number to start reading from (1-indexed)" })),
|
|
28
27
|
limit: Type.Optional(Type.Number({ description: "Maximum number of lines to read" })),
|
|
28
|
+
byteOffset: Type.Optional(Type.Number({
|
|
29
|
+
description: "Byte offset into the first selected line. Use to page through a line too large to return whole.",
|
|
30
|
+
})),
|
|
29
31
|
});
|
|
32
|
+
/**
|
|
33
|
+
* Trim bytes that would split a multi-byte UTF-8 sequence at the slice end, so
|
|
34
|
+
* paging through a long line never emits a replacement character at the seam.
|
|
35
|
+
*/
|
|
36
|
+
function trimToCharBoundary(buffer) {
|
|
37
|
+
for (let back = 1; back <= Math.min(4, buffer.length); back++) {
|
|
38
|
+
const byte = buffer[buffer.length - back];
|
|
39
|
+
if (byte === undefined || (byte & 0xc0) === 0x80)
|
|
40
|
+
continue; // continuation byte; keep walking back
|
|
41
|
+
const needed = byte < 0x80 ? 1 : byte < 0xe0 ? 2 : byte < 0xf0 ? 3 : 4;
|
|
42
|
+
return back === needed ? buffer : buffer.subarray(0, buffer.length - back);
|
|
43
|
+
}
|
|
44
|
+
return buffer;
|
|
45
|
+
}
|
|
30
46
|
export function createReadTool(executor) {
|
|
31
47
|
return {
|
|
32
48
|
name: "read",
|
|
33
49
|
label: "read",
|
|
34
|
-
description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files.`,
|
|
50
|
+
description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files, and byteOffset to page through a single line larger than the byte limit.`,
|
|
35
51
|
parameters: readSchema,
|
|
36
|
-
execute: async (_toolCallId, { path, offset, limit }, signal) => {
|
|
52
|
+
execute: async (_toolCallId, { path, offset, limit, byteOffset, }, signal) => {
|
|
37
53
|
const mimeType = isImageFile(path);
|
|
38
54
|
if (mimeType) {
|
|
39
|
-
//
|
|
40
|
-
const
|
|
41
|
-
if (result.code !== 0) {
|
|
42
|
-
throw new Error(result.stderr || `Failed to read file: ${path}`);
|
|
43
|
-
}
|
|
44
|
-
const base64 = result.stdout.replace(/\s/g, ""); // Remove whitespace from base64
|
|
55
|
+
// Binary content rides the executor's own transport, never shell argv.
|
|
56
|
+
const base64 = await executor.readFileBase64(path, { signal });
|
|
45
57
|
return {
|
|
46
58
|
content: [
|
|
47
59
|
{ type: "text", text: `Read image file [${mimeType}]` },
|
|
@@ -50,12 +62,10 @@ export function createReadTool(executor) {
|
|
|
50
62
|
details: undefined,
|
|
51
63
|
};
|
|
52
64
|
}
|
|
53
|
-
//
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
const totalFileLines = Number.parseInt(countResult.stdout.trim(), 10) + 1; // wc -l counts newlines, not lines
|
|
65
|
+
// One transport read; line selection is plain code, not shell strings.
|
|
66
|
+
const fileText = await executor.readFile(path, { signal });
|
|
67
|
+
const fileLines = fileText.split("\n");
|
|
68
|
+
const totalFileLines = fileLines.length;
|
|
59
69
|
// Apply offset if specified (1-indexed)
|
|
60
70
|
const startLine = offset ? Math.max(1, offset) : 1;
|
|
61
71
|
const startLineDisplay = startLine;
|
|
@@ -63,19 +73,7 @@ export function createReadTool(executor) {
|
|
|
63
73
|
if (startLine > totalFileLines) {
|
|
64
74
|
throw new Error(`Offset ${offset} is beyond end of file (${totalFileLines} lines total)`);
|
|
65
75
|
}
|
|
66
|
-
|
|
67
|
-
let cmd;
|
|
68
|
-
if (startLine === 1) {
|
|
69
|
-
cmd = `cat ${shellEscape(path)}`;
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
cmd = `tail -n +${startLine} ${shellEscape(path)}`;
|
|
73
|
-
}
|
|
74
|
-
const result = await executor.exec(cmd, { signal });
|
|
75
|
-
if (result.code !== 0) {
|
|
76
|
-
throw new Error(result.stderr || `Failed to read file: ${path}`);
|
|
77
|
-
}
|
|
78
|
-
let selectedContent = result.stdout;
|
|
76
|
+
let selectedContent = startLine === 1 ? fileText : fileLines.slice(startLine - 1).join("\n");
|
|
79
77
|
let userLimitedLines;
|
|
80
78
|
// Apply user limit if specified
|
|
81
79
|
if (limit !== undefined) {
|
|
@@ -89,9 +87,17 @@ export function createReadTool(executor) {
|
|
|
89
87
|
let outputText;
|
|
90
88
|
let details;
|
|
91
89
|
if (truncation.firstLineExceedsLimit) {
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
// Serve the line in byte-addressed slices rather than pointing at
|
|
91
|
+
// another tool: the caller may not hold one (Session Dream grants only
|
|
92
|
+
// read/edit/write), and a dead end there costs a whole run.
|
|
93
|
+
const lineBuffer = Buffer.from(selectedContent.split("\n")[0] ?? "", "utf-8");
|
|
94
|
+
const start = Math.max(0, Math.min(byteOffset ?? 0, lineBuffer.length));
|
|
95
|
+
const slice = trimToCharBoundary(lineBuffer.subarray(start, start + DEFAULT_MAX_BYTES));
|
|
96
|
+
const end = start + slice.length;
|
|
97
|
+
outputText = slice.toString("utf-8");
|
|
98
|
+
outputText += `\n\n[Line ${startLineDisplay} is ${formatSize(lineBuffer.length)}; showing bytes ${start}-${end}.`;
|
|
99
|
+
outputText +=
|
|
100
|
+
end < lineBuffer.length ? ` Use byteOffset=${end} to continue]` : " End of line reached]";
|
|
95
101
|
details = { truncation };
|
|
96
102
|
}
|
|
97
103
|
else if (truncation.truncated) {
|
package/dist/tools/read.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport { Type } from \"@sinclair/typebox\";\nimport { extname } from \"path\";\nimport type { Executor } from \"../sandbox/index.js\";\nimport { shellEscape } from \"../sandbox/utils.js\";\nimport {\n DEFAULT_MAX_BYTES,\n DEFAULT_MAX_LINES,\n formatSize,\n type TruncationResult,\n truncateHead,\n} from \"./truncate.js\";\n\n/**\n * Map of file extensions to MIME types for common image formats\n */\nconst IMAGE_MIME_TYPES: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n};\n\n/**\n * Check if a file is an image based on its extension\n */\nfunction isImageFile(filePath: string): string | null {\n const ext = extname(filePath).toLowerCase();\n return IMAGE_MIME_TYPES[ext] || null;\n}\n\nconst readSchema = Type.Object({\n label: Type.String({\n description: \"Brief description of what you're reading and why (shown to user)\",\n }),\n path: Type.String({ description: \"Path to the file to read (relative or absolute)\" }),\n offset: Type.Optional(\n Type.Number({ description: \"Line number to start reading from (1-indexed)\" }),\n ),\n limit: Type.Optional(Type.Number({ description: \"Maximum number of lines to read\" })),\n});\n\ninterface ReadToolDetails {\n truncation?: TruncationResult;\n}\n\nexport function createReadTool(executor: Executor): AgentTool<typeof readSchema> {\n return {\n name: \"read\",\n label: \"read\",\n description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files.`,\n parameters: readSchema,\n execute: async (\n _toolCallId: string,\n { path, offset, limit }: { label: string; path: string; offset?: number; limit?: number },\n signal?: AbortSignal,\n ): Promise<{\n content: (TextContent | ImageContent)[];\n details: ReadToolDetails | undefined;\n }> => {\n const mimeType = isImageFile(path);\n\n if (mimeType) {\n // Read as image (binary) - use base64\n const result = await executor.exec(`base64 < ${shellEscape(path)}`, { signal });\n if (result.code !== 0) {\n throw new Error(result.stderr || `Failed to read file: ${path}`);\n }\n const base64 = result.stdout.replace(/\\s/g, \"\"); // Remove whitespace from base64\n\n return {\n content: [\n { type: \"text\", text: `Read image file [${mimeType}]` },\n { type: \"image\", data: base64, mimeType },\n ],\n details: undefined,\n };\n }\n\n // Get total line count first\n const countResult = await executor.exec(`wc -l < ${shellEscape(path)}`, { signal });\n if (countResult.code !== 0) {\n throw new Error(countResult.stderr || `Failed to read file: ${path}`);\n }\n const totalFileLines = Number.parseInt(countResult.stdout.trim(), 10) + 1; // wc -l counts newlines, not lines\n\n // Apply offset if specified (1-indexed)\n const startLine = offset ? Math.max(1, offset) : 1;\n const startLineDisplay = startLine;\n\n // Check if offset is out of bounds\n if (startLine > totalFileLines) {\n throw new Error(`Offset ${offset} is beyond end of file (${totalFileLines} lines total)`);\n }\n\n // Read content with offset\n let cmd: string;\n if (startLine === 1) {\n cmd = `cat ${shellEscape(path)}`;\n } else {\n cmd = `tail -n +${startLine} ${shellEscape(path)}`;\n }\n\n const result = await executor.exec(cmd, { signal });\n if (result.code !== 0) {\n throw new Error(result.stderr || `Failed to read file: ${path}`);\n }\n\n let selectedContent = result.stdout;\n let userLimitedLines: number | undefined;\n\n // Apply user limit if specified\n if (limit !== undefined) {\n const lines = selectedContent.split(\"\\n\");\n const endLine = Math.min(limit, lines.length);\n selectedContent = lines.slice(0, endLine).join(\"\\n\");\n userLimitedLines = endLine;\n }\n\n // Apply truncation (respects both line and byte limits)\n const truncation = truncateHead(selectedContent);\n\n let outputText: string;\n let details: ReadToolDetails | undefined;\n\n if (truncation.firstLineExceedsLimit) {\n // First line at offset exceeds 50KB - tell model to use bash\n const firstLineSize = formatSize(\n Buffer.byteLength(selectedContent.split(\"\\n\")[0], \"utf-8\"),\n );\n outputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES)} limit. Use bash: sed -n '${startLineDisplay}p' ${path} | head -c ${DEFAULT_MAX_BYTES}]`;\n details = { truncation };\n } else if (truncation.truncated) {\n // Truncation occurred - build actionable notice\n const endLineDisplay = startLineDisplay + truncation.outputLines - 1;\n const nextOffset = endLineDisplay + 1;\n\n outputText = truncation.content;\n\n if (truncation.truncatedBy === \"lines\") {\n outputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue]`;\n } else {\n outputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue]`;\n }\n details = { truncation };\n } else if (userLimitedLines !== undefined) {\n // User specified limit, check if there's more content\n const linesFromStart = startLine - 1 + userLimitedLines;\n if (linesFromStart < totalFileLines) {\n const remaining = totalFileLines - linesFromStart;\n const nextOffset = startLine + userLimitedLines;\n\n outputText = truncation.content;\n outputText += `\\n\\n[${remaining} more lines in file. Use offset=${nextOffset} to continue]`;\n } else {\n outputText = truncation.content;\n }\n } else {\n // No truncation, no user limit exceeded\n outputText = truncation.content;\n }\n\n return {\n content: [{ type: \"text\", text: outputText }],\n details,\n };\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport { Type } from \"@sinclair/typebox\";\nimport { extname } from \"node:path\";\nimport type { Executor } from \"../sandbox/index.js\";\nimport {\n DEFAULT_MAX_BYTES,\n DEFAULT_MAX_LINES,\n formatSize,\n type TruncationResult,\n truncateHead,\n} from \"@earendil-works/pi-agent-core\";\n\n/**\n * Map of file extensions to MIME types for common image formats\n */\nconst IMAGE_MIME_TYPES: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n};\n\n/**\n * Check if a file is an image based on its extension\n */\nfunction isImageFile(filePath: string): string | null {\n const ext = extname(filePath).toLowerCase();\n return IMAGE_MIME_TYPES[ext] || null;\n}\n\nconst readSchema = Type.Object({\n label: Type.String({\n description: \"Brief description of what you're reading and why (shown to user)\",\n }),\n path: Type.String({ description: \"Path to the file to read (relative or absolute)\" }),\n offset: Type.Optional(\n Type.Number({ description: \"Line number to start reading from (1-indexed)\" }),\n ),\n limit: Type.Optional(Type.Number({ description: \"Maximum number of lines to read\" })),\n byteOffset: Type.Optional(\n Type.Number({\n description:\n \"Byte offset into the first selected line. Use to page through a line too large to return whole.\",\n }),\n ),\n});\n\n/**\n * Trim bytes that would split a multi-byte UTF-8 sequence at the slice end, so\n * paging through a long line never emits a replacement character at the seam.\n */\nfunction trimToCharBoundary(buffer: Buffer): Buffer {\n for (let back = 1; back <= Math.min(4, buffer.length); back++) {\n const byte = buffer[buffer.length - back];\n if (byte === undefined || (byte & 0xc0) === 0x80) continue; // continuation byte; keep walking back\n const needed = byte < 0x80 ? 1 : byte < 0xe0 ? 2 : byte < 0xf0 ? 3 : 4;\n return back === needed ? buffer : buffer.subarray(0, buffer.length - back);\n }\n return buffer;\n}\n\ninterface ReadToolDetails {\n truncation?: TruncationResult;\n}\n\nexport function createReadTool(executor: Executor): AgentTool<typeof readSchema> {\n return {\n name: \"read\",\n label: \"read\",\n description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files, and byteOffset to page through a single line larger than the byte limit.`,\n parameters: readSchema,\n execute: async (\n _toolCallId: string,\n {\n path,\n offset,\n limit,\n byteOffset,\n }: {\n label: string;\n path: string;\n offset?: number;\n limit?: number;\n byteOffset?: number;\n },\n signal?: AbortSignal,\n ): Promise<{\n content: (TextContent | ImageContent)[];\n details: ReadToolDetails | undefined;\n }> => {\n const mimeType = isImageFile(path);\n\n if (mimeType) {\n // Binary content rides the executor's own transport, never shell argv.\n const base64 = await executor.readFileBase64(path, { signal });\n\n return {\n content: [\n { type: \"text\", text: `Read image file [${mimeType}]` },\n { type: \"image\", data: base64, mimeType },\n ],\n details: undefined,\n };\n }\n\n // One transport read; line selection is plain code, not shell strings.\n const fileText = await executor.readFile(path, { signal });\n const fileLines = fileText.split(\"\\n\");\n const totalFileLines = fileLines.length;\n\n // Apply offset if specified (1-indexed)\n const startLine = offset ? Math.max(1, offset) : 1;\n const startLineDisplay = startLine;\n\n // Check if offset is out of bounds\n if (startLine > totalFileLines) {\n throw new Error(`Offset ${offset} is beyond end of file (${totalFileLines} lines total)`);\n }\n\n let selectedContent = startLine === 1 ? fileText : fileLines.slice(startLine - 1).join(\"\\n\");\n let userLimitedLines: number | undefined;\n\n // Apply user limit if specified\n if (limit !== undefined) {\n const lines = selectedContent.split(\"\\n\");\n const endLine = Math.min(limit, lines.length);\n selectedContent = lines.slice(0, endLine).join(\"\\n\");\n userLimitedLines = endLine;\n }\n\n // Apply truncation (respects both line and byte limits)\n const truncation = truncateHead(selectedContent);\n\n let outputText: string;\n let details: ReadToolDetails | undefined;\n\n if (truncation.firstLineExceedsLimit) {\n // Serve the line in byte-addressed slices rather than pointing at\n // another tool: the caller may not hold one (Session Dream grants only\n // read/edit/write), and a dead end there costs a whole run.\n const lineBuffer = Buffer.from(selectedContent.split(\"\\n\")[0] ?? \"\", \"utf-8\");\n const start = Math.max(0, Math.min(byteOffset ?? 0, lineBuffer.length));\n const slice = trimToCharBoundary(lineBuffer.subarray(start, start + DEFAULT_MAX_BYTES));\n const end = start + slice.length;\n\n outputText = slice.toString(\"utf-8\");\n outputText += `\\n\\n[Line ${startLineDisplay} is ${formatSize(lineBuffer.length)}; showing bytes ${start}-${end}.`;\n outputText +=\n end < lineBuffer.length ? ` Use byteOffset=${end} to continue]` : \" End of line reached]\";\n details = { truncation };\n } else if (truncation.truncated) {\n // Truncation occurred - build actionable notice\n const endLineDisplay = startLineDisplay + truncation.outputLines - 1;\n const nextOffset = endLineDisplay + 1;\n\n outputText = truncation.content;\n\n if (truncation.truncatedBy === \"lines\") {\n outputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue]`;\n } else {\n outputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue]`;\n }\n details = { truncation };\n } else if (userLimitedLines !== undefined) {\n // User specified limit, check if there's more content\n const linesFromStart = startLine - 1 + userLimitedLines;\n if (linesFromStart < totalFileLines) {\n const remaining = totalFileLines - linesFromStart;\n const nextOffset = startLine + userLimitedLines;\n\n outputText = truncation.content;\n outputText += `\\n\\n[${remaining} more lines in file. Use offset=${nextOffset} to continue]`;\n } else {\n outputText = truncation.content;\n }\n } else {\n // No truncation, no user limit exceeded\n outputText = truncation.content;\n }\n\n return {\n content: [{ type: \"text\", text: outputText }],\n details,\n };\n },\n };\n}\n"]}
|
package/dist/tools/sandbox.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
2
|
-
import type { DockerContainerManager } from "../provisioner.js";
|
|
3
2
|
import type { SandboxConfig } from "../sandbox/index.js";
|
|
3
|
+
import type { SandboxResourceController } from "../types.js";
|
|
4
4
|
declare const sandboxSchema: import("@sinclair/typebox").TObject<{
|
|
5
5
|
action: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"status">, import("@sinclair/typebox").TLiteral<"set">]>;
|
|
6
6
|
cpus: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
@@ -12,7 +12,7 @@ interface SandboxToolContext {
|
|
|
12
12
|
}
|
|
13
13
|
interface SandboxToolController {
|
|
14
14
|
sandbox: SandboxConfig;
|
|
15
|
-
|
|
15
|
+
resourceController?: Pick<SandboxResourceController, "getLimitStatus" | "setLimits">;
|
|
16
16
|
}
|
|
17
17
|
export declare function createSandboxTool(controller: SandboxToolController): {
|
|
18
18
|
tool: AgentTool<typeof sandboxSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/tools/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/tools/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAkB,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAG7E,QAAA,MAAM,aAAa;;;;EAcjB,CAAC;AAQH,UAAU,kBAAkB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,qBAAqB;IAC7B,OAAO,EAAE,aAAa,CAAC;IACvB,kBAAkB,CAAC,EAAE,IAAI,CAAC,yBAAyB,EAAE,gBAAgB,GAAG,WAAW,CAAC,CAAC;CACtF;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,qBAAqB,GAAG;IACpE,IAAI,EAAE,SAAS,CAAC,OAAO,aAAa,CAAC,CAAC;IACtC,iBAAiB,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC1D,CAkDA"}
|
package/dist/tools/sandbox.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
|
-
import {
|
|
2
|
+
import { runtimeResourceKey } from "../sandbox/identity.js";
|
|
3
3
|
const sandboxSchema = Type.Object({
|
|
4
4
|
action: Type.Union([Type.Literal("status"), Type.Literal("set")], {
|
|
5
5
|
description: "Use status to inspect current limits, or set to apply temporary limits.",
|
|
6
6
|
}),
|
|
7
7
|
cpus: Type.Optional(Type.String({
|
|
8
|
-
description: "
|
|
8
|
+
description: "CPU limit for action=set, for example '0.5', '1', or '2'.",
|
|
9
9
|
})),
|
|
10
10
|
memory: Type.Optional(Type.String({
|
|
11
11
|
description: "Docker memory limit for action=set, for example '512m', '1g', or '4g'.",
|
|
@@ -16,7 +16,8 @@ export function createSandboxTool(controller) {
|
|
|
16
16
|
const tool = {
|
|
17
17
|
name: "sandbox",
|
|
18
18
|
label: "sandbox",
|
|
19
|
-
|
|
19
|
+
executionMode: "sequential",
|
|
20
|
+
description: "Inspect or temporarily set CPU/memory limits for the current managed sandbox. Limits apply to this conversation's runtime and are cleared when it stops.",
|
|
20
21
|
parameters: sandboxSchema,
|
|
21
22
|
execute: async (_toolCallId, params, signal) => {
|
|
22
23
|
if (signal?.aborted) {
|
|
@@ -25,16 +26,20 @@ export function createSandboxTool(controller) {
|
|
|
25
26
|
if (!sandboxContext) {
|
|
26
27
|
throw new Error("Sandbox context not configured");
|
|
27
28
|
}
|
|
28
|
-
if (controller.sandbox.type !== "image"
|
|
29
|
-
|
|
29
|
+
if ((controller.sandbox.type !== "image" && controller.sandbox.type !== "gondolin") ||
|
|
30
|
+
!controller.resourceController) {
|
|
31
|
+
throw new Error("The sandbox tool only supports image:* and gondolin:* managed sandboxes");
|
|
30
32
|
}
|
|
31
|
-
const containerKey =
|
|
33
|
+
const containerKey = runtimeResourceKey(controller.sandbox, {
|
|
34
|
+
userId: sandboxContext.userId,
|
|
35
|
+
conversationId: sandboxContext.conversationId,
|
|
36
|
+
});
|
|
32
37
|
if (params.action === "set") {
|
|
33
38
|
const limits = normalizeLimits(params);
|
|
34
|
-
const status = await controller.
|
|
35
|
-
return textResult(`Updated sandbox limits for ${containerKey}: ${formatLimits(status.limits)}. These temporary limits are cleared when the sandbox
|
|
39
|
+
const status = await controller.resourceController.setLimits(containerKey, limits);
|
|
40
|
+
return textResult(`Updated sandbox limits for ${containerKey}: ${formatLimits(status.limits)}. These temporary limits are cleared when the sandbox runtime stops.`);
|
|
36
41
|
}
|
|
37
|
-
const status = controller.
|
|
42
|
+
const status = controller.resourceController.getLimitStatus(containerKey);
|
|
38
43
|
return textResult(`Sandbox limits for ${containerKey}: ${formatLimits(status.limits)}${status.boosted ? " (boosted)" : ""}.`);
|
|
39
44
|
},
|
|
40
45
|
};
|