@fastagent-sh/fastagent 0.21.0 → 0.22.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 +9 -12
- package/dist/agent.d.ts +24 -37
- package/dist/agent.js +7 -15
- package/dist/atomic-write.d.ts +13 -17
- package/dist/atomic-write.js +18 -29
- package/dist/bind.d.ts +12 -22
- package/dist/bind.js +18 -27
- package/dist/channel.d.ts +11 -33
- package/dist/channels/agentcore-limits.d.ts +2 -13
- package/dist/channels/agentcore-limits.js +2 -13
- package/dist/channels/agentcore-protocol.d.ts +67 -58
- package/dist/channels/agentcore-protocol.js +23 -15
- package/dist/channels/agentcore-service.d.ts +19 -33
- package/dist/channels/agentcore-service.js +176 -59
- package/dist/channels/agentcore.d.ts +39 -33
- package/dist/channels/agentcore.js +90 -224
- package/dist/channels/body.d.ts +15 -2
- package/dist/channels/body.js +24 -2
- package/dist/channels/busy.d.ts +1 -21
- package/dist/channels/busy.js +2 -39
- package/dist/channels/control.d.ts +17 -62
- package/dist/channels/control.js +74 -182
- package/dist/channels/define-channel.d.ts +39 -0
- package/dist/channels/define-channel.js +9 -0
- package/dist/channels/discover.d.ts +10 -31
- package/dist/channels/discover.js +37 -31
- package/dist/channels/feishu/bootstrap-token.d.ts +1 -8
- package/dist/channels/feishu/bootstrap-token.js +7 -23
- package/dist/channels/feishu/card.d.ts +14 -28
- package/dist/channels/feishu/card.js +16 -30
- package/dist/channels/feishu/cloud.d.ts +1 -5
- package/dist/channels/feishu/context-buffer.d.ts +4 -23
- package/dist/channels/feishu/context-buffer.js +8 -31
- package/dist/channels/feishu/crypto.d.ts +10 -5
- package/dist/channels/feishu/crypto.js +12 -19
- package/dist/channels/feishu/feishu-api.d.ts +2 -1
- package/dist/channels/feishu/feishu-api.js +5 -4
- package/dist/channels/feishu/feishu.d.ts +4 -10
- package/dist/channels/feishu/feishu.js +113 -227
- package/dist/channels/feishu/invoke-turn.d.ts +5 -4
- package/dist/channels/feishu/invoke-turn.js +36 -54
- package/dist/channels/feishu/model.d.ts +4 -21
- package/dist/channels/feishu/model.js +1 -8
- package/dist/channels/feishu/normalize.d.ts +2 -10
- package/dist/channels/feishu/normalize.js +7 -42
- package/dist/channels/feishu/parse.d.ts +9 -29
- package/dist/channels/feishu/parse.js +8 -26
- package/dist/channels/feishu/preview.d.ts +12 -14
- package/dist/channels/feishu/preview.js +108 -207
- package/dist/channels/feishu/register-app.d.ts +8 -23
- package/dist/channels/feishu/register-app.js +7 -20
- package/dist/channels/feishu/register-webhook.d.ts +2 -9
- package/dist/channels/feishu/register-webhook.js +9 -33
- package/dist/channels/feishu/scaffold/channel.ts +27 -19
- package/dist/channels/feishu/scaffold/channel.websocket.ts +31 -0
- package/dist/channels/feishu/setup-mode.d.ts +11 -36
- package/dist/channels/feishu/setup-mode.js +7 -26
- package/dist/channels/feishu/ws-ingress.d.ts +1 -2
- package/dist/channels/feishu/ws-ingress.js +6 -8
- package/dist/channels/http.d.ts +15 -15
- package/dist/channels/http.js +19 -9
- package/dist/channels/kit/attachment-path.d.ts +4 -5
- package/dist/channels/kit/attachment-path.js +10 -34
- package/dist/channels/kit/context-buffer.d.ts +14 -21
- package/dist/channels/kit/context-buffer.js +25 -38
- package/dist/channels/kit/delivery.d.ts +35 -0
- package/dist/channels/kit/delivery.js +129 -0
- package/dist/channels/kit/event-stream.d.ts +5 -0
- package/dist/channels/kit/event-stream.js +29 -0
- package/dist/channels/kit/invoke-turn-kit.d.ts +53 -26
- package/dist/channels/kit/invoke-turn-kit.js +89 -32
- package/dist/channels/kit/preview-kit.d.ts +18 -72
- package/dist/channels/kit/preview-kit.js +22 -88
- package/dist/channels/kit/signature.d.ts +3 -9
- package/dist/channels/kit/signature.js +3 -9
- package/dist/channels/kit/state.d.ts +1 -2
- package/dist/channels/kit/state.js +5 -14
- package/dist/channels/kit/stop-command.d.ts +1 -2
- package/dist/channels/kit/stop-command.js +6 -9
- package/dist/channels/kit/tasks.d.ts +1 -1
- package/dist/channels/kit/tasks.js +8 -21
- package/dist/channels/kit/text.d.ts +2 -16
- package/dist/channels/kit/text.js +23 -31
- package/dist/channels/kit/thread-participants.d.ts +4 -17
- package/dist/channels/kit/thread-participants.js +8 -55
- package/dist/channels/kit/transport.d.ts +26 -0
- package/dist/channels/kit/transport.js +20 -0
- package/dist/channels/kit/turn-queue.d.ts +7 -11
- package/dist/channels/kit/turn-queue.js +21 -39
- package/dist/channels/kit/turn-runner.d.ts +32 -18
- package/dist/channels/kit/turn-runner.js +98 -53
- package/dist/channels/kit/turn-store.d.ts +32 -32
- package/dist/channels/kit/turn-store.js +45 -88
- package/dist/channels/lark/lark.d.ts +1 -5
- package/dist/channels/lark/onboard.d.ts +3 -12
- package/dist/channels/lark/onboard.js +3 -13
- package/dist/channels/lark/scaffold/channel.ts +27 -19
- package/dist/channels/lark/scaffold/channel.websocket.ts +31 -0
- package/dist/channels/registration.d.ts +9 -35
- package/dist/channels/registration.js +6 -37
- package/dist/channels/secret.js +2 -5
- package/dist/channels/serve.d.ts +47 -44
- package/dist/channels/serve.js +165 -101
- package/dist/channels/slack/config-api.d.ts +4 -27
- package/dist/channels/slack/config-api.js +5 -34
- package/dist/channels/slack/context-buffer.d.ts +2 -3
- package/dist/channels/slack/context-buffer.js +5 -5
- package/dist/channels/slack/invoke-turn.d.ts +3 -1
- package/dist/channels/slack/invoke-turn.js +25 -34
- package/dist/channels/slack/manifest.js +1 -3
- package/dist/channels/slack/model.d.ts +1 -2
- package/dist/channels/slack/model.js +1 -1
- package/dist/channels/slack/onboard.d.ts +4 -3
- package/dist/channels/slack/onboard.js +8 -11
- package/dist/channels/slack/onboarding-state.d.ts +3 -5
- package/dist/channels/slack/onboarding-state.js +9 -6
- package/dist/channels/slack/parse.d.ts +4 -13
- package/dist/channels/slack/parse.js +7 -28
- package/dist/channels/slack/preview.d.ts +12 -2
- package/dist/channels/slack/preview.js +292 -269
- package/dist/channels/slack/reaction.d.ts +11 -3
- package/dist/channels/slack/reaction.js +19 -8
- package/dist/channels/slack/register-webhook.js +4 -7
- package/dist/channels/slack/scaffold/channel.ts +20 -13
- package/dist/channels/slack/scaffold/slack-send.ts +2 -2
- package/dist/channels/slack/setup-server.d.ts +1 -5
- package/dist/channels/slack/setup-server.js +1 -5
- package/dist/channels/slack/shared-api.d.ts +1 -4
- package/dist/channels/slack/shared-api.js +2 -13
- package/dist/channels/slack/slack-api.d.ts +2 -1
- package/dist/channels/slack/slack-api.js +6 -4
- package/dist/channels/slack/slack.d.ts +11 -14
- package/dist/channels/slack/slack.js +121 -122
- package/dist/channels/sse.d.ts +1 -1
- package/dist/channels/sse.js +1 -1
- package/dist/channels/telegram/context-buffer.d.ts +7 -22
- package/dist/channels/telegram/context-buffer.js +6 -23
- package/dist/channels/telegram/invoke-turn.d.ts +7 -7
- package/dist/channels/telegram/invoke-turn.js +24 -43
- package/dist/channels/telegram/parse.d.ts +24 -51
- package/dist/channels/telegram/parse.js +32 -84
- package/dist/channels/telegram/preview.d.ts +10 -1
- package/dist/channels/telegram/preview.js +79 -100
- package/dist/channels/telegram/register-webhook.js +5 -23
- package/dist/channels/telegram/scaffold/channel.ts +25 -18
- package/dist/channels/telegram/scaffold/telegram-send.ts +6 -4
- package/dist/channels/telegram/telegram-api.d.ts +4 -3
- package/dist/channels/telegram/telegram-api.js +9 -7
- package/dist/channels/telegram/telegram.d.ts +4 -18
- package/dist/channels/telegram/telegram.js +38 -94
- package/dist/channels/telegram/turn-store.d.ts +11 -14
- package/dist/channels/telegram/turn-store.js +8 -6
- package/dist/channels/wait-health.d.ts +4 -6
- package/dist/channels/wait-health.js +10 -14
- package/dist/cli/add-feishu.d.ts +2 -12
- package/dist/cli/add-feishu.js +24 -71
- package/dist/cli/add-slack.d.ts +5 -3
- package/dist/cli/add-slack.js +53 -76
- package/dist/cli/auth-view.d.ts +2 -16
- package/dist/cli/auth-view.js +2 -16
- package/dist/cli/commands/add.js +25 -43
- package/dist/cli/commands/chat.d.ts +0 -1
- package/dist/cli/commands/chat.js +5 -6
- package/dist/cli/commands/deploy/agentcore.js +60 -65
- package/dist/cli/commands/deploy/docker.js +50 -23
- package/dist/cli/commands/deploy/fly.js +23 -61
- package/dist/cli/commands/deploy/railway.js +23 -18
- package/dist/cli/commands/deploy/shared.d.ts +38 -57
- package/dist/cli/commands/deploy/shared.js +40 -59
- package/dist/cli/commands/deploy.d.ts +10 -27
- package/dist/cli/commands/deploy.js +38 -60
- package/dist/cli/commands/destroy.d.ts +4 -0
- package/dist/cli/commands/destroy.js +56 -0
- package/dist/cli/commands/dev.d.ts +2 -1
- package/dist/cli/commands/dev.js +20 -23
- package/dist/cli/commands/info.d.ts +0 -2
- package/dist/cli/commands/info.js +83 -49
- package/dist/cli/commands/init.d.ts +1 -2
- package/dist/cli/commands/init.js +16 -55
- package/dist/cli/commands/invoke.d.ts +0 -1
- package/dist/cli/commands/invoke.js +5 -7
- package/dist/cli/commands/login.d.ts +2 -1
- package/dist/cli/commands/login.js +33 -38
- package/dist/cli/commands/logs.js +3 -4
- package/dist/cli/commands/models.js +1 -5
- package/dist/cli/commands/routine-run.d.ts +6 -0
- package/dist/cli/commands/routine-run.js +47 -0
- package/dist/cli/commands/routine.d.ts +25 -0
- package/dist/cli/commands/routine.js +122 -0
- package/dist/cli/commands/start.d.ts +31 -3
- package/dist/cli/commands/start.js +131 -81
- package/dist/cli/commands/tool.js +26 -12
- package/dist/cli/fail.d.ts +13 -23
- package/dist/cli/fail.js +20 -23
- package/dist/cli/invoke-stream.d.ts +1 -8
- package/dist/cli/kernel.d.ts +6 -38
- package/dist/cli/kernel.js +14 -77
- package/dist/cli/models-view.d.ts +1 -9
- package/dist/cli/models-view.js +11 -22
- package/dist/cli/program.d.ts +5 -6
- package/dist/cli/program.js +120 -157
- package/dist/cli/serve.d.ts +57 -41
- package/dist/cli/serve.js +94 -121
- package/dist/cli/shared.d.ts +15 -61
- package/dist/cli/shared.js +55 -181
- package/dist/cli.js +1 -8
- package/dist/collect.d.ts +6 -0
- package/dist/collect.js +6 -0
- package/dist/core.d.ts +4 -1
- package/dist/core.js +9 -7
- package/dist/declared-secrets.d.ts +55 -0
- package/dist/declared-secrets.js +88 -0
- package/dist/deploy/agentcore/aws-cli.d.ts +91 -0
- package/dist/deploy/agentcore/aws-cli.js +64 -0
- package/dist/deploy/agentcore/destroy.d.ts +51 -0
- package/dist/deploy/agentcore/destroy.js +273 -0
- package/dist/deploy/agentcore/forwarder.js +28 -79
- package/dist/deploy/agentcore/logs.d.ts +2 -18
- package/dist/deploy/agentcore/logs.js +27 -51
- package/dist/deploy/agentcore/plan.d.ts +85 -105
- package/dist/deploy/agentcore/plan.js +152 -314
- package/dist/deploy/agentcore/run.d.ts +28 -28
- package/dist/deploy/agentcore/run.js +227 -306
- package/dist/deploy/agentcore/zip.d.ts +2 -15
- package/dist/deploy/agentcore/zip.js +3 -17
- package/dist/deploy/build-context.d.ts +21 -0
- package/dist/deploy/build-context.js +137 -0
- package/dist/deploy/channel-ingress.d.ts +26 -39
- package/dist/deploy/channel-ingress.js +57 -28
- package/dist/deploy/container.d.ts +20 -34
- package/dist/deploy/container.js +49 -100
- package/dist/deploy/docker/plan.d.ts +12 -11
- package/dist/deploy/docker/plan.js +43 -24
- package/dist/deploy/docker/run.d.ts +22 -25
- package/dist/deploy/docker/run.js +39 -37
- package/dist/deploy/fly/plan.d.ts +15 -44
- package/dist/deploy/fly/plan.js +41 -73
- package/dist/deploy/fly/run.d.ts +16 -51
- package/dist/deploy/fly/run.js +42 -95
- package/dist/deploy/hosts.d.ts +24 -3
- package/dist/deploy/hosts.js +24 -3
- package/dist/deploy/preflight.d.ts +47 -41
- package/dist/deploy/preflight.js +282 -383
- package/dist/deploy/railway/plan.d.ts +16 -42
- package/dist/deploy/railway/plan.js +42 -60
- package/dist/deploy/railway/run.d.ts +30 -68
- package/dist/deploy/railway/run.js +86 -100
- package/dist/deploy/registration-gate.d.ts +6 -13
- package/dist/deploy/residency.d.ts +37 -0
- package/dist/deploy/residency.js +24 -0
- package/dist/deploy/runner.d.ts +10 -9
- package/dist/deploy/runner.js +7 -18
- package/dist/deploy/secrets.d.ts +40 -41
- package/dist/deploy/secrets.js +117 -103
- package/dist/deploy/workspace.d.ts +50 -0
- package/dist/deploy/workspace.js +197 -0
- package/dist/dev-supervisor.d.ts +1 -9
- package/dist/dev-supervisor.js +21 -64
- package/dist/effect-port.d.ts +50 -0
- package/dist/effect-port.js +77 -0
- package/dist/engines/pi/agent-session-factory.d.ts +50 -69
- package/dist/engines/pi/agent-session-factory.js +249 -146
- package/dist/engines/pi/auth.d.ts +15 -11
- package/dist/engines/pi/auth.js +96 -99
- package/dist/engines/pi/chat.d.ts +1 -5
- package/dist/engines/pi/chat.js +2 -14
- package/dist/engines/pi/config.d.ts +53 -51
- package/dist/engines/pi/config.js +83 -92
- package/dist/engines/pi/create.d.ts +60 -75
- package/dist/engines/pi/create.js +108 -141
- package/dist/engines/pi/definition.d.ts +14 -58
- package/dist/engines/pi/definition.js +21 -85
- package/dist/engines/pi/invoke-session.d.ts +5 -25
- package/dist/engines/pi/invoke-session.js +209 -244
- package/dist/engines/pi/login.d.ts +95 -35
- package/dist/engines/pi/login.js +259 -107
- package/dist/engines/pi/machine.d.ts +31 -0
- package/dist/engines/pi/machine.js +106 -0
- package/dist/engines/pi/models.d.ts +70 -89
- package/dist/engines/pi/models.js +188 -81
- package/dist/engines/pi/open.d.ts +65 -53
- package/dist/engines/pi/open.js +129 -69
- package/dist/engines/pi/report.d.ts +3 -12
- package/dist/engines/pi/report.js +2 -16
- package/dist/engines/pi/search-tools.d.ts +1 -9
- package/dist/engines/pi/search-tools.js +26 -57
- package/dist/engines/pi/service.d.ts +2 -16
- package/dist/engines/pi/service.js +2 -16
- package/dist/engines/pi/session-builder.d.ts +5 -9
- package/dist/engines/pi/session-builder.js +44 -82
- package/dist/engines/pi/session-control.js +286 -269
- package/dist/engines/pi/session-effects.d.ts +14 -0
- package/dist/engines/pi/session-effects.js +30 -0
- package/dist/engines/pi/session-inheritance.d.ts +9 -18
- package/dist/engines/pi/session-inheritance.js +103 -160
- package/dist/engines/pi/session-markers.d.ts +31 -30
- package/dist/engines/pi/session-markers.js +26 -25
- package/dist/engines/pi/session-settings.d.ts +6 -22
- package/dist/engines/pi/session-settings.js +10 -21
- package/dist/engines/pi/session-store.d.ts +26 -92
- package/dist/engines/pi/session-store.js +96 -310
- package/dist/engines/pi/tool-context.d.ts +17 -45
- package/dist/engines/pi/tool-context.js +7 -26
- package/dist/engines/pi/tool.d.ts +45 -36
- package/dist/engines/pi/tool.js +43 -57
- package/dist/engines/pi/turn-kit.d.ts +14 -52
- package/dist/engines/pi/turn-kit.js +18 -67
- package/dist/engines/pi/wake-tool.d.ts +2 -10
- package/dist/engines/pi/wake-tool.js +7 -27
- package/dist/env.d.ts +27 -28
- package/dist/env.js +45 -50
- package/dist/index.js +0 -2
- package/dist/lark.d.ts +1 -2
- package/dist/lark.js +1 -2
- package/dist/loader.d.ts +14 -55
- package/dist/loader.js +24 -43
- package/dist/log.d.ts +2 -12
- package/dist/log.js +3 -24
- package/dist/node.d.ts +2 -15
- package/dist/node.js +2 -18
- package/dist/observe.d.ts +2 -8
- package/dist/open-url.d.ts +1 -1
- package/dist/open-url.js +1 -1
- package/dist/paths.d.ts +70 -134
- package/dist/paths.js +165 -232
- package/dist/pi.d.ts +4 -6
- package/dist/pi.js +3 -3
- package/dist/proxy.d.ts +16 -6
- package/dist/proxy.js +52 -16
- package/dist/runtime.d.ts +18 -12
- package/dist/runtime.js +18 -11
- package/dist/scaffold/add-channel.d.ts +14 -31
- package/dist/scaffold/add-channel.js +48 -112
- package/dist/scaffold/init.d.ts +9 -31
- package/dist/scaffold/init.js +45 -138
- package/dist/scaffold/templates/env.example +6 -4
- package/dist/scaffold/templates/fastagent.config.ts +36 -0
- package/dist/scaffold/templates.d.ts +3 -3
- package/dist/scaffold/templates.js +5 -8
- package/dist/scaffold/vendor-skill.d.ts +2 -5
- package/dist/scaffold/vendor-skill.js +19 -29
- package/dist/schedule/cron.d.ts +9 -5
- package/dist/schedule/cron.js +9 -11
- package/dist/schedule/discover.d.ts +12 -12
- package/dist/schedule/discover.js +43 -34
- package/dist/schedule/routine.d.ts +43 -0
- package/dist/schedule/routine.js +32 -0
- package/dist/schedule/run.d.ts +55 -0
- package/dist/schedule/run.js +146 -0
- package/dist/schedule/scheduler.d.ts +44 -55
- package/dist/schedule/scheduler.js +291 -265
- package/dist/schedule/state.d.ts +105 -10
- package/dist/schedule/state.js +293 -19
- package/dist/schedule/wake-alarm.d.ts +10 -23
- package/dist/schedule/wake-alarm.js +91 -121
- package/dist/schedule/wakeups.d.ts +23 -39
- package/dist/schedule/wakeups.js +33 -75
- package/dist/secrets-gate.d.ts +32 -0
- package/dist/secrets-gate.js +33 -0
- package/dist/service.d.ts +137 -98
- package/dist/service.js +250 -252
- package/dist/session-remote.d.ts +33 -44
- package/dist/session-remote.js +203 -192
- package/dist/session.d.ts +153 -228
- package/dist/session.js +33 -55
- package/dist/tunnel.d.ts +8 -36
- package/dist/tunnel.js +24 -65
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/package.json +10 -16
- package/dist/channels/agentcore-state.d.ts +0 -77
- package/dist/channels/agentcore-state.js +0 -276
- package/dist/channels/github/github.d.ts +0 -31
- package/dist/channels/github/github.js +0 -89
- package/dist/channels/github/scaffold/channel.ts +0 -25
- package/dist/cli/commands/attach.d.ts +0 -108
- package/dist/cli/commands/attach.js +0 -637
- package/dist/cli/commands/fire.d.ts +0 -7
- package/dist/cli/commands/fire.js +0 -38
- package/dist/cli/commands/schedule.d.ts +0 -12
- package/dist/cli/commands/schedule.js +0 -87
- package/dist/github.d.ts +0 -3
- package/dist/github.js +0 -2
- package/dist/scaffold/templates/fastagent.config.mjs +0 -23
- package/dist/schedule/audit.d.ts +0 -18
- package/dist/schedule/audit.js +0 -57
- package/dist/schedule/schedule.d.ts +0 -35
- package/dist/schedule/schedule.js +0 -23
package/dist/engines/pi/auth.js
CHANGED
|
@@ -1,48 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Auth for the pi engine: a read-WRITE {@link CredentialStore} over a fastagent credentials file,
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* global location used as the override target / login default, not an implicit per-provider fallback.
|
|
6
|
-
*
|
|
7
|
-
* Project-level default + NO implicit project↔global fallback, for two reasons: (1) isolation — each
|
|
8
|
-
* agent can use a different account/subscription; (2) fail-visibly — a missing credential surfaces at
|
|
9
|
-
* startup instead of being masked by a machine-global one that won't exist on a fresh deploy box. A
|
|
10
|
-
* *fallback* specifically is refused because the only safe shape (read global, write the rotated token
|
|
11
|
-
* back to the project file) would diverge: OAuth refresh tokens are single-use, so consuming global's
|
|
12
|
-
* token and persisting the new one elsewhere leaves global stale for every other consumer.
|
|
13
|
-
*
|
|
14
|
-
* Sharing is still SAFE the right way: point everything at ONE file (`FASTAGENT_AUTH_PATH` → the
|
|
15
|
-
* global path). One file means one refresh lifecycle under the store's cross-process write lock
|
|
16
|
-
* (refresh re-reads the latest token under the lock), the documented same-machine pattern.
|
|
17
|
-
* fastagent's store stays SEPARATE from the pi CLI's `~/.pi/agent/auth.json` for the same single-
|
|
18
|
-
* lifecycle reason: two uncoordinated files over one grant would each rotate and break the other.
|
|
19
|
-
*
|
|
20
|
-
* Locking is vendored here on `proper-lockfile`, with the same parameters pi's file backend used
|
|
21
|
-
* before pi 0.80.8 stopped exporting it (upstream's stated migration path for SDK consumers is a
|
|
22
|
-
* custom pi-ai `CredentialStore`, which this file is). The lock guards the WRITE path only. `read`
|
|
23
|
-
* is pi-ai's per-request hot path, so it stays UNLOCKED — safe because every write that carries a
|
|
24
|
-
* CREDENTIAL publishes by rename ({@link writeFileAtomic}): a reader sees one whole version of the
|
|
25
|
-
* file or another, never a partial one, so a rotation has no torn-read window for an unlocked read
|
|
26
|
-
* to absorb. The one in-place write left is the `{}` bootstrap below, whose window an unlocked read
|
|
27
|
-
* observes as an empty file — reported as corrupt, which for a zero-byte auth.json is the right
|
|
28
|
-
* answer either way. The write path refuses to overwrite a corrupt file (never clobbering other
|
|
29
|
-
* providers' credentials).
|
|
2
|
+
* Auth for the pi engine: a read-WRITE {@link CredentialStore} over a fastagent credentials file, consumed by the
|
|
3
|
+
* `Models` collection (models.ts). The write path refuses to overwrite a corrupt file, so a torn read never clobbers
|
|
4
|
+
* the other providers' credentials.
|
|
30
5
|
*/
|
|
31
|
-
import {
|
|
6
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, realpathSync, writeFileSync } from "node:fs";
|
|
32
7
|
import { homedir } from "node:os";
|
|
33
|
-
import { dirname, join } from "node:path";
|
|
34
|
-
import { GLOBAL_HOME_DIR, SECRETS_DIRNAME, SECRET_FILE_MODE
|
|
8
|
+
import { dirname, join, resolve } from "node:path";
|
|
9
|
+
import { GLOBAL_HOME_DIR, SECRETS_DIRNAME, SECRET_FILE_MODE } from "../../paths.js";
|
|
35
10
|
import { writeFileAtomic } from "../../atomic-write.js";
|
|
36
11
|
import { log } from "../../log.js";
|
|
37
12
|
import lockfile from "proper-lockfile";
|
|
38
13
|
/**
|
|
39
|
-
* The GLOBAL fastagent credentials file (distinct from pi's `~/.pi`), under the user-global machinery
|
|
40
|
-
*
|
|
41
|
-
* The project-level default is `<agentDir>/.secrets/auth.json` (computed by the opener and by
|
|
42
|
-
* `fastagent login`); this is only the `loginFlow()` PROGRAMMATIC fallback (when a caller omits
|
|
43
|
-
* `authPath`) and the path to point `--auth-path`/`FASTAGENT_AUTH_PATH` at to deliberately share ONE
|
|
44
|
-
* credential file across projects (safe — one file, one lock-serialized refresh lifecycle). The
|
|
45
|
-
* `fastagent login` CLI is project-level by default, never this.
|
|
14
|
+
* The GLOBAL fastagent credentials file (distinct from pi's `~/.pi`), under the user-global machinery home
|
|
15
|
+
* `~/.fastagent/`.
|
|
46
16
|
*/
|
|
47
17
|
export const GLOBAL_AUTH_PATH = join(homedir(), GLOBAL_HOME_DIR, SECRETS_DIRNAME, "auth.json");
|
|
48
18
|
/** A valid stored credential, or undefined — a foreign/old entry reads as not-configured, not a crash. */
|
|
@@ -52,27 +22,33 @@ function pick(creds, providerId) {
|
|
|
52
22
|
}
|
|
53
23
|
const AUTH_FILE_WRITE_OPTIONS = { encoding: "utf8", mode: SECRET_FILE_MODE };
|
|
54
24
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* failed unlock after a successful operation rejects instead of leaving a stale lock silently.
|
|
25
|
+
* The file a write must land IN, which is not always the path it is addressed BY. pi writes the auth file in place,
|
|
26
|
+
* so it follows a symlink to the target; an atomic rename would replace the link with a regular file instead, and
|
|
27
|
+
* from then on the two tools would be editing different files — the same split the shared lock exists to prevent,
|
|
28
|
+
* arriving one write later. A dangling link (a dotfile manager that has not checked the target out yet) still names
|
|
29
|
+
* where the credentials belong, so it is followed too rather than overwritten.
|
|
61
30
|
*/
|
|
31
|
+
function writeTarget(authPath) {
|
|
32
|
+
if (existsSync(authPath))
|
|
33
|
+
return realpathSync(authPath);
|
|
34
|
+
const link = lstatSync(authPath, { throwIfNoEntry: false });
|
|
35
|
+
// ponytail: one hop. A chain of dangling links would have its second link replaced; resolve iteratively if that
|
|
36
|
+
// ever shows up in a real layout.
|
|
37
|
+
return link?.isSymbolicLink() ? resolve(dirname(authPath), readlinkSync(authPath)) : authPath;
|
|
38
|
+
}
|
|
39
|
+
/** Serialized cross-process read-modify-write of the credentials file. */
|
|
62
40
|
async function withLockedAuthFile(authPath, fn) {
|
|
63
|
-
|
|
64
|
-
// credential file somewhere is asking for that somewhere to hold a credential. Where the process
|
|
65
|
-
// cannot chmod (a mount it does not own), this raises — the write fails visibly instead of
|
|
66
|
-
// quietly leaving the directory readable, which is the trade this repo takes everywhere else.
|
|
67
|
-
await ensureSecretsDir(dirname(authPath));
|
|
41
|
+
mkdirSync(dirname(authPath), { recursive: true });
|
|
68
42
|
if (!existsSync(authPath)) {
|
|
69
43
|
try {
|
|
44
|
+
// `wx` makes this an exclusive CREATE, which is the one case `writeFileSync` honours `mode` in — so no chmod
|
|
45
|
+
// after it (unlike writeFileAtomic, whose temp may already exist from a crashed writer).
|
|
70
46
|
writeFileSync(authPath, "{}", { ...AUTH_FILE_WRITE_OPTIONS, flag: "wx" });
|
|
71
|
-
chmodSync(authPath, SECRET_FILE_MODE);
|
|
72
47
|
}
|
|
73
48
|
catch (error) {
|
|
74
|
-
// EEXIST:
|
|
75
|
-
//
|
|
49
|
+
// EEXIST: the path IS taken, by something `existsSync` does not see through — either another process created
|
|
50
|
+
// the file just now (its credentials must not be clobbered) or the path is a dangling symlink. Both are left
|
|
51
|
+
// alone: the write below resolves where they belong.
|
|
76
52
|
if (error.code !== "EEXIST")
|
|
77
53
|
throw error;
|
|
78
54
|
}
|
|
@@ -83,6 +59,12 @@ async function withLockedAuthFile(authPath, fn) {
|
|
|
83
59
|
throw compromised;
|
|
84
60
|
};
|
|
85
61
|
const release = await lockfile.lock(authPath, {
|
|
62
|
+
// MUST match pi-coding-agent's `core/auth-storage.js`, which locks with `realpath: false`. When the auth file
|
|
63
|
+
// itself is a symlink (dotfile managers do this), the two settings name DIFFERENT lock files and both locks can
|
|
64
|
+
// be held at once — so `pi` and `fastagent` would refresh the same provider concurrently, and a rotated refresh
|
|
65
|
+
// token logs one of them out. Resolving the link would be the stronger rule, but only if BOTH sides did it, and
|
|
66
|
+
// we do not own the other side.
|
|
67
|
+
realpath: false,
|
|
86
68
|
retries: { retries: 10, factor: 2, minTimeout: 100, maxTimeout: 10_000, randomize: true },
|
|
87
69
|
stale: 30_000,
|
|
88
70
|
onCompromised: (error) => {
|
|
@@ -95,12 +77,11 @@ async function withLockedAuthFile(authPath, fn) {
|
|
|
95
77
|
const current = existsSync(authPath) ? readFileSync(authPath, "utf8") : undefined;
|
|
96
78
|
const out = await fn(current);
|
|
97
79
|
throwIfCompromised();
|
|
98
|
-
// Rename, not an in-place rewrite: it is what lets `read` stay unlocked, and it is the only
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
writeFileAtomic(authPath, out.next, SECRET_FILE_MODE);
|
|
80
|
+
// Rename, not an in-place rewrite: it is what lets `read` stay unlocked, and it is the only spelling that applies
|
|
81
|
+
// the mode before the content is reachable.
|
|
82
|
+
if (out.next !== undefined) {
|
|
83
|
+
writeFileAtomic(writeTarget(authPath), out.next, SECRET_FILE_MODE);
|
|
84
|
+
}
|
|
104
85
|
throwIfCompromised();
|
|
105
86
|
result = out.result;
|
|
106
87
|
}
|
|
@@ -114,10 +95,8 @@ async function withLockedAuthFile(authPath, fn) {
|
|
|
114
95
|
}
|
|
115
96
|
throw error;
|
|
116
97
|
}
|
|
117
|
-
// Success path: a failed release is a real cleanup failure (the leftover auth.json.lock stalls
|
|
118
|
-
// the
|
|
119
|
-
// resolving a silently degraded operation. A compromise detected after the last in-band check
|
|
120
|
-
// surfaces here too.
|
|
98
|
+
// Success path: a failed release is a real cleanup failure (the leftover auth.json.lock stalls the next writer for
|
|
99
|
+
// the staleness window with zero diagnostics), so it surfaces instead of resolving a silently degraded operation.
|
|
121
100
|
try {
|
|
122
101
|
await release();
|
|
123
102
|
}
|
|
@@ -128,12 +107,7 @@ async function withLockedAuthFile(authPath, fn) {
|
|
|
128
107
|
throwIfCompromised();
|
|
129
108
|
return result;
|
|
130
109
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Decode the credentials JSON, shared by the read and write paths. The root must be a plain
|
|
133
|
-
* non-null, non-array object: `[]`, `null`, and scalar roots pass JSON.parse but break the record
|
|
134
|
-
* semantics (an array root even swallows writes, since JSON.stringify drops string keys on arrays).
|
|
135
|
-
* Structurally invalid = corrupt, exactly like unparsable text.
|
|
136
|
-
*/
|
|
110
|
+
/** Decode the credentials JSON, shared by the read and write paths. */
|
|
137
111
|
function decodeCreds(raw) {
|
|
138
112
|
let parsed;
|
|
139
113
|
try {
|
|
@@ -146,13 +120,7 @@ function decodeCreds(raw) {
|
|
|
146
120
|
return undefined;
|
|
147
121
|
return parsed;
|
|
148
122
|
}
|
|
149
|
-
/**
|
|
150
|
-
* UNLOCKED read of the whole credentials file, shared by `read` and `list`. ONE read: the write
|
|
151
|
-
* publishes by rename, so this observes one whole version or another and has nothing to absorb by
|
|
152
|
-
* re-reading. A missing file reads as undefined silently (normal not-configured); anything that
|
|
153
|
-
* does not decode is a real corruption — a hand-edit — and says so immediately, rather than after
|
|
154
|
-
* retrying a race that cannot happen.
|
|
155
|
-
*/
|
|
123
|
+
/** UNLOCKED read of the whole credentials file, shared by `read` and `list`. */
|
|
156
124
|
function readCreds(authPath, warn) {
|
|
157
125
|
let raw;
|
|
158
126
|
try {
|
|
@@ -171,9 +139,8 @@ function readCreds(authPath, warn) {
|
|
|
171
139
|
return undefined;
|
|
172
140
|
}
|
|
173
141
|
/**
|
|
174
|
-
* Parse the credentials JSON for a WRITE: a corrupt file must THROW, because serializing `{}` over
|
|
175
|
-
*
|
|
176
|
-
* file intact.
|
|
142
|
+
* Parse the credentials JSON for a WRITE: a corrupt file must THROW, because serializing `{}` over it would wipe every
|
|
143
|
+
* other provider's credentials.
|
|
177
144
|
*/
|
|
178
145
|
function parseForWrite(raw, where) {
|
|
179
146
|
if (!raw)
|
|
@@ -184,32 +151,61 @@ function parseForWrite(raw, where) {
|
|
|
184
151
|
}
|
|
185
152
|
return creds;
|
|
186
153
|
}
|
|
187
|
-
/**
|
|
188
|
-
*
|
|
154
|
+
/**
|
|
155
|
+
* A read-write `CredentialStore` over the given credentials file (default {@link GLOBAL_AUTH_PATH}; the directory
|
|
156
|
+
* opener passes the project-level `<root>/.secrets/auth.json`), optionally falling back to a second file.
|
|
157
|
+
*
|
|
158
|
+
* The fallback is PER PROVIDER, not per file: logging one provider into a project must not hide the others a person
|
|
159
|
+
* already has globally. And the layer a credential was READ from is the layer its refresh is written back to —
|
|
160
|
+
* anything else would conjure a second holder of the same OAuth grant, which is the failure this whole area exists
|
|
161
|
+
* to avoid. A provider present in neither layer is new, and new credentials belong to the primary.
|
|
162
|
+
*/
|
|
189
163
|
export function fastagentCredentialStore(authPath = GLOBAL_AUTH_PATH, options = {}) {
|
|
190
164
|
const warn = options.warn ?? ((message) => log.warn(message));
|
|
165
|
+
const fallback = options.fallbackPath !== undefined && options.fallbackPath !== authPath ? options.fallbackPath : undefined;
|
|
166
|
+
/**
|
|
167
|
+
* The file that owns this provider: where it already is, else the primary.
|
|
168
|
+
*
|
|
169
|
+
* Known ceiling: this read is UNLOCKED, so a concurrent `fastagent login` writing the same provider into the
|
|
170
|
+
* primary between here and the lock below sends this refresh to the fallback instead — the one window in which the
|
|
171
|
+
* "one grant, one copy" rule can be lost. Re-checking under the lock means locking both files in a fixed order;
|
|
172
|
+
* worth it only if concurrent logins stop being a rounding error.
|
|
173
|
+
*/
|
|
174
|
+
const owner = (providerId) => {
|
|
175
|
+
if (fallback === undefined)
|
|
176
|
+
return authPath;
|
|
177
|
+
const primary = readCreds(authPath, warn);
|
|
178
|
+
if (primary && pick(primary, providerId))
|
|
179
|
+
return authPath;
|
|
180
|
+
const secondary = readCreds(fallback, warn);
|
|
181
|
+
return secondary && pick(secondary, providerId) ? fallback : authPath;
|
|
182
|
+
};
|
|
191
183
|
return {
|
|
192
184
|
async read(providerId) {
|
|
193
|
-
const
|
|
194
|
-
|
|
185
|
+
for (const path of fallback === undefined ? [authPath] : [authPath, fallback]) {
|
|
186
|
+
const creds = readCreds(path, warn);
|
|
187
|
+
const found = creds && pick(creds, providerId);
|
|
188
|
+
if (found)
|
|
189
|
+
return found;
|
|
190
|
+
}
|
|
191
|
+
return undefined;
|
|
195
192
|
},
|
|
196
193
|
async list() {
|
|
197
|
-
// Metadata only, never secrets (the pi-ai `list` contract).
|
|
198
|
-
//
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (cred && (cred.type === "oauth" || cred.type === "api_key")) {
|
|
205
|
-
infos.push({ providerId, type: cred.type });
|
|
194
|
+
// Metadata only, never secrets (the pi-ai `list` contract). Reverse order, so the primary's entry for a
|
|
195
|
+
// provider present in both overwrites the fallback's — the same precedence `read` applies.
|
|
196
|
+
const infos = new Map();
|
|
197
|
+
for (const path of fallback === undefined ? [authPath] : [fallback, authPath]) {
|
|
198
|
+
for (const [providerId, cred] of Object.entries(readCreds(path, warn) ?? {})) {
|
|
199
|
+
if (cred && (cred.type === "oauth" || cred.type === "api_key"))
|
|
200
|
+
infos.set(providerId, { providerId, type: cred.type });
|
|
206
201
|
}
|
|
207
202
|
}
|
|
208
|
-
return infos;
|
|
203
|
+
return [...infos.values()];
|
|
209
204
|
},
|
|
210
205
|
modify(providerId, fn) {
|
|
211
|
-
|
|
212
|
-
|
|
206
|
+
const path = owner(providerId);
|
|
207
|
+
return withLockedAuthFile(path, async (current) => {
|
|
208
|
+
const creds = parseForWrite(current, path); // corrupt → throw → no clobber
|
|
213
209
|
const next = await fn(pick(creds, providerId));
|
|
214
210
|
if (next === undefined)
|
|
215
211
|
return { result: pick(creds, providerId) }; // unchanged: no write
|
|
@@ -218,12 +214,13 @@ export function fastagentCredentialStore(authPath = GLOBAL_AUTH_PATH, options =
|
|
|
218
214
|
});
|
|
219
215
|
},
|
|
220
216
|
async delete(providerId) {
|
|
221
|
-
|
|
222
|
-
//
|
|
223
|
-
|
|
217
|
+
const path = owner(providerId);
|
|
218
|
+
// No-op when nothing is stored: do NOT take the lock (which would create the file) on a machine that never
|
|
219
|
+
// stored this provider.
|
|
220
|
+
if (!existsSync(path))
|
|
224
221
|
return;
|
|
225
|
-
await withLockedAuthFile(
|
|
226
|
-
const creds = parseForWrite(current,
|
|
222
|
+
await withLockedAuthFile(path, async (current) => {
|
|
223
|
+
const creds = parseForWrite(current, path);
|
|
227
224
|
if (!(providerId in creds))
|
|
228
225
|
return { result: undefined }; // absent: no write
|
|
229
226
|
delete creds[providerId];
|
|
@@ -1,7 +1,3 @@
|
|
|
1
1
|
import { type BuildSessionRuntimeOptions } from "./session-builder.ts";
|
|
2
|
-
/**
|
|
3
|
-
* Open the workspace's agent in pi's interactive TUI and run until the user exits. The agent is
|
|
4
|
-
* fastagent's assembled agent (same model/tools/skills/prompt/auth as dev/start serve); pi's TUI
|
|
5
|
-
* handles login, rendering, and same-workspace sessions natively.
|
|
6
|
-
*/
|
|
2
|
+
/** Open the workspace's agent in pi's interactive TUI and run until the user exits. */
|
|
7
3
|
export declare function runPiChat(dir: string, options?: BuildSessionRuntimeOptions): Promise<void>;
|
package/dist/engines/pi/chat.js
CHANGED
|
@@ -1,19 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chat: open a workspace into pi's interactive TUI (`fastagent chat`). A pi-specific COMMAND, not an
|
|
3
|
-
* engine-neutral channel: it drives pi's full session API (InteractiveMode) for fidelity, so it lives
|
|
4
|
-
* under engines/pi/ and is not re-exported.
|
|
5
|
-
*
|
|
6
|
-
* The TUI is ONE consumer of the shared definition-aware builder (session-builder.ts) — the same
|
|
7
|
-
* assembly, model surface, and fastagent auth that serving uses. Log in with `fastagent login` (or
|
|
8
|
-
* pi's TUI `/login`, which writes through the same credential store into the workspace auth file).
|
|
9
|
-
*/
|
|
1
|
+
/** Chat: open a workspace into pi's interactive TUI (`fastagent chat`). */
|
|
10
2
|
import { InteractiveMode } from "@earendil-works/pi-coding-agent";
|
|
11
3
|
import { buildAgentSessionRuntime } from "./session-builder.js";
|
|
12
|
-
/**
|
|
13
|
-
* Open the workspace's agent in pi's interactive TUI and run until the user exits. The agent is
|
|
14
|
-
* fastagent's assembled agent (same model/tools/skills/prompt/auth as dev/start serve); pi's TUI
|
|
15
|
-
* handles login, rendering, and same-workspace sessions natively.
|
|
16
|
-
*/
|
|
4
|
+
/** Open the workspace's agent in pi's interactive TUI and run until the user exits. */
|
|
17
5
|
export async function runPiChat(dir, options = {}) {
|
|
18
6
|
const runtime = await buildAgentSessionRuntime(dir, options);
|
|
19
7
|
await new InteractiveMode(runtime, {}).run();
|
|
@@ -2,47 +2,40 @@ import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
|
2
2
|
import type { FastagentTool } from "./tool.ts";
|
|
3
3
|
import type { Models } from "@earendil-works/pi-ai";
|
|
4
4
|
import type { AnyModel } from "./models.ts";
|
|
5
|
+
import type { HttpSurface } from "../../service.ts";
|
|
5
6
|
export interface FastagentConfig {
|
|
6
|
-
/** "provider/modelId".
|
|
7
|
+
/** "provider/modelId". */
|
|
7
8
|
model?: string;
|
|
8
|
-
/** Reasoning effort for the model, pi's scale ("off" | "minimal" | "low" | "medium" | "high" |
|
|
9
|
-
* "xhigh" | "max"). Unset = pi's default. Authors tune thinking in the pi TUI while vibing — this
|
|
10
|
-
* is the serving-side counterpart (fidelity). Levels a model doesn't support are clamped by pi. */
|
|
9
|
+
/** Reasoning effort for the model, pi's scale ("off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max"). */
|
|
11
10
|
thinkingLevel?: ThinkingLevel;
|
|
12
|
-
/** Extra custom tools, appended after the pi coding tools — never replaces them.
|
|
13
|
-
* = AgentTool plus the optional `deferred` marker (see defineTool). */
|
|
11
|
+
/** Extra custom tools, appended after the pi coding tools — never replaces them. */
|
|
14
12
|
tools?: FastagentTool[];
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
/** What the serve publishes on its port, and to which browsers (each key is documented on {@link HttpSurface}). */
|
|
14
|
+
http?: HttpSurface & {
|
|
15
|
+
/** Default port for `dev` / `start` (`DEFAULT_HTTP_PORT` when unset). */
|
|
18
16
|
port?: number;
|
|
19
|
-
host?: string;
|
|
20
17
|
};
|
|
21
|
-
/** Mount the built-in `wake` tool so the agent can schedule its OWN follow-up turns (self-scheduling).
|
|
22
|
-
* Off by default — self-scheduling is an autonomy capability, opt in when you want it. Only takes
|
|
23
|
-
* effect on the serving path (`dev`/`start`, where the scheduler poller honors a wake-up). */
|
|
24
|
-
selfSchedule?: boolean;
|
|
25
18
|
/**
|
|
26
|
-
* Serve the session control plane over HTTP (`/control/*`: state/entries/events + dispatch —
|
|
27
|
-
*
|
|
28
|
-
* attach`. Default off (it is a remote-control surface). When on, `dev`/`start` generate a
|
|
29
|
-
* per-boot bearer token and write `<stateRoot>/control.json` for local discovery. The serve
|
|
30
|
-
* binds all interfaces by default, so the routes are LAN-reachable with the token as the only
|
|
31
|
-
* protection — bind loopback (`--bind 127.0.0.1`; not `http.host`, which travels into a deployed
|
|
32
|
-
* image), firewall the port, or wrap it for real exposure (docs/design/session-control.md §14).
|
|
19
|
+
* Serve the session control plane over HTTP (`/control/*`: state/entries/events + dispatch — steer/abort/compact +
|
|
20
|
+
* session properties and lifecycle) for remote consumers.
|
|
33
21
|
*/
|
|
34
22
|
sessionControl?: boolean;
|
|
35
|
-
/**
|
|
36
|
-
*
|
|
23
|
+
/**
|
|
24
|
+
* Deploy-time declarations for what the agent needs on the box, so real agents don't hand-write a Dockerfile /
|
|
25
|
+
* hand-set variables.
|
|
26
|
+
*/
|
|
37
27
|
deploy?: {
|
|
38
|
-
/** Extra
|
|
39
|
-
* a `GH_TOKEN` its tools use. `deploy` carries each from the LOCAL env to the host secret store and
|
|
40
|
-
* lists them in the runbook; a missing value gates `--run` (like a channel secret). */
|
|
41
|
-
secrets?: string[];
|
|
42
|
-
/** Extra apt packages baked into the generated image (Debian default repos: git, ripgrep, jq…). For a
|
|
43
|
-
* package needing a custom apt repo (e.g. gh) or a different base image, provide your own Dockerfile
|
|
44
|
-
* — `deploy` keeps an existing one. */
|
|
28
|
+
/** Extra apt packages baked into the generated image (Debian default repos: git, ripgrep, jq…). */
|
|
45
29
|
apt?: string[];
|
|
30
|
+
/** `deploy agentcore` only. */
|
|
31
|
+
agentcore?: {
|
|
32
|
+
/**
|
|
33
|
+
* How long an idle AgentCore session keeps its microVM, 60–1209600 seconds (default 180). Memory bills for the
|
|
34
|
+
* whole idle tail, and a session past it cold-starts — the workload picks the trade: a chat agent talked to in
|
|
35
|
+
* bursts wants a longer tail, a schedule-only agent a shorter one.
|
|
36
|
+
*/
|
|
37
|
+
idleTimeoutSeconds?: number;
|
|
38
|
+
};
|
|
46
39
|
};
|
|
47
40
|
}
|
|
48
41
|
/** Identity function for typing and IDE completion (vite/next-style). */
|
|
@@ -52,37 +45,46 @@ export interface LoadedConfig {
|
|
|
52
45
|
/** Config file path; undefined when the loader was pointed at a directory holding none. */
|
|
53
46
|
path?: string;
|
|
54
47
|
}
|
|
55
|
-
/** A valid bindable port. */
|
|
56
48
|
export declare function isValidPort(n: number): boolean;
|
|
57
|
-
/** Load `<dir>/fastagent.config.ts
|
|
49
|
+
/** Load `<dir>/fastagent.config.ts`. */
|
|
58
50
|
export declare function loadConfig(dir: string): Promise<LoadedConfig>;
|
|
59
|
-
/** The provider prefix of a "provider/modelId" spec.
|
|
60
|
-
* lookups then miss visibly (an unknown-provider error / a login-required hint), never a mangled id
|
|
61
|
-
* (`slice(0, indexOf("/"))` silently drops the last char when "/" is absent). */
|
|
51
|
+
/** The provider prefix of a "provider/modelId" spec. */
|
|
62
52
|
export declare function providerOf(spec: string): string;
|
|
63
53
|
/** Resolve "provider/modelId" → a pi Model from `models`, so auth resolves from the same collection. */
|
|
64
54
|
export declare function resolveModel(models: Models, spec: string): AnyModel;
|
|
65
55
|
/** All registered "provider/modelId" specs in `models`, sorted — the list behind `fastagent models`. */
|
|
66
56
|
export declare function listModels(models: Models): string[];
|
|
67
|
-
/**
|
|
68
|
-
* Rewrite the `model` in a config file's SOURCE TEXT to `spec`, for the first-run picker's write-back.
|
|
69
|
-
* Handles the scaffold's commented placeholder (`// model: "…"`) and an existing `model:` line; returns
|
|
70
|
-
* null when neither is present (no config file, or a hand-shaped one) so the caller falls back to a
|
|
71
|
-
* printed hint instead of guessing where to insert. Text-level (not AST) on purpose — it only ever
|
|
72
|
-
* touches a line it recognizes, never reformats the author's file.
|
|
73
|
-
*/
|
|
57
|
+
/** Rewrite the `model` in a config file's SOURCE TEXT to `spec`, for the first-run picker's write-back. */
|
|
74
58
|
export declare function rewriteConfigModel(src: string, spec: string): string | null;
|
|
75
|
-
/** Model selection precedence: CLI flag > FASTAGENT_MODEL env > config default. */
|
|
76
|
-
export declare function resolveModelSpec(flag: string | undefined, config: FastagentConfig, env?: NodeJS.ProcessEnv): string | undefined;
|
|
77
59
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
60
|
+
* Model selection precedence: CLI flag > FASTAGENT_MODEL env > config default. An EMPTY `FASTAGENT_MODEL` is
|
|
61
|
+
* "unset", not "no model": `export FASTAGENT_MODEL=` in a shell or CI job, and an `environment:`/`env` entry that
|
|
62
|
+
* interpolates a missing variable, both arrive as `""` — and a set-but-empty value that shadowed `config.model`
|
|
63
|
+
* would refuse to start an agent whose config names a model.
|
|
81
64
|
*/
|
|
82
|
-
export declare function
|
|
65
|
+
export declare function resolveModelSpec(flag: string | undefined, config: FastagentConfig, env?: NodeJS.ProcessEnv): string | undefined;
|
|
83
66
|
/** The default credentials file under a resolved secrets dir ({@link resolveSecretsDir}). */
|
|
84
67
|
export declare function defaultAuthPath(secretsDir: string): string;
|
|
85
68
|
/** The effective auth file for an agent: override if present, else `<secrets dir>/auth.json`. */
|
|
86
|
-
export declare function resolveAuthPath(dir: string, flag
|
|
87
|
-
/**
|
|
88
|
-
|
|
69
|
+
export declare function resolveAuthPath(dir: string, flag?: string, env?: NodeJS.ProcessEnv): string;
|
|
70
|
+
/**
|
|
71
|
+
* Which credentials files an agent reads: `path` first, then, per provider, `fallback` — present only when nothing
|
|
72
|
+
* named the path ({@link resolveAuthFallback}). One value because it is one decision: the opener, the model list, the
|
|
73
|
+
* startup report and the first-run picker all read through it.
|
|
74
|
+
*/
|
|
75
|
+
export interface AuthLayers {
|
|
76
|
+
path: string;
|
|
77
|
+
fallback?: string;
|
|
78
|
+
}
|
|
79
|
+
/** The {@link AuthLayers} an agent directory reads: `authPath` option > `FASTAGENT_AUTH_PATH` > its own file. */
|
|
80
|
+
export declare function resolveAuthLayers(agentDir: string, authPath?: string, env?: NodeJS.ProcessEnv): AuthLayers;
|
|
81
|
+
/**
|
|
82
|
+
* Where a credential the project does not have is read from instead: the user-global store, because a login is a
|
|
83
|
+
* PERSON on a machine and not a project — one `login -g` then serves every agent here. Undefined when an explicit
|
|
84
|
+
* path was named: "use this file" is an instruction, not a preference, so it gets no second layer.
|
|
85
|
+
*
|
|
86
|
+
* BOTH knobs {@link resolveAuthPath} reads count as that instruction, `FASTAGENT_SECRETS_DIR` included — it is what
|
|
87
|
+
* the Fly/Railway/AgentCore artifacts set, and a deployed container must read its mounted credentials and nothing
|
|
88
|
+
* else (the artifact is the truth).
|
|
89
|
+
*/
|
|
90
|
+
export declare function resolveAuthFallback(flag?: string, env?: NodeJS.ProcessEnv): string | undefined;
|