@fastagent-sh/fastagent 0.29.0 → 0.30.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 (312) hide show
  1. package/README.md +9 -4
  2. package/dist/atomic-write.d.ts +4 -5
  3. package/dist/atomic-write.js +4 -5
  4. package/dist/authoring.d.ts +32 -15
  5. package/dist/authoring.js +147 -127
  6. package/dist/channels/agentcore-protocol.d.ts +8 -3
  7. package/dist/channels/agentcore-protocol.js +3 -1
  8. package/dist/channels/agentcore-service.d.ts +1 -0
  9. package/dist/channels/agentcore-service.js +14 -4
  10. package/dist/channels/agentcore.d.ts +9 -0
  11. package/dist/channels/agentcore.js +29 -4
  12. package/dist/channels/context.d.ts +2 -0
  13. package/dist/channels/context.js +5 -1
  14. package/dist/channels/feishu/feishu-api.d.ts +2 -1
  15. package/dist/channels/feishu/feishu.d.ts +0 -3
  16. package/dist/channels/feishu/feishu.js +10 -10
  17. package/dist/channels/feishu/register-app.js +3 -5
  18. package/dist/channels/feishu/scaffold/channel.ts +32 -34
  19. package/dist/channels/feishu/scaffold/feishu-send.ts +5 -5
  20. package/dist/channels/feishu/scaffold/feishu-threads.ts +3 -3
  21. package/dist/channels/feishu/setup-mode.d.ts +2 -12
  22. package/dist/channels/feishu/setup-mode.js +2 -22
  23. package/dist/channels/feishu/setup.d.ts +12 -0
  24. package/dist/channels/feishu/setup.js +197 -0
  25. package/dist/channels/kit/abortable.d.ts +8 -0
  26. package/dist/channels/kit/abortable.js +22 -0
  27. package/dist/channels/lark/lark.d.ts +0 -3
  28. package/dist/channels/lark/lark.js +0 -5
  29. package/dist/channels/lark/scaffold/channel.ts +33 -35
  30. package/dist/channels/lark/scaffold/lark-send.ts +5 -5
  31. package/dist/channels/lark/scaffold/lark-threads.ts +3 -3
  32. package/dist/channels/lark/setup.d.ts +9 -0
  33. package/dist/channels/lark/setup.js +57 -0
  34. package/dist/channels/setup.d.ts +112 -0
  35. package/dist/channels/setup.js +31 -0
  36. package/dist/channels/slack/history.js +1 -1
  37. package/dist/channels/slack/manifest.d.ts +17 -7
  38. package/dist/channels/slack/manifest.js +12 -16
  39. package/dist/channels/slack/scaffold/channel.ts +44 -30
  40. package/dist/channels/slack/scaffold/slack-send.ts +8 -8
  41. package/dist/channels/slack/scaffold/slack-threads.ts +4 -4
  42. package/dist/channels/slack/setup.d.ts +7 -0
  43. package/dist/channels/slack/setup.js +119 -0
  44. package/dist/channels/slack/slack-api.d.ts +2 -0
  45. package/dist/channels/slack/slack-api.js +4 -0
  46. package/dist/channels/slack/slack.d.ts +21 -2
  47. package/dist/channels/slack/slack.js +398 -338
  48. package/dist/channels/slack/socket.d.ts +57 -0
  49. package/dist/channels/slack/socket.js +305 -0
  50. package/dist/channels/telegram/polling.d.ts +27 -0
  51. package/dist/channels/telegram/polling.js +105 -0
  52. package/dist/channels/telegram/scaffold/channel.ts +52 -32
  53. package/dist/channels/telegram/scaffold/telegram-send.ts +9 -9
  54. package/dist/channels/telegram/setup.d.ts +2 -0
  55. package/dist/channels/telegram/setup.js +42 -0
  56. package/dist/channels/telegram/telegram-api.d.ts +27 -1
  57. package/dist/channels/telegram/telegram-api.js +7 -6
  58. package/dist/channels/telegram/telegram.d.ts +11 -3
  59. package/dist/channels/telegram/telegram.js +184 -157
  60. package/dist/channels/webhook-evidence.d.ts +11 -0
  61. package/dist/channels/webhook-evidence.js +71 -0
  62. package/dist/channels/webhooks.d.ts +37 -0
  63. package/dist/channels/webhooks.js +70 -0
  64. package/dist/child-env.d.ts +16 -0
  65. package/dist/child-env.js +30 -0
  66. package/dist/cli/box-login.js +4 -1
  67. package/dist/cli/channel-app.d.ts +3 -0
  68. package/dist/cli/channel-app.js +35 -0
  69. package/dist/cli/channel-setup.d.ts +38 -0
  70. package/dist/cli/channel-setup.js +195 -0
  71. package/dist/cli/commands/add.d.ts +6 -14
  72. package/dist/cli/commands/add.js +45 -303
  73. package/dist/cli/commands/auth.js +8 -2
  74. package/dist/cli/commands/build.d.ts +5 -0
  75. package/dist/cli/commands/build.js +16 -0
  76. package/dist/cli/commands/channels.d.ts +19 -0
  77. package/dist/cli/commands/channels.js +230 -0
  78. package/dist/cli/commands/content.d.ts +7 -3
  79. package/dist/cli/commands/content.js +16 -10
  80. package/dist/cli/commands/deploy/agentcore.js +55 -23
  81. package/dist/cli/commands/deploy/channel-apps.d.ts +17 -0
  82. package/dist/cli/commands/deploy/channel-apps.js +30 -0
  83. package/dist/cli/commands/deploy/docker.js +32 -65
  84. package/dist/cli/commands/deploy/fly.js +28 -12
  85. package/dist/cli/commands/deploy/railway.js +38 -13
  86. package/dist/cli/commands/deploy/secrets-step.d.ts +19 -0
  87. package/dist/cli/commands/deploy/secrets-step.js +66 -0
  88. package/dist/cli/commands/deploy/shared.d.ts +16 -5
  89. package/dist/cli/commands/deploy/shared.js +25 -8
  90. package/dist/cli/commands/deploy.js +53 -60
  91. package/dist/cli/commands/dev.d.ts +2 -0
  92. package/dist/cli/commands/dev.js +15 -3
  93. package/dist/cli/commands/env.js +1 -1
  94. package/dist/cli/commands/info.d.ts +2 -0
  95. package/dist/cli/commands/info.js +60 -25
  96. package/dist/cli/commands/init.js +3 -1
  97. package/dist/cli/commands/invoke.d.ts +2 -0
  98. package/dist/cli/commands/invoke.js +20 -7
  99. package/dist/cli/commands/login.d.ts +0 -7
  100. package/dist/cli/commands/login.js +22 -10
  101. package/dist/cli/commands/logout.js +1 -1
  102. package/dist/cli/commands/mcp.js +14 -6
  103. package/dist/cli/commands/models.js +3 -2
  104. package/dist/cli/commands/schedules.d.ts +4 -2
  105. package/dist/cli/commands/schedules.js +14 -10
  106. package/dist/cli/commands/secrets.d.ts +14 -0
  107. package/dist/cli/commands/secrets.js +213 -0
  108. package/dist/cli/commands/start.d.ts +14 -14
  109. package/dist/cli/commands/start.js +46 -60
  110. package/dist/cli/content-view.d.ts +4 -6
  111. package/dist/cli/content-view.js +5 -11
  112. package/dist/cli/first-run-channels.d.ts +3 -0
  113. package/dist/cli/first-run-channels.js +63 -0
  114. package/dist/cli/instance.d.ts +41 -0
  115. package/dist/cli/instance.js +155 -0
  116. package/dist/cli/invoke-stream.d.ts +5 -2
  117. package/dist/cli/invoke-stream.js +7 -2
  118. package/dist/cli/kernel.js +3 -0
  119. package/dist/cli/program.js +282 -110
  120. package/dist/cli/serve.d.ts +4 -5
  121. package/dist/cli/serve.js +4 -7
  122. package/dist/cli/shared.d.ts +11 -2
  123. package/dist/cli/shared.js +32 -19
  124. package/dist/cli/ticket.d.ts +7 -0
  125. package/dist/cli/ticket.js +106 -30
  126. package/dist/content/declare.d.ts +31 -37
  127. package/dist/content/declare.js +59 -60
  128. package/dist/content/file.d.ts +23 -12
  129. package/dist/content/file.js +48 -35
  130. package/dist/content/git.d.ts +0 -10
  131. package/dist/content/git.js +5 -39
  132. package/dist/content/resolve.d.ts +18 -22
  133. package/dist/content/resolve.js +32 -66
  134. package/dist/content/source.d.ts +7 -8
  135. package/dist/content/source.js +10 -28
  136. package/dist/credentials-page.d.ts +26 -0
  137. package/dist/credentials-page.js +185 -0
  138. package/dist/declared-secrets.d.ts +10 -3
  139. package/dist/declared-secrets.js +8 -4
  140. package/dist/deploy/agentcore/destroy.d.ts +4 -1
  141. package/dist/deploy/agentcore/destroy.js +25 -1
  142. package/dist/deploy/agentcore/forwarder.js +1 -1
  143. package/dist/deploy/agentcore/plan.d.ts +7 -21
  144. package/dist/deploy/agentcore/plan.js +47 -49
  145. package/dist/deploy/agentcore/run.d.ts +18 -10
  146. package/dist/deploy/agentcore/run.js +93 -70
  147. package/dist/deploy/agentcore/runtime-secrets.d.ts +7 -0
  148. package/dist/deploy/agentcore/runtime-secrets.js +108 -0
  149. package/dist/deploy/agentcore/shell.js +12 -19
  150. package/dist/deploy/agentcore/sigv4.d.ts +7 -0
  151. package/dist/deploy/agentcore/sigv4.js +15 -0
  152. package/dist/deploy/agentcore/slr.d.ts +18 -0
  153. package/dist/deploy/agentcore/slr.js +27 -0
  154. package/dist/deploy/agentcore/store.d.ts +7 -0
  155. package/dist/deploy/agentcore/store.js +115 -0
  156. package/dist/deploy/api.d.ts +14 -14
  157. package/dist/deploy/api.js +26 -24
  158. package/dist/deploy/box-shell.d.ts +3 -1
  159. package/dist/deploy/build-context.d.ts +4 -4
  160. package/dist/deploy/build-context.js +11 -15
  161. package/dist/deploy/channel-ingress.d.ts +35 -9
  162. package/dist/deploy/channel-ingress.js +119 -22
  163. package/dist/deploy/container.d.ts +35 -10
  164. package/dist/deploy/container.js +79 -37
  165. package/dist/deploy/delivered-text.d.ts +13 -0
  166. package/dist/deploy/delivered-text.js +86 -0
  167. package/dist/deploy/docker/plan.d.ts +7 -8
  168. package/dist/deploy/docker/plan.js +31 -52
  169. package/dist/deploy/docker/run.d.ts +5 -43
  170. package/dist/deploy/docker/run.js +9 -84
  171. package/dist/deploy/file-store.d.ts +2 -0
  172. package/dist/deploy/file-store.js +17 -0
  173. package/dist/deploy/fly/plan.d.ts +3 -2
  174. package/dist/deploy/fly/plan.js +20 -9
  175. package/dist/deploy/fly/run.d.ts +18 -8
  176. package/dist/deploy/fly/run.js +24 -42
  177. package/dist/deploy/fly/store.d.ts +12 -0
  178. package/dist/deploy/fly/store.js +83 -0
  179. package/dist/deploy/hosts.d.ts +1 -2
  180. package/dist/deploy/hosts.js +1 -2
  181. package/dist/deploy/preflight.d.ts +18 -5
  182. package/dist/deploy/preflight.js +135 -63
  183. package/dist/deploy/railway/ignore.d.ts +8 -0
  184. package/dist/deploy/railway/ignore.js +57 -0
  185. package/dist/deploy/railway/plan.d.ts +1 -2
  186. package/dist/deploy/railway/plan.js +8 -6
  187. package/dist/deploy/railway/run.d.ts +21 -15
  188. package/dist/deploy/railway/run.js +32 -78
  189. package/dist/deploy/railway/store.d.ts +29 -0
  190. package/dist/deploy/railway/store.js +143 -0
  191. package/dist/deploy/runner.d.ts +5 -2
  192. package/dist/deploy/runner.js +4 -3
  193. package/dist/deploy/secret-store.d.ts +63 -0
  194. package/dist/deploy/secret-store.js +98 -0
  195. package/dist/deploy/secrets.d.ts +29 -46
  196. package/dist/deploy/secrets.js +49 -122
  197. package/dist/deploy/workspace.d.ts +6 -12
  198. package/dist/deploy/workspace.js +18 -94
  199. package/dist/dev-supervisor.js +6 -8
  200. package/dist/environment/declare.js +3 -2
  201. package/dist/environment/mise.d.ts +3 -1
  202. package/dist/environment/mise.js +4 -2
  203. package/dist/feishu.d.ts +1 -1
  204. package/dist/feishu.js +1 -1
  205. package/dist/harnesses/models/catalog.d.ts +1 -0
  206. package/dist/harnesses/models/catalog.js +1 -2
  207. package/dist/harnesses/models/environment.d.ts +7 -2
  208. package/dist/harnesses/models/environment.js +9 -5
  209. package/dist/harnesses/models/host.d.ts +0 -7
  210. package/dist/harnesses/models/host.js +10 -1
  211. package/dist/harnesses/models/login.d.ts +0 -8
  212. package/dist/harnesses/models/login.js +5 -4
  213. package/dist/harnesses/models/models.d.ts +7 -2
  214. package/dist/harnesses/models/models.js +28 -4
  215. package/dist/harnesses/pi-durable/agent.js +59 -38
  216. package/dist/harnesses/pi-durable/build.d.ts +12 -0
  217. package/dist/harnesses/pi-durable/build.js +270 -0
  218. package/dist/harnesses/pi-durable/built.d.ts +24 -0
  219. package/dist/harnesses/pi-durable/built.js +136 -0
  220. package/dist/harnesses/pi-durable/config.d.ts +81 -0
  221. package/dist/harnesses/pi-durable/config.js +266 -0
  222. package/dist/harnesses/pi-durable/define.d.ts +63 -13
  223. package/dist/harnesses/pi-durable/define.js +23 -2
  224. package/dist/harnesses/pi-durable/definition.d.ts +72 -0
  225. package/dist/harnesses/pi-durable/definition.js +143 -0
  226. package/dist/harnesses/pi-durable/events.d.ts +4 -3
  227. package/dist/harnesses/pi-durable/events.js +179 -136
  228. package/dist/harnesses/pi-durable/execution-env.d.ts +17 -0
  229. package/dist/harnesses/pi-durable/execution-env.js +11 -0
  230. package/dist/harnesses/pi-durable/mcp.js +1 -3
  231. package/dist/harnesses/pi-durable/open.d.ts +35 -37
  232. package/dist/harnesses/pi-durable/open.js +91 -153
  233. package/dist/harnesses/pi-durable/reads.d.ts +0 -1
  234. package/dist/harnesses/pi-durable/reads.js +1 -3
  235. package/dist/harnesses/pi-durable/registry.d.ts +4 -6
  236. package/dist/harnesses/pi-durable/registry.js +29 -26
  237. package/dist/harnesses/pi-durable/release.d.ts +2 -2
  238. package/dist/harnesses/pi-durable/release.js +10 -7
  239. package/dist/harnesses/pi-durable/serve.d.ts +91 -15
  240. package/dist/harnesses/pi-durable/serve.js +109 -47
  241. package/dist/harnesses/pi-durable/sessions.js +15 -12
  242. package/dist/harnesses/pi-durable/text-sources.d.ts +30 -0
  243. package/dist/harnesses/pi-durable/text-sources.js +55 -0
  244. package/dist/harnesses/pi-durable/text.d.ts +16 -4
  245. package/dist/harnesses/pi-durable/text.js +115 -59
  246. package/dist/harnesses/pi-durable/wake.js +8 -8
  247. package/dist/http/client.js +9 -3
  248. package/dist/http/contract.d.ts +3 -3
  249. package/dist/http/server.d.ts +1 -1
  250. package/dist/http/server.js +1 -1
  251. package/dist/index.d.ts +8 -5
  252. package/dist/index.js +4 -1
  253. package/dist/instance-name.d.ts +7 -0
  254. package/dist/instance-name.js +26 -0
  255. package/dist/lark.d.ts +1 -1
  256. package/dist/lark.js +1 -1
  257. package/dist/mcp/client.js +11 -2
  258. package/dist/mcp/config.d.ts +70 -18
  259. package/dist/mcp/config.js +136 -53
  260. package/dist/mcp/host.d.ts +5 -2
  261. package/dist/mcp/host.js +14 -6
  262. package/dist/mcp/sign-in.js +2 -2
  263. package/dist/mcp-api.d.ts +14 -0
  264. package/dist/paths.d.ts +22 -8
  265. package/dist/paths.js +44 -11
  266. package/dist/runtime-websocket.d.ts +14 -0
  267. package/dist/runtime-websocket.js +39 -0
  268. package/dist/scaffold/add-channel.d.ts +9 -16
  269. package/dist/scaffold/add-channel.js +13 -83
  270. package/dist/scaffold/templates/env.example +4 -5
  271. package/dist/scaffold/templates/fastagent.config.ts +20 -14
  272. package/dist/scaffold/templates/gitignore +9 -6
  273. package/dist/scaffold/templates.d.ts +6 -2
  274. package/dist/scaffold/templates.js +7 -2
  275. package/dist/scaffold/vendor-skill.js +4 -2
  276. package/dist/service.d.ts +44 -6
  277. package/dist/service.js +110 -10
  278. package/dist/serving-command.d.ts +10 -0
  279. package/dist/serving-command.js +1 -0
  280. package/dist/slack.d.ts +1 -1
  281. package/dist/slack.js +1 -1
  282. package/dist/strip-edges.d.ts +10 -0
  283. package/dist/strip-edges.js +22 -0
  284. package/dist/telegram.d.ts +1 -1
  285. package/dist/telegram.js +1 -1
  286. package/dist/tunnel.d.ts +0 -1
  287. package/dist/tunnel.js +2 -8
  288. package/dist/value-file.d.ts +11 -6
  289. package/dist/value-file.js +21 -9
  290. package/dist/version.d.ts +7 -1
  291. package/dist/version.js +9 -3
  292. package/package.json +6 -5
  293. package/dist/channels/lark/credentials-page.d.ts +0 -25
  294. package/dist/channels/lark/credentials-page.js +0 -206
  295. package/dist/channels/lark/onboard.d.ts +0 -52
  296. package/dist/channels/lark/onboard.js +0 -86
  297. package/dist/channels/slack/config-api.d.ts +0 -69
  298. package/dist/channels/slack/config-api.js +0 -162
  299. package/dist/channels/slack/onboard.d.ts +0 -40
  300. package/dist/channels/slack/onboard.js +0 -136
  301. package/dist/channels/slack/onboarding-state.d.ts +0 -31
  302. package/dist/channels/slack/onboarding-state.js +0 -64
  303. package/dist/channels/slack/register-webhook.d.ts +0 -12
  304. package/dist/channels/slack/register-webhook.js +0 -67
  305. package/dist/channels/slack/setup-server.d.ts +0 -32
  306. package/dist/channels/slack/setup-server.js +0 -246
  307. package/dist/cli/add-feishu.d.ts +0 -41
  308. package/dist/cli/add-feishu.js +0 -391
  309. package/dist/cli/add-slack.d.ts +0 -18
  310. package/dist/cli/add-slack.js +0 -216
  311. package/dist/harnesses/pi-durable/parked.d.ts +0 -18
  312. package/dist/harnesses/pi-durable/parked.js +0 -27
