@intentface/latch-core 0.9.1
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/LICENSE +21 -0
- package/README.md +45 -0
- package/dist/agent.d.ts +200 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +9 -0
- package/dist/agent.js.map +1 -0
- package/dist/compaction.d.ts +33 -0
- package/dist/compaction.d.ts.map +1 -0
- package/dist/compaction.js +104 -0
- package/dist/compaction.js.map +1 -0
- package/dist/connections.d.ts +16 -0
- package/dist/connections.d.ts.map +1 -0
- package/dist/connections.js +41 -0
- package/dist/connections.js.map +1 -0
- package/dist/context.d.ts +41 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +25 -0
- package/dist/context.js.map +1 -0
- package/dist/current-date.d.ts +12 -0
- package/dist/current-date.d.ts.map +1 -0
- package/dist/current-date.js +25 -0
- package/dist/current-date.js.map +1 -0
- package/dist/extensions.d.ts +333 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +569 -0
- package/dist/extensions.js.map +1 -0
- package/dist/harness/index.d.ts +17 -0
- package/dist/harness/index.d.ts.map +1 -0
- package/dist/harness/index.js +15 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/harness/tools.d.ts +88 -0
- package/dist/harness/tools.d.ts.map +1 -0
- package/dist/harness/tools.js +296 -0
- package/dist/harness/tools.js.map +1 -0
- package/dist/harness/web-fetch.d.ts +47 -0
- package/dist/harness/web-fetch.d.ts.map +1 -0
- package/dist/harness/web-fetch.js +247 -0
- package/dist/harness/web-fetch.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/limits.d.ts +152 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/limits.js +97 -0
- package/dist/limits.js.map +1 -0
- package/dist/memory.d.ts +93 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +13 -0
- package/dist/memory.js.map +1 -0
- package/dist/message.d.ts +46 -0
- package/dist/message.d.ts.map +1 -0
- package/dist/message.js +2 -0
- package/dist/message.js.map +1 -0
- package/dist/models/catalog.d.ts +56 -0
- package/dist/models/catalog.d.ts.map +1 -0
- package/dist/models/catalog.js +211 -0
- package/dist/models/catalog.js.map +1 -0
- package/dist/models/defaults.d.ts +23 -0
- package/dist/models/defaults.d.ts.map +1 -0
- package/dist/models/defaults.js +19 -0
- package/dist/models/defaults.js.map +1 -0
- package/dist/models/index.d.ts +23 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +19 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/prompt-caching.d.ts +19 -0
- package/dist/models/prompt-caching.d.ts.map +1 -0
- package/dist/models/prompt-caching.js +18 -0
- package/dist/models/prompt-caching.js.map +1 -0
- package/dist/models/provider.d.ts +19 -0
- package/dist/models/provider.d.ts.map +1 -0
- package/dist/models/provider.js +22 -0
- package/dist/models/provider.js.map +1 -0
- package/dist/models/reasoning.d.ts +21 -0
- package/dist/models/reasoning.d.ts.map +1 -0
- package/dist/models/reasoning.js +59 -0
- package/dist/models/reasoning.js.map +1 -0
- package/dist/pricing.d.ts +52 -0
- package/dist/pricing.d.ts.map +1 -0
- package/dist/pricing.js +37 -0
- package/dist/pricing.js.map +1 -0
- package/dist/principal.d.ts +37 -0
- package/dist/principal.d.ts.map +1 -0
- package/dist/principal.js +30 -0
- package/dist/principal.js.map +1 -0
- package/dist/projections.d.ts +37 -0
- package/dist/projections.d.ts.map +1 -0
- package/dist/projections.js +128 -0
- package/dist/projections.js.map +1 -0
- package/dist/prompt-caching.d.ts +106 -0
- package/dist/prompt-caching.d.ts.map +1 -0
- package/dist/prompt-caching.js +165 -0
- package/dist/prompt-caching.js.map +1 -0
- package/dist/runtime.d.ts +670 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +2425 -0
- package/dist/runtime.js.map +1 -0
- package/dist/scheduler.d.ts +31 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +43 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/storage.d.ts +389 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +38 -0
- package/dist/storage.js.map +1 -0
- package/dist/telemetry.d.ts +155 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +2 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/vault-node.d.ts +20 -0
- package/dist/vault-node.d.ts.map +1 -0
- package/dist/vault-node.js +30 -0
- package/dist/vault-node.js.map +1 -0
- package/dist/vault.d.ts +62 -0
- package/dist/vault.d.ts.map +1 -0
- package/dist/vault.js +88 -0
- package/dist/vault.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,gBAAgB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE9E;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,mBAAmB;gBACpB,MAAM,EAAE,MAAM;CAI3B;AAED;;;;;;;GAOG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAGpC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,gGAAgG;IAChG,QAAQ,CAAC,YAAY,EAAE,MAAM;IAJ/B,QAAQ,CAAC,IAAI,eAAe;gBAEjB,MAAM,EAAE,MAAM;IACvB,gGAAgG;IACvF,YAAY,EAAE,MAAM;CAKhC;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,aAAa,CAE9D;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAE/B,UAAU,CACR,SAAS,EAAE,CAAC,EACZ,KAAK,EAAE;QACL,6EAA6E;QAC7E,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,+DAA+D;QAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GACA,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,2DAA2D;IAC3D,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAC9D;;;;OAIG;IACH,SAAS,CACP,SAAS,EAAE,CAAC,EACZ,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GACvC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAGzB,qDAAqD;IACrD,YAAY,CAAC,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAClE,2EAA2E;IAC3E,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAGtE,8EAA8E;IAC9E;;;;;OAKG;IACH,SAAS,CACP,SAAS,EAAE,CAAC,EACZ,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GACtD,OAAO,CAAC,SAAS,CAAC,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE;QACd,SAAS,EAAE,CAAC,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACvB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,CACP,SAAS,EAAE,CAAC,EACZ,KAAK,EAAE;QACL,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,KAAK,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAC1C,GACA,OAAO,CAAC,SAAS,CAAC,CAAC;IAMtB;;;;;OAKG;IACH,YAAY,CACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB;;;;;;;;OAQG;IACH,UAAU,CACR,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAG7B;;;;;;OAMG;IACH,SAAS,CACP,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,EACzB,KAAK,CAAC,EAAE,QAAQ,GACf,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAC9C,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACxE;;;;;OAKG;IACH,eAAe,CACb,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GACxB,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAGxB,WAAW,CACT,SAAS,EAAE,CAAC,EACZ,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,WAAW,GAAG,OAAO,CAAC,GACrD,OAAO,CAAC,IAAI,CAAC,CAAC;IAGjB,qFAAqF;IACrF,cAAc,CACZ,SAAS,EAAE,CAAC,EACZ,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,qFAAqF;QACrF,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,oFAAoF;QACpF,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KAC5B,GACA,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3B,2DAA2D;IAC3D,aAAa,CAAC,SAAS,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACvD,4CAA4C;IAC5C,cAAc,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD;;;;;;;;;OASG;IACH,YAAY,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACxF;;;;;;;OAOG;IACH,gBAAgB,CACd,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EACjE,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB;;;;;;;;;;;;;;;;OAgBG;IACH,gBAAgB,CAAC,CACf,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAC7C,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by `createChat` when the requested chat id already exists (typically a
|
|
3
|
+
* client-supplied id colliding with a chat the caller doesn't own — the scoped
|
|
4
|
+
* `getChat` missed, so the create raced into the PK). Carries a stable `code`
|
|
5
|
+
* so the server layer can map it to a 409 instead of a 500.
|
|
6
|
+
*/
|
|
7
|
+
export class ChatConflictError extends Error {
|
|
8
|
+
code = "chat_conflict";
|
|
9
|
+
constructor(chatId) {
|
|
10
|
+
super(`Chat id is not available: ${chatId}`);
|
|
11
|
+
this.name = "ChatConflictError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Thrown by `createRun` / `claimRun` when the chat already has a LIVE active
|
|
16
|
+
* run — one turn per conversation is a storage-level invariant (a partial
|
|
17
|
+
* unique index in the shipped adapters), so two tabs, a webhook retry racing a
|
|
18
|
+
* reply, or a schedule firing mid-conversation can never interleave one
|
|
19
|
+
* history. `retryAfterMs` is the live run's remaining lease (or the stale
|
|
20
|
+
* timeout for a non-durable run). Stable `code` → the server maps it to 409.
|
|
21
|
+
*/
|
|
22
|
+
export class ChatBusyError extends Error {
|
|
23
|
+
chatId;
|
|
24
|
+
retryAfterMs;
|
|
25
|
+
code = "chat_busy";
|
|
26
|
+
constructor(chatId,
|
|
27
|
+
/** Milliseconds until the live run's lease expires — when a retry can succeed at the latest. */
|
|
28
|
+
retryAfterMs) {
|
|
29
|
+
super(`A turn is already running in this chat; try again in ${Math.ceil(retryAfterMs / 1000)}s.`);
|
|
30
|
+
this.chatId = chatId;
|
|
31
|
+
this.retryAfterMs = retryAfterMs;
|
|
32
|
+
this.name = "ChatBusyError";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function isChatBusyError(e) {
|
|
36
|
+
return e?.code === "chat_busy";
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AA8BA;;;;;GAKG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,IAAI,GAAG,eAAe,CAAC;IAChC,YAAY,MAAc;QACxB,KAAK,CAAC,6BAA6B,MAAM,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAG3B;IAEA;IAJF,IAAI,GAAG,WAAW,CAAC;IAC5B,YACW,MAAc;IACvB,gGAAgG;IACvF,YAAoB;QAE7B,KAAK,CAAC,wDAAwD,IAAI,CAAC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QAJzF,WAAM,GAAN,MAAM,CAAQ;QAEd,iBAAY,GAAZ,YAAY,CAAQ;QAG7B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,UAAU,eAAe,CAAC,CAAU;IACxC,OAAQ,CAA8B,EAAE,IAAI,KAAK,WAAW,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { TelemetryOptions } from "ai";
|
|
2
|
+
/**
|
|
3
|
+
* The telemetry seam — THE observation point for a turn, kept out of core so it
|
|
4
|
+
* carries no OTEL/vendor dep. A host supplies an implementation via
|
|
5
|
+
* `RuntimeConfig.telemetry`: a full tracer (`@intentface/latch-langfuse`), or
|
|
6
|
+
* just the hooks it wants (`onRunFinished` for a usage ledger or an
|
|
7
|
+
* operational notification, `onStep` for per-tool analytics). Without one,
|
|
8
|
+
* nothing changes.
|
|
9
|
+
*
|
|
10
|
+
* The runtime calls it around the single model-call choke-point in
|
|
11
|
+
* `buildTurn`: per-run settings feed the AI SDK's `telemetry` option, the run
|
|
12
|
+
* span wrapper lets a tracer root all spans in one trace, `onStep` fires after
|
|
13
|
+
* each generation step, and `onRunFinished` fires after the turn is persisted
|
|
14
|
+
* (scores, judges, flush). Every hook is guarded: a throwing or rejecting hook
|
|
15
|
+
* is swallowed, so telemetry can never fail a turn.
|
|
16
|
+
*
|
|
17
|
+
* Opting a run out: an impl that defines `telemetryFor` and returns undefined
|
|
18
|
+
* for a run silences ALL hooks for that run (not just the AI SDK settings).
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* What started a turn — and, in practice, whether a human is at the other end
|
|
22
|
+
* of it:
|
|
23
|
+
*
|
|
24
|
+
* - `"chat"` — a user message (`handleChat`). Someone is watching the stream.
|
|
25
|
+
* - `"decision"` — a human answered a pending request: an approval decision or
|
|
26
|
+
* a client-handled tool result. Someone is watching.
|
|
27
|
+
* - `"schedule"` — a cron/one-shot fire (`runDue`). NOBODY is watching.
|
|
28
|
+
* - `"programmatic"` — the host called `runAgent` directly (a background job, a
|
|
29
|
+
* webhook handler, a test run). There is no client stream, and only the host
|
|
30
|
+
* knows whether a person is waiting on the result — so `runAgent` takes a
|
|
31
|
+
* `trigger` to say when it does.
|
|
32
|
+
* - `"resume"` — the durability sweep recovered a crashed run and drove it to
|
|
33
|
+
* completion server-side. Nobody is watching.
|
|
34
|
+
*
|
|
35
|
+
* That distinction is what makes `onRunFinished` usable as an operational
|
|
36
|
+
* notification channel and not just an analytics feed: a turn that finishes
|
|
37
|
+
* `awaiting_input` under `"schedule"` or `"resume"` is a person who needs to
|
|
38
|
+
* be told, while the same status under `"chat"` or `"decision"` is just a gate
|
|
39
|
+
* rendering in front of someone who can answer it.
|
|
40
|
+
*
|
|
41
|
+
* A subagent turn inherits its parent's trigger (like `rootChatId`), so a
|
|
42
|
+
* whole delegation tree is attributable to what set it off.
|
|
43
|
+
*/
|
|
44
|
+
export type TurnTrigger = "chat" | "decision" | "programmatic" | "schedule" | "resume";
|
|
45
|
+
/** Identity of one run/turn, known before the model call starts. */
|
|
46
|
+
export interface TelemetryRunMeta<P = unknown> {
|
|
47
|
+
/** Per-turn run id (`latch_runs.id`) — the natural trace correlation key. */
|
|
48
|
+
runId: string;
|
|
49
|
+
/** The conversation id — the natural session id. */
|
|
50
|
+
chatId: string;
|
|
51
|
+
/** Registered agent name. */
|
|
52
|
+
agent: string;
|
|
53
|
+
/** Display model id for the turn. */
|
|
54
|
+
modelId: string;
|
|
55
|
+
/** The caller the run is scoped to (tenant/user isolation flows from this). */
|
|
56
|
+
principal: P;
|
|
57
|
+
/**
|
|
58
|
+
* Run start time (epoch ms, `latch_runs.startedAt`). A stable per-run clock:
|
|
59
|
+
* out-of-band score writers (judge verdicts, user feedback, human
|
|
60
|
+
* corrections) pin their Langfuse score timestamp to it so repeated writes
|
|
61
|
+
* for the same run+rubric upsert one score instead of duplicating across days.
|
|
62
|
+
*/
|
|
63
|
+
startedAt: number;
|
|
64
|
+
/** Delegation depth: 0 = top-level turn, >0 = a subagent turn. */
|
|
65
|
+
depth: number;
|
|
66
|
+
/** What started this turn — see {@link TurnTrigger}. */
|
|
67
|
+
trigger: TurnTrigger;
|
|
68
|
+
/**
|
|
69
|
+
* The run that spawned this subagent turn, when applicable. Absent at the top
|
|
70
|
+
* level. Lets a tracer link a helper's trace back to the agent it ran for.
|
|
71
|
+
*/
|
|
72
|
+
parentRunId?: string;
|
|
73
|
+
/**
|
|
74
|
+
* The top-level conversation id — stable across a turn AND its subagent
|
|
75
|
+
* turns (a subagent's own `chatId` is an internal `sub_…` thread). A tracer
|
|
76
|
+
* can use it as the session id so a whole delegation tree groups together.
|
|
77
|
+
* Falls back to `chatId` when unset (top-level turns).
|
|
78
|
+
*/
|
|
79
|
+
rootChatId?: string;
|
|
80
|
+
}
|
|
81
|
+
/** Outcome of one finished turn, delivered after persistence. */
|
|
82
|
+
export interface TelemetryRunOutcome {
|
|
83
|
+
status: "completed" | "awaiting_input" | "errored";
|
|
84
|
+
/** Present when status is "errored". */
|
|
85
|
+
error?: string;
|
|
86
|
+
/** Plain text of the incoming user message for this turn, if any. */
|
|
87
|
+
inputText?: string;
|
|
88
|
+
/**
|
|
89
|
+
* The turn's persisted messages (assistant message last). Typed loosely so
|
|
90
|
+
* implementations stay decoupled from the message shape; cast to
|
|
91
|
+
* `AppMessage[]` to walk parts.
|
|
92
|
+
*/
|
|
93
|
+
messages: unknown[];
|
|
94
|
+
usage: {
|
|
95
|
+
inputTokens: number;
|
|
96
|
+
outputTokens: number;
|
|
97
|
+
cacheReadTokens?: number;
|
|
98
|
+
cacheWriteTokens?: number;
|
|
99
|
+
};
|
|
100
|
+
/** Cost for the turn (0 without a pricing config). */
|
|
101
|
+
cost: number;
|
|
102
|
+
endedAt?: number;
|
|
103
|
+
}
|
|
104
|
+
/** One completed generation step (model output + the step's tool calls/results). */
|
|
105
|
+
export interface TelemetryStep {
|
|
106
|
+
text?: string;
|
|
107
|
+
finishReason?: string;
|
|
108
|
+
usage?: {
|
|
109
|
+
inputTokens?: number;
|
|
110
|
+
outputTokens?: number;
|
|
111
|
+
cacheReadTokens?: number;
|
|
112
|
+
cacheWriteTokens?: number;
|
|
113
|
+
};
|
|
114
|
+
toolCalls?: Array<{
|
|
115
|
+
toolCallId: string;
|
|
116
|
+
toolName: string;
|
|
117
|
+
input?: unknown;
|
|
118
|
+
}>;
|
|
119
|
+
toolResults?: Array<{
|
|
120
|
+
toolCallId: string;
|
|
121
|
+
toolName: string;
|
|
122
|
+
output?: unknown;
|
|
123
|
+
}>;
|
|
124
|
+
}
|
|
125
|
+
export interface LatchTelemetry<P = unknown> {
|
|
126
|
+
/**
|
|
127
|
+
* Per-run AI SDK telemetry options (integrations, functionId, …), passed as
|
|
128
|
+
* `telemetry` on the turn's agent. Return undefined to skip this run — every
|
|
129
|
+
* other hook goes silent for it too.
|
|
130
|
+
*/
|
|
131
|
+
telemetryFor?(run: TelemetryRunMeta<P>): TelemetryOptions | undefined;
|
|
132
|
+
/**
|
|
133
|
+
* After each generation step (model output + that step's tool calls and
|
|
134
|
+
* results). Fire-and-forget: not awaited, never fails the turn. For per-tool
|
|
135
|
+
* analytics and step-level metrics.
|
|
136
|
+
*/
|
|
137
|
+
onStep?(run: TelemetryRunMeta<P>, step: TelemetryStep): void | Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* Wrap the model call so the impl can root it in a trace context (seeded
|
|
140
|
+
* trace id, session/user/tags). Identity when absent.
|
|
141
|
+
*/
|
|
142
|
+
withRunSpan?<T>(run: TelemetryRunMeta<P>, fn: () => Promise<T>): Promise<T>;
|
|
143
|
+
/**
|
|
144
|
+
* Post-turn hook, fired after messages/run/usage are persisted (and on
|
|
145
|
+
* error/abort with status "errored", carrying the error message). Awaited,
|
|
146
|
+
* errors swallowed — telemetry must never fail a turn. With `run.trigger`
|
|
147
|
+
* this doubles as the operational notification seam: `status:
|
|
148
|
+
* "awaiting_input"` under `"schedule"`/`"resume"` is a fire nobody can
|
|
149
|
+
* answer.
|
|
150
|
+
*/
|
|
151
|
+
onRunFinished?(run: TelemetryRunMeta<P>, outcome: TelemetryRunOutcome): void | Promise<void>;
|
|
152
|
+
/** Flush exporters (serverless). Awaited after onRunFinished. */
|
|
153
|
+
flush?(): Promise<void>;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive a base64 32-byte `masterKey` from a free-form passphrase via scrypt.
|
|
3
|
+
*
|
|
4
|
+
* NOTE — Node-only entry point (`@intentface/latch-core/node`): the vault
|
|
5
|
+
* itself is pure Web Crypto (`crypto.subtle`) so the package root stays
|
|
6
|
+
* portable to edge/serverless. `scryptSync` is a Node-only KDF and is used
|
|
7
|
+
* deliberately here: it's a convenience for the common case where the KEK
|
|
8
|
+
* comes from a human passphrase env var rather than a raw base64 key, and key
|
|
9
|
+
* derivation happens once at startup on the server (never in an edge request
|
|
10
|
+
* path). Consumers on non-Node runtimes should supply a raw base64 32-byte
|
|
11
|
+
* `masterKey` to `createVault` directly and skip this helper.
|
|
12
|
+
*
|
|
13
|
+
* `salt` is required and must be a stable per-deployment value (deployment
|
|
14
|
+
* config/KMS — it need not be secret): a shared default salt would make the
|
|
15
|
+
* same passphrase yield the same KEK on every deployment.
|
|
16
|
+
*/
|
|
17
|
+
export declare function deriveMasterKey(passphrase: string, opts: {
|
|
18
|
+
salt: string;
|
|
19
|
+
}): string;
|
|
20
|
+
//# sourceMappingURL=vault-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault-node.d.ts","sourceRoot":"","sources":["../src/vault-node.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GACrB,MAAM,CAaR"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { scryptSync } from "node:crypto";
|
|
2
|
+
/**
|
|
3
|
+
* Derive a base64 32-byte `masterKey` from a free-form passphrase via scrypt.
|
|
4
|
+
*
|
|
5
|
+
* NOTE — Node-only entry point (`@intentface/latch-core/node`): the vault
|
|
6
|
+
* itself is pure Web Crypto (`crypto.subtle`) so the package root stays
|
|
7
|
+
* portable to edge/serverless. `scryptSync` is a Node-only KDF and is used
|
|
8
|
+
* deliberately here: it's a convenience for the common case where the KEK
|
|
9
|
+
* comes from a human passphrase env var rather than a raw base64 key, and key
|
|
10
|
+
* derivation happens once at startup on the server (never in an edge request
|
|
11
|
+
* path). Consumers on non-Node runtimes should supply a raw base64 32-byte
|
|
12
|
+
* `masterKey` to `createVault` directly and skip this helper.
|
|
13
|
+
*
|
|
14
|
+
* `salt` is required and must be a stable per-deployment value (deployment
|
|
15
|
+
* config/KMS — it need not be secret): a shared default salt would make the
|
|
16
|
+
* same passphrase yield the same KEK on every deployment.
|
|
17
|
+
*/
|
|
18
|
+
export function deriveMasterKey(passphrase, opts) {
|
|
19
|
+
// Fail closed: a missing/blank passphrase or salt (an unset env var) must not
|
|
20
|
+
// silently derive a valid-looking key — that would encrypt the vault under a
|
|
21
|
+
// predictable KEK.
|
|
22
|
+
if (!passphrase || passphrase.trim() === "") {
|
|
23
|
+
throw new Error("deriveMasterKey: passphrase must be a non-empty string");
|
|
24
|
+
}
|
|
25
|
+
if (!opts?.salt || opts.salt.trim() === "") {
|
|
26
|
+
throw new Error("deriveMasterKey: salt must be a non-empty, deployment-stable string");
|
|
27
|
+
}
|
|
28
|
+
return scryptSync(passphrase, opts.salt, 32).toString("base64");
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=vault-node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault-node.js","sourceRoot":"","sources":["../src/vault-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAC7B,UAAkB,EAClB,IAAsB;IAEtB,8EAA8E;IAC9E,6EAA6E;IAC7E,mBAAmB;IACnB,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,qEAAqE,CACtE,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAClE,CAAC"}
|
package/dist/vault.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { SecretResolver } from "./context.js";
|
|
2
|
+
/**
|
|
3
|
+
* The Vault — server-side, envelope-encrypted secret storage.
|
|
4
|
+
*
|
|
5
|
+
* Connection credentials (API keys, OAuth tokens) live here, encrypted at rest
|
|
6
|
+
* in the customer's own database and scoped per tenant. The decrypted value is
|
|
7
|
+
* brokered server-side only: it reaches a tool's egress (fetch/MCP) but never
|
|
8
|
+
* the model, logs, or telemetry. The read-side is a `SecretResolver`, so the
|
|
9
|
+
* existing context/tools plumbing consumes it without knowing it's encrypted.
|
|
10
|
+
*
|
|
11
|
+
* Envelope encryption: each secret gets a random data key (DEK) that encrypts
|
|
12
|
+
* the value (AES-256-GCM); the DEK itself is wrapped by a master key (KEK) held
|
|
13
|
+
* in config/env/KMS. Rotating the KEK only requires re-wrapping DEKs, not
|
|
14
|
+
* re-encrypting values. Crypto is Web Crypto (`crypto.subtle`) — portable to
|
|
15
|
+
* Node and edge/serverless, no native deps.
|
|
16
|
+
*/
|
|
17
|
+
/** The opaque encrypted record persisted by a `SecretStore`. Never holds plaintext. */
|
|
18
|
+
export interface SecretRecord {
|
|
19
|
+
key: string;
|
|
20
|
+
/** base64 AES-GCM ciphertext of the value (auth tag appended by Web Crypto). */
|
|
21
|
+
ciphertext: string;
|
|
22
|
+
/** base64 nonce used to encrypt the value. */
|
|
23
|
+
iv: string;
|
|
24
|
+
/** base64 AES-GCM ciphertext of the raw DEK, wrapped under the KEK. */
|
|
25
|
+
wrappedDek: string;
|
|
26
|
+
/** base64 nonce used to wrap the DEK. */
|
|
27
|
+
dekIv: string;
|
|
28
|
+
createdAt: number;
|
|
29
|
+
updatedAt: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Persistence seam for encrypted secret records (Drizzle impl in latch-drizzle).
|
|
33
|
+
* Isolation lives here: each method receives the opaque `Principal` and the store
|
|
34
|
+
* scopes by it (the default derives an `owner` key). The framework never reads `P`.
|
|
35
|
+
*/
|
|
36
|
+
export interface SecretStore<P> {
|
|
37
|
+
put(principal: P, record: SecretRecord): Promise<void>;
|
|
38
|
+
get(principal: P, key: string): Promise<SecretRecord | null>;
|
|
39
|
+
delete(principal: P, key: string): Promise<void>;
|
|
40
|
+
/** Keys only — never values — for the caller. */
|
|
41
|
+
list(principal: P): Promise<string[]>;
|
|
42
|
+
}
|
|
43
|
+
/** The Vault operations. `get` returns decrypted plaintext; storage stays opaque. */
|
|
44
|
+
export interface Vault<P> {
|
|
45
|
+
set(principal: P, key: string, value: string): Promise<void>;
|
|
46
|
+
get(principal: P, key: string): Promise<string | undefined>;
|
|
47
|
+
has(principal: P, key: string): Promise<boolean>;
|
|
48
|
+
delete(principal: P, key: string): Promise<void>;
|
|
49
|
+
list(principal: P): Promise<string[]>;
|
|
50
|
+
/** Read-side adapter for context/tools (a `SecretResolver`). */
|
|
51
|
+
readonly resolver: SecretResolver<P>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build a Vault over a `SecretStore`. `masterKey` is a base64-encoded 32-byte
|
|
55
|
+
* (256-bit) key — generate with `crypto.getRandomValues(new Uint8Array(32))`
|
|
56
|
+
* and keep it in env/KMS, never in the database.
|
|
57
|
+
*/
|
|
58
|
+
export declare function createVault<P>(opts: {
|
|
59
|
+
store: SecretStore<P>;
|
|
60
|
+
masterKey: string;
|
|
61
|
+
}): Vault<P>;
|
|
62
|
+
//# sourceMappingURL=vault.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD;;;;;;;;;;;;;;GAcG;AAEH,uFAAuF;AACvF,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,EAAE,EAAE,MAAM,CAAC;IACX,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,GAAG,CAAC,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,GAAG,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC7D,MAAM,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,iDAAiD;IACjD,IAAI,CAAC,SAAS,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACvC;AAED,qFAAqF;AACrF,MAAM,WAAW,KAAK,CAAC,CAAC;IACtB,GAAG,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,GAAG,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC5D,GAAG,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,MAAM,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,CAAC,SAAS,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtC,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;CACtC;AA2BD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE;IACnC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,KAAK,CAAC,CAAC,CAAC,CA+FX"}
|
package/dist/vault.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// --- base64 <-> bytes (no Buffer; works in Node + browsers/edge) ------------
|
|
2
|
+
function toB64(bytes) {
|
|
3
|
+
const u8 = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
4
|
+
let s = "";
|
|
5
|
+
for (const b of u8)
|
|
6
|
+
s += String.fromCharCode(b);
|
|
7
|
+
return btoa(s);
|
|
8
|
+
}
|
|
9
|
+
function fromB64(b64) {
|
|
10
|
+
const s = atob(b64);
|
|
11
|
+
const u8 = new Uint8Array(s.length);
|
|
12
|
+
for (let i = 0; i < s.length; i++)
|
|
13
|
+
u8[i] = s.charCodeAt(i);
|
|
14
|
+
return u8;
|
|
15
|
+
}
|
|
16
|
+
const enc = new TextEncoder();
|
|
17
|
+
const dec = new TextDecoder();
|
|
18
|
+
// `deriveMasterKey` (passphrase → KEK via scrypt) lives in
|
|
19
|
+
// `@intentface/latch-core/node` — it needs `node:crypto`, and importing it here
|
|
20
|
+
// would make the package root unusable on edge/serverless runtimes.
|
|
21
|
+
// Web Crypto's lib types narrow BufferSource to ArrayBuffer-backed views; our
|
|
22
|
+
// Uint8Arrays are structurally fine, so coerce at the crypto call boundary.
|
|
23
|
+
const bs = (u) => u;
|
|
24
|
+
/**
|
|
25
|
+
* Build a Vault over a `SecretStore`. `masterKey` is a base64-encoded 32-byte
|
|
26
|
+
* (256-bit) key — generate with `crypto.getRandomValues(new Uint8Array(32))`
|
|
27
|
+
* and keep it in env/KMS, never in the database.
|
|
28
|
+
*/
|
|
29
|
+
export function createVault(opts) {
|
|
30
|
+
const { store } = opts;
|
|
31
|
+
const rawKek = fromB64(opts.masterKey);
|
|
32
|
+
if (rawKek.length !== 32) {
|
|
33
|
+
throw new Error("Vault masterKey must be base64 of 32 bytes (256-bit)");
|
|
34
|
+
}
|
|
35
|
+
// Import the KEK once; reused to wrap/unwrap per-secret DEKs.
|
|
36
|
+
const kekPromise = crypto.subtle.importKey("raw", bs(rawKek), { name: "AES-GCM" }, false, ["encrypt", "decrypt"]);
|
|
37
|
+
async function encryptValue(value) {
|
|
38
|
+
const kek = await kekPromise;
|
|
39
|
+
const dek = await crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]);
|
|
40
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
41
|
+
const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv: bs(iv) }, dek, bs(enc.encode(value)));
|
|
42
|
+
const rawDek = await crypto.subtle.exportKey("raw", dek);
|
|
43
|
+
const dekIv = crypto.getRandomValues(new Uint8Array(12));
|
|
44
|
+
const wrappedDek = await crypto.subtle.encrypt({ name: "AES-GCM", iv: bs(dekIv) }, kek, rawDek);
|
|
45
|
+
return {
|
|
46
|
+
ciphertext: toB64(ciphertext),
|
|
47
|
+
iv: toB64(iv),
|
|
48
|
+
wrappedDek: toB64(wrappedDek),
|
|
49
|
+
dekIv: toB64(dekIv),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async function decryptValue(record) {
|
|
53
|
+
const kek = await kekPromise;
|
|
54
|
+
const rawDek = await crypto.subtle.decrypt({ name: "AES-GCM", iv: bs(fromB64(record.dekIv)) }, kek, bs(fromB64(record.wrappedDek)));
|
|
55
|
+
const dek = await crypto.subtle.importKey("raw", rawDek, { name: "AES-GCM" }, false, ["decrypt"]);
|
|
56
|
+
const plaintext = await crypto.subtle.decrypt({ name: "AES-GCM", iv: bs(fromB64(record.iv)) }, dek, bs(fromB64(record.ciphertext)));
|
|
57
|
+
return dec.decode(plaintext);
|
|
58
|
+
}
|
|
59
|
+
const get = async (principal, key) => {
|
|
60
|
+
const record = await store.get(principal, key);
|
|
61
|
+
if (!record)
|
|
62
|
+
return undefined;
|
|
63
|
+
return decryptValue(record);
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
async set(principal, key, value) {
|
|
67
|
+
const now = Date.now();
|
|
68
|
+
await store.put(principal, {
|
|
69
|
+
key,
|
|
70
|
+
...(await encryptValue(value)),
|
|
71
|
+
createdAt: now,
|
|
72
|
+
updatedAt: now,
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
get,
|
|
76
|
+
async has(principal, key) {
|
|
77
|
+
return (await store.get(principal, key)) != null;
|
|
78
|
+
},
|
|
79
|
+
async delete(principal, key) {
|
|
80
|
+
await store.delete(principal, key);
|
|
81
|
+
},
|
|
82
|
+
list(principal) {
|
|
83
|
+
return store.list(principal);
|
|
84
|
+
},
|
|
85
|
+
resolver: (principal, key) => get(principal, key),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=vault.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault.js","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@intentface/latch-core",
|
|
3
|
+
"version": "0.9.1",
|
|
4
|
+
"description": "Latch core — runtime, types, and seams for building agents on the AI SDK. Subpaths: /models (models.dev catalog + provider hooks) and /harness (default sandbox/app tools); their extra deps are optional peers, loaded lazily.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"ai-sdk",
|
|
8
|
+
"agents",
|
|
9
|
+
"llm",
|
|
10
|
+
"agent-runtime",
|
|
11
|
+
"durable-execution",
|
|
12
|
+
"tool-calling"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"module": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./node": {
|
|
25
|
+
"types": "./dist/vault-node.d.ts",
|
|
26
|
+
"import": "./dist/vault-node.js"
|
|
27
|
+
},
|
|
28
|
+
"./models": {
|
|
29
|
+
"types": "./dist/models/index.d.ts",
|
|
30
|
+
"import": "./dist/models/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./harness": {
|
|
33
|
+
"types": "./dist/harness/index.d.ts",
|
|
34
|
+
"import": "./dist/harness/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
],
|
|
40
|
+
"sideEffects": false,
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public",
|
|
43
|
+
"registry": "https://registry.npmjs.org"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"zod": "^4.0.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"ai": ">=7.0.0",
|
|
50
|
+
"@ai-sdk/anthropic": ">=4.0.0",
|
|
51
|
+
"@ai-sdk/google": ">=4.0.0",
|
|
52
|
+
"@ai-sdk/openai": ">=4.0.0",
|
|
53
|
+
"turndown": ">=7.0.0",
|
|
54
|
+
"@intentface/latch-net": "^0.9.1"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@ai-sdk/anthropic": "^4.0.0",
|
|
58
|
+
"@ai-sdk/google": "^4.0.0",
|
|
59
|
+
"@ai-sdk/openai": "^4.0.0",
|
|
60
|
+
"@types/node": "^22",
|
|
61
|
+
"@types/turndown": "^5.0.6",
|
|
62
|
+
"ai": "^7.0.2",
|
|
63
|
+
"turndown": "^7.2.4",
|
|
64
|
+
"typescript": "^5.7.0",
|
|
65
|
+
"vitest": "^4",
|
|
66
|
+
"@intentface/latch-net": "^0.9.1"
|
|
67
|
+
},
|
|
68
|
+
"repository": {
|
|
69
|
+
"type": "git",
|
|
70
|
+
"url": "git+https://github.com/Intentface/intentface-latch.git",
|
|
71
|
+
"directory": "packages/core"
|
|
72
|
+
},
|
|
73
|
+
"peerDependenciesMeta": {
|
|
74
|
+
"@ai-sdk/anthropic": {
|
|
75
|
+
"optional": true
|
|
76
|
+
},
|
|
77
|
+
"@ai-sdk/google": {
|
|
78
|
+
"optional": true
|
|
79
|
+
},
|
|
80
|
+
"@ai-sdk/openai": {
|
|
81
|
+
"optional": true
|
|
82
|
+
},
|
|
83
|
+
"turndown": {
|
|
84
|
+
"optional": true
|
|
85
|
+
},
|
|
86
|
+
"@intentface/latch-net": {
|
|
87
|
+
"optional": true
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"scripts": {
|
|
91
|
+
"build": "tsc -p tsconfig.json",
|
|
92
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json",
|
|
93
|
+
"test": "vitest run"
|
|
94
|
+
}
|
|
95
|
+
}
|