@fastagent-sh/fastagent 0.12.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 (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +214 -0
  3. package/dist/agent.d.ts +72 -0
  4. package/dist/agent.js +14 -0
  5. package/dist/channels/body.d.ts +9 -0
  6. package/dist/channels/body.js +29 -0
  7. package/dist/channels/github/github.d.ts +31 -0
  8. package/dist/channels/github/github.js +80 -0
  9. package/dist/channels/github/scaffold/channel.ts +25 -0
  10. package/dist/channels/http.d.ts +13 -0
  11. package/dist/channels/http.js +161 -0
  12. package/dist/channels/respond.d.ts +5 -0
  13. package/dist/channels/respond.js +3 -0
  14. package/dist/channels/telegram/context-buffer.d.ts +59 -0
  15. package/dist/channels/telegram/context-buffer.js +139 -0
  16. package/dist/channels/telegram/invoke-turn.d.ts +53 -0
  17. package/dist/channels/telegram/invoke-turn.js +127 -0
  18. package/dist/channels/telegram/parse.d.ts +160 -0
  19. package/dist/channels/telegram/parse.js +153 -0
  20. package/dist/channels/telegram/preview.d.ts +22 -0
  21. package/dist/channels/telegram/preview.js +266 -0
  22. package/dist/channels/telegram/register-webhook.d.ts +13 -0
  23. package/dist/channels/telegram/register-webhook.js +73 -0
  24. package/dist/channels/telegram/scaffold/channel.ts +25 -0
  25. package/dist/channels/telegram/scaffold/telegram-send.ts +107 -0
  26. package/dist/channels/telegram/state.d.ts +9 -0
  27. package/dist/channels/telegram/state.js +58 -0
  28. package/dist/channels/telegram/telegram-api.d.ts +77 -0
  29. package/dist/channels/telegram/telegram-api.js +345 -0
  30. package/dist/channels/telegram/telegram.d.ts +35 -0
  31. package/dist/channels/telegram/telegram.js +352 -0
  32. package/dist/channels/telegram/turn-queue.d.ts +21 -0
  33. package/dist/channels/telegram/turn-queue.js +47 -0
  34. package/dist/channels/telegram/turn-store.d.ts +38 -0
  35. package/dist/channels/telegram/turn-store.js +150 -0
  36. package/dist/cli-auth.d.ts +24 -0
  37. package/dist/cli-auth.js +30 -0
  38. package/dist/cli-models.d.ts +11 -0
  39. package/dist/cli-models.js +20 -0
  40. package/dist/cli.d.ts +2 -0
  41. package/dist/cli.js +1288 -0
  42. package/dist/collect.d.ts +20 -0
  43. package/dist/collect.js +27 -0
  44. package/dist/core.d.ts +10 -0
  45. package/dist/core.js +8 -0
  46. package/dist/deploy/container.d.ts +56 -0
  47. package/dist/deploy/container.js +169 -0
  48. package/dist/deploy/fly/plan.d.ts +65 -0
  49. package/dist/deploy/fly/plan.js +142 -0
  50. package/dist/deploy/fly/run.d.ts +51 -0
  51. package/dist/deploy/fly/run.js +89 -0
  52. package/dist/deploy/preflight.d.ts +59 -0
  53. package/dist/deploy/preflight.js +191 -0
  54. package/dist/deploy/railway/plan.d.ts +48 -0
  55. package/dist/deploy/railway/plan.js +91 -0
  56. package/dist/deploy/railway/run.d.ts +81 -0
  57. package/dist/deploy/railway/run.js +176 -0
  58. package/dist/deploy/runner.d.ts +18 -0
  59. package/dist/deploy/runner.js +25 -0
  60. package/dist/deploy/secrets.d.ts +49 -0
  61. package/dist/deploy/secrets.js +88 -0
  62. package/dist/dev-supervisor.d.ts +14 -0
  63. package/dist/dev-supervisor.js +158 -0
  64. package/dist/engines/pi/auth.d.ts +17 -0
  65. package/dist/engines/pi/auth.js +118 -0
  66. package/dist/engines/pi/channel.d.ts +31 -0
  67. package/dist/engines/pi/channel.js +113 -0
  68. package/dist/engines/pi/chat.d.ts +19 -0
  69. package/dist/engines/pi/chat.js +200 -0
  70. package/dist/engines/pi/config.d.ts +110 -0
  71. package/dist/engines/pi/config.js +285 -0
  72. package/dist/engines/pi/create.d.ts +127 -0
  73. package/dist/engines/pi/create.js +222 -0
  74. package/dist/engines/pi/definition.d.ts +72 -0
  75. package/dist/engines/pi/definition.js +129 -0
  76. package/dist/engines/pi/harness.d.ts +50 -0
  77. package/dist/engines/pi/harness.js +41 -0
  78. package/dist/engines/pi/invoke.d.ts +28 -0
  79. package/dist/engines/pi/invoke.js +298 -0
  80. package/dist/engines/pi/login.d.ts +51 -0
  81. package/dist/engines/pi/login.js +125 -0
  82. package/dist/engines/pi/models.d.ts +41 -0
  83. package/dist/engines/pi/models.js +76 -0
  84. package/dist/engines/pi/report.d.ts +13 -0
  85. package/dist/engines/pi/report.js +21 -0
  86. package/dist/engines/pi/sessions.d.ts +15 -0
  87. package/dist/engines/pi/sessions.js +130 -0
  88. package/dist/engines/pi/tool-context.d.ts +17 -0
  89. package/dist/engines/pi/tool-context.js +13 -0
  90. package/dist/engines/pi/tool.d.ts +45 -0
  91. package/dist/engines/pi/tool.js +85 -0
  92. package/dist/engines/pi/wake-tool.d.ts +20 -0
  93. package/dist/engines/pi/wake-tool.js +110 -0
  94. package/dist/engines/pi/workspace.d.ts +53 -0
  95. package/dist/engines/pi/workspace.js +70 -0
  96. package/dist/env.d.ts +24 -0
  97. package/dist/env.js +57 -0
  98. package/dist/github.d.ts +3 -0
  99. package/dist/github.js +2 -0
  100. package/dist/host/node.d.ts +41 -0
  101. package/dist/host/node.js +50 -0
  102. package/dist/index.d.ts +2 -0
  103. package/dist/index.js +5 -0
  104. package/dist/invoke-stream.d.ts +10 -0
  105. package/dist/invoke-stream.js +26 -0
  106. package/dist/loader.d.ts +38 -0
  107. package/dist/loader.js +69 -0
  108. package/dist/log.d.ts +26 -0
  109. package/dist/log.js +51 -0
  110. package/dist/observe.d.ts +12 -0
  111. package/dist/observe.js +44 -0
  112. package/dist/pi.d.ts +16 -0
  113. package/dist/pi.js +12 -0
  114. package/dist/proxy.d.ts +9 -0
  115. package/dist/proxy.js +23 -0
  116. package/dist/runtime.d.ts +26 -0
  117. package/dist/runtime.js +29 -0
  118. package/dist/scaffold/add-channel.d.ts +46 -0
  119. package/dist/scaffold/add-channel.js +227 -0
  120. package/dist/scaffold/init.d.ts +54 -0
  121. package/dist/scaffold/init.js +249 -0
  122. package/dist/scaffold/templates/env.example +24 -0
  123. package/dist/scaffold/templates/fastagent.config.mjs +19 -0
  124. package/dist/scaffold/templates/gitignore +8 -0
  125. package/dist/scaffold/templates/gitignore.agentdir-root +5 -0
  126. package/dist/scaffold/templates/gitignore.kit +2 -0
  127. package/dist/scaffold/templates/persona.md +10 -0
  128. package/dist/scaffold/templates/skills/writing-great-skills/GLOSSARY.md +195 -0
  129. package/dist/scaffold/templates/skills/writing-great-skills/LICENSE +21 -0
  130. package/dist/scaffold/templates/skills/writing-great-skills/SKILL.md +82 -0
  131. package/dist/scaffold/templates/tools/fetch-url.ts +27 -0
  132. package/dist/scaffold/templates.d.ts +17 -0
  133. package/dist/scaffold/templates.js +56 -0
  134. package/dist/scaffold/vendor-skill.d.ts +24 -0
  135. package/dist/scaffold/vendor-skill.js +157 -0
  136. package/dist/schedule/audit.d.ts +18 -0
  137. package/dist/schedule/audit.js +57 -0
  138. package/dist/schedule/cron.d.ts +7 -0
  139. package/dist/schedule/cron.js +33 -0
  140. package/dist/schedule/discover.d.ts +17 -0
  141. package/dist/schedule/discover.js +64 -0
  142. package/dist/schedule/schedule.d.ts +35 -0
  143. package/dist/schedule/schedule.js +23 -0
  144. package/dist/schedule/scheduler.d.ts +36 -0
  145. package/dist/schedule/scheduler.js +253 -0
  146. package/dist/schedule/state.d.ts +14 -0
  147. package/dist/schedule/state.js +56 -0
  148. package/dist/schedule/wakeups.d.ts +82 -0
  149. package/dist/schedule/wakeups.js +196 -0
  150. package/dist/telegram.d.ts +2 -0
  151. package/dist/telegram.js +2 -0
  152. package/dist/tunnel.d.ts +31 -0
  153. package/dist/tunnel.js +139 -0
  154. package/dist/version.d.ts +5 -0
  155. package/dist/version.js +13 -0
  156. package/dist/workspace.d.ts +9 -0
  157. package/dist/workspace.js +45 -0
  158. package/package.json +97 -0
@@ -0,0 +1,31 @@
1
+ /**
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; github prints the
4
+ * URL to paste into repo settings). This closes the "local dev → public URL" gap webhooks need.
5
+ *
6
+ * Process orchestration, not assembly — lives outside the engine, beside dev-supervisor.ts.
7
+ */
8
+ import { type ChildProcess } from "node:child_process";
9
+ export interface Tunnel {
10
+ url: string;
11
+ close(): void;
12
+ }
13
+ /** Extract a Cloudflare quick-tunnel URL from a chunk of cloudflared output, if present. */
14
+ export declare function parseTunnelUrl(chunk: string): string | undefined;
15
+ /** How cloudflared is launched; injectable so tests can drive the child without a real process. */
16
+ type SpawnCloudflared = (port: number) => ChildProcess;
17
+ /**
18
+ * Start a Cloudflare quick tunnel to localhost:`port`, resolving once its public URL appears.
19
+ * cloudflared sometimes exits before printing a URL (a transient trycloudflare API error), so retry a
20
+ * few times. ALWAYS resolves to undefined WITH an operator log saying why — missing binary, the exit
21
+ * reason, or "gave up after retries" — never silently; serving continues without a tunnel either way.
22
+ * (Edge warmup AFTER the URL appears is handled downstream: the telegram registrar polls /health before
23
+ * it calls setWebhook, so a not-yet-routable tunnel just delays registration rather than failing it.)
24
+ */
25
+ export declare function startCloudflareTunnel(port: number, spawnFn?: SpawnCloudflared): Promise<Tunnel | undefined>;
26
+ /**
27
+ * Print the public URL and wire up the first-party webhook channels found under `dir`: telegram is
28
+ * auto-registered via setWebhook (using .env tokens); github prints the URL to add in repo settings.
29
+ */
30
+ export declare function announceWebhooks(dir: string, baseUrl: string): Promise<void>;
31
+ export {};
package/dist/tunnel.js ADDED
@@ -0,0 +1,139 @@
1
+ /**
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; github prints the
4
+ * URL to paste into repo settings). This closes the "local dev → public URL" gap webhooks need.
5
+ *
6
+ * Process orchestration, not assembly — lives outside the engine, beside dev-supervisor.ts.
7
+ */
8
+ import { spawn } from "node:child_process";
9
+ import { readdirSync } from "node:fs";
10
+ import { join } from "node:path";
11
+ import { setTimeout as sleep } from "node:timers/promises";
12
+ import { registerTelegramWebhook } from "./channels/telegram/register-webhook.js";
13
+ import { loadDotEnv } from "./env.js";
14
+ import { log } from "./log.js";
15
+ // `(?!api\.)`: cloudflared's ERROR lines mention its request endpoint (`https://api.trycloudflare.com/tunnel`,
16
+ // e.g. "failed to request quick Tunnel: Post ... timeout" under a flaky proxy) — without the exclusion a
17
+ // transient error line parses as the assigned URL and the webhook gets registered against Cloudflare's
18
+ // API host instead of the tunnel.
19
+ const TUNNEL_URL_RE = /https:\/\/(?!api\.)[a-z0-9-]+\.trycloudflare\.com/i;
20
+ /** Extract a Cloudflare quick-tunnel URL from a chunk of cloudflared output, if present. */
21
+ export function parseTunnelUrl(chunk) {
22
+ return chunk.match(TUNNEL_URL_RE)?.[0];
23
+ }
24
+ const TUNNEL_ATTEMPTS = 3;
25
+ const TUNNEL_RETRY_MS = 2000;
26
+ const spawnCloudflared = (port) => spawn("cloudflared", ["tunnel", "--url", `http://localhost:${port}`], { stdio: ["ignore", "pipe", "pipe"] });
27
+ /**
28
+ * Start a Cloudflare quick tunnel to localhost:`port`, resolving once its public URL appears.
29
+ * cloudflared sometimes exits before printing a URL (a transient trycloudflare API error), so retry a
30
+ * few times. ALWAYS resolves to undefined WITH an operator log saying why — missing binary, the exit
31
+ * reason, or "gave up after retries" — never silently; serving continues without a tunnel either way.
32
+ * (Edge warmup AFTER the URL appears is handled downstream: the telegram registrar polls /health before
33
+ * it calls setWebhook, so a not-yet-routable tunnel just delays registration rather than failing it.)
34
+ */
35
+ export async function startCloudflareTunnel(port, spawnFn = spawnCloudflared) {
36
+ for (let attempt = 1; attempt <= TUNNEL_ATTEMPTS; attempt++) {
37
+ const r = await spawnTunnelOnce(port, spawnFn);
38
+ if (r.tunnel)
39
+ return r.tunnel;
40
+ if (r.fatal) {
41
+ log.error(r.message); // missing binary — retrying cannot help
42
+ return undefined;
43
+ }
44
+ const more = attempt < TUNNEL_ATTEMPTS;
45
+ log.warn(`[fastagent] --tunnel: cloudflared exited before a public URL appeared${r.detail ? ` (${r.detail})` : ""}` +
46
+ (more ? ` — retrying (${attempt}/${TUNNEL_ATTEMPTS - 1})…` : ". Serving without a tunnel."));
47
+ if (more)
48
+ await sleep(TUNNEL_RETRY_MS);
49
+ }
50
+ return undefined;
51
+ }
52
+ /** One cloudflared launch: a Tunnel on the first URL, or a failure (missing binary / exit before a URL). */
53
+ function spawnTunnelOnce(port, spawnFn) {
54
+ return new Promise((resolve) => {
55
+ const child = spawnFn(port);
56
+ let settled = false;
57
+ let tail = ""; // recent output, surfaced as the failure reason
58
+ const onChunk = (buf) => {
59
+ tail = (tail + String(buf)).slice(-600);
60
+ if (settled)
61
+ return;
62
+ const url = parseTunnelUrl(String(buf));
63
+ if (url) {
64
+ settled = true;
65
+ resolve({ tunnel: { url, close: () => child.kill("SIGTERM") } });
66
+ }
67
+ };
68
+ child.stdout?.on("data", onChunk);
69
+ child.stderr?.on("data", onChunk); // cloudflared prints the URL (and its errors) on stderr
70
+ child.on("error", (e) => {
71
+ if (settled)
72
+ return;
73
+ settled = true;
74
+ if (e.code === "ENOENT") {
75
+ resolve({
76
+ fatal: true,
77
+ message: "[fastagent] --tunnel needs cloudflared — install it (e.g. `brew install cloudflared`), then re-run. Serving without a tunnel.",
78
+ });
79
+ }
80
+ else {
81
+ resolve({ fatal: false, detail: e.message });
82
+ }
83
+ });
84
+ child.on("exit", () => {
85
+ if (settled)
86
+ return;
87
+ settled = true;
88
+ resolve({ fatal: false, detail: lastErrorLine(tail) });
89
+ });
90
+ });
91
+ }
92
+ /** The most informative line of cloudflared's output tail (prefer an error line) for a failure log. */
93
+ function lastErrorLine(tail) {
94
+ const lines = tail
95
+ .split("\n")
96
+ .map((l) => l.trim())
97
+ .filter(Boolean);
98
+ return ([...lines].reverse().find((l) => /err|error|failed/i.test(l)) ?? lines.at(-1) ?? "").slice(0, 200);
99
+ }
100
+ /** Channel basenames present in `<dir>/channels/`. */
101
+ function channelBasenames(dir) {
102
+ try {
103
+ return readdirSync(join(dir, "channels"))
104
+ .filter((n) => /\.(ts|js|mjs)$/.test(n) && !n.endsWith(".d.ts"))
105
+ .map((n) => n.replace(/\.(ts|js|mjs)$/, ""));
106
+ }
107
+ catch {
108
+ return [];
109
+ }
110
+ }
111
+ /**
112
+ * Print the public URL and wire up the first-party webhook channels found under `dir`: telegram is
113
+ * auto-registered via setWebhook (using .env tokens); github prints the URL to add in repo settings.
114
+ */
115
+ export async function announceWebhooks(dir, baseUrl) {
116
+ log.info(`[fastagent] public URL: ${baseUrl}`);
117
+ try {
118
+ loadDotEnv(dir); // telegram registration reads tokens from .env
119
+ }
120
+ catch (error) {
121
+ // best-effort boundary: a MISSING .env is already tolerated by loadDotEnv; an unreadable one (EACCES,
122
+ // or .env is a directory) must NOT crash the long-running dev/start server — announceWebhooks is
123
+ // void-called with no unhandledRejection handler, so a throw here would terminate the process. Warn
124
+ // (surface it, rule 8) and continue best-effort; telegram registration then degrades to its manual
125
+ // instruction if the token is absent. loadDotEnv keeps throwing for the synchronous command callers.
126
+ log.warn(`[fastagent] could not read ${join(dir, ".env")}: ${error.message} — continuing without it`);
127
+ }
128
+ const channels = channelBasenames(dir);
129
+ if (channels.length === 0)
130
+ return;
131
+ // Readiness is the registrar's job now: a fresh quick tunnel returns Cloudflare 530 for ~20-30s before
132
+ // its origin connects, and registerTelegramWebhook polls /health until it serves before setWebhook (the
133
+ // same wait the deploy runners rely on). github needs no wait — the operator adds that webhook by hand.
134
+ if (channels.includes("telegram"))
135
+ await registerTelegramWebhook(baseUrl);
136
+ if (channels.includes("github")) {
137
+ log.info(`[fastagent] github: add a webhook in your repo (Settings → Webhooks): Payload URL = ${baseUrl}/webhook, content type application/json, secret = GITHUB_WEBHOOK_SECRET`);
138
+ }
139
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * This build's own @fastagent-sh/fastagent version. THROWS if unreadable — the version is load-bearing for
3
+ * the scaffolded dependency range (`^${version}`), so init must never scaffold an uninstallable `^0.0.0`.
4
+ */
5
+ export declare function fastagentVersion(): Promise<string>;
@@ -0,0 +1,13 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { fileURLToPath } from "node:url";
3
+ /**
4
+ * This build's own @fastagent-sh/fastagent version. THROWS if unreadable — the version is load-bearing for
5
+ * the scaffolded dependency range (`^${version}`), so init must never scaffold an uninstallable `^0.0.0`.
6
+ */
7
+ export async function fastagentVersion() {
8
+ const pkgPath = fileURLToPath(new URL("../package.json", import.meta.url));
9
+ const pkg = JSON.parse(await readFile(pkgPath, "utf8"));
10
+ if (typeof pkg.version !== "string" || pkg.version === "")
11
+ throw new Error(`no version in ${pkgPath}`);
12
+ return pkg.version;
13
+ }
@@ -0,0 +1,9 @@
1
+ import { type Ignore } from "ignore";
2
+ /**
3
+ * Guard that `<workspaceDir>/<name>` resolves INSIDE the workspace — a symlink that escapes (or an
4
+ * absolute target) is rejected, so discovery/scaffolding never reaches out of the definition directory.
5
+ * A missing target is fine (nothing to guard yet).
6
+ */
7
+ export declare function assertInsideWorkspace(workspaceDir: string, name: string): Promise<void>;
8
+ /** Load `.gitignore` + `.fastagentignore` from `dir` into one matcher (case-sensitive), or undefined if none. */
9
+ export declare function loadRootIgnore(dir: string): Promise<Ignore | undefined>;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Workspace path/ignore utilities — engine-neutral (pure fs/path + the `ignore` matcher). Shared by the
3
+ * scaffold (init/add) and the engine's channel discovery, so they live here, not under engines/pi.
4
+ */
5
+ import { readFile, realpath } from "node:fs/promises";
6
+ import { isAbsolute, join, relative, resolve } from "node:path";
7
+ import ignore, {} from "ignore";
8
+ /**
9
+ * Guard that `<workspaceDir>/<name>` resolves INSIDE the workspace — a symlink that escapes (or an
10
+ * absolute target) is rejected, so discovery/scaffolding never reaches out of the definition directory.
11
+ * A missing target is fine (nothing to guard yet).
12
+ */
13
+ export async function assertInsideWorkspace(workspaceDir, name) {
14
+ const target = join(workspaceDir, name);
15
+ const real = await realpath(target).catch((e) => {
16
+ if (e.code === "ENOENT" || e.code === "not_found")
17
+ return undefined;
18
+ throw e;
19
+ });
20
+ if (real === undefined)
21
+ return;
22
+ const root = await realpath(workspaceDir).catch(() => resolve(workspaceDir));
23
+ const rel = relative(root, real);
24
+ if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
25
+ throw new Error(`${target} resolves outside the workspace (${real}) — it must live inside the definition directory; ` +
26
+ `use a real directory or a symlink that stays within it`);
27
+ }
28
+ }
29
+ /** Load `.gitignore` + `.fastagentignore` from `dir` into one matcher (case-sensitive), or undefined if none. */
30
+ export async function loadRootIgnore(dir) {
31
+ let rules = "";
32
+ for (const name of [".gitignore", ".fastagentignore"]) {
33
+ try {
34
+ rules += `\n${await readFile(join(dir, name), "utf8")}`;
35
+ }
36
+ catch (error) {
37
+ if (error.code !== "ENOENT") {
38
+ throw new Error(`cannot read ${join(dir, name)}: ${error.message}`);
39
+ }
40
+ }
41
+ }
42
+ // ignorecase:false — the library defaults to case-INSENSITIVE, which would make a rule `README.md`
43
+ // also drop an authored `readme.md`. Match git on a case-sensitive filesystem, reproducibly.
44
+ return rules.trim() === "" ? undefined : ignore({ ignorecase: false }).add(rules);
45
+ }
package/package.json ADDED
@@ -0,0 +1,97 @@
1
+ {
2
+ "name": "@fastagent-sh/fastagent",
3
+ "version": "0.12.0",
4
+ "description": "Vibe first. Then FastAgent: turn a local agent directory into a running service in your app, on GitHub, in Telegram, or behind any channel.",
5
+ "keywords": [
6
+ "agent",
7
+ "ai-agent",
8
+ "llm",
9
+ "agents.md",
10
+ "agent-skills",
11
+ "agent-serving",
12
+ "sse",
13
+ "pi",
14
+ "fastagent"
15
+ ],
16
+ "license": "MIT",
17
+ "author": "the fastagent authors (https://github.com/fastagent-sh/fastagent)",
18
+ "homepage": "https://github.com/fastagent-sh/fastagent#readme",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/fastagent-sh/fastagent.git"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/fastagent-sh/fastagent/issues"
25
+ },
26
+ "type": "module",
27
+ "sideEffects": false,
28
+ "engines": {
29
+ "node": ">=22.19.0"
30
+ },
31
+ "main": "./dist/index.js",
32
+ "types": "./dist/index.d.ts",
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/index.d.ts",
36
+ "default": "./dist/index.js"
37
+ },
38
+ "./core": {
39
+ "types": "./dist/core.d.ts",
40
+ "default": "./dist/core.js"
41
+ },
42
+ "./pi": {
43
+ "types": "./dist/pi.d.ts",
44
+ "default": "./dist/pi.js"
45
+ },
46
+ "./github": {
47
+ "types": "./dist/github.d.ts",
48
+ "default": "./dist/github.js"
49
+ },
50
+ "./telegram": {
51
+ "types": "./dist/telegram.d.ts",
52
+ "default": "./dist/telegram.js"
53
+ },
54
+ "./package.json": "./package.json"
55
+ },
56
+ "bin": {
57
+ "fastagent": "./dist/cli.js"
58
+ },
59
+ "files": [
60
+ "dist",
61
+ "LICENSE",
62
+ "README.md"
63
+ ],
64
+ "publishConfig": {
65
+ "registry": "https://registry.npmjs.org",
66
+ "access": "public"
67
+ },
68
+ "scripts": {
69
+ "prebuild": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
70
+ "build": "tsc -p tsconfig.build.json",
71
+ "prepack": "npm run build",
72
+ "test": "vitest --run",
73
+ "typecheck": "tsc --noEmit",
74
+ "lint": "biome check src test && node scripts/check-doc-links.mjs",
75
+ "format": "biome check --write src test",
76
+ "postbuild": "node scripts/copy-scaffold-assets.mjs"
77
+ },
78
+ "dependencies": {
79
+ "@clack/prompts": "^1.6.0",
80
+ "@earendil-works/pi-agent-core": "^0.80.3",
81
+ "@earendil-works/pi-ai": "^0.80.3",
82
+ "@earendil-works/pi-coding-agent": "^0.80.3",
83
+ "@octokit/webhooks-methods": "^6.0.0",
84
+ "@octokit/webhooks-types": "^7.6.1",
85
+ "chokidar": "^5.0.0",
86
+ "croner": "^9.1.0",
87
+ "giget": "^3.3.0",
88
+ "ignore": "^7.0.5",
89
+ "undici": "^8.6.0",
90
+ "zod": "^4.4.3"
91
+ },
92
+ "devDependencies": {
93
+ "@biomejs/biome": "^2.5.2",
94
+ "typescript": "^6.0.3",
95
+ "vitest": "^4.1.9"
96
+ }
97
+ }