@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,18 +1,18 @@
1
1
  /**
2
- * WHAT AN AUTHOR DECLARES an agent works on, read and refused in ONE place (file.ts reads the files through
3
- * it): the `content` map of `context.json`, which is shared and so holds only repositories every instance reaches, and
4
- * the `content` map of `context.local.json`, the directories of this machine it is bound to. Pure: what is on the disk
5
- * is resolve.ts's question. docs/design/agent-model.md §3 is the rule.
2
+ * WHAT AN AGENT WORKS ON, declared and refused in ONE place (file.ts reads the files through it): the `content` map of
3
+ * the program's `context.json`, which holds only repositories every instance reaches, and the `content` map of an
4
+ * instance's `fastagent.json`, which adds repositories and directories of its own. An instance only adds: a name the
5
+ * program declares is not one it may take. Pure: what is on the disk is resolve.ts's question.
6
+ * docs/design/agent-artifact.md §3.3 and §4.2 are the rule.
6
7
  */
7
- import { homedir } from "node:os";
8
- import { isAbsolute, join, resolve } from "node:path";
9
- import { CONTEXT_FILE, LOCAL_CONTEXT_FILE, isUnderDir } from "../paths.js";
8
+ import { isAbsolute } from "node:path";
9
+ import { CONTEXT_FILE, configurationPath, isUnderDir } from "../paths.js";
10
10
  /**
11
- * The keys an entry and a binding carry, in the order they are written: where it is, then how it is treated. One list
12
- * each, so a key the reader accepts is one the writer keeps.
11
+ * The keys an entry carries, in the order they are written: where it is, then how it is treated. One list each, so a
12
+ * key the reader accepts is one the writer keeps.
13
13
  */
14
- const ENTRY_KEYS = ["github", "ref", "description"];
15
- const BINDING_KEYS = ["path", "description"];
14
+ const GITHUB_KEYS = ["github", "ref", "description"];
15
+ const PATH_KEYS = ["path", "description"];
16
16
  /** A name becomes a directory name, so it is one path segment (the spelling a release's agent name has). */
17
17
  const NAME = /^[A-Za-z0-9_-]+$/;
18
18
  /** Whether `name` can name a content entry. */
@@ -24,13 +24,9 @@ const GITHUB_REPO = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
24
24
  export function isGithubRepo(repo) {
25
25
  return GITHUB_REPO.test(repo);
26
26
  }
27
- /** `entry` with its keys in {@link ENTRY_KEYS} order: the form written. */
27
+ /** `entry` with its keys in the order they are written. */
28
28
  export function canonicalEntry(entry) {
29
- return pick(entry, ENTRY_KEYS);
30
- }
31
- /** `binding` with its keys in {@link BINDING_KEYS} order: the form written. */
32
- export function canonicalBinding(binding) {
33
- return pick(binding, BINDING_KEYS);
29
+ return pick(entry, "github" in entry ? GITHUB_KEYS : PATH_KEYS);
34
30
  }
35
31
  function pick(value, keys) {
36
32
  const out = {};
@@ -41,42 +37,26 @@ function pick(value, keys) {
41
37
  }
42
38
  return out;
43
39
  }
