@michael-joseph-miller/ant-bot 0.1.4 → 0.2.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,47 @@ All notable changes to ant-bot are recorded here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
5
5
  [semantic versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.2.0] — 2026-08-23
8
+
9
+ ### Added
10
+
11
+ - **MCP connectors.** External MCP servers can be registered account-wide and assigned to
12
+ individual Bots, the way skills are. Assignment *is* the permission: a Bot that has not been
13
+ given a connector never has the server mounted, so its tools do not exist for that Bot.
14
+ Disabling a connector withdraws it from every Bot at once.
15
+ - Manage them on the new **Connectors** screen, over `/api/connectors`, or with
16
+ `antbot connector list|add|enable|disable|remove|test`.
17
+ - `antbot connector test` connects to the server and lists the tools it offers, so a broken
18
+ command or a wrong URL is visible before a Bot ever tries to use it.
19
+ - stdio, http and sse transports; http and sse accept an optional per-tool allowlist.
20
+ - Tools reach Bots as `mcp__<name>__<tool>` and pass the permission gateway unchanged — the
21
+ first call raises an approval card, and you allow what you trust with a rule.
22
+ - **Credentials by reference.** Any connector env value or header may contain `{{secret:NAME}}`.
23
+ The daemon resolves it from the keychain when the server starts; the value lives only in that
24
+ subprocess's environment or its outbound headers, never in the database, an API response, a log
25
+ line, or a Bot's context. A reference with nothing behind it is flagged in the UI and CLI, and
26
+ the connector is skipped for the turn rather than failing it.
27
+ - This gives `SecretsService` a scoped `resolve()`; the unscoped `envOverlay()` remains unused.
28
+
29
+ ### Changed
30
+
31
+ - `docs/USER-GUIDE.md` gains §11 (Connectors); later sections renumbered, §23 is now the
32
+ known-limitations list. `docs/API-CONTRACT.md` documents seven new endpoints — a deliberate
33
+ change to a frozen contract. `docs/SECURITY.md` gains a connectors section covering what the
34
+ workspace boundary does not cover, why allow rules should be fully qualified, and the fact that
35
+ a credential does reach the connector's own process.
36
+
37
+ ## [0.1.5] — 2026-08-23
38
+
39
+ ### Fixed
40
+
41
+ - **Input is now dispatched in order.** The screencast socket handles each frame without awaiting
42
+ the last, so events raced: a mouse down and up could invert and a burst of typing arrived
43
+ shuffled. Slow human typing mostly survived it, which is why this looked like "some keys work"
44
+ rather than like a bug. Input is serialised per screen, and the takeover check runs again at
45
+ dispatch so a queued event cannot land after control is handed back. Backlogged pointer moves
46
+ are dropped rather than queued without bound; clicks, keys and text never are.
47
+
7
48
  ## [0.1.4] — 2026-08-23
8
49
 
9
50
  ### Added
package/README.md CHANGED
@@ -14,6 +14,9 @@ subscription login rather than a metered `ANTHROPIC_API_KEY`.
14
14
  and a memory directory that survives daemon restarts.
15
15
  - **A shared computer** — one workspace directory, one persistent browser profile, one terminal;
16
16
  every Bot can reach what every other Bot can reach.
17
+ - **Connectors** — attach an MCP server (GitHub, filesystem, your own) once, then assign it per Bot.
18
+ A Bot without the assignment cannot see its tools; credentials stay in the keychain as
19
+ `{{secret:NAME}}` references.
17
20
  - **Approvals** — every tool call a Bot proposes passes a Permission Gateway: deterministic rules,
18
21
  optional Haiku auto-review, or a human approval card in the thread.
19
22
  - **Skills** — standard Claude skills (`SKILL.md`), installed with `antbot skill add <source>` from
@@ -91,6 +94,7 @@ web assets. There's no separate frontend server to run.
91
94
  | `antbot restart` | Stop and start again |
92
95
  | `antbot status` | Whether it's running, on what port, with how many bots |
93
96
  | `antbot doctor` | Diagnose the environment; every failure prints its fix |
97
+ | `antbot connector` | Manage the MCP servers your bots can use (`list`/`add`/`test`/`remove`) |
94
98
  | `antbot update` | Update to the latest published version (`--check` to look without installing) |
95
99
 
96
100
  Run `antbot --help` for the full list, or `antbot <command> --help` for one command.
@@ -275,11 +279,11 @@ Current totals, as run against this checkout:
275
279
 
276
280
  | Package | Test files | Tests |
277
281
  |---|---|---|
278
- | `@antbot/contract` | 1 | 22 |
279
- | `@antbot/daemon` | 20 | 469 |
280
- | `@antbot/ui` | 8 | 63 |
281
- | `@antbot/cli` | 7 | 116 |
282
- | **Total** | **36** | **670** |
282
+ | `@antbot/contract` | 1 | 34 |
283
+ | `@antbot/daemon` | 23 | 528 |
284
+ | `@antbot/ui` | 9 | 80 |
285
+ | `@antbot/cli` | 8 | 133 |
286
+ | **Total** | **41** | **775** |
283
287
 
284
288
  ## Status / not built
285
289
 
@@ -134,6 +134,7 @@ function errMsg(err) {
134
134
  return err instanceof Error ? err.message : String(err);
135
135
  }
136
136
  var MAX_SELECTION_CHARS = 1e5;
