@op0ai/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/LICENSE +38 -0
  2. package/README.md +28 -0
  3. package/dist/agent.d.ts +23 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +72 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/agui.d.ts +87 -0
  8. package/dist/agui.d.ts.map +1 -0
  9. package/dist/agui.js +22 -0
  10. package/dist/agui.js.map +1 -0
  11. package/dist/config.d.ts +76 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +38 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/data.d.ts +168 -0
  16. package/dist/data.d.ts.map +1 -0
  17. package/dist/data.js +211 -0
  18. package/dist/data.js.map +1 -0
  19. package/dist/define.d.ts +30 -0
  20. package/dist/define.d.ts.map +1 -0
  21. package/dist/define.js +87 -0
  22. package/dist/define.js.map +1 -0
  23. package/dist/distill.d.ts +68 -0
  24. package/dist/distill.d.ts.map +1 -0
  25. package/dist/distill.js +113 -0
  26. package/dist/distill.js.map +1 -0
  27. package/dist/events.d.ts +39 -0
  28. package/dist/events.d.ts.map +1 -0
  29. package/dist/events.js +25 -0
  30. package/dist/events.js.map +1 -0
  31. package/dist/evlog.d.ts +71 -0
  32. package/dist/evlog.d.ts.map +1 -0
  33. package/dist/evlog.js +124 -0
  34. package/dist/evlog.js.map +1 -0
  35. package/dist/guards.d.ts +61 -0
  36. package/dist/guards.d.ts.map +1 -0
  37. package/dist/guards.js +88 -0
  38. package/dist/guards.js.map +1 -0
  39. package/dist/hash.d.ts +6 -0
  40. package/dist/hash.d.ts.map +1 -0
  41. package/dist/hash.js +18 -0
  42. package/dist/hash.js.map +1 -0
  43. package/dist/index.d.ts +120 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +175 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/platform.d.ts +97 -0
  48. package/dist/platform.d.ts.map +1 -0
  49. package/dist/platform.js +10 -0
  50. package/dist/platform.js.map +1 -0
  51. package/dist/session.d.ts +47 -0
  52. package/dist/session.d.ts.map +1 -0
  53. package/dist/session.js +88 -0
  54. package/dist/session.js.map +1 -0
  55. package/dist/source.d.ts +65 -0
  56. package/dist/source.d.ts.map +1 -0
  57. package/dist/source.js +96 -0
  58. package/dist/source.js.map +1 -0
  59. package/dist/tool.d.ts +43 -0
  60. package/dist/tool.d.ts.map +1 -0
  61. package/dist/tool.js +16 -0
  62. package/dist/tool.js.map +1 -0
  63. package/dist/usectx.d.ts +93 -0
  64. package/dist/usectx.d.ts.map +1 -0
  65. package/dist/usectx.js +220 -0
  66. package/dist/usectx.js.map +1 -0
  67. package/dist/vault.d.ts +21 -0
  68. package/dist/vault.d.ts.map +1 -0
  69. package/dist/vault.js +25 -0
  70. package/dist/vault.js.map +1 -0
  71. package/package.json +75 -0
