@fastagent-sh/fastagent 0.24.4 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -82
- package/dist/agent-api.d.ts +460 -0
- package/dist/agent-api.js +209 -0
- package/dist/answer-text.d.ts +8 -0
- package/dist/answer-text.js +18 -0
- package/dist/atomic-write.d.ts +2 -2
- package/dist/atomic-write.js +2 -2
- package/dist/authoring.d.ts +81 -0
- package/dist/authoring.js +245 -0
- package/dist/channel.d.ts +29 -15
- package/dist/channel.js +4 -1
- package/dist/channels/agentcore-protocol.d.ts +36 -50
- package/dist/channels/agentcore-protocol.js +3 -3
- package/dist/channels/agentcore-service.d.ts +8 -18
- package/dist/channels/agentcore-service.js +108 -127
- package/dist/channels/agentcore.d.ts +8 -24
- package/dist/channels/agentcore.js +32 -65
- package/dist/channels/body.d.ts +0 -16
- package/dist/channels/body.js +0 -25
- package/dist/channels/busy.js +6 -1
- package/dist/channels/context.d.ts +4 -0
- package/dist/channels/context.js +35 -0
- package/dist/channels/discover.d.ts +18 -20
- package/dist/channels/discover.js +41 -99
- package/dist/channels/feishu/feishu-api.d.ts +54 -4
- package/dist/channels/feishu/feishu-api.js +192 -149
- package/dist/channels/feishu/feishu.d.ts +3 -0
- package/dist/channels/feishu/feishu.js +117 -106
- package/dist/channels/feishu/history.d.ts +55 -0
- package/dist/channels/feishu/history.js +199 -0
- package/dist/channels/feishu/invoke-turn.d.ts +13 -11
- package/dist/channels/feishu/invoke-turn.js +9 -10
- package/dist/channels/feishu/model.d.ts +2 -1
- package/dist/channels/feishu/normalize.js +100 -0
- package/dist/channels/feishu/preview.d.ts +2 -2
- package/dist/channels/feishu/register-webhook.d.ts +1 -0
- package/dist/channels/feishu/register-webhook.js +3 -2
- package/dist/channels/feishu/scaffold/channel.ts +65 -46
- package/dist/channels/feishu/scaffold/feishu-send.ts +38 -33
- package/dist/channels/feishu/scaffold/feishu-threads.ts +25 -0
- package/dist/channels/feishu/setup-mode.d.ts +45 -25
- package/dist/channels/feishu/setup-mode.js +74 -23
- package/dist/channels/feishu/shared-api.d.ts +24 -6
- package/dist/channels/feishu/shared-api.js +30 -24
- package/dist/channels/kit/context-buffer.d.ts +11 -2
- package/dist/channels/kit/context-buffer.js +7 -4
- package/dist/channels/kit/delivery.d.ts +19 -3
- package/dist/channels/kit/delivery.js +74 -15
- package/dist/channels/kit/event-stream.js +2 -1
- package/dist/channels/kit/invoke-turn-kit.d.ts +41 -41
- package/dist/channels/kit/invoke-turn-kit.js +62 -71
- package/dist/channels/kit/place-history.d.ts +107 -0
- package/dist/channels/kit/place-history.js +182 -0
- package/dist/channels/kit/preview-kit.d.ts +9 -5
- package/dist/channels/kit/preview-kit.js +36 -15
- package/dist/channels/kit/room-threads.d.ts +46 -0
- package/dist/channels/kit/room-threads.js +81 -0
- package/dist/channels/kit/seen.js +1 -1
- package/dist/channels/kit/stop-command.d.ts +6 -3
- package/dist/channels/kit/stop-command.js +20 -18
- package/dist/channels/kit/thread-fork.d.ts +17 -0
- package/dist/channels/kit/thread-fork.js +43 -0
- package/dist/channels/kit/thread-participants.js +1 -1
- package/dist/channels/kit/transport.d.ts +5 -0
- package/dist/channels/kit/transport.js +5 -0
- package/dist/channels/kit/turn-runner.d.ts +10 -9
- package/dist/channels/kit/turn-runner.js +17 -19
- package/dist/channels/kit/turn-store.d.ts +5 -4
- package/dist/channels/kit/turn-store.js +5 -5
- package/dist/channels/lark/lark.d.ts +3 -0
- package/dist/channels/lark/lark.js +5 -0
- package/dist/channels/lark/onboard.d.ts +5 -3
- package/dist/channels/lark/onboard.js +14 -14
- package/dist/channels/lark/scaffold/channel.ts +67 -44
- package/dist/channels/lark/scaffold/lark-send.ts +38 -33
- package/dist/channels/lark/scaffold/lark-threads.ts +25 -0
- package/dist/channels/respond.d.ts +0 -4
- package/dist/channels/respond.js +1 -1
- package/dist/channels/router.d.ts +18 -0
- package/dist/channels/router.js +68 -0
- package/dist/channels/serve.d.ts +5 -70
- package/dist/channels/serve.js +105 -287
- package/dist/channels/slack/history.d.ts +42 -0
- package/dist/channels/slack/history.js +282 -0
- package/dist/channels/slack/invoke-turn.d.ts +12 -5
- package/dist/channels/slack/invoke-turn.js +7 -5
- package/dist/channels/slack/manifest.d.ts +1 -4
- package/dist/channels/slack/manifest.js +22 -10
- package/dist/channels/slack/model.d.ts +2 -1
- package/dist/channels/slack/onboard.d.ts +0 -2
- package/dist/channels/slack/onboard.js +2 -4
- package/dist/channels/slack/onboarding-state.d.ts +0 -2
- package/dist/channels/slack/onboarding-state.js +0 -1
- package/dist/channels/slack/parse.d.ts +0 -5
- package/dist/channels/slack/parse.js +1 -16
- package/dist/channels/slack/preview.d.ts +2 -3
- package/dist/channels/slack/preview.js +78 -52
- package/dist/channels/slack/register-webhook.d.ts +1 -0
- package/dist/channels/slack/register-webhook.js +6 -5
- package/dist/channels/slack/scaffold/channel.ts +23 -24
- package/dist/channels/slack/scaffold/slack-send.ts +50 -43
- package/dist/channels/slack/scaffold/slack-threads.ts +29 -0
- package/dist/channels/slack/setup-server.d.ts +19 -0
- package/dist/channels/slack/setup-server.js +113 -11
- package/dist/channels/slack/shared-api.d.ts +15 -4
- package/dist/channels/slack/shared-api.js +19 -14
- package/dist/channels/slack/slack-api.d.ts +61 -2
- package/dist/channels/slack/slack-api.js +28 -5
- package/dist/channels/slack/slack.js +97 -52
- package/dist/channels/slack/welcomed.js +1 -1
- package/dist/channels/telegram/context-buffer.d.ts +6 -1
- package/dist/channels/telegram/context-buffer.js +19 -0
- package/dist/channels/telegram/invoke-turn.d.ts +8 -4
- package/dist/channels/telegram/invoke-turn.js +7 -7
- package/dist/channels/telegram/parse.d.ts +7 -2
- package/dist/channels/telegram/parse.js +7 -0
- package/dist/channels/telegram/preview.d.ts +2 -2
- package/dist/channels/telegram/register-webhook.d.ts +1 -0
- package/dist/channels/telegram/register-webhook.js +3 -2
- package/dist/channels/telegram/scaffold/channel.ts +27 -28
- package/dist/channels/telegram/scaffold/telegram-send.ts +61 -108
- package/dist/channels/telegram/shared-api.d.ts +34 -0
- package/dist/channels/telegram/shared-api.js +79 -0
- package/dist/channels/telegram/telegram-api.d.ts +15 -5
- package/dist/channels/telegram/telegram-api.js +10 -6
- package/dist/channels/telegram/telegram.js +27 -21
- package/dist/channels/telegram/turn-store.js +1 -1
- package/dist/channels/{kit/turn-queue.d.ts → turn-queue.d.ts} +2 -2
- package/dist/channels/{kit/turn-queue.js → turn-queue.js} +10 -10
- package/dist/cli/add-feishu.d.ts +42 -12
- package/dist/cli/add-feishu.js +177 -124
- package/dist/cli/add-slack.d.ts +8 -3
- package/dist/cli/add-slack.js +116 -64
- package/dist/cli/auth-view.d.ts +10 -3
- package/dist/cli/auth-view.js +8 -6
- package/dist/cli/box-login.d.ts +18 -7
- package/dist/cli/box-login.js +46 -12
- package/dist/cli/commands/add.d.ts +15 -4
- package/dist/cli/commands/add.js +253 -143
- package/dist/cli/commands/auth.d.ts +6 -0
- package/dist/cli/commands/auth.js +50 -0
- package/dist/cli/commands/content.d.ts +6 -0
- package/dist/cli/commands/content.js +45 -0
- package/dist/cli/commands/deploy/agentcore.js +50 -77
- package/dist/cli/commands/deploy/docker.js +38 -39
- package/dist/cli/commands/deploy/fly.js +21 -18
- package/dist/cli/commands/deploy/host-login.d.ts +26 -0
- package/dist/cli/commands/deploy/host-login.js +90 -0
- package/dist/cli/commands/deploy/railway.js +21 -26
- package/dist/cli/commands/deploy/shared.d.ts +45 -17
- package/dist/cli/commands/deploy/shared.js +34 -15
- package/dist/cli/commands/deploy.d.ts +0 -4
- package/dist/cli/commands/deploy.js +237 -50
- package/dist/cli/commands/destroy.js +8 -6
- package/dist/cli/commands/dev.d.ts +0 -2
- package/dist/cli/commands/dev.js +20 -19
- package/dist/cli/commands/env.d.ts +12 -0
- package/dist/cli/commands/env.js +191 -0
- package/dist/cli/commands/info.js +95 -156
- package/dist/cli/commands/init.d.ts +2 -2
- package/dist/cli/commands/init.js +35 -33
- package/dist/cli/commands/invoke.d.ts +6 -0
- package/dist/cli/commands/invoke.js +132 -16
- package/dist/cli/commands/login.d.ts +31 -2
- package/dist/cli/commands/login.js +416 -65
- package/dist/cli/commands/logout.d.ts +4 -0
- package/dist/cli/commands/logout.js +53 -0
- package/dist/cli/commands/logs.js +8 -6
- package/dist/cli/commands/models.d.ts +2 -1
- package/dist/cli/commands/models.js +39 -37
- package/dist/cli/commands/schedules.d.ts +21 -0
- package/dist/cli/commands/schedules.js +143 -0
- package/dist/cli/commands/start.d.ts +11 -10
- package/dist/cli/commands/start.js +35 -62
- package/dist/cli/content-view.d.ts +9 -0
- package/dist/cli/content-view.js +26 -0
- package/dist/cli/fail.d.ts +9 -12
- package/dist/cli/fail.js +17 -14
- package/dist/cli/invoke-stream.d.ts +12 -3
- package/dist/cli/invoke-stream.js +85 -23
- package/dist/cli/kernel.d.ts +9 -2
- package/dist/cli/kernel.js +15 -6
- package/dist/cli/login-relay.d.ts +6 -4
- package/dist/cli/login-relay.js +19 -7
- package/dist/cli/models-view.d.ts +5 -1
- package/dist/cli/models-view.js +1 -1
- package/dist/cli/person.d.ts +10 -0
- package/dist/cli/person.js +23 -0
- package/dist/cli/program.js +421 -203
- package/dist/cli/serve.d.ts +13 -63
- package/dist/cli/serve.js +31 -121
- package/dist/cli/shared.d.ts +21 -48
- package/dist/cli/shared.js +70 -89
- package/dist/cli/ticket.d.ts +136 -0
- package/dist/cli/ticket.js +476 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.js +2 -0
- package/dist/content/declare.d.ts +70 -0
- package/dist/content/declare.js +163 -0
- package/dist/content/file.d.ts +32 -0
- package/dist/content/file.js +119 -0
- package/dist/content/git.d.ts +41 -0
- package/dist/content/git.js +220 -0
- package/dist/content/mount.d.ts +2 -0
- package/dist/content/mount.js +15 -0
- package/dist/content/resolve.d.ts +52 -0
- package/dist/content/resolve.js +151 -0
- package/dist/content/source.d.ts +27 -0
- package/dist/content/source.js +53 -0
- package/dist/conversation-sessions.d.ts +26 -0
- package/dist/conversation-sessions.js +99 -0
- package/dist/declared-secrets.d.ts +19 -37
- package/dist/declared-secrets.js +16 -58
- package/dist/deploy/agentcore/destroy.d.ts +3 -3
- package/dist/deploy/agentcore/destroy.js +46 -28
- package/dist/deploy/agentcore/forwarder.js +105 -22
- package/dist/deploy/agentcore/logs.js +1 -1
- package/dist/deploy/agentcore/plan.d.ts +10 -24
- package/dist/deploy/agentcore/plan.js +31 -135
- package/dist/deploy/agentcore/run.d.ts +1 -1
- package/dist/deploy/agentcore/run.js +8 -5
- package/dist/deploy/agentcore/shell.d.ts +1 -1
- package/dist/deploy/agentcore/shell.js +5 -5
- package/dist/deploy/api.d.ts +34 -0
- package/dist/deploy/api.js +50 -0
- package/dist/deploy/box-shell.d.ts +6 -0
- package/dist/deploy/box-shell.js +7 -0
- package/dist/deploy/build-context.d.ts +7 -5
- package/dist/deploy/build-context.js +41 -35
- package/dist/deploy/channel-ingress.d.ts +6 -1
- package/dist/deploy/channel-ingress.js +18 -5
- package/dist/deploy/container.d.ts +22 -9
- package/dist/deploy/container.js +96 -55
- package/dist/deploy/docker/plan.d.ts +3 -2
- package/dist/deploy/docker/plan.js +13 -14
- package/dist/deploy/docker/run.d.ts +2 -2
- package/dist/deploy/docker/run.js +8 -4
- package/dist/deploy/fly/plan.d.ts +1 -1
- package/dist/deploy/fly/plan.js +12 -21
- package/dist/deploy/fly/run.d.ts +10 -6
- package/dist/deploy/fly/run.js +11 -6
- package/dist/deploy/hosts.d.ts +2 -1
- package/dist/deploy/hosts.js +2 -1
- package/dist/deploy/preflight.d.ts +21 -23
- package/dist/deploy/preflight.js +223 -202
- package/dist/deploy/railway/plan.d.ts +8 -6
- package/dist/deploy/railway/plan.js +15 -58
- package/dist/deploy/railway/run.d.ts +8 -3
- package/dist/deploy/railway/run.js +12 -8
- package/dist/deploy/residency.d.ts +5 -11
- package/dist/deploy/residency.js +0 -6
- package/dist/deploy/runner.d.ts +1 -1
- package/dist/deploy/runner.js +1 -1
- package/dist/deploy/secrets.d.ts +16 -2
- package/dist/deploy/secrets.js +33 -6
- package/dist/deploy/workspace.d.ts +11 -6
- package/dist/deploy/workspace.js +55 -38
- package/dist/dev-supervisor.d.ts +11 -2
- package/dist/dev-supervisor.js +52 -27
- package/dist/effect-port.d.ts +4 -4
- package/dist/effect-port.js +4 -4
- package/dist/env.d.ts +0 -13
- package/dist/env.js +1 -44
- package/dist/environment/apt.d.ts +4 -0
- package/dist/environment/apt.js +32 -0
- package/dist/environment/declare.d.ts +59 -0
- package/dist/environment/declare.js +210 -0
- package/dist/environment/mise.d.ts +51 -0
- package/dist/environment/mise.js +272 -0
- package/dist/feishu.d.ts +2 -2
- package/dist/feishu.js +2 -2
- package/dist/git.d.ts +13 -0
- package/dist/git.js +55 -0
- package/dist/harnesses/models/catalog.d.ts +20 -0
- package/dist/harnesses/models/catalog.js +254 -0
- package/dist/{engines/pi/auth.d.ts → harnesses/models/credentials.d.ts} +3 -3
- package/dist/{engines/pi/auth.js → harnesses/models/credentials.js} +3 -3
- package/dist/harnesses/models/environment.d.ts +48 -0
- package/dist/harnesses/models/environment.js +88 -0
- package/dist/harnesses/models/host.d.ts +30 -0
- package/dist/harnesses/models/host.js +97 -0
- package/dist/{engines/pi → harnesses/models}/login.d.ts +66 -70
- package/dist/harnesses/models/login.js +439 -0
- package/dist/harnesses/models/models.d.ts +84 -0
- package/dist/harnesses/models/models.js +197 -0
- package/dist/harnesses/pi-durable/agent.d.ts +42 -0
- package/dist/harnesses/pi-durable/agent.js +581 -0
- package/dist/harnesses/pi-durable/defaults.d.ts +28 -0
- package/dist/harnesses/pi-durable/defaults.js +26 -0
- package/dist/harnesses/pi-durable/define.d.ts +77 -0
- package/dist/harnesses/pi-durable/define.js +28 -0
- package/dist/harnesses/pi-durable/entries.d.ts +32 -0
- package/dist/harnesses/pi-durable/entries.js +126 -0
- package/dist/harnesses/pi-durable/events.d.ts +25 -0
- package/dist/harnesses/pi-durable/events.js +238 -0
- package/dist/harnesses/pi-durable/ids.d.ts +16 -0
- package/dist/harnesses/pi-durable/ids.js +55 -0
- package/dist/harnesses/pi-durable/messages.d.ts +41 -0
- package/dist/harnesses/pi-durable/messages.js +116 -0
- package/dist/harnesses/pi-durable/open.d.ts +95 -0
- package/dist/harnesses/pi-durable/open.js +330 -0
- package/dist/harnesses/pi-durable/reads.d.ts +30 -0
- package/dist/harnesses/pi-durable/reads.js +94 -0
- package/dist/harnesses/pi-durable/registry.d.ts +18 -0
- package/dist/harnesses/pi-durable/registry.js +56 -0
- package/dist/harnesses/pi-durable/release.d.ts +13 -0
- package/dist/harnesses/pi-durable/release.js +40 -0
- package/dist/harnesses/pi-durable/serve.d.ts +90 -0
- package/dist/harnesses/pi-durable/serve.js +186 -0
- package/dist/harnesses/pi-durable/sessions.d.ts +27 -0
- package/dist/harnesses/pi-durable/sessions.js +47 -0
- package/dist/harnesses/pi-durable/storage.d.ts +4 -0
- package/dist/harnesses/pi-durable/storage.js +49 -0
- package/dist/harnesses/pi-durable/stream.d.ts +20 -0
- package/dist/harnesses/pi-durable/stream.js +221 -0
- package/dist/harnesses/pi-durable/text.d.ts +30 -0
- package/dist/harnesses/pi-durable/text.js +292 -0
- package/dist/harnesses/pi-durable/wake.d.ts +11 -0
- package/dist/harnesses/pi-durable/wake.js +90 -0
- package/dist/http/client.d.ts +6 -0
- package/dist/http/client.js +256 -0
- package/dist/http/contract.d.ts +541 -0
- package/dist/http/contract.js +179 -0
- package/dist/http/server.d.ts +34 -0
- package/dist/http/server.js +194 -0
- package/dist/index.d.ts +19 -4
- package/dist/index.js +13 -5
- package/dist/lark.d.ts +2 -2
- package/dist/lark.js +2 -2
- package/dist/locked-file.d.ts +17 -0
- package/dist/{engines/pi/locked-file.js → locked-file.js} +16 -10
- package/dist/once.d.ts +6 -0
- package/dist/once.js +23 -0
- package/dist/paths.d.ts +36 -52
- package/dist/paths.js +66 -182
- package/dist/runtime.d.ts +25 -2
- package/dist/runtime.js +27 -0
- package/dist/scaffold/add-channel.d.ts +14 -27
- package/dist/scaffold/add-channel.js +82 -180
- package/dist/scaffold/init.d.ts +17 -18
- package/dist/scaffold/init.js +87 -99
- package/dist/scaffold/templates/SYSTEM.md +12 -0
- package/dist/scaffold/templates/env.example +4 -10
- package/dist/scaffold/templates/fastagent.config.ts +21 -33
- package/dist/scaffold/templates/gitignore +8 -1
- package/dist/scaffold/templates/skills/writing-great-skills/SKILL.md +1 -2
- package/dist/scaffold/templates.d.ts +9 -4
- package/dist/scaffold/templates.js +7 -5
- package/dist/scaffold/vendor-skill.d.ts +1 -4
- package/dist/scaffold/vendor-skill.js +5 -6
- package/dist/schedule/cron.d.ts +13 -0
- package/dist/schedule/cron.js +52 -0
- package/dist/schedule/eventbridge-cron.d.ts +17 -0
- package/dist/schedule/eventbridge-cron.js +88 -0
- package/dist/schedule/schedule.d.ts +23 -0
- package/dist/schedule/schedule.js +34 -0
- package/dist/schedule/scheduler.d.ts +34 -33
- package/dist/schedule/scheduler.js +251 -137
- package/dist/schedule/state.d.ts +4 -14
- package/dist/schedule/state.js +7 -7
- package/dist/schedule/wake-alarm.d.ts +22 -2
- package/dist/schedule/wake-alarm.js +66 -20
- package/dist/schedule/wakeups.d.ts +16 -15
- package/dist/schedule/wakeups.js +47 -45
- package/dist/service.d.ts +56 -169
- package/dist/service.js +91 -187
- package/dist/serving-command.d.ts +10 -0
- package/dist/serving-command.js +16 -0
- package/dist/sign-in-api.d.ts +147 -0
- package/dist/sign-in-api.js +9 -0
- package/dist/slack.d.ts +1 -1
- package/dist/slack.js +1 -1
- package/dist/{channels/kit/state.js → state-file.js} +6 -6
- package/dist/telegram.d.ts +1 -0
- package/dist/telegram.js +1 -0
- package/dist/tunnel.d.ts +3 -0
- package/dist/tunnel.js +14 -5
- package/dist/value-file.d.ts +40 -0
- package/dist/value-file.js +164 -0
- package/dist/version.d.ts +5 -0
- package/dist/version.js +14 -1
- package/package.json +18 -28
- package/dist/agent.d.ts +0 -106
- package/dist/agent.js +0 -21
- package/dist/channels/control.d.ts +0 -31
- package/dist/channels/control.js +0 -329
- package/dist/channels/define-channel.d.ts +0 -39
- package/dist/channels/define-channel.js +0 -9
- package/dist/channels/feishu/context-buffer.d.ts +0 -35
- package/dist/channels/feishu/context-buffer.js +0 -65
- package/dist/channels/feishu/scaffold/channel.websocket.ts +0 -31
- package/dist/channels/http.d.ts +0 -23
- package/dist/channels/http.js +0 -57
- package/dist/channels/lark/scaffold/channel.websocket.ts +0 -31
- package/dist/channels/slack/context-buffer.d.ts +0 -23
- package/dist/channels/slack/context-buffer.js +0 -37
- package/dist/channels/sse.d.ts +0 -4
- package/dist/channels/sse.js +0 -66
- package/dist/cli/commands/chat.d.ts +0 -3
- package/dist/cli/commands/chat.js +0 -14
- package/dist/cli/commands/routine-run.d.ts +0 -6
- package/dist/cli/commands/routine-run.js +0 -46
- package/dist/cli/commands/routine.d.ts +0 -25
- package/dist/cli/commands/routine.js +0 -122
- package/dist/cli/commands/tool.d.ts +0 -1
- package/dist/cli/commands/tool.js +0 -57
- package/dist/collect.d.ts +0 -63
- package/dist/collect.js +0 -90
- package/dist/core.d.ts +0 -13
- package/dist/core.js +0 -15
- package/dist/engines/pi/agent-models.d.ts +0 -83
- package/dist/engines/pi/agent-models.js +0 -120
- package/dist/engines/pi/agent-session-factory.d.ts +0 -121
- package/dist/engines/pi/agent-session-factory.js +0 -535
- package/dist/engines/pi/chat.d.ts +0 -3
- package/dist/engines/pi/chat.js +0 -8
- package/dist/engines/pi/config.d.ts +0 -71
- package/dist/engines/pi/config.js +0 -199
- package/dist/engines/pi/create.d.ts +0 -170
- package/dist/engines/pi/create.js +0 -343
- package/dist/engines/pi/definition.d.ts +0 -74
- package/dist/engines/pi/definition.js +0 -236
- package/dist/engines/pi/entry-images.d.ts +0 -14
- package/dist/engines/pi/entry-images.js +0 -23
- package/dist/engines/pi/invoke-session.d.ts +0 -18
- package/dist/engines/pi/invoke-session.js +0 -403
- package/dist/engines/pi/locked-file.d.ts +0 -9
- package/dist/engines/pi/login.js +0 -331
- package/dist/engines/pi/machine.d.ts +0 -53
- package/dist/engines/pi/machine.js +0 -137
- package/dist/engines/pi/models.d.ts +0 -200
- package/dist/engines/pi/models.js +0 -533
- package/dist/engines/pi/open.d.ts +0 -180
- package/dist/engines/pi/open.js +0 -270
- package/dist/engines/pi/openai-account-models.d.ts +0 -35
- package/dist/engines/pi/openai-account-models.js +0 -116
- package/dist/engines/pi/report.d.ts +0 -18
- package/dist/engines/pi/report.js +0 -59
- package/dist/engines/pi/retry-event.d.ts +0 -6
- package/dist/engines/pi/retry-event.js +0 -15
- package/dist/engines/pi/service.d.ts +0 -9
- package/dist/engines/pi/service.js +0 -14
- package/dist/engines/pi/session-builder.d.ts +0 -13
- package/dist/engines/pi/session-builder.js +0 -117
- package/dist/engines/pi/session-control.d.ts +0 -77
- package/dist/engines/pi/session-control.js +0 -908
- package/dist/engines/pi/session-effects.d.ts +0 -14
- package/dist/engines/pi/session-effects.js +0 -30
- package/dist/engines/pi/session-inheritance.d.ts +0 -21
- package/dist/engines/pi/session-inheritance.js +0 -204
- package/dist/engines/pi/session-markers.d.ts +0 -49
- package/dist/engines/pi/session-markers.js +0 -60
- package/dist/engines/pi/session-settings.d.ts +0 -67
- package/dist/engines/pi/session-settings.js +0 -119
- package/dist/engines/pi/session-store.d.ts +0 -69
- package/dist/engines/pi/session-store.js +0 -430
- package/dist/engines/pi/tool-context.d.ts +0 -45
- package/dist/engines/pi/tool-context.js +0 -31
- package/dist/engines/pi/tool.d.ts +0 -99
- package/dist/engines/pi/tool.js +0 -118
- package/dist/engines/pi/turn-kit.d.ts +0 -92
- package/dist/engines/pi/turn-kit.js +0 -288
- package/dist/engines/pi/wake-tool.d.ts +0 -9
- package/dist/engines/pi/wake-tool.js +0 -92
- package/dist/loader.d.ts +0 -41
- package/dist/loader.js +0 -116
- package/dist/node.d.ts +0 -3
- package/dist/node.js +0 -4
- package/dist/observe.d.ts +0 -6
- package/dist/observe.js +0 -47
- package/dist/pi.d.ts +0 -25
- package/dist/pi.js +0 -15
- package/dist/scaffold/templates/APPEND_SYSTEM.md +0 -12
- package/dist/scaffold/templates/tools/fetch-url.ts +0 -25
- package/dist/schedule/discover.d.ts +0 -17
- package/dist/schedule/discover.js +0 -61
- package/dist/schedule/routine.d.ts +0 -43
- package/dist/schedule/routine.js +0 -32
- package/dist/schedule/run.d.ts +0 -55
- package/dist/schedule/run.js +0 -146
- package/dist/secrets-gate.d.ts +0 -32
- package/dist/secrets-gate.js +0 -33
- package/dist/session-remote.d.ts +0 -47
- package/dist/session-remote.js +0 -460
- package/dist/session.d.ts +0 -466
- package/dist/session.js +0 -57
- /package/dist/{channels/kit/state.d.ts → state-file.d.ts} +0 -0
package/dist/channels/control.js
DELETED
|
@@ -1,329 +0,0 @@
|
|
|
1
|
-
import { INVALID_COMMAND_CODE, SESSIONS_UNAVAILABLE_CODE, UNSUPPORTED_CAPABILITY_CODE, UPDATE_FIELDS, } from "../session.js";
|
|
2
|
-
import { parseRouteKey, withoutBody } from "./serve.js";
|
|
3
|
-
import { log } from "../log.js";
|
|
4
|
-
import { readBodyCapped } from "./body.js";
|
|
5
|
-
import { MAX_BODY_BYTES } from "./http.js";
|
|
6
|
-
import { sseResponse } from "./sse.js";
|
|
7
|
-
import { text } from "./respond.js";
|
|
8
|
-
/** The prefix this plane OWNS: everything under it is the plane's to answer. */
|
|
9
|
-
export const CONTROL_PREFIX = "/control";
|
|
10
|
-
/** The one variable segment in this plane's paths: a percent-encoded session id. */
|
|
11
|
-
const SESSION_SEGMENT = "{session}";
|
|
12
|
-
/**
|
|
13
|
-
* What `.../image` may answer under the image's own type. `mimeType` is whatever the prompt's sender wrote, and served
|
|
14
|
-
* as-is a `text/html` or `image/svg+xml` "image" would run script on whatever origin fronts this plane.
|
|
15
|
-
*/
|
|
16
|
-
const RASTER_IMAGE_TYPES = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
|
|
17
|
-
const json = (value, status = 200) => new Response(`${JSON.stringify(value)}\n`, { status, headers: { "content-type": "application/json" } });
|
|
18
|
-
/** The plane as one mounted sub-application rather than routes sharing a prefix. */
|
|
19
|
-
function planeApp(routes) {
|
|
20
|
-
/** A route key's path split into segments, with `{session}` marked. */
|
|
21
|
-
const compiled = Object.entries(routes).map(([key, handler]) => {
|
|
22
|
-
const { method, path } = parseRouteKey(key);
|
|
23
|
-
return { method, path, segments: path.split("/"), handler };
|
|
24
|
-
});
|
|
25
|
-
const match = (path) => {
|
|
26
|
-
const segments = path.split("/");
|
|
27
|
-
const hits = [];
|
|
28
|
-
for (const route of compiled) {
|
|
29
|
-
if (route.segments.length !== segments.length)
|
|
30
|
-
continue;
|
|
31
|
-
let session;
|
|
32
|
-
let ok = true;
|
|
33
|
-
for (const [i, expected] of route.segments.entries()) {
|
|
34
|
-
const actual = segments[i];
|
|
35
|
-
if (expected === SESSION_SEGMENT) {
|
|
36
|
-
// The one place a path segment becomes a Caller id again.
|
|
37
|
-
if (actual === "") {
|
|
38
|
-
ok = false;
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
try {
|
|
42
|
-
session = decodeURIComponent(actual);
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
// `%zz` and friends: not an id any client could have produced, so this path matches nothing and falls
|
|
46
|
-
// through to the plane's own 404.
|
|
47
|
-
ok = false;
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
else if (expected !== actual) {
|
|
52
|
-
ok = false;
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
if (ok)
|
|
57
|
-
hits.push({ route, session });
|
|
58
|
-
}
|
|
59
|
-
return hits;
|
|
60
|
-
};
|
|
61
|
-
return async (req) => {
|
|
62
|
-
const url = new URL(req.url);
|
|
63
|
-
const path = url.pathname;
|
|
64
|
-
const hits = match(path);
|
|
65
|
-
const answer = async () => {
|
|
66
|
-
const hit = hits.find((h) => h.route.method === req.method) ??
|
|
67
|
-
(req.method === "HEAD" ? hits.find((h) => h.route.method === "GET") : undefined);
|
|
68
|
-
if (hit)
|
|
69
|
-
return await hit.route.handler(req, url, hit.session ?? "");
|
|
70
|
-
// 404 vs 405 as in the host router: a client reads 404 as "this serve predates the route".
|
|
71
|
-
if (hits.length > 0)
|
|
72
|
-
return text("method not allowed\n", 405);
|
|
73
|
-
return text("not found\n", 404);
|
|
74
|
-
};
|
|
75
|
-
let res;
|
|
76
|
-
try {
|
|
77
|
-
// HEAD carries no content, whichever branch answered — including this plane's own 404/405.
|
|
78
|
-
const answered = await answer();
|
|
79
|
-
res = req.method === "HEAD" ? withoutBody(answered) : answered;
|
|
80
|
-
}
|
|
81
|
-
catch (error) {
|
|
82
|
-
// The plane's own totality boundary: a rejecting handler (`commands()` on an unreadable definition) must still
|
|
83
|
-
// answer with the headers; the message stays internal.
|
|
84
|
-
log.error(`[control] ${req.method} ${path} failed: ${String(error)}`);
|
|
85
|
-
res = text("internal error\n", 500);
|
|
86
|
-
}
|
|
87
|
-
// CORS is NOT set here: the host router owns that verdict for every path it publishes, this prefix included
|
|
88
|
-
// (channels/serve.ts). A second writer of those headers is a second policy to keep in sync.
|
|
89
|
-
return res;
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
// ONE constant for every Prompt-bearing wire surface (imported from the invoke channel — the two caps cannot drift
|
|
93
|
-
// apart).
|
|
94
|
-
const ACTION_BODY_LIMIT = MAX_BODY_BYTES;
|
|
95
|
-
/**
|
|
96
|
-
* Parse-don't-validate at the wire: a remote client can send any JSON, and the hub's inner layers trust action shapes
|
|
97
|
-
* (a malformed `steer` would surface as an ENGINE failure misclassified as `run_command_failed`).
|
|
98
|
-
*/
|
|
99
|
-
function parseWireAction(raw) {
|
|
100
|
-
// COMPILE-TIME drift guard, variant level: this switch hand-mirrors the SessionAction union, and a new variant
|
|
101
|
-
// added in session.ts would otherwise compile clean while the wire answers it `invalid_command` — silently breaking
|
|
102
|
-
// local/remote isomorphism.
|
|
103
|
-
const _actionDriftGuard = {
|
|
104
|
-
steer: true,
|
|
105
|
-
follow_up: true,
|
|
106
|
-
abort: true,
|
|
107
|
-
compact: true,
|
|
108
|
-
};
|
|
109
|
-
void _actionDriftGuard;
|
|
110
|
-
if (typeof raw !== "object" || raw === null)
|
|
111
|
-
return undefined;
|
|
112
|
-
const c = raw;
|
|
113
|
-
const imageOk = (i) => typeof i === "object" &&
|
|
114
|
-
i !== null &&
|
|
115
|
-
typeof i.data === "string" &&
|
|
116
|
-
typeof i.mimeType === "string";
|
|
117
|
-
const promptOk = (p) => {
|
|
118
|
-
if (typeof p !== "object" || p === null)
|
|
119
|
-
return false;
|
|
120
|
-
if (typeof p.text !== "string")
|
|
121
|
-
return false;
|
|
122
|
-
const images = p.images;
|
|
123
|
-
// Element-level: `images: [42]` reaching the engine would resurface exactly the misclassified failure this parser
|
|
124
|
-
// exists to prevent (ImageRef shape from src/session.ts's Prompt).
|
|
125
|
-
return images === undefined || (Array.isArray(images) && images.every(imageOk));
|
|
126
|
-
};
|
|
127
|
-
// REBUILD, never pass raw through: "typed out" must be construction, not assertion — a passed-through object would
|
|
128
|
-
// carry arbitrary extra keys into the engine.
|
|
129
|
-
const rebuildPrompt = (p) => {
|
|
130
|
-
const images = p.images;
|
|
131
|
-
return {
|
|
132
|
-
text: p.text,
|
|
133
|
-
...(images ? { images: images.map((i) => ({ data: i.data, mimeType: i.mimeType })) } : {}),
|
|
134
|
-
};
|
|
135
|
-
};
|
|
136
|
-
// COMPILE-TIME drift guard: whitelist reconstruction silently strips any field it does not know.
|
|
137
|
-
const _promptDriftGuard = {};
|
|
138
|
-
void _promptDriftGuard;
|
|
139
|
-
// Same guard one level down: the image whitelist ({data, mimeType}) must break when ImageRef grows a field.
|
|
140
|
-
const _imageDriftGuard = {};
|
|
141
|
-
void _imageDriftGuard;
|
|
142
|
-
switch (c.type) {
|
|
143
|
-
case "steer":
|
|
144
|
-
case "follow_up":
|
|
145
|
-
return promptOk(c.prompt) ? { type: c.type, prompt: rebuildPrompt(c.prompt) } : undefined;
|
|
146
|
-
case "abort":
|
|
147
|
-
return { type: "abort" };
|
|
148
|
-
case "compact":
|
|
149
|
-
return c.instructions === undefined || typeof c.instructions === "string"
|
|
150
|
-
? { type: "compact", instructions: c.instructions }
|
|
151
|
-
: undefined;
|
|
152
|
-
default:
|
|
153
|
-
return undefined;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Parse a PATCH body into a session update — or into the REASON it is not one, because the two reasons are different
|
|
158
|
-
* answers to the client.
|
|
159
|
-
*/
|
|
160
|
-
function parseWireUpdate(raw) {
|
|
161
|
-
if (typeof raw !== "object" || raw === null) {
|
|
162
|
-
return { code: INVALID_COMMAND_CODE, message: "expected an object of session properties" };
|
|
163
|
-
}
|
|
164
|
-
const c = raw;
|
|
165
|
-
const unknown = Object.keys(c).filter((key) => !UPDATE_FIELDS.includes(key));
|
|
166
|
-
if (unknown.length > 0) {
|
|
167
|
-
return {
|
|
168
|
-
code: UNSUPPORTED_CAPABILITY_CODE,
|
|
169
|
-
message: `update field(s) ${unknown.join(", ")} — capabilities().updatable lists what this serve sets`,
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
const patch = {};
|
|
173
|
-
// The field list is the CONTRACT's (`UPDATE_FIELDS`), not a copy: a field added to SessionUpdate travels here
|
|
174
|
-
// without anyone remembering to, and one removed cannot linger.
|
|
175
|
-
for (const field of UPDATE_FIELDS) {
|
|
176
|
-
const value = c[field];
|
|
177
|
-
if (value === undefined)
|
|
178
|
-
continue;
|
|
179
|
-
if (typeof value !== "string") {
|
|
180
|
-
return { code: INVALID_COMMAND_CODE, message: `${field} must be a string` };
|
|
181
|
-
}
|
|
182
|
-
patch[field] = value;
|
|
183
|
-
}
|
|
184
|
-
return { patch };
|
|
185
|
-
}
|
|
186
|
-
/** Create the control plane as a mountable prefix owner. */
|
|
187
|
-
export function createControlPlane(control) {
|
|
188
|
-
return mountControlPlane(controlPlaneRoutes(control));
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Mount a plane route table as a {@link PrefixMount} — the plane owns a PREFIX, while a route table is a set of paths,
|
|
192
|
-
* at most one segment of which is a session id.
|
|
193
|
-
*/
|
|
194
|
-
export function mountControlPlane(routes) {
|
|
195
|
-
return { prefix: CONTROL_PREFIX, handler: planeApp(routes) };
|
|
196
|
-
}
|
|
197
|
-
export function controlPlaneRoutes(control) {
|
|
198
|
-
const epoch = crypto.randomUUID();
|
|
199
|
-
/**
|
|
200
|
-
* Read a JSON body under the shared cap.
|
|
201
|
-
*
|
|
202
|
-
* No content-type gate here: this plane only ever rides the host router, which applies it to every route that
|
|
203
|
-
* authenticates nobody — this whole prefix included (channels/serve.ts).
|
|
204
|
-
*/
|
|
205
|
-
const readJson = async (req) => {
|
|
206
|
-
const body = await readBodyCapped(req, ACTION_BODY_LIMIT);
|
|
207
|
-
// The 413 names the ceiling: the docs promise images on this plane, and an unexplained rejection would send a
|
|
208
|
-
// client author hunting everywhere but the cap.
|
|
209
|
-
if ("tooLarge" in body) {
|
|
210
|
-
return {
|
|
211
|
-
error: text(`body too large (limit ${MAX_BODY_BYTES >> 20} MiB — images count base64-inflated)\n`, 413),
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
// An empty body is an empty object: `POST …/actions` always carries one, but `PATCH` with nothing to set is a
|
|
215
|
-
// legal no-op and a client should not have to send `{}` to say so.
|
|
216
|
-
if (body.text.trim() === "")
|
|
217
|
-
return { value: {} };
|
|
218
|
-
try {
|
|
219
|
-
return { value: JSON.parse(body.text) };
|
|
220
|
-
}
|
|
221
|
-
catch {
|
|
222
|
-
return { error: text("invalid JSON\n", 400) };
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
return {
|
|
226
|
-
"GET /control/capabilities": () => json(control.capabilities()),
|
|
227
|
-
"GET /control/commands": async () => json(await control.commands()),
|
|
228
|
-
// The DEPLOYMENT's conversation list — and the one read that may fail.
|
|
229
|
-
"GET /control/sessions": async () => {
|
|
230
|
-
try {
|
|
231
|
-
return json(await control.sessions.list());
|
|
232
|
-
}
|
|
233
|
-
catch (error) {
|
|
234
|
-
// ONLY a store fault becomes the retryable code.
|
|
235
|
-
const code = error?.code;
|
|
236
|
-
if (typeof code !== "string" || !/^E[A-Z]+$/.test(code))
|
|
237
|
-
throw error;
|
|
238
|
-
// Logged as well as answered: the catch would otherwise be the one place a store fault is invisible on the
|
|
239
|
-
// server, since it preempts the boundary that does the logging.
|
|
240
|
-
log.error(`[control] GET /control/sessions failed: ${String(error)}`);
|
|
241
|
-
return json({ code: SESSIONS_UNAVAILABLE_CODE, message: String(error), retryable: true }, 503);
|
|
242
|
-
}
|
|
243
|
-
},
|
|
244
|
-
// PUT, because a fork is idempotent: this id, holding the history that was at `from`@`at`.
|
|
245
|
-
[`PUT /control/sessions/${SESSION_SEGMENT}`]: async (req, _url, session) => {
|
|
246
|
-
const read = await readJson(req);
|
|
247
|
-
if ("error" in read)
|
|
248
|
-
return read.error;
|
|
249
|
-
// `JSON.parse("null")` is null, and a body is whatever the client sent: reaching into it unguarded turns a
|
|
250
|
-
// malformed request into a 500 the client cannot act on.
|
|
251
|
-
const body = read.value;
|
|
252
|
-
if (typeof body?.from !== "string" || typeof body.at !== "string") {
|
|
253
|
-
return text("expected { from: string, at: string }\n", 400);
|
|
254
|
-
}
|
|
255
|
-
return json(await control.sessions.fork({ from: body.from, at: body.at, into: session }));
|
|
256
|
-
},
|
|
257
|
-
[`GET /control/sessions/${SESSION_SEGMENT}`]: async (_req, _url, session) => json(await control.sessions.get(session).state()),
|
|
258
|
-
// PATCH, because these are session PROPERTIES: last-wins, durable, applied by the next turn.
|
|
259
|
-
[`PATCH /control/sessions/${SESSION_SEGMENT}`]: async (req, _url, session) => {
|
|
260
|
-
const read = await readJson(req);
|
|
261
|
-
if ("error" in read)
|
|
262
|
-
return read.error;
|
|
263
|
-
const parsed = parseWireUpdate(read.value);
|
|
264
|
-
// A protocol-level answer carrying the SAME code the hub would have used.
|
|
265
|
-
if (!("patch" in parsed)) {
|
|
266
|
-
return json({ ok: false, error: { ...parsed, retryable: false } });
|
|
267
|
-
}
|
|
268
|
-
return json(await control.sessions.get(session).update(parsed.patch));
|
|
269
|
-
},
|
|
270
|
-
[`DELETE /control/sessions/${SESSION_SEGMENT}`]: async (_req, _url, session) => json(await control.sessions.get(session).delete()),
|
|
271
|
-
[`GET /control/sessions/${SESSION_SEGMENT}/entries`]: async (_req, url, session) => {
|
|
272
|
-
const since = url.searchParams.get("since") ?? undefined;
|
|
273
|
-
return json(await control.sessions.get(session).entries(since !== undefined ? { since } : undefined));
|
|
274
|
-
},
|
|
275
|
-
// Raw bytes, not JSON-wrapped base64: a client can hand the response straight to an <img>. The ref names a
|
|
276
|
-
// durable entry, so the answer never changes. `ref` rides the query because this router has one path variable.
|
|
277
|
-
[`GET /control/sessions/${SESSION_SEGMENT}/image`]: async (_req, url, session) => {
|
|
278
|
-
const ref = url.searchParams.get("ref");
|
|
279
|
-
if (ref === null)
|
|
280
|
-
return text("expected ?ref=, an images[].ref from entries()\n", 400);
|
|
281
|
-
const image = await control.sessions.get(session).image(ref);
|
|
282
|
-
// The local call RETURNS undefined, so this is a 2xx (§13); a 404 stays "this serve predates the route".
|
|
283
|
-
if (!image)
|
|
284
|
-
return new Response(null, { status: 204 });
|
|
285
|
-
return new Response(Buffer.from(image.data, "base64"), {
|
|
286
|
-
headers: {
|
|
287
|
-
"content-type": RASTER_IMAGE_TYPES.has(image.mimeType) ? image.mimeType : "application/octet-stream",
|
|
288
|
-
"x-content-type-options": "nosniff",
|
|
289
|
-
"cache-control": "private, max-age=31536000, immutable",
|
|
290
|
-
},
|
|
291
|
-
});
|
|
292
|
-
},
|
|
293
|
-
// The run actions.
|
|
294
|
-
[`POST /control/sessions/${SESSION_SEGMENT}/actions`]: async (req, _url, session) => {
|
|
295
|
-
const read = await readJson(req);
|
|
296
|
-
if ("error" in read)
|
|
297
|
-
return read.error;
|
|
298
|
-
const action = parseWireAction(read.value);
|
|
299
|
-
if (!action) {
|
|
300
|
-
return json({
|
|
301
|
-
ok: false,
|
|
302
|
-
error: { code: INVALID_COMMAND_CODE, message: "malformed action", retryable: false },
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
const s = control.sessions.get(session);
|
|
306
|
-
// The result rides HTTP 200 either way: `ok: false` is a protocol-level answer (rejected before acceptance),
|
|
307
|
-
// not a transport failure.
|
|
308
|
-
switch (action.type) {
|
|
309
|
-
case "steer":
|
|
310
|
-
return json(await s.steer(action.prompt));
|
|
311
|
-
case "follow_up":
|
|
312
|
-
return json(await s.followUp(action.prompt));
|
|
313
|
-
case "abort":
|
|
314
|
-
return json(await s.abort());
|
|
315
|
-
case "compact":
|
|
316
|
-
return json(await s.compact(action.instructions !== undefined ? { instructions: action.instructions } : {}));
|
|
317
|
-
}
|
|
318
|
-
},
|
|
319
|
-
[`GET /control/sessions/${SESSION_SEGMENT}/events`]: (_req, _url, session) => {
|
|
320
|
-
let seq = 0;
|
|
321
|
-
return sseResponse(control.sessions.get(session).events(), (event) => ({
|
|
322
|
-
sessionId: session,
|
|
323
|
-
epoch,
|
|
324
|
-
seq: seq++,
|
|
325
|
-
event,
|
|
326
|
-
}));
|
|
327
|
-
},
|
|
328
|
-
};
|
|
329
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `defineChannel` — a channel file's authoring surface, and the third member of the `defineX` family
|
|
3
|
-
* (with `defineTool` / `defineRoutine`). Its whole job is the secrets: a channel is the one code
|
|
4
|
-
* input that is ALL credentials (a bot token, a signing secret), and before this it read them from
|
|
5
|
-
* `process.env` at module scope, which meant a CUSTOM channel could not tell `deploy` what to carry —
|
|
6
|
-
* the deploy could only guess from a table of first-party names.
|
|
7
|
-
*
|
|
8
|
-
* The declaration attaches to the module WITHOUT adding a third module form to the Channel contract
|
|
9
|
-
* (channel.ts §7 fixes two: a function is a route channel, an object with `connect` is a long
|
|
10
|
-
* connection). The builder runs at import and returns one of those two; the declared names ride along
|
|
11
|
-
* as a property that the discovery reads and everything else ignores.
|
|
12
|
-
*
|
|
13
|
-
* Values are read at import, so a rotated credential needs a restart — the same lifetime an adapter
|
|
14
|
-
* configured with a literal already has, and the reason there is no per-request accessor here.
|
|
15
|
-
*
|
|
16
|
-
* KNOWN GAP: every declared name is REQUIRED (the gate refuses an empty value), so an
|
|
17
|
-
* OPTIONAL credential has no expression here — declare it and an agent that does not use it cannot
|
|
18
|
-
* start; leave it out and `deploy` does not carry it. First-party channels have the third answer in
|
|
19
|
-
* the scaffold table (`ChannelEnv.required`), which is why feishu/lark still read their optional
|
|
20
|
-
* `*_ENCRYPT_KEY` from the environment. Closing it means a second entry shape here
|
|
21
|
-
* (`{ name, required: false }`) carried through `DeclaredSecret`, `missingSecrets` and the deploy
|
|
22
|
-
* runbook's required flag — a contract change, not a local one.
|
|
23
|
-
*/
|
|
24
|
-
import type { ChannelModule, LongConnectionChannelModule } from "../channel.ts";
|
|
25
|
-
/** A channel module carrying what it declared it needs. Read by discovery; ignored by the server. */
|
|
26
|
-
type DeclaringChannelModule<M> = M & {
|
|
27
|
-
secrets?: readonly string[];
|
|
28
|
-
};
|
|
29
|
-
export interface DefineChannelOptions<S extends readonly string[], M> {
|
|
30
|
-
/**
|
|
31
|
-
* Env vars this channel needs (`["TELEGRAM_BOT_TOKEN"]`), typed into `channel`. `deploy` carries
|
|
32
|
-
* them to the host and `dev`/`start` refuse to serve while one is unset, naming this file.
|
|
33
|
-
*/
|
|
34
|
-
secrets?: S;
|
|
35
|
-
/** Build the channel from those values — usually one call to an adapter (`telegramChannel({...})`). */
|
|
36
|
-
channel: (secrets: Record<S[number], string>) => M;
|
|
37
|
-
}
|
|
38
|
-
export declare function defineChannel<const S extends readonly string[] = readonly [], M extends ChannelModule | LongConnectionChannelModule = ChannelModule>(options: DefineChannelOptions<S, M>): DeclaringChannelModule<M>;
|
|
39
|
-
export {};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { secretValues } from "../declared-secrets.js";
|
|
2
|
-
// `S` defaults to the EMPTY tuple for the same reason as `defineTool`: a channel that declares
|
|
3
|
-
// nothing must not type-check `secrets.ANYTHING`.
|
|
4
|
-
export function defineChannel(options) {
|
|
5
|
-
const built = options.channel(secretValues(options.secrets));
|
|
6
|
-
// Object.assign on a FUNCTION module keeps it a function (the route-channel form); on the
|
|
7
|
-
// long-connection object it adds one field. Either way the shape the server sees is unchanged.
|
|
8
|
-
return Object.assign(built, options.secrets ? { secrets: options.secrets } : {});
|
|
9
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/** Feishu/Lark's half of the shared context buffer (mechanics + consume protocol: ../kit/context-buffer.ts). */
|
|
2
|
-
import { type ContextBuffer } from "../kit/context-buffer.ts";
|
|
3
|
-
import type { NormalizedFeishuMessage } from "./model.ts";
|
|
4
|
-
export interface FeishuBufferedResource {
|
|
5
|
-
messageId: string;
|
|
6
|
-
key: string;
|
|
7
|
-
name?: string;
|
|
8
|
-
}
|
|
9
|
-
export interface FeishuBufferEntry {
|
|
10
|
-
sender: string;
|
|
11
|
-
body: string;
|
|
12
|
-
messageId: string;
|
|
13
|
-
replyTo?: string;
|
|
14
|
-
files?: FeishuBufferedResource[];
|
|
15
|
-
images?: FeishuBufferedResource[];
|
|
16
|
-
}
|
|
17
|
-
/** A background resource carried into a later turn, with attribution for its prompt manifest. */
|
|
18
|
-
export interface FeishuBufferedRef extends FeishuBufferedResource {
|
|
19
|
-
from: string;
|
|
20
|
-
}
|
|
21
|
-
/** The place a message belongs to: the main chat, or a thread within it. */
|
|
22
|
-
export declare function feishuBufferPlaceKey(conversation: Pick<NormalizedFeishuMessage["conversation"], "chatId" | "threadId">): string;
|
|
23
|
-
/** One-line, bounded background text. */
|
|
24
|
-
export declare function feishuBufferText(text: string): string;
|
|
25
|
-
/** Select the most recent background resources, excluding resources already primary on this turn. */
|
|
26
|
-
export declare function collectFeishuBufferedAttachments(consumed: FeishuBufferEntry[], primary: {
|
|
27
|
-
files: FeishuBufferedResource[];
|
|
28
|
-
images: FeishuBufferedResource[];
|
|
29
|
-
}): {
|
|
30
|
-
files: FeishuBufferedRef[];
|
|
31
|
-
images: FeishuBufferedRef[];
|
|
32
|
-
skipped: number;
|
|
33
|
-
};
|
|
34
|
-
export type FeishuContextBuffer = ContextBuffer<FeishuBufferEntry>;
|
|
35
|
-
export declare function createFeishuContextBuffer(path: string, label: string): FeishuContextBuffer;
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/** Feishu/Lark's half of the shared context buffer (mechanics + consume protocol: ../kit/context-buffer.ts). */
|
|
2
|
-
import { capBufferedRefs, BUFFER_LINE_MAX_CHARS, createContextBuffer as createGenericContextBuffer, } from "../kit/context-buffer.js";
|
|
3
|
-
import { truncateCodePointPrefix } from "../kit/text.js";
|
|
4
|
-
function bufferLine(entry) {
|
|
5
|
-
const meta = [`msg ${entry.messageId}`, entry.replyTo ? `reply to msg ${entry.replyTo}` : undefined]
|
|
6
|
-
.filter(Boolean)
|
|
7
|
-
.join(", ");
|
|
8
|
-
return `${entry.sender} (${meta}): ${entry.body}`;
|
|
9
|
-
}
|
|
10
|
-
/** The place a message belongs to: the main chat, or a thread within it. */
|
|
11
|
-
export function feishuBufferPlaceKey(conversation) {
|
|
12
|
-
return conversation.threadId ? `${conversation.chatId}:thread:${conversation.threadId}` : conversation.chatId;
|
|
13
|
-
}
|
|
14
|
-
/** One-line, bounded background text. */
|
|
15
|
-
export function feishuBufferText(text) {
|
|
16
|
-
return truncateCodePointPrefix(text.replace(/\s+/g, " ").trim(), BUFFER_LINE_MAX_CHARS);
|
|
17
|
-
}
|
|
18
|
-
function resourceIdentity(resource) {
|
|
19
|
-
return `${resource.messageId}\u0000${resource.key}`;
|
|
20
|
-
}
|
|
21
|
-
/** Select the most recent background resources, excluding resources already primary on this turn. */
|
|
22
|
-
export function collectFeishuBufferedAttachments(consumed, primary) {
|
|
23
|
-
const refs = (pick, primaryRefs) => {
|
|
24
|
-
const excluded = new Set(primaryRefs.map(resourceIdentity));
|
|
25
|
-
const seen = new Set();
|
|
26
|
-
const out = [];
|
|
27
|
-
for (const entry of consumed) {
|
|
28
|
-
for (const resource of pick(entry) ?? []) {
|
|
29
|
-
const identity = resourceIdentity(resource);
|
|
30
|
-
if (excluded.has(identity) || seen.has(identity))
|
|
31
|
-
continue;
|
|
32
|
-
seen.add(identity);
|
|
33
|
-
out.push({ ...resource, from: entry.sender });
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return out;
|
|
37
|
-
};
|
|
38
|
-
const files = capBufferedRefs(refs((entry) => entry.files, primary.files));
|
|
39
|
-
const images = capBufferedRefs(refs((entry) => entry.images, primary.images));
|
|
40
|
-
return { files: files.kept, images: images.kept, skipped: files.skipped + images.skipped };
|
|
41
|
-
}
|
|
42
|
-
function isResource(value) {
|
|
43
|
-
const resource = value;
|
|
44
|
-
return (typeof resource?.messageId === "string" &&
|
|
45
|
-
typeof resource.key === "string" &&
|
|
46
|
-
(resource.name === undefined || typeof resource.name === "string"));
|
|
47
|
-
}
|
|
48
|
-
function isEntry(value) {
|
|
49
|
-
const entry = value;
|
|
50
|
-
const resources = (candidate) => candidate === undefined || (Array.isArray(candidate) && candidate.every(isResource));
|
|
51
|
-
return (typeof entry?.sender === "string" &&
|
|
52
|
-
typeof entry.body === "string" &&
|
|
53
|
-
typeof entry.messageId === "string" &&
|
|
54
|
-
(entry.replyTo === undefined || typeof entry.replyTo === "string") &&
|
|
55
|
-
resources(entry.files) &&
|
|
56
|
-
resources(entry.images));
|
|
57
|
-
}
|
|
58
|
-
export function createFeishuContextBuffer(path, label) {
|
|
59
|
-
return createGenericContextBuffer({
|
|
60
|
-
path,
|
|
61
|
-
label,
|
|
62
|
-
isEntry,
|
|
63
|
-
line: bufferLine,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { feishuWebSocketChannel } from "@fastagent-sh/fastagent/feishu";
|
|
2
|
-
import { defineChannel } from "@fastagent-sh/fastagent";
|
|
3
|
-
|
|
4
|
-
// Feishu WebSocket long connection: the process connects OUT to the platform, so no public URL,
|
|
5
|
-
// Verification Token, Encrypt Key, or --tunnel is needed. In Events & Callbacks choose long
|
|
6
|
-
// connection, subscribe im.message.receive_v1, then publish the app version. Keep one process
|
|
7
|
-
// running in production: scale-to-zero/App Sleeping would disconnect ingress.
|
|
8
|
-
export default defineChannel({
|
|
9
|
-
// The env vars this channel needs. fastagent carries them to a deployed box and refuses to serve
|
|
10
|
-
// while one is unset — a bare process.env read gets neither guarantee.
|
|
11
|
-
secrets: ["FEISHU_APP_ID", "FEISHU_APP_SECRET"],
|
|
12
|
-
channel: (secrets) =>
|
|
13
|
-
feishuWebSocketChannel({
|
|
14
|
-
appId: secrets.FEISHU_APP_ID,
|
|
15
|
-
appSecret: secrets.FEISHU_APP_SECRET,
|
|
16
|
-
// No session modes: a chat is one session and a thread is another, and where the answer goes follows
|
|
17
|
-
// from that (docs/design/participant-model.md).
|
|
18
|
-
// Dev/personal bot: surface raw errors to the chat so you (and your AI agent) can act on them. The
|
|
19
|
-
// chat is customer-facing by default — for a public bot, drop this or return a neutral string;
|
|
20
|
-
// full details always go to the server log regardless.
|
|
21
|
-
onError: (failed) => `⚠️ ${failed.details}`,
|
|
22
|
-
// The channel owns transport + format (markdown card) + attachments (image→vision, file→disk) +
|
|
23
|
-
// the live streaming preview. `route` (POLICY) is OPTIONAL — omitted, it uses defaultFeishuRoute:
|
|
24
|
-
// p2p chats always answer; groups answer on @this-bot, plus bare messages in a thread where the
|
|
25
|
-
// Agent takes part and exactly ONE human does. Other human group/thread discussion buffers until
|
|
26
|
-
// that place's next answered turn; @other-only messages buffer rather than triggering the Agent.
|
|
27
|
-
// Override to customise explicit routing, reusing the export:
|
|
28
|
-
// route: (e) => defaultFeishuRoute(e, { botOpenId: "ou_xxx" }) && { session: `user:${e.sender?.sender_id?.open_id}` },
|
|
29
|
-
// route: (e) => defaultFeishuRoute(e, { botOpenId: "ou_xxx" }) && { text: `${feishuEnvelope(e)}\n[extra]` },
|
|
30
|
-
}),
|
|
31
|
-
});
|
package/dist/channels/http.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTTP/SSE channel: fan one invoke stream out to Server-Sent Events. The web stream primitives supply cancellation
|
|
3
|
-
* natively (consumer disconnect → `cancel()` → `iterator.return()` → invoke cancellation, SPEC MUST 3), backpressure,
|
|
4
|
-
* and the body cap.
|
|
5
|
-
*/
|
|
6
|
-
import type { Agent } from "../agent.ts";
|
|
7
|
-
/**
|
|
8
|
-
* Request body cap (1 MiB) — shared by every Prompt-bearing wire surface (the control plane's dispatch imports it), so
|
|
9
|
-
* the two caps cannot drift apart.
|
|
10
|
-
*/
|
|
11
|
-
export declare const MAX_BODY_BYTES: number;
|
|
12
|
-
/**
|
|
13
|
-
* A valid example request body for the invoke handler — lives HERE, next to the shape check it must satisfy, so the
|
|
14
|
-
* CLI's "try it" hint can't drift from the protocol.
|
|
15
|
-
*/
|
|
16
|
-
export declare const INVOKE_EXAMPLE_BODY = "{\"session\":\"dev\",\"text\":\"hello\"}";
|
|
17
|
-
/**
|
|
18
|
-
* Fetch-shaped invoke handler.
|
|
19
|
-
*
|
|
20
|
-
* No CORS here: who may call this from a browser is decided once, before dispatch, in `channels/serve.ts`'s router
|
|
21
|
-
* — which is also the only layer that can answer the `OPTIONS` preflight, since this route registers only `POST`.
|
|
22
|
-
*/
|
|
23
|
-
export declare function createInvokeHandler(agent: Agent): (req: Request) => Promise<Response>;
|
package/dist/channels/http.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { readBodyCapped, refuseNonJsonBody } from "./body.js";
|
|
2
|
-
import { text } from "./respond.js";
|
|
3
|
-
import { sseResponse } from "./sse.js";
|
|
4
|
-
/**
|
|
5
|
-
* Request body cap (1 MiB) — shared by every Prompt-bearing wire surface (the control plane's dispatch imports it), so
|
|
6
|
-
* the two caps cannot drift apart.
|
|
7
|
-
*/
|
|
8
|
-
export const MAX_BODY_BYTES = 1 << 20;
|
|
9
|
-
/**
|
|
10
|
-
* A valid example request body for the invoke handler — lives HERE, next to the shape check it must satisfy, so the
|
|
11
|
-
* CLI's "try it" hint can't drift from the protocol.
|
|
12
|
-
*/
|
|
13
|
-
export const INVOKE_EXAMPLE_BODY = '{"session":"dev","text":"hello"}';
|
|
14
|
-
/**
|
|
15
|
-
* Fetch-shaped invoke handler.
|
|
16
|
-
*
|
|
17
|
-
* No CORS here: who may call this from a browser is decided once, before dispatch, in `channels/serve.ts`'s router
|
|
18
|
-
* — which is also the only layer that can answer the `OPTIONS` preflight, since this route registers only `POST`.
|
|
19
|
-
*/
|
|
20
|
-
export function createInvokeHandler(agent) {
|
|
21
|
-
return async (req) => {
|
|
22
|
-
if (req.method !== "POST")
|
|
23
|
-
return text("POST only\n", 405);
|
|
24
|
-
// Also applied by the host router over every unguarded route — kept HERE too because this handler is a
|
|
25
|
-
// PUBLIC standalone artifact (docs/overview.md mounts it as a Next.js route), and a handler you can mount
|
|
26
|
-
// anywhere has to be safe anywhere. The router's copy is what stops a route added later from forgetting.
|
|
27
|
-
const wrongType = refuseNonJsonBody(req);
|
|
28
|
-
if (wrongType)
|
|
29
|
-
return wrongType;
|
|
30
|
-
const body = await readBodyCapped(req, MAX_BODY_BYTES);
|
|
31
|
-
if ("tooLarge" in body)
|
|
32
|
-
return text("body too large\n", 413);
|
|
33
|
-
let payload;
|
|
34
|
-
try {
|
|
35
|
-
payload = JSON.parse(body.text);
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return text("invalid json\n", 400);
|
|
39
|
-
}
|
|
40
|
-
const { session, text: promptText, parentSession, branchHints, } = (payload ?? {});
|
|
41
|
-
if (typeof session !== "string" || typeof promptText !== "string") {
|
|
42
|
-
return text('need { "session": string, "text": string }\n', 400);
|
|
43
|
-
}
|
|
44
|
-
// INVOKE_EXAMPLE_BODY must keep satisfying this request shape.
|
|
45
|
-
if (parentSession !== undefined && typeof parentSession !== "string") {
|
|
46
|
-
return text('"parentSession" must be a string\n', 400);
|
|
47
|
-
}
|
|
48
|
-
if (branchHints !== undefined && !(Array.isArray(branchHints) && branchHints.every((h) => typeof h === "string"))) {
|
|
49
|
-
return text('"branchHints" must be an array of strings\n', 400);
|
|
50
|
-
}
|
|
51
|
-
return sseResponse(agent.invoke({
|
|
52
|
-
session,
|
|
53
|
-
...(parentSession !== undefined ? { parentSession } : {}),
|
|
54
|
-
...(branchHints !== undefined ? { branchHints } : {}),
|
|
55
|
-
}, { text: promptText }));
|
|
56
|
-
};
|
|
57
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { larkWebSocketChannel } from "@fastagent-sh/fastagent/lark";
|
|
2
|
-
import { defineChannel } from "@fastagent-sh/fastagent";
|
|
3
|
-
|
|
4
|
-
// Lark WebSocket long connection: the process connects OUT to the platform, so no public URL,
|
|
5
|
-
// Verification Token, Encrypt Key, or --tunnel is needed. In Events & Callbacks choose long
|
|
6
|
-
// connection, subscribe im.message.receive_v1, then publish the app version. Keep one process
|
|
7
|
-
// running in production: scale-to-zero/App Sleeping would disconnect ingress.
|
|
8
|
-
export default defineChannel({
|
|
9
|
-
// The env vars this channel needs. fastagent carries them to a deployed box and refuses to serve
|
|
10
|
-
// while one is unset — a bare process.env read gets neither guarantee.
|
|
11
|
-
secrets: ["LARK_APP_ID", "LARK_APP_SECRET"],
|
|
12
|
-
channel: (secrets) =>
|
|
13
|
-
larkWebSocketChannel({
|
|
14
|
-
appId: secrets.LARK_APP_ID,
|
|
15
|
-
appSecret: secrets.LARK_APP_SECRET,
|
|
16
|
-
// No session modes: a chat is one session and a thread is another, and where the answer goes follows
|
|
17
|
-
// from that (docs/design/participant-model.md).
|
|
18
|
-
// Dev/personal bot: surface raw errors to the chat so you (and your AI agent) can act on them. The
|
|
19
|
-
// chat is customer-facing by default — for a public bot, drop this or return a neutral string;
|
|
20
|
-
// full details always go to the server log regardless.
|
|
21
|
-
onError: (failed) => `⚠️ ${failed.details}`,
|
|
22
|
-
// The channel owns transport + format (markdown card) + attachments (image→vision, file→disk) +
|
|
23
|
-
// the live streaming preview. `route` (POLICY) is OPTIONAL — omitted, it uses defaultLarkRoute:
|
|
24
|
-
// p2p chats always answer; groups answer on @this-bot, plus bare messages in a thread where the
|
|
25
|
-
// Agent takes part and exactly ONE human does. Other human group/thread discussion buffers until
|
|
26
|
-
// that place's next answered turn; @other-only messages buffer rather than triggering the Agent.
|
|
27
|
-
// Override to customise explicit routing, reusing the export:
|
|
28
|
-
// route: (e) => defaultLarkRoute(e, { botOpenId: "ou_xxx" }) && { session: `user:${e.sender?.sender_id?.open_id}` },
|
|
29
|
-
// route: (e) => defaultLarkRoute(e, { botOpenId: "ou_xxx" }) && { text: `${larkEnvelope(e)}\n[extra]` },
|
|
30
|
-
}),
|
|
31
|
-
});
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slack's half of the shared context buffer (mechanics + consume protocol: ../kit/context-buffer.ts): the entry shape,
|
|
3
|
-
* its fold-line rendering, and buffered-file selection.
|
|
4
|
-
*/
|
|
5
|
-
import { type ContextBuffer } from "../kit/context-buffer.ts";
|
|
6
|
-
export interface SlackBufferEntry {
|
|
7
|
-
sender: string;
|
|
8
|
-
body: string;
|
|
9
|
-
messageId: string;
|
|
10
|
-
replyTo?: string;
|
|
11
|
-
fileIds?: string[];
|
|
12
|
-
}
|
|
13
|
-
export interface SlackBufferedFileRef {
|
|
14
|
-
id: string;
|
|
15
|
-
from: string;
|
|
16
|
-
messageId: string;
|
|
17
|
-
}
|
|
18
|
-
export declare function collectSlackBufferedFiles(consumed: SlackBufferEntry[], primaryIds: Set<string>): {
|
|
19
|
-
files: SlackBufferedFileRef[];
|
|
20
|
-
skipped: number;
|
|
21
|
-
};
|
|
22
|
-
export type SlackContextBuffer = ContextBuffer<SlackBufferEntry>;
|
|
23
|
-
export declare function createSlackContextBuffer(path: string, label: string): SlackContextBuffer;
|