137
+ var MAX_QUEUED_INPUT = 32;
137
138
  var BrowserService = class {
138
139
  constructor(deps) {
139
140
  this.deps = deps;
@@ -160,6 +161,9 @@ var BrowserService = class {
160
161
  * likely to be rescuing (a login form sitting still, waiting for input).
161
162
  */
162
163
  lastFrameSize = /* @__PURE__ */ new Map();
164
+ /** Per-bot serialisation chain for human input — see forwardInput. */
165
+ inputQueue = /* @__PURE__ */ new Map();
166
+ inputDepth = /* @__PURE__ */ new Map();
163
167
  get isHeadless() {
164
168
  return this.headlessMode;
165
169
  }
@@ -511,6 +515,8 @@ ${this.orientLine(o)}`;
511
515
  }
512
516
  returnControl(botId) {
513
517
  this.takenOver.delete(botId);
518
+ this.inputQueue.delete(botId);
519
+ this.inputDepth.delete(botId);
514
520
  }
515
521
  /**
516
522
  * The remote page's current text selection, for copying out of a taken-over screen.
@@ -580,11 +586,12 @@ ${this.orientLine(o)}`;
580
586
  /**
581
587
  * Dispatches human input into a taken-over page.
582
588
  *
583
- * The takeover check is the whole security model here, and it is deliberately a hard refusal
584
- * rather than a queue: input is only ever legitimate while the bot is blocked, and silently
585
- * buffering it would let a stale click land after control was returned into a page the bot
586
- * has since navigated. Input does not pass the Permission Gateway, because the gateway governs
587
- * what *bots* do; this is the human acting as themselves on their own computer.
589
+ * The takeover check is the whole security model here. It is applied twice on purpose: on entry,
590
+ * so a caller is refused immediately, and again at dispatch, because events *are* queued for
591
+ * ordering and control can be returned while some are still pending. Without the second check a
592
+ * stale click would land after handback, into a page the bot has since navigated. Input does not
593
+ * pass the Permission Gateway, because the gateway governs what *bots* do; this is the human
594
+ * acting as themselves on their own computer.
588
595
  *
589
596
  * Dispatch goes through Playwright's `page.mouse` / `page.keyboard` rather than raw CDP so the
590
597
  * key-code mapping is the SDK's problem, matching how `click()` and `type()` above work.
@@ -595,6 +602,25 @@ ${this.orientLine(o)}`;
595
602
  "Input was sent for a screen that is not taken over. Take over the screen first."
596
603
  );
597
604
  }
605
+ const depth = (this.inputDepth.get(botId) ?? 0) + 1;
606
+ this.inputDepth.set(botId, depth);
607
+ if (ev.kind === "mouse" && ev.action === "move" && depth > MAX_QUEUED_INPUT) {
608
+ this.inputDepth.set(botId, depth - 1);
609
+ return;
610
+ }
611
+ const run = async () => {
612
+ try {
613
+ if (this.takenOver.has(botId)) await this.dispatchInput(botId, ev);
614
+ } finally {
615
+ this.inputDepth.set(botId, Math.max(0, (this.inputDepth.get(botId) ?? 1) - 1));
616
+ }
617
+ };
618
+ const chained = (this.inputQueue.get(botId) ?? Promise.resolve()).then(run, run);
619
+ this.inputQueue.set(botId, chained.catch(() => {
620
+ }));
621
+ return chained;
622
+ }
623
+ async dispatchInput(botId, ev) {
598
624
  const page = await this.getPage(botId);
599
625
  if (ev.kind === "text") {
600
626
  await page.keyboard.insertText(ev.text);
@@ -677,4 +703,4 @@ export {
677
703
  detectBlockFromSignals,
678
704
  normalizeUrl
679
705
  };
680
- //# sourceMappingURL=browser-4LFD7NX2.js.map
706
+ //# sourceMappingURL=browser-NOWM4S6C.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../daemon/src/computer/browser.ts", "../../daemon/src/computer/input.ts"],
4
+ "sourcesContent": ["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { chromium } from 'playwright';\nimport type { BrowserContext, CDPSession, Page } from 'playwright';\nimport type { EventBus } from '../util/bus.js';\nimport { toPageCoords, isForwardableKey, clampWheel, type FrameSize } from './input.js';\nimport type { ScreencastInput } from '@antbot/contract';\nimport { logger } from '../util/log.js';\n\nconst log = logger('browser');\n\n/* ------------------------------------------------------------------------------------------- *\n * Errors\n * ------------------------------------------------------------------------------------------- */\n\n/** Thrown when the browser cannot be launched (e.g. Chromium isn't installed). */\nexport class BrowserUnavailableError extends Error {\n constructor(public readonly reason: string) {\n super(`Browser is unavailable: ${reason}. Try: npx playwright install chromium`);\n this.name = 'BrowserUnavailableError';\n }\n}\n\n/** Thrown by ScreenLock when a bot's screen already has a computer-use task in flight. */\nexport class ScreenBusyError extends Error {\n constructor(public readonly botId: string) {\n super(`That bot's screen is already busy with another computer-use task. Wait for it to finish before starting another.`);\n this.name = 'ScreenBusyError';\n }\n}\n\n/** Thrown by normalizeUrl for disallowed / malformed URLs. */\nexport class InvalidUrlError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'InvalidUrlError';\n }\n}\n\n/** Thrown when an action targets a bot screen the human currently has taken over. */\nexport class ScreenNotTakenOverError extends Error {\n constructor(message = 'This screen is not taken over.') {\n super(message);\n this.name = 'ScreenNotTakenOverError';\n }\n}\n\nexport class ScreenTakenOverError extends Error {\n constructor() {\n super('The human has taken control of this screen; wait until they return it.');\n this.name = 'ScreenTakenOverError';\n }\n}\n\n/* ------------------------------------------------------------------------------------------- *\n * Pure helpers (no browser required) \u2014 exported for unit testing.\n * ------------------------------------------------------------------------------------------- */\n\n/**\n * Adds `https://` to bare domains/paths, rejects `javascript:` and `file:` URLs outright, and\n * otherwise passes the input through unchanged. Deliberately permissive about other schemes\n * (e.g. `data:`, `about:`) \u2014 computer-use tasks legitimately need to load those in tests and\n * sandboxes; the block list is specifically the two schemes that are dangerous or meaningless\n * for a screen-driving agent.\n */\nexport function normalizeUrl(input: string): string {\n const trimmed = (input ?? '').trim();\n if (!trimmed) throw new InvalidUrlError('URL is empty.');\n const schemeMatch = trimmed.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):/);\n if (!schemeMatch) return `https://${trimmed}`;\n const scheme = schemeMatch[1]!.toLowerCase();\n if (scheme === 'javascript') throw new InvalidUrlError('javascript: URLs are not allowed.');\n if (scheme === 'file') throw new InvalidUrlError('file: URLs are not allowed.');\n return trimmed;\n}\n\nexport interface BlockSignals {\n hasPasswordInput: boolean;\n iframeSrcs: string[];\n bodyText: string;\n}\n\nexport interface BlockDetection {\n kind: 'login' | 'captcha' | '2fa';\n message: string;\n}\n\n/**\n * Heuristic login-wall / CAPTCHA / 2FA detector over already-extracted page signals. Kept pure\n * (no Page dependency) so it can run without a browser in unit tests; `BrowserService.detectBlock`\n * gathers the signals from a live Page and delegates here.\n */\nexport function detectBlockFromSignals(signals: BlockSignals): BlockDetection | null {\n const iframeBlob = (signals.iframeSrcs ?? []).join(' ').toLowerCase();\n const body = signals.bodyText ?? '';\n\n if (/recaptcha/i.test(iframeBlob) || /hcaptcha/i.test(iframeBlob)) {\n return { kind: 'captcha', message: 'A CAPTCHA challenge (reCAPTCHA/hCaptcha) is present on this page.' };\n }\n if (/challenges\\.cloudflare\\.com|cf-challenge|turnstile/i.test(iframeBlob) || /checking your browser|cloudflare/i.test(body)) {\n return { kind: 'captcha', message: 'A Cloudflare browser challenge is present on this page.' };\n }\n if (/verify (your \\w+|it'?s you)|two-factor|one-time code/i.test(body)) {\n return { kind: '2fa', message: \"This page is asking for two-factor / one-time-code verification.\" };\n }\n if (signals.hasPasswordInput) {\n return { kind: 'login', message: 'This page has a password field \u2014 it looks like a login wall.' };\n }\n return null;\n}\n\n/**\n * Per-key mutex: `run` executes `fn` immediately if the key is free, otherwise rejects with\n * `ScreenBusyError` rather than queueing \u2014 mirrors \"one computer-use task per Bot screen at a\n * time\" (outline \u00A713): a second concurrent call is a caller bug, not something to serialize.\n */\nexport class ScreenLock {\n private busy = new Set<string>();\n\n isBusy(key: string): boolean {\n return this.busy.has(key);\n }\n\n async run<T>(key: string, fn: () => Promise<T>): Promise<T> {\n if (this.busy.has(key)) throw new ScreenBusyError(key);\n this.busy.add(key);\n try {\n return await fn();\n } finally {\n this.busy.delete(key);\n }\n }\n}\n\n/**\n * Frame-rate limiter for the screencast. `shouldEmit()` returns true at most once per\n * `1000/fps` ms according to the injected clock (defaults to `Date.now`), so tests can drive it\n * deterministically without real timers.\n */\nexport class FrameThrottle {\n private lastEmit = -Infinity;\n\n constructor(\n private readonly fps: number,\n private readonly clock: () => number = () => Date.now(),\n ) {}\n\n get intervalMs(): number {\n return 1000 / this.fps;\n }\n\n shouldEmit(): boolean {\n const now = this.clock();\n if (now - this.lastEmit >= this.intervalMs) {\n this.lastEmit = now;\n return true;\n }\n return false;\n }\n}\n\nfunction errMsg(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/* ------------------------------------------------------------------------------------------- *\n * BrowserService\n * ------------------------------------------------------------------------------------------- */\n\nexport interface BrowserServiceDeps {\n profileDir: string;\n bus: EventBus;\n headless?: boolean;\n}\n\nexport interface ComputerPageStatus {\n botId: string;\n url: string;\n title: string;\n}\n\nexport interface BrowserStatus {\n available: boolean;\n reason?: string;\n mode: 'host';\n headless: boolean;\n pages: ComputerPageStatus[];\n}\n\nexport interface TakeOverResult {\n ok: boolean;\n mode: 'screencast-only' | 'window';\n message: string;\n}\n\ntype FrameListener = (jpegBase64: string, w: number, h: number) => void;\n\n/** A selection can be a whole document; this socket is otherwise carrying video. */\nconst MAX_SELECTION_CHARS = 100_000;\n\n/** Queued input events per screen before pointer moves start being dropped. */\nconst MAX_QUEUED_INPUT = 32;\n\n/**\n * One Playwright persistent browser context shared by every Bot (\"the computer\"), with a\n * dedicated Page (\"screen\") per botId. Because all pages share one persistent context, cookies\n * and logins are shared across bots by design (outline \u00A75: \"one computer, shared by all your\n * Bots\") \u2014 this is intentional, not a bug.\n */\nexport class BrowserService {\n private context: BrowserContext | null = null;\n private launchPromise: Promise<BrowserContext> | null = null;\n private unavailableReason: string | undefined;\n\n private readonly headlessMode: boolean;\n private readonly pages = new Map<string, Page>();\n private readonly titleCache = new Map<string, string>();\n private readonly takenOver = new Set<string>();\n private readonly lock = new ScreenLock();\n\n private readonly screencastSessions = new Map<string, CDPSession>();\n private readonly screencastListeners = new Map<string, Set<FrameListener>>();\n private readonly screencastThrottles = new Map<string, FrameThrottle>();\n private readonly viewerCounts = new Map<string, number>();\n /**\n * Last known viewport, per bot. Seeded from the page and refreshed by screencast frames.\n * Input coordinates scale against this, NOT against frame arrival: Chromium only emits\n * screencast frames on visual change, so a static page delivers none at all and a\n * frame-dependent geometry would drop every click on exactly the pages a human is most\n * likely to be rescuing (a login form sitting still, waiting for input).\n */\n private readonly lastFrameSize = new Map<string, FrameSize>();\n /** Per-bot serialisation chain for human input \u2014 see forwardInput. */\n private readonly inputQueue = new Map<string, Promise<void>>();\n private readonly inputDepth = new Map<string, number>();\n\n constructor(private readonly deps: BrowserServiceDeps) {\n this.headlessMode = deps.headless ?? true;\n }\n\n get isHeadless(): boolean {\n return this.headlessMode;\n }\n\n /** Lazily launches the shared persistent context. Concurrent callers share one launch. */\n private async ensureContext(): Promise<BrowserContext> {\n if (this.context) return this.context;\n if (this.launchPromise) return this.launchPromise;\n\n this.launchPromise = (async () => {\n try {\n fs.mkdirSync(this.deps.profileDir, { recursive: true });\n const ctx = await chromium.launchPersistentContext(this.deps.profileDir, {\n headless: this.headlessMode,\n viewport: { width: 1280, height: 800 },\n });\n this.context = ctx;\n ctx.on('close', () => {\n this.context = null;\n this.launchPromise = null;\n this.pages.clear();\n });\n return ctx;\n } catch (err) {\n this.unavailableReason = errMsg(err);\n this.launchPromise = null;\n throw new BrowserUnavailableError(this.unavailableReason);\n }\n })();\n return this.launchPromise;\n }\n\n /** Returns this bot's dedicated page, creating it lazily. Pages persist across turns. */\n async getPage(botId: string): Promise<Page> {\n const existing = this.pages.get(botId);\n if (existing && !existing.isClosed()) return existing;\n const ctx = await this.ensureContext();\n const page = await ctx.newPage();\n this.pages.set(botId, page);\n page.on('close', () => {\n if (this.pages.get(botId) === page) this.pages.delete(botId);\n });\n return page;\n }\n\n async closePage(botId: string): Promise<void> {\n const page = this.pages.get(botId);\n if (page) {\n await page.close().catch(() => {});\n this.pages.delete(botId);\n }\n this.titleCache.delete(botId);\n this.takenOver.delete(botId);\n }\n\n /** Serializes computer-use tasks per bot screen; a concurrent second call is rejected. */\n async withScreen<T>(botId: string, fn: (page: Page) => Promise<T>): Promise<T> {\n return this.lock.run(botId, async () => {\n if (this.takenOver.has(botId)) throw new ScreenTakenOverError();\n const page = await this.getPage(botId);\n return fn(page);\n });\n }\n\n private async orient(botId: string, page: Page): Promise<{ url: string; title: string }> {\n const url = page.url();\n let title = this.titleCache.get(botId) ?? '';\n try {\n title = await page.title();\n this.titleCache.set(botId, title);\n } catch {\n // page may be mid-navigation or closed; fall back to the cached title.\n }\n return { url, title };\n }\n\n private orientLine(o: { url: string; title: string }): string {\n return `URL: ${o.url}\\nTitle: ${o.title}`;\n }\n\n /** Gathers page signals and runs them through the pure detector. Never throws. */\n async detectBlock(page: Page): Promise<BlockDetection | null> {\n try {\n const hasPasswordInput = (await page.$$('input[type=\"password\"]').catch(() => [])).length > 0;\n const iframeSrcs = await page\n .$$eval('iframe', (els) => els.map((e) => e.getAttribute('src') ?? ''))\n .catch(() => [] as string[]);\n const bodyText = await page\n .evaluate(() => document.body?.innerText ?? '')\n .catch(() => '');\n return detectBlockFromSignals({ hasPasswordInput, iframeSrcs, bodyText: bodyText.slice(0, 4000) });\n } catch {\n return null;\n }\n }\n\n /** If a block is detected, publishes a warn notification and returns the STOP text to prepend. */\n private async checkBlock(botId: string, page: Page): Promise<string | null> {\n const block = await this.detectBlock(page);\n if (!block) return null;\n this.deps.bus.publish({\n type: 'notify',\n botId,\n threadId: null,\n level: 'warn',\n title: 'Browser needs a human',\n body: block.message,\n });\n return (\n `${block.message} STOP: do not attempt to solve or bypass this yourself \u2014 ` +\n `ask the human to take over the computer and wait for them to return control.`\n );\n }\n\n /* ---------------------------------------------------------------------------------------- *\n * Actions \u2014 each returns a short result string including the resulting URL + title, and is\n * safe to call even if the page has navigated away, closed, or errored mid-action.\n * ---------------------------------------------------------------------------------------- */\n\n async navigate(botId: string, url: string): Promise<string> {\n const target = normalizeUrl(url);\n return this.withScreen(botId, async (page) => {\n try {\n await page.goto(target, { waitUntil: 'domcontentloaded', timeout: 30000 });\n } catch (err) {\n return `Navigation to ${target} failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const block = await this.checkBlock(botId, page);\n const o = await this.orient(botId, page);\n return block ? `${block}\\n${this.orientLine(o)}` : `Navigated.\\n${this.orientLine(o)}`;\n });\n }\n\n async click(botId: string, selector: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n await page.click(selector, { timeout: 10000 });\n } catch (err) {\n return `Click on \"${selector}\" failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const block = await this.checkBlock(botId, page);\n const o = await this.orient(botId, page);\n return block ? `${block}\\n${this.orientLine(o)}` : `Clicked \"${selector}\".\\n${this.orientLine(o)}`;\n });\n }\n\n async type(botId: string, selector: string, text: string, opts?: { submit?: boolean }): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n const isPassword = await page\n .$eval(selector, (el) => (el as HTMLInputElement).type === 'password')\n .catch(() => false);\n if (isPassword) {\n return (\n `Refused: \"${selector}\" looks like a password field. Never type credentials into the browser \u2014 ` +\n `ask the human to take over the computer instead.\\n${this.orientLine(await this.orient(botId, page))}`\n );\n }\n await page.fill(selector, text, { timeout: 10000 });\n if (opts?.submit) await page.press(selector, 'Enter');\n } catch (err) {\n return `Type into \"${selector}\" failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const block = await this.checkBlock(botId, page);\n const o = await this.orient(botId, page);\n return block ? `${block}\\n${this.orientLine(o)}` : `Typed into \"${selector}\".\\n${this.orientLine(o)}`;\n });\n }\n\n async pressKey(botId: string, key: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n await page.keyboard.press(key);\n } catch (err) {\n return `Key press \"${key}\" failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n return `Pressed \"${key}\".\\n${this.orientLine(await this.orient(botId, page))}`;\n });\n }\n\n /** Returns visible text (page body, or a selector's text), capped at ~8000 characters. */\n async readText(botId: string, selector?: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n let text: string;\n try {\n text = selector\n ? ((await page.$eval(selector, (el) => (el as HTMLElement).innerText ?? '')) ?? '')\n : await page.evaluate(() => document.body?.innerText ?? '');\n } catch (err) {\n return `Read${selector ? ` of \"${selector}\"` : ''} failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const capped = text.length > 8000 ? `${text.slice(0, 8000)}\\n\u2026(truncated)` : text;\n return `${this.orientLine(await this.orient(botId, page))}\\n---\\n${capped}`;\n });\n }\n\n async readLinks(botId: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n let links: Array<{ text: string; href: string }>;\n try {\n links = await page.$$eval('a[href]', (els) =>\n els\n .slice(0, 200)\n .map((e) => ({ text: (e as HTMLElement).innerText.trim().slice(0, 120), href: (e as HTMLAnchorElement).href })),\n );\n } catch (err) {\n return `Reading links failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const body = links.map((l) => `- ${l.text || '(no text)'} -> ${l.href}`).join('\\n') || '(no links found)';\n return `${this.orientLine(await this.orient(botId, page))}\\n---\\n${body}`;\n });\n }\n\n /** Saves a PNG screenshot (to `filePath`, or a temp file if omitted) and returns its path. */\n async screenshot(botId: string, filePath?: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n const target = filePath ?? path.join(os.tmpdir(), `antbot-screenshot-${botId}-${Date.now()}.png`);\n try {\n fs.mkdirSync(path.dirname(target), { recursive: true });\n await page.screenshot({ path: target });\n } catch (err) {\n return `Screenshot failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n return `Screenshot saved to ${target}\\n${this.orientLine(await this.orient(botId, page))}`;\n });\n }\n\n async currentUrl(botId: string): Promise<string> {\n return this.withScreen(botId, async (page) => this.orientLine(await this.orient(botId, page)));\n }\n\n async waitFor(botId: string, selector: string, timeoutMs: number): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n await page.waitForSelector(selector, { timeout: timeoutMs });\n } catch (err) {\n return `Waiting for \"${selector}\" timed out: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n return `Found \"${selector}\".\\n${this.orientLine(await this.orient(botId, page))}`;\n });\n }\n\n async scroll(botId: string, dy: number): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n await page.mouse.wheel(0, dy);\n } catch (err) {\n return `Scroll failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n return `Scrolled by ${dy}px.\\n${this.orientLine(await this.orient(botId, page))}`;\n });\n }\n\n async goBack(botId: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n await page.goBack({ waitUntil: 'domcontentloaded', timeout: 15000 });\n } catch (err) {\n return `Go back failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const block = await this.checkBlock(botId, page);\n const o = await this.orient(botId, page);\n return block ? `${block}\\n${this.orientLine(o)}` : `Went back.\\n${this.orientLine(o)}`;\n });\n }\n\n /* ---------------------------------------------------------------------------------------- *\n * Screencast \u2014 CDP-driven JPEG frames, throttled to ~4fps, reference-counted per bot so it\n * auto-stops once the last viewer detaches.\n * ---------------------------------------------------------------------------------------- */\n\n async startScreencast(botId: string, onFrame: FrameListener): Promise<() => void> {\n const page = await this.getPage(botId);\n\n let listeners = this.screencastListeners.get(botId);\n if (!listeners) {\n listeners = new Set();\n this.screencastListeners.set(botId, listeners);\n }\n listeners.add(onFrame);\n this.viewerCounts.set(botId, (this.viewerCounts.get(botId) ?? 0) + 1);\n\n if (!this.screencastSessions.has(botId)) {\n const ctx = await this.ensureContext();\n const session = await ctx.newCDPSession(page);\n const throttle = new FrameThrottle(4);\n this.screencastSessions.set(botId, session);\n this.screencastThrottles.set(botId, throttle);\n\n session.on('Page.screencastFrame', (evt) => {\n void session.send('Page.screencastFrameAck', { sessionId: evt.sessionId }).catch(() => {});\n const w = evt.metadata?.deviceWidth ?? 0;\n const h = evt.metadata?.deviceHeight ?? 0;\n // Recorded on every frame, before the throttle: input must scale against the page's\n // current geometry, which changes on resize and navigation regardless of what the\n // viewer happens to be shown.\n if (w > 0 && h > 0) this.lastFrameSize.set(botId, { width: w, height: h });\n if (!throttle.shouldEmit()) return;\n for (const l of listeners!) {\n try {\n l(evt.data, w, h);\n } catch (err) {\n log.warn('screencast frame listener threw', err);\n }\n }\n });\n\n await session.send('Page.startScreencast', { format: 'jpeg', quality: 60, maxWidth: 1280, everyNthFrame: 2 });\n\n // Chromium emits screencast frames only when something repaints, so a page sitting still\n // \u2014 a login form, a 2FA prompt, exactly what a human takes over to deal with \u2014 delivers\n // nothing and the viewer stays blank forever. Seed it with one screenshot so there is\n // always something on screen; live frames take over from there.\n void this.seedFirstFrame(botId, page).catch((err) => log.warn('screencast seed frame failed', err));\n }\n\n let stopped = false;\n return () => {\n if (stopped) return;\n stopped = true;\n listeners!.delete(onFrame);\n const remaining = Math.max(0, (this.viewerCounts.get(botId) ?? 1) - 1);\n this.viewerCounts.set(botId, remaining);\n if (remaining > 0) return;\n\n const session = this.screencastSessions.get(botId);\n this.screencastSessions.delete(botId);\n this.screencastThrottles.delete(botId);\n this.screencastListeners.delete(botId);\n this.lastFrameSize.delete(botId);\n if (session) {\n void session\n .send('Page.stopScreencast')\n .catch(() => {})\n .then(() => session.detach().catch(() => {}));\n }\n };\n }\n\n /* ---------------------------------------------------------------------------------------- *\n * Takeover \u2014 pauses agent-driven actions on a bot's screen for the human.\n * ---------------------------------------------------------------------------------------- */\n\n isTakenOver(botId: string): boolean {\n return this.takenOver.has(botId);\n }\n\n /**\n * Marks the screen as human-controlled. When headless, there is no window to bring forward\n * (and launching a second headed context on the same profile dir isn't possible \u2014 Chromium\n * locks the profile), so the human acts through the screencast view instead; interactive input\n * forwarding through that view is out of scope here. When headed, brings the real window to\n * the front for the human to drive directly.\n */\n async takeOver(botId: string): Promise<TakeOverResult> {\n this.takenOver.add(botId);\n if (this.headlessMode) {\n return {\n ok: true,\n mode: 'screencast-only',\n message:\n 'This computer is running headless, so there is no window to bring to the front. ' +\n 'Act through the screencast view for the blocked step (password, 2FA, CAPTCHA), then return control. ' +\n 'Never paste secrets into chat.',\n };\n }\n try {\n const page = await this.getPage(botId);\n await page.bringToFront();\n } catch (err) {\n log.warn('failed to bring page to front for takeover', err);\n }\n return {\n ok: true,\n mode: 'window',\n message: 'The browser window for this bot has been brought to the front. Complete the blocked step, then return control.',\n };\n }\n\n returnControl(botId: string): void {\n this.takenOver.delete(botId);\n this.inputQueue.delete(botId);\n this.inputDepth.delete(botId);\n }\n\n /**\n * The remote page's current text selection, for copying out of a taken-over screen.\n *\n * Gated the same way as input: while a bot is working the screencast is a window, not a\n * console. Reading a selection is milder than clicking, but the rule \"this channel does\n * nothing unless the human holds control\" is worth more than the exception.\n *\n * Capped, because a selection can be an entire document and this crosses a socket that is\n * otherwise carrying video.\n */\n async readSelection(botId: string): Promise<string> {\n if (!this.takenOver.has(botId)) {\n throw new ScreenNotTakenOverError(\n 'A selection was requested for a screen that is not taken over. Take over the screen first.',\n );\n }\n const page = await this.getPage(botId);\n const text = await page.evaluate(() => {\n // Text selected inside a form field is not reliably part of the document selection, so\n // check the focused control first \u2014 copying out of a login field is a likely reason to be\n // here in the first place.\n const el = document.activeElement as HTMLInputElement | HTMLTextAreaElement | null;\n if (el && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA')) {\n const { selectionStart: a, selectionEnd: b, value } = el;\n if (typeof a === 'number' && typeof b === 'number' && b > a) return value.slice(a, b);\n }\n return window.getSelection()?.toString() ?? '';\n });\n return text.slice(0, MAX_SELECTION_CHARS);\n }\n\n /** One immediate JPEG so a static page is not a blank pane. See startScreencast. */\n private async seedFirstFrame(botId: string, page: Page): Promise<void> {\n const listeners = this.screencastListeners.get(botId);\n if (!listeners?.size) return;\n const buf = await page.screenshot({ type: 'jpeg', quality: 60 });\n const vp = page.viewportSize() ?? { width: 0, height: 0 };\n if (vp.width > 0 && vp.height > 0) this.lastFrameSize.set(botId, vp);\n for (const l of listeners) {\n try {\n l(buf.toString('base64'), vp.width, vp.height);\n } catch (err) {\n log.warn('screencast seed listener threw', err);\n }\n }\n }\n\n /**\n * The page's CSS viewport, which is what input coordinates are in.\n *\n * `viewportSize()` is synchronous and correct whenever the context sets one; a persistent\n * context launched without an explicit viewport returns null, so fall back to asking the page.\n * The cached value is only a last resort for a page that has since closed.\n */\n private async viewportOf(botId: string, page: Page): Promise<FrameSize | undefined> {\n const vp = page.viewportSize();\n if (vp && vp.width > 0 && vp.height > 0) {\n this.lastFrameSize.set(botId, { width: vp.width, height: vp.height });\n return vp;\n }\n try {\n const inner = await page.evaluate(() => ({ width: window.innerWidth, height: window.innerHeight }));\n if (inner.width > 0 && inner.height > 0) {\n this.lastFrameSize.set(botId, inner);\n return inner;\n }\n } catch { /* page closed or navigating */ }\n return this.lastFrameSize.get(botId);\n }\n\n /**\n * Dispatches human input into a taken-over page.\n *\n * The takeover check is the whole security model here. It is applied twice on purpose: on entry,\n * so a caller is refused immediately, and again at dispatch, because events *are* queued for\n * ordering and control can be returned while some are still pending. Without the second check a\n * stale click would land after handback, into a page the bot has since navigated. Input does not\n * pass the Permission Gateway, because the gateway governs what *bots* do; this is the human\n * acting as themselves on their own computer.\n *\n * Dispatch goes through Playwright's `page.mouse` / `page.keyboard` rather than raw CDP so the\n * key-code mapping is the SDK's problem, matching how `click()` and `type()` above work.\n */\n async forwardInput(botId: string, ev: ScreencastInput): Promise<void> {\n if (!this.takenOver.has(botId)) {\n throw new ScreenNotTakenOverError(\n 'Input was sent for a screen that is not taken over. Take over the screen first.',\n );\n }\n\n // Input is strictly ordered per screen. The websocket handler dispatches each frame without\n // awaiting the last, so without this chain a mouse-down and mouse-up race each other and a\n // burst of typing arrives shuffled \u2014 which reads as \"some keys work\" rather than as a bug.\n const depth = (this.inputDepth.get(botId) ?? 0) + 1;\n this.inputDepth.set(botId, depth);\n\n // A pointer streams moves faster than they can be dispatched. Dropping stale moves under\n // backlog keeps the queue from growing without bound; the next move supersedes them anyway.\n // Never dropped: clicks, keys and text, where every event is meaningful.\n if (ev.kind === 'mouse' && ev.action === 'move' && depth > MAX_QUEUED_INPUT) {\n this.inputDepth.set(botId, depth - 1);\n return;\n }\n\n const run = async (): Promise<void> => {\n try {\n // Re-checked here, not just on entry: control can be returned while events are queued,\n // and a click that lands afterwards would hit a page the bot has already moved on.\n if (this.takenOver.has(botId)) await this.dispatchInput(botId, ev);\n } finally {\n this.inputDepth.set(botId, Math.max(0, (this.inputDepth.get(botId) ?? 1) - 1));\n }\n };\n\n const chained = (this.inputQueue.get(botId) ?? Promise.resolve()).then(run, run);\n // Stored swallowing rejections so one failed event cannot poison every later one.\n this.inputQueue.set(botId, chained.catch(() => {}));\n return chained;\n }\n\n private async dispatchInput(botId: string, ev: ScreencastInput): Promise<void> {\n const page = await this.getPage(botId);\n\n if (ev.kind === 'text') {\n await page.keyboard.insertText(ev.text);\n return;\n }\n\n if (ev.kind === 'key') {\n if (!isForwardableKey(ev.key)) return;\n if (ev.action === 'down') await page.keyboard.down(ev.key);\n else await page.keyboard.up(ev.key);\n return;\n }\n\n const pt = toPageCoords({ x: ev.x, y: ev.y }, await this.viewportOf(botId, page));\n // Geometry genuinely unknown \u2014 a guessed coordinate is a click the human did not aim.\n if (!pt) return;\n\n switch (ev.action) {\n case 'move':\n await page.mouse.move(pt.x, pt.y);\n break;\n case 'down':\n await page.mouse.move(pt.x, pt.y);\n await page.mouse.down({ button: ev.button, clickCount: Math.max(1, ev.clickCount) });\n break;\n case 'up':\n await page.mouse.up({ button: ev.button, clickCount: Math.max(1, ev.clickCount) });\n break;\n case 'wheel':\n await page.mouse.move(pt.x, pt.y);\n await page.mouse.wheel(clampWheel(ev.deltaX), clampWheel(ev.deltaY));\n break;\n }\n }\n\n /* ---------------------------------------------------------------------------------------- */\n\n /** Never launches the browser. Reports optimistically until a launch attempt has failed. */\n status(): BrowserStatus {\n if (this.unavailableReason) {\n return { available: false, reason: this.unavailableReason, mode: 'host', headless: this.headlessMode, pages: [] };\n }\n const pages: ComputerPageStatus[] = [];\n if (this.context) {\n for (const [botId, page] of this.pages) {\n if (page.isClosed()) continue;\n pages.push({ botId, url: page.url(), title: this.titleCache.get(botId) ?? '' });\n }\n }\n return { available: true, mode: 'host', headless: this.headlessMode, pages };\n }\n\n async shutdown(): Promise<void> {\n for (const session of this.screencastSessions.values()) {\n await session\n .send('Page.stopScreencast')\n .catch(() => {})\n .then(() => session.detach().catch(() => {}));\n }\n this.screencastSessions.clear();\n this.screencastListeners.clear();\n this.screencastThrottles.clear();\n this.viewerCounts.clear();\n\n for (const page of this.pages.values()) {\n await page.close().catch(() => {});\n }\n this.pages.clear();\n this.titleCache.clear();\n this.takenOver.clear();\n\n if (this.context) {\n await this.context.close().catch(() => {});\n this.context = null;\n }\n this.launchPromise = null;\n }\n}\n", "// Turning normalised screencast input into page coordinates.\n//\n// The client sends fractions of the frame, not pixels, because neither side knows the other's\n// geometry: the screencast is captured at up to 1280px wide (Chromium picks the scale), and the\n// browser then fits that image into whatever the pane happens to be. Pixels sent from the client\n// would be in a third coordinate space belonging to neither.\n//\n// Pure, so every rounding and clamping case below is testable without a browser.\n\n/** Viewport size reported by the most recent screencast frame, in CSS pixels. */\nexport interface FrameSize {\n width: number;\n height: number;\n}\n\n/**\n * Converts a normalised point to page CSS pixels, or null when the conversion cannot be trusted.\n *\n * Null rather than a clamped guess when the frame size is unknown or degenerate: dispatching a\n * click at (0, 0) because no frame has arrived yet would hit whatever is in the top-left corner,\n * which is exactly the kind of silent wrong action this codebase avoids.\n */\nexport function toPageCoords(\n norm: { x: number; y: number },\n frame: FrameSize | undefined,\n): { x: number; y: number } | null {\n if (!frame) return null;\n if (!Number.isFinite(frame.width) || !Number.isFinite(frame.height)) return null;\n if (frame.width <= 0 || frame.height <= 0) return null;\n if (!Number.isFinite(norm.x) || !Number.isFinite(norm.y)) return null;\n\n const clamp01 = (n: number): number => (n < 0 ? 0 : n > 1 ? 1 : n);\n // Clamped to the last addressable pixel: x = 1.0 would otherwise land one pixel outside the\n // viewport, which Chromium ignores rather than treating as an edge click.\n return {\n x: Math.min(Math.round(clamp01(norm.x) * frame.width), frame.width - 1),\n y: Math.min(Math.round(clamp01(norm.y) * frame.height), frame.height - 1),\n };\n}\n\n/**\n * Keys that must not be forwarded to the page, whatever the client sends.\n *\n * These either close or navigate away from the page the human was asked to unblock \u2014 losing the\n * session they took over to rescue \u2014 or they open browser-level UI the screencast cannot show,\n * leaving the view frozen on a page that is no longer in front. The human still has every normal\n * key, including Tab, Enter and Escape.\n */\nconst BLOCKED_KEYS = new Set(['F5', 'F11', 'F12', 'BrowserRefresh', 'BrowserBack', 'BrowserForward']);\n\n/** Whether a key event is safe to dispatch into a taken-over page. */\nexport function isForwardableKey(key: string): boolean {\n return key.length > 0 && !BLOCKED_KEYS.has(key);\n}\n\n/**\n * Wheel deltas, bounded. An unbounded delta from a malformed client would scroll a page by\n * millions of pixels in one event; clamping keeps a bad frame from being disorienting.\n */\nexport function clampWheel(delta: number): number {\n if (!Number.isFinite(delta)) return 0;\n const MAX = 1000;\n return Math.max(-MAX, Math.min(MAX, Math.round(delta)));\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -33,9 +33,6 @@ var LimitError = class extends Error {
33
33
  }
34
34
  };
35
35
 
36
- // contract/dist/events.js
37
- import { z as z2 } from "zod";
38
-
39
36
  // contract/dist/entities.js
40
37
  import { z } from "zod";
41
38
  var BotStateSchema = z.enum([
@@ -157,6 +154,40 @@ var SkillSchema = z.object({
157
154
  source: z.enum(["user", "taught", "imported"]).default("user"),
158
155
  createdAt: z.number()
159
156
  });
157
+ var CONNECTOR_NAME_RE = /^[a-z0-9][a-z0-9-]{0,31}$/;
158
+ var RESERVED_CONNECTOR_NAMES = ["antbot", "browser"];
159
+ var ConnectorConfigSchema = z.discriminatedUnion("transport", [
160
+ z.object({
161
+ transport: z.literal("stdio"),
162
+ command: z.string().min(1),
163
+ args: z.array(z.string()).default([]),
164
+ env: z.record(z.string(), z.string()).default({})
165
+ }),
166
+ z.object({
167
+ transport: z.literal("http"),
168
+ url: z.string().url(),
169
+ headers: z.record(z.string(), z.string()).default({}),
170
+ /** Optional allowlist passed through to the SDK. Omit to expose every tool the server offers. */
171
+ tools: z.array(z.string()).optional()
172
+ }),
173
+ z.object({
174
+ transport: z.literal("sse"),
175
+ url: z.string().url(),
176
+ headers: z.record(z.string(), z.string()).default({}),
177
+ tools: z.array(z.string()).optional()
178
+ })
179
+ ]);
180
+ var ConnectorSchema = z.object({
181
+ id: z.string(),
182
+ name: z.string().regex(CONNECTOR_NAME_RE, "lowercase letters, digits and hyphens only, max 32 characters").refine((n) => !RESERVED_CONNECTOR_NAMES.includes(n), {
183
+ message: `"antbot" and "browser" are reserved for the built-in servers`
184
+ }),
185
+ description: z.string().default(""),
186
+ /** Account-wide switch. A disabled connector mounts for nobody, whatever the assignments say. */
187
+ enabled: z.boolean().default(true),
188
+ config: ConnectorConfigSchema,
189
+ createdAt: z.number()
190
+ });
160
191
  var RoutineSchema = z.object({
161
192
  id: z.string(),
162
193
  botId: z.string(),
@@ -202,6 +233,7 @@ var UsageRowSchema = z.object({
202
233
  var TurnOriginSchema = z.enum(["user", "bot", "routine", "system"]);
203
234
 
204
235
  // contract/dist/events.js
236
+ import { z as z2 } from "zod";
205
237
  var base = { seq: z2.number(), threadId: z2.string().nullable(), botId: z2.string().nullable() };
206
238
  var ServerEventSchema = z2.discriminatedUnion("type", [
207
239
  /** Connection handshake. Carries the current seq so a client can detect gaps. */
@@ -308,6 +340,17 @@ var CreateSkillRequest = z3.object({
308
340
  bodyMd: z3.string().min(1),
309
341
  source: z3.enum(["user", "taught", "imported"]).optional()
310
342
  });
343
+ var CreateConnectorRequest = z3.object({
344
+ name: ConnectorSchema.shape.name,
345
+ description: z3.string().default(""),
346
+ config: ConnectorConfigSchema,
347
+ enabled: z3.boolean().optional()
348
+ });
349
+ var UpdateConnectorRequest = z3.object({
350
+ description: z3.string().optional(),
351
+ config: ConnectorConfigSchema.optional(),
352
+ enabled: z3.boolean().optional()
353
+ });
311
354
  var settingsFields = {
312
355
  timezone: z3.string(),
313
356
  maxConcurrentSessions: z3.number().min(1).max(8),
@@ -345,6 +388,7 @@ export {
345
388
  LIMITS,
346
389
  LIMIT_ERROR,
347
390
  LimitError,
391
+ ConnectorConfigSchema,
348
392
  ScreencastClientFrameSchema,
349
393
  CreateBotRequest,
350
394
  UpdateBotRequest,
@@ -354,7 +398,9 @@ export {
354
398
  CreateRuleRequest,
355
399
  CreateRoutineRequest,
356
400
  CreateSkillRequest,
401
+ CreateConnectorRequest,
402
+ UpdateConnectorRequest,
357
403
  SettingsSchema,
358
404
  SettingsPatchSchema
359
405
  };
360
- //# sourceMappingURL=chunk-4XML2GPY.js.map
406
+ //# sourceMappingURL=chunk-RMDMUCVS.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../contract/src/limits.ts", "../../contract/src/entities.ts", "../../contract/src/events.ts", "../../contract/src/api.ts"],
4
+ "sourcesContent": ["/** Operational limits \u2014 mirrors grok-bot-system-outline.md \u00A713. */\nexport const LIMITS = {\n MAX_BOTS_AND_GROUPS: 50,\n MIN_GROUP_MEMBERS: 2,\n MAX_GROUP_MEMBERS: 6,\n MAX_ROUTINES_PER_BOT: 50,\n ROUTINE_RUNS_RETAINED: 20,\n MAX_ATTACHMENTS_PER_MESSAGE: 6,\n MAX_ATTACHMENT_BYTES: 25 * 1024 * 1024,\n MAX_VIDEO_ATTACHMENT_BYTES: 200 * 1024 * 1024,\n MAX_BOT_TO_BOT_HOPS: 5,\n DEFAULT_MAX_CONCURRENT_SESSIONS: 2,\n APPROVAL_TIMEOUT_MS: 15 * 60 * 1000,\n TEACH_RECORDING_MAX_MS: 10 * 60 * 1000,\n} as const;\n\n/** Error codes returned by the service layer when a limit is violated. */\nexport const LIMIT_ERROR = {\n TOO_MANY_BOTS: 'TOO_MANY_BOTS',\n GROUP_SIZE: 'GROUP_SIZE',\n TOO_MANY_ROUTINES: 'TOO_MANY_ROUTINES',\n TOO_MANY_ATTACHMENTS: 'TOO_MANY_ATTACHMENTS',\n ATTACHMENT_TOO_LARGE: 'ATTACHMENT_TOO_LARGE',\n HOP_LIMIT: 'HOP_LIMIT',\n} as const;\nexport type LimitErrorCode = (typeof LIMIT_ERROR)[keyof typeof LIMIT_ERROR];\n\nexport class LimitError extends Error {\n constructor(\n public code: LimitErrorCode,\n message: string,\n ) {\n super(message);\n this.name = 'LimitError';\n }\n}\n", "import { z } from 'zod';\n\nexport const BotStateSchema = z.enum([\n 'idle',\n 'queued',\n 'running',\n 'waiting_approval',\n 'waiting_input',\n 'interrupted',\n]);\nexport type BotState = z.infer<typeof BotStateSchema>;\n\nexport const AttentionSchema = z.enum(['none', 'unread', 'needs_attention']);\nexport type Attention = z.infer<typeof AttentionSchema>;\n\n/**\n * Model tiers a Bot can run on, ordered most to least capable \u2014 this is also the order the UI\n * renders them in, so both pickers stay consistent without repeating the list.\n *\n * Each value is a `claude` CLI model alias, passed through verbatim by `resolveModel()`. Adding a\n * tier here means adding an alias the CLI accepts (`claude --model`), not an API model ID.\n */\nexport const MODEL_TIERS = ['fable', 'opus', 'sonnet', 'haiku'] as const;\nexport const ModelTierSchema = z.enum(MODEL_TIERS);\nexport type ModelTier = z.infer<typeof ModelTierSchema>;\n\nexport const BotSchema = z.object({\n id: z.string(),\n slug: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),\n name: z.string().min(1).max(60),\n title: z.string().max(120).default(''),\n description: z.string().max(8000).default(''),\n avatarEmoji: z.string().max(8).default('\uD83E\uDD16'),\n modelTier: ModelTierSchema.default('sonnet'),\n pinned: z.boolean().default(false),\n hidden: z.boolean().default(false),\n notifications: z.boolean().default(true),\n sessionId: z.string().nullable().default(null),\n state: BotStateSchema.default('idle'),\n attention: AttentionSchema.default('none'),\n threadId: z.string().nullable().default(null),\n createdAt: z.number(),\n deletedAt: z.number().nullable().default(null),\n});\nexport type Bot = z.infer<typeof BotSchema>;\n\nexport const ThreadKindSchema = z.enum(['dm', 'group']);\nexport type ThreadKind = z.infer<typeof ThreadKindSchema>;\n\nexport const ThreadSchema = z.object({\n id: z.string(),\n kind: ThreadKindSchema,\n title: z.string().default(''),\n memberBotIds: z.array(z.string()).default([]),\n pinned: z.boolean().default(false),\n hidden: z.boolean().default(false),\n lastReadAt: z.number().default(0),\n createdAt: z.number(),\n});\nexport type Thread = z.infer<typeof ThreadSchema>;\n\n/** Cards render structured, non-prose content inside a message. */\nexport const CardSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('tool'),\n toolName: z.string(),\n summary: z.string(),\n input: z.unknown().optional(),\n result: z.string().optional(),\n status: z.enum(['running', 'ok', 'error', 'denied']),\n }),\n z.object({\n type: z.literal('file'),\n path: z.string(),\n name: z.string(),\n mime: z.string(),\n bytes: z.number(),\n action: z.enum(['created', 'modified']).default('created'),\n }),\n z.object({ type: z.literal('approval'), approvalId: z.string() }),\n z.object({ type: z.literal('handoff'), fromBotId: z.string(), toBotId: z.string(), note: z.string() }),\n z.object({ type: z.literal('error'), message: z.string() }),\n]);\nexport type Card = z.infer<typeof CardSchema>;\n\nexport const AuthorKindSchema = z.enum(['user', 'bot', 'system']);\nexport type AuthorKind = z.infer<typeof AuthorKindSchema>;\n\nexport const MessageSchema = z.object({\n id: z.string(),\n threadId: z.string(),\n authorKind: AuthorKindSchema,\n authorBotId: z.string().nullable().default(null),\n replyToId: z.string().nullable().default(null),\n contentMd: z.string().default(''),\n cards: z.array(CardSchema).default([]),\n streaming: z.boolean().default(false),\n createdAt: z.number(),\n});\nexport type Message = z.infer<typeof MessageSchema>;\n\nexport const AttachmentSchema = z.object({\n id: z.string(),\n messageId: z.string().nullable(),\n path: z.string(),\n name: z.string(),\n mime: z.string(),\n bytes: z.number(),\n createdAt: z.number(),\n});\nexport type Attachment = z.infer<typeof AttachmentSchema>;\n\nexport const ApprovalStatusSchema = z.enum(['pending', 'allowed', 'denied', 'expired']);\nexport type ApprovalStatus = z.infer<typeof ApprovalStatusSchema>;\n\nexport const ApprovalSchema = z.object({\n id: z.string(),\n botId: z.string(),\n threadId: z.string(),\n toolName: z.string(),\n inputSummary: z.string(),\n rawInput: z.unknown(),\n status: ApprovalStatusSchema.default('pending'),\n decidedBy: z.enum(['user', 'rule', 'auto_review']).nullable().default(null),\n reason: z.string().default(''),\n ruleId: z.string().nullable().default(null),\n createdAt: z.number(),\n decidedAt: z.number().nullable().default(null),\n});\nexport type Approval = z.infer<typeof ApprovalSchema>;\n\nexport const RuleKindSchema = z.enum(['require', 'allow']);\nexport type RuleKind = z.infer<typeof RuleKindSchema>;\n\nexport const RuleSchema = z.object({\n id: z.string(),\n kind: RuleKindSchema,\n /** Glob over tool name, e.g. \"Bash\", \"browser_*\", \"*\" */\n toolPattern: z.string().default('*'),\n /** Optional regex tested against the serialized tool input. */\n inputPattern: z.string().default(''),\n scopeNote: z.string().default(''),\n builtin: z.boolean().default(false),\n enabled: z.boolean().default(true),\n createdAt: z.number(),\n});\nexport type Rule = z.infer<typeof RuleSchema>;\n\nexport const SkillSchema = z.object({\n id: z.string(),\n slug: z.string(),\n name: z.string(),\n description: z.string().default(''),\n path: z.string(),\n source: z.enum(['user', 'taught', 'imported']).default('user'),\n createdAt: z.number(),\n});\nexport type Skill = z.infer<typeof SkillSchema>;\n\n/* ------------------------------ MCP connectors ------------------------------ */\n\n/**\n * Connector names become the middle segment of every tool name the model sees:\n * `mcp__<name>__<tool>`. Underscores are banned outright because `toolNameAliases()`\n * splits on the first `__` pair \u2014 a name containing one would make a connector's tools\n * unmatchable by the rules that are supposed to gate them.\n */\nexport const CONNECTOR_NAME_RE = /^[a-z0-9][a-z0-9-]{0,31}$/;\n\n/** Taken by the built-in servers; a connector using one would overwrite it in the turn's server map. */\nexport const RESERVED_CONNECTOR_NAMES = ['antbot', 'browser'] as const;\n\n/**\n * How to reach an MCP server. Mirrors the Agent SDK's own `McpServerConfig` minus the\n * in-process `sdk` variant, which only the built-in servers use.\n *\n * Secret values are never stored here. An env value or header may embed `{{secret:NAME}}`,\n * resolved against the keychain at mount time \u2014 see `daemon/src/bots/connectors.ts`.\n */\nexport const ConnectorConfigSchema = z.discriminatedUnion('transport', [\n z.object({\n transport: z.literal('stdio'),\n command: z.string().min(1),\n args: z.array(z.string()).default([]),\n env: z.record(z.string(), z.string()).default({}),\n }),\n z.object({\n transport: z.literal('http'),\n url: z.string().url(),\n headers: z.record(z.string(), z.string()).default({}),\n /** Optional allowlist passed through to the SDK. Omit to expose every tool the server offers. */\n tools: z.array(z.string()).optional(),\n }),\n z.object({\n transport: z.literal('sse'),\n url: z.string().url(),\n headers: z.record(z.string(), z.string()).default({}),\n tools: z.array(z.string()).optional(),\n }),\n]);\nexport type ConnectorConfig = z.infer<typeof ConnectorConfigSchema>;\n\nexport const ConnectorSchema = z.object({\n id: z.string(),\n name: z\n .string()\n .regex(CONNECTOR_NAME_RE, 'lowercase letters, digits and hyphens only, max 32 characters')\n .refine((n) => !(RESERVED_CONNECTOR_NAMES as readonly string[]).includes(n), {\n message: `\"antbot\" and \"browser\" are reserved for the built-in servers`,\n }),\n description: z.string().default(''),\n /** Account-wide switch. A disabled connector mounts for nobody, whatever the assignments say. */\n enabled: z.boolean().default(true),\n config: ConnectorConfigSchema,\n createdAt: z.number(),\n});\nexport type Connector = z.infer<typeof ConnectorSchema>;\n\nexport const RoutineSchema = z.object({\n id: z.string(),\n botId: z.string(),\n name: z.string().min(1),\n cronExpr: z.string(),\n timezone: z.string().default('UTC'),\n instructionMd: z.string(),\n enabled: z.boolean().default(true),\n lastRunAt: z.number().nullable().default(null),\n nextRunAt: z.number().nullable().default(null),\n createdAt: z.number(),\n});\nexport type Routine = z.infer<typeof RoutineSchema>;\n\nexport const RoutineRunSchema = z.object({\n id: z.string(),\n routineId: z.string(),\n startedAt: z.number(),\n finishedAt: z.number().nullable().default(null),\n status: z.enum(['running', 'ok', 'failed', 'interrupted']),\n summary: z.string().default(''),\n threadId: z.string().nullable().default(null),\n isTest: z.boolean().default(false),\n});\nexport type RoutineRun = z.infer<typeof RoutineRunSchema>;\n\nexport const MailboxEntrySchema = z.object({\n id: z.string(),\n fromBotId: z.string(),\n toBotId: z.string(),\n contentMd: z.string(),\n hops: z.number().default(1),\n delivered: z.boolean().default(false),\n createdAt: z.number(),\n});\nexport type MailboxEntry = z.infer<typeof MailboxEntrySchema>;\n\nexport const UsageRowSchema = z.object({\n id: z.string(),\n botId: z.string(),\n turnId: z.string(),\n model: z.string(),\n inputTokens: z.number().default(0),\n outputTokens: z.number().default(0),\n cacheReadTokens: z.number().default(0),\n costEstimate: z.number().default(0),\n createdAt: z.number(),\n});\nexport type UsageRow = z.infer<typeof UsageRowSchema>;\n\nexport const TurnOriginSchema = z.enum(['user', 'bot', 'routine', 'system']);\nexport type TurnOrigin = z.infer<typeof TurnOriginSchema>;\n", "import { z } from 'zod';\nimport { BotStateSchema, AttentionSchema, CardSchema, MessageSchema, ApprovalSchema, RoutineRunSchema } from './entities.js';\n\n/** Every server\u2192client event carries {threadId, botId, seq} for ordering/reconciliation. */\nconst base = { seq: z.number(), threadId: z.string().nullable(), botId: z.string().nullable() };\n\nexport const ServerEventSchema = z.discriminatedUnion('type', [\n /** Connection handshake. Carries the current seq so a client can detect gaps. */\n z.object({ ...base, type: z.literal('hello') }),\n z.object({ ...base, type: z.literal('message.created'), message: MessageSchema }),\n z.object({ ...base, type: z.literal('message.delta'), messageId: z.string(), delta: z.string() }),\n z.object({ ...base, type: z.literal('message.done'), messageId: z.string(), contentMd: z.string() }),\n z.object({ ...base, type: z.literal('message.card'), messageId: z.string(), card: CardSchema, cardIndex: z.number() }),\n z.object({ ...base, type: z.literal('bot.state'), state: BotStateSchema, attention: AttentionSchema }),\n z.object({ ...base, type: z.literal('approval.pending'), approval: ApprovalSchema }),\n z.object({ ...base, type: z.literal('approval.resolved'), approval: ApprovalSchema }),\n z.object({ ...base, type: z.literal('routine.run'), run: RoutineRunSchema }),\n z.object({ ...base, type: z.literal('usage.tick'), inputTokens: z.number(), outputTokens: z.number(), model: z.string() }),\n z.object({ ...base, type: z.literal('notify'), title: z.string(), body: z.string(), level: z.enum(['info', 'warn', 'error']) }),\n z.object({ ...base, type: z.literal('secret.request'), requestId: z.string(), name: z.string(), reason: z.string() }),\n z.object({ ...base, type: z.literal('thread.updated'), threadId2: z.string() }),\n]);\nexport type ServerEvent = z.infer<typeof ServerEventSchema>;\nexport type ServerEventType = ServerEvent['type'];\n\n/* ------------------------- screencast input (client \u2192 server) ------------------------- */\n\n/**\n * Human input forwarded over the screencast websocket while a screen is taken over.\n *\n * Coordinates are **normalised** (0\u20131, fractions of the rendered frame) rather than pixels: the\n * screencast is capped at 1280px wide and the browser then scales the image to fit the pane, so\n * the client cannot know the page's real viewport and the server cannot know the client's. Each\n * side converts against what it does know.\n *\n * The daemon dispatches these only while `takeOver()` is active for that bot \u2014 see\n * `docs/SECURITY.md`. Input is a human acting as themselves, so it does not pass the Permission\n * Gateway; the gateway governs what *bots* do.\n */\nexport const ScreencastInputSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('mouse'),\n action: z.enum(['move', 'down', 'up', 'wheel']),\n x: z.number().min(0).max(1),\n y: z.number().min(0).max(1),\n button: z.enum(['left', 'middle', 'right']).default('left'),\n clickCount: z.number().int().min(0).max(3).default(1),\n /** Wheel deltas, in CSS pixels. Only read for `action: 'wheel'`. */\n deltaX: z.number().default(0),\n deltaY: z.number().default(0),\n }),\n z.object({\n kind: z.literal('key'),\n action: z.enum(['down', 'up']),\n /** A KeyboardEvent.key value \u2014 Playwright's keyboard maps these to the right key codes. */\n key: z.string().min(1).max(32),\n }),\n z.object({\n kind: z.literal('text'),\n /** Committed text (IME, paste, or a printable keypress), inserted verbatim. */\n text: z.string().min(1).max(4096),\n }),\n]);\nexport type ScreencastInput = z.infer<typeof ScreencastInputSchema>;\n\n/** Frames the client may send on the screencast socket. */\nexport const ScreencastClientFrameSchema = z.discriminatedUnion('type', [\n z.object({ type: z.literal('input'), input: ScreencastInputSchema }),\n /**\n * Asks for the remote page's current text selection, so the human can copy out of it.\n *\n * A round trip is needed because the two clipboards are different: pressing Ctrl+C in the\n * viewer copies whatever is selected in *your* browser (nothing \u2014 the page is a JPEG), and\n * forwarding Ctrl+C to the page would write to the headless browser's clipboard, which you\n * have no way to read. So the daemon reads the selection and hands the text back for the\n * viewer to put on your clipboard.\n */\n z.object({ type: z.literal('selection-request') }),\n]);\nexport type ScreencastClientFrame = z.infer<typeof ScreencastClientFrameSchema>;\n", "import { z } from 'zod';\nimport {\n BotSchema, ThreadSchema, MessageSchema, ApprovalSchema, RuleSchema,\n SkillSchema, RoutineSchema, RoutineRunSchema, UsageRowSchema, ModelTierSchema,\n ConnectorSchema, ConnectorConfigSchema, type Connector,\n} from './entities.js';\n\nexport const CreateBotRequest = z.object({\n name: z.string().min(1).max(60),\n title: z.string().max(120).optional(),\n description: z.string().max(8000).optional(),\n avatarEmoji: z.string().max(8).optional(),\n modelTier: ModelTierSchema.optional(),\n});\nexport type CreateBotRequest = z.infer<typeof CreateBotRequest>;\n\nexport const UpdateBotRequest = CreateBotRequest.partial().extend({\n pinned: z.boolean().optional(),\n hidden: z.boolean().optional(),\n notifications: z.boolean().optional(),\n});\nexport type UpdateBotRequest = z.infer<typeof UpdateBotRequest>;\n\nexport const CreateThreadRequest = z.object({\n kind: z.enum(['dm', 'group']),\n title: z.string().optional(),\n memberBotIds: z.array(z.string()),\n});\nexport type CreateThreadRequest = z.infer<typeof CreateThreadRequest>;\n\nexport const PostMessageRequest = z.object({\n contentMd: z.string(),\n attachmentIds: z.array(z.string()).optional(),\n replyToId: z.string().nullable().optional(),\n /** explicit @-mention targets resolved by the client */\n mentionBotIds: z.array(z.string()).optional(),\n mentionEveryone: z.boolean().optional(),\n});\nexport type PostMessageRequest = z.infer<typeof PostMessageRequest>;\n\nexport const ApprovalDecisionRequest = z.object({\n decision: z.enum(['allow', 'deny']),\n alwaysRule: z\n .object({ toolPattern: z.string(), inputPattern: z.string().default(''), scopeNote: z.string().default('') })\n .optional(),\n});\nexport type ApprovalDecisionRequest = z.infer<typeof ApprovalDecisionRequest>;\n\nexport const CreateRuleRequest = z.object({\n kind: z.enum(['require', 'allow']),\n toolPattern: z.string().min(1),\n inputPattern: z.string().default(''),\n scopeNote: z.string().default(''),\n});\nexport type CreateRuleRequest = z.infer<typeof CreateRuleRequest>;\n\nexport const CreateRoutineRequest = z.object({\n botId: z.string(),\n name: z.string().min(1),\n cronExpr: z.string().min(1),\n timezone: z.string().optional(),\n instructionMd: z.string().min(1),\n enabled: z.boolean().optional(),\n});\nexport type CreateRoutineRequest = z.infer<typeof CreateRoutineRequest>;\n\nexport const CreateSkillRequest = z.object({\n name: z.string().min(1),\n description: z.string().default(''),\n bodyMd: z.string().min(1),\n source: z.enum(['user', 'taught', 'imported']).optional(),\n});\nexport type CreateSkillRequest = z.infer<typeof CreateSkillRequest>;\n\nexport const CreateConnectorRequest = z.object({\n name: ConnectorSchema.shape.name,\n description: z.string().default(''),\n config: ConnectorConfigSchema,\n enabled: z.boolean().optional(),\n});\nexport type CreateConnectorRequest = z.infer<typeof CreateConnectorRequest>;\n\n/**\n * No `name`: renaming a connector renames every tool the model and the rules see\n * (`mcp__<name>__<tool>`), silently orphaning any rule written against the old one.\n * Delete and re-add instead.\n */\nexport const UpdateConnectorRequest = z.object({\n description: z.string().optional(),\n config: ConnectorConfigSchema.optional(),\n enabled: z.boolean().optional(),\n});\nexport type UpdateConnectorRequest = z.infer<typeof UpdateConnectorRequest>;\n\n/**\n * A connector as the API returns it. `missingSecrets` names the `{{secret:\u2026}}` references\n * that have nothing behind them \u2014 surfaced so a connector that will silently fail to mount\n * says so in the UI before a turn runs, rather than going quiet at turn time.\n */\nexport type ApiConnector = Connector & { missingSecrets: string[] };\n\n/** What `POST /api/connectors/:id/test` reports. Tool names and descriptions only \u2014 never config. */\nexport interface ConnectorProbeResult {\n ok: boolean;\n tools: { name: string; description: string }[];\n error?: string;\n}\n\n/**\n * Field types, declared once and without defaults. `SettingsSchema` layers the\n * defaults on for reads; `SettingsPatchSchema` deliberately leaves them off.\n */\nconst settingsFields = {\n timezone: z.string(),\n maxConcurrentSessions: z.number().min(1).max(8),\n autoReviewEnabled: z.boolean(),\n theme: z.enum(['system', 'light', 'dark']),\n localExecution: z.enum(['ask', 'always', 'never']),\n dailyTokenBudget: z.number(),\n notificationsEnabled: z.boolean(),\n billingMode: z.enum(['subscription', 'api']),\n computerMode: z.enum(['host', 'container']),\n};\n\nexport const SettingsSchema = z.object({\n timezone: settingsFields.timezone.default('UTC'),\n maxConcurrentSessions: settingsFields.maxConcurrentSessions.default(2),\n autoReviewEnabled: settingsFields.autoReviewEnabled.default(true),\n theme: settingsFields.theme.default('system'),\n localExecution: settingsFields.localExecution.default('ask'),\n dailyTokenBudget: settingsFields.dailyTokenBudget.default(0),\n notificationsEnabled: settingsFields.notificationsEnabled.default(true),\n billingMode: settingsFields.billingMode.default('subscription'),\n computerMode: settingsFields.computerMode.default('host'),\n});\nexport type Settings = z.infer<typeof SettingsSchema>;\n\n/**\n * Body schema for `PATCH /api/settings`. It must NOT carry defaults: parsing a\n * one-field patch through a defaulted schema yields a complete object, and\n * persisting that would reset every setting the client didn't mention \u2014 including\n * `localExecution`, which is a security control (see docs/SECURITY.md).\n */\nexport const SettingsPatchSchema = z.object(settingsFields).partial();\nexport type SettingsPatch = z.infer<typeof SettingsPatchSchema>;\n\nexport const SearchResultSchema = z.object({\n kind: z.enum(['message', 'file', 'routine', 'bot']),\n id: z.string(),\n threadId: z.string().nullable(),\n botId: z.string().nullable(),\n title: z.string(),\n snippet: z.string(),\n createdAt: z.number(),\n});\nexport type SearchResult = z.infer<typeof SearchResultSchema>;\n\nexport type ApiBot = z.infer<typeof BotSchema>;\nexport type ApiThread = z.infer<typeof ThreadSchema>;\nexport type ApiMessage = z.infer<typeof MessageSchema>;\nexport type ApiApproval = z.infer<typeof ApprovalSchema>;\nexport type ApiRule = z.infer<typeof RuleSchema>;\nexport type ApiSkill = z.infer<typeof SkillSchema>;\nexport type ApiRoutine = z.infer<typeof RoutineSchema>;\nexport type ApiRoutineRun = z.infer<typeof RoutineRunSchema>;\nexport type ApiUsageRow = z.infer<typeof UsageRowSchema>;\n\nexport interface RosterEntry { bot: ApiBot; thread: ApiThread | null; lastMessageAt: number }\nexport interface ThreadWithMessages { thread: ApiThread; messages: ApiMessage[] }\nexport interface UsageSummary {\n totals: { inputTokens: number; outputTokens: number; cacheReadTokens: number };\n byBot: Array<{ botId: string; botName: string; inputTokens: number; outputTokens: number }>;\n byDay: Array<{ day: string; inputTokens: number; outputTokens: number }>;\n byModel: Array<{ model: string; inputTokens: number; outputTokens: number }>;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["z", "z", "z", "z"]
7
+ }