@fastagent-sh/fastagent 0.24.4 → 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 -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/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
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* workspace's deployed box instead (box-login.ts); `--stdio` is the box's half of that.
|
|
5
|
-
*/
|
|
6
|
-
import { existsSync } from "node:fs";
|
|
7
|
-
import { join } from "node:path";
|
|
8
|
-
import { enterAgentEnv } from "../../env.js";
|
|
9
|
-
import { GLOBAL_AUTH_PATH, resolveAuthPath } from "../../engines/pi/auth.js";
|
|
10
|
-
import { agentModels } from "../../engines/pi/agent-models.js";
|
|
1
|
+
import { enterAgentEnv, dotEnvPath } from "../../env.js";
|
|
2
|
+
import { GLOBAL_AUTH_PATH, resolveAuthPath, } from "../../harnesses/models/credentials.js";
|
|
3
|
+
import { modelEnvironment } from "../../harnesses/models/environment.js";
|
|
11
4
|
import { DEPLOY_HOSTS } from "../../deploy/hosts.js";
|
|
12
|
-
import { findAgentDir, globalHome,
|
|
13
|
-
import { LoginCancelled, loginFlow } from "../../
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
5
|
+
import { findAgentDir, globalHome, selectAgentEnvironment } from "../../paths.js";
|
|
6
|
+
import { LoginCancelled, LoginRefused, PI_DEFAULT_MODELS, chooseLogin, loginFlow, loginOptionsOver, loginOver, loginStatusText, } from "../../harnesses/models/login.js";
|
|
7
|
+
import { environmentAuth, keyVariables, loginProviders } from "../../harnesses/models/models.js";
|
|
8
|
+
import { definitionProviders, loadConfig, modelSpecFor } from "../../harnesses/pi-durable/open.js";
|
|
9
|
+
import { loginOnBox, ticketLoginIO } from "../box-login.js";
|
|
10
|
+
import { deploymentLoginCommand } from "../../deploy/box-shell.js";
|
|
11
|
+
import { agentDirOrExit, failStartup, failUsage, optionalAgentDirOrExit } from "../fail.js";
|
|
12
|
+
import { printReport, refusedCheck, checkTicket, runTicket, startTicket, ticketExitCode, ticketReport, } from "../ticket.js";
|
|
17
13
|
import { stdioLoginIO } from "../login-relay.js";
|
|
18
14
|
import { isInteractive, terminalLoginIO } from "../shared.js";
|
|
19
15
|
import { HOSTS } from "./deploy.js";
|
|
16
|
+
/** The command that reads a sign-in's ticket, as every such ticket records it. */
|
|
17
|
+
const LOGIN_CHECK = "fastagent login --check";
|
|
18
|
+
/** Without a terminal, how long a sign-in stays open for the person to finish it. */
|
|
19
|
+
const UNATTENDED_TIMEOUT_SECONDS = 600;
|
|
20
20
|
export async function runLogin(provider, opts) {
|
|
21
21
|
if (opts.stdio)
|
|
22
22
|
return runStdioLogin(provider, opts);
|
|
23
23
|
if (opts.deployment !== undefined)
|
|
24
24
|
return runDeploymentLogin(provider, opts);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
if (opts.check !== undefined)
|
|
26
|
+
return runCheck(opts.check, opts);
|
|
27
|
+
if (opts.code !== undefined)
|
|
28
|
+
failUsage("--code hands an address to a sign-in: pass --check <ticket> too");
|
|
29
|
+
const method = opts.method === undefined ? undefined : methodOf(opts.method);
|
|
30
|
+
const givenTimeout = opts.timeout === undefined ? undefined : secondsOf(opts.timeout);
|
|
31
|
+
// "Outside an agent" must mean exactly that: inside one is refused (findAgentDir), never a global login.
|
|
32
|
+
const agentDir = optionalAgentDirOrExit(process.cwd());
|
|
30
33
|
// Outside any agent the target is the user-global machinery home — handed over explicitly, so the path resolvers
|
|
31
34
|
// need no "is this $HOME?" special case to infer it.
|
|
32
35
|
const loginDir = agentDir ?? globalHome();
|
|
@@ -41,86 +44,425 @@ export async function runLogin(provider, opts) {
|
|
|
41
44
|
// exactly where the operator said, or a second `login` for a provider they already have globally would silently
|
|
42
45
|
// rewrite the global credential instead of creating the project-level override they asked for.
|
|
43
46
|
const authPath = opts.global ? GLOBAL_AUTH_PATH : resolveAuthPath(loginDir);
|
|
47
|
+
const ownAgent = opts.global ? undefined : agentDir;
|
|
48
|
+
// The definition's providers too: a gateway's key is verified against the gateway, not a built-in's endpoint. Not for
|
|
49
|
+
// `-g`: the global file serves every agent on this machine, so no one agent's providers decide what it holds.
|
|
50
|
+
const providersOf = () => (ownAgent ? definitionProviders(ownAgent) : Promise.resolve([]));
|
|
51
|
+
if (opts.ticket !== undefined) {
|
|
52
|
+
// The process `startTicket` started: it takes the ticket before loading the definition, then signs in.
|
|
53
|
+
await runTicket(opts.ticket, async (step) => {
|
|
54
|
+
const providers = await providersOf();
|
|
55
|
+
const interaction = signInInteraction(step, provider);
|
|
56
|
+
await loginOver({ provider: provider, method: "oauth", authPath, interaction }, { providers });
|
|
57
|
+
const model = ownAgent ? await defaultModelHint(ownAgent, provider) : undefined;
|
|
58
|
+
const name = loginProviders(providers).find((p) => p.id === provider)?.name ?? provider;
|
|
59
|
+
return { provider, path: authPath, ...(model === undefined ? {} : { model, name }) };
|
|
60
|
+
});
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
const providers = await providersOf().catch(failStartup);
|
|
44
64
|
// Announce when the FALLBACK is what decided the target: outside an agent with no explicit path, the credential
|
|
45
65
|
// lands somewhere no agent will read.
|
|
46
66
|
if (!agentDir && !opts.global && !process.env.FASTAGENT_AUTH_PATH) {
|
|
47
|
-
console.error(`[fastagent] no agent here (no fastagent.config.ts
|
|
67
|
+
console.error(`[fastagent] no agent here (no fastagent.config.ts) — ` +
|
|
48
68
|
`logging in GLOBALLY (${authPath}). An agent on this machine uses this file for a provider it has no ` +
|
|
49
|
-
`credential of its own for (no entry in its .secrets/auth.json, no
|
|
50
|
-
`
|
|
69
|
+
`credential of its own for (no entry in its .secrets/auth.json, no env variable), so this is usually what ` +
|
|
70
|
+
`you want; \`cd\` into an agent to give that one its own account instead.`);
|
|
51
71
|
}
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
// What the agent reads, its file over the global one, is what authenticates each provider for it now.
|
|
73
|
+
const statusFrom = ownAgent
|
|
74
|
+
? (await modelEnvironment(ownAgent, {}, providers)).credentials
|
|
75
|
+
: authPath;
|
|
76
|
+
if (opts.input === false || opts.json === true || !isInteractive()) {
|
|
77
|
+
const offered = await loginOptionsOver(statusFrom, providers);
|
|
78
|
+
return requestLogin(offered, { provider, method }, opts, {
|
|
79
|
+
authPath,
|
|
80
|
+
providers,
|
|
81
|
+
valueFile: ownAgent === undefined ? undefined : dotEnvPath(ownAgent),
|
|
82
|
+
heldIn: async (id) => (typeof statusFrom === "string" ? statusFrom : statusFrom.layerOf(id)),
|
|
83
|
+
timeoutSeconds: givenTimeout ?? UNATTENDED_TIMEOUT_SECONDS,
|
|
84
|
+
});
|
|
56
85
|
}
|
|
86
|
+
const timeout = givenTimeout === undefined ? undefined : AbortSignal.timeout(givenTimeout * 1000);
|
|
57
87
|
// An entered API key is verified with one minimal request (login.ts); a rejected one is asked for again.
|
|
58
|
-
// Inside an agent, the key is checked on that agent's registry: its models.json may point a provider at a gateway.
|
|
59
|
-
// Not with `-g`: the global file serves every agent on the machine, so no one agent's routing may judge its key.
|
|
60
88
|
const result = await loginFlow(terminalLoginIO(), {
|
|
61
89
|
authPath,
|
|
90
|
+
providers,
|
|
91
|
+
statusFrom: typeof statusFrom === "string" ? undefined : statusFrom,
|
|
62
92
|
...(provider ? { provider } : {}),
|
|
63
|
-
...(
|
|
93
|
+
...(method ? { method } : {}),
|
|
94
|
+
...(timeout ? { signal: timeout } : {}),
|
|
64
95
|
}).catch((error) => {
|
|
96
|
+
if (timeout?.aborted)
|
|
97
|
+
failStartup(new Error(`login timed out after ${givenTimeout}s (--timeout)`));
|
|
65
98
|
if (error instanceof LoginCancelled) {
|
|
66
99
|
// A decision, not a failure — neutral wording; non-zero exit because no credential was stored.
|
|
67
100
|
console.error(`[fastagent] login cancelled`);
|
|
68
101
|
process.exit(1);
|
|
69
102
|
}
|
|
103
|
+
if (error instanceof LoginRefused)
|
|
104
|
+
failUsage(error.message);
|
|
70
105
|
failStartup(error);
|
|
71
106
|
});
|
|
72
|
-
|
|
107
|
+
const name = loginProviders(providers).find((p) => p.id === result.provider)?.name ?? result.provider;
|
|
108
|
+
console.error(result.method === "oauth"
|
|
109
|
+
? `[fastagent] logged in to ${name} — saved to ${authPath}`
|
|
110
|
+
: `[fastagent] saved the API key for ${name} to ${authPath}`);
|
|
111
|
+
const model = ownAgent ? await defaultModelHint(ownAgent, result.provider) : undefined;
|
|
112
|
+
if (model !== undefined)
|
|
113
|
+
console.error(`[fastagent] ${modelHint(model, name)}`);
|
|
73
114
|
// The environment outranks the global file for every agent, so a global login it shadows would sit unused while
|
|
74
115
|
// agents run on, say, an API key billed per request, with only a startup line to show it.
|
|
75
|
-
const shadowedBy = authPath === GLOBAL_AUTH_PATH ? await
|
|
116
|
+
const shadowedBy = authPath === GLOBAL_AUTH_PATH ? (await environmentAuth(result.provider, shellEnv))?.source : undefined;
|
|
76
117
|
if (shadowedBy !== undefined) {
|
|
77
118
|
console.error(`[fastagent] warning: ${result.provider} is also authenticated by ${shadowedBy} in your shell environment, which ` +
|
|
78
119
|
`agents use before the global file, so this login is not used while it is set. Unset it to use this login.`);
|
|
79
120
|
}
|
|
80
121
|
process.exit(0); // the undici proxy agent's keep-alive sockets would otherwise hold the event loop open
|
|
81
122
|
}
|
|
123
|
+
const modelHint = (model, name) => `this agent has no model: \`model: "${model}"\` in fastagent.config.ts uses ${name}'s default`;
|
|
124
|
+
/** `--method`'s words, pi's: an account (OAuth) or an API key. */
|
|
125
|
+
function methodOf(value) {
|
|
126
|
+
if (value === "account")
|
|
127
|
+
return "oauth";
|
|
128
|
+
if (value === "api-key")
|
|
129
|
+
return "api_key";
|
|
130
|
+
return failUsage(`--method must be account or api-key, not "${value}"`);
|
|
131
|
+
}
|
|
132
|
+
const methodWord = (method) => (method === "oauth" ? "account" : "api-key");
|
|
133
|
+
function secondsOf(value) {
|
|
134
|
+
const seconds = Number(value);
|
|
135
|
+
if (!Number.isInteger(seconds) || seconds <= 0)
|
|
136
|
+
failUsage(`--timeout must be a whole number of seconds, not "${value}"`);
|
|
137
|
+
return seconds;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* pi's default model for `provider`, when the agent in `agentDir` has no model of its own: what pi starts on after a
|
|
141
|
+
* sign-in. Printed, never written: the model belongs in the author's own config.
|
|
142
|
+
*/
|
|
143
|
+
async function defaultModelHint(agentDir, provider) {
|
|
144
|
+
const config = await loadConfig(agentDir).catch(failStartup);
|
|
145
|
+
if (modelSpecFor(config, undefined) !== undefined)
|
|
146
|
+
return undefined;
|
|
147
|
+
const modelId = PI_DEFAULT_MODELS[provider];
|
|
148
|
+
return modelId === undefined ? undefined : `${provider}/${modelId}`;
|
|
149
|
+
}
|
|
82
150
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
151
|
+
* Login with no one at a terminal to ask, as Netlify's `login --request` and Dosu's tickets have it: a choice not
|
|
152
|
+
* given is named with a command for each way (`need_choice`, exit 2); an account sign-in starts in a process of its
|
|
153
|
+
* own and returns its address with a ticket (`need_user_action`, exit 0); an API key is the person's to set where the
|
|
154
|
+
* agent reads it, never handed through the agent (`need_user_action` naming the variables).
|
|
155
|
+
*/
|
|
156
|
+
async function requestLogin(offered, given, opts, target) {
|
|
157
|
+
const global = opts.global ? " -g" : "";
|
|
158
|
+
let choice;
|
|
159
|
+
try {
|
|
160
|
+
choice = await chooseLogin(offered, given, undefined);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (!(error instanceof LoginRefused))
|
|
164
|
+
throw error;
|
|
165
|
+
return choiceNotGiven(error, opts, { flags: global, statuses: true });
|
|
166
|
+
}
|
|
167
|
+
if (choice.method === "api_key")
|
|
168
|
+
return keyNeeded(choice, opts, target);
|
|
169
|
+
const ticket = await startTicket({
|
|
170
|
+
// One subject per provider, here or on a deployment: they hold the same callback port on this machine.
|
|
171
|
+
subject: `login:${choice.provider}`,
|
|
172
|
+
fields: { provider: choice.provider, method: "account" },
|
|
173
|
+
action: `sign in to ${choice.name}`,
|
|
174
|
+
check: LOGIN_CHECK,
|
|
175
|
+
restart: `fastagent login ${choice.provider} --method account${global}`,
|
|
176
|
+
timeoutSeconds: target.timeoutSeconds,
|
|
177
|
+
waitsFirst: true,
|
|
178
|
+
whenRunning: "replace",
|
|
179
|
+
command: {
|
|
180
|
+
file: process.execPath,
|
|
181
|
+
args: [
|
|
182
|
+
...process.execArgv,
|
|
183
|
+
process.argv[1],
|
|
184
|
+
"login",
|
|
185
|
+
choice.provider,
|
|
186
|
+
"--method",
|
|
187
|
+
"account",
|
|
188
|
+
...(opts.global ? ["-g"] : []),
|
|
189
|
+
],
|
|
190
|
+
cwd: process.cwd(),
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
// No browser is opened: the agent hands the address to its person, who may be on another machine.
|
|
194
|
+
reportTicket(ticket, opts, "started");
|
|
195
|
+
process.exit(ticketExitCode(ticket));
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* An API key with no terminal to type it in: the variables the person sets themselves where the agent reads them, and
|
|
199
|
+
* how to tell it worked. With no agent's value file to name (`-g`, or no agent here), the person signs in at a terminal
|
|
200
|
+
* of their own, which keeps the key in the global file `auth check -g` reads: the agent's environment was fixed when it
|
|
201
|
+
* started, so a variable set now would never reach it.
|
|
202
|
+
*/
|
|
203
|
+
async function keyNeeded(choice, opts, target) {
|
|
204
|
+
const base = { provider: choice.provider, method: "api-key" };
|
|
205
|
+
if (choice.status?.type === "api_key") {
|
|
206
|
+
printReport(opts.json, { status: "ready", ...base, source: choice.status.source }, [
|
|
207
|
+
`ready: ${choice.name} is authenticated by ${choice.status.source}`,
|
|
208
|
+
]);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const check = `fastagent auth check --provider ${choice.provider}${target.valueFile === undefined ? " -g" : ""}`;
|
|
212
|
+
if (target.valueFile === undefined) {
|
|
213
|
+
const terminal = `fastagent login ${choice.provider} --method api-key -g`;
|
|
214
|
+
printReport(opts.json, {
|
|
215
|
+
status: "need_user_action",
|
|
216
|
+
...base,
|
|
217
|
+
terminal_command: terminal,
|
|
218
|
+
check_command: `${check} --json`,
|
|
219
|
+
agent_next_steps: "Ask the user to run terminal_command in a terminal of their own: it asks for the key there, not in this " +
|
|
220
|
+
"conversation, and keeps it in the global credentials file. Once they say they have, run check_command.",
|
|
221
|
+
}, [`need_user_action: run in a terminal of your own: ${terminal}`, `then run: ${check}`]);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// A stored account sign-in outranks any key in the environment: it goes first, or the key set now is never used.
|
|
225
|
+
const outranking = choice.status?.source === "OAuth" ? await target.heldIn(choice.provider) : undefined;
|
|
226
|
+
const logout = outranking === undefined
|
|
227
|
+
? undefined
|
|
228
|
+
: `fastagent logout ${choice.provider}${outranking === GLOBAL_AUTH_PATH ? " -g" : ""}`;
|
|
229
|
+
const { variables, what } = await keyToSet(choice, target.providers);
|
|
230
|
+
const first = logout === undefined
|
|
231
|
+
? ""
|
|
232
|
+
: `${choice.name} is signed in with an account in ${outranking}, which outranks a key in the environment: ` +
|
|
233
|
+
"run logout_command first (with the user's agreement: it removes that sign-in). Then ";
|
|
234
|
+
printReport(opts.json, {
|
|
235
|
+
status: "need_user_action",
|
|
236
|
+
...base,
|
|
237
|
+
variables,
|
|
238
|
+
value_file: target.valueFile,
|
|
239
|
+
...(logout === undefined ? {} : { logout_command: logout }),
|
|
240
|
+
check_command: `${check} --json`,
|
|
241
|
+
agent_next_steps: `${first}${first ? "ask" : "Ask"} the user to set ${what} in ${target.valueFile} themselves, not in this ` +
|
|
242
|
+
"conversation. Once they say they have, run check_command.",
|
|
243
|
+
}, [
|
|
244
|
+
...(logout === undefined ? [] : [`first, to replace the account sign-in in ${outranking}: ${logout}`]),
|
|
245
|
+
`need_user_action: set ${what} in ${target.valueFile}`,
|
|
246
|
+
`then run: ${check}`,
|
|
247
|
+
]);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* A sign-in not chosen with no one to ask (exit 2): with `--json`, the choices and the command for each, `flags`
|
|
251
|
+
* added to it. `statuses`: what authenticates each provider here is worth showing (it is not, for a deployment).
|
|
252
|
+
*/
|
|
253
|
+
function choiceNotGiven(error, opts, how) {
|
|
254
|
+
if (opts.json) {
|
|
255
|
+
const choices = error.choices.map((o) => ({
|
|
256
|
+
provider: o.provider,
|
|
257
|
+
name: o.name,
|
|
258
|
+
method: methodWord(o.method),
|
|
259
|
+
label: o.label,
|
|
260
|
+
...(how.statuses ? { status: loginStatusText(o) } : {}),
|
|
261
|
+
command: `fastagent login ${o.provider} --method ${methodWord(o.method)}${how.flags} --json`,
|
|
262
|
+
}));
|
|
263
|
+
printReport(true, {
|
|
264
|
+
status: "need_choice",
|
|
265
|
+
message: error.message,
|
|
266
|
+
choices,
|
|
267
|
+
agent_next_steps: "Ask the user which of these to sign in with, then run that choice's command.",
|
|
268
|
+
}, []);
|
|
269
|
+
}
|
|
270
|
+
return failUsage(error.message);
|
|
271
|
+
}
|
|
272
|
+
/** The variables `choice`'s key is read from, and how to tell the person to set it. */
|
|
273
|
+
async function keyToSet(choice, providers) {
|
|
274
|
+
const provider = loginProviders(providers).find((p) => p.id === choice.provider);
|
|
275
|
+
const variables = provider ? await keyVariables(provider) : [];
|
|
276
|
+
const what = variables.length === 0
|
|
277
|
+
? `its key as ${choice.name}'s own documentation says`
|
|
278
|
+
: variables.length === 1
|
|
279
|
+
? `${variables[0]}=<their ${choice.name} key>`
|
|
280
|
+
: `the variables ${choice.name} reads its key from (${variables.join(", ")})`;
|
|
281
|
+
return { variables, what };
|
|
282
|
+
}
|
|
283
|
+
/** `login --check <ticket> [--code <address>]`. */
|
|
284
|
+
async function runCheck(id, opts) {
|
|
285
|
+
const refused = refusedCheck(id, LOGIN_CHECK);
|
|
286
|
+
if (refused !== undefined)
|
|
287
|
+
failUsage(refused);
|
|
288
|
+
// There: refusedCheck read it, and a ticket is pruned only a day after it ends.
|
|
289
|
+
const ticket = (await checkTicket(id, opts.code));
|
|
290
|
+
reportTicket(ticket, opts, "checked");
|
|
291
|
+
process.exit(ticketExitCode(ticket));
|
|
292
|
+
}
|
|
293
|
+
/** A sign-in's ticket for whoever started or checked it: the shared report, and what a finished sign-in adds. */
|
|
294
|
+
function reportTicket(ticket, opts, when) {
|
|
295
|
+
const deployment = ticket.fields?.deployment;
|
|
296
|
+
const { json, text } = ticketReport(ticket, when, (result) => {
|
|
297
|
+
if (deployment !== undefined) {
|
|
298
|
+
return { fields: {}, text: [`signed in on the ${deployment} deployment`], next: "Signed in on the deployment." };
|
|
299
|
+
}
|
|
300
|
+
const hint = typeof result.model === "string" ? modelHint(result.model, String(result.name)) : undefined;
|
|
301
|
+
return {
|
|
302
|
+
fields: { path: result.path, ...(result.model ? { model: result.model } : {}) },
|
|
303
|
+
text: [`saved to ${String(result.path)}`, ...(hint === undefined ? [] : [hint])],
|
|
304
|
+
next: hint === undefined ? "Signed in." : `Signed in. Tell the user: ${hint}.`,
|
|
305
|
+
};
|
|
306
|
+
});
|
|
307
|
+
printReport(opts.json, json, text);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* pi-ai's account sign-in, run by a ticket's process with no one to answer it. A choice takes its first option, pi's
|
|
311
|
+
* default (the browser sign-in); a text question is left blank, the one pi-ai's account sign-ins ask being Copilot's
|
|
312
|
+
* optional Enterprise domain (a required one fails in the provider's own flow, which the ticket reports); a secret it
|
|
313
|
+
* cannot take; the code or address a browser ends on comes from `login --check --code`, unless the provider's callback
|
|
314
|
+
* brings it first. Not public: a test seam.
|
|
315
|
+
*/
|
|
316
|
+
export function signInInteraction(step, provider) {
|
|
317
|
+
return {
|
|
318
|
+
signal: step.signal,
|
|
319
|
+
prompt: async (prompt) => {
|
|
320
|
+
if (prompt.type === "select")
|
|
321
|
+
return prompt.options[0].id;
|
|
322
|
+
if (prompt.type === "text")
|
|
323
|
+
return "";
|
|
324
|
+
if (prompt.type === "secret") {
|
|
325
|
+
throw new Error(`the sign-in asks "${prompt.message}", which only a terminal can answer: run \`fastagent login ${provider}\` ` +
|
|
326
|
+
"in one");
|
|
327
|
+
}
|
|
328
|
+
return step.address(prompt.signal ? AbortSignal.any([prompt.signal, step.signal]) : step.signal);
|
|
329
|
+
},
|
|
330
|
+
notify: (event) => {
|
|
331
|
+
if (event.type === "auth_url") {
|
|
332
|
+
step.waits({
|
|
333
|
+
url: event.url,
|
|
334
|
+
takesAddress: true,
|
|
335
|
+
...(event.instructions ? { instructions: event.instructions } : {}),
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
else if (event.type === "device_code") {
|
|
339
|
+
step.waits({ url: event.verificationUri, code: event.userCode });
|
|
340
|
+
}
|
|
341
|
+
console.error(`[fastagent] ${event.type}: ${"message" in event ? event.message : ""}`);
|
|
342
|
+
},
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* `--deployment <host>`: always named. The agent directory cannot answer which host it means: a Railway deploy leaves
|
|
347
|
+
* no file of its own there, and a directory can hold several hosts' files, so a guess could log a different box in
|
|
348
|
+
* than the one that asked. Every command fastagent prints names it (`deploymentLoginCommand`, `deployedHost`).
|
|
85
349
|
*/
|
|
86
350
|
async function runDeploymentLogin(provider, opts) {
|
|
87
351
|
if (opts.global)
|
|
88
352
|
failUsage("--deployment logs the deployment in; -g names this machine's global file — pick one");
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
353
|
+
// A ticket is read on its own: with --deployment, this would start another sign-in and replace the one it names.
|
|
354
|
+
if (opts.check !== undefined || opts.code !== undefined) {
|
|
355
|
+
failUsage("--check reads a sign-in's ticket by itself: run `fastagent login --check <ticket>`, without --deployment");
|
|
356
|
+
}
|
|
357
|
+
const agentDir = agentDirOrExit(process.cwd());
|
|
358
|
+
selectAgentEnvironment("production");
|
|
359
|
+
enterAgentEnv(agentDir);
|
|
360
|
+
if (!DEPLOY_HOSTS.includes(opts.deployment)) {
|
|
361
|
+
failUsage(`--deployment takes a host (${DEPLOY_HOSTS.join(", ")}), not "${opts.deployment}" — to name a provider too: ` +
|
|
362
|
+
`fastagent login <provider> --deployment <host>`);
|
|
363
|
+
}
|
|
364
|
+
const host = opts.deployment;
|
|
365
|
+
const method = opts.method === undefined ? undefined : methodOf(opts.method);
|
|
366
|
+
if (opts.ticket !== undefined) {
|
|
367
|
+
// The process `startTicket` started: it holds the box's shell while the person signs in.
|
|
368
|
+
const retry = deploymentLoginCommand(host, provider);
|
|
369
|
+
await runTicket(opts.ticket, async (step) => {
|
|
370
|
+
const io = ticketLoginIO(step, retry);
|
|
371
|
+
const failed = await loginOnBox({
|
|
372
|
+
host,
|
|
373
|
+
shell: await HOSTS[host].shell(agentDir),
|
|
374
|
+
provider: provider,
|
|
375
|
+
method: "oauth",
|
|
376
|
+
input: true,
|
|
377
|
+
io,
|
|
378
|
+
});
|
|
379
|
+
if (failed)
|
|
380
|
+
throw new Error(io.refusal() ?? failed);
|
|
381
|
+
return { provider, deployment: host };
|
|
382
|
+
});
|
|
383
|
+
process.exit(0);
|
|
108
384
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
385
|
+
if (opts.input === false || opts.json === true || !isInteractive()) {
|
|
386
|
+
const timeout = opts.timeout === undefined ? UNATTENDED_TIMEOUT_SECONDS : secondsOf(opts.timeout);
|
|
387
|
+
return requestDeploymentLogin(agentDir, host, { provider, method }, opts, timeout);
|
|
112
388
|
}
|
|
113
389
|
const failed = await loginOnBox({
|
|
114
390
|
host,
|
|
115
|
-
shell: await HOSTS[host].shell(
|
|
116
|
-
placement,
|
|
391
|
+
shell: await HOSTS[host].shell(agentDir).catch(failStartup),
|
|
117
392
|
...(provider ? { provider } : {}),
|
|
118
|
-
|
|
393
|
+
...(method ? { method } : {}),
|
|
394
|
+
input: true,
|
|
119
395
|
});
|
|
120
396
|
if (failed)
|
|
121
397
|
failStartup(new Error(failed));
|
|
122
398
|
process.exit(0);
|
|
123
399
|
}
|
|
400
|
+
/**
|
|
401
|
+
* `login --deployment <host>` with no one at a terminal. The sign-in is chosen here, from the definition the box
|
|
402
|
+
* serves; what this machine holds says nothing of the box, so no status is shown. An account sign-in runs on the box
|
|
403
|
+
* through a ticket whose process holds the box's shell (box-login.ts `ticketLoginIO`). An API key reaches a box only
|
|
404
|
+
* as a variable its deploy carries, so the person sets it in the production value file and the agent deploys again.
|
|
405
|
+
*/
|
|
406
|
+
async function requestDeploymentLogin(agentDir, host, given, opts, timeoutSeconds) {
|
|
407
|
+
const providers = await definitionProviders(agentDir).catch(failStartup);
|
|
408
|
+
const offered = await loginOptionsOver(resolveAuthPath(agentDir), providers);
|
|
409
|
+
let choice;
|
|
410
|
+
try {
|
|
411
|
+
choice = await chooseLogin(offered, given, undefined);
|
|
412
|
+
}
|
|
413
|
+
catch (error) {
|
|
414
|
+
if (!(error instanceof LoginRefused))
|
|
415
|
+
throw error;
|
|
416
|
+
return choiceNotGiven(error, opts, { flags: ` --deployment ${host}`, statuses: false });
|
|
417
|
+
}
|
|
418
|
+
if (choice.method === "api_key") {
|
|
419
|
+
const valueFile = dotEnvPath(agentDir);
|
|
420
|
+
const { variables, what } = await keyToSet(choice, providers);
|
|
421
|
+
const deploy = `fastagent deploy ${host} --run`;
|
|
422
|
+
printReport(opts.json, {
|
|
423
|
+
status: "need_user_action",
|
|
424
|
+
provider: choice.provider,
|
|
425
|
+
method: "api-key",
|
|
426
|
+
deployment: host,
|
|
427
|
+
variables,
|
|
428
|
+
value_file: valueFile,
|
|
429
|
+
check_command: deploy,
|
|
430
|
+
agent_next_steps: `Ask the user to set ${what} in ${valueFile} themselves, not in this conversation. A key reaches the ` +
|
|
431
|
+
`${host} deployment with its next deploy: once they say they have, run check_command.`,
|
|
432
|
+
}, [
|
|
433
|
+
`need_user_action: set ${what} in ${valueFile}`,
|
|
434
|
+
`then run: ${deploy} # the key reaches the deployment with its deploy`,
|
|
435
|
+
]);
|
|
436
|
+
process.exit(0);
|
|
437
|
+
}
|
|
438
|
+
const ticket = await startTicket({
|
|
439
|
+
subject: `login:${choice.provider}`,
|
|
440
|
+
fields: { provider: choice.provider, method: "account", deployment: host },
|
|
441
|
+
action: `sign in to ${choice.name} for the ${host} deployment`,
|
|
442
|
+
check: LOGIN_CHECK,
|
|
443
|
+
restart: `fastagent login ${choice.provider} --method account --deployment ${host}`,
|
|
444
|
+
timeoutSeconds,
|
|
445
|
+
// Reaching the box comes first, and can take a while (a host's shell, an idle runtime woken).
|
|
446
|
+
waitsFirst: false,
|
|
447
|
+
whenRunning: "replace",
|
|
448
|
+
command: {
|
|
449
|
+
file: process.execPath,
|
|
450
|
+
args: [
|
|
451
|
+
...process.execArgv,
|
|
452
|
+
process.argv[1],
|
|
453
|
+
"login",
|
|
454
|
+
choice.provider,
|
|
455
|
+
"--method",
|
|
456
|
+
"account",
|
|
457
|
+
"--deployment",
|
|
458
|
+
host,
|
|
459
|
+
],
|
|
460
|
+
cwd: process.cwd(),
|
|
461
|
+
},
|
|
462
|
+
});
|
|
463
|
+
reportTicket(ticket, opts, "started");
|
|
464
|
+
process.exit(ticketExitCode(ticket));
|
|
465
|
+
}
|
|
124
466
|
/**
|
|
125
467
|
* `--stdio`: the box's half of `--deployment`. Runs where the server runs; everything it would show or ask travels as
|
|
126
468
|
* the relay wire, and it ends with exactly one result line. Never started by hand: the credential path is the one the
|
|
@@ -146,10 +488,11 @@ async function stdioLogin(io, provider, opts) {
|
|
|
146
488
|
// proxy they name. AgentCore's command shell hands down none of the runtime's, so a proxy carried there in
|
|
147
489
|
// FASTAGENT_ENV does not reach the login (docs/deploy.md).
|
|
148
490
|
enterAgentEnv(agentDir);
|
|
149
|
-
// The model environment the serving
|
|
150
|
-
// use.
|
|
151
|
-
const
|
|
152
|
-
const
|
|
491
|
+
// The model environment the serving Agent reads (openServing), its definition's providers included, so "logged in"
|
|
492
|
+
// means what the server will use, and a provider only the definition declares can be signed in to.
|
|
493
|
+
const providers = await definitionProviders(agentDir);
|
|
494
|
+
const models = await modelEnvironment(agentDir, {}, providers);
|
|
495
|
+
const auth = models.auth;
|
|
153
496
|
if (opts.ifMissing && provider) {
|
|
154
497
|
// The server's own answer (`authStatus`), the one its startup report prints. Known ceiling: nothing is asked of
|
|
155
498
|
// the provider beyond a due refresh, so a revoked grant whose access token has not expired yet, or a revoked API
|
|
@@ -169,6 +512,12 @@ async function stdioLogin(io, provider, opts) {
|
|
|
169
512
|
if (opts.input === false) {
|
|
170
513
|
return { ok: false, reason: "missing", message: `no ${provider ?? "model"} credential in ${auth.path}` };
|
|
171
514
|
}
|
|
172
|
-
const
|
|
515
|
+
const method = opts.method === undefined ? undefined : methodOf(opts.method);
|
|
516
|
+
const result = await loginFlow(io, {
|
|
517
|
+
authPath: auth.path,
|
|
518
|
+
providers,
|
|
519
|
+
...(provider ? { provider } : {}),
|
|
520
|
+
...(method ? { method } : {}),
|
|
521
|
+
});
|
|
173
522
|
return { ok: true, provider: result.provider, method: result.method, path: auth.path };
|
|
174
523
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `fastagent logout [provider]`: remove the credential `login` stored for a provider, as pi's `/logout` does, from the
|
|
3
|
+
* file `login` writes (the agent's, or with `-g` or outside an agent the global one). Environment variables and the
|
|
4
|
+
* grant at the provider are left as they are.
|
|
5
|
+
*/
|
|
6
|
+
import { enterAgentEnv } from "../../env.js";
|
|
7
|
+
import { GLOBAL_AUTH_PATH, fastagentCredentialStore, resolveAuthPath } from "../../harnesses/models/credentials.js";
|
|
8
|
+
import { loginProviders } from "../../harnesses/models/models.js";
|
|
9
|
+
import { definitionProviders } from "../../harnesses/pi-durable/open.js";
|
|
10
|
+
import { globalHome } from "../../paths.js";
|
|
11
|
+
import { failStartup, failUsage, optionalAgentDirOrExit } from "../fail.js";
|
|
12
|
+
import { isInteractive, terminalLoginIO } from "../shared.js";
|
|
13
|
+
export async function runLogout(provider, opts) {
|
|
14
|
+
const agentDir = opts.global ? undefined : optionalAgentDirOrExit(process.cwd());
|
|
15
|
+
enterAgentEnv(agentDir ?? globalHome());
|
|
16
|
+
const authPath = opts.global ? GLOBAL_AUTH_PATH : resolveAuthPath(agentDir ?? globalHome());
|
|
17
|
+
const store = fastagentCredentialStore(authPath);
|
|
18
|
+
const known = loginProviders(agentDir ? await definitionProviders(agentDir).catch(failStartup) : []);
|
|
19
|
+
const stored = (await store.list())
|
|
20
|
+
.map(({ providerId, type }) => ({
|
|
21
|
+
id: providerId,
|
|
22
|
+
type,
|
|
23
|
+
name: known.find((p) => p.id === providerId)?.name ?? providerId,
|
|
24
|
+
}))
|
|
25
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
26
|
+
const held = stored.length === 0 ? "it holds none" : `it holds ${stored.map(({ id }) => id).join(", ")}`;
|
|
27
|
+
let chosen;
|
|
28
|
+
if (provider !== undefined) {
|
|
29
|
+
const named = provider.trim().toLowerCase();
|
|
30
|
+
chosen = stored.find(({ id, name }) => id.toLowerCase() === named || name.toLowerCase() === named);
|
|
31
|
+
if (chosen === undefined)
|
|
32
|
+
failStartup(new Error(`no credential for "${provider}" is stored in ${authPath}: ${held}`));
|
|
33
|
+
}
|
|
34
|
+
else if (stored.length === 0) {
|
|
35
|
+
console.error(`[fastagent] no credential is stored in ${authPath}; environment variables are not login's to remove`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
else if (opts.input === false || !isInteractive()) {
|
|
39
|
+
failUsage(`name the provider to log out of: ${held} (${authPath})`);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
const value = await terminalLoginIO().select("Select provider to logout:", stored.map(({ id, name, type }) => ({ value: id, label: name, hint: type === "oauth" ? "account" : "API key" })));
|
|
43
|
+
chosen = stored.find(({ id }) => id === value);
|
|
44
|
+
if (chosen === undefined) {
|
|
45
|
+
console.error("[fastagent] logout cancelled");
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
await store.delete(chosen.id);
|
|
50
|
+
console.error(chosen.type === "oauth"
|
|
51
|
+
? `[fastagent] logged out of ${chosen.name} — removed from ${authPath}`
|
|
52
|
+
: `[fastagent] removed the stored API key for ${chosen.name} from ${authPath}; environment variables are unchanged`);
|
|
53
|
+
}
|
|
@@ -1,26 +1,28 @@
|
|
|
1
|
-
/** `fastagent logs agentcore [
|
|
1
|
+
/** `fastagent logs agentcore [agent]`: discover and tail the deployed AgentCore CloudWatch logs. */
|
|
2
2
|
import { basename, resolve } from "node:path";
|
|
3
3
|
import { agentcoreName } from "../../deploy/agentcore/plan.js";
|
|
4
4
|
import { tailAgentcoreLogs } from "../../deploy/agentcore/logs.js";
|
|
5
5
|
import { awsRunner } from "../../deploy/runner.js";
|
|
6
6
|
import { enterAgentEnv } from "../../env.js";
|
|
7
|
-
import {
|
|
7
|
+
import { selectAgentEnvironment } from "../../paths.js";
|
|
8
|
+
import { agentDirOrExit, failStartup, failUsage } from "../fail.js";
|
|
8
9
|
export async function runLogs(host, dirArg, opts) {
|
|
9
10
|
// The host argument is DISPATCHED here, as in runDeploy.
|
|
10
11
|
if (host !== "agentcore")
|
|
11
12
|
failUsage(`logs: unsupported host "${host}" — only agentcore has remote logs`);
|
|
12
|
-
const
|
|
13
|
-
|
|
13
|
+
const agentDir = agentDirOrExit(resolve(dirArg));
|
|
14
|
+
selectAgentEnvironment("production");
|
|
15
|
+
enterAgentEnv(agentDir);
|
|
14
16
|
const source = opts.source ?? "runtime";
|
|
15
17
|
if (source !== "runtime" && source !== "forwarder") {
|
|
16
18
|
failUsage(`logs: --source must be "runtime" or "forwarder"`);
|
|
17
19
|
}
|
|
18
20
|
const outcome = await tailAgentcoreLogs({
|
|
19
|
-
name: agentcoreName(basename(
|
|
21
|
+
name: agentcoreName(basename(agentDir)),
|
|
20
22
|
source: source,
|
|
21
23
|
since: opts.since,
|
|
22
24
|
follow: opts.follow === true,
|
|
23
|
-
}, awsRunner(
|
|
25
|
+
}, awsRunner(agentDir), (message) => console.error(`[fastagent] logs: ${message}`));
|
|
24
26
|
if (!outcome.ok)
|
|
25
27
|
failStartup(new Error(`logs stopped: ${outcome.gate}`));
|
|
26
28
|
}
|