44
- /** Read `context.json`'s `content` map (undefined is none). Every refusal names the entry; nothing is defaulted. */
45
- export function declareContent(raw) {
46
- return entriesByName(raw).map(([name, entry]) => declareOne(name, entry));
40
+ /**
41
+ * Read a `content` map (undefined is none) from `from`. Every refusal names the entry; nothing is defaulted. The
42
+ * program's declares repositories only, since it is shared; an instance's may name a directory too.
43
+ */
44
+ export function declareContent(raw, from) {
45
+ return entriesByName(raw).map(([name, entry]) => declareOne(name, entry, from));
47
46
  }
48
47
  /**
49
- * Read `context.local.json`'s `content` map (undefined is none) beside `declared`, with relative paths resolved against
50
- * `agentDir`. A binding under a declared entry's name is that entry's checkout here; any other is a directory of this
51
- * machine alone.
48
+ * The program's entries and the instance's, as one list. An instance only adds: a name both declare (ignoring case,
49
+ * as names are a directory) is refused, naming both, so nothing is shadowed.
52
50
  */
53
- export function declareBindings(raw, declared, agentDir) {
54
- return entriesByName(raw).map(([name, binding]) => {
55
- const at = `content "${name}"`;
56
- const e = objectWithKeys(at, binding, BINDING_KEYS);
57
- if (typeof e.path !== "string" || e.path === "")
58
- throw new Error(`${at}: "path" must be a non-empty string`);
59
- const path = absolutePath(e.path, agentDir);
60
- const shared = declared.find((entry) => entry.name.toLowerCase() === name.toLowerCase());
61
- if (shared !== undefined) {
62
- if (shared.name !== name) {
63
- throw new Error(`${at} binds the entry ${CONTEXT_FILE} names "${shared.name}": spell it the same`);
64
- }
65
- if (e.description !== undefined) {
66
- throw new Error(`${at} binds this machine's checkout of the entry ${CONTEXT_FILE} declares, which says "description" for ` +
67
- `every instance: give it only "path"`);
68
- }
69
- return { name, path, kind: "checkout" };
51
+ export function joinContent(program, instance) {
52
+ for (const added of instance) {
53
+ const taken = program.find((entry) => entry.name.toLowerCase() === added.name.toLowerCase());
54
+ if (taken !== undefined) {
55
+ throw new Error(`content "${added.name}" is declared by the program (${CONTEXT_FILE} names "${taken.name}") and by the ` +
56
+ `instance: an instance adds to the program's content and does not replace it — name it otherwise`);
70
57
  }
71
- const description = descriptionOf(at, e);
72
- return { name, path, kind: "local", ...(description !== undefined ? { description } : {}) };
73
- });
74
- }
75
- /** `path` as written in `context.local.json`, absolute: `~/` is the home directory, a relative one the agent's. */
76
- function absolutePath(path, agentDir) {
77
- if (path === "~" || path.startsWith("~/"))
78
- return join(homedir(), path.slice(1));
79
- return isAbsolute(path) ? resolve(path) : resolve(agentDir, path);
58
+ }
59
+ return [...program, ...instance];
80
60
  }
81
61
  /** The entries of a `content` map, each name checked, unique ignoring case. */
82
62
  function entriesByName(raw) {
@@ -110,24 +90,43 @@ function objectWithKeys(at, value, keys) {
110
90
  }
111
91
  return e;
112
92
  }
113
- function descriptionOf(at, e) {
114
- if (e.description !== undefined && (typeof e.description !== "string" || e.description === "")) {
115
- throw new Error(`${at}: "description" must be a non-empty string`);
93
+ /** `path` as written in an instance configuration, absolute: `~/` is the home directory, a relative one `base`'s. */
94
+ function absolutePath(path, from, at) {
95
+ const absolute = configurationPath(path, from.base);
96
+ if (absolute === undefined) {
97
+ throw new Error(`${at}: "path" must be absolute here, since ${from.file} is not a file its directory could anchor`);
116
98
  }
117
- return e.description;
99
+ return absolute;
118
100
  }
119
- function declareOne(name, entry) {
101
+ function declareOne(name, entry, from) {
120
102
  const at = `content "${name}"`;
121
- const e = objectWithKeys(at, entry, ENTRY_KEYS);
122
- for (const key of ["github", "ref"]) {
103
+ const e = objectWithKeys(at, entry, [...GITHUB_KEYS, "path"]);
104
+ if (from.origin === "program" && e.path !== undefined) {
105
+ throw new Error(`${at}: ${from.file} is shared, so it declares only the repositories every instance reaches — add a directory ` +
106
+ `to the instance's configuration instead (fastagent content add <dir>)`);
107
+ }
108
+ for (const key of ["github", "ref", "path"]) {
123
109
  if (e[key] !== undefined && (typeof e[key] !== "string" || e[key] === "")) {
124
110
  throw new Error(`${at}: "${key}" must be a non-empty string`);
125
111
  }
126
112
  }
127
- const description = descriptionOf(at, e);
113
+ if (e.description !== undefined && (typeof e.description !== "string" || e.description === "")) {
114
+ throw new Error(`${at}: "description" must be a non-empty string`);
115
+ }
116
+ const base = {
117
+ name,
118
+ origin: from.origin,
119
+ ...(e.description !== undefined ? { description: e.description } : {}),
120
+ };
121
+ if (e.github !== undefined && e.path !== undefined)
122
+ throw new Error(`${at} names both "github" and "path": give one`);
123
+ if (e.path !== undefined) {
124
+ if (e.ref !== undefined)
125
+ throw new Error(`${at}: "ref" applies to a repository, and ${at} is a directory`);
126
+ return { ...base, kind: "local", path: absolutePath(e.path, from, at) };
127
+ }
128
128
  if (e.github === undefined) {
129
- throw new Error(`${at} needs "github": ${CONTEXT_FILE} is shared, so it declares only what every instance reaches — bind a ` +
130
- `directory of this machine in ${LOCAL_CONTEXT_FILE} instead (fastagent content add <dir>)`);
129
+ throw new Error(`${at} needs "github"${from.origin === "instance" ? ' or "path"' : ""}`);
131
130
  }
132
131
  const repo = e.github;
133
132
  if (!isGithubRepo(repo))
@@ -136,7 +135,7 @@ function declareOne(name, entry) {
136
135
  // git reads a leading "-" as an option, and no branch, tag or commit name has one.
137
136
  if (ref?.startsWith("-"))
138
137
  throw new Error(`${at}: "ref" must name a branch, tag or commit, got "${ref}"`);
139
- return { name, repo, ...(ref !== undefined ? { ref } : {}), ...(description !== undefined ? { description } : {}) };
138
+ return { ...base, kind: "github", repo, ...(ref !== undefined ? { ref } : {}) };
140
139
  }
141
140
  /**
142
141
  * A directory the agent is bound to and the agent directory are kept apart (agent-model.md §2): a definition is
@@ -1,32 +1,43 @@
1
1
  import { type DeclaredEnvironment } from "../environment/declare.ts";
2
- import { type BoundContent, type ContentBinding, type ContentDeclaration, type ContentEntry, type DeclaredContent } from "./declare.ts";
2
+ import { type ContentEntry, type DeclaredContent } from "./declare.ts";
3
3
  /** `context.json` as read: the content entries as written and as declared, and the environment. */
4
4
  export interface ContextFile {
5
5
  $schema?: string;
6
6
  content: Record<string, ContentEntry>;
7
7
  declared: DeclaredContent[];
8
8
  environment?: DeclaredEnvironment;
9
- }
10
- /** `context.local.json` as read: the bindings as written and as declared. */
11
- export interface LocalContextFile {
12
- content: Record<string, ContentBinding>;
13
- bound: BoundContent[];
9
+ /** The program's MCP servers as written. Their shape is the MCP reader's to check; an edit keeps them as they are. */
10
+ mcpServers?: Record<string, unknown>;
14
11
  }
15
12
  /** Read `text`, the contents of `path`, whole: what an edit, which writes the whole, reads. */
16
13
  export declare function parseContextFile(text: string, path: string): ContextFile;
17
- /** Read `text`, the contents of `path`, whole, beside the entries `context.json` declares. */
18
- export declare function parseLocalContextFile(text: string, path: string, declared: readonly DeclaredContent[], agentDir: string): LocalContextFile;
19
14
  /** The agent's `context.json`, read whole. */
20
15
  export declare function readContextFile(agentDir: string): ContextFile;
21
- /** The content of the agent in `agentDir`: what `context.json` declares, and what this machine binds. */
22
- export declare function loadContent(agentDir: string): ContentDeclaration;
16
+ /** The instance configuration's content, as far as this reads it: its `content` map and where it is from. */
17
+ export interface InstanceContent {
18
+ values: unknown;
19
+ label: string;
20
+ /** The configuration file's directory, which a relative `path` is relative to. */
21
+ directory?: string;
22
+ }
23
+ /**
24
+ * The content of the agent whose program is in `agentDir`: what its `context.json` declares, and what `instance` adds
25
+ * to it (an instance only adds: a name both declare is refused).
26
+ */
27
+ export declare function loadContent(agentDir: string, instance?: InstanceContent): DeclaredContent[];
28
+ /** What an instance configuration's `content` declares. */
29
+ export declare function instanceContent({ values, label, directory }: InstanceContent): DeclaredContent[];
23
30
  /** The environment the agent in `agentDir` declares, or undefined when it declares none. */
24
31
  export declare function loadEnvironment(agentDir: string): DeclaredEnvironment | undefined;
32
+ /** The program's `mcpServers` map as written in `context.json`, and the file's path, which names it in a refusal. */
33
+ export declare function readProgramMcpServers(agentDir: string): {
34
+ values: unknown;
35
+ path: string;
36
+ };
25
37
  /** The text `context.json` is written as. An environment that declares nothing is left out. */
26
38
  export declare function contextFileText(file: {
27
39
  $schema?: string;
28
40
  content: Record<string, ContentEntry>;
29
41
  environment?: DeclaredEnvironment;
42
+ mcpServers?: Record<string, unknown>;
30
43
  }): string;
31
- /** The text `context.local.json` is written as. */
32
- export declare function localContextFileText(content: Record<string, ContentBinding>): string;
@@ -1,19 +1,19 @@
1
1
  /**
2
- * The agent's `context.json` and this machine's `context.local.json`, read in ONE place, so the opener, `info`,
3
- * `content list`, `env`, `tool` and deploy read one declaration; and the one shape each is written in. A reader
4
- * declares the part it uses (its content, or its environment), so a part that is refused stops what uses it and is
5
- * reported where it is, not as the other's; an edit declares the whole, since it writes the whole. JSON, like
6
- * `mcp.json` and `package.json`, so a command, a client or the agent itself can edit it without touching TypeScript.
2
+ * The program's `context.json` and the content an instance's configuration adds, read in ONE place, so the opener,
3
+ * `info`, `content list`, `env`, `tool` and deploy read one declaration; and the one shape `context.json` is written
4
+ * in. A reader declares the part it uses (its content, or its environment), so a part that is refused stops what uses
5
+ * it and is reported where it is, not as the other's; an edit declares the whole, since it writes the whole. JSON,
6
+ * like `mcp.json` and `package.json`, so a command, a client or the agent itself can edit it without touching
7
+ * TypeScript.
7
8
  */
8
9
  import { readFileSync } from "node:fs";
9
10
  import { join, resolve } from "node:path";
10
- import { CONTEXT_FILE, LOCAL_CONTEXT_FILE } from "../paths.js";
11
+ import { CONTEXT_FILE } from "../paths.js";
11
12
  import { declareEnvironment } from "../environment/declare.js";
12
- import { declareBindings, declareContent, } from "./declare.js";
13
- const FILE_KEYS = ["$schema", "content", "environment"];
14
- const LOCAL_FILE_KEYS = ["content"];
13
+ import { declareContent, joinContent } from "./declare.js";
14
+ const FILE_KEYS = ["$schema", "content", "environment", "mcpServers"];
15
15
  /** `text`, the contents of `path`, as the object a context file is: refused when the file itself is wrong. */
16
- function parseFile(text, path, keys = FILE_KEYS) {
16
+ function parseFile(text, path) {
17
17
  let raw;
18
18
  try {
19
19
  raw = JSON.parse(text);
@@ -25,12 +25,17 @@ function parseFile(text, path, keys = FILE_KEYS) {
25
25
  throw new Error(`${path} must hold a JSON object`);
26
26
  const file = raw;
27
27
  for (const key of Object.keys(file)) {
28
- if (!keys.includes(key))
29
- throw new Error(`${path}: unknown key "${key}" (valid keys: ${keys.join(", ")})`);
28
+ if (!FILE_KEYS.includes(key)) {
29
+ throw new Error(`${path}: unknown key "${key}" (valid keys: ${FILE_KEYS.join(", ")})`);
30
+ }
30
31
  }
31
32
  if (file.$schema !== undefined && typeof file.$schema !== "string") {
32
33
  throw new Error(`${path}: "$schema" must be a string`);
33
34
  }
35
+ if (file.mcpServers !== undefined &&
36
+ (typeof file.mcpServers !== "object" || file.mcpServers === null || Array.isArray(file.mcpServers))) {
37
+ throw new Error(`${path}: "mcpServers" must be an object of servers by name`);
38
+ }
34
39
  return file;
35
40
  }
36
41
  /** One part of `context.json` at `path`, declared by `declare`; its refusal names the file. */
@@ -45,24 +50,19 @@ function declarePart(path, declare) {
45
50
  /** Read `text`, the contents of `path`, whole: what an edit, which writes the whole, reads. */
46
51
  export function parseContextFile(text, path) {
47
52
  const file = parseFile(text, path);
48
- const declared = declarePart(path, () => declareContent(file.content));
53
+ const declared = declarePart(path, () => declareContent(file.content, { origin: "program", file: CONTEXT_FILE }));
49
54
  const environment = declarePart(path, () => declareEnvironment(file.environment));
50
55
  return {
51
56
  ...(file.$schema !== undefined ? { $schema: file.$schema } : {}),
52
57
  content: (file.content ?? {}),
53
58
  declared,
54
59
  ...(environment !== undefined ? { environment } : {}),
60
+ ...(file.mcpServers !== undefined ? { mcpServers: file.mcpServers } : {}),
55
61
  };
56
62
  }
57
- /** Read `text`, the contents of `path`, whole, beside the entries `context.json` declares. */
58
- export function parseLocalContextFile(text, path, declared, agentDir) {
59
- const file = parseFile(text, path, LOCAL_FILE_KEYS);
60
- const bound = declarePart(path, () => declareBindings(file.content, declared, resolve(agentDir)));
61
- return { content: (file.content ?? {}), bound };
62
- }
63
- /** The agent's context file `name` and its path, or undefined text when it has none (it declares nothing). */
64
- function contextFileAt(agentDir, name = CONTEXT_FILE) {
65
- const path = join(resolve(agentDir), name);
63
+ /** The agent's `context.json` and its path, or undefined text when it has none (it declares nothing). */
64
+ function contextFileAt(agentDir) {
65
+ const path = join(resolve(agentDir), CONTEXT_FILE);
66
66
  try {
67
67
  return { path, text: readFileSync(path, "utf8") };
68
68
  }
@@ -77,16 +77,25 @@ export function readContextFile(agentDir) {
77
77
  const { path, text } = contextFileAt(agentDir);
78
78
  return text === undefined ? { content: {}, declared: [] } : parseContextFile(text, path);
79
79
  }
80
- /** This machine's `context.local.json` for the agent in `agentDir`, read whole, beside what it `declared`. */
81
- function readLocalContextFile(agentDir, declared) {
82
- const { path, text } = contextFileAt(agentDir, LOCAL_CONTEXT_FILE);
83
- return text === undefined ? { content: {}, bound: [] } : parseLocalContextFile(text, path, declared, agentDir);
84
- }
85
- /** The content of the agent in `agentDir`: what `context.json` declares, and what this machine binds. */
86
- export function loadContent(agentDir) {
80
+ /**
81
+ * The content of the agent whose program is in `agentDir`: what its `context.json` declares, and what `instance` adds
82
+ * to it (an instance only adds: a name both declare is refused).
83
+ */
84
+ export function loadContent(agentDir, instance) {
87
85
  const { path, text } = contextFileAt(agentDir);
88
- const declared = text === undefined ? [] : declarePart(path, () => declareContent(parseFile(text, path).content));
89
- return { declared, bound: readLocalContextFile(agentDir, declared).bound };
86
+ const program = text === undefined
87
+ ? []
88
+ : declarePart(path, () => declareContent(parseFile(text, path).content, { origin: "program", file: CONTEXT_FILE }));
89
+ return joinContent(program, instance === undefined ? [] : instanceContent(instance));
90
+ }
91
+ /** What an instance configuration's `content` declares. */
92
+ export function instanceContent({ values, label, directory }) {
93
+ const content = typeof values === "object" && values !== null ? values.content : undefined;
94
+ return declarePart(label, () => declareContent(content, {
95
+ origin: "instance",
96
+ file: label,
97
+ ...(directory === undefined ? {} : { base: directory }),
98
+ }));
90
99
  }
91
100
  /** The environment the agent in `agentDir` declares, or undefined when it declares none. */
92
101
  export function loadEnvironment(agentDir) {
@@ -96,6 +105,11 @@ export function loadEnvironment(agentDir) {
96
105
  const file = parseFile(text, path);
97
106
  return declarePart(path, () => declareEnvironment(file.environment));
98
107
  }
108
+ /** The program's `mcpServers` map as written in `context.json`, and the file's path, which names it in a refusal. */
109
+ export function readProgramMcpServers(agentDir) {
110
+ const { path, text } = contextFileAt(agentDir);
111
+ return { values: text === undefined ? undefined : parseFile(text, path).mcpServers, path };
112
+ }
99
113
  /** The text `context.json` is written as. An environment that declares nothing is left out. */
100
114
  export function contextFileText(file) {
101
115
  const packages = file.environment?.packages ?? {};
@@ -110,10 +124,9 @@ export function contextFileText(file) {
110
124
  ...(file.$schema !== undefined ? { $schema: file.$schema } : {}),
111
125
  content: file.content,
112
126
  ...(Object.keys(environment).length > 0 ? { environment } : {}),
127
+ ...(file.mcpServers !== undefined && Object.keys(file.mcpServers).length > 0
128
+ ? { mcpServers: file.mcpServers }
129
+ : {}),
113
130
  };
114
131
  return `${JSON.stringify(out, null, 2)}\n`;
115
132
  }
116
- /** The text `context.local.json` is written as. */
117
- export function localContextFileText(content) {
118
- return `${JSON.stringify({ content }, null, 2)}\n`;
119
- }
@@ -8,16 +8,6 @@ export declare function checkoutOf(dir: string): {
8
8
  root: string;
9
9
  origin?: string;
10
10
  } | undefined;
11
- /**
12
- * Why the directory `local` cannot stand for github `repo` on this machine, or undefined when it can: it is the root
13
- * of a checkout whose `origin` is that repository.
14
- */
15
- export declare function checkoutProblem(local: string, repo: string): string | undefined;
16
- /**
17
- * What to say when the checkout `dir` is not at `ref`, or undefined when it is: on that branch, or at the commit `ref`
18
- * names. FastAgent never moves a checkout the user owns, so this is said, not acted on.
19
- */
20
- export declare function refNotice(dir: string, ref: string): string | undefined;
21
11
  /**
22
12
  * What a start did with a clone: made it, moved it to what the remote has now, found it there already, or kept it as
23
13
  * it is, for the `reason` given (git refused to touch the agent's work, or the remote could not be reached).
@@ -3,11 +3,11 @@
3
3
  * `ref`, and a clone, made or brought up to date in place. git's own configuration applies throughout (credential helpers, `url.<base>.insteadOf`), so
4
4
  * a private repository is reached the way the user's own `git clone` reaches it.
5
5
  */
6
- import { existsSync, mkdirSync, realpathSync, renameSync, rmSync, statSync } from "node:fs";
6
+ import { existsSync, mkdirSync, renameSync, rmSync, statSync } from "node:fs";
7
7
  import { basename, dirname, join } from "node:path";
8
8
  import { gitFor } from "../git.js";
9
9
  const WHY = "github content needs it on this machine";
10
- const { answer: gitAnswer } = gitFor(WHY);
10
+ const { answer: checkoutAnswer } = gitFor(WHY);
11
11
  /** The `owner/repo` a GitHub remote URL names, in any of its spellings (https, ssh, scp-like), or undefined. */
12
12
  export function githubRepoOf(url) {
13
13
  const match = /^(?:(?:https?|git|ssh):\/\/(?:[^@/]+@)?github\.com\/|(?:[^@/:]+@)?github\.com:)([\w.-]+)\/([\w.-]+?)(?:\.git)?\/?$/i.exec(url.trim());
@@ -24,46 +24,12 @@ function githubUrl(repo) {
24
24
  export function checkoutOf(dir) {
25
25
  if (!existsSync(dir) || !statSync(dir).isDirectory())
26
26
  return undefined;
27
- const root = gitAnswer(["rev-parse", "--show-toplevel"], dir);
27
+ const root = checkoutAnswer(["rev-parse", "--show-toplevel"], dir);
28
28
  if (root === undefined)
29
29
  return undefined;
30
- const origin = gitAnswer(["config", "--get", "remote.origin.url"], root);
30
+ const origin = checkoutAnswer(["config", "--get", "remote.origin.url"], root);
31
31
  return { root, ...(origin ? { origin } : {}) };
32
32
  }
33
- /**
34
- * Why the directory `local` cannot stand for github `repo` on this machine, or undefined when it can: it is the root
35
- * of a checkout whose `origin` is that repository.
36
- */
37
- export function checkoutProblem(local, repo) {
38
- if (!existsSync(local))
39
- return "does not exist";
40
- const checkout = checkoutOf(local);
41
- if (checkout === undefined)
42
- return "is not a git checkout";
43
- if (realpathSync(checkout.root) !== realpathSync(local))
44
- return `is inside the checkout ${checkout.root}, not its root`;
45
- const of = checkout.origin === undefined ? undefined : githubRepoOf(checkout.origin);
46
- if (of?.toLowerCase() !== repo.toLowerCase()) {
47
- return `is a checkout of ${checkout.origin ?? "no origin"}, not of github ${repo}`;
48
- }
49
- return undefined;
50
- }
51
- /**
52
- * What to say when the checkout `dir` is not at `ref`, or undefined when it is: on that branch, or at the commit `ref`
53
- * names. FastAgent never moves a checkout the user owns, so this is said, not acted on.
54
- */
55
- export function refNotice(dir, ref) {
56
- const branch = gitAnswer(["symbolic-ref", "--quiet", "--short", "HEAD"], dir);
57
- if (branch === ref)
58
- return undefined;
59
- const head = gitAnswer(["rev-parse", "HEAD"], dir);
60
- const target = gitAnswer(["rev-parse", "--verify", "--quiet", "--end-of-options", `${ref}^{commit}`], dir);
61
- if (head !== undefined && head === target) {
62
- return undefined;
63
- }
64
- const at = branch ?? `a detached ${head?.slice(0, 7) ?? "HEAD"}`;
65
- return `the checkout is on ${at}, declared ${ref}; it is left as it is`;
66
- }
67
33
  /** A commit named in full: fetched by its hash, since `clone --branch` takes only a branch or a tag. */
68
34
  const FULL_COMMIT = /^[0-9a-f]{40}$/i;
69
35
  /**
@@ -97,7 +63,7 @@ const HELPER_KEY = "credential.https://github.com.helper";
97
63
  */
98
64
  export async function refreshClone(repo, ref, dir, env = process.env) {
99
65
  // The agent's environment, whose GITHUB_TOKEN the clone's credential helper reads.
100
- const { run: runGit } = gitFor(WHY, env);
66
+ const { run: runGit, answer: gitAnswer } = gitFor(WHY, env);
101
67
  // A library caller can hand this anything; git reads a leading "-" as an option, and no repository or ref has one
102
68
  // (a declaration with one is refused at load, declare.ts).
103
69
  if (repo.startsWith("-") || ref?.startsWith("-")) {
@@ -1,4 +1,4 @@
1
- import { type BoundContent, type ContentDeclaration, type DeclaredContent } from "./declare.ts";
1
+ import { type DeclaredContent } from "./declare.ts";
2
2
  import { type CloneOutcome } from "./git.ts";
3
3
  /** A content entry, resolved for this instance. */
4
4
  export type ResolvedContent = {
@@ -8,42 +8,38 @@ export type ResolvedContent = {
8
8
  description?: string;
9
9
  /** Where the agent reaches it on this instance, absolute. */
10
10
  location: string;
11
- /** What to tell the user about how it resolved: a checkout off its `ref`, a clone not made yet. */
11
+ /** What to tell the user about how it resolved: a clone not made yet. */
12
12
  notices: string[];
13
13
  } & ({
14
- /** A directory only this machine has, bound in `context.local.json`. */
14
+ /** A directory of this machine, where the instance configuration says. */
15
15
  kind: "local";
16
16
  } | {
17
+ /** A clone fastagent makes at `content/<name>` and brings up to date at each start while it holds nothing of the agent's. */
17
18
  kind: "github";
18
19
  /** `owner/repo`. */
19
20
  repo: string;
20
21
  ref?: string;
21
- /**
22
- * A clone fastagent makes at `content/<name>` and brings up to date at each start while it holds nothing of the
23
- * agent's. False when this machine binds its own checkout, which is never touched.
24
- */
25
- clone: boolean;
26
22
  });
23
+ /** The directories an instance's content is kept apart from. */
24
+ export interface ContentPlaces {
25
+ /** The definition's own directory, which is released and read as it is. */
26
+ dir: string;
27
+ /** The instance's working directory, where clones are made. */
28
+ workdir: string;
29
+ }
27
30
  /** Resolve the agent's content for this instance. Refuses, naming the entry, what cannot be. */
28
- export declare function resolveContent(agentDir: string, { declared, bound }: ContentDeclaration): ResolvedContent[];
31
+ export declare function resolveContent(declared: readonly DeclaredContent[], places: ContentPlaces): ResolvedContent[];
29
32
  /**
30
- * The bindings of a directory only this machine has that point at nothing here: the directory was moved or removed.
31
- * Not an error, since the binding is this machine's alone; the agent is not told of it, and whoever opens the agent
32
- * says so.
33
+ * Whether the content `name` can be the directory `target` of this machine: one that exists, and is apart from the
34
+ * definition's directory, since a definition is released, content is kept, and one directory cannot be both. The
35
+ * working directory is the instance's own writable place, so a directory inside it is only a directory the agent
36
+ * already reaches. Refuses, naming the entry, what cannot be.
33
37
  */
34
- export declare function contentAbsentHere({ bound }: ContentDeclaration): BoundContent[];
35
- /** What is said of a binding {@link contentAbsentHere} returns, after the word "content". */
36
- export declare function absentNotice(binding: BoundContent): string;
37
- /**
38
- * Whether the content `name` can be bound to the directory `target` of this machine: a directory, apart from the agent
39
- * directory, and for a declared repository the root of a checkout of it. Returns what to tell the user (a checkout off
40
- * its `ref`); refuses, naming the entry, what cannot be.
41
- */
42
- export declare function checkBinding(agentDir: string, name: string, target: string, repository?: Pick<DeclaredContent, "repo" | "ref">): string[];
38
+ export declare function checkDirectory({ dir }: Pick<ContentPlaces, "dir">, name: string, target: string): void;
43
39
  /**
44
40
  * Make a clone real, or bring it up to date at its `ref` in place, by git's rules, which never overwrite what the
45
41
  * agent did in it (git.ts `refreshClone`): what git refuses, or a remote that cannot be reached, keeps it as it is,
46
- * with the reason. Only a process that runs the agent calls this. A checkout this machine binds is never cloned over.
42
+ * with the reason. Only a process that runs the agent calls this.
47
43
  */
48
44
  export declare function cloneContent(entry: Extract<ResolvedContent, {
49
45
  kind: "github";