@fastagent-sh/fastagent 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (277) hide show
  1. package/README.md +16 -6
  2. package/dist/agent.d.ts +20 -0
  3. package/dist/agent.js +9 -0
  4. package/dist/channels/agentcore-limits.d.ts +7 -0
  5. package/dist/channels/agentcore-limits.js +9 -0
  6. package/dist/channels/agentcore-state.d.ts +83 -0
  7. package/dist/channels/agentcore-state.js +258 -0
  8. package/dist/channels/agentcore.d.ts +98 -0
  9. package/dist/channels/agentcore.js +260 -0
  10. package/dist/channels/busy.d.ts +23 -0
  11. package/dist/channels/busy.js +53 -0
  12. package/dist/channels/context-buffer.d.ts +35 -0
  13. package/dist/channels/context-buffer.js +103 -0
  14. package/dist/channels/control.d.ts +28 -0
  15. package/dist/channels/control.js +214 -0
  16. package/dist/channels/feishu/card.js +1 -1
  17. package/dist/channels/feishu/context-buffer.d.ts +15 -13
  18. package/dist/channels/feishu/context-buffer.js +62 -69
  19. package/dist/channels/feishu/feishu-api.d.ts +11 -3
  20. package/dist/channels/feishu/feishu-api.js +24 -3
  21. package/dist/channels/feishu/feishu.d.ts +27 -27
  22. package/dist/channels/feishu/feishu.js +318 -207
  23. package/dist/channels/feishu/invoke-turn.d.ts +7 -20
  24. package/dist/channels/feishu/invoke-turn.js +44 -79
  25. package/dist/channels/feishu/model.d.ts +2 -2
  26. package/dist/channels/feishu/normalize.d.ts +2 -1
  27. package/dist/channels/feishu/normalize.js +0 -1
  28. package/dist/channels/feishu/parse.d.ts +22 -8
  29. package/dist/channels/feishu/parse.js +24 -7
  30. package/dist/channels/feishu/preview.d.ts +4 -7
  31. package/dist/channels/feishu/preview.js +27 -142
  32. package/dist/channels/feishu/register-app.d.ts +2 -1
  33. package/dist/channels/feishu/register-webhook.d.ts +2 -1
  34. package/dist/channels/feishu/scaffold/channel.ts +9 -8
  35. package/dist/channels/feishu/scaffold/feishu-send.ts +6 -4
  36. package/dist/channels/feishu/setup-mode.d.ts +37 -0
  37. package/dist/channels/feishu/setup-mode.js +28 -0
  38. package/dist/channels/feishu/ws-ingress.d.ts +28 -0
  39. package/dist/channels/feishu/ws-ingress.js +136 -0
  40. package/dist/channels/github/github.js +16 -7
  41. package/dist/channels/http.d.ts +14 -0
  42. package/dist/channels/http.js +36 -3
  43. package/dist/channels/invoke-turn-kit.d.ts +65 -0
  44. package/dist/channels/invoke-turn-kit.js +87 -0
  45. package/dist/channels/lark/lark.d.ts +4 -2
  46. package/dist/channels/lark/lark.js +4 -1
  47. package/dist/channels/lark/onboard.d.ts +8 -4
  48. package/dist/channels/lark/onboard.js +8 -0
  49. package/dist/channels/lark/scaffold/channel.ts +9 -8
  50. package/dist/channels/lark/scaffold/lark-send.ts +6 -4
  51. package/dist/channels/preview-kit.d.ts +115 -0
  52. package/dist/channels/preview-kit.js +184 -0
  53. package/dist/channels/seen.d.ts +5 -0
  54. package/dist/channels/seen.js +35 -0
  55. package/dist/channels/slack/bot-auth.d.ts +15 -0
  56. package/dist/channels/slack/bot-auth.js +146 -0
  57. package/dist/channels/slack/config-api.d.ts +60 -0
  58. package/dist/channels/slack/config-api.js +149 -0
  59. package/dist/channels/slack/context-buffer.d.ts +24 -0
  60. package/dist/channels/slack/context-buffer.js +37 -0
  61. package/dist/channels/slack/invoke-turn.d.ts +19 -0
  62. package/dist/channels/slack/invoke-turn.js +63 -0
  63. package/dist/channels/slack/manifest.d.ts +49 -0
  64. package/dist/channels/slack/manifest.js +69 -0
  65. package/dist/channels/slack/model.d.ts +67 -0
  66. package/dist/channels/slack/model.js +2 -0
  67. package/dist/channels/slack/onboard.d.ts +41 -0
  68. package/dist/channels/slack/onboard.js +120 -0
  69. package/dist/channels/slack/onboarding-state.d.ts +31 -0
  70. package/dist/channels/slack/onboarding-state.js +69 -0
  71. package/dist/channels/slack/parse.d.ts +38 -0
  72. package/dist/channels/slack/parse.js +124 -0
  73. package/dist/channels/slack/preview.d.ts +23 -0
  74. package/dist/channels/slack/preview.js +403 -0
  75. package/dist/channels/slack/reaction.d.ts +24 -0
  76. package/dist/channels/slack/reaction.js +62 -0
  77. package/dist/channels/slack/register-webhook.d.ts +10 -0
  78. package/dist/channels/slack/register-webhook.js +49 -0
  79. package/dist/channels/slack/scaffold/channel.ts +33 -0
  80. package/dist/channels/slack/scaffold/slack-send.ts +171 -0
  81. package/dist/channels/slack/setup-server.d.ts +17 -0
  82. package/dist/channels/slack/setup-server.js +103 -0
  83. package/dist/channels/slack/slack-api.d.ts +57 -0
  84. package/dist/channels/slack/slack-api.js +399 -0
  85. package/dist/channels/slack/slack.d.ts +51 -0
  86. package/dist/channels/slack/slack.js +496 -0
  87. package/dist/channels/slack/welcomed.d.ts +5 -0
  88. package/dist/channels/slack/welcomed.js +32 -0
  89. package/dist/channels/state.d.ts +11 -4
  90. package/dist/channels/state.js +22 -15
  91. package/dist/channels/stop-command.d.ts +6 -0
  92. package/dist/channels/stop-command.js +36 -0
  93. package/dist/channels/tasks.d.ts +7 -0
  94. package/dist/channels/tasks.js +25 -0
  95. package/dist/channels/telegram/context-buffer.d.ts +8 -17
  96. package/dist/channels/telegram/context-buffer.js +6 -85
  97. package/dist/channels/telegram/invoke-turn.d.ts +5 -22
  98. package/dist/channels/telegram/invoke-turn.js +11 -58
  99. package/dist/channels/telegram/parse.d.ts +0 -7
  100. package/dist/channels/telegram/parse.js +4 -2
  101. package/dist/channels/telegram/preview.d.ts +4 -7
  102. package/dist/channels/telegram/preview.js +24 -142
  103. package/dist/channels/telegram/scaffold/telegram-send.ts +6 -3
  104. package/dist/channels/telegram/telegram.js +24 -10
  105. package/dist/channels/{feishu/text.d.ts → text.d.ts} +15 -1
  106. package/dist/channels/{feishu/text.js → text.js} +15 -1
  107. package/dist/channels/thread-participants.d.ts +21 -0
  108. package/dist/channels/thread-participants.js +132 -0
  109. package/dist/channels/turn-queue.js +8 -1
  110. package/dist/channels/turn-store.d.ts +1 -1
  111. package/dist/channels/turn-store.js +2 -3
  112. package/dist/cli/add-feishu.d.ts +30 -0
  113. package/dist/cli/add-feishu.js +366 -0
  114. package/dist/cli/add-slack.d.ts +11 -0
  115. package/dist/cli/add-slack.js +199 -0
  116. package/dist/{cli-auth.d.ts → cli/auth-view.d.ts} +1 -1
  117. package/dist/{cli-auth.js → cli/auth-view.js} +1 -1
  118. package/dist/cli/commands/add.d.ts +4 -0
  119. package/dist/cli/commands/add.js +191 -60
  120. package/dist/cli/commands/attach.d.ts +82 -0
  121. package/dist/cli/commands/attach.js +563 -0
  122. package/dist/cli/commands/chat.d.ts +1 -0
  123. package/dist/cli/commands/chat.js +12 -7
  124. package/dist/cli/commands/deploy.d.ts +3 -1
  125. package/dist/cli/commands/deploy.js +384 -82
  126. package/dist/cli/commands/dev.js +34 -26
  127. package/dist/cli/commands/fire.js +17 -18
  128. package/dist/cli/commands/info.js +36 -29
  129. package/dist/cli/commands/init.d.ts +1 -1
  130. package/dist/cli/commands/init.js +65 -53
  131. package/dist/cli/commands/invoke.js +11 -9
  132. package/dist/cli/commands/login.js +48 -45
  133. package/dist/cli/commands/models.js +1 -1
  134. package/dist/cli/commands/schedule.js +6 -8
  135. package/dist/cli/commands/start.js +102 -39
  136. package/dist/cli/commands/tool.js +23 -18
  137. package/dist/cli/fail.d.ts +17 -2
  138. package/dist/cli/fail.js +25 -1
  139. package/dist/{invoke-stream.d.ts → cli/invoke-stream.d.ts} +1 -1
  140. package/dist/{invoke-stream.js → cli/invoke-stream.js} +4 -0
  141. package/dist/cli/kernel.d.ts +3 -2
  142. package/dist/cli/models-view.d.ts +21 -0
  143. package/dist/cli/models-view.js +66 -0
  144. package/dist/cli/program.js +135 -56
  145. package/dist/cli/serve.d.ts +60 -20
  146. package/dist/cli/serve.js +252 -47
  147. package/dist/cli/shared.d.ts +40 -7
  148. package/dist/cli/shared.js +180 -38
  149. package/dist/collect.d.ts +14 -3
  150. package/dist/collect.js +24 -0
  151. package/dist/core.d.ts +3 -1
  152. package/dist/core.js +2 -0
  153. package/dist/deploy/agentcore/plan.d.ts +117 -0
  154. package/dist/deploy/agentcore/plan.js +721 -0
  155. package/dist/deploy/agentcore/run.d.ts +73 -0
  156. package/dist/deploy/agentcore/run.js +412 -0
  157. package/dist/deploy/agentcore/zip.d.ts +17 -0
  158. package/dist/deploy/agentcore/zip.js +68 -0
  159. package/dist/deploy/container.d.ts +26 -25
  160. package/dist/deploy/container.js +93 -89
  161. package/dist/deploy/docker/plan.d.ts +3 -3
  162. package/dist/deploy/docker/plan.js +20 -23
  163. package/dist/deploy/fly/plan.d.ts +5 -1
  164. package/dist/deploy/fly/plan.js +39 -26
  165. package/dist/deploy/fly/run.d.ts +17 -5
  166. package/dist/deploy/fly/run.js +52 -7
  167. package/dist/deploy/preflight.d.ts +20 -8
  168. package/dist/deploy/preflight.js +267 -71
  169. package/dist/deploy/railway/plan.d.ts +10 -1
  170. package/dist/deploy/railway/plan.js +53 -20
  171. package/dist/deploy/railway/run.d.ts +13 -5
  172. package/dist/deploy/railway/run.js +22 -7
  173. package/dist/deploy/runner.d.ts +7 -3
  174. package/dist/deploy/runner.js +9 -3
  175. package/dist/deploy/secrets.d.ts +2 -1
  176. package/dist/deploy/secrets.js +23 -3
  177. package/dist/dev-supervisor.d.ts +11 -10
  178. package/dist/dev-supervisor.js +56 -50
  179. package/dist/engines/pi/auth.d.ts +8 -7
  180. package/dist/engines/pi/auth.js +12 -10
  181. package/dist/engines/pi/channel.d.ts +22 -16
  182. package/dist/engines/pi/channel.js +92 -62
  183. package/dist/engines/pi/chat.d.ts +4 -16
  184. package/dist/engines/pi/chat.js +8 -261
  185. package/dist/engines/pi/config.d.ts +20 -55
  186. package/dist/engines/pi/config.js +49 -121
  187. package/dist/engines/pi/create.d.ts +30 -10
  188. package/dist/engines/pi/create.js +33 -26
  189. package/dist/engines/pi/definition.d.ts +7 -26
  190. package/dist/engines/pi/definition.js +8 -54
  191. package/dist/engines/pi/harness.d.ts +49 -0
  192. package/dist/engines/pi/harness.js +90 -2
  193. package/dist/engines/pi/invoke.d.ts +55 -2
  194. package/dist/engines/pi/invoke.js +304 -19
  195. package/dist/engines/pi/login.d.ts +12 -1
  196. package/dist/engines/pi/login.js +16 -4
  197. package/dist/engines/pi/models.d.ts +59 -13
  198. package/dist/engines/pi/models.js +62 -24
  199. package/dist/engines/pi/open.d.ts +114 -0
  200. package/dist/engines/pi/open.js +127 -0
  201. package/dist/engines/pi/session-builder.d.ts +16 -0
  202. package/dist/engines/pi/session-builder.js +308 -0
  203. package/dist/engines/pi/session-control.d.ts +50 -0
  204. package/dist/engines/pi/session-control.js +604 -0
  205. package/dist/engines/pi/sessions.d.ts +17 -2
  206. package/dist/engines/pi/sessions.js +9 -0
  207. package/dist/engines/pi/tool-context.d.ts +18 -11
  208. package/dist/engines/pi/tool-context.js +3 -9
  209. package/dist/engines/pi/tool.d.ts +6 -8
  210. package/dist/engines/pi/tool.js +10 -1
  211. package/dist/engines/pi/wake-tool.d.ts +0 -3
  212. package/dist/engines/pi/wake-tool.js +9 -7
  213. package/dist/env.d.ts +16 -4
  214. package/dist/env.js +43 -5
  215. package/dist/feishu.d.ts +1 -1
  216. package/dist/feishu.js +1 -1
  217. package/dist/host/node.d.ts +25 -8
  218. package/dist/host/node.js +5 -4
  219. package/dist/index.d.ts +1 -0
  220. package/dist/index.js +1 -0
  221. package/dist/lark.d.ts +1 -1
  222. package/dist/lark.js +1 -1
  223. package/dist/loader.d.ts +2 -2
  224. package/dist/loader.js +3 -3
  225. package/dist/log.d.ts +1 -1
  226. package/dist/log.js +1 -1
  227. package/dist/observe.js +3 -0
  228. package/dist/paths.d.ts +138 -0
  229. package/dist/paths.js +326 -0
  230. package/dist/pi.d.ts +6 -5
  231. package/dist/pi.js +4 -3
  232. package/dist/runtime.d.ts +7 -5
  233. package/dist/runtime.js +2 -2
  234. package/dist/scaffold/add-channel.d.ts +26 -9
  235. package/dist/scaffold/add-channel.js +175 -40
  236. package/dist/scaffold/init.d.ts +32 -41
  237. package/dist/scaffold/init.js +161 -185
  238. package/dist/scaffold/templates/env.example +15 -6
  239. package/dist/scaffold/templates/fastagent.config.mjs +5 -4
  240. package/dist/scaffold/templates/gitignore +14 -6
  241. package/dist/scaffold/templates/persona.md +4 -2
  242. package/dist/scaffold/templates/secrets.gitignore +5 -0
  243. package/dist/scaffold/templates.d.ts +1 -7
  244. package/dist/scaffold/templates.js +3 -25
  245. package/dist/scaffold/vendor-skill.d.ts +2 -2
  246. package/dist/scaffold/vendor-skill.js +13 -13
  247. package/dist/schedule/discover.js +4 -4
  248. package/dist/schedule/scheduler.d.ts +40 -1
  249. package/dist/schedule/scheduler.js +89 -56
  250. package/dist/schedule/state.js +1 -1
  251. package/dist/schedule/wake-alarm.d.ts +47 -0
  252. package/dist/schedule/wake-alarm.js +136 -0
  253. package/dist/schedule/wakeups.d.ts +1 -3
  254. package/dist/schedule/wakeups.js +19 -1
  255. package/dist/session-remote.d.ts +53 -0
  256. package/dist/session-remote.js +336 -0
  257. package/dist/session.d.ts +265 -0
  258. package/dist/session.js +37 -0
  259. package/dist/slack.d.ts +2 -0
  260. package/dist/slack.js +2 -0
  261. package/dist/tunnel.d.ts +7 -4
  262. package/dist/tunnel.js +23 -12
  263. package/package.json +22 -7
  264. package/dist/channels/feishu/owned-threads.d.ts +0 -11
  265. package/dist/channels/feishu/owned-threads.js +0 -47
  266. package/dist/channels/feishu/seen.d.ts +0 -5
  267. package/dist/channels/feishu/seen.js +0 -47
  268. package/dist/cli-add-feishu.d.ts +0 -8
  269. package/dist/cli-add-feishu.js +0 -223
  270. package/dist/cli-models.d.ts +0 -11
  271. package/dist/cli-models.js +0 -20
  272. package/dist/engines/pi/workspace.d.ts +0 -56
  273. package/dist/engines/pi/workspace.js +0 -72
  274. package/dist/scaffold/templates/gitignore.agentdir-root +0 -5
  275. package/dist/scaffold/templates/gitignore.kit +0 -2
  276. package/dist/workspace.d.ts +0 -9
  277. package/dist/workspace.js +0 -45
