@vendoai/agent 0.4.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 (51) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +26 -0
  3. package/dist/agent.d.ts +62 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +443 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/capability-miss.d.ts +24 -0
  8. package/dist/capability-miss.d.ts.map +1 -0
  9. package/dist/capability-miss.js +133 -0
  10. package/dist/capability-miss.js.map +1 -0
  11. package/dist/ids.d.ts +6 -0
  12. package/dist/ids.d.ts.map +1 -0
  13. package/dist/ids.js +9 -0
  14. package/dist/ids.js.map +1 -0
  15. package/dist/index.d.ts +8 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +4 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/pack.d.ts +37 -0
  20. package/dist/pack.d.ts.map +1 -0
  21. package/dist/pack.js +225 -0
  22. package/dist/pack.js.map +1 -0
  23. package/dist/prompt.d.ts +8 -0
  24. package/dist/prompt.d.ts.map +1 -0
  25. package/dist/prompt.js +43 -0
  26. package/dist/prompt.js.map +1 -0
  27. package/dist/runner.d.ts +20 -0
  28. package/dist/runner.d.ts.map +1 -0
  29. package/dist/runner.js +114 -0
  30. package/dist/runner.js.map +1 -0
  31. package/dist/test-helpers.d.ts +55 -0
  32. package/dist/test-helpers.d.ts.map +1 -0
  33. package/dist/test-helpers.js +230 -0
  34. package/dist/test-helpers.js.map +1 -0
  35. package/dist/threads.d.ts +48 -0
  36. package/dist/threads.d.ts.map +1 -0
  37. package/dist/threads.js +251 -0
  38. package/dist/threads.js.map +1 -0
  39. package/dist/tool-pack.d.ts +41 -0
  40. package/dist/tool-pack.d.ts.map +1 -0
  41. package/dist/tool-pack.js +17 -0
  42. package/dist/tool-pack.js.map +1 -0
  43. package/dist/tool-search.d.ts +72 -0
  44. package/dist/tool-search.d.ts.map +1 -0
  45. package/dist/tool-search.js +135 -0
  46. package/dist/tool-search.js.map +1 -0
  47. package/dist/tools.d.ts +22 -0
  48. package/dist/tools.d.ts.map +1 -0
  49. package/dist/tools.js +151 -0
  50. package/dist/tools.js.map +1 -0
  51. package/package.json +63 -0