@@ -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 { applyCarriedEnv } from "../../deploy/secrets.js";
15
- import { applyReleaseEnv, installAgentDependencies, parseDeploymentRelease, prepareDeployment, } from "../../deploy/workspace.js";
16
- import { selectAgentEnvironment, resolveSecretsDir, isAgentcoreRuntime, isUnderDir, exists } from "../../paths.js";
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: () => prepareStartWorkspace(dirArg),
43
- assemble: async (prepared) => {
44
- const service = await openPreparedWorkspace(prepared, opts);
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`, a failed install) are the operator's only
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, stateRoot: service.stateRoot, config: service.config });
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: verify it is mounted, apply the release, and point the machinery at the volume.
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 { dir: dirArg };
71
- const storage = process.env.FASTAGENT_STORAGE_DIR;
58
+ return dirArg;
59
+ const storage = process.env[INSTANCE_ROOT_ENV];
72
60
  if (!storage)
73
- throw new Error("FASTAGENT_STORAGE_DIR is required for a deployment");
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
- const dir = await prepareDeployment(resolve(dirArg), root, manifest);
77
- // Defaults, not overrides: an operator who pointed either dir somewhere else meant it, and silently relocating
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
- process.chdir(dir);
89
- return { dir, deployed: { root } };
77
+ return dirArg;
90
78
  }
91
79
  /**
92
- * Stage two — RUN the prepared agent directory: install its dependencies, then open through its own FastAgent install.
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 openPreparedWorkspace(prepared, opts) {
95
- let open = openPreparedStartService;
96
- if (prepared.deployed) {
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 openPreparedWorkspace(await prepareStartWorkspace(dirArg), opts);
88
+ return openPreparedStartService(await prepareStartWorkspace(dirArg), opts);
116
89
  }
117
- /** Internal entry loaded from the agent's installed package after storage initialization. */
90
+ /** Stage two: open the built definition in `dirArg` and serve it. */
118
91
  export async function openPreparedStartService(dirArg, opts) {
119
- const { agentDir, modelSpec } = await enterAgentCommand(dirArg, opts);
120
- const opened = await openServing(agentDir, {
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.definition;
113
+ const { config: effective } = opened;
134
114
  const service = await (isAgentcoreRuntime()
135
115
  ? mountAgentcoreService(opened)
136
- : serveAgent(opened, cliMountOptions(config)));
137
- return { ...service, agent: opened.agent, stateRoot, port: config.http?.port ?? DEFAULT_HTTP_PORT, config };
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 { BoundContent } from "../content/declare.ts";
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
- * thing its resolution has to say, then one for each directory this machine binds that is not here — shared by the
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[], absent?: readonly BoundContent[]): [label: string, value: string][];
7
+ export declare function contentLines(content: readonly ResolvedContent[]): [label: string, value: string][];
@@ -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 `this machine only, bound in ${LOCAL_CONTEXT_FILE}`;
7
- const github = `github ${c.repo}${c.ref ? `@${c.ref}` : ""}`;
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
- * thing its resolution has to say, then one for each directory this machine binds that is not here — shared by the
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, absent = []) {
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,3 @@
1
+ export declare function setUpMissingChannels(agentDir: string, opts?: {
2
+ input?: boolean;
3
+ }): Promise<void>;
@@ -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
- /** The answer as text on `out`, what the tools did and why it failed on `err`. */
6
- export declare function runInvokeStream(events: AsyncIterable<MessageStreamEvent>, out: (text: string) => void, err: (line: string) => void): Promise<number>;
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
- /** The answer as text on `out`, what the tools did and why it failed on `err`. */
35
- export async function runInvokeStream(events, out, err) {
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:
@@ -13,6 +13,9 @@ export function buildProgram(specs, options = {}) {
13
13
  // The exit-code policy: commander throws only for parse-level events — help/version displays carry exitCode 0 (→
14
14
  // 0), everything else it rejects is a usage error (→ 2).
15
15
  program.exitOverride((err) => exit(err.exitCode === 0 ? 0 : 2));
16
+ // commander reads a program option anywhere by default, a subcommand's values included: an `invoke --session <id>`
17
+ // whose id begins with "-v" (base64url, 1 in 4096) printed the version and exited 0. Only before the subcommand.
18
+ program.enablePositionalOptions();
16
19
  program.configureHelp({
17
20
  ...(options.helpWidth !== undefined ? { helpWidth: options.helpWidth } : {}),
18
21
  styleTitle: title,