@fastagent-sh/fastagent 0.21.1 → 0.22.1
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 -40
- 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 +233 -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 +166 -229
- 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
|
@@ -1,125 +1,175 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
/** Production serving. */
|
|
10
|
+
import { join, resolve } from "node:path";
|
|
11
|
+
import { pathToFileURL } from "node:url";
|
|
12
|
+
import { createRequire } from "node:module";
|
|
13
|
+
import { readFile } from "node:fs/promises";
|
|
14
|
+
import * as Effect from "effect/Effect";
|
|
6
15
|
import { writeFileAtomic } from "../../atomic-write.js";
|
|
7
|
-
import { authSeedBytes, collectAuthSeed } from "../../deploy/secrets.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
16
|
+
import { applyCarriedEnv, authSeedBytes, collectAuthSeed } from "../../deploy/secrets.js";
|
|
17
|
+
import { applyReleaseEnv, installAgentDependencies, parseDeploymentRelease, prepareDeployment, } from "../../deploy/workspace.js";
|
|
18
|
+
import { resolveAuthPath } from "../../engines/pi/config.js";
|
|
19
|
+
import { SECRET_FILE_MODE, resolveSecretsDir, isAgentcoreRuntime, isUnderDir, exists } from "../../paths.js";
|
|
10
20
|
import { log, setLogLevel } from "../../log.js";
|
|
11
21
|
import { createPiAgentFromDir } from "../../engines/pi/open.js";
|
|
12
|
-
import { mountAgentService } from "../../service.js";
|
|
22
|
+
import { DEFAULT_HTTP_PORT, mountAgentService } from "../../service.js";
|
|
13
23
|
import { logAgentLoop } from "../../observe.js";
|
|
14
|
-
import {
|
|
24
|
+
import { mountAgentcoreService, deferAgentcoreService } from "../../channels/agentcore-service.js";
|
|
15
25
|
import { createWakeAlarmSink } from "../../schedule/wake-alarm.js";
|
|
16
26
|
import { setWakeupsSink } from "../../schedule/wakeups.js";
|
|
17
27
|
import { failStartup } from "../fail.js";
|
|
18
|
-
import {
|
|
28
|
+
import { announceControl, assertTunnelBindable, bindLine, cliMountOptions, serveService, serve, withRunOverrides, } from "../serve.js";
|
|
19
29
|
import { enterAgentCommand, parseBind, parsePort, reportAssembly } from "../shared.js";
|
|
20
30
|
export async function runStart(dirArg, opts) {
|
|
21
|
-
// Flag validation first: a bad --port is a USAGE error (exit 2), and reporting it must not depend on
|
|
22
|
-
// the directory being an agent (which is a runtime/environment failure, exit 1).
|
|
23
31
|
const portFlag = parsePort(opts.port, "--port", "flag");
|
|
24
32
|
const bindFlag = parseBind(opts.bind);
|
|
33
|
+
// A host that carries the value file as ONE encoded variable (AgentCore): expanded before anything reads the env.
|
|
34
|
+
try {
|
|
35
|
+
applyCarriedEnv();
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
failStartup(error);
|
|
39
|
+
}
|
|
40
|
+
setLogLevel("info");
|
|
41
|
+
if (isAgentcoreRuntime()) {
|
|
42
|
+
// The generated Runtime resource sets PORT; 8080 is the platform's contract when nothing does.
|
|
43
|
+
const port = portFlag ?? parsePort(process.env.PORT, "PORT env", "env") ?? 8080;
|
|
44
|
+
const deferred = deferAgentcoreService({
|
|
45
|
+
prepare: () => prepareStartWorkspace(dirArg),
|
|
46
|
+
assemble: async (prepared) => {
|
|
47
|
+
const service = await openPreparedWorkspace(prepared, opts);
|
|
48
|
+
await service.ready;
|
|
49
|
+
announceControl(service, { host: bindFlag, tunnel: false });
|
|
50
|
+
return service;
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
serve(deferred.handler, { port, host: bindFlag }, {
|
|
54
|
+
// The assembly report waits for the first envelope, so this line is the only sign of life a booted container
|
|
55
|
+
// gives.
|
|
56
|
+
onListening: (port) => {
|
|
57
|
+
// NOT `readyAddressLines`: this posture serves the Runtime's `/invocations` contract, not our `/invoke`.
|
|
58
|
+
log.info(bindLine(bindFlag, port));
|
|
59
|
+
log.info("[fastagent] agentcore: the definition opens on the first invocation");
|
|
60
|
+
},
|
|
61
|
+
onShutdown: () => deferred.close(),
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// Deployed storage refusals (no mount, a held lease, a missing `flock`, a failed install) are the operator's only
|
|
66
|
+
// clue in a crash-looping container.
|
|
67
|
+
const service = await openStartService(dirArg, opts).catch(failStartup);
|
|
25
68
|
const tunnel = opts.tunnel ?? false;
|
|
26
|
-
|
|
69
|
+
// An unset bind stays the wildcard: this is the container posture, and a published port needs it.
|
|
70
|
+
assertTunnelBindable(bindFlag, tunnel);
|
|
71
|
+
serveService(service, { port: portFlag ?? parsePort(process.env.PORT, "PORT env", "env") ?? service.port, host: bindFlag }, { tunnel, agentDir: service.agentDir, stateRoot: service.stateRoot });
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Stage one — TAKE the workspace: verify the storage is mounted, apply the release, and point the machinery at the
|
|
75
|
+
* volume.
|
|
76
|
+
*/
|
|
77
|
+
export async function prepareStartWorkspace(dirArg) {
|
|
78
|
+
const manifestPath = process.env.FASTAGENT_RELEASE_FILE;
|
|
79
|
+
if (!manifestPath)
|
|
80
|
+
return { dir: dirArg };
|
|
81
|
+
const storage = process.env.FASTAGENT_STORAGE_DIR;
|
|
82
|
+
if (!storage)
|
|
83
|
+
throw new Error("FASTAGENT_STORAGE_DIR is required for a deployed workspace");
|
|
84
|
+
const root = resolve(storage);
|
|
85
|
+
const manifest = parseDeploymentRelease(await readFile(manifestPath, "utf8"));
|
|
86
|
+
const dir = await prepareDeployment(resolve(dirArg), root, manifest);
|
|
87
|
+
// Defaults, not overrides: an operator who pointed either dir somewhere else meant it, and silently relocating
|
|
88
|
+
// their state is the one failure they could not diagnose from the logs.
|
|
89
|
+
process.env.FASTAGENT_STATE_DIR ||= join(root, ".state");
|
|
90
|
+
process.env.FASTAGENT_SECRETS_DIR ||= join(root, ".secrets");
|
|
91
|
+
process.env.FASTAGENT_AGENT = manifest.agent;
|
|
92
|
+
// The release's own declarations, projected into the environment it was resolved FOR. This must stay BEFORE
|
|
93
|
+
// `enterAgentEnv` reads the workspace's `.env`, which is what makes either source outrank a value edited on the
|
|
94
|
+
// box (applyReleaseEnv's own tests pin the precedence).
|
|
95
|
+
applyReleaseEnv(manifest);
|
|
96
|
+
process.chdir(dir);
|
|
97
|
+
return { dir, deployed: { root, agent: manifest.agent } };
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Stage two — RUN in the prepared workspace: install the agent's dependencies, then open through the workspace's own
|
|
101
|
+
* FastAgent install.
|
|
102
|
+
*/
|
|
103
|
+
export async function openPreparedWorkspace(prepared, opts) {
|
|
104
|
+
let open = openPreparedStartService;
|
|
105
|
+
if (prepared.deployed) {
|
|
106
|
+
const { root, agent } = prepared.deployed;
|
|
107
|
+
const agentDir = join(prepared.dir, agent);
|
|
108
|
+
if (await exists(join(agentDir, "package.json"))) {
|
|
109
|
+
await installAgentDependencies(root, agentDir);
|
|
110
|
+
// Tools and their session context must share the workspace's runtime module instance.
|
|
111
|
+
const entry = createRequire(join(agentDir, "package.json")).resolve("@fastagent-sh/fastagent");
|
|
112
|
+
const local = (await import(__rewriteRelativeImportExtension(new URL("./cli/commands/start.js", pathToFileURL(entry)).href)));
|
|
113
|
+
// A version-skewed dependency resolves and imports fine, then fails as "open is not a function" with nothing
|
|
114
|
+
// naming the two versions.
|
|
115
|
+
if (typeof local.openPreparedStartService !== "function") {
|
|
116
|
+
throw new Error(`${entry} does not export openPreparedStartService — align the agent's @fastagent-sh/fastagent version with the deploy CLI`);
|
|
117
|
+
}
|
|
118
|
+
open = local.openPreparedStartService;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return open(prepared.dir, opts);
|
|
122
|
+
}
|
|
123
|
+
export async function openStartService(dirArg, opts) {
|
|
124
|
+
return openPreparedWorkspace(await prepareStartWorkspace(dirArg), opts);
|
|
125
|
+
}
|
|
126
|
+
/** Internal entry loaded from the active workspace's installed package after storage initialization. */
|
|
127
|
+
export async function openPreparedStartService(dirArg, opts) {
|
|
27
128
|
const placement = await enterAgentCommand(dirArg, opts);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// Same resolveAuthPath the opener uses — ONE owner of the flag > env > default chain.
|
|
31
|
-
await maybeSeedAuth(resolveAuthPath(placement.agentDir, opts.authPath));
|
|
32
|
-
// The same opener dev uses (single assembly source), just no watch.
|
|
33
|
-
const opened = await createPiAgentFromDir(placement.workspace, {
|
|
129
|
+
await maybeSeedAuth(resolveAuthPath(placement.agentDir));
|
|
130
|
+
const opened = await createPiAgentFromDir(placement.agentDir, {
|
|
34
131
|
model: opts.model,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
serving: true, // long-running serve: the scheduler poller runs (wake mounts iff config.selfSchedule)
|
|
38
|
-
}).catch(failStartup);
|
|
132
|
+
serving: true,
|
|
133
|
+
});
|
|
39
134
|
const { agent, agentDir, config, stateRoot, sessionsDir } = opened;
|
|
40
|
-
// The same report `dev` prints; `state:`/`sessions:` are start's own extras, and the persistence
|
|
41
|
-
// notes below are why (see reportAssembly on the asymmetry).
|
|
42
135
|
await reportAssembly(opened, {
|
|
43
136
|
afterTools: [
|
|
44
137
|
["state", stateRoot],
|
|
45
138
|
["sessions", sessionsDir],
|
|
46
139
|
],
|
|
47
140
|
});
|
|
48
|
-
// State defaults under the agent dir, which a redeploy may replace wholesale. Gate on where the
|
|
49
|
-
// state root ACTUALLY resolved (inside the agent dir?), not on the raw env var: an empty
|
|
50
|
-
// `FASTAGENT_STATE_DIR=""` reads as unset (resolveStateRoot) and still lands in-agent, so a raw
|
|
51
|
-
// `=== undefined` check would wrongly silence the warning. A sessions override to a volume does not
|
|
52
|
-
// help — channel state (the telegram turn/context files replay depends on) is still in-agent.
|
|
53
|
-
// (auth.json is NOT under the state root — it lives in the secrets dir, resolveSecretsDir.)
|
|
54
141
|
if (isUnderDir(stateRoot, agentDir)) {
|
|
55
|
-
log.info(
|
|
56
|
-
`FASTAGENT_STATE_DIR at a persistent volume so a redeploy that replaces the dir does not wipe it.`);
|
|
142
|
+
log.info("[fastagent] note: state lives under the definition; use FASTAGENT_STATE_DIR on persistent storage for deployment.");
|
|
57
143
|
}
|
|
58
|
-
// The secrets dir is the SAME trap on a different lifecycle: auth.json is MACHINE-WRITTEN (OAuth
|
|
59
|
-
// rotation), so the copy under the definition dir is the only valid one — a redeploy that replaces
|
|
60
|
-
// the dir loses a credential no re-seed can restore. An independent check on purpose: moving ONE
|
|
61
|
-
// of the two to a volume must not silence the note about the other.
|
|
62
144
|
if (isUnderDir(resolveSecretsDir(agentDir), agentDir)) {
|
|
63
|
-
log.info(
|
|
64
|
-
`FASTAGENT_SECRETS_DIR at a persistent volume so a redeploy that replaces the dir does not wipe them.`);
|
|
145
|
+
log.info("[fastagent] note: credentials live under the definition; use FASTAGENT_SECRETS_DIR on persistent storage for deployment.");
|
|
65
146
|
}
|
|
66
|
-
// Same debug turn trace as dev; gated out here by the info level.
|
|
67
147
|
const traced = logAgentLoop(agent);
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
// pre-restore state mount, an external clock, no resident connections — but it yields the same
|
|
71
|
-
// AgentService, so everything below this point is common.
|
|
72
|
-
// The wake-alarm sink is a PROCESS-global (schedule/wakeups.ts) — this process IS the AgentCore
|
|
73
|
-
// deployment, so the process entry installs it. A service can be closed; a global cannot be
|
|
74
|
-
// handed to something that can, without inventing an ownership the singleton does not have.
|
|
75
|
-
const onStateReady = isAgentcoreRuntime() && config.selfSchedule ? armWakeAlarms(stateRoot) : undefined;
|
|
148
|
+
const onStateReady = isAgentcoreRuntime() ? armWakeAlarms(stateRoot) : undefined;
|
|
149
|
+
const mountable = withRunOverrides(opened, opts);
|
|
76
150
|
const service = await (isAgentcoreRuntime()
|
|
77
|
-
? mountAgentcoreService(
|
|
78
|
-
: mountAgentService(
|
|
79
|
-
|
|
80
|
-
// No graceful drain: webhook turns run fire-and-forget; SIGTERM just exits mid-turn. Whether an
|
|
81
|
-
// in-flight turn is LOST depends on the channel: the Telegram channel persists turn intent pre-ACK
|
|
82
|
-
// and replays it next start (turn-store.ts, L1 durable execution, at-least-once); HTTP and other
|
|
83
|
-
// channels have no such layer, so their in-flight turns are still lost (the asker re-invokes).
|
|
151
|
+
? mountAgentcoreService(mountable, { wrapAgent: () => traced, onStateReady })
|
|
152
|
+
: mountAgentService(mountable, cliMountOptions(() => traced)));
|
|
153
|
+
return { ...service, stateRoot, port: config.http?.port ?? DEFAULT_HTTP_PORT };
|
|
84
154
|
}
|
|
85
|
-
/**
|
|
86
|
-
* Materialize `FASTAGENT_AUTH_SEED` (base64 of an auth.json, set by `deploy --run`) into the
|
|
87
|
-
* writable secrets dir ONCE — only when the seed is set AND the auth file is absent, so a refreshed
|
|
88
|
-
* volume copy is never clobbered by the stale seed. Lets a deploy carry the operator's local
|
|
89
|
-
* OAuth/API credential so the box runs on the SAME subscription. No-op locally (the seed is unset).
|
|
90
|
-
*/
|
|
91
155
|
async function maybeSeedAuth(authPath) {
|
|
92
|
-
// collectAuthSeed: the seed may arrive CHUNKED (FASTAGENT_AUTH_SEED + _2…) on hosts with a small
|
|
93
|
-
// env-value max length (AgentCore); single-var hosts are unchanged.
|
|
94
156
|
const bytes = authSeedBytes(collectAuthSeed(process.env), await exists(authPath));
|
|
95
157
|
if (!bytes)
|
|
96
158
|
return;
|
|
97
|
-
|
|
98
|
-
// Same spelling as the credential store: the mode is applied before the content is reachable, so
|
|
99
|
-
// the seed can never be published at some other file's looser permissions. It does NOT close the
|
|
100
|
-
// gap between the `exists` check and the write — the rename would overwrite a file created in
|
|
101
|
-
// between, against this function's absent-only promise. That window needs two `start` processes on
|
|
102
|
-
// one secrets dir, which no supported deployment runs (one container, one volume).
|
|
103
|
-
writeFileAtomic(authPath, bytes, SECRET_FILE_MODE);
|
|
159
|
+
writeFileAtomic(authPath, bytes, SECRET_FILE_MODE); // creates the directory it needs
|
|
104
160
|
log.info(`[fastagent] seeded ${authPath} from FASTAGENT_AUTH_SEED (first boot)`);
|
|
105
161
|
}
|
|
106
162
|
/**
|
|
107
|
-
* Install the wake-ALARM sink before the scheduler starts
|
|
108
|
-
*
|
|
109
|
-
* running it at boot would read the pre-restore state mount, see no pending wake-ups, and conclude
|
|
110
|
-
* there is nothing to re-arm.
|
|
163
|
+
* Install the wake-ALARM sink before the scheduler starts: the first wake poll may advance a recurring entry, and that
|
|
164
|
+
* save must already re-arm its alarm.
|
|
111
165
|
*/
|
|
112
166
|
function armWakeAlarms(stateRoot) {
|
|
113
167
|
const secret = process.env.FASTAGENT_WAKE_SECRET;
|
|
114
168
|
if (!secret) {
|
|
115
|
-
log.warn(
|
|
116
|
-
`(redeploy with the current template to fix)`);
|
|
169
|
+
log.warn("[fastagent] FASTAGENT_WAKE_SECRET is missing; external wake alarms cannot be registered");
|
|
117
170
|
return undefined;
|
|
118
171
|
}
|
|
119
|
-
const sink = createWakeAlarmSink({ secret });
|
|
172
|
+
const sink = Effect.runSync(createWakeAlarmSink({ secret }));
|
|
120
173
|
setWakeupsSink(sink);
|
|
121
|
-
log.info(`[fastagent] wake alarms: EventBridge-backed via the forwarder`);
|
|
122
|
-
// Boot reconcile: pending wake-ups may exist while their alarms were lost (a deploy replaced the
|
|
123
|
-
// forwarder, a sink call failed). The sink re-reads the store, so a bare notification is enough.
|
|
124
174
|
return () => sink(stateRoot);
|
|
125
175
|
}
|
|
@@ -1,36 +1,50 @@
|
|
|
1
1
|
/** `fastagent tool <name> '<json>' [dir]`: run one tool's body directly with JSON args — no model. */
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { enterAgentEnv } from "../../env.js";
|
|
4
4
|
import { loadConfig } from "../../engines/pi/config.js";
|
|
5
5
|
import { resolveAgentTools } from "../../engines/pi/create.js";
|
|
6
6
|
import { reportModuleLoadFailures } from "../../loader.js";
|
|
7
7
|
import { turnContext } from "../../engines/pi/tool-context.js";
|
|
8
|
-
import { failStartup, failUsage, placementOrExit } from "../fail.js";
|
|
8
|
+
import { failStartup, failUsage, gateSecretsOrExit, placementOrExit } from "../fail.js";
|
|
9
9
|
export async function runTool(name, argsJson, dirArg) {
|
|
10
|
-
// Argument shape first: malformed JSON is a USAGE error (exit 2), independent of whether the
|
|
11
|
-
//
|
|
10
|
+
// Argument shape first: malformed JSON is a USAGE error (exit 2), independent of whether the directory is an agent
|
|
11
|
+
// (a runtime failure, exit 1).
|
|
12
12
|
const args = parseToolArgs(argsJson);
|
|
13
13
|
const { agentDir, workspace } = placementOrExit(resolve(dirArg));
|
|
14
|
-
|
|
14
|
+
enterAgentEnv(agentDir); // a tool may read a key from .env — and fetch through the proxy it declares
|
|
15
15
|
const { config } = await loadConfig(agentDir).catch(failStartup);
|
|
16
16
|
// The same tool set dev/start mount (all coding tools + config.tools + discovered, deduped), so the runner
|
|
17
|
-
// exercises exactly what gets served
|
|
18
|
-
|
|
19
|
-
const { tools, toolCollisions, toolFailures } = await resolveAgentTools(config, agentDir, workspace).catch(failStartup);
|
|
17
|
+
// exercises exactly what gets served.
|
|
18
|
+
const { tools, toolCollisions, toolFailures, toolSecrets } = await resolveAgentTools(config, agentDir, workspace).catch(failStartup);
|
|
20
19
|
for (const c of toolCollisions) {
|
|
21
20
|
console.error(`[fastagent] warn: tool "${c.name}" (${c.source}) is shadowed by a default/config tool — not mounted`);
|
|
22
21
|
}
|
|
22
|
+
// Reported BEFORE the name is looked up: a file that failed to import is missing from `tools`, so
|
|
23
|
+
// "unknown tool" is exactly the case where the author most needs to hear that something blew up
|
|
24
|
+
// rather than that they mistyped it.
|
|
23
25
|
reportModuleLoadFailures(toolFailures);
|
|
24
26
|
const tool = tools.find((t) => t.name === name);
|
|
25
27
|
if (!tool) {
|
|
26
28
|
failStartup(new Error(`unknown tool "${name}". available: ${tools.map((t) => t.name).join(", ") || "(none)"}`));
|
|
27
29
|
}
|
|
30
|
+
// This command RUNS one tool body, so it takes the same guarantee dev/start take — for THAT tool
|
|
31
|
+
// only (`owner`): running one tool by hand must not require the credentials of the tools it is not
|
|
32
|
+
// running, and `routine run` scopes the same way for one routine.
|
|
33
|
+
// The failures go to the gate as well, even though they were just printed: the gate's guarantee is
|
|
34
|
+
// that a refusal never hides them, and it cannot know a caller already reported. A repeated line on
|
|
35
|
+
// the refusal path is the cheaper failure than one that depends on this call site remembering.
|
|
36
|
+
gateSecretsOrExit({ declared: toolSecrets, failures: toolFailures, owner: name });
|
|
28
37
|
// Authored tools read cwd from turnContext; coding tools are already rooted at the workspace.
|
|
29
38
|
const result = await turnContext.run({ cwd: workspace }, () => tool.execute(`cli-${name}`, args)).catch(failStartup);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
// What the MODEL receives, which is not what is printed below: the printed form is `details` (readable, indented),
|
|
40
|
+
// the model's is the content text (compact JSON). Piping stdout through `wc -c` therefore answers the wrong
|
|
41
|
+
// question, and there is nowhere else to ask this one — so the run that a tool author already does reports it.
|
|
42
|
+
const modelText = (result?.content ?? []).map((c) => ("text" in c ? c.text : "")).join("");
|
|
43
|
+
const out = result?.details !== undefined ? result.details : modelText;
|
|
44
|
+
console.log(typeof out === "string" ? out : JSON.stringify(out, null, 2)); // stdout stays DATA
|
|
45
|
+
// No threshold warning: context windows run from 128k to 1M, so any fixed ceiling here would be invented. The
|
|
46
|
+
// number is the signal; docs/api-reference.md carries the judgement. ~4 chars/token is the usual rough figure.
|
|
47
|
+
console.error(`[fastagent] result: ${modelText.length} chars ≈ ${Math.ceil(modelText.length / 4)} tokens to the model`);
|
|
34
48
|
}
|
|
35
49
|
/** Parse the CLI's JSON args blob; malformed input syntax is a usage error (exit 2). */
|
|
36
50
|
function parseToolArgs(argsJson) {
|
package/dist/cli/fail.d.ts
CHANGED
|
@@ -1,34 +1,24 @@
|
|
|
1
1
|
import { type ResolvedPlacement } from "../paths.ts";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* otherwise. Errors are the only place the CLI uses color at all.
|
|
5
|
-
*/
|
|
2
|
+
import { gateSecrets } from "../secrets-gate.ts";
|
|
3
|
+
/** The ONE error prefix every error message carries — bold red when stderr renders color, plain otherwise. */
|
|
6
4
|
export declare function errorPrefix(colors?: boolean): string;
|
|
7
5
|
/**
|
|
8
|
-
* User-fixable startup problems (missing model / bad config / broken definition) are thrown as plain
|
|
9
|
-
*
|
|
10
|
-
* Shared by the kernel and the command modules; exit 1 (runtime failure).
|
|
6
|
+
* User-fixable startup problems (missing model / bad config / broken definition) are thrown as plain `Error` — print
|
|
7
|
+
* just the message. Anything else (a TypeError, a non-Error throw) is a bug: keep the stack.
|
|
11
8
|
*/
|
|
12
9
|
export declare function failStartup(error: unknown): never;
|
|
13
10
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* exists, so it cannot ride the `.catch(failStartup)` every async startup chain carries — and its
|
|
20
|
-
* refusals ("not a fastagent agent", plus the two dead ends with their own exits) are user-fixable,
|
|
21
|
-
* which means a one-line `Error:` and exit 1, never a stack.
|
|
22
|
-
*
|
|
23
|
-
* Not every command calls it — and the exceptions are the useful part of this note. `init` CREATES the
|
|
24
|
-
* agent (it must run where there is none). `models` is directory-independent. `login` needs one only for
|
|
25
|
-
* the project-level credential and falls back to the global one, and `attach --url/--token` reads
|
|
26
|
-
* nothing local. Everything else needs an agent, so it comes through here.
|
|
11
|
+
* {@link gateSecrets} at the process boundary, for a command that runs ONE owner's code (`fastagent
|
|
12
|
+
* tool`, `fastagent routine run`). The gate throws SYNCHRONOUSLY, so there is no promise to hang the usual
|
|
13
|
+
* `.catch(failStartup)` on, and a raw throw reaches `cli.ts`'s top-level await as a Node stack that
|
|
14
|
+
* buries the one line naming the file. The catch translates that expected failure into the CLI's
|
|
15
|
+
* single-line refusal and exits 1; nothing is recovered.
|
|
27
16
|
*/
|
|
17
|
+
export declare function gateSecretsOrExit(input: Parameters<typeof gateSecrets>[0]): void;
|
|
18
|
+
/** THE placement entry point for commands: resolve `dir`, or exit 1 with the one-line refusal. */
|
|
28
19
|
export declare function placementOrExit(dir: string): ResolvedPlacement;
|
|
29
20
|
/**
|
|
30
|
-
* A usage error the parser could not catch (a bad value shape, an invalid flag/argument combination
|
|
31
|
-
*
|
|
32
|
-
* Exit codes follow responsibility, not the layer that happens to discover the problem.
|
|
21
|
+
* A usage error the parser could not catch (a bad value shape, an invalid flag/argument combination discovered in a
|
|
22
|
+
* command body): print the message and exit 2.
|
|
33
23
|
*/
|
|
34
24
|
export declare function failUsage(message: string): never;
|
package/dist/cli/fail.js
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import { resolvePlacement } from "../paths.js";
|
|
2
|
+
import { gateSecrets } from "../secrets-gate.js";
|
|
2
3
|
/** stderr renders color: a color TTY, with Node's `hasColors()` carrying the NO_COLOR/TERM=dumb veto. */
|
|
3
4
|
function stderrHasColors() {
|
|
4
5
|
return process.stderr.isTTY === true && (process.stderr.hasColors?.() ?? false);
|
|
5
6
|
}
|
|
6
|
-
/**
|
|
7
|
-
* The ONE error prefix every error message carries — bold red when stderr renders color, plain
|
|
8
|
-
* otherwise. Errors are the only place the CLI uses color at all.
|
|
9
|
-
*/
|
|
7
|
+
/** The ONE error prefix every error message carries — bold red when stderr renders color, plain otherwise. */
|
|
10
8
|
export function errorPrefix(colors = stderrHasColors()) {
|
|
11
9
|
return colors ? "\x1b[1;31mError:\x1b[0m" : "Error:";
|
|
12
10
|
}
|
|
13
11
|
/**
|
|
14
|
-
* User-fixable startup problems (missing model / bad config / broken definition) are thrown as plain
|
|
15
|
-
*
|
|
16
|
-
* Shared by the kernel and the command modules; exit 1 (runtime failure).
|
|
12
|
+
* User-fixable startup problems (missing model / bad config / broken definition) are thrown as plain `Error` — print
|
|
13
|
+
* just the message. Anything else (a TypeError, a non-Error throw) is a bug: keep the stack.
|
|
17
14
|
*/
|
|
18
15
|
export function failStartup(error) {
|
|
19
16
|
if (error instanceof Error && error.constructor === Error)
|
|
@@ -23,20 +20,21 @@ export function failStartup(error) {
|
|
|
23
20
|
process.exit(1);
|
|
24
21
|
}
|
|
25
22
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* exists, so it cannot ride the `.catch(failStartup)` every async startup chain carries — and its
|
|
32
|
-
* refusals ("not a fastagent agent", plus the two dead ends with their own exits) are user-fixable,
|
|
33
|
-
* which means a one-line `Error:` and exit 1, never a stack.
|
|
34
|
-
*
|
|
35
|
-
* Not every command calls it — and the exceptions are the useful part of this note. `init` CREATES the
|
|
36
|
-
* agent (it must run where there is none). `models` is directory-independent. `login` needs one only for
|
|
37
|
-
* the project-level credential and falls back to the global one, and `attach --url/--token` reads
|
|
38
|
-
* nothing local. Everything else needs an agent, so it comes through here.
|
|
23
|
+
* {@link gateSecrets} at the process boundary, for a command that runs ONE owner's code (`fastagent
|
|
24
|
+
* tool`, `fastagent routine run`). The gate throws SYNCHRONOUSLY, so there is no promise to hang the usual
|
|
25
|
+
* `.catch(failStartup)` on, and a raw throw reaches `cli.ts`'s top-level await as a Node stack that
|
|
26
|
+
* buries the one line naming the file. The catch translates that expected failure into the CLI's
|
|
27
|
+
* single-line refusal and exits 1; nothing is recovered.
|
|
39
28
|
*/
|
|
29
|
+
export function gateSecretsOrExit(input) {
|
|
30
|
+
try {
|
|
31
|
+
gateSecrets(input);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
failStartup(error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** THE placement entry point for commands: resolve `dir`, or exit 1 with the one-line refusal. */
|
|
40
38
|
export function placementOrExit(dir) {
|
|
41
39
|
try {
|
|
42
40
|
return resolvePlacement(dir);
|
|
@@ -46,9 +44,8 @@ export function placementOrExit(dir) {
|
|
|
46
44
|
}
|
|
47
45
|
}
|
|
48
46
|
/**
|
|
49
|
-
* A usage error the parser could not catch (a bad value shape, an invalid flag/argument combination
|
|
50
|
-
*
|
|
51
|
-
* Exit codes follow responsibility, not the layer that happens to discover the problem.
|
|
47
|
+
* A usage error the parser could not catch (a bad value shape, an invalid flag/argument combination discovered in a
|
|
48
|
+
* command body): print the message and exit 2.
|
|
52
49
|
*/
|
|
53
50
|
export function failUsage(message) {
|
|
54
51
|
console.error(`${errorPrefix()} ${message}`);
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Render an Agent event stream to two sinks plus an exit code — the `fastagent invoke` contract, a
|
|
3
|
-
* PURE function (IO injected) so it is unit-testable: text deltas → `out`; tool start + an ERRORED
|
|
4
|
-
* tool_ended → `err`; `failed` → `err` + a non-zero exit code (the CI-gating guarantee).
|
|
5
|
-
*
|
|
6
|
-
* An errored tool inside an otherwise-completed turn still surfaces (the diagnostic the operator
|
|
7
|
-
* needs); tool_ended carries no name, so it is remembered from the matching tool_started.
|
|
8
|
-
*/
|
|
1
|
+
/** Render an Agent event stream to two sinks plus an exit code. */
|
|
9
2
|
import type { AgentEvent } from "../agent.ts";
|
|
10
3
|
export declare function runInvokeStream(events: AsyncIterable<AgentEvent>, out: (text: string) => void, err: (line: string) => void): Promise<number>;
|
package/dist/cli/kernel.d.ts
CHANGED
|
@@ -1,16 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI kernel — commands as data. A {@link CommandSpec} carries everything the CLI surface needs
|
|
3
|
-
* (summary, args/flags, examples, narrative notes, a lazy `run`), and {@link buildProgram} renders
|
|
4
|
-
* the set through commander. Commander is called ONLY from this module; the notation specs are
|
|
5
|
-
* written in — docopt-style argument brackets (`<required>`/`[optional]`), the flag DSL
|
|
6
|
-
* (`--auth-path <file>`, `--no-x` negation), and the derived option keys ({@link optionKey}) — is a
|
|
7
|
-
* contract this module owns and validates at build time. Replacing the parser means re-implementing
|
|
8
|
-
* that notation here (one module), not editing the specs.
|
|
9
|
-
*
|
|
10
|
-
* Follows clig.dev: per-command help in four spellings (`-h`/`--help`/`help <cmd>`/bare-with-missing-args),
|
|
11
|
-
* examples in help, "did you mean" suggestions (never auto-run), and one exit-code policy — 0 success,
|
|
12
|
-
* 1 runtime failure (owned by the command bodies), 2 usage error (anything the parser itself rejects).
|
|
13
|
-
*/
|
|
1
|
+
/** CLI kernel — commands as data. */
|
|
14
2
|
import { Command } from "commander";
|
|
15
3
|
/** One positional argument, in commander syntax: `<name>` required, `[dir]` optional. */
|
|
16
4
|
interface ArgSpec {
|
|
@@ -20,12 +8,10 @@ interface ArgSpec {
|
|
|
20
8
|
/** Closed value set — the parser rejects anything else as a usage error (exit 2). */
|
|
21
9
|
choices?: string[];
|
|
22
10
|
}
|
|
23
|
-
/** One flag, in the flag DSL: `--json`, or `--
|
|
11
|
+
/** One flag, in the flag DSL: `--json`, or `--bind <addr>` for a value-taking flag. */
|
|
24
12
|
export interface FlagSpec {
|
|
25
13
|
flags: string;
|
|
26
14
|
description: string;
|
|
27
|
-
/** Mutually exclusive with these {@link optionKey} values — validated at build time. */
|
|
28
|
-
conflicts?: string[];
|
|
29
15
|
}
|
|
30
16
|
interface ExampleSpec {
|
|
31
17
|
cmd: string;
|
|
@@ -46,13 +32,11 @@ export interface CommandSpec {
|
|
|
46
32
|
/** A group command (e.g. `schedule`) declares subcommands instead of `run`. */
|
|
47
33
|
subcommands?: CommandSpec[];
|
|
48
34
|
/**
|
|
49
|
-
* The implementation: positional args in declaration order (an optional arg without a default is
|
|
50
|
-
*
|
|
51
|
-
* for the modules that command uses. Runtime failures exit 1 from inside (fail visibly).
|
|
35
|
+
* The implementation: positional args in declaration order (an optional arg without a default is `undefined`), then
|
|
36
|
+
* the parsed flags.
|
|
52
37
|
*/
|
|
53
38
|
run?: (args: (string | undefined)[], flags: Record<string, unknown>) => Promise<void> | void;
|
|
54
39
|
}
|
|
55
|
-
/** Program-level configuration. Output/exit/width seams let tests drive the program in-process. */
|
|
56
40
|
export interface ProgramOptions {
|
|
57
41
|
/** Printed by `-v`/`--version`. */
|
|
58
42
|
version?: string;
|
|
@@ -60,29 +44,13 @@ export interface ProgramOptions {
|
|
|
60
44
|
examples?: ExampleSpec[];
|
|
61
45
|
/** Top-level closing prose (the docs link) — reflowed like any notes. */
|
|
62
46
|
notes?: string;
|
|
63
|
-
/**
|
|
64
|
-
* Fixed help width — a TEST seam. Production omits it: commander then adapts to the terminal
|
|
65
|
-
* (and falls back to 80 when piped), the modern behavior. Our verbatim Examples/notes text is
|
|
66
|
-
* hand-wrapped at ≤78 columns so it reads well at any width ≥ 80 (prose caps, like man pages).
|
|
67
|
-
*/
|
|
47
|
+
/** Fixed help width — a TEST seam. */
|
|
68
48
|
helpWidth?: number;
|
|
69
|
-
/**
|
|
70
|
-
* Force help colors on/off — a TEST seam. Production omits it: commander detects per stream
|
|
71
|
-
* (color TTY → on; pipe, NO_COLOR, TERM=dumb → off) and strips every SGR code when off.
|
|
72
|
-
*/
|
|
49
|
+
/** Force help colors on/off — a TEST seam. */
|
|
73
50
|
colors?: boolean;
|
|
74
51
|
out?: (chunk: string) => void;
|
|
75
52
|
err?: (chunk: string) => void;
|
|
76
53
|
exit?: (code: number) => never;
|
|
77
54
|
}
|
|
78
|
-
/**
|
|
79
|
-
* The option key a flag string yields on the parsed-flags record — THE naming rule specs rely on:
|
|
80
|
-
* camelCase of the long name (`--auth-path` → `authPath`); a `--no-x` flag negates and stores under
|
|
81
|
-
* `x` (absent ⇒ `x !== false`). Owned and enforced here so `conflicts` references and run-body reads
|
|
82
|
-
* answer to one authority, not to an implicit parser behavior. Throws on a flag without a long form
|
|
83
|
-
* (clig: every flag has a full-length spelling).
|
|
84
|
-
*/
|
|
85
|
-
export declare function optionKey(flags: string): string;
|
|
86
|
-
/** Build the commander program for `specs`. The CLI entry parses with it; tests inject the IO seams. */
|
|
87
55
|
export declare function buildProgram(specs: readonly CommandSpec[], options?: ProgramOptions): Command;
|
|
88
56
|
export {};
|