@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
@@ -4,14 +4,43 @@ import type { CredentialSourceOptions } from "../models/credentials.ts";
4
4
  import { type ModelEnvironment } from "../models/environment.ts";
5
5
  import type { CredentialStore } from "../../sign-in-api.ts";
6
6
  import type { McpOptions } from "../../mcp-api.ts";
7
+ import { type RunsAs } from "../../serving-command.ts";
7
8
  import { type ResolvedContent } from "../../content/resolve.ts";
8
9
  import type { Agent } from "../../agent-api.ts";
9
10
  import { type Service } from "../../service.ts";
10
11
  import type { DurableAgent, Unfinished } from "./agent.ts";
11
- import { type AgentDefinition, type BuiltDefinition } from "./open.ts";
12
+ import { type EffectiveConfig, type InstanceConfig, type InstanceConfigSource } from "./config.ts";
13
+ import { type AgentDefinition } from "./definition.ts";
14
+ import { type BuiltDefinition } from "./open.ts";
12
15
  import { type StorageLocking } from "./storage.ts";
13
16
  export interface OpenServingOptions extends CredentialSourceOptions {
14
17
  mcp?: McpOptions;
18
+ /** The instance's name, over the configuration's. Default: the configuration's, else the definition's as one segment. */
19
+ name?: string;
20
+ /**
21
+ * The values the instance's code, its MCP servers and its model's authentication read by name (`needs`, `${VAR}`,
22
+ * a provider's variable): the one source of them, never this process's environment. A caller that wants its own
23
+ * passes it (`process.env`).
24
+ */
25
+ secrets: Readonly<Record<string, string | undefined>>;
26
+ /**
27
+ * The base environment of the processes the agent starts (`baseEnv(process.env)` is the CLI's): the commands of
28
+ * its declared packages come ahead on its `PATH`, and the declared secrets are added to it. Nothing else of this
29
+ * process's reaches them.
30
+ */
31
+ env: Readonly<Record<string, string>>;
32
+ /**
33
+ * The environment FastAgent's own work for the instance runs in: installing the declared packages, cloning content,
34
+ * finding `git` and `mise`, and where a CLI instance's files are. The CLI gives this process's; an app, its `env`.
35
+ * The instance's secrets are added to it.
36
+ */
37
+ ownEnv: Readonly<Record<string, string | undefined>>;
38
+ /** Who runs the instance: what decides how a channel that names no way receives, and whether its prompt describes a deployment. */
39
+ runsAs: RunsAs;
40
+ /** Whether the model lists are refreshed without the network. Default: `ownEnv`'s `FASTAGENT_OFFLINE` is `1`. */
41
+ offline?: boolean;
42
+ /** What the instance sets over the program's defaults (`fastagent.json`, or an object); none runs on the defaults. */
43
+ config?: InstanceConfigSource;
15
44
  /** What a deployment sets over the definition's defaults (a flag, `FASTAGENT_MODEL`). */
16
45
  model?: string;
17
46
  thinkingLevel?: ModelThinkingLevel;
@@ -25,8 +54,26 @@ export interface OpenServingOptions extends CredentialSourceOptions {
25
54
  storage?: ServingStorage;
26
55
  /** What becomes of the messages an earlier process left unfinished in the storage. Default `"resume"`. */
27
56
  unfinished?: Unfinished;
28
- /** The instance's state root, over `FASTAGENT_STATE_DIR` and the directory's own. */
57
+ /**
58
+ * The instance's directory: its working directory, where its content is cloned, its secrets and, by default, its
59
+ * state are. Default: the definition's own, which is how a source project runs. A built package is read-only and is
60
+ * opened with a directory of its own.
61
+ */
62
+ workdir?: string;
63
+ /**
64
+ * The directory whose `.secrets/` (values, model credentials, MCP grants) and default state
65
+ * root the instance reads. Default: the working directory. Temporary: secrets and content become inputs of their own.
66
+ */
67
+ projectDir?: string;
68
+ /** The instance's state root, over `FASTAGENT_STATE_DIR` and the project directory's own. */
29
69
  stateRoot?: string;
70
+ /**
71
+ * Where the instance keeps its model credentials and MCP grants when it is given no store: `"secrets"`, the project's
72
+ * `.secrets/` over the machine's own credentials and as `FASTAGENT_AUTH_PATH` and `FASTAGENT_SECRETS_DIR` place them
73
+ * (the CLI's), or `"state"`, `auth.json` and `mcp-auth.json` in the state root and nothing else (an app's).
74
+ * Default `"secrets"`.
75
+ */
76
+ keeps?: "secrets" | "state";
30
77
  /** Whether a clock fires the instance's wake-ups now (`assembleAgent`'s `wakeTicking`). Default always. */
31
78
  wakeTicking?: () => boolean;
32
79
  }
@@ -39,11 +86,20 @@ type ServingStorage = {
39
86
  export interface OpenedServing {
40
87
  agent: DurableAgent;
41
88
  definition: AgentDefinition;
89
+ /** The instance's name: what `info().name` reports. */
90
+ name: string;
42
91
  code: BuiltDefinition;
92
+ /** The configuration this instance opened with: the program's defaults and the instance's over them. */
93
+ config: EffectiveConfig;
94
+ /** The secrets it was given that hold a value: what its code was built with, and its webhooks are pointed with. */
95
+ secrets: Readonly<Record<string, string>>;
43
96
  models: ModelEnvironment;
44
97
  /** What the agent works on, resolved for this instance. */
45
98
  content: readonly ResolvedContent[];
99
+ /** The project directory: whose `.secrets/` the instance reads. */
46
100
  agentDir: string;
101
+ /** The agent's working directory. */
102
+ workdir: string;
47
103
  /** Where the instance's state is: its storage, its channels' and schedules' state, its wake-ups. */
48
104
  stateRoot: string;
49
105
  /** The definition's channels and schedules, as `serveAgent` serves them: `serveAgent(opened)`. */
@@ -55,7 +111,7 @@ export interface OpenedServing {
55
111
  * instance's state outside a serve without losing a write to a serve's own.
56
112
  */
57
113
  export declare function holdingInstance<T>(stateRoot: string, work: () => T): Promise<T>;
58
- export declare function openServing(directory: string, options?: OpenServingOptions): Promise<OpenedServing>;
114
+ export declare function openServing(definition: AgentDefinition, options: OpenServingOptions): Promise<OpenedServing>;
59
115
  /** An agent opened in this process (SPEC.md §8): the Agent API, and how it is served and operated. */
60
116
  export interface LocalAgent extends Agent {
61
117
  /**
@@ -72,23 +128,43 @@ export interface ServeAgentOptions {
72
128
  /** The keys a Caller of the Agent API may present (SPEC.md §9.1). */
73
129
  apiKeys?: readonly string[];
74
130
  }
75
- export interface OpenAgentOptions {
131
+ /** The instance root, the agent's working directory with its state in `.state/`; or the two apart (SPEC.md §8). */
132
+ export type InstanceLocation = {
133
+ root: string;
134
+ } | {
135
+ stateDir: string;
136
+ workdir: string;
137
+ };
138
+ export type OpenAgentOptions<Settings = unknown> = InstanceLocation & {
139
+ /** The instance configuration, over the program's defaults: an object, or the absolute path of a `fastagent.json`. */
140
+ config?: InstanceConfig<Settings> | string;
141
+ /** The instance's name, over `config`'s: one path segment. Default: `config`'s, else the definition's as one. */
142
+ name?: string;
143
+ /**
144
+ * The values the agent's code (`needs`), its MCP servers (`${VAR}`) and its model's authentication read by name. The
145
+ * only source of them: nothing is read from the process's environment or from a file, so pass what the agent needs
146
+ * (`process.env` is a choice an app can make).
147
+ */
148
+ secrets?: Readonly<Record<string, string | undefined>>;
149
+ /**
150
+ * The base environment of the processes the agent starts (its commands, stdio MCP servers, skill scripts). Default:
151
+ * empty; `baseEnv(process.env)` is an app's own. The commands of the agent's declared packages come ahead on its
152
+ * `PATH`, and the secrets the definition declares are added; nothing else of the host's reaches them.
153
+ */
154
+ env?: Readonly<Record<string, string>>;
76
155
  /** Per-instance MCP grants and interpolation values; no global credential discovery. */
77
156
  mcp?: McpOptions;
78
157
  /** `"provider/modelId"`, over the definition's: what a session that names none answers with. */
79
158
  model?: string;
80
- /** Where provider credentials are kept, instead of the agent's own `.secrets/auth.json` over the machine's. */
159
+ /** Where provider credentials are kept, instead of the state directory's `auth.json`. */
81
160
  credentials?: CredentialStore;
82
- /**
83
- * Where this instance keeps its sessions, its channels' and schedules' state and its model lists, instead of
84
- * `FASTAGENT_STATE_DIR` or the agent's `.state/`: a host's own instance of an agent beside `fastagent dev`'s.
85
- */
86
- stateDir?: string;
87
- }
161
+ /** Refresh the model lists without the network: each is the one last kept, or pi-ai's own. Default: false. */
162
+ offline?: boolean;
163
+ };
88
164
  /**
89
- * Open the agent directory `dir` the way `dev` and `start` do before they serve: its definition, its code built with
90
- * the secrets it declares, its environment, its content and the instance's storage, which one process holds at a time.
91
- * Nothing reaches the agent until `serve`.
165
+ * Open one instance of `definition`, the default export of an agent's package, the way `dev` and `start` do before they
166
+ * serve: its code built with the secrets it declares, its environment, its content and the instance's storage, which
167
+ * one process holds at a time. Nothing reaches the agent until `serve`.
92
168
  */
93
- export declare function openAgent(dir: string, options?: OpenAgentOptions): Promise<LocalAgent>;
169
+ export declare function openAgent<Settings = unknown>(definition: AgentDefinition<Settings>, options: OpenAgentOptions<Settings>): Promise<LocalAgent>;
94
170
  export {};
@@ -1,27 +1,33 @@
1
1
  /**
2
- * An agent package opened: its definition prepared (the registry generated, the secrets manifest written), its code
3
- * built with its secrets, its model environment, its storage, and the Agent over them. `openAgent` is how an app opens
4
- * one (SPEC.md §8); `dev`, `start`, AgentCore, `invoke` and `schedules run` open it through `openServing`, which
5
- * also takes where the Agent keeps its sessions and what becomes of an earlier process's messages.
2
+ * A definition opened: its code built with its secrets, its model environment, its storage, and the Agent over them.
3
+ * `openAgent` is how an app opens one (SPEC.md §8); `dev`, `start`, AgentCore, `invoke` and `schedules run` open it
4
+ * through `openServing`, which also takes where the Agent keeps its sessions and what becomes of an earlier process's
5
+ * messages.
6
6
  */
7
- import { join } from "node:path";
7
+ import { dirname, isAbsolute, join } from "node:path";
8
8
  import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
9
9
  import { MemoryStorage } from "@earendil-works/pi-durable";
10
10
  import { modelEnvironment } from "../models/environment.js";
11
11
  import { piCredentials } from "../models/host.js";
12
12
  import { openMcpClients } from "../../mcp/client.js";
13
- import { resolveMcpServers } from "../../mcp/config.js";
14
- import { mcpAuthorization } from "../../mcp/host.js";
13
+ import { declareMcp, resolveMcpServers } from "../../mcp/config.js";
14
+ import { mcpAuthorization, mcpAuthorizationInState } from "../../mcp/host.js";
15
+ import { NOT_HOSTED } from "../../serving-command.js";
15
16
  import { mcpTools } from "./mcp.js";
16
17
  import { loadContent } from "../../content/file.js";
17
- import { absentNotice, cloneContent, contentAbsentHere, resolveContent, } from "../../content/resolve.js";
18
- import { agentValues } from "../../value-file.js";
18
+ import { cloneContent, resolveContent } from "../../content/resolve.js";
19
+ import { processEnvironment } from "../../child-env.js";
20
+ import { definedValues } from "../../declared-secrets.js";
19
21
  import { prepareEnvironment } from "../../environment/mise.js";
20
22
  import { log } from "../../log.js";
21
- import { resolveOverridePath, resolveStateRoot } from "../../paths.js";
23
+ import { STATE_DIRNAME, resolveStateRoot } from "../../paths.js";
22
24
  import { serveAgent } from "../../service.js";
23
- import { buildDefinition, assembleAgent, prepareDefinition, } from "./open.js";
25
+ import { readInstanceConfigFile, resolveConfig, } from "./config.js";
26
+ import { assertDefinition } from "./definition.js";
27
+ import { assembleAgent, buildDefinition } from "./open.js";
24
28
  import { openLockedStorage } from "./storage.js";
29
+ import { openText } from "./text.js";
30
+ import { instanceName } from "../../instance-name.js";
25
31
  /** Who opens the instance's storage, for the refusal of a second opener. */
26
32
  const INSTANCE_HOLDERS = "another `fastagent dev`, `start` or `schedules` command of this agent (or of another agent with the same state root)";
27
33
  /**
@@ -30,10 +36,11 @@ const INSTANCE_HOLDERS = "another `fastagent dev`, `start` or `schedules` comman
30
36
  * up to date in place where git can do so without touching the agent's work, first; then resolved again as what is now
31
37
  * on disk.
32
38
  */
33
- async function contentForThisRun(dir, env) {
34
- const declaration = loadContent(dir);
35
- for (const entry of resolveContent(dir, declaration)) {
36
- if (entry.kind !== "github" || !entry.clone)
39
+ async function contentForThisRun(dir, instance, workdir, env) {
40
+ const declared = loadContent(dir, instance);
41
+ const places = { dir, workdir };
42
+ for (const entry of resolveContent(declared, places)) {
43
+ if (entry.kind !== "github")
37
44
  continue;
38
45
  const done = await cloneContent(entry, env);
39
46
  if (done.outcome === "kept") {
@@ -44,9 +51,7 @@ async function contentForThisRun(dir, env) {
44
51
  log.info(`[fastagent] github ${entry.repo}${entry.ref ? ` at ${entry.ref}` : ""}: ${said} in ${entry.location}`);
45
52
  }
46
53
  }
47
- for (const absent of contentAbsentHere(declaration))
48
- log.warn(`[fastagent] content ${absentNotice(absent)}`);
49
- return resolveContent(dir, declaration);
54
+ return resolveContent(declared, places);
50
55
  }
51
56
  /** The instance's database, under its state root. */
52
57
  const instanceStorageFile = (stateRoot) => join(stateRoot, "agent.sqlite");
@@ -70,35 +75,57 @@ function openStorage(stateRoot, storage) {
70
75
  return openLockedStorage(storage.file, "posix", storage.holders);
71
76
  return openLockedStorage(instanceStorageFile(stateRoot), storage.instance, INSTANCE_HOLDERS);
72
77
  }
73
- export async function openServing(directory, options = {}) {
74
- const definition = await prepareDefinition(directory);
78
+ export async function openServing(definition, options) {
75
79
  const { dir } = definition;
76
- // The agent's environment is ONE value every reader below is given, and this process's is never written: a process
80
+ const workdir = options.workdir ?? dir;
81
+ const projectDir = options.projectDir ?? workdir;
82
+ const config = resolveConfig(definition, options.config);
83
+ const name = instanceName(definition.name, options.name ?? config.name);
84
+ const text = openText(dir, options.config);
85
+ const mcpServers = declareMcp(dir, options.config);
86
+ // The instance's values are ONE input every reader below is given, and this process's is never written: a process
77
87
  // may run several agents, each with its own values and packages.
78
- const values = agentValues(dir);
79
- const code = buildDefinition(definition, { ...process.env, ...values });
80
- // The commands the agent runs, as `context.json`'s environment declares them, before anything can run one.
81
- const environment = { ...values, ...(await prepareEnvironment(dir, { ...process.env, ...values })) };
82
- const env = { ...process.env, ...environment };
83
- const content = await contentForThisRun(dir, env);
84
- const stateRoot = options.stateRoot ?? resolveStateRoot(dir, env);
85
- const models = await modelEnvironment(dir, {
86
- ...(options.authPath === undefined ? {} : { authPath: options.authPath }),
88
+ const secrets = definedValues(options.secrets);
89
+ const code = buildDefinition(definition, secrets, { ...config, dev: options.runsAs.dev });
90
+ // FastAgent's own work for the instance (installing packages, cloning content, finding its files) runs in this
91
+ // process's environment and the instance's secrets. What the AGENT starts gets an environment assembled from inputs.
92
+ const env = { ...options.ownEnv, ...secrets };
93
+ const packages = await prepareEnvironment(dir, env, { ...env, PATH: options.env.PATH });
94
+ const processEnv = processEnvironment({
95
+ base: options.env,
96
+ secrets,
97
+ declared: definition.inputs.secrets.map(({ name }) => name),
98
+ packages,
99
+ workdir,
100
+ }, dirname(workdir));
101
+ const content = await contentForThisRun(dir, options.config, workdir, env);
102
+ const stateRoot = options.stateRoot ?? resolveStateRoot(projectDir, env);
103
+ const authPath = options.authPath ??
104
+ (options.keeps === "state" && options.credentialStore === undefined ? join(stateRoot, "auth.json") : undefined);
105
+ const models = await modelEnvironment(projectDir, {
106
+ ...(authPath === undefined ? {} : { authPath }),
87
107
  ...(options.credentialStore === undefined ? {} : { credentialStore: options.credentialStore }),
88
- }, code.providers, { stateRoot, environment });
108
+ }, code.providers, { stateRoot, environment: secrets, env, offline: options.offline ?? env.FASTAGENT_OFFLINE === "1" });
89
109
  const chosen = options.storage ?? { instance: "posix" };
90
110
  const storage = await openStorage(stateRoot, chosen);
91
111
  let mcp;
92
112
  let agent;
93
113
  try {
94
- const mcpEnvironment = { ...env, ...options.mcp?.variables };
95
- mcp = await openMcpClients(resolveMcpServers(dir, mcpEnvironment), mcpAuthorization(dir, env, stateRoot, options.mcp), options.mcp);
114
+ const mcpEnvironment = { ...secrets, ...options.mcp?.variables };
115
+ mcp = await openMcpClients(resolveMcpServers(mcpServers, mcpEnvironment, undefined, workdir, processEnv), options.keeps === "state"
116
+ ? mcpAuthorizationInState(stateRoot, options.mcp)
117
+ : mcpAuthorization(projectDir, env, stateRoot, options.mcp), options.mcp);
96
118
  agent = await assembleAgent(definition, {
119
+ name,
97
120
  mcpTools: mcpTools(mcp.tools),
121
+ runsAs: options.runsAs,
98
122
  storage,
99
123
  code,
124
+ config,
125
+ text,
100
126
  content,
101
- environment,
127
+ workdir,
128
+ processEnv,
102
129
  models: models.models,
103
130
  ...(models.catalogProblem === undefined ? {} : { catalogProblem: models.catalogProblem }),
104
131
  ...(typeof chosen === "object" && "instance" in chosen ? { stateRoot } : {}),
@@ -133,36 +160,71 @@ export async function openServing(directory, options = {}) {
133
160
  return {
134
161
  agent,
135
162
  definition,
163
+ name,
136
164
  code,
165
+ config,
166
+ secrets,
137
167
  models,
138
168
  content,
139
- agentDir: dir,
169
+ agentDir: projectDir,
170
+ workdir,
140
171
  stateRoot,
141
172
  channels: code.channels,
142
173
  schedules: code.schedules,
143
174
  };
144
175
  }
145
- /** `stateDir` read as `FASTAGENT_STATE_DIR` is: `~` is the home directory, a relative one resolves against the cwd. */
146
- function stateDirOf(stateDir) {
147
- const resolved = resolveOverridePath(stateDir);
148
- if (resolved === undefined)
149
- throw new Error("stateDir needs the directory the instance's state is kept in");
150
- return resolved;
176
+ /** The `config` input as a source: an object as it is, a path (absolute, like every path here) read. */
177
+ async function configOf(config) {
178
+ if (config === undefined)
179
+ return undefined;
180
+ if (typeof config !== "string")
181
+ return { values: config, label: "the config object" };
182
+ if (!isAbsolute(config))
183
+ throw new Error(`config must be an absolute path, and is ${JSON.stringify(config)}`);
184
+ return readInstanceConfigFile(config);
185
+ }
186
+ /** Where the instance is, every path absolute: a relative one would be an input the process's cwd chooses. */
187
+ function locationOf(location) {
188
+ const absolute = (path, name) => {
189
+ if (typeof path !== "string" || !isAbsolute(path)) {
190
+ throw new Error(`${name} must be an absolute path, and is ${JSON.stringify(path)}`);
191
+ }
192
+ return path;
193
+ };
194
+ if ("root" in location && ("stateDir" in location || "workdir" in location)) {
195
+ throw new Error("give the instance a root, or a stateDir and a workdir, not both");
196
+ }
197
+ if ("root" in location) {
198
+ const root = absolute(location.root, "root");
199
+ return { workdir: root, stateRoot: join(root, STATE_DIRNAME) };
200
+ }
201
+ return { workdir: absolute(location.workdir, "workdir"), stateRoot: absolute(location.stateDir, "stateDir") };
151
202
  }
152
203
  /**
153
- * Open the agent directory `dir` the way `dev` and `start` do before they serve: its definition, its code built with
154
- * the secrets it declares, its environment, its content and the instance's storage, which one process holds at a time.
155
- * Nothing reaches the agent until `serve`.
204
+ * Open one instance of `definition`, the default export of an agent's package, the way `dev` and `start` do before they
205
+ * serve: its code built with the secrets it declares, its environment, its content and the instance's storage, which
206
+ * one process holds at a time. Nothing reaches the agent until `serve`.
156
207
  */
157
- export async function openAgent(dir, options = {}) {
208
+ export async function openAgent(definition, options) {
209
+ const { workdir, stateRoot } = locationOf(options);
210
+ const config = await configOf(options.config);
158
211
  // An app may never serve the agent, and then no clock fires a wake-up: `wake` is refused until it does.
159
212
  let ticking = false;
160
- const opened = await openServing(dir, {
213
+ const opened = await openServing(assertDefinition(definition), {
214
+ workdir,
215
+ stateRoot,
216
+ secrets: options.secrets ?? {},
217
+ env: options.env ?? {},
218
+ ownEnv: options.env ?? {},
219
+ runsAs: NOT_HOSTED,
220
+ offline: options.offline === true,
221
+ ...(options.name === undefined ? {} : { name: options.name }),
222
+ ...(config === undefined ? {} : { config }),
161
223
  wakeTicking: () => ticking,
224
+ keeps: "state",
162
225
  ...(options.mcp === undefined ? {} : { mcp: options.mcp }),
163
226
  ...(options.model === undefined ? {} : { model: options.model }),
164
227
  ...(options.credentials === undefined ? {} : { credentialStore: piCredentials(options.credentials) }),
165
- ...(options.stateDir === undefined ? {} : { stateRoot: stateDirOf(options.stateDir) }),
166
228
  });
167
229
  const { agent } = opened;
168
230
  let served;
@@ -20,20 +20,23 @@ export const trackSessions = (harness, storage, context) => Effect.gen(function*
20
20
  if (value > (newest.get(id) ?? 0))
21
21
  newest.set(id, value);
22
22
  };
23
- // Subscribed before the scan, so a commit while it reads is not lost: either reports the newest id, and the
23
+ // Observed before the scan, so a commit while it reads is not lost: either reports the newest id, and the
24
24
  // larger stands. A change's conversation may be created in the same commit, so membership is not checked here.
25
- yield* Effect.acquireRelease(Effect.sync(() => harness.subscribeCommits(({ changes }) => {
26
- for (const change of changes) {
27
- if (change.type === "conversation") {
28
- if (isSession(change.value))
29
- sessions.add(change.value.id);
30
- touch(change.value.id, change.value.id);
25
+ yield* Effect.acquireRelease(Effect.sync(() => harness.observeCommits({
26
+ advance: ({ changes }) => {
27
+ for (const change of changes) {
28
+ if (change.type === "conversation") {
29
+ if (isSession(change.value))
30
+ sessions.add(change.value.id);
31
+ touch(change.value.id, change.value.id);
32
+ }
33
+ else if (change.type === "entry" || change.type === "submission") {
34
+ touch(change.value.conversationId, change.value.id);
35
+ }
31
36
  }
32
- else if (change.type === "entry" || change.type === "submission") {
33
- touch(change.value.conversationId, change.value.id);
34
- }
35
- }
36
- })), (unsubscribe) => Effect.sync(unsubscribe));
37
+ },
38
+ end: () => { },
39
+ })), (observation) => Effect.sync(() => observation.detach()));
37
40
  yield* conversations(storage, context).pipe(Stream.filter(isSession), Stream.runForEach((conversation) => storedActivity(storage, context, conversation).pipe(Effect.tap((activity) => Effect.sync(() => {
38
41
  sessions.add(conversation.id);
39
42
  touch(conversation.id, activity);
@@ -0,0 +1,30 @@
1
+ import type { InstanceConfigSource } from "./config.ts";
2
+ export interface TextSource {
3
+ /** Absolute: a file of instructions, or a directory of skills or of prompt templates. */
4
+ path: string;
5
+ /** The instance configuration that declared it, and so expects it to exist. None for the program's own. */
6
+ declaredBy?: string;
7
+ /** The path as the configuration wrote it. */
8
+ given?: string;
9
+ }
10
+ /** Each kind's sources in the order they load: the program's first, so a later one never replaces its entries. */
11
+ export interface TextSources {
12
+ instructions: readonly TextSource[];
13
+ skills: readonly TextSource[];
14
+ prompts: readonly TextSource[];
15
+ }
16
+ export declare const NOUN: {
17
+ readonly instructions: "file";
18
+ readonly skills: "directory";
19
+ readonly prompts: "directory";
20
+ };
21
+ /** The program's own text, which `AGENTS.md` and `SYSTEM.md` already put in the prompt. */
22
+ export declare function programText(dir: string): TextSources;
23
+ /** What `path` is: a file, a directory, or nothing. */
24
+ export declare function whatIs(path: string): "file" | "directory" | undefined;
25
+ /**
26
+ * The text of the program in `dir` and of `instance` (whose shape `resolveConfig` has checked): each declared path
27
+ * resolved against the configuration's directory, and refused when it is not what its kind names or is text the
28
+ * program already loads, which would load twice.
29
+ */
30
+ export declare function declareText(dir: string, instance: InstanceConfigSource | undefined): TextSources;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Where an instance's text is (agent-artifact.md §4.2, §7): the program's own `skills/` and `prompts/`, then what the
3
+ * instance configuration's `instructions`, `skills` and `prompts` name. Resolved once, at open, into absolute paths, so
4
+ * the readers (text.ts) read exactly these for each message and scan nothing else.
5
+ */
6
+ import { statSync } from "node:fs";
7
+ import { join } from "node:path";
8
+ import { configurationPath, isUnderDir } from "../../paths.js";
9
+ export const NOUN = { instructions: "file", skills: "directory", prompts: "directory" };
10
+ /** The program's own text, which `AGENTS.md` and `SYSTEM.md` already put in the prompt. */
11
+ export function programText(dir) {
12
+ return { instructions: [], skills: [{ path: join(dir, "skills") }], prompts: [{ path: join(dir, "prompts") }] };
13
+ }
14
+ /** What `path` is: a file, a directory, or nothing. */
15
+ export function whatIs(path) {
16
+ try {
17
+ return statSync(path).isDirectory() ? "directory" : "file";
18
+ }
19
+ catch (error) {
20
+ if (error.code === "ENOENT")
21
+ return undefined;
22
+ throw error;
23
+ }
24
+ }
25
+ /**
26
+ * The text of the program in `dir` and of `instance` (whose shape `resolveConfig` has checked): each declared path
27
+ * resolved against the configuration's directory, and refused when it is not what its kind names or is text the
28
+ * program already loads, which would load twice.
29
+ */
30
+ export function declareText(dir, instance) {
31
+ const program = programText(dir);
32
+ const values = typeof instance?.values === "object" ? instance.values : {};
33
+ if (instance === undefined)
34
+ return program;
35
+ const programsOwn = ["SYSTEM.md", "AGENTS.md", "skills", "prompts"].map((name) => join(dir, name));
36
+ const declared = (kind) => (values[kind] ?? []).map((given) => {
37
+ const at = `${instance.label}: ${kind} "${given}"`;
38
+ const path = configurationPath(given, instance.directory);
39
+ if (path === undefined) {
40
+ throw new Error(`${at} must be absolute here, since ${instance.label} is not a file its directory could anchor`);
41
+ }
42
+ if (whatIs(path) !== NOUN[kind])
43
+ throw new Error(`${at} (${path}) is not a ${NOUN[kind]}`);
44
+ const own = programsOwn.find((text) => isUnderDir(path, text));
45
+ if (own !== undefined) {
46
+ throw new Error(`${at} (${path}) is the program's own text (${own}), which loads already: declare another`);
47
+ }
48
+ return { path, declaredBy: instance.label, given };
49
+ });
50
+ return {
51
+ instructions: declared("instructions"),
52
+ skills: [...program.skills, ...declared("skills")],
53
+ prompts: [...program.prompts, ...declared("prompts")],
54
+ };
55
+ }
@@ -1,6 +1,9 @@
1
1
  import { type PromptSection } from "@earendil-works/pi-durable";
2
2
  import type { ResolvedContent } from "../../content/resolve.ts";
3
+ import type { RunsAs } from "../../serving-command.ts";
3
4
  import type { AgentCommand } from "./agent.ts";
5
+ import type { InstanceConfigSource } from "./config.ts";
6
+ import { type TextSource, type TextSources } from "./text-sources.ts";
4
7
  export interface Skill {
5
8
  name: string;
6
9
  description: string;
@@ -10,8 +13,13 @@ export interface Skill {
10
13
  /** Offered only through `/skill:<name>`, never listed to the model. */
11
14
  disableModelInvocation: boolean;
12
15
  }
13
- /** The agent's skills: `skills/<name>/SKILL.md`. One that breaks the specification is reported and skipped. */
14
- export declare function readSkills(agentDir: string): Skill[];
16
+ /** The skills the agent offers, reported and skipped as above. */
17
+ export declare const readSkills: (sources: readonly TextSource[]) => Skill[];
18
+ /**
19
+ * The instance's text as it will be read: declared, and refused when an instance entry takes a name the program (or an
20
+ * earlier instance entry) has. Called at open; what goes wrong afterwards is reported as each message reads it.
21
+ */
22
+ export declare function openText(dir: string, instance: InstanceConfigSource | undefined): TextSources;
15
23
  /** Arguments as a shell splits them: by whitespace, with `"…"` or `'…'` keeping one argument together. */
16
24
  export declare function parseArguments(text: string): string[];
17
25
  /**
@@ -20,11 +28,15 @@ export declare function parseArguments(text: string): string[];
20
28
  */
21
29
  export declare function expandTemplate(body: string, args: readonly string[]): string;
22
30
  /** What a Caller may offer as `/<name>`: the prompt templates, then `skill:<name>` for each skill. */
23
- export declare function readCommands(agentDir: string): AgentCommand[];
31
+ export declare function readCommands(text: TextSources): AgentCommand[];
24
32
  /**
25
33
  * The prompt the definition contributes: `SYSTEM.md` as written, `AGENTS.md` as project context, the skills, where it
26
- * works, and, deployed, what of a change it makes to itself lasts. `wake`: the agent has the wake tool.
34
+ * works, and, deployed, what of a change it makes to itself lasts. `wake`: the agent has the wake tool; `runsAs` says
35
+ * whether it is deployed, and where.
27
36
  */
28
37
  export declare function definitionSections(agentDir: string, content: readonly ResolvedContent[], options: {
29
38
  wake: boolean;
39
+ runsAs: RunsAs;
40
+ workdir?: string;
41
+ text?: TextSources;
30
42
  }): PromptSection[];