@llui/agent 0.0.32 → 0.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -1
- package/dist/client/agentConfirm.d.ts +48 -18
- package/dist/client/agentConfirm.d.ts.map +1 -1
- package/dist/client/agentConfirm.js +28 -25
- package/dist/client/agentConfirm.js.map +1 -1
- package/dist/client/agentConnect.d.ts +95 -34
- package/dist/client/agentConnect.d.ts.map +1 -1
- package/dist/client/agentConnect.js +85 -47
- package/dist/client/agentConnect.js.map +1 -1
- package/dist/client/agentLog.d.ts +31 -14
- package/dist/client/agentLog.d.ts.map +1 -1
- package/dist/client/agentLog.js +39 -20
- package/dist/client/agentLog.js.map +1 -1
- package/dist/client/effect-handler.d.ts +23 -0
- package/dist/client/effect-handler.d.ts.map +1 -1
- package/dist/client/effect-handler.js +185 -126
- package/dist/client/effect-handler.js.map +1 -1
- package/dist/client/effects.d.ts +13 -2
- package/dist/client/effects.d.ts.map +1 -1
- package/dist/client/effects.js.map +1 -1
- package/dist/client/factory.d.ts +55 -3
- package/dist/client/factory.d.ts.map +1 -1
- package/dist/client/factory.js +30 -5
- package/dist/client/factory.js.map +1 -1
- package/dist/client/rpc/describe-visible-content.d.ts +18 -5
- package/dist/client/rpc/describe-visible-content.d.ts.map +1 -1
- package/dist/client/rpc/describe-visible-content.js +112 -7
- package/dist/client/rpc/describe-visible-content.js.map +1 -1
- package/dist/client/rpc/list-actions.d.ts +52 -2
- package/dist/client/rpc/list-actions.d.ts.map +1 -1
- package/dist/client/rpc/list-actions.js +187 -5
- package/dist/client/rpc/list-actions.js.map +1 -1
- package/dist/client/rpc/query-state.d.ts +32 -0
- package/dist/client/rpc/query-state.d.ts.map +1 -0
- package/dist/client/rpc/query-state.js +82 -0
- package/dist/client/rpc/query-state.js.map +1 -0
- package/dist/client/rpc/send-message.d.ts +2 -0
- package/dist/client/rpc/send-message.d.ts.map +1 -1
- package/dist/client/rpc/send-message.js +119 -9
- package/dist/client/rpc/send-message.js.map +1 -1
- package/dist/client/rpc/would-dispatch.d.ts +66 -0
- package/dist/client/rpc/would-dispatch.d.ts.map +1 -0
- package/dist/client/rpc/would-dispatch.js +21 -0
- package/dist/client/rpc/would-dispatch.js.map +1 -0
- package/dist/client/ws-client.d.ts +3 -1
- package/dist/client/ws-client.d.ts.map +1 -1
- package/dist/client/ws-client.js +29 -0
- package/dist/client/ws-client.js.map +1 -1
- package/dist/codecs.d.ts +107 -0
- package/dist/codecs.d.ts.map +1 -0
- package/dist/codecs.js +166 -0
- package/dist/codecs.js.map +1 -0
- package/dist/protocol.d.ts +172 -12
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +7 -1
- package/dist/protocol.js.map +1 -1
- package/dist/server/cloudflare/durable-object.d.ts +11 -4
- package/dist/server/cloudflare/durable-object.d.ts.map +1 -1
- package/dist/server/cloudflare/durable-object.js.map +1 -1
- package/dist/server/cloudflare/index.d.ts +8 -4
- package/dist/server/cloudflare/index.d.ts.map +1 -1
- package/dist/server/cloudflare/index.js +8 -4
- package/dist/server/cloudflare/index.js.map +1 -1
- package/dist/server/cloudflare/worker.d.ts +10 -2
- package/dist/server/cloudflare/worker.d.ts.map +1 -1
- package/dist/server/cloudflare/worker.js +13 -6
- package/dist/server/cloudflare/worker.js.map +1 -1
- package/dist/server/core-entry.d.ts +2 -2
- package/dist/server/core-entry.d.ts.map +1 -1
- package/dist/server/core-entry.js +1 -1
- package/dist/server/core-entry.js.map +1 -1
- package/dist/server/core.d.ts +1 -3
- package/dist/server/core.d.ts.map +1 -1
- package/dist/server/core.js +13 -12
- package/dist/server/core.js.map +1 -1
- package/dist/server/factory.d.ts +1 -1
- package/dist/server/factory.d.ts.map +1 -1
- package/dist/server/factory.js +1 -2
- package/dist/server/factory.js.map +1 -1
- package/dist/server/http/mint.d.ts +6 -1
- package/dist/server/http/mint.d.ts.map +1 -1
- package/dist/server/http/mint.js +14 -6
- package/dist/server/http/mint.js.map +1 -1
- package/dist/server/http/resume.d.ts +3 -1
- package/dist/server/http/resume.d.ts.map +1 -1
- package/dist/server/http/resume.js +9 -7
- package/dist/server/http/resume.js.map +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/lap/confirm-result.d.ts +0 -1
- package/dist/server/lap/confirm-result.d.ts.map +1 -1
- package/dist/server/lap/confirm-result.js +1 -1
- package/dist/server/lap/confirm-result.js.map +1 -1
- package/dist/server/lap/describe.d.ts +13 -2
- package/dist/server/lap/describe.d.ts.map +1 -1
- package/dist/server/lap/describe.js +23 -6
- package/dist/server/lap/describe.js.map +1 -1
- package/dist/server/lap/forward.d.ts +13 -1
- package/dist/server/lap/forward.d.ts.map +1 -1
- package/dist/server/lap/forward.js +75 -1
- package/dist/server/lap/forward.js.map +1 -1
- package/dist/server/lap/message.d.ts +0 -1
- package/dist/server/lap/message.d.ts.map +1 -1
- package/dist/server/lap/message.js +1 -1
- package/dist/server/lap/message.js.map +1 -1
- package/dist/server/lap/observe.d.ts +0 -1
- package/dist/server/lap/observe.d.ts.map +1 -1
- package/dist/server/lap/observe.js +1 -1
- package/dist/server/lap/observe.js.map +1 -1
- package/dist/server/lap/router.d.ts.map +1 -1
- package/dist/server/lap/router.js +7 -1
- package/dist/server/lap/router.js.map +1 -1
- package/dist/server/lap/wait.d.ts +0 -1
- package/dist/server/lap/wait.d.ts.map +1 -1
- package/dist/server/lap/wait.js +1 -1
- package/dist/server/lap/wait.js.map +1 -1
- package/dist/server/options.d.ts +7 -5
- package/dist/server/options.d.ts.map +1 -1
- package/dist/server/options.js.map +1 -1
- package/dist/server/token-store.d.ts +22 -0
- package/dist/server/token-store.d.ts.map +1 -1
- package/dist/server/token-store.js +24 -0
- package/dist/server/token-store.js.map +1 -1
- package/dist/server/token.d.ts +32 -17
- package/dist/server/token.d.ts.map +1 -1
- package/dist/server/token.js +40 -103
- package/dist/server/token.js.map +1 -1
- package/dist/server/web/upgrade.d.ts +1 -1
- package/dist/server/web/upgrade.js +1 -1
- package/dist/server/web/upgrade.js.map +1 -1
- package/dist/server/ws/pairing-registry.d.ts +22 -6
- package/dist/server/ws/pairing-registry.d.ts.map +1 -1
- package/dist/server/ws/pairing-registry.js +49 -0
- package/dist/server/ws/pairing-registry.js.map +1 -1
- package/dist/server/ws/upgrade.d.ts +0 -1
- package/dist/server/ws/upgrade.d.ts.map +1 -1
- package/dist/server/ws/upgrade.js +12 -4
- package/dist/server/ws/upgrade.js.map +1 -1
- package/dist/state-diff.d.ts +52 -0
- package/dist/state-diff.d.ts.map +1 -0
- package/dist/state-diff.js +119 -0
- package/dist/state-diff.js.map +1 -0
- package/package.json +7 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { tokenHashOf } from '../token.js';
|
|
2
2
|
export async function handleLapDescribe(req, deps) {
|
|
3
|
-
const auth = await verifyAndReadTid(req, deps.
|
|
3
|
+
const auth = await verifyAndReadTid(req, deps.tokenStore);
|
|
4
4
|
if (!auth.ok)
|
|
5
5
|
return json({ error: { code: auth.code } }, auth.status);
|
|
6
6
|
const rec = await deps.tokenStore.findByTid(auth.tid);
|
|
@@ -48,15 +48,32 @@ export async function handleLapDescribe(req, deps) {
|
|
|
48
48
|
});
|
|
49
49
|
return json(out, 200);
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Resolve the bearer token on a request to a `tid`. The opaque-token
|
|
53
|
+
* scheme means "verify" is "look up the SHA-256 hash in the store and
|
|
54
|
+
* check expiry." A missing prefix, an unknown hash, or an expired
|
|
55
|
+
* record all collapse to the same `auth-failed` so a probe-by-hash
|
|
56
|
+
* leak surface is uniform.
|
|
57
|
+
*
|
|
58
|
+
* Status check (revoked / paused / etc.) is the caller's job — every
|
|
59
|
+
* LAP handler does its own follow-up `findByTid` to read the current
|
|
60
|
+
* status. This function only cares whether the bearer is one of ours
|
|
61
|
+
* and unexpired.
|
|
62
|
+
*/
|
|
63
|
+
export async function verifyAndReadTid(req, tokenStore, nowMs = Date.now()) {
|
|
52
64
|
const auth = req.headers.get('authorization');
|
|
53
65
|
if (!auth || !auth.startsWith('Bearer '))
|
|
54
66
|
return { ok: false, status: 401, code: 'auth-failed' };
|
|
55
67
|
const token = auth.slice('Bearer '.length);
|
|
56
|
-
const
|
|
57
|
-
if (
|
|
68
|
+
const hash = await tokenHashOf(token);
|
|
69
|
+
if (!hash)
|
|
58
70
|
return { ok: false, status: 401, code: 'auth-failed' };
|
|
59
|
-
|
|
71
|
+
const rec = await tokenStore.findByTokenHash(hash);
|
|
72
|
+
if (!rec)
|
|
73
|
+
return { ok: false, status: 401, code: 'auth-failed' };
|
|
74
|
+
if (rec.expiresAt <= nowMs)
|
|
75
|
+
return { ok: false, status: 401, code: 'auth-failed' };
|
|
76
|
+
return { ok: true, tid: rec.tid };
|
|
60
77
|
}
|
|
61
78
|
function json(b, s) {
|
|
62
79
|
return new Response(JSON.stringify(b), {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe.js","sourceRoot":"","sources":["../../../src/server/lap/describe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"describe.js","sourceRoot":"","sources":["../../../src/server/lap/describe.ts"],"names":[],"mappings":"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","sourcesContent":["import { tokenHashOf } from '../token.js'\nimport type { TokenStore } from '../token-store.js'\nimport type { PairingRegistry } from '../ws/pairing-registry.js'\nimport type { AuditSink } from '../audit.js'\nimport type { RateLimiter } from '../rate-limit.js'\nimport type { LapDescribeResponse, MessageSchemaEntry } from '../../protocol.js'\n\nexport type LapDescribeDeps = {\n tokenStore: TokenStore\n registry: PairingRegistry\n auditSink: AuditSink\n rateLimiter: RateLimiter\n now?: () => number\n}\n\nexport async function handleLapDescribe(req: Request, deps: LapDescribeDeps): Promise<Response> {\n const auth = await verifyAndReadTid(req, deps.tokenStore)\n if (!auth.ok) return json({ error: { code: auth.code } }, auth.status)\n\n const rec = await deps.tokenStore.findByTid(auth.tid)\n if (!rec || rec.status === 'revoked') return json({ error: { code: 'revoked' } }, 403)\n if (!deps.registry.isPaired(auth.tid)) return json({ error: { code: 'paused' } }, 503)\n\n const rlCheck = await deps.rateLimiter.check(auth.tid, 'token')\n if (!rlCheck.allowed) {\n return json({ error: { code: 'rate-limited', retryAfterMs: rlCheck.retryAfterMs } }, 429)\n }\n\n const hello = deps.registry.getHello(auth.tid)\n if (!hello) return json({ error: { code: 'paused' } }, 503)\n\n const messages: Record<string, MessageSchemaEntry> = hello.msgSchema as Record<\n string,\n MessageSchemaEntry\n >\n const out: LapDescribeResponse = {\n name: hello.appName,\n version: hello.appVersion,\n stateSchema: hello.stateSchema,\n messages,\n docs: hello.docs,\n conventions: {\n dispatchModel: 'TEA',\n confirmationModel: 'runtime-mediated',\n readSurfaces: ['state', 'query_dom', 'describe_visible_content', 'describe_context'],\n },\n schemaHash: hello.schemaHash,\n }\n\n const nowMs = (deps.now ?? (() => Date.now()))()\n // Transition to active: Claude has made its first LAP call to /describe,\n // confirming both the browser WS and Claude are live.\n const wasAwaitingClaude = rec.status === 'awaiting-claude'\n const label = rec.uid ?? 'Claude'\n await deps.tokenStore.markActive(auth.tid, label, nowMs)\n // Fire the active signal to the browser only on the first transition.\n if (wasAwaitingClaude) {\n deps.registry.send(auth.tid, { t: 'active' })\n }\n await deps.auditSink.write({\n at: nowMs,\n tid: auth.tid,\n uid: rec.uid,\n event: 'lap-call',\n detail: { path: '/lap/v1/describe' },\n })\n return json(out, 200)\n}\n\n/**\n * Resolve the bearer token on a request to a `tid`. The opaque-token\n * scheme means \"verify\" is \"look up the SHA-256 hash in the store and\n * check expiry.\" A missing prefix, an unknown hash, or an expired\n * record all collapse to the same `auth-failed` so a probe-by-hash\n * leak surface is uniform.\n *\n * Status check (revoked / paused / etc.) is the caller's job — every\n * LAP handler does its own follow-up `findByTid` to read the current\n * status. This function only cares whether the bearer is one of ours\n * and unexpired.\n */\nexport async function verifyAndReadTid(\n req: Request,\n tokenStore: TokenStore,\n nowMs: number = Date.now(),\n): Promise<{ ok: true; tid: string } | { ok: false; status: number; code: string }> {\n const auth = req.headers.get('authorization')\n if (!auth || !auth.startsWith('Bearer ')) return { ok: false, status: 401, code: 'auth-failed' }\n const token = auth.slice('Bearer '.length)\n const hash = await tokenHashOf(token)\n if (!hash) return { ok: false, status: 401, code: 'auth-failed' }\n const rec = await tokenStore.findByTokenHash(hash)\n if (!rec) return { ok: false, status: 401, code: 'auth-failed' }\n if (rec.expiresAt <= nowMs) return { ok: false, status: 401, code: 'auth-failed' }\n return { ok: true, tid: rec.tid }\n}\n\nfunction json(b: unknown, s: number): Response {\n return new Response(JSON.stringify(b), {\n status: s,\n headers: { 'content-type': 'application/json' },\n })\n}\n"]}
|
|
@@ -3,7 +3,6 @@ import type { PairingRegistry } from '../ws/pairing-registry.js';
|
|
|
3
3
|
import type { AuditSink } from '../audit.js';
|
|
4
4
|
import type { RateLimiter } from '../rate-limit.js';
|
|
5
5
|
export type ForwardDeps = {
|
|
6
|
-
signingKey: string | Uint8Array;
|
|
7
6
|
tokenStore: TokenStore;
|
|
8
7
|
registry: PairingRegistry;
|
|
9
8
|
auditSink: AuditSink;
|
|
@@ -17,8 +16,21 @@ export type ForwardDeps = {
|
|
|
17
16
|
*/
|
|
18
17
|
export declare function makeForwardHandler(tool: string, parseArgs: (body: unknown) => object | null, auditDetail?: (tid: string, args: object) => Record<string, unknown>): (req: Request, deps: ForwardDeps) => Promise<Response>;
|
|
19
18
|
export declare const handleLapState: (req: Request, deps: ForwardDeps) => Promise<Response>;
|
|
19
|
+
export declare const handleLapQueryState: (req: Request, deps: ForwardDeps) => Promise<Response>;
|
|
20
20
|
export declare const handleLapActions: (req: Request, deps: ForwardDeps) => Promise<Response>;
|
|
21
21
|
export declare const handleLapQueryDom: (req: Request, deps: ForwardDeps) => Promise<Response>;
|
|
22
22
|
export declare const handleLapDescribeVisible: (req: Request, deps: ForwardDeps) => Promise<Response>;
|
|
23
23
|
export declare const handleLapContext: (req: Request, deps: ForwardDeps) => Promise<Response>;
|
|
24
|
+
export declare const handleLapWouldDispatch: (req: Request, deps: ForwardDeps) => Promise<Response>;
|
|
25
|
+
/**
|
|
26
|
+
* Read recent log entries from the pairing registry's ring buffer.
|
|
27
|
+
* Server-side only — no round-trip to the browser. Used by the
|
|
28
|
+
* agent's `describe_recent_actions` tool to introspect its own
|
|
29
|
+
* activity history without re-fetching state.
|
|
30
|
+
*
|
|
31
|
+
* Diverges from `makeForwardHandler` because the data lives on the
|
|
32
|
+
* server (registry-owned), not the browser. The auth + paused +
|
|
33
|
+
* rate-limit gates run identically.
|
|
34
|
+
*/
|
|
35
|
+
export declare function handleLapRecentActions(req: Request, deps: ForwardDeps): Promise<Response>;
|
|
24
36
|
//# sourceMappingURL=forward.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forward.d.ts","sourceRoot":"","sources":["../../../src/server/lap/forward.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGnD,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"forward.d.ts","sourceRoot":"","sources":["../../../src/server/lap/forward.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGnD,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,eAAe,CAAA;IACzB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,WAAW,CAAA;IACxB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,EAC3C,WAAW,GAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAc,IAElE,KAAK,OAAO,EAAE,MAAM,WAAW,KAAG,OAAO,CAAC,QAAQ,CAAC,CAoClE;AAUD,eAAO,MAAM,cAAc,QA9CN,OAAO,QAAQ,WAAW,KAAG,OAAO,CAAC,QAAQ,CAkDhE,CAAA;AAEF,eAAO,MAAM,mBAAmB,QApDX,OAAO,QAAQ,WAAW,KAAG,OAAO,CAAC,QAAQ,CAwDhE,CAAA;AAEF,eAAO,MAAM,gBAAgB,QA1DR,OAAO,QAAQ,WAAW,KAAG,OAAO,CAAC,QAAQ,CA0DY,CAAA;AAE9E,eAAO,MAAM,iBAAiB,QA5DT,OAAO,QAAQ,WAAW,KAAG,OAAO,CAAC,QAAQ,CAgEhE,CAAA;AAEF,eAAO,MAAM,wBAAwB,QAlEhB,OAAO,QAAQ,WAAW,KAAG,OAAO,CAAC,QAAQ,CAkEgC,CAAA;AAElG,eAAO,MAAM,gBAAgB,QApER,OAAO,QAAQ,WAAW,KAAG,OAAO,CAAC,QAAQ,CAoEgB,CAAA;AAElF,eAAO,MAAM,sBAAsB,QAtEd,OAAO,QAAQ,WAAW,KAAG,OAAO,CAAC,QAAQ,CAiFhE,CAAA;AAEF;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwD/F"}
|
|
@@ -6,7 +6,7 @@ import { verifyAndReadTid } from './describe.js';
|
|
|
6
6
|
*/
|
|
7
7
|
export function makeForwardHandler(tool, parseArgs, auditDetail = () => ({})) {
|
|
8
8
|
return async (req, deps) => {
|
|
9
|
-
const auth = await verifyAndReadTid(req, deps.
|
|
9
|
+
const auth = await verifyAndReadTid(req, deps.tokenStore);
|
|
10
10
|
if (!auth.ok)
|
|
11
11
|
return json({ error: { code: auth.code } }, auth.status);
|
|
12
12
|
const rec = await deps.tokenStore.findByTid(auth.tid);
|
|
@@ -56,6 +56,12 @@ export const handleLapState = makeForwardHandler('get_state', (body) => {
|
|
|
56
56
|
return null;
|
|
57
57
|
return { path: b.path };
|
|
58
58
|
});
|
|
59
|
+
export const handleLapQueryState = makeForwardHandler('query_state', (body) => {
|
|
60
|
+
const b = (body ?? {});
|
|
61
|
+
if (typeof b.path !== 'string')
|
|
62
|
+
return null;
|
|
63
|
+
return { path: b.path };
|
|
64
|
+
});
|
|
59
65
|
export const handleLapActions = makeForwardHandler('list_actions', () => ({}));
|
|
60
66
|
export const handleLapQueryDom = makeForwardHandler('query_dom', (body) => {
|
|
61
67
|
const b = (body ?? {});
|
|
@@ -65,4 +71,72 @@ export const handleLapQueryDom = makeForwardHandler('query_dom', (body) => {
|
|
|
65
71
|
});
|
|
66
72
|
export const handleLapDescribeVisible = makeForwardHandler('describe_visible_content', () => ({}));
|
|
67
73
|
export const handleLapContext = makeForwardHandler('describe_context', () => ({}));
|
|
74
|
+
export const handleLapWouldDispatch = makeForwardHandler('would_dispatch', (body) => {
|
|
75
|
+
const b = (body ?? {});
|
|
76
|
+
if (b.msg === null ||
|
|
77
|
+
b.msg === undefined ||
|
|
78
|
+
typeof b.msg !== 'object' ||
|
|
79
|
+
typeof b.msg.type !== 'string') {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return { msg: b.msg };
|
|
83
|
+
});
|
|
84
|
+
/**
|
|
85
|
+
* Read recent log entries from the pairing registry's ring buffer.
|
|
86
|
+
* Server-side only — no round-trip to the browser. Used by the
|
|
87
|
+
* agent's `describe_recent_actions` tool to introspect its own
|
|
88
|
+
* activity history without re-fetching state.
|
|
89
|
+
*
|
|
90
|
+
* Diverges from `makeForwardHandler` because the data lives on the
|
|
91
|
+
* server (registry-owned), not the browser. The auth + paused +
|
|
92
|
+
* rate-limit gates run identically.
|
|
93
|
+
*/
|
|
94
|
+
export async function handleLapRecentActions(req, deps) {
|
|
95
|
+
const auth = await verifyAndReadTid(req, deps.tokenStore);
|
|
96
|
+
if (!auth.ok)
|
|
97
|
+
return new Response(JSON.stringify({ error: { code: auth.code } }), {
|
|
98
|
+
status: auth.status,
|
|
99
|
+
headers: { 'content-type': 'application/json' },
|
|
100
|
+
});
|
|
101
|
+
const rec = await deps.tokenStore.findByTid(auth.tid);
|
|
102
|
+
if (!rec || rec.status === 'revoked') {
|
|
103
|
+
return new Response(JSON.stringify({ error: { code: 'revoked' } }), {
|
|
104
|
+
status: 403,
|
|
105
|
+
headers: { 'content-type': 'application/json' },
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
if (!deps.registry.isPaired(auth.tid)) {
|
|
109
|
+
return new Response(JSON.stringify({ error: { code: 'paused' } }), {
|
|
110
|
+
status: 503,
|
|
111
|
+
headers: { 'content-type': 'application/json' },
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
const rlCheck = await deps.rateLimiter.check(auth.tid, 'token');
|
|
115
|
+
if (!rlCheck.allowed) {
|
|
116
|
+
return new Response(JSON.stringify({ error: { code: 'rate-limited', retryAfterMs: rlCheck.retryAfterMs } }), { status: 429, headers: { 'content-type': 'application/json' } });
|
|
117
|
+
}
|
|
118
|
+
const body = req.method === 'POST' ? await req.json().catch(() => null) : null;
|
|
119
|
+
const b = (body ?? {});
|
|
120
|
+
const n = typeof b.n === 'number' && b.n > 0 ? Math.floor(b.n) : 10;
|
|
121
|
+
// Allow filtering by kind so the agent can ask for "just dispatches"
|
|
122
|
+
// without sifting through reads. Default `null` returns all kinds.
|
|
123
|
+
const kindFilter = typeof b.kind === 'string' ? b.kind : null;
|
|
124
|
+
let entries = deps.registry.getRecentLog(auth.tid, kindFilter !== null ? 100 : n);
|
|
125
|
+
if (kindFilter !== null) {
|
|
126
|
+
entries = entries.filter((e) => e.kind === kindFilter).slice(0, n);
|
|
127
|
+
}
|
|
128
|
+
const nowMs = (deps.now ?? (() => Date.now()))();
|
|
129
|
+
await deps.tokenStore.touch(auth.tid, nowMs);
|
|
130
|
+
await deps.auditSink.write({
|
|
131
|
+
at: nowMs,
|
|
132
|
+
tid: auth.tid,
|
|
133
|
+
uid: rec.uid,
|
|
134
|
+
event: 'lap-call',
|
|
135
|
+
detail: { tool: 'describe_recent_actions', count: entries.length, kindFilter },
|
|
136
|
+
});
|
|
137
|
+
return new Response(JSON.stringify({ entries }), {
|
|
138
|
+
status: 200,
|
|
139
|
+
headers: { 'content-type': 'application/json' },
|
|
140
|
+
});
|
|
141
|
+
}
|
|
68
142
|
//# sourceMappingURL=forward.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forward.js","sourceRoot":"","sources":["../../../src/server/lap/forward.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TokenStore } from '../token-store.js'\nimport type { PairingRegistry } from '../ws/pairing-registry.js'\nimport type { AuditSink } from '../audit.js'\nimport type { RateLimiter } from '../rate-limit.js'\nimport { verifyAndReadTid } from './describe.js'\n\nexport type ForwardDeps = {\n signingKey: string | Uint8Array\n tokenStore: TokenStore\n registry: PairingRegistry\n auditSink: AuditSink\n rateLimiter: RateLimiter\n now?: () => number\n}\n\n/**\n * Generic LAP handler. `parseArgs` is called with the parsed body (may be\n * null for empty bodies); it returns the args object to forward or null\n * to reject as invalid. `tool` is the browser-side tool name.\n */\nexport function makeForwardHandler(\n tool: string,\n parseArgs: (body: unknown) => object | null,\n auditDetail: (tid: string, args: object) => Record<string, unknown> = () => ({}),\n) {\n return async (req: Request, deps: ForwardDeps): Promise<Response> => {\n const auth = await verifyAndReadTid(req, deps.signingKey)\n if (!auth.ok) return json({ error: { code: auth.code } }, auth.status)\n\n const rec = await deps.tokenStore.findByTid(auth.tid)\n if (!rec || rec.status === 'revoked') return json({ error: { code: 'revoked' } }, 403)\n if (!deps.registry.isPaired(auth.tid)) return json({ error: { code: 'paused' } }, 503)\n\n const rlCheck = await deps.rateLimiter.check(auth.tid, 'token')\n if (!rlCheck.allowed) {\n return json({ error: { code: 'rate-limited', retryAfterMs: rlCheck.retryAfterMs } }, 429)\n }\n\n const rawBody = req.method === 'POST' ? await req.json().catch(() => null) : null\n const args = parseArgs(rawBody)\n if (args === null) return json({ error: { code: 'invalid' } }, 400)\n\n try {\n const result = await deps.registry.rpc(auth.tid, tool, args)\n const nowMs = (deps.now ?? (() => Date.now()))()\n await deps.tokenStore.touch(auth.tid, nowMs)\n await deps.auditSink.write({\n at: nowMs,\n tid: auth.tid,\n uid: rec.uid,\n event: 'lap-call',\n detail: { tool, ...auditDetail(auth.tid, args) },\n })\n return json(result, 200)\n } catch (e: unknown) {\n const err = e as { code?: string; detail?: string }\n const code = err.code ?? 'internal'\n const status = code === 'paused' ? 503 : code === 'timeout' ? 504 : 500\n return json({ error: { code, detail: err.detail } }, status)\n }\n }\n}\n\nfunction json(b: unknown, s: number): Response {\n return new Response(JSON.stringify(b), {\n status: s,\n headers: { 'content-type': 'application/json' },\n })\n}\n\n// Concrete handlers:\nexport const handleLapState = makeForwardHandler('get_state', (body) => {\n const b = (body ?? {}) as { path?: unknown }\n if (b.path !== undefined && typeof b.path !== 'string') return null\n return { path: b.path }\n})\n\nexport const handleLapActions = makeForwardHandler('list_actions', () => ({}))\n\nexport const handleLapQueryDom = makeForwardHandler('query_dom', (body) => {\n const b = (body ?? {}) as { name?: unknown; multiple?: unknown }\n if (typeof b.name !== 'string') return null\n return { name: b.name, multiple: !!b.multiple }\n})\n\nexport const handleLapDescribeVisible = makeForwardHandler('describe_visible_content', () => ({}))\n\nexport const handleLapContext = makeForwardHandler('describe_context', () => ({}))\n"]}
|
|
1
|
+
{"version":3,"file":"forward.js","sourceRoot":"","sources":["../../../src/server/lap/forward.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TokenStore } from '../token-store.js'\nimport type { PairingRegistry } from '../ws/pairing-registry.js'\nimport type { AuditSink } from '../audit.js'\nimport type { RateLimiter } from '../rate-limit.js'\nimport { verifyAndReadTid } from './describe.js'\n\nexport type ForwardDeps = {\n tokenStore: TokenStore\n registry: PairingRegistry\n auditSink: AuditSink\n rateLimiter: RateLimiter\n now?: () => number\n}\n\n/**\n * Generic LAP handler. `parseArgs` is called with the parsed body (may be\n * null for empty bodies); it returns the args object to forward or null\n * to reject as invalid. `tool` is the browser-side tool name.\n */\nexport function makeForwardHandler(\n tool: string,\n parseArgs: (body: unknown) => object | null,\n auditDetail: (tid: string, args: object) => Record<string, unknown> = () => ({}),\n) {\n return async (req: Request, deps: ForwardDeps): Promise<Response> => {\n const auth = await verifyAndReadTid(req, deps.tokenStore)\n if (!auth.ok) return json({ error: { code: auth.code } }, auth.status)\n\n const rec = await deps.tokenStore.findByTid(auth.tid)\n if (!rec || rec.status === 'revoked') return json({ error: { code: 'revoked' } }, 403)\n if (!deps.registry.isPaired(auth.tid)) return json({ error: { code: 'paused' } }, 503)\n\n const rlCheck = await deps.rateLimiter.check(auth.tid, 'token')\n if (!rlCheck.allowed) {\n return json({ error: { code: 'rate-limited', retryAfterMs: rlCheck.retryAfterMs } }, 429)\n }\n\n const rawBody = req.method === 'POST' ? await req.json().catch(() => null) : null\n const args = parseArgs(rawBody)\n if (args === null) return json({ error: { code: 'invalid' } }, 400)\n\n try {\n const result = await deps.registry.rpc(auth.tid, tool, args)\n const nowMs = (deps.now ?? (() => Date.now()))()\n await deps.tokenStore.touch(auth.tid, nowMs)\n await deps.auditSink.write({\n at: nowMs,\n tid: auth.tid,\n uid: rec.uid,\n event: 'lap-call',\n detail: { tool, ...auditDetail(auth.tid, args) },\n })\n return json(result, 200)\n } catch (e: unknown) {\n const err = e as { code?: string; detail?: string }\n const code = err.code ?? 'internal'\n const status = code === 'paused' ? 503 : code === 'timeout' ? 504 : 500\n return json({ error: { code, detail: err.detail } }, status)\n }\n }\n}\n\nfunction json(b: unknown, s: number): Response {\n return new Response(JSON.stringify(b), {\n status: s,\n headers: { 'content-type': 'application/json' },\n })\n}\n\n// Concrete handlers:\nexport const handleLapState = makeForwardHandler('get_state', (body) => {\n const b = (body ?? {}) as { path?: unknown }\n if (b.path !== undefined && typeof b.path !== 'string') return null\n return { path: b.path }\n})\n\nexport const handleLapQueryState = makeForwardHandler('query_state', (body) => {\n const b = (body ?? {}) as { path?: unknown }\n if (typeof b.path !== 'string') return null\n return { path: b.path }\n})\n\nexport const handleLapActions = makeForwardHandler('list_actions', () => ({}))\n\nexport const handleLapQueryDom = makeForwardHandler('query_dom', (body) => {\n const b = (body ?? {}) as { name?: unknown; multiple?: unknown }\n if (typeof b.name !== 'string') return null\n return { name: b.name, multiple: !!b.multiple }\n})\n\nexport const handleLapDescribeVisible = makeForwardHandler('describe_visible_content', () => ({}))\n\nexport const handleLapContext = makeForwardHandler('describe_context', () => ({}))\n\nexport const handleLapWouldDispatch = makeForwardHandler('would_dispatch', (body) => {\n const b = (body ?? {}) as { msg?: unknown }\n if (\n b.msg === null ||\n b.msg === undefined ||\n typeof b.msg !== 'object' ||\n typeof (b.msg as { type?: unknown }).type !== 'string'\n ) {\n return null\n }\n return { msg: b.msg }\n})\n\n/**\n * Read recent log entries from the pairing registry's ring buffer.\n * Server-side only — no round-trip to the browser. Used by the\n * agent's `describe_recent_actions` tool to introspect its own\n * activity history without re-fetching state.\n *\n * Diverges from `makeForwardHandler` because the data lives on the\n * server (registry-owned), not the browser. The auth + paused +\n * rate-limit gates run identically.\n */\nexport async function handleLapRecentActions(req: Request, deps: ForwardDeps): Promise<Response> {\n const auth = await verifyAndReadTid(req, deps.tokenStore)\n if (!auth.ok)\n return new Response(JSON.stringify({ error: { code: auth.code } }), {\n status: auth.status,\n headers: { 'content-type': 'application/json' },\n })\n\n const rec = await deps.tokenStore.findByTid(auth.tid)\n if (!rec || rec.status === 'revoked') {\n return new Response(JSON.stringify({ error: { code: 'revoked' } }), {\n status: 403,\n headers: { 'content-type': 'application/json' },\n })\n }\n if (!deps.registry.isPaired(auth.tid)) {\n return new Response(JSON.stringify({ error: { code: 'paused' } }), {\n status: 503,\n headers: { 'content-type': 'application/json' },\n })\n }\n\n const rlCheck = await deps.rateLimiter.check(auth.tid, 'token')\n if (!rlCheck.allowed) {\n return new Response(\n JSON.stringify({ error: { code: 'rate-limited', retryAfterMs: rlCheck.retryAfterMs } }),\n { status: 429, headers: { 'content-type': 'application/json' } },\n )\n }\n\n const body = req.method === 'POST' ? await req.json().catch(() => null) : null\n const b = (body ?? {}) as { n?: unknown; kind?: unknown }\n const n = typeof b.n === 'number' && b.n > 0 ? Math.floor(b.n) : 10\n // Allow filtering by kind so the agent can ask for \"just dispatches\"\n // without sifting through reads. Default `null` returns all kinds.\n const kindFilter = typeof b.kind === 'string' ? b.kind : null\n\n let entries = deps.registry.getRecentLog(auth.tid, kindFilter !== null ? 100 : n)\n if (kindFilter !== null) {\n entries = entries.filter((e) => e.kind === kindFilter).slice(0, n)\n }\n\n const nowMs = (deps.now ?? (() => Date.now()))()\n await deps.tokenStore.touch(auth.tid, nowMs)\n await deps.auditSink.write({\n at: nowMs,\n tid: auth.tid,\n uid: rec.uid,\n event: 'lap-call',\n detail: { tool: 'describe_recent_actions', count: entries.length, kindFilter },\n })\n\n return new Response(JSON.stringify({ entries }), {\n status: 200,\n headers: { 'content-type': 'application/json' },\n })\n}\n"]}
|
|
@@ -3,7 +3,6 @@ import type { PairingRegistry } from '../ws/pairing-registry.js';
|
|
|
3
3
|
import type { AuditSink } from '../audit.js';
|
|
4
4
|
import type { RateLimiter } from '../rate-limit.js';
|
|
5
5
|
export type LapMessageDeps = {
|
|
6
|
-
signingKey: string | Uint8Array;
|
|
7
6
|
tokenStore: TokenStore;
|
|
8
7
|
registry: PairingRegistry;
|
|
9
8
|
auditSink: AuditSink;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../src/server/lap/message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAInD,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../src/server/lap/message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAInD,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,eAAe,CAAA;IACzB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,WAAW,CAAA;IACxB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB,CAAA;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6G5F"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { verifyAndReadTid } from './describe.js';
|
|
2
2
|
export async function handleLapMessage(req, deps) {
|
|
3
|
-
const auth = await verifyAndReadTid(req, deps.
|
|
3
|
+
const auth = await verifyAndReadTid(req, deps.tokenStore);
|
|
4
4
|
if (!auth.ok)
|
|
5
5
|
return json({ error: { code: auth.code } }, auth.status);
|
|
6
6
|
const rec = await deps.tokenStore.findByTid(auth.tid);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../../src/server/lap/message.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../../src/server/lap/message.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TokenStore } from '../token-store.js'\nimport type { PairingRegistry } from '../ws/pairing-registry.js'\nimport type { AuditSink } from '../audit.js'\nimport type { RateLimiter } from '../rate-limit.js'\nimport { verifyAndReadTid } from './describe.js'\nimport type { LapMessageRequest, LapMessageResponse } from '../../protocol.js'\n\nexport type LapMessageDeps = {\n tokenStore: TokenStore\n registry: PairingRegistry\n auditSink: AuditSink\n rateLimiter: RateLimiter\n now?: () => number\n}\n\nexport async function handleLapMessage(req: Request, deps: LapMessageDeps): Promise<Response> {\n const auth = await verifyAndReadTid(req, deps.tokenStore)\n if (!auth.ok) return json({ error: { code: auth.code } }, auth.status)\n\n const rec = await deps.tokenStore.findByTid(auth.tid)\n if (!rec || rec.status === 'revoked') return json({ error: { code: 'revoked' } }, 403)\n if (!deps.registry.isPaired(auth.tid)) return json({ error: { code: 'paused' } }, 503)\n\n const rlCheck = await deps.rateLimiter.check(auth.tid, 'token')\n if (!rlCheck.allowed) {\n return json({ error: { code: 'rate-limited', retryAfterMs: rlCheck.retryAfterMs } }, 429)\n }\n\n const body = (await req.json().catch(() => null)) as LapMessageRequest | null\n if (!body || !body.msg || typeof body.msg.type !== 'string') {\n return json({ error: { code: 'invalid' } }, 400)\n }\n\n const timeoutMs = body.timeoutMs ?? 5_000\n\n // The browser-side drain loop caps at `timeoutMs`; give the outer\n // RPC a small buffer so a near-edge drain doesn't race the transport\n // timeout and come back as a false 504.\n const rpcTimeoutMs = timeoutMs + 1_000\n\n let initial: LapMessageResponse\n try {\n initial = (await deps.registry.rpc(auth.tid, 'send_message', body, {\n timeoutMs: rpcTimeoutMs,\n })) as LapMessageResponse\n } catch (e: unknown) {\n const err = e as { code?: string; detail?: string }\n const status = err.code === 'paused' ? 503 : err.code === 'timeout' ? 504 : 500\n // Build a detail string that surfaces whatever info we have — the rpc-error\n // frame from the browser sometimes lacks `detail` (e.g., when a JS TypeError\n // bubbles out of the handler). Falling back to the code + any Error-like\n // fields gives Claude something actionable instead of an opaque 500.\n const detail =\n err.detail ??\n (e instanceof Error ? `${e.name}: ${e.message}` : undefined) ??\n (err.code ? `rpc rejected with code '${err.code}'` : 'rpc rejected without a code')\n // Mirror to the server console so operators see the real cause even when\n // the client just shows \"internal\".\n console.error(\n `[llui-agent] /lap/v1/message 500 — code=${err.code ?? 'internal'}, detail=${detail}`,\n )\n return json({ error: { code: err.code ?? 'internal', detail } }, status)\n }\n\n const nowMs = (deps.now ?? (() => Date.now()))()\n await deps.tokenStore.touch(auth.tid, nowMs)\n\n if (\n initial.status === 'dispatched' ||\n initial.status === 'confirmed' ||\n initial.status === 'rejected'\n ) {\n await deps.auditSink.write({\n at: nowMs,\n tid: auth.tid,\n uid: rec.uid,\n event: initial.status === 'rejected' ? 'msg-blocked' : 'msg-dispatched',\n detail: { variant: body.msg.type, status: initial.status },\n })\n return json(initial, 200)\n }\n\n if (initial.status === 'pending-confirmation') {\n await deps.auditSink.write({\n at: nowMs,\n tid: auth.tid,\n uid: rec.uid,\n event: 'confirm-proposed',\n detail: { variant: body.msg.type, confirmId: initial.confirmId },\n })\n const resolved = await deps.registry.waitForConfirm(auth.tid, initial.confirmId, timeoutMs)\n const nowMs2 = (deps.now ?? (() => Date.now()))()\n if (resolved.outcome === 'confirmed') {\n await deps.auditSink.write({\n at: nowMs2,\n tid: auth.tid,\n uid: rec.uid,\n event: 'confirm-approved',\n detail: { variant: body.msg.type, confirmId: initial.confirmId },\n })\n return json(\n { status: 'confirmed', stateAfter: resolved.stateAfter } satisfies LapMessageResponse,\n 200,\n )\n }\n await deps.auditSink.write({\n at: nowMs2,\n tid: auth.tid,\n uid: rec.uid,\n event: 'confirm-rejected',\n detail: { variant: body.msg.type, confirmId: initial.confirmId },\n })\n return json({ status: 'rejected', reason: 'user-cancelled' } satisfies LapMessageResponse, 200)\n }\n\n return json(\n {\n error: {\n code: 'internal',\n detail: `unexpected browser status: ${String((initial as { status?: unknown }).status ?? 'undefined')}`,\n },\n },\n 500,\n )\n}\n\nfunction json(b: unknown, s: number): Response {\n return new Response(JSON.stringify(b), {\n status: s,\n headers: { 'content-type': 'application/json' },\n })\n}\n"]}
|
|
@@ -3,7 +3,6 @@ import type { PairingRegistry } from '../ws/pairing-registry.js';
|
|
|
3
3
|
import type { AuditSink } from '../audit.js';
|
|
4
4
|
import type { RateLimiter } from '../rate-limit.js';
|
|
5
5
|
export type LapObserveDeps = {
|
|
6
|
-
signingKey: string | Uint8Array;
|
|
7
6
|
tokenStore: TokenStore;
|
|
8
7
|
registry: PairingRegistry;
|
|
9
8
|
auditSink: AuditSink;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../../src/server/lap/observe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAUnD,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../../src/server/lap/observe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAUnD,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,eAAe,CAAA;IACzB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,WAAW,CAAA;IACxB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6D5F"}
|
|
@@ -13,7 +13,7 @@ import { verifyAndReadTid } from './describe.js';
|
|
|
13
13
|
* is one call instead of three.
|
|
14
14
|
*/
|
|
15
15
|
export async function handleLapObserve(req, deps) {
|
|
16
|
-
const auth = await verifyAndReadTid(req, deps.
|
|
16
|
+
const auth = await verifyAndReadTid(req, deps.tokenStore);
|
|
17
17
|
if (!auth.ok)
|
|
18
18
|
return json({ error: { code: auth.code } }, auth.status);
|
|
19
19
|
const rec = await deps.tokenStore.findByTid(auth.tid);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observe.js","sourceRoot":"","sources":["../../../src/server/lap/observe.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"observe.js","sourceRoot":"","sources":["../../../src/server/lap/observe.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TokenStore } from '../token-store.js'\nimport type { PairingRegistry } from '../ws/pairing-registry.js'\nimport type { AuditSink } from '../audit.js'\nimport type { RateLimiter } from '../rate-limit.js'\nimport { verifyAndReadTid } from './describe.js'\nimport type {\n AgentContext,\n LapActionsResponse,\n LapDescribeResponse,\n LapObserveResponse,\n MessageSchemaEntry,\n} from '../../protocol.js'\n\nexport type LapObserveDeps = {\n tokenStore: TokenStore\n registry: PairingRegistry\n auditSink: AuditSink\n rateLimiter: RateLimiter\n now?: () => number\n}\n\n/**\n * Unified bootstrap endpoint. One call returns everything the LLM\n * needs to start acting on the app:\n * - state (dynamic, from browser)\n * - actions (dynamic, from browser)\n * - description (static, from cached hello frame)\n * - context (dynamic, from browser — agentContext(state))\n *\n * Replaces the get_state + list_actions + describe_app trio at the\n * MCP layer. Those LAP endpoints remain available for specialized\n * callers, but the common \"what can I see, what can I do\" question\n * is one call instead of three.\n */\nexport async function handleLapObserve(req: Request, deps: LapObserveDeps): Promise<Response> {\n const auth = await verifyAndReadTid(req, deps.tokenStore)\n if (!auth.ok) return json({ error: { code: auth.code } }, auth.status)\n\n const rec = await deps.tokenStore.findByTid(auth.tid)\n if (!rec || rec.status === 'revoked') return json({ error: { code: 'revoked' } }, 403)\n if (!deps.registry.isPaired(auth.tid)) return json({ error: { code: 'paused' } }, 503)\n\n const rlCheck = await deps.rateLimiter.check(auth.tid, 'token')\n if (!rlCheck.allowed) {\n return json({ error: { code: 'rate-limited', retryAfterMs: rlCheck.retryAfterMs } }, 429)\n }\n\n const hello = deps.registry.getHello(auth.tid)\n if (!hello) return json({ error: { code: 'paused' } }, 503)\n\n let dynamic: {\n state: unknown\n actions: LapActionsResponse['actions']\n context: AgentContext | null\n }\n try {\n dynamic = (await deps.registry.rpc(auth.tid, 'observe', {})) as typeof dynamic\n } catch (e: unknown) {\n const err = e as { code?: string; detail?: string }\n const code = err.code ?? 'internal'\n const status = code === 'paused' ? 503 : code === 'timeout' ? 504 : 500\n return json({ error: { code, detail: err.detail } }, status)\n }\n\n const description: LapDescribeResponse = {\n name: hello.appName,\n version: hello.appVersion,\n stateSchema: hello.stateSchema,\n messages: hello.msgSchema as Record<string, MessageSchemaEntry>,\n docs: hello.docs,\n conventions: {\n dispatchModel: 'TEA',\n confirmationModel: 'runtime-mediated',\n readSurfaces: ['state', 'query_dom', 'describe_visible_content', 'describe_context'],\n },\n schemaHash: hello.schemaHash,\n }\n\n const out: LapObserveResponse = {\n state: dynamic.state,\n actions: dynamic.actions,\n description,\n context: dynamic.context,\n }\n\n const nowMs = (deps.now ?? (() => Date.now()))()\n await deps.tokenStore.touch(auth.tid, nowMs)\n await deps.auditSink.write({\n at: nowMs,\n tid: auth.tid,\n uid: rec.uid,\n event: 'lap-call',\n detail: { tool: 'observe' },\n })\n return json(out, 200)\n}\n\nfunction json(b: unknown, s: number): Response {\n return new Response(JSON.stringify(b), {\n status: s,\n headers: { 'content-type': 'application/json' },\n })\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/server/lap/router.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/server/lap/router.ts"],"names":[],"mappings":"AACA,OAAO,EASL,KAAK,WAAW,EACjB,MAAM,cAAc,CAAA;AAMrB,MAAM,MAAM,aAAa,GAAG,WAAW,CAAA;AAEvC,wBAAgB,eAAe,CAC7B,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,MAAM,GACf,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAqC5C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { handleLapDescribe } from './describe.js';
|
|
2
|
-
import { handleLapState, handleLapActions, handleLapQueryDom, handleLapDescribeVisible, handleLapContext, } from './forward.js';
|
|
2
|
+
import { handleLapState, handleLapQueryState, handleLapActions, handleLapQueryDom, handleLapDescribeVisible, handleLapContext, handleLapRecentActions, handleLapWouldDispatch, } from './forward.js';
|
|
3
3
|
import { handleLapMessage } from './message.js';
|
|
4
4
|
import { handleLapWait } from './wait.js';
|
|
5
5
|
import { handleLapConfirmResult } from './confirm-result.js';
|
|
@@ -16,6 +16,8 @@ export function createLapRouter(deps, basePath) {
|
|
|
16
16
|
return handleLapDescribe(req, deps);
|
|
17
17
|
case '/state':
|
|
18
18
|
return handleLapState(req, deps);
|
|
19
|
+
case '/query-state':
|
|
20
|
+
return handleLapQueryState(req, deps);
|
|
19
21
|
case '/actions':
|
|
20
22
|
return handleLapActions(req, deps);
|
|
21
23
|
case '/message':
|
|
@@ -32,6 +34,10 @@ export function createLapRouter(deps, basePath) {
|
|
|
32
34
|
return handleLapContext(req, deps);
|
|
33
35
|
case '/observe':
|
|
34
36
|
return handleLapObserve(req, deps);
|
|
37
|
+
case '/recent-actions':
|
|
38
|
+
return handleLapRecentActions(req, deps);
|
|
39
|
+
case '/would-dispatch':
|
|
40
|
+
return handleLapWouldDispatch(req, deps);
|
|
35
41
|
default:
|
|
36
42
|
return null;
|
|
37
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/server/lap/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/server/lap/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,GAEvB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAI/C,MAAM,UAAU,eAAe,CAC7B,IAAmB,EACnB,QAAgB;IAEhB,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE;QACnB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAA;QACzB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC;YAAE,OAAO,IAAI,CAAA;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QACxC,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,WAAW;gBACd,OAAO,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACrC,KAAK,QAAQ;gBACX,OAAO,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YAClC,KAAK,cAAc;gBACjB,OAAO,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACvC,KAAK,UAAU;gBACb,OAAO,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACpC,KAAK,UAAU;gBACb,OAAO,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACpC,KAAK,iBAAiB;gBACpB,OAAO,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YAC1C,KAAK,OAAO;gBACV,OAAO,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACjC,KAAK,YAAY;gBACf,OAAO,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACrC,KAAK,mBAAmB;gBACtB,OAAO,wBAAwB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YAC5C,KAAK,UAAU;gBACb,OAAO,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACpC,KAAK,UAAU;gBACb,OAAO,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACpC,KAAK,iBAAiB;gBACpB,OAAO,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YAC1C,KAAK,iBAAiB;gBACpB,OAAO,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YAC1C;gBACE,OAAO,IAAI,CAAA;QACf,CAAC;IACH,CAAC,CAAA;AACH,CAAC","sourcesContent":["import { handleLapDescribe } from './describe.js'\nimport {\n handleLapState,\n handleLapQueryState,\n handleLapActions,\n handleLapQueryDom,\n handleLapDescribeVisible,\n handleLapContext,\n handleLapRecentActions,\n handleLapWouldDispatch,\n type ForwardDeps,\n} from './forward.js'\nimport { handleLapMessage } from './message.js'\nimport { handleLapWait } from './wait.js'\nimport { handleLapConfirmResult } from './confirm-result.js'\nimport { handleLapObserve } from './observe.js'\n\nexport type LapRouterDeps = ForwardDeps\n\nexport function createLapRouter(\n deps: LapRouterDeps,\n basePath: string,\n): (req: Request) => Promise<Response | null> {\n return async (req) => {\n const url = new URL(req.url)\n const path = url.pathname\n if (!path.startsWith(basePath + '/')) return null\n const tail = path.slice(basePath.length)\n switch (tail) {\n case '/describe':\n return handleLapDescribe(req, deps)\n case '/state':\n return handleLapState(req, deps)\n case '/query-state':\n return handleLapQueryState(req, deps)\n case '/actions':\n return handleLapActions(req, deps)\n case '/message':\n return handleLapMessage(req, deps)\n case '/confirm-result':\n return handleLapConfirmResult(req, deps)\n case '/wait':\n return handleLapWait(req, deps)\n case '/query-dom':\n return handleLapQueryDom(req, deps)\n case '/describe-visible':\n return handleLapDescribeVisible(req, deps)\n case '/context':\n return handleLapContext(req, deps)\n case '/observe':\n return handleLapObserve(req, deps)\n case '/recent-actions':\n return handleLapRecentActions(req, deps)\n case '/would-dispatch':\n return handleLapWouldDispatch(req, deps)\n default:\n return null\n }\n }\n}\n"]}
|
|
@@ -3,7 +3,6 @@ import type { PairingRegistry } from '../ws/pairing-registry.js';
|
|
|
3
3
|
import type { AuditSink } from '../audit.js';
|
|
4
4
|
import type { RateLimiter } from '../rate-limit.js';
|
|
5
5
|
export type LapWaitDeps = {
|
|
6
|
-
signingKey: string | Uint8Array;
|
|
7
6
|
tokenStore: TokenStore;
|
|
8
7
|
registry: PairingRegistry;
|
|
9
8
|
auditSink: AuditSink;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../../../src/server/lap/wait.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAInD,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../../../src/server/lap/wait.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAInD,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,eAAe,CAAA;IACzB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,WAAW,CAAA;IACxB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB,CAAA;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2BtF"}
|
package/dist/server/lap/wait.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { verifyAndReadTid } from './describe.js';
|
|
2
2
|
export async function handleLapWait(req, deps) {
|
|
3
|
-
const auth = await verifyAndReadTid(req, deps.
|
|
3
|
+
const auth = await verifyAndReadTid(req, deps.tokenStore);
|
|
4
4
|
if (!auth.ok)
|
|
5
5
|
return json({ error: { code: auth.code } }, auth.status);
|
|
6
6
|
const rec = await deps.tokenStore.findByTid(auth.tid);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../../../src/server/lap/wait.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../../../src/server/lap/wait.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAWhD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAY,EAAE,IAAiB;IACjE,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;IACzD,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IAEtE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACrD,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,CAAC,CAAA;IACtF,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,CAAC,CAAA;IAEtF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IAC/D,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,EAAE,EAAE,GAAG,CAAC,CAAA;IAC3F,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAmB,CAAA;IAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAA;IAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAChF,MAAM,GAAG,GAAoB,MAAM,CAAA;IAEnC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAA;IAChD,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QACzB,EAAE,EAAE,KAAK;QACT,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,KAAK,EAAE,UAAU;QACjB,MAAM,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;KACzD,CAAC,CAAA;IACF,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;AACvB,CAAC;AAED,SAAS,IAAI,CAAC,CAAU,EAAE,CAAS;IACjC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;QACrC,MAAM,EAAE,CAAC;QACT,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAChD,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import type { TokenStore } from '../token-store.js'\nimport type { PairingRegistry } from '../ws/pairing-registry.js'\nimport type { AuditSink } from '../audit.js'\nimport type { RateLimiter } from '../rate-limit.js'\nimport { verifyAndReadTid } from './describe.js'\nimport type { LapWaitRequest, LapWaitResponse } from '../../protocol.js'\n\nexport type LapWaitDeps = {\n tokenStore: TokenStore\n registry: PairingRegistry\n auditSink: AuditSink\n rateLimiter: RateLimiter\n now?: () => number\n}\n\nexport async function handleLapWait(req: Request, deps: LapWaitDeps): Promise<Response> {\n const auth = await verifyAndReadTid(req, deps.tokenStore)\n if (!auth.ok) return json({ error: { code: auth.code } }, auth.status)\n\n const rec = await deps.tokenStore.findByTid(auth.tid)\n if (!rec || rec.status === 'revoked') return json({ error: { code: 'revoked' } }, 403)\n if (!deps.registry.isPaired(auth.tid)) return json({ error: { code: 'paused' } }, 503)\n\n const rlCheck = await deps.rateLimiter.check(auth.tid, 'token')\n if (!rlCheck.allowed) {\n return json({ error: { code: 'rate-limited', retryAfterMs: rlCheck.retryAfterMs } }, 429)\n }\n\n const body = ((await req.json().catch(() => null)) ?? {}) as LapWaitRequest\n const timeoutMs = body.timeoutMs ?? 10_000\n const result = await deps.registry.waitForChange(auth.tid, body.path, timeoutMs)\n const out: LapWaitResponse = result\n\n const nowMs = (deps.now ?? (() => Date.now()))()\n await deps.auditSink.write({\n at: nowMs,\n tid: auth.tid,\n uid: rec.uid,\n event: 'lap-call',\n detail: { path: '/lap/v1/wait', outcome: result.status },\n })\n return json(out, 200)\n}\n\nfunction json(b: unknown, s: number): Response {\n return new Response(JSON.stringify(b), {\n status: s,\n headers: { 'content-type': 'application/json' },\n })\n}\n"]}
|
package/dist/server/options.d.ts
CHANGED
|
@@ -8,13 +8,15 @@ import type { PairingRegistry } from './ws/pairing-registry.js';
|
|
|
8
8
|
import type { AcceptResult } from './core.js';
|
|
9
9
|
import type { PairingConnection } from './ws/pairing-registry.js';
|
|
10
10
|
/**
|
|
11
|
-
* Options accepted by `createLluiAgentServer`. All values
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Options accepted by `createLluiAgentServer`. All values are
|
|
12
|
+
* optional and fall back to in-memory defaults. See spec §10.1.
|
|
13
|
+
*
|
|
14
|
+
* Pre-0.0.35 this required a `signingKey` for HMAC-signed JWT tokens.
|
|
15
|
+
* The new opaque-token scheme (token.ts) doesn't sign anything — the
|
|
16
|
+
* server stores the SHA-256 hash and looks tokens up. The option is
|
|
17
|
+
* gone; existing config that passed `signingKey` should drop it.
|
|
14
18
|
*/
|
|
15
19
|
export type ServerOptions = {
|
|
16
|
-
/** HMAC key for signing tokens. ≥32 bytes; rotation invalidates all tokens. */
|
|
17
|
-
signingKey: string | Uint8Array;
|
|
18
20
|
/** Token store. Defaults to an `InMemoryTokenStore`. */
|
|
19
21
|
tokenStore?: TokenStore;
|
|
20
22
|
/** Identity resolver. Defaults to anonymous (always null). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/server/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAEjE
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/server/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAEjE;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,wDAAwD;IACxD,UAAU,CAAC,EAAE,UAAU,CAAA;IAEvB,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IAEnC,kDAAkD;IAClD,SAAS,CAAC,EAAE,SAAS,CAAA;IAErB,qEAAqE;IACrE,WAAW,CAAC,EAAE,WAAW,CAAA;IAEzB,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB,gEAAgE;IAChE,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAChC,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAA;IAClD;;;;;;OAMG;IACH,SAAS,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAChF,oEAAoE;IACpE,QAAQ,EAAE,eAAe,CAAA;IACzB,8BAA8B;IAC9B,UAAU,EAAE,UAAU,CAAA;IACtB,6BAA6B;IAC7B,SAAS,EAAE,SAAS,CAAA;IACpB;;;;;;OAMG;IACH,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;CACpF,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/server/options.ts"],"names":[],"mappings":"","sourcesContent":["import type { IncomingMessage } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport type { TokenStore } from './token-store.js'\nimport type { IdentityResolver } from './identity.js'\nimport type { AuditSink } from './audit.js'\nimport type { RateLimiter } from './rate-limit.js'\nimport type { PairingRegistry } from './ws/pairing-registry.js'\nimport type { AcceptResult } from './core.js'\nimport type { PairingConnection } from './ws/pairing-registry.js'\n\n/**\n * Options accepted by `createLluiAgentServer`. All values
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/server/options.ts"],"names":[],"mappings":"","sourcesContent":["import type { IncomingMessage } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport type { TokenStore } from './token-store.js'\nimport type { IdentityResolver } from './identity.js'\nimport type { AuditSink } from './audit.js'\nimport type { RateLimiter } from './rate-limit.js'\nimport type { PairingRegistry } from './ws/pairing-registry.js'\nimport type { AcceptResult } from './core.js'\nimport type { PairingConnection } from './ws/pairing-registry.js'\n\n/**\n * Options accepted by `createLluiAgentServer`. All values are\n * optional and fall back to in-memory defaults. See spec §10.1.\n *\n * Pre-0.0.35 this required a `signingKey` for HMAC-signed JWT tokens.\n * The new opaque-token scheme (token.ts) doesn't sign anything — the\n * server stores the SHA-256 hash and looks tokens up. The option is\n * gone; existing config that passed `signingKey` should drop it.\n */\nexport type ServerOptions = {\n /** Token store. Defaults to an `InMemoryTokenStore`. */\n tokenStore?: TokenStore\n\n /** Identity resolver. Defaults to anonymous (always null). */\n identityResolver?: IdentityResolver\n\n /** Audit sink. Defaults to `consoleAuditSink`. */\n auditSink?: AuditSink\n\n /** Rate limiter. Defaults to `defaultRateLimiter` with 30/minute. */\n rateLimiter?: RateLimiter\n\n /** Base path prefix for LAP endpoints. Defaults to `/agent/lap/v1`. */\n lapBasePath?: string\n\n /** Pairing grace window after a tab closes, in ms. Default 15 min. */\n pairingGraceMs?: number\n\n /** Sliding TTL for active tokens, in ms. Default 1 h. */\n slidingTtlMs?: number\n\n /** Allowed origins for the HTTP surface (CORS). Empty = any. */\n corsOrigins?: readonly string[]\n}\n\n/**\n * Value returned by `createLluiAgentServer`. `router` matches any\n * `/agent/*` request and returns a Response (or null to fall through).\n * `wsUpgrade` handles Node HTTP upgrade events for `/agent/ws`.\n */\nexport type AgentServerHandle = {\n router: (req: Request) => Promise<Response | null>\n /**\n * Handles Node HTTP upgrade events for `/agent/ws`. Returns a Promise\n * because token verification uses WebCrypto (async). Node's\n * `server.on('upgrade', handler)` fires the handler without awaiting,\n * which is fine — the handler writes errors directly to the socket\n * and never throws back to the caller.\n */\n wsUpgrade: (req: IncomingMessage, socket: Duplex, head: Buffer) => Promise<void>\n /** The pairing registry. Runtime-neutral adapters may access it. */\n registry: PairingRegistry\n /** The active token store. */\n tokenStore: TokenStore\n /** The active audit sink. */\n auditSink: AuditSink\n /**\n * Runtime-neutral WebSocket acceptance primitive. Validates a token\n * and registers a `PairingConnection` with the registry. The Node\n * `wsUpgrade` above calls this internally; web-runtime adapters\n * (`@llui/agent/server/web`) use it after accepting a WebSocket via\n * their native API.\n */\n acceptConnection: (token: string, conn: PairingConnection) => Promise<AcceptResult>\n}\n"]}
|