package/dist/tunnel.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * `--tunnel`: expose the local dev server on a public HTTPS URL via a Cloudflare quick tunnel, then
3
- * auto-register the first-party webhook channels against it (Telegram setWebhook; Feishu/Lark
4
- * application-config PATCH; GitHub prints the URL to paste into repo settings). This closes the
3
+ * auto-register the first-party webhook channels against it (Telegram setWebhook; onboarded Slack
4
+ * App Manifest update; Feishu/Lark application-config PATCH; GitHub/manual Slack print URLs). This closes the
5
5
  * "local dev → public URL" gap webhooks need.
6
6
  *
7
7
  * Process orchestration, not assembly — lives outside the engine, beside dev-supervisor.ts.
@@ -25,10 +25,13 @@ type SpawnCloudflared = (port: number) => ChildProcess;
25
25
  */
26
26
  export declare function startCloudflareTunnel(port: number, spawnFn?: SpawnCloudflared, attemptTimeoutMs?: number): Promise<Tunnel | undefined>;
27
27
  /**
28
- * Print the public URL and wire up the first-party webhook channels found under `dir`: Telegram and
29
- * Feishu/Lark auto-register using credentials from .env; GitHub prints the URL to add in repo settings.
28
+ * Print the public URL and wire up first-party webhook channels found under `dir` (the agent
29
+ * ROOT): Telegram and Feishu/Lark use runtime credentials; onboarded Slack uses its owner-local config
30
+ * token; GitHub and a manually scaffolded Slack app receive explicit console URLs.
30
31
  */
