@fastagent-sh/fastagent 0.20.0 → 0.21.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.
Files changed (155) hide show
  1. package/README.md +5 -1
  2. package/dist/channels/agentcore-protocol.d.ts +112 -0
  3. package/dist/channels/agentcore-protocol.js +22 -0
  4. package/dist/channels/agentcore-service.d.ts +0 -4
  5. package/dist/channels/agentcore-service.js +1 -6
  6. package/dist/channels/agentcore-state.d.ts +5 -11
  7. package/dist/channels/agentcore-state.js +4 -1
  8. package/dist/channels/agentcore.d.ts +1 -67
  9. package/dist/channels/agentcore.js +90 -89
  10. package/dist/channels/control.d.ts +1 -1
  11. package/dist/channels/control.js +13 -62
  12. package/dist/channels/discover.d.ts +0 -1
  13. package/dist/channels/discover.js +1 -3
  14. package/dist/channels/feishu/context-buffer.d.ts +6 -0
  15. package/dist/channels/feishu/context-buffer.js +0 -38
  16. package/dist/channels/feishu/crypto.d.ts +0 -2
  17. package/dist/channels/feishu/crypto.js +3 -8
  18. package/dist/channels/feishu/feishu-api.js +2 -4
  19. package/dist/channels/feishu/feishu.js +56 -115
  20. package/dist/channels/feishu/parse.d.ts +4 -3
  21. package/dist/channels/feishu/parse.js +5 -4
  22. package/dist/channels/feishu/register-webhook.d.ts +5 -5
  23. package/dist/channels/feishu/register-webhook.js +43 -57
  24. package/dist/channels/feishu/scaffold/feishu-send.ts +12 -67
  25. package/dist/channels/feishu/setup-mode.d.ts +30 -0
  26. package/dist/channels/feishu/setup-mode.js +26 -0
  27. package/dist/channels/feishu/shared-api.d.ts +10 -0
  28. package/dist/channels/feishu/shared-api.js +38 -0
  29. package/dist/channels/http.d.ts +0 -8
  30. package/dist/channels/http.js +4 -56
  31. package/dist/channels/kit/turn-runner.d.ts +59 -0
  32. package/dist/channels/kit/turn-runner.js +84 -0
  33. package/dist/channels/lark/scaffold/lark-send.ts +12 -67
  34. package/dist/channels/registration.d.ts +36 -1
  35. package/dist/channels/registration.js +57 -1
  36. package/dist/channels/secret.d.ts +1 -0
  37. package/dist/channels/secret.js +16 -0
  38. package/dist/channels/slack/config-api.d.ts +35 -3
  39. package/dist/channels/slack/config-api.js +51 -9
  40. package/dist/channels/slack/manifest.js +5 -1
  41. package/dist/channels/slack/onboard.d.ts +5 -5
  42. package/dist/channels/slack/onboard.js +41 -20
  43. package/dist/channels/slack/register-webhook.d.ts +3 -2
  44. package/dist/channels/slack/register-webhook.js +34 -14
  45. package/dist/channels/slack/scaffold/channel.ts +3 -10
  46. package/dist/channels/slack/scaffold/slack-send.ts +18 -126
  47. package/dist/channels/slack/shared-api.d.ts +10 -0
  48. package/dist/channels/slack/shared-api.js +34 -0
  49. package/dist/channels/slack/slack-api.d.ts +20 -2
  50. package/dist/channels/slack/slack-api.js +81 -22
  51. package/dist/channels/slack/slack.d.ts +0 -10
  52. package/dist/channels/slack/slack.js +60 -99
  53. package/dist/channels/sse.d.ts +4 -0
  54. package/dist/channels/sse.js +66 -0
  55. package/dist/channels/telegram/register-webhook.d.ts +6 -9
  56. package/dist/channels/telegram/register-webhook.js +44 -42
  57. package/dist/channels/telegram/telegram.js +47 -142
  58. package/dist/channels/wait-health.js +7 -4
  59. package/dist/cli/add-feishu.js +3 -10
  60. package/dist/cli/add-slack.js +7 -20
  61. package/dist/cli/commands/add.d.ts +0 -1
  62. package/dist/cli/commands/add.js +25 -37
  63. package/dist/cli/commands/chat.js +6 -12
  64. package/dist/cli/commands/deploy/agentcore.d.ts +2 -0
  65. package/dist/cli/commands/deploy/agentcore.js +178 -0
  66. package/dist/cli/commands/deploy/docker.d.ts +2 -0
  67. package/dist/cli/commands/deploy/docker.js +119 -0
  68. package/dist/cli/commands/deploy/fly.d.ts +2 -0
  69. package/dist/cli/commands/deploy/fly.js +131 -0
  70. package/dist/cli/commands/deploy/railway.d.ts +2 -0
  71. package/dist/cli/commands/deploy/railway.js +71 -0
  72. package/dist/cli/commands/deploy/shared.d.ts +114 -0
  73. package/dist/cli/commands/deploy/shared.js +124 -0
  74. package/dist/cli/commands/deploy.d.ts +17 -49
  75. package/dist/cli/commands/deploy.js +39 -618
  76. package/dist/cli/commands/dev.js +17 -46
  77. package/dist/cli/commands/fire.js +6 -12
  78. package/dist/cli/commands/info.js +2 -1
  79. package/dist/cli/commands/invoke.js +4 -11
  80. package/dist/cli/commands/schedule.js +1 -1
  81. package/dist/cli/commands/start.js +17 -46
  82. package/dist/cli/commands/tool.js +3 -8
  83. package/dist/cli/kernel.d.ts +0 -2
  84. package/dist/cli/kernel.js +0 -2
  85. package/dist/cli/program.js +7 -12
  86. package/dist/cli/serve.d.ts +36 -19
  87. package/dist/cli/serve.js +91 -7
  88. package/dist/cli/shared.d.ts +13 -18
  89. package/dist/cli/shared.js +20 -4
  90. package/dist/deploy/agentcore/forwarder.js +250 -0
  91. package/dist/deploy/agentcore/plan.d.ts +23 -2
  92. package/dist/deploy/agentcore/plan.js +29 -244
  93. package/dist/deploy/agentcore/run.d.ts +4 -20
  94. package/dist/deploy/agentcore/run.js +22 -7
  95. package/dist/deploy/channel-ingress.js +1 -1
  96. package/dist/deploy/docker/run.d.ts +17 -3
  97. package/dist/deploy/docker/run.js +30 -8
  98. package/dist/deploy/fly/plan.js +7 -0
  99. package/dist/deploy/fly/run.d.ts +27 -0
  100. package/dist/deploy/fly/run.js +102 -20
  101. package/dist/deploy/hosts.d.ts +5 -0
  102. package/dist/deploy/hosts.js +4 -0
  103. package/dist/deploy/preflight.js +3 -3
  104. package/dist/deploy/railway/plan.d.ts +5 -0
  105. package/dist/deploy/railway/plan.js +7 -0
  106. package/dist/deploy/railway/run.d.ts +2 -1
  107. package/dist/deploy/railway/run.js +5 -4
  108. package/dist/deploy/secrets.js +0 -17
  109. package/dist/engines/pi/agent-session-factory.d.ts +37 -17
  110. package/dist/engines/pi/agent-session-factory.js +109 -85
  111. package/dist/engines/pi/config.d.ts +1 -1
  112. package/dist/engines/pi/create.d.ts +22 -39
  113. package/dist/engines/pi/create.js +58 -73
  114. package/dist/engines/pi/definition.js +8 -8
  115. package/dist/engines/pi/invoke-session.js +13 -30
  116. package/dist/engines/pi/open.d.ts +2 -2
  117. package/dist/engines/pi/open.js +31 -41
  118. package/dist/engines/pi/retry-event.d.ts +6 -0
  119. package/dist/engines/pi/retry-event.js +15 -0
  120. package/dist/engines/pi/session-builder.js +26 -113
  121. package/dist/engines/pi/session-control.d.ts +10 -18
  122. package/dist/engines/pi/session-control.js +47 -81
  123. package/dist/engines/pi/session-settings.d.ts +1 -1
  124. package/dist/engines/pi/session-settings.js +1 -1
  125. package/dist/engines/pi/session-store.d.ts +12 -17
  126. package/dist/engines/pi/session-store.js +18 -40
  127. package/dist/engines/pi/tool-context.d.ts +3 -3
  128. package/dist/engines/pi/tool.d.ts +6 -9
  129. package/dist/engines/pi/tool.js +1 -0
  130. package/dist/feishu.d.ts +1 -0
  131. package/dist/feishu.js +1 -0
  132. package/dist/lark.d.ts +1 -0
  133. package/dist/lark.js +1 -0
  134. package/dist/loader.d.ts +2 -0
  135. package/dist/loader.js +5 -0
  136. package/dist/log.d.ts +9 -17
  137. package/dist/log.js +25 -30
  138. package/dist/paths.d.ts +7 -3
  139. package/dist/paths.js +17 -4
  140. package/dist/scaffold/add-channel.d.ts +6 -1
  141. package/dist/scaffold/add-channel.js +48 -65
  142. package/dist/schedule/wake-alarm.d.ts +1 -12
  143. package/dist/schedule/wake-alarm.js +2 -3
  144. package/dist/service.d.ts +23 -22
  145. package/dist/service.js +7 -73
  146. package/dist/session-remote.d.ts +5 -5
  147. package/dist/session-remote.js +25 -28
  148. package/dist/session.d.ts +1 -1
  149. package/dist/slack.d.ts +2 -0
  150. package/dist/slack.js +1 -0
  151. package/dist/tunnel.d.ts +16 -6
  152. package/dist/tunnel.js +53 -12
  153. package/package.json +5 -4
  154. package/dist/channels/slack/bot-auth.d.ts +0 -15
  155. package/dist/channels/slack/bot-auth.js +0 -135
