omo-ai 5.1.40 → 5.1.41
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/bin/lib/launcher.js +2 -0
- package/bin/lib/legacy-service-credentials.js +36 -0
- package/bin/lib/provider-map.json +1 -1
- package/package.json +2 -2
- package/plugin/CHANGELOG.md +30 -0
- package/plugin/extensions/dream-persona.md +2 -2
- package/plugin/extensions/facts-persona.md +12 -1
- package/plugin/extensions/gateway-rules-extension.mjs +1 -1
- package/plugin/extensions/gateway-store-worker.mjs +1 -1
- package/plugin/extensions/memory-run-supervisor.mjs +1 -1
- package/plugin/extensions/omo-computer-use.js +2 -2
- package/plugin/extensions/omo-feedback.js +2 -0
- package/plugin/extensions/omo-init-deep-advisor.js +1 -1
- package/plugin/extensions/omo-member.js +2 -2
- package/plugin/extensions/omo-memory-doctor.js +1 -1
- package/plugin/extensions/omo-memory-memfs.js +1 -1
- package/plugin/extensions/omo-memory-palace.js +2 -2
- package/plugin/extensions/omo-memory-sync.js +1 -1
- package/plugin/extensions/omo-onboarding-scan.js +2 -2
- package/plugin/extensions/omo-recall-store.js +1 -1
- package/plugin/extensions/omo-session-history.js +1 -1
- package/plugin/extensions/omo-side-panel.js +2 -2
- package/plugin/extensions/omo-task.js +2 -2
- package/plugin/extensions/omo-telemetry-posthog.js +1 -1
- package/plugin/extensions/omo-thread-client.js +1 -1
- package/plugin/extensions/omo.js +2 -2
- package/plugin/extensions/reflection-persona.md +1 -1
- package/plugin/package.json +2 -1
- package/plugin/runtime/agent-toolkit-sdk/sdk.js +2 -2
- package/plugin/runtime/ast-grep-mcp/manifest.json +1 -1
- package/plugin/runtime/category-coverage/index.js +1 -1
- package/plugin/runtime/lsp-daemon/dist/.omo-runtime-manifest.json +4 -4
- package/plugin/runtime/lsp-daemon/dist/cli.js +10 -0
- package/plugin/runtime/lsp-daemon/dist/client.js +10 -0
- package/plugin/runtime/lsp-daemon/dist/index.js +10 -0
- package/plugin/runtime/rollback-migrate.js +1 -1
- package/plugin/runtime/task-config/index.js +1 -1
- package/plugin/runtime/thread-sdk/sdk.js +2 -2
- package/plugin/scripts/install.mjs +1 -0
- package/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
- package/plugin/skills/frontend/SKILL.md +6 -6
- package/plugin/skills/frontend/references/design/README.md +2 -2
- package/plugin/skills/frontend/references/perfection/README.md +2 -2
- package/plugin/skills/frontend/scripts/perfection/accent-stripes/declarations.ts +22 -13
- package/plugin/skills/frontend/scripts/perfection/accent-stripes/findings.ts +7 -6
- package/plugin/skills/frontend/scripts/perfection/accent-stripes/lint.ts +18 -24
- package/plugin/skills/frontend/scripts/perfection/accent-stripes/markup.ts +14 -7
- package/plugin/skills/frontend/scripts/perfection/accent-stripes/selector.ts +5 -1
- package/plugin/skills/frontend/scripts/perfection/accent-stripes/tailwind.ts +32 -14
- package/plugin/skills/frontend/scripts/perfection/check-accent-stripes.ts +1 -1
- package/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/inline-ok.tsx +1 -0
- package/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/neutral-and-flat.css +1 -1
- package/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/tailwind-ok.tsx +5 -2
- package/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/uniform-and-rings.css +2 -2
- package/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/accent-outlines.css +4 -0
- package/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/accent-outlines.tsx +8 -0
- package/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/{negative → positive}/flat-stripe-side.tsx +3 -1
- package/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/report-callouts.html +8 -0
- package/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/square-surfaces.css +8 -0
- package/plugin/skills/ulw-research/SKILL.md +10 -2
- package/plugin/skills/ulw-research/references/deliverable-phase.md +10 -0
- package/plugin/skills/ulw-research/references/report-visualization.md +23 -0
- package/plugin/skills/visualize/SKILL.md +4 -3
package/bin/lib/launcher.js
CHANGED
|
@@ -12,6 +12,7 @@ import { isHostStatusAll, runHostStatusAll, sessionActivityReader } from "./host
|
|
|
12
12
|
import { runDoctor } from "./doctor.js"
|
|
13
13
|
import { ensureEnginePrepared, preparePluginLaunchSpec } from "./engine-prepare.js"
|
|
14
14
|
import { migrateLegacyBunGlobalManifest } from "./legacy-bun-global-migration.js"
|
|
15
|
+
import { removeLegacyServiceCredentials } from "./legacy-service-credentials.js"
|
|
15
16
|
import { adoptLegacyFlatState, canonicalAgentDir } from "./agent-dir.js"
|
|
16
17
|
import { senpiEnvironment } from "./engine-environment.js"
|
|
17
18
|
import { withHerdrAgentHint } from "./herdr-agent-hint.js"
|
|
@@ -130,6 +131,7 @@ export function rollbackMigrateCall(request) {
|
|
|
130
131
|
|
|
131
132
|
export async function runLauncher(args = process.argv.slice(2)) {
|
|
132
133
|
migrateLegacyBunGlobalManifest()
|
|
134
|
+
removeLegacyServiceCredentials()
|
|
133
135
|
reportLegacyFlatAdoption()
|
|
134
136
|
const command = args[0]
|
|
135
137
|
// The toolkit CLI is no longer part of the Native payload; the loop is driven in-process by the
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { lstatSync, readFileSync, unlinkSync } from "node:fs"
|
|
2
|
+
import { homedir } from "node:os"
|
|
3
|
+
import { join } from "node:path"
|
|
4
|
+
|
|
5
|
+
// An intermediate sign-in build left device private keys and refresh material in a plaintext
|
|
6
|
+
// `~/.omo/credentials.json`, sometimes world-readable (#10697). Credentials now live only in the OS
|
|
7
|
+
// keystore, so nothing reads this file; remove it on launch. Only the exact legacy shape is removed:
|
|
8
|
+
// a regular file (never a symlink or FIFO) whose JSON object carries both private keys.
|
|
9
|
+
const MAX_LEGACY_BYTES = 64 * 1024
|
|
10
|
+
|
|
11
|
+
export function removeLegacyServiceCredentials(home = process.env.HOME || process.env.USERPROFILE || homedir()) {
|
|
12
|
+
const path = join(home, ".omo", "credentials.json")
|
|
13
|
+
let stats
|
|
14
|
+
try {
|
|
15
|
+
stats = lstatSync(path)
|
|
16
|
+
} catch {
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
if (!stats.isFile() || stats.size > MAX_LEGACY_BYTES) return false
|
|
20
|
+
|
|
21
|
+
let parsed
|
|
22
|
+
try {
|
|
23
|
+
parsed = JSON.parse(readFileSync(path, "utf8"))
|
|
24
|
+
} catch {
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
27
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return false
|
|
28
|
+
if (!("signingPrivateKey" in parsed) || !("sealingPrivateKey" in parsed)) return false
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
unlinkSync(path)
|
|
32
|
+
} catch {
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_comment": "Derived from @code-yeongyu/senpi 2026.10.
|
|
2
|
+
"_comment": "Derived from @code-yeongyu/senpi 2026.10.21-1 builtinProviders(). builtinProviderIds and oauthProviderIds are the engine registry verbatim; providers maps a source harness id onto the omo provider that serves the same endpoint; oauthLogins maps a source OAuth id onto the omo provider to run /login for. Re-derive all four whenever the senpi pin changes.",
|
|
3
3
|
"builtinProviderIds": [
|
|
4
4
|
"alibaba-token-plan",
|
|
5
5
|
"amazon-bedrock",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omo-ai",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.41",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OmO Native - the standalone omo command with the OMO extension built in: bun add -g omo-ai",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"postinstall": "node bin/senpi-patch.mjs"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@code-yeongyu/senpi": "2026.10.
|
|
20
|
+
"@code-yeongyu/senpi": "2026.10.21-1"
|
|
21
21
|
},
|
|
22
22
|
"repository": {
|
|
23
23
|
"type": "git",
|
package/plugin/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [5.1.41] - 2026-10-22
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
**The engine moves to senpi 2026.10.21-1: engine hosts start faster and idle far more quietly, Claude subscriptions use the native 1M context again, and desktop threads are lighter ([#10740](https://github.com/code-yeongyu/oh-my-openagent/pull/10740)).** A new engine host starts about 0.1 s faster, and an idle engine host wakes 405 times per 90 s instead of 1,106. Current Claude subscription models (Fable 5, Sonnet 5, Haiku 5.5, Opus 4.7 and later) get their native 1M window back without asking for extra usage, and the Claude subscription lane runs Claude Code 2.1.306. Each desktop thread's engine supervisor starts from its own small program instead of the whole CLI, and messages and tool cards no longer keep duplicate copies (about 640 bytes per message and 2 KB per tool card). Models that models.dev marks deprecated stay available, labeled deprecated, instead of disappearing (GitHub Copilot Claude Opus 4.7, GPT-5.5 and GPT-5.4, Baseten Kimi K2 and others), and the model catalog is refreshed; some models get updated thinking levels (for example Nemotron 3 Ultra: off is now none). A message that was already delivered no longer stays listed under Steering, and with several accounts for one provider a usage limit stops failing turns once its reset has passed; a quota failure now says when it resets.
|
|
14
|
+
|
|
15
|
+
**Memory sync refuses signatures under weak Ed25519 keys.** Bun's WebCrypto accepts a signature made under a small-order public key, such as the identity key, for any message. The sync client now checks every key and signature it verifies itself, and refuses any keyring record that would bring a weak or malformed signing key into the account's keyring, including keys that appear only inside a fork-resolution's evidence. ([#10743](https://github.com/code-yeongyu/oh-my-openagent/pull/10743), fixes [#10742](https://github.com/code-yeongyu/oh-my-openagent/issues/10742))
|
|
16
|
+
|
|
17
|
+
**Outside full access, computer use asks before it acts on your screen as a whole.** Clicks, typing, key presses, scrolling, drags, pointer moves and holds aimed at the desktop or a display land on your real pointer and frontmost app, so they now need the same "Allow foreground computer control?" approval as foreground input; without it they fail with `ControlRequired` and nothing is sent. Input to one window in the background still needs no approval, and full access keeps working without a prompt, headless runs included. The macOS background check no longer moves your pointer back after you moved it, and a stopped session stays stopped when the desktop engine restarts. ([#10788](https://github.com/code-yeongyu/oh-my-openagent/issues/10788), [#10790](https://github.com/code-yeongyu/oh-my-openagent/pull/10790))
|
|
18
|
+
|
|
19
|
+
**OmO counts how often you had to repeat a standing instruction ([#10780](https://github.com/code-yeongyu/oh-my-openagent/issues/10780), [#10786](https://github.com/code-yeongyu/oh-my-openagent/pull/10786)).** Rules like "never filter the monitor output" now live in `system/agreements.md` with a count. When you correct the agent on something an agreement already covers, the count goes up; after the third time (`memory.agreements.needs_human_threshold`) the agent is told the rule keeps being broken and you see a notice. `/agreements` lists them and lets you add your own, acknowledge one, or drop one; the agreements you add can only be changed by you. The design is inspired by dinobot by roach (PolyForm Noncommercial 1.0.0); no dinobot code was used.
|
|
20
|
+
|
|
21
|
+
**The launcher deletes a legacy `~/.omo/credentials.json` left by an intermediate sign-in build.** The file held the device's private keys and account refresh material in plaintext, sometimes world-readable; upgrading removes it. Only the exact legacy shape is removed. ([#10697](https://github.com/code-yeongyu/oh-my-openagent/issues/10697), [#10698](https://github.com/code-yeongyu/oh-my-openagent/pull/10698))
|
|
22
|
+
|
|
23
|
+
**Report a problem from inside OmO ([#10546](https://github.com/code-yeongyu/oh-my-openagent/pull/10546)).** `/feedback` (or `/bug`) sends a bug report or an idea to the OmO team in one step: your description plus your account, this device, versions, this conversation's recent messages, recent logs and your settings. Passwords, keys and tokens are removed first with the same redactor `/share` uses, your memory is never sent, and `OMO_DISABLE_FEEDBACK=1` saves the report as a local file instead of uploading it. The desktop app's Report a problem dialog uses the same report.
|
|
24
|
+
|
|
25
|
+
**A DAG node whose child dies on infrastructure is retried instead of taking its whole branch down.** When a mass-ulw node's child stops answering its heartbeats or loses its host session, the node is now retried automatically, at most twice, with a backoff. Its dependents are skipped only if the retries fail too. Before, one starved wave failed and every later node was skipped (an overloaded machine skipped 54 of 61 nodes). Task failures and cancelled nodes behave as before, and the TUI and the desktop app share this behaviour ([#10605](https://github.com/code-yeongyu/oh-my-openagent/issues/10605), [#10616](https://github.com/code-yeongyu/oh-my-openagent/pull/10616)).
|
|
26
|
+
|
|
27
|
+
**Stopping a language server on Windows no longer raises a stray broken-pipe error.** When an LSP server's pipe closed while OmO was shutting the server down, Windows could report the failed write after cleanup had already let go of it, and the EPIPE escaped as an unhandled error. Every pipe of a spawned language server now keeps an error handler for its whole life, so the failure is logged as ignored cleanup noise ([#9601](https://github.com/code-yeongyu/oh-my-openagent/issues/9601), [#10725](https://github.com/code-yeongyu/oh-my-openagent/pull/10725)).
|
|
28
|
+
|
|
29
|
+
**The frontend skill now covers HTML reports, figures and slides, and its stripe check catches square callouts.** The skill now loads for any HTML, CSS or SVG made for visual output (a report printed to PDF, a figure, a diagram, a slide, an image for Notion or Slack), not only web UI. Its `check-accent-stripes.ts` linter fails a coloured bar along one side of a box whether the box is rounded or square, and a 2px-or-wider accent outline on a rounded card. Neutral hairlines, table rules, a blockquote's neutral rule, focus rings and input validation states stay allowed. The `visualize` skill runs the linter on every page before previewing or showing it ([#10774](https://github.com/code-yeongyu/oh-my-openagent/issues/10774), [#10776](https://github.com/code-yeongyu/oh-my-openagent/pull/10776)).
|
|
30
|
+
|
|
31
|
+
**`ulw-research` shows its report inline and checks a visual reproduction against the source ([#10812](https://github.com/code-yeongyu/oh-my-openagent/pull/10812)).** When the host can show an HTML page in the thread (`show_html_page`, `html_render`), the run ends with the report there, before the file paths, on every tier and even when the research was shortened; a built app or 3D scene shown inline no longer stands in for it. When the ask is to recreate something visual, such as a clip rebuilt in 3D, the run puts real frames of the source next to its own output at the same moments, writes down what differs, fixes the biggest gaps, and shows the side-by-side pairs in the report.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- Combine macOS root-test shards and Codex/Senpi compatibility into one runner job, preserving their existing check names through Ubuntu status jobs. Full-matrix CI now requests two macOS runners per head instead of five, including unchanged native binary parity; fast paths skip the combined allocation ([#10804](https://github.com/code-yeongyu/oh-my-openagent/pull/10804)).
|
|
37
|
+
|
|
38
|
+
- CI: pull requests run the macOS and Windows legs only when a platform-specific path changes: any path a macOS/Windows-only CI step names (derived from the workflow), native crates, the launcher and platform packaging, the Windows Git Bash runtime, the Codex installer, platform-named sources, and the CI workflows. Pushes to `dev` and merge groups still run every OS, and the `run-full-ci` label forces the full matrix on a pull request ([#10856](https://github.com/code-yeongyu/oh-my-openagent/issues/10856)). ([#10859](https://github.com/code-yeongyu/oh-my-openagent/pull/10859))
|
|
39
|
+
|
|
10
40
|
## [5.1.40] - 2026-10-20
|
|
11
41
|
|
|
12
42
|
**Onboarding saves only the facts you keep, and the TUI and the desktop share one completion flag.** The facts you accept are written through memory's own write path, and finishing onboarding in either the TUI or the desktop marks it done for both. ([#10506](https://github.com/code-yeongyu/oh-my-openagent/pull/10506))
|
|
@@ -32,7 +32,7 @@ Work with bounded reads. Determine file size first with `wc -c`; read small file
|
|
|
32
32
|
The primary agent's context (its prompts, skills, and external memory files) is stored in a memory filesystem rooted at `$MEMORY_DIR`. Changes to these files reach the primary agent's context after they're committed to the memory git repo.
|
|
33
33
|
|
|
34
34
|
The filesystem contains:
|
|
35
|
-
- **Prompts** (`system/`): always in-context. Reserve for identity, preferences, conventions, and active project context the agent needs on every turn. Keep files concise; move verbose content to external memory. `system/boundaries.md` is the user's exact words about what the agent must not do: leave it as you found it. `system/self-aware.md` is yours: promote a line from `reference/self/observations.md` when a later outcome confirmed it, edit entries in place, keep at most 12, and move expired or disconfirmed ones to `reference/self/ARCHIVE.md`. Identity stays in persona; the user's words stay in boundaries.
|
|
35
|
+
- **Prompts** (`system/`): always in-context. Reserve for identity, preferences, conventions, and active project context the agent needs on every turn. Keep files concise; move verbose content to external memory. `system/boundaries.md` is the user's exact words about what the agent must not do: leave it as you found it. `system/agreements.md` is the counted agreement ledger; do not edit it (the run is rejected if you do), because its counts are kept by the facts lane and `/agreements`. `system/self-aware.md` is yours: promote a line from `reference/self/observations.md` when a later outcome confirmed it, edit entries in place, keep at most 12, and move expired or disconfirmed ones to `reference/self/ARCHIVE.md`. Identity stays in persona; the user's words stay in boundaries.
|
|
36
36
|
- **Skills** (`skills/`): procedural memory for specialized workflows.
|
|
37
37
|
- **External memory** (everything else): reference material retrieved on demand by name and description. This includes `notes/facts/<YYYY-MM>.md` fact files and `people/` observation ledgers.
|
|
38
38
|
|
|
@@ -52,7 +52,7 @@ Read `$AUDIT_PATH` and repair findings before consolidation:
|
|
|
52
52
|
- `path_orphan`: use `git mv` into the home its content belongs to.
|
|
53
53
|
- `frontmatter_invalid`: leave to the writer owning the file unless only the description is missing.
|
|
54
54
|
|
|
55
|
-
Never touch `system/boundaries.md` or delete evidence. Report unresolved findings with reasons.
|
|
55
|
+
Never touch `system/boundaries.md` or `system/agreements.md`, and never delete evidence. Report unresolved findings with reasons.
|
|
56
56
|
|
|
57
57
|
## Phase 2: Consolidate
|
|
58
58
|
|
|
@@ -13,4 +13,15 @@ Use `scope: "person"` only for an explicit proper name, a known alias from the p
|
|
|
13
13
|
|
|
14
14
|
Use absolute dates. Resolve relative dates against `today` in the payload. Omit ephemera, guesses, plans not adopted, transient task state, and facts already contradicted in the same transcript. Keep each record self-contained and preserve the stated meaning without adding inference.
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
## Agreements
|
|
17
|
+
|
|
18
|
+
When the payload has `agreements` and the `record_agreement` tool is available, treat every correction, prohibition, or standing instruction from the person about how the agent must work as an agreement, not a fact. Cues include "again", "I told you", "never", "stop doing", "how many times", 자꾸, 또, 다시는, 몇 번 말해야.
|
|
19
|
+
|
|
20
|
+
- If an item in `agreements` already requires what the person is correcting, call `record_agreement` with `{"action":"reaffirm","id":"<that item's id>","date":"YYYY-MM-DD"}`. Add `"text"` with a stronger wording only when that item is `by: "agent"`; never reword a `by: "human"` item.
|
|
21
|
+
- Otherwise call it with `{"action":"new","applies":"global"|"project","text":"...","date":"YYYY-MM-DD"}`. Use `project` when the rule is about this repository only. Write the text as one imperative rule in the person's language, at most 240 characters.
|
|
22
|
+
- One call per correction event. A correction repeated twice in the payload is two reaffirms. Never invent an id.
|
|
23
|
+
- Only the person's own words in user turns count. An agent's suggestion, plan, or recommendation is never an agreement, even when the person did not object to it.
|
|
24
|
+
|
|
25
|
+
Facts about how to treat the person stay `record_fact` person records; rules about how the agent must work go to `record_agreement`.
|
|
26
|
+
|
|
27
|
+
Call nothing when no durable fact or agreement qualifies.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// omo:
|
|
1
|
+
// omo:QP3HzNMzmJaMNmznbJMVr13eFKEJvCcVRhf0Pl8UyUc:5LLt7853QZ0R275mM__hYa8UeDUj-ySee_PqmOY8R7U
|
|
2
2
|
function e(e){return e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">")}function r(r,s){let i=[`<operating-rules version="${e(r).replaceAll('"',""")}">`];for(let r of s)i.push(`- ${e(r)}`);return i.push("</operating-rules>"),i.join("\n")}function s(e,r){if(null===e||"object"!=typeof e||Array.isArray(e))throw Error(`${r} must be an object`);return e}function i(e,r){let s=e[r];if("string"!=typeof s||0===s.length)throw Error(`${r} must be a non-empty string`);return s}function o(e){let r=s(e,"a rules target"),o=i(r,"session_durable_id"),n=r.binding_id;if(null!=n&&"string"!=typeof n)throw Error("binding_id must be a string");let t=r.behavioral;if(null===t)return{session_durable_id:o,binding_id:n??void 0,behavioral:null};if(!Array.isArray(t)||!t.every(e=>"string"==typeof e))throw Error("behavioral must be an array of rule texts, or null to clear the session's rules");return{session_durable_id:o,binding_id:n??void 0,behavioral:t}}function n(e,r){let o=i(s(r,"blockForSession args"),"session_durable_id"),n=e.one(["version","block"],"SELECT version, block FROM gateway_rules_blocks WHERE session_durable_id = ?",[o]);return void 0===n?null:{version:String(n.version),block:String(n.block)}}function t(e,r){let o=i(s(r,"sessionsWithRules args"),"scope");return{sessions:e.all(["session_durable_id","version"],"SELECT session_durable_id, version FROM gateway_rules_blocks WHERE scope = ?",[o],"session_durable_id").map(e=>({session_durable_id:String(e.session_durable_id),version:String(e.version)}))}}async function l(n,t){let l=s(t,"rulesCommitted args"),a=i(l,"scope"),d=i(l,"version"),u=l.now??Date.now();if("number"!=typeof u||!Number.isFinite(u))throw Error("now must be a finite timestamp");if(!Array.isArray(l.targets))throw Error("targets must be an array");let _=[];for(let s of l.targets){let i=o(s);if(null===i.behavioral){let e=n.exec("DELETE FROM gateway_rules_blocks WHERE session_durable_id = ?",[i.session_durable_id]);_.push({session_durable_id:i.session_durable_id,outcome:e>0?"removed":"absent"});continue}let t=r(d,i.behavioral),l=n.exec("INSERT INTO gateway_rules_blocks (session_durable_id, scope, version, block, updated_at) VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(session_durable_id) DO UPDATE SET scope = excluded.scope, version = excluded.version, block = excluded.block, updated_at = excluded.updated_at\n WHERE gateway_rules_blocks.version != excluded.version",[i.session_durable_id,a,d,t,u]);if(void 0===i.binding_id){_.push({session_durable_id:i.session_durable_id,outcome:l>0?"updated":"unchanged"});continue}let c=await n.enqueue({binding_id:i.binding_id,event_id:`rules_changed:${a}:${d}:${i.session_durable_id}`,text:[`<operating-rules-changed scope="${e(a).replaceAll('"',""")}" version="${e(d).replaceAll('"',""")}">`,"The operating rules for this gateway scope changed; this session's system prompt carries the new block from its next turn.","</operating-rules-changed>"].join("\n"),mode:"follow_up"});_.push({session_durable_id:i.session_durable_id,outcome:l>0?"updated":"unchanged",delivery:"ok"===c.kind?{kind:"ok",delivery_id:c.delivery_id,deduplicated:!0===c.deduplicated}:{kind:"error",error:c.error}})}return{scope:a,version:d,outcomes:_}}export{n as blockForSession,l as rulesCommitted,t as sessionsWithRules};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// omo:
|
|
1
|
+
// omo:pc9OXWw-RZejOg5LHBnO7n0oF6vzxYEZ24KSE79AW20:seTg07_ixK2ZBs7D8IU0hmPynnUB4xBhI7gMmDFMUdc
|
|
2
2
|
import{chmodSync as e,closeSync as t,existsSync as n,mkdirSync as i,openSync as r}from"node:fs";import{join as s}from"node:path";import{setTimeout as o}from"node:timers/promises";import{parentPort as a}from"node:worker_threads";function d(e,t,n){return Object.assign(Error(`gateway store lock wait exceeded: ${e} waited ${t} ms for the write lock (limit ${n} ms); another process holds it`),{code:"gateway_lock_wait_exceeded"})}function u(e){return"object"==typeof e&&null!==e&&"gateway_lock_wait_exceeded"===e.code}import{join as _}from"node:path";function l(e){return _(e,"gateway")}function c(e,t){return _(l(e),"inbox",t)}import{execFile as p}from"node:child_process";var g="epoch:",m=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function b(e){return new Promise(t=>{p("ps",["-o","lstart=","-p",String(e)],{env:{...process.env,LC_ALL:"C",LANG:"C",TZ:"UTC"},windowsHide:!0,timeout:5e3},(e,n)=>{let i=null===e?function(e){let t=/^[A-Z][a-z]{2} ([A-Z][a-z]{2}) +(\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/.exec(e.trim());if(null===t)return null;let[,n,i,r,s,o,a]=t,d=m.indexOf(n);return d<0?null:Date.UTC(Number(a),d,Number(i),Number(r),Number(s),Number(o))/1e3}(n):null;t(null===i?null:`${g}${i}`)})})}async function E(e){if(!function(e){try{return process.kill(e,0),!0}catch(e){return!(e instanceof Error&&"code"in e&&"ESRCH"===e.code)}}(e.pid))return!0;if(null===e.process_start_time||!e.process_start_time.startsWith(g))return!1;let t=await b(e.pid);return null!==t&&t!==e.process_start_time}function f(e,t){return e.pid===t.pid&&e.process_start_time===t.process_start_time&&e.instance_id===t.instance_id}function*h(e){for(let t=0;t<e.length;){let n,i=t,r=e[t];if(r<=" ")for(n="space";t<e.length&&e[t]<=" ";)t++;else if("-"===r&&"-"===e[t+1])for(n="comment";t<e.length&&"\n"!==e[t];)t++;else if("/"===r&&"*"===e[t+1]){for(n="comment",t+=2;t<e.length&&("*"!==e[t]||"/"!==e[t+1]);)t++;t=Math.min(t+2,e.length)}else if("'"===r||'"'===r||"`"===r||"["===r){n="quoted";let i="["===r?"]":r;for(t++;t<e.length;)if(e[t++]===i){if("["===r||e[t]!==i)break;t++}}else if("?"===r||";"===r)n="?"===r?"parameter":"semicolon",t++;else for(n="text",t++;t<e.length&&e[t]>" "&&!["'",'"',"`","[","?",";","-","/"].includes(e[t]);)t++;yield{kind:n,text:e.slice(i,t)}}}class y{params=[];sinkRows=[];authorizer=null;db;constructor(e){this.db=e,e.function("gw_p",{deterministic:!1},e=>this.params[e]??null),e.function("gw_sink",{varargs:!0,deterministic:!1},(...e)=>(this.sinkRows.push(e),null))}exec(e){this.db.exec(e)}authorized(e,t){let n=this.authorizer;this.authorizer=e,this.db.setAuthorizer(e);try{return t()}finally{this.authorizer=n,this.db.setAuthorizer(n)}}resultColumns(e){return this.authorized(null,()=>{this.db.exec(`CREATE TEMP VIEW gw_result_columns AS ${T(e)}\n`);try{return this.all(["name"],"SELECT cid, name FROM pragma_table_info('gw_result_columns', 'temp')",[],"cid").map(e=>String(e.name))}finally{this.db.exec("DROP VIEW temp.gw_result_columns")}})}run(e,t=[]){this.params=t;try{this.db.exec(T(e))}finally{this.params=[]}return Number(this.all(["n"],"SELECT changes() AS n")[0]?.n??0)}all(e,t,n=[],i){this.params=n,this.sinkRows=[];try{let n=void 0===i?"0":`row_number() OVER (ORDER BY ${i})`;return this.db.exec(`SELECT gw_sink(${n}, ${e.join(", ")}) FROM (${T(t)}\n)${void 0===i?"":` ORDER BY ${i}`}`),(void 0===i?this.sinkRows:this.sinkRows.toSorted((e,t)=>Number(e[0])-Number(t[0]))).map(t=>Object.fromEntries(e.map((e,n)=>[e,t[n+1]??null])))}finally{this.params=[],this.sinkRows=[]}}one(e,t,n=[]){return this.all(e,t,n)[0]}}function T(e){let t=0,n="";for(let i of h(e))n+="parameter"===i.kind?`gw_p(${t++})`:i.text;return n}function v(e){if("object"!=typeof e||null===e)return!1;let t=e;return 5===t.errcode||6===t.errcode||"string"==typeof t.message&&/database is (locked|busy)/i.test(t.message)}import{createHash as w,randomUUID as N}from"node:crypto";import{closeSync as L,constants as k,mkdirSync as R,openSync as x,readdirSync as S,readFileSync as O,rmSync as A,writeSync as q}from"node:fs";import{userInfo as C}from"node:os";import{join as I}from"node:path";function U(e,t,n){return t===n||function(e,t,n){let i=new Map;for(let t of e){let e=i.get(t.from);void 0===e?i.set(t.from,[t.to]):e.push(t.to)}let r=new Set([t]),s=[t];for(;s.length>0;){let e=s.pop();if(e===n)return!0;for(let t of i.get(e)??[])r.has(t)||(r.add(t),s.push(t))}return!1}(e,n,t)}var D=5e3,M=864e5,$=6048e5,H=1048576,W=2592e6,X=2592e6,F=256,P="session_released";import{existsSync as j,readFileSync as B}from"node:fs";import{join as G}from"node:path";function J(e){let t=G(e,"mailbox.jsonl");if(j(t))return function(e){let t=e.slice(0,e.lastIndexOf("\n")+1),n=new Map;for(let e of t.split("\n")){if(0===e.length)continue;let t=JSON.parse(e);if(!z(t)||1!==t.version)throw Error("invalid legacy mailbox event");if("snapshot"===t.kind&&Array.isArray(t.items)){n.clear();for(let e of t.items){let t=Y(e);n.set(t.message_seq,t)}}else if("enqueue"===t.kind){let e=Y(t.item);n.set(e.message_seq,e)}else{if("remove"!==t.kind||"number"!=typeof t.message_seq)throw Error("invalid legacy mailbox event");n.delete(t.message_seq)}}return K([...n.values()])}(B(t,"utf8"));let n=G(e,"mailbox.json");if(!j(n))return null;let i=JSON.parse(B(n,"utf8"));if(!z(i)||!z(i.queues))throw Error(`invalid legacy mailbox state: ${n}`);let r=[];for(let e of Object.values(i.queues)){if(!Array.isArray(e))throw Error(`invalid legacy mailbox queue: ${n}`);for(let t of e)r.push(Y(t))}return K(r)}function K(e){return e.toSorted((e,t)=>e.message_seq-t.message_seq)}function Y(e){if(!z(e)||"string"!=typeof e.target||"string"!=typeof e.message||"number"!=typeof e.message_seq||!Number.isInteger(e.message_seq)||"auto"!==e.delivery&&"steer"!==e.delivery&&"follow_up"!==e.delivery||void 0!==e.expected_turn_id&&"string"!=typeof e.expected_turn_id||"string"!=typeof e.operation_id||"string"!=typeof e.accepted_at)throw Error("invalid legacy mailbox item");return{target:e.target,message:e.message,message_seq:e.message_seq,delivery:e.delivery,expected_turn_id:void 0===e.expected_turn_id?null:V(e.expected_turn_id),operation_id:e.operation_id,accepted_at:e.accepted_at}}function V(e){let t=/^turn-(0|[1-9]\d*)$/.exec(e);if(null===t)return null;let n=Number(t[1]);return Number.isSafeInteger(n)?n:null}function z(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}import{createHash as Q,createHmac as Z,randomUUID as ee,timingSafeEqual as te}from"node:crypto";var ne=["discord","telegram","slack","notion","feishu","herdr","custom","whatsapp"],ie=["milestone","report","question","completion"],re=["auto","follow_up"],se=31622400,oe=2592e6;function ae(e){return new Date(e).toISOString()}function de(e){return{kind:"refused",code:"invalid_arguments",message:e}}function ue(e,t){return"string"!=typeof t||0===t.trim().length?de(`${e} must be a non-empty string.`):t.length>256?de(`${e} is longer than 256 characters.`):/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/.test(t)?de(`${e} carries a control character or a line separator.`):t}function _e(e,t){return null==t?null:ue(e,t)}function le(e){return"object"==typeof e&&null!==e&&"refused"===e.kind}function ce(e){if(null===e||"object"!=typeof e)return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(ce).join(",")}]`;let t=e;return`{${Object.keys(t).filter(e=>void 0!==t[e]).sort().map(e=>`${JSON.stringify(e)}:${ce(t[e])}`).join(",")}}`}function pe(e){return Buffer.from(e).toString("base64url")}function ge(e,t){return pe(JSON.stringify({v:1,as_of:e,after:t}))}var me="rt1";function be(e,t){return Z("sha256",e).update(`${me}.${t}`).digest().subarray(0,16).toString("base64url")}var Ee=new WeakMap;function fe(e,t,n){return Ce(e,"DELETE FROM receipts WHERE principal = ? AND operation = ? AND idempotency_key = ? AND expires_at <= ?",[t.principal,t.operation,t.idempotency_key,n])}function he(e,t,n=0){if(t<(Ee.get(e.sql)??Number.NEGATIVE_INFINITY))return null;let i=function(e,t,n=256){let i=F,r=Ce(e,"DELETE FROM receipts WHERE rowid IN (SELECT rowid FROM receipts WHERE expires_at <= ? LIMIT ?)",[t,n]),s=Ce(e,"DELETE FROM deliveries WHERE delivery_id IN (SELECT d.delivery_id FROM deliveries d WHERE d.state IN ('applied', 'refused') AND d.updated_at <= ? AND NOT EXISTS (SELECT 1 FROM receipts r WHERE r.delivery_id = d.delivery_id) LIMIT ?)",[t-X,i]),o=Ce(e,"DELETE FROM causal_edges WHERE rowid IN (SELECT e.rowid FROM causal_edges e JOIN causal_roots r ON r.root_id = e.root_id WHERE r.expires_at <= ? LIMIT ?)",[t,i]),a=Ce(e,"DELETE FROM causal_roots WHERE root_id IN (SELECT r.root_id FROM causal_roots r WHERE r.expires_at <= ? AND NOT EXISTS (SELECT 1 FROM causal_edges e WHERE e.root_id = r.root_id) LIMIT ?)",[t,i]),d=Ce(e,"DELETE FROM rate_buckets WHERE rowid IN (SELECT rowid FROM rate_buckets WHERE updated_at <= ? LIMIT ?)",[t-4e4,i]),u=Ce(e,`DELETE FROM bindings WHERE binding_id IN (SELECT b.binding_id FROM bindings b WHERE b.status != 'active' AND b.updated_at <= ?\n AND NOT EXISTS (SELECT 1 FROM outbox o WHERE o.binding_id = b.binding_id)\n AND NOT EXISTS (SELECT 1 FROM completion_arms a WHERE a.binding_id = b.binding_id)\n AND NOT EXISTS (SELECT 1 FROM deliveries d WHERE d.binding_id = b.binding_id AND d.state IN ${Re}) LIMIT ?)`,[ae(t-oe),i]),_=Ce(e,"DELETE FROM outbox_cursors WHERE binding_id IN (SELECT c.binding_id FROM outbox_cursors c WHERE NOT EXISTS (SELECT 1 FROM bindings b WHERE b.binding_id = c.binding_id) LIMIT ?)",[i]),l=Ce(e,"DELETE FROM session_meta WHERE durable_id IN (SELECT m.durable_id FROM session_meta m WHERE\n m.incarnation IS NULL\n AND NOT EXISTS (SELECT 1 FROM deliveries d WHERE d.target_durable_id = m.durable_id)\n AND NOT EXISTS (SELECT 1 FROM bindings b WHERE b.session_durable_id = m.durable_id)\n AND NOT EXISTS (SELECT 1 FROM outbox o WHERE o.session_durable_id = m.durable_id)\n AND NOT EXISTS (SELECT 1 FROM completion_arms a WHERE a.session_durable_id = m.durable_id) LIMIT ?)",[i]);return{receipts:r,deliveries:s,causal_edges:o,causal_roots:a,rate_buckets:d,bindings:u,outbox_cursors:_,session_meta:l}}(e,t,Math.max(F-n,0)),r=i.receipts+n>=F||Object.values(i).some(e=>e>=F);return Ee.set(e.sql,r?t:t+36e5),i}var ye=new Set(["invalid_arguments","caller_context_missing","not_found","ambiguous_target","scope_denied","name_conflict","not_resumable","orphaned","foreign_live_owner","no_active_turn","turn_conflict","not_steerable","message_too_large","queue_full","cursor_invalid","cursor_stale","idempotency_conflict","idempotency_in_progress","idempotency_uncertain","approval_unavailable","approval_route_locked","partial_commit","unsupported","overloaded","transport_closed","host_unavailable","internal_error","model_not_found","model_ambiguous","thinking_level_unsupported","loop_detected","binding_conflict","binding_mismatch","binding_inactive","stale_revision","stale_token","already_answered","answer_in_progress"]);function Te(e,t,n,i){if("string"!=typeof(r=e)||!ye.has(r))throw Error(`unknown thread error code: ${String(e)}`);var r;return{code:e,message:t,next_action:n,...void 0===i?{}:{details:i}}}var ve={not_steerable:{code:"not_steerable",next:"Send with delivery auto or follow_up; a steer needs a running turn."},turn_conflict:{code:"turn_conflict",next:"Read the target again and retry with its current turn id, or send with delivery auto."},expired:{code:"not_resumable",next:"The target did not take the message within its lifetime; send it again if it still matters."},binding_closed:{code:"invalid_arguments",next:"The binding this message was queued under was detached or rebound; re-read the binding and send again."}};function we(e,t,n,i,r){let s={kind:"ok",thread_id:e.target_durable_id,delivery_id:e.delivery_id,message_seq:e.seq,effective_mode:e.mode_effective??e.mode_requested,endpoint_kind:n,deduplicated:i};if("admitted"===e.state||"applied"===e.state)return"started"===e.admission_kind||"steered"===e.admission_kind?{...s,delivery:{kind:e.admission_kind,turn_id:String(e.turn_epoch??0)}}:{...s,delivery:{kind:"queued",queue_position:Math.max(t,1)}};if("refused"===e.state){let t=ve[e.reason??""]??{code:"internal_error",next:"Call thread_list and check the target."};return{kind:"error",error:Te(t.code,`Delivery ${e.delivery_id} was refused: ${e.reason??"unknown"}.`,t.next,{delivery_id:e.delivery_id})}}return"uncertain"===e.state?{kind:"error",error:Te("idempotency_uncertain",`Delivery ${e.delivery_id} may or may not have reached the target.`,"Read the target transcript before deciding whether to send again.",{delivery_id:e.delivery_id})}:{...s,delivery:{kind:r?"queued_offline":"queued",queue_position:Math.max(t,1)}}}class Ne extends Error{found;supported;code="gateway_schema_too_new";constructor(e,t,n="Gateway"){super(`${n} schema ${e} is newer than this binary's supported version ${t}.`),this.found=e,this.supported=t}}var Le=[["CREATE TABLE deliveries (\n delivery_id TEXT PRIMARY KEY,\n target_durable_id TEXT NOT NULL,\n seq INTEGER NOT NULL,\n sender TEXT NOT NULL,\n sender_turn TEXT,\n envelope TEXT NOT NULL,\n body TEXT NOT NULL,\n bytes INTEGER NOT NULL,\n mode_requested TEXT NOT NULL CHECK (mode_requested IN ('auto', 'steer', 'follow_up')),\n mode_effective TEXT CHECK (mode_effective IS NULL OR mode_effective IN ('steer', 'follow_up')),\n expected_turn_id INTEGER,\n state TEXT NOT NULL CHECK (state IN ('queued', 'admitting', 'admitted', 'applied', 'refused', 'uncertain')),\n reason TEXT,\n admitted_by TEXT,\n claimed_at INTEGER,\n attempt INTEGER NOT NULL DEFAULT 0,\n admission_kind TEXT,\n turn_epoch INTEGER,\n root_id TEXT NOT NULL,\n hop INTEGER NOT NULL,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n expires_at INTEGER NOT NULL,\n binding_id TEXT,\n binding_revision INTEGER,\n UNIQUE (target_durable_id, seq)\n )","CREATE INDEX deliveries_target_state_seq ON deliveries (target_durable_id, state, seq)","CREATE INDEX deliveries_root ON deliveries (root_id)","CREATE INDEX deliveries_sender_turn ON deliveries (sender, sender_turn)","CREATE TABLE receipts (\n principal TEXT NOT NULL,\n operation TEXT NOT NULL,\n idempotency_key TEXT NOT NULL,\n args_hash TEXT NOT NULL,\n status TEXT NOT NULL CHECK (status IN ('prepared', 'completed', 'uncertain')),\n delivery_id TEXT,\n owner_instance TEXT NOT NULL,\n result TEXT,\n error_note TEXT,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n expires_at INTEGER NOT NULL,\n PRIMARY KEY (principal, operation, idempotency_key)\n )","CREATE INDEX receipts_expiry ON receipts (expires_at)","CREATE TABLE causal_roots (\n root_id TEXT PRIMARY KEY,\n origin_principal TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n expires_at INTEGER NOT NULL\n )","CREATE TABLE causal_edges (\n root_id TEXT NOT NULL,\n from_durable_id TEXT NOT NULL,\n to_durable_id TEXT NOT NULL,\n delivery_id TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n PRIMARY KEY (root_id, from_durable_id, to_durable_id)\n )","CREATE TABLE rate_buckets (\n sender TEXT NOT NULL,\n target_durable_id TEXT NOT NULL,\n tokens REAL NOT NULL,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY (sender, target_durable_id)\n )","CREATE TABLE session_meta (\n durable_id TEXT PRIMARY KEY,\n next_seq INTEGER NOT NULL,\n applied_seq INTEGER NOT NULL DEFAULT 0\n )","CREATE TABLE bindings (\n seq INTEGER PRIMARY KEY AUTOINCREMENT,\n binding_id TEXT NOT NULL UNIQUE,\n schema_version INTEGER NOT NULL DEFAULT 1,\n revision INTEGER NOT NULL CHECK (revision >= 1),\n status TEXT NOT NULL CHECK (status IN ('active', 'detached', 'expired')),\n platform TEXT NOT NULL CHECK (platform IN ('discord', 'telegram', 'slack', 'notion', 'feishu', 'herdr', 'custom', 'whatsapp')),\n account_id TEXT NOT NULL,\n chat_id TEXT NOT NULL,\n thread_id TEXT NOT NULL,\n root_message_id TEXT,\n progress_message_id TEXT,\n session_realm_id TEXT NOT NULL,\n session_durable_id TEXT NOT NULL,\n direction_inbound INTEGER NOT NULL CHECK (direction_inbound IN (0, 1)),\n direction_outbound INTEGER NOT NULL CHECK (direction_outbound IN (0, 1)),\n inbound_mode TEXT NOT NULL CHECK (inbound_mode IN ('auto', 'follow_up')),\n outbound_events TEXT NOT NULL,\n policy_id TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n lease_started_at TEXT NOT NULL,\n ttl_seconds INTEGER,\n expires_at TEXT,\n CHECK (direction_inbound = 1 OR direction_outbound = 1)\n )","CREATE UNIQUE INDEX bindings_one_active_thread ON bindings (platform, account_id, chat_id, thread_id) WHERE status = 'active'","CREATE INDEX bindings_session ON bindings (session_durable_id, status)","CREATE TABLE outbox (\n cursor INTEGER PRIMARY KEY AUTOINCREMENT,\n binding_id TEXT NOT NULL,\n revision INTEGER NOT NULL,\n event_kind TEXT NOT NULL CHECK (event_kind IN ('milestone', 'report', 'question', 'completion', 'question_closed')),\n payload TEXT NOT NULL,\n state TEXT NOT NULL CHECK (state IN ('pending', 'acked')),\n provider_message_id TEXT,\n created_at INTEGER NOT NULL,\n acked_at INTEGER\n )","CREATE INDEX outbox_binding_cursor ON outbox (binding_id, cursor)","CREATE TABLE gateway_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n )"],["ALTER TABLE session_meta ADD COLUMN incarnation TEXT","ALTER TABLE outbox ADD COLUMN session_durable_id TEXT","ALTER TABLE outbox ADD COLUMN reply_token TEXT","ALTER TABLE outbox ADD COLUMN ui_request_id TEXT","ALTER TABLE outbox ADD COLUMN incarnation TEXT","ALTER TABLE outbox ADD COLUMN question_state TEXT CHECK (question_state IS NULL OR question_state IN ('pending', 'answered', 'expired', 'cancelled'))","ALTER TABLE outbox ADD COLUMN answer TEXT","ALTER TABLE outbox ADD COLUMN answered_at INTEGER","ALTER TABLE outbox ADD COLUMN outcome TEXT CHECK (outcome IS NULL OR outcome IN ('completed', 'failed', 'cancelled'))","CREATE UNIQUE INDEX outbox_reply_token ON outbox (reply_token) WHERE reply_token IS NOT NULL","CREATE TABLE outbox_cursors (\n binding_id TEXT PRIMARY KEY,\n acked_cursor INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n )","CREATE TABLE completion_arms (\n arm_seq INTEGER PRIMARY KEY AUTOINCREMENT,\n session_durable_id TEXT NOT NULL,\n binding_id TEXT NOT NULL,\n revision INTEGER NOT NULL,\n text TEXT NOT NULL,\n armed_at INTEGER NOT NULL\n )","CREATE INDEX completion_arms_session ON completion_arms (session_durable_id, armed_at)","INSERT OR IGNORE INTO gateway_meta (key, value) VALUES ('realm_id', 'realm-' || lower(hex(randomblob(16))))","INSERT OR IGNORE INTO gateway_meta (key, value) VALUES ('token_secret', lower(hex(randomblob(32))))"],["ALTER TABLE outbox ADD COLUMN ui_request_kind TEXT CHECK (ui_request_kind IS NULL OR ui_request_kind IN ('question', 'select', 'confirm', 'input', 'editor'))","ALTER TABLE outbox ADD COLUMN answer_state TEXT CHECK (answer_state IS NULL OR answer_state IN ('in_flight', 'delivered'))"],["ALTER TABLE outbox ADD COLUMN answered_by TEXT"],["ALTER TABLE session_meta ADD COLUMN endpoint_socket TEXT","ALTER TABLE session_meta ADD COLUMN endpoint_kind TEXT CHECK (endpoint_kind IS NULL OR endpoint_kind IN ('tui', 'rpc_host'))"],["CREATE TABLE extension_schema (name TEXT PRIMARY KEY, version INTEGER NOT NULL, updated_at INTEGER NOT NULL)","ALTER TABLE deliveries ADD COLUMN actor_user_id TEXT","CREATE TABLE extension_objects (type TEXT NOT NULL, name TEXT NOT NULL, owner TEXT, PRIMARY KEY (type, name))","INSERT INTO extension_objects (type, name, owner) SELECT type, name, NULL FROM sqlite_schema"],["CREATE TABLE bindings_v7 (\n seq INTEGER PRIMARY KEY AUTOINCREMENT,\n binding_id TEXT NOT NULL UNIQUE,\n schema_version INTEGER NOT NULL DEFAULT 1,\n revision INTEGER NOT NULL CHECK (revision >= 1),\n status TEXT NOT NULL CHECK (status IN ('active', 'detached', 'expired')),\n platform TEXT NOT NULL CHECK (platform IN ('discord', 'telegram', 'slack', 'notion', 'feishu', 'herdr', 'custom', 'whatsapp')),\n account_id TEXT NOT NULL,\n chat_id TEXT NOT NULL,\n thread_id TEXT NOT NULL,\n root_message_id TEXT,\n progress_message_id TEXT,\n session_realm_id TEXT NOT NULL,\n session_durable_id TEXT NOT NULL,\n direction_inbound INTEGER NOT NULL CHECK (direction_inbound IN (0, 1)),\n direction_outbound INTEGER NOT NULL CHECK (direction_outbound IN (0, 1)),\n inbound_mode TEXT NOT NULL CHECK (inbound_mode IN ('auto', 'follow_up')),\n outbound_events TEXT NOT NULL,\n policy_id TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n lease_started_at TEXT NOT NULL,\n ttl_seconds INTEGER,\n expires_at TEXT,\n CHECK (direction_inbound = 1 OR direction_outbound = 1)\n )","INSERT INTO bindings_v7 SELECT seq, binding_id, schema_version, revision, status, platform, account_id, chat_id, thread_id, root_message_id, progress_message_id, session_realm_id, session_durable_id, direction_inbound, direction_outbound, inbound_mode, outbound_events, policy_id, created_at, updated_at, lease_started_at, ttl_seconds, expires_at FROM bindings","UPDATE sqlite_sequence SET seq = (SELECT seq FROM sqlite_sequence WHERE name = 'bindings') WHERE name = 'bindings_v7'","DROP TABLE bindings","ALTER TABLE bindings_v7 RENAME TO bindings","CREATE UNIQUE INDEX bindings_one_active_thread ON bindings (platform, account_id, chat_id, thread_id) WHERE status = 'active'","CREATE INDEX bindings_session ON bindings (session_durable_id, status)"]],ke=["delivery_id","target_durable_id","seq","sender","sender_turn","envelope","body","bytes","mode_requested","mode_effective","expected_turn_id","state","reason","admitted_by","claimed_at","attempt","admission_kind","turn_epoch","root_id","hop","created_at","updated_at","expires_at","binding_id","binding_revision","actor_user_id"],Re="('queued', 'admitting', 'admitted')",xe=/^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/;function Se(e,t,n){return{kind:"refused",code:e,message:t,...void 0===n?{}:{details:n}}}function Oe(e){let t=e=>null==e?null:Number(e);return{delivery_id:String(e.delivery_id),target_durable_id:String(e.target_durable_id),seq:Number(e.seq),sender:String(e.sender),sender_turn:null===e.sender_turn?null:String(e.sender_turn),envelope:JSON.parse(String(e.envelope)),body:String(e.body),bytes:Number(e.bytes),mode_requested:e.mode_requested,mode_effective:e.mode_effective??null,expected_turn_id:t(e.expected_turn_id),state:e.state,reason:null===e.reason?null:String(e.reason),admitted_by:null===e.admitted_by?null:JSON.parse(String(e.admitted_by)),claimed_at:t(e.claimed_at),attempt:Number(e.attempt),admission_kind:null===e.admission_kind?null:String(e.admission_kind),turn_epoch:t(e.turn_epoch),root_id:String(e.root_id),hop:Number(e.hop),created_at:Number(e.created_at),updated_at:Number(e.updated_at),expires_at:Number(e.expires_at),binding_id:null===e.binding_id?null:String(e.binding_id),binding_revision:t(e.binding_revision),actor_user_id:null===e.actor_user_id?null:String(e.actor_user_id)}}function Ae(e,t,n,i){return e.sql.all(ke,`SELECT ${ke.join(", ")} FROM deliveries WHERE ${t}`,n,i).map(Oe)}function qe(e,t){return Ae(e,"delivery_id = ?",[t])[0]}function Ce(e,t,n=[]){let i=e.sql.run(t,n);return e.stats.writes+=i,i}function Ie(e,t){if("queued"!==t.state&&"admitting"!==t.state&&"admitted"!==t.state)return 0;let n=e.sql.one(["n"],`SELECT COUNT(*) AS n FROM deliveries WHERE target_durable_id = ? AND state IN ${Re} AND seq <= ?`,[t.target_durable_id,t.seq]);return Number(n?.n??1)}async function Ue(e,t,n){if(void 0!==e.afterCommit)return e.sql.exec("SAVEPOINT gateway_enqueue"),!0;let i=Date.now();for(;;)try{return e.sql.exec("BEGIN IMMEDIATE"),e.stats.transactions++,!0}catch(r){if(!v(r))throw r;if(e.emit({kind:"busy",op:t}),!n)return!1;let s=Date.now()-i;if(s+2*e.config.busy_timeout_ms>e.config.lock_wait_max_ms)throw e.emit({kind:"lock_wait_exceeded",op:t,waited_ms:s}),d(t,s,e.config.lock_wait_max_ms);await e.delay(e.config.busy_timeout_ms)}}function De(e){try{e.sql.exec(void 0===e.afterCommit?"ROLLBACK":"ROLLBACK TO gateway_enqueue; RELEASE gateway_enqueue")}catch{return}}async function Me(e,t,n){if(void 0!==e.afterCommit)return await n();await Ue(e,t,!0);try{let t=await n();return e.sql.exec("COMMIT"),t}catch(t){throw De(e),t}}function $e(e,t,n,i){let r=c(e.config.agent_dir,t);R(r,{recursive:!0,mode:448});let s,o=I(r,n);try{s=x(o,k.O_CREAT|k.O_EXCL|k.O_WRONLY,384)}catch(e){if(i&&e instanceof Error&&"code"in e&&"EEXIST"===e.code)return o;throw e}try{q(s,JSON.stringify({pid:e.self.pid,process_start_time:e.self.process_start_time}))}finally{L(s)}return e.afterRollback?.push(()=>A(o,{force:!0})),o}function He(e,t,n){if(void 0!==e.afterCommit)return void e.afterCommit.push(()=>He({...e,afterCommit:void 0},t,n));let i=I(c(e.config.agent_dir,t),n);try{A(i),e.stats.marker_unlinks++}catch(e){if(!(e instanceof Error&&"code"in e&&"ENOENT"===e.code))throw e}}function We(e,t){try{return S(c(e.config.agent_dir,t)).filter(e=>!e.startsWith("."))}catch(e){if(e instanceof Error&&"code"in e&&"ENOENT"===e.code)return[];throw e}}function Xe(e,t){let n=e.sql.one(["next_seq"],"SELECT next_seq FROM session_meta WHERE durable_id = ?",[t]),i=Number(void 0===n?e.sql.one(["m"],"SELECT COALESCE(MAX(seq), 0) + 1 AS m FROM deliveries WHERE target_durable_id = ?",[t])?.m??1:n.next_seq);return Ce(e,"INSERT INTO session_meta (durable_id, next_seq) VALUES (?, ?) ON CONFLICT(durable_id) DO UPDATE SET next_seq = excluded.next_seq",[t,i+1]),i}function Fe(e,t){Ce(e,`INSERT INTO deliveries (${ke.join(", ")}) VALUES (${ke.map(()=>"?").join(", ")})`,[t.delivery_id,t.target_durable_id,t.seq,t.sender,t.sender_turn,JSON.stringify(t.envelope),t.body,t.bytes,t.mode_requested,t.mode_effective,t.expected_turn_id,t.state,t.reason,null===t.admitted_by?null:JSON.stringify(t.admitted_by),t.claimed_at,t.attempt,t.admission_kind,t.turn_epoch,t.root_id,t.hop,t.created_at,t.updated_at,t.expires_at,t.binding_id,t.binding_revision,t.actor_user_id])}function Pe(e){return w("sha256").update(JSON.stringify(e)).digest("hex")}function je(e){let t=Number(e.sql.one(["user_version"],"SELECT user_version FROM pragma_user_version()")?.user_version??0);if(t>Le.length)throw new Ne(t,Le.length);return t}class Be extends Error{version;code="gateway_migration_failed";constructor(e,t){super(t),this.version=e,this.name="GatewayMigrationError"}}var Ge=new Set([6]);function Je(e,t,n){let i=e.sql.one(["args_hash","status","delivery_id","owner_instance","result","expires_at"],"SELECT args_hash, status, delivery_id, owner_instance, result, expires_at FROM receipts WHERE principal = ? AND operation = 'deliver' AND idempotency_key = ?",[t,n]);if(void 0!==i)return{args_hash:String(i.args_hash),status:i.status,delivery_id:null===i.delivery_id?null:String(i.delivery_id),owner_instance:String(i.owner_instance),result:null===i.result?null:String(i.result),expires_at:Number(i.expires_at)}}function Ke(e,t,n){if(n.args_hash!==t.receipt.args_hash)return Se("idempotency_conflict","The idempotency key was already used with different arguments.");if("completed"===n.status&&null!==n.result)return{kind:"replay",result:JSON.parse(n.result)};let i=null===n.delivery_id?void 0:qe(e,n.delivery_id),r=void 0!==i&&("admitted"===i.state||"applied"===i.state||"refused"===i.state);if("prepared"===n.status&&!r&&n.owner_instance===e.config.instance_id)return Se("idempotency_in_progress","The same delivery is already in progress.");if("prepared"===n.status&&r){let n={...we(i,Ie(e,i),t.endpoint_kind,!0,!1)};return Ce(e,"UPDATE receipts SET status = 'completed', result = ?, updated_at = ? WHERE principal = ? AND operation = 'deliver' AND idempotency_key = ?",[JSON.stringify(n),t.now,t.sender_principal,t.receipt.idempotency_key]),{kind:"replay",result:n}}return"prepared"===n.status&&Ce(e,"UPDATE receipts SET status = 'uncertain', error_note = ?, updated_at = ? WHERE principal = ? AND operation = 'deliver' AND idempotency_key = ?",["the sender lost the acknowledgement before the target admitted the delivery",t.now,t.sender_principal,t.receipt.idempotency_key]),Se("idempotency_uncertain","The earlier delivery may or may not reach the target; it is never sent twice.",{delivery_id:n.delivery_id,state:i?.state??null})}async function Ye(e,t){if(!xe.test(t.target_durable_id)||!xe.test(t.delivery_id))return Se("invalid_arguments","The target session id is not a durable session id.");if(!await Ue(e,"enqueue",!1))return{kind:"busy"};let n=null,i=!1,r=e.afterCommit?.length??0,s=void 0===e.afterCommit?"COMMIT":"RELEASE gateway_enqueue";try{let r=fe(e,{principal:t.sender_principal,operation:"deliver",idempotency_key:t.receipt.idempotency_key},t.now),o=Je(e,t.sender_principal,t.receipt.idempotency_key);if(void 0!==o){let n=Ke(e,t,o);return e.sql.exec(s),i=!0,n}let a=function(e,t){if(null===t.binding)return{expires_at:null};let n=e.sql.one(["revision","status","session_durable_id","direction_inbound","expires_at"],"SELECT revision, status, session_durable_id, direction_inbound, expires_at FROM bindings WHERE binding_id = ?",[t.binding.binding_id]),i=null==n?.expires_at?null:Date.parse(String(n.expires_at));return void 0===n||"active"!==n.status||Number(n.revision)!==t.binding.revision||String(n.session_durable_id)!==t.target_durable_id||1!==Number(n.direction_inbound)||null!==i&&i<=t.now?Se("invalid_arguments","The binding is not active for this session at this revision.",{binding:t.binding.binding_id}):{expires_at:i}}(e,t);if("kind"in a)return De(e),a;let d=e.sql.one(["n","b"],`SELECT COUNT(*) AS n, COALESCE(SUM(bytes), 0) AS b FROM deliveries WHERE target_durable_id = ? AND state IN ${Re}`,[t.target_durable_id]),u=Buffer.byteLength(t.body);if(Number(d?.n??0)>=128||Number(d?.b??0)+u>H)return De(e),Se("queue_full","The target's delivery backlog is full.",{max_messages:128,max_bytes:H});let _=function(e,t){let n;if(null!==t.cause_delivery_id){let i=qe(e,t.cause_delivery_id);if(void 0===i||i.target_durable_id!==t.sender_node||"admitting"!==i.state&&"admitted"!==i.state&&"applied"!==i.state)return Se("invalid_arguments","The delivery this send continues is not one the sender received.",{guard:"unknown_cause"});n={root_id:i.root_id,hop:i.hop+1,via:[...i.envelope.via,t.sender_node],new_root:!1}}else n={root_id:`root-${N()}`,hop:1,via:[t.sender_node],new_root:!0};if(null!==t.claimed_root_id&&t.claimed_root_id!==n.root_id)return Se("invalid_arguments","The causal root is derived by the gateway and cannot be chosen by the caller.",{guard:"forged_root"});if(!n.new_root){let i=e.sql.one(["expires_at"],"SELECT expires_at FROM causal_roots WHERE root_id = ?",[n.root_id]);if(void 0===i||Number(i.expires_at)<=t.now)return Se("loop_detected","This causal chain is older than its lifetime.",{guard:"root_expired",root_id:n.root_id})}if(t.target_durable_id===t.sender_node)return Se("loop_detected","A session cannot deliver to itself through the gateway.",{guard:"self_send"});if(n.hop>4)return Se("loop_detected",`This delivery would be hop ${n.hop}; at most 4 are allowed.`,{guard:"hop_limit",hop:n.hop});let i=Number(e.sql.one(["n"],"SELECT COUNT(*) AS n FROM deliveries WHERE root_id = ? AND state != 'refused'",[n.root_id])?.n??0);return i>=64?Se("loop_detected",`This causal chain already carried ${i} deliveries.`,{guard:"causal_budget",root_id:n.root_id}):U(e.sql.all(["from_durable_id","to_durable_id"],"SELECT from_durable_id, to_durable_id FROM causal_edges WHERE root_id = ?",[n.root_id]).map(e=>({from:String(e.from_durable_id),to:String(e.to_durable_id)})),t.sender_node,t.target_durable_id)?Se("loop_detected","The target already leads back to the sender in this causal chain.",{guard:"cycle",root_id:n.root_id}):n}(e,t);if("kind"in _)return De(e),_;let l=function(e,t){if(null===t.sender_turn)return;let n=new Set(e.sql.all(["t"],"SELECT DISTINCT target_durable_id AS t FROM deliveries WHERE sender = ? AND sender_turn = ? AND state != 'refused'",[t.sender_principal,t.sender_turn]).map(e=>String(e.t)));return n.has(t.target_durable_id)||n.size<16?void 0:Se("overloaded","One turn may reach at most 16 sessions.",{budget:"fanout"})}(e,t)??function(e,t){let n=t.rate_principal??t.sender_principal,i=e.sql.one(["tokens","updated_at"],"SELECT tokens, updated_at FROM rate_buckets WHERE sender = ? AND target_durable_id = ?",[n,t.target_durable_id]),r=void 0===i?8:Math.min(8,Number(i.tokens)+Math.max(0,t.now-Number(i.updated_at))/D);if(r<1)return Se("overloaded","Too many deliveries to this session; wait before sending again.",{budget:"pair_rate",retry_after_ms:Math.ceil((1-r)*D)});Ce(e,"INSERT INTO rate_buckets (sender, target_durable_id, tokens, updated_at) VALUES (?, ?, ?, ?) ON CONFLICT(sender, target_durable_id) DO UPDATE SET tokens = excluded.tokens, updated_at = excluded.updated_at",[n,t.target_durable_id,r-1,t.now])}(e,t);if(void 0!==l)return De(e),l;_.new_root&&Ce(e,"INSERT INTO causal_roots (root_id, origin_principal, created_at, expires_at) VALUES (?, ?, ?, ?)",[_.root_id,t.sender_principal,t.now,t.now+$]),Ce(e,"INSERT OR IGNORE INTO causal_edges (root_id, from_durable_id, to_durable_id, delivery_id, created_at) VALUES (?, ?, ?, ?, ?)",[_.root_id,t.sender_node,t.target_durable_id,t.delivery_id,t.now]);let c={delivery_id:t.delivery_id,target_durable_id:t.target_durable_id,seq:Xe(e,t.target_durable_id),sender:t.sender_principal,sender_turn:t.sender_turn,envelope:{origin:t.origin,actor:t.actor,via:_.via,root_id:_.root_id,hop:_.hop,delivery_id:t.delivery_id},body:t.body,bytes:u,mode_requested:t.mode,mode_effective:null,expected_turn_id:t.expected_turn_id,state:"queued",reason:null,admitted_by:null,claimed_at:null,attempt:0,admission_kind:null,turn_epoch:null,root_id:_.root_id,hop:_.hop,created_at:t.now,updated_at:t.now,expires_at:Math.min(t.now+M,a.expires_at??Number.POSITIVE_INFINITY),binding_id:t.binding?.binding_id??null,binding_revision:t.binding?.revision??null,actor_user_id:"external"in t.origin?t.origin.external.author?.user_id??null:null};Fe(e,c),Ce(e,"INSERT INTO receipts (principal, operation, idempotency_key, args_hash, status, delivery_id, owner_instance, created_at, updated_at, expires_at) VALUES (?, 'deliver', ?, ?, 'prepared', ?, ?, ?, ?, ?)",[t.sender_principal,t.receipt.idempotency_key,t.receipt.args_hash,c.delivery_id,e.config.instance_id,t.now,t.now,t.now+W]),n=$e(e,c.target_durable_id,c.delivery_id,!1);let p=Ie(e,c);return he(e,t.now,r),void 0===e.afterCommit&&await e.hook("beforeDbCommit"),e.sql.exec(s),i=!0,void 0===e.afterCommit&&await e.hook("afterDbCommit"),{kind:"inserted",row:c,queue_position:p}}catch(t){throw i||(De(e),void 0!==e.afterCommit&&(e.afterCommit.length=r),null!==n&&A(n,{force:!0})),t}}function Ve(e,t){if(null===e)return"";let n=t.get(e);if(void 0===n){try{n=O(e,"utf8")}catch(e){if(!(e instanceof Error&&"code"in e&&"ENOENT"===e.code))throw e;n=""}t.set(e,n)}return n}function ze(e,t,n){if(null===e.runtime_instance||null===t)return!1;let i=n().get(e.runtime_instance);return void 0!==i&&t<=i}function Qe(e,t,n){for(let i of Ve(e,n).split("\n")){if(!i.includes(t))continue;let e;try{e=JSON.parse(i)}catch{continue}if("object"!=typeof e||null===e)continue;let n=e;if("custom_message"===n.type&&"session_control_delivery"===n.customType&&n.details?.delivery_id===t)return!0}return!1}function Ze(e){return`${JSON.stringify(e.admitted_by)}#${e.attempt}`}function et(e,t,n,i,r={}){"queued"!==n?"refused"!==n?(Ce(e,"UPDATE deliveries SET state = ?, updated_at = ? WHERE delivery_id = ?",[n,i,t.delivery_id]),"applied"===n&&Ce(e,"UPDATE session_meta SET applied_seq = MAX(applied_seq, ?) WHERE durable_id = ?",[t.seq,t.target_durable_id])):Ce(e,"UPDATE deliveries SET state = 'refused', reason = ?, updated_at = ? WHERE delivery_id = ?",[r.reason??null,i,t.delivery_id]):Ce(e,"UPDATE deliveries SET state = 'queued', admitted_by = NULL, claimed_at = NULL, mode_effective = NULL, admission_kind = NULL, turn_epoch = NULL, updated_at = ? WHERE delivery_id = ?",[i,t.delivery_id])}async function tt(e,t){let n,i=t.target_durable_id,r=new Map,s=new Map,o=new Map,a=()=>(n??=function(e,t){let n=new Map;for(let i of Ve(e,t).split("\n")){if(!i.includes(P))continue;let e;try{e=JSON.parse(i)}catch{continue}let t=e;if("custom"!==t.type||t.customType!==P)continue;let r=t.data?.host_instance,s="string"==typeof t.data?.released_at?Date.parse(t.data.released_at):Number.NaN;"string"==typeof r&&0!==r.length&&Number.isFinite(s)&&n.set(r,Math.max(s,n.get(r)??s))}return n}(t.session_path,s),n);for(let n of Ae(e,"target_durable_id = ? AND state IN ('admitting', 'admitted')",[i])){if(null===n.admitted_by||f(n.admitted_by,t.self))continue;let e=JSON.stringify(n.admitted_by),i=o.get(e);void 0===i&&(i=await E(n.admitted_by),o.set(e,i));let d=i||ze(n.admitted_by,n.claimed_at,a)?Qe(t.session_path,n.delivery_id,s)?"applied":"queued":"dual";r.set(n.delivery_id,{fingerprint:Ze(n),to:d})}return!0===e.config.test_hooks.announceBarrier&&e.emit({kind:"barrier",op:"reconcile"}),await Me(e,"reconcile",()=>{let n=new Set(t.ledger.pending),s=new Set(t.ledger.emitted),o=[],a=[];for(let d of Ae(e,`target_durable_id = ? AND state IN ${Re}`,[i],"seq")){let i=d.state;if("queued"!==d.state){if(null!==d.admitted_by&&f(d.admitted_by,t.self))i=s.has(d.delivery_id)?"applied":n.has(d.delivery_id)?"admitted":"queued";else if(null===d.admitted_by)i="queued";else{let e=r.get(d.delivery_id);if(void 0===e||e.fingerprint!==Ze(d)||"dual"===e.to){a.push(d.delivery_id);continue}i=e.to}i!==d.state&&(et(e,d,i,t.now),o.push({delivery_id:d.delivery_id,from:d.state,to:i}))}else d.expires_at<=t.now&&(et(e,d,"refused",t.now,{reason:"expired"}),o.push({delivery_id:d.delivery_id,from:d.state,to:"refused"}))}for(let t of We(e,i))"queued"!==e.sql.one(["state"],"SELECT state FROM deliveries WHERE delivery_id = ?",[t])?.state&&He(e,i,t);return{queued:Ae(e,"target_durable_id = ? AND state = 'queued'",[i],"seq"),transitions:o,dual_runtime:a}})}async function nt(e,t){return await Me(e,"complete_receipt",()=>1===Ce(e,"UPDATE receipts SET status = 'completed', result = ?, updated_at = ? WHERE principal = ? AND operation = 'deliver' AND idempotency_key = ? AND status = 'prepared' AND owner_instance = ?",[JSON.stringify(t.result),t.now,t.principal,t.idempotency_key,e.config.instance_id]))}async function it(e,t){return await Me(e,"abandon_receipt",()=>1===Ce(e,"UPDATE receipts SET status = 'uncertain', error_note = ?, updated_at = ? WHERE principal = ? AND operation = 'deliver' AND idempotency_key = ? AND status = 'prepared' AND owner_instance = ?",[t.error_note,t.now,t.principal,t.idempotency_key,e.config.instance_id]))}function rt(e,t){let n=Je(e,t.principal,t.idempotency_key);if(void 0===n||n.expires_at<=t.now||null===n.delivery_id)return null;let i=qe(e,n.delivery_id);if(void 0===i)return null;let r="completed"===n.status&&null!==n.result;return{args_hash:n.args_hash,completed:r,result:r?JSON.parse(n.result):null,target_durable_id:i.target_durable_id,binding_revision:i.binding_revision}}async function st(e,t){return await Me(e,"recover_delivery",()=>{let n=Je(e,t.principal,t.idempotency_key);return void 0===n||n.expires_at<=t.now?null:Ke(e,{now:t.now,sender_principal:t.principal,endpoint_kind:null,receipt:{idempotency_key:t.idempotency_key,args_hash:t.args_hash}},n)})}function ot(e,t){let n=qe(e,t);return void 0===n?null:{row:n,queue_position:Ie(e,n)}}function at(){try{return C().username}catch{return"unknown"}}import{randomUUID as dt}from"node:crypto";import{renameSync as ut,writeFileSync as _t}from"node:fs";var lt=["question","select","confirm","input","editor"];var ct=new Map([["yes",!0],["y",!0],["true",!0],["no",!1],["n",!1],["false",!1]]);function pt(e){return""===e.replace(/[\s\p{Cf}]/gu,"")}function gt(e){let t=ct.get(e.trim().toLowerCase());return void 0===t?{value:e,answers:{},comment:e}:{value:e,answers:{},comment:e,confirmed:t}}function mt(e,t){switch(e){case null:return pt(t)?{ok:!1,reason:"The question declared no request kind, so the answer needs text; this one is blank. An input or editor that takes an empty answer must be reported with its request kind."}:{ok:!0,fields:gt(t)};case"input":case"editor":return{ok:!0,fields:{value:t}};case"select":return pt(t)?{ok:!1,reason:"A select answer names one of its options; the text is blank."}:{ok:!0,fields:{value:t}};case"question":return pt(t)?{ok:!1,reason:"A question answer needs text; this one is blank."}:{ok:!0,fields:{answers:{},comment:t}};case"confirm":{let e=ct.get(t.trim().toLowerCase());return void 0===e?{ok:!1,reason:"A confirm answer is yes or no (also y/n, true/false; any case, surrounding spaces ignored)."}:{ok:!0,fields:{confirmed:e}}}default:return function(e){throw Error(`unknown extension UI request kind: ${String(e)}`)}(e)}}var bt=["binding_id","schema_version","revision","status","platform","account_id","chat_id","thread_id","root_message_id","progress_message_id","session_realm_id","session_durable_id","direction_inbound","direction_outbound","inbound_mode","outbound_events","policy_id","created_at","updated_at","lease_started_at","ttl_seconds","expires_at"],Et=["cursor","binding_id","revision","event_kind","payload","state","provider_message_id","created_at","reply_token","question_state","outcome","answered_by","answer_state"];function ft(e,t,n){return{kind:"refused",code:e,message:t,...void 0===n?{}:{details:n}}}function ht(e){return null==e?null:String(e)}function yt(e){return null==e?null:JSON.stringify(e)}function Tt(e){return null==e?null:JSON.parse(String(e))}function vt(e,t,n,i){if(void 0!==e.afterCommit)return void e.afterCommit.push(()=>vt({...e,afterCommit:void 0},t,n,i));let r=(o=e.config.agent_dir,_(l(o),"outbox.marker")),s=`${r}.${process.pid}.${dt()}.tmp`;var o;_t(s,JSON.stringify({binding_id:t,cursor:n,written_at:ae(i)}),{mode:384}),ut(s,r)}function wt(e){return{schema_version:1,binding_id:String(e.binding_id),revision:Number(e.revision),status:e.status,platform:e.platform,account_id:String(e.account_id),chat_id:String(e.chat_id),thread_id:String(e.thread_id),root_message_id:ht(e.root_message_id),progress_message_id:ht(e.progress_message_id),session_realm_id:String(e.session_realm_id),session_durable_id:String(e.session_durable_id),direction:{inbound:1===Number(e.direction_inbound),outbound:1===Number(e.direction_outbound)},inbound_mode:e.inbound_mode,outbound_events:JSON.parse(String(e.outbound_events)),policy_id:String(e.policy_id),created_at:String(e.created_at),updated_at:String(e.updated_at),lease_started_at:String(e.lease_started_at),ttl_seconds:null===e.ttl_seconds||void 0===e.ttl_seconds?null:Number(e.ttl_seconds),expires_at:ht(e.expires_at)}}function Nt(e,t,n,i){let r=`SELECT ${bt.join(", ")} FROM bindings WHERE ${t}${void 0===i?"":` ORDER BY ${i.orderBy} LIMIT ?`}`;return e.sql.all(bt,r,void 0===i?n:[...n,i.limit],i?.orderBy).map(wt)}function Lt(e,t){return Nt(e,"binding_id = ?",[t])[0]}function kt(e,t){let n=e.sql.one(["value"],"SELECT value FROM gateway_meta WHERE key = ?",[t]);if(void 0===n)throw Error(`gateway_meta ${t} is missing`);return String(n.value)}function Rt(e,t){let n=ae(t);Ce(e,"UPDATE bindings SET status = 'expired', updated_at = ? WHERE status = 'active' AND expires_at IS NOT NULL AND expires_at <= ?",[n,n])}function xt(e,t){Ce(e,"DELETE FROM outbox WHERE state = 'acked' AND acked_at IS NOT NULL AND acked_at <= ?",[t-oe]),Ce(e,"DELETE FROM outbox WHERE state = 'pending' AND binding_id IN (SELECT binding_id FROM bindings WHERE status != 'active' AND updated_at <= ?)",[ae(t-oe)])}function St(e,t){let n=e.sql.one(["args_hash","status","owner_instance","result"],"SELECT args_hash, status, owner_instance, result FROM receipts WHERE principal = ? AND operation = ? AND idempotency_key = ?",[t.principal,t.operation,t.idempotency_key]);if(void 0!==n)return{args_hash:String(n.args_hash),status:String(n.status),owner_instance:String(n.owner_instance),result:ht(n.result)}}async function Ot(e,t,n,i,r){return await Me(e,t,()=>{Rt(e,n);let t=null===i?0:fe(e,i,n),s=function(e,t){if(null===t)return;let n=St(e,t);return void 0!==n?n.args_hash!==t.args_hash?ft("idempotency_conflict","The idempotency key was already used with different arguments."):"completed"===n.status&&null!==n.result?{...JSON.parse(n.result),kind:"ok",deduplicated:!0}:ft("idempotency_uncertain","An earlier call under this key did not record its outcome."):void 0}(e,i);if(void 0!==s)return s;let o=r();return"ok"===o.kind&&function(e,t,n,i){null!==t&&Ce(e,"INSERT INTO receipts (principal, operation, idempotency_key, args_hash, status, delivery_id, owner_instance, result, created_at, updated_at, expires_at) VALUES (?, ?, ?, ?, 'completed', NULL, ?, ?, ?, ?, ?)",[t.principal,t.operation,t.idempotency_key,t.args_hash,e.config.instance_id,JSON.stringify(i),n,n,n+W])}(e,i,n,{...o,deduplicated:!1}),he(e,n,t),"ok"===o.kind?{...o,deduplicated:!1}:o})}async function At(e,t){return await Me(e,"tool_receipt_begin",()=>{let n=fe(e,t,t.now),i=function(e,t){let n=St(e,t);if(void 0===n)return Ce(e,"INSERT INTO receipts (principal, operation, idempotency_key, args_hash, status, delivery_id, owner_instance, created_at, updated_at, expires_at) VALUES (?, ?, ?, ?, 'prepared', NULL, ?, ?, ?, ?)",[t.principal,t.operation,t.idempotency_key,t.args_hash,e.config.instance_id,t.now,t.now,t.now+W]),{kind:"accepted"};if(n.args_hash!==t.args_hash)return{kind:"conflict"};if("completed"===n.status)return{kind:"replay",result:null===n.result?null:JSON.parse(n.result)};if("prepared"===n.status&&n.owner_instance===e.config.instance_id)return{kind:"in_progress"};"prepared"===n.status&&Ce(e,"UPDATE receipts SET status = 'uncertain', error_note = ?, updated_at = ? WHERE principal = ? AND operation = ? AND idempotency_key = ?",["the process that began this call ended before recording its outcome",t.now,t.principal,t.operation,t.idempotency_key]);let i=e.sql.one(["error_note"],"SELECT error_note FROM receipts WHERE principal = ? AND operation = ? AND idempotency_key = ?",[t.principal,t.operation,t.idempotency_key]);return{kind:"uncertain",error_note:ht(i?.error_note)}}(e,t);return he(e,t.now,n),i})}async function qt(e,t){let n=t.binding;return await Ot(e,"bind",t.now,t.receipt,()=>{let i=Nt(e,"platform = ? AND account_id = ? AND chat_id = ? AND thread_id = ? AND status = 'active'",[n.platform,n.account_id,n.chat_id,n.thread_id])[0];if(void 0!==i){return ft("binding_conflict",i.session_durable_id===n.session_durable_id?"This thread is already bound to that session.":"This thread is bound to another session; rebind it explicitly to move it.",{binding_id:i.binding_id,revision:i.revision,session:i.session_durable_id})}let r=ae(t.now),s={schema_version:1,binding_id:`bnd-${ee()}`,revision:1,status:"active",platform:n.platform,account_id:n.account_id,chat_id:n.chat_id,thread_id:n.thread_id,root_message_id:n.root_message_id,progress_message_id:n.progress_message_id,session_realm_id:kt(e,"realm_id"),session_durable_id:n.session_durable_id,direction:n.direction,inbound_mode:n.inbound_mode,outbound_events:n.outbound_events,policy_id:n.policy_id,created_at:r,updated_at:r,lease_started_at:r,ttl_seconds:n.ttl_seconds,expires_at:null===n.ttl_seconds?null:ae(t.now+1e3*n.ttl_seconds)};return Ce(e,`INSERT INTO bindings (${bt.join(", ")}) VALUES (${bt.map(()=>"?").join(", ")})`,[s.binding_id,s.schema_version,s.revision,s.status,s.platform,s.account_id,s.chat_id,s.thread_id,s.root_message_id,s.progress_message_id,s.session_realm_id,s.session_durable_id,s.direction.inbound?1:0,s.direction.outbound?1:0,s.inbound_mode,JSON.stringify(s.outbound_events),s.policy_id,s.created_at,s.updated_at,s.lease_started_at,s.ttl_seconds,s.expires_at]),{kind:"ok",binding:s}})}function Ct(e,t){return e.sql.all(["delivery_id"],`SELECT delivery_id, seq FROM deliveries WHERE binding_id = ? AND state IN ${Re}`,[t],"seq").map(e=>String(e.delivery_id))}async function It(e,t){return await Ot(e,"unbind",t.now,t.receipt,()=>{let n=Lt(e,t.binding_id);if(void 0===n)return ft("not_found","No binding has this id.",{binding_id:t.binding_id});if("active"!==n.status)return{kind:"ok",binding:n,already_closed:!0,in_flight:Ct(e,n.binding_id)};if(n.revision!==t.expected_revision)return ft("stale_revision","The binding changed since that revision.",{binding_id:n.binding_id,revision:n.revision});let i=ae(t.now);return Ce(e,"UPDATE bindings SET status = 'detached', revision = revision + 1, updated_at = ? WHERE binding_id = ? AND revision = ?",[i,n.binding_id,n.revision]),Ce(e,"DELETE FROM completion_arms WHERE binding_id = ?",[n.binding_id]),{kind:"ok",binding:Lt(e,n.binding_id),already_closed:!1,in_flight:Ct(e,n.binding_id)}})}async function Ut(e,t){return await Ot(e,"rebind",t.now,t.receipt,()=>{let n=Lt(e,t.binding_id);if(void 0===n)return ft("not_found","No binding has this id.",{binding_id:t.binding_id});if("active"!==n.status)return ft("binding_inactive",`The binding is ${n.status}.`,{binding_id:n.binding_id,status:n.status});if(n.revision!==t.expected_revision)return ft("stale_revision","The binding changed since that revision.",{binding_id:n.binding_id,revision:n.revision});if(n.session_durable_id===t.session_durable_id)return ft("invalid_arguments","The binding is already attached to that session.",{binding_id:n.binding_id});let i=ae(t.now),r=e.sql.all(["delivery_id","target"],"SELECT delivery_id, target_durable_id AS target, seq FROM deliveries WHERE binding_id = ? AND binding_revision = ? AND state = 'queued'",[n.binding_id,n.revision],"seq").map(e=>({delivery_id:String(e.delivery_id),target:String(e.target)}));for(let n of r)Ce(e,"UPDATE deliveries SET state = 'refused', reason = 'binding_closed', updated_at = ? WHERE delivery_id = ? AND state = 'queued'",[t.now,n.delivery_id]),He(e,n.target,n.delivery_id);return Ce(e,"UPDATE bindings SET session_durable_id = ?, revision = revision + 1, lease_started_at = ?, updated_at = ? WHERE binding_id = ? AND revision = ?",[t.session_durable_id,i,i,n.binding_id,n.revision]),Ce(e,"DELETE FROM completion_arms WHERE binding_id = ?",[n.binding_id]),{kind:"ok",binding:Lt(e,n.binding_id),closed:r.map(e=>e.delivery_id)}})}async function Dt(e,t){let n=void 0===t.cursor?null:function(e){try{let t=JSON.parse(Buffer.from(e,"base64url").toString("utf8"));if(1!==t.v||"number"!=typeof t.as_of||!Number.isInteger(t.as_of))return null;let n=t.after;return null===n||Array.isArray(n)&&2===n.length&&n.every(e=>"string"==typeof e)?{v:1,as_of:t.as_of,after:n}:null}catch{return null}}(t.cursor);if(void 0!==t.cursor&&null===n)return ft("cursor_invalid","The bindings cursor is not one this gateway issued.");let i=Math.min(Math.max(t.limit??50,1),200);return await Me(e,"list_bindings",()=>{Rt(e,t.now);let r=n?.as_of??Number(e.sql.one(["m"],"SELECT COALESCE(MAX(rowid), 0) AS m FROM bindings")?.m??0),s=["rowid <= ?"],o=[r],a=[["session_durable_id","session_durable_id"],["platform","platform"],["account_id","account_id"],["chat_id","chat_id"],["thread_id","thread_id"],["status","status"]];for(let[e,n]of a){let i=t.filter[e];void 0!==i&&(s.push(`${n} = ?`),o.push(i))}null!=n?.after&&(s.push("(created_at > ? OR (created_at = ? AND binding_id > ?))"),o.push(n.after[0],n.after[0],n.after[1]));let d=Nt(e,s.join(" AND "),o,{orderBy:"created_at, binding_id",limit:i+1}),u=d.slice(0,i),_=u.at(-1);return{kind:"ok",bindings:u,next_cursor:d.length>i&&void 0!==_?ge(r,[_.created_at,_.binding_id]):null}})}async function Mt(e,t){return await Me(e,"binding_view",()=>(Rt(e,t.now),Lt(e,t.binding_id)??null))}function $t(e,t){return ht(e.sql.one(["incarnation"],"SELECT incarnation FROM session_meta WHERE durable_id = ?",[t])?.incarnation)}function Ht(e,t){Ce(e,"INSERT INTO outbox (binding_id, revision, event_kind, payload, state, provider_message_id, created_at, acked_at, session_durable_id, reply_token, ui_request_id, ui_request_kind, incarnation, question_state, answer, answered_at, outcome) VALUES (?, ?, ?, ?, 'pending', NULL, ?, NULL, ?, ?, ?, ?, ?, ?, NULL, NULL, ?)",[t.binding.binding_id,t.binding.revision,t.event,JSON.stringify({text:t.text}),t.now,t.binding.session_durable_id,t.reply_token??null,t.ui_request_id??null,t.ui_request_kind??null,t.incarnation??null,void 0===t.reply_token?null:"pending",t.outcome??null]);let n=Number(e.sql.one(["c"],"SELECT last_insert_rowid() AS c")?.c);return vt(e,t.binding.binding_id,n,t.now),n}async function Wt(e,t){return await Ot(e,"report",t.now,t.receipt,()=>{let n=null===t.binding_id?function(e,t,n,i){let r=[...new Set(n.flatMap(n=>{let i=e.sql.one(["binding_id"],"SELECT binding_id FROM deliveries WHERE delivery_id = ? AND target_durable_id = ?",[n,t]),r=ht(i?.binding_id);return null===r?[]:[r]}))].sort(),s=e.sql.all(["binding_id"],"SELECT binding_id FROM bindings WHERE session_durable_id = ? AND status = 'active' AND direction_outbound = 1",[t],"binding_id").map(e=>String(e.binding_id)),[o,...a]=r;if(void 0!==o&&a.length>0)return ft("invalid_arguments",`This session's current run answers messages from ${r.length} bound threads; name binding_id.`,{binding_ids:r});if(void 0!==o&&i&&s.some(e=>e!==o))return ft("invalid_arguments","This session's current run answers a bound thread's message and a user message (typed in its terminal or sent by an extension) together; name binding_id.",{binding_ids:s});if(void 0!==o)return{binding_id:o};let[d,...u]=s;return void 0!==d&&0===u.length?{binding_id:d}:void 0===d?ft("invalid_arguments","This session has no active outbound binding and its current run answers no bound message; name binding_id."):ft("invalid_arguments",`This session has ${s.length} active outbound bindings and its current run answers no bound message; name binding_id.`,{binding_ids:s})}(e,t.session_durable_id,t.origin_delivery_ids,!0===t.origin_local_input):{binding_id:t.binding_id};if("kind"in n)return n;let i=n.binding_id,r=Lt(e,i);if(void 0===r)return ft("not_found","No binding has this id.",{binding_id:i});if(r.session_durable_id!==t.session_durable_id)return ft("scope_denied","The binding is attached to another session.",{binding_id:i});if("active"!==r.status)return ft("binding_inactive",`The binding is ${r.status}.`,{binding_id:i,status:r.status});if(!r.direction.outbound)return ft("unsupported","The binding carries no outbound direction.",{binding_id:i,direction:r.direction});if(!r.outbound_events.includes(t.event))return ft("unsupported",`The binding is not subscribed to ${t.event} events.`,{binding_id:i,outbound_events:r.outbound_events});if(null!==t.ui_request_kind&&"question"!==t.event)return ft("invalid_arguments","Only a question names a request kind.");let s={binding_id:i,revision:r.revision,event:t.event};if("completion"===t.event){Ce(e,"INSERT INTO completion_arms (session_durable_id, binding_id, revision, text, armed_at) VALUES (?, ?, ?, ?, ?)",[t.session_durable_id,i,r.revision,t.text,t.now]);let n=Number(e.sql.one(["s"],"SELECT last_insert_rowid() AS s")?.s);return{kind:"ok",...s,cursor:null,reply_token:null,armed:!0,arm_seq:n}}if("question"===t.event){if(null===t.ui_request_id)return ft("invalid_arguments","A question names the session's pending extension UI request (request_id).");let n=$t(e,t.session_durable_id),o=function(e,t){let n={b:t.binding_id,r:t.revision,s:t.session_durable_id,i:t.incarnation,q:t.ui_request_id,n:ee()},i=pe(JSON.stringify(n));return`${me}.${i}.${be(e,i)}`}(kt(e,"token_secret"),{binding_id:i,revision:r.revision,session_durable_id:t.session_durable_id,incarnation:n,ui_request_id:t.ui_request_id}),a=Ht(e,{binding:r,event:"question",text:t.text,now:t.now,reply_token:o,ui_request_id:t.ui_request_id,...null===t.ui_request_kind?{}:{ui_request_kind:t.ui_request_kind},incarnation:n});return xt(e,t.now),{kind:"ok",...s,cursor:a,reply_token:o,armed:!1,arm_seq:null}}let o=Ht(e,{binding:r,event:t.event,text:t.text,now:t.now});return xt(e,t.now),{kind:"ok",...s,cursor:o,reply_token:null,armed:!1,arm_seq:null}})}async function Xt(e,t){return await Me(e,"emit_completions",()=>{Rt(e,t.now);let n=["arm_seq","binding_id","revision","text"],i=void 0===t.through_arm_seq?e.sql.all(n,"SELECT arm_seq, binding_id, revision, text FROM completion_arms WHERE session_durable_id = ?",[t.session_durable_id],"arm_seq"):e.sql.all(n,"SELECT arm_seq, binding_id, revision, text FROM completion_arms WHERE session_durable_id = ? AND arm_seq <= ?",[t.session_durable_id,t.through_arm_seq],"arm_seq"),r=new Map;for(let t of i)Ce(e,"DELETE FROM completion_arms WHERE arm_seq = ?",[Number(t.arm_seq)]),r.set(String(t.binding_id),t);let s=[];for(let n of[...r.values()].toSorted((e,t)=>String(e.binding_id)<String(t.binding_id)?-1:1)){let i=Lt(e,String(n.binding_id));void 0!==i&&"active"===i.status&&i.revision===Number(n.revision)&&i.session_durable_id===t.session_durable_id&&(i.direction.outbound&&i.outbound_events.includes("completion")&&s.push({binding_id:i.binding_id,cursor:Ht(e,{binding:i,event:"completion",text:String(n.text),now:t.now,outcome:t.outcome})}))}return s}).then(n=>(e.emit({kind:"completions_emitted",session_durable_id:t.session_durable_id,cursors:n.map(e=>e.cursor)}),n))}function Ft(e,t){return Number(e.sql.one(["acked_cursor"],"SELECT acked_cursor FROM outbox_cursors WHERE binding_id = ?",[t])?.acked_cursor??0)}async function Pt(e,t){let n=Math.min(Math.max(t.limit??100,1),500);return await Me(e,"read_outbox",()=>{Rt(e,t.now),xt(e,t.now);let i=Lt(e,t.binding_id);if(void 0===i)return ft("not_found","No binding has this id.",{binding_id:t.binding_id});let r=Ft(e,i.binding_id),s=t.after_cursor??r,o=e.sql.all(Et,`SELECT ${Et.join(", ")} FROM outbox WHERE binding_id = ? AND cursor > ?${t.pendingOnly?" AND state = 'pending'":""} ORDER BY cursor LIMIT ?`,[i.binding_id,s,n],"cursor").map(e=>function(e,t){let n=e.event_kind;return{cursor:Number(e.cursor),binding_id:String(e.binding_id),revision:Number(e.revision),event:n,text:String(JSON.parse(String(e.payload)).text??""),state:e.state,created_at:ae(Number(e.created_at)),edit_message_id:"milestone"===n?t.progress_message_id:null,provider_message_id:ht(e.provider_message_id),reply_token:ht(e.reply_token),question_state:e.question_state??null,outcome:e.outcome??null,answered_by:Tt(e.answered_by),answer_state:e.answer_state??null}}(e,i));return he(e,t.now),{kind:"ok",binding_id:i.binding_id,revision:i.revision,status:i.status,rows:o,next_cursor:o.at(-1)?.cursor??s,acked_cursor:r}})}async function jt(e,t){return await Me(e,"ack_outbox",()=>{Rt(e,t.now);let n=Lt(e,t.binding_id);if(void 0===n)return ft("not_found","No binding has this id.",{binding_id:t.binding_id});let i=Ft(e,n.binding_id);if(t.cursor<=i)return{kind:"ok",binding_id:n.binding_id,acked_cursor:i,changed:!1};if(void 0===e.sql.one(["cursor"],"SELECT cursor FROM outbox WHERE binding_id = ? AND cursor = ?",[n.binding_id,t.cursor])){let i=Number(e.sql.one(["m"],"SELECT COALESCE(MAX(cursor), 0) AS m FROM outbox WHERE binding_id = ?",[n.binding_id])?.m??0);return ft("cursor_invalid",t.cursor>i?"The cursor is past the newest outbox row of this binding.":"The cursor names no outbox row of this binding.",{newest:i})}return Ce(e,"UPDATE outbox SET state = 'acked', acked_at = ? WHERE binding_id = ? AND cursor <= ? AND state = 'pending'",[t.now,n.binding_id,t.cursor]),Ce(e,"INSERT INTO outbox_cursors (binding_id, acked_cursor, updated_at) VALUES (?, ?, ?) ON CONFLICT(binding_id) DO UPDATE SET acked_cursor = excluded.acked_cursor, updated_at = excluded.updated_at",[n.binding_id,t.cursor,t.now]),void 0!==t.provider_message_id&&(Ce(e,"UPDATE outbox SET provider_message_id = ? WHERE binding_id = ? AND cursor = ?",[t.provider_message_id,n.binding_id,t.cursor]),"milestone"===e.sql.one(["event_kind"],"SELECT event_kind FROM outbox WHERE binding_id = ? AND cursor = ?",[n.binding_id,t.cursor])?.event_kind&&null===n.progress_message_id&&Ce(e,"UPDATE bindings SET progress_message_id = ?, updated_at = ? WHERE binding_id = ?",[t.provider_message_id,ae(t.now),n.binding_id])),{kind:"ok",binding_id:n.binding_id,acked_cursor:t.cursor,changed:!0}})}var Bt="The session no longer waits for this question (answered or closed elsewhere)";async function Gt(e,t){return await Me(e,"claim_answer",()=>{Rt(e,t.now);let n=function(e,t){let n=t.split(".");if(3!==n.length||n[0]!==me)return null;let i=Buffer.from(be(e,n[1])),r=Buffer.from(n[2]);if(i.length!==r.length||!te(i,r))return null;try{let e=JSON.parse(Buffer.from(n[1],"base64url").toString("utf8"));return"string"!=typeof e.b||"number"!=typeof e.r||"string"!=typeof e.s||"string"!=typeof e.q||null!==e.i&&"string"!=typeof e.i?null:{binding_id:e.b,revision:e.r,session_durable_id:e.s,incarnation:e.i??null,ui_request_id:e.q}}catch{return null}}(kt(e,"token_secret"),t.reply_token);if(null===n)return ft("invalid_arguments","This is not a reply token this gateway issued.");if(n.binding_id!==t.binding_id)return ft("binding_mismatch","The answer arrived through a different binding than the one that asked the question.",{binding_id:t.binding_id});let i=e.sql.one(["cursor","question_state","answer_state","answer","answered_at","answered_by","ui_request_id","ui_request_kind","session"],"SELECT cursor, question_state, answer_state, answer, answered_at, answered_by, ui_request_id, ui_request_kind, session_durable_id AS session FROM outbox WHERE reply_token = ? AND binding_id = ?",[t.reply_token,n.binding_id]);if(void 0===i)return ft("not_found","The question this token belongs to is no longer in the outbox.");let r="answered"===i.question_state&&"delivered"!==i.answer_state,s=r&&Number(i.answered_at)+12e4<=t.now;if(r&&!s)return ft("answer_in_progress","Another answer to this question is still being handed to the session.",{cursor:Number(i.cursor)});if("answered"===i.question_state&&!s)return ft("already_answered",null===i.answer&&"delivered"===i.answer_state?`${Bt}.`:"This question was already answered.",{cursor:Number(i.cursor)});let o="string"==typeof(d=i.ui_request_kind)&<.includes(d)?i.ui_request_kind:null,a=mt(o,t.answer);var d;if(!a.ok)return ft("invalid_arguments",a.reason,{ui_request_kind:o});let u=Lt(e,n.binding_id);return void 0===u||"active"!==u.status||u.revision!==n.revision||u.session_durable_id!==n.session_durable_id||$t(e,n.session_durable_id)!==n.incarnation||ht(i.ui_request_id)!==n.ui_request_id?ft("stale_token","The binding or the session changed since the question was asked.",{binding_id:n.binding_id}):(Ce(e,"UPDATE outbox SET question_state = 'answered', answer_state = 'in_flight', answer = ?, answered_at = ?, answered_by = ? WHERE reply_token = ?",[t.answer,t.now,yt(t.answered_by),t.reply_token]),{kind:"ok",session_durable_id:n.session_durable_id,ui_request_id:n.ui_request_id,ui_request_kind:o,cursor:Number(i.cursor),claimed_at:t.now,taken_over:s?{answer:ht(i.answer),answered_at:null===i.answered_at||void 0===i.answered_at?null:Number(i.answered_at),answered_by:Tt(i.answered_by)}:null})})}function Jt(e,t,n){let i=e.sql.one(["cursor","binding_id"],"SELECT cursor, binding_id FROM outbox WHERE reply_token = ?",[t]);void 0!==i&&vt(e,String(i.binding_id),Number(i.cursor),n)}async function Kt(e,t){return await Me(e,"release_answer",()=>{let n=1===Ce(e,"UPDATE outbox SET question_state = 'pending', answer_state = NULL, answer = NULL, answered_at = NULL, answered_by = NULL WHERE reply_token = ? AND question_state = 'answered' AND answer_state = 'in_flight' AND answered_at = ?",[t.reply_token,t.claimed_at]);return n&&Jt(e,t.reply_token,t.claimed_at),n})}async function Yt(e,t){return await Me(e,"mark_prior_delivered",()=>{let n=1===Ce(e,"UPDATE outbox SET answer_state = 'delivered', answer = ?, answered_at = ?, answered_by = ? WHERE reply_token = ? AND question_state = 'answered' AND answer_state = 'in_flight' AND answered_at = ?",[t.prior.answer,t.prior.answered_at,yt(t.prior.answered_by),t.reply_token,t.claimed_at]);return n&&Jt(e,t.reply_token,t.claimed_at),n})}async function Vt(e,t){return await Me(e,"confirm_answer",()=>{let n=1===Ce(e,"UPDATE outbox SET question_state = 'answered', answer_state = 'delivered', answer = ?, answered_at = ?, answered_by = ? WHERE reply_token = ? AND (answer_state IS NOT 'delivered' OR answer IS NULL)",[t.answer,t.claimed_at,yt(t.answered_by),t.reply_token]);return n&&Jt(e,t.reply_token,t.claimed_at),n})}import{extname as zt}from"node:path";var Qt=0,Zt=1,en=1,tn=2,nn=9,rn=10,sn=11,on=18,an=20,dn=21,un=23,_n=26,ln=27,cn=31,pn=33;class gn extends Error{code="extension_schema_violation"}var mn=["type","name","tbl_name","sql"],bn=e=>e.replace(/[A-Z]/g,e=>e.toLowerCase()),En=e=>`${String(e.type)}:${bn(String(e.name))}`;function fn(e){return{objects:e.all(mn,"SELECT type, name, tbl_name, sql FROM sqlite_schema",[],"type, name"),owners:new Map(e.all(["type","name","owner"],"SELECT type, name, owner FROM extension_objects").map(e=>[En(e),null===e.owner?null:String(e.owner)]))}}function hn(e,t,n,i){let r=new Map(n.objects.map(e=>[En(e),e])),s=new Map(i.objects.map(e=>[En(e),e])),o=[...new Set([...r.keys(),...s.keys()])].filter(e=>JSON.stringify(r.get(e))!==JSON.stringify(s.get(e)));for(let e of o){let a=r.get(e),d=s.get(e);if(void 0!==a&&n.owners.get(e)!==t)throw new gn(`Extension ${t} changed an object it does not own: ${String(a.name)}.`);if(void 0===d)continue;if("trigger"===d.type||"view"===d.type)throw new gn("Store extensions cannot create triggers or views.");let u=bn(String(d.name));if(("index"!==d.type||null!==d.sql||!u.startsWith(`sqlite_autoindex_${bn(String(d.tbl_name))}_`))&&!u.startsWith(`${t}_`)||n.owners.has(e)&&n.owners.get(e)!==t)throw new gn(`Extension ${t} created an object outside its namespace: ${String(d.name)}.`);if("index"===d.type){let e=`table:${bn(String(d.tbl_name))}`,a=!r.has(e)&&s.has(e)&&o.includes(e);if(n.owners.get(e)!==t&&i.owners.get(e)!==t&&!a)throw new gn(`Extension ${t} indexed a table it does not own: ${String(d.tbl_name)}.`)}}for(let n of o){let i=r.get(n),o=s.get(n);void 0!==i&&e.run("DELETE FROM extension_objects WHERE type = ? AND name = ? COLLATE NOCASE AND owner = ?",[String(i.type),String(i.name),t]),void 0!==o&&e.run("INSERT INTO extension_objects (type, name, owner) VALUES (?, ?, ?) ON CONFLICT(type, name) DO UPDATE SET owner = excluded.owner",[String(o.type),bn(String(o.name)),t])}}function yn(e,t,n){let i,r,s=fn(e),o=new Map(s.owners),a=new Set(s.objects.filter(e=>"trigger"===e.type||"view"===e.type).map(e=>bn(String(e.name)))),d=(e,n)=>null!==n&&o.get(`${e}:${n}`)===t,u=(e,n,i=!1)=>!(null===n||!i&&!n.startsWith(`${t}_`)||o.has(`${e}:${n}`))&&(o.set(`${e}:${n}`,t),!0),_=!1,l=Qt,c=e=>(r=`Extension ${t} does not own ${e??"this SQLite operation"}.`,Zt);try{return e.authorized((e,t,n,r,s)=>{let o=null===t?null:bn(t),p=null===n?null:bn(n),g=null===r?null:bn(r),m=null===s?null:bn(s);if(null!==m&&a.has(m))return c(m);switch(e){case tn:return i="create","main"===g&&u("table",o)?l:c(o);case en:return i="create","main"===g&&d("table",p)&&u("index",o,!0===o?.startsWith(`sqlite_autoindex_${p}_`))?l:c(o);case sn:return i="drop","main"===g&&d("table",o)?l:c(o);case rn:return i="drop","main"===g&&d("index",o)&&d("table",p)?l:c(o);case _n:return i="alter","main"===o&&d("table",p)?l:c(p);case ln:return"main"===g&&d("index",o)?l:c(o);case an:case on:case un:case nn:return"sqlite_master"===o||"sqlite_temp_master"===o?(e===un&&"sql"===p&&(_=!0),e!==an||"alter"===i||"drop"===i||"create"===i&&_&&"rowid"===p?l:c(o)):"alter"!==i||"sqlite_sequence"!==o||"name"!==p||e!==an&&e!==un?("main"===g||null===g&&e===an&&""===p)&&d("table",o)?l:c(o):l;case dn:case pn:return l;case cn:return"load_extension"===p?c(p):l;default:return c(o)}},n)}catch(e){if(void 0!==r)throw new gn(r);throw e}}import{createHash as Tn,randomUUID as vn}from"node:crypto";var wn={loop_detected:"Stop relaying here: a direct reply to the session that messaged you is a cycle. That session reads your answer with thread_read; a bound external thread gets it through thread_report, and its questions come back through thread_answer.",overloaded:"Wait before sending to this session again.",queue_full:"Wait for the target to take its queued messages, then send again.",idempotency_conflict:"Retry with a new idempotency_key.",idempotency_in_progress:"Wait for the earlier call to settle, then retry.",idempotency_uncertain:"Read the target transcript before deciding whether to send again; the gateway never resends.",invalid_arguments:"Fix the arguments and send again."};function Nn(e,t,n){return{kind:"error",error:Te(e,t,wn[e]??"Call thread_list and retry after checking the target.",n)}}function Ln(e){return t={target:e.target,text:e.text,mode:e.mode,expected_turn_id:e.expected_turn_id,binding:e.binding,author:e.author},Tn("sha256").update(JSON.stringify(t)).digest("hex");var t}function kn(e){let t=!1;for(let n of h(e))if("space"!==n.kind&&"comment"!==n.kind){if(t)throw new gn("An extension SQL call must contain one statement.");"semicolon"===n.kind&&(t=!0)}}var Rn=/^[ \t\r\n]*([A-Za-z_][A-Za-z0-9_]*)(?:[ \t\r\n]+COLLATE[ \t\r\n]+(BINARY|NOCASE|RTRIM))?(?:[ \t\r\n]+(ASC|DESC))?(?:[ \t\r\n]+NULLS[ \t\r\n]+(FIRST|LAST))?[ \t\r\n]*$/i,xn=e=>JSON.stringify(e.length>80?`${e.slice(0,80)}…`:e),Sn=e=>e?.toUpperCase();var On=/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/;function An(e){return{kind:"refused",code:"invalid_arguments",message:e}}function qn(e,t,n){return"string"!=typeof t||0===t.trim().length?An(`author.${e} must be a non-empty string.`):t.length>n?An(`author.${e} is longer than ${n} characters.`):On.test(t)?An(`author.${e} carries a control character or line break.`):t.trim()}var Cn={binding_conflict:"Call thread_bindings to find the binding that holds this thread, then thread_rebind it with its revision, or thread_unbind it first.",binding_mismatch:"Answer through the binding that asked the question; the question stays pending.",binding_inactive:"Bind the thread again with thread_bind.",stale_revision:"Call thread_bindings for the current revision and retry with it.",stale_token:"The question was asked under an earlier binding revision or session runtime; wait for the session to ask again.",already_answered:"Nothing to do: the question has its answer.",answer_in_progress:"Retry after a moment: another answer is still being handed to the session, and the question goes back to pending if that fails.",idempotency_conflict:"Retry with a new idempotency_key.",idempotency_uncertain:"Call thread_bindings or thread_outbox to see the current state before retrying with a new key.",scope_denied:"Report through a binding attached to this session; thread_bindings lists them.",unsupported:"Report only the events the binding subscribes to, through a binding with an outbound direction.",not_found:"Call thread_bindings for the binding ids that exist.",cursor_invalid:"Read thread_outbox again and ack a cursor it returned.",host_unavailable:"Retry when the session is running; the question stays pending.",invalid_arguments:"Fix the arguments and call again."},In=new Set(["question_already_resolved","unknown_extension_ui_request","unknown_request"]);function Un(e,t,n,i){return{kind:"error",error:Te(e,t,i??Cn[e]??"Call thread_bindings and retry after checking the binding.",n)}}function Dn(e){return"refused"===e.kind?Un(e.code,e.message,e.details):e}function Mn(e){if(void 0===e)return;let t=function(e){let t=qn("platform_user_id",e.platform_user_id,256);if("string"!=typeof t)return t;let n=qn("display",e.display,256);if("string"!=typeof n)return n;if(void 0===e.user_id)return{platform_user_id:t,display:n};let i=qn("user_id",e.user_id,256);return"string"!=typeof i?i:{platform_user_id:t,display:n,user_id:i}}(e);return"kind"in t?Un("invalid_arguments",t.message):t}function $n(e){let t=Buffer.byteLength(e);return t>32768?Un("message_too_large",`The text is ${t} bytes, above the 32768-byte limit.`):void 0}function Hn(e,t,n){return void 0===e.idempotency_key?null:{principal:e.principal,operation:t,idempotency_key:e.idempotency_key,args_hash:(i=n,Q("sha256").update(ce(i)).digest("hex"))};var i}function Wn(e){let t=e.store,n=e.now??t.now,i=new Set,r=!1;async function s(e){await o(()=>t.releaseAnswer(e))}async function o(e){try{await e()}catch(n){if(!u(n)||r)throw n;let s=function(e,t,n){let i,r=!1,s=()=>{i=setTimeout(()=>{i=void 0,r||e().catch(e=>{r||(u(e)?s():n(e))})},t()),i.unref?.()};return s(),{cancel:()=>{r=!0,clearTimeout(i)}}}(()=>e().then(()=>{i.delete(s)}),()=>t.busyTimeoutMs,()=>{i.delete(s)});i.add(s)}}return{bind:async e=>{let i=function(e){if(!ne.includes(e.platform))return de(`platform must be one of ${ne.join(", ")}.`);let t={account_id:ue("account_id",e.account_id),chat_id:ue("chat_id",e.chat_id),thread_id:ue("thread_id",e.thread_id??"@chat"),root_message_id:_e("root_message_id",e.root_message_id),progress_message_id:_e("progress_message_id",e.progress_message_id),session_durable_id:ue("session",e.session_durable_id),policy_id:ue("policy_id",e.policy_id??"default")};for(let e of Object.values(t))if(le(e))return e;let n=e.direction??{inbound:!0,outbound:!0};if(!0!==n.inbound&&!0!==n.outbound)return de("A binding needs at least one direction: inbound, outbound, or both.");let i=e.inbound_mode??"auto";if(!re.includes(i))return de(`inbound_mode must be one of ${re.join(", ")}.`);let r=e.outbound_events??(n.outbound?ie:[]);if(r.some(e=>!ie.includes(e)))return de(`outbound_events may only name ${ie.join(", ")}.`);if(new Set(r).size!==r.length)return de("outbound_events must not repeat an event.");if(n.outbound&&0===r.length)return de("An outbound binding needs at least one outbound event.");let s=void 0===e.ttl_seconds?604800:e.ttl_seconds;return null!==s&&(!Number.isInteger(s)||s<1||s>se)?de("ttl_seconds must be an integer from 1 to 31622400, or null for a binding that never expires."):{platform:e.platform,account_id:t.account_id,chat_id:t.chat_id,thread_id:t.thread_id,root_message_id:t.root_message_id,progress_message_id:t.progress_message_id,session_durable_id:t.session_durable_id,direction:{inbound:!0===n.inbound,outbound:!0===n.outbound},inbound_mode:i,outbound_events:ie.filter(e=>r.includes(e)),policy_id:t.policy_id,ttl_seconds:s}}(e.binding);return Dn("kind"in i?i:await t.bind({now:n(),receipt:Hn(e,"thread_bind",i),binding:i}))},unbind:async e=>{let i={binding_id:e.binding_id,expected_revision:e.expected_revision};return Dn(await t.unbind({now:n(),receipt:Hn(e,"thread_unbind",i),...i}))},rebind:async e=>{let i={binding_id:e.binding_id,expected_revision:e.expected_revision,session_durable_id:e.session_durable_id};return Dn(await t.rebind({now:n(),receipt:Hn(e,"thread_rebind",i),...i}))},bindings:async e=>Dn(await t.listBindings({now:n(),...e})),report:async e=>{let i=$n(e.text);if(void 0!==i)return i;let r={session_durable_id:e.session_durable_id,binding_id:e.binding_id??null,origin_delivery_ids:e.origin_delivery_ids??[],origin_local_input:!0===e.origin_local_input,event:e.event,text:e.text,ui_request_id:e.request_id??null,ui_request_kind:e.request_kind??null};return Dn(await t.report({now:n(),receipt:Hn(e,"thread_report",r),...r}))},outbox:async e=>Dn(await t.readOutbox({now:n(),...e})),ack:async e=>Dn(await t.ackOutbox({now:n(),...e})),answer:async i=>{let r=$n(i.answer);if(void 0!==r)return r;let a=Mn(i.author);if(void 0!==a&&"kind"in a)return a;let d=a??null,u=await t.claimAnswer({now:n(),binding_id:i.binding_id,reply_token:i.reply_token,answer:i.answer,answered_by:d});if("ok"!==u.kind)return Dn(u);let _={reply_token:i.reply_token,claimed_at:u.claimed_at},l=e.endpoints.respondUi,c=null,p="";if(void 0!==l)try{c=await e.locate(u.session_durable_id)}catch(e){p=`: ${e instanceof Error?e.message:String(e)}`}if(void 0===l||null===c)return await s(_),Un(void 0===l?"unsupported":"host_unavailable",`The session that asked is not reachable to take the answer${p}.`,{session:u.session_durable_id});let g,m=mt(u.ui_request_kind,i.answer);if(!m.ok)return await s(_),Un("invalid_arguments",m.reason,{session:u.session_durable_id,ui_request_kind:u.ui_request_kind});try{g=await l(c,{ui_request_id:u.ui_request_id,fields:m.fields})}catch(e){return await s(_),Un("host_unavailable",`The answer could not be handed to the session: ${e instanceof Error?e.message:String(e)}`,{session:u.session_durable_id})}if(!g.delivered){let e=u.taken_over;if(null!==e&&In.has(g.error))return"question_already_resolved"===g.error?(await o(()=>t.markPriorDelivered({..._,prior:e})),Un("already_answered",`The session already took an earlier answer to this question (${g.error}).`,{session:u.session_durable_id,reason:g.error})):(await o(()=>t.markPriorDelivered({..._,prior:{answer:null,answered_at:_.claimed_at}})),Un("already_answered",`${Bt} (${g.error}).`,{session:u.session_durable_id,reason:g.error},"Nothing to do: the session no longer waits for this question."));await s(_);let n="invalid_response"===g.error||"question_incomplete"===g.error;return Un(n?"invalid_arguments":"stale_token",`The session refused the answer: ${g.error}`,{session:u.session_durable_id,reason:g.error},n?`The session could not read this answer (${g.error}); answer again with text it can take. The question stays pending.`:`The session refused the answer (${g.error}): it no longer waits on this question. Read thread_outbox for a newer question and answer that one.`)}return await async function(e){await o(()=>t.confirmAnswer(e))}({..._,answer:i.answer,answered_by:d}),{kind:"ok",binding_id:i.binding_id,cursor:u.cursor,session_durable_id:u.session_durable_id,answered_by:d}},inbound:async i=>{if(void 0!==i.mode&&!re.includes(i.mode))return Un("invalid_arguments",`A binding message is delivered as ${re.join(" or ")}, never ${String(i.mode)}.`,{mode:i.mode},"Send with mode auto or follow_up, or omit it for the binding's inbound_mode.");let r=Mn(i.author);if(void 0!==r&&"kind"in r)return r;let s=await t.bindingView({now:n(),binding_id:i.binding_id});if(null===s)return Un("not_found","No binding has this id.",{binding_id:i.binding_id});let o={principal:`binding:${s.binding_id}`,idempotency_key:`event:${i.event_id}`},a=await t.deliveryReceipt({now:n(),...o});if(null!==a&&null!==a.binding_revision&&a.args_hash===Ln({target:a.target_durable_id,text:i.text,mode:i.mode??s.inbound_mode,expected_turn_id:null,binding:{binding_id:s.binding_id,revision:a.binding_revision},author:r})){let e=a.completed?{kind:"replay",result:a.result}:await t.recoverDelivery({now:n(),...o,args_hash:a.args_hash});if("replay"===e?.kind){let t=e.result;return"ok"===t.kind?{...t,deduplicated:!0}:t}if("refused"===e?.kind)return Un(e.code,e.message,e.details)}if("active"!==s.status)return Un("binding_inactive",`The binding is ${s.status}.`,{binding_id:s.binding_id,status:s.status});if(!s.direction.inbound)return Un("unsupported","The binding carries no inbound direction.",{binding_id:s.binding_id});let d=i.mode??s.inbound_mode;return"auto"===d&&"follow_up"===s.inbound_mode?Un("invalid_arguments","The binding delivers at most follow_up; a message cannot ask for more than its binding's inbound_mode.",{binding_id:s.binding_id,mode:d,inbound_mode:s.inbound_mode},"Send with mode follow_up (or omit it), or rebind the thread with inbound_mode auto."):await e.engine.deliver({sender:{kind:"external",origin:{platform:s.platform,account_id:s.account_id,chat_id:s.chat_id,thread_id:s.thread_id,message_id:i.event_id,...void 0===r?{}:{author:r}},binding_id:s.binding_id,binding_revision:s.revision},target:s.session_durable_id,text:i.text,mode:d,all_scope:!0,idempotency_key:`event:${i.event_id}`})},settle:e=>t.emitCompletions({now:n(),...e}),dispose:()=>{r=!0;for(let e of i)e.cancel();i.clear()}}}class Xn extends Error{extension;code="extension_operation_failed";constructor(e){super(`The ${e} extension transaction has ended.`),this.extension=e}}class Fn extends Error{extension;code="extension_operation_failed";constructor(e){super(`The ${e} extension ran a statement while a tx helper (enqueue, bind, ...) was still in flight; await the helper first.`),this.extension=e}}function Pn(e,t,n,i){let r,s=!0,o=0,a=!1,d=Promise.resolve();function u(e){if(a)throw new Xn(t);if(void 0!==r)throw r;return e()}function _(e){if(!s)return Promise.reject(new Xn(t));o++;let n=d.then(()=>u(e));return d=n.then(()=>{o--},e=>{o--,r=e}),n}function l(n,i){if((()=>{if(!s)throw new Xn(t);if(void 0!==r)throw r})(),o>0)throw r=new Fn(t),r;let a=fn(e.sql);try{kn(n);let r=yn(e.sql,t,i);return hn(e.sql,t,a,fn(e.sql)),r}catch(e){throw r=e,e}}let c={now:()=>n,busyTimeoutMs:e.config.busy_timeout_ms,enqueue:t=>u(()=>Ye(e,t)),completeReceipt:t=>u(()=>nt(e,t)),abandonReceipt:t=>u(()=>it(e,t)),deliveryView:async t=>u(()=>ot(e,t)),deliveryReceipt:async t=>u(()=>rt(e,t)),recoverDelivery:t=>u(()=>st(e,t)),bind:t=>u(()=>qt(e,t)),unbind:t=>u(()=>It(e,t)),rebind:t=>u(()=>Ut(e,t)),listBindings:t=>u(()=>Dt(e,t)),bindingView:t=>u(()=>Mt(e,t)),report:t=>u(()=>Wt(e,t)),readOutbox:t=>u(()=>Pt(e,{...t,pendingOnly:!0})),ackOutbox:t=>u(()=>jt(e,t)),claimAnswer:t=>u(()=>Gt(e,t)),releaseAnswer:t=>u(()=>Kt(e,t)),confirmAnswer:t=>u(()=>Vt(e,t)),markPriorDelivered:t=>u(()=>Yt(e,t)),emitCompletions:t=>u(()=>Xt(e,t))},p={wake:async()=>{throw Error("An extension enqueue cannot contact a live endpoint.")}},g=function(e){let t=e.store,n=e.now??t.now;return{deliver:async function(i){let r=i.mode??"auto";if("steer"===r&&void 0===i.expected_turn_id)return Nn("invalid_arguments","A steer needs expected_turn_id (the target's current turn_epoch).");let s=Buffer.byteLength(i.text);if(s>H)return Nn("message_too_large",`The message is ${s} bytes, above the 1048576-byte limit.`);let o=await e.resolve(i.target,{all_scope:i.all_scope});if("error"===o.kind)return o;let a=o.target,d="routable"===a.liveness?a.endpoint:null;if(null===d&&"refuse"===function(e,t,n,i){return"offline"===e?"steer"===t?{kind:"refuse",reason:"turn_conflict"}:{kind:"queued_offline"}:"steer"===t?"mid_turn"!==e?{kind:"refuse",reason:"not_steerable"}:null===n||null===i||n!==i?{kind:"refuse",reason:"turn_conflict"}:{kind:"admit",deliverAs:"steer",expected_turn_id:n,expect:"steered"}:{kind:"admit",deliverAs:"followUp",expect:"idle"===e?"started":"queued"}}("offline",r,i.expected_turn_id??null,null).kind)return Nn("turn_conflict","The target has no live turn to steer.",{target:a.durable_id});let u=function(e){if("session"===e.kind)return{principal:`session:${e.durable_id}`,rate_principal:`session:${e.durable_id}`,node:e.durable_id,turn:e.turn_id??null,cause:e.cause_delivery_id??null,actor:e.name??e.durable_id,origin:()=>({session:e.durable_id}),binding:null};if("cli"===e.kind){let t=`cli:${e.uid}`;return{principal:t,rate_principal:t,node:t,turn:null,cause:null,actor:e.user,origin:t=>({external:{platform:"cli",account_id:e.user,chat_id:"@cli",thread_id:"@chat",message_id:t}}),binding:null}}let t=`binding:${e.binding_id}`,n=e.origin.author;return{principal:t,rate_principal:void 0===n?t:`${t}#author:${n.platform_user_id}`,node:t,turn:null,cause:null,actor:e.origin.account_id,origin:()=>({external:e.origin}),binding:{binding_id:e.binding_id,revision:e.binding_revision}}}(i.sender),_=vn(),l=i.idempotency_key??`auto:${_}`,c=await t.enqueue({now:n(),delivery_id:_,target_durable_id:a.durable_id,sender_principal:u.principal,rate_principal:u.rate_principal,sender_node:u.node,sender_turn:u.turn,cause_delivery_id:u.cause,claimed_root_id:i.root_id??null,origin:u.origin(_),actor:u.actor,body:i.text,mode:r,expected_turn_id:i.expected_turn_id??null,binding:u.binding,receipt:{idempotency_key:l,args_hash:Ln({target:a.durable_id,text:i.text,mode:r,expected_turn_id:i.expected_turn_id??null,binding:u.binding,author:"external"===i.sender.kind?i.sender.origin.author:void 0})},endpoint_kind:d?.kind??null});if("busy"===c.kind)return Nn("overloaded","The gateway store is locked by a suspended writer; nothing was sent.",{budget:"store_lock"});if("refused"===c.kind)return Nn(c.code,c.message,c.details);if("replay"===c.kind){let e=c.result;return"ok"===e.kind?{...e,deduplicated:!0}:e}let p=async e=>(await t.completeReceipt({now:n(),principal:u.principal,idempotency_key:l,result:e}),e);try{if(null===d)return await p(we(c.row,c.queue_position,null,!1,!0));let n=!0;try{await e.endpoints.wake(d,[_])}catch{n=!1}let i=await t.deliveryView(_);if(null===i)throw Error(`delivery ${_} vanished after commit`);return await p(we(i.row,i.queue_position,d.kind,!1,!n))}catch(e){throw await t.abandonReceipt({now:n(),principal:u.principal,idempotency_key:l,error_note:e instanceof Error?e.message:String(e)}).catch(()=>!1),e}}}}({store:c,endpoints:p,resolve:async(e,t)=>{let n=await i(e,t);return"error"===n.kind?n:{kind:"ok",target:{...n.target,endpoint:null,liveness:"dead"}}}}),m=Wn({store:c,engine:g,endpoints:p,locate:async()=>null});return{tx:{all:(t,n,i,r)=>l(n,()=>{for(let e of t)kn(e);if(void 0===r)return e.sql.all(t,n,i);let s=function(e){return e.split(",").map(t=>{let n=Rn.exec(t);if(null===n)throw new gn(`orderBy must list the statement's output columns, each optionally with COLLATE BINARY/NOCASE/RTRIM, ASC/DESC or NULLS FIRST/LAST; got ${xn(e)}. Put LIMIT, OFFSET and table-qualified ordering in the statement itself.`);return{column:n[1],collate:Sn(n[2]),direction:Sn(n[3]),nulls:Sn(n[4])}})}(r);return e.sql.all(["0"],`SELECT 0 FROM (${n}\n) WHERE 0`,i),e.sql.all(t,n,i,function(e,t){return e.map(e=>{let n=t.find(t=>bn(t)===bn(e.column));if(void 0===n)throw new gn(`orderBy must list the statement's output columns; ${xn(e.column)} is not one of them (${xn(t.join(", "))}). Select it in the statement or order by a column it returns.`);return[`"${n.replaceAll('"','""')}"`,e.collate&&`COLLATE ${e.collate}`,e.direction,e.nulls&&`NULLS ${e.nulls}`].filter(Boolean).join(" ")}).join(", ")}(s,e.sql.resultColumns(n)))}),one:(t,n,i)=>l(n,()=>{for(let e of t)kn(e);return e.sql.one(t,n,i)}),exec:(t,n)=>l(t,()=>e.sql.run(t,n)),enqueue:e=>_(()=>m.inbound(e)),outboxAck:e=>_(()=>m.ack(e)),bind:e=>_(()=>m.bind(e)),unbind:e=>_(()=>m.unbind(e)),rebind:e=>_(()=>m.rebind(e)),bindingFor:t=>_(()=>async function(e,t){return await Me(e,"binding_for",()=>(Rt(e,t.now),Nt(e,"platform = ? AND account_id = ? AND chat_id = ? AND thread_id = ? AND status = 'active'",[t.platform,t.account_id,t.chat_id,t.thread_id])[0]??null))}(e,{...t,now:n})),outboxPending:e=>_(()=>m.outbox(e))},cancel:()=>{s=!1,a=!0,m.dispose()},finish:async()=>{if(s=!1,await d,m.dispose(),void 0!==r)throw r}}}function jn(e,t){return{kind:"refused",code:e,message:t}}function Bn(e){let t=e instanceof Error?e.message:String(e);return e instanceof gn||e instanceof Ne?jn(e.code,t):u(e)?jn("gateway_lock_wait_exceeded",t):jn("extension_operation_failed",t)}class Gn{ctx;resolveTarget;registered=new Map;constructor(e,t){this.ctx=e,this.resolveTarget=t}async register(e,t){if(!/^[a-z][a-z0-9_]{1,31}$/.test(e.name)||!Array.isArray(e.migrations)||!e.migrations.every(e=>Array.isArray(e)&&e.every(e=>"string"==typeof e)))return jn("invalid_arguments","An extension needs a valid namespace and an array of SQL migration steps.");try{!function(e,t){let n=e.all(["name"],"SELECT name FROM extension_objects WHERE owner IS NULL");if(["gateway","thread","sqlite"].includes(t)||n.some(e=>bn(String(e.name)).startsWith(t)))throw new gn(`Extension name ${t} collides with a core namespace.`)}(this.ctx.sql,e.name)}catch(e){return Bn(e)}let n;try{let t=new URL(e.moduleUrl);if("file:"!==t.protocol||![".js",".mjs",".cjs"].includes(zt(t.pathname)))return jn("extension_import_failed","moduleUrl must name a compiled JavaScript file URL.");n=await(import(e.moduleUrl))}catch(t){return jn("extension_import_failed",`Cannot import extension ${e.name}: ${t instanceof Error?t.message:String(t)}`)}try{let i=await this.ensure(e,t);return this.registered.set(e.name,{descriptor:e,module:n}),{kind:"ok",value:{version:i}}}catch(t){return t instanceof Ne||this.registered.set(e.name,{descriptor:e,module:n}),Bn(t)}}holds(e){return this.registered.get(e.name)?.descriptor===e}async ensure(e,t){let{name:n,migrations:i}=e,r=this.ctx.sql.one(["version"],"SELECT version FROM extension_schema WHERE name = ?",[n]);if(void 0!==r&&Number(r.version)===i.length)return i.length;for(;;){let e=await Me(this.ctx,"extension_migrate",()=>{let e=this.ctx.sql.one(["version"],"SELECT version FROM extension_schema WHERE name = ?",[n]),r=Number(e?.version??0);if(r>i.length)throw new Ne(r,i.length,`Extension ${n}`);let s=fn(this.ctx.sql);if(void 0===e&&s.objects.some(e=>bn(String(e.name)).startsWith(`${n}_`)&&null==s.owners.get(`${String(e.type)}:${bn(String(e.name))}`)))throw new gn(`Namespace ${n} already contains unowned objects.`);if(r===i.length)return void 0===e&&this.ctx.sql.run("INSERT INTO extension_schema (name, version, updated_at) VALUES (?, 0, ?)",[n,t]),{version:r,applied:!1};for(let e of i[r]){kn(e);let t=fn(this.ctx.sql);yn(this.ctx.sql,n,()=>this.ctx.sql.exec(e)),hn(this.ctx.sql,n,t,fn(this.ctx.sql))}return hn(this.ctx.sql,n,s,fn(this.ctx.sql)),this.ctx.sql.run("INSERT INTO extension_schema (name, version, updated_at) VALUES (?, ?, ?) ON CONFLICT(name) DO UPDATE SET version = excluded.version, updated_at = excluded.updated_at",[n,r+1,t]),{version:r+1,applied:!0}});if(!e.applied)return e.version}}async call(e,t,n,i){let r=this.registered.get(e);if(void 0===r)return jn("extension_unknown_name",`No store extension is registered as ${e}.`);let s=Object.hasOwn(r.module,t)?r.module[t]:void 0;if("function"!=typeof s)return jn("extension_unknown_op",`Extension ${e} exports no operation ${t}.`);let o,a=[],d=[];try{let u=await this.ensure(r.descriptor,i);o=await Me(this.ctx,"extension_call",async()=>{let o=this.ctx.sql.one(["version"],"SELECT version FROM extension_schema WHERE name = ?",[e]),_=Number(o?.version??0);if(_!==u)throw new Ne(_,r.descriptor.migrations.length,`Extension ${e}`);let l,c=fn(this.ctx.sql),p=Pn({...this.ctx,afterCommit:a,afterRollback:d},e,i,this.resolveTarget);try{let i=async()=>{try{return await s(p.tx,n)}finally{await p.finish()}},r=new Promise((n,i)=>{l=setTimeout(()=>{p.cancel(),i(Error(`Extension ${e}.${t} exceeded its ${this.ctx.config.lock_wait_max_ms} ms operation budget.`))},this.ctx.config.lock_wait_max_ms)}),o=await Promise.race([i(),r]);return hn(this.ctx.sql,e,c,fn(this.ctx.sql)),structuredClone(o)}finally{clearTimeout(l),p.cancel()}})}catch(t){for(let t of d)try{t()}catch(t){this.ctx.emit({kind:"extension_error",extension:e,phase:"after_rollback",error:t instanceof Error?t.message:String(t)})}return Bn(t)}await this.ctx.hook("afterDbCommit");for(let t of a)try{t()}catch(t){this.ctx.emit({kind:"extension_error",extension:e,phase:"after_commit",error:t instanceof Error?t.message:String(t)})}return{kind:"ok",value:o}}}var Jn=a;if(null===Jn)throw Error("the gateway store worker must run as a worker thread");var Kn,Yn,Vn,zn,Qn=[],Zn=new Map,ei=!1,ti=1,ni=new Map,ii=(e,t)=>new Promise((n,i)=>{let r=ti++;ni.set(r,{resolve:n,reject:i}),Jn.postMessage({type:"resolve",id:r,address:e,request:t})});function ri(e){si(e instanceof Xn?{kind:"extension_error",extension:e.extension,phase:"stale_transaction",error:e.message}:{kind:"extension_error",extension:zn??"worker",phase:"async",error:e instanceof Error?e.message:String(e)})}function si(e){Jn?.postMessage({type:"event",event:e})}async function oi(a,u){if("init"===a)return await async function(a){let{config:u}=a,c=l(u.agent_dir);i(s(c,"inbox"),{recursive:!0,mode:448}),e(c,448);let p=(g=u.agent_dir,_(l(g),"gateway.sqlite"));var g;t(r(p,"a",384)),e(p,384);let m=await(import("node:sqlite"));Yn=new m.DatabaseSync(p,{timeout:u.busy_timeout_ms});let E=new y(Yn);E.exec(`PRAGMA busy_timeout = ${Math.trunc(u.busy_timeout_ms)}`);let f=Date.now();for(;;)try{E.exec("PRAGMA journal_mode = WAL");break}catch(e){if(!v(e))throw e;let t=Date.now()-f;if(t+10>u.lock_wait_max_ms)throw si({kind:"lock_wait_exceeded",op:"open",waited_ms:t}),d("open",t,u.lock_wait_max_ms);await o(10)}E.exec("PRAGMA synchronous = FULL");for(let t of["-wal","-shm"])n(`${p}${t}`)&&e(`${p}${t}`,384);let h={pid:process.pid,process_start_time:await b(process.pid),instance_id:u.instance_id,runtime_instance:u.runtime_instance};Kn={sql:E,config:u,self:h,stats:{writes:0,marker_unlinks:0,transactions:0},emit:si,hook:ai,delay:e=>o(e)};try{await async function(e){if(!(je(e)>=Le.length))for(;;){let t=je(e);if(t>=Le.length)return;let n=Ge.has(t),i=n?Number(e.sql.one(["foreign_keys"],"SELECT foreign_keys FROM pragma_foreign_keys")?.foreign_keys??1):1;n&&e.sql.exec("PRAGMA foreign_keys = OFF");try{await Me(e,"migrate",()=>{let i=je(e);if(i===t){for(let t of Le[i])e.sql.exec(t);if(n&&e.sql.all(["parent"],"SELECT parent FROM pragma_foreign_key_check").filter(e=>"bindings"===e.parent).length>0)throw new Be(i+1,`gateway schema ${i+1} would leave a foreign-key violation referencing bindings; staying at v${i}`);e.sql.exec(`PRAGMA user_version = ${i+1}`)}})}finally{n&&e.sql.exec("PRAGMA foreign_keys = "+(0===i?"OFF":"ON"))}}}(Kn),Vn=new Gn(Kn,ii);let e=await async function(e,t){let n=0;for(let i of e.config.legacy_mailbox_directories){let r,s=`legacy_mailbox:${i}`;if(void 0!==e.sql.one(["value"],"SELECT value FROM gateway_meta WHERE key = ?",[s]))continue;try{r=J(i)}catch(t){e.emit({kind:"legacy_mailbox_invalid",directory:i,error:t instanceof Error?t.message:String(t)});continue}if(null===r)continue;let o=at(),a=r.filter(e=>!xe.test(e.target)).map(e=>({message_seq:e.message_seq,target:e.target,reason:"invalid_target"})),d=r.filter(e=>xe.test(e.target));n+=await Me(e,"migrate_legacy",()=>{let n=0;for(let r of d){let s=`legacy-${Pe([i,r.message_seq]).slice(0,32)}`;if(void 0!==qe(e,s))continue;let a=`root-${N()}`,d=`legacy:${i}`;Ce(e,"INSERT INTO causal_roots (root_id, origin_principal, created_at, expires_at) VALUES (?, ?, ?, ?)",[a,d,t,t+$]);let u=Date.parse(r.accepted_at);Fe(e,{delivery_id:s,target_durable_id:r.target,seq:Xe(e,r.target),sender:d,sender_turn:null,envelope:{origin:{external:{platform:"legacy_mailbox",account_id:o,chat_id:i,thread_id:"@chat",message_id:r.operation_id}},actor:"legacy thread mailbox",via:[d],root_id:a,hop:1,delivery_id:s},body:r.message,bytes:Buffer.byteLength(r.message),mode_requested:r.delivery,mode_effective:null,expected_turn_id:r.expected_turn_id,state:"queued",reason:null,admitted_by:null,claimed_at:null,attempt:0,admission_kind:null,turn_epoch:null,root_id:a,hop:1,created_at:Number.isFinite(u)?u:t,updated_at:t,expires_at:t+M,binding_id:null,binding_revision:null,actor_user_id:null}),$e(e,r.target,s,!0),n++}return Ce(e,"INSERT INTO gateway_meta (key, value) VALUES (?, ?)",[s,JSON.stringify({migrated_at:t,count:n,skipped:a})]),n}),a.length>0&&e.emit({kind:"legacy_mailbox_skipped",directory:i,items:a})}return n}(Kn,a.now);return Kn.stats.writes=0,Kn.stats.transactions=0,Kn.stats.marker_unlinks=0,{self:h,legacy_migrated:e}}catch(e){try{Yn.exec("ROLLBACK")}catch{}try{Yn.close()}finally{Yn=void 0,Kn=void 0,si({kind:"store_closed"})}throw e}}(u);if("close"===a)return Yn?.close(),Yn=void 0,Kn=void 0,Vn=void 0,null;let c=function(){if(void 0===Kn)throw Error("the gateway store is not open");return Kn}();switch(a){case"extension_register":{let e=u;return zn=e.extension.name,{result:await(Vn?.register(e.extension,e.now)),retained:!0===Vn?.holds(e.extension)}}case"extension_call":{let e=u;zn=e.name;try{return await(Vn?.call(e.name,e.op,e.args,e.now))}finally{for(let t of ni.values())t.reject(new Xn(e.name));ni.clear()}}case"enqueue":return await Ye(c,u);case"reconcile":return await tt(c,u);case"claim":return await async function(e,t){return await Me(e,"claim",()=>{let n=qe(e,t.delivery_id);return void 0===n||"queued"!==n.state?{kind:"lost",state:n?.state??null}:n.expires_at<=t.now?(et(e,n,"refused",t.now,{reason:"expired"}),He(e,n.target_durable_id,n.delivery_id),{kind:"lost",state:"refused"}):(Ce(e,"UPDATE deliveries SET state = 'admitting', admitted_by = ?, claimed_at = ?, attempt = attempt + 1, mode_effective = ?, updated_at = ? WHERE delivery_id = ? AND state = 'queued'",[JSON.stringify(t.self),t.now,t.lane,t.now,t.delivery_id]),He(e,n.target_durable_id,n.delivery_id),{kind:"claimed",row:qe(e,t.delivery_id)})})}(c,u);case"record_outcome":return await async function(e,t){return await Me(e,"record_outcome",()=>{let n=qe(e,t.delivery_id);if(void 0===n||"admitting"!==n.state&&"admitted"!==n.state||null===n.admitted_by||!f(n.admitted_by,t.self))return{kind:"lost",state:n?.state??null};let i=t.outcome;return"requeue"===i.kind?et(e,n,"queued",t.now):"refused"===i.kind?et(e,n,"refused",t.now,{reason:i.reason}):(Ce(e,"UPDATE deliveries SET admission_kind = ?, turn_epoch = ?, updated_at = ? WHERE delivery_id = ?",[i.admission_kind,i.turn_epoch,t.now,n.delivery_id]),n.state!==i.kind&&et(e,n,i.kind,t.now)),{kind:"claimed",row:qe(e,t.delivery_id)}})}(c,u);case"refuse_queued":return await async function(e,t){return await Me(e,"refuse",()=>{let n=qe(e,t.delivery_id);return void 0!==n&&"queued"===n.state&&(et(e,n,"refused",t.now,{reason:t.reason}),He(e,n.target_durable_id,n.delivery_id),!0)})}(c,u);case"complete_receipt":return await nt(c,u);case"abandon_receipt":return await it(c,u);case"delivery_view":return ot(c,u);case"delivery_receipt":return rt(c,u);case"recover_delivery":return await st(c,u);case"list":return function(e,t){return void 0!==t.target_durable_id?Ae(e,"target_durable_id = ?",[t.target_durable_id],"seq"):void 0!==t.root_id?Ae(e,"root_id = ?",[t.root_id],"created_at, seq"):Ae(e,"1 = 1",[],"created_at, seq")}(c,u);case"is_referenced":return function(e,t){return Number(e.sql.one(["n"],`SELECT COUNT(*) AS n FROM deliveries WHERE target_durable_id = ? AND state IN ${Re}`,[t])?.n??0)>0||Number(e.sql.one(["n"],"SELECT COUNT(*) AS n FROM bindings WHERE session_durable_id = ? AND status = 'active'",[t])?.n??0)>0||We(e,t).length>0}(c,u);case"journal_mode":return function(e){return String(e.sql.one(["journal_mode"],"SELECT journal_mode FROM pragma_journal_mode()")?.journal_mode??"")}(c);case"stats":return function(e){return{...e.stats}}(c);case"tool_receipt_begin":return await At(c,u);case"tool_receipt_settle":return await async function(e,t){return await Me(e,"tool_receipt_settle",()=>{let n="result"in t;return 1===Ce(e,`UPDATE receipts SET status = ?, ${n?"result":"error_note"} = ?, updated_at = ? WHERE principal = ? AND operation = ? AND idempotency_key = ? AND status = 'prepared' AND owner_instance = ?`,[n?"completed":"uncertain",n?JSON.stringify(t.result):t.error_note,t.now,t.principal,t.operation,t.idempotency_key,e.config.instance_id])})}(c,u);case"bind":return await qt(c,u);case"unbind":return await It(c,u);case"rebind":return await Ut(c,u);case"list_bindings":return await Dt(c,u);case"binding_view":return await Mt(c,u);case"register_incarnation":return await async function(e,t){await Me(e,"register_incarnation",()=>{Ce(e,"INSERT INTO session_meta (durable_id, next_seq, incarnation, endpoint_socket, endpoint_kind)\n VALUES (?, (SELECT COALESCE(MAX(seq), 0) + 1 FROM deliveries WHERE target_durable_id = ?), ?, ?, ?)\n ON CONFLICT(durable_id) DO UPDATE SET incarnation = excluded.incarnation,\n endpoint_socket = excluded.endpoint_socket, endpoint_kind = excluded.endpoint_kind",[t.durable_id,t.durable_id,t.incarnation,t.endpoint?.socket??null,t.endpoint?.kind??null])})}(c,u);case"clear_endpoint":return await async function(e,t){await Me(e,"clear_endpoint",()=>{Ce(e,"UPDATE session_meta SET endpoint_socket = NULL, endpoint_kind = NULL WHERE durable_id = ? AND incarnation = ?",[t.durable_id,t.incarnation])})}(c,u);case"session_owner":return function(e,t){let n=e.sql.one(["incarnation","endpoint_socket","endpoint_kind"],"SELECT incarnation, endpoint_socket, endpoint_kind FROM session_meta WHERE durable_id = ?",[t]);return void 0===n||"string"!=typeof n.incarnation?null:{incarnation:n.incarnation,endpoint:"string"!=typeof n.endpoint_socket||"tui"!==n.endpoint_kind&&"rpc_host"!==n.endpoint_kind?null:{socket:n.endpoint_socket,kind:n.endpoint_kind}}}(c,u);case"report":return await Wt(c,u);case"emit_completions":return await Xt(c,u);case"pending_completion_arms":return function(e,t){return Number(e.sql.one(["n"],"SELECT COUNT(*) AS n FROM completion_arms WHERE session_durable_id = ?",[t])?.n??0)}(c,u);case"latest_completion_arm":return function(e,t){let n=e.sql.one(["s"],"SELECT MAX(arm_seq) AS s FROM completion_arms WHERE session_durable_id = ?",[t])?.s;return null==n?null:Number(n)}(c,u);case"read_outbox":return await Pt(c,u);case"ack_outbox":return await jt(c,u);case"claim_answer":return await Gt(c,u);case"release_answer":return await Kt(c,u);case"confirm_answer":return await Vt(c,u);case"mark_prior_delivered":return await Yt(c,u);case"close_question":return await async function(e,t){return await Me(e,"close_question",()=>{let n=e.sql.all(["cursor","binding_id"],"SELECT cursor, binding_id FROM outbox WHERE event_kind = 'question' AND session_durable_id = ? AND ui_request_id = ? AND (question_state = 'pending' OR (question_state = 'answered' AND answer_state = 'in_flight'))",[t.session_durable_id,t.ui_request_id],"cursor");for(let i of n)Ce(e,"UPDATE outbox SET question_state = 'answered', answer_state = 'delivered', answer = NULL, answered_at = ?, answered_by = NULL WHERE cursor = ? AND (question_state = 'pending' OR (question_state = 'answered' AND answer_state = 'in_flight'))",[t.now,Number(i.cursor)]),vt(e,String(i.binding_id),Number(i.cursor),t.now);return n.length})}(c,u);default:throw Error(`unknown gateway store op: ${a}`)}}async function ai(e){let t=Kn?.config.test_hooks[e];if(void 0===t)return;if("throw"===t)throw Error(`gateway test hook ${e}`);"sigkill"===t&&(process.kill(process.pid,"SIGKILL"),await new Promise(()=>{}));let n=new Promise(t=>Zn.set(e,t));si({kind:"paused",hook:e}),await n}process.on("uncaughtException",ri),process.on("unhandledRejection",ri),Jn.on("message",e=>{if("resolution"===e.type){let t=ni.get(e.id);return ni.delete(e.id),void(e.ok?t?.resolve(e.value):t?.reject(Error(e.error)))}if("resume"===e.type)return Zn.get(e.hook)?.(),void Zn.delete(e.hook);Qn.push(e),async function(){if(ei)return;ei=!0;try{for(let e=Qn.shift();void 0!==e;e=Qn.shift())try{let t=await oi(e.op,e.args);Jn?.postMessage({type:"response",id:e.id,ok:!0,value:t})}catch(t){Jn?.postMessage({type:"response",id:e.id,ok:!1,error:{message:t instanceof Error?t.message:String(t),stack:t instanceof Error?t.stack:void 0,code:"string"==typeof t?.code?t.code:void 0}})}}finally{ei=!1}}()});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// omo:
|
|
2
|
+
// omo:W700EJzOUalGNmx_WJ6UgheDnBCxd1QqDbGKAjHyp5I:cyyKk3v072Wr0yihI5kP-aCZ5ol1QhmoND6_-vNXPHI
|
|
3
3
|
import{spawn as e}from"node:child_process";import*as t from"node:fs";import*as r from"node:fs/promises";function n(e){if(e instanceof Error&&"code"in e)return"string"==typeof e.code?e.code:void 0}async function i(e){for(let t=0;;t+=1)try{return await e()}catch(e){if("EINTR"!==n(e)||t>=128)throw e}}function o(e){for(let t=0;;t+=1)try{return e()}catch(e){if("EINTR"!==n(e)||t>=128)throw e}}var a=new Set(["EPERM","EBUSY","EACCES"]),s=[10,25,50,100,200,400],c=e=>new Promise(t=>setTimeout(t,e));import{Buffer as l}from"node:buffer";import{constants as u}from"node:fs";function d(e){return"number"==typeof e?0!==(e&u.O_EXCL):"string"==typeof e&&e.toLowerCase().includes("x")}async function f(e,t,r,n){let o="string"==typeof t?l.from(t,r??"utf8"):t,a=0;for(;a<o.length;){n?.throwIfAborted();let{bytesWritten:t}=await i(()=>e.write(o,a));if(t<=0)throw Error(`fs write made no progress at offset ${a}`);a+=t}}function p(e){return"function"==typeof e}function m(e){return(...t)=>i(async()=>e(...t))}function w(e){return(...t)=>o(()=>e(...t))}function h(e,t){let r="async"===t?m:w,n=new Map;return new Proxy(e,{get(e,t){if(n.has(t))return n.get(t);let i=Reflect.get(e,t);if(!p(i))return i;let o=r(i),a=Reflect.get(i,"native");return p(a)&&Object.assign(o,{native:r(a)}),n.set(t,o),o}})}var y=new Set(["stat","sync","datasync","chmod","chown","utimes","truncate"]);var v=h(r,"async");function g(e,t){return async function(e,t,r){let i="win32"===r.platform?r.delaysMs??s:[],o=r.sleep??c;for(let s=0;;s+=1)try{return void await r.rename(e,t)}catch(e){let t=i[s],r=n(e);if(void 0===t||void 0===r||!a.has(r))throw e;await o(t)}}(e,t,{rename:v.rename,platform:process.platform})}var E=h(t,"sync"),{access:b,chmod:S,copyFile:_,cp:I,link:N,lstat:O,mkdir:x,mkdtemp:k,readFile:M,readdir:T,readlink:P,realpath:R,rm:A,rmdir:$,stat:D,unlink:L}=v,{accessSync:C,chmodSync:U,fsyncSync:q,linkSync:j,lstatSync:F,mkdirSync:z,readFileSync:B,readdirSync:G,realpathSync:H,statSync:J,unlinkSync:K,writeFileSync:Y,writeSync:Z}=E,{constants:V,watch:W}=t,X=async(...e)=>{let t=()=>r.open(...e);return function(e){return new Proxy(e,{get(e,t){let r=Reflect.get(e,t);if(!p(r))return r;let o=t=>Reflect.apply(r,e,[...t]);return"close"===t||t===Symbol.asyncDispose?(...e)=>{let t=o(e);return t instanceof Promise?t.catch(e=>{if("EINTR"!==n(e))throw e}):t}:"string"==typeof t&&y.has(t)?(...e)=>{let t=o(e);return t instanceof Promise?t.catch(t=>{if("EINTR"!==n(t))throw t;return i(async()=>o(e))}):t}:(...e)=>o(e)}})}(await(d(e[1]??"r")?t():i(t)))},Q=(e,r,n)=>function(e,t,r,n){return d(r)?e(t,r,n):o(()=>e(t,r,n))}(t.openSync,e,r,n??void 0);function ee(e){try{t.closeSync(e)}catch(e){if("EINTR"!==n(e))throw e}}function te(e){try{return o(()=>t.statSync(e)),!0}catch{return!1}}import{join as re}from"node:path";import{fileURLToPath as ne}from"node:url";import ie from"node:path";import oe from"node:path";import{randomUUID as ae}from"node:crypto";import{hostname as se}from"node:os";import{execFile as ce}from"node:child_process";var le=null;function ue(){return le??=async function(){if("darwin"!==process.platform)return null;try{let{dlopen:e,FFIType:t}=await(import("bun:ffi")),r=e("/usr/lib/libSystem.B.dylib",{proc_pidinfo:{args:[t.i32,t.i32,t.u64,t.ptr,t.i32],returns:t.i32}});return(e,t,n,i,o)=>Number(r.symbols.proc_pidinfo(e,t,n,i,o))}catch{return null}}(),le}var de=null;async function fe(e){if("win32"!==process.platform)return null;if(!Number.isSafeInteger(e)||e<=0)return null;de??=async function(){if("win32"!==process.platform)return null;try{let{dlopen:e,FFIType:t}=await(import("bun:ffi"));return e("kernel32.dll",{OpenProcess:{args:[t.u32,t.i32,t.u32],returns:t.ptr},GetProcessTimes:{args:[t.ptr,t.ptr,t.ptr,t.ptr,t.ptr],returns:t.i32},CloseHandle:{args:[t.ptr],returns:t.i32}}).symbols}catch{return null}}();let t=await de;if(null===t)return null;let r=t.OpenProcess(4096,0,e);if(null===r||0===r||0n===r)return null;try{let e=new BigUint64Array(1),n=t.GetProcessTimes(r,e,new BigUint64Array(1),new BigUint64Array(1),new BigUint64Array(1)),i=e[0]??0n;return 0===n||0n===i?null:i}finally{t.CloseHandle(r)}}async function pe(e,t){return await new Promise(r=>{ce(e,t,{encoding:"utf8",timeout:2e3,windowsHide:!0},(e,t)=>{if(null!==e)return void r(null);let n=t.trim();r(n.length>0?n:null)})})}var me=function(e,t){let r;return n=>n!==t?e(n):(r??=e(n).then(e=>(null===e&&(r=void 0),e),e=>{throw r=void 0,e}),r)}(async function(e){if("linux"===process.platform)return await async function(e){try{let t=await M(`/proc/${e}/stat`,"utf8"),r=t.lastIndexOf(")");if(r<0)return null;let n=t.slice(r+2).trim().split(/\s+/)[19];return void 0===n?null:`linux-proc-start-ticks:${n}`}catch{return null}}(e);if("darwin"===process.platform||"freebsd"===process.platform){if("dead"===he(e))return null;let t=await async function(e){if("darwin"!==process.platform)return null;if(!Number.isSafeInteger(e)||e<=0)return null;let t=await ue();if(null===t)return null;let r=new Uint8Array(136),n=0;try{n=t(e,3,0n,r,136)}catch{return null}if(136!==n)return null;let i=new DataView(r.buffer,r.byteOffset,r.byteLength),o=Number(i.getBigUint64(120,!0));return o>0?o:null}(e);if(null!==t)return`proc-start-epoch:${t}`;let r=await pe("/bin/ps",["-o","lstart=","-p",String(e)]);return null===r?null:`ps-lstart:${r.replace(/\s+/g," ")}`}return"win32"===process.platform?await async function(e){if("dead"===he(e))return null;let t=await fe(e);if(null!==t)return`win32-creation-filetime:${t}`;let r=await pe("powershell.exe",["-NoProfile","-Command",`(Get-Process -Id ${e} -ErrorAction SilentlyContinue).StartTime.ToUniversalTime().ToString('o')`]);return null===r?null:`win32-creation-date:${r}`}(e):null},process.pid);function we(e){let t=e.indexOf(":");return t<=0?null:e.slice(0,t)}function he(e){try{return process.kill(e,0),"alive"}catch(e){let t=function(e){if(e instanceof Error&&"code"in e)return"string"==typeof e.code?e.code:void 0}(e);return"ESRCH"===t?"dead":"EPERM"===t?"alive":"unknown"}}function ye(e){return"string"==typeof e&&e.length>0}function ve(e){let t;try{t=JSON.parse(e)}catch{return null}if("object"!=typeof t||null===t||Array.isArray(t))return null;let r=t;return!Number.isInteger(r.pid)||Number(r.pid)<=0?null:ye(r.process_start)&&ye(r.hostname)&&ye(r.nonce)?!ye(r.created_at)||Number.isNaN(Date.parse(r.created_at))?null:ye(r.purpose)&&(void 0===r.run_id||ye(r.run_id))?{pid:Number(r.pid),process_start:r.process_start,hostname:r.hostname,nonce:r.nonce,created_at:r.created_at,purpose:r.purpose,...void 0===r.run_id?{}:{run_id:r.run_id}}:null:null}async function ge(e,t={}){if(0===e.length)throw Error("lock purpose must not be empty");let r=await me(process.pid);return{pid:process.pid,process_start:r??"unavailable",hostname:se(),nonce:ae(),created_at:(new Date).toISOString(),purpose:e,...void 0===t.runId?{}:{run_id:t.runId}}}var Ee=new Map;function be(e,t,r){Ee.set(e,{previous:t,takeoverNonce:r})}function Se(e,t){Ee.get(e)?.takeoverNonce===t&&Ee.delete(e)}function _e(e){if(e instanceof Error&&"code"in e)return"string"==typeof e.code?e.code:void 0}async function Ie(e){try{let t=await M(e,"utf8"),r=await D(e,{bigint:!0});return{raw:t,record:ve(t),dev:r.dev,ino:r.ino,mtimeMs:Number(r.mtimeMs)}}catch(e){let t=_e(e);if("ENOENT"===t)return null;if("\\"===oe.sep&&"EPERM"===t)return{raw:"",record:null,dev:0,ino:0,mtimeMs:Date.now()};throw e}}function Ne(e,t){return e.dev===t.dev&&e.ino===t.ino&&e.mtimeMs===t.mtimeMs&&e.raw===t.raw}async function Oe(e,t){Se(e,t.nonce);let r=await Ie(e);if(null===r||r.record?.nonce!==t.nonce)return!1;try{return await L(e),!0}catch(e){if("ENOENT"===_e(e))return!1;throw e}}import{randomUUID as xe}from"node:crypto";import ke from"node:path";import Me from"node:path";var Te=new Set;function Pe(e){Te.add(e)}function Re(e){Te.delete(e)}var Ae=/\.candidate-(?:(\d+)-)?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function $e(e){let t=Ae.exec(e)?.[1];return void 0!==t&&"dead"===he(Number(t))}function De(e){if(e instanceof Error&&"code"in e)return"string"==typeof e.code?e.code:void 0}function Le(e,t){try{e.onFailure?.(t)}catch{}}function Ce(e){if("win32"!==process.platform)return!1;let t=De(e);return"EBUSY"===t||"EPERM"===t||"EACCES"===t}var Ue=new Map;function qe(e){Ue.delete(e)}var je=new Set(["EACCES","EPERM","ENOTSUP"]);function Fe(e){if(e instanceof Error&&"code"in e)return"string"==typeof e.code?e.code:void 0}function ze(e,t){if(void 0!==t)return t(e);if("win32"!==process.platform)return!1;let r=Fe(e);return"EBUSY"===r||"EPERM"===r||"EACCES"===r}var Be={};function Ge(){return Be}async function He(e){for(let t=0;t<3;t+=1)try{return await(Be.unlink??L)(e),Re(e),!0}catch(r){if("ENOENT"===Fe(r))return Re(e),!0;if(!ze(r,Be.isSharingError))throw Pe(e),qe(ke.dirname(e)),r;if(t+1===3)return Pe(e),qe(ke.dirname(e)),!1}return!1}async function Je(e,t){await x(ke.dirname(e),{recursive:!0,mode:448});let{candidatePath:r,handle:n}=await async function(e){for(let t=0;;t+=1){let r=`${e}.candidate-${process.pid}-${xe()}`;try{return{candidatePath:r,handle:await X(r,"wx",384)}}catch(n){if(await He(r)||qe(ke.dirname(e)),"EINTR"!==Fe(n)||t>=128)throw n}}}(e);try{try{await f(n,`${JSON.stringify(t)}\n`,"utf8"),await n.sync()}finally{await n.close()}try{return await(Be.link??N)(r,e),!0}catch(r){if(function(e){let t=Fe(e);return"EEXIST"===t||"ENOENT"===t}(r))return!1;if(je.has(Fe(r)??""))return await async function(e,t){let r;try{r=await X(e,"wx",384)}catch(e){if("EEXIST"===Fe(e))return!1;throw e}try{return await(Be.writeFallback??f)(r,`${JSON.stringify(t)}\n`,"utf8"),await r.sync(),!0}finally{await r.close()}}(e,t);throw r}}finally{await He(r)||qe(ke.dirname(e))}}function Ke(e,t,r=Math.random){let n=Math.min(250,t*2**Math.min(e,30));return Math.max(1,Math.round(n/2+r()*n/2))}function Ye(e,t){return t?.throwIfAborted(),new Promise((r,n)=>{let i=setTimeout(a,e),o=()=>a(t?.reason??new DOMException("The operation was aborted","AbortError"));function a(e){clearTimeout(i),t?.removeEventListener("abort",o),void 0===e?r():n(e)}t?.addEventListener("abort",o,{once:!0})})}import{randomUUID as Ze}from"node:crypto";import{hostname as Ve}from"node:os";function We(e){if(e instanceof Error&&"code"in e)return"string"==typeof e.code?e.code:void 0}async function Xe(e){if(e.hostname!==Ve())return!1;let t=he(e.pid);if("dead"===t)return!0;if("unknown"===t)return!1;let r=await me(e.pid);return null!==r&&"unavailable"!==e.process_start&&function(e,t){let r=we(e);return null!==r&&r===we(t)&&e!==t}(e.process_start,r)}async function Qe(e,t,r){return null!==e.record?Xe(e.record):t-e.mtimeMs>r}async function et(e,t,r){let n=await Ie(e);if(null===n||!await Qe(n,t,r))return!1;let i=`${e}.reaping-${Ze()}`;try{await g(e,i)}catch(e){if("ENOENT"===We(e))return!1;if(ze(e))return!1;throw e}let o=await Ie(i);if(null!==o&&Ne(o,n))return await L(i),!0;try{await N(i,e)}catch(e){if("EEXIST"!==We(e))throw e}return await L(i),!1}async function tt(e,t,r,n,i){if(!await Qe(t,n,i))return!1;let o=`${e}.recovery`,a={...r,nonce:Ze(),created_at:(new Date).toISOString(),purpose:`${r.purpose}:recovery`};for(let e=0;null!==await Ie(o)||!await Je(o,a);e+=1)if(e>0||!await et(o,n,i))return!1;try{let s=await Ie(e);if(null===s)return!0;if(!Ne(s,t))return!1;if(!await Qe(s,n,i))return!1;let c=await Ie(o);return null!==c&&c.record?.nonce===a.nonce&&(await L(e),null!==s.record&&be(e,s.record,r.nonce),!0)}finally{await Oe(o,a)}}class rt extends Error{lockPath;owner;retriable=!0;constructor(e,t){super(`Lock is held: ${e}`),this.lockPath=e,this.owner=t,this.name="LockContentionError"}}async function nt(e,t,r={}){let n=r.waitTimeoutMs??0,i=r.retryDelayMs??25,o=r.incompleteLockGraceMs??5e3,a=r.now??Date.now;if(n<0||i<=0||o<0)throw Error("lock wait options must be positive");let s=a()+n;try{return await async function(e,t,r,n){let{retryDelayMs:i,incompleteLockGraceMs:o,now:a,deadline:s}=n,c=!1,l=!1;for(let n=0;;n+=1){r.signal?.throwIfAborted();let u=await Ie(e);if(null===u){if(await Je(e,t))return{sawOtherOwner:c};if(r.signal?.throwIfAborted(),c=!0,l=it(e,t,l),u=await Ie(e),null===u)continue}if(c=!0,l=it(e,t,l),await tt(e,u,t,a(),o))l=!0;else{if(r.signal?.throwIfAborted(),a()>=s)throw new rt(e,u.record);await Ye(Math.min(Ke(n,i),Math.max(1,s-a())),r.signal)}}}(e,t,r,{retryDelayMs:i,incompleteLockGraceMs:o,now:a,deadline:s})}catch(r){throw Se(e,t.nonce),r}}function it(e,t,r){return r&&Se(e,t.nonce),!1}import{hostname as ot}from"node:os";import at from"node:path";function st(e){if(e instanceof Error&&"code"in e)return"string"==typeof e.code?e.code:void 0}async function ct(e,t){let r=!0===(await O(e).catch(()=>{}))?.isFile()?await async function(e){let t;try{t=await M(e,"utf8")}catch(e){if("ENOENT"===st(e))return null;throw e}let r=ve(t);return null===r||r.hostname!==ot()||"dead"!==he(r.pid)?null:await Xe(r)?r:null}(e):null;if(null===r)return!1;let n=await ge("dead-owner-sweep");try{await nt(e,n,{waitTimeoutMs:0})}catch(e){if(e instanceof rt)return!1;throw e}return await Oe(e,n),t.onReclaimed?.(e,r),!0}async function lt(e,t,r={}){let n,i=ie.dirname(e);if(function(e,t){let r=Ue.get(e);return!(void 0!==r&&t-r<6e5||(Ue.set(e,t),0))}(i,(r.now??Date.now)())){let t=Ge();await async function(e,t=Date.now,r={}){let n;try{n=await T(e)}catch(t){if("ENOENT"===De(t)){for(let t of Te)Me.dirname(t)===e&&Re(t);return 0}throw t}let i=0;for(let o of n){if(!Ae.test(o))continue;let n=Me.join(e,o);try{let e=await D(n);if(!(Te.has(n)||$e(o)||t()-e.mtimeMs>36e5))continue;let a=!1;for(let e=0;e<3;e+=1)try{await(r.unlink??L)(n),Re(n),a=!0;break}catch(t){if("ENOENT"===De(t)){Re(n),a=!0;break}if(!(r.isSharingError?.(t)??Ce(t)))throw t;e+1===3&&Le(r,n)}a&&(i+=1)}catch(e){"ENOENT"===De(e)&&Re(n),Le(r,n)}}return i}(i,Date.now,{...void 0===t.unlink?{}:{unlink:t.unlink},...void 0===t.isSharingError?{}:{isSharingError:t.isSharingError},onFailure:()=>qe(i)}).catch(()=>{qe(i)}),await async function(e,t={}){let r;try{r=await T(e)}catch(r){return"ENOENT"!==st(r)&&t.onFailure?.(e,r),0}let n=0;for(let i of r){if(!i.endsWith(".lock"))continue;let r=at.join(e,i);try{await ct(r,t)&&(n+=1)}catch(e){t.onFailure?.(r,e)}}return n}(i,{onReclaimed:(t,r)=>{ie.resolve(t)===ie.resolve(e)&&(n=r)}})}let o=await nt(e,t,r);void 0===n||o.sawOtherOwner||void 0!==function(e,t){let r=Ee.get(e);return r?.takeoverNonce===t?r.previous:void 0}(e,t.nonce)||be(e,n,t.nonce)}async function ut(e,t,r,n){await lt(e,t,n);try{return await r()}finally{await Oe(e,t)}}Promise.resolve();!function(){let e=process.env.OMO_TEST_GIT_LOCK_SETTLE_MS;if(void 0===e)return;let t=Number.parseInt(e,10);Number.isInteger(t)}();[{class:"aws_access_key",ere:"(^|[^A-Za-z0-9_])AKIA[0-9A-Z]{16}([^A-Za-z0-9_]|$)"},{class:"credential_assignment",ere:"(^|[^A-Za-z0-9_])([Bb][Ee][Aa][Rr][Ee][Rr]|[Tt][Oo][Kk][Ee][Nn]|[Aa][Pp][Ii][-_]?[Kk][Ee][Yy]|[Ss][Ee][Cc][Rr][Ee][Tt]|[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd]|[Pp][Aa][Ss][Ss][Ww][Dd]|[Pp][Ww][Dd])[[:space:]]*[=:][[:space:]]*[^[:space:]]{1,255}"},{class:"authorization_header",ere:"(^|[^A-Za-z0-9_])[Aa][Uu][Tt][Hh][Oo][Rr][Ii][Zz][Aa][Tt][Ii][Oo][Nn][[:space:]]*:[[:space:]]*[Bb][Ee][Aa][Rr][Ee][Rr][[:space:]]+[^[:space:]]{1,255}"},{class:"openai_key",ere:"(^|[^A-Za-z0-9_])sk-(proj-)?[-_A-Za-z0-9]+([^A-Za-z0-9_-]|$)"},{class:"vendor_token",ere:"(^|[^A-Za-z0-9_])(ghp|github_pat|glpat|xox[baprs])[-_][-_A-Za-z0-9]+([^A-Za-z0-9_-]|$)"}].map(({class:e,ere:t})=>[` if printf '%s' "$blob" | grep -E -q -e '${t}'; then`,` printf 'memory pre-commit: %s contains secret-like content (${e})\\n' "$p"`," fi"].join("\n")).join("\n"),new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0});import{dirname as dt}from"node:path";import{fileURLToPath as ft}from"node:url";dt(ft(import.meta.url));import{dirname as pt}from"node:path";import{fileURLToPath as mt}from"node:url";pt(mt(import.meta.url)),new Date(0).toISOString();var wt="\\p{Script=Hangul}\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\u30fc",ht=(new RegExp(`[${wt}]+|(?:(?![${wt}])[\\p{L}\\p{M}\\p{N}])+`,"gu"),new RegExp(`^[${wt}]+$`,"u"),new Map);new FinalizationRegistry(({dir:e,ref:t})=>{ht.get(e)===t&&ht.delete(e)}),new RegExp(`[${wt}]`,"u"),new RegExp(`[${wt}]`,"gu"),new RegExp(`[\\p{L}${wt}]`,"gu");import{dirname as yt}from"node:path";import{fileURLToPath as vt}from"node:url";yt(vt(import.meta.url));import{Buffer as gt}from"node:buffer";import{Buffer as Et}from"node:buffer";Et.from([0,32]),Et.from([0,1]),Et.from([0,2]),gt.concat([gt.from("omo-sync/v1/wrap","ascii"),gt.from([0])]);import{randomUUID as bt}from"node:crypto";import{dirname as St}from"node:path";async function _t(e){return JSON.parse(await M(e,"utf8"))}async function It(e,t,r=384){let n=`${e}.tmp-${process.pid}-${bt()}`,i=await X(n,"wx",r),o=!1;try{try{await i.writeFile(`${JSON.stringify(t,null,2)}\n`,"utf8"),await i.sync()}finally{await i.close()}await g(n,e),o=!0,await async function(e){try{let t=await X(e,"r");try{await t.sync()}finally{await t.close()}}catch(e){let t=e instanceof Error&&"code"in e?e.code:void 0;if("win32"!==process.platform||!["EISDIR","EPERM"].includes(String(t)))throw e}}(St(e))}finally{o||await Ot(n)}}async function Nt(e,t){let r=await _t(e);await It(e,{...r,...t})}async function Ot(e){try{await L(e)}catch(e){if(!(e instanceof Error&&"code"in e&&"ENOENT"===e.code))throw e}}import{spawn as xt,spawnSync as kt}from"node:child_process";function Mt(){return"1"===process.env.OMO_MEMORY_SUPERVISOR_ALLOW_TEST_SEAMS}function Tt(){if(Mt()){let e=process.env.OMO_MEMORY_SUPERVISOR_PLATFORM;if("posix"===e||"win32"===e)return e}return"win32"===process.platform?"win32":"posix"}function Pt(){let e=Mt()?process.env.OMO_MEMORY_SUPERVISOR_CLOCK_PATH:void 0;return void 0===e?Date.now():$t(e)}function Rt(e,t){let r=Mt()?process.env.OMO_MEMORY_SUPERVISOR_CLOCK_PATH:void 0;if(void 0===r){let r=setTimeout(t,Math.max(0,e-Date.now()));return()=>clearTimeout(r)}let n=!1,i=()=>{if(n)return;let i=$t(r);!Number.isFinite(i)||i<e||(n=!0,o?.close(),clearInterval(a),t())};if($t(r)>=e)return n=!0,t(),()=>{};let o=W(r,i),a=setInterval(i,At);return i(),()=>{n||(n=!0,o.close(),clearInterval(a))}}var At=25;function $t(e){let t=G(e).map(e=>/^(\d+)-(-?\d+(?:\.\d+)?)$/.exec(e)).filter(e=>null!==e).sort((e,t)=>Number(e[1])-Number(t[1])).at(-1);return void 0===t?Number.NaN:Number(t[2])}function Dt(e,t){if(!Mt())return;let r=process.env.OMO_MEMORY_SUPERVISOR_TASKKILL_RUN_DIR;void 0!==r&&Y(`${r}/${e}-${process.pid}.json`,`${JSON.stringify({targetPid:t})}\n`,"utf8")}function Lt(e){if(!Mt())return;let t=process.env[e];if(void 0===t)return;let r=JSON.parse(t);if(!Array.isArray(r)||!r.every(e=>"string"==typeof e)||0===r.length)throw TypeError(`${e} must be a non-empty string array`);return r}function Ct(e,t,r){let[n,...i]=e;if(void 0===n)throw TypeError("termination command is required");if(r){let e=kt(n,[...i,...t],{env:process.env,stdio:"ignore",windowsHide:!0});if(void 0!==e.error)throw e.error;return}xt(n,[...i,...t],{env:process.env,stdio:"ignore",windowsHide:!0}).once("error",e=>process.stderr.write(`${e.message}\n`))}function Ut(e,t){Dt(`posix-${t}`,e);let r=Lt("OMO_MEMORY_SUPERVISOR_POSIX_SIGNAL_COMMAND");if(void 0===r)try{process.kill(-e,t)}catch(e){if(!(e instanceof Error&&"code"in e&&"ESRCH"===e.code))throw e}else Ct(r,["--signal-group",String(e),t],!1)}function qt(e){void 0!==e&&Dt("win32-graceful",e)}function jt(e,t){"win32"===e?(qt(t.pid),t.kill()):void 0!==t.pid&&Ut(t.pid,"SIGTERM")}function Ft(e,t,r=!1){void 0!==t&&("win32"===e?function(e,t){Ct(Lt("OMO_MEMORY_SUPERVISOR_TASKKILL_COMMAND")??["taskkill"],["/pid",String(e),"/T","/F"],t)}(t,r):Ut(t,"SIGKILL"))}async function zt(e){return await me(e)}import{join as Bt}from"node:path";function Gt(e){return"object"==typeof e&&null!==e}function Ht(e,t){try{return e?.[t]}catch(e){return void Error}}function Jt(e,t){let r=Ht(e,t);return Gt(r)?r:void 0}function Kt(e){if(!e)return"";if("string"==typeof e)return e.toLowerCase();if(!Gt(e))try{return JSON.stringify(e).toLowerCase()}catch(e){if(!(e instanceof Error))throw e;return""}let t=Jt(e,"data"),r=[t,Jt(e,"error"),e,Jt(t,"error")].filter(e=>void 0!==e);for(let e of r){let t=Ht(e,"message");if("string"==typeof t&&t.length>0)return t.toLowerCase()}let n=Ht(e,"name");if("string"==typeof n&&n.length>0){let e=n.match(/:\s*(.+)/);if(e)return e[1]?.trim().toLowerCase()??""}try{return JSON.stringify(e).toLowerCase()}catch(e){if(!(e instanceof Error))throw e;return""}}function Yt(e,t){if(function(e){return"object"==typeof e&&null!==e}(e))try{return e[t]}catch(e){return void Error}}function Zt(e){return"terminal_quota_exhausted"===function(e){let t=Yt(e,"data"),r=Yt(e,"detail")??Yt(t,"detail")??e,n=Yt(r,"error")??r,i=Yt(n,"type")??Yt(r,"type");return"string"==typeof i?i.toLowerCase():void 0}(e)||(t=Kt(e),!/\bnon[-\s]+terminal\s+quota\b/i.test(t)&&!/\bnon[-\s]+terminal\s+billing\s+limit\b/i.test(t)&&(/\bterminal\s+quota\b/i.test(t)||/\bterminal\s+billing\s+limit\b/i.test(t)||/\bhard\s+billing\s+limit\b/i.test(t)));var t}function Vt(e){if(Zt(e))return"abort";let t=Kt(e),r=function(e){if(!Gt(e))return;let t=Jt(e,"data"),r=[e,t,Jt(e,"error"),Jt(t,"error")].filter(e=>void 0!==e);for(let e of r){let t=Ht(e,"name");if("string"==typeof t&&t.length>0)return t}}(e)?.toLowerCase().replace(/[_-]/g,"");return r?.includes("messageabortederror")||r?.includes("aborterror")?"abort":"contextoverflowerror"===r?"context_overflow":r?.includes("ailoadapikeyerror")||r?.includes("loadapi")||/api.?key.?is.?missing/i.test(t)&&/environment variable/i.test(t)?"missing_api_key":/api.?key/i.test(t)&&/must be a string/i.test(t)?"invalid_api_key":r?.includes("providermodelnotfounderror")||r?.includes("modelnotfounderror")||r?.includes("unknownerror")&&/model\s+not\s+found/i.test(t)?"model_not_found":r?.includes("quotaexceeded")||r?.includes("insufficientquota")||r?.includes("billingerror")||r?.includes("resourceexhausted")||r?.includes("insufficientcredits")||r?.includes("usagelimit")||/quota.?exceeded/i.test(t)||/exceeded.*quota/i.test(t)||/quota\b.*\breset/i.test(t)||/usage\s*quota/i.test(t)||/subscription.?(?:quota|limit)/i.test(t)||/insufficient.?(?:quota|balance|funds?|credits?)/i.test(t)||/credits?\s+exhausted/i.test(t)||/\b(?:session|weekly|monthly|daily|hourly|\d+[-\s]hour|plan|call)\s+limit\b/i.test(t)||/\bhit\s+your\b[^.]*\blimit\b/i.test(t)||/\bin\s+arrears\b/i.test(t)||/\brecharge\s+and\s+try\b/i.test(t)||/billing.?(?:hard.?)?limit/i.test(t)||/exhausted\s+your\s+capacity/i.test(t)||/resource.?exhausted/i.test(t)||/\bcapacity_limit\b/i.test(t)||/out\s+of\s+credits?/i.test(t)||/payment.?required/i.test(t)||/usage\s+limit/i.test(t)||/credit\s+balance.*too\s+low/i.test(t)||/limit\s+exhausted/i.test(t)||/使用上限/.test(t)||/用量上限/.test(t)||/达到.*限制/.test(t)||/额度.*不足/.test(t)||/余额.*不足/.test(t)||/已耗尽/.test(t)||function(e){return/预扣费额度失败/i.test(e)&&/用户剩余额度/i.test(e)||/用户剩余额度/i.test(e)&&/需要预扣费额度/i.test(e)}(t)?"quota_exceeded":void 0}var Wt=new Set(["providermodelnotfounderror","ratelimiterror","modelunavailableerror","providerconnectionerror","authenticationerror"]),Xt=new Set(["messageabortederror","permissiondeniederror","contextlengtherror","timeouterror","validationerror","syntaxerror","usererror"]),Qt=["rate_limit","rate limit","usage_limit_reached","usage limit has been reached","quota","all credentials for model","cooling down","exhausted your capacity","not found","unavailable","insufficient","too many requests","over limit","overloaded","bad gateway","bad request","unknown provider","provider not found","model_not_supported","model not supported","model is not supported","connection error","network error","timeout","service unavailable","internal_server_error","free usage","usage exceeded","credit","balance","temporarily unavailable","try again","请稍后重试","503","502","504","429","529","selected provider is forbidden","provider is forbidden","频率限制","请求过于频繁","暂时不可用","服务不可用","server_error","an error occurred while processing","upstream request failed"],er=["rate limit","cooling down","credentials for model"];function tr(e){let t=e.name?.toLowerCase();if(void 0!==t&&Xt.has(t))return!1;if(Zt(e))return!1;if("quota_exceeded"===Vt(e))return!0;if(void 0!==t&&Wt.has(t))return!0;let r=e.message?.toLowerCase()??"";return!(!(n=r).includes("retrying in")||!er.some(e=>n.includes(e)))||(null!=e.statusCode&&(429===e.statusCode||503===e.statusCode||529===e.statusCode)||Qt.some(e=>r.includes(e)));var n}var rr=[/prompt is too long/i,/request_too_large/i,/input is too long for requested model/i,/exceeds the context window/i,/exceeds (?:the )?(?:model'?s )?maximum context length(?: of [\d,]+ tokens?|\s*\([\d,]+\))/i,/input token count.*exceeds the maximum/i,/maximum prompt length is \d+/i,/reduce the length of the messages/i,/maximum context length is \d+ tokens/i,/exceeds (?:the )?maximum allowed input length of [\d,]+ tokens?/i,/input \(\d+ tokens\) is longer than the model'?s context length \d+ tokens/i,/exceeds the limit of \d+/i,/exceeds the available context size/i,/greater than the context length/i,/context window exceeds limit/i,/exceeded model token limit/i,/too large for model with \d+ maximum context length/i,/prompt has [\d,]+ tokens?, but the configured context size is [\d,]+ tokens?/i,/prompt too long; exceeded (?:max )?context length/i,/range of input length should be/i,/model_context_window_exceeded/i,/context[_ ]length[_ ]exceeded/i,/too many tokens/i,/token limit exceeded/i,/^4(?:00|13)\s*(?:status code)?\s*\(no body\)/i,/(?:request[ _])?(?:body|entity|payload)[_ ]too[_ ]large/i,/Request payload is \d+ (?:bytes, over the \d+ byte|tokens, over the \d+ token) limit Kiro accepts\./i,/Model context limit reached\. Conversation size exceeds model capacity\./i],nr=[/^(Throttling error|Service unavailable):/i,/rate limit/i,/too many requests/i];var ir=/^Error: Model "([^"]+)" not found\. Use --list-models to see available models\.$/m,or=/^(?:Error:\s*)?No API key found for\s+([^\s.]+)/m,ar=/(?:^|\s)(\d{3})\s*:/;function sr(e){if(e.timedOut||0===e.code)return;let t=`${e.stderr}\n${e.stdout}`,r=ir.exec(t)?.[1];if(void 0!==r)return{kind:"model_not_visible",id:r};let n=or.exec(t)?.[1];if(void 0!==n)return{kind:"auth_missing",provider:n};let i=function(e){for(let t of[e.stderr,e.stdout]){let e=t.split("\n").map(e=>e.trim()).find(e=>e.length>0&&!cr.test(e));if(void 0!==e)return e.slice(0,200)}return}(e);if(void 0===i)return;if(o=i,!nr.some(e=>e.test(o))&&rr.some(e=>e.test(o)))return{kind:"context_overflow",detail:i};var o;let a=Number.parseInt(ar.exec(i)?.[1]??"",10);return tr({message:i,...Number.isNaN(a)?{}:{statusCode:a}})?{kind:"provider_unavailable",detail:i}:void 0}var cr=/\bunder (?:Bun|Node(?:\.js)?|Deno)\b|^(?:\[[^\]]*\]\s*)?(?:note|notice|info|hint|debug|warn|warning)\s*:/i;import{randomUUID as lr}from"node:crypto";import{dirname as ur,join as dr}from"node:path";class fr extends Error{runDir;constructor(e,t){super(`Run terminal claim cannot be recovered in ${e}`,t),this.runDir=e,this.name="RunTerminalClaimUnrecoverableError"}}function pr(e){return dr(e,"terminal-claim.json")}function mr(e,t,r){return e.runId===t.runId&&e.attempt===t.attempt&&(void 0===r||e.kind===r)}function wr(e,t){let r=`${e}.${process.pid}.${lr()}.candidate`;!function(e,t){let r=Q(e,"wx",384);try{Y(r,`${JSON.stringify(t,null,2)}\n`,"utf8"),q(r)}finally{ee(r)}}(r,t);try{j(r,e)}catch(e){if("EEXIST"===br(e))return!1;throw e}finally{vr(r)}return function(e){let t;try{t=Q(e,"r")}catch(e){if("win32"===process.platform&&["EISDIR","EPERM"].includes(br(e)??""))return;throw e}try{q(t)}catch(e){if("win32"!==process.platform||!["EPERM","EACCES","EINVAL"].includes(br(e)??""))throw e}finally{ee(t)}}(ur(e)),!0}function hr(e){let t;try{t=B(e,"utf8")}catch(e){if("ENOENT"===br(e))return;throw e}try{return{raw:t,claim:Er(JSON.parse(t))}}catch{return{raw:t,claim:void 0}}}async function yr(e,t,r,n,i,o){let a=await ge("reflection-finalize",{runId:i.runId});return ut(dr(e,"terminal-claim-recovery.lock"),a,async()=>{let e=hr(t);if(void 0!==e){if(e.raw!==r.raw)return e.claim;if("invalid"===n){if(void 0!==e.claim)return e.claim}else{if(void 0===e.claim)return;if("publish"!==e.claim.kind||!gr(e.claim,o))return e.claim}vr(t)}},{waitTimeoutMs:Number.POSITIVE_INFINITY})}function vr(e){try{K(e)}catch(e){if("ENOENT"!==br(e))throw e}}function gr(e,t){return"dead"===(t.getPidLiveness??he)(e.claimantPid)}function Er(e){if(!function(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}(e)||1!==e.version||"publish"!==e.kind&&"abandon"!==e.kind||"string"!=typeof e.runId||!Number.isInteger(e.attempt)||!Number.isInteger(e.claimantPid)||Number(e.claimantPid)<=0)throw TypeError("Invalid run terminal claim");return{version:1,kind:e.kind,runId:e.runId,attempt:Number(e.attempt),claimantPid:Number(e.claimantPid)}}function br(e){return e instanceof Error&&"code"in e?String(e.code):void 0}import{join as Sr}from"node:path";async function _r(e,t,r){let n={runId:t.runId,attempt:t.attempt??1},i=await async function(e,t,r,n={},i=process.pid){let o=pr(e),a={version:1,kind:r,runId:t.runId,attempt:t.attempt,claimantPid:i},s=0;for(;;){if(wr(o,a))return a;let i;try{i=hr(o)}catch(t){throw new fr(e,{cause:t})}if(void 0===i)continue;let c=i.claim;if(void 0===c){if(s>0)throw new fr(e);s+=1,await(n.beforeRecovery?.("invalid"));let r=await yr(e,o,i,"invalid",t,n);if(void 0!==r)return r;continue}if(mr(c,t,r))return c;if("publish"!==c.kind||!gr(c,n))return c;await(n.beforeRecovery?.("dead-publish"));let l=await yr(e,o,i,"dead-publish",t,n);if(void 0!==l)return l}}(e,n,"publish");mr(i,n,"publish")&&(await It(Bt(e,"publishing.json"),{version:1,...n,finishedAt:r.finishedAt}),await async function(e,t,r,n=ut,i=ge){let o=await i("reflection-finalize",{runId:t});return n(Sr(e,"terminalization.lock"),o,r,{waitTimeoutMs:Number.POSITIVE_INFINITY})}(e,t.runId,async()=>{if(te(Bt(e,"final.json"))||te(Bt(e,"abandoned.json")))return;if(!mr(function(e){return Er(JSON.parse(B(pr(e),"utf8")))}(e),n,"publish"))return;let i=void 0!==sr({code:r.childExit.code,stdout:B(t.stdoutPath,"utf8"),stderr:B(t.stderrPath,"utf8"),timedOut:r.timedOut});i&&void 0!==t.nextAttempt&&await Nt(Bt(e,"ledger.json"),{attempt:t.nextAttempt.attempt,model:t.nextAttempt.model,...void 0===t.nextAttempt.thinking?{thinking:void 0}:{thinking:t.nextAttempt.thinking},launching:!0,pid:void 0,processStart:void 0,childPid:void 0,childProcessStart:void 0}),await It(Bt(e,"outcome.json"),r),i&&await Ot(pr(e))}))}function Ir(e){try{Z(3,`${JSON.stringify(e)}\n`)}catch(e){if(!(e instanceof Error&&"code"in e&&["EPIPE","EBADF"].includes(String(e.code))))throw e}}var Nr=process.argv.slice(2);try{if("--child-bootstrap"===Nr[0]){if(void 0===Nr[1])throw TypeError("run directory is required");await async function(t){if(!await async function(){for await(let e of process.stdin)if(Buffer.byteLength(e)>0)return!0;return!1}())return;let r=await _t(re(t,"launch.json")),n=Tt(),i=e(r.command,[...r.args],{cwd:r.cwd,env:r.env,detached:!1,stdio:["ignore","inherit","inherit"],windowsHide:!0});Ir({code:i.pid??null,signal:"MODEL_PID"});let o=()=>{"win32"!==n&&"win32"!==process.platform||i.kill()};process.on("SIGTERM",o),process.on("SIGINT",o);let a=!1,s=Rt(r.hardDeadlineAt,()=>{a=!0,"win32"===n?jt(n,i):Ut(process.pid,"SIGTERM")}),c=Rt(r.hardDeadlineAt+r.terminationGraceMs,()=>{a=!0,Ft(n,process.pid)}),l=await new Promise(e=>{let t=!1;i.once("error",()=>{t||(t=!0,e({code:null,signal:null}))}),i.once("close",(r,n)=>{t||(t=!0,e({code:r,signal:n}))})}).finally(()=>{s(),c()});var u,d;await It(re(t,"child-exit.json"),{version:1,runId:r.runId,attempt:r.attempt,code:l.code,signal:l.signal,finishedAt:(new Date).toISOString(),timedOut:a||(u=Pt(),d=r.hardDeadlineAt,!Number.isFinite(u)||u>=d)}),Ir(l)}(Nr[1])}else{if(void 0===Nr[0])throw TypeError("run directory is required");await async function(t){let r=re(t,"launch.json"),n=re(t,"ledger.json"),i=await _t(r),o=Tt();await Nt(n,{launching:!1,pid:process.pid,processStart:await zt(process.pid)});let a,s=Q(i.stdoutPath,"w"),c=Q(i.stderrPath,"w"),l=e(process.execPath,[ne(import.meta.url),"--child-bootstrap",t],{env:process.env,detached:!0,stdio:["pipe",s,c,"pipe"],windowsHide:!0}),u=l.pid,d="",f=l.stdio[3];null!=f&&"setEncoding"in f&&(f.setEncoding("utf8"),f.on("data",e=>{d+=e;for(let e of d.split("\n"))try{let t=JSON.parse(e);"MODEL_PID"===t.signal&&"number"==typeof t.code&&(a=t.code)}catch(e){if(!(e instanceof SyntaxError))throw e}}));let p=(e=!1)=>{try{Ft(o,u,e)}catch(e){process.stderr.write(`${e instanceof Error?e.message:String(e)}\n`)}};if(process.once("exit",()=>p(!0)),process.once("SIGTERM",()=>{p(),u=void 0,process.exit(143)}),process.once("SIGINT",()=>{p(),u=void 0,process.exit(130)}),void 0===l.pid)throw Error("child bootstrap did not receive a pid");await Nt(n,{childPid:l.pid,childProcessStart:await zt(l.pid)}),l.stdin?.end("1\n");let m,w=!1,h=Promise.resolve();"win32"===o&&(h=new Promise(e=>{m=e}));let y=Rt(i.hardDeadlineAt,()=>{w=!0,"win32"===o?qt(l.pid):jt(o,l)}),v=Rt(i.hardDeadlineAt+i.terminationGraceMs,()=>{Ft(o,a??u),m?.()}),g=await new Promise((e,t)=>{let r=!1;l.once("error",e=>{r||(r=!0,t(e))}),l.once("close",(t,n)=>{r||(r=!0,e({code:t,signal:n}))})}),E=function(e){let t=e.trim().split("\n").at(-1);if(void 0!==t&&0!==t.length)try{let e=JSON.parse(t),r="number"==typeof e.code||null===e.code?e.code:void 0,n="string"==typeof e.signal||null===e.signal?e.signal:void 0;return void 0===r||void 0===n||"MODEL_PID"===n?void 0:{code:r,signal:n}}catch{return}}(d);"win32"===o&&w&&void 0===E&&await h,y(),v(),u=void 0,ee(s),ee(c),function(e,t={}){if(process.env.OMO_MEMORY_KILL_POINT!==e)return;let r=t.kill??((e,t)=>{process.kill(e,t)});"win32"===(t.platform??process.platform)?r(process.pid):r(process.pid,"SIGKILL")}("after-child-exit");let b=Pt(),S=(new Date).toISOString(),_={version:1,runId:i.runId,attempt:i.attempt,finishedAt:S,childExit:E??g,timedOut:w||Number.isFinite(b)&&b>=i.hardDeadlineAt};await _r(t,i,_),await Ot(r),process.exit(0)}(Nr[0])}}catch(e){process.stderr.write(`${e instanceof Error?e.stack??e.message:String(e)}\n`),process.exitCode=1}
|