@ai-ecoverse/slicc-agent 7.4.2 → 7.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/agent.js +11 -0
- package/dist/agent.js.map +2 -2
- package/dist/approvals/index.js +8 -3
- package/dist/approvals/index.js.map +2 -2
- package/dist/clock.js +1 -0
- package/dist/clock.js.map +7 -0
- package/dist/host.js +1 -0
- package/dist/host.js.map +2 -2
- package/dist/index.js.map +2 -2
- package/dist/monitor/index.js +29 -1
- package/dist/monitor/index.js.map +2 -2
- package/dist/services.js.map +2 -2
- package/dist/spectrum/monitor-port.js +25 -4
- package/dist/spectrum/monitor-port.js.map +3 -3
- package/dist/timings.js +55 -0
- package/dist/timings.js.map +7 -0
- package/dist/types/agent.d.ts +4 -0
- package/dist/types/approvals/index.d.ts +2 -0
- package/dist/types/clock.d.ts +4 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/monitor/index.d.ts +5 -1
- package/dist/types/services.d.ts +13 -0
- package/dist/types/spectrum/monitor-port.d.ts +1 -0
- package/dist/types/timings.d.ts +18 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ agent.transcript.subscribe((view) => render(view));
|
|
|
26
26
|
await agent.prompt('What is in /home?');
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
- `openAgent({ models, model, storage?, registry?, settings? })` opens a durable Harness (in memory unless `storage` is given) and its root conversation, and resumes work a previous worker left unfinished.
|
|
29
|
+
- `openAgent({ models, model, storage?, registry?, settings?, clock? })` opens a durable Harness (in memory unless `storage` is given) and its root conversation, and resumes work a previous worker left unfinished. `clock` (`{ now, setTimer }`) is the Harness clock: task times, sleeps and the timers of its tasks, such as a guest review's expiry, run on it; `attachApprovals` takes the same `now` and `setTimer`. Tests pass a fake one and move it forward.
|
|
30
30
|
- `openOpfsSqliteStorage({ directory?, file? })` keeps the session in wasm SQLite ([`@sqlite.org/sqlite-wasm`](https://www.npmjs.com/package/@sqlite.org/sqlite-wasm)) in an `opfs-sahpool` pool, by default `/.slicc/agent/` in OPFS. It needs a dedicated worker. Only one worker holds a pool at a time: the opener takes a Web Lock per directory and waits until every file of the pool can be opened before sqlite-wasm installs it, because a failed install deletes the pool's directory. `openMemorySqliteStorage()` keeps the same database in memory. **Document bases.** Every session and conversation document the agent defines stores a complete base after 64 deltas (`boundedDeltas` in `src/checkpoints.ts`, the policy pi durable's codemode journal uses), so reading one replays at most 64 changes: with deltas only, a document changed 5,000 times took about 26 ms to read after a reopen, against under 1 ms. Task documents, which end with their task, keep deltas only. **Profile marker:** every open, under the pool's lock and before pi durable opens (and migrates) the database, writes `<directory>-profile.json` next to the pool, `/.slicc/agent-profile.json` by default: `{ "durableSchema": 2, "agent": "<version>" }`, with pi durable's `CURRENT_SQLITE_SCHEMA_VERSION` and the agent's version (the `agent` option, or the version in the agent's `package.json`). A `durableSchema` already in the file is never lowered. bios reads it from OPFS before it starts an agent, and refuses one whose pi durable schema is lower (slicc-agent 6.x is 1): the schema version lives in a `durable_schema` table, not in the SQLite header, so the database itself can't be checked without opening it. On pi durable 1.4, opening a database written by an earlier agent migrates it to durable's SQLite schema 2, once and in place; an agent on pi durable 1.3 or earlier (slicc-agent 6.19.13 and earlier) can't open it afterwards, so the agent can't be rolled back past this version. Requests through the Harness are attributed to SLICC (`identity: { attribution: { name: 'SLICC', url: 'https://www.sliccy.com' } }`), which pi-ai sends as OpenRouter's `HTTP-Referer` and `X-OpenRouter-Title`, NVIDIA's `X-BILLING-INVOKE-ORIGIN` and OpenCode's `x-opencode-client`; OpenRouter's preflight allows them from `https://seven.sliccy.ai`, and NVIDIA and OpenCode answer no browser preflight at all, so they go through a CORS-free transport either way. pi durable's crash-loop guard is on with its default: a task cut off 5 times in a row without committing a new state (a crash, a reload or `restart()`, which end the worker without closing the session) is parked instead of started again. The monitor shows it as `blocked: restart limit` with an error alert, "generating of sliccy is parked", whose command is `agent retry <task id>`; run from a terminal, that runs the task again (`Harness.retryTask`). Only the user can retry: an agent's `agent retry` is refused, and so is a task that isn't parked.
|
|
31
31
|
- `hostAgent(agent)` serves the agent from one Chord host named `agent` (`serveAgent` in [`src/host.ts`](src/host.ts)). Its remote contracts, in [`src/services.ts`](src/services.ts), are `slicc.agent.control` (send with `whenBusy` `steer`, `followUp` or `reject`, wait, withdraw, abort, compact) and `slicc.agent.transcript` (the conversation's durable view as replicated state, plus `deliveries`: how each user entry was delivered, `run`, `steer` or `follow-up`, derived by the host from where each send it accepted was placed: after a tool result it steered, queued first it's a follow-up or a late steer per its `whenBusy`, placed at once it started a run), `slicc.agent.settings`, `slicc.agent.remote` (remote control), `slicc.agent.pages` (Panels) and `slicc.agent.guest` (Guest seats). `serveConnections(self, host)` hands it every `MessagePort` the page sends, and each port becomes one Chord link whose principal is a seat: `owner` (a page of the owner, with its own Panels), `control` (a follower with Control), `view` (a follower without) or `guest` (a guest seat, with its id, label and epoch), plus the link's number, so every link gets its own objects. The principal is typed (`AgentPrincipal` in [`src/serving.ts`](src/serving.ts)); the host's own code acts as `{ seat: 'host' }`, which no link gets. Each factory picks a variant per seat. Every contract places its objects on the host `agent` (`hostNamed`), so no caller names a host. The contracts take their methods' arguments as one JSON array, and the client in [`src/serving.ts`](src/serving.ts) turns them back into the `AgentControl`, `AgentSettings`, `AgentRemote` and `AgentPages` interfaces and their replicated states, so callers don't see Chord.
|
|
32
32
|
- `@ai-ecoverse/slicc-agent/page` has what the page needs (`startAgent`, `connectAgent`) without the agent's runtime: no pi-durable, pi-ai, providers or SQLite, which load only in the worker. `@ai-ecoverse/slicc-agent/spectrum` is just as light, and a test keeps both that way.
|
|
@@ -619,6 +619,7 @@ Spectrum's Monitor panel (`MonitorPort`, opened from the Budget chip) shows the
|
|
|
619
619
|
- **Tasks:** `harness.watchTaskGraph()` gives every live task with its kind, owner, conversation, state and abort mark, a sleeping task's `until` and a blocked task's reason. The adapter shows a sleeping task with how long it still sleeps (`sleeps 30s`) and a blocked one (`blocked: restart limit`, `blocked: no definition`, …) as a warning. Generation retry backoffs sleep on pi durable 1.4, so a retrying agent's generation task sleeps until its next attempt.
|
|
620
620
|
- **Usage:** `harness.usage()` gives the session's tokens and cost. The cost is pi-ai's, recorded with each response.
|
|
621
621
|
- **Failures, retries and usage changes:** one `subscribeCommits` listener catches them, the way `watchEvents` derives `task_failed`.
|
|
622
|
+
- **Model latency:** the agent passes pi durable a telemetry context (`HarnessOptions.telemetry`, `src/timings.ts`) that keeps only pi-ai's `pi.ai.request` spans: provider, model, stop reason, duration and the time of the `pi.ai.first_chunk` event, the last 50 of them (`agent.timings`). pi's spans are content-free, and nothing else of them is kept. The feed's `latency` has the median duration and median time to the first chunk of the last 20 requests, how many failed, their durations as a series, and the median per model. The adapter shows it as the `Model latency` vital (`1.2 s`, `first chunk 400 ms · 1 failed`, the per-model medians as its hint). Requests outside the Harness, such as titles and the judge, aren't counted.
|
|
622
623
|
- **Reported failures:** pi durable's `onReport` gets what fails without failing the calling operation: a throwing section, hook or listener, a faulted or parked task, a failed migration, a host callback that threw, and the Session's own failure. The agent keeps the last 50 (`agent.reports`) whether or not the panel is open, and the feed adds them to `problems` as `kind: 'report'` with `report: { type, source }` (the extension or host callback, when known). The adapter names a row by its type and source (`sliccy · extension error (slicc-memory)`), shows it as a warning, and as an error with an alert for `session_failed`, `task_faulted`, `task_parked` and `migration_failed`. A faulted task appears once, whether the report or the commit listener sees it first.
|
|
623
624
|
- **Agent state:** each agent's `pi.live`, `pi.inbox` and `pi.agent` come from the views the host already mounts. `inspect()` runs only on a resync.
|
|
624
625
|
|
package/dist/agent.js
CHANGED
|
@@ -10,6 +10,7 @@ import { guestToolGate } from "./guests/guard.js";
|
|
|
10
10
|
import { guestReviews } from "./guests/review.js";
|
|
11
11
|
import { scoopReviews } from "./guests/scoop.js";
|
|
12
12
|
import { createReports } from "./reports.js";
|
|
13
|
+
import { createTimings } from "./timings.js";
|
|
13
14
|
function answerText(content) {
|
|
14
15
|
if (typeof content === "string") return content;
|
|
15
16
|
if (!Array.isArray(content)) return "";
|
|
@@ -25,6 +26,12 @@ async function prompt(root, text, context) {
|
|
|
25
26
|
}
|
|
26
27
|
const SLICC_ATTRIBUTION = { name: "SLICC", url: "https://www.sliccy.com" };
|
|
27
28
|
const IDENTITY = { attribution: SLICC_ATTRIBUTION };
|
|
29
|
+
function clocked(clock) {
|
|
30
|
+
return {
|
|
31
|
+
now: () => clock.now(),
|
|
32
|
+
setTimer: (callback, delayMs) => clock.setTimer(callback, delayMs)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
28
35
|
async function openAgent(options) {
|
|
29
36
|
const context = options.context ?? BACKGROUND_CONTEXT;
|
|
30
37
|
const registry = options.registry ?? createRegistry();
|
|
@@ -36,6 +43,7 @@ async function openAgent(options) {
|
|
|
36
43
|
const scooped = scoopReviews();
|
|
37
44
|
registry.install(scooped.extension);
|
|
38
45
|
const reports = createReports();
|
|
46
|
+
const timings = createTimings();
|
|
39
47
|
const harness = await Harness.open(
|
|
40
48
|
options.storage ?? new MemoryStorage(),
|
|
41
49
|
{
|
|
@@ -44,6 +52,8 @@ async function openAgent(options) {
|
|
|
44
52
|
identity: IDENTITY,
|
|
45
53
|
...options.settings ? { settings: options.settings } : {},
|
|
46
54
|
onReport: (error, info) => reports.record(error, info),
|
|
55
|
+
telemetry: timings.telemetry,
|
|
56
|
+
...options.clock ? clocked(options.clock) : {},
|
|
47
57
|
...options.env ? { env: options.env } : {},
|
|
48
58
|
...options.conversationCreated ? { conversationCreated: options.conversationCreated } : {}
|
|
49
59
|
},
|
|
@@ -62,6 +72,7 @@ async function openAgent(options) {
|
|
|
62
72
|
gate,
|
|
63
73
|
scoopReviews: scooped,
|
|
64
74
|
reports,
|
|
75
|
+
timings,
|
|
65
76
|
cone: () => agents.cone(),
|
|
66
77
|
switchCone: (conversation, switching) => agents.switchCone(conversation, switching),
|
|
67
78
|
onCone: (listener) => agents.onCone(listener),
|
package/dist/agent.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/agent.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { Models } from '@earendil-works/pi-ai/models';\nimport {\n AssistantEntry,\n type Conversation,\n createRegistry,\n type EntryId,\n Harness,\n type HarnessOptions,\n MemoryStorage,\n type ModelRef,\n type Registry,\n type Storage,\n} from '@earendil-works/pi-durable';\nimport { type Agents, openAgents } from './agents.ts';\nimport type { Cones } from './cone.ts';\nimport { type GuestToolGate, guestToolGate } from './guests/guard.ts';\nimport { type GuestReviews, guestReviews } from './guests/review.ts';\nimport { type ScoopReviews, scoopReviews } from './guests/scoop.ts';\nimport { createReports, type Reports } from './reports.ts';\n\nexport interface AgentOptions {\n models: Models;\n model: ModelRef;\n storage?: Storage;\n registry?: Registry;\n settings?: HarnessOptions['settings'];\n env?: HarnessOptions['env'];\n conversationCreated?: HarnessOptions['conversationCreated'];\n context?: Context;\n beforeResume?: (harness: Harness, context: Context) => Promise<unknown>;\n}\n\nexport interface Agent extends Cones {\n readonly harness: Harness;\n readonly root: Conversation;\n readonly agents: Agents;\n readonly reviews: GuestReviews;\n readonly gate: GuestToolGate;\n readonly scoopReviews: ScoopReviews;\n readonly reports: Reports;\n onCone(listener: (conversation: Conversation) => void | Promise<void>): () => void;\n prompt(text: string): Promise<string>;\n close(): Promise<void>;\n}\n\ninterface Block {\n type: string;\n text?: string;\n}\n\nexport function answerText(content: unknown): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return (content as Block[])\n .filter((block) => block.type === 'text')\n .map((block) => block.text ?? '')\n .join('');\n}\n\nasync function prompt(root: Conversation, text: string, context: Context): Promise<string> {\n const submission = await root.submit({ type: 'input', content: text }, context);\n const settled = await submission.wait(context);\n const { answer, reason } = settled as { answer?: EntryId; reason?: string };\n if (answer === undefined) throw new Error(`unanswered: ${reason}`);\n const entry = await root.commit((tx) => tx.entry(AssistantEntry, answer), context);\n return answerText(entry?.model?.[0]?.content);\n}\n\nexport const SLICC_ATTRIBUTION = { name: 'SLICC', url: 'https://www.sliccy.com' };\nconst IDENTITY = { attribution: SLICC_ATTRIBUTION };\nexport async function openAgent(options: AgentOptions): Promise<Agent> {\n const context = options.context ?? BACKGROUND_CONTEXT;\n const registry = options.registry ?? createRegistry();\n let opened: Harness | undefined;\n const gate = guestToolGate(() => opened);\n registry.install(gate.extension);\n const reviews = guestReviews();\n registry.install(reviews.extension);\n const scooped = scoopReviews();\n registry.install(scooped.extension);\n const reports = createReports();\n const harness = await Harness.open(\n options.storage ?? new MemoryStorage(),\n {\n models: options.models,\n registry,\n identity: IDENTITY,\n ...(options.settings ? { settings: options.settings } : {}),\n onReport: (error, info) => reports.record(error, info),\n ...(options.env ? { env: options.env } : {}),\n ...(options.conversationCreated ? { conversationCreated: options.conversationCreated } : {}),\n },\n context\n );\n opened = harness;\n const root = await harness.root(context, { agent: { model: options.model } });\n const agents = await openAgents(harness, root, context);\n await options.beforeResume?.(harness, context);\n harness.resume();\n return {\n harness,\n root,\n agents,\n reviews,\n gate,\n scoopReviews: scooped,\n reports,\n cone: () => agents.cone(),\n switchCone: (conversation, switching) => agents.switchCone(conversation, switching),\n onCone: (listener) => agents.onCone(listener),\n prompt: (text) => prompt(agents.cone(), text, context),\n close: () => harness.close(context),\n };\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,0BAA0B;AAEnC;AAAA,EACE;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,OAIK;AACP,SAAsB,kBAAkB;
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { Models } from '@earendil-works/pi-ai/models';\nimport {\n AssistantEntry,\n type Conversation,\n createRegistry,\n type EntryId,\n Harness,\n type HarnessOptions,\n MemoryStorage,\n type ModelRef,\n type Registry,\n type Storage,\n} from '@earendil-works/pi-durable';\nimport { type Agents, openAgents } from './agents.ts';\nimport type { Clock } from './clock.ts';\nimport type { Cones } from './cone.ts';\nimport { type GuestToolGate, guestToolGate } from './guests/guard.ts';\nimport { type GuestReviews, guestReviews } from './guests/review.ts';\nimport { type ScoopReviews, scoopReviews } from './guests/scoop.ts';\nimport { createReports, type Reports } from './reports.ts';\nimport { createTimings, type Timings } from './timings.ts';\n\nexport interface AgentOptions {\n models: Models;\n model: ModelRef;\n storage?: Storage;\n registry?: Registry;\n settings?: HarnessOptions['settings'];\n env?: HarnessOptions['env'];\n conversationCreated?: HarnessOptions['conversationCreated'];\n context?: Context;\n beforeResume?: (harness: Harness, context: Context) => Promise<unknown>;\n clock?: Clock;\n}\n\nexport interface Agent extends Cones {\n readonly harness: Harness;\n readonly root: Conversation;\n readonly agents: Agents;\n readonly reviews: GuestReviews;\n readonly gate: GuestToolGate;\n readonly scoopReviews: ScoopReviews;\n readonly reports: Reports;\n readonly timings: Timings;\n onCone(listener: (conversation: Conversation) => void | Promise<void>): () => void;\n prompt(text: string): Promise<string>;\n close(): Promise<void>;\n}\n\ninterface Block {\n type: string;\n text?: string;\n}\n\nexport function answerText(content: unknown): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return (content as Block[])\n .filter((block) => block.type === 'text')\n .map((block) => block.text ?? '')\n .join('');\n}\n\nasync function prompt(root: Conversation, text: string, context: Context): Promise<string> {\n const submission = await root.submit({ type: 'input', content: text }, context);\n const settled = await submission.wait(context);\n const { answer, reason } = settled as { answer?: EntryId; reason?: string };\n if (answer === undefined) throw new Error(`unanswered: ${reason}`);\n const entry = await root.commit((tx) => tx.entry(AssistantEntry, answer), context);\n return answerText(entry?.model?.[0]?.content);\n}\n\nexport const SLICC_ATTRIBUTION = { name: 'SLICC', url: 'https://www.sliccy.com' };\nconst IDENTITY = { attribution: SLICC_ATTRIBUTION };\nfunction clocked(clock: Clock): Pick<HarnessOptions, 'now' | 'setTimer'> {\n return {\n now: () => clock.now(),\n setTimer: (callback, delayMs) => clock.setTimer(callback, delayMs),\n };\n}\n\nexport async function openAgent(options: AgentOptions): Promise<Agent> {\n const context = options.context ?? BACKGROUND_CONTEXT;\n const registry = options.registry ?? createRegistry();\n let opened: Harness | undefined;\n const gate = guestToolGate(() => opened);\n registry.install(gate.extension);\n const reviews = guestReviews();\n registry.install(reviews.extension);\n const scooped = scoopReviews();\n registry.install(scooped.extension);\n const reports = createReports();\n const timings = createTimings();\n const harness = await Harness.open(\n options.storage ?? new MemoryStorage(),\n {\n models: options.models,\n registry,\n identity: IDENTITY,\n ...(options.settings ? { settings: options.settings } : {}),\n onReport: (error, info) => reports.record(error, info),\n telemetry: timings.telemetry,\n ...(options.clock ? clocked(options.clock) : {}),\n ...(options.env ? { env: options.env } : {}),\n ...(options.conversationCreated ? { conversationCreated: options.conversationCreated } : {}),\n },\n context\n );\n opened = harness;\n const root = await harness.root(context, { agent: { model: options.model } });\n const agents = await openAgents(harness, root, context);\n await options.beforeResume?.(harness, context);\n harness.resume();\n return {\n harness,\n root,\n agents,\n reviews,\n gate,\n scoopReviews: scooped,\n reports,\n timings,\n cone: () => agents.cone(),\n switchCone: (conversation, switching) => agents.switchCone(conversation, switching),\n onCone: (listener) => agents.onCone(listener),\n prompt: (text) => prompt(agents.cone(), text, context),\n close: () => harness.close(context),\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/approvals/index.js
CHANGED
|
@@ -106,10 +106,15 @@ function settledIn(state, id, using) {
|
|
|
106
106
|
off = state.subscribe((items) => check(items));
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
|
+
const systemTimer = (callback, delayMs) => {
|
|
110
|
+
const timer = setTimeout(callback, delayMs);
|
|
111
|
+
return () => clearTimeout(timer);
|
|
112
|
+
};
|
|
109
113
|
async function attachApprovals(options, context = BACKGROUND_CONTEXT) {
|
|
110
114
|
const { harness } = options;
|
|
111
115
|
const now = options.now ?? Date.now;
|
|
112
116
|
const ttl = options.ttlMs ?? APPROVAL_MS;
|
|
117
|
+
const setTimer = options.setTimer ?? systemTimer;
|
|
113
118
|
const timers = /* @__PURE__ */ new Map();
|
|
114
119
|
let line = Promise.resolve();
|
|
115
120
|
let closed = false;
|
|
@@ -167,12 +172,12 @@ async function attachApprovals(options, context = BACKGROUND_CONTEXT) {
|
|
|
167
172
|
if (timers.has(item.id) || closed) continue;
|
|
168
173
|
timers.set(
|
|
169
174
|
item.id,
|
|
170
|
-
|
|
175
|
+
setTimer(() => expire(item.id), Math.min(MAX_DELAY, Math.max(0, item.expiresAt - now())))
|
|
171
176
|
);
|
|
172
177
|
}
|
|
173
178
|
for (const [id, timer] of timers)
|
|
174
179
|
if (!pending.has(id)) {
|
|
175
|
-
|
|
180
|
+
timer();
|
|
176
181
|
timers.delete(id);
|
|
177
182
|
}
|
|
178
183
|
}
|
|
@@ -268,7 +273,7 @@ async function attachApprovals(options, context = BACKGROUND_CONTEXT) {
|
|
|
268
273
|
},
|
|
269
274
|
close() {
|
|
270
275
|
closed = true;
|
|
271
|
-
for (const timer of timers.values())
|
|
276
|
+
for (const timer of timers.values()) timer();
|
|
272
277
|
timers.clear();
|
|
273
278
|
}
|
|
274
279
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/approvals/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { type Context, type ReplicatedState, replicatedState } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { DocumentState, Harness } from '@earendil-works/pi-durable';\nimport type { ApprovalJudge, Judgement } from './judge.ts';\nimport {\n APPROVAL_MS,\n type Approval,\n type ApprovalDraft,\n type ApprovalKind,\n type ApprovalState,\n ApprovalsDoc,\n type ApprovalsState,\n cleanReason,\n type DecidedBy,\n guestKind,\n knownTier,\n MAX_DELAY,\n prune,\n REASONS,\n routable,\n ruled,\n type Settle,\n scoopTier,\n sudoApprover,\n tierOf,\n} from './record.ts';\n\nexport * from './intent.ts';\nexport * from './judge.ts';\nexport * from './record.ts';\n\nexport type ApprovalDecided =\n | { done: true; state: ApprovalState; error: null }\n | { done: false; state: null; error: string };\n\nexport type Decider = DecidedBy | { by: DecidedBy; device?: string };\n\nconst deciderOf = (decider: Decider) => (typeof decider === 'string' ? { by: decider } : decider);\n\nexport interface Approvals {\n readonly state: ReplicatedState<Approval[]>;\n request(draft: ApprovalDraft & { id?: string }, context: Context): Promise<Approval>;\n decide(\n id: string,\n answer: unknown,\n reason: string | null,\n by: Decider,\n context: Context\n ): Promise<ApprovalDecided>;\n settled(id: string, context: Context): Promise<Approval>;\n assign(id: string, reviewer: string, context: Context): Promise<Approval | undefined>;\n withdraw(id: string, reason: string | null, context: Context): Promise<Approval | undefined>;\n withdrawSeat(seat: string, context: Context): Promise<number>;\n expire(id: string, context: Context): Promise<Approval | undefined>;\n close(): void;\n}\n\nexport interface ScoopRouter {\n route(item: Approval): Promise<void>;\n}\n\nexport interface ApprovalsAttach {\n harness: Pick<Harness, 'commit' | 'documentState'>;\n now?: () => number;\n ttlMs?: number;\n judge?: ApprovalJudge;\n scoops?: ScoopRouter;\n guestAlways?: (kind: ApprovalKind) => boolean;\n sudoApprover?: () => unknown;\n}\n\nconst copy = (items: readonly Approval[]): Approval[] => JSON.parse(JSON.stringify(items));\n\nfunction mark(item: Approval, how: Settle, at: number) {\n item.state = how.state;\n item.decidedBy = how.by;\n item.decidedAt = at;\n if (how.reason) item.reason = how.reason;\n}\n\nconst offered = (options: ApprovalsAttach, draft: ApprovalDraft): boolean =>\n guestKind(draft.kind) ? options.guestAlways?.(draft.kind) === true : draft.always === true;\n\nfunction fresh(\n draft: ApprovalDraft & { id?: string },\n at: number,\n ttl: number,\n options: ApprovalsAttach\n): Approval {\n const item = {\n ...draft,\n tier: tierOf(draft.kind, draft.tier, sudoApprover(options.sudoApprover?.())),\n id: draft.id ?? `apr-${crypto.randomUUID()}`,\n state: 'pending',\n decidedBy: null,\n always: offered(options, draft),\n createdAt: at,\n expiresAt: draft.expiresAt ?? at + ttl,\n } as Approval;\n if (!knownTier(item.tier))\n mark(item, { state: 'unanswered', by: 'host', reason: REASONS.unknownTier }, at);\n else if (!routable(draft.kind, item.tier))\n mark(item, { state: 'unanswered', by: 'host', reason: REASONS.unroutable }, at);\n return item;\n}\n\nconst withdrawIn =\n (match: (item: Approval) => boolean, reason: string | undefined, now: () => number) =>\n (doc: ApprovalsState) => {\n const hit = doc.items.filter((item) => item.state === 'pending' && match(item));\n for (const item of hit)\n mark(item, { state: 'withdrawn', by: 'host', ...(reason ? { reason } : {}) }, now());\n return hit.map((item) => copy([item])[0] as Approval);\n };\n\nconst judgedIn = (id: string, judgement: Judgement, now: () => number) => (doc: ApprovalsState) => {\n const item = doc.items.find((entry) => entry.id === id);\n if (item?.tier !== 'agent') return undefined;\n const late = item.state === 'unanswered' && item.reason === REASONS.timeout && !item.verdict;\n if (item.state !== 'pending' && !(late && judgement.verdict)) return undefined;\n if (judgement.verdict) item.verdict = judgement.verdict;\n if (late) return copy([item])[0] as Approval;\n if (judgement.outcome === 'ask') item.tier = 'user';\n else {\n const at = now();\n const ruling = ruled(\n item,\n judgement.outcome === 'approve' ? 'once' : 'deny',\n null,\n 'judge',\n at\n );\n if (ruling.answer) item.answer = ruling.answer;\n if (ruling.settle) mark(item, ruling.settle, at);\n }\n return copy([item])[0] as Approval;\n};\n\nfunction following(\n committed: DocumentState<ApprovalsState>,\n changed: (using: Context, items: Approval[]) => void\n) {\n const items = () => (committed.value as ApprovalsState).items;\n let shown = items();\n return (using: Context) => {\n const now = items();\n if (now === shown) return;\n shown = now;\n changed(using, copy(now));\n };\n}\n\nfunction settledIn(\n state: ReplicatedState<Approval[]>,\n id: string,\n using: Context\n): Promise<Approval> {\n return new Promise((resolve, reject) => {\n const signal = using.abortSignal;\n let done = false;\n let off: (() => void) | undefined;\n const finish = (end: () => void) => {\n done = true;\n off?.();\n signal?.removeEventListener('abort', abort);\n end();\n };\n const abort = () => finish(() => reject(signal?.reason));\n const check = (items: readonly Approval[] | undefined) => {\n const item = items?.find((entry) => entry.id === id);\n if (!item) finish(() => reject(new Error(`There is no approval ${id}.`)));\n else if (item.state !== 'pending') finish(() => resolve(item));\n };\n if (signal?.aborted) return abort();\n check(state.value);\n if (done) return;\n signal?.addEventListener('abort', abort, { once: true });\n off = state.subscribe((items) => check(items));\n });\n}\n\nexport async function attachApprovals(\n options: ApprovalsAttach,\n context: Context = BACKGROUND_CONTEXT\n): Promise<Approvals> {\n const { harness } = options;\n const now = options.now ?? Date.now;\n const ttl = options.ttlMs ?? APPROVAL_MS;\n const timers = new Map<string, ReturnType<typeof setTimeout>>();\n let line: Promise<unknown> = Promise.resolve();\n let closed = false;\n const settle = (item: Approval, how: Settle) => mark(item, how, now());\n const write = <R>(\n change: (doc: ApprovalsState) => R,\n using: Context\n ): Promise<{ result: R; items: Approval[] }> =>\n harness.commit(async (tx) => {\n const doc = await tx.doc(ApprovalsDoc);\n const result = change(doc);\n doc.items = prune(doc.items);\n return { result, items: copy(doc.items) };\n }, using);\n const startup = await write((doc) => {\n for (const item of doc.items) {\n if (item.state !== 'pending') continue;\n if (item.kind === 'sudo')\n settle(item, { state: 'withdrawn', by: 'host', reason: REASONS.restart });\n else if (item.expiresAt <= now())\n settle(item, { state: 'unanswered', by: 'host', reason: REASONS.timeout });\n else if (options.judge && item.tier === 'agent') item.tier = 'user';\n }\n }, context);\n const state = replicatedState<Approval[]>(startup.items);\n const committed = (await harness.documentState(\n ApprovalsDoc,\n context\n )) as DocumentState<ApprovalsState>;\n const follow = following(committed, (using, items) => {\n state.replace(using, items);\n arm(items);\n });\n committed.subscribe((_value, using) => follow(using));\n const serial = <R>(change: (doc: ApprovalsState) => R, using: Context): Promise<R> => {\n const run = line.then(async () => {\n const { result } = await write(change, using);\n follow(using);\n return result;\n });\n line = run.catch(() => undefined);\n return run;\n };\n const expire = (id: string) => {\n timers.delete(id);\n const due = (state.value as Approval[]).find((entry) => entry.id === id);\n if (due?.state === 'pending' && due.expiresAt > now()) return arm(state.value as Approval[]);\n void serial((doc) => {\n const item = doc.items.find((entry) => entry.id === id);\n if (item?.state === 'pending' && item.expiresAt <= now())\n settle(item, { state: 'unanswered', by: 'host', reason: REASONS.timeout });\n }, BACKGROUND_CONTEXT).catch(() => undefined);\n };\n function arm(items: readonly Approval[]) {\n const pending = new Set<string>();\n for (const item of items) {\n if (item.state !== 'pending') continue;\n pending.add(item.id);\n if (timers.has(item.id) || closed) continue;\n timers.set(\n item.id,\n setTimeout(() => expire(item.id), Math.min(MAX_DELAY, Math.max(0, item.expiresAt - now())))\n );\n }\n for (const [id, timer] of timers)\n if (!pending.has(id)) {\n clearTimeout(timer);\n timers.delete(id);\n }\n }\n arm(startup.items);\n const toScoop = (item: Approval) => {\n if (options.scoops && item.state === 'pending' && scoopTier(item.tier))\n void options.scoops.route(item).catch(() => undefined);\n };\n for (const item of startup.items) toScoop(item);\n const withdrawWhere = (match: (item: Approval) => boolean, reason: string | undefined) =>\n withdrawIn(match, reason, now);\n const judging = async (judge: ApprovalJudge, item: Approval, using: Context) => {\n const signal = using.abortSignal;\n let gone = false;\n const abort = () => {\n gone = true;\n void serial(\n withdrawWhere((entry) => entry.id === item.id && entry.tier === 'agent', REASONS.aborted),\n BACKGROUND_CONTEXT\n ).catch(() => undefined);\n };\n if (signal?.aborted) return abort();\n signal?.addEventListener('abort', abort, { once: true });\n const judgement = await judge\n .judge(item, using)\n .catch((error: unknown): Judgement => ({ outcome: 'ask', error: String(error) }));\n signal?.removeEventListener('abort', abort);\n if (gone || closed) return;\n const after = await serial(judgedIn(item.id, judgement, now), BACKGROUND_CONTEXT).catch(\n () => undefined\n );\n if (after) await judge.record?.(after, judgement, BACKGROUND_CONTEXT).catch(() => undefined);\n };\n return {\n state,\n async request(draft, using) {\n let created = true;\n const made = await serial((doc) => {\n const kept = draft.id && doc.items.find((entry) => entry.id === draft.id);\n if (kept) {\n created = false;\n return copy([kept])[0] as Approval;\n }\n const item = fresh(draft, now(), ttl, options);\n doc.items.push(item);\n return copy([item])[0] as Approval;\n }, using);\n if (created && options.judge && made.state === 'pending' && made.tier === 'agent')\n void judging(options.judge, made, using);\n if (created) toScoop(made);\n return made;\n },\n decide(id, answer, reason, decider, using) {\n const { by, device } = deciderOf(decider);\n return serial((doc): ApprovalDecided => {\n const item = doc.items.find((entry) => entry.id === id);\n const ruling = item\n ? ruled(item, answer, reason, by, now())\n : { error: `There is no approval ${id}.` };\n if (item && ruling.settle) {\n if (ruling.answer) item.answer = ruling.answer;\n if (device && ruling.settle.by === by) item.device = device;\n settle(item, ruling.settle);\n }\n if ('error' in ruling && ruling.error)\n return { done: false, state: null, error: ruling.error };\n return { done: true, state: (item as Approval).state, error: null };\n }, using);\n },\n settled: (id, using) => settledIn(state, id, using),\n assign(id, reviewer, using) {\n return serial((doc) => {\n const item = doc.items.find((entry) => entry.id === id);\n if (item?.state === 'pending' && scoopTier(item.tier)) item.reviewer ??= reviewer;\n return item ? (copy([item])[0] as Approval) : undefined;\n }, using);\n },\n async withdraw(id, reason, using) {\n const [hit] = await serial(\n withdrawWhere((item) => item.id === id, cleanReason(reason)),\n using\n );\n return hit;\n },\n async withdrawSeat(seat, using) {\n return (\n await serial(\n withdrawWhere((item) => item.seat === seat, REASONS.revoked),\n using\n )\n ).length;\n },\n async expire(id, using) {\n return serial((doc) => {\n const item = doc.items.find((entry) => entry.id === id);\n if (item?.state === 'pending' && item.expiresAt <= now())\n settle(item, { state: 'unanswered', by: 'host', reason: REASONS.timeout });\n return item ? (copy([item])[0] as Approval) : undefined;\n }, using);\n },\n close() {\n closed = true;\n for (const timer of timers.values()) clearTimeout(timer);\n timers.clear();\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAA6C,uBAAuB;AACpE,SAAS,0BAA0B;
|
|
4
|
+
"sourcesContent": ["import { type Context, type ReplicatedState, replicatedState } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { DocumentState, Harness } from '@earendil-works/pi-durable';\nimport type { Clock } from '../clock.ts';\nimport type { ApprovalJudge, Judgement } from './judge.ts';\nimport {\n APPROVAL_MS,\n type Approval,\n type ApprovalDraft,\n type ApprovalKind,\n type ApprovalState,\n ApprovalsDoc,\n type ApprovalsState,\n cleanReason,\n type DecidedBy,\n guestKind,\n knownTier,\n MAX_DELAY,\n prune,\n REASONS,\n routable,\n ruled,\n type Settle,\n scoopTier,\n sudoApprover,\n tierOf,\n} from './record.ts';\n\nexport * from './intent.ts';\nexport * from './judge.ts';\nexport * from './record.ts';\n\nexport type ApprovalDecided =\n | { done: true; state: ApprovalState; error: null }\n | { done: false; state: null; error: string };\n\nexport type Decider = DecidedBy | { by: DecidedBy; device?: string };\n\nconst deciderOf = (decider: Decider) => (typeof decider === 'string' ? { by: decider } : decider);\n\nexport interface Approvals {\n readonly state: ReplicatedState<Approval[]>;\n request(draft: ApprovalDraft & { id?: string }, context: Context): Promise<Approval>;\n decide(\n id: string,\n answer: unknown,\n reason: string | null,\n by: Decider,\n context: Context\n ): Promise<ApprovalDecided>;\n settled(id: string, context: Context): Promise<Approval>;\n assign(id: string, reviewer: string, context: Context): Promise<Approval | undefined>;\n withdraw(id: string, reason: string | null, context: Context): Promise<Approval | undefined>;\n withdrawSeat(seat: string, context: Context): Promise<number>;\n expire(id: string, context: Context): Promise<Approval | undefined>;\n close(): void;\n}\n\nexport interface ScoopRouter {\n route(item: Approval): Promise<void>;\n}\n\nexport interface ApprovalsAttach {\n harness: Pick<Harness, 'commit' | 'documentState'>;\n now?: () => number;\n setTimer?: Clock['setTimer'];\n ttlMs?: number;\n judge?: ApprovalJudge;\n scoops?: ScoopRouter;\n guestAlways?: (kind: ApprovalKind) => boolean;\n sudoApprover?: () => unknown;\n}\n\nconst copy = (items: readonly Approval[]): Approval[] => JSON.parse(JSON.stringify(items));\n\nfunction mark(item: Approval, how: Settle, at: number) {\n item.state = how.state;\n item.decidedBy = how.by;\n item.decidedAt = at;\n if (how.reason) item.reason = how.reason;\n}\n\nconst offered = (options: ApprovalsAttach, draft: ApprovalDraft): boolean =>\n guestKind(draft.kind) ? options.guestAlways?.(draft.kind) === true : draft.always === true;\n\nfunction fresh(\n draft: ApprovalDraft & { id?: string },\n at: number,\n ttl: number,\n options: ApprovalsAttach\n): Approval {\n const item = {\n ...draft,\n tier: tierOf(draft.kind, draft.tier, sudoApprover(options.sudoApprover?.())),\n id: draft.id ?? `apr-${crypto.randomUUID()}`,\n state: 'pending',\n decidedBy: null,\n always: offered(options, draft),\n createdAt: at,\n expiresAt: draft.expiresAt ?? at + ttl,\n } as Approval;\n if (!knownTier(item.tier))\n mark(item, { state: 'unanswered', by: 'host', reason: REASONS.unknownTier }, at);\n else if (!routable(draft.kind, item.tier))\n mark(item, { state: 'unanswered', by: 'host', reason: REASONS.unroutable }, at);\n return item;\n}\n\nconst withdrawIn =\n (match: (item: Approval) => boolean, reason: string | undefined, now: () => number) =>\n (doc: ApprovalsState) => {\n const hit = doc.items.filter((item) => item.state === 'pending' && match(item));\n for (const item of hit)\n mark(item, { state: 'withdrawn', by: 'host', ...(reason ? { reason } : {}) }, now());\n return hit.map((item) => copy([item])[0] as Approval);\n };\n\nconst judgedIn = (id: string, judgement: Judgement, now: () => number) => (doc: ApprovalsState) => {\n const item = doc.items.find((entry) => entry.id === id);\n if (item?.tier !== 'agent') return undefined;\n const late = item.state === 'unanswered' && item.reason === REASONS.timeout && !item.verdict;\n if (item.state !== 'pending' && !(late && judgement.verdict)) return undefined;\n if (judgement.verdict) item.verdict = judgement.verdict;\n if (late) return copy([item])[0] as Approval;\n if (judgement.outcome === 'ask') item.tier = 'user';\n else {\n const at = now();\n const ruling = ruled(\n item,\n judgement.outcome === 'approve' ? 'once' : 'deny',\n null,\n 'judge',\n at\n );\n if (ruling.answer) item.answer = ruling.answer;\n if (ruling.settle) mark(item, ruling.settle, at);\n }\n return copy([item])[0] as Approval;\n};\n\nfunction following(\n committed: DocumentState<ApprovalsState>,\n changed: (using: Context, items: Approval[]) => void\n) {\n const items = () => (committed.value as ApprovalsState).items;\n let shown = items();\n return (using: Context) => {\n const now = items();\n if (now === shown) return;\n shown = now;\n changed(using, copy(now));\n };\n}\n\nfunction settledIn(\n state: ReplicatedState<Approval[]>,\n id: string,\n using: Context\n): Promise<Approval> {\n return new Promise((resolve, reject) => {\n const signal = using.abortSignal;\n let done = false;\n let off: (() => void) | undefined;\n const finish = (end: () => void) => {\n done = true;\n off?.();\n signal?.removeEventListener('abort', abort);\n end();\n };\n const abort = () => finish(() => reject(signal?.reason));\n const check = (items: readonly Approval[] | undefined) => {\n const item = items?.find((entry) => entry.id === id);\n if (!item) finish(() => reject(new Error(`There is no approval ${id}.`)));\n else if (item.state !== 'pending') finish(() => resolve(item));\n };\n if (signal?.aborted) return abort();\n check(state.value);\n if (done) return;\n signal?.addEventListener('abort', abort, { once: true });\n off = state.subscribe((items) => check(items));\n });\n}\n\nconst systemTimer: Clock['setTimer'] = (callback, delayMs) => {\n const timer = setTimeout(callback, delayMs);\n return () => clearTimeout(timer);\n};\n\nexport async function attachApprovals(\n options: ApprovalsAttach,\n context: Context = BACKGROUND_CONTEXT\n): Promise<Approvals> {\n const { harness } = options;\n const now = options.now ?? Date.now;\n const ttl = options.ttlMs ?? APPROVAL_MS;\n const setTimer = options.setTimer ?? systemTimer;\n const timers = new Map<string, () => void>();\n let line: Promise<unknown> = Promise.resolve();\n let closed = false;\n const settle = (item: Approval, how: Settle) => mark(item, how, now());\n const write = <R>(\n change: (doc: ApprovalsState) => R,\n using: Context\n ): Promise<{ result: R; items: Approval[] }> =>\n harness.commit(async (tx) => {\n const doc = await tx.doc(ApprovalsDoc);\n const result = change(doc);\n doc.items = prune(doc.items);\n return { result, items: copy(doc.items) };\n }, using);\n const startup = await write((doc) => {\n for (const item of doc.items) {\n if (item.state !== 'pending') continue;\n if (item.kind === 'sudo')\n settle(item, { state: 'withdrawn', by: 'host', reason: REASONS.restart });\n else if (item.expiresAt <= now())\n settle(item, { state: 'unanswered', by: 'host', reason: REASONS.timeout });\n else if (options.judge && item.tier === 'agent') item.tier = 'user';\n }\n }, context);\n const state = replicatedState<Approval[]>(startup.items);\n const committed = (await harness.documentState(\n ApprovalsDoc,\n context\n )) as DocumentState<ApprovalsState>;\n const follow = following(committed, (using, items) => {\n state.replace(using, items);\n arm(items);\n });\n committed.subscribe((_value, using) => follow(using));\n const serial = <R>(change: (doc: ApprovalsState) => R, using: Context): Promise<R> => {\n const run = line.then(async () => {\n const { result } = await write(change, using);\n follow(using);\n return result;\n });\n line = run.catch(() => undefined);\n return run;\n };\n const expire = (id: string) => {\n timers.delete(id);\n const due = (state.value as Approval[]).find((entry) => entry.id === id);\n if (due?.state === 'pending' && due.expiresAt > now()) return arm(state.value as Approval[]);\n void serial((doc) => {\n const item = doc.items.find((entry) => entry.id === id);\n if (item?.state === 'pending' && item.expiresAt <= now())\n settle(item, { state: 'unanswered', by: 'host', reason: REASONS.timeout });\n }, BACKGROUND_CONTEXT).catch(() => undefined);\n };\n function arm(items: readonly Approval[]) {\n const pending = new Set<string>();\n for (const item of items) {\n if (item.state !== 'pending') continue;\n pending.add(item.id);\n if (timers.has(item.id) || closed) continue;\n timers.set(\n item.id,\n setTimer(() => expire(item.id), Math.min(MAX_DELAY, Math.max(0, item.expiresAt - now())))\n );\n }\n for (const [id, timer] of timers)\n if (!pending.has(id)) {\n timer();\n timers.delete(id);\n }\n }\n arm(startup.items);\n const toScoop = (item: Approval) => {\n if (options.scoops && item.state === 'pending' && scoopTier(item.tier))\n void options.scoops.route(item).catch(() => undefined);\n };\n for (const item of startup.items) toScoop(item);\n const withdrawWhere = (match: (item: Approval) => boolean, reason: string | undefined) =>\n withdrawIn(match, reason, now);\n const judging = async (judge: ApprovalJudge, item: Approval, using: Context) => {\n const signal = using.abortSignal;\n let gone = false;\n const abort = () => {\n gone = true;\n void serial(\n withdrawWhere((entry) => entry.id === item.id && entry.tier === 'agent', REASONS.aborted),\n BACKGROUND_CONTEXT\n ).catch(() => undefined);\n };\n if (signal?.aborted) return abort();\n signal?.addEventListener('abort', abort, { once: true });\n const judgement = await judge\n .judge(item, using)\n .catch((error: unknown): Judgement => ({ outcome: 'ask', error: String(error) }));\n signal?.removeEventListener('abort', abort);\n if (gone || closed) return;\n const after = await serial(judgedIn(item.id, judgement, now), BACKGROUND_CONTEXT).catch(\n () => undefined\n );\n if (after) await judge.record?.(after, judgement, BACKGROUND_CONTEXT).catch(() => undefined);\n };\n return {\n state,\n async request(draft, using) {\n let created = true;\n const made = await serial((doc) => {\n const kept = draft.id && doc.items.find((entry) => entry.id === draft.id);\n if (kept) {\n created = false;\n return copy([kept])[0] as Approval;\n }\n const item = fresh(draft, now(), ttl, options);\n doc.items.push(item);\n return copy([item])[0] as Approval;\n }, using);\n if (created && options.judge && made.state === 'pending' && made.tier === 'agent')\n void judging(options.judge, made, using);\n if (created) toScoop(made);\n return made;\n },\n decide(id, answer, reason, decider, using) {\n const { by, device } = deciderOf(decider);\n return serial((doc): ApprovalDecided => {\n const item = doc.items.find((entry) => entry.id === id);\n const ruling = item\n ? ruled(item, answer, reason, by, now())\n : { error: `There is no approval ${id}.` };\n if (item && ruling.settle) {\n if (ruling.answer) item.answer = ruling.answer;\n if (device && ruling.settle.by === by) item.device = device;\n settle(item, ruling.settle);\n }\n if ('error' in ruling && ruling.error)\n return { done: false, state: null, error: ruling.error };\n return { done: true, state: (item as Approval).state, error: null };\n }, using);\n },\n settled: (id, using) => settledIn(state, id, using),\n assign(id, reviewer, using) {\n return serial((doc) => {\n const item = doc.items.find((entry) => entry.id === id);\n if (item?.state === 'pending' && scoopTier(item.tier)) item.reviewer ??= reviewer;\n return item ? (copy([item])[0] as Approval) : undefined;\n }, using);\n },\n async withdraw(id, reason, using) {\n const [hit] = await serial(\n withdrawWhere((item) => item.id === id, cleanReason(reason)),\n using\n );\n return hit;\n },\n async withdrawSeat(seat, using) {\n return (\n await serial(\n withdrawWhere((item) => item.seat === seat, REASONS.revoked),\n using\n )\n ).length;\n },\n async expire(id, using) {\n return serial((doc) => {\n const item = doc.items.find((entry) => entry.id === id);\n if (item?.state === 'pending' && item.expiresAt <= now())\n settle(item, { state: 'unanswered', by: 'host', reason: REASONS.timeout });\n return item ? (copy([item])[0] as Approval) : undefined;\n }, using);\n },\n close() {\n closed = true;\n for (const timer of timers.values()) timer();\n timers.clear();\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/clock.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=clock.js.map
|
package/dist/host.js
CHANGED
package/dist/host.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/host.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type Context,\n createHost,\n forbidden,\n type Host,\n type Readable,\n type ReplicatedState,\n replicatedState,\n type Self,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport type { Agent } from './agent.ts';\nimport {\n type ApprovalJudge,\n type Approvals,\n attachApprovals,\n type Decider,\n} from './approvals/index.ts';\nimport { type ApprovalPolicies, alwaysFor, attachApprovalPolicy } from './approvals/policy.ts';\nimport { type AgentSudo, createSudo, ownedSudo } from './approvals/sudo.ts';\nimport type { ChangesView } from './changes/git.ts';\nimport type { ChangesRuntime } from './changes/index.ts';\nimport { createAgentControl, type HostLicks, type HostScoops } from './control.ts';\nimport { trackDeliveries } from './deliveries.ts';\nimport type { FreezerRuntime, FrozenCone } from './freezer/index.ts';\nimport { IDLE, type ImportProgress } from './freezer/v6.ts';\nimport { createGuests, type Guests } from './guests/index.ts';\nimport type { ScoopReviewHost } from './guests/scoop.ts';\nimport { admitGuest, guestOpener } from './guests/serve.ts';\nimport type { UserClients } from './kernel/users.ts';\nimport type { McpRuntime } from './mcp/index.ts';\nimport type { MemoryEntry, MemoryScope } from './memory/format.ts';\nimport type { MemoryRuntime } from './memory/index.ts';\nimport { createMonitor, type MonitorOptions } from './monitor/index.ts';\nimport { viewRemote } from './readonly.ts';\nimport { type AgentRemote, createRemote } from './remote/host.ts';\nimport { createPages, ownedPages, type Pages } from './remote/pages.ts';\nimport type { SecretListing } from './secrets/names.ts';\nimport type { VaultState } from './secrets/vault.ts';\nimport {\n AgentControl,\n type AgentGuest,\n AgentGuestService,\n AgentPagesService,\n AgentRemoteService,\n AgentSettings,\n AgentSudoService,\n AgentTranscript,\n CONTROL_METHODS,\n CONTROL_READS,\n type Command,\n GUEST_METHODS,\n OWNER_DEVICE_METHODS,\n PAGE_METHODS,\n type PrivateRevision,\n REMOTE_METHODS,\n REMOTE_READS,\n SETTINGS_METHODS,\n SUDO_METHODS,\n} from './services.ts';\nimport {\n AGENT_HOST,\n type AgentPrincipal,\n type GuestPrincipal,\n principalKey,\n readable,\n readablesOf,\n SELF,\n type Seat,\n served,\n} from './serving.ts';\nimport type { SkillsRuntime } from './skills/index.ts';\nimport type { SprinklesRuntime } from './sprinkles/index.ts';\nimport type { Sprinkle } from './sprinkles/kind.ts';\nimport { slimmer, type Thumbnail, thumbnail } from './thumbs.ts';\nimport { type LabelsRuntime, visibleLabels, watchLabel } from './titles/labels.ts';\nimport type { Uploads } from './uploads.ts';\nimport { agentViews } from './views.ts';\nimport { type PortEndpoint, PortLink } from './wire.ts';\n\nexport interface ConnectOptions {\n readOnly?: boolean;\n pages?: boolean;\n guest?: { id: string; label: string };\n device?: string;\n}\n\nexport interface AgentHost {\n readonly serverId: string;\n readonly agent: Agent;\n readonly users?: UserClients;\n readonly pages: Pages;\n readonly guests: Guests;\n readonly approvals: Approvals;\n connect(endpoint: PortEndpoint, options?: ConnectOptions): void;\n close(): Promise<void>;\n}\n\nconst noSettings: AgentSettings = {\n state: replicatedState({ models: [], accounts: [] }),\n connect: async () => {\n throw new Error('this agent has no accounts');\n },\n disconnect: async () => {},\n remove: async () => {},\n serverUrl: async () => null,\n signIn: async () => null,\n dismissMoved: async () => {},\n};\n\nasync function follow(\n agent: Agent,\n context: Context,\n slim: (view: ConversationView) => ConversationView\n) {\n let attached = await agent.cone().viewState(context);\n const state = replicatedState<ConversationView>(slim(attached.value));\n const mirror = (value: ConversationView, from: Context) => state.replace(from, slim(value));\n let off = attached.subscribe(mirror);\n const stop = agent.onCone(async (conversation) => {\n const next = await conversation.viewState(context);\n off();\n attached.dispose();\n attached = next;\n state.replace(context, slim(next.value));\n off = next.subscribe(mirror);\n });\n return {\n state,\n refresh: () => state.replace(context, slim(attached.value)),\n dispose() {\n stop();\n off();\n attached.dispose();\n },\n };\n}\n\nexport interface HostSecrets {\n vault: ReplicatedState<VaultState>;\n list(): SecretListing;\n close?(): void;\n}\n\nconst idleVault = replicatedState<VaultState>({\n port: 'none',\n needed: false,\n version: 0,\n locked: 'no',\n held: 0,\n});\n\nfunction gatedControls(\n control: AgentControl,\n shown: (entry: number) => boolean,\n views: () => readonly ConversationView[],\n labels: ReplicatedState<Record<string, string>>\n) {\n const visible = (entry: number) =>\n views().some((view) => view.entries.some((item) => item.id === entry));\n const gated =\n (allowed: (entry: number) => boolean): AgentControl['image'] =>\n async (ref, using) =>\n allowed(ref.entry) ? control.image(ref, using) : { data: null, mimeType: null };\n const trusted: AgentControl = { ...control, image: gated(shown) };\n const viewed: AgentControl = { ...control, image: gated(visible), toolLabel: watchLabel(labels) };\n return { trusted, viewed };\n}\n\nasync function approving(\n agent: Agent,\n policy: ApprovalPolicies,\n options: { judge?: ApprovalJudge; intent?: ScoopReviewHost['intent']; approvalMs?: number },\n context: Context\n): Promise<Approvals> {\n const approvals = await attachApprovals(\n {\n harness: agent.harness,\n guestAlways: alwaysFor(policy),\n sudoApprover: () => policy.current().sudo.approver,\n scoops: agent.scoopReviews,\n ...(options.judge ? { judge: options.judge } : {}),\n ...(options.approvalMs ? { ttlMs: options.approvalMs } : {}),\n },\n context\n );\n agent.scoopReviews.bind({\n approvals,\n agents: agent.agents,\n harness: agent.harness,\n ...(options.intent ? { intent: options.intent } : {}),\n });\n return approvals;\n}\n\nasync function guestsOf(\n agent: Agent,\n approvals: Approvals,\n policy: ApprovalPolicies,\n context: Context\n): Promise<Guests> {\n const guests = await createGuests({\n harness: agent.harness,\n agents: agent.agents,\n approvals,\n policy,\n reviews: agent.reviews,\n context,\n });\n agent.gate.bind({ approvals, policy: () => guests.policy() });\n return guests;\n}\n\nconst noRevision = () => replicatedState<PrivateRevision>({ revision: 0 });\n\nexport async function hostAgent(\n agent: Agent,\n options: {\n serverId?: string;\n context?: Context;\n settings?: AgentSettings;\n licks?: HostLicks;\n scoops?: HostScoops;\n skills?: SkillsRuntime;\n sprinkles?: SprinklesRuntime;\n memory?: MemoryRuntime;\n freezer?: FreezerRuntime;\n changes?: ChangesRuntime;\n mcp?: Pick<McpRuntime, 'close'>;\n users?: UserClients;\n monitor?: Pick<MonitorOptions, 'kernel' | 'groups' | 'users'>;\n pages?: Pages;\n secrets?: HostSecrets;\n uploads?: Uploads;\n thumbnail?: Thumbnail;\n labels?: LabelsRuntime;\n approvals?: Approvals;\n judge?: ApprovalJudge;\n intent?: ScoopReviewHost['intent'];\n approvalMs?: number;\n } = {}\n): Promise<AgentHost> {\n const context = options.context ?? BACKGROUND_CONTEXT;\n const serverId = options.serverId ?? crypto.randomUUID();\n let refresh = () => {};\n const slims = slimmer(options.thumbnail ?? thumbnail, () => refresh());\n const transcript = await follow(agent, context, slims.slim);\n const { state } = transcript;\n const mounted = await agentViews(agent, context, slims.slim);\n refresh = () => {\n transcript.refresh();\n mounted.refresh();\n };\n const touch = () => options.freezer?.touch();\n const untouch = [state.subscribe(touch), mounted.views.subscribe(touch)];\n const pages = options.pages ?? createPages();\n const deliveries = trackDeliveries(agent.harness, state, context);\n const policy = await attachApprovalPolicy(agent.harness, context);\n const approvals = options.approvals ?? (await approving(agent, policy, options, context));\n const monitor = createMonitor({\n ...options.monitor,\n harness: agent.harness,\n agents: agent.agents,\n views: mounted.views,\n reports: agent.reports,\n context,\n });\n const guests = await guestsOf(agent, approvals, policy, context);\n const control: AgentControl = {\n ...createAgentControl(\n agent.harness,\n agent,\n deliveries,\n options.licks,\n options.scoops,\n options.skills,\n options.sprinkles,\n options.memory,\n options.freezer,\n options.changes,\n monitor,\n options.secrets?.list,\n options.uploads,\n options.labels,\n guests\n ),\n approvalPolicySet: (change, using) => policy.set(change, using),\n };\n const remote = createRemote({\n harness: agent.harness,\n send: (request, using) => control.send(request, using),\n vault: options.secrets?.vault ?? idleVault,\n async conversation(agentId, using) {\n if (!agentId) return agent.cone();\n const found = await agent.agents.conversation(agentId, using);\n if (!found) throw new Error(`There is no agent ${agentId}.`);\n return found;\n },\n });\n const shownViews = () => [state.value, ...Object.values(mounted.views.value)];\n const kept = options.labels?.labels ?? replicatedState<Record<string, string>>({});\n const labels = visibleLabels(kept, [state, mounted.views], shownViews);\n const transcriptService = {\n state,\n deliveries: deliveries.state,\n agents: mounted.agents,\n views: mounted.views,\n commands: options.skills?.commands ?? replicatedState<Command[]>([]),\n privateRevision: options.skills?.privateRevision ?? noRevision(),\n sprinkles: options.sprinkles?.sprinkles ?? replicatedState<Sprinkle[]>([]),\n memories: options.memory?.memories ?? replicatedState<MemoryEntry[]>([]),\n memoryScopes: options.memory?.scopes ?? replicatedState<MemoryScope[]>([]),\n frozen: options.freezer?.frozen ?? replicatedState<FrozenCone[]>([]),\n importing: options.freezer?.importing ?? replicatedState<ImportProgress>(IDLE),\n changes:\n options.changes?.view ?? replicatedState<ChangesView>({ unavailable: null, changes: [] }),\n monitor: monitor.state,\n vault: options.secrets?.vault ?? idleVault,\n labels: labels.state,\n guests: guests.seats,\n approvals: approvals.state,\n approvalPolicy: policy.state,\n };\n const sudo = createSudo({\n approvals,\n agents: () => agent.agents.state(),\n ...(options.licks ? { licks: options.licks.licks } : {}),\n });\n const settings = options.settings ?? noSettings;\n const gates = gatedControls(control, slims.shown, shownViews, transcriptService.labels);\n const { trusted, viewed } = gates;\n const host = serveAgent({\n trusted,\n viewed,\n transcript: transcriptService,\n viewMonitor: monitor.viewState,\n sudo,\n settings,\n remote,\n pages,\n guest: guestOpener(guests, agent.agents, mounted.views, context),\n decide: (by) => (id, decision, reason, using) =>\n approvals.decide(id, decision, reason, by, using),\n });\n const offGuests = guests.onEnd((id) => {\n void host.invalidatePrincipal(\n (principal) => principal.seat === 'guest' && principal.guest.id === id\n );\n });\n let links = 0;\n return {\n serverId,\n agent,\n pages,\n guests,\n approvals,\n ...(options.users ? { users: options.users } : {}),\n connect(endpoint, connectOptions) {\n if (connectOptions?.guest) {\n links += 1;\n admitGuest(guests, endpoint, connectOptions.guest, serverId, links, host);\n return;\n }\n const seat: Exclude<Seat, 'guest'> = connectOptions?.readOnly\n ? 'view'\n : connectOptions?.pages === false\n ? 'control'\n : 'owner';\n links += 1;\n const link = new PortLink(endpoint);\n link.greet(serverId);\n const device = connectOptions?.device ? { device: connectOptions.device } : {};\n host.accept(link, {\n principal: { seat, link: links, ...device } satisfies AgentPrincipal,\n });\n },\n async close() {\n offGuests();\n await host.close();\n guests.dispose();\n await pages.dispose();\n await monitor.dispose();\n await remote.dispose();\n deliveries.dispose();\n sudo.close();\n approvals.close();\n transcript.dispose();\n mounted.dispose();\n labels.dispose();\n slims.dispose();\n for (const off of untouch) off();\n options.freezer?.close();\n options.secrets?.close?.();\n await options.changes?.close(context);\n await options.memory?.close(context);\n await options.sprinkles?.close(context);\n await options.skills?.close(context);\n await options.mcp?.close(context);\n await options.scoops?.runtime.close(context);\n await options.licks?.sources.close(context);\n await agent.close();\n await options.users?.close();\n },\n };\n}\n\ninterface Served {\n trusted: AgentControl;\n viewed: AgentControl;\n transcript: Record<keyof AgentTranscript, ReplicatedState<unknown>>;\n viewMonitor: ReplicatedState<unknown>;\n sudo?: AgentSudo;\n settings: AgentSettings;\n remote: AgentRemote;\n pages: Pages;\n guest?: (principal: GuestPrincipal) => { value: AgentGuest; dispose(): void } | undefined;\n decide: (by: Decider) => AgentControl['decide'];\n}\n\nexport const CLOSED_TO_GUESTS = 'a guest seat has only its transcript and propose';\n\nconst opened = new WeakSet<object>();\n\nexport const openToGuests = <F extends object>(factory: F): F => {\n opened.add(factory);\n return factory;\n};\n\nexport function closedToGuests(host: Host<AgentPrincipal>): Host<AgentPrincipal> {\n const serve = ((type: never, factory: (...args: unknown[]) => unknown, options?: never) =>\n host.serve(\n type,\n (opened.has(factory)\n ? factory\n : (input: unknown, principal: AgentPrincipal, self: unknown) => {\n if (principal.seat === 'guest') throw forbidden(CLOSED_TO_GUESTS);\n return factory(input, principal, self);\n }) as never,\n options\n )) as Host<AgentPrincipal>['serve'];\n return new Proxy(host, {\n get(target, key) {\n if (key === 'serve') return serve;\n const value = Reflect.get(target, key, target) as unknown;\n return typeof value === 'function' ? value.bind(target) : value;\n },\n });\n}\n\nexport function lazily<T>(state: () => ReplicatedState<T>): Readable<T> {\n return {\n get value() {\n return readable(state()).value;\n },\n subscribe: (listener) => readable(state()).subscribe(listener),\n events: (listener) => readable(state()).events(listener),\n };\n}\n\nconst seated = (serving: Served, principal: AgentPrincipal): AgentControl => ({\n ...(principal.seat === 'view' ? serving.viewed : serving.trusted),\n decide: serving.decide({\n by: principal.seat === 'owner' ? 'owner' : 'follower',\n ...('device' in principal && principal.device ? { device: principal.device } : {}),\n }),\n});\n\nconst VIEW_METHODS = [...CONTROL_READS, ...OWNER_DEVICE_METHODS];\n\nexport function serveAgent(serving: Served): Host<AgentPrincipal> {\n const host = closedToGuests(\n createHost<AgentPrincipal>({ name: AGENT_HOST, self: SELF, principalKey })\n );\n const viewing = { ...serving.transcript, monitor: serving.viewMonitor };\n host.serve(AgentControl, (_input, principal) => {\n const control = seated(serving, principal);\n return principal.seat === 'view'\n ? { variant: 'view', ...served(() => control, VIEW_METHODS) }\n : { variant: 'control', ...served(() => control, CONTROL_METHODS) };\n });\n host.serve(AgentTranscript, (_input, principal) => ({\n variant: 'transcript',\n ...readablesOf(principal.seat === 'view' ? viewing : serving.transcript),\n }));\n host.serve(AgentSettings, (_input, principal) =>\n principal.seat === 'view'\n ? { variant: 'view', state: readable(serving.settings.state) }\n : {\n variant: 'settings',\n state: readable(serving.settings.state),\n ...served(() => serving.settings, SETTINGS_METHODS),\n }\n );\n host.serve(AgentRemoteService, (_input, principal) => {\n if (principal.seat !== 'view')\n return { variant: 'remote', ...served(() => serving.remote, REMOTE_METHODS) };\n const scoped = viewRemote(serving.remote);\n return { variant: 'watch', ...served(() => scoped, REMOTE_READS) };\n });\n host.serve(AgentPagesService, (_input, principal, self) => {\n if (principal.seat !== 'owner') return { variant: 'none' };\n const mine = self.resource('mine', {\n version: 1,\n open: () => ownedPages(serving.pages),\n close: (owned) => owned.release(),\n });\n return { variant: 'pages', ...served(() => mine.value, PAGE_METHODS) };\n });\n host.serve(\n AgentGuestService,\n openToGuests((_input: unknown, principal: AgentPrincipal, self: Self<AgentPrincipal>) => {\n if (principal.seat !== 'guest') return { variant: 'none' };\n const opening = serving.guest?.(principal.guest);\n if (!opening) throw forbidden(CLOSED_TO_GUESTS);\n const seat = self.resource('seat', {\n version: 1,\n open: () => opening,\n close: (made) => made.dispose(),\n });\n const later = (name: 'transcript' | 'seat' | 'proposals') =>\n lazily(() => seat.value.value[name] as ReplicatedState<unknown>);\n return {\n variant: 'guest',\n transcript: later('transcript'),\n seat: later('seat'),\n proposals: later('proposals'),\n ...served(() => seat.value.value, GUEST_METHODS),\n };\n })\n );\n host.serve(AgentSudoService, (_input, principal, self) => {\n const sudo = serving.sudo;\n if (principal.seat !== 'owner' || !sudo) return { variant: 'none' };\n const mine = self.resource('mine', {\n version: 1,\n open: () => ownedSudo(sudo),\n close: (owned) => owned.release(),\n });\n return {\n variant: 'sudo',\n approvals: readable(sudo.approvals),\n ...served(() => mine.value, SUDO_METHODS),\n };\n });\n return host;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import {\n type Context,\n createHost,\n forbidden,\n type Host,\n type Readable,\n type ReplicatedState,\n replicatedState,\n type Self,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport type { Agent } from './agent.ts';\nimport {\n type ApprovalJudge,\n type Approvals,\n attachApprovals,\n type Decider,\n} from './approvals/index.ts';\nimport { type ApprovalPolicies, alwaysFor, attachApprovalPolicy } from './approvals/policy.ts';\nimport { type AgentSudo, createSudo, ownedSudo } from './approvals/sudo.ts';\nimport type { ChangesView } from './changes/git.ts';\nimport type { ChangesRuntime } from './changes/index.ts';\nimport { createAgentControl, type HostLicks, type HostScoops } from './control.ts';\nimport { trackDeliveries } from './deliveries.ts';\nimport type { FreezerRuntime, FrozenCone } from './freezer/index.ts';\nimport { IDLE, type ImportProgress } from './freezer/v6.ts';\nimport { createGuests, type Guests } from './guests/index.ts';\nimport type { ScoopReviewHost } from './guests/scoop.ts';\nimport { admitGuest, guestOpener } from './guests/serve.ts';\nimport type { UserClients } from './kernel/users.ts';\nimport type { McpRuntime } from './mcp/index.ts';\nimport type { MemoryEntry, MemoryScope } from './memory/format.ts';\nimport type { MemoryRuntime } from './memory/index.ts';\nimport { createMonitor, type MonitorOptions } from './monitor/index.ts';\nimport { viewRemote } from './readonly.ts';\nimport { type AgentRemote, createRemote } from './remote/host.ts';\nimport { createPages, ownedPages, type Pages } from './remote/pages.ts';\nimport type { SecretListing } from './secrets/names.ts';\nimport type { VaultState } from './secrets/vault.ts';\nimport {\n AgentControl,\n type AgentGuest,\n AgentGuestService,\n AgentPagesService,\n AgentRemoteService,\n AgentSettings,\n AgentSudoService,\n AgentTranscript,\n CONTROL_METHODS,\n CONTROL_READS,\n type Command,\n GUEST_METHODS,\n OWNER_DEVICE_METHODS,\n PAGE_METHODS,\n type PrivateRevision,\n REMOTE_METHODS,\n REMOTE_READS,\n SETTINGS_METHODS,\n SUDO_METHODS,\n} from './services.ts';\nimport {\n AGENT_HOST,\n type AgentPrincipal,\n type GuestPrincipal,\n principalKey,\n readable,\n readablesOf,\n SELF,\n type Seat,\n served,\n} from './serving.ts';\nimport type { SkillsRuntime } from './skills/index.ts';\nimport type { SprinklesRuntime } from './sprinkles/index.ts';\nimport type { Sprinkle } from './sprinkles/kind.ts';\nimport { slimmer, type Thumbnail, thumbnail } from './thumbs.ts';\nimport { type LabelsRuntime, visibleLabels, watchLabel } from './titles/labels.ts';\nimport type { Uploads } from './uploads.ts';\nimport { agentViews } from './views.ts';\nimport { type PortEndpoint, PortLink } from './wire.ts';\n\nexport interface ConnectOptions {\n readOnly?: boolean;\n pages?: boolean;\n guest?: { id: string; label: string };\n device?: string;\n}\n\nexport interface AgentHost {\n readonly serverId: string;\n readonly agent: Agent;\n readonly users?: UserClients;\n readonly pages: Pages;\n readonly guests: Guests;\n readonly approvals: Approvals;\n connect(endpoint: PortEndpoint, options?: ConnectOptions): void;\n close(): Promise<void>;\n}\n\nconst noSettings: AgentSettings = {\n state: replicatedState({ models: [], accounts: [] }),\n connect: async () => {\n throw new Error('this agent has no accounts');\n },\n disconnect: async () => {},\n remove: async () => {},\n serverUrl: async () => null,\n signIn: async () => null,\n dismissMoved: async () => {},\n};\n\nasync function follow(\n agent: Agent,\n context: Context,\n slim: (view: ConversationView) => ConversationView\n) {\n let attached = await agent.cone().viewState(context);\n const state = replicatedState<ConversationView>(slim(attached.value));\n const mirror = (value: ConversationView, from: Context) => state.replace(from, slim(value));\n let off = attached.subscribe(mirror);\n const stop = agent.onCone(async (conversation) => {\n const next = await conversation.viewState(context);\n off();\n attached.dispose();\n attached = next;\n state.replace(context, slim(next.value));\n off = next.subscribe(mirror);\n });\n return {\n state,\n refresh: () => state.replace(context, slim(attached.value)),\n dispose() {\n stop();\n off();\n attached.dispose();\n },\n };\n}\n\nexport interface HostSecrets {\n vault: ReplicatedState<VaultState>;\n list(): SecretListing;\n close?(): void;\n}\n\nconst idleVault = replicatedState<VaultState>({\n port: 'none',\n needed: false,\n version: 0,\n locked: 'no',\n held: 0,\n});\n\nfunction gatedControls(\n control: AgentControl,\n shown: (entry: number) => boolean,\n views: () => readonly ConversationView[],\n labels: ReplicatedState<Record<string, string>>\n) {\n const visible = (entry: number) =>\n views().some((view) => view.entries.some((item) => item.id === entry));\n const gated =\n (allowed: (entry: number) => boolean): AgentControl['image'] =>\n async (ref, using) =>\n allowed(ref.entry) ? control.image(ref, using) : { data: null, mimeType: null };\n const trusted: AgentControl = { ...control, image: gated(shown) };\n const viewed: AgentControl = { ...control, image: gated(visible), toolLabel: watchLabel(labels) };\n return { trusted, viewed };\n}\n\nasync function approving(\n agent: Agent,\n policy: ApprovalPolicies,\n options: { judge?: ApprovalJudge; intent?: ScoopReviewHost['intent']; approvalMs?: number },\n context: Context\n): Promise<Approvals> {\n const approvals = await attachApprovals(\n {\n harness: agent.harness,\n guestAlways: alwaysFor(policy),\n sudoApprover: () => policy.current().sudo.approver,\n scoops: agent.scoopReviews,\n ...(options.judge ? { judge: options.judge } : {}),\n ...(options.approvalMs ? { ttlMs: options.approvalMs } : {}),\n },\n context\n );\n agent.scoopReviews.bind({\n approvals,\n agents: agent.agents,\n harness: agent.harness,\n ...(options.intent ? { intent: options.intent } : {}),\n });\n return approvals;\n}\n\nasync function guestsOf(\n agent: Agent,\n approvals: Approvals,\n policy: ApprovalPolicies,\n context: Context\n): Promise<Guests> {\n const guests = await createGuests({\n harness: agent.harness,\n agents: agent.agents,\n approvals,\n policy,\n reviews: agent.reviews,\n context,\n });\n agent.gate.bind({ approvals, policy: () => guests.policy() });\n return guests;\n}\n\nconst noRevision = () => replicatedState<PrivateRevision>({ revision: 0 });\n\nexport async function hostAgent(\n agent: Agent,\n options: {\n serverId?: string;\n context?: Context;\n settings?: AgentSettings;\n licks?: HostLicks;\n scoops?: HostScoops;\n skills?: SkillsRuntime;\n sprinkles?: SprinklesRuntime;\n memory?: MemoryRuntime;\n freezer?: FreezerRuntime;\n changes?: ChangesRuntime;\n mcp?: Pick<McpRuntime, 'close'>;\n users?: UserClients;\n monitor?: Pick<MonitorOptions, 'kernel' | 'groups' | 'users'>;\n pages?: Pages;\n secrets?: HostSecrets;\n uploads?: Uploads;\n thumbnail?: Thumbnail;\n labels?: LabelsRuntime;\n approvals?: Approvals;\n judge?: ApprovalJudge;\n intent?: ScoopReviewHost['intent'];\n approvalMs?: number;\n } = {}\n): Promise<AgentHost> {\n const context = options.context ?? BACKGROUND_CONTEXT;\n const serverId = options.serverId ?? crypto.randomUUID();\n let refresh = () => {};\n const slims = slimmer(options.thumbnail ?? thumbnail, () => refresh());\n const transcript = await follow(agent, context, slims.slim);\n const { state } = transcript;\n const mounted = await agentViews(agent, context, slims.slim);\n refresh = () => {\n transcript.refresh();\n mounted.refresh();\n };\n const touch = () => options.freezer?.touch();\n const untouch = [state.subscribe(touch), mounted.views.subscribe(touch)];\n const pages = options.pages ?? createPages();\n const deliveries = trackDeliveries(agent.harness, state, context);\n const policy = await attachApprovalPolicy(agent.harness, context);\n const approvals = options.approvals ?? (await approving(agent, policy, options, context));\n const monitor = createMonitor({\n ...options.monitor,\n harness: agent.harness,\n agents: agent.agents,\n views: mounted.views,\n reports: agent.reports,\n timings: agent.timings,\n context,\n });\n const guests = await guestsOf(agent, approvals, policy, context);\n const control: AgentControl = {\n ...createAgentControl(\n agent.harness,\n agent,\n deliveries,\n options.licks,\n options.scoops,\n options.skills,\n options.sprinkles,\n options.memory,\n options.freezer,\n options.changes,\n monitor,\n options.secrets?.list,\n options.uploads,\n options.labels,\n guests\n ),\n approvalPolicySet: (change, using) => policy.set(change, using),\n };\n const remote = createRemote({\n harness: agent.harness,\n send: (request, using) => control.send(request, using),\n vault: options.secrets?.vault ?? idleVault,\n async conversation(agentId, using) {\n if (!agentId) return agent.cone();\n const found = await agent.agents.conversation(agentId, using);\n if (!found) throw new Error(`There is no agent ${agentId}.`);\n return found;\n },\n });\n const shownViews = () => [state.value, ...Object.values(mounted.views.value)];\n const kept = options.labels?.labels ?? replicatedState<Record<string, string>>({});\n const labels = visibleLabels(kept, [state, mounted.views], shownViews);\n const transcriptService = {\n state,\n deliveries: deliveries.state,\n agents: mounted.agents,\n views: mounted.views,\n commands: options.skills?.commands ?? replicatedState<Command[]>([]),\n privateRevision: options.skills?.privateRevision ?? noRevision(),\n sprinkles: options.sprinkles?.sprinkles ?? replicatedState<Sprinkle[]>([]),\n memories: options.memory?.memories ?? replicatedState<MemoryEntry[]>([]),\n memoryScopes: options.memory?.scopes ?? replicatedState<MemoryScope[]>([]),\n frozen: options.freezer?.frozen ?? replicatedState<FrozenCone[]>([]),\n importing: options.freezer?.importing ?? replicatedState<ImportProgress>(IDLE),\n changes:\n options.changes?.view ?? replicatedState<ChangesView>({ unavailable: null, changes: [] }),\n monitor: monitor.state,\n vault: options.secrets?.vault ?? idleVault,\n labels: labels.state,\n guests: guests.seats,\n approvals: approvals.state,\n approvalPolicy: policy.state,\n };\n const sudo = createSudo({\n approvals,\n agents: () => agent.agents.state(),\n ...(options.licks ? { licks: options.licks.licks } : {}),\n });\n const settings = options.settings ?? noSettings;\n const gates = gatedControls(control, slims.shown, shownViews, transcriptService.labels);\n const { trusted, viewed } = gates;\n const host = serveAgent({\n trusted,\n viewed,\n transcript: transcriptService,\n viewMonitor: monitor.viewState,\n sudo,\n settings,\n remote,\n pages,\n guest: guestOpener(guests, agent.agents, mounted.views, context),\n decide: (by) => (id, decision, reason, using) =>\n approvals.decide(id, decision, reason, by, using),\n });\n const offGuests = guests.onEnd((id) => {\n void host.invalidatePrincipal(\n (principal) => principal.seat === 'guest' && principal.guest.id === id\n );\n });\n let links = 0;\n return {\n serverId,\n agent,\n pages,\n guests,\n approvals,\n ...(options.users ? { users: options.users } : {}),\n connect(endpoint, connectOptions) {\n if (connectOptions?.guest) {\n links += 1;\n admitGuest(guests, endpoint, connectOptions.guest, serverId, links, host);\n return;\n }\n const seat: Exclude<Seat, 'guest'> = connectOptions?.readOnly\n ? 'view'\n : connectOptions?.pages === false\n ? 'control'\n : 'owner';\n links += 1;\n const link = new PortLink(endpoint);\n link.greet(serverId);\n const device = connectOptions?.device ? { device: connectOptions.device } : {};\n host.accept(link, {\n principal: { seat, link: links, ...device } satisfies AgentPrincipal,\n });\n },\n async close() {\n offGuests();\n await host.close();\n guests.dispose();\n await pages.dispose();\n await monitor.dispose();\n await remote.dispose();\n deliveries.dispose();\n sudo.close();\n approvals.close();\n transcript.dispose();\n mounted.dispose();\n labels.dispose();\n slims.dispose();\n for (const off of untouch) off();\n options.freezer?.close();\n options.secrets?.close?.();\n await options.changes?.close(context);\n await options.memory?.close(context);\n await options.sprinkles?.close(context);\n await options.skills?.close(context);\n await options.mcp?.close(context);\n await options.scoops?.runtime.close(context);\n await options.licks?.sources.close(context);\n await agent.close();\n await options.users?.close();\n },\n };\n}\n\ninterface Served {\n trusted: AgentControl;\n viewed: AgentControl;\n transcript: Record<keyof AgentTranscript, ReplicatedState<unknown>>;\n viewMonitor: ReplicatedState<unknown>;\n sudo?: AgentSudo;\n settings: AgentSettings;\n remote: AgentRemote;\n pages: Pages;\n guest?: (principal: GuestPrincipal) => { value: AgentGuest; dispose(): void } | undefined;\n decide: (by: Decider) => AgentControl['decide'];\n}\n\nexport const CLOSED_TO_GUESTS = 'a guest seat has only its transcript and propose';\n\nconst opened = new WeakSet<object>();\n\nexport const openToGuests = <F extends object>(factory: F): F => {\n opened.add(factory);\n return factory;\n};\n\nexport function closedToGuests(host: Host<AgentPrincipal>): Host<AgentPrincipal> {\n const serve = ((type: never, factory: (...args: unknown[]) => unknown, options?: never) =>\n host.serve(\n type,\n (opened.has(factory)\n ? factory\n : (input: unknown, principal: AgentPrincipal, self: unknown) => {\n if (principal.seat === 'guest') throw forbidden(CLOSED_TO_GUESTS);\n return factory(input, principal, self);\n }) as never,\n options\n )) as Host<AgentPrincipal>['serve'];\n return new Proxy(host, {\n get(target, key) {\n if (key === 'serve') return serve;\n const value = Reflect.get(target, key, target) as unknown;\n return typeof value === 'function' ? value.bind(target) : value;\n },\n });\n}\n\nexport function lazily<T>(state: () => ReplicatedState<T>): Readable<T> {\n return {\n get value() {\n return readable(state()).value;\n },\n subscribe: (listener) => readable(state()).subscribe(listener),\n events: (listener) => readable(state()).events(listener),\n };\n}\n\nconst seated = (serving: Served, principal: AgentPrincipal): AgentControl => ({\n ...(principal.seat === 'view' ? serving.viewed : serving.trusted),\n decide: serving.decide({\n by: principal.seat === 'owner' ? 'owner' : 'follower',\n ...('device' in principal && principal.device ? { device: principal.device } : {}),\n }),\n});\n\nconst VIEW_METHODS = [...CONTROL_READS, ...OWNER_DEVICE_METHODS];\n\nexport function serveAgent(serving: Served): Host<AgentPrincipal> {\n const host = closedToGuests(\n createHost<AgentPrincipal>({ name: AGENT_HOST, self: SELF, principalKey })\n );\n const viewing = { ...serving.transcript, monitor: serving.viewMonitor };\n host.serve(AgentControl, (_input, principal) => {\n const control = seated(serving, principal);\n return principal.seat === 'view'\n ? { variant: 'view', ...served(() => control, VIEW_METHODS) }\n : { variant: 'control', ...served(() => control, CONTROL_METHODS) };\n });\n host.serve(AgentTranscript, (_input, principal) => ({\n variant: 'transcript',\n ...readablesOf(principal.seat === 'view' ? viewing : serving.transcript),\n }));\n host.serve(AgentSettings, (_input, principal) =>\n principal.seat === 'view'\n ? { variant: 'view', state: readable(serving.settings.state) }\n : {\n variant: 'settings',\n state: readable(serving.settings.state),\n ...served(() => serving.settings, SETTINGS_METHODS),\n }\n );\n host.serve(AgentRemoteService, (_input, principal) => {\n if (principal.seat !== 'view')\n return { variant: 'remote', ...served(() => serving.remote, REMOTE_METHODS) };\n const scoped = viewRemote(serving.remote);\n return { variant: 'watch', ...served(() => scoped, REMOTE_READS) };\n });\n host.serve(AgentPagesService, (_input, principal, self) => {\n if (principal.seat !== 'owner') return { variant: 'none' };\n const mine = self.resource('mine', {\n version: 1,\n open: () => ownedPages(serving.pages),\n close: (owned) => owned.release(),\n });\n return { variant: 'pages', ...served(() => mine.value, PAGE_METHODS) };\n });\n host.serve(\n AgentGuestService,\n openToGuests((_input: unknown, principal: AgentPrincipal, self: Self<AgentPrincipal>) => {\n if (principal.seat !== 'guest') return { variant: 'none' };\n const opening = serving.guest?.(principal.guest);\n if (!opening) throw forbidden(CLOSED_TO_GUESTS);\n const seat = self.resource('seat', {\n version: 1,\n open: () => opening,\n close: (made) => made.dispose(),\n });\n const later = (name: 'transcript' | 'seat' | 'proposals') =>\n lazily(() => seat.value.value[name] as ReplicatedState<unknown>);\n return {\n variant: 'guest',\n transcript: later('transcript'),\n seat: later('seat'),\n proposals: later('proposals'),\n ...served(() => seat.value.value, GUEST_METHODS),\n };\n })\n );\n host.serve(AgentSudoService, (_input, principal, self) => {\n const sudo = serving.sudo;\n if (principal.seat !== 'owner' || !sudo) return { variant: 'none' };\n const mine = self.resource('mine', {\n version: 1,\n open: () => ownedSudo(sudo),\n close: (owned) => owned.release(),\n });\n return {\n variant: 'sudo',\n approvals: readable(sudo.approvals),\n ...served(() => mine.value, SUDO_METHODS),\n };\n });\n return host;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["export {\n ADOBE,\n ADOBE_PROXY,\n type AdobeConfig,\n type AdobeModelInfo,\n adobeClassifiers,\n adobeConfig,\n adobeIdentity,\n adobeModel,\n adobeProvider,\n adobeUsage,\n type Budget,\n SESSION_HEADER,\n VERSION_HEADER,\n withAdobeIdentity,\n} from './adobe.ts';\nexport { type Agent, type AgentOptions, answerText, openAgent } from './agent.ts';\nexport {\n APPROVAL_MS,\n type Approval,\n type ApprovalAnswer,\n type ApprovalDecided,\n type ApprovalDraft,\n type ApprovalJudge,\n type ApprovalKind,\n type ApprovalRequester,\n type ApprovalState,\n type Approvals,\n ApprovalsDoc,\n type ApprovalTier,\n type ApprovalVerdict,\n approvalJudge,\n attachApprovals,\n DEFAULT_POLICY,\n type DecidedBy,\n type Decider,\n JUDGE_ALLOW,\n JUDGE_DENY,\n JUDGE_KIND,\n JUDGE_MODEL,\n JUDGE_QUESTIONS,\n type Judgement,\n judgeModelOf,\n judgeSpender,\n judgeState,\n type OwnerIntent,\n ownerIntent,\n POLICY_FILE,\n REASONS,\n seedPolicy,\n VERDICT_REASONS,\n verdictOf,\n verdictRecorder,\n} from './approvals/index.ts';\nexport {\n type ApprovalPolicy,\n type ApprovalPolicyChange,\n type ApprovalPolicySet,\n DEFAULT_APPROVAL_POLICY,\n type SudoPolicy,\n} from './approvals/policy.ts';\nexport type { AgentSudo, SudoAnswer, SudoRequest } from './approvals/sudo.ts';\nexport {\n FILE_LIMIT,\n IMAGE_LIMIT,\n type SendAttachment,\n type ShownAttachment,\n splitUser,\n TOTAL_LIMIT,\n userParts,\n} from './attachments.ts';\nexport { type AgentConnection, connectAgent } from './client.ts';\nexport { createAgentControl } from './control.ts';\nexport {\n connectGuest,\n GUEST_ONLY,\n type GuestConnection,\n SEAT_REFUSED,\n} from './guests/client.ts';\nexport type { GuestOpened, Proposed, ProposeRequest } from './guests/index.ts';\nexport type { GateKind, GuestPolicy } from './guests/policy.ts';\nexport type { GuestDraft, GuestGate, GuestGates, GuestSeat } from './guests/seats.ts';\nexport { type AgentHost, type ConnectOptions, hostAgent } from './host.ts';\nexport type {\n KernelClient,\n KernelFs,\n KernelProcess,\n KernelStat,\n SpawnOptions,\n} from './kernel/client.ts';\nexport { HOME, type KernelEnvOptions, kernelEnvironment, SliccKernelEnv } from './kernel/env.ts';\nexport {\n adminOver,\n type KernelAdmin,\n type KernelGroup,\n type KernelGroups,\n type KernelUser,\n type KernelUsers,\n serveAdmin,\n type UserClient,\n type UserClients,\n type UserConnect,\n type UserSpec,\n userClients,\n} from './kernel/users.ts';\nexport {\n type AgentWorkerOptions,\n type AgentWorkerScope,\n type KernelAttach,\n runAgentWorker,\n} from './main.ts';\nexport {\n type Loopback,\n type Transport,\n type TransportResponse,\n transportFetch,\n} from './net.ts';\nexport {\n AGENT_LOCK,\n type AgentOwner,\n type AgentWorker,\n type KernelSource,\n type OwnerOptions,\n startAgent,\n} from './owner.ts';\nexport { SliccPrompt, sliccPrompt } from './prompt.ts';\nexport {\n type AgentPages,\n createPages,\n type PageBatch,\n type PageCaller,\n type PageRequest,\n type PageResult,\n type Pages,\n type PagesOpened,\n type PageTab,\n} from './remote/pages.ts';\nexport {\n type AccountState,\n AgentControl,\n AgentPagesService,\n AgentSettings,\n type AgentSettingsChange,\n AgentTranscript,\n type BudgetState,\n type ModelChoice,\n type OperationError,\n type PromptResult,\n type SendMode,\n type SendRequest,\n type SendResponse,\n type SettingsState,\n type SignIn,\n} from './services.ts';\nexport {\n BEDROCK,\n createAgentSettings,\n createSliccModels,\n DEFAULT_MODEL,\n DEFAULT_REGIONS,\n PREFERRED_MODELS,\n preferredModel,\n resolveDefaultModel,\n sliccProviders,\n withDefaultRegions,\n} from './settings.ts';\nexport {\n AGENT_DIRECTORY,\n type OpfsSqliteOptions,\n openMemorySqliteStorage,\n openOpfsSqliteStorage,\n WasmSqliteDatabase,\n} from './sqlite.ts';\nexport { type SystemFacts, systemSection } from './system.ts';\nexport { UPLOADS, type Uploads, upload } from './uploads.ts';\nexport { type PortEndpoint, PortLink } from './wire.ts';\nexport {\n type KernelPorts,\n kernelPort,\n kernelPorts,\n serveConnections,\n type WorkerScope,\n} from './worker.ts';\n"],
|
|
5
|
-
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAwC,YAAY,iBAAiB;AACrE;AAAA,EACE;AAAA,EAUA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EAIE;AAAA,OAEK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAA+B,oBAAoB;
|
|
4
|
+
"sourcesContent": ["export {\n ADOBE,\n ADOBE_PROXY,\n type AdobeConfig,\n type AdobeModelInfo,\n adobeClassifiers,\n adobeConfig,\n adobeIdentity,\n adobeModel,\n adobeProvider,\n adobeUsage,\n type Budget,\n SESSION_HEADER,\n VERSION_HEADER,\n withAdobeIdentity,\n} from './adobe.ts';\nexport { type Agent, type AgentOptions, answerText, openAgent } from './agent.ts';\nexport {\n APPROVAL_MS,\n type Approval,\n type ApprovalAnswer,\n type ApprovalDecided,\n type ApprovalDraft,\n type ApprovalJudge,\n type ApprovalKind,\n type ApprovalRequester,\n type ApprovalState,\n type Approvals,\n ApprovalsDoc,\n type ApprovalTier,\n type ApprovalVerdict,\n approvalJudge,\n attachApprovals,\n DEFAULT_POLICY,\n type DecidedBy,\n type Decider,\n JUDGE_ALLOW,\n JUDGE_DENY,\n JUDGE_KIND,\n JUDGE_MODEL,\n JUDGE_QUESTIONS,\n type Judgement,\n judgeModelOf,\n judgeSpender,\n judgeState,\n type OwnerIntent,\n ownerIntent,\n POLICY_FILE,\n REASONS,\n seedPolicy,\n VERDICT_REASONS,\n verdictOf,\n verdictRecorder,\n} from './approvals/index.ts';\nexport {\n type ApprovalPolicy,\n type ApprovalPolicyChange,\n type ApprovalPolicySet,\n DEFAULT_APPROVAL_POLICY,\n type SudoPolicy,\n} from './approvals/policy.ts';\nexport type { AgentSudo, SudoAnswer, SudoRequest } from './approvals/sudo.ts';\nexport {\n FILE_LIMIT,\n IMAGE_LIMIT,\n type SendAttachment,\n type ShownAttachment,\n splitUser,\n TOTAL_LIMIT,\n userParts,\n} from './attachments.ts';\nexport { type AgentConnection, connectAgent } from './client.ts';\nexport type { Clock } from './clock.ts';\nexport { createAgentControl } from './control.ts';\nexport {\n connectGuest,\n GUEST_ONLY,\n type GuestConnection,\n SEAT_REFUSED,\n} from './guests/client.ts';\nexport type { GuestOpened, Proposed, ProposeRequest } from './guests/index.ts';\nexport type { GateKind, GuestPolicy } from './guests/policy.ts';\nexport type { GuestDraft, GuestGate, GuestGates, GuestSeat } from './guests/seats.ts';\nexport { type AgentHost, type ConnectOptions, hostAgent } from './host.ts';\nexport type {\n KernelClient,\n KernelFs,\n KernelProcess,\n KernelStat,\n SpawnOptions,\n} from './kernel/client.ts';\nexport { HOME, type KernelEnvOptions, kernelEnvironment, SliccKernelEnv } from './kernel/env.ts';\nexport {\n adminOver,\n type KernelAdmin,\n type KernelGroup,\n type KernelGroups,\n type KernelUser,\n type KernelUsers,\n serveAdmin,\n type UserClient,\n type UserClients,\n type UserConnect,\n type UserSpec,\n userClients,\n} from './kernel/users.ts';\nexport {\n type AgentWorkerOptions,\n type AgentWorkerScope,\n type KernelAttach,\n runAgentWorker,\n} from './main.ts';\nexport {\n type Loopback,\n type Transport,\n type TransportResponse,\n transportFetch,\n} from './net.ts';\nexport {\n AGENT_LOCK,\n type AgentOwner,\n type AgentWorker,\n type KernelSource,\n type OwnerOptions,\n startAgent,\n} from './owner.ts';\nexport { SliccPrompt, sliccPrompt } from './prompt.ts';\nexport {\n type AgentPages,\n createPages,\n type PageBatch,\n type PageCaller,\n type PageRequest,\n type PageResult,\n type Pages,\n type PagesOpened,\n type PageTab,\n} from './remote/pages.ts';\nexport {\n type AccountState,\n AgentControl,\n AgentPagesService,\n AgentSettings,\n type AgentSettingsChange,\n AgentTranscript,\n type BudgetState,\n type ModelChoice,\n type OperationError,\n type PromptResult,\n type SendMode,\n type SendRequest,\n type SendResponse,\n type SettingsState,\n type SignIn,\n} from './services.ts';\nexport {\n BEDROCK,\n createAgentSettings,\n createSliccModels,\n DEFAULT_MODEL,\n DEFAULT_REGIONS,\n PREFERRED_MODELS,\n preferredModel,\n resolveDefaultModel,\n sliccProviders,\n withDefaultRegions,\n} from './settings.ts';\nexport {\n AGENT_DIRECTORY,\n type OpfsSqliteOptions,\n openMemorySqliteStorage,\n openOpfsSqliteStorage,\n WasmSqliteDatabase,\n} from './sqlite.ts';\nexport { type SystemFacts, systemSection } from './system.ts';\nexport { UPLOADS, type Uploads, upload } from './uploads.ts';\nexport { type PortEndpoint, PortLink } from './wire.ts';\nexport {\n type KernelPorts,\n kernelPort,\n kernelPorts,\n serveConnections,\n type WorkerScope,\n} from './worker.ts';\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAwC,YAAY,iBAAiB;AACrE;AAAA,EACE;AAAA,EAUA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EAIE;AAAA,OAEK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAA+B,oBAAoB;AAEnD,SAAS,0BAA0B;AACnC;AAAA,EACE;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AAIP,SAA8C,iBAAiB;AAQ/D,SAAS,MAA6B,mBAAmB,sBAAsB;AAC/E;AAAA,EACE;AAAA,EAMA;AAAA,EAKA;AAAA,OACK;AACP;AAAA,EAIE;AAAA,OACK;AACP;AAAA,EAIE;AAAA,OACK;AACP;AAAA,EACE;AAAA,EAKA;AAAA,OACK;AACP,SAAS,aAAa,mBAAmB;AACzC;AAAA,EAEE;AAAA,OAQK;AACP;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OAUK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAA2B,qBAAqB;AAChD,SAAS,SAAuB,cAAc;AAC9C,SAA4B,gBAAgB;AAC5C;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/monitor/index.js
CHANGED
|
@@ -139,6 +139,7 @@ class Session {
|
|
|
139
139
|
options.agents.onChange(() => this.schedule()),
|
|
140
140
|
options.views.subscribe(() => this.schedule())
|
|
141
141
|
);
|
|
142
|
+
if (options.timings) this.#off.push(options.timings.subscribe(() => this.schedule()));
|
|
142
143
|
if (options.reports) {
|
|
143
144
|
for (const report of [...options.reports.list()].reverse()) this.#reported(report);
|
|
144
145
|
this.#off.push(
|
|
@@ -406,7 +407,8 @@ class Session {
|
|
|
406
407
|
processes,
|
|
407
408
|
kernel: this.#kernel,
|
|
408
409
|
problems: [...this.#problems],
|
|
409
|
-
paused: this.#paused
|
|
410
|
+
paused: this.#paused,
|
|
411
|
+
latency: latencyOf(this.#options.timings?.list() ?? [])
|
|
410
412
|
};
|
|
411
413
|
const key = JSON.stringify({ ...feed, at: 0 });
|
|
412
414
|
if (key === this.#last) return;
|
|
@@ -414,6 +416,30 @@ class Session {
|
|
|
414
416
|
this.#publish(feed, narrowed(feed, programs));
|
|
415
417
|
}
|
|
416
418
|
}
|
|
419
|
+
const LATENCY_WINDOW = 20;
|
|
420
|
+
const median = (values) => {
|
|
421
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
422
|
+
const middle = Math.floor(sorted.length / 2);
|
|
423
|
+
return sorted.length % 2 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
|
|
424
|
+
};
|
|
425
|
+
function latencyOf(timings) {
|
|
426
|
+
const recent = timings.slice(0, LATENCY_WINDOW);
|
|
427
|
+
if (!recent.length) return null;
|
|
428
|
+
const firsts = recent.map((timing) => timing.firstChunkMs).filter((value) => value !== null);
|
|
429
|
+
const byModel = Map.groupBy(recent, (timing) => `${timing.provider}/${timing.model}`);
|
|
430
|
+
return {
|
|
431
|
+
requests: recent.length,
|
|
432
|
+
medianMs: Math.round(median(recent.map((timing) => timing.durationMs))),
|
|
433
|
+
firstChunkMedianMs: firsts.length ? Math.round(median(firsts)) : null,
|
|
434
|
+
errors: recent.filter((timing) => timing.stop === "error").length,
|
|
435
|
+
series: recent.map((timing) => Math.round(timing.durationMs)).reverse(),
|
|
436
|
+
models: [...byModel].map(([model, list]) => ({
|
|
437
|
+
model,
|
|
438
|
+
requests: list.length,
|
|
439
|
+
medianMs: Math.round(median(list.map((timing) => timing.durationMs)))
|
|
440
|
+
}))
|
|
441
|
+
};
|
|
442
|
+
}
|
|
417
443
|
function createMonitor(options) {
|
|
418
444
|
const settings = {
|
|
419
445
|
now: options.now ?? Date.now,
|
|
@@ -484,6 +510,7 @@ function createMonitor(options) {
|
|
|
484
510
|
};
|
|
485
511
|
}
|
|
486
512
|
export {
|
|
513
|
+
LATENCY_WINDOW,
|
|
487
514
|
PROBLEMS_MAX,
|
|
488
515
|
PS_MS,
|
|
489
516
|
PS_TIMEOUT_MS,
|
|
@@ -495,6 +522,7 @@ export {
|
|
|
495
522
|
createMonitor,
|
|
496
523
|
emptyFeed,
|
|
497
524
|
globalTimers,
|
|
525
|
+
latencyOf,
|
|
498
526
|
narrowed,
|
|
499
527
|
totals
|
|
500
528
|
};
|