@@ -0,0 +1,124 @@
1
+ /**
2
+ * What every host's deploy command shares: the context the dispatcher hands a host, the artifact
3
+ * writer with its ownership rule, and the `--run` credential carry. Host facts live in
4
+ * `cli/commands/deploy/<host>.ts`; this file holds nothing that names one.
5
+ */
6
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
7
+ import { dirname, join } from "node:path";
8
+ import { registerFeishuWebhook } from "../../../channels/feishu/register-webhook.js";
9
+ import { DEPLOY_REGISTRATION_ATTEMPTS } from "../../../channels/registration.js";
10
+ import { registerSlackWebhook } from "../../../channels/slack/register-webhook.js";
11
+ import { registerTelegramWebhook } from "../../../channels/telegram/register-webhook.js";
12
+ import { isGeneratedDockerfile, isGeneratedDockerignore } from "../../../deploy/container.js";
13
+ import { assembleSecrets } from "../../../deploy/secrets.js";
14
+ import { exists, resolveStateRoot } from "../../../paths.js";
15
+ import { failStartup } from "../../fail.js";
16
+ /** The registrars every host driver gets. One wiring: a channel's credentials are the channel's, not
17
+ * the host's, so which of them can run end-to-end never varies by deployment target.
18
+ *
19
+ * All three get {@link DEPLOY_REGISTRATION_ATTEMPTS} rather than the default: a host CLI returns
20
+ * before the deployment answers, and a registration that gives up first GATES the deploy — reporting
21
+ * a working deployment as one to re-run. `dev --tunnel` keeps the shorter default; it is a resident
22
+ * process whose URL is live when it is printed, as does `deploy docker --run` — it reuses that same
23
+ * announcer, having already health-probed the container and waited for the Quick Tunnel URL.
24
+ *
25
+ * Accepted cost: pointChannelsAt registers serially, so a deployment whose channels are ALL
26
+ * unreachable spends the budget once per channel (3 x 180s) before it gates. Registering in parallel
27
+ * would not shorten a single failing channel, and the failing case is the one nobody is waiting on. */
28
+ export function registrarsFor(agentDir) {
29
+ const attempts = DEPLOY_REGISTRATION_ATTEMPTS;
30
+ return {
31
+ telegram: (baseUrl) => registerTelegramWebhook(baseUrl, { attempts }),
32
+ slack: (baseUrl) => registerSlackWebhook(baseUrl, { stateRoot: resolveStateRoot(agentDir), attempts }),
33
+ feishu: (baseUrl, kind) => registerFeishuWebhook(baseUrl, kind, { attempts }),
34
+ };
35
+ }
36
+ /**
37
+ * The `--run` credential carry, for every host: the local model credential (an env key, or the whole
38
+ * auth.json as a `FASTAGENT_AUTH_SEED`) plus channel secrets. Four drivers assembled this identically.
39
+ */
40
+ export async function carryCredentials(params) {
41
+ const { modelAuth, modelKeyInDefinition, authPath, channels, extraSecrets } = params;
42
+ return assembleSecrets({
43
+ modelAuth,
44
+ modelKeyInDefinition,
45
+ authFile: (await exists(authPath)) ? await readFile(authPath) : undefined,
46
+ channels,
47
+ extraSecrets,
48
+ env: process.env,
49
+ });
50
+ }
51
+ /** Gate a `--run` that has no model credential to carry. Its remediation is `fastagent login`, which
52
+ * is why it is separate from `missingSecrets` (a `.env` fix) rather than folded into it. Docker states
53
+ * the same gate inside its driver, where it belongs after the daemon check. */
54
+ export function gateOnModelCredential(needsModelCredential) {
55
+ if (!needsModelCredential)
56
+ return;
57
+ failStartup(new Error(`deploy stopped: no model credential — run \`fastagent login\`, or set a provider API key in .env, then re-run`));
58
+ }
59
+ /**
60
+ * Write each generated artifact under `target`, under ONE ownership rule: **deploy only ever overwrites
61
+ * its own output.** Each generated file opens with a marker, so a file on disk is either OURS (a previous
62
+ * `deploy` wrote it) or the author's — and `--force` means "my generated artifact is authoritative",
63
+ * which never licenses clobbering a file we did not write. To hand a path back to fastagent, delete it.
64
+ *
65
+ * That single rule replaced a second mechanism (a per-host list of paths exempt from `--force`), which
66
+ * only described one shape: with the agent inside the workspace, the root `.dockerignore` is the
67
+ * WORKSPACE's file and was listed; with the agent flat, the list was empty — so `--force` would have
68
+ * overwritten a hand-written root `Dockerfile` in a repository `init --flat` had explicitly adopted.
69
+ * Ownership is a property of the file, not of where the agent sits.
70
+ *
71
+ * A KEPT file of OURS that no longer matches what deploy would generate now (config/channel/lockfile/
72
+ * version drift — or the author's edits, which we cannot tell apart) is flagged stale; `--force`
73
+ * regenerates that one.
74
+ *
75
+ * Exported for its own test — this is a four-branch state machine over (exists, ours, force) that used
76
+ * to be proven by spawning the CLI eight times, which is command LOGIC re-run through a subprocess
77
+ * (see vitest.config.ts) and the suite's slowest test.
78
+ */
79
+ export async function writeArtifacts(target, artifacts, options) {
80
+ for (const a of artifacts) {
81
+ const abs = join(target, a.path);
82
+ // Pure build output, not operator-owned configuration. It must track the generated template/runbook.
83
+ if (options.alwaysWrite?.includes(a.path)) {
84
+ await mkdir(dirname(abs), { recursive: true });
85
+ await writeFile(abs, a.content);
86
+ console.error(`[fastagent] wrote ${a.path}`);
87
+ continue;
88
+ }
89
+ const existing = (await exists(abs)) ? await readFile(abs, "utf8") : undefined;
90
+ const ours = existing !== undefined && isOurArtifact(a.path, existing, options.isOurs);
91
+ if (existing !== undefined && !ours) {
92
+ // Only the `.dockerignore` has content checks in preflight — pointing at "the preflight warnings"
93
+ // for the other kinds would send the reader looking for output that is never printed.
94
+ console.error(`[fastagent] kept ${a.path} — not generated by fastagent, so --force does not touch it ` +
95
+ `(delete it to let deploy own the path)` +
96
+ (a.path.endsWith(".dockerignore")
97
+ ? `; see the preflight warnings for what it must exclude`
98
+ : a.path.endsWith("Dockerfile")
99
+ ? `; deploy still assumes it listens on $PORT and runs \`fastagent start /app\``
100
+ : ``));
101
+ continue;
102
+ }
103
+ if (existing !== undefined && !options.force) {
104
+ console.error(existing !== a.content
105
+ ? `[fastagent] kept ${a.path} — it no longer matches what deploy would generate (config changed, or ` +
106
+ `you edited it); pass --force to regenerate.`
107
+ : `[fastagent] kept ${a.path} (unchanged)`);
108
+ continue;
109
+ }
110
+ await mkdir(dirname(abs), { recursive: true }); // artifacts live under fastagent/
111
+ await writeFile(abs, a.content);
112
+ console.error(`[fastagent] wrote ${a.path}`);
113
+ }
114
+ }
115
+ /** Did fastagent generate the file at `path`? The container's two artifacts are every host's; the
116
+ * rest is the host's own answer. A kind neither names is permanently classified as the author's,
117
+ * which silently turns `--force` into a no-op for that file. */
118
+ function isOurArtifact(path, content, host) {
119
+ if (path.endsWith("Dockerfile"))
120
+ return isGeneratedDockerfile(content);
121
+ if (path.endsWith(".dockerignore"))
122
+ return isGeneratedDockerignore(content);
123
+ return host(path, content);
124
+ }
@@ -1,25 +1,21 @@
1
- /** The deploy targets, as a value: {@link HOST_ONLY_FLAGS} is checked against this list by a test, and
2
- * a type alone cannot be enumerated at runtime. NOT the only copy `cli/program.ts` repeats it as the
3
- * `<host>` argument's `choices`, because that file may not import a command module at load time (its
4
- * per-command imports are lazy). Adding a host means editing both; the type there rides in on a
5
- * `import type`, which costs nothing at runtime. */
6
- export declare const DEPLOY_HOSTS: readonly ["docker", "fly", "railway", "agentcore"];
7
- export type DeployHost = (typeof DEPLOY_HOSTS)[number];
8
- export interface DeployOptions {
9
- run?: boolean;
10
- tunnel?: boolean;
11
- force?: boolean;
12
- stop?: boolean;
13
- /** false `--no-scale-to-zero`. */
14
- scaleToZero?: boolean;
15
- intoLinked?: boolean;
16
- model?: string;
17
- authPath?: string;
18
- /** false ⇔ `--no-input`. */
19
- input?: boolean;
20
- }
1
+ /**
2
+ * `fastagent deploy <host> [dir]`: generate host artifacts from the resolved definition and print an
3
+ * ordered deploy runbook. Host-scoped (`docker` | `fly` | `railway` the extension seam). It does NOT
4
+ * run the host CLI by default: fastagent owns the definition-aware artifacts and precise runbook;
5
+ * Docker may opt into a generated ephemeral tunnel, while durable ingress stays operator-owned. The pre-flight
6
+ * (config/model/channels/container facts) is host-neutral; each host's module (`./deploy/<host>.ts`)
7
+ * adds its artifacts, its kept-file semantics, its gates and its `--run` drive over the neutral
8
+ * `deploy/<host>/` plan + driver. Read-only on the definition; the only writes are generated
9
+ * artifacts (never clobbered without --force). `--run` drives the target CLI instead of printing.
10
+ */
11
+ import type { DeployHost } from "../../deploy/hosts.ts";
12
+ import { type DeployOptions, type HostDeploy, writeArtifacts } from "./deploy/shared.ts";
13
+ export { writeArtifacts };
14
+ /** Every host, by the name the CLI takes. Typed over {@link DeployHost} so a host added to the list
15
+ * without a module here fails to compile. */
16
+ export declare const HOSTS: Record<DeployHost, HostDeploy>;
21
17
  /** A flag exactly one host honours, and what the OTHERS do instead. `instead` is exhaustive over the
22
- * non-owners, so a host added to {@link DEPLOY_HOSTS} cannot silently lose its line. */
18
+ * non-owners, so a host added to `DEPLOY_HOSTS` cannot silently lose its line. */
23
19
  interface HostOnlyFlag<Owner extends DeployHost> {
24
20
  flag: string;
25
21
  owner: Owner;
@@ -43,31 +39,3 @@ export declare const HOST_ONLY_FLAGS: (HostOnlyFlag<"fly"> | HostOnlyFlag<"railw
43
39
  * disagree about the spelling of a host name. */
44
40
  export declare function warnHostOnlyFlags(host: DeployHost, opts: DeployOptions): void;
45
41
  export declare function runDeploy(host: DeployHost, dirArg: string, opts: DeployOptions): Promise<void>;
46
- /**
47
- * Write each generated artifact under `target`, under ONE ownership rule: **deploy only ever overwrites
48
- * its own output.** Each generated file opens with a marker, so a file on disk is either OURS (a previous
49
- * `deploy` wrote it) or the author's — and `--force` means "my generated artifact is authoritative",
50
- * which never licenses clobbering a file we did not write. To hand a path back to fastagent, delete it.
51
- *
52
- * That single rule replaced a second mechanism (a per-host list of paths exempt from `--force`), which
53
- * only described one shape: with the agent inside the workspace, the root `.dockerignore` is the
54
- * WORKSPACE's file and was listed; with the agent flat, the list was empty — so `--force` would have
55
- * overwritten a hand-written root `Dockerfile` in a repository `init --flat` had explicitly adopted.
56
- * Ownership is a property of the file, not of where the agent sits.
57
- *
58
- * A KEPT file of OURS that no longer matches what deploy would generate now (config/channel/lockfile/
59
- * version drift — or the author's edits, which we cannot tell apart) is flagged stale; `--force`
60
- * regenerates that one.
61
- *
62
- * Exported for its own test — this is a four-branch state machine over (exists, ours, force) that used
63
- * to be proven by spawning the CLI eight times, which is command LOGIC re-run through a subprocess
64
- * (see vitest.config.ts) and the suite's slowest test.
65
- */
66
- export declare function writeArtifacts(target: string, artifacts: {
67
- path: string;
68
- content: string;
69
- }[], options: {
70
- force: boolean;
71
- alwaysWrite?: string[];
72
- }): Promise<void>;
73
- export {};