@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/service.js
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
/** The product, as one call: an agent
|
|
1
|
+
/** The product, as one call: an opened agent becomes a live service, its channels, schedules and wake-ups. */
|
|
2
2
|
import * as Cause from "effect/Cause";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
4
|
import * as Exit from "effect/Exit";
|
|
5
5
|
import * as Fiber from "effect/Fiber";
|
|
6
6
|
import * as Scope from "effect/Scope";
|
|
7
|
-
import {
|
|
8
|
-
import { createInvokeHandler } from "./channels/http.js";
|
|
7
|
+
import { mountChannels } from "./channels/discover.js";
|
|
9
8
|
import { text } from "./channels/respond.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
9
|
+
import { parseRouteKey, router } from "./channels/router.js";
|
|
10
|
+
import { serveHandler, totalFetch } from "./channels/serve.js";
|
|
11
|
+
import { portCleanup } from "./effect-port.js";
|
|
12
|
+
import { API_PREFIX } from "./http/contract.js";
|
|
13
|
+
import { apiHandler, isApiPath } from "./http/server.js";
|
|
15
14
|
import { log } from "./log.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
15
|
+
import { once } from "./once.js";
|
|
16
|
+
import { createScheduler } from "./schedule/scheduler.js";
|
|
18
17
|
/** Default wait for a channel's `closed` before reporting it stuck. */
|
|
19
18
|
const CLOSE_DEADLINE_MS = 5_000;
|
|
20
19
|
/** One deadline for all connections; a failed close must not hide a sibling that is still running. */
|
|
@@ -42,98 +41,23 @@ function closeWithin(runs, names, deadlineMs) {
|
|
|
42
41
|
}
|
|
43
42
|
/** The port a serve binds when neither a flag, `PORT` (start only) nor `http.port` names one. */
|
|
44
43
|
export const DEFAULT_HTTP_PORT = 8787;
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* What an anonymous caller of a port can do, worst first — the ONE wording the startup report and deploy's pre-flight
|
|
55
|
-
* both print, each from its own facts (what mounted vs what will mount).
|
|
56
|
-
*/
|
|
57
|
-
export function describeAnonymousSurface(open) {
|
|
58
|
-
return [
|
|
59
|
-
...(open.invoke ? ["POST /invoke (run a turn with this agent's tools)"] : []),
|
|
60
|
-
...(open.run ? ["POST /run (run any routine this agent declares; GET /routines lists them)"] : []),
|
|
61
|
-
...(open.controlPrefix ? [`${open.controlPrefix}/* (read, steer or delete any session)`] : []),
|
|
62
|
-
];
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* The surface this deployment serves: the DATA plane (`POST /invoke`), `GET /health`, and the discovered channels.
|
|
66
|
-
*
|
|
67
|
-
* `/invoke` is the framework's interface, so it is served whatever channels a definition declares (unless
|
|
68
|
-
* `http.invoke: false`). It is RESERVED for the same reason `/control/*` is: a channel taking that path would silently replace the one route every client,
|
|
69
|
-
* every doc and the startup line all name. `/health` stays overridable — a probe is the deployment's to shape.
|
|
70
|
-
*/
|
|
71
|
-
export async function routesFor(agentDir, agent, stateRoot, control,
|
|
72
|
-
/**
|
|
73
|
-
* `http.invoke: false` withholds the data plane. Two callers, two reasons: the AgentCore adapter serves the
|
|
74
|
-
* Runtime's `/invocations` contract instead, and an author sets it to leave the channels' signature checks as the
|
|
75
|
-
* only way into a public port.
|
|
76
|
-
*
|
|
77
|
-
* `routines` mounts `POST /run` and `GET /routines` (per {@link shouldServeRun}). Passed in rather than loaded here
|
|
78
|
-
* so the routes and the resident clock cannot disagree about which routines exist (`loadServingRoutines`).
|
|
79
|
-
*/
|
|
80
|
-
options = {}) {
|
|
81
|
-
const { routes, longConnections, routeChannels, collisions, failures } = await loadChannels(agentDir, {
|
|
82
|
-
agent,
|
|
83
|
-
stateRoot,
|
|
84
|
-
control,
|
|
85
|
-
});
|
|
86
|
-
for (const c of collisions) {
|
|
87
|
-
log.warn(`[fastagent] channel route "${c.route}" (${c.source}) collides with an earlier channel — not mounted`);
|
|
88
|
-
}
|
|
89
|
-
refuseBrokenDeclarations(failures);
|
|
90
|
-
if (collisions.length > 0) {
|
|
91
|
-
throw new Error(`${collisions.length} channel route collision(s) — two channels cannot serve one route`);
|
|
44
|
+
/** Mount the channels and the health check. */
|
|
45
|
+
export function routesFor(agent, stateRoot, channels) {
|
|
46
|
+
const { routes, longConnections, routeChannels } = mountChannels(channels, agent, stateRoot);
|
|
47
|
+
for (const key of Object.keys(routes)) {
|
|
48
|
+
if (isApiPath(parseRouteKey(key).path)) {
|
|
49
|
+
throw new Error(`route "${key}" is under ${API_PREFIX}, which the Agent API serves — move it`);
|
|
50
|
+
}
|
|
92
51
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Which channel key already serves this path for the method a built-in would answer — the CHANNEL's spelling, not
|
|
95
|
-
* ours. A channel may write the method-less `"/invoke"`, and an error naming `"POST /invoke"` sends its author
|
|
96
|
-
* grepping their own file for a string that is not in it.
|
|
97
|
-
*/
|
|
98
|
-
const covered = (path, method) => Object.keys(routes).find((key) => {
|
|
99
|
-
const entry = parseRouteKey(key);
|
|
100
|
-
return entry.path === path && (entry.method === undefined || entry.method === method);
|
|
101
|
-
});
|
|
102
52
|
let ready = longConnections.length === 0;
|
|
103
53
|
const health = () => (ready ? text("ok\n", 200) : text("starting\n", 503));
|
|
104
|
-
|
|
105
|
-
// with no `/invoke` of ours on that surface there is nothing to reserve, which is why the refusal is in here.
|
|
106
|
-
const unverified = { ...(covered("/health", "GET") ? {} : { "GET /health": health }) };
|
|
107
|
-
if (options.http?.invoke !== false)
|
|
108
|
-
unverified["POST /invoke"] = createInvokeHandler(agent);
|
|
109
|
-
// `POST /run` exists only where there is something to run, and `GET /routines` exactly where that route does:
|
|
110
|
-
// it is the catalogue OF that route, so listing names nobody can use would be a catalogue of nothing. Both ride
|
|
111
|
-
// this table for the reason the table exists: they authenticate nobody, so they inherit the JSON body gate, the
|
|
112
|
-
// cross-origin policy, the reserved path and the startup report's account of what is open.
|
|
113
|
-
if (shouldServeRun(options.http)) {
|
|
114
|
-
const routines = options.routines ?? [];
|
|
115
|
-
const run = createRunHandler({ agent, routines });
|
|
116
|
-
if (run)
|
|
117
|
-
unverified["POST /run"] = run;
|
|
118
|
-
const list = createRoutineListHandler({ routines });
|
|
119
|
-
if (list)
|
|
120
|
-
unverified["GET /routines"] = list;
|
|
121
|
-
}
|
|
122
|
-
// ONE rule over the whole table, so the next route we add is reserved by existing here rather than by someone
|
|
123
|
-
// remembering to write a second check for it. `/health` is exempt by construction: it is only in `ours` when no
|
|
124
|
-
// channel already serves it, because a probe is the deployment's to shape.
|
|
125
|
-
const taken = Object.keys(unverified).flatMap((key) => {
|
|
54
|
+
const probed = Object.keys(routes).some((key) => {
|
|
126
55
|
const entry = parseRouteKey(key);
|
|
127
|
-
|
|
128
|
-
return channelKey === undefined ? [] : [{ channelKey, key }];
|
|
56
|
+
return entry.path === "/health" && (entry.method === undefined || entry.method === "GET");
|
|
129
57
|
});
|
|
130
|
-
if (taken.length > 0) {
|
|
131
|
-
throw new Error(`channel route(s) ${taken.map((t) => `"${t.channelKey}"`).join(", ")} take a path this serve answers on ` +
|
|
132
|
-
`itself (${taken.map((t) => `"${t.key}"`).join(", ")}) — rename the channel route`);
|
|
133
|
-
}
|
|
134
58
|
return {
|
|
135
|
-
|
|
136
|
-
|
|
59
|
+
// A probe is the deployment's to shape, so a channel may serve `/health` itself.
|
|
60
|
+
routes: probed ? routes : { ...routes, "GET /health": health },
|
|
137
61
|
longConnections,
|
|
138
62
|
routeChannels,
|
|
139
63
|
setReady(value) {
|
|
@@ -141,78 +65,71 @@ options = {}) {
|
|
|
141
65
|
},
|
|
142
66
|
};
|
|
143
67
|
}
|
|
144
|
-
/**
|
|
145
|
-
export function
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
export function mountSessionControl(routes, control) {
|
|
153
|
-
if (!control)
|
|
154
|
-
return { routes, mounts: [] };
|
|
155
|
-
const plane = createControlPlane(control);
|
|
156
|
-
assertNoControlPlaneCollision(routes, plane);
|
|
157
|
-
return { routes, mounts: [plane], controlPrefix: plane.prefix };
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Load the agent's `routines/`, gated.
|
|
161
|
-
*
|
|
162
|
-
* Separate from {@link startSchedules} because two things need the SAME list and one of them runs first: the
|
|
163
|
-
* `POST /run` route is built with the routes (so a channel cannot take that path unnoticed), and the resident
|
|
164
|
-
* clock starts later, inside the service's scope. Loading twice would let them disagree about which routines exist.
|
|
165
|
-
*/
|
|
166
|
-
export async function loadServingRoutines(agentDir) {
|
|
167
|
-
// Thrown, not exited on: this runs inside an embedder's app as well as the CLI, and a library that calls
|
|
168
|
-
// process.exit takes a decision (degrade? retry? stop?) that belongs to its host.
|
|
169
|
-
const { routines, secrets, failures } = await loadRoutines(agentDir);
|
|
170
|
-
// The routines' half of the serving-path gate (the opener does the tools', loadChannels the
|
|
171
|
-
// channels'): a routine reads its env at IMPORT time, so an unset declared value has already
|
|
172
|
-
// produced a broken prompt — refusing here is the last point where that is a startup failure.
|
|
173
|
-
gateSecrets({ declared: secrets, failures });
|
|
174
|
-
refuseBrokenDeclarations(failures);
|
|
175
|
-
return routines;
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Start the clock over routines {@link loadServingRoutines} already gated — on every serve, routines or not: the
|
|
179
|
-
* agent's own wake-ups are a default capability, and this is what fires them.
|
|
180
|
-
*/
|
|
181
|
-
export function startSchedules(agent, stateRoot, routines, options = {}) {
|
|
182
|
-
const scheduler = Effect.runSync(createScheduler({ agent, stateRoot, routines, externalClock: options.externalClock }));
|
|
68
|
+
/** Start the clock: the definition's schedules, and the wake-ups the agent sets for itself, on every serve. */
|
|
69
|
+
export function startSchedules(agent, stateRoot, schedules, options = {}) {
|
|
70
|
+
const scheduler = Effect.runSync(createScheduler({
|
|
71
|
+
agent,
|
|
72
|
+
stateRoot,
|
|
73
|
+
schedules,
|
|
74
|
+
...(options.localClock === false ? { localClock: false } : {}),
|
|
75
|
+
}));
|
|
183
76
|
scheduler.start();
|
|
184
|
-
if (
|
|
185
|
-
log.info(`[fastagent]
|
|
186
|
-
|
|
187
|
-
return { routines, stop: () => scheduler.stop() };
|
|
77
|
+
if (schedules.length > 0)
|
|
78
|
+
log.info(`[fastagent] schedules: ${schedules.map((s) => s.name).join(", ")}`);
|
|
79
|
+
return scheduler;
|
|
188
80
|
}
|
|
189
81
|
/**
|
|
190
|
-
*
|
|
191
|
-
*
|
|
82
|
+
* A Service over `handler`: answered in process, or served on a server of its own. `endStreams` ends what would hold
|
|
83
|
+
* the server's close open (a Caller watching events), and `shutdown` stops the rest once the server has.
|
|
192
84
|
*/
|
|
193
|
-
export
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
85
|
+
export function serviceOver(handler, ready, shutdown, endStreams = async () => { }) {
|
|
86
|
+
let listener;
|
|
87
|
+
let closing;
|
|
88
|
+
const fetch = totalFetch(handler);
|
|
89
|
+
return {
|
|
90
|
+
fetch,
|
|
91
|
+
listen(port, host) {
|
|
92
|
+
if (closing !== undefined)
|
|
93
|
+
return Promise.reject(new Error("the service is closed"));
|
|
94
|
+
if (listener !== undefined)
|
|
95
|
+
return Promise.reject(new Error("the service is already listening"));
|
|
96
|
+
const current = serveHandler(handler, { port, ...(host === undefined ? {} : { host }) });
|
|
97
|
+
listener = current;
|
|
98
|
+
return current.listening.catch(async (error) => {
|
|
99
|
+
// A bind that failed holds nothing once its scope is closed, so the service may listen again, elsewhere.
|
|
100
|
+
if (listener === current)
|
|
101
|
+
listener = undefined;
|
|
102
|
+
await current.close();
|
|
103
|
+
throw error;
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
ready,
|
|
107
|
+
close() {
|
|
108
|
+
closing ??= (async () => {
|
|
109
|
+
// The server first, so nothing new reaches what stops after it; each step runs, and every failure is said.
|
|
110
|
+
const failures = [];
|
|
111
|
+
for (const step of [endStreams, () => listener?.close(), shutdown]) {
|
|
112
|
+
await Promise.resolve()
|
|
113
|
+
.then(step)
|
|
114
|
+
.catch((error) => failures.push(error));
|
|
115
|
+
}
|
|
116
|
+
if (failures.length > 0) {
|
|
117
|
+
throw failures.length === 1 ? failures[0] : new AggregateError(failures, "the service did not close cleanly");
|
|
118
|
+
}
|
|
119
|
+
})();
|
|
120
|
+
return closing;
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/** The assembly itself: channels, schedules and long connections, composed into one handler. */
|
|
125
|
+
export async function serveAgent(opened, options = {}) {
|
|
126
|
+
const { agent, agentDir, stateRoot, schedules } = opened;
|
|
198
127
|
const closeTimeoutMs = options.closeTimeoutMs ?? CLOSE_DEADLINE_MS;
|
|
199
|
-
|
|
200
|
-
// trailing slash would refuse the front end with nothing naming the rule.
|
|
201
|
-
const corsOrigins = opened.http?.cors;
|
|
202
|
-
if (corsOrigins)
|
|
203
|
-
assertCorsOrigins(corsOrigins, "mountAgentService: http.cors");
|
|
204
|
-
// Loaded BEFORE the routes, because `POST /run` is one of them and the resident clock below must run over the
|
|
205
|
-
// same list — two loads would be two answers to "which routines exist".
|
|
206
|
-
const routines = await loadServingRoutines(agentDir);
|
|
207
|
-
const routed = await routesFor(agentDir, agent, stateRoot, sessionControl, { http: opened.http, routines });
|
|
208
|
-
const withControl = mountSessionControl(routed.selfVerifying, opened.publishControl ? sessionControl : undefined);
|
|
128
|
+
const routed = routesFor(agent, stateRoot, opened.channels);
|
|
209
129
|
// Composed BEFORE anything starts.
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
mounts: withControl.mounts,
|
|
214
|
-
...(corsOrigins ? { corsOrigins } : {}),
|
|
215
|
-
});
|
|
130
|
+
const channels = router(routed.routes);
|
|
131
|
+
const api = options.apiKeys?.length ? apiHandler(agent, { keys: options.apiKeys }) : undefined;
|
|
132
|
+
const handler = api === undefined ? channels : (req) => (isApiPath(new URL(req.url).pathname) ? api.fetch(req) : channels(req));
|
|
216
133
|
return Effect.runPromise(Effect.gen(function* () {
|
|
217
134
|
const lifetime = yield* Scope.make();
|
|
218
135
|
const abort = new AbortController();
|
|
@@ -229,21 +146,21 @@ export async function mountAgentService(opened, options = {}) {
|
|
|
229
146
|
routed.setReady(false);
|
|
230
147
|
onClosed(name, error);
|
|
231
148
|
};
|
|
232
|
-
// Scope.close alone does not join concurrent closes or retain their failure.
|
|
233
|
-
|
|
149
|
+
// Scope.close alone does not join concurrent closes or retain their failure. Every later call, the rollback a
|
|
150
|
+
// close itself triggers included, awaits the first one's outcome.
|
|
151
|
+
const shutdown = once(Effect.gen(function* () {
|
|
234
152
|
abort.abort();
|
|
235
153
|
yield* Scope.close(lifetime, Exit.void);
|
|
236
154
|
}));
|
|
237
155
|
const close = () => Effect.runPromise(shutdown);
|
|
238
156
|
const rollback = shutdown.pipe(Effect.catchCause((cause) => Effect.sync(() => log.error(`[fastagent] cleanup after a failed start also failed: ${String(Cause.squash(cause))}`))));
|
|
239
|
-
const onAbort = () => {
|
|
240
|
-
void close().catch((error) => log.error(`[fastagent] service close failed: ${String(error)}`));
|
|
241
|
-
};
|
|
242
157
|
return yield* Effect.gen(function* () {
|
|
158
|
+
if (api !== undefined)
|
|
159
|
+
yield* Effect.addFinalizer(() => portCleanup("closing the Agent API", api.dispose));
|
|
243
160
|
// Registered first, so subscriptions and schedule timers stop before waiting for transports.
|
|
244
161
|
yield* Effect.addFinalizer(() => closeWithin(runs, names, closeTimeoutMs).pipe(Effect.orDie));
|
|
245
|
-
|
|
246
|
-
try: () => startSchedules(agent, stateRoot,
|
|
162
|
+
yield* Effect.acquireRelease(Effect.try({
|
|
163
|
+
try: () => startSchedules(agent, stateRoot, schedules),
|
|
247
164
|
catch: (error) => error,
|
|
248
165
|
}), (scheduled) => Effect.sync(scheduled.stop));
|
|
249
166
|
const readiness = yield* Effect.forEach(routed.longConnections, (connection) => Effect.gen(function* () {
|
|
@@ -269,10 +186,6 @@ export async function mountAgentService(opened, options = {}) {
|
|
|
269
186
|
log.info(`[fastagent] long connection ready: ${connection.name}`);
|
|
270
187
|
})), Effect.forkScoped({ startImmediately: true }));
|
|
271
188
|
}));
|
|
272
|
-
if (options.signal?.aborted)
|
|
273
|
-
yield* shutdown;
|
|
274
|
-
else
|
|
275
|
-
yield* Effect.acquireRelease(Effect.sync(() => options.signal?.addEventListener("abort", onAbort, { once: true })), () => Effect.sync(() => options.signal?.removeEventListener("abort", onAbort)));
|
|
276
189
|
// The public readiness waiter lives outside the scope it may roll back.
|
|
277
190
|
const ready = Effect.runPromise(Effect.gen(function* () {
|
|
278
191
|
yield* Effect.forEach(readiness, Fiber.join, { concurrency: "unbounded", discard: true });
|
|
@@ -287,21 +200,12 @@ export async function mountAgentService(opened, options = {}) {
|
|
|
287
200
|
// The rejection is still delivered to callers that await ready.
|
|
288
201
|
ready.catch(() => { });
|
|
289
202
|
return {
|
|
290
|
-
handler,
|
|
291
|
-
|
|
292
|
-
routes: { ...routed.unverified, ...withControl.routes },
|
|
203
|
+
...serviceOver(handler, ready, close, async () => api?.endStreams()),
|
|
204
|
+
routes: routed.routes,
|
|
293
205
|
agentDir,
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
longConnections: names,
|
|
298
|
-
},
|
|
299
|
-
unverifiedRoutes: Object.keys(routed.unverified),
|
|
300
|
-
...(corsOrigins ? { corsOrigins } : {}),
|
|
301
|
-
routines: scheduled.routines,
|
|
302
|
-
ready,
|
|
303
|
-
...(withControl.controlPrefix ? { controlPrefix: withControl.controlPrefix } : {}),
|
|
304
|
-
close,
|
|
206
|
+
channels: { routes: routed.routeChannels, longConnections: names },
|
|
207
|
+
schedules,
|
|
208
|
+
api: api !== undefined,
|
|
305
209
|
};
|
|
306
210
|
}).pipe(Scope.provide(lifetime), Effect.onError(() => rollback));
|
|
307
211
|
}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which command serves this process: `dev` marks it, and everything else (`start`, a deployed box, an embedder) is
|
|
3
|
+
* the default. A channel file reads it at import through the agent's OWN installed copy of this package, which shares
|
|
4
|
+
* nothing with the CLI's copy but the process environment, so the mark lives there.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEV_SERVE_ENV = "FASTAGENT_DEV";
|
|
7
|
+
export declare function markDevServe(env?: NodeJS.ProcessEnv): void;
|
|
8
|
+
/** For a command that is never `dev` (`start`, `deploy`), run from a shell or a tool that a `dev` process spawned. */
|
|
9
|
+
export declare function unmarkDevServe(env?: NodeJS.ProcessEnv): void;
|
|
10
|
+
export declare function servedByDev(env?: NodeJS.ProcessEnv): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which command serves this process: `dev` marks it, and everything else (`start`, a deployed box, an embedder) is
|
|
3
|
+
* the default. A channel file reads it at import through the agent's OWN installed copy of this package, which shares
|
|
4
|
+
* nothing with the CLI's copy but the process environment, so the mark lives there.
|
|
5
|
+
*/
|
|
6
|
+
export const DEV_SERVE_ENV = "FASTAGENT_DEV";
|
|
7
|
+
export function markDevServe(env = process.env) {
|
|
8
|
+
env[DEV_SERVE_ENV] = "1";
|
|
9
|
+
}
|
|
10
|
+
/** For a command that is never `dev` (`start`, `deploy`), run from a shell or a tool that a `dev` process spawned. */
|
|
11
|
+
export function unmarkDevServe(env = process.env) {
|
|
12
|
+
delete env[DEV_SERVE_ENV];
|
|
13
|
+
}
|
|
14
|
+
export function servedByDev(env = process.env) {
|
|
15
|
+
return env[DEV_SERVE_ENV] === "1";
|
|
16
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model credentials and provider sign-in as an embedding host sees them: FastAgent's own types, so a host keeps the
|
|
3
|
+
* credentials where it chooses and runs a sign-in in its own UI without knowing the harness. Imports nothing; the
|
|
4
|
+
* functions over these types are in harnesses/models/host.ts.
|
|
5
|
+
*/
|
|
6
|
+
/** One provider's credential, kept by a {@link CredentialStore} whole, as it is given. */
|
|
7
|
+
export type Credential = {
|
|
8
|
+
type: "api_key";
|
|
9
|
+
key?: string;
|
|
10
|
+
env?: Record<string, string>;
|
|
11
|
+
} | {
|
|
12
|
+
type: "oauth";
|
|
13
|
+
access: string;
|
|
14
|
+
refresh: string;
|
|
15
|
+
expires: number;
|
|
16
|
+
[field: string]: unknown;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Where model credentials are kept, one per provider. `modify` is the only write, and it runs one at a time per
|
|
20
|
+
* provider (across processes, where the store can): an OAuth refresh happens inside it, and a rotated refresh token
|
|
21
|
+
* must never be used twice. A store it cannot read rejects; answering it as empty would let the next write replace
|
|
22
|
+
* every provider's credential.
|
|
23
|
+
*/
|
|
24
|
+
export interface CredentialStore {
|
|
25
|
+
/** The stored credential, possibly expired; undefined when the provider has none. */
|
|
26
|
+
read(provider: string): Promise<Credential | undefined>;
|
|
27
|
+
/** Which providers have a credential, and of what kind; never the secrets. */
|
|
28
|
+
list(): Promise<readonly {
|
|
29
|
+
provider: string;
|
|
30
|
+
type: Credential["type"];
|
|
31
|
+
}[]>;
|
|
32
|
+
/** `change` returns the new credential, or undefined to leave it as it is. Resolves with what is stored after. */
|
|
33
|
+
modify(provider: string, change: (current: Credential | undefined) => Promise<Credential | undefined>): Promise<Credential | undefined>;
|
|
34
|
+
delete(provider: string): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export type SignInMethod = Credential["type"];
|
|
37
|
+
/** One way to sign in to one provider, with what authenticates the provider now. */
|
|
38
|
+
export interface SignInOption {
|
|
39
|
+
provider: string;
|
|
40
|
+
/** The provider's name: "OpenAI", "OpenAI Codex (legacy)". */
|
|
41
|
+
name: string;
|
|
42
|
+
method: SignInMethod;
|
|
43
|
+
/** What signing in this way is called: the provider's own label ("Sign in with ChatGPT"), else a generic one. */
|
|
44
|
+
label: string;
|
|
45
|
+
/** An account sign-in backed by a provider subscription. */
|
|
46
|
+
subscription: boolean;
|
|
47
|
+
/** Its key comes from the environment only: there is no sign-in to run. */
|
|
48
|
+
external: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* What authenticates the provider now: a stored credential (`OAuth`, `stored credential`), else the environment
|
|
51
|
+
* (a variable such as `OPENAI_API_KEY`). One credential is stored per provider, so signing in with the other method
|
|
52
|
+
* replaces a stored one.
|
|
53
|
+
*/
|
|
54
|
+
status?: {
|
|
55
|
+
type: SignInMethod;
|
|
56
|
+
source: string;
|
|
57
|
+
};
|
|
58
|
+
/** What in the environment authenticates the provider with nothing stored: what still answers after a sign-out. */
|
|
59
|
+
environment?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Why checking the environment for the provider failed: `environment` is then unknown, and so is `status` when
|
|
62
|
+
* nothing is stored.
|
|
63
|
+
*/
|
|
64
|
+
problem?: string;
|
|
65
|
+
}
|
|
66
|
+
/** A question a sign-in asks. `manual_code`: the address the browser ended on after signing in, or the code its page showed. */
|
|
67
|
+
export type SignInPrompt = {
|
|
68
|
+
signal?: AbortSignal;
|
|
69
|
+
} & ({
|
|
70
|
+
type: "text" | "secret" | "manual_code";
|
|
71
|
+
message: string;
|
|
72
|
+
placeholder?: string;
|
|
73
|
+
} | {
|
|
74
|
+
type: "select";
|
|
75
|
+
message: string;
|
|
76
|
+
options: readonly {
|
|
77
|
+
id: string;
|
|
78
|
+
label: string;
|
|
79
|
+
description?: string;
|
|
80
|
+
}[];
|
|
81
|
+
});
|
|
82
|
+
/** What a sign-in tells the person: a page to open, a code to enter there, progress. */
|
|
83
|
+
export type SignInEvent = {
|
|
84
|
+
type: "info";
|
|
85
|
+
message: string;
|
|
86
|
+
links?: readonly {
|
|
87
|
+
url: string;
|
|
88
|
+
label?: string;
|
|
89
|
+
}[];
|
|
90
|
+
} | {
|
|
91
|
+
type: "progress";
|
|
92
|
+
message: string;
|
|
93
|
+
} | {
|
|
94
|
+
type: "auth_url";
|
|
95
|
+
url: string;
|
|
96
|
+
instructions?: string;
|
|
97
|
+
} | {
|
|
98
|
+
type: "device_code";
|
|
99
|
+
userCode: string;
|
|
100
|
+
verificationUri: string;
|
|
101
|
+
intervalSeconds?: number;
|
|
102
|
+
expiresInSeconds?: number;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* How a sign-in reaches the person. `prompt` resolves with the answer (a select's option `id`); it rejects with
|
|
106
|
+
* {@link SignInCancelled} when the person backs out, which ends the sign-in with that error, and with any other error
|
|
107
|
+
* when asking failed, which fails the sign-in with it. A prompt's `signal` aborts when the sign-in no longer needs the
|
|
108
|
+
* answer, such as a `manual_code` question a browser callback answered first.
|
|
109
|
+
*/
|
|
110
|
+
export interface SignInInteraction {
|
|
111
|
+
signal?: AbortSignal;
|
|
112
|
+
prompt(prompt: SignInPrompt): Promise<string>;
|
|
113
|
+
notify(event: SignInEvent): void;
|
|
114
|
+
}
|
|
115
|
+
export interface SignInRequest {
|
|
116
|
+
credentials: CredentialStore;
|
|
117
|
+
provider: string;
|
|
118
|
+
method: SignInMethod;
|
|
119
|
+
interaction: SignInInteraction;
|
|
120
|
+
/**
|
|
121
|
+
* A stable id of this installation, which Sign in with ChatGPT requires. `credentialFile` keeps one beside its
|
|
122
|
+
* file; a store of the host's own passes it here.
|
|
123
|
+
*/
|
|
124
|
+
deviceId?: string;
|
|
125
|
+
}
|
|
126
|
+
export interface SignInResult {
|
|
127
|
+
provider: string;
|
|
128
|
+
method: SignInMethod;
|
|
129
|
+
/** An API key is checked with one request before it is stored: accepted, or not decidable (stored). */
|
|
130
|
+
verified: "ok" | "unknown" | "n/a";
|
|
131
|
+
}
|
|
132
|
+
/** What a request to a provider authenticates with. */
|
|
133
|
+
export interface ProviderAuth {
|
|
134
|
+
type: SignInMethod;
|
|
135
|
+
/** Where it comes from: `OAuth`, `stored credential`, an environment variable's name. */
|
|
136
|
+
source?: string;
|
|
137
|
+
/** The key or access token a request sends. */
|
|
138
|
+
apiKey?: string;
|
|
139
|
+
/** Headers a request sends, where the provider authenticates by them (an `Authorization` of its own). */
|
|
140
|
+
headers?: Record<string, string>;
|
|
141
|
+
/** Where the request goes, where the credential decides it (an enterprise endpoint). */
|
|
142
|
+
baseUrl?: string;
|
|
143
|
+
}
|
|
144
|
+
/** The person backed out of a sign-in, or its signal aborted: a decision, not a failure. Nothing was stored. */
|
|
145
|
+
export declare class SignInCancelled extends Error {
|
|
146
|
+
name: string;
|
|
147
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model credentials and provider sign-in as an embedding host sees them: FastAgent's own types, so a host keeps the
|
|
3
|
+
* credentials where it chooses and runs a sign-in in its own UI without knowing the harness. Imports nothing; the
|
|
4
|
+
* functions over these types are in harnesses/models/host.ts.
|
|
5
|
+
*/
|
|
6
|
+
/** The person backed out of a sign-in, or its signal aborted: a decision, not a failure. Nothing was stored. */
|
|
7
|
+
export class SignInCancelled extends Error {
|
|
8
|
+
name = "SignInCancelled";
|
|
9
|
+
}
|
package/dist/slack.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** `@fastagent-sh/fastagent/slack` — the first-party Slack Events API bot-channel surface. */
|
|
2
2
|
export { slackChannel, defaultSlackRoute, slackEnvelope, verifySlackSignature, type SlackChannelOptions, type SlackEventEnvelope, type SlackFile, type SlackMessageEvent, type SlackRendering, type SlackRoute, type SlackFailure, } from "./channels/slack/slack.ts";
|
|
3
|
-
export { slackTransport, type SlackTransport } from "./channels/slack/shared-api.ts";
|
|
3
|
+
export { slackThreads, slackTransport, type SlackTransport } from "./channels/slack/shared-api.ts";
|
|
4
4
|
export type { SentSlackMessage, SlackTarget, UploadedSlackFile } from "./channels/slack/slack-api.ts";
|
package/dist/slack.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/** `@fastagent-sh/fastagent/slack` — the first-party Slack Events API bot-channel surface. */
|
|
2
2
|
export { slackChannel, defaultSlackRoute, slackEnvelope, verifySlackSignature, } from "./channels/slack/slack.js";
|
|
3
|
-
export { slackTransport } from "./channels/slack/shared-api.js";
|
|
3
|
+
export { slackThreads, slackTransport } from "./channels/slack/shared-api.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* (`<stateRoot>/channels/<
|
|
4
|
-
* means one ingress credential in two places, and no
|
|
5
|
-
*
|
|
2
|
+
* A Caller's durable state under the state root, with no cross-instance locking: a channel's files are in its own
|
|
3
|
+
* directory (`<stateRoot>/channels/<the channel file's name>/`) and the schedules' in `schedule/`, so what must not
|
|
4
|
+
* happen is two processes serving the SAME channel — which also means one ingress credential in two places, and no
|
|
5
|
+
* local guard can see that (docs/design/core.md §9).
|
|
6
6
|
*/
|
|
7
7
|
import { mkdirSync, readFileSync } from "node:fs";
|
|
8
|
-
import { writeFileAtomic } from "
|
|
9
|
-
import { log } from "
|
|
8
|
+
import { writeFileAtomic } from "./atomic-write.js";
|
|
9
|
+
import { log } from "./log.js";
|
|
10
10
|
/** Create the channel's state home — the one shared spelling of it, so no channel invents its own. */
|
|
11
11
|
export function ensureStateHome(dir) {
|
|
12
12
|
mkdirSync(dir, { recursive: true });
|
package/dist/telegram.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
/** `@fastagent-sh/fastagent/telegram` — the Telegram bot channel subpath export, kept off the root surface. */
|
|
2
2
|
export { telegramChannel, defaultTelegramRoute, telegramEnvelope, telegramStop, type TelegramChannelOptions, type TelegramUpdate, type TelegramMessage, type TelegramRoute, type TelegramFailure, } from "./channels/telegram/telegram.ts";
|
|
3
|
+
export { telegramTransport, type TelegramSendTarget, type TelegramSent, type TelegramTransport, } from "./channels/telegram/shared-api.ts";
|
package/dist/telegram.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
/** `@fastagent-sh/fastagent/telegram` — the Telegram bot channel subpath export, kept off the root surface. */
|
|
2
2
|
export { telegramChannel, defaultTelegramRoute, telegramEnvelope, telegramStop, } from "./channels/telegram/telegram.js";
|
|
3
|
+
export { telegramTransport, } from "./channels/telegram/shared-api.js";
|
package/dist/tunnel.d.ts
CHANGED
|
@@ -27,6 +27,9 @@ export declare function startCloudflareTunnel(port: number, spawnFn?: SpawnCloud
|
|
|
27
27
|
export declare function announceWebhooks(dir: string, baseUrl: string, channels: readonly DeclaredChannel[], opts?: {
|
|
28
28
|
openUrl?: (url: string) => void;
|
|
29
29
|
stateRoot?: string;
|
|
30
|
+
env?: NodeJS.ProcessEnv;
|
|
31
|
+
/** {@link Registrars.leave}. */
|
|
32
|
+
leave?: (step: string) => void;
|
|
30
33
|
}): Promise<{
|
|
31
34
|
kind: string;
|
|
32
35
|
outcome: RegistrationOutcome;
|
package/dist/tunnel.js
CHANGED
|
@@ -7,10 +7,11 @@ import { spawn } from "node:child_process";
|
|
|
7
7
|
import { registerFeishuWebhook } from "./channels/feishu/register-webhook.js";
|
|
8
8
|
import { registerSlackWebhook } from "./channels/slack/register-webhook.js";
|
|
9
9
|
import { registerTelegramWebhook } from "./channels/telegram/register-webhook.js";
|
|
10
|
-
import { pointChannelsAt } from "./deploy/channel-ingress.js";
|
|
11
|
-
import {
|
|
10
|
+
import { pointChannelsAt, webhookKinds } from "./deploy/channel-ingress.js";
|
|
11
|
+
import { loadDotEnv } from "./env.js";
|
|
12
|
+
import { dotEnvPath } from "./value-file.js";
|
|
12
13
|
import { installProxyFetch } from "./proxy.js";
|
|
13
|
-
import { resolveStateRoot } from "./paths.js";
|
|
14
|
+
import { AGENT_ENVIRONMENT_ENV, resolveStateRoot } from "./paths.js";
|
|
14
15
|
import { log } from "./log.js";
|
|
15
16
|
// `(?!api\.)`: cloudflared's ERROR lines mention its request endpoint (`https://api.trycloudflare.com/tunnel`, e.g.
|
|
16
17
|
// "failed to request quick Tunnel: Post ... timeout" under a flaky proxy) — without the exclusion a transient error
|
|
@@ -130,7 +131,8 @@ function lastErrorLine(tail) {
|
|
|
130
131
|
export async function announceWebhooks(dir, baseUrl, channels, opts = {}) {
|
|
131
132
|
log.info(`[fastagent] public URL: ${baseUrl}`);
|
|
132
133
|
try {
|
|
133
|
-
|
|
134
|
+
if (!opts.env)
|
|
135
|
+
loadDotEnv(dir);
|
|
134
136
|
}
|
|
135
137
|
catch (error) {
|
|
136
138
|
// best-effort boundary: an unreadable .env (a MISSING one is already tolerated) still leaves registrars that can
|
|
@@ -141,16 +143,23 @@ export async function announceWebhooks(dir, baseUrl, channels, opts = {}) {
|
|
|
141
143
|
// Readiness is the registrar's job: a fresh quick tunnel returns Cloudflare 530 for ~20-30s before its origin
|
|
142
144
|
// connects, and each registrar absorbs that by retrying the platform call whose own URL verification reports it.
|
|
143
145
|
const feishuOptions = {
|
|
146
|
+
env: opts.env,
|
|
144
147
|
onManualRegistration: ({ consoleUrl }) => opts.openUrl?.(consoleUrl),
|
|
145
148
|
};
|
|
149
|
+
const moving = webhookKinds(channels);
|
|
150
|
+
if (moving.length > 0) {
|
|
151
|
+
log.info(`[fastagent] pointing the selected ${moving.join(", ")} app at ${baseUrl}; only this app's Request URL changes`);
|
|
152
|
+
}
|
|
146
153
|
return pointChannelsAt({
|
|
147
154
|
baseUrl,
|
|
148
155
|
channels,
|
|
149
156
|
log: (message) => log.info(`[fastagent] ${message}`),
|
|
150
157
|
registrars: {
|
|
151
|
-
|
|
158
|
+
...(opts.leave === undefined ? {} : { leave: opts.leave }),
|
|
159
|
+
telegram: (url) => registerTelegramWebhook(url, { env: opts.env }),
|
|
152
160
|
slack: (url) => registerSlackWebhook(url, {
|
|
153
161
|
stateRoot: opts.stateRoot ?? resolveStateRoot(dir),
|
|
162
|
+
environment: process.env[AGENT_ENVIRONMENT_ENV] === "production" ? "production" : "dev",
|
|
154
163
|
log: (message) => log.info(message),
|
|
155
164
|
}),
|
|
156
165
|
feishu: (url, kind) => registerFeishuWebhook(url, kind, feishuOptions),
|