@llui/agent 0.0.30 → 0.0.31
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/dist/server/cloudflare/durable-object.d.ts +58 -0
- package/dist/server/cloudflare/durable-object.d.ts.map +1 -0
- package/dist/server/cloudflare/durable-object.js +33 -0
- package/dist/server/cloudflare/durable-object.js.map +1 -0
- package/dist/server/cloudflare/index.d.ts +49 -0
- package/dist/server/cloudflare/index.d.ts.map +1 -0
- package/dist/server/cloudflare/index.js +49 -0
- package/dist/server/cloudflare/index.js.map +1 -0
- package/dist/server/cloudflare/worker.d.ts +40 -0
- package/dist/server/cloudflare/worker.d.ts.map +1 -0
- package/dist/server/cloudflare/worker.js +55 -0
- package/dist/server/cloudflare/worker.js.map +1 -0
- package/dist/server/core-entry.d.ts +27 -0
- package/dist/server/core-entry.d.ts.map +1 -0
- package/dist/server/core-entry.js +19 -0
- package/dist/server/core-entry.js.map +1 -0
- package/dist/server/core.d.ts +78 -0
- package/dist/server/core.d.ts.map +1 -0
- package/dist/server/core.js +84 -0
- package/dist/server/core.js.map +1 -0
- package/dist/server/factory.d.ts +5 -3
- package/dist/server/factory.d.ts.map +1 -1
- package/dist/server/factory.js +18 -58
- package/dist/server/factory.js.map +1 -1
- package/dist/server/http/mint.d.ts.map +1 -1
- package/dist/server/http/mint.js +2 -3
- package/dist/server/http/mint.js.map +1 -1
- package/dist/server/http/resume.js +1 -1
- package/dist/server/http/resume.js.map +1 -1
- package/dist/server/identity.d.ts +5 -1
- package/dist/server/identity.d.ts.map +1 -1
- package/dist/server/identity.js +49 -11
- package/dist/server/identity.js.map +1 -1
- package/dist/server/index.d.ts +16 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +13 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/lap/confirm-result.d.ts +2 -2
- 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 +4 -4
- package/dist/server/lap/describe.d.ts.map +1 -1
- package/dist/server/lap/describe.js +4 -4
- package/dist/server/lap/describe.js.map +1 -1
- package/dist/server/lap/forward.d.ts +2 -2
- package/dist/server/lap/forward.d.ts.map +1 -1
- package/dist/server/lap/forward.js +1 -1
- package/dist/server/lap/forward.js.map +1 -1
- package/dist/server/lap/message.d.ts +2 -2
- 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 +2 -2
- 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/wait.d.ts +2 -2
- 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 +25 -1
- package/dist/server/options.d.ts.map +1 -1
- package/dist/server/options.js.map +1 -1
- package/dist/server/token.d.ts +7 -3
- package/dist/server/token.d.ts.map +1 -1
- package/dist/server/token.js +66 -26
- package/dist/server/token.js.map +1 -1
- package/dist/server/web/adapter.d.ts +16 -0
- package/dist/server/web/adapter.d.ts.map +1 -0
- package/dist/server/web/adapter.js +45 -0
- package/dist/server/web/adapter.js.map +1 -0
- package/dist/server/web/index.d.ts +12 -0
- package/dist/server/web/index.d.ts.map +1 -0
- package/dist/server/web/index.js +12 -0
- package/dist/server/web/index.js.map +1 -0
- package/dist/server/web/upgrade.d.ts +41 -0
- package/dist/server/web/upgrade.d.ts.map +1 -0
- package/dist/server/web/upgrade.js +96 -0
- package/dist/server/web/upgrade.js.map +1 -0
- package/dist/server/ws/pairing-registry.d.ts +84 -21
- package/dist/server/ws/pairing-registry.d.ts.map +1 -1
- package/dist/server/ws/pairing-registry.js +89 -151
- package/dist/server/ws/pairing-registry.js.map +1 -1
- package/dist/server/ws/rpc.d.ts +39 -0
- package/dist/server/ws/rpc.d.ts.map +1 -0
- package/dist/server/ws/rpc.js +126 -0
- package/dist/server/ws/rpc.js.map +1 -0
- package/dist/server/ws/upgrade.d.ts +3 -3
- package/dist/server/ws/upgrade.d.ts.map +1 -1
- package/dist/server/ws/upgrade.js +2 -2
- package/dist/server/ws/upgrade.js.map +1 -1
- package/package.json +13 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable Object helper for hosting the agent pairing + LAP surface
|
|
3
|
+
* on Cloudflare Workers. One DO instance owns one `tid` — its
|
|
4
|
+
* in-memory `PairingRegistry` survives across Worker isolate
|
|
5
|
+
* invocations because the DO IS persistent.
|
|
6
|
+
*
|
|
7
|
+
* This file exports a class designed to be composed into a real
|
|
8
|
+
* Durable Object in the user's Worker project. We intentionally
|
|
9
|
+
* don't subclass `DurableObject` from `@cloudflare/workers-types` —
|
|
10
|
+
* that dependency belongs to the user's project, not ours. Users
|
|
11
|
+
* wrap an instance of `AgentPairingDurableObject` in their own DO
|
|
12
|
+
* class and forward `fetch` to it.
|
|
13
|
+
*
|
|
14
|
+
* Usage in a Worker project:
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* // worker.ts
|
|
18
|
+
* import { AgentPairingDurableObject } from '@llui/agent/server/cloudflare'
|
|
19
|
+
*
|
|
20
|
+
* export class AgentDO {
|
|
21
|
+
* private agent: AgentPairingDurableObject
|
|
22
|
+
* constructor(_state: DurableObjectState, env: Env) {
|
|
23
|
+
* this.agent = new AgentPairingDurableObject({
|
|
24
|
+
* signingKey: env.AGENT_SIGNING_KEY,
|
|
25
|
+
* })
|
|
26
|
+
* }
|
|
27
|
+
* fetch(req: Request): Promise<Response> {
|
|
28
|
+
* return this.agent.fetch(req)
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* export default {
|
|
33
|
+
* async fetch(req: Request, env: Env): Promise<Response> {
|
|
34
|
+
* return routeToAgentDO(req, env.AGENT_DO, env.AGENT_SIGNING_KEY)
|
|
35
|
+
* },
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* See `./worker.ts` for `routeToAgentDO` and the full wiring.
|
|
40
|
+
*/
|
|
41
|
+
import type { CoreOptions, AgentCoreHandle } from '../core.js';
|
|
42
|
+
export type DurableObjectOptions = Omit<CoreOptions, 'registry'>;
|
|
43
|
+
/**
|
|
44
|
+
* Agent server instance scoped to a single Durable Object. All
|
|
45
|
+
* pairing state lives in the DO's in-process memory — which is safe
|
|
46
|
+
* here because the DO is a persistent addressable entity, not a
|
|
47
|
+
* one-shot Worker isolate.
|
|
48
|
+
*
|
|
49
|
+
* Users instantiate one of these inside their DO class's constructor
|
|
50
|
+
* and delegate `fetch` to `agent.fetch(req)`. LAP HTTP routes and
|
|
51
|
+
* WebSocket upgrades both flow through this single entry.
|
|
52
|
+
*/
|
|
53
|
+
export declare class AgentPairingDurableObject {
|
|
54
|
+
readonly agent: AgentCoreHandle;
|
|
55
|
+
constructor(opts: DurableObjectOptions);
|
|
56
|
+
fetch(req: Request): Promise<Response>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=durable-object.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-object.d.ts","sourceRoot":"","sources":["../../../src/server/cloudflare/durable-object.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAI9D,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAA;AAEhE;;;;;;;;;GASG;AACH,qBAAa,yBAAyB;IACpC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;gBAEnB,IAAI,EAAE,oBAAoB;IAIhC,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;CAgB7C"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createLluiAgentCore } from '../core.js';
|
|
2
|
+
import { handleCloudflareUpgrade } from '../web/upgrade.js';
|
|
3
|
+
/**
|
|
4
|
+
* Agent server instance scoped to a single Durable Object. All
|
|
5
|
+
* pairing state lives in the DO's in-process memory — which is safe
|
|
6
|
+
* here because the DO is a persistent addressable entity, not a
|
|
7
|
+
* one-shot Worker isolate.
|
|
8
|
+
*
|
|
9
|
+
* Users instantiate one of these inside their DO class's constructor
|
|
10
|
+
* and delegate `fetch` to `agent.fetch(req)`. LAP HTTP routes and
|
|
11
|
+
* WebSocket upgrades both flow through this single entry.
|
|
12
|
+
*/
|
|
13
|
+
export class AgentPairingDurableObject {
|
|
14
|
+
agent;
|
|
15
|
+
constructor(opts) {
|
|
16
|
+
this.agent = createLluiAgentCore(opts);
|
|
17
|
+
}
|
|
18
|
+
async fetch(req) {
|
|
19
|
+
const url = new URL(req.url);
|
|
20
|
+
// LAP routes (/agent/lap/v1/*, /agent/*). `router` returns null
|
|
21
|
+
// for non-matching paths so we can fall through to the upgrade.
|
|
22
|
+
const lapRes = await this.agent.router(req);
|
|
23
|
+
if (lapRes)
|
|
24
|
+
return lapRes;
|
|
25
|
+
// WebSocket upgrade — uses `WebSocketPair`, which only exists in
|
|
26
|
+
// Cloudflare Workers.
|
|
27
|
+
if (url.pathname === '/agent/ws') {
|
|
28
|
+
return handleCloudflareUpgrade(req, this.agent);
|
|
29
|
+
}
|
|
30
|
+
return new Response('Not Found', { status: 404 });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=durable-object.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-object.js","sourceRoot":"","sources":["../../../src/server/cloudflare/durable-object.ts"],"names":[],"mappings":"AAyCA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAI3D;;;;;;;;;GASG;AACH,MAAM,OAAO,yBAAyB;IAC3B,KAAK,CAAiB;IAE/B,YAAY,IAA0B;QACpC,IAAI,CAAC,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAA;IACxC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,GAAY;QACtB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAE5B,gEAAgE;QAChE,gEAAgE;QAChE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC3C,IAAI,MAAM;YAAE,OAAO,MAAM,CAAA;QAEzB,iEAAiE;QACjE,sBAAsB;QACtB,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;YACjC,OAAO,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;QACjD,CAAC;QAED,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IACnD,CAAC;CACF","sourcesContent":["/**\n * Durable Object helper for hosting the agent pairing + LAP surface\n * on Cloudflare Workers. One DO instance owns one `tid` — its\n * in-memory `PairingRegistry` survives across Worker isolate\n * invocations because the DO IS persistent.\n *\n * This file exports a class designed to be composed into a real\n * Durable Object in the user's Worker project. We intentionally\n * don't subclass `DurableObject` from `@cloudflare/workers-types` —\n * that dependency belongs to the user's project, not ours. Users\n * wrap an instance of `AgentPairingDurableObject` in their own DO\n * class and forward `fetch` to it.\n *\n * Usage in a Worker project:\n *\n * ```ts\n * // worker.ts\n * import { AgentPairingDurableObject } from '@llui/agent/server/cloudflare'\n *\n * export class AgentDO {\n * private agent: AgentPairingDurableObject\n * constructor(_state: DurableObjectState, env: Env) {\n * this.agent = new AgentPairingDurableObject({\n * signingKey: env.AGENT_SIGNING_KEY,\n * })\n * }\n * fetch(req: Request): Promise<Response> {\n * return this.agent.fetch(req)\n * }\n * }\n *\n * export default {\n * async fetch(req: Request, env: Env): Promise<Response> {\n * return routeToAgentDO(req, env.AGENT_DO, env.AGENT_SIGNING_KEY)\n * },\n * }\n * ```\n *\n * See `./worker.ts` for `routeToAgentDO` and the full wiring.\n */\nimport type { CoreOptions, AgentCoreHandle } from '../core.js'\nimport { createLluiAgentCore } from '../core.js'\nimport { handleCloudflareUpgrade } from '../web/upgrade.js'\n\nexport type DurableObjectOptions = Omit<CoreOptions, 'registry'>\n\n/**\n * Agent server instance scoped to a single Durable Object. All\n * pairing state lives in the DO's in-process memory — which is safe\n * here because the DO is a persistent addressable entity, not a\n * one-shot Worker isolate.\n *\n * Users instantiate one of these inside their DO class's constructor\n * and delegate `fetch` to `agent.fetch(req)`. LAP HTTP routes and\n * WebSocket upgrades both flow through this single entry.\n */\nexport class AgentPairingDurableObject {\n readonly agent: AgentCoreHandle\n\n constructor(opts: DurableObjectOptions) {\n this.agent = createLluiAgentCore(opts)\n }\n\n async fetch(req: Request): Promise<Response> {\n const url = new URL(req.url)\n\n // LAP routes (/agent/lap/v1/*, /agent/*). `router` returns null\n // for non-matching paths so we can fall through to the upgrade.\n const lapRes = await this.agent.router(req)\n if (lapRes) return lapRes\n\n // WebSocket upgrade — uses `WebSocketPair`, which only exists in\n // Cloudflare Workers.\n if (url.pathname === '/agent/ws') {\n return handleCloudflareUpgrade(req, this.agent)\n }\n\n return new Response('Not Found', { status: 404 })\n }\n}\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudflare Workers + Durable Object adapter. Use this sub-path
|
|
3
|
+
* from a Cloudflare Workers project where the agent pairing state
|
|
4
|
+
* lives inside a Durable Object.
|
|
5
|
+
*
|
|
6
|
+
* See the full deployment recipe at
|
|
7
|
+
* https://llui.dev/api/agent#cloudflare-deployment — the short
|
|
8
|
+
* version:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import {
|
|
12
|
+
* AgentPairingDurableObject,
|
|
13
|
+
* routeToAgentDO,
|
|
14
|
+
* } from '@llui/agent/server/cloudflare'
|
|
15
|
+
*
|
|
16
|
+
* export class AgentDO {
|
|
17
|
+
* private agent: AgentPairingDurableObject
|
|
18
|
+
* constructor(_state: DurableObjectState, env: Env) {
|
|
19
|
+
* this.agent = new AgentPairingDurableObject({
|
|
20
|
+
* signingKey: env.AGENT_SIGNING_KEY,
|
|
21
|
+
* })
|
|
22
|
+
* }
|
|
23
|
+
* fetch(req: Request) {
|
|
24
|
+
* return this.agent.fetch(req)
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* export default {
|
|
29
|
+
* async fetch(req: Request, env: Env) {
|
|
30
|
+
* return routeToAgentDO(req, env.AGENT_DO, env.AGENT_SIGNING_KEY)
|
|
31
|
+
* },
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* `wrangler.toml`:
|
|
36
|
+
* ```toml
|
|
37
|
+
* [[durable_objects.bindings]]
|
|
38
|
+
* name = "AGENT_DO"
|
|
39
|
+
* class_name = "AgentDO"
|
|
40
|
+
*
|
|
41
|
+
* [[migrations]]
|
|
42
|
+
* tag = "v1"
|
|
43
|
+
* new_classes = ["AgentDO"]
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export { AgentPairingDurableObject, type DurableObjectOptions } from './durable-object.js';
|
|
47
|
+
export { routeToAgentDO, type MinimalDurableObjectNamespace, type MinimalDurableObjectId, type MinimalDurableObjectStub, } from './worker.js';
|
|
48
|
+
export { createWHATWGPairingConnection, handleCloudflareUpgrade, extractToken, } from '../web/index.js';
|
|
49
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/cloudflare/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,OAAO,EAAE,yBAAyB,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1F,OAAO,EACL,cAAc,EACd,KAAK,6BAA6B,EAClC,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,GAC9B,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,6BAA6B,EAC7B,uBAAuB,EACvB,YAAY,GACb,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudflare Workers + Durable Object adapter. Use this sub-path
|
|
3
|
+
* from a Cloudflare Workers project where the agent pairing state
|
|
4
|
+
* lives inside a Durable Object.
|
|
5
|
+
*
|
|
6
|
+
* See the full deployment recipe at
|
|
7
|
+
* https://llui.dev/api/agent#cloudflare-deployment — the short
|
|
8
|
+
* version:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import {
|
|
12
|
+
* AgentPairingDurableObject,
|
|
13
|
+
* routeToAgentDO,
|
|
14
|
+
* } from '@llui/agent/server/cloudflare'
|
|
15
|
+
*
|
|
16
|
+
* export class AgentDO {
|
|
17
|
+
* private agent: AgentPairingDurableObject
|
|
18
|
+
* constructor(_state: DurableObjectState, env: Env) {
|
|
19
|
+
* this.agent = new AgentPairingDurableObject({
|
|
20
|
+
* signingKey: env.AGENT_SIGNING_KEY,
|
|
21
|
+
* })
|
|
22
|
+
* }
|
|
23
|
+
* fetch(req: Request) {
|
|
24
|
+
* return this.agent.fetch(req)
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* export default {
|
|
29
|
+
* async fetch(req: Request, env: Env) {
|
|
30
|
+
* return routeToAgentDO(req, env.AGENT_DO, env.AGENT_SIGNING_KEY)
|
|
31
|
+
* },
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* `wrangler.toml`:
|
|
36
|
+
* ```toml
|
|
37
|
+
* [[durable_objects.bindings]]
|
|
38
|
+
* name = "AGENT_DO"
|
|
39
|
+
* class_name = "AgentDO"
|
|
40
|
+
*
|
|
41
|
+
* [[migrations]]
|
|
42
|
+
* tag = "v1"
|
|
43
|
+
* new_classes = ["AgentDO"]
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export { AgentPairingDurableObject } from './durable-object.js';
|
|
47
|
+
export { routeToAgentDO, } from './worker.js';
|
|
48
|
+
export { createWHATWGPairingConnection, handleCloudflareUpgrade, extractToken, } from '../web/index.js';
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/cloudflare/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,OAAO,EAAE,yBAAyB,EAA6B,MAAM,qBAAqB,CAAA;AAC1F,OAAO,EACL,cAAc,GAIf,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,6BAA6B,EAC7B,uBAAuB,EACvB,YAAY,GACb,MAAM,iBAAiB,CAAA","sourcesContent":["/**\n * Cloudflare Workers + Durable Object adapter. Use this sub-path\n * from a Cloudflare Workers project where the agent pairing state\n * lives inside a Durable Object.\n *\n * See the full deployment recipe at\n * https://llui.dev/api/agent#cloudflare-deployment — the short\n * version:\n *\n * ```ts\n * import {\n * AgentPairingDurableObject,\n * routeToAgentDO,\n * } from '@llui/agent/server/cloudflare'\n *\n * export class AgentDO {\n * private agent: AgentPairingDurableObject\n * constructor(_state: DurableObjectState, env: Env) {\n * this.agent = new AgentPairingDurableObject({\n * signingKey: env.AGENT_SIGNING_KEY,\n * })\n * }\n * fetch(req: Request) {\n * return this.agent.fetch(req)\n * }\n * }\n *\n * export default {\n * async fetch(req: Request, env: Env) {\n * return routeToAgentDO(req, env.AGENT_DO, env.AGENT_SIGNING_KEY)\n * },\n * }\n * ```\n *\n * `wrangler.toml`:\n * ```toml\n * [[durable_objects.bindings]]\n * name = \"AGENT_DO\"\n * class_name = \"AgentDO\"\n *\n * [[migrations]]\n * tag = \"v1\"\n * new_classes = [\"AgentDO\"]\n * ```\n */\nexport { AgentPairingDurableObject, type DurableObjectOptions } from './durable-object.js'\nexport {\n routeToAgentDO,\n type MinimalDurableObjectNamespace,\n type MinimalDurableObjectId,\n type MinimalDurableObjectStub,\n} from './worker.js'\nexport {\n createWHATWGPairingConnection,\n handleCloudflareUpgrade,\n extractToken,\n} from '../web/index.js'\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal DurableObjectNamespace surface we need — `idFromName` +
|
|
3
|
+
* `get` returning a `Stub` with `fetch(req)`. Kept structural so we
|
|
4
|
+
* don't depend on `@cloudflare/workers-types` (the user's project has
|
|
5
|
+
* them; we shouldn't duplicate).
|
|
6
|
+
*/
|
|
7
|
+
export interface MinimalDurableObjectNamespace {
|
|
8
|
+
idFromName(name: string): MinimalDurableObjectId;
|
|
9
|
+
get(id: MinimalDurableObjectId): MinimalDurableObjectStub;
|
|
10
|
+
}
|
|
11
|
+
export interface MinimalDurableObjectId {
|
|
12
|
+
readonly name?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface MinimalDurableObjectStub {
|
|
15
|
+
fetch(req: Request): Promise<Response>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Route an incoming Worker `fetch` request to the Durable Object
|
|
19
|
+
* that owns its `tid`.
|
|
20
|
+
*
|
|
21
|
+
* The token travels in three places depending on the route:
|
|
22
|
+
* - LAP HTTP calls: `Authorization: Bearer <token>` header
|
|
23
|
+
* - Mint / resume HTTP calls: no token (identity resolver runs
|
|
24
|
+
* inside the DO via the LAP router; we route by origin or a
|
|
25
|
+
* special `/agent/mint` path — see below)
|
|
26
|
+
* - WebSocket upgrade: `?token=<token>` in the URL
|
|
27
|
+
*
|
|
28
|
+
* Requests that don't carry a tid (mint, resume-list, sessions) are
|
|
29
|
+
* routed to a "root" DO named `__root`, which handles identity /
|
|
30
|
+
* token store operations centrally. LAP and WS calls route to the
|
|
31
|
+
* per-tid DO so the pairing state stays local.
|
|
32
|
+
*
|
|
33
|
+
* This is the recommended entry for Cloudflare Workers deployments;
|
|
34
|
+
* users who need custom routing can write their own and call the
|
|
35
|
+
* underlying primitives (`verifyToken`, `namespace.get`, etc).
|
|
36
|
+
*/
|
|
37
|
+
export declare function routeToAgentDO(req: Request, namespace: MinimalDurableObjectNamespace, signingKey: string | Uint8Array, opts?: {
|
|
38
|
+
rootName?: string;
|
|
39
|
+
}): Promise<Response>;
|
|
40
|
+
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../../src/server/cloudflare/worker.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,WAAW,6BAA6B;IAC5C,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,CAAA;IAChD,GAAG,CAAC,EAAE,EAAE,sBAAsB,GAAG,wBAAwB,CAAA;CAC1D;AACD,MAAM,WAAW,sBAAsB;IAErC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AACD,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACvC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,6BAA6B,EACxC,UAAU,EAAE,MAAM,GAAG,UAAU,EAC/B,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,QAAQ,CAAC,CA4BnB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { verifyToken } from '../token.js';
|
|
2
|
+
/**
|
|
3
|
+
* Route an incoming Worker `fetch` request to the Durable Object
|
|
4
|
+
* that owns its `tid`.
|
|
5
|
+
*
|
|
6
|
+
* The token travels in three places depending on the route:
|
|
7
|
+
* - LAP HTTP calls: `Authorization: Bearer <token>` header
|
|
8
|
+
* - Mint / resume HTTP calls: no token (identity resolver runs
|
|
9
|
+
* inside the DO via the LAP router; we route by origin or a
|
|
10
|
+
* special `/agent/mint` path — see below)
|
|
11
|
+
* - WebSocket upgrade: `?token=<token>` in the URL
|
|
12
|
+
*
|
|
13
|
+
* Requests that don't carry a tid (mint, resume-list, sessions) are
|
|
14
|
+
* routed to a "root" DO named `__root`, which handles identity /
|
|
15
|
+
* token store operations centrally. LAP and WS calls route to the
|
|
16
|
+
* per-tid DO so the pairing state stays local.
|
|
17
|
+
*
|
|
18
|
+
* This is the recommended entry for Cloudflare Workers deployments;
|
|
19
|
+
* users who need custom routing can write their own and call the
|
|
20
|
+
* underlying primitives (`verifyToken`, `namespace.get`, etc).
|
|
21
|
+
*/
|
|
22
|
+
export async function routeToAgentDO(req, namespace, signingKey, opts = {}) {
|
|
23
|
+
const rootName = opts.rootName ?? '__root';
|
|
24
|
+
const url = new URL(req.url);
|
|
25
|
+
const path = url.pathname;
|
|
26
|
+
// Non-LAP / non-WS management endpoints (mint, resume, sessions,
|
|
27
|
+
// revoke) — there's no per-tid routing; use the root DO which owns
|
|
28
|
+
// the shared token store + identity resolver.
|
|
29
|
+
if (path === '/agent/mint' ||
|
|
30
|
+
path === '/agent/revoke' ||
|
|
31
|
+
path === '/agent/resume/list' ||
|
|
32
|
+
path === '/agent/resume/claim' ||
|
|
33
|
+
path === '/agent/sessions') {
|
|
34
|
+
const stub = namespace.get(namespace.idFromName(rootName));
|
|
35
|
+
return stub.fetch(req);
|
|
36
|
+
}
|
|
37
|
+
// Token-bearing routes (LAP + WS upgrade) — route by tid.
|
|
38
|
+
const token = extractTokenFromRequest(req);
|
|
39
|
+
if (!token)
|
|
40
|
+
return new Response('Unauthorized', { status: 401 });
|
|
41
|
+
const verified = await verifyToken(token, signingKey);
|
|
42
|
+
if (verified.kind !== 'ok')
|
|
43
|
+
return new Response('Unauthorized', { status: 401 });
|
|
44
|
+
const stub = namespace.get(namespace.idFromName(verified.payload.tid));
|
|
45
|
+
return stub.fetch(req);
|
|
46
|
+
}
|
|
47
|
+
function extractTokenFromRequest(req) {
|
|
48
|
+
const auth = req.headers.get('authorization');
|
|
49
|
+
if (auth?.startsWith('Bearer '))
|
|
50
|
+
return auth.slice('Bearer '.length);
|
|
51
|
+
const url = new URL(req.url);
|
|
52
|
+
const q = url.searchParams.get('token');
|
|
53
|
+
return q;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../src/server/cloudflare/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAoBzC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAY,EACZ,SAAwC,EACxC,UAA+B,EAC/B,OAA8B,EAAE;IAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAA;IAC1C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAA;IAEzB,iEAAiE;IACjE,mEAAmE;IACnE,8CAA8C;IAC9C,IACE,IAAI,KAAK,aAAa;QACtB,IAAI,KAAK,eAAe;QACxB,IAAI,KAAK,oBAAoB;QAC7B,IAAI,KAAK,qBAAqB;QAC9B,IAAI,KAAK,iBAAiB,EAC1B,CAAC;QACD,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAA;QAC1D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACxB,CAAC;IAED,0DAA0D;IAC1D,MAAM,KAAK,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAA;IAC1C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IAEhE,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;IACrD,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IAEhF,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAA;IACtE,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC;AAED,SAAS,uBAAuB,CAAC,GAAY;IAC3C,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IAC7C,IAAI,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACpE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACvC,OAAO,CAAC,CAAA;AACV,CAAC","sourcesContent":["import { verifyToken } from '../token.js'\n\n/**\n * Minimal DurableObjectNamespace surface we need — `idFromName` +\n * `get` returning a `Stub` with `fetch(req)`. Kept structural so we\n * don't depend on `@cloudflare/workers-types` (the user's project has\n * them; we shouldn't duplicate).\n */\nexport interface MinimalDurableObjectNamespace {\n idFromName(name: string): MinimalDurableObjectId\n get(id: MinimalDurableObjectId): MinimalDurableObjectStub\n}\nexport interface MinimalDurableObjectId {\n // Opaque, but DO ids are passed back into `namespace.get()`.\n readonly name?: string\n}\nexport interface MinimalDurableObjectStub {\n fetch(req: Request): Promise<Response>\n}\n\n/**\n * Route an incoming Worker `fetch` request to the Durable Object\n * that owns its `tid`.\n *\n * The token travels in three places depending on the route:\n * - LAP HTTP calls: `Authorization: Bearer <token>` header\n * - Mint / resume HTTP calls: no token (identity resolver runs\n * inside the DO via the LAP router; we route by origin or a\n * special `/agent/mint` path — see below)\n * - WebSocket upgrade: `?token=<token>` in the URL\n *\n * Requests that don't carry a tid (mint, resume-list, sessions) are\n * routed to a \"root\" DO named `__root`, which handles identity /\n * token store operations centrally. LAP and WS calls route to the\n * per-tid DO so the pairing state stays local.\n *\n * This is the recommended entry for Cloudflare Workers deployments;\n * users who need custom routing can write their own and call the\n * underlying primitives (`verifyToken`, `namespace.get`, etc).\n */\nexport async function routeToAgentDO(\n req: Request,\n namespace: MinimalDurableObjectNamespace,\n signingKey: string | Uint8Array,\n opts: { rootName?: string } = {},\n): Promise<Response> {\n const rootName = opts.rootName ?? '__root'\n const url = new URL(req.url)\n const path = url.pathname\n\n // Non-LAP / non-WS management endpoints (mint, resume, sessions,\n // revoke) — there's no per-tid routing; use the root DO which owns\n // the shared token store + identity resolver.\n if (\n path === '/agent/mint' ||\n path === '/agent/revoke' ||\n path === '/agent/resume/list' ||\n path === '/agent/resume/claim' ||\n path === '/agent/sessions'\n ) {\n const stub = namespace.get(namespace.idFromName(rootName))\n return stub.fetch(req)\n }\n\n // Token-bearing routes (LAP + WS upgrade) — route by tid.\n const token = extractTokenFromRequest(req)\n if (!token) return new Response('Unauthorized', { status: 401 })\n\n const verified = await verifyToken(token, signingKey)\n if (verified.kind !== 'ok') return new Response('Unauthorized', { status: 401 })\n\n const stub = namespace.get(namespace.idFromName(verified.payload.tid))\n return stub.fetch(req)\n}\n\nfunction extractTokenFromRequest(req: Request): string | null {\n const auth = req.headers.get('authorization')\n if (auth?.startsWith('Bearer ')) return auth.slice('Bearer '.length)\n const url = new URL(req.url)\n const q = url.searchParams.get('token')\n return q\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-neutral entry point. Import from `@llui/agent/server/core`
|
|
3
|
+
* when targeting runtimes without the Node `ws` library (Cloudflare
|
|
4
|
+
* Workers, Deno, Bun, Deno Deploy). Pair with
|
|
5
|
+
* `@llui/agent/server/web` for WebSocket upgrade helpers.
|
|
6
|
+
*
|
|
7
|
+
* Node/standard server processes should keep using the default
|
|
8
|
+
* `@llui/agent/server` entry, which includes this plus the `ws`-based
|
|
9
|
+
* upgrade handler.
|
|
10
|
+
*/
|
|
11
|
+
export { createLluiAgentCore } from './core.js';
|
|
12
|
+
export type { CoreOptions, AgentCoreHandle, AcceptResult } from './core.js';
|
|
13
|
+
export { InMemoryPairingRegistry } from './ws/pairing-registry.js';
|
|
14
|
+
export type { PairingConnection, PairingRegistry, FrameSubscriber } from './ws/pairing-registry.js';
|
|
15
|
+
export { rpc, waitForConfirm, waitForChange } from './ws/rpc.js';
|
|
16
|
+
export type { RpcOptions, RpcError } from './ws/rpc.js';
|
|
17
|
+
export { InMemoryTokenStore } from './token-store.js';
|
|
18
|
+
export type { TokenStore } from './token-store.js';
|
|
19
|
+
export { defaultIdentityResolver, signCookieValue } from './identity.js';
|
|
20
|
+
export type { IdentityResolver } from './identity.js';
|
|
21
|
+
export { consoleAuditSink } from './audit.js';
|
|
22
|
+
export type { AuditSink } from './audit.js';
|
|
23
|
+
export { defaultRateLimiter } from './rate-limit.js';
|
|
24
|
+
export type { RateLimiter } from './rate-limit.js';
|
|
25
|
+
export { signToken, verifyToken } from './token.js';
|
|
26
|
+
export type { TokenPayload, VerifyResult } from './token.js';
|
|
27
|
+
//# sourceMappingURL=core-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core-entry.d.ts","sourceRoot":"","sources":["../../src/server/core-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAC/C,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAClE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AACnG,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACxE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACpD,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACnD,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-neutral entry point. Import from `@llui/agent/server/core`
|
|
3
|
+
* when targeting runtimes without the Node `ws` library (Cloudflare
|
|
4
|
+
* Workers, Deno, Bun, Deno Deploy). Pair with
|
|
5
|
+
* `@llui/agent/server/web` for WebSocket upgrade helpers.
|
|
6
|
+
*
|
|
7
|
+
* Node/standard server processes should keep using the default
|
|
8
|
+
* `@llui/agent/server` entry, which includes this plus the `ws`-based
|
|
9
|
+
* upgrade handler.
|
|
10
|
+
*/
|
|
11
|
+
export { createLluiAgentCore } from './core.js';
|
|
12
|
+
export { InMemoryPairingRegistry } from './ws/pairing-registry.js';
|
|
13
|
+
export { rpc, waitForConfirm, waitForChange } from './ws/rpc.js';
|
|
14
|
+
export { InMemoryTokenStore } from './token-store.js';
|
|
15
|
+
export { defaultIdentityResolver, signCookieValue } from './identity.js';
|
|
16
|
+
export { consoleAuditSink } from './audit.js';
|
|
17
|
+
export { defaultRateLimiter } from './rate-limit.js';
|
|
18
|
+
export { signToken, verifyToken } from './token.js';
|
|
19
|
+
//# sourceMappingURL=core-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core-entry.js","sourceRoot":"","sources":["../../src/server/core-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAE/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAElE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAErD,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAExE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAEpD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA","sourcesContent":["/**\n * Runtime-neutral entry point. Import from `@llui/agent/server/core`\n * when targeting runtimes without the Node `ws` library (Cloudflare\n * Workers, Deno, Bun, Deno Deploy). Pair with\n * `@llui/agent/server/web` for WebSocket upgrade helpers.\n *\n * Node/standard server processes should keep using the default\n * `@llui/agent/server` entry, which includes this plus the `ws`-based\n * upgrade handler.\n */\nexport { createLluiAgentCore } from './core.js'\nexport type { CoreOptions, AgentCoreHandle, AcceptResult } from './core.js'\nexport { InMemoryPairingRegistry } from './ws/pairing-registry.js'\nexport type { PairingConnection, PairingRegistry, FrameSubscriber } from './ws/pairing-registry.js'\nexport { rpc, waitForConfirm, waitForChange } from './ws/rpc.js'\nexport type { RpcOptions, RpcError } from './ws/rpc.js'\nexport { InMemoryTokenStore } from './token-store.js'\nexport type { TokenStore } from './token-store.js'\nexport { defaultIdentityResolver, signCookieValue } from './identity.js'\nexport type { IdentityResolver } from './identity.js'\nexport { consoleAuditSink } from './audit.js'\nexport type { AuditSink } from './audit.js'\nexport { defaultRateLimiter } from './rate-limit.js'\nexport type { RateLimiter } from './rate-limit.js'\nexport { signToken, verifyToken } from './token.js'\nexport type { TokenPayload, VerifyResult } from './token.js'\n"]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-neutral core of the LLui agent server. Exports everything
|
|
3
|
+
* that works on any runtime with `crypto.subtle` + `Request`/`Response`
|
|
4
|
+
* + long-lived connection primitives — in practice: Node, Bun, Deno,
|
|
5
|
+
* Deno Deploy, Cloudflare Workers + Durable Objects.
|
|
6
|
+
*
|
|
7
|
+
* Intentionally does NOT import the `ws` library or any `node:*`
|
|
8
|
+
* modules. Node-specific wiring lives in `./factory.ts`
|
|
9
|
+
* (`createLluiAgentServer`); web runtimes use `./web/` adapters on
|
|
10
|
+
* top of this core.
|
|
11
|
+
*/
|
|
12
|
+
import type { ServerOptions } from './options.js';
|
|
13
|
+
import type { TokenStore } from './token-store.js';
|
|
14
|
+
import type { IdentityResolver } from './identity.js';
|
|
15
|
+
import type { AuditSink } from './audit.js';
|
|
16
|
+
import type { RateLimiter } from './rate-limit.js';
|
|
17
|
+
import type { PairingConnection, PairingRegistry } from './ws/pairing-registry.js';
|
|
18
|
+
/**
|
|
19
|
+
* Options accepted by `createLluiAgentCore`. Strict subset of
|
|
20
|
+
* `ServerOptions` — everything needed to build the router, registry,
|
|
21
|
+
* and accept-connection primitive. The Node factory adds WebSocket
|
|
22
|
+
* upgrade wiring on top.
|
|
23
|
+
*/
|
|
24
|
+
export type CoreOptions = {
|
|
25
|
+
signingKey: ServerOptions['signingKey'];
|
|
26
|
+
tokenStore?: TokenStore;
|
|
27
|
+
identityResolver?: IdentityResolver;
|
|
28
|
+
auditSink?: AuditSink;
|
|
29
|
+
rateLimiter?: RateLimiter;
|
|
30
|
+
lapBasePath?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Override the default `InMemoryPairingRegistry`. Web runtimes that
|
|
33
|
+
* need a different pairing implementation (e.g. a Cloudflare
|
|
34
|
+
* Durable Object that persists across isolates) pass it here.
|
|
35
|
+
*/
|
|
36
|
+
registry?: PairingRegistry;
|
|
37
|
+
};
|
|
38
|
+
export type AcceptResult = {
|
|
39
|
+
ok: true;
|
|
40
|
+
tid: string;
|
|
41
|
+
} | {
|
|
42
|
+
ok: false;
|
|
43
|
+
status: number;
|
|
44
|
+
code: 'auth-failed' | 'revoked';
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Handle returned by `createLluiAgentCore`. Purely runtime-neutral —
|
|
48
|
+
* `router` is a Fetch-style handler, `acceptConnection` is the
|
|
49
|
+
* primitive that runtime-specific WebSocket adapters call after
|
|
50
|
+
* accepting a socket in their native way.
|
|
51
|
+
*/
|
|
52
|
+
export type AgentCoreHandle = {
|
|
53
|
+
router: (req: Request) => Promise<Response | null>;
|
|
54
|
+
registry: PairingRegistry;
|
|
55
|
+
tokenStore: TokenStore;
|
|
56
|
+
auditSink: AuditSink;
|
|
57
|
+
/**
|
|
58
|
+
* Validate an agent token and register a `PairingConnection` with
|
|
59
|
+
* the registry. Use this after accepting a WebSocket upgrade via
|
|
60
|
+
* your runtime's native API (e.g. `WebSocketPair` on Cloudflare,
|
|
61
|
+
* `Deno.upgradeWebSocket` on Deno, `server.upgrade` on Bun).
|
|
62
|
+
*
|
|
63
|
+
* On success: marks the token `awaiting-claude`, writes an audit
|
|
64
|
+
* entry, and returns `{ok: true, tid}`. On failure: returns an
|
|
65
|
+
* appropriate HTTP status for the caller to encode into the
|
|
66
|
+
* upgrade response (401 for auth failure, 403 for revoked).
|
|
67
|
+
*/
|
|
68
|
+
acceptConnection: (token: string, conn: PairingConnection) => Promise<AcceptResult>;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Compose the runtime-neutral agent server. The returned handle has
|
|
72
|
+
* everything the LAP HTTP routes and the WebSocket acceptance
|
|
73
|
+
* plumbing need; runtime adapters wire the native upgrade API on
|
|
74
|
+
* top (see `@llui/agent/server` for Node, `@llui/agent/server/web`
|
|
75
|
+
* for WHATWG runtimes).
|
|
76
|
+
*/
|
|
77
|
+
export declare function createLluiAgentCore(opts: CoreOptions): AgentCoreHandle;
|
|
78
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/server/core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,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,iBAAiB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAWlF;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;IACvC,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,aAAa,GAAG,SAAS,CAAA;CAAE,CAAA;AAElE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAA;IAClD,QAAQ,EAAE,eAAe,CAAA;IACzB,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB;;;;;;;;;;OAUG;IACH,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;CACpF,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG,eAAe,CA2EtE"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { InMemoryTokenStore } from './token-store.js';
|
|
2
|
+
import { consoleAuditSink } from './audit.js';
|
|
3
|
+
import { defaultRateLimiter } from './rate-limit.js';
|
|
4
|
+
import { createHttpRouter } from './http/router.js';
|
|
5
|
+
import { createLapRouter } from './lap/router.js';
|
|
6
|
+
import { InMemoryPairingRegistry } from './ws/pairing-registry.js';
|
|
7
|
+
import { verifyToken } from './token.js';
|
|
8
|
+
const ANONYMOUS_RESOLVER = async () => null;
|
|
9
|
+
/**
|
|
10
|
+
* Compose the runtime-neutral agent server. The returned handle has
|
|
11
|
+
* everything the LAP HTTP routes and the WebSocket acceptance
|
|
12
|
+
* plumbing need; runtime adapters wire the native upgrade API on
|
|
13
|
+
* top (see `@llui/agent/server` for Node, `@llui/agent/server/web`
|
|
14
|
+
* for WHATWG runtimes).
|
|
15
|
+
*/
|
|
16
|
+
export function createLluiAgentCore(opts) {
|
|
17
|
+
if (!opts.signingKey) {
|
|
18
|
+
throw new Error('createLluiAgentCore: signingKey is required');
|
|
19
|
+
}
|
|
20
|
+
const tokenStore = opts.tokenStore ?? new InMemoryTokenStore();
|
|
21
|
+
const identityResolver = opts.identityResolver ?? ANONYMOUS_RESOLVER;
|
|
22
|
+
const auditSink = opts.auditSink ?? consoleAuditSink;
|
|
23
|
+
const rateLimiter = opts.rateLimiter ?? defaultRateLimiter({ perBucket: '30/minute' });
|
|
24
|
+
const lapBasePath = opts.lapBasePath ?? '/agent/lap/v1';
|
|
25
|
+
const registry = opts.registry ??
|
|
26
|
+
new InMemoryPairingRegistry({
|
|
27
|
+
onLogAppend: (tid, entry) => {
|
|
28
|
+
void auditSink.write({
|
|
29
|
+
at: entry.at,
|
|
30
|
+
tid,
|
|
31
|
+
uid: null,
|
|
32
|
+
event: 'lap-call',
|
|
33
|
+
detail: {
|
|
34
|
+
source: 'client-log',
|
|
35
|
+
kind: entry.kind,
|
|
36
|
+
variant: entry.variant,
|
|
37
|
+
intent: entry.intent,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
const httpRouter = createHttpRouter({
|
|
43
|
+
signingKey: opts.signingKey,
|
|
44
|
+
tokenStore,
|
|
45
|
+
identityResolver,
|
|
46
|
+
auditSink,
|
|
47
|
+
lapBasePath,
|
|
48
|
+
});
|
|
49
|
+
const lapRouter = createLapRouter({
|
|
50
|
+
signingKey: opts.signingKey,
|
|
51
|
+
tokenStore,
|
|
52
|
+
registry,
|
|
53
|
+
auditSink,
|
|
54
|
+
rateLimiter,
|
|
55
|
+
}, lapBasePath);
|
|
56
|
+
const router = async (req) => {
|
|
57
|
+
const lapRes = await lapRouter(req);
|
|
58
|
+
if (lapRes)
|
|
59
|
+
return lapRes;
|
|
60
|
+
return httpRouter(req);
|
|
61
|
+
};
|
|
62
|
+
const acceptConnection = async (token, conn) => {
|
|
63
|
+
const verified = await verifyToken(token, opts.signingKey);
|
|
64
|
+
if (verified.kind !== 'ok')
|
|
65
|
+
return { ok: false, status: 401, code: 'auth-failed' };
|
|
66
|
+
const { tid } = verified.payload;
|
|
67
|
+
const rec = await tokenStore.findByTid(tid);
|
|
68
|
+
if (!rec || rec.status === 'revoked')
|
|
69
|
+
return { ok: false, status: 403, code: 'revoked' };
|
|
70
|
+
registry.register(tid, conn);
|
|
71
|
+
const nowMs = Date.now();
|
|
72
|
+
await tokenStore.markAwaitingClaude(tid, nowMs);
|
|
73
|
+
await auditSink.write({
|
|
74
|
+
at: nowMs,
|
|
75
|
+
tid,
|
|
76
|
+
uid: null,
|
|
77
|
+
event: 'claim',
|
|
78
|
+
detail: { transport: 'ws' },
|
|
79
|
+
});
|
|
80
|
+
return { ok: true, tid };
|
|
81
|
+
};
|
|
82
|
+
return { router, registry, tokenStore, auditSink, acceptConnection };
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/server/core.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Runtime-neutral core of the LLui agent server. Exports everything\n * that works on any runtime with `crypto.subtle` + `Request`/`Response`\n * + long-lived connection primitives — in practice: Node, Bun, Deno,\n * Deno Deploy, Cloudflare Workers + Durable Objects.\n *\n * Intentionally does NOT import the `ws` library or any `node:*`\n * modules. Node-specific wiring lives in `./factory.ts`\n * (`createLluiAgentServer`); web runtimes use `./web/` adapters on\n * top of this core.\n */\nimport type { ServerOptions } from './options.js'\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 { PairingConnection, PairingRegistry } from './ws/pairing-registry.js'\nimport { InMemoryTokenStore } from './token-store.js'\nimport { consoleAuditSink } from './audit.js'\nimport { defaultRateLimiter } from './rate-limit.js'\nimport { createHttpRouter } from './http/router.js'\nimport { createLapRouter } from './lap/router.js'\nimport { InMemoryPairingRegistry } from './ws/pairing-registry.js'\nimport { verifyToken } from './token.js'\n\nconst ANONYMOUS_RESOLVER: IdentityResolver = async () => null\n\n/**\n * Options accepted by `createLluiAgentCore`. Strict subset of\n * `ServerOptions` — everything needed to build the router, registry,\n * and accept-connection primitive. The Node factory adds WebSocket\n * upgrade wiring on top.\n */\nexport type CoreOptions = {\n signingKey: ServerOptions['signingKey']\n tokenStore?: TokenStore\n identityResolver?: IdentityResolver\n auditSink?: AuditSink\n rateLimiter?: RateLimiter\n lapBasePath?: string\n /**\n * Override the default `InMemoryPairingRegistry`. Web runtimes that\n * need a different pairing implementation (e.g. a Cloudflare\n * Durable Object that persists across isolates) pass it here.\n */\n registry?: PairingRegistry\n}\n\nexport type AcceptResult =\n | { ok: true; tid: string }\n | { ok: false; status: number; code: 'auth-failed' | 'revoked' }\n\n/**\n * Handle returned by `createLluiAgentCore`. Purely runtime-neutral —\n * `router` is a Fetch-style handler, `acceptConnection` is the\n * primitive that runtime-specific WebSocket adapters call after\n * accepting a socket in their native way.\n */\nexport type AgentCoreHandle = {\n router: (req: Request) => Promise<Response | null>\n registry: PairingRegistry\n tokenStore: TokenStore\n auditSink: AuditSink\n /**\n * Validate an agent token and register a `PairingConnection` with\n * the registry. Use this after accepting a WebSocket upgrade via\n * your runtime's native API (e.g. `WebSocketPair` on Cloudflare,\n * `Deno.upgradeWebSocket` on Deno, `server.upgrade` on Bun).\n *\n * On success: marks the token `awaiting-claude`, writes an audit\n * entry, and returns `{ok: true, tid}`. On failure: returns an\n * appropriate HTTP status for the caller to encode into the\n * upgrade response (401 for auth failure, 403 for revoked).\n */\n acceptConnection: (token: string, conn: PairingConnection) => Promise<AcceptResult>\n}\n\n/**\n * Compose the runtime-neutral agent server. The returned handle has\n * everything the LAP HTTP routes and the WebSocket acceptance\n * plumbing need; runtime adapters wire the native upgrade API on\n * top (see `@llui/agent/server` for Node, `@llui/agent/server/web`\n * for WHATWG runtimes).\n */\nexport function createLluiAgentCore(opts: CoreOptions): AgentCoreHandle {\n if (!opts.signingKey) {\n throw new Error('createLluiAgentCore: signingKey is required')\n }\n\n const tokenStore = opts.tokenStore ?? new InMemoryTokenStore()\n const identityResolver = opts.identityResolver ?? ANONYMOUS_RESOLVER\n const auditSink = opts.auditSink ?? consoleAuditSink\n const rateLimiter = opts.rateLimiter ?? defaultRateLimiter({ perBucket: '30/minute' })\n const lapBasePath = opts.lapBasePath ?? '/agent/lap/v1'\n\n const registry: PairingRegistry =\n opts.registry ??\n new InMemoryPairingRegistry({\n onLogAppend: (tid, entry) => {\n void auditSink.write({\n at: entry.at,\n tid,\n uid: null,\n event: 'lap-call',\n detail: {\n source: 'client-log',\n kind: entry.kind,\n variant: entry.variant,\n intent: entry.intent,\n },\n })\n },\n })\n\n const httpRouter = createHttpRouter({\n signingKey: opts.signingKey,\n tokenStore,\n identityResolver,\n auditSink,\n lapBasePath,\n })\n\n const lapRouter = createLapRouter(\n {\n signingKey: opts.signingKey,\n tokenStore,\n registry,\n auditSink,\n rateLimiter,\n },\n lapBasePath,\n )\n\n const router: AgentCoreHandle['router'] = async (req) => {\n const lapRes = await lapRouter(req)\n if (lapRes) return lapRes\n return httpRouter(req)\n }\n\n const acceptConnection: AgentCoreHandle['acceptConnection'] = async (token, conn) => {\n const verified = await verifyToken(token, opts.signingKey)\n if (verified.kind !== 'ok') return { ok: false, status: 401, code: 'auth-failed' }\n const { tid } = verified.payload\n const rec = await tokenStore.findByTid(tid)\n if (!rec || rec.status === 'revoked') return { ok: false, status: 403, code: 'revoked' }\n registry.register(tid, conn)\n const nowMs = Date.now()\n await tokenStore.markAwaitingClaude(tid, nowMs)\n await auditSink.write({\n at: nowMs,\n tid,\n uid: null,\n event: 'claim',\n detail: { transport: 'ws' },\n })\n return { ok: true, tid }\n }\n\n return { router, registry, tokenStore, auditSink, acceptConnection }\n}\n"]}
|
package/dist/server/factory.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { ServerOptions, AgentServerHandle } from './options.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* `
|
|
5
|
-
*
|
|
3
|
+
* Node adapter. Wraps the runtime-neutral core with a Node-specific
|
|
4
|
+
* `wsUpgrade` handler that uses the `ws` library. Imports `ws`
|
|
5
|
+
* eagerly, so this module only works where `ws` is available — use
|
|
6
|
+
* `@llui/agent/server/web` for Cloudflare Workers, Deno, or other
|
|
7
|
+
* WHATWG runtimes.
|
|
6
8
|
*
|
|
7
9
|
* Spec §10.1, §10.4.
|
|
8
10
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/server/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/server/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAIpE;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,aAAa,GAAG,iBAAiB,CAkB5E"}
|