@lloyal-labs/rig 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +107 -0
- package/LICENSE-FAQ.md +256 -0
- package/README.md +78 -72
- package/dist/bundle.d.ts +211 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +296 -0
- package/dist/bundle.js.map +1 -0
- package/dist/cancellable-fetch.d.ts +98 -0
- package/dist/cancellable-fetch.d.ts.map +1 -0
- package/dist/cancellable-fetch.js +133 -0
- package/dist/cancellable-fetch.js.map +1 -0
- package/dist/config-store.d.ts +30 -0
- package/dist/config-store.d.ts.map +1 -0
- package/dist/config-store.js +45 -0
- package/dist/config-store.js.map +1 -0
- package/dist/define-app.d.ts +98 -0
- package/dist/define-app.d.ts.map +1 -0
- package/dist/define-app.js +232 -0
- package/dist/define-app.js.map +1 -0
- package/dist/grant-store.d.ts +31 -0
- package/dist/grant-store.d.ts.map +1 -0
- package/dist/grant-store.js +49 -0
- package/dist/grant-store.js.map +1 -0
- package/dist/index.d.ts +13 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -11
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +3 -2
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +3 -2
- package/dist/node.js.map +1 -1
- package/dist/protocol.d.ts +155 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +184 -0
- package/dist/protocol.js.map +1 -0
- package/dist/registry.d.ts +87 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +245 -0
- package/dist/registry.js.map +1 -0
- package/dist/reranker.d.ts +25 -7
- package/dist/reranker.d.ts.map +1 -1
- package/dist/reranker.js +103 -63
- package/dist/reranker.js.map +1 -1
- package/dist/resources/types.d.ts +10 -37
- package/dist/resources/types.d.ts.map +1 -1
- package/dist/resources/types.js +12 -0
- package/dist/resources/types.js.map +1 -1
- package/dist/spine-render.d.ts +97 -0
- package/dist/spine-render.d.ts.map +1 -0
- package/dist/spine-render.js +121 -0
- package/dist/spine-render.js.map +1 -0
- package/dist/tools/delegate.js +1 -1
- package/dist/tools/index.d.ts +26 -22
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +24 -28
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/keyless-search.d.ts +67 -0
- package/dist/tools/keyless-search.d.ts.map +1 -0
- package/dist/tools/keyless-search.js +401 -0
- package/dist/tools/keyless-search.js.map +1 -0
- package/dist/tools/plan.d.ts +31 -4
- package/dist/tools/plan.d.ts.map +1 -1
- package/dist/tools/plan.js +46 -11
- package/dist/tools/plan.js.map +1 -1
- package/dist/tools/report.d.ts +4 -3
- package/dist/tools/report.d.ts.map +1 -1
- package/dist/tools/report.js +4 -3
- package/dist/tools/report.js.map +1 -1
- package/dist/tools/types.d.ts +12 -56
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +17 -0
- package/dist/tools/types.js.map +1 -1
- package/dist/tools/web-search.d.ts +9 -25
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +11 -119
- package/dist/tools/web-search.js.map +1 -1
- package/package.json +9 -6
- package/dist/sources/corpus.d.ts +0 -80
- package/dist/sources/corpus.d.ts.map +0 -1
- package/dist/sources/corpus.js +0 -100
- package/dist/sources/corpus.js.map +0 -1
- package/dist/sources/index.d.ts +0 -12
- package/dist/sources/index.d.ts.map +0 -1
- package/dist/sources/index.js +0 -14
- package/dist/sources/index.js.map +0 -1
- package/dist/sources/web.d.ts +0 -67
- package/dist/sources/web.d.ts.map +0 -1
- package/dist/sources/web.js +0 -104
- package/dist/sources/web.js.map +0 -1
- package/dist/tools/fetch-page.d.ts +0 -48
- package/dist/tools/fetch-page.d.ts.map +0 -1
- package/dist/tools/fetch-page.js +0 -309
- package/dist/tools/fetch-page.js.map +0 -1
- package/dist/tools/grep.d.ts +0 -35
- package/dist/tools/grep.d.ts.map +0 -1
- package/dist/tools/grep.js +0 -84
- package/dist/tools/grep.js.map +0 -1
- package/dist/tools/read-file.d.ts +0 -74
- package/dist/tools/read-file.d.ts.map +0 -1
- package/dist/tools/read-file.js +0 -192
- package/dist/tools/read-file.js.map +0 -1
- package/dist/tools/search.d.ts +0 -34
- package/dist/tools/search.d.ts.map +0 -1
- package/dist/tools/search.js +0 -101
- package/dist/tools/search.js.map +0 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `cancellableFetch(url, init, opts)` — Effection-native HTTP with
|
|
4
|
+
* scope-linked cancellation and a deadline timeout.
|
|
5
|
+
*
|
|
6
|
+
* Wraps the global `fetch` so:
|
|
7
|
+
*
|
|
8
|
+
* 1. **Outer-scope halt aborts the in-flight request.** The Effection
|
|
9
|
+
* `useAbortSignal()` returns a signal linked to the current scope;
|
|
10
|
+
* when the scope halts (because a containing operation throws,
|
|
11
|
+
* `race` chose another leg, the harness is cancelled, etc.) the
|
|
12
|
+
* signal aborts and the underlying socket closes. The fetch is
|
|
13
|
+
* *genuinely* cancelled — not abandoned.
|
|
14
|
+
*
|
|
15
|
+
* 2. **Timeout aborts the in-flight request.** A second leg sleeps for
|
|
16
|
+
* `opts.timeoutMs` and throws on completion. `race` halts whichever
|
|
17
|
+
* leg loses, propagating the abort the same way an outer halt does.
|
|
18
|
+
*
|
|
19
|
+
* Three current/planned consumers route through this primitive:
|
|
20
|
+
*
|
|
21
|
+
* - `@lloyal-labs/web-app/src/tools/fetch-page.ts` (post-migration —
|
|
22
|
+
* replaces raw `AbortController` + `setTimeout`, closes the latent
|
|
23
|
+
* socket-leak bug where a halted pool kept fetch-page sockets open).
|
|
24
|
+
* - `@lloyal-labs/web-app/src/tools/keyless-search.ts` (post-migration
|
|
25
|
+
* — replaces the private `fetchWithTimeout` from which this primitive
|
|
26
|
+
* was lifted; zero behavior change, just consolidation).
|
|
27
|
+
* - `@lloyal-labs/rig/src/bundle.ts` (`resolveAppEntry`) — fetches the
|
|
28
|
+
* signed catalog via `cancellableFetch` so a halted scope during
|
|
29
|
+
* resolution tears down cleanly. Used by `harness.dev install` to
|
|
30
|
+
* resolve names against the canonical channel.
|
|
31
|
+
*
|
|
32
|
+
* Third-party apps SHOULD use `cancellableFetch` for any HTTP they do
|
|
33
|
+
* under structured concurrency, rather than reinventing the
|
|
34
|
+
* `race + useAbortSignal` pattern.
|
|
35
|
+
*
|
|
36
|
+
* @packageDocumentation
|
|
37
|
+
* @category Contract
|
|
38
|
+
*/
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.FetchTimeoutError = void 0;
|
|
41
|
+
exports.cancellableFetch = cancellableFetch;
|
|
42
|
+
const effection_1 = require("effection");
|
|
43
|
+
/**
|
|
44
|
+
* Thrown when the timeout leg of `cancellableFetch` wins the race.
|
|
45
|
+
* Distinct from generic `Error` so consumers can catch only the
|
|
46
|
+
* timeout case (e.g., to retry with a longer timeout) without also
|
|
47
|
+
* catching network-layer errors thrown from the fetch leg.
|
|
48
|
+
*/
|
|
49
|
+
class FetchTimeoutError extends Error {
|
|
50
|
+
constructor(url, timeoutMs) {
|
|
51
|
+
super(`Fetch timed out after ${timeoutMs}ms: ${url}`);
|
|
52
|
+
this.name = 'FetchTimeoutError';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.FetchTimeoutError = FetchTimeoutError;
|
|
56
|
+
/**
|
|
57
|
+
* Default request timeout. Chosen to be comfortably longer than typical
|
|
58
|
+
* web pages (95th percentile of `fetch-page.ts` traces resolves in under
|
|
59
|
+
* 10s) while still bounded enough to fail fast on dead URLs. Override
|
|
60
|
+
* via `opts.timeoutMs` for known-slow endpoints.
|
|
61
|
+
*/
|
|
62
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
63
|
+
/**
|
|
64
|
+
* Fetch a URL with Effection-scope-linked cancellation and a timeout.
|
|
65
|
+
*
|
|
66
|
+
* @param url - The URL to fetch.
|
|
67
|
+
* @param init - Standard `RequestInit` options. `init.signal` is *replaced*
|
|
68
|
+
* by the Effection-scope-linked signal; callers cannot pass their own
|
|
69
|
+
* AbortController. (If you want to compose with an external abort
|
|
70
|
+
* source, do it at the outer-scope level — halting the outer scope
|
|
71
|
+
* propagates here.)
|
|
72
|
+
* @param opts - Timeout + injection knobs.
|
|
73
|
+
* @returns The `Response` object — unread. Callers `yield* call(() => res.text())`
|
|
74
|
+
* etc. as appropriate to their use case.
|
|
75
|
+
*
|
|
76
|
+
* @throws {FetchTimeoutError} If the timeout leg wins.
|
|
77
|
+
* @throws Network-layer errors thrown by the underlying `fetch` (e.g., DNS
|
|
78
|
+
* resolution failure, TLS error, socket reset). When the abort signal
|
|
79
|
+
* fires, `fetch` throws a `DOMException` with `name === 'AbortError'` —
|
|
80
|
+
* distinguishable from real network errors by that name.
|
|
81
|
+
*
|
|
82
|
+
* **Body buffering.** The returned `Response`'s body is **fully buffered
|
|
83
|
+
* in memory** before the function returns; the caller may safely call
|
|
84
|
+
* `.text()` / `.json()` / `.arrayBuffer()` on it without further async
|
|
85
|
+
* coordination. This is load-bearing: the underlying `useAbortSignal()`
|
|
86
|
+
* aborts when the http leg's scope unwinds (after `race` resolves),
|
|
87
|
+
* which would otherwise cause the caller's body-read to throw
|
|
88
|
+
* `AbortError` mid-flight (the body is still bound to the request's
|
|
89
|
+
* signal in undici). Pre-consuming inside the http leg, before the
|
|
90
|
+
* signal aborts, sidesteps that interaction. Cost: streaming is not
|
|
91
|
+
* supported — all responses are fully resident before return. Acceptable
|
|
92
|
+
* for the consumers we have (catalog JSON, manifest JSON, signed
|
|
93
|
+
* bundles up to a few hundred KB).
|
|
94
|
+
*/
|
|
95
|
+
function* cancellableFetch(url, init, opts) {
|
|
96
|
+
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
97
|
+
const fetchImpl = opts?.fetchImpl ?? fetch;
|
|
98
|
+
const httpLeg = function* () {
|
|
99
|
+
const signal = yield* (0, effection_1.useAbortSignal)();
|
|
100
|
+
// Strip caller's signal if any — the Effection scope owns abort.
|
|
101
|
+
// Keeping caller-supplied signal would mean two abort sources, which
|
|
102
|
+
// confuses the cancellation chain.
|
|
103
|
+
const { signal: _ignored, ...restInit } = init ?? {};
|
|
104
|
+
const res = yield* (0, effection_1.call)(() => fetchImpl(url, { ...restInit, signal }));
|
|
105
|
+
// Pre-consume the body while the signal is still live. After `race`
|
|
106
|
+
// returns, this http leg's scope unwinds and the signal aborts —
|
|
107
|
+
// reading the original Response's body at that point throws
|
|
108
|
+
// AbortError from undici's consumeBody. Wrapping the buffered bytes
|
|
109
|
+
// in a fresh Response (which has no associated signal) lets the
|
|
110
|
+
// caller read the body on their own schedule.
|
|
111
|
+
const bytes = yield* (0, effection_1.call)(() => res.arrayBuffer());
|
|
112
|
+
return new Response(bytes, {
|
|
113
|
+
status: res.status,
|
|
114
|
+
statusText: res.statusText,
|
|
115
|
+
headers: res.headers,
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
const timeoutLeg = function* () {
|
|
119
|
+
if (timeoutMs === Infinity) {
|
|
120
|
+
// Sleep forever — the http leg will win or the outer scope halts.
|
|
121
|
+
// Using a deliberately-never-resolving operation rather than
|
|
122
|
+
// sleeping for MAX_SAFE_INTEGER ms (which Node's timer subsystem
|
|
123
|
+
// doesn't handle gracefully).
|
|
124
|
+
yield* (0, effection_1.call)(() => new Promise(() => { }));
|
|
125
|
+
// Unreachable, but type-required.
|
|
126
|
+
throw new FetchTimeoutError(url, timeoutMs);
|
|
127
|
+
}
|
|
128
|
+
yield* (0, effection_1.sleep)(timeoutMs);
|
|
129
|
+
throw new FetchTimeoutError(url, timeoutMs);
|
|
130
|
+
};
|
|
131
|
+
return yield* (0, effection_1.race)([httpLeg(), timeoutLeg()]);
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=cancellable-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancellable-fetch.js","sourceRoot":"","sources":["../src/cancellable-fetch.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;;;AA4EH,4CA4CC;AArHD,yCAA8D;AAoB9D;;;;;GAKG;AACH,MAAa,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,GAAW,EAAE,SAAiB;QACxC,KAAK,CAAC,yBAAyB,SAAS,OAAO,GAAG,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AALD,8CAKC;AAED;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,QAAe,CAAC,CAAC,gBAAgB,CAC/B,GAAW,EACX,IAAkB,EAClB,IAA8B;IAE9B,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,kBAAkB,CAAC;IACxD,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,KAAK,CAAC;IAE3C,MAAM,OAAO,GAAG,QAAQ,CAAC;QACvB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,IAAA,0BAAc,GAAE,CAAC;QACvC,iEAAiE;QACjE,qEAAqE;QACrE,mCAAmC;QACnC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QACvE,oEAAoE;QACpE,iEAAiE;QACjE,4DAA4D;QAC5D,oEAAoE;QACpE,gEAAgE;QAChE,8CAA8C;QAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;QACnD,OAAO,IAAI,QAAQ,CAAC,KAAK,EAAE;YACzB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,OAAO,EAAE,GAAG,CAAC,OAAO;SACrB,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,QAAQ,CAAC;QAC1B,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC3B,kEAAkE;YAClE,6DAA6D;YAC7D,iEAAiE;YACjE,8BAA8B;YAC9B,KAAK,CAAC,CAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,CAAC,IAAI,OAAO,CAAQ,GAAG,EAAE,GAAwB,CAAC,CAAC,CAAC,CAAC;YACtE,kCAAkC;YAClC,MAAM,IAAI,iBAAiB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC9C,CAAC;QACD,KAAK,CAAC,CAAC,IAAA,iBAAK,EAAC,SAAS,CAAC,CAAC;QACxB,MAAM,IAAI,iBAAiB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC9C,CAAC,CAAC;IAEF,OAAO,KAAK,CAAC,CAAC,IAAA,gBAAI,EAAC,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory implementation of {@link AppConfigStore}.
|
|
3
|
+
*
|
|
4
|
+
* The `AppConfigStore` interface itself lives in
|
|
5
|
+
* `@lloyal-labs/lloyal-agents` (so the framework context
|
|
6
|
+
* `AppConfigStoreCtx` and app factories can share it without a
|
|
7
|
+
* dependency cycle). This module supplies the reference impl that dev
|
|
8
|
+
* harnesses, examples, and tests use; harnesses needing durable
|
|
9
|
+
* storage implement the interface themselves.
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
* @category Contract
|
|
13
|
+
*/
|
|
14
|
+
import type { AppConfigStore } from '@lloyal-labs/lloyal-agents';
|
|
15
|
+
/**
|
|
16
|
+
* Create an in-memory `AppConfigStore` backed by a `Map`.
|
|
17
|
+
*
|
|
18
|
+
* Intended for development, tests, and single-process harnesses that
|
|
19
|
+
* don't need cross-restart persistence. Harnesses needing durable
|
|
20
|
+
* storage implement the interface themselves against their preferred
|
|
21
|
+
* backend (file system, encrypted secret store, remote KV, etc.).
|
|
22
|
+
*
|
|
23
|
+
* Configs are stored as-is (no deep clone on set/get). If the caller
|
|
24
|
+
* mutates a returned config object, those mutations are visible to
|
|
25
|
+
* subsequent reads — which would violate the whole-replace semantics.
|
|
26
|
+
* Callers should treat returned configs as immutable and re-`set` to
|
|
27
|
+
* update.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createInMemoryConfigStore(): AppConfigStore;
|
|
30
|
+
//# sourceMappingURL=config-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../src/config-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,IAAI,cAAc,CAa1D"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* In-memory implementation of {@link AppConfigStore}.
|
|
4
|
+
*
|
|
5
|
+
* The `AppConfigStore` interface itself lives in
|
|
6
|
+
* `@lloyal-labs/lloyal-agents` (so the framework context
|
|
7
|
+
* `AppConfigStoreCtx` and app factories can share it without a
|
|
8
|
+
* dependency cycle). This module supplies the reference impl that dev
|
|
9
|
+
* harnesses, examples, and tests use; harnesses needing durable
|
|
10
|
+
* storage implement the interface themselves.
|
|
11
|
+
*
|
|
12
|
+
* @packageDocumentation
|
|
13
|
+
* @category Contract
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.createInMemoryConfigStore = createInMemoryConfigStore;
|
|
17
|
+
/**
|
|
18
|
+
* Create an in-memory `AppConfigStore` backed by a `Map`.
|
|
19
|
+
*
|
|
20
|
+
* Intended for development, tests, and single-process harnesses that
|
|
21
|
+
* don't need cross-restart persistence. Harnesses needing durable
|
|
22
|
+
* storage implement the interface themselves against their preferred
|
|
23
|
+
* backend (file system, encrypted secret store, remote KV, etc.).
|
|
24
|
+
*
|
|
25
|
+
* Configs are stored as-is (no deep clone on set/get). If the caller
|
|
26
|
+
* mutates a returned config object, those mutations are visible to
|
|
27
|
+
* subsequent reads — which would violate the whole-replace semantics.
|
|
28
|
+
* Callers should treat returned configs as immutable and re-`set` to
|
|
29
|
+
* update.
|
|
30
|
+
*/
|
|
31
|
+
function createInMemoryConfigStore() {
|
|
32
|
+
const store = new Map();
|
|
33
|
+
return {
|
|
34
|
+
*get(appName) {
|
|
35
|
+
return store.get(appName);
|
|
36
|
+
},
|
|
37
|
+
*set(appName, config) {
|
|
38
|
+
store.set(appName, config);
|
|
39
|
+
},
|
|
40
|
+
*clear(appName) {
|
|
41
|
+
store.delete(appName);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=config-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.js","sourceRoot":"","sources":["../src/config-store.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;AAmBH,8DAaC;AA3BD;;;;;;;;;;;;;GAaG;AACH,SAAgB,yBAAyB;IACvC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAmC,CAAC;IACzD,OAAO;QACL,CAAC,GAAG,CAAC,OAAe;YAClB,OAAO,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;QACD,CAAC,GAAG,CAAC,OAAe,EAAE,MAA+B;YACnD,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,CAAC;QACD,CAAC,KAAK,CAAC,OAAe;YACpB,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineApp(spec): App` — sync wiring helper called inside every app's
|
|
3
|
+
* factory after constructing its `Source` and `Tool[]` instances.
|
|
4
|
+
*
|
|
5
|
+
* Performs all framework-side validations of the app's declared shape
|
|
6
|
+
* before the App enters the registry:
|
|
7
|
+
*
|
|
8
|
+
* - **Manifest schema.** `name` and `protocol.name` match
|
|
9
|
+
* `[a-z][a-z0-9_-]{1,63}`; `protocol.tools` is a non-empty unique array
|
|
10
|
+
* of names matching the same regex; `protocol.useWhen` is a single
|
|
11
|
+
* bounded sentence with no chat-role markers, code fences, or newlines
|
|
12
|
+
* (metadata sanitization).
|
|
13
|
+
* - **App protocol version.** `manifest.appProtocolVersion` is in
|
|
14
|
+
* `SUPPORTED_APP_PROTOCOL_VERSIONS`. Absence is permitted
|
|
15
|
+
* (treated as `"3.0"`).
|
|
16
|
+
* - **Tool map coverage.** The keys of the supplied `tools` object equal
|
|
17
|
+
* `manifest.protocol.tools[]` as a set — every declared tool has an
|
|
18
|
+
* implementation, no extras.
|
|
19
|
+
* - **Boundary-marker double-emission.** `skill` (when string-typed) MUST
|
|
20
|
+
* NOT contain the literal `Apply the **` substring — the framework
|
|
21
|
+
* prepends the marker via `BOUNDARY_MARKER`, so an `skill.eta` that
|
|
22
|
+
* includes the line would emit it twice.
|
|
23
|
+
*
|
|
24
|
+
* Validation errors throw synchronously with a clear message naming the
|
|
25
|
+
* failing field and the violated rule. App factories should call
|
|
26
|
+
* `defineApp` last (after `yield*`ing tool factories) so a malformed
|
|
27
|
+
* manifest fails at construction time, not later at registration.
|
|
28
|
+
*
|
|
29
|
+
* @packageDocumentation
|
|
30
|
+
* @category Protocol
|
|
31
|
+
*/
|
|
32
|
+
import type { Tool, Source, App, AppManifest, SkillTemplateFn, ExamplesTemplateFn, ConfigFlow, AppHints } from '@lloyal-labs/lloyal-agents';
|
|
33
|
+
/**
|
|
34
|
+
* Argument to {@link defineApp}. The fields that survive into the
|
|
35
|
+
* returned {@link App} are surfaced here with the same names. There are
|
|
36
|
+
* no lifecycle hooks — setup is the factory body, teardown is `ensure(...)`.
|
|
37
|
+
*/
|
|
38
|
+
export interface DefineAppSpec {
|
|
39
|
+
/** The declarative app manifest, imported from `app.json`. */
|
|
40
|
+
manifest: AppManifest;
|
|
41
|
+
/** The app's Source. */
|
|
42
|
+
source: Source;
|
|
43
|
+
/**
|
|
44
|
+
* Map of tool-name → Tool instance. Keys MUST equal
|
|
45
|
+
* `manifest.protocol.tools[]` as a set (exact membership match — no
|
|
46
|
+
* missing tools, no extras). Each value's `.name` property must match
|
|
47
|
+
* its key (otherwise the catalog's `Tools:` line and the agent's
|
|
48
|
+
* dispatched tool call would disagree).
|
|
49
|
+
*/
|
|
50
|
+
tools: Readonly<Record<string, Tool>>;
|
|
51
|
+
/**
|
|
52
|
+
* The per-spawn template body. String → rendered via Eta with the
|
|
53
|
+
* `AgentRenderCtx` fields available as `it.*`. Function → invoked
|
|
54
|
+
* directly with the render context.
|
|
55
|
+
*
|
|
56
|
+
* MUST NOT contain the literal `Apply the **` substring when given as
|
|
57
|
+
* a string — the framework prepends the boundary marker.
|
|
58
|
+
*/
|
|
59
|
+
skill: string | SkillTemplateFn;
|
|
60
|
+
/**
|
|
61
|
+
* Optional discipline content rendered into the per-spawn preamble of
|
|
62
|
+
* agents assigned to this app. Never enters the shared spine.
|
|
63
|
+
*/
|
|
64
|
+
examples?: string | ExamplesTemplateFn;
|
|
65
|
+
/** Optional UX/marketplace hints (overrides `manifest.hints` if both present). */
|
|
66
|
+
hints?: AppHints;
|
|
67
|
+
/** Optional interactive config flow. */
|
|
68
|
+
configFlow?: ConfigFlow;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Validate an app's declared shape and return the runtime {@link App}
|
|
72
|
+
* object the framework will register and render against.
|
|
73
|
+
*
|
|
74
|
+
* Throws synchronously on the first validation failure with a message
|
|
75
|
+
* naming the failing field and the violated rule.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* export function* createJiraApp(): Operation<App> {
|
|
80
|
+
* const cfgStore = yield* AppConfigStoreCtx.expect();
|
|
81
|
+
* const cfg = yield* cfgStore.get(manifest.name);
|
|
82
|
+
* if (!cfg) throw new Error('jira app requires config');
|
|
83
|
+
*
|
|
84
|
+
* const source = new JiraSource(cfg);
|
|
85
|
+
* const searchTool = yield* createJiraSearchTool(cfg);
|
|
86
|
+
* const readTool = yield* createJiraReadTool(cfg);
|
|
87
|
+
*
|
|
88
|
+
* return defineApp({
|
|
89
|
+
* manifest,
|
|
90
|
+
* source,
|
|
91
|
+
* tools: { jira_search: searchTool, jira_read: readTool },
|
|
92
|
+
* skill: skillTemplate,
|
|
93
|
+
* });
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export declare function defineApp(spec: DefineAppSpec): App;
|
|
98
|
+
//# sourceMappingURL=define-app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-app.d.ts","sourceRoot":"","sources":["../src/define-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,KAAK,EACV,IAAI,EACJ,MAAM,EACN,GAAG,EACH,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACT,MAAM,4BAA4B,CAAC;AAGpC;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,8DAA8D;IAC9D,QAAQ,EAAE,WAAW,CAAC;IACtB,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IACtC;;;;;;;OAOG;IACH,KAAK,EAAE,MAAM,GAAG,eAAe,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAAC;IACvC,kFAAkF;IAClF,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,wCAAwC;IACxC,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AA+KD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,GAAG,CAmClD"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `defineApp(spec): App` — sync wiring helper called inside every app's
|
|
4
|
+
* factory after constructing its `Source` and `Tool[]` instances.
|
|
5
|
+
*
|
|
6
|
+
* Performs all framework-side validations of the app's declared shape
|
|
7
|
+
* before the App enters the registry:
|
|
8
|
+
*
|
|
9
|
+
* - **Manifest schema.** `name` and `protocol.name` match
|
|
10
|
+
* `[a-z][a-z0-9_-]{1,63}`; `protocol.tools` is a non-empty unique array
|
|
11
|
+
* of names matching the same regex; `protocol.useWhen` is a single
|
|
12
|
+
* bounded sentence with no chat-role markers, code fences, or newlines
|
|
13
|
+
* (metadata sanitization).
|
|
14
|
+
* - **App protocol version.** `manifest.appProtocolVersion` is in
|
|
15
|
+
* `SUPPORTED_APP_PROTOCOL_VERSIONS`. Absence is permitted
|
|
16
|
+
* (treated as `"3.0"`).
|
|
17
|
+
* - **Tool map coverage.** The keys of the supplied `tools` object equal
|
|
18
|
+
* `manifest.protocol.tools[]` as a set — every declared tool has an
|
|
19
|
+
* implementation, no extras.
|
|
20
|
+
* - **Boundary-marker double-emission.** `skill` (when string-typed) MUST
|
|
21
|
+
* NOT contain the literal `Apply the **` substring — the framework
|
|
22
|
+
* prepends the marker via `BOUNDARY_MARKER`, so an `skill.eta` that
|
|
23
|
+
* includes the line would emit it twice.
|
|
24
|
+
*
|
|
25
|
+
* Validation errors throw synchronously with a clear message naming the
|
|
26
|
+
* failing field and the violated rule. App factories should call
|
|
27
|
+
* `defineApp` last (after `yield*`ing tool factories) so a malformed
|
|
28
|
+
* manifest fails at construction time, not later at registration.
|
|
29
|
+
*
|
|
30
|
+
* @packageDocumentation
|
|
31
|
+
* @category Protocol
|
|
32
|
+
*/
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.defineApp = defineApp;
|
|
35
|
+
const protocol_1 = require("./protocol");
|
|
36
|
+
// ── Validation regexes / constants ───────────────────────────────
|
|
37
|
+
/**
|
|
38
|
+
* Identifier shape for app names and protocol names. Lowercase ASCII
|
|
39
|
+
* start, lowercase alphanumeric / underscore / hyphen rest, length 2-64.
|
|
40
|
+
* This grammar is the M3 sanitization on shared-spine metadata — it
|
|
41
|
+
* ensures app-supplied strings can't break the markdown bold in the
|
|
42
|
+
* boundary marker (no `*`) and can't inject newlines, code fences, or
|
|
43
|
+
* chat-role markers.
|
|
44
|
+
*/
|
|
45
|
+
const ID_RE = /^[a-z][a-z0-9_-]{1,63}$/;
|
|
46
|
+
/**
|
|
47
|
+
* Maximum length of `protocol.useWhen`. Bounded so the rendered catalog
|
|
48
|
+
* stays compact and to limit the residual semantic-injection surface
|
|
49
|
+
* available within the grammar's allowed character set.
|
|
50
|
+
*/
|
|
51
|
+
const USE_WHEN_MAX_LEN = 280;
|
|
52
|
+
/**
|
|
53
|
+
* Patterns forbidden anywhere in `protocol.useWhen` — chat-role markers
|
|
54
|
+
* (would confuse the model into treating the catalog text as a fake
|
|
55
|
+
* conversation) and markdown code fences (would let an attacker break
|
|
56
|
+
* out of the catalog block into structured content).
|
|
57
|
+
*/
|
|
58
|
+
const USE_WHEN_FORBIDDEN = [
|
|
59
|
+
/\bSYSTEM:/i,
|
|
60
|
+
/\bUSER:/i,
|
|
61
|
+
/\bASSISTANT\s+calls?:/i,
|
|
62
|
+
/\bASSISTANT:/i,
|
|
63
|
+
/```/,
|
|
64
|
+
/\r/,
|
|
65
|
+
/\n/,
|
|
66
|
+
];
|
|
67
|
+
/** Substring whose presence in `skill` (string form) would cause double-emission. */
|
|
68
|
+
const BOUNDARY_MARKER_PREFIX = 'Apply the **';
|
|
69
|
+
// ── Validation helpers ───────────────────────────────────────────
|
|
70
|
+
function assertIdentifier(value, field) {
|
|
71
|
+
if (typeof value !== 'string') {
|
|
72
|
+
throw new Error(`defineApp: ${field} must be a string, got ${typeof value}`);
|
|
73
|
+
}
|
|
74
|
+
if (!ID_RE.test(value)) {
|
|
75
|
+
throw new Error(`defineApp: ${field} ${JSON.stringify(value)} does not match the required ` +
|
|
76
|
+
`identifier grammar ${ID_RE.toString()} (lowercase alphanumeric + _-, length 2-64). ` +
|
|
77
|
+
`This is an App protocol metadata invariant — names appear in the boundary ` +
|
|
78
|
+
`marker and shared spine catalog where injection-prone characters must be excluded.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function assertUseWhen(value) {
|
|
82
|
+
if (typeof value !== 'string') {
|
|
83
|
+
throw new Error(`defineApp: manifest.protocol.useWhen must be a string, got ${typeof value}`);
|
|
84
|
+
}
|
|
85
|
+
if (value.length === 0 || value.length > USE_WHEN_MAX_LEN) {
|
|
86
|
+
throw new Error(`defineApp: manifest.protocol.useWhen length ${value.length} out of bounds ` +
|
|
87
|
+
`[1, ${USE_WHEN_MAX_LEN}]. Keep it to a single short sentence.`);
|
|
88
|
+
}
|
|
89
|
+
for (const pattern of USE_WHEN_FORBIDDEN) {
|
|
90
|
+
if (pattern.test(value)) {
|
|
91
|
+
throw new Error(`defineApp: manifest.protocol.useWhen contains forbidden pattern ${pattern.toString()}. ` +
|
|
92
|
+
`useWhen renders into the shared spine catalog; chat-role markers, code fences, and ` +
|
|
93
|
+
`line breaks are excluded to prevent injection at the catalog-text layer.`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function assertProtocolTools(tools) {
|
|
98
|
+
if (!Array.isArray(tools) || tools.length === 0) {
|
|
99
|
+
throw new Error(`defineApp: manifest.protocol.tools must be a non-empty array of tool-name strings`);
|
|
100
|
+
}
|
|
101
|
+
const seen = new Set();
|
|
102
|
+
for (const name of tools) {
|
|
103
|
+
assertIdentifier(name, `manifest.protocol.tools[*] (${JSON.stringify(name)})`);
|
|
104
|
+
if (seen.has(name)) {
|
|
105
|
+
throw new Error(`defineApp: manifest.protocol.tools contains duplicate ${JSON.stringify(name)}`);
|
|
106
|
+
}
|
|
107
|
+
seen.add(name);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function assertAppProtocolVersion(version) {
|
|
111
|
+
// Undefined is permitted — apps that don't declare a version are
|
|
112
|
+
// assumed to target the framework's default ("3.0"). The registry
|
|
113
|
+
// (enable-time) may tighten this if needed.
|
|
114
|
+
if (version === undefined)
|
|
115
|
+
return;
|
|
116
|
+
if (!protocol_1.SUPPORTED_APP_PROTOCOL_VERSIONS.includes(version)) {
|
|
117
|
+
throw new Error(`defineApp: manifest.appProtocolVersion ${JSON.stringify(version)} is not in the ` +
|
|
118
|
+
`supported set ${JSON.stringify(protocol_1.SUPPORTED_APP_PROTOCOL_VERSIONS)}. ` +
|
|
119
|
+
`This build of @lloyal-labs/rig only validates apps targeting one of those versions.`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function assertToolMapCoverage(protocolTools, toolsMap) {
|
|
123
|
+
const declared = new Set(protocolTools);
|
|
124
|
+
const provided = new Set(Object.keys(toolsMap));
|
|
125
|
+
// Missing — tools declared in the protocol but not supplied as instances.
|
|
126
|
+
const missing = [];
|
|
127
|
+
for (const name of declared) {
|
|
128
|
+
if (!provided.has(name))
|
|
129
|
+
missing.push(name);
|
|
130
|
+
}
|
|
131
|
+
if (missing.length > 0) {
|
|
132
|
+
throw new Error(`defineApp: tools map is missing implementations for protocol.tools: ` +
|
|
133
|
+
`${JSON.stringify(missing)}. Every declared tool must have a corresponding ` +
|
|
134
|
+
`entry in the \`tools\` map passed to defineApp.`);
|
|
135
|
+
}
|
|
136
|
+
// Extras — tools supplied as instances but not declared in the protocol.
|
|
137
|
+
const extras = [];
|
|
138
|
+
for (const name of provided) {
|
|
139
|
+
if (!declared.has(name))
|
|
140
|
+
extras.push(name);
|
|
141
|
+
}
|
|
142
|
+
if (extras.length > 0) {
|
|
143
|
+
throw new Error(`defineApp: tools map contains entries not declared in manifest.protocol.tools: ` +
|
|
144
|
+
`${JSON.stringify(extras)}. Add them to protocol.tools or remove from the tools map ` +
|
|
145
|
+
`— the catalog Tools: line is rendered from protocol.tools and the auth-guard's ` +
|
|
146
|
+
`allowed-tools set is derived from the same array, so extras would never be callable.`);
|
|
147
|
+
}
|
|
148
|
+
// Name agreement — each Tool instance's .name must match its key.
|
|
149
|
+
for (const [key, tool] of Object.entries(toolsMap)) {
|
|
150
|
+
if (tool.name !== key) {
|
|
151
|
+
throw new Error(`defineApp: tools[${JSON.stringify(key)}].name = ${JSON.stringify(tool.name)} ` +
|
|
152
|
+
`does not match its map key. The map key is what the framework dispatches against; ` +
|
|
153
|
+
`the Tool's name is what the model sees in the schema. They must agree.`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function assertSkillTemplate(skill) {
|
|
158
|
+
if (typeof skill === 'function') {
|
|
159
|
+
// Function-typed templates can't be statically validated here. The
|
|
160
|
+
// framework's first-render check catches double-emission
|
|
161
|
+
// at the first preamble render, not at defineApp time.
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (typeof skill !== 'string') {
|
|
165
|
+
throw new Error(`defineApp: spec.skill must be a string or SkillTemplateFn, got ${typeof skill}`);
|
|
166
|
+
}
|
|
167
|
+
if (skill.includes(BOUNDARY_MARKER_PREFIX)) {
|
|
168
|
+
throw new Error(`defineApp: skill template contains the literal ${JSON.stringify(BOUNDARY_MARKER_PREFIX)} substring. ` +
|
|
169
|
+
`The framework prepends \`Apply the **<name>** protocol.\\n\\n\` via BOUNDARY_MARKER at ` +
|
|
170
|
+
`render time; including it in the template would emit it twice. Strip the ` +
|
|
171
|
+
`\`Apply the **...** protocol.\` line (and its trailing blank line) from skill.eta.`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// ── defineApp ─────────────────────────────────────────────────────
|
|
175
|
+
/**
|
|
176
|
+
* Validate an app's declared shape and return the runtime {@link App}
|
|
177
|
+
* object the framework will register and render against.
|
|
178
|
+
*
|
|
179
|
+
* Throws synchronously on the first validation failure with a message
|
|
180
|
+
* naming the failing field and the violated rule.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* export function* createJiraApp(): Operation<App> {
|
|
185
|
+
* const cfgStore = yield* AppConfigStoreCtx.expect();
|
|
186
|
+
* const cfg = yield* cfgStore.get(manifest.name);
|
|
187
|
+
* if (!cfg) throw new Error('jira app requires config');
|
|
188
|
+
*
|
|
189
|
+
* const source = new JiraSource(cfg);
|
|
190
|
+
* const searchTool = yield* createJiraSearchTool(cfg);
|
|
191
|
+
* const readTool = yield* createJiraReadTool(cfg);
|
|
192
|
+
*
|
|
193
|
+
* return defineApp({
|
|
194
|
+
* manifest,
|
|
195
|
+
* source,
|
|
196
|
+
* tools: { jira_search: searchTool, jira_read: readTool },
|
|
197
|
+
* skill: skillTemplate,
|
|
198
|
+
* });
|
|
199
|
+
* }
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
function defineApp(spec) {
|
|
203
|
+
// 1. Manifest top-level identifier.
|
|
204
|
+
assertIdentifier(spec.manifest.name, 'manifest.name');
|
|
205
|
+
// 2. App protocol version (if declared).
|
|
206
|
+
assertAppProtocolVersion(spec.manifest.appProtocolVersion);
|
|
207
|
+
// 3. Protocol substructure: name, useWhen, tools.
|
|
208
|
+
assertIdentifier(spec.manifest.protocol.name, 'manifest.protocol.name');
|
|
209
|
+
assertUseWhen(spec.manifest.protocol.useWhen);
|
|
210
|
+
assertProtocolTools(spec.manifest.protocol.tools);
|
|
211
|
+
// 4. Tools map coverage and name agreement.
|
|
212
|
+
assertToolMapCoverage(spec.manifest.protocol.tools, spec.tools);
|
|
213
|
+
// 5. Agent template double-emission guard.
|
|
214
|
+
assertSkillTemplate(spec.skill);
|
|
215
|
+
// Preserve `protocol.tools` insertion order in the runtime tools array
|
|
216
|
+
// — that's the order the catalog renders and the order the spine
|
|
217
|
+
// prefill receives schemas in. The framework relies on stable ordering
|
|
218
|
+
// for the §10.1 snapshot gate.
|
|
219
|
+
const tools = spec.manifest.protocol.tools.map((name) => spec.tools[name]);
|
|
220
|
+
return {
|
|
221
|
+
name: spec.manifest.name,
|
|
222
|
+
manifest: spec.manifest,
|
|
223
|
+
source: spec.source,
|
|
224
|
+
tools,
|
|
225
|
+
skill: spec.skill,
|
|
226
|
+
examples: spec.examples,
|
|
227
|
+
configSchema: spec.manifest.configSchema,
|
|
228
|
+
hints: spec.hints ?? spec.manifest.hints,
|
|
229
|
+
configFlow: spec.configFlow,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=define-app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-app.js","sourceRoot":"","sources":["../src/define-app.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;AA6PH,8BAmCC;AAnRD,yCAA6D;AAwC7D,oEAAoE;AAEpE;;;;;;;GAOG;AACH,MAAM,KAAK,GAAG,yBAAyB,CAAC;AAExC;;;;GAIG;AACH,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B;;;;;GAKG;AACH,MAAM,kBAAkB,GAAsB;IAC5C,YAAY;IACZ,UAAU;IACV,wBAAwB;IACxB,eAAe;IACf,KAAK;IACL,IAAI;IACJ,IAAI;CACL,CAAC;AAEF,qFAAqF;AACrF,MAAM,sBAAsB,GAAG,cAAc,CAAC;AAE9C,oEAAoE;AAEpE,SAAS,gBAAgB,CAAC,KAAa,EAAE,KAAa;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,cAAc,KAAK,0BAA0B,OAAO,KAAK,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,cAAc,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,+BAA+B;YACzE,sBAAsB,KAAK,CAAC,QAAQ,EAAE,+CAA+C;YACrF,4EAA4E;YAC5E,oFAAoF,CACvF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,8DAA8D,OAAO,KAAK,EAAE,CAAC,CAAC;IAChG,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CACb,+CAA+C,KAAK,CAAC,MAAM,iBAAiB;YAC1E,OAAO,gBAAgB,wCAAwC,CAClE,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,kBAAkB,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CACb,mEAAmE,OAAO,CAAC,QAAQ,EAAE,IAAI;gBACvF,qFAAqF;gBACrF,0EAA0E,CAC7E,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAwB;IACnD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CACb,mFAAmF,CACpF,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,gBAAgB,CAAC,IAAI,EAAE,+BAA+B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/E,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,yDAAyD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnG,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,OAA2B;IAC3D,iEAAiE;IACjE,kEAAkE;IAClE,4CAA4C;IAC5C,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO;IAClC,IAAI,CAAC,0CAA+B,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CACb,0CAA0C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,iBAAiB;YAChF,iBAAiB,IAAI,CAAC,SAAS,CAAC,0CAA+B,CAAC,IAAI;YACpE,qFAAqF,CACxF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAC5B,aAAgC,EAChC,QAAwC;IAExC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEhD,0EAA0E;IAC1E,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,sEAAsE;YACpE,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,kDAAkD;YAC5E,iDAAiD,CACpD,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,iFAAiF;YAC/E,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,4DAA4D;YACrF,iFAAiF;YACjF,sFAAsF,CACzF,CAAC;IACJ,CAAC;IAED,kEAAkE;IAClE,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnD,IAAI,IAAI,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CACb,oBAAoB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;gBAC7E,oFAAoF;gBACpF,wEAAwE,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,KAA+B;IAC1D,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,mEAAmE;QACnE,yDAAyD;QACzD,uDAAuD;QACvD,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,kEAAkE,OAAO,KAAK,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,kDAAkD,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC,cAAc;YACpG,yFAAyF;YACzF,2EAA2E;YAC3E,oFAAoF,CACvF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,qEAAqE;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,SAAgB,SAAS,CAAC,IAAmB;IAC3C,oCAAoC;IACpC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAEtD,yCAAyC;IACzC,wBAAwB,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAE3D,kDAAkD;IAClD,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;IACxE,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9C,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAElD,4CAA4C;IAC5C,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAEhE,2CAA2C;IAC3C,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEhC,uEAAuE;IACvE,iEAAiE;IACjE,uEAAuE;IACvE,+BAA+B;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAE3E,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;QACxB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK;QACL,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY;QACxC,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK;QACxC,UAAU,EAAE,IAAI,CAAC,UAAU;KAC5B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory implementation of {@link GrantStore}.
|
|
3
|
+
*
|
|
4
|
+
* The `GrantStore` interface itself lives in `@lloyal-labs/lloyal-agents`
|
|
5
|
+
* (so the framework context `GrantStoreCtx` and app/harness code share it
|
|
6
|
+
* without a dependency cycle). This module supplies the reference impl that
|
|
7
|
+
* dev harnesses, examples, and tests use; harnesses that back grants with
|
|
8
|
+
* a secrets manager or remote authorization service implement the
|
|
9
|
+
* interface themselves.
|
|
10
|
+
*
|
|
11
|
+
* A grant records that the session has obtained consent to invoke a
|
|
12
|
+
* `protected` tool (see {@link Tool.protected}). The **credential** behind
|
|
13
|
+
* that consent (an OAuth token, an API key) is the harness's concern and
|
|
14
|
+
* never enters the model's context — this store holds only the binary
|
|
15
|
+
* decision the authGuard reads.
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
* @category Contract
|
|
19
|
+
*/
|
|
20
|
+
import type { GrantStore } from '@lloyal-labs/lloyal-agents';
|
|
21
|
+
/**
|
|
22
|
+
* Create an in-memory `GrantStore` backed by a `Set`.
|
|
23
|
+
*
|
|
24
|
+
* Intended for development, tests, and single-process harnesses. Pass
|
|
25
|
+
* `initial` to pre-grant a set of protected tools at construction (a
|
|
26
|
+
* harness that has already obtained consent, or a test fixture).
|
|
27
|
+
* Harnesses needing durable or audited grants implement the interface
|
|
28
|
+
* themselves against their preferred backend.
|
|
29
|
+
*/
|
|
30
|
+
export declare function createGrantStore(initial?: Iterable<string>): GrantStore;
|
|
31
|
+
//# sourceMappingURL=grant-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grant-store.d.ts","sourceRoot":"","sources":["../src/grant-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7D;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,UAAU,CAgBvE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* In-memory implementation of {@link GrantStore}.
|
|
4
|
+
*
|
|
5
|
+
* The `GrantStore` interface itself lives in `@lloyal-labs/lloyal-agents`
|
|
6
|
+
* (so the framework context `GrantStoreCtx` and app/harness code share it
|
|
7
|
+
* without a dependency cycle). This module supplies the reference impl that
|
|
8
|
+
* dev harnesses, examples, and tests use; harnesses that back grants with
|
|
9
|
+
* a secrets manager or remote authorization service implement the
|
|
10
|
+
* interface themselves.
|
|
11
|
+
*
|
|
12
|
+
* A grant records that the session has obtained consent to invoke a
|
|
13
|
+
* `protected` tool (see {@link Tool.protected}). The **credential** behind
|
|
14
|
+
* that consent (an OAuth token, an API key) is the harness's concern and
|
|
15
|
+
* never enters the model's context — this store holds only the binary
|
|
16
|
+
* decision the authGuard reads.
|
|
17
|
+
*
|
|
18
|
+
* @packageDocumentation
|
|
19
|
+
* @category Contract
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.createGrantStore = createGrantStore;
|
|
23
|
+
/**
|
|
24
|
+
* Create an in-memory `GrantStore` backed by a `Set`.
|
|
25
|
+
*
|
|
26
|
+
* Intended for development, tests, and single-process harnesses. Pass
|
|
27
|
+
* `initial` to pre-grant a set of protected tools at construction (a
|
|
28
|
+
* harness that has already obtained consent, or a test fixture).
|
|
29
|
+
* Harnesses needing durable or audited grants implement the interface
|
|
30
|
+
* themselves against their preferred backend.
|
|
31
|
+
*/
|
|
32
|
+
function createGrantStore(initial) {
|
|
33
|
+
const grants = new Set(initial);
|
|
34
|
+
return {
|
|
35
|
+
*has(toolName) {
|
|
36
|
+
return grants.has(toolName);
|
|
37
|
+
},
|
|
38
|
+
*grant(toolName) {
|
|
39
|
+
grants.add(toolName);
|
|
40
|
+
},
|
|
41
|
+
*revoke(toolName) {
|
|
42
|
+
grants.delete(toolName);
|
|
43
|
+
},
|
|
44
|
+
*granted() {
|
|
45
|
+
return [...grants];
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=grant-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grant-store.js","sourceRoot":"","sources":["../src/grant-store.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;AAcH,4CAgBC;AAzBD;;;;;;;;GAQG;AACH,SAAgB,gBAAgB,CAAC,OAA0B;IACzD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAS,OAAO,CAAC,CAAC;IACxC,OAAO;QACL,CAAC,GAAG,CAAC,QAAgB;YACnB,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9B,CAAC;QACD,CAAC,KAAK,CAAC,QAAgB;YACrB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;QACD,CAAC,MAAM,CAAC,QAAgB;YACtB,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QACD,CAAC,OAAO;YACN,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;QACrB,CAAC;KACF,CAAC;AACJ,CAAC"}
|