@fastagent-sh/fastagent 0.28.0 → 0.30.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 +10 -4
- package/dist/atomic-write.d.ts +4 -5
- package/dist/atomic-write.js +4 -5
- package/dist/authoring.d.ts +32 -15
- package/dist/authoring.js +147 -127
- package/dist/channels/agentcore-protocol.d.ts +8 -3
- package/dist/channels/agentcore-protocol.js +3 -1
- package/dist/channels/agentcore-service.d.ts +1 -0
- package/dist/channels/agentcore-service.js +14 -4
- package/dist/channels/agentcore.d.ts +9 -0
- package/dist/channels/agentcore.js +29 -4
- package/dist/channels/context.d.ts +2 -0
- package/dist/channels/context.js +5 -1
- package/dist/channels/feishu/feishu-api.d.ts +3 -1
- package/dist/channels/feishu/feishu-api.js +4 -0
- package/dist/channels/feishu/feishu.d.ts +0 -3
- package/dist/channels/feishu/feishu.js +10 -10
- package/dist/channels/feishu/register-app.d.ts +2 -0
- package/dist/channels/feishu/register-app.js +4 -6
- package/dist/channels/feishu/scaffold/channel.ts +32 -34
- package/dist/channels/feishu/scaffold/feishu-send.ts +5 -5
- package/dist/channels/feishu/scaffold/feishu-threads.ts +3 -3
- package/dist/channels/feishu/setup-mode.d.ts +2 -12
- package/dist/channels/feishu/setup-mode.js +2 -22
- package/dist/channels/feishu/setup.d.ts +12 -0
- package/dist/channels/feishu/setup.js +197 -0
- package/dist/channels/kit/abortable.d.ts +8 -0
- package/dist/channels/kit/abortable.js +22 -0
- package/dist/channels/lark/lark.d.ts +0 -3
- package/dist/channels/lark/lark.js +0 -5
- package/dist/channels/lark/scaffold/channel.ts +33 -35
- package/dist/channels/lark/scaffold/lark-send.ts +5 -5
- package/dist/channels/lark/scaffold/lark-threads.ts +3 -3
- package/dist/channels/lark/setup.d.ts +9 -0
- package/dist/channels/lark/setup.js +57 -0
- package/dist/channels/setup.d.ts +112 -0
- package/dist/channels/setup.js +31 -0
- package/dist/channels/slack/history.js +1 -1
- package/dist/channels/slack/manifest.d.ts +17 -7
- package/dist/channels/slack/manifest.js +12 -16
- package/dist/channels/slack/scaffold/channel.ts +44 -30
- package/dist/channels/slack/scaffold/slack-send.ts +8 -8
- package/dist/channels/slack/scaffold/slack-threads.ts +4 -4
- package/dist/channels/slack/setup.d.ts +7 -0
- package/dist/channels/slack/setup.js +119 -0
- package/dist/channels/slack/slack-api.d.ts +2 -0
- package/dist/channels/slack/slack-api.js +4 -0
- package/dist/channels/slack/slack.d.ts +21 -2
- package/dist/channels/slack/slack.js +398 -338
- package/dist/channels/slack/socket.d.ts +57 -0
- package/dist/channels/slack/socket.js +305 -0
- package/dist/channels/telegram/polling.d.ts +27 -0
- package/dist/channels/telegram/polling.js +105 -0
- package/dist/channels/telegram/scaffold/channel.ts +52 -32
- package/dist/channels/telegram/scaffold/telegram-send.ts +9 -9
- package/dist/channels/telegram/setup.d.ts +2 -0
- package/dist/channels/telegram/setup.js +42 -0
- package/dist/channels/telegram/telegram-api.d.ts +27 -1
- package/dist/channels/telegram/telegram-api.js +7 -6
- package/dist/channels/telegram/telegram.d.ts +11 -3
- package/dist/channels/telegram/telegram.js +184 -157
- package/dist/channels/wait-health.js +1 -1
- package/dist/channels/webhook-evidence.d.ts +11 -0
- package/dist/channels/webhook-evidence.js +71 -0
- package/dist/channels/webhooks.d.ts +37 -0
- package/dist/channels/webhooks.js +70 -0
- package/dist/child-env.d.ts +16 -0
- package/dist/child-env.js +30 -0
- package/dist/cli/box-login.js +4 -1
- package/dist/cli/channel-app.d.ts +3 -0
- package/dist/cli/channel-app.js +35 -0
- package/dist/cli/channel-setup.d.ts +38 -0
- package/dist/cli/channel-setup.js +195 -0
- package/dist/cli/commands/add.d.ts +6 -14
- package/dist/cli/commands/add.js +45 -310
- package/dist/cli/commands/auth.js +8 -2
- package/dist/cli/commands/build.d.ts +5 -0
- package/dist/cli/commands/build.js +16 -0
- package/dist/cli/commands/channels.d.ts +19 -0
- package/dist/cli/commands/channels.js +230 -0
- package/dist/cli/commands/content.d.ts +7 -3
- package/dist/cli/commands/content.js +16 -10
- package/dist/cli/commands/deploy/agentcore.js +55 -23
- package/dist/cli/commands/deploy/channel-apps.d.ts +17 -0
- package/dist/cli/commands/deploy/channel-apps.js +30 -0
- package/dist/cli/commands/deploy/docker.js +32 -65
- package/dist/cli/commands/deploy/fly.js +28 -12
- package/dist/cli/commands/deploy/railway.js +38 -13
- package/dist/cli/commands/deploy/secrets-step.d.ts +19 -0
- package/dist/cli/commands/deploy/secrets-step.js +66 -0
- package/dist/cli/commands/deploy/shared.d.ts +16 -5
- package/dist/cli/commands/deploy/shared.js +25 -8
- package/dist/cli/commands/deploy.js +53 -67
- package/dist/cli/commands/dev.d.ts +2 -0
- package/dist/cli/commands/dev.js +15 -3
- package/dist/cli/commands/env.js +1 -1
- package/dist/cli/commands/info.d.ts +2 -0
- package/dist/cli/commands/info.js +63 -24
- package/dist/cli/commands/init.js +3 -1
- package/dist/cli/commands/invoke.d.ts +2 -0
- package/dist/cli/commands/invoke.js +20 -7
- package/dist/cli/commands/login.d.ts +0 -7
- package/dist/cli/commands/login.js +22 -10
- package/dist/cli/commands/logout.js +1 -1
- package/dist/cli/commands/mcp.d.ts +12 -0
- package/dist/cli/commands/mcp.js +164 -0
- package/dist/cli/commands/models.js +3 -2
- package/dist/cli/commands/schedules.d.ts +4 -2
- package/dist/cli/commands/schedules.js +14 -10
- package/dist/cli/commands/secrets.d.ts +14 -0
- package/dist/cli/commands/secrets.js +213 -0
- package/dist/cli/commands/start.d.ts +14 -14
- package/dist/cli/commands/start.js +46 -60
- package/dist/cli/content-view.d.ts +4 -6
- package/dist/cli/content-view.js +5 -11
- package/dist/cli/first-run-channels.d.ts +3 -0
- package/dist/cli/first-run-channels.js +63 -0
- package/dist/cli/instance.d.ts +41 -0
- package/dist/cli/instance.js +155 -0
- package/dist/cli/invoke-stream.d.ts +5 -2
- package/dist/cli/invoke-stream.js +7 -2
- package/dist/cli/program.js +339 -108
- package/dist/cli/serve.d.ts +4 -5
- package/dist/cli/serve.js +4 -7
- package/dist/cli/shared.d.ts +11 -2
- package/dist/cli/shared.js +32 -19
- package/dist/cli/ticket.js +50 -6
- package/dist/content/declare.d.ts +31 -37
- package/dist/content/declare.js +59 -60
- package/dist/content/file.d.ts +23 -12
- package/dist/content/file.js +48 -35
- package/dist/content/git.d.ts +0 -10
- package/dist/content/git.js +5 -39
- package/dist/content/resolve.d.ts +18 -22
- package/dist/content/resolve.js +32 -66
- package/dist/content/source.d.ts +7 -8
- package/dist/content/source.js +10 -28
- package/dist/credentials-page.d.ts +26 -0
- package/dist/credentials-page.js +185 -0
- package/dist/declared-secrets.d.ts +10 -3
- package/dist/declared-secrets.js +8 -4
- package/dist/deploy/agentcore/destroy.d.ts +4 -1
- package/dist/deploy/agentcore/destroy.js +26 -2
- package/dist/deploy/agentcore/forwarder.js +1 -1
- package/dist/deploy/agentcore/plan.d.ts +7 -21
- package/dist/deploy/agentcore/plan.js +47 -49
- package/dist/deploy/agentcore/run.d.ts +18 -10
- package/dist/deploy/agentcore/run.js +93 -70
- package/dist/deploy/agentcore/runtime-secrets.d.ts +7 -0
- package/dist/deploy/agentcore/runtime-secrets.js +108 -0
- package/dist/deploy/agentcore/shell.js +12 -19
- package/dist/deploy/agentcore/sigv4.d.ts +7 -0
- package/dist/deploy/agentcore/sigv4.js +15 -0
- package/dist/deploy/agentcore/slr.d.ts +18 -0
- package/dist/deploy/agentcore/slr.js +27 -0
- package/dist/deploy/agentcore/store.d.ts +7 -0
- package/dist/deploy/agentcore/store.js +115 -0
- package/dist/deploy/api.d.ts +14 -14
- package/dist/deploy/api.js +26 -24
- package/dist/deploy/box-shell.d.ts +3 -1
- package/dist/deploy/build-context.d.ts +4 -4
- package/dist/deploy/build-context.js +11 -11
- package/dist/deploy/channel-ingress.d.ts +35 -9
- package/dist/deploy/channel-ingress.js +119 -22
- package/dist/deploy/container.d.ts +35 -10
- package/dist/deploy/container.js +80 -39
- package/dist/deploy/delivered-text.d.ts +13 -0
- package/dist/deploy/delivered-text.js +86 -0
- package/dist/deploy/docker/plan.d.ts +7 -8
- package/dist/deploy/docker/plan.js +31 -52
- package/dist/deploy/docker/run.d.ts +18 -43
- package/dist/deploy/docker/run.js +57 -79
- package/dist/deploy/file-store.d.ts +2 -0
- package/dist/deploy/file-store.js +17 -0
- package/dist/deploy/fly/plan.d.ts +3 -2
- package/dist/deploy/fly/plan.js +20 -9
- package/dist/deploy/fly/run.d.ts +18 -22
- package/dist/deploy/fly/run.js +25 -44
- package/dist/deploy/fly/store.d.ts +12 -0
- package/dist/deploy/fly/store.js +83 -0
- package/dist/deploy/hosts.d.ts +1 -2
- package/dist/deploy/hosts.js +1 -2
- package/dist/deploy/preflight.d.ts +18 -5
- package/dist/deploy/preflight.js +135 -63
- package/dist/deploy/railway/ignore.d.ts +8 -0
- package/dist/deploy/railway/ignore.js +57 -0
- package/dist/deploy/railway/plan.d.ts +1 -2
- package/dist/deploy/railway/plan.js +8 -6
- package/dist/deploy/railway/run.d.ts +21 -15
- package/dist/deploy/railway/run.js +32 -78
- package/dist/deploy/railway/store.d.ts +29 -0
- package/dist/deploy/railway/store.js +143 -0
- package/dist/deploy/runner.d.ts +5 -2
- package/dist/deploy/runner.js +4 -3
- package/dist/deploy/secret-store.d.ts +63 -0
- package/dist/deploy/secret-store.js +98 -0
- package/dist/deploy/secrets.d.ts +29 -46
- package/dist/deploy/secrets.js +49 -122
- package/dist/deploy/workspace.d.ts +6 -12
- package/dist/deploy/workspace.js +18 -94
- package/dist/dev-supervisor.js +6 -7
- package/dist/environment/declare.js +3 -2
- package/dist/environment/mise.d.ts +3 -1
- package/dist/environment/mise.js +4 -2
- package/dist/feishu.d.ts +1 -1
- package/dist/feishu.js +1 -1
- package/dist/harnesses/models/catalog.d.ts +1 -0
- package/dist/harnesses/models/catalog.js +1 -2
- package/dist/harnesses/models/environment.d.ts +7 -2
- package/dist/harnesses/models/environment.js +9 -5
- package/dist/harnesses/models/host.d.ts +0 -7
- package/dist/harnesses/models/host.js +10 -1
- package/dist/harnesses/models/login.d.ts +0 -8
- package/dist/harnesses/models/login.js +5 -4
- package/dist/harnesses/models/models.d.ts +7 -2
- package/dist/harnesses/models/models.js +28 -4
- package/dist/harnesses/pi-durable/agent.js +59 -38
- package/dist/harnesses/pi-durable/build.d.ts +12 -0
- package/dist/harnesses/pi-durable/build.js +270 -0
- package/dist/harnesses/pi-durable/built.d.ts +24 -0
- package/dist/harnesses/pi-durable/built.js +136 -0
- package/dist/harnesses/pi-durable/config.d.ts +81 -0
- package/dist/harnesses/pi-durable/config.js +266 -0
- package/dist/harnesses/pi-durable/define.d.ts +63 -13
- package/dist/harnesses/pi-durable/define.js +23 -2
- package/dist/harnesses/pi-durable/definition.d.ts +72 -0
- package/dist/harnesses/pi-durable/definition.js +143 -0
- package/dist/harnesses/pi-durable/events.d.ts +4 -3
- package/dist/harnesses/pi-durable/events.js +179 -136
- package/dist/harnesses/pi-durable/execution-env.d.ts +17 -0
- package/dist/harnesses/pi-durable/execution-env.js +11 -0
- package/dist/harnesses/pi-durable/mcp.d.ts +3 -0
- package/dist/harnesses/pi-durable/mcp.js +32 -0
- package/dist/harnesses/pi-durable/open.d.ts +36 -38
- package/dist/harnesses/pi-durable/open.js +97 -150
- package/dist/harnesses/pi-durable/reads.d.ts +0 -1
- package/dist/harnesses/pi-durable/reads.js +1 -3
- package/dist/harnesses/pi-durable/registry.d.ts +4 -6
- package/dist/harnesses/pi-durable/registry.js +29 -26
- package/dist/harnesses/pi-durable/release.d.ts +2 -2
- package/dist/harnesses/pi-durable/release.js +10 -7
- package/dist/harnesses/pi-durable/serve.d.ts +95 -15
- package/dist/harnesses/pi-durable/serve.js +151 -59
- package/dist/harnesses/pi-durable/sessions.js +15 -12
- package/dist/harnesses/pi-durable/text-sources.d.ts +30 -0
- package/dist/harnesses/pi-durable/text-sources.js +55 -0
- package/dist/harnesses/pi-durable/text.d.ts +16 -4
- package/dist/harnesses/pi-durable/text.js +115 -59
- package/dist/harnesses/pi-durable/wake.js +8 -8
- package/dist/http/client.js +9 -3
- package/dist/http/server.d.ts +1 -1
- package/dist/http/server.js +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.js +8 -1
- package/dist/instance-name.d.ts +7 -0
- package/dist/instance-name.js +26 -0
- package/dist/lark.d.ts +1 -1
- package/dist/lark.js +1 -1
- package/dist/locked-file.d.ts +2 -2
- package/dist/locked-file.js +8 -3
- package/dist/mcp/auth.d.ts +22 -0
- package/dist/mcp/auth.js +180 -0
- package/dist/mcp/client.d.ts +15 -0
- package/dist/mcp/client.js +179 -0
- package/dist/mcp/config.d.ts +86 -0
- package/dist/mcp/config.js +225 -0
- package/dist/mcp/grants.d.ts +4 -0
- package/dist/mcp/grants.js +132 -0
- package/dist/mcp/host.d.ts +19 -0
- package/dist/mcp/host.js +128 -0
- package/dist/mcp/network.d.ts +12 -0
- package/dist/mcp/network.js +150 -0
- package/dist/mcp/sign-in.d.ts +2 -0
- package/dist/mcp/sign-in.js +204 -0
- package/dist/mcp-api.d.ts +107 -0
- package/dist/mcp-api.js +10 -0
- package/dist/paths.d.ts +22 -8
- package/dist/paths.js +44 -11
- package/dist/runtime-websocket.d.ts +14 -0
- package/dist/runtime-websocket.js +39 -0
- package/dist/scaffold/add-channel.d.ts +9 -16
- package/dist/scaffold/add-channel.js +13 -83
- package/dist/scaffold/templates/env.example +4 -5
- package/dist/scaffold/templates/fastagent.config.ts +20 -14
- package/dist/scaffold/templates/gitignore +9 -6
- package/dist/scaffold/templates.d.ts +6 -2
- package/dist/scaffold/templates.js +7 -2
- package/dist/scaffold/vendor-skill.js +4 -2
- package/dist/service.d.ts +44 -6
- package/dist/service.js +110 -10
- package/dist/serving-command.d.ts +10 -0
- package/dist/serving-command.js +1 -0
- package/dist/setup-page.d.ts +51 -0
- package/dist/setup-page.js +149 -0
- package/dist/slack.d.ts +1 -1
- package/dist/slack.js +1 -1
- package/dist/strip-edges.d.ts +10 -0
- package/dist/strip-edges.js +22 -0
- package/dist/telegram.d.ts +1 -1
- package/dist/telegram.js +1 -1
- package/dist/tunnel.d.ts +0 -1
- package/dist/tunnel.js +2 -8
- package/dist/value-file.d.ts +12 -6
- package/dist/value-file.js +36 -25
- package/dist/version.d.ts +7 -1
- package/dist/version.js +9 -3
- package/package.json +8 -6
- package/dist/channels/lark/onboard.d.ts +0 -36
- package/dist/channels/lark/onboard.js +0 -56
- package/dist/channels/slack/config-api.d.ts +0 -69
- package/dist/channels/slack/config-api.js +0 -162
- package/dist/channels/slack/onboard.d.ts +0 -40
- package/dist/channels/slack/onboard.js +0 -136
- package/dist/channels/slack/onboarding-state.d.ts +0 -31
- package/dist/channels/slack/onboarding-state.js +0 -64
- package/dist/channels/slack/register-webhook.d.ts +0 -12
- package/dist/channels/slack/register-webhook.js +0 -67
- package/dist/channels/slack/setup-server.d.ts +0 -32
- package/dist/channels/slack/setup-server.js +0 -201
- package/dist/cli/add-feishu.d.ts +0 -50
- package/dist/cli/add-feishu.js +0 -367
- package/dist/cli/add-slack.d.ts +0 -18
- package/dist/cli/add-slack.js +0 -216
- package/dist/harnesses/pi-durable/parked.d.ts +0 -18
- package/dist/harnesses/pi-durable/parked.js +0 -27
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Agent } from "../../agent-api.ts";
|
|
2
|
-
import type {
|
|
2
|
+
import type { EffectiveConfig } from "../../harnesses/pi-durable/config.ts";
|
|
3
|
+
import { type InstanceFlags } from "../instance.ts";
|
|
3
4
|
import { type ServedAgent } from "../../service.ts";
|
|
4
5
|
export interface StartOptions {
|
|
5
6
|
port?: string;
|
|
@@ -7,29 +8,28 @@ export interface StartOptions {
|
|
|
7
8
|
model?: string;
|
|
8
9
|
tunnel?: boolean;
|
|
9
10
|
input?: boolean;
|
|
11
|
+
instance?: InstanceFlags;
|
|
10
12
|
}
|
|
11
13
|
/** What `start` opened and serves: the agent too, for a deployment's own check of what it runs. */
|
|
12
14
|
type StartedService = ServedAgent & {
|
|
13
15
|
agent: Agent;
|
|
14
16
|
stateRoot: string;
|
|
15
17
|
port: number;
|
|
16
|
-
config:
|
|
18
|
+
config: EffectiveConfig;
|
|
17
19
|
};
|
|
18
20
|
export declare function runStart(dirArg: string, opts: StartOptions): Promise<void>;
|
|
19
|
-
/** What the storage stage hands the opening stage. */
|
|
20
|
-
export interface PreparedWorkspace {
|
|
21
|
-
/** The agent directory to open — the storage's deployed definition when a release manifest selected one. */
|
|
22
|
-
dir: string;
|
|
23
|
-
/** The storage root, set when this process took a deployment's storage. */
|
|
24
|
-
deployed?: {
|
|
25
|
-
root: string;
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
21
|
/**
|
|
29
|
-
* Stage one — TAKE the storage
|
|
22
|
+
* Stage one — TAKE the storage, on a deployed box (a release manifest names it): it is mounted, held by this process,
|
|
23
|
+
* and this agent's; it becomes the instance's root, and the machinery points at it. The program stays where the image
|
|
24
|
+
* built it, `dirArg`. Returns that directory. Elsewhere, nothing is taken.
|
|
25
|
+
*/
|
|
26
|
+
export declare function prepareStartWorkspace(dirArg: string): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* AgentCore's stage one: the deployment's values first, on the first invocation, so a failed read is that invocation's
|
|
29
|
+
* failure and the next asks again; then the storage.
|
|
30
30
|
*/
|
|
31
|
-
export declare function
|
|
31
|
+
export declare function prepareAgentcoreWorkspace(dirArg: string): Promise<string>;
|
|
32
32
|
export declare function openStartService(dirArg: string, opts: StartOptions): Promise<StartedService>;
|
|
33
|
-
/**
|
|
33
|
+
/** Stage two: open the built definition in `dirArg` and serve it. */
|
|
34
34
|
export declare function openPreparedStartService(dirArg: string, opts: StartOptions): Promise<StartedService>;
|
|
35
35
|
export {};
|
|
@@ -1,21 +1,14 @@
|
|
|
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
1
|
/** Production serving. */
|
|
10
2
|
import { join, resolve } from "node:path";
|
|
11
|
-
import { pathToFileURL } from "node:url";
|
|
12
|
-
import { createRequire } from "node:module";
|
|
13
3
|
import { readFile } from "node:fs/promises";
|
|
14
|
-
import {
|
|
15
|
-
import { applyReleaseEnv,
|
|
16
|
-
import { selectAgentEnvironment, resolveSecretsDir, isAgentcoreRuntime, isUnderDir,
|
|
4
|
+
import { applyRuntimeSecrets } from "../../deploy/agentcore/runtime-secrets.js";
|
|
5
|
+
import { applyReleaseEnv, parseDeploymentRelease, prepareDeployment } from "../../deploy/workspace.js";
|
|
6
|
+
import { selectAgentEnvironment, resolveSecretsDir, isAgentcoreRuntime, isDeployedWorkspace, isUnderDir, INSTANCE_ROOT_ENV, } from "../../paths.js";
|
|
17
7
|
import { log, setLogLevel } from "../../log.js";
|
|
8
|
+
import { loadProjectBuild } from "../../harnesses/pi-durable/built.js";
|
|
9
|
+
import { namedInstanceConfig } from "../../harnesses/pi-durable/config.js";
|
|
18
10
|
import { openServing } from "../../harnesses/pi-durable/serve.js";
|
|
11
|
+
import { instanceInputs } from "../instance.js";
|
|
19
12
|
import { DEFAULT_HTTP_PORT, serveAgent } from "../../service.js";
|
|
20
13
|
import { mountAgentcoreService, deferAgentcoreService } from "../../channels/agentcore-service.js";
|
|
21
14
|
import { failStartup } from "../fail.js";
|
|
@@ -25,13 +18,6 @@ import { enterAgentCommand, parseBind, parsePort, reportAssembly } from "../shar
|
|
|
25
18
|
export async function runStart(dirArg, opts) {
|
|
26
19
|
const portFlag = parsePort(opts.port, "--port", "flag");
|
|
27
20
|
const bindFlag = parseBind(opts.bind);
|
|
28
|
-
// A host that carries the value file as ONE encoded variable (AgentCore): expanded before anything reads the env.
|
|
29
|
-
try {
|
|
30
|
-
applyCarriedEnv();
|
|
31
|
-
}
|
|
32
|
-
catch (error) {
|
|
33
|
-
failStartup(error);
|
|
34
|
-
}
|
|
35
21
|
setLogLevel("info");
|
|
36
22
|
selectAgentEnvironment("production");
|
|
37
23
|
unmarkDevServe();
|
|
@@ -39,9 +25,9 @@ export async function runStart(dirArg, opts) {
|
|
|
39
25
|
// The generated Runtime resource sets PORT; 8080 is the platform's contract when nothing does.
|
|
40
26
|
const port = portFlag ?? parsePort(process.env.PORT, "PORT env", "env") ?? 8080;
|
|
41
27
|
const deferred = deferAgentcoreService({
|
|
42
|
-
prepare: () =>
|
|
43
|
-
assemble: async (
|
|
44
|
-
const service = await
|
|
28
|
+
prepare: () => prepareAgentcoreWorkspace(dirArg),
|
|
29
|
+
assemble: async (dir) => {
|
|
30
|
+
const service = await openPreparedStartService(dir, opts);
|
|
45
31
|
await service.ready;
|
|
46
32
|
return service;
|
|
47
33
|
},
|
|
@@ -53,28 +39,31 @@ export async function runStart(dirArg, opts) {
|
|
|
53
39
|
});
|
|
54
40
|
return;
|
|
55
41
|
}
|
|
56
|
-
// Deployed storage refusals (no mount, a held lease, a missing `flock`,
|
|
42
|
+
// Deployed storage refusals (no mount, a held lease, a missing `flock`, another agent's storage) are the operator's only
|
|
57
43
|
// clue in a crash-looping container.
|
|
58
44
|
const service = await openStartService(dirArg, opts).catch(failStartup);
|
|
59
45
|
const tunnel = opts.tunnel ?? false;
|
|
60
46
|
// An unset bind stays the wildcard: this is the container posture, and a published port needs it.
|
|
61
47
|
assertTunnelBindable(bindFlag, tunnel);
|
|
62
|
-
serveService(service, { port: portFlag ?? parsePort(process.env.PORT, "PORT env", "env") ?? service.port, host: bindFlag }, { tunnel, agentDir: service.agentDir,
|
|
48
|
+
serveService(service, { port: portFlag ?? parsePort(process.env.PORT, "PORT env", "env") ?? service.port, host: bindFlag }, { tunnel, agentDir: service.agentDir, config: service.config });
|
|
63
49
|
}
|
|
64
50
|
/**
|
|
65
|
-
* Stage one — TAKE the storage
|
|
51
|
+
* Stage one — TAKE the storage, on a deployed box (a release manifest names it): it is mounted, held by this process,
|
|
52
|
+
* and this agent's; it becomes the instance's root, and the machinery points at it. The program stays where the image
|
|
53
|
+
* built it, `dirArg`. Returns that directory. Elsewhere, nothing is taken.
|
|
66
54
|
*/
|
|
67
55
|
export async function prepareStartWorkspace(dirArg) {
|
|
68
56
|
const manifestPath = process.env.FASTAGENT_RELEASE_FILE;
|
|
69
57
|
if (!manifestPath)
|
|
70
|
-
return
|
|
71
|
-
const storage = process.env
|
|
58
|
+
return dirArg;
|
|
59
|
+
const storage = process.env[INSTANCE_ROOT_ENV];
|
|
72
60
|
if (!storage)
|
|
73
|
-
throw new Error(
|
|
61
|
+
throw new Error(`${INSTANCE_ROOT_ENV} is required for a deployment`);
|
|
74
62
|
const root = resolve(storage);
|
|
75
63
|
const manifest = parseDeploymentRelease(await readFile(manifestPath, "utf8"));
|
|
76
|
-
|
|
77
|
-
|
|
64
|
+
await prepareDeployment(root, manifest);
|
|
65
|
+
process.env[INSTANCE_ROOT_ENV] = root;
|
|
66
|
+
// Defaults, not overrides: an operator who pointed a directory somewhere else meant it, and silently relocating
|
|
78
67
|
// their state is the one failure they could not diagnose from the logs.
|
|
79
68
|
process.env.FASTAGENT_STATE_DIR ||= join(root, ".state");
|
|
80
69
|
process.env.FASTAGENT_SECRETS_DIR ||= join(root, ".secrets");
|
|
@@ -85,40 +74,31 @@ export async function prepareStartWorkspace(dirArg) {
|
|
|
85
74
|
// `enterAgentEnv` reads the agent's `.env`, which is what makes either source outrank a value edited on the
|
|
86
75
|
// box (applyReleaseEnv's own tests pin the precedence).
|
|
87
76
|
applyReleaseEnv(manifest);
|
|
88
|
-
|
|
89
|
-
return { dir, deployed: { root } };
|
|
77
|
+
return dirArg;
|
|
90
78
|
}
|
|
91
79
|
/**
|
|
92
|
-
*
|
|
80
|
+
* AgentCore's stage one: the deployment's values first, on the first invocation, so a failed read is that invocation's
|
|
81
|
+
* failure and the next asks again; then the storage.
|
|
93
82
|
*/
|
|
94
|
-
async function
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const { root } = prepared.deployed;
|
|
98
|
-
const agentDir = prepared.dir;
|
|
99
|
-
if (await exists(join(agentDir, "package.json"))) {
|
|
100
|
-
await installAgentDependencies(root, agentDir);
|
|
101
|
-
// Tools and their session context must share the agent's runtime module instance.
|
|
102
|
-
const entry = createRequire(join(agentDir, "package.json")).resolve("@fastagent-sh/fastagent");
|
|
103
|
-
const local = (await import(__rewriteRelativeImportExtension(new URL("./cli/commands/start.js", pathToFileURL(entry)).href)));
|
|
104
|
-
// A version-skewed dependency resolves and imports fine, then fails as "open is not a function" with nothing
|
|
105
|
-
// naming the two versions.
|
|
106
|
-
if (typeof local.openPreparedStartService !== "function") {
|
|
107
|
-
throw new Error(`${entry} does not export openPreparedStartService — align the agent's @fastagent-sh/fastagent version with the deploy CLI`);
|
|
108
|
-
}
|
|
109
|
-
open = local.openPreparedStartService;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return open(prepared.dir, opts);
|
|
83
|
+
export async function prepareAgentcoreWorkspace(dirArg) {
|
|
84
|
+
await applyRuntimeSecrets();
|
|
85
|
+
return prepareStartWorkspace(dirArg);
|
|
113
86
|
}
|
|
114
87
|
export async function openStartService(dirArg, opts) {
|
|
115
|
-
return
|
|
88
|
+
return openPreparedStartService(await prepareStartWorkspace(dirArg), opts);
|
|
116
89
|
}
|
|
117
|
-
/**
|
|
90
|
+
/** Stage two: open the built definition in `dirArg` and serve it. */
|
|
118
91
|
export async function openPreparedStartService(dirArg, opts) {
|
|
119
|
-
|
|
120
|
-
|
|
92
|
+
// The build, never the source (agent-artifact.md §8): refused when there is none or the project has moved on.
|
|
93
|
+
let built;
|
|
94
|
+
// A start never reads the development `fastagent.json`: its instance configuration is the one `--config` names.
|
|
95
|
+
const loadBuilt = (dir) => (built ??= loadProjectBuild(dir, { checkSources: !isDeployedWorkspace() }).then((definition) => ({ definition })));
|
|
96
|
+
const { agentDir, modelSpec } = await enterAgentCommand(dirArg, opts, undefined, loadBuilt);
|
|
97
|
+
const config = await namedInstanceConfig();
|
|
98
|
+
const opened = await openServing((await loadBuilt(agentDir)).definition, {
|
|
121
99
|
model: modelSpec,
|
|
100
|
+
...instanceInputs(agentDir),
|
|
101
|
+
...(config === undefined ? {} : { config }),
|
|
122
102
|
// AgentCore's session storage refuses SQLite's own locks; the deployment's lease makes the dotfile lock safe.
|
|
123
103
|
storage: { instance: isAgentcoreRuntime() ? "leased-dotfile" : "posix" },
|
|
124
104
|
});
|
|
@@ -130,9 +110,15 @@ export async function openPreparedStartService(dirArg, opts) {
|
|
|
130
110
|
if (isUnderDir(resolveSecretsDir(agentDir), agentDir)) {
|
|
131
111
|
log.info("[fastagent] note: credentials live under the definition; use FASTAGENT_SECRETS_DIR on persistent storage for deployment.");
|
|
132
112
|
}
|
|
133
|
-
const { config } = opened
|
|
113
|
+
const { config: effective } = opened;
|
|
134
114
|
const service = await (isAgentcoreRuntime()
|
|
135
115
|
? mountAgentcoreService(opened)
|
|
136
|
-
: serveAgent(opened, cliMountOptions(
|
|
137
|
-
return {
|
|
116
|
+
: serveAgent(opened, cliMountOptions(effective)));
|
|
117
|
+
return {
|
|
118
|
+
...service,
|
|
119
|
+
agent: opened.agent,
|
|
120
|
+
stateRoot,
|
|
121
|
+
port: effective.http?.port ?? DEFAULT_HTTP_PORT,
|
|
122
|
+
config: effective,
|
|
123
|
+
};
|
|
138
124
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/** How the CLI writes an agent's content. */
|
|
2
|
-
import type {
|
|
3
|
-
import { type ResolvedContent } from "../content/resolve.ts";
|
|
2
|
+
import type { ResolvedContent } from "../content/resolve.ts";
|
|
4
3
|
/**
|
|
5
|
-
* The report lines for an agent's content — `works on`, one per entry, then a `notice` line for each
|
|
6
|
-
*
|
|
7
|
-
* startup report, `info` and `content list`, so the three say the same thing.
|
|
4
|
+
* The report lines for an agent's content — `works on`, one per entry, then a `notice` line for each thing its
|
|
5
|
+
* resolution has to say — shared by the startup report, `info` and `content list`, so the three say the same thing.
|
|
8
6
|
*/
|
|
9
|
-
export declare function contentLines(content: readonly ResolvedContent[]
|
|
7
|
+
export declare function contentLines(content: readonly ResolvedContent[]): [label: string, value: string][];
|
package/dist/cli/content-view.js
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
1
|
-
import { LOCAL_CONTEXT_FILE } from "../paths.js";
|
|
2
|
-
import { absentNotice } from "../content/resolve.js";
|
|
3
1
|
/** What a content entry is, in the words the reports use. */
|
|
4
2
|
function contentKind(c) {
|
|
5
3
|
if (c.kind !== "github")
|
|
6
|
-
return
|
|
7
|
-
|
|
8
|
-
return c.clone ? `${github}, a clone brought up to date at each start` : `${github}, your checkout bound here`;
|
|
4
|
+
return "a directory of this machine";
|
|
5
|
+
return `github ${c.repo}${c.ref ? `@${c.ref}` : ""}, a clone brought up to date at each start`;
|
|
9
6
|
}
|
|
10
7
|
/**
|
|
11
|
-
* The report lines for an agent's content — `works on`, one per entry, then a `notice` line for each
|
|
12
|
-
*
|
|
13
|
-
* startup report, `info` and `content list`, so the three say the same thing.
|
|
8
|
+
* The report lines for an agent's content — `works on`, one per entry, then a `notice` line for each thing its
|
|
9
|
+
* resolution has to say — shared by the startup report, `info` and `content list`, so the three say the same thing.
|
|
14
10
|
*/
|
|
15
|
-
export function contentLines(content
|
|
11
|
+
export function contentLines(content) {
|
|
16
12
|
const lines = content.flatMap((c) => [
|
|
17
13
|
["works on", `${c.name.padEnd(width(content))} ${c.location} (${contentKind(c)})`],
|
|
18
14
|
...c.notices.map((notice) => ["notice", `${c.name}: ${notice}`]),
|
|
19
15
|
]);
|
|
20
|
-
for (const binding of absent)
|
|
21
|
-
lines.push(["notice", absentNotice(binding)]);
|
|
22
16
|
return lines.length === 0 ? [["content", "(none)"]] : lines;
|
|
23
17
|
}
|
|
24
18
|
function width(content) {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A channel the development instance has no credentials for yet is set up the first time `dev` runs (channel-setup.md
|
|
3
|
+
* §2), the way the first run picks a model: in the parent process, at a terminal, once per project. Without a terminal
|
|
4
|
+
* nothing is asked and nothing waits: the command that does it for a coding agent is named.
|
|
5
|
+
*/
|
|
6
|
+
import { resolveConfig } from "../harnesses/pi-durable/config.js";
|
|
7
|
+
import { codeSecrets } from "../harnesses/pi-durable/definition.js";
|
|
8
|
+
import { chosenIngress } from "../harnesses/pi-durable/definition.js";
|
|
9
|
+
import { loadDevProject } from "../harnesses/pi-durable/open.js";
|
|
10
|
+
import { missingSecrets } from "../declared-secrets.js";
|
|
11
|
+
import { dotEnvPath, loadEnvValues } from "../value-file.js";
|
|
12
|
+
import { isSetupKind, setUpChannel, setupNames } from "./channel-setup.js";
|
|
13
|
+
import { failStartup, failUsage } from "./fail.js";
|
|
14
|
+
import { isInteractive } from "./shared.js";
|
|
15
|
+
/** The first-party channels the agent mounts whose credentials this process's environment lacks, and the configuration. */
|
|
16
|
+
async function lackingChannels(agentDir) {
|
|
17
|
+
const project = await loadDevProject(agentDir).catch(failStartup);
|
|
18
|
+
const config = resolveConfig(project.definition, project.instance);
|
|
19
|
+
const missing = missingSecrets(codeSecrets(project.definition, config), process.env);
|
|
20
|
+
const kinds = project.definition.registry.channels.flatMap(({ file, name }) => {
|
|
21
|
+
if (!isSetupKind(name))
|
|
22
|
+
return [];
|
|
23
|
+
// Only what the channel's own setup supplies: a channel file of the same name that reads other variables is its
|
|
24
|
+
// author's to fill.
|
|
25
|
+
const supplied = setupNames(name, chosenIngress(config, name, true));
|
|
26
|
+
return missing.some((secret) => secret.declaredIn === file && supplied.includes(secret.name)) ? [name] : [];
|
|
27
|
+
});
|
|
28
|
+
return { kinds, config };
|
|
29
|
+
}
|
|
30
|
+
export async function setUpMissingChannels(agentDir, opts = {}) {
|
|
31
|
+
const { kinds, config } = await lackingChannels(agentDir);
|
|
32
|
+
if (kinds.length === 0)
|
|
33
|
+
return;
|
|
34
|
+
if (opts.input === false || !isInteractive()) {
|
|
35
|
+
const lacking = kinds
|
|
36
|
+
.map((kind) => `${kind} has no credentials in ${dotEnvPath(agentDir)}: run \`fastagent channels setup ${kind} --json\``)
|
|
37
|
+
.join("; ");
|
|
38
|
+
failUsage(`${lacking} (it hands the person's part to its user), or run \`fastagent dev\` in a terminal, which asks`);
|
|
39
|
+
}
|
|
40
|
+
const file = dotEnvPath(agentDir);
|
|
41
|
+
for (const kind of kinds) {
|
|
42
|
+
console.error(`[fastagent] ${kind} has no credentials in ${file} yet: setting it up (\`fastagent channels setup ${kind}\`)`);
|
|
43
|
+
const outcome = await setUpChannel({
|
|
44
|
+
kind,
|
|
45
|
+
agentDir,
|
|
46
|
+
file,
|
|
47
|
+
way: chosenIngress(config, kind, true),
|
|
48
|
+
dev: true,
|
|
49
|
+
rerun: `fastagent channels setup ${kind}`,
|
|
50
|
+
...(config.http?.publicUrl === undefined ? {} : { publicUrl: config.http.publicUrl }),
|
|
51
|
+
}).catch((error) => failStartup(new Error(`${kind} setup did not finish (${error.message}): \`dev\` needs it while src/channels/${kind}.ts ` +
|
|
52
|
+
`exists. Run \`fastagent channels setup ${kind}\` when ready, or remove the file`, { cause: error })));
|
|
53
|
+
// What setup wrote is this process's now, and the dev worker's: a value it replaced would otherwise keep the old one.
|
|
54
|
+
const values = loadEnvValues(file);
|
|
55
|
+
for (const name of outcome.written)
|
|
56
|
+
process.env[name] = values.get(name);
|
|
57
|
+
if (outcome.after.length > 0) {
|
|
58
|
+
console.error(" next steps:");
|
|
59
|
+
for (const line of outcome.after)
|
|
60
|
+
console.error(` ${line}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ContentScope } from "../authoring.ts";
|
|
2
|
+
import type { OpenServingOptions } from "../harnesses/pi-durable/serve.ts";
|
|
3
|
+
import { type RunsAs } from "../serving-command.ts";
|
|
4
|
+
import type { FlagSpec } from "./kernel.ts";
|
|
5
|
+
/** The flags that place an instance, as the commander adapter hands them over. */
|
|
6
|
+
export interface InstanceFlags {
|
|
7
|
+
name?: string;
|
|
8
|
+
root?: string;
|
|
9
|
+
state?: string;
|
|
10
|
+
workdir?: string;
|
|
11
|
+
config?: string;
|
|
12
|
+
envFile?: string;
|
|
13
|
+
}
|
|
14
|
+
/** The flags of a command that opens, or reads the state of, an instance. */
|
|
15
|
+
export declare const INSTANCE_FLAGS: readonly FlagSpec[];
|
|
16
|
+
/** The flags of a command that reads or edits what an instance works on: where it keeps its clones, and its file. */
|
|
17
|
+
export declare const CONTENT_FLAGS: readonly FlagSpec[];
|
|
18
|
+
/** `--config`: the instance configuration, a fastagent.json, for a command that opens the agent. */
|
|
19
|
+
export declare const CONFIG_FLAG: FlagSpec;
|
|
20
|
+
export declare function instanceFlags(flags: Record<string, unknown>): InstanceFlags;
|
|
21
|
+
/** `--env-file`: the file the agent's values are read from, for a command that opens the agent or reads them. */
|
|
22
|
+
export declare const ENV_FILE_FLAG: FlagSpec;
|
|
23
|
+
/**
|
|
24
|
+
* `--env-file`, settled before the agent's values are entered: absolute, and a file that exists. Without the flag the
|
|
25
|
+
* command's default file is used again, whatever an earlier command in this process chose.
|
|
26
|
+
*/
|
|
27
|
+
export declare function enterEnvFile(given: string | undefined): void;
|
|
28
|
+
/**
|
|
29
|
+
* Enter the agent's directory as a command runs it: the value file, whose values become this process's environment
|
|
30
|
+
* and so the instance's secrets, then where the instance is.
|
|
31
|
+
*/
|
|
32
|
+
export declare function enterInstance(agentDir: string, flags?: InstanceFlags): void;
|
|
33
|
+
/** Where a content command reads and edits an agent's content, as its flags and variables say. */
|
|
34
|
+
export declare function enterContentScope(agentDir: string, flags?: InstanceFlags): ContentScope;
|
|
35
|
+
/** Who runs this process's instance, as its own variables say: the one place the CLI reads them for an open. */
|
|
36
|
+
export declare function runsAsIn(env: NodeJS.ProcessEnv): RunsAs;
|
|
37
|
+
/**
|
|
38
|
+
* What `openServing` is given for the agent in `agentDir`, as the flags and variables entered above say: where the
|
|
39
|
+
* instance is, and its secrets, which for a command are its environment once the value file is entered.
|
|
40
|
+
*/
|
|
41
|
+
export declare function instanceInputs(agentDir: string): Pick<OpenServingOptions, "projectDir" | "workdir" | "stateRoot" | "secrets" | "env" | "ownEnv" | "runsAs" | "name">;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a command's instance is (agent-artifact.md §4.1): the flags that place it, over the environment variables that
|
|
3
|
+
* name the same inputs, settled once at the command's entry into absolute paths in this process's environment. A
|
|
4
|
+
* `dev` worker inherits them, and every reader after (`resolveStateRoot`, `resolveWorkdir`, the instance configuration)
|
|
5
|
+
* reads one answer.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, mkdirSync, statSync } from "node:fs";
|
|
8
|
+
import { baseEnv } from "../child-env.js";
|
|
9
|
+
import { definedValues } from "../declared-secrets.js";
|
|
10
|
+
import { enterAgentEnv } from "../env.js";
|
|
11
|
+
import { INSTANCE_CONFIG_ENV, INSTANCE_ROOT_ENV, INSTANCE_STATE_ENV, INSTANCE_WORKDIR_ENV, isAgentcoreRuntime, isDeployedWorkspace, resolveOverridePath, resolveStateRoot, resolveWorkdir, } from "../paths.js";
|
|
12
|
+
import { INSTANCE_NAME_ENV, checkInstanceName, enteredInstanceName } from "../instance-name.js";
|
|
13
|
+
import { servedByDev } from "../serving-command.js";
|
|
14
|
+
import { useValueFile } from "../value-file.js";
|
|
15
|
+
import { failUsage } from "./fail.js";
|
|
16
|
+
const INSTANCE_LOCATION = [
|
|
17
|
+
["root", "--root", INSTANCE_ROOT_ENV],
|
|
18
|
+
["state", "--state", INSTANCE_STATE_ENV],
|
|
19
|
+
["workdir", "--workdir", INSTANCE_WORKDIR_ENV],
|
|
20
|
+
["config", "--config", INSTANCE_CONFIG_ENV],
|
|
21
|
+
];
|
|
22
|
+
const NAME_FLAG = {
|
|
23
|
+
flags: "--name <name>",
|
|
24
|
+
description: `the instance's name, one path segment (${INSTANCE_NAME_ENV}; default: the program's name)`,
|
|
25
|
+
};
|
|
26
|
+
const ROOT_FLAG = {
|
|
27
|
+
flags: "--root <dir>",
|
|
28
|
+
description: `the instance root: its working directory, with its state in <dir>/.state (${INSTANCE_ROOT_ENV})`,
|
|
29
|
+
};
|
|
30
|
+
const STATE_FLAG = {
|
|
31
|
+
flags: "--state <dir>",
|
|
32
|
+
description: `the instance's state, apart from the root (${INSTANCE_STATE_ENV})`,
|
|
33
|
+
};
|
|
34
|
+
const WORKDIR_FLAG = {
|
|
35
|
+
flags: "--workdir <dir>",
|
|
36
|
+
description: `the agent's working directory, apart from the root (${INSTANCE_WORKDIR_ENV})`,
|
|
37
|
+
};
|
|
38
|
+
/** The flags of a command that opens, or reads the state of, an instance. */
|
|
39
|
+
export const INSTANCE_FLAGS = [NAME_FLAG, ROOT_FLAG, STATE_FLAG, WORKDIR_FLAG];
|
|
40
|
+
/** The flags of a command that reads or edits what an instance works on: where it keeps its clones, and its file. */
|
|
41
|
+
export const CONTENT_FLAGS = [
|
|
42
|
+
ROOT_FLAG,
|
|
43
|
+
WORKDIR_FLAG,
|
|
44
|
+
{
|
|
45
|
+
flags: "--config <file>",
|
|
46
|
+
description: `the instance configuration to read and edit, a fastagent.json (${INSTANCE_CONFIG_ENV}; default: the project's)`,
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
/** `--config`: the instance configuration, a fastagent.json, for a command that opens the agent. */
|
|
50
|
+
export const CONFIG_FLAG = {
|
|
51
|
+
flags: "--config <file>",
|
|
52
|
+
description: `the instance configuration, a fastagent.json (${INSTANCE_CONFIG_ENV}; dev reads the one at the project root)`,
|
|
53
|
+
};
|
|
54
|
+
export function instanceFlags(flags) {
|
|
55
|
+
const picked = {};
|
|
56
|
+
for (const key of [...INSTANCE_LOCATION.map(([name]) => name), "name", "envFile"]) {
|
|
57
|
+
if (typeof flags[key] === "string")
|
|
58
|
+
picked[key] = flags[key];
|
|
59
|
+
}
|
|
60
|
+
return picked;
|
|
61
|
+
}
|
|
62
|
+
function makeDirectory(path, source) {
|
|
63
|
+
try {
|
|
64
|
+
mkdirSync(path, { recursive: true });
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
failUsage(`${source} ${path} cannot be used as a directory: ${error.message}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** `--env-file`: the file the agent's values are read from, for a command that opens the agent or reads them. */
|
|
71
|
+
export const ENV_FILE_FLAG = {
|
|
72
|
+
flags: "--env-file <file>",
|
|
73
|
+
description: "the file the agent's secrets are read from, over the default (.secrets/.env); it must exist",
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* `--env-file`, settled before the agent's values are entered: absolute, and a file that exists. Without the flag the
|
|
77
|
+
* command's default file is used again, whatever an earlier command in this process chose.
|
|
78
|
+
*/
|
|
79
|
+
export function enterEnvFile(given) {
|
|
80
|
+
if (given === undefined) {
|
|
81
|
+
useValueFile(undefined);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (given.trim() === "")
|
|
85
|
+
failUsage("--env-file needs a path");
|
|
86
|
+
const path = resolveOverridePath(given);
|
|
87
|
+
if (!existsSync(path) || !statSync(path).isFile())
|
|
88
|
+
failUsage(`--env-file ${path} is not a file`);
|
|
89
|
+
useValueFile(path);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Enter the agent's directory as a command runs it: the value file, whose values become this process's environment
|
|
93
|
+
* and so the instance's secrets, then where the instance is.
|
|
94
|
+
*/
|
|
95
|
+
export function enterInstance(agentDir, flags = {}) {
|
|
96
|
+
enterEnvFile(flags.envFile);
|
|
97
|
+
enterAgentEnv(agentDir);
|
|
98
|
+
enterInstanceLocation(flags);
|
|
99
|
+
}
|
|
100
|
+
/** Where a content command reads and edits an agent's content, as its flags and variables say. */
|
|
101
|
+
export function enterContentScope(agentDir, flags = {}) {
|
|
102
|
+
enterInstanceLocation(flags);
|
|
103
|
+
const config = process.env[INSTANCE_CONFIG_ENV];
|
|
104
|
+
return { workdir: resolveWorkdir(agentDir), ...(config === undefined ? {} : { config }) };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Settle the instance's location: a flag beats its environment variable, a relative path is resolved against the
|
|
108
|
+
* directory the command was started in (here, once), and the directories named are made. Refuses a flag with no path.
|
|
109
|
+
*/
|
|
110
|
+
function enterInstanceLocation(flags = {}) {
|
|
111
|
+
for (const [key, flag, variable] of INSTANCE_LOCATION) {
|
|
112
|
+
const given = flags[key];
|
|
113
|
+
if (given !== undefined && given.trim() === "")
|
|
114
|
+
failUsage(`${flag} needs a path`);
|
|
115
|
+
const path = resolveOverridePath(given ?? process.env[variable]);
|
|
116
|
+
if (path === undefined)
|
|
117
|
+
continue;
|
|
118
|
+
process.env[variable] = path;
|
|
119
|
+
if (key === "root" || key === "workdir")
|
|
120
|
+
makeDirectory(path, given === undefined ? variable : flag);
|
|
121
|
+
}
|
|
122
|
+
const name = flags.name ?? enteredInstanceName();
|
|
123
|
+
if (name === undefined)
|
|
124
|
+
return;
|
|
125
|
+
try {
|
|
126
|
+
checkInstanceName(name);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
failUsage(`${flags.name === undefined ? INSTANCE_NAME_ENV : "--name"}: ${error.message}`);
|
|
130
|
+
}
|
|
131
|
+
process.env[INSTANCE_NAME_ENV] = name;
|
|
132
|
+
}
|
|
133
|
+
/** Who runs this process's instance, as its own variables say: the one place the CLI reads them for an open. */
|
|
134
|
+
export function runsAsIn(env) {
|
|
135
|
+
return { dev: servedByDev(env), deployed: isDeployedWorkspace(env), agentcore: isAgentcoreRuntime(env) };
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* What `openServing` is given for the agent in `agentDir`, as the flags and variables entered above say: where the
|
|
139
|
+
* instance is, and its secrets, which for a command are its environment once the value file is entered.
|
|
140
|
+
*/
|
|
141
|
+
export function instanceInputs(agentDir) {
|
|
142
|
+
const workdir = resolveWorkdir(agentDir);
|
|
143
|
+
// A default one is the project's own `.fastagent/<environment>/`, which nothing has made yet.
|
|
144
|
+
makeDirectory(workdir, "the working directory");
|
|
145
|
+
return {
|
|
146
|
+
projectDir: agentDir,
|
|
147
|
+
...(enteredInstanceName() === undefined ? {} : { name: enteredInstanceName() }),
|
|
148
|
+
workdir,
|
|
149
|
+
stateRoot: resolveStateRoot(agentDir),
|
|
150
|
+
secrets: definedValues(process.env),
|
|
151
|
+
env: baseEnv(process.env),
|
|
152
|
+
ownEnv: process.env,
|
|
153
|
+
runsAs: runsAsIn(process.env),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
import { type Message, type MessageStreamEvent } from "../agent-api.ts";
|
|
3
3
|
/** A command that sends a message exits 0 only when it completed. */
|
|
4
4
|
export declare const exitCodeOf: (message: Pick<Message, "status">) => number;
|
|
5
|
-
/**
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* The answer as text on `out`, what the tools did and why it failed on `err`. `authHint` is what to do when the failure
|
|
7
|
+
* is a model with no credential, which depends on where the agent runs.
|
|
8
|
+
*/
|
|
9
|
+
export declare function runInvokeStream(events: AsyncIterable<MessageStreamEvent>, out: (text: string) => void, err: (line: string) => void, authHint?: string): Promise<number>;
|
|
7
10
|
/**
|
|
8
11
|
* The answer as JSON lines, for a program to read: the message's events as `messages.stream` delivers them, its
|
|
9
12
|
* `message` first, through its `done`. A message that ends no other way ends with the line that says why: `rejected`
|
|
@@ -31,8 +31,11 @@ async function readMessage(events, read, refused) {
|
|
|
31
31
|
}
|
|
32
32
|
return undefined;
|
|
33
33
|
}
|
|
34
|
-
/**
|
|
35
|
-
|
|
34
|
+
/**
|
|
35
|
+
* The answer as text on `out`, what the tools did and why it failed on `err`. `authHint` is what to do when the failure
|
|
36
|
+
* is a model with no credential, which depends on where the agent runs.
|
|
37
|
+
*/
|
|
38
|
+
export async function runInvokeStream(events, out, err, authHint) {
|
|
36
39
|
const toolName = new Map(); // a tool result carries the id; its name came with tool_started
|
|
37
40
|
const textOf = answerText();
|
|
38
41
|
const exit = await readMessage(events, (event) => {
|
|
@@ -65,6 +68,8 @@ export async function runInvokeStream(events, out, err) {
|
|
|
65
68
|
const failed = failure(event.message);
|
|
66
69
|
if (failed !== undefined)
|
|
67
70
|
err(`[fastagent] failed: ${failed}`);
|
|
71
|
+
if (authHint !== undefined && event.message.error?.code === "auth_required")
|
|
72
|
+
err(`[fastagent] next: ${authHint}`);
|
|
68
73
|
return exitCodeOf(event.message);
|
|
69
74
|
}
|
|
70
75
|
default:
|