31
32
  export declare function announceWebhooks(dir: string, baseUrl: string, opts?: {
32
33
  openUrl?: (url: string) => void;
34
+ routeChannels?: string[];
35
+ stateRoot?: string;
33
36
  }): Promise<void>;
34
37
  export {};
package/dist/tunnel.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * `--tunnel`: expose the local dev server on a public HTTPS URL via a Cloudflare quick tunnel, then
3
- * auto-register the first-party webhook channels against it (Telegram setWebhook; Feishu/Lark
4
- * application-config PATCH; GitHub prints the URL to paste into repo settings). This closes the
3
+ * auto-register the first-party webhook channels against it (Telegram setWebhook; onboarded Slack
4
+ * App Manifest update; Feishu/Lark application-config PATCH; GitHub/manual Slack print URLs). This closes the
5
5
  * "local dev → public URL" gap webhooks need.
6
6
  *
7
7
  * Process orchestration, not assembly — lives outside the engine, beside dev-supervisor.ts.
@@ -10,8 +10,10 @@ import { spawn } from "node:child_process";
10
10
  import { readdirSync } from "node:fs";
11
11
  import { join } from "node:path";
12
12
  import { registerFeishuWebhook } from "./channels/feishu/register-webhook.js";
13
+ import { registerSlackWebhook } from "./channels/slack/register-webhook.js";
13
14
  import { registerTelegramWebhook } from "./channels/telegram/register-webhook.js";