package/dist/data.js ADDED
@@ -0,0 +1,211 @@
1
+ import { newId } from "./hash.js";
2
+ /** Author a table from a zod object schema; chain .index(name, cols). */
3
+ export function defineTable(schema) {
4
+ const indexes = {};
5
+ const def = {
6
+ schema,
7
+ indexes,
8
+ index(name, columns) {
9
+ indexes[name] = columns;
10
+ return def;
11
+ },
12
+ };
13
+ return def;
14
+ }
15
+ /** Identity helper — keeps the schema object's literal types while documenting intent. */
16
+ export function defineSchema(schema) {
17
+ return schema;
18
+ }
19
+ export function query(def) {
20
+ return { kind: "query", args: def.args, handler: def.handler };
21
+ }
22
+ export function mutation(def) {
23
+ return { kind: "mutation", args: def.args, handler: def.handler };
24
+ }
25
+ export function action(def) {
26
+ return { kind: "action", args: def.args, handler: def.handler };
27
+ }
28
+ const rowKey = (table, id) => `${table}:${id}`;
29
+ export class DataEngine {
30
+ schema;
31
+ functions;
32
+ tables = new Map();
33
+ subs = new Map();
34
+ version = 0;
35
+ constructor(schema, functions) {
36
+ this.schema = schema;
37
+ this.functions = functions;
38
+ for (const t of Object.keys(schema))
39
+ this.tables.set(t, new Map());
40
+ }
41
+ table(name) {
42
+ const t = this.tables.get(name);
43
+ if (!t)
44
+ throw new Error(`data: unknown table "${name}"`);
45
+ return t;
46
+ }
47
+ /** A read-db that records into `rs` (null = untracked, for mutation-internal reads). */
48
+ readDb(rs) {
49
+ const self = this;
50
+ return {
51
+ get(table, id) {
52
+ rs?.rows.add(rowKey(table, id));
53
+ return self.table(table).get(id) ?? null;
54
+ },
55
+ query(table) {
56
+ rs?.tables.add(table); // a scan depends on the whole table (coarse but correct — never under-recomputes)
57
+ const filters = [];
58
+ const builder = {
59
+ withIndex(_name, fn) {
60
+ const iq = { eq(col, val) { filters.push({ col, val }); return iq; } };
61
+ fn(iq);
62
+ return builder;
63
+ },
64
+ collect() {
65
+ const rows = [...self.table(table).values()].filter((r) => filters.every((f) => r[f.col] === f.val));
66
+ return rows;
67
+ },
68
+ first() {
69
+ return [...self.table(table).values()].find((r) => filters.every((f) => r[f.col] === f.val)) ?? null;
70
+ },
71
+ };
72
+ return builder;
73
+ },
74
+ };
75
+ }
76
+ writeDb(writes) {
77
+ const self = this;
78
+ const read = this.readDb(null);
79
+ return {
80
+ get: read.get,
81
+ query: read.query,
82
+ insert(table, doc) {
83
+ self.table(table); // validate table exists
84
+ const id = typeof doc['id'] === "string" ? doc['id'] : newId();
85
+ const def = self.schema[table];
86
+ if (!def)
87
+ throw new Error(`data: unknown table "${table}"`);
88
+ def.schema.parse({ ...doc, id }); // zod-validate the row shape
89
+ self.table(table).set(id, { ...doc, id, _v: self.version }); // version already bumped for this mutation
90
+ writes.push({ table, id });
91
+ return id;
92
+ },
93
+ patch(table, id, partial) {
94
+ const cur = self.table(table).get(id);
95
+ if (!cur)
96
+ throw new Error(`data: patch missing ${table}:${id}`);
97
+ const next = { ...cur, ...partial, id, _v: self.version };
98
+ const def = self.schema[table];
99
+ if (!def)
100
+ throw new Error(`data: unknown table "${table}"`);
101
+ def.schema.parse(next);
102
+ self.table(table).set(id, next);
103
+ writes.push({ table, id });
104
+ },
105
+ delete(table, id) {
106
+ if (self.table(table).delete(id))
107
+ writes.push({ table, id });
108
+ },
109
+ };
110
+ }
111
+ fn(name, kind) {
112
+ const f = this.functions[name];
113
+ if (!f)
114
+ throw new Error(`data: unknown function "${name}"`);
115
+ if (f.kind !== kind)
116
+ throw new Error(`data: "${name}" is a ${f.kind}, not a ${kind}`);
117
+ return f;
118
+ }
119
+ /** Run a query (tracked). Returns the result + the read-set (for subscription registration). */
120
+ runQuery(name, args) {
121
+ const f = this.fn(name, "query");
122
+ const rs = { rows: new Set(), tables: new Set() };
123
+ const result = f.handler(this.readDb(rs), f.args.parse(args));
124
+ return { result, readSet: rs, version: this.version };
125
+ }
126
+ /** Run a mutation (single-writer), bump the version, then recompute ONLY the subscriptions whose read-set intersects the write. */
127
+ runMutation(name, args) {
128
+ const f = this.fn(name, "mutation");
129
+ const writes = [];
130
+ this.version += 1;
131
+ const result = f.handler(this.writeDb(writes), f.args.parse(args));
132
+ const writtenTables = new Set(writes.map((w) => w.table));
133
+ const writtenRows = new Set(writes.map((w) => rowKey(w.table, w.id)));
134
+ const transitions = [];
135
+ for (const sub of this.subs.values()) {
136
+ const hit = [...sub.readSet.tables].some((t) => writtenTables.has(t)) ||
137
+ [...sub.readSet.rows].some((r) => writtenRows.has(r));
138
+ if (!hit)
139
+ continue;
140
+ const re = this.runQuery(sub.name, sub.args); // re-execute → FULL result
141
+ sub.readSet = re.readSet; // refresh the read-set (deps can change)
142
+ transitions.push({ subId: sub.subId, connId: sub.connId, name: sub.name, args: sub.args, result: re.result, version: this.version });
143
+ }
144
+ return { result, version: this.version, transitions };
145
+ }
146
+ /** Run an action (I/O escape hatch): it calls query/mutation through the ctx; not reactive. */
147
+ async runAction(name, args, bridge) {
148
+ const f = this.fn(name, "action");
149
+ const ctx = {
150
+ runQuery: (n, a) => this.runQuery(n, a).result,
151
+ runMutation: (n, a) => this.runMutation(n, a).result,
152
+ ...(bridge?.runCordTool !== undefined ? { runCordTool: bridge.runCordTool } : {}),
153
+ };
154
+ return f.handler(ctx, f.args.parse(args));
155
+ }
156
+ /** Register a live subscription: returns the initial result; future intersecting mutations push Transitions. */
157
+ subscribe(subId, connId, name, args) {
158
+ const { result, readSet, version } = this.runQuery(name, args);
159
+ this.subs.set(subId, { subId, connId, name, args, readSet });
160
+ return { result, version };
161
+ }
162
+ unsubscribe(subId) {
163
+ this.subs.delete(subId);
164
+ }
165
+ /** Drop all subscriptions for a connection (on WS close). */
166
+ unsubscribeConn(connId) {
167
+ for (const [id, s] of this.subs)
168
+ if (s.connId === connId)
169
+ this.subs.delete(id);
170
+ }
171
+ /** Durability: snapshot the tables (persist to the DO's this.sql) and restore on wake. */
172
+ snapshot() {
173
+ const out = {};
174
+ for (const [t, m] of this.tables)
175
+ out[t] = [...m.values()];
176
+ return { version: this.version, tables: out };
177
+ }
178
+ restore(snap) {
179
+ this.version = snap.version;
180
+ for (const [t, rows] of Object.entries(snap.tables)) {
181
+ const m = this.tables.get(t) ?? new Map();
182
+ m.clear();
183
+ for (const r of rows)
184
+ m.set(r.id, r);
185
+ this.tables.set(t, m);
186
+ }
187
+ }
188
+ }
189
+ /**
190
+ * Dispatch a DataRequest against the engine. The DO host wires this into its fetch (one-shot query/mutation/
191
+ * action) and its WebSocket handler (subscribe/unsubscribe), then BROADCASTS the returned `transitions` to the
192
+ * subscribed connections (group by transition.connId). Persist engine.snapshot() to this.sql after a mutation.
193
+ */
194
+ export async function dataPlaneRpc(engine, req, connId = "rpc") {
195
+ try {
196
+ switch (req.op) {
197
+ case "query": return { ok: true, ...engine.runQuery(req.name, req.args) };
198
+ case "subscribe": return { ok: true, ...engine.subscribe(req.subId, connId, req.name, req.args) };
199
+ case "unsubscribe":
200
+ engine.unsubscribe(req.subId);
201
+ return { ok: true };
202
+ case "mutation": return { ok: true, ...engine.runMutation(req.name, req.args) };
203
+ case "action": return { ok: true, result: await engine.runAction(req.name, req.args) };
204
+ default: return { ok: false, error: "unknown op" };
205
+ }
206
+ }
207
+ catch (e) {
208
+ return { ok: false, error: e instanceof Error ? e.message : String(e) };
209
+ }
210
+ }
211
+ //# sourceMappingURL=data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data.js","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { CordEvent } from "./agui.ts";
2
+ import type { Kv } from "./platform.ts";
3
+ import type { Source } from "./source.ts";
4
+ /** The Agent surface the event store needs — structural, so it's testable with fakes and satisfied by `this`. */
5
+ export interface DurableHost {
6
+ sql: (strings: TemplateStringsArray, ...values: unknown[]) => unknown[];
7
+ broadcast: (message: string) => void;
8
+ }
9
+ /**
10
+ * Durable AG-UI event log on the cord's DO: every event is persisted (so the timeline survives reload) AND the
11
+ * sink broadcasts it live; replay() feeds onConnect so a reconnecting client reconstructs the timeline.
12
+ */
13
+ export declare function cordEventStore(host: DurableHost): {
14
+ sink: (event: CordEvent) => void;
15
+ replay: () => CordEvent[];
16
+ };
17
+ /** Context for {@link cordRpc}: the ports it can serve + any custom typed functions. */
18
+ export interface CordRpcContext {
19
+ source?: Source;
20
+ kv?: Kv;
21
+ /** Custom functions by name. The built-in source and kv functions are always served. Pair with client queryRef/mutationRef. */
22
+ functions?: Record<string, (args: Record<string, unknown>, ctx: CordRpcContext) => Promise<unknown>>;
23
+ }
24
+ /**
25
+ * Serve the typed cord client's RPC calls (POST { fn, args }). Wire into the cord's `fetch` (e.g. at /api/cord/rpc):
26
+ * the built-in source.read/source.edit/kv.get/kv.put map onto the Source + Kv ports; register more via `functions`.
27
+ * This is the server half of the thin typed client (client.tsx). RPC edits commit immediately (no debounce).
28
+ */
29
+ export declare function cordRpc(request: Request, ctx: CordRpcContext): Promise<Response>;
30
+ //# sourceMappingURL=define.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,iHAAiH;AACjH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC;IACxE,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AASD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG;IAAE,IAAI,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,SAAS,EAAE,CAAA;CAAE,CA6BjH;AAED,wFAAwF;AACxF,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,EAAE,CAAC;IACR,+HAA+H;IAC/H,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;CACtG;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAgCtF"}
package/dist/define.js ADDED
@@ -0,0 +1,87 @@
1
+ // Hoisted from inside cordEventStore (captures nothing — pure formatting of its own params).
2
+ const log = (where, e) => console.log(JSON.stringify({ evlog: `cord_events.${where}`, error: e instanceof Error ? e.message : String(e) }));
3
+ // Hoisted from inside cordRpc (captures nothing — pure formatting of its own params).
4
+ const json = (body, status = 200) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
5
+ /**
6
+ * Durable AG-UI event log on the cord's DO: every event is persisted (so the timeline survives reload) AND the
7
+ * sink broadcasts it live; replay() feeds onConnect so a reconnecting client reconstructs the timeline.
8
+ */
9
+ export function cordEventStore(host) {
10
+ let ready = false;
11
+ try {
12
+ void host.sql `CREATE TABLE IF NOT EXISTS cord_events (seq INTEGER PRIMARY KEY AUTOINCREMENT, run TEXT, json TEXT)`;
13
+ ready = true;
14
+ }
15
+ catch (e) {
16
+ log("init", e);
17
+ }
18
+ return {
19
+ // Never throw — a failed event must not break a chat turn; log so the tail reveals any this.sql/broadcast issue.
20
+ sink: (event) => {
21
+ if (!ready)
22
+ return;
23
+ try {
24
+ void host.sql `INSERT INTO cord_events (run, json) VALUES (${event.runId}, ${JSON.stringify(event)})`;
25
+ host.broadcast(JSON.stringify({ cordEvent: event }));
26
+ }
27
+ catch (e) {
28
+ log("sink", e);
29
+ }
30
+ },
31
+ replay: () => {
32
+ if (!ready)
33
+ return [];
34
+ try {
35
+ return host.sql `SELECT json FROM cord_events ORDER BY seq`.map((row) => JSON.parse(row.json));
36
+ }
37
+ catch (e) {
38
+ log("replay", e);
39
+ return [];
40
+ }
41
+ },
42
+ };
43
+ }
44
+ /**
45
+ * Serve the typed cord client's RPC calls (POST { fn, args }). Wire into the cord's `fetch` (e.g. at /api/cord/rpc):
46
+ * the built-in source.read/source.edit/kv.get/kv.put map onto the Source + Kv ports; register more via `functions`.
47
+ * This is the server half of the thin typed client (client.tsx). RPC edits commit immediately (no debounce).
48
+ */
49
+ export async function cordRpc(request, ctx) {
50
+ let parsed;
51
+ try {
52
+ parsed = (await request.json());
53
+ }
54
+ catch {
55
+ return json({ error: "invalid json" }, 400);
56
+ }
57
+ const fn = parsed.fn ?? "";
58
+ const args = parsed.args ?? {};
59
+ const builtins = {
60
+ "source.read": async (a) => ({ path: a['path'], content: ctx.source ? await ctx.source.read(String(a['path'])) : null }),
61
+ "source.edit": async (a) => {
62
+ if (!ctx.source)
63
+ throw new Error("no source bound");
64
+ await ctx.source.stage(String(a['path']), String(a['content']));
65
+ await ctx.source.flush(); // direct RPC write commits immediately (no debounce)
66
+ return { staged: String(a['path']), commitsInSeconds: 0 };
67
+ },
68
+ "kv.get": async (a) => ({ value: ctx.kv ? await ctx.kv.get(String(a['key'])) : null }),
69
+ "kv.put": async (a) => {
70
+ if (!ctx.kv)
71
+ throw new Error("no kv bound");
72
+ await ctx.kv.put(String(a['key']), String(a['value']));
73
+ return { ok: true };
74
+ },
75
+ };
76
+ const custom = ctx.functions?.[fn];
77
+ const handler = builtins[fn] ?? (custom ? (a) => custom(a, ctx) : undefined);
78
+ if (!handler)
79
+ return json({ error: `unknown fn: ${fn}` }, 404);
80
+ try {
81
+ return json(await handler(args));
82
+ }
83
+ catch (e) {
84
+ return json({ error: e instanceof Error ? e.message : String(e) }, 500);
85
+ }
86
+ }
87
+ //# sourceMappingURL=define.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import type { CordEvent } from "./agui.ts";
2
+ import type { WideEvent, AuditEntry } from "./guards.ts";
3
+ import { type SessionStream, type Interception } from "./session.ts";
4
+ import type { Inference } from "./platform.ts";
5
+ export type SessionSource = "cord" | "agent";
6
+ /** One envelope over both session kinds. The distiller depends ONLY on this. */
7
+ export interface Session {
8
+ runId: string;
9
+ source: SessionSource;
10
+ harness?: string;
11
+ mode?: string;
12
+ events: WideEvent[];
13
+ audit: AuditEntry[];
14
+ interceptions?: Interception[];
15
+ }
16
+ /**
17
+ * Build a Session from a cord runtime session's CordEvent timeline (e.g. cordEventStore.replay() filtered by
18
+ * runId). Pairs TOOL_CALL_START/RESULT into one wide-event with a real durationMs; folds in source commits + errors.
19
+ */
20
+ export declare function cordSessionFromEvents(runId: string, events: CordEvent[], audit?: AuditEntry[]): Session;
21
+ /** Build a Session from a coding-agent capture (lapdog/trajectory) via session.ts ingest (→ WideEvents + audit + interceptions). */
22
+ export declare function agentSession(stream: SessionStream): Session;
23
+ /** The distilled output — maps onto CreateSkill (name/description/whenToUse/documentation/tags). */
24
+ export interface SkillDraft {
25
+ name: string;
26
+ description: string;
27
+ whenToUse: string;
28
+ documentation: string;
29
+ tags: string[];
30
+ evidence: {
31
+ sourceRunId: string;
32
+ source: SessionSource;
33
+ tools: string[];
34
+ steps: number;
35
+ ok: boolean;
36
+ failures: string[];
37
+ flagged: string[];
38
+ note?: string;
39
+ };
40
+ }
41
+ export interface DistillOptions {
42
+ name?: string;
43
+ tags?: string[];
44
+ }
45
+ /** Deterministic distillation: summarize a session (+ optional human note) into a SkillDraft skeleton. No model needed. */
46
+ export declare function distill(session: Session, note?: string, opts?: DistillOptions): SkillDraft;
47
+ /** Optional model-backed enrichment: the Inference port sharpens name/description/whenToUse/doc; falls back to the deterministic draft. */
48
+ export declare function distillWithModel(session: Session, note: string | undefined, inference: Inference, opts?: DistillOptions): Promise<SkillDraft>;
49
+ /** Persist a SkillDraft. Host-bound (the KB / skillkit); the real sink is wired by the platform. */
50
+ export type SkillSink = (draft: SkillDraft) => Promise<{
51
+ ok: boolean;
52
+ id?: string;
53
+ }>;
54
+ /** A no-network sink that collects drafts (tests + dry runs). */
55
+ export declare function collectSink(into: SkillDraft[]): SkillSink;
56
+ /** A durable store the skill sink writes to — the cord's Source `stage`, an R2 `put`, etc. (structural, host-bound). */
57
+ export interface SkillStore {
58
+ put(path: string, content: string): Promise<void>;
59
+ }
60
+ /**
61
+ * Persist a SkillDraft to a durable store as `<prefix>/<slug>.md` (the skill doc) + `<prefix>/<slug>.json` (the
62
+ * structured draft, for promotion to a real KB skill). Returns the `.md` path as the id. Wire `store.put` to the
63
+ * cord's Source so a distilled session becomes a committed artifact (R2 + GitHub) — not just a returned object.
64
+ */
65
+ export declare function storeSkillSink(store: SkillStore, opts?: {
66
+ prefix?: string;
67
+ }): SkillSink;
68
+ //# sourceMappingURL=distill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distill.d.ts","sourceRoot":"","sources":["../src/distill.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAiB,KAAK,aAAa,EAAqB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AACvG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC;AAE7C,gFAAgF;AAChF,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;CAChC;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,KAAK,GAAE,UAAU,EAAO,GAAG,OAAO,CAqB3G;AAED,oIAAoI;AACpI,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAG3D;AAED,oGAAoG;AACpG,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE;QACR,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,aAAa,CAAC;QACtB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,EAAE,EAAE,OAAO,CAAC;QACZ,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,2HAA2H;AAC3H,wBAAgB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,UAAU,CAgC9F;AAED,2IAA2I;AAC3I,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CAiBvJ;AAED,oGAAoG;AACpG,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAErF,iEAAiE;AACjE,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,SAAS,CAKzD;AAED,wHAAwH;AACxH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAID;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAOvF"}
@@ -0,0 +1,113 @@
1
+ import { ingestSession } from "./session.js";
2
+ const iso = (ts) => new Date(ts).toISOString();
3
+ /**
4
+ * Build a Session from a cord runtime session's CordEvent timeline (e.g. cordEventStore.replay() filtered by
5
+ * runId). Pairs TOOL_CALL_START/RESULT into one wide-event with a real durationMs; folds in source commits + errors.
6
+ */
7
+ export function cordSessionFromEvents(runId, events, audit = []) {
8
+ const wide = [];
9
+ const open = new Map();
10
+ for (const e of events) {
11
+ if (e.type === "TOOL_CALL_START") {
12
+ open.set(e.toolCallId, { name: e.name, ts: e.ts });
13
+ }
14
+ else if (e.type === "TOOL_CALL_RESULT") {
15
+ const s = open.get(e.toolCallId);
16
+ open.delete(e.toolCallId);
17
+ wide.push({
18
+ ts: iso(e.ts), runId, tenantId: "cord", cordId: "cord", kind: "tool", name: e.name,
19
+ durationMs: s ? e.ts - s.ts : 0, ok: e.ok,
20
+ ...(e.ok ? {} : { error: { code: "tool_error", why: e.error ?? "" } }),
21
+ });
22
+ }
23
+ else if (e.type === "SOURCE_COMMITTED") {
24
+ wide.push({ ts: iso(e.ts), runId, tenantId: "cord", cordId: "cord", kind: "tool", name: "source.commit", durationMs: 0, ok: true, attrs: { paths: e.paths } });
25
+ }
26
+ else if (e.type === "RUN_ERROR") {
27
+ wide.push({ ts: iso(e.ts), runId, tenantId: "cord", cordId: "cord", kind: "turn", name: "run", durationMs: 0, ok: false, error: { code: "run_error", why: e.error } });
28
+ }
29
+ }
30
+ return { runId, source: "cord", events: wide, audit };
31
+ }
32
+ /** Build a Session from a coding-agent capture (lapdog/trajectory) via session.ts ingest (→ WideEvents + audit + interceptions). */
33
+ export function agentSession(stream) {
34
+ const t = ingestSession(stream);
35
+ return { runId: t.runId, source: "agent", harness: t.harness, mode: t.mode, events: t.events, audit: t.audit, interceptions: t.interceptions };
36
+ }
37
+ /** Deterministic distillation: summarize a session (+ optional human note) into a SkillDraft skeleton. No model needed. */
38
+ export function distill(session, note, opts = {}) {
39
+ const tools = [];
40
+ const failures = [];
41
+ for (const e of session.events) {
42
+ if (e.kind === "tool" && !tools.includes(e.name))
43
+ tools.push(e.name);
44
+ if (!e.ok)
45
+ failures.push(`${e.name}: ${e.error?.why ?? "failed"}`);
46
+ }
47
+ const flagged = (session.interceptions ?? []).filter((i) => i.decision !== "allow").map((i) => `${i.rule.id} (${i.decision})`);
48
+ const ok = failures.length === 0 && flagged.every((f) => !f.includes("(deny)"));
49
+ const name = opts.name ?? `${session.source}-${tools[0] ?? "session"}-pattern`;
50
+ const seq = session.events.filter((e) => e.kind === "tool").map((e) => e.name);
51
+ const documentation = [
52
+ `# ${name}`,
53
+ "",
54
+ note ? `> ${note}` : `> Distilled from a ${session.source} session (run ${session.runId}).`,
55
+ "",
56
+ "## Observed pattern",
57
+ seq.length ? seq.map((n, i) => `${i + 1}. ${n}`).join("\n") : "_(no tool steps)_",
58
+ "",
59
+ "## Tools",
60
+ tools.length ? tools.map((t) => `- ${t}`).join("\n") : "_(none)_",
61
+ failures.length ? `\n## Failures observed\n${failures.map((f) => `- ${f}`).join("\n")}` : "",
62
+ flagged.length ? `\n## Governance flags\n${flagged.map((f) => `- ${f}`).join("\n")}` : "",
63
+ ].filter(Boolean).join("\n");
64
+ return {
65
+ name,
66
+ description: `${session.source} session pattern over ${tools.length} tool(s): ${tools.slice(0, 4).join(", ") || "—"}.`,
67
+ whenToUse: note ?? `When repeating the ${tools[0] ?? "this"} workflow distilled from run ${session.runId}.`,
68
+ documentation,
69
+ tags: ["distilled", session.source, ...(opts.tags ?? [])],
70
+ evidence: { sourceRunId: session.runId, source: session.source, tools, steps: session.events.length, ok, failures, flagged, ...(note !== undefined ? { note } : {}) },
71
+ };
72
+ }
73
+ /** Optional model-backed enrichment: the Inference port sharpens name/description/whenToUse/doc; falls back to the deterministic draft. */
74
+ export async function distillWithModel(session, note, inference, opts = {}) {
75
+ const base = distill(session, note, opts);
76
+ const prompt = "You distill agent sessions into reusable skills. Given this evidence, write a crisp, reusable skill.\n" +
77
+ `Evidence: ${JSON.stringify(base.evidence)}\nNote: ${note ?? "(none)"}\n` +
78
+ 'Return ONLY JSON: {"name","description","whenToUse","documentation"}.';
79
+ try {
80
+ const res = await inference.generate({ messages: [{ role: "user", content: prompt }] });
81
+ const m = (res.text ?? "").match(/\{[\s\S]*\}/);
82
+ if (m) {
83
+ const j = JSON.parse(m[0]);
84
+ return { ...base, ...j };
85
+ }
86
+ }
87
+ catch {
88
+ /* fall back to the deterministic draft */
89
+ }
90
+ return base;
91
+ }
92
+ /** A no-network sink that collects drafts (tests + dry runs). */
93
+ export function collectSink(into) {
94
+ return async (draft) => {
95
+ into.push(draft);
96
+ return { ok: true, id: draft.name };
97
+ };
98
+ }
99
+ const slugify = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "skill";
100
+ /**
101
+ * Persist a SkillDraft to a durable store as `<prefix>/<slug>.md` (the skill doc) + `<prefix>/<slug>.json` (the
102
+ * structured draft, for promotion to a real KB skill). Returns the `.md` path as the id. Wire `store.put` to the
103
+ * cord's Source so a distilled session becomes a committed artifact (R2 + GitHub) — not just a returned object.
104
+ */
105
+ export function storeSkillSink(store, opts) {
106
+ return async (draft) => {
107
+ const base = `${opts?.prefix ?? "skills"}/${slugify(draft.name)}`;
108
+ await store.put(`${base}.md`, draft.documentation);
109
+ await store.put(`${base}.json`, JSON.stringify(draft, null, 2));
110
+ return { ok: true, id: `${base}.md` };
111
+ };
112
+ }
113
+ //# sourceMappingURL=distill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distill.js","sourceRoot":"","sources":["../src/distill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /** One governed run, as the host reports it to the evlog sink (and the meter counts it). */
2
+ export type AskLedgerEvent = {
3
+ kind: "ask";
4
+ /** The cord's addr (`<team>--<name>` under a team, bare name solo). Tenant derives from the `--` prefix. */
5
+ cord: string;
6
+ /** Run id — the meter's idempotency key (INSERT OR IGNORE by run id). */
7
+ run: string;
8
+ ok: boolean;
9
+ /** Wall-clock duration of the run in ms. */
10
+ ms?: number;
11
+ /** Pure inference time (summed gateway-call ms across loop steps) — excludes tool execution + host
12
+ * overhead. tok/s(out) derives as tokensOut / (modelMs/1000); never stored, always derived. */
13
+ modelMs?: number | null;
14
+ /** Streaming time-to-first-token. Only measurable on streaming surfaces (the chat lane via onChunk);
15
+ * the non-streaming /ask host reports null — a null here is honest, not missing. */
16
+ ttftMs?: number | null;
17
+ tokensIn?: number | null;
18
+ tokensOut?: number | null;
19
+ model?: string;
20
+ engine?: string;
21
+ /** Chain envelope (F1): identity, never authority. */
22
+ root?: string;
23
+ parent?: string | null;
24
+ caller?: string | null;
25
+ depth?: number;
26
+ pattern?: string;
27
+ error?: string;
28
+ /** ISO 8601; the sink stamps its own receive time separately. */
29
+ at?: string;
30
+ };
31
+ /** Build a well-formed ask ledger event. The host's ONLY approved way to author one. */
32
+ export declare function askLedgerEvent(fields: Omit<AskLedgerEvent, "kind" | "at"> & {
33
+ at?: string;
34
+ }): AskLedgerEvent;
35
+ /** Ingest-side guard: is this record a countable governed run? (The meter's admission check.) */
36
+ export declare function isAskLedgerEvent(r: unknown): r is AskLedgerEvent;
37
+ /** The tenant a cord addr belongs to under the LOCKED `<team>--<name>` scheme; null = solo/untenanted. */
38
+ export declare const tenantOfCord: (cord: string) => string | null;
39
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAaA,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,KAAK,CAAC;IACZ,4GAA4G;IAC5G,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,OAAO,CAAC;IACZ,4CAA4C;IAC5C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;oGACgG;IAChG,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;yFACqF;IACrF,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,cAAc,CAE5G;AAED,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,cAAc,CAIhE;AAED,0GAA0G;AAC1G,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,MAAM,GAAG,IAAoE,CAAC"}
package/dist/events.js ADDED
@@ -0,0 +1,25 @@
1
+ // events.ts — the HOST LEDGER event contract, defined ONCE (C1.1, 2026-07-06).
2
+ //
3
+ // Before this file the ask-ledger event existed as three drifting copies: the host entry's ad-hoc
4
+ // object literals, the evlog-sink's hand-rolled `AskEvent`, and nothing canonical in the SDK. That is
5
+ // coupling by copy — invisible until a field renames and the meter silently stops counting. Now:
6
+ // • the HOST builds events through `askLedgerEvent(...)` (bundled into sdk.mjs via gen-sdk-base),
7
+ // • the SINK validates ingest with `isAskLedgerEvent(...)` before metering,
8
+ // • both import THIS shape — one definition, one enforcement point, zero copies.
9
+ //
10
+ // Distinct from guards.ts `WideEvent` on purpose: WideEvent is the IN-RUN observability lane
11
+ // (turn/step/model/tool/eval); AskLedgerEvent is the host's PER-RUN billing/ops record — the thing
12
+ // the meter counts. Plain TS, no zod: this rides the hot path of every governed run.
13
+ /** Build a well-formed ask ledger event. The host's ONLY approved way to author one. */
14
+ export function askLedgerEvent(fields) {
15
+ return { kind: "ask", at: fields.at ?? new Date().toISOString(), ...fields };
16
+ }
17
+ /** Ingest-side guard: is this record a countable governed run? (The meter's admission check.) */
18
+ export function isAskLedgerEvent(r) {
19
+ const e = r;
20
+ return Boolean(e) && e.kind === "ask" && typeof e.cord === "string" && e.cord.length > 0
21
+ && typeof e.run === "string" && e.run.length > 0 && typeof e.ok === "boolean";
22
+ }
23
+ /** The tenant a cord addr belongs to under the LOCKED `<team>--<name>` scheme; null = solo/untenanted. */
24
+ export const tenantOfCord = (cord) => (cord.includes("--") ? (cord.split("--")[0] ?? null) : null);
25
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,kGAAkG;AAClG,sGAAsG;AACtG,iGAAiG;AACjG,oGAAoG;AACpG,8EAA8E;AAC9E,mFAAmF;AACnF,EAAE;AACF,6FAA6F;AAC7F,mGAAmG;AACnG,qFAAqF;AA8BrF,wFAAwF;AACxF,MAAM,UAAU,cAAc,CAAC,MAA6D;IAC1F,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC;AAC/E,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,gBAAgB,CAAC,CAAU;IACzC,MAAM,CAAC,GAAG,CAAmB,CAAC;IAC9B,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;WACnF,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC;AAClF,CAAC;AAED,0GAA0G;AAC1G,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAY,EAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC"}