@@ -0,0 +1,230 @@
1
+ import { MockLanguageModelV3, simulateReadableStream } from "ai/test";
2
+ import { expect } from "vitest";
3
+ export const ZERO_USAGE = {
4
+ inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },
5
+ outputTokens: { total: 0, text: 0, reasoning: 0 },
6
+ };
7
+ export function textTurn(text, id = "text_1") {
8
+ return [
9
+ { type: "text-start", id },
10
+ { type: "text-delta", id, delta: text },
11
+ { type: "text-end", id },
12
+ { type: "finish", usage: ZERO_USAGE, finishReason: { unified: "stop", raw: undefined } },
13
+ ];
14
+ }
15
+ export function toolCallTurn(toolName, input, toolCallId = "call_1") {
16
+ return [
17
+ { type: "tool-call", toolCallId, toolName, input: JSON.stringify(input) },
18
+ { type: "finish", usage: ZERO_USAGE, finishReason: { unified: "tool-calls", raw: undefined } },
19
+ ];
20
+ }
21
+ export function scriptedModel(turns) {
22
+ const remaining = turns.map((turn) => [...turn]);
23
+ const prompts = [];
24
+ const toolNamesPerCall = [];
25
+ const shift = (request) => {
26
+ prompts.push(structuredClone(request.prompt));
27
+ toolNamesPerCall.push((request.tools ?? []).map((tool) => tool.name));
28
+ const chunks = remaining.shift();
29
+ if (chunks === undefined)
30
+ throw new Error("scripted model exhausted");
31
+ return chunks;
32
+ };
33
+ const model = new MockLanguageModelV3({
34
+ doStream: async (request) => {
35
+ const chunks = shift(request);
36
+ return { stream: simulateReadableStream({ chunks }) };
37
+ },
38
+ doGenerate: async (request) => {
39
+ const chunks = shift(request);
40
+ const finish = chunks.find((part) => part.type === "finish");
41
+ const content = [];
42
+ const text = chunks
43
+ .filter((part) => part.type === "text-delta")
44
+ .map((part) => part.delta)
45
+ .join("");
46
+ if (text.length > 0)
47
+ content.push({ type: "text", text });
48
+ for (const part of chunks) {
49
+ if (part.type === "tool-call")
50
+ content.push(structuredClone(part));
51
+ }
52
+ return {
53
+ content,
54
+ finishReason: finish?.finishReason ?? { unified: "stop", raw: undefined },
55
+ usage: finish?.usage ?? ZERO_USAGE,
56
+ warnings: [],
57
+ };
58
+ },
59
+ });
60
+ model.prompts = prompts;
61
+ model.toolNamesPerCall = toolNamesPerCall;
62
+ return model;
63
+ }
64
+ function deepFreeze(value) {
65
+ if (value !== null && typeof value === "object") {
66
+ for (const child of Object.values(value))
67
+ deepFreeze(child);
68
+ Object.freeze(value);
69
+ }
70
+ return value;
71
+ }
72
+ export function testGuard(policy, directions = []) {
73
+ const approvalsByCall = new Map();
74
+ const decisions = new Map();
75
+ const subscribers = new Set();
76
+ const events = [];
77
+ const directionValues = [...directions];
78
+ const guard = {
79
+ events,
80
+ directionValues,
81
+ abandoned: [],
82
+ // AGENT-6: mirror the real guard — abandoning denies each still-pending
83
+ // approval (idempotent; unknown/decided ids are no-ops) and notifies
84
+ // decision subscribers.
85
+ async abandonApprovals(ids) {
86
+ for (const id of ids) {
87
+ const known = [...approvalsByCall.values()].some((approval) => approval.id === id);
88
+ if (!known || decisions.has(id))
89
+ continue;
90
+ guard.abandoned.push(id);
91
+ guard.decide(id, false);
92
+ }
93
+ },
94
+ async check(call, descriptor, runCtx) {
95
+ const action = policy[call.tool] ?? "run";
96
+ if (action === "run")
97
+ return { action: "run", decidedBy: "default" };
98
+ if (action === "block")
99
+ return { action: "block", reason: "blocked", decidedBy: "rule" };
100
+ let approval = approvalsByCall.get(call.id);
101
+ if (approval === undefined) {
102
+ approval = {
103
+ id: `apr_${call.id}`,
104
+ call: structuredClone(call),
105
+ descriptor: deepFreeze(structuredClone(descriptor)),
106
+ inputPreview: JSON.stringify(call.args),
107
+ ctx: {
108
+ principal: structuredClone(runCtx.principal),
109
+ venue: runCtx.venue,
110
+ presence: runCtx.presence,
111
+ ...(runCtx.appId === undefined ? {} : { appId: runCtx.appId }),
112
+ ...(runCtx.trigger === undefined ? {} : { trigger: structuredClone(runCtx.trigger) }),
113
+ },
114
+ createdAt: new Date().toISOString(),
115
+ };
116
+ approvalsByCall.set(call.id, approval);
117
+ }
118
+ const approved = decisions.get(approval.id);
119
+ if (approved === true)
120
+ return { action: "run", decidedBy: "default" };
121
+ if (approved === false)
122
+ return { action: "block", reason: "denied", decidedBy: "rule" };
123
+ return { action: "ask", approval, decidedBy: "rule" };
124
+ },
125
+ async report(event) {
126
+ events.push(structuredClone(event));
127
+ },
128
+ async directions() {
129
+ return [...directionValues];
130
+ },
131
+ onApprovalDecision(callback) {
132
+ subscribers.add(callback);
133
+ return () => subscribers.delete(callback);
134
+ },
135
+ decide(approvalId, approved) {
136
+ decisions.set(approvalId, approved);
137
+ for (const subscriber of subscribers)
138
+ subscriber(approvalId, approved);
139
+ },
140
+ pending() {
141
+ return [...approvalsByCall.values()].filter((approval) => !decisions.has(approval.id));
142
+ },
143
+ };
144
+ return guard;
145
+ }
146
+ export function boundRegistry(implementations, guard) {
147
+ const invocations = Object.fromEntries(Object.keys(implementations).map((name) => [name, 0]));
148
+ return {
149
+ invocations,
150
+ async descriptors() {
151
+ return Object.values(implementations).map(({ descriptor }) => structuredClone(descriptor));
152
+ },
153
+ async execute(call, runCtx) {
154
+ const implementation = implementations[call.tool];
155
+ if (implementation === undefined) {
156
+ return { status: "error", error: { code: "not-found", message: `Unknown tool: ${call.tool}` } };
157
+ }
158
+ const decision = await guard.check(call, implementation.descriptor, runCtx);
159
+ let outcome;
160
+ if (decision.action === "block") {
161
+ outcome = { status: "blocked", reason: decision.reason };
162
+ }
163
+ else if (decision.action === "ask") {
164
+ outcome = { status: "pending-approval", approvalId: decision.approval.id };
165
+ }
166
+ else {
167
+ invocations[call.tool] = (invocations[call.tool] ?? 0) + 1;
168
+ try {
169
+ outcome = { status: "ok", output: await implementation.execute(call.args, runCtx, call) };
170
+ }
171
+ catch (error) {
172
+ outcome = {
173
+ status: "error",
174
+ error: {
175
+ code: "execution",
176
+ message: error instanceof Error ? error.message : String(error),
177
+ },
178
+ };
179
+ }
180
+ }
181
+ await guard.report({
182
+ id: `aud_${call.id}`,
183
+ at: new Date().toISOString(),
184
+ kind: "tool-call",
185
+ principal: structuredClone(runCtx.principal),
186
+ venue: runCtx.venue,
187
+ presence: runCtx.presence,
188
+ ...(runCtx.appId === undefined ? {} : { appId: runCtx.appId }),
189
+ ...(runCtx.trigger === undefined ? {} : { trigger: structuredClone(runCtx.trigger) }),
190
+ tool: call.tool,
191
+ inputPreview: JSON.stringify(call.args),
192
+ outcome: outcome.status,
193
+ decidedBy: decision.decidedBy,
194
+ });
195
+ return outcome;
196
+ },
197
+ };
198
+ }
199
+ // The core conformance kit ships the reference in-memory StoreAdapter; tests
200
+ // exercise the same double every other block will use.
201
+ export { memoryStoreAdapter as memoryStore } from "@vendoai/core/conformance";
202
+ export async function readSse(response) {
203
+ const raw = await response.text();
204
+ expect(raw.endsWith("\n\n")).toBe(true);
205
+ const blocks = raw.slice(0, -2).split("\n\n");
206
+ expect(blocks.length).toBeGreaterThan(0);
207
+ expect(blocks.every((block) => block.startsWith("data: ") && !block.includes("\n"))).toBe(true);
208
+ const rawFrames = blocks.map((block) => `${block}\n\n`);
209
+ expect(rawFrames.at(-1)).toBe("data: [DONE]\n\n");
210
+ const parts = blocks.slice(0, -1).map((block) => JSON.parse(block.slice("data: ".length)));
211
+ return { rawFrames, parts };
212
+ }
213
+ export function ctx(overrides = {}) {
214
+ return {
215
+ principal: { kind: "user", subject: "u1" },
216
+ venue: "chat",
217
+ presence: "present",
218
+ sessionId: "s1",
219
+ ...overrides,
220
+ };
221
+ }
222
+ /** A minimal single-text-part user UIMessage — the shape every suite feeds stream(). */
223
+ export function userMessage(id, text) {
224
+ return { id, role: "user", parts: [{ type: "text", text }] };
225
+ }
226
+ /** The first assembled UIMessage part of a given type (e.g. "data-vendo-view"). */
227
+ export function partOfType(message, type) {
228
+ return message.parts.find((part) => part.type === type);
229
+ }
230
+ //# sourceMappingURL=test-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { type IsoDateTime, type RunContext, type StoreAdapter, type ThreadId } from "@vendoai/core";
2
+ import type { UIMessage } from "ai";
3
+ /** 03-agent §5 */
4
+ export interface Thread {
5
+ id: ThreadId;
6
+ subject: string;
7
+ messages: UIMessage[];
8
+ /** Precomputed listing title. Persisted beside the thread so `list` need not load the
9
+ * full messages array to derive it; absent on legacy rows (derived from messages then). */
10
+ title?: string;
11
+ createdAt: IsoDateTime;
12
+ updatedAt: IsoDateTime;
13
+ }
14
+ /** 03-agent §5 */
15
+ export interface ThreadSummary {
16
+ id: ThreadId;
17
+ title: string;
18
+ updatedAt: IsoDateTime;
19
+ }
20
+ /** 03-agent §5 */
21
+ export declare class ThreadRepository {
22
+ private readonly store;
23
+ constructor(store: StoreAdapter);
24
+ resolve(id: ThreadId | undefined, ctx: RunContext): Promise<Thread>;
25
+ get(id: ThreadId, ctx: RunContext): Promise<Thread | null>;
26
+ list(ctx: RunContext): Promise<ThreadSummary[]>;
27
+ delete(id: ThreadId, ctx: RunContext): Promise<void>;
28
+ persist(thread: Thread, messages: UIMessage[]): Promise<void>;
29
+ /** The Thread as it should be written for this turn: merged messages, a
30
+ * freshly-derived listing title (never a stale prior title — `list` reads it
31
+ * back without loading messages), and a new updatedAt. */
32
+ private updatedThread;
33
+ private create;
34
+ /** AGENT-11 / ENG-237: drop a subject's threads from the store on session
35
+ * eviction. Store-backed: a no-op — the store's own TTL sweep already erased
36
+ * the rows (02-store §4 erase cascade) before the umbrella calls this, so the
37
+ * list below simply finds none. Internal-default (no `store` configured):
38
+ * the ONLY place those rows get reclaimed, since nothing else sweeps them.
39
+ * Returns the evicted thread ids so callers can release any per-thread state
40
+ * keyed by id (ENG-252 loadouts) — otherwise a reused `thr_*` id would inherit
41
+ * the evicted thread's searched-in tools. */
42
+ evictSubject(subject: string): Promise<ThreadId[]>;
43
+ /** Follows the store's pagination cursor to exhaustion (it pages at 100) —
44
+ * otherwise a subject's >100th thread, possibly their most recently active,
45
+ * would silently vanish from `list`/`evictSubject`. */
46
+ private listRecords;
47
+ }
48
+ //# sourceMappingURL=threads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../src/threads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAoB,MAAM,eAAe,CAAC;AAClI,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAMpC,kBAAkB;AAClB,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,QAAQ,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB;gGAC4F;IAC5F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,EAAE,WAAW,CAAC;CACxB;AAED,kBAAkB;AAClB,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,QAAQ,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,WAAW,CAAC;CACxB;AAqFD,kBAAkB;AAClB,qBAAa,gBAAgB;IAOf,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,YAAY;IAE1C,OAAO,CAAC,EAAE,EAAE,QAAQ,GAAG,SAAS,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBnE,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAY1D,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAU/C,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAUpD,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8CnE;;+DAE2D;IAC3D,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,MAAM;IAWd;;;;;;;kDAO8C;IACxC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAOxD;;4DAEwD;YAC1C,WAAW;CAa1B"}
@@ -0,0 +1,251 @@
1
+ import { VendoError } from "@vendoai/core";
2
+ import { mintThreadId } from "./ids.js";
3
+ const THREAD_COLLECTION = "vendo_threads";
4
+ const THREAD_ID_PATTERN = /^thr_.+$/;
5
+ /** Reconstruct a Thread from a store record. The store seam (core §12) carries
6
+ * the id + timestamps on the VendoRecord envelope and the reserved
7
+ * vendo_threads routing projects `data` down to `{ subject, messages }` (02
8
+ * §2) — so the whole Thread is never inside `data`. Read it back from the
9
+ * envelope, not from `data`. */
10
+ function threadFromRecord(record) {
11
+ if (!THREAD_ID_PATTERN.test(record.id))
12
+ return null;
13
+ // Timestamps ride the envelope, but a hand-written row (threadStore(store).put
14
+ // accepts any Json) could still be malformed — validate before trusting them so
15
+ // one bad row cannot brick the whole listing.
16
+ if (typeof record.createdAt !== "string" || typeof record.updatedAt !== "string")
17
+ return null;
18
+ const data = record.data;
19
+ if (typeof data !== "object" || data === null)
20
+ return null;
21
+ const candidate = data;
22
+ if (typeof candidate.subject !== "string" || !Array.isArray(candidate.messages))
23
+ return null;
24
+ return {
25
+ id: record.id,
26
+ subject: candidate.subject,
27
+ messages: candidate.messages,
28
+ ...(typeof candidate.title === "string" ? { title: candidate.title } : {}),
29
+ createdAt: record.createdAt,
30
+ updatedAt: record.updatedAt,
31
+ };
32
+ }
33
+ function titleFor(thread) {
34
+ // A persisted title short-circuits the message scan (and the listing skips loading the
35
+ // messages array entirely once a title exists — routing.ts).
36
+ if (typeof thread.title === "string" && thread.title.trim())
37
+ return thread.title.slice(0, 80);
38
+ return deriveTitle(thread.messages);
39
+ }
40
+ function deriveTitle(messages) {
41
+ // Messages come from a Json array (parseThreadData accepts any shape), so a
42
+ // message may lack an iterable `parts` or carry non-text parts — tolerate both,
43
+ // skipping rather than throwing.
44
+ for (const message of messages) {
45
+ if (message === null || typeof message !== "object")
46
+ continue;
47
+ if (message.role !== "user")
48
+ continue;
49
+ const parts = message.parts;
50
+ if (!Array.isArray(parts))
51
+ continue;
52
+ for (const part of parts) {
53
+ if (part !== null && typeof part === "object"
54
+ && part.type === "text"
55
+ && typeof part.text === "string") {
56
+ const title = part.text.trim();
57
+ return title ? title.slice(0, 80) : "New thread";
58
+ }
59
+ }
60
+ }
61
+ return "New thread";
62
+ }
63
+ function toSummary(thread) {
64
+ return { id: thread.id, title: titleFor(thread), updatedAt: thread.updatedAt };
65
+ }
66
+ /** Serialize to plain JSON so the value satisfies the store seam's `Json` type
67
+ * (drops explicit `undefined`-valued props that JSON.stringify would omit). */
68
+ function toPlainJson(messages) {
69
+ return JSON.parse(JSON.stringify(messages));
70
+ }
71
+ // ENG-310 / kill-list B5: how many times persist re-reads and re-merges after
72
+ // losing a CAS race. Each retry starts from the freshly-read row, so a loss
73
+ // only recurs while OTHER writers keep landing between our read and our
74
+ // guarded write.
75
+ const MAX_PERSIST_ATTEMPTS = 5;
76
+ /** ENG-310: fold this turn's messages into the CURRENT persisted history —
77
+ * upsert by message id (same identity rule as the in-stream upsertMessage),
78
+ * so two concurrent turns on one thread both survive: shared history is
79
+ * updated in place, each turn's new messages are appended. */
80
+ function mergeMessages(current, turn) {
81
+ const merged = [...current];
82
+ for (const message of turn) {
83
+ const index = merged.findIndex((candidate) => candidate.id === message.id);
84
+ if (index === -1)
85
+ merged.push(message);
86
+ else
87
+ merged[index] = message;
88
+ }
89
+ return merged;
90
+ }
91
+ /** 03-agent §5 */
92
+ export class ThreadRepository {
93
+ store;
94
+ // kill-list B5: threads live ONLY in the store — a caller that omits
95
+ // `createAgent({ store })` still gets one; `createAgent` (agent.ts) passes
96
+ // core's in-memory `memoryStoreAdapter` (@vendoai/core/conformance) as that
97
+ // default, so every composition — BYO or store-backed — resolves, lists,
98
+ // persists, and evicts threads through this SAME code path. There is no
99
+ // separate in-memory branch here to keep behavior-parity with.
100
+ constructor(store) {
101
+ this.store = store;
102
+ }
103
+ async resolve(id, ctx) {
104
+ if (id === undefined)
105
+ return this.create(ctx);
106
+ if (!THREAD_ID_PATTERN.test(id)) {
107
+ throw new VendoError("validation", "threadId is malformed");
108
+ }
109
+ // ONE ownership-blind read is the friendly fast-path (03 §5). vendo_threads is
110
+ // keyed by the bare id, so a foreign row reads as non-null here; reusing the id
111
+ // would let persist() take it over. Free id → create; ours → return; anyone
112
+ // else's (or unparseable) → conflict. The store's guarded upsert is the real,
113
+ // atomic guarantee — this only surfaces the conflict early with a clear error.
114
+ // Ephemeral principals resolve through this exact path too (02-store §4: no
115
+ // overlay, ordinary rows under their subject) — nothing here is BYO-specific.
116
+ const record = await this.store.records(THREAD_COLLECTION).get(id);
117
+ if (record === null)
118
+ return this.create(ctx, id);
119
+ const thread = threadFromRecord(record);
120
+ if (thread !== null && thread.subject === ctx.principal.subject)
121
+ return thread;
122
+ throw new VendoError("conflict", "threadId is already in use");
123
+ }
124
+ async get(id, ctx) {
125
+ if (!THREAD_ID_PATTERN.test(id))
126
+ return null;
127
+ // Reserved vendo_threads rows are keyed by the bare thread id (02 §2:
128
+ // `id` is the thread id). Subject scoping is enforced here, on read, by
129
+ // checking the row's subject — never returning another subject's thread.
130
+ const record = await this.store.records(THREAD_COLLECTION).get(id);
131
+ if (!record)
132
+ return null;
133
+ const thread = threadFromRecord(record);
134
+ if (!thread || thread.subject !== ctx.principal.subject)
135
+ return null;
136
+ return thread;
137
+ }
138
+ async list(ctx) {
139
+ const records = await this.listRecords({ subject: ctx.principal.subject });
140
+ const threads = records
141
+ .map(threadFromRecord)
142
+ .filter((thread) => thread !== null && thread.subject === ctx.principal.subject);
143
+ return threads
144
+ .map(toSummary)
145
+ .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
146
+ }
147
+ async delete(id, ctx) {
148
+ if (!THREAD_ID_PATTERN.test(id))
149
+ return;
150
+ // The bare id is shared across subjects; delete only after confirming the
151
+ // row belongs to this subject (get() returns null otherwise), so one
152
+ // subject can never delete another's thread (03 §5).
153
+ const existing = await this.get(id, ctx);
154
+ if (existing === null)
155
+ return;
156
+ await this.store.records(THREAD_COLLECTION).delete(id);
157
+ }
158
+ async persist(thread, messages) {
159
+ // ai-SDK UIMessages carry explicit `undefined`-valued optional props on
160
+ // tool parts (e.g. an approval-requested part with no output yet). The
161
+ // store seam is typed `Json` and rejects `undefined` values, so serialize
162
+ // to plain JSON — dropping absent-anyway keys — before it crosses.
163
+ const turnMessages = toPlainJson(messages);
164
+ const records = this.store.records(THREAD_COLLECTION);
165
+ // Guarded write via the store's atomic capability (01 §12 / 02-store §4):
166
+ // insert-if-absent for a first turn, revision CAS for an existing row —
167
+ // exactly one concurrent writer lands per attempt; the loser re-reads and
168
+ // re-merges (ENG-310 / AGENT-9: two overlapping turns on one thread each
169
+ // finish with their OWN copy of the history, so persist is read-merge-write,
170
+ // never a blind overwrite). No fallback: v2 has no adapter or row that
171
+ // predates the capability (kill-list B5 — same reasoning as the crypto v1
172
+ // cut), so an adapter that omits `atomic` fails closed rather than risking
173
+ // a lost update under concurrent writers.
174
+ const atomic = records.atomic;
175
+ if (atomic === undefined) {
176
+ throw new VendoError("not-implemented", "thread persistence needs a store with atomic record claims (02-store §4); this adapter omits the capability");
177
+ }
178
+ for (let attempt = 0; attempt < MAX_PERSIST_ATTEMPTS; attempt += 1) {
179
+ const record = await records.get(thread.id);
180
+ const current = record === null ? null : threadFromRecord(record);
181
+ if (current !== null && current.subject !== thread.subject) {
182
+ // Mirror the door's guarded upsert (03 §5): never take over a foreign row.
183
+ throw new VendoError("conflict", "threadId is already in use");
184
+ }
185
+ const updated = this.updatedThread(thread, current === null ? turnMessages : mergeMessages(current.messages, turnMessages));
186
+ const input = { id: updated.id, data: updated, refs: { subject: updated.subject } };
187
+ const written = record === null
188
+ ? await atomic.insertIfAbsent(input)
189
+ : await atomic.compareAndSwap(input, record.revision);
190
+ if (written !== null)
191
+ return;
192
+ }
193
+ throw new VendoError("conflict", `thread ${thread.id} persist lost the update race ${MAX_PERSIST_ATTEMPTS} times`);
194
+ }
195
+ /** The Thread as it should be written for this turn: merged messages, a
196
+ * freshly-derived listing title (never a stale prior title — `list` reads it
197
+ * back without loading messages), and a new updatedAt. */
198
+ updatedThread(thread, messages) {
199
+ return {
200
+ ...thread,
201
+ messages,
202
+ title: deriveTitle(messages),
203
+ updatedAt: new Date().toISOString(),
204
+ };
205
+ }
206
+ // create() never writes: it hands back a fresh, not-yet-persisted Thread.
207
+ // The first persist() call is what puts the row in the store — same for
208
+ // every composition, so a get()/list() before that first persist correctly
209
+ // sees nothing yet, exactly as a store-backed agent always has.
210
+ create(ctx, requestedId) {
211
+ const now = new Date().toISOString();
212
+ return {
213
+ id: requestedId ?? mintThreadId(),
214
+ subject: ctx.principal.subject,
215
+ messages: [],
216
+ createdAt: now,
217
+ updatedAt: now,
218
+ };
219
+ }
220
+ /** AGENT-11 / ENG-237: drop a subject's threads from the store on session
221
+ * eviction. Store-backed: a no-op — the store's own TTL sweep already erased
222
+ * the rows (02-store §4 erase cascade) before the umbrella calls this, so the
223
+ * list below simply finds none. Internal-default (no `store` configured):
224
+ * the ONLY place those rows get reclaimed, since nothing else sweeps them.
225
+ * Returns the evicted thread ids so callers can release any per-thread state
226
+ * keyed by id (ENG-252 loadouts) — otherwise a reused `thr_*` id would inherit
227
+ * the evicted thread's searched-in tools. */
228
+ async evictSubject(subject) {
229
+ const records = await this.listRecords({ subject });
230
+ const ids = records.map((record) => record.id);
231
+ await Promise.all(ids.map((id) => this.store.records(THREAD_COLLECTION).delete(id)));
232
+ return ids;
233
+ }
234
+ /** Follows the store's pagination cursor to exhaustion (it pages at 100) —
235
+ * otherwise a subject's >100th thread, possibly their most recently active,
236
+ * would silently vanish from `list`/`evictSubject`. */
237
+ async listRecords(refs) {
238
+ const records = [];
239
+ let cursor;
240
+ do {
241
+ const result = await this.store.records(THREAD_COLLECTION).list({
242
+ refs,
243
+ ...(cursor === undefined ? {} : { cursor }),
244
+ });
245
+ records.push(...result.records);
246
+ cursor = result.cursor;
247
+ } while (cursor !== undefined);
248
+ return records;
249
+ }
250
+ }
251
+ //# sourceMappingURL=threads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threads.js","sourceRoot":"","sources":["../src/threads.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type { AgentRunReport, Principal, VendoToolEnvelope } from "@vendoai/core";
2
+ /**
3
+ * Existing-agents contract — the public tool-pack surface a BYO agent loop
4
+ * gets from the umbrella's `./ai-sdk` and `./mastra` subpaths. Wave 0 freezes
5
+ * the names and option shapes here (the docs, examples, and both shims build
6
+ * against them); Wave 1 Lane A supplies the implementation behind them.
7
+ * Frozen in `docs/superpowers/specs/2026-07-20-existing-agents-contracts.md`.
8
+ */
9
+ /** Every pack tool is namespaced under this prefix to avoid collisions with
10
+ * the host loop's own tools: a registered host tool `host_x` ships as
11
+ * `vendo_host_x`; the built-ins below are already prefixed. */
12
+ export declare const VENDO_TOOL_PACK_PREFIX: "vendo_";
13
+ /** Generate UI. Returns fast with a `vendo/app-ref@1`; the build streams over
14
+ * the wire, so the host loop is never blocked on generation. */
15
+ export declare const VENDO_CREATE_APP_TOOL: "vendo_create_app";
16
+ /** Whole-task delegation via `agent.asRunner()`; returns `VendoDelegateResult`. */
17
+ export declare const VENDO_DELEGATE_TOOL: "vendo_delegate";
18
+ /** Pack filtering, matched against FINAL (namespaced) tool names. The static
19
+ * Mastra shim accepts exactly this (its principal resolves lazily per call
20
+ * from the framework's runtime context). */
21
+ export interface VendoToolPackFilter {
22
+ include?: string[];
23
+ exclude?: string[];
24
+ }
25
+ /** What the per-request AI SDK shim accepts: tool execution needs a
26
+ * principal-scoped RunContext, so the pack is built per request. */
27
+ export interface VendoToolPackOptions extends VendoToolPackFilter {
28
+ principal: Principal;
29
+ /** RunContext requires a session id; pass the host session's for audit
30
+ * continuity, or leave unset and the shim mints one per pack build. */
31
+ sessionId?: string;
32
+ }
33
+ /** `vendo_delegate`'s output is plain data (no embed): the run report's
34
+ * status and summary, plus envelope refs to anything the delegated run
35
+ * produced — the host renders each ref with `<VendoToolResult>` if it wants. */
36
+ export interface VendoDelegateResult {
37
+ status: AgentRunReport["status"];
38
+ summary: string;
39
+ refs: VendoToolEnvelope[];
40
+ }
41
+ //# sourceMappingURL=tool-pack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-pack.d.ts","sourceRoot":"","sources":["../src/tool-pack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElF;;;;;;GAMG;AAEH;;gEAEgE;AAChE,eAAO,MAAM,sBAAsB,EAAG,QAAiB,CAAC;AAExD;iEACiE;AACjE,eAAO,MAAM,qBAAqB,EAAG,kBAA2B,CAAC;AAEjE,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,EAAG,gBAAyB,CAAC;AAE7D;;6CAE6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;qEACqE;AACrE,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,SAAS,EAAE,SAAS,CAAC;IACrB;4EACwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;iFAEiF;AACjF,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,iBAAiB,EAAE,CAAC;CAC3B"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Existing-agents contract — the public tool-pack surface a BYO agent loop
3
+ * gets from the umbrella's `./ai-sdk` and `./mastra` subpaths. Wave 0 freezes
4
+ * the names and option shapes here (the docs, examples, and both shims build
5
+ * against them); Wave 1 Lane A supplies the implementation behind them.
6
+ * Frozen in `docs/superpowers/specs/2026-07-20-existing-agents-contracts.md`.
7
+ */
8
+ /** Every pack tool is namespaced under this prefix to avoid collisions with
9
+ * the host loop's own tools: a registered host tool `host_x` ships as
10
+ * `vendo_host_x`; the built-ins below are already prefixed. */
11
+ export const VENDO_TOOL_PACK_PREFIX = "vendo_";
12
+ /** Generate UI. Returns fast with a `vendo/app-ref@1`; the build streams over
13
+ * the wire, so the host loop is never blocked on generation. */
14
+ export const VENDO_CREATE_APP_TOOL = "vendo_create_app";
15
+ /** Whole-task delegation via `agent.asRunner()`; returns `VendoDelegateResult`. */
16
+ export const VENDO_DELEGATE_TOOL = "vendo_delegate";
17
+ //# sourceMappingURL=tool-pack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-pack.js","sourceRoot":"","sources":["../src/tool-pack.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH;;gEAEgE;AAChE,MAAM,CAAC,MAAM,sBAAsB,GAAG,QAAiB,CAAC;AAExD;iEACiE;AACjE,MAAM,CAAC,MAAM,qBAAqB,GAAG,kBAA2B,CAAC;AAEjE,mFAAmF;AACnF,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAyB,CAAC"}