14
- import { loadDotEnv } from "./env.js";
15
+ import { dotEnvPath, loadDotEnv } from "./env.js";
16
+ import { resolveStateRoot } from "./paths.js";
15
17
  import { log } from "./log.js";
16
18
  // `(?!api\.)`: cloudflared's ERROR lines mention its request endpoint (`https://api.trycloudflare.com/tunnel`,
17
19
  // e.g. "failed to request quick Tunnel: Post ... timeout" under a flaky proxy) — without the exclusion a
@@ -116,8 +118,9 @@ function channelBasenames(dir) {
116
118
  }
117
119
  }
118
120
  /**
119
- * Print the public URL and wire up the first-party webhook channels found under `dir`: Telegram and
120
- * Feishu/Lark auto-register using credentials from .env; GitHub prints the URL to add in repo settings.
121
+ * Print the public URL and wire up first-party webhook channels found under `dir` (the agent
122
+ * ROOT): Telegram and Feishu/Lark use runtime credentials; onboarded Slack uses its owner-local config
123
+ * token; GitHub and a manually scaffolded Slack app receive explicit console URLs.
121
124
  */
122
125
  export async function announceWebhooks(dir, baseUrl, opts = {}) {
123
126
  log.info(`[fastagent] public URL: ${baseUrl}`);
@@ -130,27 +133,35 @@ export async function announceWebhooks(dir, baseUrl, opts = {}) {
130
133
  // void-called with no unhandledRejection handler, so a throw here would terminate the process. Warn
131
134
  // (surface it, rule 8) and continue best-effort; each registrar then surfaces its own
132
135
  // missing-credential guidance. loadDotEnv keeps throwing for the synchronous command callers.
133
- log.warn(`[fastagent] could not read ${join(dir, ".env")}: ${error.message} — continuing without it`);
136
+ log.warn(`[fastagent] could not read ${dotEnvPath(dir)}: ${error.message} — continuing without it`);
134
137
  }
135
- const channels = channelBasenames(dir);
136
- if (channels.length === 0)
138
+ // Serving passes the validated route-channel subset. The basename fallback preserves the public
139
+ // helper's behavior for callers that did not assemble channels first.
140
+ const routeChannels = opts.routeChannels ?? channelBasenames(dir);
141
+ if (routeChannels.length === 0)
137
142
  return;
138
143
  // Readiness is the registrar's job now: a fresh quick tunnel returns Cloudflare 530 for ~20-30s before
139
144
  // its origin connects, and the automatic registrars poll /health before configuring the platform (the
140
145
  // same wait the deploy runners rely on). GitHub needs no wait — the operator adds that webhook by hand.
141
- if (channels.includes("telegram"))
146
+ if (routeChannels.includes("telegram"))
142
147
  await registerTelegramWebhook(baseUrl);
143
- if (channels.includes("github")) {
148
+ if (routeChannels.includes("github")) {
144
149
  log.info(`[fastagent] github: add a webhook in your repo (Settings → Webhooks): Payload URL = ${baseUrl}/webhook, content type application/json, secret = GITHUB_WEBHOOK_SECRET`);
145
150
  }
151
+ if (routeChannels.includes("slack")) {
152
+ await registerSlackWebhook(baseUrl, {
153
+ stateRoot: opts.stateRoot ?? resolveStateRoot(dir),
154
+ log: (message) => log.info(message),
155
+ });
156
+ }
146
157
  // feishu/lark register programmatically too (application-v7 config PATCH — telegram-setWebhook
147
158
  // parity), once per mounted kind (each kind is its own app with its own credentials); the registrar
148
159
  // owns its own health wait and degrades to the manual console instruction.
149
160
  const feishuOptions = {
150
161
  onManualRegistration: ({ consoleUrl }) => opts.openUrl?.(consoleUrl),
151
162
  };
152
- if (channels.includes("feishu"))
163
+ if (routeChannels.includes("feishu"))
153
164
  await registerFeishuWebhook(baseUrl, "feishu", feishuOptions);
154
- if (channels.includes("lark"))
165
+ if (routeChannels.includes("lark"))
155
166
  await registerFeishuWebhook(baseUrl, "lark", feishuOptions);
156
167
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fastagent-sh/fastagent",
3
- "version": "0.14.0",
4
- "description": "Vibe first. Then FastAgent: turn a local agent directory into a live service in your app, on GitHub, in Telegram, or behind any channel.",
3
+ "version": "0.16.0",
4
+ "description": "Vibe first. Then FastAgent: turn a local agent directory into a live service in your app, on GitHub, Telegram, Slack, or behind any channel.",
5
5
  "keywords": [
6
6
  "agent",
7
7
  "ai-agent",
@@ -10,6 +10,7 @@
10
10
  "agent-skills",
11
11
  "agent-serving",
12
12
  "telegram",
13
+ "slack",
13
14
  "github",
14
15
  "webhook",
15
16
  "sse",
@@ -42,6 +43,10 @@
42
43
  "types": "./dist/core.d.ts",
43
44
  "default": "./dist/core.js"
44
45
  },
46
+ "./session": {
47
+ "types": "./dist/session.d.ts",
48
+ "default": "./dist/session.js"
49
+ },
45
50
  "./pi": {
46
51
  "types": "./dist/pi.d.ts",
47
52
  "default": "./dist/pi.js"
@@ -54,6 +59,10 @@
54
59
  "types": "./dist/telegram.d.ts",
55
60
  "default": "./dist/telegram.js"
56
61
  },
62
+ "./slack": {
63
+ "types": "./dist/slack.d.ts",
64
+ "default": "./dist/slack.js"
65
+ },
57
66
  "./feishu": {
58
67
  "types": "./dist/feishu.d.ts",
59
68
  "default": "./dist/feishu.js"
@@ -82,15 +91,20 @@
82
91
  "prepack": "npm run build",
83
92
  "test": "vitest --run",
84
93
  "typecheck": "tsc --noEmit",
85
- "lint": "biome check src test && node scripts/check-doc-links.mjs",
94
+ "lint": "biome check src test && node scripts/check-doc-links.mjs && knip",
86
95
  "format": "biome check --write src test",
87
- "postbuild": "node scripts/copy-scaffold-assets.mjs"
96
+ "postbuild": "node scripts/copy-scaffold-assets.mjs",
97
+ "release:patch": "node scripts/release.mjs patch",
98
+ "release:minor": "node scripts/release.mjs minor",
99
+ "release:major": "node scripts/release.mjs major",
100
+ "knip": "knip"
88
101
  },
89
102
  "dependencies": {
90
103
  "@clack/prompts": "^1.6.0",
91
- "@earendil-works/pi-agent-core": "^0.80.10",
92
- "@earendil-works/pi-ai": "^0.80.10",
93
- "@earendil-works/pi-coding-agent": "^0.80.10",
104
+ "@earendil-works/pi-agent-core": "^0.81.1",
105
+ "@earendil-works/pi-ai": "^0.81.1",
106
+ "@earendil-works/pi-coding-agent": "^0.81.1",
107
+ "@larksuiteoapi/node-sdk": "^1.71.1",
94
108
  "@octokit/webhooks-methods": "^6.0.0",
95
109
  "@octokit/webhooks-types": "^7.6.1",
96
110
  "chokidar": "^5.0.0",
@@ -105,6 +119,7 @@
105
119
  "devDependencies": {
106
120
  "@biomejs/biome": "^2.5.2",
107
121
  "@types/proper-lockfile": "^4.1.4",
122
+ "knip": "^6.29.0",
108
123
  "typescript": "^7.0.2",
109
124
  "vitest": "^4.1.9"
110
125
  }
@@ -1,11 +0,0 @@
1
- export interface OwnedFeishuThread {
2
- rootId: string;
3
- chatId: string;
4
- createdAt: number;
5
- }
6
- export interface OwnedFeishuThreads {
7
- has(chatId: string, rootId: string): boolean;
8
- /** Idempotent, synchronous, pre-ACK persistence. A failed write throws so the platform redelivers. */
9
- add(chatId: string, rootId: string): void;
10
- }
11
- export declare function createOwnedFeishuThreads(path: string, label: string, now?: () => number): OwnedFeishuThreads;
@@ -1,47 +0,0 @@
1
- /**
2
- * Durable ownership index for group threads the channel created from a top-level summon. Feishu/Lark
3
- * deliver an ordinary thread continuation as `thread_id + root_id`; the root is the original user
4
- * message the channel reply-threaded under. Keeping that root across restarts lets the default route
5
- * admit unmentioned continuations only inside Agent-managed threads, never across the whole group.
6
- */
7
- import { log } from "../../log.js";
8
- import { loadStateFile, saveStateFile } from "../state.js";
9
- function isRecord(value) {
10
- const record = value;
11
- return (typeof record?.rootId === "string" &&
12
- typeof record.chatId === "string" &&
13
- typeof record.createdAt === "number" &&
14
- Number.isFinite(record.createdAt));
15
- }
16
- export function createOwnedFeishuThreads(path, label, now = Date.now) {
17
- const raw = loadStateFile(path);
18
- let records = new Map();
19
- if (raw !== undefined) {
20
- if (typeof raw === "object" &&
21
- raw !== null &&
22
- !Array.isArray(raw) &&
23
- Object.entries(raw).every(([rootId, record]) => isRecord(record) && record.rootId === rootId)) {
24
- records = new Map(Object.entries(raw));
25
- }
26
- else {
27
- log.warn(`${label} unexpected shape in ${path} — starting with no managed group threads`);
28
- }
29
- }
30
- return {
31
- has(chatId, rootId) {
32
- const record = records.get(rootId);
33
- return record?.chatId === chatId;
34
- },
35
- add(chatId, rootId) {
36
- const existing = records.get(rootId);
37
- if (existing?.chatId === chatId)
38
- return;
39
- const next = new Map(records);
40
- next.set(rootId, { rootId, chatId, createdAt: now() });
41
- // Persist the staged copy first: an IO failure must not leave memory claiming durability the file
42
- // does not have. The webhook remains un-ACKed and the platform can redeliver after recovery.
43
- saveStateFile(path, Object.fromEntries(next));
44
- records = next;
45
- },
46
- };
47
- }
@@ -1,5 +0,0 @@
1
- export interface SeenRing {
2
- has(id: string): boolean;
3
- add(id: string): void;
4
- }
5
- export declare function createSeenRing(path: string, label?: string, cap?: number): SeenRing;
@@ -1,47 +0,0 @@
1
- /**
2
- * Bounded delivery dedup for message_ids whose webhook handling produced a durable side effect: either
3
- * an accepted turn intent or a buffered group-context entry. Feishu/Lark document duplicate pushes even
4
- * after a successful 200 and recommend idempotency on message_id (not event_id). The unfinished-turn
5
- * store cannot cover a duplicate after completion, and a duplicated background event would otherwise be
6
- * folded twice.
7
- *
8
- * Record only AFTER the pre-ACK side effect is durable: recording first could turn a later state-write
9
- * failure into silent loss when the platform redelivers. The ring write is best-effort post-persist
10
- * insurance. A crash between the two writes, a ring-write failure, or an id older than the bounded cap
11
- * retains L1's at-least-once tail; this is dedup, not exactly-once execution.
12
- */
13
- import { log } from "../../log.js";
14
- import { loadStateFile, saveStateFile } from "../state.js";
15
- export function createSeenRing(path, label = "[feishu]", cap = 2000) {
16
- const load = () => {
17
- const raw = loadStateFile(path);
18
- if (raw === undefined)
19
- return [];
20
- if (Array.isArray(raw) && raw.every((id) => typeof id === "string"))
21
- return raw.slice(-cap);
22
- log.warn(`${label} unexpected shape in ${path} — starting with no seen ids`);
23
- return [];
24
- };
25
- const order = load();
26
- const ids = new Set(order);
27
- return {
28
- has: (id) => ids.has(id),
29
- add(id) {
30
- if (ids.has(id))
31
- return;
32
- ids.add(id);
33
- order.push(id);
34
- while (order.length > cap) {
35
- const evicted = order.shift();
36
- if (evicted !== undefined)
37
- ids.delete(evicted);
38
- }
39
- try {
40
- saveStateFile(path, order);
41
- }
42
- catch (error) {
43
- log.warn(`${label} seen-ring write failed (delivery dedup is in-memory until restart): ${String(error)}`);
44
- }
45
- },
46
- };
47
- }
@@ -1,8 +0,0 @@
1
- /**
2
- * Create or resume the platform app behind `add feishu` / `add lark`. Returns credentials for the
3
- * caller's generic .env write (the guided Lark path), or undefined when nothing remains to write —
4
- * the feishu path persists its own two credential stages internally (the App ID/Secret boundary is
5
- * irreversible and must not wait for the caller). Throws on refusal (a committable .env, a
6
- * non-interactive lark run); the caller surfaces that as a startup failure.
7
- */
8
- export declare function onboardFeishuCloudApp(target: string, kind: "feishu" | "lark", envIgnored: boolean): Promise<Record<string, string> | undefined>;
@@ -1,223 +0,0 @@
1
- /**
2
- * `fastagent add feishu|lark` app onboarding — the cloud-facing half of runAdd, kept out of cli.ts
3
- * (which self-executes on import), mirroring cli-models.ts/cli-auth.ts. The POLICY already lives in
4
- * testable modules (register-app.ts, bootstrap-token.ts, lark/onboard.ts); this layer is the terminal
5
- * wiring: clack prompts, .env staging, browser opens, progress lines.
6
- *
7
- * Feishu (scan-to-create): the device flow creates the app; App ID/Secret are persisted at the
8
- * irreversible creation boundary, then the Verification Token is captured over a throwaway tunnel and
9
- * persisted as a second stage — a re-run RESUMES the app instead of minting another. Lark
10
- * (guided-console): open the unbound launcher, validate entered credentials, probe the same
11
- * webhook/token bootstrap, and fall back to a manual token prompt on the definitive config-route 404.
12
- */
13
- import { readFile } from "node:fs/promises";
14
- import { join } from "node:path";
15
- import { isCancel, log as clackLog, password, text as clackText } from "@clack/prompts";
16
- import { bootstrapFeishuVerificationToken } from "./channels/feishu/bootstrap-token.js";
17
- import { cloudFor } from "./channels/feishu/cloud.js";
18
- import { createFeishuApi, isFeishuConfigApiMissing, isTransientFeishuRegistrationError, } from "./channels/feishu/feishu-api.js";
19
- import { registerFeishuApp } from "./channels/feishu/register-app.js";
20
- import { onboardLarkApp } from "./channels/lark/onboard.js";
21
- import { parseEnvContent } from "./env.js";
22
- import { openExternalUrl } from "./open-url.js";
23
- import { appendChannelDotEnv } from "./scaffold/add-channel.js";
24
- import { startCloudflareTunnel } from "./tunnel.js";
25
- /**
26
- * Create or resume the platform app behind `add feishu` / `add lark`. Returns credentials for the
27
- * caller's generic .env write (the guided Lark path), or undefined when nothing remains to write —
28
- * the feishu path persists its own two credential stages internally (the App ID/Secret boundary is
29
- * irreversible and must not wait for the caller). Throws on refusal (a committable .env, a
30
- * non-interactive lark run); the caller surfaces that as a startup failure.
31
- */
32
- export async function onboardFeishuCloudApp(target, kind, envIgnored) {
33
- const { envPrefix, apiBase, capabilities } = cloudFor(kind);
34
- // The CLI must never materialize a real credential into a committable file — refuse, don't warn.
35
- if (!envIgnored) {
36
- throw new Error(kind === "feishu"
37
- ? "`add feishu` creates an app and writes real credentials to .env — add .env to .gitignore/.fastagentignore first, then re-run"
38
- : "`add lark` writes real app credentials to .env — add .env to .gitignore/.fastagentignore first, then re-run");
39
- }
40
- const existing = await activeDotEnvValues(target, [
41
- `${envPrefix}_APP_ID`,
42
- `${envPrefix}_APP_SECRET`,
43
- `${envPrefix}_VERIFICATION_TOKEN`,
44
- ]);
45
- if (Object.keys(existing).length === 3) {
46
- console.error(`[fastagent] ${envPrefix}_APP_ID/SECRET/VERIFICATION_TOKEN already set in .env — keeping them`);
47
- return undefined;
48
- }
49
- if (capabilities.appCreation === "scan-to-create") {
50
- await createFeishuAppFlow(target, existing);
51
- return undefined;
52
- }
53
- // guided-console (lark): the intl cloud cannot complete the bound device flow — collect + validate.
54
- if (!(process.stdin.isTTY && process.stdout.isTTY)) {
55
- throw new Error("`add lark` needs an interactive terminal to onboard the Lark app credentials — re-run it in a terminal");
56
- }
57
- return onboardLarkApp({
58
- openUrl: openExternalUrl,
59
- note: (message) => clackLog.info(message),
60
- async prompt(message, opts) {
61
- const result = opts?.hidden ? await password({ message }) : await clackText({ message });
62
- return isCancel(result) ? undefined : result;
63
- },
64
- }, {
65
- existing,
66
- verifyCredentials: async (appId, appSecret) => {
67
- await createFeishuApi({ kind: "lark", baseUrl: apiBase, appId, appSecret }).verifyCredentials();
68
- console.error(`[fastagent] Lark App ID / Secret verified`);
69
- },
70
- bootstrapWebhook: async (appId, appSecret) => {
71
- const api = createFeishuApi({ kind: "lark", baseUrl: apiBase, appId, appSecret });
72
- console.error(`[fastagent] trying Lark's webhook-mode + Verification-Token bootstrap (temporary tunnel)…`);
73
- try {
74
- const token = await bootstrapFeishuVerificationToken({
75
- api,
76
- appId,
77
- kind: "lark",
78
- startTunnel: (port) => startCloudflareTunnel(port),
79
- onTunnelReady: (url) => console.error(`[fastagent] temporary tunnel ready → ${url}; registering webhook mode now…`),
80
- onPatchRetry: ({ error, attempt, attempts, retryMs }) => console.error(`[fastagent] Lark could not validate the fresh tunnel yet (${String(error)}); retrying PATCH ${attempt + 1}/${attempts} in ${Math.round(retryMs / 1000)}s…`),
81
- // A route-level 404 is definitive, not edge weather: fall back immediately. Retry only
82
- // actual edge/network weather; scope/auth/config failures remain immediate.
83
- shouldRetryPatch: (error) => !isFeishuConfigApiMissing(error) && isTransientFeishuRegistrationError(error),
84
- });
85
- console.error(`[fastagent] Lark Verification Token captured; Subscription mode changed to webhook in the app draft`);
86
- return { token };
87
- }
88
- catch (error) {
89
- if (!isFeishuConfigApiMissing(error))
90
- throw error;
91
- const manualReason = "This Lark app returned HTTP 404 for the application-config API, so automatic mode/token bootstrap is unavailable.";
92
- console.error(`[fastagent] ${manualReason}`);
93
- return { manualReason };
94
- }
95
- },
96
- });
97
- }
98
- /**
99
- * The scan-to-create flow `add feishu` runs by default. The device-authorization grant
100
- * creates a pre-configured agent app (bot capability, messaging scopes, event subscriptions) when the
101
- * user confirms a link in the app, and hands back the credentials; App ID/Secret are persisted at that
102
- * irreversible boundary before the platform-generated Verification Token is captured from the
103
- * registration challenge (bootstrap-token.ts). The Token is persisted as a second stage, so .env is
104
- * complete before the one remaining version-publish action. The event Request URL is NOT left pointing at the throwaway
105
- * tunnel for long: `dev --tunnel` / `deploy --run` re-register it against the live URL.
106
- *
107
- * Feishu is the reference cloud and the only kind that runs this BOUND device flow. Lark is an explicit
108
- * compatibility profile: its lagging control plane uses the unbound launcher + guided credentials,
109
- * then probes the canonical token/mode bootstrap with a manual fallback.
110
- */
111
- async function createFeishuAppFlow(target, existing) {
112
- const { apiBase } = cloudFor("feishu");
113
- let appId = existing.FEISHU_APP_ID;
114
- let appSecret = existing.FEISHU_APP_SECRET;
115
- if (appId && appSecret) {
116
- console.error(`[fastagent] resuming Feishu app ${appId} from .env to capture its missing Verification Token`);
117
- }
118
- else {
119
- console.error(`[fastagent] creating the Feishu app (confirm in the app)…`);
120
- const app = await registerFeishuApp({
121
- name: "{user}'s agent", // the platform expands {user} to the confirming user's name; editable on the page
122
- desc: "Served by fastagent",
123
- // The agent template alone is not enough to SERVE: the v7 config PATCH (webhook auto-registration
124
- // in `dev --tunnel` / `deploy --run`) demands application:application:patch, and the app must
125
- // subscribe the receive event. Addons merge both onto the confirm page — no manual app setup.
126
- addons: {
127
- scopes: { tenant: ["application:application:patch"] },
128
- events: { items: { tenant: ["im.message.receive_v1"] } },
129
- },
130
- onVerificationUrl: ({ url, expiresInS }) => {
131
- console.error(`\n Opening the confirmation link in your browser (or open it in Feishu / render it as a QR code) — valid for ${Math.round(expiresInS / 60)} minutes:\n\n ${url}\n\n waiting for confirmation… (keep this running — the credentials are delivered here)`);
132
- openExternalUrl(url); // best-effort, like `login` — the URL above is the fallback
133
- },
134
- });
135
- console.error(`[fastagent] app created: ${app.appId}${app.tenantBrand ? ` (${app.tenantBrand} tenant)` : ""}`);
136
- // A cross-brand confirmation should be impossible (each confirm page refuses the other brand's
137
- // code) — but if the platform ever reports one, the credentials would land in the WRONG kind's env
138
- // namespace and serve the wrong cloud. Fail visibly instead of writing them.
139
- if (app.tenantBrand && app.tenantBrand !== "feishu") {
140
- throw new Error(`the confirming account is a ${app.tenantBrand} tenant, but this is \`add feishu\` — run \`fastagent add ${app.tenantBrand}\` instead`);
141
- }
142
- appId = app.appId;
143
- appSecret = app.appSecret;
144
- // IRREVERSIBLE BOUNDARY: the remote app now exists and its one-time Secret is in memory. Persist
145
- // both before any config read, temporary tunnel, or Token bootstrap can be interrupted. Partial old
146
- // lines are overwritten because these newly-minted credentials are authoritative as one pair.
147
- await appendChannelDotEnv(target, "feishu", {
148
- FEISHU_APP_ID: appId,
149
- FEISHU_APP_SECRET: appSecret,
150
- // A Token from a partial OLD credential set belongs to another App. Clear it at the same
151
- // boundary; successful bootstrap below replaces the empty line with this App's Token.
152
- FEISHU_VERIFICATION_TOKEN: "",
153
- }, ["FEISHU_APP_ID", "FEISHU_APP_SECRET", "FEISHU_VERIFICATION_TOKEN"]);
154
- console.error(`[fastagent] wrote FEISHU_APP_ID, FEISHU_APP_SECRET to .env before Token bootstrap`);
155
- }
156
- // The webhook channel authenticates plaintext events by the platform-generated Verification Token.
157
- // Try the cheap read first (the v6 detail MAY someday return `encryption`), then the real path: the
158
- // token's only programmatic delivery is the url_verification challenge during registration — capture
159
- // it over a throwaway tunnel (bootstrap-token.ts). Failing both is a one-line manual copy; the staged
160
- // ID/Secret pair makes a re-run resume this App rather than mint another one.
161
- const tokenVar = "FEISHU_VERIFICATION_TOKEN";
162
- const api = createFeishuApi({ baseUrl: apiBase, appId, appSecret });
163
- let token;
164
- let webhookModeChanged = false;
165
- try {
166
- const cfg = await api.getAppConfig(appId);
167
- token = cfg.verificationToken;
168
- }
169
- catch {
170
- /* the read surface is best-effort — the bootstrap below is the real path */
171
- }
172
- if (!token) {
173
- console.error(`[fastagent] capturing the Verification Token — a throwaway webhook registration delivers it (spinning up a temporary tunnel; can take a few minutes on a slow edge)…`);
174
- try {
175
- token = await bootstrapFeishuVerificationToken({
176
- api,
177
- appId,
178
- startTunnel: (port) => startCloudflareTunnel(port),
179
- });
180
- webhookModeChanged = true;
181
- console.error(`[fastagent] Verification Token captured`);
182
- }
183
- catch (e) {
184
- // Transient tunnel weather is the usual cause. Do NOT suggest re-running `add feishu` as a new
185
- // scan: the staged pair makes the re-run resume THIS app; manual copy completes it too.
186
- console.error(`[fastagent] warn: could not capture the Verification Token: ${String(e)} — usually a transient tunnel issue; finish this app with the manual copy below`);
187
- }
188
- }
189
- if (token) {
190
- // Persist the second credential stage immediately too — opening the publish page and generic
191
- // scaffold finalization happen only after the complete runtime credential set is durable.
192
- const staged = await appendChannelDotEnv(target, "feishu", { [tokenVar]: token }, [tokenVar]);
193
- console.error(`[fastagent] wrote ${staged.written.join(", ")} to .env`);
194
- }
195
- else {
196
- console.error(`[fastagent] copy it manually: developer console → Events & Callbacks → Encryption Strategy → Verification Token → ${tokenVar} in .env`);
197
- }
198
- if (webhookModeChanged) {
199
- // The bootstrap's PATCH flipped event mode in the DRAFT. It takes effect only after a version
200
- // publish, which has no API; later dev/deploy runs change only the Request URL immediately.
201
- const versionUrl = `${apiBase}/app/${appId}/version`;
202
- console.error(`[fastagent] one console click remains: CREATE + PUBLISH a version (self-approved) — the switch to webhook mode takes effect on publish. Opening ${versionUrl}`);
203
- openExternalUrl(versionUrl);
204
- }
205
- }
206
- /** Active run-root `.env` values for the requested names — decided by THE .env parser, so this
207
- * check can never disagree with what `loadEnvFile` reads. Empty/commented values are absent. */
208
- async function activeDotEnvValues(dir, names) {
209
- let content;
210
- try {
211
- content = await readFile(join(dir, ".env"), "utf8");
212
- }
213
- catch (e) {
214
- if (e.code === "ENOENT")
215
- return {};
216
- throw e;
217
- }
218
- const parsed = parseEnvContent(content);
219
- return Object.fromEntries(names.flatMap((name) => {
220
- const value = parsed.get(name)?.trim();
221
- return value ? [[name, value]] : [];
222
- }));
223
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * CLI presenter for `fastagent models [search]`: the stdout/stderr output DECISION, kept out of the
3
- * engine config layer (config.ts owns model resolution / listModels) so this process-boundary behavior
4
- * is unit-testable without spawning the CLI.
5
- */
6
- /** The output of `fastagent models [search]`: the spec `lines` to print to stdout (a case-insensitive
7
- * substring filter; no search → all), and an stderr `error` diagnostic when a search matches nothing. */
8
- export declare function formatModelsCommand(specs: string[], search?: string): {
9
- lines: string[];
10
- error?: string;
11
- };
@@ -1,20 +0,0 @@
1
- /**
2
- * CLI presenter for `fastagent models [search]`: the stdout/stderr output DECISION, kept out of the
3
- * engine config layer (config.ts owns model resolution / listModels) so this process-boundary behavior
4
- * is unit-testable without spawning the CLI.
5
- */
6
- /** The output of `fastagent models [search]`: the spec `lines` to print to stdout (a case-insensitive
7
- * substring filter; no search → all), and an stderr `error` diagnostic when a search matches nothing. */
8
- export function formatModelsCommand(specs, search) {
9
- if (!search)
10
- return { lines: specs };
11
- const q = search.toLowerCase();
12
- const matches = specs.filter((spec) => spec.toLowerCase().includes(q));
13
- if (matches.length === 0)
14
- return { lines: matches, error: `no model matches "${search}"` };
15
- // Rank a PROVIDER-name match (query in the part before "/") above an incidental model-id match, so
16
- // `models anthropic` leads with anthropic/* rather than burying it under amazon-bedrock/anthropic.*
17
- // and google-vertex/…-anthropic-… (which only match in the model id). Order within each group is kept.
18
- const providerMatch = (spec) => spec.slice(0, spec.indexOf("/")).toLowerCase().includes(q);
19
- return { lines: [...matches.filter(providerMatch), ...matches.filter((s) => !providerMatch(s))] };
20
- }
@@ -1,56 +0,0 @@
1
- import type { Agent } from "../../agent.ts";
2
- import { type FastagentConfig } from "./config.ts";
3
- import type { ModuleLoadFailure } from "../../loader.ts";
4
- import { type LoadedDefinition } from "./definition.ts";
5
- import type { ToolCollision } from "./tool.ts";
6
- export interface CreatePiAgentFromWorkspaceOptions {
7
- /** Model spec override (e.g. the CLI --model flag). Precedence: this > FASTAGENT_MODEL > config.model. */
8
- model?: string;
9
- /**
10
- * Session store directory. Default `<dir>/.fastagent/sessions` (gitignored machine state). `start`
11
- * overrides it (--sessions-dir / FASTAGENT_SESSIONS_DIR / a mounted volume) so production continuity
12
- * survives redeploys.
13
- */
14
- sessionsDir?: string;
15
- /**
16
- * Credentials file override. Default `<dir>/.fastagent/auth.json` (project-level, gitignored under
17
- * the same `*`-ignored `.fastagent`). Override via --auth-path / FASTAGENT_AUTH_PATH; point it at
18
- * `~/.fastagent/auth.json` to share one credential across projects.
19
- */
20
- authPath?: string;
21
- /**
22
- * This is a long-running SERVE (`dev`/`start`), where the scheduler poller runs — so a self-scheduled
23
- * wake-up is actually honored. One-shot entries (`invoke`/`fire`) leave it off (they exit after the turn
24
- * and never poll). The built-in `wake` tool mounts only when this is set AND `config.selfSchedule` is on.
25
- */
26
- serving?: boolean;
27
- }
28
- /**
29
- * "Point at a workspace → agent": load the config, resolve model and tools, then L2. Throws a clear
30
- * error when no model source is set (fail visibly at startup). Returns everything an entry point needs
31
- * to report what it assembled.
32
- */
33
- export declare function createPiAgentFromWorkspace(dir: string, options?: CreatePiAgentFromWorkspaceOptions): Promise<{
34
- agent: Agent;
35
- definition: LoadedDefinition;
36
- config: FastagentConfig;
37
- configPath?: string;
38
- /** The resolved "provider/modelId" spec actually in use. */
39
- modelSpec: string;
40
- /** Absolute agent-definition dir in use (config.agentDir resolved against dir; = dir when unset). Channels/tools/persona come from here. */
41
- agentDir: string;
42
- /** Absolute state root in use (FASTAGENT_STATE_DIR > <dir>/.fastagent) — the ChannelContext's stateRoot. */
43
- stateRoot: string;
44
- /** Absolute session store directory in use (for the startup report). */
45
- sessionsDir: string;
46
- /** Absolute credentials file in use (for the startup report). */
47
- authPath: string;
48
- /** Non-default, active-by-default tool names in effect: config.tools + discovered tools/. Each name
49
- * lives in exactly one report slot — deferred names are in {@link deferredToolNames} instead. */
50
- toolNames: string[];
51
- /** Tools registered but not initially active (deferred) — activated via search_tools. */
52
- deferredToolNames: string[];
53
- toolCollisions: ToolCollision[];
54
- /** `tools/` files that failed to import — skipped, reported by the caller, never fatal. */
55
- toolFailures: ModuleLoadFailure[];
56
- }>;