@fastagent-sh/fastagent 0.14.0 → 0.16.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 +16 -6
- package/dist/agent.d.ts +20 -0
- package/dist/agent.js +9 -0
- package/dist/channels/agentcore-limits.d.ts +7 -0
- package/dist/channels/agentcore-limits.js +9 -0
- package/dist/channels/agentcore-state.d.ts +83 -0
- package/dist/channels/agentcore-state.js +258 -0
- package/dist/channels/agentcore.d.ts +98 -0
- package/dist/channels/agentcore.js +260 -0
- package/dist/channels/busy.d.ts +23 -0
- package/dist/channels/busy.js +53 -0
- package/dist/channels/context-buffer.d.ts +35 -0
- package/dist/channels/context-buffer.js +103 -0
- package/dist/channels/control.d.ts +28 -0
- package/dist/channels/control.js +214 -0
- package/dist/channels/feishu/card.js +1 -1
- package/dist/channels/feishu/context-buffer.d.ts +15 -13
- package/dist/channels/feishu/context-buffer.js +62 -69
- package/dist/channels/feishu/feishu-api.d.ts +11 -3
- package/dist/channels/feishu/feishu-api.js +24 -3
- package/dist/channels/feishu/feishu.d.ts +27 -27
- package/dist/channels/feishu/feishu.js +318 -207
- package/dist/channels/feishu/invoke-turn.d.ts +7 -20
- package/dist/channels/feishu/invoke-turn.js +44 -79
- package/dist/channels/feishu/model.d.ts +2 -2
- package/dist/channels/feishu/normalize.d.ts +2 -1
- package/dist/channels/feishu/normalize.js +0 -1
- package/dist/channels/feishu/parse.d.ts +22 -8
- package/dist/channels/feishu/parse.js +24 -7
- package/dist/channels/feishu/preview.d.ts +4 -7
- package/dist/channels/feishu/preview.js +27 -142
- package/dist/channels/feishu/register-app.d.ts +2 -1
- package/dist/channels/feishu/register-webhook.d.ts +2 -1
- package/dist/channels/feishu/scaffold/channel.ts +9 -8
- package/dist/channels/feishu/scaffold/feishu-send.ts +6 -4
- package/dist/channels/feishu/setup-mode.d.ts +37 -0
- package/dist/channels/feishu/setup-mode.js +28 -0
- package/dist/channels/feishu/ws-ingress.d.ts +28 -0
- package/dist/channels/feishu/ws-ingress.js +136 -0
- package/dist/channels/github/github.js +16 -7
- package/dist/channels/http.d.ts +14 -0
- package/dist/channels/http.js +36 -3
- package/dist/channels/invoke-turn-kit.d.ts +65 -0
- package/dist/channels/invoke-turn-kit.js +87 -0
- package/dist/channels/lark/lark.d.ts +4 -2
- package/dist/channels/lark/lark.js +4 -1
- package/dist/channels/lark/onboard.d.ts +8 -4
- package/dist/channels/lark/onboard.js +8 -0
- package/dist/channels/lark/scaffold/channel.ts +9 -8
- package/dist/channels/lark/scaffold/lark-send.ts +6 -4
- package/dist/channels/preview-kit.d.ts +115 -0
- package/dist/channels/preview-kit.js +184 -0
- package/dist/channels/seen.d.ts +5 -0
- package/dist/channels/seen.js +35 -0
- package/dist/channels/slack/bot-auth.d.ts +15 -0
- package/dist/channels/slack/bot-auth.js +146 -0
- package/dist/channels/slack/config-api.d.ts +60 -0
- package/dist/channels/slack/config-api.js +149 -0
- package/dist/channels/slack/context-buffer.d.ts +24 -0
- package/dist/channels/slack/context-buffer.js +37 -0
- package/dist/channels/slack/invoke-turn.d.ts +19 -0
- package/dist/channels/slack/invoke-turn.js +63 -0
- package/dist/channels/slack/manifest.d.ts +49 -0
- package/dist/channels/slack/manifest.js +69 -0
- package/dist/channels/slack/model.d.ts +67 -0
- package/dist/channels/slack/model.js +2 -0
- package/dist/channels/slack/onboard.d.ts +41 -0
- package/dist/channels/slack/onboard.js +120 -0
- package/dist/channels/slack/onboarding-state.d.ts +31 -0
- package/dist/channels/slack/onboarding-state.js +69 -0
- package/dist/channels/slack/parse.d.ts +38 -0
- package/dist/channels/slack/parse.js +124 -0
- package/dist/channels/slack/preview.d.ts +23 -0
- package/dist/channels/slack/preview.js +403 -0
- package/dist/channels/slack/reaction.d.ts +24 -0
- package/dist/channels/slack/reaction.js +62 -0
- package/dist/channels/slack/register-webhook.d.ts +10 -0
- package/dist/channels/slack/register-webhook.js +49 -0
- package/dist/channels/slack/scaffold/channel.ts +33 -0
- package/dist/channels/slack/scaffold/slack-send.ts +171 -0
- package/dist/channels/slack/setup-server.d.ts +17 -0
- package/dist/channels/slack/setup-server.js +103 -0
- package/dist/channels/slack/slack-api.d.ts +57 -0
- package/dist/channels/slack/slack-api.js +399 -0
- package/dist/channels/slack/slack.d.ts +51 -0
- package/dist/channels/slack/slack.js +496 -0
- package/dist/channels/slack/welcomed.d.ts +5 -0
- package/dist/channels/slack/welcomed.js +32 -0
- package/dist/channels/state.d.ts +11 -4
- package/dist/channels/state.js +22 -15
- package/dist/channels/stop-command.d.ts +6 -0
- package/dist/channels/stop-command.js +36 -0
- package/dist/channels/tasks.d.ts +7 -0
- package/dist/channels/tasks.js +25 -0
- package/dist/channels/telegram/context-buffer.d.ts +8 -17
- package/dist/channels/telegram/context-buffer.js +6 -85
- package/dist/channels/telegram/invoke-turn.d.ts +5 -22
- package/dist/channels/telegram/invoke-turn.js +11 -58
- package/dist/channels/telegram/parse.d.ts +0 -7
- package/dist/channels/telegram/parse.js +4 -2
- package/dist/channels/telegram/preview.d.ts +4 -7
- package/dist/channels/telegram/preview.js +24 -142
- package/dist/channels/telegram/scaffold/telegram-send.ts +6 -3
- package/dist/channels/telegram/telegram.js +24 -10
- package/dist/channels/{feishu/text.d.ts → text.d.ts} +15 -1
- package/dist/channels/{feishu/text.js → text.js} +15 -1
- package/dist/channels/thread-participants.d.ts +21 -0
- package/dist/channels/thread-participants.js +132 -0
- package/dist/channels/turn-queue.js +8 -1
- package/dist/channels/turn-store.d.ts +1 -1
- package/dist/channels/turn-store.js +2 -3
- package/dist/cli/add-feishu.d.ts +30 -0
- package/dist/cli/add-feishu.js +366 -0
- package/dist/cli/add-slack.d.ts +11 -0
- package/dist/cli/add-slack.js +199 -0
- package/dist/{cli-auth.d.ts → cli/auth-view.d.ts} +1 -1
- package/dist/{cli-auth.js → cli/auth-view.js} +1 -1
- package/dist/cli/commands/add.d.ts +4 -0
- package/dist/cli/commands/add.js +191 -60
- package/dist/cli/commands/attach.d.ts +82 -0
- package/dist/cli/commands/attach.js +563 -0
- package/dist/cli/commands/chat.d.ts +1 -0
- package/dist/cli/commands/chat.js +12 -7
- package/dist/cli/commands/deploy.d.ts +3 -1
- package/dist/cli/commands/deploy.js +384 -82
- package/dist/cli/commands/dev.js +34 -26
- package/dist/cli/commands/fire.js +17 -18
- package/dist/cli/commands/info.js +36 -29
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/init.js +65 -53
- package/dist/cli/commands/invoke.js +11 -9
- package/dist/cli/commands/login.js +48 -45
- package/dist/cli/commands/models.js +1 -1
- package/dist/cli/commands/schedule.js +6 -8
- package/dist/cli/commands/start.js +102 -39
- package/dist/cli/commands/tool.js +23 -18
- package/dist/cli/fail.d.ts +17 -2
- package/dist/cli/fail.js +25 -1
- package/dist/{invoke-stream.d.ts → cli/invoke-stream.d.ts} +1 -1
- package/dist/{invoke-stream.js → cli/invoke-stream.js} +4 -0
- package/dist/cli/kernel.d.ts +3 -2
- package/dist/cli/models-view.d.ts +21 -0
- package/dist/cli/models-view.js +66 -0
- package/dist/cli/program.js +135 -56
- package/dist/cli/serve.d.ts +60 -20
- package/dist/cli/serve.js +252 -47
- package/dist/cli/shared.d.ts +40 -7
- package/dist/cli/shared.js +180 -38
- package/dist/collect.d.ts +14 -3
- package/dist/collect.js +24 -0
- package/dist/core.d.ts +3 -1
- package/dist/core.js +2 -0
- package/dist/deploy/agentcore/plan.d.ts +117 -0
- package/dist/deploy/agentcore/plan.js +721 -0
- package/dist/deploy/agentcore/run.d.ts +73 -0
- package/dist/deploy/agentcore/run.js +412 -0
- package/dist/deploy/agentcore/zip.d.ts +17 -0
- package/dist/deploy/agentcore/zip.js +68 -0
- package/dist/deploy/container.d.ts +26 -25
- package/dist/deploy/container.js +93 -89
- package/dist/deploy/docker/plan.d.ts +3 -3
- package/dist/deploy/docker/plan.js +20 -23
- package/dist/deploy/fly/plan.d.ts +5 -1
- package/dist/deploy/fly/plan.js +39 -26
- package/dist/deploy/fly/run.d.ts +17 -5
- package/dist/deploy/fly/run.js +52 -7
- package/dist/deploy/preflight.d.ts +20 -8
- package/dist/deploy/preflight.js +267 -71
- package/dist/deploy/railway/plan.d.ts +10 -1
- package/dist/deploy/railway/plan.js +53 -20
- package/dist/deploy/railway/run.d.ts +13 -5
- package/dist/deploy/railway/run.js +22 -7
- package/dist/deploy/runner.d.ts +7 -3
- package/dist/deploy/runner.js +9 -3
- package/dist/deploy/secrets.d.ts +2 -1
- package/dist/deploy/secrets.js +23 -3
- package/dist/dev-supervisor.d.ts +11 -10
- package/dist/dev-supervisor.js +56 -50
- package/dist/engines/pi/auth.d.ts +8 -7
- package/dist/engines/pi/auth.js +12 -10
- package/dist/engines/pi/channel.d.ts +22 -16
- package/dist/engines/pi/channel.js +92 -62
- package/dist/engines/pi/chat.d.ts +4 -16
- package/dist/engines/pi/chat.js +8 -261
- package/dist/engines/pi/config.d.ts +20 -55
- package/dist/engines/pi/config.js +49 -121
- package/dist/engines/pi/create.d.ts +30 -10
- package/dist/engines/pi/create.js +33 -26
- package/dist/engines/pi/definition.d.ts +7 -26
- package/dist/engines/pi/definition.js +8 -54
- package/dist/engines/pi/harness.d.ts +49 -0
- package/dist/engines/pi/harness.js +90 -2
- package/dist/engines/pi/invoke.d.ts +55 -2
- package/dist/engines/pi/invoke.js +304 -19
- package/dist/engines/pi/login.d.ts +12 -1
- package/dist/engines/pi/login.js +16 -4
- package/dist/engines/pi/models.d.ts +59 -13
- package/dist/engines/pi/models.js +62 -24
- package/dist/engines/pi/open.d.ts +114 -0
- package/dist/engines/pi/open.js +127 -0
- package/dist/engines/pi/session-builder.d.ts +16 -0
- package/dist/engines/pi/session-builder.js +308 -0
- package/dist/engines/pi/session-control.d.ts +50 -0
- package/dist/engines/pi/session-control.js +604 -0
- package/dist/engines/pi/sessions.d.ts +17 -2
- package/dist/engines/pi/sessions.js +9 -0
- package/dist/engines/pi/tool-context.d.ts +18 -11
- package/dist/engines/pi/tool-context.js +3 -9
- package/dist/engines/pi/tool.d.ts +6 -8
- package/dist/engines/pi/tool.js +10 -1
- package/dist/engines/pi/wake-tool.d.ts +0 -3
- package/dist/engines/pi/wake-tool.js +9 -7
- package/dist/env.d.ts +16 -4
- package/dist/env.js +43 -5
- package/dist/feishu.d.ts +1 -1
- package/dist/feishu.js +1 -1
- package/dist/host/node.d.ts +25 -8
- package/dist/host/node.js +5 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lark.d.ts +1 -1
- package/dist/lark.js +1 -1
- package/dist/loader.d.ts +2 -2
- package/dist/loader.js +3 -3
- package/dist/log.d.ts +1 -1
- package/dist/log.js +1 -1
- package/dist/observe.js +3 -0
- package/dist/paths.d.ts +138 -0
- package/dist/paths.js +326 -0
- package/dist/pi.d.ts +6 -5
- package/dist/pi.js +4 -3
- package/dist/runtime.d.ts +7 -5
- package/dist/runtime.js +2 -2
- package/dist/scaffold/add-channel.d.ts +26 -9
- package/dist/scaffold/add-channel.js +175 -40
- package/dist/scaffold/init.d.ts +32 -41
- package/dist/scaffold/init.js +161 -185
- package/dist/scaffold/templates/env.example +15 -6
- package/dist/scaffold/templates/fastagent.config.mjs +5 -4
- package/dist/scaffold/templates/gitignore +14 -6
- package/dist/scaffold/templates/persona.md +4 -2
- package/dist/scaffold/templates/secrets.gitignore +5 -0
- package/dist/scaffold/templates.d.ts +1 -7
- package/dist/scaffold/templates.js +3 -25
- package/dist/scaffold/vendor-skill.d.ts +2 -2
- package/dist/scaffold/vendor-skill.js +13 -13
- package/dist/schedule/discover.js +4 -4
- package/dist/schedule/scheduler.d.ts +40 -1
- package/dist/schedule/scheduler.js +89 -56
- package/dist/schedule/state.js +1 -1
- package/dist/schedule/wake-alarm.d.ts +47 -0
- package/dist/schedule/wake-alarm.js +136 -0
- package/dist/schedule/wakeups.d.ts +1 -3
- package/dist/schedule/wakeups.js +19 -1
- package/dist/session-remote.d.ts +53 -0
- package/dist/session-remote.js +336 -0
- package/dist/session.d.ts +265 -0
- package/dist/session.js +37 -0
- package/dist/slack.d.ts +2 -0
- package/dist/slack.js +2 -0
- package/dist/tunnel.d.ts +7 -4
- package/dist/tunnel.js +23 -12
- package/package.json +22 -7
- package/dist/channels/feishu/owned-threads.d.ts +0 -11
- package/dist/channels/feishu/owned-threads.js +0 -47
- package/dist/channels/feishu/seen.d.ts +0 -5
- package/dist/channels/feishu/seen.js +0 -47
- package/dist/cli-add-feishu.d.ts +0 -8
- package/dist/cli-add-feishu.js +0 -223
- package/dist/cli-models.d.ts +0 -11
- package/dist/cli-models.js +0 -20
- package/dist/engines/pi/workspace.d.ts +0 -56
- package/dist/engines/pi/workspace.js +0 -72
- package/dist/scaffold/templates/gitignore.agentdir-root +0 -5
- package/dist/scaffold/templates/gitignore.kit +0 -2
- package/dist/workspace.d.ts +0 -9
- package/dist/workspace.js +0 -45
package/dist/cli/shared.js
CHANGED
|
@@ -1,17 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Helpers shared across command modules: interactivity gates, port parsing, the startup auth report,
|
|
3
|
-
*
|
|
4
|
-
* (`values.*`) became parameters.
|
|
3
|
+
* first-run model resolution, and the login terminal IO. Bodies moved verbatim from cli.ts; the
|
|
4
|
+
* module-scoped flag access (`values.*`) became parameters.
|
|
5
5
|
*/
|
|
6
6
|
import { readFile, writeFile } from "node:fs/promises";
|
|
7
7
|
import { relative } from "node:path";
|
|
8
|
-
import { autocomplete, isCancel, select } from "@clack/prompts";
|
|
8
|
+
import { autocomplete, isCancel, log as clackLog, password, select, text as clackText } from "@clack/prompts";
|
|
9
|
+
import { buildModelPickerOptions } from "./models-view.js";
|
|
9
10
|
import { fastagentCredentialStore } from "../engines/pi/auth.js";
|
|
10
|
-
import { isValidPort, loadConfig, resolveAuthPath, resolveModelSpec, rewriteConfigModel, } from "../engines/pi/config.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { isValidPort, listModels, loadConfig, providerOf, resolveAuthPath, resolveModel, resolveModelSpec, rewriteConfigModel, } from "../engines/pi/config.js";
|
|
12
|
+
import { LoginCancelled, loginFlow } from "../engines/pi/login.js";
|
|
13
|
+
import { createPiModels, probeApiKey, probeAuthSource, providerAuthStatuses } from "../engines/pi/models.js";
|
|
14
|
+
import { formatAuthReport } from "./auth-view.js";
|
|
13
15
|
import { log } from "../log.js";
|
|
16
|
+
import { openExternalUrl } from "../open-url.js";
|
|
14
17
|
import { failStartup, failUsage } from "./fail.js";
|
|
18
|
+
/**
|
|
19
|
+
* The padded label writer for the STARTUP report (`dev`/`start`, stderr via the log level). Hand-spaced
|
|
20
|
+
* labels drift out of alignment the moment a longer one appears — which is exactly what happened when
|
|
21
|
+
* `workspace:` joined `config:`/`model:`/`state:`. `info` keeps its own writer on purpose: its report is
|
|
22
|
+
* stdout DATA (pipeable, its own label set, its own width), not a log line — the shared thing is the
|
|
23
|
+
* policy (pad, never hand-space), not a constant.
|
|
24
|
+
*/
|
|
25
|
+
export function reportLine(label, value) {
|
|
26
|
+
log.info(`[fastagent] ${`${label}:`.padEnd(11)}${value}`);
|
|
27
|
+
}
|
|
28
|
+
/** The workspace hint under the `agent:`/`workspace:` pair, when there is one ({@link workspaceHint}):
|
|
29
|
+
* you pointed at the agent, and the project around it is probably what you meant. A hint, so it renders
|
|
30
|
+
* as one and is silent otherwise — `dev` and `start` both print the pair, so both ask for it. */
|
|
31
|
+
export function reportWorkspaceHint(hint) {
|
|
32
|
+
if (hint)
|
|
33
|
+
reportLine("hint", hint);
|
|
34
|
+
}
|
|
15
35
|
/** Both stdin and stdout are a terminal — the precondition for an interactive prompt. */
|
|
16
36
|
export function isInteractive() {
|
|
17
37
|
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
@@ -38,7 +58,7 @@ export function parsePort(value, source, from) {
|
|
|
38
58
|
}
|
|
39
59
|
/** Report which source provides the model's credentials, surfacing a remediation hint at startup. Non-blocking. */
|
|
40
60
|
export async function reportAuth(modelSpec, authPath) {
|
|
41
|
-
const provider =
|
|
61
|
+
const provider = providerOf(modelSpec);
|
|
42
62
|
const source = await probeAuthSource(createPiModels({ authPath }), modelSpec);
|
|
43
63
|
// Only when nothing satisfies auth do we read the store (refresh-FREE) to tell "nothing stored" from
|
|
44
64
|
// "stored but unusable" — see formatAuthReport for why. store.read warns on a corrupt file itself.
|
|
@@ -53,54 +73,176 @@ export async function reportAuth(modelSpec, authPath) {
|
|
|
53
73
|
log.warn(`[fastagent] ${report.warn}`);
|
|
54
74
|
}
|
|
55
75
|
/**
|
|
56
|
-
* First-run model resolution for
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
76
|
+
* First-run model resolution for every assembly command (dev/start/invoke/fire/chat/deploy): ONE
|
|
77
|
+
* funnel, no dead ends. When no model is set (flag/env/config) and we're on a TTY, show the FULL
|
|
78
|
+
* catalog annotated per provider — ready (with the credential source, so which account pays is
|
|
79
|
+
* visible at the decision point) or login-required — and, when the choice needs auth, run the login
|
|
80
|
+
* flow INLINE instead of exiting with "run `fastagent login` and come back". A no-op when a model is
|
|
81
|
+
* already set; on a non-TTY (CI, a piped stdin), with `--no-input`, on cancel, or on a failed login
|
|
82
|
+
* it stays quiet and lets the caller raise its own clear error (`missing model`, or deploy's
|
|
83
|
+
* model-travel gate). The pick is exported to FASTAGENT_MODEL so a spawned `dev` worker inherits it,
|
|
84
|
+
* and best-effort written back to the config so the next run is quiet. `agentDir` is the resolved
|
|
85
|
+
* AGENT DIR (resolvePlacement().agentDir) — config and auth both live there.
|
|
62
86
|
*/
|
|
63
|
-
export async function resolveFirstRunModel(
|
|
64
|
-
const { config, path: configPath } = await loadConfig(
|
|
87
|
+
export async function resolveFirstRunModel(agentDir, options = {}) {
|
|
88
|
+
const { config, path: configPath } = await loadConfig(agentDir).catch(failStartup);
|
|
65
89
|
if (resolveModelSpec(options.model, config))
|
|
66
90
|
return; // already set (flag > FASTAGENT_MODEL > config)
|
|
67
91
|
if (options.input === false)
|
|
68
92
|
return; // --no-input: never prompt (clig) — the opener raises the clear error
|
|
69
93
|
if (!isInteractive())
|
|
70
94
|
return; // CI/deploy: the opener throws the actionable missing-model error
|
|
71
|
-
const authPath = resolveAuthPath(
|
|
72
|
-
|
|
95
|
+
const authPath = resolveAuthPath(agentDir, options.authPath);
|
|
96
|
+
const models = createPiModels({ authPath });
|
|
97
|
+
const chosen = await pickWithCredentials(models, authPath);
|
|
98
|
+
if (chosen === undefined)
|
|
99
|
+
return; // cancelled (or auth probe failed): the caller raises its clear missing-model error
|
|
100
|
+
process.env.FASTAGENT_MODEL = chosen; // this process + any spawned dev worker inherits it
|
|
101
|
+
await persistModelChoice(agentDir, configPath, chosen);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The credential-aware pick: full catalog annotated per provider, then the post-pick auth policy —
|
|
105
|
+
* remedy warnings for providers no login flow can fix (the choice is KEPT: model validity is
|
|
106
|
+
* independent of credentials), or the inline login for the rest. Returns the chosen spec, or
|
|
107
|
+
* undefined when the pick should be discarded (picker cancel, login cancel, a failed auth probe).
|
|
108
|
+
*/
|
|
109
|
+
async function pickWithCredentials(models, authPath) {
|
|
110
|
+
let statuses;
|
|
73
111
|
try {
|
|
74
|
-
|
|
112
|
+
statuses = await providerAuthStatuses(models);
|
|
75
113
|
}
|
|
76
114
|
catch (error) {
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
// raises the clear missing-model error.
|
|
80
|
-
log.warn(`[fastagent] could not
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
if (specs.length === 0) {
|
|
84
|
-
log.warn(`[fastagent] no model set and no authenticated provider — run \`fastagent login\`, then \`fastagent dev\``);
|
|
85
|
-
return;
|
|
115
|
+
// Per-provider auth throws are captured as `broken` INSIDE providerAuthStatuses; reaching here
|
|
116
|
+
// means the enumeration itself failed (getProviders / a provider with no probe-able surface) — a
|
|
117
|
+
// system fault. Surface it; the opener then still raises the clear missing-model error.
|
|
118
|
+
log.warn(`[fastagent] could not probe provider auth: ${error.message}`);
|
|
119
|
+
return undefined;
|
|
86
120
|
}
|
|
87
|
-
const r = await
|
|
121
|
+
const r = await autocomplete({
|
|
88
122
|
message: "Choose a model for this agent",
|
|
89
|
-
options:
|
|
123
|
+
options: buildModelPickerOptions(listModels(models), statuses),
|
|
90
124
|
});
|
|
91
125
|
if (isCancel(r))
|
|
92
|
-
return; // cancelled:
|
|
126
|
+
return undefined; // cancelled: the caller raises its clear missing-model error
|
|
93
127
|
const chosen = r;
|
|
94
|
-
|
|
95
|
-
|
|
128
|
+
const provider = providerOf(chosen);
|
|
129
|
+
const status = statuses.get(provider);
|
|
130
|
+
if (status?.state === "ready")
|
|
131
|
+
return chosen; // usable now — nothing to fix
|
|
132
|
+
if (status && status.login === "none") {
|
|
133
|
+
// No login flow exists for this provider — KEEP the choice and name the remedy. The remedy depends
|
|
134
|
+
// on WHY it is not ready: a BROKEN stored credential still owns the provider (env is consulted
|
|
135
|
+
// only when nothing is stored — createPiModels), so "set the env var" would not help there.
|
|
136
|
+
if (status.state === "broken") {
|
|
137
|
+
log.warn(`[fastagent] stored auth for "${provider}" is unusable: ${status.message} — fix or remove it in ${authPath}; invokes fail until then`);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
log.warn(`[fastagent] "${provider}" has no interactive login — set its API key env var; invokes fail until then`);
|
|
141
|
+
}
|
|
142
|
+
return chosen;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
// Verified against the CHOSEN model — the exact request the agent is about to make; a rejected
|
|
146
|
+
// key re-prompts inside the loop, so reaching here means a usable (or at worst unverifiable) key.
|
|
147
|
+
await loginWithKeyCheck(provider, authPath, chosen);
|
|
148
|
+
console.error(`[fastagent] logged in to ${provider} — saved to ${authPath}`);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
if (error instanceof LoginCancelled)
|
|
152
|
+
return undefined; // user backed out — discard the choice, like a picker cancel
|
|
153
|
+
// A FAILED login keeps the choice: the pick persists, the startup auth report names the remedy,
|
|
154
|
+
// and a later `fastagent login` fixes auth without re-picking the model.
|
|
155
|
+
log.warn(`[fastagent] login for "${provider}" failed: ${error.message} — model saved; run \`fastagent login\` to fix auth`);
|
|
156
|
+
}
|
|
157
|
+
return chosen;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Interactive login with the api_key quick-fail probe closed into a LOOP: a definitively rejected key
|
|
161
|
+
* (HTTP 401) deletes the bad credential and RE-PROMPTS immediately — the user's hands are on the
|
|
162
|
+
* keyboard NOW; parking the failure for a later `fastagent login` would waste that. The loop exits on
|
|
163
|
+
* a verified/unverifiable key (kept), an OAuth login (completing the flow already proved the
|
|
164
|
+
* credential), or cancel (LoginCancelled propagates to the caller's cancel policy). Used by both the
|
|
165
|
+
* `login` command and the first-run picker's inline login.
|
|
166
|
+
*/
|
|
167
|
+
export async function loginWithKeyCheck(provider, authPath, spec,
|
|
168
|
+
// Test seams: this loop DESTROYS credential state on `rejected`, so its policy (rejected → delete →
|
|
169
|
+
// re-ask ONLY the key) is pinned by a test through fake flow/verify; production callers omit both.
|
|
170
|
+
seams = {}) {
|
|
171
|
+
const flow = seams.flow ?? loginFlow;
|
|
172
|
+
const verify = seams.verify ?? verifyApiKeyLogin;
|
|
173
|
+
const io = terminalLoginIO();
|
|
174
|
+
let method;
|
|
175
|
+
for (;;) {
|
|
176
|
+
const result = await flow(io, { provider, authPath, method });
|
|
177
|
+
if (result.method !== "api_key")
|
|
178
|
+
return result;
|
|
179
|
+
const verdict = await verify(result.provider, authPath, spec);
|
|
180
|
+
if (verdict !== "rejected")
|
|
181
|
+
return result;
|
|
182
|
+
// Retry re-asks ONLY the key: the provider/method choices weren't the mistake, the keystrokes were.
|
|
183
|
+
provider = result.provider;
|
|
184
|
+
method = "api_key";
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Quick-fail check after an api_key login (OAuth needs none — completing the flow already proved the
|
|
189
|
+
* credential): probe the stored key with one minimal request against `spec`, or the provider's first
|
|
190
|
+
* model. Policy over {@link probeApiKey}'s verdict: `rejected` (definitive HTTP 401) DELETES the
|
|
191
|
+
* just-stored credential — a mistyped key must not persist as plausible state — and the caller
|
|
192
|
+
* ({@link loginWithKeyCheck}) re-prompts; `unknown` (network, quota, permissions) keeps it and prints
|
|
193
|
+
* the provider's message: the key may still be right, and wrongly destroying a good credential costs
|
|
194
|
+
* more than keeping a doubtful one.
|
|
195
|
+
*/
|
|
196
|
+
async function verifyApiKeyLogin(provider, authPath, spec) {
|
|
197
|
+
const models = createPiModels({ authPath });
|
|
198
|
+
const model = spec ? resolveModel(models, spec) : models.getProvider(provider)?.getModels()[0];
|
|
199
|
+
if (!model) {
|
|
200
|
+
console.error(`[fastagent] cannot verify the key: provider "${provider}" lists no models — kept as stored`);
|
|
201
|
+
return "unknown";
|
|
202
|
+
}
|
|
203
|
+
const label = `${model.provider}/${model.id}`;
|
|
204
|
+
console.error(`[fastagent] verifying the key with ${label}…`);
|
|
205
|
+
const probe = await probeApiKey(models, model);
|
|
206
|
+
if (probe.state === "ok") {
|
|
207
|
+
console.error(`[fastagent] key verified — ${label} responded`);
|
|
208
|
+
}
|
|
209
|
+
else if (probe.state === "rejected") {
|
|
210
|
+
await fastagentCredentialStore(authPath).delete(provider);
|
|
211
|
+
console.error(`[fastagent] ${provider} rejected the API key (HTTP 401): ${probe.message} — enter it again (or cancel)`);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
console.error(`[fastagent] could not verify the key with ${label}: ${probe.message} — kept; invokes surface the provider's error`);
|
|
215
|
+
}
|
|
216
|
+
return probe.state;
|
|
217
|
+
}
|
|
218
|
+
/** Login terminal IO via @clack/prompts: a searchable list once long, a hidden prompt for keys. Shared
|
|
219
|
+
* by the `login` command and the first-run picker's inline login. */
|
|
220
|
+
function terminalLoginIO() {
|
|
221
|
+
return {
|
|
222
|
+
async select(message, options) {
|
|
223
|
+
const r = await (options.length > 7 ? autocomplete : select)({ message, options });
|
|
224
|
+
return isCancel(r) ? undefined : r;
|
|
225
|
+
},
|
|
226
|
+
async prompt(message, opts) {
|
|
227
|
+
const r = opts?.hidden
|
|
228
|
+
? await password({ message, signal: opts.signal })
|
|
229
|
+
: await clackText({ message, signal: opts?.signal });
|
|
230
|
+
return isCancel(r) ? undefined : r;
|
|
231
|
+
},
|
|
232
|
+
note: (message) => clackLog.info(message),
|
|
233
|
+
openUrl: openExternalUrl,
|
|
234
|
+
};
|
|
96
235
|
}
|
|
97
236
|
/**
|
|
98
|
-
* Best-effort persist the picked model so the next run does not prompt.
|
|
99
|
-
* `model:` placeholder the scaffold writes
|
|
100
|
-
*
|
|
237
|
+
* Best-effort persist the picked model so the next run does not prompt. Rewrites the commented
|
|
238
|
+
* `model:` placeholder the scaffold writes / an existing `model:` line, or re-inserts the line into a
|
|
239
|
+
* scaffold-shaped config (the hand-deleted-to-reset case); anything else (a hand-shaped config) is
|
|
240
|
+
* left untouched with a printed hint. Never throws — persistence is a convenience.
|
|
101
241
|
*/
|
|
102
|
-
async function persistModelChoice(
|
|
103
|
-
const hint = () => console.error(
|
|
242
|
+
async function persistModelChoice(agentDir, configPath, spec) {
|
|
243
|
+
const hint = () => console.error(
|
|
244
|
+
// No "using it for this run" promise: deploy's model-travel gate rightly ignores the un-persisted pick.
|
|
245
|
+
`[fastagent] picked ${spec} — set \`model: ${JSON.stringify(spec)}\` in your config to persist`);
|
|
104
246
|
if (!configPath)
|
|
105
247
|
return hint();
|
|
106
248
|
try {
|
|
@@ -108,7 +250,7 @@ async function persistModelChoice(workspaceDir, configPath, spec) {
|
|
|
108
250
|
if (!replaced)
|
|
109
251
|
return hint();
|
|
110
252
|
await writeFile(configPath, replaced);
|
|
111
|
-
console.error(`[fastagent] saved model ${JSON.stringify(spec)} to ${relative(
|
|
253
|
+
console.error(`[fastagent] saved model ${JSON.stringify(spec)} to ${relative(agentDir, configPath)}`);
|
|
112
254
|
}
|
|
113
255
|
catch {
|
|
114
256
|
hint();
|
package/dist/collect.d.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* encoding the terminal discipline (failed → throw, missing terminal →
|
|
4
|
-
* for-await themselves.
|
|
2
|
+
* Caller-side stream helpers: `collect` (buffered consumption, SPEC §7) reduces an AgentEvent
|
|
3
|
+
* stream to a final value, encoding the terminal discipline (failed → throw, missing terminal →
|
|
4
|
+
* error) — streaming consumers for-await themselves. `abortFirstIterator` is the shared
|
|
5
|
+
* cancellation protocol for generator-backed streams.
|
|
5
6
|
*/
|
|
6
7
|
import type { AgentEvent, Json } from "./agent.ts";
|
|
8
|
+
/**
|
|
9
|
+
* The abort-first cancellation protocol, ONCE: an async generator suspended on a quiet await (a
|
|
10
|
+
* tool mid-execution, a silent SSE read) parks inside that await, and `gen.return()`/`gen.throw()`
|
|
11
|
+
* queue behind the pending `next()` FOREVER (async-generator semantics) — a consumer's cancel
|
|
12
|
+
* would deadlock. The wrapper's `return()` first runs `cancel` (abort the underlying work, which
|
|
13
|
+
* settles the suspension), then delegates to `gen.return`, swallowing its rejection (the
|
|
14
|
+
* generator's own catch/finally already surfaced the outcome). `throw()` tears down identically
|
|
15
|
+
* and rethrows the caller's error deterministically instead of poking a completed generator.
|
|
16
|
+
*/
|
|
17
|
+
export declare function abortFirstIterator<T>(gen: AsyncGenerator<T>, cancel: () => void): AsyncIterator<T>;
|
|
7
18
|
/** Exception form of a failed event (thrown by collect). Carries the failed event's fields verbatim, so
|
|
8
19
|
* a buffered consumer can branch on `code` (SPEC §8 failure subdivision) just like a streaming one. */
|
|
9
20
|
export declare class AgentFailure extends Error {
|
package/dist/collect.js
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The abort-first cancellation protocol, ONCE: an async generator suspended on a quiet await (a
|
|
3
|
+
* tool mid-execution, a silent SSE read) parks inside that await, and `gen.return()`/`gen.throw()`
|
|
4
|
+
* queue behind the pending `next()` FOREVER (async-generator semantics) — a consumer's cancel
|
|
5
|
+
* would deadlock. The wrapper's `return()` first runs `cancel` (abort the underlying work, which
|
|
6
|
+
* settles the suspension), then delegates to `gen.return`, swallowing its rejection (the
|
|
7
|
+
* generator's own catch/finally already surfaced the outcome). `throw()` tears down identically
|
|
8
|
+
* and rethrows the caller's error deterministically instead of poking a completed generator.
|
|
9
|
+
*/
|
|
10
|
+
export function abortFirstIterator(gen, cancel) {
|
|
11
|
+
return {
|
|
12
|
+
next: () => gen.next(),
|
|
13
|
+
async return(value) {
|
|
14
|
+
cancel();
|
|
15
|
+
await gen.return(value).catch(() => { });
|
|
16
|
+
return { done: true, value: undefined };
|
|
17
|
+
},
|
|
18
|
+
async throw(error) {
|
|
19
|
+
cancel();
|
|
20
|
+
await gen.return(undefined).catch(() => { });
|
|
21
|
+
throw error;
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
1
25
|
/** Exception form of a failed event (thrown by collect). Carries the failed event's fields verbatim, so
|
|
2
26
|
* a buffered consumer can branch on `code` (SPEC §8 failure subdivision) just like a streaming one. */
|
|
3
27
|
export class AgentFailure extends Error {
|
package/dist/core.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ export type { Agent, AgentEvent, ImageRef, Json, Prompt, Scope } from "./agent.t
|
|
|
2
2
|
export { collect, AgentFailure, type CollectResult } from "./collect.ts";
|
|
3
3
|
export type { ModuleLoadFailure } from "./loader.ts";
|
|
4
4
|
export { createInvokeHandler, nodeListener } from "./channels/http.ts";
|
|
5
|
+
export { controlRoutes, type ControlRoutesOptions, type WireEvent } from "./channels/control.ts";
|
|
6
|
+
export { ControlRequestError, connectAgent, connectSessionControl, type RemoteEndpointOptions, } from "./session-remote.ts";
|
|
5
7
|
export { readBodyCapped } from "./channels/body.ts";
|
|
6
8
|
export { text, textHeaders } from "./channels/respond.ts";
|
|
7
|
-
export { type ChannelContext, type ChannelHandler, type ChannelModule, type Routes, router, serveNode, } from "./host/node.ts";
|
|
9
|
+
export { type ChannelContext, type ChannelHandler, type ChannelModule, type LongConnection, type LongConnectionChannelModule, type Routes, router, serveNode, } from "./host/node.ts";
|
|
8
10
|
export { defineSchedule, type LoadedSchedule, type Schedule } from "./schedule/schedule.ts";
|
|
9
11
|
export { discoverScheduleFiles, loadSchedules } from "./schedule/discover.ts";
|
|
10
12
|
export { createScheduler, scheduleSession, type Scheduler, type SchedulerOptions } from "./schedule/scheduler.ts";
|
package/dist/core.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { collect, AgentFailure } from "./collect.js";
|
|
2
2
|
export { createInvokeHandler, nodeListener } from "./channels/http.js";
|
|
3
|
+
export { controlRoutes } from "./channels/control.js";
|
|
4
|
+
export { ControlRequestError, connectAgent, connectSessionControl, } from "./session-remote.js";
|
|
3
5
|
export { readBodyCapped } from "./channels/body.js";
|
|
4
6
|
export { text, textHeaders } from "./channels/respond.js";
|
|
5
7
|
export { router, serveNode, } from "./host/node.js";
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { ChannelKind } from "../../scaffold/add-channel.ts";
|
|
2
|
+
import { type Artifact, type ContainerInput } from "../container.ts";
|
|
3
|
+
/** The one schedule fact the plan needs (from loadSchedules) — name + cron + tz. */
|
|
4
|
+
export interface ScheduleFact {
|
|
5
|
+
name: string;
|
|
6
|
+
cron: string;
|
|
7
|
+
tz?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface AgentcorePlanInput extends ContainerInput {
|
|
10
|
+
/** Base name (dir basename) — shapes the runtime name, stack name, ECR repo, session id. */
|
|
11
|
+
name: string;
|
|
12
|
+
/** What satisfies model auth locally: an env-var name, an OAuth/stored label, or undefined. */
|
|
13
|
+
modelAuth: string | undefined;
|
|
14
|
+
/** Known first-party channels — each contributes its secret metadata + webhook step. */
|
|
15
|
+
channels: ChannelKind[];
|
|
16
|
+
/** ALL route-channel basenames (customs included) — any of them requires the forwarder. */
|
|
17
|
+
routeChannels: string[];
|
|
18
|
+
/** Extra secret env-var names (fastagent.config deploy.secrets). */
|
|
19
|
+
extraSecrets?: string[];
|
|
20
|
+
/** Static schedules — each becomes an EventBridge Scheduler rule targeting the forwarder. */
|
|
21
|
+
schedules: ScheduleFact[];
|
|
22
|
+
/** Wake tool enabled — DEGRADED here (fires only while a session happens to be awake); warned. */
|
|
23
|
+
selfSchedule: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface AgentcorePlan {
|
|
26
|
+
/** template + forwarder + Dockerfile/.dockerignore — written by the CLI (kept unless --force). */
|
|
27
|
+
artifacts: Artifact[];
|
|
28
|
+
/** The ordered, values-resolved deploy runbook — printed to stdout. */
|
|
29
|
+
runbook: string[];
|
|
30
|
+
/** Cron expressions EventBridge cannot express — surfaced as runbook warnings, not silent drops. */
|
|
31
|
+
untranslatableSchedules: {
|
|
32
|
+
name: string;
|
|
33
|
+
reason: string;
|
|
34
|
+
}[];
|
|
35
|
+
}
|
|
36
|
+
/** SessionStorage mount = FASTAGENT_STATE_DIR (AgentCore requires exactly `/mnt/<one-level>`). It is
|
|
37
|
+
* a fast LOCAL disk only: the platform wipes it on every runtime version update (= every deploy).
|
|
38
|
+
* Durability across deploys comes from the S3 snapshot (channels/agentcore-state.ts). */
|
|
39
|
+
export declare const MOUNT = "/mnt/state";
|
|
40
|
+
/**
|
|
41
|
+
* How long an idle session keeps its microVM. Memory is billed per second across the WHOLE session
|
|
42
|
+
* — idle included, at the peak level reached — so this tail is the standing cost of every burst of
|
|
43
|
+
* activity, while CPU stops billing the moment the agent stops working. 3 minutes rather than the
|
|
44
|
+
* platform's 15: the tail shrinks 5×, and the cost is a cold start (image + Node + snapshot restore)
|
|
45
|
+
* for anyone who returns after a longer gap. `/ping` reports HealthyBusy while work is in flight, so
|
|
46
|
+
* this timer only ever starts once the agent has genuinely settled — a long turn is never cut short.
|
|
47
|
+
* AWS accepts 60–28800.
|
|
48
|
+
*/
|
|
49
|
+
export declare const IDLE_TIMEOUT_SECONDS = 180;
|
|
50
|
+
/** The platform ceiling on one session's compute (8 h). The session ID outlives it: the next invoke
|
|
51
|
+
* simply gets fresh compute with the same storage. */
|
|
52
|
+
export declare const MAX_LIFETIME_SECONDS = 28800;
|
|
53
|
+
/** The state snapshot's object key in the deployment bucket (one object; see agentcore-state.ts). */
|
|
54
|
+
export declare const STATE_KEY = "state/snapshot.json.gz";
|
|
55
|
+
/** The forwarder artifact. Named `index.js` because it IS the Lambda deployment package's entry:
|
|
56
|
+
* zipping it as-is produces a valid package (`Handler: index.handler`), with nothing to rename. */
|
|
57
|
+
export declare const FORWARDER_FILE = "lambda/index.js";
|
|
58
|
+
/** The deployment bucket: forwarder code + the state snapshot. Account-suffixed for S3's GLOBAL
|
|
59
|
+
* namespace, and created OUTSIDE the stack (like the ECR repo) so a `delete-stack` cannot take the
|
|
60
|
+
* agent's memory with it. Bucket names cap at 63 chars; `name` is already gated to 40. */
|
|
61
|
+
export declare function stateBucketName(name: string, account: string): string;
|
|
62
|
+
/** AgentCore env values max 2048 chars — a real OAuth auth.json's base64 exceeds it, so the seed is
|
|
63
|
+
* CHUNKED across FASTAGENT_AUTH_SEED + _2… (collectAuthSeed reassembles at boot). 2000 keeps margin. */
|
|
64
|
+
export declare const AUTH_SEED_CHUNK_SIZE = 2000;
|
|
65
|
+
export declare const AUTH_SEED_MAX_CHUNKS = 4;
|
|
66
|
+
/** The generated template's filename (namespaced under the kit in the agentDir layout). */
|
|
67
|
+
export declare const TEMPLATE_FILE = "agentcore.template.yaml";
|
|
68
|
+
/** The generated template's first-line marker — the ONE source for both the generator and the
|
|
69
|
+
* "did fastagent generate this?" check (deploy's drift gate), so they cannot drift apart. */
|
|
70
|
+
export declare const GENERATED_TEMPLATE_MARKER = "# Generated by `fastagent deploy agentcore`";
|
|
71
|
+
/** Whether an on-disk template is fastagent-generated (vs hand-written — kept, never gated). */
|
|
72
|
+
export declare function isGeneratedAgentcoreTemplate(content: string): boolean;
|
|
73
|
+
/** Runtime name (`[a-zA-Z][a-zA-Z0-9_]{0,47}`) from a dir basename. */
|
|
74
|
+
export declare function toRuntimeName(basename: string): string;
|
|
75
|
+
/** The ONE fixed ingress session id (webhooks + schedule fires) — ≥ 33 chars (the API minimum),
|
|
76
|
+
* deterministic (the Lambda holds it in env), padded so any name clears the floor. */
|
|
77
|
+
export declare function ingressSessionId(name: string): string;
|
|
78
|
+
/** CFN parameter logical id for a secret env-var name: TELEGRAM_BOT_TOKEN → TelegramBotToken
|
|
79
|
+
* (parameter names must be alphanumeric). Deterministic — run.ts builds the same mapping. */
|
|
80
|
+
export declare function cfnParamName(envName: string): string;
|
|
81
|
+
/**
|
|
82
|
+
* Translate a 5-field cron into EventBridge Scheduler's `cron(m h dom mon dow *)`, or say why it
|
|
83
|
+
* can't be. The two dialects disagree exactly where silent translation would misfire:
|
|
84
|
+
* - EventBridge numbers day-of-week 1–7 (1 = Sunday); standard cron uses 0–6 (0/7 = Sunday) —
|
|
85
|
+
* numeric dow values and range endpoints are remapped ({@link mapDowField}); steps and names
|
|
86
|
+
* pass through; a range that wraps under renumbering is refused.
|
|
87
|
+
* - EventBridge requires `?` in dom or dow: a `*` on either side becomes `?`; BOTH restricted is
|
|
88
|
+
* standard cron's OR semantics, which EventBridge cannot express — refused, never approximated.
|
|
89
|
+
* - A 6-field (seconds) expression and L/# day-of-week forms are refused for the same reason.
|
|
90
|
+
*/
|
|
91
|
+
export declare function toEventBridgeCron(cron: string): {
|
|
92
|
+
expression: string;
|
|
93
|
+
} | {
|
|
94
|
+
error: string;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* The forwarder Lambda source — the ONLY string both the template's inline ZipFile and the readable
|
|
98
|
+
* `lambda/forwarder.js` artifact are generated from (one source, no drift). Zero-dependency: the
|
|
99
|
+
* Lambda Node runtime bundles AWS SDK v3. CommonJS ON PURPOSE: CloudFormation inline code always
|
|
100
|
+
* lands as `index.js`, where ESM `import` is a syntax error (found by the first real deploy). Two
|
|
101
|
+
* event shapes: a Function URL webhook (reconstructed verbatim into a `webhook` envelope; the
|
|
102
|
+
* channel's REAL response rides back inside the transport reply and is re-emitted byte-exact —
|
|
103
|
+
* Feishu's URL-verification challenge depends on it), and an EventBridge Scheduler fire
|
|
104
|
+
* (`{ scheduleFire }`, slot = the scheduled instant — the container's idempotency key). MUST stay
|
|
105
|
+
* under CloudFormation's 4096-byte inline-code cap.
|
|
106
|
+
*/
|
|
107
|
+
export declare function forwarderSource(): string;
|
|
108
|
+
/**
|
|
109
|
+
* The EventBridge physical name for a schedule. A schedule's local name is an arbitrary MODULE FILE
|
|
110
|
+
* NAME (`schedules/晨报.ts`, `schedules/deploy check.ts`), while AWS requires `[0-9A-Za-z-_.]+` within
|
|
111
|
+
* 64 chars — and the `fa-<agent>-` prefix already eats up to 44 of them. So: sanitize, bound the
|
|
112
|
+
* readable part, and end with a hash of the ORIGINAL name, which keeps distinct schedules distinct
|
|
113
|
+
* where sanitizing or truncation would have merged them (one rule silently firing for two).
|
|
114
|
+
*/
|
|
115
|
+
export declare function scheduleResourceName(agent: string, schedule: string): string;
|
|
116
|
+
/** Compute the AgentCore deploy plan from the resolved definition. */
|
|
117
|
+
export declare function planAgentcoreDeploy(input: AgentcorePlanInput): AgentcorePlan;
|