@fastagent-sh/fastagent 0.24.3 → 0.25.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 +53 -82
- package/dist/agent-api.d.ts +452 -0
- package/dist/agent-api.js +201 -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 +77 -0
- package/dist/authoring.js +238 -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 +115 -63
- package/dist/cli/auth-view.d.ts +10 -3
- package/dist/cli/auth-view.js +8 -6
- package/dist/cli/box-login.d.ts +17 -7
- package/dist/cli/box-login.js +46 -12
- package/dist/cli/commands/add.d.ts +15 -4
- package/dist/cli/commands/add.js +252 -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 +190 -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 +131 -16
- package/dist/cli/commands/login.d.ts +31 -2
- package/dist/cli/commands/login.js +413 -64
- 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 +3 -2
- package/dist/cli/login-relay.js +18 -6
- 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 +68 -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 +217 -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 +222 -201
- 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 +51 -26
- package/dist/effect-port.d.ts +4 -4
- package/dist/effect-port.js +4 -4
- 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 +50 -0
- package/dist/environment/mise.js +268 -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 +43 -0
- package/dist/harnesses/models/environment.js +82 -0
- package/dist/{engines/pi → harnesses/models}/login.d.ts +57 -26
- package/dist/{engines/pi → harnesses/models}/login.js +187 -79
- package/dist/harnesses/models/models.d.ts +83 -0
- package/dist/harnesses/models/models.js +158 -0
- package/dist/harnesses/pi-durable/agent.d.ts +42 -0
- package/dist/harnesses/pi-durable/agent.js +579 -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 +88 -0
- package/dist/harnesses/pi-durable/open.js +329 -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 +80 -0
- package/dist/harnesses/pi-durable/serve.js +156 -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 +4 -0
- package/dist/harnesses/pi-durable/wake.js +81 -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 +17 -4
- package/dist/index.js +10 -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/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 +12 -4
- package/dist/value-file.d.ts +21 -0
- package/dist/value-file.js +108 -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 -517
- 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/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 -83
- package/dist/engines/pi/turn-kit.js +0 -275
- 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
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `deploy railway`:
|
|
2
|
+
* `deploy railway`: no config file of its own, scale-to-zero is a manual dashboard step, the URL is minted (see
|
|
3
3
|
* planRailwayDeploy).
|
|
4
4
|
*/
|
|
5
5
|
import { basename } from "node:path";
|
|
6
|
-
import {
|
|
6
|
+
import { planRailwayDeploy, toRailwayName } from "../../../deploy/railway/plan.js";
|
|
7
7
|
import { deployRailwayRun } from "../../../deploy/railway/run.js";
|
|
8
8
|
import { spawnRunner } from "../../../deploy/runner.js";
|
|
9
9
|
import { assembleSecrets } from "../../../deploy/secrets.js";
|
|
10
10
|
import { processShell } from "../../../deploy/box-shell.js";
|
|
11
11
|
import { failStartup } from "../../fail.js";
|
|
12
|
-
import {
|
|
12
|
+
import { RAILWAY_LOGIN, hostLogin } from "./host-login.js";
|
|
13
13
|
import { boxLoginStep, registrarsFor } from "./shared.js";
|
|
14
14
|
export const railwayHost = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
shell: async (
|
|
15
|
+
// Railway's only artifacts are the container's, which planArtifacts owns for every host.
|
|
16
|
+
isOurs: () => false,
|
|
17
|
+
shell: async (agentDir) => railwayShell(toRailwayName(basename(agentDir)), agentDir),
|
|
18
18
|
async deploy(ctx) {
|
|
19
|
-
const { opts, agentDir,
|
|
19
|
+
const { opts, agentDir, pre, channels, write } = ctx;
|
|
20
20
|
const { hasCron, modelAuth, boxLogin, container, declaredSecrets, values, valueFile } = pre;
|
|
21
|
-
const serviceName = toRailwayName(basename(
|
|
21
|
+
const serviceName = toRailwayName(basename(agentDir));
|
|
22
22
|
const plan = planRailwayDeploy({
|
|
23
23
|
serviceName,
|
|
24
24
|
boxLogin,
|
|
@@ -29,36 +29,29 @@ export const railwayHost = {
|
|
|
29
29
|
});
|
|
30
30
|
await write(plan.artifacts, { force: !!opts.force });
|
|
31
31
|
if (opts.run) {
|
|
32
|
-
// The BUILD entry is guaranteed by the RAILWAY_DOCKERFILE_PATH service variable the runner sets (Railway's
|
|
33
|
-
// documented non-root-Dockerfile route), and Railway's default restart policy already equals the file's
|
|
34
|
-
// ON_FAILURE — the dashboard-only Config-as-code pointer only adds the /health deploy gate (boot-crash
|
|
35
|
-
// visibility), so it is an OPTIONAL note, not a gate.
|
|
36
|
-
console.error(`[fastagent] note: optional — point the service at fastagent/railway.json (Service → Settings → ` +
|
|
37
|
-
`Config-as-code, dashboard-only) so the /health healthcheck marks a boot-crashing deploy as FAILED; ` +
|
|
38
|
-
`the build already uses fastagent/Dockerfile via the RAILWAY_DOCKERFILE_PATH variable`);
|
|
39
32
|
return runDeployRailway({
|
|
40
33
|
agentDir,
|
|
41
|
-
workspace,
|
|
42
34
|
name: serviceName,
|
|
43
35
|
modelAuth,
|
|
44
36
|
boxLogin,
|
|
45
|
-
|
|
37
|
+
answerer: ctx.answerer,
|
|
38
|
+
rerun: ctx.rerun,
|
|
46
39
|
channels,
|
|
47
40
|
declaredSecrets,
|
|
48
41
|
values,
|
|
49
42
|
valueFile,
|
|
50
43
|
intoLinked: !!opts.intoLinked,
|
|
51
|
-
dockerfilePath: dockerfilePathVar(pre.container.agentPrefix),
|
|
52
44
|
});
|
|
53
45
|
}
|
|
54
46
|
console.log(plan.runbook.join("\n"));
|
|
55
|
-
|
|
47
|
+
// Railway mints the domain when the runbook's step generates it.
|
|
48
|
+
return undefined;
|
|
56
49
|
},
|
|
57
50
|
};
|
|
58
51
|
/** `deploy railway --run`: drive the railway CLI to completion. */
|
|
59
52
|
async function runDeployRailway(params) {
|
|
60
|
-
const { agentDir,
|
|
61
|
-
const railway = spawnRunner("railway",
|
|
53
|
+
const { agentDir, name, channels, intoLinked } = params;
|
|
54
|
+
const railway = spawnRunner("railway", agentDir);
|
|
62
55
|
// Fail fast if the railway CLI is absent (spawn ENOENT → 127), with the install link.
|
|
63
56
|
if ((await railway(["--version"], { capture: true })).code === 127) {
|
|
64
57
|
failStartup(new Error(`railway CLI not found — install it: https://docs.railway.com/guides/cli, then re-run`));
|
|
@@ -76,15 +69,17 @@ async function runDeployRailway(params) {
|
|
|
76
69
|
valueFile: params.valueFile,
|
|
77
70
|
channels,
|
|
78
71
|
intoLinked,
|
|
79
|
-
|
|
80
|
-
...
|
|
81
|
-
|
|
72
|
+
...boxLoginStep("railway", params, () => railwayShell(name, agentDir)),
|
|
73
|
+
...hostLogin(RAILWAY_LOGIN, params.answerer, agentDir),
|
|
74
|
+
forAgent: `${params.rerun} --json`,
|
|
75
|
+
}, railway, (m) => console.error(`[fastagent] ${m}`), registrarsFor(agentDir, params.values, params.answerer));
|
|
82
76
|
if (!outcome.ok)
|
|
83
77
|
failStartup(new Error(`deploy stopped: ${outcome.gate}`));
|
|
84
78
|
console.error(`[fastagent] deployed → ${outcome.url}`);
|
|
79
|
+
return outcome.url;
|
|
85
80
|
}
|
|
86
81
|
/** `railway ssh` into the service, in the project and environment this directory is linked to. */
|
|
87
|
-
function railwayShell(service,
|
|
82
|
+
function railwayShell(service, agentDir) {
|
|
88
83
|
// One quoted word: the command reaches the box as ONE line its shell parses, the way OpenSSH hands it over.
|
|
89
|
-
return processShell("railway", (command) => ["ssh", "--service", service, "--", `sh -c '${command}'`],
|
|
84
|
+
return processShell("railway", (command) => ["ssh", "--service", service, "--", `sh -c '${command}'`], agentDir);
|
|
90
85
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { DeclaredChannel } from "../../../channels/discover.ts";
|
|
2
2
|
import type { Registrars } from "../../../deploy/channel-ingress.ts";
|
|
3
3
|
import type { DeployPreflight } from "../../../deploy/preflight.ts";
|
|
4
|
-
import type {
|
|
5
|
-
import { type ResolvedPlacement } from "../../../paths.ts";
|
|
4
|
+
import type { AgentConfig } from "../../../harnesses/pi-durable/define.ts";
|
|
6
5
|
import { type BoxLoginStep, type BoxShell } from "../../../deploy/box-shell.ts";
|
|
6
|
+
import type { TicketStep } from "../../ticket.ts";
|
|
7
7
|
import type { DeployHost } from "../../../deploy/hosts.ts";
|
|
8
8
|
export interface DeployOptions {
|
|
9
9
|
run?: boolean;
|
|
@@ -12,23 +12,49 @@ export interface DeployOptions {
|
|
|
12
12
|
intoLinked?: boolean;
|
|
13
13
|
/** false ⇔ `--no-input`. */
|
|
14
14
|
input?: boolean;
|
|
15
|
+
/** `--json`: a coding agent's `--run`, run in a ticket that hands each step only a person can take to its user. */
|
|
16
|
+
json?: boolean;
|
|
17
|
+
/** `--check <ticket>`: where such a deploy stands. */
|
|
18
|
+
check?: string;
|
|
19
|
+
/** `--code <code>` (with `--check`): the code a host's approval page showed, when it could not reach this machine. */
|
|
20
|
+
code?: string;
|
|
21
|
+
/** `--stop` (with `--check`): stop that deploy where it is. */
|
|
22
|
+
stop?: boolean;
|
|
23
|
+
/** `--timeout <seconds>`: how long it stays open. */
|
|
24
|
+
timeout?: string;
|
|
25
|
+
/** `--ticket <id>`: the process that runs it. */
|
|
26
|
+
ticket?: string;
|
|
15
27
|
}
|
|
16
28
|
/**
|
|
17
|
-
*
|
|
29
|
+
* Who takes a deploy's steps only a person can (a host account's sign-in, a production app's confirmation, the box's
|
|
30
|
+
* model login): the person at this terminal, a coding agent's person through the deploy's ticket, or nobody (CI, or a
|
|
31
|
+
* script), for whom such a step stops the deploy naming how to give it.
|
|
32
|
+
*/
|
|
33
|
+
export type Answerer = {
|
|
34
|
+
kind: "terminal";
|
|
35
|
+
} | {
|
|
36
|
+
kind: "ticket";
|
|
37
|
+
step: TicketStep;
|
|
38
|
+
} | {
|
|
39
|
+
kind: "nobody";
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* What the dispatcher resolved before handing off: the agent directory, the flags, the config and the host-neutral
|
|
18
43
|
* pre-flight, plus the channel lists every host asks about.
|
|
19
44
|
*/
|
|
20
45
|
interface DeployContext {
|
|
21
46
|
opts: DeployOptions;
|
|
47
|
+
answerer: Answerer;
|
|
48
|
+
/** The command that runs this deploy again, from where it ran: its agent directory and flags. */
|
|
49
|
+
rerun: string;
|
|
22
50
|
agentDir: string;
|
|
23
|
-
|
|
24
|
-
config: FastagentConfig;
|
|
51
|
+
config: AgentConfig;
|
|
25
52
|
pre: Extract<DeployPreflight, {
|
|
26
53
|
ok: true;
|
|
27
54
|
}>;
|
|
28
55
|
channels: readonly DeclaredChannel[];
|
|
29
56
|
webhookChannels: readonly DeclaredChannel[];
|
|
30
|
-
|
|
31
|
-
/** Write this host's planned artifacts into the workspace under the ownership rule. */
|
|
57
|
+
/** Write this host's planned artifacts into the agent directory under the ownership rule. */
|
|
32
58
|
write(artifacts: {
|
|
33
59
|
path: string;
|
|
34
60
|
content: string;
|
|
@@ -41,26 +67,28 @@ interface DeployContext {
|
|
|
41
67
|
export interface HostDeploy {
|
|
42
68
|
/** Did this host generate the file at `path`? */
|
|
43
69
|
isOurs(path: string, content: string): boolean;
|
|
44
|
-
/** The
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
shell(placement: ResolvedPlacement): Promise<BoxShell>;
|
|
70
|
+
/** The shell into this agent's running box (`fastagent login --deployment`). */
|
|
71
|
+
shell(agentDir: string): Promise<BoxShell>;
|
|
72
|
+
validate?(ctx: Pick<DeployContext, "opts" | "agentDir" | "pre">): void;
|
|
48
73
|
/**
|
|
49
74
|
* Plan the artifacts from the pre-flight facts and what is on disk, write them, then either drive the host CLI
|
|
50
|
-
* (`--run`) or print the runbook.
|
|
75
|
+
* (`--run`) or print the runbook. Answers the URL the deployment is reached at, when this host knows it.
|
|
51
76
|
*/
|
|
52
|
-
deploy(ctx: DeployContext): Promise<
|
|
77
|
+
deploy(ctx: DeployContext): Promise<string | undefined>;
|
|
53
78
|
}
|
|
54
|
-
/**
|
|
55
|
-
export declare function
|
|
79
|
+
/** Where a step left to the person goes for `answerer`: a ticket's `afterwards`; nowhere else but the log. */
|
|
80
|
+
export declare function leftToPerson(answerer: Answerer): ((step: string) => void) | undefined;
|
|
81
|
+
/** The registrars every host driver gets; a channel's manual step also goes to `answerer`'s person. */
|
|
82
|
+
export declare function registrarsFor(agentDir: string, values: ReadonlyMap<string, string>, answerer: Answerer): Registrars;
|
|
56
83
|
/**
|
|
57
84
|
* The login `--run` starts on the box it just deployed, before any webhook is pointed at it (a host driver's `boxLogin`): for
|
|
58
85
|
* the model's provider, keeping a credential the box already holds (a redeploy), and asking only when a person can
|
|
59
86
|
* answer. None when the model's credential travels as a variable.
|
|
60
87
|
*/
|
|
61
|
-
export declare function boxLoginStep<Args extends unknown[]>(host: DeployHost, params:
|
|
88
|
+
export declare function boxLoginStep<Args extends unknown[]>(host: DeployHost, params: {
|
|
89
|
+
agentDir: string;
|
|
62
90
|
boxLogin: string | undefined;
|
|
63
|
-
|
|
91
|
+
answerer: Answerer;
|
|
64
92
|
},
|
|
65
93
|
/** The shell, from whatever the driver learns only after deploying (AgentCore's runtime ARN). */
|
|
66
94
|
shell: (...args: Args) => BoxShell): {
|
|
@@ -3,23 +3,29 @@
|
|
|
3
3
|
* ownership rule.
|
|
4
4
|
*/
|
|
5
5
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
6
|
-
import { dirname, join } from "node:path";
|
|
6
|
+
import { basename, dirname, join } from "node:path";
|
|
7
7
|
import { registerFeishuWebhook } from "../../../channels/feishu/register-webhook.js";
|
|
8
8
|
import { DEPLOY_REGISTRATION_ATTEMPTS } from "../../../channels/registration.js";
|
|
9
9
|
import { registerSlackWebhook } from "../../../channels/slack/register-webhook.js";
|
|
10
10
|
import { registerTelegramWebhook } from "../../../channels/telegram/register-webhook.js";
|
|
11
|
-
import { isGeneratedDockerfile, isGeneratedDockerignore } from "../../../deploy/container.js";
|
|
12
|
-
import { RELEASE_FILE } from "../../../deploy/workspace.js";
|
|
11
|
+
import { BUILD_OUTPUTS, IMAGE_DEFINITION_DIR, isGeneratedDockerfile, isGeneratedDockerignore, } from "../../../deploy/container.js";
|
|
13
12
|
import { exists, resolveStateRoot } from "../../../paths.js";
|
|
14
13
|
import { deploymentLoginCommand } from "../../../deploy/box-shell.js";
|
|
15
|
-
import { loginOnBox } from "../../box-login.js";
|
|
16
|
-
/**
|
|
17
|
-
export function
|
|
14
|
+
import { loginOnBox, ticketLoginIO } from "../../box-login.js";
|
|
15
|
+
/** Where a step left to the person goes for `answerer`: a ticket's `afterwards`; nowhere else but the log. */
|
|
16
|
+
export function leftToPerson(answerer) {
|
|
17
|
+
return answerer.kind === "ticket" ? (step) => answerer.step.person.afterwards(step) : undefined;
|
|
18
|
+
}
|
|
19
|
+
/** The registrars every host driver gets; a channel's manual step also goes to `answerer`'s person. */
|
|
20
|
+
export function registrarsFor(agentDir, values, answerer) {
|
|
18
21
|
const attempts = DEPLOY_REGISTRATION_ATTEMPTS;
|
|
22
|
+
const env = Object.fromEntries(values);
|
|
23
|
+
const leave = leftToPerson(answerer);
|
|
19
24
|
return {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
...(leave === undefined ? {} : { leave }),
|
|
26
|
+
telegram: (baseUrl) => registerTelegramWebhook(baseUrl, { attempts, env }),
|
|
27
|
+
slack: (baseUrl) => registerSlackWebhook(baseUrl, { stateRoot: resolveStateRoot(agentDir), environment: "production", attempts }),
|
|
28
|
+
feishu: (baseUrl, kind) => registerFeishuWebhook(baseUrl, kind, { attempts, env }),
|
|
23
29
|
};
|
|
24
30
|
}
|
|
25
31
|
/**
|
|
@@ -33,11 +39,24 @@ shell) {
|
|
|
33
39
|
const provider = params.boxLogin;
|
|
34
40
|
if (provider === undefined)
|
|
35
41
|
return {};
|
|
36
|
-
const
|
|
42
|
+
const command = deploymentLoginCommand(host, provider);
|
|
43
|
+
const { answerer } = params;
|
|
37
44
|
return {
|
|
38
45
|
boxLogin: {
|
|
39
|
-
command
|
|
40
|
-
run: (...args) =>
|
|
46
|
+
command,
|
|
47
|
+
run: async (...args) => {
|
|
48
|
+
const request = { host, shell: shell(...args), provider, ifMissing: true };
|
|
49
|
+
if (answerer.kind !== "ticket")
|
|
50
|
+
return loginOnBox({ ...request, input: answerer.kind === "terminal" });
|
|
51
|
+
// An account sign-in: a key cannot be typed into a ticket.
|
|
52
|
+
const io = ticketLoginIO(answerer.step, command);
|
|
53
|
+
const failed = await loginOnBox({ ...request, method: "oauth", input: true, io });
|
|
54
|
+
if (failed !== undefined)
|
|
55
|
+
return io.refusal() ?? failed;
|
|
56
|
+
// Logged in: what follows (the webhooks) is the deploy finishing, never cut by the person's deadline.
|
|
57
|
+
answerer.step.person.carriesOn();
|
|
58
|
+
return undefined;
|
|
59
|
+
},
|
|
41
60
|
},
|
|
42
61
|
};
|
|
43
62
|
}
|
|
@@ -54,7 +73,7 @@ export async function planArtifacts(target, artifacts, options) {
|
|
|
54
73
|
for (const a of artifacts) {
|
|
55
74
|
const abs = join(target, a.path);
|
|
56
75
|
// Pure build output, not operator-owned configuration. It must track the generated template/runbook.
|
|
57
|
-
if (a.path
|
|
76
|
+
if (BUILD_OUTPUTS.includes(basename(a.path)) || options.alwaysWrite?.includes(a.path)) {
|
|
58
77
|
write(a.path, abs, a.content);
|
|
59
78
|
continue;
|
|
60
79
|
}
|
|
@@ -67,7 +86,7 @@ export async function planArtifacts(target, artifacts, options) {
|
|
|
67
86
|
(a.path.endsWith(".dockerignore")
|
|
68
87
|
? `; see the preflight warnings for what it must exclude`
|
|
69
88
|
: a.path.endsWith("Dockerfile")
|
|
70
|
-
? `; deploy still assumes it listens on $PORT and runs \`fastagent start
|
|
89
|
+
? `; deploy still assumes it listens on $PORT and runs \`fastagent start ${IMAGE_DEFINITION_DIR}\``
|
|
71
90
|
: ``));
|
|
72
91
|
continue;
|
|
73
92
|
}
|
|
@@ -88,7 +107,7 @@ export async function planArtifacts(target, artifacts, options) {
|
|
|
88
107
|
export async function applyArtifactPlan(plan) {
|
|
89
108
|
for (const step of plan.steps) {
|
|
90
109
|
if (step.content !== undefined) {
|
|
91
|
-
await mkdir(dirname(step.abs), { recursive: true });
|
|
110
|
+
await mkdir(dirname(step.abs), { recursive: true });
|
|
92
111
|
await writeFile(step.abs, step.content);
|
|
93
112
|
}
|
|
94
113
|
console.error(step.message);
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `fastagent deploy <host> [dir]`: generate host artifacts from the resolved definition and print an ordered deploy
|
|
3
|
-
* runbook.
|
|
4
|
-
*/
|
|
5
1
|
import type { DeployHost } from "../../deploy/hosts.ts";
|
|
6
2
|
import { type DeployOptions, type HostDeploy, applyArtifactPlan, planArtifacts } from "./deploy/shared.ts";
|
|
7
3
|
export { applyArtifactPlan, planArtifacts };
|
|
@@ -1,12 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `fastagent deploy <host> [agent]`: generate host artifacts from the resolved definition and print an ordered deploy
|
|
3
|
+
* runbook.
|
|
4
|
+
*/
|
|
5
|
+
import { relative } from "node:path";
|
|
6
|
+
import { cloudFor } from "../../channels/feishu/cloud.js";
|
|
7
|
+
import { FEISHU_INGRESS_SETTINGS } from "../../channels/feishu/setup-mode.js";
|
|
8
|
+
import { assembleSecrets, divergentSettingsGate, missingValuesGate } from "../../deploy/secrets.js";
|
|
9
|
+
import { dotEnvPath, loadEnvValues } from "../../env.js";
|
|
10
|
+
import { unmarkDevServe } from "../../serving-command.js";
|
|
11
|
+
import { assertIndependentFeishuApps, feishuAppSecretNames, larkCredentialsNeeded, prepareFeishuApps, unpreparedFeishuApps, } from "../add-feishu.js";
|
|
12
|
+
import { displayPath, selectAgentEnvironment } from "../../paths.js";
|
|
1
13
|
import { preflightDeploy } from "../../deploy/preflight.js";
|
|
2
|
-
import {
|
|
14
|
+
import { apiReport, deploymentApi, writeApiKey } from "../../deploy/api.js";
|
|
15
|
+
import { unprotectedSecretsNote } from "../../value-file.js";
|
|
16
|
+
import { loadConfig } from "../../harnesses/pi-durable/open.js";
|
|
3
17
|
import { failStartup, failUsage } from "../fail.js";
|
|
4
|
-
import { enterAgentDirectory } from "../shared.js";
|
|
18
|
+
import { enterAgentDirectory, isInteractive, shellArg } from "../shared.js";
|
|
19
|
+
import { terminalPerson } from "../person.js";
|
|
20
|
+
import { checkTicket, printReport, refusedCheck, runTicket, startTicket, stopTicket, ticketExitCode, ticketReport, } from "../ticket.js";
|
|
5
21
|
import { agentcoreHost } from "./deploy/agentcore.js";
|
|
6
22
|
import { dockerHost } from "./deploy/docker.js";
|
|
7
23
|
import { flyHost } from "./deploy/fly.js";
|
|
8
24
|
import { railwayHost } from "./deploy/railway.js";
|
|
9
|
-
import { applyArtifactPlan, planArtifacts } from "./deploy/shared.js";
|
|
25
|
+
import { applyArtifactPlan, planArtifacts, } from "./deploy/shared.js";
|
|
10
26
|
export { applyArtifactPlan, planArtifacts };
|
|
11
27
|
/** Every host, by the name the CLI takes. */
|
|
12
28
|
export const HOSTS = {
|
|
@@ -50,59 +66,230 @@ export function warnHostOnlyFlags(host, opts) {
|
|
|
50
66
|
console.error(`[fastagent] warn: ${rule.flag}: ${rule.owner}-only — ${instead}`);
|
|
51
67
|
}
|
|
52
68
|
}
|
|
69
|
+
/** The command that reads a deploy's ticket, as every such ticket records it. */
|
|
70
|
+
const deployCheck = (host) => `fastagent deploy ${host} --check`;
|
|
71
|
+
/** How long a coding agent's deploy stays open: a build, and the person's steps between. */
|
|
72
|
+
const TICKET_TIMEOUT_SECONDS = 3600;
|
|
53
73
|
export async function runDeploy(host, dirArg, opts) {
|
|
74
|
+
if (opts.check !== undefined)
|
|
75
|
+
return checkDeploy(host, opts.check, opts);
|
|
76
|
+
if (opts.stop)
|
|
77
|
+
failUsage("--stop stops a deploy started with --json: pass --check <ticket> too");
|
|
78
|
+
if (opts.ticket !== undefined) {
|
|
79
|
+
// The process `startTicket` started: it takes the ticket before the pre-flight (seconds of building the
|
|
80
|
+
// definition), then does the whole deploy, its person the ticket's.
|
|
81
|
+
await runTicket(opts.ticket, (step) => deploy(host, dirArg, opts, step));
|
|
82
|
+
process.exit(0);
|
|
83
|
+
}
|
|
84
|
+
await deploy(host, dirArg, opts);
|
|
85
|
+
}
|
|
86
|
+
/** The deploy itself: through a ticket's `step` when one runs it, else at this terminal or with nobody to ask. */
|
|
87
|
+
async function deploy(host, dirArg, opts, step) {
|
|
88
|
+
if (opts.code !== undefined)
|
|
89
|
+
failUsage("--code hands a code to a deploy's ticket: pass --check <ticket> too");
|
|
54
90
|
if (opts.tunnel && host !== "docker") {
|
|
55
91
|
// A flag/host combination the parser cannot see (host is an argument) — usage class, exit 2.
|
|
56
92
|
failUsage(`deploy stopped: --tunnel is supported only by the local Docker target`);
|
|
57
93
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const { agentDir
|
|
62
|
-
const
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
94
|
+
if (opts.json && !opts.run)
|
|
95
|
+
failUsage("--json reports a deploy --run drives: pass --run too");
|
|
96
|
+
selectAgentEnvironment("production");
|
|
97
|
+
const { agentDir } = await enterAgentDirectory(dirArg, opts);
|
|
98
|
+
const config = await loadConfig(agentDir).catch(failStartup);
|
|
99
|
+
// Never `dev`, whatever spawned this; and what decides a channel's shape is read here as the box will read it.
|
|
100
|
+
unmarkDevServe();
|
|
101
|
+
const shaped = divergentSettingsGate(FEISHU_INGRESS_SETTINGS, process.env, loadEnvValues(dotEnvPath(agentDir)), relative(agentDir, dotEnvPath(agentDir)));
|
|
102
|
+
if (shaped)
|
|
103
|
+
failStartup(new Error(`deploy stopped: ${shaped}`));
|
|
104
|
+
const independentApps = (values) => {
|
|
105
|
+
try {
|
|
106
|
+
assertIndependentFeishuApps(agentDir, ["feishu", "lark"], values);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
failStartup(error);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
independentApps(loadEnvValues(dotEnvPath(agentDir)));
|
|
113
|
+
const api = deploymentApi({
|
|
67
114
|
config,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// AgentCore DOES get a public URL (the forwarder's, AuthType NONE) — but nothing of ours answers behind it:
|
|
72
|
-
// that relay reaches the channels' routes only, each verifying its platform's signature (agentcore-service.ts).
|
|
73
|
-
publicUrl: host !== "agentcore",
|
|
74
|
-
}).catch(failStartup);
|
|
75
|
-
if (!pre.ok)
|
|
76
|
-
failStartup(new Error(`deploy stopped: ${pre.gate}`));
|
|
77
|
-
for (const m of pre.messages)
|
|
78
|
-
console.error(`[fastagent] ${m.level}: ${m.text}`);
|
|
79
|
-
const { channels } = pre;
|
|
80
|
-
warnHostOnlyFlags(host, opts);
|
|
115
|
+
hostServes: host !== "agentcore",
|
|
116
|
+
values: loadEnvValues(dotEnvPath(agentDir)),
|
|
117
|
+
});
|
|
81
118
|
const target = HOSTS[host];
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
119
|
+
const preflight = async () => {
|
|
120
|
+
const facts = await preflightDeploy({
|
|
121
|
+
agentDir,
|
|
122
|
+
config,
|
|
123
|
+
run: !!opts.run,
|
|
124
|
+
force: !!opts.force,
|
|
125
|
+
noResidentProcess: host === "agentcore", // alarms and webhooks wake the container there — no machine to keep up
|
|
126
|
+
// Every AgentCore deployment starts the storage over (core.md §9).
|
|
127
|
+
storageResets: host === "agentcore",
|
|
128
|
+
servesApi: api.served,
|
|
129
|
+
}).catch(failStartup);
|
|
130
|
+
if (!facts.ok)
|
|
131
|
+
failStartup(new Error(`deploy stopped: ${facts.gate}`));
|
|
132
|
+
target.validate?.({ opts, agentDir, pre: facts });
|
|
133
|
+
return facts;
|
|
134
|
+
};
|
|
135
|
+
let pre = await preflight();
|
|
136
|
+
const agentArg = displayPath(process.cwd(), agentDir);
|
|
137
|
+
const rerun = `fastagent deploy ${host}${agentArg === undefined ? "" : ` ${shellArg(agentArg)}`}` +
|
|
138
|
+
`${opts.tunnel ? " --tunnel" : ""}${opts.intoLinked ? " --into-linked" : ""} --run`;
|
|
139
|
+
const unprepared = opts.run ? unpreparedFeishuApps(pre.channels, pre.values) : [];
|
|
140
|
+
if (opts.json && step === undefined) {
|
|
141
|
+
// A coding agent's deploy: what this machine can refuse is refused above, at once; the rest runs in a ticket.
|
|
142
|
+
if (unprepared.some(({ kind }) => kind === "lark")) {
|
|
143
|
+
const needed = await larkCredentialsNeeded(agentDir, rerun).catch(failStartup);
|
|
144
|
+
if (needed !== undefined) {
|
|
145
|
+
printReport(true, needed.json, needed.text);
|
|
146
|
+
process.exit(0);
|
|
104
147
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
148
|
+
}
|
|
149
|
+
const timeout = opts.timeout === undefined ? TICKET_TIMEOUT_SECONDS : Number(opts.timeout);
|
|
150
|
+
if (!Number.isInteger(timeout) || timeout <= 0)
|
|
151
|
+
failUsage("--timeout must be a whole number of seconds");
|
|
152
|
+
const ticket = await startTicket({
|
|
153
|
+
subject: `deploy:${host}:${agentDir}`,
|
|
154
|
+
fields: { deployment: host },
|
|
155
|
+
action: `deploy the agent to ${host}`,
|
|
156
|
+
check: deployCheck(host),
|
|
157
|
+
restart: rerun,
|
|
158
|
+
timeoutSeconds: timeout,
|
|
159
|
+
waitsFirst: false,
|
|
160
|
+
// A deploy stopped halfway leaves the host half-changed: one already running is the answer.
|
|
161
|
+
whenRunning: "join",
|
|
162
|
+
command: {
|
|
163
|
+
file: process.execPath,
|
|
164
|
+
args: [
|
|
165
|
+
...process.execArgv,
|
|
166
|
+
process.argv[1],
|
|
167
|
+
"deploy",
|
|
168
|
+
host,
|
|
169
|
+
agentDir,
|
|
170
|
+
...(opts.tunnel ? ["--tunnel"] : []),
|
|
171
|
+
...(opts.force ? ["--force"] : []),
|
|
172
|
+
...(opts.intoLinked ? ["--into-linked"] : []),
|
|
173
|
+
"--run",
|
|
174
|
+
"--json",
|
|
175
|
+
],
|
|
176
|
+
cwd: process.cwd(),
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
reportDeploy(ticket, "started");
|
|
180
|
+
process.exit(ticketExitCode(ticket));
|
|
181
|
+
}
|
|
182
|
+
/** Everything past the pre-flight, its person's steps taken by `answerer`; the URL and what the API report says. */
|
|
183
|
+
const deployWith = async (answerer) => {
|
|
184
|
+
if (unprepared.length > 0) {
|
|
185
|
+
const supplied = unprepared.flatMap(({ kind, ingress }) => feishuAppSecretNames(kind, ingress));
|
|
186
|
+
const kinds = unprepared.map(({ kind }) => kind);
|
|
187
|
+
const { values } = pre;
|
|
188
|
+
const absent = supplied.filter((name) => !values.get(name)?.trim());
|
|
189
|
+
const { missingSecrets } = assembleSecrets({
|
|
190
|
+
modelAuth: pre.modelAuth,
|
|
191
|
+
declared: pre.declaredSecrets,
|
|
192
|
+
values: pre.values,
|
|
193
|
+
});
|
|
194
|
+
const missing = missingValuesGate(missingSecrets.filter((name) => !supplied.includes(name)), pre.valueFile);
|
|
195
|
+
if (missing)
|
|
196
|
+
failStartup(new Error(`deploy stopped: ${missing}`));
|
|
197
|
+
if (host === "docker" && !opts.tunnel && unprepared.some(({ ingress }) => ingress === "webhook")) {
|
|
198
|
+
failStartup(new Error(`deploy stopped: ${kinds.join(", ")} receive by webhook here, and this Docker deployment has no ` +
|
|
199
|
+
`public URL to point the app at — re-run with --tunnel (the app is prepared then), or set up your own ` +
|
|
200
|
+
`ingress and supply ${absent.join(", ")} from a separate production app in ${pre.valueFile}, or ` +
|
|
201
|
+
`set ${kinds.map((kind) => `${cloudFor(kind).envPrefix}_INGRESS=websocket`).join(", ")} there`));
|
|
202
|
+
}
|
|
203
|
+
if (answerer.kind === "nobody") {
|
|
204
|
+
failUsage(`deploy stopped: ${pre.valueFile} has no ${absent.join(", ")}: setting up the separate production app ` +
|
|
205
|
+
`needs a person — run this deploy in a terminal; from a coding agent, run \`${rerun} --json\`, which ` +
|
|
206
|
+
`hands their part to its user`);
|
|
207
|
+
}
|
|
208
|
+
const person = answerer.kind === "ticket" ? answerer.step.person : terminalPerson;
|
|
209
|
+
const again = answerer.kind === "ticket" ? `${rerun} --json` : rerun;
|
|
210
|
+
await prepareFeishuApps(agentDir, unprepared, again, person).catch(failStartup);
|
|
211
|
+
pre = await preflight();
|
|
212
|
+
}
|
|
213
|
+
independentApps(pre.values);
|
|
214
|
+
if (api.served && api.generatesKey) {
|
|
215
|
+
// Past every refusal the pre-flight makes, and read again, so this deploy carries it.
|
|
216
|
+
const unprotected = await writeApiKey(agentDir).catch(failStartup);
|
|
217
|
+
if (unprotected !== undefined)
|
|
218
|
+
console.error(`[fastagent] note: ${unprotectedSecretsNote(unprotected)}`);
|
|
219
|
+
pre = await preflight();
|
|
220
|
+
}
|
|
221
|
+
for (const m of pre.messages)
|
|
222
|
+
console.error(`[fastagent] ${m.level}: ${m.text}`);
|
|
223
|
+
const { channels } = pre;
|
|
224
|
+
warnHostOnlyFlags(host, opts);
|
|
225
|
+
// What follows is the host's work: a deadline meant for the person must never cut it halfway. Its own steps for
|
|
226
|
+
// the person (a host sign-in, the box's login) wait again, and are bounded again.
|
|
227
|
+
if (answerer.kind === "ticket")
|
|
228
|
+
answerer.step.person.carriesOn();
|
|
229
|
+
const reachedAt = await target.deploy({
|
|
230
|
+
opts,
|
|
231
|
+
answerer,
|
|
232
|
+
rerun,
|
|
233
|
+
agentDir,
|
|
234
|
+
config,
|
|
235
|
+
pre,
|
|
236
|
+
channels,
|
|
237
|
+
webhookChannels: channels.filter((channel) => channel.ingress === "webhook"),
|
|
238
|
+
// The ownership predicate is bound HERE, from the same lookup that chose the host, so no host module can pass
|
|
239
|
+
// one.
|
|
240
|
+
// Reporting a stale artifact is enough when only generating them — the operator reads the line and decides. But
|
|
241
|
+
// `--run` would then deploy FROM it: a determinate mismatch between what ships and what the definition says,
|
|
242
|
+
// the same class as a Dockerfile that cannot read the manifest, and gated the
|
|
243
|
+
// same way. `--force` regenerates ours; a file we did not generate is never touched by either, and the marker
|
|
244
|
+
// line is how an operator takes a path back on purpose.
|
|
245
|
+
write: async (artifacts, options) => {
|
|
246
|
+
const plan = await planArtifacts(agentDir, artifacts, { ...options, isOurs: target.isOurs });
|
|
247
|
+
if (opts.run && plan.stale.length > 0) {
|
|
248
|
+
failStartup(new Error(`deploy stopped: ${plan.stale.join(", ")} no longer match what this definition generates, and --run ` +
|
|
249
|
+
`would deploy from them. Re-run with --force to regenerate, or remove each file's generated-by ` +
|
|
250
|
+
`marker to own it yourself.`));
|
|
251
|
+
}
|
|
252
|
+
await applyArtifactPlan(plan);
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
const notes = apiReport(api, { valueFile: pre.valueFile, agentArg }, reachedAt);
|
|
256
|
+
for (const line of notes)
|
|
257
|
+
console.error(`[fastagent] ${line}`);
|
|
258
|
+
return { ...(reachedAt === undefined ? {} : { url: reachedAt }), notes };
|
|
259
|
+
};
|
|
260
|
+
if (step !== undefined)
|
|
261
|
+
return deployWith({ kind: "ticket", step });
|
|
262
|
+
return deployWith(opts.input === false || !isInteractive() ? { kind: "nobody" } : { kind: "terminal" });
|
|
263
|
+
}
|
|
264
|
+
/** `deploy <host> --check <ticket> [--code <code>]`. */
|
|
265
|
+
async function checkDeploy(host, id, opts) {
|
|
266
|
+
const refused = refusedCheck(id, deployCheck(host));
|
|
267
|
+
if (refused !== undefined)
|
|
268
|
+
failUsage(refused);
|
|
269
|
+
// There: refusedCheck read it, and a ticket is pruned only a day after it ends.
|
|
270
|
+
const ticket = opts.stop ? await stopTicket(id) : (await checkTicket(id, opts.code));
|
|
271
|
+
reportDeploy(ticket, "checked");
|
|
272
|
+
process.exit(ticketExitCode(ticket));
|
|
273
|
+
}
|
|
274
|
+
/** A deploy's ticket for the agent that started or checked it, always as JSON: `--json` is how one started. */
|
|
275
|
+
function reportDeploy(ticket, when) {
|
|
276
|
+
const report = ticketReport(ticket, when, (result) => ({
|
|
277
|
+
fields: result,
|
|
278
|
+
text: [],
|
|
279
|
+
next: result.url === undefined
|
|
280
|
+
? "Deployed. Tell the user what the notes say."
|
|
281
|
+
: `Deployed to ${String(result.url)}. Tell the user what the notes say.`,
|
|
282
|
+
}));
|
|
283
|
+
const running = ticket.status === "starting" || ticket.status === "working" || ticket.status === "need_user_action";
|
|
284
|
+
if (!running) {
|
|
285
|
+
printReport(true, report.json, []);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
// A deploy finishing is never cut by its deadline, so one that hangs there ends only on someone's say.
|
|
289
|
+
const stop = `${ticket.check} ${ticket.ticket} --stop --json`;
|
|
290
|
+
const hung = ticket.status === "need_user_action"
|
|
291
|
+
? ""
|
|
292
|
+
: " If its log has shown no progress for a long while, stop_command stops it where it is, which can leave the " +
|
|
293
|
+
"host half-changed: ask the user first.";
|
|
294
|
+
printReport(true, { ...report.json, stop_command: stop, agent_next_steps: `${String(report.json.agent_next_steps)}${hung}` }, []);
|
|
108
295
|
}
|