@agimon-ai/po-core 0.0.0-alpha.103 → 0.0.0-alpha.105
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/apiContracts.d.mts +159 -7
- package/dist/apiContracts.d.mts.map +1 -1
- package/dist/headlessProtocol.cjs +2 -1
- package/dist/headlessProtocol.cjs.map +1 -1
- package/dist/headlessProtocol.mjs +2 -1
- package/dist/headlessProtocol.mjs.map +1 -1
- package/dist/headlessServer.cjs +20 -1
- package/dist/headlessServer.cjs.map +1 -1
- package/dist/headlessServer.mjs +20 -1
- package/dist/headlessServer.mjs.map +1 -1
- package/dist/headlessSessionHost.d.mts +1 -1
- package/dist/machineApi.cjs +2 -46
- package/dist/machineApi.cjs.map +1 -1
- package/dist/machineApi.d.mts.map +1 -1
- package/dist/machineApi.mjs +2 -46
- package/dist/machineApi.mjs.map +1 -1
- package/dist/nodePlatform.cjs +4 -1
- package/dist/nodePlatform.cjs.map +1 -1
- package/dist/nodePlatform.d.mts +3 -0
- package/dist/nodePlatform.d.mts.map +1 -1
- package/dist/nodePlatform.mjs +4 -1
- package/dist/nodePlatform.mjs.map +1 -1
- package/dist/packageApiServer.cjs +1 -0
- package/dist/packageApiServer.cjs.map +1 -1
- package/dist/packageApiServer.d.mts +1 -0
- package/dist/packageApiServer.d.mts.map +1 -1
- package/dist/packageApiServer.mjs +1 -0
- package/dist/packageApiServer.mjs.map +1 -1
- package/dist/platform.cjs +2 -0
- package/dist/platform.d.mts +2 -2
- package/dist/platform.mjs +2 -2
- package/dist/providerAuth.cjs +8 -0
- package/dist/providerAuth.d.mts +4 -0
- package/dist/providerAuth.mjs +3 -0
- package/dist/serverPlugin.cjs +6 -0
- package/dist/serverPlugin.d.mts +5 -2
- package/dist/serverPlugin.mjs +4 -1
- package/dist/src/pi/piSessionRuntime.cjs +13 -2
- package/dist/src/pi/piSessionRuntime.cjs.map +1 -1
- package/dist/src/pi/piSessionRuntime.d.mts +1 -1
- package/dist/src/pi/piSessionRuntime.mjs +13 -2
- package/dist/src/pi/piSessionRuntime.mjs.map +1 -1
- package/dist/src/schemas/approval.cjs +4 -1
- package/dist/src/schemas/approval.cjs.map +1 -1
- package/dist/src/schemas/approval.d.mts.map +1 -1
- package/dist/src/schemas/approval.mjs +4 -1
- package/dist/src/schemas/approval.mjs.map +1 -1
- package/dist/src/schemas/brain.cjs +43 -0
- package/dist/src/schemas/brain.cjs.map +1 -0
- package/dist/src/schemas/brain.d.mts +105 -0
- package/dist/src/schemas/brain.d.mts.map +1 -0
- package/dist/src/schemas/brain.mjs +43 -0
- package/dist/src/schemas/brain.mjs.map +1 -0
- package/dist/src/schemas/codemode.cjs +4 -1
- package/dist/src/schemas/codemode.cjs.map +1 -1
- package/dist/src/schemas/codemode.d.mts.map +1 -1
- package/dist/src/schemas/codemode.mjs +4 -1
- package/dist/src/schemas/codemode.mjs.map +1 -1
- package/dist/src/schemas/globalServices.cjs.map +1 -1
- package/dist/src/schemas/globalServices.d.mts +2 -2
- package/dist/src/schemas/globalServices.d.mts.map +1 -1
- package/dist/src/schemas/globalServices.mjs.map +1 -1
- package/dist/src/schemas/headless.d.mts +1 -1
- package/dist/src/schemas/hostServiceContracts.cjs +34 -0
- package/dist/src/schemas/hostServiceContracts.cjs.map +1 -0
- package/dist/src/schemas/hostServiceContracts.d.mts +23 -0
- package/dist/src/schemas/hostServiceContracts.d.mts.map +1 -0
- package/dist/src/schemas/hostServiceContracts.mjs +34 -0
- package/dist/src/schemas/hostServiceContracts.mjs.map +1 -0
- package/dist/src/schemas/packageApi.cjs.map +1 -1
- package/dist/src/schemas/packageApi.d.mts +3 -0
- package/dist/src/schemas/packageApi.d.mts.map +1 -1
- package/dist/src/schemas/packageApi.mjs.map +1 -1
- package/dist/src/schemas/platform.cjs +6 -0
- package/dist/src/schemas/platform.cjs.map +1 -1
- package/dist/src/schemas/platform.d.mts +68 -0
- package/dist/src/schemas/platform.d.mts.map +1 -1
- package/dist/src/schemas/platform.mjs +5 -1
- package/dist/src/schemas/platform.mjs.map +1 -1
- package/dist/src/schemas/serverBundle.d.mts +5 -0
- package/dist/src/schemas/serverBundle.d.mts.map +1 -1
- package/dist/src/schemas/serverScope.cjs +18 -1
- package/dist/src/schemas/serverScope.cjs.map +1 -1
- package/dist/src/schemas/serverScope.d.mts +11 -0
- package/dist/src/schemas/serverScope.d.mts.map +1 -1
- package/dist/src/schemas/serverScope.mjs +18 -2
- package/dist/src/schemas/serverScope.mjs.map +1 -1
- package/dist/src/server/conversationEvents.cjs +3 -2
- package/dist/src/server/conversationEvents.cjs.map +1 -1
- package/dist/src/server/conversationEvents.mjs +3 -2
- package/dist/src/server/conversationEvents.mjs.map +1 -1
- package/dist/src/server/directHarnessRuntime.cjs +55 -5
- package/dist/src/server/directHarnessRuntime.cjs.map +1 -1
- package/dist/src/server/directHarnessRuntime.d.mts.map +1 -1
- package/dist/src/server/directHarnessRuntime.mjs +55 -5
- package/dist/src/server/directHarnessRuntime.mjs.map +1 -1
- package/dist/src/server/providerRoutes.cjs +58 -0
- package/dist/src/server/providerRoutes.cjs.map +1 -0
- package/dist/src/server/providerRoutes.d.mts +16 -0
- package/dist/src/server/providerRoutes.d.mts.map +1 -0
- package/dist/src/server/providerRoutes.mjs +58 -0
- package/dist/src/server/providerRoutes.mjs.map +1 -0
- package/dist/src/server/serverScope.cjs +189 -9
- package/dist/src/server/serverScope.cjs.map +1 -1
- package/dist/src/server/serverScope.d.mts +8 -3
- package/dist/src/server/serverScope.d.mts.map +1 -1
- package/dist/src/server/serverScope.mjs +191 -11
- package/dist/src/server/serverScope.mjs.map +1 -1
- package/dist/src/services/edgeModelRuntime/index.cjs +363 -0
- package/dist/src/services/edgeModelRuntime/index.cjs.map +1 -0
- package/dist/src/services/edgeModelRuntime/index.d.mts +24 -0
- package/dist/src/services/edgeModelRuntime/index.d.mts.map +1 -0
- package/dist/src/services/edgeModelRuntime/index.mjs +360 -0
- package/dist/src/services/edgeModelRuntime/index.mjs.map +1 -0
- package/dist/src/services/edgeModelRuntime/type.d.mts +32 -0
- package/dist/src/services/edgeModelRuntime/type.d.mts.map +1 -0
- package/dist/src/services/globalServices/index.cjs +12 -3
- package/dist/src/services/globalServices/index.cjs.map +1 -1
- package/dist/src/services/globalServices/index.d.mts +2 -2
- package/dist/src/services/globalServices/index.d.mts.map +1 -1
- package/dist/src/services/globalServices/index.mjs +12 -3
- package/dist/src/services/globalServices/index.mjs.map +1 -1
- package/dist/src/services/providerAuth/index.cjs +1 -4
- package/dist/src/services/providerAuth/index.cjs.map +1 -1
- package/dist/src/services/providerAuth/index.mjs +0 -1
- package/dist/src/services/providerAuth/index.mjs.map +1 -1
- package/dist/src/systems/main/adapters/headlessSessionHost.cjs +3 -0
- package/dist/src/systems/main/adapters/headlessSessionHost.cjs.map +1 -1
- package/dist/src/systems/main/adapters/headlessSessionHost.mjs +3 -0
- package/dist/src/systems/main/adapters/headlessSessionHost.mjs.map +1 -1
- package/dist/src/systems/main/types/headlessHost.d.mts +1 -1
- package/dist/src/types/server/auth.d.mts +99 -0
- package/dist/src/types/server/auth.d.mts.map +1 -0
- package/dist/src/types/server/directHarnessRuntime.d.mts +10 -0
- package/dist/src/types/server/directHarnessRuntime.d.mts.map +1 -1
- package/dist/src/web/hostSlots.cjs +117 -0
- package/dist/src/web/hostSlots.cjs.map +1 -0
- package/dist/src/web/hostSlots.d.mts +109 -0
- package/dist/src/web/hostSlots.d.mts.map +1 -0
- package/dist/src/web/hostSlots.mjs +114 -0
- package/dist/src/web/hostSlots.mjs.map +1 -0
- package/dist/src/web/types/webPlugin.d.mts +4 -0
- package/dist/src/web/types/webPlugin.d.mts.map +1 -1
- package/dist/web.cjs +5 -0
- package/dist/web.d.mts +3 -1
- package/dist/web.mjs +2 -1
- package/dist/webCompositions.cjs.map +1 -1
- package/dist/webCompositions.d.mts +6 -0
- package/dist/webCompositions.d.mts.map +1 -1
- package/dist/webCompositions.mjs.map +1 -1
- package/package.json +9 -4
package/dist/apiContracts.d.mts
CHANGED
|
@@ -1,17 +1,111 @@
|
|
|
1
1
|
import { Static, TSchema, Type } from "typebox";
|
|
2
2
|
import { Context, method } from "@earendil-works/chord";
|
|
3
3
|
import { Events } from "@deepseek-ai/cordis";
|
|
4
|
+
import { AuthResult, ModelType, ModelsStoreEntry } from "@earendil-works/pi-ai";
|
|
4
5
|
import { Storage } from "@earendil-works/pi-durable";
|
|
5
6
|
import { FileSystem, Shell } from "@earendil-works/pi-durable/env";
|
|
6
7
|
import { SqliteDatabase } from "@earendil-works/pi-durable/storage/sqlite";
|
|
7
8
|
import "@agimon-ai/po-web-security/deviceProof";
|
|
8
9
|
import { Schema } from "@earendil-works/pi-schema";
|
|
9
10
|
import "@earendil-works/chord/context";
|
|
11
|
+
//#region src/schemas/serverBundle.d.ts
|
|
12
|
+
/** Every occurrence that can activate a package in this repository. */
|
|
13
|
+
interface PoServerBundleOwner {
|
|
14
|
+
readonly majorMode: string;
|
|
15
|
+
readonly layer: string;
|
|
16
|
+
}
|
|
17
|
+
interface PoServerBundleEntry {
|
|
18
|
+
readonly packageName: string;
|
|
19
|
+
/** Host-admitted distribution catalog origin, never inferred from a local path. */
|
|
20
|
+
readonly origin?: 'po' | 'personal' | 'unknown';
|
|
21
|
+
/** Validated additive client metadata, retained without importing browser code. */
|
|
22
|
+
readonly webMetadata?: PoWebBrainMetadata;
|
|
23
|
+
/** Parsed at package load. Missing or malformed contracts cannot authorize federation. */
|
|
24
|
+
readonly apiContract?: PoApiContract;
|
|
25
|
+
/** The declared package-relative source entry, retained for attribution. */
|
|
26
|
+
readonly entry: string;
|
|
27
|
+
/** Absolute path of the package's built module; the live loader imports it from its content URL. */
|
|
28
|
+
readonly module: string;
|
|
29
|
+
readonly scopes: readonly PoApiScope[];
|
|
30
|
+
readonly owners: readonly PoServerBundleOwner[];
|
|
31
|
+
readonly required: boolean;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/schemas/brain.d.ts
|
|
35
|
+
/** Detached descriptions only. No service values, fibers, paths or callbacks cross this boundary. */
|
|
36
|
+
interface BrainScope {
|
|
37
|
+
id: string;
|
|
38
|
+
level: PoApiScope;
|
|
39
|
+
}
|
|
40
|
+
interface BrainOwner {
|
|
41
|
+
kind: 'host' | 'package' | 'unknown';
|
|
42
|
+
packageName: string | null;
|
|
43
|
+
origin: NonNullable<PoServerBundleEntry['origin']>;
|
|
44
|
+
}
|
|
45
|
+
interface BrainService {
|
|
46
|
+
id: string;
|
|
47
|
+
name: string;
|
|
48
|
+
scope: BrainScope;
|
|
49
|
+
visibleFrom: BrainScope;
|
|
50
|
+
owner: BrainOwner;
|
|
51
|
+
public: boolean;
|
|
52
|
+
description: string | null;
|
|
53
|
+
}
|
|
54
|
+
interface BrainConsumer {
|
|
55
|
+
id: string;
|
|
56
|
+
name: string;
|
|
57
|
+
scope: BrainScope;
|
|
58
|
+
owner: BrainOwner;
|
|
59
|
+
}
|
|
60
|
+
/** Declared injections only, never inferred from ctx.get or requirePo helpers. */
|
|
61
|
+
interface BrainEdge {
|
|
62
|
+
consumer: string;
|
|
63
|
+
service: string | null;
|
|
64
|
+
name: string;
|
|
65
|
+
status: 'resolved' | 'waiting';
|
|
66
|
+
}
|
|
67
|
+
interface BrainPackage {
|
|
68
|
+
scope: BrainScope;
|
|
69
|
+
owner: BrainOwner;
|
|
70
|
+
web: PoWebBrainMetadata | null;
|
|
71
|
+
}
|
|
72
|
+
interface BrainServicesSnapshot {
|
|
73
|
+
scope: BrainScope;
|
|
74
|
+
scopes: BrainScope[];
|
|
75
|
+
packages: BrainPackage[];
|
|
76
|
+
/** Exact published browser mounts, when the host supplied every scope's inventory. */
|
|
77
|
+
clientPackages?: BrainPackage[];
|
|
78
|
+
services: BrainService[];
|
|
79
|
+
consumers: BrainConsumer[];
|
|
80
|
+
edges: BrainEdge[];
|
|
81
|
+
diagnostics: string[];
|
|
82
|
+
}
|
|
83
|
+
/** Additive manifest metadata. Older manifests omit this block rather than claiming no slots. */
|
|
84
|
+
interface PoWebBrainMetadata {
|
|
85
|
+
version: 1;
|
|
86
|
+
slots: {
|
|
87
|
+
name: string;
|
|
88
|
+
scope: PoApiScope;
|
|
89
|
+
description?: string;
|
|
90
|
+
parent?: string;
|
|
91
|
+
kind: 'data' | 'component';
|
|
92
|
+
}[];
|
|
93
|
+
fills: {
|
|
94
|
+
id: string;
|
|
95
|
+
slot: string | null;
|
|
96
|
+
scope: PoApiScope;
|
|
97
|
+
placement: 'verified' | 'unverified';
|
|
98
|
+
}[];
|
|
99
|
+
diagnostics: string[];
|
|
100
|
+
}
|
|
101
|
+
//#endregion
|
|
10
102
|
//#region src/schemas/serverScope.d.ts
|
|
11
103
|
/** An abstract service: the name every level resolves and the level that provides it. */
|
|
12
104
|
interface PoServiceContract<T> {
|
|
13
105
|
readonly name: string;
|
|
14
106
|
readonly scope: PoApiScope;
|
|
107
|
+
/** What this service offers an author. Built public contracts require a nonblank description. */
|
|
108
|
+
readonly description?: string;
|
|
15
109
|
/** Type carrier only; never set at runtime. */
|
|
16
110
|
readonly _type?: T;
|
|
17
111
|
}
|
|
@@ -33,6 +127,8 @@ interface PoServerPluginShare<TRoots> {
|
|
|
33
127
|
/** What a plugin sees of the scope it is installed into. */
|
|
34
128
|
interface PoServerScopeService {
|
|
35
129
|
readonly level: PoApiScope;
|
|
130
|
+
/** Detached current scope and ancestry only, without reading service values. */
|
|
131
|
+
snapshot(): BrainServicesSnapshot;
|
|
36
132
|
/**
|
|
37
133
|
* Bind the concrete value of a contract owned by this level, visible here and in every descendant.
|
|
38
134
|
* Settles once every descendant publishes it. The binding unwinds with the calling fiber; the
|
|
@@ -332,6 +428,68 @@ interface PoIsolateService {
|
|
|
332
428
|
readonly liveObjects: boolean;
|
|
333
429
|
run(request: PoIsolateRequest): Promise<PoIsolateResult>;
|
|
334
430
|
}
|
|
431
|
+
/** An OpenAI- or Anthropic-compatible endpoint added by hand. Holds no secret: its key is a stored credential. */
|
|
432
|
+
interface PoCustomProviderDefinition {
|
|
433
|
+
readonly id: string;
|
|
434
|
+
readonly name: string;
|
|
435
|
+
/** `http:` or `https:`, without userinfo or a query string. */
|
|
436
|
+
readonly baseUrl: string;
|
|
437
|
+
readonly api: 'openai-completions' | 'openai-responses' | 'anthropic-messages';
|
|
438
|
+
readonly models: readonly {
|
|
439
|
+
readonly id: string;
|
|
440
|
+
readonly name?: string;
|
|
441
|
+
readonly reasoning?: boolean;
|
|
442
|
+
readonly input?: readonly ('text' | 'image')[];
|
|
443
|
+
readonly contextWindow?: number;
|
|
444
|
+
readonly maxTokens?: number;
|
|
445
|
+
}[];
|
|
446
|
+
}
|
|
447
|
+
/** What the credential owner tells sessions: never a key, token, header or URL secret. */
|
|
448
|
+
interface PoProviderAuthSnapshot {
|
|
449
|
+
/** Changes whenever anything below changes; compare with `!==`, as an owner restart starts afresh. */
|
|
450
|
+
readonly version: number;
|
|
451
|
+
/** Configured providers only; every other provider is unconfigured. */
|
|
452
|
+
readonly providers: readonly {
|
|
453
|
+
readonly id: string;
|
|
454
|
+
readonly type: 'api_key' | 'oauth';
|
|
455
|
+
readonly source?: string;
|
|
456
|
+
readonly subscription: boolean;
|
|
457
|
+
}[];
|
|
458
|
+
/** Models of every type the deployment target can use, after each provider's credential filter. */
|
|
459
|
+
readonly available: readonly {
|
|
460
|
+
readonly provider: string;
|
|
461
|
+
readonly id: string;
|
|
462
|
+
readonly type: ModelType;
|
|
463
|
+
}[];
|
|
464
|
+
/** Dynamic catalogs by provider id, with headers and URL secrets removed. */
|
|
465
|
+
readonly models: Readonly<Record<string, ModelsStoreEntry>>;
|
|
466
|
+
readonly customProviders: readonly PoCustomProviderDefinition[];
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Provider credentials held by one owner per deployment target (the org on hosted Po), for hosts
|
|
470
|
+
* whose sessions must never store them. Node leaves it unbound: `auth.json` is the authority there.
|
|
471
|
+
*/
|
|
472
|
+
interface PoProviderAuth {
|
|
473
|
+
readonly abiVersion: 1;
|
|
474
|
+
/**
|
|
475
|
+
* Provider-level auth for one request, resolved like local `Models.getAuth` (stored OAuth refreshed,
|
|
476
|
+
* then the stored key) and never persisted by the caller. `version` is the owner's snapshot version.
|
|
477
|
+
*/
|
|
478
|
+
resolveAuth(provider: string): Promise<{
|
|
479
|
+
readonly version: number;
|
|
480
|
+
readonly auth?: AuthResult;
|
|
481
|
+
}>;
|
|
482
|
+
/** The full snapshot, or just `{ version }` while `sinceVersion` is still current. */
|
|
483
|
+
snapshot(sinceVersion?: number): Promise<PoProviderAuthSnapshot | {
|
|
484
|
+
readonly version: number;
|
|
485
|
+
}>;
|
|
486
|
+
refresh(options?: {
|
|
487
|
+
readonly allowNetwork?: boolean;
|
|
488
|
+
}): Promise<{
|
|
489
|
+
readonly version: number;
|
|
490
|
+
readonly errors: Readonly<Record<string, string>>;
|
|
491
|
+
}>;
|
|
492
|
+
}
|
|
335
493
|
declare module '@deepseek-ai/cordis' {
|
|
336
494
|
interface Context {
|
|
337
495
|
'po/fs': FileSystem;
|
|
@@ -342,6 +500,7 @@ declare module '@deepseek-ai/cordis' {
|
|
|
342
500
|
'po/npm': PoNpm;
|
|
343
501
|
'po/electron': PoElectronService;
|
|
344
502
|
'po/browser': PoBrowserService;
|
|
503
|
+
'po/provider-auth': PoProviderAuth;
|
|
345
504
|
'po/session-files': {
|
|
346
505
|
readonly temporaryDirectory: string;
|
|
347
506
|
};
|
|
@@ -689,13 +848,6 @@ declare module '@deepseek-ai/cordis' {
|
|
|
689
848
|
}
|
|
690
849
|
}
|
|
691
850
|
//#endregion
|
|
692
|
-
//#region src/schemas/serverBundle.d.ts
|
|
693
|
-
/** Every occurrence that can activate a package in this repository. */
|
|
694
|
-
interface PoServerBundleOwner {
|
|
695
|
-
readonly majorMode: string;
|
|
696
|
-
readonly layer: string;
|
|
697
|
-
}
|
|
698
|
-
//#endregion
|
|
699
851
|
//#region src/schemas/apiContracts.d.ts
|
|
700
852
|
export declare const PO_API_CONTRACT_VERSION = 1;
|
|
701
853
|
export declare const PO_API_CONTRACT_FILE = "contracts.json";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiContracts.d.mts","names":["_0","_0","_0","IoContext","_0","_$__hubChannel0.PoHubSessionUsage","_0","_$__protocolContracts0.ChordMethods"],"sources":["../src/schemas/
|
|
1
|
+
{"version":3,"file":"apiContracts.d.mts","names":["_0","_0","_0","IoContext","_0","_$__hubChannel0.PoHubSessionUsage","_0","_$__protocolContracts0.ChordMethods"],"sources":["../src/schemas/serverBundle.ts","../src/schemas/brain.ts","../src/schemas/serverScope.ts","../src/schemas/approvalPrompt.ts","../src/schemas/approval.ts","../src/schemas/backgroundWork.ts","../src/schemas/platform.ts","../src/schemas/workflow.ts","../src/schemas/hubChannel.ts","../src/schemas/packageApi.ts","../src/schemas/apiContracts.ts","../src/services/apiContracts/index.ts","../src/schemas/builtinApiContracts.ts","../src/schemas/httpApiContracts.ts","../src/schemas/protocolContracts.ts","../src/schemas/sessionProtocol.ts","../src/schemas/sessionApiContracts.ts","../src/schemas/transportApiContracts.ts"],"mappings":"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"}
|
|
@@ -291,7 +291,7 @@ function createHeadlessProtocol(options) {
|
|
|
291
291
|
}
|
|
292
292
|
};
|
|
293
293
|
});
|
|
294
|
-
require_piSessionRuntime.serveAgentSessions(host, { resolve(sessionId, principal) {
|
|
294
|
+
const clearSessionBindings = require_piSessionRuntime.serveAgentSessions(host, { resolve(sessionId, principal) {
|
|
295
295
|
const connection = connectionOf(principal);
|
|
296
296
|
const session = hub.session(sessionId);
|
|
297
297
|
if (!session || !reachable(connection, session.id)) return void 0;
|
|
@@ -358,6 +358,7 @@ function createHeadlessProtocol(options) {
|
|
|
358
358
|
closing ??= (async () => {
|
|
359
359
|
stopClaims?.();
|
|
360
360
|
threads.close();
|
|
361
|
+
clearSessionBindings();
|
|
361
362
|
await host.close();
|
|
362
363
|
})();
|
|
363
364
|
return closing;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headlessProtocol.cjs","names":["createThreadJournals","createHost","PO_SERVER_HOST","harnessErrorMessage","forbidden","PoHubContract","chordSchema","Type","SessionSummarySchema","HubWorkspaceSchema","HubNoticeSchema","HubCompositionsSchema","randomUUID","PoHubRevisionsContract","HubRevisionsSchema","PoThreadContract","PoThreadFrameSchema","PoChannelsContract","PoChannelsStateSchema","reportingLargeFrames"],"sources":["../src/server/headlessProtocol.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { createHost, forbidden, type Link, type Subscribable } from '@earendil-works/chord';\nimport { Type } from 'typebox';\n\nimport type { PoPluginCall } from '../exports/pluginProtocol';\nimport {\n HubCompositionsSchema,\n HubNoticeSchema,\n HubRevisionsSchema,\n PO_SERVER_HOST,\n PoChannelsContract,\n PoHubContract,\n PoHubRevisionsContract,\n PoThreadContract,\n type HubNotice,\n type HubSessionView,\n type HubWorkspaceView,\n type JsonValue,\n} from '../exports/sessionProtocol';\nimport { serveAgentSessions, type AgentSessionBinding } from '../pi/piSessionRuntime';\nimport { SessionSummarySchema } from '../schemas/httpApiContracts';\nimport type { PoSocketMount } from '../schemas/packageApi';\nimport { PoChannelsStateSchema } from '../schemas/protocolChannelsContract';\nimport { chordSchema } from '../schemas/protocolContracts';\nimport { HubWorkspaceSchema } from '../schemas/protocolHubContract';\nimport { PoThreadFrameSchema } from '../schemas/protocolThreadContract';\nimport type { OpenSessionRecord } from '../services/openSessionRegistry';\nimport type { ServerTelemetry } from '../services/serverTelemetry';\nimport { harnessErrorMessage } from './harnessErrorMessage';\nimport type { HeadlessHub, HeadlessHubEvent, HeadlessHubSession } from './headlessHub';\nimport { reportingLargeFrames } from './largeFrameLink';\nimport { createThreadJournals } from './threadJournals';\n\n// ponytail: unacknowledged notices beyond this drop oldest first; raise it if a client misses dialogs.\nconst MAX_PENDING_NOTICES = 64;\n/** A browser switching back to a thread quickly keeps its tail open. */\nconst THREAD_LINGER_MS = 5_000;\n\nfunction sessionView(session: HeadlessHubSession): HubSessionView {\n return {\n id: session.id,\n ...(session.workspaceId === undefined ? {} : { workspaceId: session.workspaceId }),\n ...(session.webComposition === undefined ? {} : { webComposition: { ...session.webComposition } }),\n ...(session.nativeComposition === undefined ? {} : { nativeComposition: { ...session.nativeComposition } }),\n name: session.name,\n cwd: session.cwd,\n createdAt: session.createdAt,\n updatedAt: session.updatedAt ?? session.createdAt,\n phase: session.phase ?? 'idle',\n phaseSince: session.phaseSince ?? session.createdAt,\n attach: 'attached',\n pendingMessageCount: session.pendingMessageCount ?? 0,\n everPrompted: session.everPrompted ?? false,\n awaitingInput: session.awaitingInput ?? false,\n ...(session.lastSettledAt === undefined ? {} : { lastSettledAt: session.lastSettledAt }),\n // null: the host has not reported yet.\n ...(session.backgroundWorkActive == null ? {} : { backgroundWorkActive: session.backgroundWorkActive }),\n ...(session.git === undefined ? {} : { git: { branch: session.git.branch, dirty: session.git.dirty } }),\n ...(session.profile === undefined\n ? {}\n : {\n profile: {\n name: session.profile.name,\n ...(session.profile.displayName === undefined ? {} : { displayName: session.profile.displayName }),\n ...(session.profile.iconVersion === undefined ? {} : { iconVersion: session.profile.iconVersion }),\n },\n }),\n ...(session.parentSessionId === undefined ? {} : { parentSessionId: session.parentSessionId }),\n ...(session.sessionProvenance === undefined ? {} : { sessionProvenance: session.sessionProvenance }),\n ...(session.interaction === undefined ? {} : { interaction: session.interaction }),\n ...(session.groups === undefined || session.groups.length === 0 ? {} : { groups: [...session.groups] }),\n ...(session.pendingSetups === undefined\n ? {}\n : {\n pendingSetups: session.pendingSetups.map((setup) => ({\n id: setup.id,\n name: setup.name,\n createdAt: setup.createdAt,\n ...(setup.cwd === undefined ? {} : { cwd: setup.cwd }),\n ...(setup.setupKind === undefined ? {} : { setupKind: setup.setupKind }),\n ...(setup.status === undefined ? {} : { status: setup.status }),\n ...(setup.errorCode === undefined ? {} : { errorCode: setup.errorCode }),\n })),\n }),\n ...(session.activity === undefined\n ? {}\n : {\n activity: {\n label: session.activity.label,\n ...(session.activity.attention === true ? { attention: true } : {}),\n ...(session.activity.since === undefined ? {} : { since: session.activity.since }),\n },\n }),\n ...(session.pendingApprovalCount === undefined ? {} : { pendingApprovalCount: session.pendingApprovalCount }),\n };\n}\n\n/**\n * A recorded session with no runtime behind it yet.\n *\n * Carries the same field set as a live session so the rail keys both by id and\n * swaps one for the other in place once the server reopens the journal.\n */\nfunction dormantView(record: OpenSessionRecord, pendingApprovalCount?: number): HubSessionView {\n return {\n id: record.sessionId,\n workspaceId: record.workspaceId,\n name: record.name,\n cwd: record.cwd,\n createdAt: record.createdAt,\n updatedAt: record.createdAt,\n phase: 'idle',\n phaseSince: record.createdAt,\n attach: 'attached',\n pendingMessageCount: 0,\n everPrompted: false,\n awaitingInput: false,\n dormant: true,\n ...(pendingApprovalCount === undefined ? {} : { pendingApprovalCount }),\n ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\n ...(record.interaction === undefined ? {} : { interaction: record.interaction }),\n ...(record.groups === undefined || record.groups.length === 0 ? {} : { groups: [...record.groups] }),\n };\n}\n\n/** Each restarted session host gets a new generation, so its projection starts fresh. */\nconst generations = new WeakMap<object, number>();\nlet nextGeneration = 0;\nfunction generationOf(host: object): number {\n let generation = generations.get(host);\n if (generation === undefined) {\n generation = nextGeneration++;\n generations.set(host, generation);\n }\n return generation;\n}\n\nfunction permitsSession(\n hub: HeadlessHub,\n mount: PoSocketMount,\n sessionId: string,\n authorize: (id: string) => boolean = () => true,\n): boolean {\n const session = hub.session(sessionId);\n return (\n session !== undefined &&\n authorize(sessionId) &&\n (mount.scope === 'global' ||\n (session.workspaceId === mount.workspaceId && (mount.scope === 'workspace' || mount.sessionId === sessionId)))\n );\n}\n\nfunction permitsDormant(mount: PoSocketMount, record: OpenSessionRecord): boolean {\n if (mount.scope === 'global') return true;\n if (record.workspaceId !== mount.workspaceId) return false;\n return mount.scope === 'workspace' || mount.sessionId === record.sessionId;\n}\n\n/** What one upgraded connection may reach, decided from its request when it connected. */\nexport interface ConnectionAccess {\n readonly mount: PoSocketMount;\n /** Evaluated for every call, including references taken before a Desktop claim. */\n authorizeSession(sessionId: string): boolean;\n authorizeDesktop(): boolean;\n authorizeComputerUse(sessionId: string): boolean;\n}\n\ninterface Connection extends ConnectionAccess {\n /** Sessions this connection reached, rechecked when computer-use ownership changes. */\n readonly sessions: Set<string>;\n}\n\ninterface Principal {\n connectionId: string;\n}\n\nexport interface HeadlessProtocol {\n /** Hands an authenticated link to the shared host. Without `access` it sees everything Desktop does not own. */\n accept(link: Link, access?: Partial<ConnectionAccess>): void;\n close(): Promise<void>;\n}\n\nconst eventsOf = (hub: HeadlessHub): Subscribable<HeadlessHubEvent> => ({\n subscribe: (listener) => hub.onEvent(listener),\n});\n\n/** One Chord host for every browser, native and relayed connection over the process-local hub. */\nexport function createHeadlessProtocol(options: {\n hub: HeadlessHub;\n telemetry?: ServerTelemetry;\n onNotice?: (message: string) => void;\n /** Recorded sessions the server has not reopened. */\n dormantSessions?: () => readonly OpenSessionRecord[];\n}): HeadlessProtocol {\n const hub = options.hub;\n const dormantSessions = () => (options.dormantSessions === undefined ? [] : options.dormantSessions());\n const connections = new Map<string, Connection>();\n const threads = createThreadJournals({\n resolve: (sessionId, threadId) => hub.childThread(sessionId, threadId),\n });\n const host = createHost<Principal>({\n name: PO_SERVER_HOST,\n self: { connectionId: PO_SERVER_HOST },\n principalKey: (principal) => principal.connectionId,\n onError: (error) => options.onNotice?.(`headless protocol error (${harnessErrorMessage(error)})`),\n });\n const connectionOf = (principal: Principal): Connection & { connectionId: string } => {\n const connection = connections.get(principal.connectionId);\n if (connection === undefined) throw forbidden('This connection has closed.');\n return { ...connection, connectionId: principal.connectionId };\n };\n const reachable = (connection: Connection, sessionId: string): boolean =>\n permitsSession(hub, connection.mount, sessionId, (id) => connection.authorizeSession(id));\n\n // A Desktop claim makes every reference the connection holds to that session gone at once.\n const stopClaims = hub.computerUse?.subscribe?.(() => {\n for (const [connectionId, connection] of connections) {\n let revoked = false;\n for (const sessionId of connection.sessions) if (!connection.authorizeSession(sessionId)) revoked = true;\n if (!revoked) continue;\n connection.sessions.clear();\n void host.invalidatePrincipal((principal) => principal.connectionId === connectionId);\n }\n });\n\n host.serve(PoHubContract, (_input, principal, self) => {\n const connection = connectionOf(principal);\n const { mount } = connection;\n const visibleSessions = (): Record<string, HubSessionView> => {\n const views: Record<string, HubSessionView> = {};\n for (const session of hub.snapshot())\n if (reachable(connection, session.id)) views[session.id] = sessionView(session);\n // A dormant record of a removed workspace has no HTTP list to come from, so clients would never agree on it.\n const registered = new Set(hub.workspaces().map((workspace) => workspace.id));\n for (const record of dormantSessions())\n if (\n views[record.sessionId] === undefined &&\n registered.has(record.workspaceId) &&\n connection.authorizeSession(record.sessionId) &&\n permitsDormant(mount, record)\n )\n views[record.sessionId] = dormantView(record, hub.sessionPendingApprovalCount?.(record.sessionId));\n return views;\n };\n const visibleWorkspaces = (): Record<string, HubWorkspaceView> => {\n const views: Record<string, HubWorkspaceView> = {};\n for (const workspace of hub.workspaces())\n if (mount.scope === 'global' || workspace.id === mount.workspaceId)\n views[workspace.id] = {\n id: workspace.id,\n root: workspace.root,\n ...(workspace.kind === undefined ? {} : { kind: workspace.kind }),\n ...(workspace.name === undefined ? {} : { name: workspace.name }),\n ...(workspace.sandbox === undefined ? {} : { sandbox: workspace.sandbox }),\n ...(workspace.sandboxState === undefined ? {} : { sandboxState: workspace.sandboxState }),\n ...(workspace.sandboxReason === undefined ? {} : { sandboxReason: workspace.sandboxReason }),\n available: workspace.available !== false,\n };\n return views;\n };\n const sessions = self.state('sessions', chordSchema(Type.Record(Type.String(), SessionSummarySchema)), {\n init: visibleSessions,\n });\n const workspaces = self.state('workspaces', chordSchema(Type.Record(Type.String(), HubWorkspaceSchema)), {\n init: visibleWorkspaces,\n });\n const pending = self.state('pending', chordSchema(Type.Array(HubNoticeSchema)), [] as HubNotice[]);\n const visibleCompositions = (): Record<string, number> => {\n const revisions = hub.compositionRevisions?.() ?? {};\n if (mount.scope === 'global') return { ...revisions };\n const own = `workspace:${mount.workspaceId}`;\n return Object.fromEntries(Object.entries(revisions).filter(([key]) => key === 'global' || key === own));\n };\n const compositions = self.state('compositions', chordSchema(HubCompositionsSchema), { init: visibleCompositions });\n self.on('hub', eventsOf(hub), (event, ctx) => {\n switch (event.kind) {\n case 'upsert':\n case 'removed':\n case 'dormant_changed':\n // Recomputed rather than patched, so an event before this listener started cannot leave a stale row.\n sessions.replace(ctx, visibleSessions(), { diff: true });\n return;\n case 'workspace_upsert':\n case 'workspace_removed':\n workspaces.replace(ctx, visibleWorkspaces(), { diff: true });\n return;\n case 'compositions':\n compositions.replace(ctx, visibleCompositions(), { diff: true });\n return;\n case 'frame':\n if (!reachable(connection, event.sessionId)) return;\n pending.change(ctx, (draft) => {\n draft.push({\n id: randomUUID(),\n sessionId: event.sessionId,\n frame: event.frame as Record<string, JsonValue>,\n });\n if (draft.length > MAX_PENDING_NOTICES) draft.splice(0, draft.length - MAX_PENDING_NOTICES);\n });\n return;\n case 'channel':\n return;\n }\n });\n return {\n variant: 'default',\n sessions,\n workspaces,\n pending,\n compositions,\n readHome: async (request) => {\n if (!hub.readHome) throw new Error('Home read is unavailable.');\n return hub.readHome(request, (id) => reachable(connection, id));\n },\n invoke: async (call: PoPluginCall, ctx) => {\n if (call.mount.scope === 'session' && !connection.authorizeSession(call.mount.sessionId))\n throw forbidden('This session belongs to its Desktop instance.');\n if (mount.scope !== 'global') {\n const permitted =\n call.mount.scope === 'session'\n ? permitsSession(hub, mount, call.mount.sessionId)\n : mount.scope === 'workspace' &&\n call.mount.scope === 'workspace' &&\n call.mount.workspaceId === mount.workspaceId;\n if (!permitted) throw forbidden('Plugin is outside this WebSocket scope.');\n }\n return (await hub.invokePlugin(call, 'client-to-server', {\n connectionId: connection.connectionId,\n signal: ctx.signal,\n })) as JsonValue;\n },\n ackNotice: async ({ id }, ctx) => {\n pending.change(ctx, (draft) => draft.filter((notice) => notice.id !== id));\n },\n };\n });\n\n host.serve(PoHubRevisionsContract, (_input, principal, self) => {\n const { mount } = connectionOf(principal);\n const visibleRevisions = (): Record<string, number> => {\n const revisions = hub.revisions?.() ?? {};\n if (mount.scope === 'global') return { ...revisions };\n const own = `workspace:${mount.workspaceId}:`;\n return Object.fromEntries(\n Object.entries(revisions).filter(([topic]) => topic.startsWith('global:') || topic.startsWith(own)),\n );\n };\n const revisions = self.state('revisions', chordSchema(HubRevisionsSchema), { init: visibleRevisions });\n self.on('hub', eventsOf(hub), (event, ctx) => {\n if (event.kind === 'revisions') revisions.replace(ctx, visibleRevisions(), { diff: true });\n });\n return { variant: 'default', revisions };\n });\n\n host.serve(\n PoThreadContract,\n ({ sessionId, threadId }, principal, self) => {\n const connection = connectionOf(principal);\n if (!reachable(connection, sessionId)) throw forbidden(`No session ${sessionId}`);\n connection.sessions.add(sessionId);\n const tail = self.resource('tail', {\n version: 1,\n open: () => threads.subscribe(sessionId, threadId),\n close: () => threads.unsubscribe(sessionId, threadId),\n });\n const frame = self.state('frame', chordSchema(PoThreadFrameSchema), {\n init: () => (tail.value?.at(-1) ?? null) as never,\n });\n self.on(\n 'frames',\n { subscribe: (listener) => threads.onFrame(listener) } as Subscribable<{\n sessionId: string;\n threadId: string;\n frame: Record<string, unknown>;\n }>,\n (event, ctx) => {\n // Each frame is a fresh wrapper around the child's state, so only an explicit diff sends ops, not the whole state.\n if (event.sessionId === sessionId && event.threadId === threadId)\n frame.replace(ctx, event.frame as never, { diff: true });\n },\n );\n return { variant: 'default', frame };\n },\n { linger: THREAD_LINGER_MS },\n );\n\n host.serve(PoChannelsContract, ({ sessionId }, principal, self) => {\n const connection = connectionOf(principal);\n if (!reachable(connection, sessionId)) throw forbidden(`No session ${sessionId}`);\n connection.sessions.add(sessionId);\n const visible = (frameType: string): boolean =>\n frameType !== 'computer_use_state' || connection.authorizeComputerUse(sessionId);\n const latest = self.state('latest', chordSchema(PoChannelsStateSchema), {\n init: () => {\n const payloads: Record<string, JsonValue> = {};\n for (const channelFrame of hub.channelFrames(sessionId))\n if (visible(channelFrame.type)) payloads[channelFrame.type] = channelFrame.payload as JsonValue;\n return payloads;\n },\n });\n // ponytail: a channel keeps only its latest payload; a package that needs every event must carry a sequence.\n self.on('hub', eventsOf(hub), (event, ctx) => {\n if (event.kind !== 'channel' || event.sessionId !== sessionId || !visible(event.frameType)) return;\n if (event.connectionId !== undefined && event.connectionId !== connection.connectionId) return;\n latest.change(ctx, (draft) => {\n draft[event.frameType] = event.payload as JsonValue;\n });\n });\n return {\n variant: 'default',\n latest,\n receive: async ({ type, payload }) => {\n if (!connection.authorizeSession(sessionId)) throw forbidden('This session belongs to Desktop.');\n hub.receiveChannel(\n sessionId,\n type,\n payload,\n connection.connectionId,\n connection.authorizeDesktop(),\n connection.authorizeComputerUse(sessionId),\n );\n },\n };\n });\n\n serveAgentSessions(host, {\n resolve(sessionId, principal): AgentSessionBinding | undefined {\n const connection = connectionOf(principal as Principal);\n const session = hub.session(sessionId);\n if (!session || !reachable(connection, session.id)) return undefined;\n connection.sessions.add(sessionId);\n const permitted = () => hub.session(session.id)?.host === session.host && connection.authorizeSession(session.id);\n // A mirror of a session another host runs forwards there; keyed by its host object, never by session id.\n const forward = session.host.agentSession;\n if (forward !== undefined)\n return { generation: generationOf(session.host), exited: session.host.runtime.exited, permitted, forward };\n return {\n generation: generationOf(session.host),\n exited: session.host.runtime.exited,\n permitted,\n options: {\n runtime: session.host.runtime,\n onPresentationFrame: (listen) =>\n session.host.onPresentationFrame((frame) => {\n if (permitted()) listen(frame);\n }),\n respondToExtensionUi: (frame) => {\n if (!permitted()) throw forbidden('This session belongs to Desktop.');\n return session.host.respondToExtensionUi(frame);\n },\n readThreadTranscript: (threadId, request, readContext) => {\n if (!permitted()) throw forbidden('This session belongs to Desktop.');\n return threads.readPage(session.id, threadId, request, readContext);\n },\n sessionId: session.id,\n sessionName: session.name,\n cwd: session.cwd,\n telemetry: options.telemetry,\n },\n };\n },\n });\n\n let closing: Promise<void> | undefined;\n return {\n accept(link, access = {}) {\n if (closing !== undefined) {\n link.close();\n return;\n }\n const connectionId = randomUUID();\n const authorizeSession = access.authorizeSession ?? ((id: string) => !hub.computerUse?.ownsSession?.(id));\n const authorizeDesktop = access.authorizeDesktop ?? (() => false);\n connections.set(connectionId, {\n mount: access.mount ?? { scope: 'global' },\n authorizeSession,\n authorizeDesktop,\n authorizeComputerUse: access.authorizeComputerUse ?? (() => authorizeDesktop()),\n sessions: new Set(),\n });\n link.onClose(() => {\n connections.delete(connectionId);\n hub.disconnectChannels(connectionId);\n });\n host.accept(reportingLargeFrames(link, options.onNotice, options.telemetry), {\n principal: { connectionId },\n kind: 'client',\n });\n },\n close() {\n closing ??= (async () => {\n stopClaims?.();\n threads.close();\n await host.close();\n })();\n return closing;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAmCA,MAAM,sBAAsB;;AAE5B,MAAM,mBAAmB;AAEzB,SAAS,YAAY,SAA6C;CAChE,OAAO;EACL,IAAI,QAAQ;EACZ,GAAI,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,YAAY;EAChF,GAAI,QAAQ,mBAAmB,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,QAAQ,eAAe,EAAE;EAChG,GAAI,QAAQ,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,QAAQ,kBAAkB,EAAE;EACzG,MAAM,QAAQ;EACd,KAAK,QAAQ;EACb,WAAW,QAAQ;EACnB,WAAW,QAAQ,aAAa,QAAQ;EACxC,OAAO,QAAQ,SAAS;EACxB,YAAY,QAAQ,cAAc,QAAQ;EAC1C,QAAQ;EACR,qBAAqB,QAAQ,uBAAuB;EACpD,cAAc,QAAQ,gBAAgB;EACtC,eAAe,QAAQ,iBAAiB;EACxC,GAAI,QAAQ,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,QAAQ,cAAc;EAEtF,GAAI,QAAQ,wBAAwB,OAAO,CAAC,IAAI,EAAE,sBAAsB,QAAQ,qBAAqB;EACrG,GAAI,QAAQ,QAAQ,KAAA,IAAY,CAAC,IAAI,EAAE,KAAK;GAAE,QAAQ,QAAQ,IAAI;GAAQ,OAAO,QAAQ,IAAI;EAAM,EAAE;EACrG,GAAI,QAAQ,YAAY,KAAA,IACpB,CAAC,IACD,EACE,SAAS;GACP,MAAM,QAAQ,QAAQ;GACtB,GAAI,QAAQ,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,QAAQ,YAAY;GAChG,GAAI,QAAQ,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,QAAQ,YAAY;EAClG,EACF;EACJ,GAAI,QAAQ,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,QAAQ,gBAAgB;EAC5F,GAAI,QAAQ,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,QAAQ,kBAAkB;EAClG,GAAI,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,YAAY;EAChF,GAAI,QAAQ,WAAW,KAAA,KAAa,QAAQ,OAAO,WAAW,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,QAAQ,MAAM,EAAE;EACrG,GAAI,QAAQ,kBAAkB,KAAA,IAC1B,CAAC,IACD,EACE,eAAe,QAAQ,cAAc,KAAK,WAAW;GACnD,IAAI,MAAM;GACV,MAAM,MAAM;GACZ,WAAW,MAAM;GACjB,GAAI,MAAM,QAAQ,KAAA,IAAY,CAAC,IAAI,EAAE,KAAK,MAAM,IAAI;GACpD,GAAI,MAAM,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,MAAM,UAAU;GACtE,GAAI,MAAM,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,OAAO;GAC7D,GAAI,MAAM,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,MAAM,UAAU;EACxE,EAAE,EACJ;EACJ,GAAI,QAAQ,aAAa,KAAA,IACrB,CAAC,IACD,EACE,UAAU;GACR,OAAO,QAAQ,SAAS;GACxB,GAAI,QAAQ,SAAS,cAAc,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;GACjE,GAAI,QAAQ,SAAS,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,SAAS,MAAM;EAClF,EACF;EACJ,GAAI,QAAQ,yBAAyB,KAAA,IAAY,CAAC,IAAI,EAAE,sBAAsB,QAAQ,qBAAqB;CAC7G;AACF;;;;;;;AAQA,SAAS,YAAY,QAA2B,sBAA+C;CAC7F,OAAO;EACL,IAAI,OAAO;EACX,aAAa,OAAO;EACpB,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,WAAW,OAAO;EAClB,WAAW,OAAO;EAClB,OAAO;EACP,YAAY,OAAO;EACnB,QAAQ;EACR,qBAAqB;EACrB,cAAc;EACd,eAAe;EACf,SAAS;EACT,GAAI,yBAAyB,KAAA,IAAY,CAAC,IAAI,EAAE,qBAAqB;EACrE,GAAI,OAAO,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,OAAO,gBAAgB;EAC1F,GAAI,OAAO,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,OAAO,kBAAkB;EAChG,GAAI,OAAO,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,OAAO,YAAY;EAC9E,GAAI,OAAO,WAAW,KAAA,KAAa,OAAO,OAAO,WAAW,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,OAAO,MAAM,EAAE;CACpG;AACF;;AAGA,MAAM,8BAAc,IAAI,QAAwB;AAChD,IAAI,iBAAiB;AACrB,SAAS,aAAa,MAAsB;CAC1C,IAAI,aAAa,YAAY,IAAI,IAAI;CACrC,IAAI,eAAe,KAAA,GAAW;EAC5B,aAAa;EACb,YAAY,IAAI,MAAM,UAAU;CAClC;CACA,OAAO;AACT;AAEA,SAAS,eACP,KACA,OACA,WACA,kBAA2C,MAClC;CACT,MAAM,UAAU,IAAI,QAAQ,SAAS;CACrC,OACE,YAAY,KAAA,KACZ,UAAU,SAAS,MAClB,MAAM,UAAU,YACd,QAAQ,gBAAgB,MAAM,gBAAgB,MAAM,UAAU,eAAe,MAAM,cAAc;AAExG;AAEA,SAAS,eAAe,OAAsB,QAAoC;CAChF,IAAI,MAAM,UAAU,UAAU,OAAO;CACrC,IAAI,OAAO,gBAAgB,MAAM,aAAa,OAAO;CACrD,OAAO,MAAM,UAAU,eAAe,MAAM,cAAc,OAAO;AACnE;AA0BA,MAAM,YAAY,SAAsD,EACtE,YAAY,aAAa,IAAI,QAAQ,QAAQ,EAC/C;;AAGA,SAAgB,uBAAuB,SAMlB;CACnB,MAAM,MAAM,QAAQ;CACpB,MAAM,wBAAyB,QAAQ,oBAAoB,KAAA,IAAY,CAAC,IAAI,QAAQ,gBAAgB;CACpG,MAAM,8BAAc,IAAI,IAAwB;CAChD,MAAM,UAAUA,uBAAAA,qBAAqB,EACnC,UAAU,WAAW,aAAa,IAAI,YAAY,WAAW,QAAQ,EACvE,CAAC;CACD,MAAM,QAAA,GAAOC,uBAAAA,WAAAA,CAAsB;EACjC,MAAMC,0BAAAA;EACN,MAAM,EAAE,cAAcA,0BAAAA,eAAe;EACrC,eAAe,cAAc,UAAU;EACvC,UAAU,UAAU,QAAQ,WAAW,4BAA4BC,4BAAAA,oBAAoB,KAAK,EAAE,EAAE;CAClG,CAAC;CACD,MAAM,gBAAgB,cAAgE;EACpF,MAAM,aAAa,YAAY,IAAI,UAAU,YAAY;EACzD,IAAI,eAAe,KAAA,GAAW,OAAA,GAAMC,uBAAAA,UAAAA,CAAU,6BAA6B;EAC3E,OAAO;GAAE,GAAG;GAAY,cAAc,UAAU;EAAa;CAC/D;CACA,MAAM,aAAa,YAAwB,cACzC,eAAe,KAAK,WAAW,OAAO,YAAY,OAAO,WAAW,iBAAiB,EAAE,CAAC;CAG1F,MAAM,aAAa,IAAI,aAAa,kBAAkB;EACpD,KAAK,MAAM,CAAC,cAAc,eAAe,aAAa;GACpD,IAAI,UAAU;GACd,KAAK,MAAM,aAAa,WAAW,UAAU,IAAI,CAAC,WAAW,iBAAiB,SAAS,GAAG,UAAU;GACpG,IAAI,CAAC,SAAS;GACd,WAAW,SAAS,MAAM;GAC1B,KAAU,qBAAqB,cAAc,UAAU,iBAAiB,YAAY;EACtF;CACF,CAAC;CAED,KAAK,MAAMC,4BAAAA,gBAAgB,QAAQ,WAAW,SAAS;EACrD,MAAM,aAAa,aAAa,SAAS;EACzC,MAAM,EAAE,UAAU;EAClB,MAAM,wBAAwD;GAC5D,MAAM,QAAwC,CAAC;GAC/C,KAAK,MAAM,WAAW,IAAI,SAAS,GACjC,IAAI,UAAU,YAAY,QAAQ,EAAE,GAAG,MAAM,QAAQ,MAAM,YAAY,OAAO;GAEhF,MAAM,aAAa,IAAI,IAAI,IAAI,WAAW,CAAC,CAAC,KAAK,cAAc,UAAU,EAAE,CAAC;GAC5E,KAAK,MAAM,UAAU,gBAAgB,GACnC,IACE,MAAM,OAAO,eAAe,KAAA,KAC5B,WAAW,IAAI,OAAO,WAAW,KACjC,WAAW,iBAAiB,OAAO,SAAS,KAC5C,eAAe,OAAO,MAAM,GAE5B,MAAM,OAAO,aAAa,YAAY,QAAQ,IAAI,8BAA8B,OAAO,SAAS,CAAC;GACrG,OAAO;EACT;EACA,MAAM,0BAA4D;GAChE,MAAM,QAA0C,CAAC;GACjD,KAAK,MAAM,aAAa,IAAI,WAAW,GACrC,IAAI,MAAM,UAAU,YAAY,UAAU,OAAO,MAAM,aACrD,MAAM,UAAU,MAAM;IACpB,IAAI,UAAU;IACd,MAAM,UAAU;IAChB,GAAI,UAAU,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,UAAU,KAAK;IAC/D,GAAI,UAAU,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,UAAU,KAAK;IAC/D,GAAI,UAAU,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,UAAU,QAAQ;IACxE,GAAI,UAAU,iBAAiB,KAAA,IAAY,CAAC,IAAI,EAAE,cAAc,UAAU,aAAa;IACvF,GAAI,UAAU,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,UAAU,cAAc;IAC1F,WAAW,UAAU,cAAc;GACrC;GACJ,OAAO;EACT;EACA,MAAM,WAAW,KAAK,MAAM,YAAYC,0BAAAA,YAAYC,QAAAA,KAAK,OAAOA,QAAAA,KAAK,OAAO,GAAGC,yBAAAA,oBAAoB,CAAC,GAAG,EACrG,MAAM,gBACR,CAAC;EACD,MAAM,aAAa,KAAK,MAAM,cAAcF,0BAAAA,YAAYC,QAAAA,KAAK,OAAOA,QAAAA,KAAK,OAAO,GAAGE,4BAAAA,kBAAkB,CAAC,GAAG,EACvG,MAAM,kBACR,CAAC;EACD,MAAM,UAAU,KAAK,MAAM,WAAWH,0BAAAA,YAAYC,QAAAA,KAAK,MAAMG,4BAAAA,eAAe,CAAC,GAAG,CAAC,CAAgB;EACjG,MAAM,4BAAoD;GACxD,MAAM,YAAY,IAAI,uBAAuB,KAAK,CAAC;GACnD,IAAI,MAAM,UAAU,UAAU,OAAO,EAAE,GAAG,UAAU;GACpD,MAAM,MAAM,aAAa,MAAM;GAC/B,OAAO,OAAO,YAAY,OAAO,QAAQ,SAAS,CAAC,CAAC,QAAQ,CAAC,SAAS,QAAQ,YAAY,QAAQ,GAAG,CAAC;EACxG;EACA,MAAM,eAAe,KAAK,MAAM,gBAAgBJ,0BAAAA,YAAYK,4BAAAA,qBAAqB,GAAG,EAAE,MAAM,oBAAoB,CAAC;EACjH,KAAK,GAAG,OAAO,SAAS,GAAG,IAAI,OAAO,QAAQ;GAC5C,QAAQ,MAAM,MAAd;IACE,KAAK;IACL,KAAK;IACL,KAAK;KAEH,SAAS,QAAQ,KAAK,gBAAgB,GAAG,EAAE,MAAM,KAAK,CAAC;KACvD;IACF,KAAK;IACL,KAAK;KACH,WAAW,QAAQ,KAAK,kBAAkB,GAAG,EAAE,MAAM,KAAK,CAAC;KAC3D;IACF,KAAK;KACH,aAAa,QAAQ,KAAK,oBAAoB,GAAG,EAAE,MAAM,KAAK,CAAC;KAC/D;IACF,KAAK;KACH,IAAI,CAAC,UAAU,YAAY,MAAM,SAAS,GAAG;KAC7C,QAAQ,OAAO,MAAM,UAAU;MAC7B,MAAM,KAAK;OACT,KAAA,GAAIC,YAAAA,WAAAA,CAAW;OACf,WAAW,MAAM;OACjB,OAAO,MAAM;MACf,CAAC;MACD,IAAI,MAAM,SAAS,qBAAqB,MAAM,OAAO,GAAG,MAAM,SAAS,mBAAmB;KAC5F,CAAC;KACD;IACF,KAAK,WACH;GACJ;EACF,CAAC;EACD,OAAO;GACL,SAAS;GACT;GACA;GACA;GACA;GACA,UAAU,OAAO,YAAY;IAC3B,IAAI,CAAC,IAAI,UAAU,MAAM,IAAI,MAAM,2BAA2B;IAC9D,OAAO,IAAI,SAAS,UAAU,OAAO,UAAU,YAAY,EAAE,CAAC;GAChE;GACA,QAAQ,OAAO,MAAoB,QAAQ;IACzC,IAAI,KAAK,MAAM,UAAU,aAAa,CAAC,WAAW,iBAAiB,KAAK,MAAM,SAAS,GACrF,OAAA,GAAMR,uBAAAA,UAAAA,CAAU,+CAA+C;IACjE,IAAI,MAAM,UAAU,UAOd;SAAA,EALF,KAAK,MAAM,UAAU,YACjB,eAAe,KAAK,OAAO,KAAK,MAAM,SAAS,IAC/C,MAAM,UAAU,eAChB,KAAK,MAAM,UAAU,eACrB,KAAK,MAAM,gBAAgB,MAAM,cACvB,OAAA,GAAMA,uBAAAA,UAAAA,CAAU,yCAAyC;IAAA;IAE3E,OAAQ,MAAM,IAAI,aAAa,MAAM,oBAAoB;KACvD,cAAc,WAAW;KACzB,QAAQ,IAAI;IACd,CAAC;GACH;GACA,WAAW,OAAO,EAAE,MAAM,QAAQ;IAChC,QAAQ,OAAO,MAAM,UAAU,MAAM,QAAQ,WAAW,OAAO,OAAO,EAAE,CAAC;GAC3E;EACF;CACF,CAAC;CAED,KAAK,MAAMS,4BAAAA,yBAAyB,QAAQ,WAAW,SAAS;EAC9D,MAAM,EAAE,UAAU,aAAa,SAAS;EACxC,MAAM,yBAAiD;GACrD,MAAM,YAAY,IAAI,YAAY,KAAK,CAAC;GACxC,IAAI,MAAM,UAAU,UAAU,OAAO,EAAE,GAAG,UAAU;GACpD,MAAM,MAAM,aAAa,MAAM,YAAY;GAC3C,OAAO,OAAO,YACZ,OAAO,QAAQ,SAAS,CAAC,CAAC,QAAQ,CAAC,WAAW,MAAM,WAAW,SAAS,KAAK,MAAM,WAAW,GAAG,CAAC,CACpG;EACF;EACA,MAAM,YAAY,KAAK,MAAM,aAAaP,0BAAAA,YAAYQ,4BAAAA,kBAAkB,GAAG,EAAE,MAAM,iBAAiB,CAAC;EACrG,KAAK,GAAG,OAAO,SAAS,GAAG,IAAI,OAAO,QAAQ;GAC5C,IAAI,MAAM,SAAS,aAAa,UAAU,QAAQ,KAAK,iBAAiB,GAAG,EAAE,MAAM,KAAK,CAAC;EAC3F,CAAC;EACD,OAAO;GAAE,SAAS;GAAW;EAAU;CACzC,CAAC;CAED,KAAK,MACHC,+BAAAA,mBACC,EAAE,WAAW,YAAY,WAAW,SAAS;EAC5C,MAAM,aAAa,aAAa,SAAS;EACzC,IAAI,CAAC,UAAU,YAAY,SAAS,GAAG,OAAA,GAAMX,uBAAAA,UAAAA,CAAU,cAAc,WAAW;EAChF,WAAW,SAAS,IAAI,SAAS;EACjC,MAAM,OAAO,KAAK,SAAS,QAAQ;GACjC,SAAS;GACT,YAAY,QAAQ,UAAU,WAAW,QAAQ;GACjD,aAAa,QAAQ,YAAY,WAAW,QAAQ;EACtD,CAAC;EACD,MAAM,QAAQ,KAAK,MAAM,SAASE,0BAAAA,YAAYU,+BAAAA,mBAAmB,GAAG,EAClE,YAAa,KAAK,OAAO,GAAG,EAAE,KAAK,KACrC,CAAC;EACD,KAAK,GACH,UACA,EAAE,YAAY,aAAa,QAAQ,QAAQ,QAAQ,EAAE,IAKpD,OAAO,QAAQ;GAEd,IAAI,MAAM,cAAc,aAAa,MAAM,aAAa,UACtD,MAAM,QAAQ,KAAK,MAAM,OAAgB,EAAE,MAAM,KAAK,CAAC;EAC3D,CACF;EACA,OAAO;GAAE,SAAS;GAAW;EAAM;CACrC,GACA,EAAE,QAAQ,iBAAiB,CAC7B;CAEA,KAAK,MAAMC,iCAAAA,qBAAqB,EAAE,aAAa,WAAW,SAAS;EACjE,MAAM,aAAa,aAAa,SAAS;EACzC,IAAI,CAAC,UAAU,YAAY,SAAS,GAAG,OAAA,GAAMb,uBAAAA,UAAAA,CAAU,cAAc,WAAW;EAChF,WAAW,SAAS,IAAI,SAAS;EACjC,MAAM,WAAW,cACf,cAAc,wBAAwB,WAAW,qBAAqB,SAAS;EACjF,MAAM,SAAS,KAAK,MAAM,UAAUE,0BAAAA,YAAYY,iCAAAA,qBAAqB,GAAG,EACtE,YAAY;GACV,MAAM,WAAsC,CAAC;GAC7C,KAAK,MAAM,gBAAgB,IAAI,cAAc,SAAS,GACpD,IAAI,QAAQ,aAAa,IAAI,GAAG,SAAS,aAAa,QAAQ,aAAa;GAC7E,OAAO;EACT,EACF,CAAC;EAED,KAAK,GAAG,OAAO,SAAS,GAAG,IAAI,OAAO,QAAQ;GAC5C,IAAI,MAAM,SAAS,aAAa,MAAM,cAAc,aAAa,CAAC,QAAQ,MAAM,SAAS,GAAG;GAC5F,IAAI,MAAM,iBAAiB,KAAA,KAAa,MAAM,iBAAiB,WAAW,cAAc;GACxF,OAAO,OAAO,MAAM,UAAU;IAC5B,MAAM,MAAM,aAAa,MAAM;GACjC,CAAC;EACH,CAAC;EACD,OAAO;GACL,SAAS;GACT;GACA,SAAS,OAAO,EAAE,MAAM,cAAc;IACpC,IAAI,CAAC,WAAW,iBAAiB,SAAS,GAAG,OAAA,GAAMd,uBAAAA,UAAAA,CAAU,kCAAkC;IAC/F,IAAI,eACF,WACA,MACA,SACA,WAAW,cACX,WAAW,iBAAiB,GAC5B,WAAW,qBAAqB,SAAS,CAC3C;GACF;EACF;CACF,CAAC;CAED,yBAAA,mBAAmB,MAAM,EACvB,QAAQ,WAAW,WAA4C;EAC7D,MAAM,aAAa,aAAa,SAAsB;EACtD,MAAM,UAAU,IAAI,QAAQ,SAAS;EACrC,IAAI,CAAC,WAAW,CAAC,UAAU,YAAY,QAAQ,EAAE,GAAG,OAAO,KAAA;EAC3D,WAAW,SAAS,IAAI,SAAS;EACjC,MAAM,kBAAkB,IAAI,QAAQ,QAAQ,EAAE,CAAC,EAAE,SAAS,QAAQ,QAAQ,WAAW,iBAAiB,QAAQ,EAAE;EAEhH,MAAM,UAAU,QAAQ,KAAK;EAC7B,IAAI,YAAY,KAAA,GACd,OAAO;GAAE,YAAY,aAAa,QAAQ,IAAI;GAAG,QAAQ,QAAQ,KAAK,QAAQ;GAAQ;GAAW;EAAQ;EAC3G,OAAO;GACL,YAAY,aAAa,QAAQ,IAAI;GACrC,QAAQ,QAAQ,KAAK,QAAQ;GAC7B;GACA,SAAS;IACP,SAAS,QAAQ,KAAK;IACtB,sBAAsB,WACpB,QAAQ,KAAK,qBAAqB,UAAU;KAC1C,IAAI,UAAU,GAAG,OAAO,KAAK;IAC/B,CAAC;IACH,uBAAuB,UAAU;KAC/B,IAAI,CAAC,UAAU,GAAG,OAAA,GAAMA,uBAAAA,UAAAA,CAAU,kCAAkC;KACpE,OAAO,QAAQ,KAAK,qBAAqB,KAAK;IAChD;IACA,uBAAuB,UAAU,SAAS,gBAAgB;KACxD,IAAI,CAAC,UAAU,GAAG,OAAA,GAAMA,uBAAAA,UAAAA,CAAU,kCAAkC;KACpE,OAAO,QAAQ,SAAS,QAAQ,IAAI,UAAU,SAAS,WAAW;IACpE;IACA,WAAW,QAAQ;IACnB,aAAa,QAAQ;IACrB,KAAK,QAAQ;IACb,WAAW,QAAQ;GACrB;EACF;CACF,EACF,CAAC;CAED,IAAI;CACJ,OAAO;EACL,OAAO,MAAM,SAAS,CAAC,GAAG;GACxB,IAAI,YAAY,KAAA,GAAW;IACzB,KAAK,MAAM;IACX;GACF;GACA,MAAM,gBAAA,GAAeQ,YAAAA,WAAAA,CAAW;GAChC,MAAM,mBAAmB,OAAO,sBAAsB,OAAe,CAAC,IAAI,aAAa,cAAc,EAAE;GACvG,MAAM,mBAAmB,OAAO,2BAA2B;GAC3D,YAAY,IAAI,cAAc;IAC5B,OAAO,OAAO,SAAS,EAAE,OAAO,SAAS;IACzC;IACA;IACA,sBAAsB,OAAO,+BAA+B,iBAAiB;IAC7E,0BAAU,IAAI,IAAI;GACpB,CAAC;GACD,KAAK,cAAc;IACjB,YAAY,OAAO,YAAY;IAC/B,IAAI,mBAAmB,YAAY;GACrC,CAAC;GACD,KAAK,OAAOO,uBAAAA,qBAAqB,MAAM,QAAQ,UAAU,QAAQ,SAAS,GAAG;IAC3E,WAAW,EAAE,aAAa;IAC1B,MAAM;GACR,CAAC;EACH;EACA,QAAQ;GACN,aAAa,YAAY;IACvB,aAAa;IACb,QAAQ,MAAM;IACd,MAAM,KAAK,MAAM;GACnB,EAAA,CAAG;GACH,OAAO;EACT;CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"headlessProtocol.cjs","names":["createThreadJournals","createHost","PO_SERVER_HOST","harnessErrorMessage","forbidden","PoHubContract","chordSchema","Type","SessionSummarySchema","HubWorkspaceSchema","HubNoticeSchema","HubCompositionsSchema","randomUUID","PoHubRevisionsContract","HubRevisionsSchema","PoThreadContract","PoThreadFrameSchema","PoChannelsContract","PoChannelsStateSchema","serveAgentSessions","reportingLargeFrames"],"sources":["../src/server/headlessProtocol.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { createHost, forbidden, type Link, type Subscribable } from '@earendil-works/chord';\nimport { Type } from 'typebox';\n\nimport type { PoPluginCall } from '../exports/pluginProtocol';\nimport {\n HubCompositionsSchema,\n HubNoticeSchema,\n HubRevisionsSchema,\n PO_SERVER_HOST,\n PoChannelsContract,\n PoHubContract,\n PoHubRevisionsContract,\n PoThreadContract,\n type HubNotice,\n type HubSessionView,\n type HubWorkspaceView,\n type JsonValue,\n} from '../exports/sessionProtocol';\nimport { serveAgentSessions, type AgentSessionBinding } from '../pi/piSessionRuntime';\nimport { SessionSummarySchema } from '../schemas/httpApiContracts';\nimport type { PoSocketMount } from '../schemas/packageApi';\nimport { PoChannelsStateSchema } from '../schemas/protocolChannelsContract';\nimport { chordSchema } from '../schemas/protocolContracts';\nimport { HubWorkspaceSchema } from '../schemas/protocolHubContract';\nimport { PoThreadFrameSchema } from '../schemas/protocolThreadContract';\nimport type { OpenSessionRecord } from '../services/openSessionRegistry';\nimport type { ServerTelemetry } from '../services/serverTelemetry';\nimport { harnessErrorMessage } from './harnessErrorMessage';\nimport type { HeadlessHub, HeadlessHubEvent, HeadlessHubSession } from './headlessHub';\nimport { reportingLargeFrames } from './largeFrameLink';\nimport { createThreadJournals } from './threadJournals';\n\n// ponytail: unacknowledged notices beyond this drop oldest first; raise it if a client misses dialogs.\nconst MAX_PENDING_NOTICES = 64;\n/** A browser switching back to a thread quickly keeps its tail open. */\nconst THREAD_LINGER_MS = 5_000;\n\nfunction sessionView(session: HeadlessHubSession): HubSessionView {\n return {\n id: session.id,\n ...(session.workspaceId === undefined ? {} : { workspaceId: session.workspaceId }),\n ...(session.webComposition === undefined ? {} : { webComposition: { ...session.webComposition } }),\n ...(session.nativeComposition === undefined ? {} : { nativeComposition: { ...session.nativeComposition } }),\n name: session.name,\n cwd: session.cwd,\n createdAt: session.createdAt,\n updatedAt: session.updatedAt ?? session.createdAt,\n phase: session.phase ?? 'idle',\n phaseSince: session.phaseSince ?? session.createdAt,\n attach: 'attached',\n pendingMessageCount: session.pendingMessageCount ?? 0,\n everPrompted: session.everPrompted ?? false,\n awaitingInput: session.awaitingInput ?? false,\n ...(session.lastSettledAt === undefined ? {} : { lastSettledAt: session.lastSettledAt }),\n // null: the host has not reported yet.\n ...(session.backgroundWorkActive == null ? {} : { backgroundWorkActive: session.backgroundWorkActive }),\n ...(session.git === undefined ? {} : { git: { branch: session.git.branch, dirty: session.git.dirty } }),\n ...(session.profile === undefined\n ? {}\n : {\n profile: {\n name: session.profile.name,\n ...(session.profile.displayName === undefined ? {} : { displayName: session.profile.displayName }),\n ...(session.profile.iconVersion === undefined ? {} : { iconVersion: session.profile.iconVersion }),\n },\n }),\n ...(session.parentSessionId === undefined ? {} : { parentSessionId: session.parentSessionId }),\n ...(session.sessionProvenance === undefined ? {} : { sessionProvenance: session.sessionProvenance }),\n ...(session.interaction === undefined ? {} : { interaction: session.interaction }),\n ...(session.groups === undefined || session.groups.length === 0 ? {} : { groups: [...session.groups] }),\n ...(session.pendingSetups === undefined\n ? {}\n : {\n pendingSetups: session.pendingSetups.map((setup) => ({\n id: setup.id,\n name: setup.name,\n createdAt: setup.createdAt,\n ...(setup.cwd === undefined ? {} : { cwd: setup.cwd }),\n ...(setup.setupKind === undefined ? {} : { setupKind: setup.setupKind }),\n ...(setup.status === undefined ? {} : { status: setup.status }),\n ...(setup.errorCode === undefined ? {} : { errorCode: setup.errorCode }),\n })),\n }),\n ...(session.activity === undefined\n ? {}\n : {\n activity: {\n label: session.activity.label,\n ...(session.activity.attention === true ? { attention: true } : {}),\n ...(session.activity.since === undefined ? {} : { since: session.activity.since }),\n },\n }),\n ...(session.pendingApprovalCount === undefined ? {} : { pendingApprovalCount: session.pendingApprovalCount }),\n };\n}\n\n/**\n * A recorded session with no runtime behind it yet.\n *\n * Carries the same field set as a live session so the rail keys both by id and\n * swaps one for the other in place once the server reopens the journal.\n */\nfunction dormantView(record: OpenSessionRecord, pendingApprovalCount?: number): HubSessionView {\n return {\n id: record.sessionId,\n workspaceId: record.workspaceId,\n name: record.name,\n cwd: record.cwd,\n createdAt: record.createdAt,\n updatedAt: record.createdAt,\n phase: 'idle',\n phaseSince: record.createdAt,\n attach: 'attached',\n pendingMessageCount: 0,\n everPrompted: false,\n awaitingInput: false,\n dormant: true,\n ...(pendingApprovalCount === undefined ? {} : { pendingApprovalCount }),\n ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\n ...(record.interaction === undefined ? {} : { interaction: record.interaction }),\n ...(record.groups === undefined || record.groups.length === 0 ? {} : { groups: [...record.groups] }),\n };\n}\n\n/** Each restarted session host gets a new generation, so its projection starts fresh. */\nconst generations = new WeakMap<object, number>();\nlet nextGeneration = 0;\nfunction generationOf(host: object): number {\n let generation = generations.get(host);\n if (generation === undefined) {\n generation = nextGeneration++;\n generations.set(host, generation);\n }\n return generation;\n}\n\nfunction permitsSession(\n hub: HeadlessHub,\n mount: PoSocketMount,\n sessionId: string,\n authorize: (id: string) => boolean = () => true,\n): boolean {\n const session = hub.session(sessionId);\n return (\n session !== undefined &&\n authorize(sessionId) &&\n (mount.scope === 'global' ||\n (session.workspaceId === mount.workspaceId && (mount.scope === 'workspace' || mount.sessionId === sessionId)))\n );\n}\n\nfunction permitsDormant(mount: PoSocketMount, record: OpenSessionRecord): boolean {\n if (mount.scope === 'global') return true;\n if (record.workspaceId !== mount.workspaceId) return false;\n return mount.scope === 'workspace' || mount.sessionId === record.sessionId;\n}\n\n/** What one upgraded connection may reach, decided from its request when it connected. */\nexport interface ConnectionAccess {\n readonly mount: PoSocketMount;\n /** Evaluated for every call, including references taken before a Desktop claim. */\n authorizeSession(sessionId: string): boolean;\n authorizeDesktop(): boolean;\n authorizeComputerUse(sessionId: string): boolean;\n}\n\ninterface Connection extends ConnectionAccess {\n /** Sessions this connection reached, rechecked when computer-use ownership changes. */\n readonly sessions: Set<string>;\n}\n\ninterface Principal {\n connectionId: string;\n}\n\nexport interface HeadlessProtocol {\n /** Hands an authenticated link to the shared host. Without `access` it sees everything Desktop does not own. */\n accept(link: Link, access?: Partial<ConnectionAccess>): void;\n close(): Promise<void>;\n}\n\nconst eventsOf = (hub: HeadlessHub): Subscribable<HeadlessHubEvent> => ({\n subscribe: (listener) => hub.onEvent(listener),\n});\n\n/** One Chord host for every browser, native and relayed connection over the process-local hub. */\nexport function createHeadlessProtocol(options: {\n hub: HeadlessHub;\n telemetry?: ServerTelemetry;\n onNotice?: (message: string) => void;\n /** Recorded sessions the server has not reopened. */\n dormantSessions?: () => readonly OpenSessionRecord[];\n}): HeadlessProtocol {\n const hub = options.hub;\n const dormantSessions = () => (options.dormantSessions === undefined ? [] : options.dormantSessions());\n const connections = new Map<string, Connection>();\n const threads = createThreadJournals({\n resolve: (sessionId, threadId) => hub.childThread(sessionId, threadId),\n });\n const host = createHost<Principal>({\n name: PO_SERVER_HOST,\n self: { connectionId: PO_SERVER_HOST },\n principalKey: (principal) => principal.connectionId,\n onError: (error) => options.onNotice?.(`headless protocol error (${harnessErrorMessage(error)})`),\n });\n const connectionOf = (principal: Principal): Connection & { connectionId: string } => {\n const connection = connections.get(principal.connectionId);\n if (connection === undefined) throw forbidden('This connection has closed.');\n return { ...connection, connectionId: principal.connectionId };\n };\n const reachable = (connection: Connection, sessionId: string): boolean =>\n permitsSession(hub, connection.mount, sessionId, (id) => connection.authorizeSession(id));\n\n // A Desktop claim makes every reference the connection holds to that session gone at once.\n const stopClaims = hub.computerUse?.subscribe?.(() => {\n for (const [connectionId, connection] of connections) {\n let revoked = false;\n for (const sessionId of connection.sessions) if (!connection.authorizeSession(sessionId)) revoked = true;\n if (!revoked) continue;\n connection.sessions.clear();\n void host.invalidatePrincipal((principal) => principal.connectionId === connectionId);\n }\n });\n\n host.serve(PoHubContract, (_input, principal, self) => {\n const connection = connectionOf(principal);\n const { mount } = connection;\n const visibleSessions = (): Record<string, HubSessionView> => {\n const views: Record<string, HubSessionView> = {};\n for (const session of hub.snapshot())\n if (reachable(connection, session.id)) views[session.id] = sessionView(session);\n // A dormant record of a removed workspace has no HTTP list to come from, so clients would never agree on it.\n const registered = new Set(hub.workspaces().map((workspace) => workspace.id));\n for (const record of dormantSessions())\n if (\n views[record.sessionId] === undefined &&\n registered.has(record.workspaceId) &&\n connection.authorizeSession(record.sessionId) &&\n permitsDormant(mount, record)\n )\n views[record.sessionId] = dormantView(record, hub.sessionPendingApprovalCount?.(record.sessionId));\n return views;\n };\n const visibleWorkspaces = (): Record<string, HubWorkspaceView> => {\n const views: Record<string, HubWorkspaceView> = {};\n for (const workspace of hub.workspaces())\n if (mount.scope === 'global' || workspace.id === mount.workspaceId)\n views[workspace.id] = {\n id: workspace.id,\n root: workspace.root,\n ...(workspace.kind === undefined ? {} : { kind: workspace.kind }),\n ...(workspace.name === undefined ? {} : { name: workspace.name }),\n ...(workspace.sandbox === undefined ? {} : { sandbox: workspace.sandbox }),\n ...(workspace.sandboxState === undefined ? {} : { sandboxState: workspace.sandboxState }),\n ...(workspace.sandboxReason === undefined ? {} : { sandboxReason: workspace.sandboxReason }),\n available: workspace.available !== false,\n };\n return views;\n };\n const sessions = self.state('sessions', chordSchema(Type.Record(Type.String(), SessionSummarySchema)), {\n init: visibleSessions,\n });\n const workspaces = self.state('workspaces', chordSchema(Type.Record(Type.String(), HubWorkspaceSchema)), {\n init: visibleWorkspaces,\n });\n const pending = self.state('pending', chordSchema(Type.Array(HubNoticeSchema)), [] as HubNotice[]);\n const visibleCompositions = (): Record<string, number> => {\n const revisions = hub.compositionRevisions?.() ?? {};\n if (mount.scope === 'global') return { ...revisions };\n const own = `workspace:${mount.workspaceId}`;\n return Object.fromEntries(Object.entries(revisions).filter(([key]) => key === 'global' || key === own));\n };\n const compositions = self.state('compositions', chordSchema(HubCompositionsSchema), { init: visibleCompositions });\n self.on('hub', eventsOf(hub), (event, ctx) => {\n switch (event.kind) {\n case 'upsert':\n case 'removed':\n case 'dormant_changed':\n // Recomputed rather than patched, so an event before this listener started cannot leave a stale row.\n sessions.replace(ctx, visibleSessions(), { diff: true });\n return;\n case 'workspace_upsert':\n case 'workspace_removed':\n workspaces.replace(ctx, visibleWorkspaces(), { diff: true });\n return;\n case 'compositions':\n compositions.replace(ctx, visibleCompositions(), { diff: true });\n return;\n case 'frame':\n if (!reachable(connection, event.sessionId)) return;\n pending.change(ctx, (draft) => {\n draft.push({\n id: randomUUID(),\n sessionId: event.sessionId,\n frame: event.frame as Record<string, JsonValue>,\n });\n if (draft.length > MAX_PENDING_NOTICES) draft.splice(0, draft.length - MAX_PENDING_NOTICES);\n });\n return;\n case 'channel':\n return;\n }\n });\n return {\n variant: 'default',\n sessions,\n workspaces,\n pending,\n compositions,\n readHome: async (request) => {\n if (!hub.readHome) throw new Error('Home read is unavailable.');\n return hub.readHome(request, (id) => reachable(connection, id));\n },\n invoke: async (call: PoPluginCall, ctx) => {\n if (call.mount.scope === 'session' && !connection.authorizeSession(call.mount.sessionId))\n throw forbidden('This session belongs to its Desktop instance.');\n if (mount.scope !== 'global') {\n const permitted =\n call.mount.scope === 'session'\n ? permitsSession(hub, mount, call.mount.sessionId)\n : mount.scope === 'workspace' &&\n call.mount.scope === 'workspace' &&\n call.mount.workspaceId === mount.workspaceId;\n if (!permitted) throw forbidden('Plugin is outside this WebSocket scope.');\n }\n return (await hub.invokePlugin(call, 'client-to-server', {\n connectionId: connection.connectionId,\n signal: ctx.signal,\n })) as JsonValue;\n },\n ackNotice: async ({ id }, ctx) => {\n pending.change(ctx, (draft) => draft.filter((notice) => notice.id !== id));\n },\n };\n });\n\n host.serve(PoHubRevisionsContract, (_input, principal, self) => {\n const { mount } = connectionOf(principal);\n const visibleRevisions = (): Record<string, number> => {\n const revisions = hub.revisions?.() ?? {};\n if (mount.scope === 'global') return { ...revisions };\n const own = `workspace:${mount.workspaceId}:`;\n return Object.fromEntries(\n Object.entries(revisions).filter(([topic]) => topic.startsWith('global:') || topic.startsWith(own)),\n );\n };\n const revisions = self.state('revisions', chordSchema(HubRevisionsSchema), { init: visibleRevisions });\n self.on('hub', eventsOf(hub), (event, ctx) => {\n if (event.kind === 'revisions') revisions.replace(ctx, visibleRevisions(), { diff: true });\n });\n return { variant: 'default', revisions };\n });\n\n host.serve(\n PoThreadContract,\n ({ sessionId, threadId }, principal, self) => {\n const connection = connectionOf(principal);\n if (!reachable(connection, sessionId)) throw forbidden(`No session ${sessionId}`);\n connection.sessions.add(sessionId);\n const tail = self.resource('tail', {\n version: 1,\n open: () => threads.subscribe(sessionId, threadId),\n close: () => threads.unsubscribe(sessionId, threadId),\n });\n const frame = self.state('frame', chordSchema(PoThreadFrameSchema), {\n init: () => (tail.value?.at(-1) ?? null) as never,\n });\n self.on(\n 'frames',\n { subscribe: (listener) => threads.onFrame(listener) } as Subscribable<{\n sessionId: string;\n threadId: string;\n frame: Record<string, unknown>;\n }>,\n (event, ctx) => {\n // Each frame is a fresh wrapper around the child's state, so only an explicit diff sends ops, not the whole state.\n if (event.sessionId === sessionId && event.threadId === threadId)\n frame.replace(ctx, event.frame as never, { diff: true });\n },\n );\n return { variant: 'default', frame };\n },\n { linger: THREAD_LINGER_MS },\n );\n\n host.serve(PoChannelsContract, ({ sessionId }, principal, self) => {\n const connection = connectionOf(principal);\n if (!reachable(connection, sessionId)) throw forbidden(`No session ${sessionId}`);\n connection.sessions.add(sessionId);\n const visible = (frameType: string): boolean =>\n frameType !== 'computer_use_state' || connection.authorizeComputerUse(sessionId);\n const latest = self.state('latest', chordSchema(PoChannelsStateSchema), {\n init: () => {\n const payloads: Record<string, JsonValue> = {};\n for (const channelFrame of hub.channelFrames(sessionId))\n if (visible(channelFrame.type)) payloads[channelFrame.type] = channelFrame.payload as JsonValue;\n return payloads;\n },\n });\n // ponytail: a channel keeps only its latest payload; a package that needs every event must carry a sequence.\n self.on('hub', eventsOf(hub), (event, ctx) => {\n if (event.kind !== 'channel' || event.sessionId !== sessionId || !visible(event.frameType)) return;\n if (event.connectionId !== undefined && event.connectionId !== connection.connectionId) return;\n latest.change(ctx, (draft) => {\n draft[event.frameType] = event.payload as JsonValue;\n });\n });\n return {\n variant: 'default',\n latest,\n receive: async ({ type, payload }) => {\n if (!connection.authorizeSession(sessionId)) throw forbidden('This session belongs to Desktop.');\n hub.receiveChannel(\n sessionId,\n type,\n payload,\n connection.connectionId,\n connection.authorizeDesktop(),\n connection.authorizeComputerUse(sessionId),\n );\n },\n };\n });\n\n const clearSessionBindings = serveAgentSessions(host, {\n resolve(sessionId, principal): AgentSessionBinding | undefined {\n const connection = connectionOf(principal as Principal);\n const session = hub.session(sessionId);\n if (!session || !reachable(connection, session.id)) return undefined;\n connection.sessions.add(sessionId);\n const permitted = () => hub.session(session.id)?.host === session.host && connection.authorizeSession(session.id);\n // A mirror of a session another host runs forwards there; keyed by its host object, never by session id.\n const forward = session.host.agentSession;\n if (forward !== undefined)\n return { generation: generationOf(session.host), exited: session.host.runtime.exited, permitted, forward };\n return {\n generation: generationOf(session.host),\n exited: session.host.runtime.exited,\n permitted,\n options: {\n runtime: session.host.runtime,\n onPresentationFrame: (listen) =>\n session.host.onPresentationFrame((frame) => {\n if (permitted()) listen(frame);\n }),\n respondToExtensionUi: (frame) => {\n if (!permitted()) throw forbidden('This session belongs to Desktop.');\n return session.host.respondToExtensionUi(frame);\n },\n readThreadTranscript: (threadId, request, readContext) => {\n if (!permitted()) throw forbidden('This session belongs to Desktop.');\n return threads.readPage(session.id, threadId, request, readContext);\n },\n sessionId: session.id,\n sessionName: session.name,\n cwd: session.cwd,\n telemetry: options.telemetry,\n },\n };\n },\n });\n\n let closing: Promise<void> | undefined;\n return {\n accept(link, access = {}) {\n if (closing !== undefined) {\n link.close();\n return;\n }\n const connectionId = randomUUID();\n const authorizeSession = access.authorizeSession ?? ((id: string) => !hub.computerUse?.ownsSession?.(id));\n const authorizeDesktop = access.authorizeDesktop ?? (() => false);\n connections.set(connectionId, {\n mount: access.mount ?? { scope: 'global' },\n authorizeSession,\n authorizeDesktop,\n authorizeComputerUse: access.authorizeComputerUse ?? (() => authorizeDesktop()),\n sessions: new Set(),\n });\n link.onClose(() => {\n connections.delete(connectionId);\n hub.disconnectChannels(connectionId);\n });\n host.accept(reportingLargeFrames(link, options.onNotice, options.telemetry), {\n principal: { connectionId },\n kind: 'client',\n });\n },\n close() {\n closing ??= (async () => {\n stopClaims?.();\n threads.close();\n clearSessionBindings();\n await host.close();\n })();\n return closing;\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -290,7 +290,7 @@ function createHeadlessProtocol(options) {
|
|
|
290
290
|
}
|
|
291
291
|
};
|
|
292
292
|
});
|
|
293
|
-
serveAgentSessions(host, { resolve(sessionId, principal) {
|
|
293
|
+
const clearSessionBindings = serveAgentSessions(host, { resolve(sessionId, principal) {
|
|
294
294
|
const connection = connectionOf(principal);
|
|
295
295
|
const session = hub.session(sessionId);
|
|
296
296
|
if (!session || !reachable(connection, session.id)) return void 0;
|
|
@@ -357,6 +357,7 @@ function createHeadlessProtocol(options) {
|
|
|
357
357
|
closing ??= (async () => {
|
|
358
358
|
stopClaims?.();
|
|
359
359
|
threads.close();
|
|
360
|
+
clearSessionBindings();
|
|
360
361
|
await host.close();
|
|
361
362
|
})();
|
|
362
363
|
return closing;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headlessProtocol.mjs","names":[],"sources":["../src/server/headlessProtocol.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { createHost, forbidden, type Link, type Subscribable } from '@earendil-works/chord';\nimport { Type } from 'typebox';\n\nimport type { PoPluginCall } from '../exports/pluginProtocol';\nimport {\n HubCompositionsSchema,\n HubNoticeSchema,\n HubRevisionsSchema,\n PO_SERVER_HOST,\n PoChannelsContract,\n PoHubContract,\n PoHubRevisionsContract,\n PoThreadContract,\n type HubNotice,\n type HubSessionView,\n type HubWorkspaceView,\n type JsonValue,\n} from '../exports/sessionProtocol';\nimport { serveAgentSessions, type AgentSessionBinding } from '../pi/piSessionRuntime';\nimport { SessionSummarySchema } from '../schemas/httpApiContracts';\nimport type { PoSocketMount } from '../schemas/packageApi';\nimport { PoChannelsStateSchema } from '../schemas/protocolChannelsContract';\nimport { chordSchema } from '../schemas/protocolContracts';\nimport { HubWorkspaceSchema } from '../schemas/protocolHubContract';\nimport { PoThreadFrameSchema } from '../schemas/protocolThreadContract';\nimport type { OpenSessionRecord } from '../services/openSessionRegistry';\nimport type { ServerTelemetry } from '../services/serverTelemetry';\nimport { harnessErrorMessage } from './harnessErrorMessage';\nimport type { HeadlessHub, HeadlessHubEvent, HeadlessHubSession } from './headlessHub';\nimport { reportingLargeFrames } from './largeFrameLink';\nimport { createThreadJournals } from './threadJournals';\n\n// ponytail: unacknowledged notices beyond this drop oldest first; raise it if a client misses dialogs.\nconst MAX_PENDING_NOTICES = 64;\n/** A browser switching back to a thread quickly keeps its tail open. */\nconst THREAD_LINGER_MS = 5_000;\n\nfunction sessionView(session: HeadlessHubSession): HubSessionView {\n return {\n id: session.id,\n ...(session.workspaceId === undefined ? {} : { workspaceId: session.workspaceId }),\n ...(session.webComposition === undefined ? {} : { webComposition: { ...session.webComposition } }),\n ...(session.nativeComposition === undefined ? {} : { nativeComposition: { ...session.nativeComposition } }),\n name: session.name,\n cwd: session.cwd,\n createdAt: session.createdAt,\n updatedAt: session.updatedAt ?? session.createdAt,\n phase: session.phase ?? 'idle',\n phaseSince: session.phaseSince ?? session.createdAt,\n attach: 'attached',\n pendingMessageCount: session.pendingMessageCount ?? 0,\n everPrompted: session.everPrompted ?? false,\n awaitingInput: session.awaitingInput ?? false,\n ...(session.lastSettledAt === undefined ? {} : { lastSettledAt: session.lastSettledAt }),\n // null: the host has not reported yet.\n ...(session.backgroundWorkActive == null ? {} : { backgroundWorkActive: session.backgroundWorkActive }),\n ...(session.git === undefined ? {} : { git: { branch: session.git.branch, dirty: session.git.dirty } }),\n ...(session.profile === undefined\n ? {}\n : {\n profile: {\n name: session.profile.name,\n ...(session.profile.displayName === undefined ? {} : { displayName: session.profile.displayName }),\n ...(session.profile.iconVersion === undefined ? {} : { iconVersion: session.profile.iconVersion }),\n },\n }),\n ...(session.parentSessionId === undefined ? {} : { parentSessionId: session.parentSessionId }),\n ...(session.sessionProvenance === undefined ? {} : { sessionProvenance: session.sessionProvenance }),\n ...(session.interaction === undefined ? {} : { interaction: session.interaction }),\n ...(session.groups === undefined || session.groups.length === 0 ? {} : { groups: [...session.groups] }),\n ...(session.pendingSetups === undefined\n ? {}\n : {\n pendingSetups: session.pendingSetups.map((setup) => ({\n id: setup.id,\n name: setup.name,\n createdAt: setup.createdAt,\n ...(setup.cwd === undefined ? {} : { cwd: setup.cwd }),\n ...(setup.setupKind === undefined ? {} : { setupKind: setup.setupKind }),\n ...(setup.status === undefined ? {} : { status: setup.status }),\n ...(setup.errorCode === undefined ? {} : { errorCode: setup.errorCode }),\n })),\n }),\n ...(session.activity === undefined\n ? {}\n : {\n activity: {\n label: session.activity.label,\n ...(session.activity.attention === true ? { attention: true } : {}),\n ...(session.activity.since === undefined ? {} : { since: session.activity.since }),\n },\n }),\n ...(session.pendingApprovalCount === undefined ? {} : { pendingApprovalCount: session.pendingApprovalCount }),\n };\n}\n\n/**\n * A recorded session with no runtime behind it yet.\n *\n * Carries the same field set as a live session so the rail keys both by id and\n * swaps one for the other in place once the server reopens the journal.\n */\nfunction dormantView(record: OpenSessionRecord, pendingApprovalCount?: number): HubSessionView {\n return {\n id: record.sessionId,\n workspaceId: record.workspaceId,\n name: record.name,\n cwd: record.cwd,\n createdAt: record.createdAt,\n updatedAt: record.createdAt,\n phase: 'idle',\n phaseSince: record.createdAt,\n attach: 'attached',\n pendingMessageCount: 0,\n everPrompted: false,\n awaitingInput: false,\n dormant: true,\n ...(pendingApprovalCount === undefined ? {} : { pendingApprovalCount }),\n ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\n ...(record.interaction === undefined ? {} : { interaction: record.interaction }),\n ...(record.groups === undefined || record.groups.length === 0 ? {} : { groups: [...record.groups] }),\n };\n}\n\n/** Each restarted session host gets a new generation, so its projection starts fresh. */\nconst generations = new WeakMap<object, number>();\nlet nextGeneration = 0;\nfunction generationOf(host: object): number {\n let generation = generations.get(host);\n if (generation === undefined) {\n generation = nextGeneration++;\n generations.set(host, generation);\n }\n return generation;\n}\n\nfunction permitsSession(\n hub: HeadlessHub,\n mount: PoSocketMount,\n sessionId: string,\n authorize: (id: string) => boolean = () => true,\n): boolean {\n const session = hub.session(sessionId);\n return (\n session !== undefined &&\n authorize(sessionId) &&\n (mount.scope === 'global' ||\n (session.workspaceId === mount.workspaceId && (mount.scope === 'workspace' || mount.sessionId === sessionId)))\n );\n}\n\nfunction permitsDormant(mount: PoSocketMount, record: OpenSessionRecord): boolean {\n if (mount.scope === 'global') return true;\n if (record.workspaceId !== mount.workspaceId) return false;\n return mount.scope === 'workspace' || mount.sessionId === record.sessionId;\n}\n\n/** What one upgraded connection may reach, decided from its request when it connected. */\nexport interface ConnectionAccess {\n readonly mount: PoSocketMount;\n /** Evaluated for every call, including references taken before a Desktop claim. */\n authorizeSession(sessionId: string): boolean;\n authorizeDesktop(): boolean;\n authorizeComputerUse(sessionId: string): boolean;\n}\n\ninterface Connection extends ConnectionAccess {\n /** Sessions this connection reached, rechecked when computer-use ownership changes. */\n readonly sessions: Set<string>;\n}\n\ninterface Principal {\n connectionId: string;\n}\n\nexport interface HeadlessProtocol {\n /** Hands an authenticated link to the shared host. Without `access` it sees everything Desktop does not own. */\n accept(link: Link, access?: Partial<ConnectionAccess>): void;\n close(): Promise<void>;\n}\n\nconst eventsOf = (hub: HeadlessHub): Subscribable<HeadlessHubEvent> => ({\n subscribe: (listener) => hub.onEvent(listener),\n});\n\n/** One Chord host for every browser, native and relayed connection over the process-local hub. */\nexport function createHeadlessProtocol(options: {\n hub: HeadlessHub;\n telemetry?: ServerTelemetry;\n onNotice?: (message: string) => void;\n /** Recorded sessions the server has not reopened. */\n dormantSessions?: () => readonly OpenSessionRecord[];\n}): HeadlessProtocol {\n const hub = options.hub;\n const dormantSessions = () => (options.dormantSessions === undefined ? [] : options.dormantSessions());\n const connections = new Map<string, Connection>();\n const threads = createThreadJournals({\n resolve: (sessionId, threadId) => hub.childThread(sessionId, threadId),\n });\n const host = createHost<Principal>({\n name: PO_SERVER_HOST,\n self: { connectionId: PO_SERVER_HOST },\n principalKey: (principal) => principal.connectionId,\n onError: (error) => options.onNotice?.(`headless protocol error (${harnessErrorMessage(error)})`),\n });\n const connectionOf = (principal: Principal): Connection & { connectionId: string } => {\n const connection = connections.get(principal.connectionId);\n if (connection === undefined) throw forbidden('This connection has closed.');\n return { ...connection, connectionId: principal.connectionId };\n };\n const reachable = (connection: Connection, sessionId: string): boolean =>\n permitsSession(hub, connection.mount, sessionId, (id) => connection.authorizeSession(id));\n\n // A Desktop claim makes every reference the connection holds to that session gone at once.\n const stopClaims = hub.computerUse?.subscribe?.(() => {\n for (const [connectionId, connection] of connections) {\n let revoked = false;\n for (const sessionId of connection.sessions) if (!connection.authorizeSession(sessionId)) revoked = true;\n if (!revoked) continue;\n connection.sessions.clear();\n void host.invalidatePrincipal((principal) => principal.connectionId === connectionId);\n }\n });\n\n host.serve(PoHubContract, (_input, principal, self) => {\n const connection = connectionOf(principal);\n const { mount } = connection;\n const visibleSessions = (): Record<string, HubSessionView> => {\n const views: Record<string, HubSessionView> = {};\n for (const session of hub.snapshot())\n if (reachable(connection, session.id)) views[session.id] = sessionView(session);\n // A dormant record of a removed workspace has no HTTP list to come from, so clients would never agree on it.\n const registered = new Set(hub.workspaces().map((workspace) => workspace.id));\n for (const record of dormantSessions())\n if (\n views[record.sessionId] === undefined &&\n registered.has(record.workspaceId) &&\n connection.authorizeSession(record.sessionId) &&\n permitsDormant(mount, record)\n )\n views[record.sessionId] = dormantView(record, hub.sessionPendingApprovalCount?.(record.sessionId));\n return views;\n };\n const visibleWorkspaces = (): Record<string, HubWorkspaceView> => {\n const views: Record<string, HubWorkspaceView> = {};\n for (const workspace of hub.workspaces())\n if (mount.scope === 'global' || workspace.id === mount.workspaceId)\n views[workspace.id] = {\n id: workspace.id,\n root: workspace.root,\n ...(workspace.kind === undefined ? {} : { kind: workspace.kind }),\n ...(workspace.name === undefined ? {} : { name: workspace.name }),\n ...(workspace.sandbox === undefined ? {} : { sandbox: workspace.sandbox }),\n ...(workspace.sandboxState === undefined ? {} : { sandboxState: workspace.sandboxState }),\n ...(workspace.sandboxReason === undefined ? {} : { sandboxReason: workspace.sandboxReason }),\n available: workspace.available !== false,\n };\n return views;\n };\n const sessions = self.state('sessions', chordSchema(Type.Record(Type.String(), SessionSummarySchema)), {\n init: visibleSessions,\n });\n const workspaces = self.state('workspaces', chordSchema(Type.Record(Type.String(), HubWorkspaceSchema)), {\n init: visibleWorkspaces,\n });\n const pending = self.state('pending', chordSchema(Type.Array(HubNoticeSchema)), [] as HubNotice[]);\n const visibleCompositions = (): Record<string, number> => {\n const revisions = hub.compositionRevisions?.() ?? {};\n if (mount.scope === 'global') return { ...revisions };\n const own = `workspace:${mount.workspaceId}`;\n return Object.fromEntries(Object.entries(revisions).filter(([key]) => key === 'global' || key === own));\n };\n const compositions = self.state('compositions', chordSchema(HubCompositionsSchema), { init: visibleCompositions });\n self.on('hub', eventsOf(hub), (event, ctx) => {\n switch (event.kind) {\n case 'upsert':\n case 'removed':\n case 'dormant_changed':\n // Recomputed rather than patched, so an event before this listener started cannot leave a stale row.\n sessions.replace(ctx, visibleSessions(), { diff: true });\n return;\n case 'workspace_upsert':\n case 'workspace_removed':\n workspaces.replace(ctx, visibleWorkspaces(), { diff: true });\n return;\n case 'compositions':\n compositions.replace(ctx, visibleCompositions(), { diff: true });\n return;\n case 'frame':\n if (!reachable(connection, event.sessionId)) return;\n pending.change(ctx, (draft) => {\n draft.push({\n id: randomUUID(),\n sessionId: event.sessionId,\n frame: event.frame as Record<string, JsonValue>,\n });\n if (draft.length > MAX_PENDING_NOTICES) draft.splice(0, draft.length - MAX_PENDING_NOTICES);\n });\n return;\n case 'channel':\n return;\n }\n });\n return {\n variant: 'default',\n sessions,\n workspaces,\n pending,\n compositions,\n readHome: async (request) => {\n if (!hub.readHome) throw new Error('Home read is unavailable.');\n return hub.readHome(request, (id) => reachable(connection, id));\n },\n invoke: async (call: PoPluginCall, ctx) => {\n if (call.mount.scope === 'session' && !connection.authorizeSession(call.mount.sessionId))\n throw forbidden('This session belongs to its Desktop instance.');\n if (mount.scope !== 'global') {\n const permitted =\n call.mount.scope === 'session'\n ? permitsSession(hub, mount, call.mount.sessionId)\n : mount.scope === 'workspace' &&\n call.mount.scope === 'workspace' &&\n call.mount.workspaceId === mount.workspaceId;\n if (!permitted) throw forbidden('Plugin is outside this WebSocket scope.');\n }\n return (await hub.invokePlugin(call, 'client-to-server', {\n connectionId: connection.connectionId,\n signal: ctx.signal,\n })) as JsonValue;\n },\n ackNotice: async ({ id }, ctx) => {\n pending.change(ctx, (draft) => draft.filter((notice) => notice.id !== id));\n },\n };\n });\n\n host.serve(PoHubRevisionsContract, (_input, principal, self) => {\n const { mount } = connectionOf(principal);\n const visibleRevisions = (): Record<string, number> => {\n const revisions = hub.revisions?.() ?? {};\n if (mount.scope === 'global') return { ...revisions };\n const own = `workspace:${mount.workspaceId}:`;\n return Object.fromEntries(\n Object.entries(revisions).filter(([topic]) => topic.startsWith('global:') || topic.startsWith(own)),\n );\n };\n const revisions = self.state('revisions', chordSchema(HubRevisionsSchema), { init: visibleRevisions });\n self.on('hub', eventsOf(hub), (event, ctx) => {\n if (event.kind === 'revisions') revisions.replace(ctx, visibleRevisions(), { diff: true });\n });\n return { variant: 'default', revisions };\n });\n\n host.serve(\n PoThreadContract,\n ({ sessionId, threadId }, principal, self) => {\n const connection = connectionOf(principal);\n if (!reachable(connection, sessionId)) throw forbidden(`No session ${sessionId}`);\n connection.sessions.add(sessionId);\n const tail = self.resource('tail', {\n version: 1,\n open: () => threads.subscribe(sessionId, threadId),\n close: () => threads.unsubscribe(sessionId, threadId),\n });\n const frame = self.state('frame', chordSchema(PoThreadFrameSchema), {\n init: () => (tail.value?.at(-1) ?? null) as never,\n });\n self.on(\n 'frames',\n { subscribe: (listener) => threads.onFrame(listener) } as Subscribable<{\n sessionId: string;\n threadId: string;\n frame: Record<string, unknown>;\n }>,\n (event, ctx) => {\n // Each frame is a fresh wrapper around the child's state, so only an explicit diff sends ops, not the whole state.\n if (event.sessionId === sessionId && event.threadId === threadId)\n frame.replace(ctx, event.frame as never, { diff: true });\n },\n );\n return { variant: 'default', frame };\n },\n { linger: THREAD_LINGER_MS },\n );\n\n host.serve(PoChannelsContract, ({ sessionId }, principal, self) => {\n const connection = connectionOf(principal);\n if (!reachable(connection, sessionId)) throw forbidden(`No session ${sessionId}`);\n connection.sessions.add(sessionId);\n const visible = (frameType: string): boolean =>\n frameType !== 'computer_use_state' || connection.authorizeComputerUse(sessionId);\n const latest = self.state('latest', chordSchema(PoChannelsStateSchema), {\n init: () => {\n const payloads: Record<string, JsonValue> = {};\n for (const channelFrame of hub.channelFrames(sessionId))\n if (visible(channelFrame.type)) payloads[channelFrame.type] = channelFrame.payload as JsonValue;\n return payloads;\n },\n });\n // ponytail: a channel keeps only its latest payload; a package that needs every event must carry a sequence.\n self.on('hub', eventsOf(hub), (event, ctx) => {\n if (event.kind !== 'channel' || event.sessionId !== sessionId || !visible(event.frameType)) return;\n if (event.connectionId !== undefined && event.connectionId !== connection.connectionId) return;\n latest.change(ctx, (draft) => {\n draft[event.frameType] = event.payload as JsonValue;\n });\n });\n return {\n variant: 'default',\n latest,\n receive: async ({ type, payload }) => {\n if (!connection.authorizeSession(sessionId)) throw forbidden('This session belongs to Desktop.');\n hub.receiveChannel(\n sessionId,\n type,\n payload,\n connection.connectionId,\n connection.authorizeDesktop(),\n connection.authorizeComputerUse(sessionId),\n );\n },\n };\n });\n\n serveAgentSessions(host, {\n resolve(sessionId, principal): AgentSessionBinding | undefined {\n const connection = connectionOf(principal as Principal);\n const session = hub.session(sessionId);\n if (!session || !reachable(connection, session.id)) return undefined;\n connection.sessions.add(sessionId);\n const permitted = () => hub.session(session.id)?.host === session.host && connection.authorizeSession(session.id);\n // A mirror of a session another host runs forwards there; keyed by its host object, never by session id.\n const forward = session.host.agentSession;\n if (forward !== undefined)\n return { generation: generationOf(session.host), exited: session.host.runtime.exited, permitted, forward };\n return {\n generation: generationOf(session.host),\n exited: session.host.runtime.exited,\n permitted,\n options: {\n runtime: session.host.runtime,\n onPresentationFrame: (listen) =>\n session.host.onPresentationFrame((frame) => {\n if (permitted()) listen(frame);\n }),\n respondToExtensionUi: (frame) => {\n if (!permitted()) throw forbidden('This session belongs to Desktop.');\n return session.host.respondToExtensionUi(frame);\n },\n readThreadTranscript: (threadId, request, readContext) => {\n if (!permitted()) throw forbidden('This session belongs to Desktop.');\n return threads.readPage(session.id, threadId, request, readContext);\n },\n sessionId: session.id,\n sessionName: session.name,\n cwd: session.cwd,\n telemetry: options.telemetry,\n },\n };\n },\n });\n\n let closing: Promise<void> | undefined;\n return {\n accept(link, access = {}) {\n if (closing !== undefined) {\n link.close();\n return;\n }\n const connectionId = randomUUID();\n const authorizeSession = access.authorizeSession ?? ((id: string) => !hub.computerUse?.ownsSession?.(id));\n const authorizeDesktop = access.authorizeDesktop ?? (() => false);\n connections.set(connectionId, {\n mount: access.mount ?? { scope: 'global' },\n authorizeSession,\n authorizeDesktop,\n authorizeComputerUse: access.authorizeComputerUse ?? (() => authorizeDesktop()),\n sessions: new Set(),\n });\n link.onClose(() => {\n connections.delete(connectionId);\n hub.disconnectChannels(connectionId);\n });\n host.accept(reportingLargeFrames(link, options.onNotice, options.telemetry), {\n principal: { connectionId },\n kind: 'client',\n });\n },\n close() {\n closing ??= (async () => {\n stopClaims?.();\n threads.close();\n await host.close();\n })();\n return closing;\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"headlessProtocol.mjs","names":[],"sources":["../src/server/headlessProtocol.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { createHost, forbidden, type Link, type Subscribable } from '@earendil-works/chord';\nimport { Type } from 'typebox';\n\nimport type { PoPluginCall } from '../exports/pluginProtocol';\nimport {\n HubCompositionsSchema,\n HubNoticeSchema,\n HubRevisionsSchema,\n PO_SERVER_HOST,\n PoChannelsContract,\n PoHubContract,\n PoHubRevisionsContract,\n PoThreadContract,\n type HubNotice,\n type HubSessionView,\n type HubWorkspaceView,\n type JsonValue,\n} from '../exports/sessionProtocol';\nimport { serveAgentSessions, type AgentSessionBinding } from '../pi/piSessionRuntime';\nimport { SessionSummarySchema } from '../schemas/httpApiContracts';\nimport type { PoSocketMount } from '../schemas/packageApi';\nimport { PoChannelsStateSchema } from '../schemas/protocolChannelsContract';\nimport { chordSchema } from '../schemas/protocolContracts';\nimport { HubWorkspaceSchema } from '../schemas/protocolHubContract';\nimport { PoThreadFrameSchema } from '../schemas/protocolThreadContract';\nimport type { OpenSessionRecord } from '../services/openSessionRegistry';\nimport type { ServerTelemetry } from '../services/serverTelemetry';\nimport { harnessErrorMessage } from './harnessErrorMessage';\nimport type { HeadlessHub, HeadlessHubEvent, HeadlessHubSession } from './headlessHub';\nimport { reportingLargeFrames } from './largeFrameLink';\nimport { createThreadJournals } from './threadJournals';\n\n// ponytail: unacknowledged notices beyond this drop oldest first; raise it if a client misses dialogs.\nconst MAX_PENDING_NOTICES = 64;\n/** A browser switching back to a thread quickly keeps its tail open. */\nconst THREAD_LINGER_MS = 5_000;\n\nfunction sessionView(session: HeadlessHubSession): HubSessionView {\n return {\n id: session.id,\n ...(session.workspaceId === undefined ? {} : { workspaceId: session.workspaceId }),\n ...(session.webComposition === undefined ? {} : { webComposition: { ...session.webComposition } }),\n ...(session.nativeComposition === undefined ? {} : { nativeComposition: { ...session.nativeComposition } }),\n name: session.name,\n cwd: session.cwd,\n createdAt: session.createdAt,\n updatedAt: session.updatedAt ?? session.createdAt,\n phase: session.phase ?? 'idle',\n phaseSince: session.phaseSince ?? session.createdAt,\n attach: 'attached',\n pendingMessageCount: session.pendingMessageCount ?? 0,\n everPrompted: session.everPrompted ?? false,\n awaitingInput: session.awaitingInput ?? false,\n ...(session.lastSettledAt === undefined ? {} : { lastSettledAt: session.lastSettledAt }),\n // null: the host has not reported yet.\n ...(session.backgroundWorkActive == null ? {} : { backgroundWorkActive: session.backgroundWorkActive }),\n ...(session.git === undefined ? {} : { git: { branch: session.git.branch, dirty: session.git.dirty } }),\n ...(session.profile === undefined\n ? {}\n : {\n profile: {\n name: session.profile.name,\n ...(session.profile.displayName === undefined ? {} : { displayName: session.profile.displayName }),\n ...(session.profile.iconVersion === undefined ? {} : { iconVersion: session.profile.iconVersion }),\n },\n }),\n ...(session.parentSessionId === undefined ? {} : { parentSessionId: session.parentSessionId }),\n ...(session.sessionProvenance === undefined ? {} : { sessionProvenance: session.sessionProvenance }),\n ...(session.interaction === undefined ? {} : { interaction: session.interaction }),\n ...(session.groups === undefined || session.groups.length === 0 ? {} : { groups: [...session.groups] }),\n ...(session.pendingSetups === undefined\n ? {}\n : {\n pendingSetups: session.pendingSetups.map((setup) => ({\n id: setup.id,\n name: setup.name,\n createdAt: setup.createdAt,\n ...(setup.cwd === undefined ? {} : { cwd: setup.cwd }),\n ...(setup.setupKind === undefined ? {} : { setupKind: setup.setupKind }),\n ...(setup.status === undefined ? {} : { status: setup.status }),\n ...(setup.errorCode === undefined ? {} : { errorCode: setup.errorCode }),\n })),\n }),\n ...(session.activity === undefined\n ? {}\n : {\n activity: {\n label: session.activity.label,\n ...(session.activity.attention === true ? { attention: true } : {}),\n ...(session.activity.since === undefined ? {} : { since: session.activity.since }),\n },\n }),\n ...(session.pendingApprovalCount === undefined ? {} : { pendingApprovalCount: session.pendingApprovalCount }),\n };\n}\n\n/**\n * A recorded session with no runtime behind it yet.\n *\n * Carries the same field set as a live session so the rail keys both by id and\n * swaps one for the other in place once the server reopens the journal.\n */\nfunction dormantView(record: OpenSessionRecord, pendingApprovalCount?: number): HubSessionView {\n return {\n id: record.sessionId,\n workspaceId: record.workspaceId,\n name: record.name,\n cwd: record.cwd,\n createdAt: record.createdAt,\n updatedAt: record.createdAt,\n phase: 'idle',\n phaseSince: record.createdAt,\n attach: 'attached',\n pendingMessageCount: 0,\n everPrompted: false,\n awaitingInput: false,\n dormant: true,\n ...(pendingApprovalCount === undefined ? {} : { pendingApprovalCount }),\n ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\n ...(record.interaction === undefined ? {} : { interaction: record.interaction }),\n ...(record.groups === undefined || record.groups.length === 0 ? {} : { groups: [...record.groups] }),\n };\n}\n\n/** Each restarted session host gets a new generation, so its projection starts fresh. */\nconst generations = new WeakMap<object, number>();\nlet nextGeneration = 0;\nfunction generationOf(host: object): number {\n let generation = generations.get(host);\n if (generation === undefined) {\n generation = nextGeneration++;\n generations.set(host, generation);\n }\n return generation;\n}\n\nfunction permitsSession(\n hub: HeadlessHub,\n mount: PoSocketMount,\n sessionId: string,\n authorize: (id: string) => boolean = () => true,\n): boolean {\n const session = hub.session(sessionId);\n return (\n session !== undefined &&\n authorize(sessionId) &&\n (mount.scope === 'global' ||\n (session.workspaceId === mount.workspaceId && (mount.scope === 'workspace' || mount.sessionId === sessionId)))\n );\n}\n\nfunction permitsDormant(mount: PoSocketMount, record: OpenSessionRecord): boolean {\n if (mount.scope === 'global') return true;\n if (record.workspaceId !== mount.workspaceId) return false;\n return mount.scope === 'workspace' || mount.sessionId === record.sessionId;\n}\n\n/** What one upgraded connection may reach, decided from its request when it connected. */\nexport interface ConnectionAccess {\n readonly mount: PoSocketMount;\n /** Evaluated for every call, including references taken before a Desktop claim. */\n authorizeSession(sessionId: string): boolean;\n authorizeDesktop(): boolean;\n authorizeComputerUse(sessionId: string): boolean;\n}\n\ninterface Connection extends ConnectionAccess {\n /** Sessions this connection reached, rechecked when computer-use ownership changes. */\n readonly sessions: Set<string>;\n}\n\ninterface Principal {\n connectionId: string;\n}\n\nexport interface HeadlessProtocol {\n /** Hands an authenticated link to the shared host. Without `access` it sees everything Desktop does not own. */\n accept(link: Link, access?: Partial<ConnectionAccess>): void;\n close(): Promise<void>;\n}\n\nconst eventsOf = (hub: HeadlessHub): Subscribable<HeadlessHubEvent> => ({\n subscribe: (listener) => hub.onEvent(listener),\n});\n\n/** One Chord host for every browser, native and relayed connection over the process-local hub. */\nexport function createHeadlessProtocol(options: {\n hub: HeadlessHub;\n telemetry?: ServerTelemetry;\n onNotice?: (message: string) => void;\n /** Recorded sessions the server has not reopened. */\n dormantSessions?: () => readonly OpenSessionRecord[];\n}): HeadlessProtocol {\n const hub = options.hub;\n const dormantSessions = () => (options.dormantSessions === undefined ? [] : options.dormantSessions());\n const connections = new Map<string, Connection>();\n const threads = createThreadJournals({\n resolve: (sessionId, threadId) => hub.childThread(sessionId, threadId),\n });\n const host = createHost<Principal>({\n name: PO_SERVER_HOST,\n self: { connectionId: PO_SERVER_HOST },\n principalKey: (principal) => principal.connectionId,\n onError: (error) => options.onNotice?.(`headless protocol error (${harnessErrorMessage(error)})`),\n });\n const connectionOf = (principal: Principal): Connection & { connectionId: string } => {\n const connection = connections.get(principal.connectionId);\n if (connection === undefined) throw forbidden('This connection has closed.');\n return { ...connection, connectionId: principal.connectionId };\n };\n const reachable = (connection: Connection, sessionId: string): boolean =>\n permitsSession(hub, connection.mount, sessionId, (id) => connection.authorizeSession(id));\n\n // A Desktop claim makes every reference the connection holds to that session gone at once.\n const stopClaims = hub.computerUse?.subscribe?.(() => {\n for (const [connectionId, connection] of connections) {\n let revoked = false;\n for (const sessionId of connection.sessions) if (!connection.authorizeSession(sessionId)) revoked = true;\n if (!revoked) continue;\n connection.sessions.clear();\n void host.invalidatePrincipal((principal) => principal.connectionId === connectionId);\n }\n });\n\n host.serve(PoHubContract, (_input, principal, self) => {\n const connection = connectionOf(principal);\n const { mount } = connection;\n const visibleSessions = (): Record<string, HubSessionView> => {\n const views: Record<string, HubSessionView> = {};\n for (const session of hub.snapshot())\n if (reachable(connection, session.id)) views[session.id] = sessionView(session);\n // A dormant record of a removed workspace has no HTTP list to come from, so clients would never agree on it.\n const registered = new Set(hub.workspaces().map((workspace) => workspace.id));\n for (const record of dormantSessions())\n if (\n views[record.sessionId] === undefined &&\n registered.has(record.workspaceId) &&\n connection.authorizeSession(record.sessionId) &&\n permitsDormant(mount, record)\n )\n views[record.sessionId] = dormantView(record, hub.sessionPendingApprovalCount?.(record.sessionId));\n return views;\n };\n const visibleWorkspaces = (): Record<string, HubWorkspaceView> => {\n const views: Record<string, HubWorkspaceView> = {};\n for (const workspace of hub.workspaces())\n if (mount.scope === 'global' || workspace.id === mount.workspaceId)\n views[workspace.id] = {\n id: workspace.id,\n root: workspace.root,\n ...(workspace.kind === undefined ? {} : { kind: workspace.kind }),\n ...(workspace.name === undefined ? {} : { name: workspace.name }),\n ...(workspace.sandbox === undefined ? {} : { sandbox: workspace.sandbox }),\n ...(workspace.sandboxState === undefined ? {} : { sandboxState: workspace.sandboxState }),\n ...(workspace.sandboxReason === undefined ? {} : { sandboxReason: workspace.sandboxReason }),\n available: workspace.available !== false,\n };\n return views;\n };\n const sessions = self.state('sessions', chordSchema(Type.Record(Type.String(), SessionSummarySchema)), {\n init: visibleSessions,\n });\n const workspaces = self.state('workspaces', chordSchema(Type.Record(Type.String(), HubWorkspaceSchema)), {\n init: visibleWorkspaces,\n });\n const pending = self.state('pending', chordSchema(Type.Array(HubNoticeSchema)), [] as HubNotice[]);\n const visibleCompositions = (): Record<string, number> => {\n const revisions = hub.compositionRevisions?.() ?? {};\n if (mount.scope === 'global') return { ...revisions };\n const own = `workspace:${mount.workspaceId}`;\n return Object.fromEntries(Object.entries(revisions).filter(([key]) => key === 'global' || key === own));\n };\n const compositions = self.state('compositions', chordSchema(HubCompositionsSchema), { init: visibleCompositions });\n self.on('hub', eventsOf(hub), (event, ctx) => {\n switch (event.kind) {\n case 'upsert':\n case 'removed':\n case 'dormant_changed':\n // Recomputed rather than patched, so an event before this listener started cannot leave a stale row.\n sessions.replace(ctx, visibleSessions(), { diff: true });\n return;\n case 'workspace_upsert':\n case 'workspace_removed':\n workspaces.replace(ctx, visibleWorkspaces(), { diff: true });\n return;\n case 'compositions':\n compositions.replace(ctx, visibleCompositions(), { diff: true });\n return;\n case 'frame':\n if (!reachable(connection, event.sessionId)) return;\n pending.change(ctx, (draft) => {\n draft.push({\n id: randomUUID(),\n sessionId: event.sessionId,\n frame: event.frame as Record<string, JsonValue>,\n });\n if (draft.length > MAX_PENDING_NOTICES) draft.splice(0, draft.length - MAX_PENDING_NOTICES);\n });\n return;\n case 'channel':\n return;\n }\n });\n return {\n variant: 'default',\n sessions,\n workspaces,\n pending,\n compositions,\n readHome: async (request) => {\n if (!hub.readHome) throw new Error('Home read is unavailable.');\n return hub.readHome(request, (id) => reachable(connection, id));\n },\n invoke: async (call: PoPluginCall, ctx) => {\n if (call.mount.scope === 'session' && !connection.authorizeSession(call.mount.sessionId))\n throw forbidden('This session belongs to its Desktop instance.');\n if (mount.scope !== 'global') {\n const permitted =\n call.mount.scope === 'session'\n ? permitsSession(hub, mount, call.mount.sessionId)\n : mount.scope === 'workspace' &&\n call.mount.scope === 'workspace' &&\n call.mount.workspaceId === mount.workspaceId;\n if (!permitted) throw forbidden('Plugin is outside this WebSocket scope.');\n }\n return (await hub.invokePlugin(call, 'client-to-server', {\n connectionId: connection.connectionId,\n signal: ctx.signal,\n })) as JsonValue;\n },\n ackNotice: async ({ id }, ctx) => {\n pending.change(ctx, (draft) => draft.filter((notice) => notice.id !== id));\n },\n };\n });\n\n host.serve(PoHubRevisionsContract, (_input, principal, self) => {\n const { mount } = connectionOf(principal);\n const visibleRevisions = (): Record<string, number> => {\n const revisions = hub.revisions?.() ?? {};\n if (mount.scope === 'global') return { ...revisions };\n const own = `workspace:${mount.workspaceId}:`;\n return Object.fromEntries(\n Object.entries(revisions).filter(([topic]) => topic.startsWith('global:') || topic.startsWith(own)),\n );\n };\n const revisions = self.state('revisions', chordSchema(HubRevisionsSchema), { init: visibleRevisions });\n self.on('hub', eventsOf(hub), (event, ctx) => {\n if (event.kind === 'revisions') revisions.replace(ctx, visibleRevisions(), { diff: true });\n });\n return { variant: 'default', revisions };\n });\n\n host.serve(\n PoThreadContract,\n ({ sessionId, threadId }, principal, self) => {\n const connection = connectionOf(principal);\n if (!reachable(connection, sessionId)) throw forbidden(`No session ${sessionId}`);\n connection.sessions.add(sessionId);\n const tail = self.resource('tail', {\n version: 1,\n open: () => threads.subscribe(sessionId, threadId),\n close: () => threads.unsubscribe(sessionId, threadId),\n });\n const frame = self.state('frame', chordSchema(PoThreadFrameSchema), {\n init: () => (tail.value?.at(-1) ?? null) as never,\n });\n self.on(\n 'frames',\n { subscribe: (listener) => threads.onFrame(listener) } as Subscribable<{\n sessionId: string;\n threadId: string;\n frame: Record<string, unknown>;\n }>,\n (event, ctx) => {\n // Each frame is a fresh wrapper around the child's state, so only an explicit diff sends ops, not the whole state.\n if (event.sessionId === sessionId && event.threadId === threadId)\n frame.replace(ctx, event.frame as never, { diff: true });\n },\n );\n return { variant: 'default', frame };\n },\n { linger: THREAD_LINGER_MS },\n );\n\n host.serve(PoChannelsContract, ({ sessionId }, principal, self) => {\n const connection = connectionOf(principal);\n if (!reachable(connection, sessionId)) throw forbidden(`No session ${sessionId}`);\n connection.sessions.add(sessionId);\n const visible = (frameType: string): boolean =>\n frameType !== 'computer_use_state' || connection.authorizeComputerUse(sessionId);\n const latest = self.state('latest', chordSchema(PoChannelsStateSchema), {\n init: () => {\n const payloads: Record<string, JsonValue> = {};\n for (const channelFrame of hub.channelFrames(sessionId))\n if (visible(channelFrame.type)) payloads[channelFrame.type] = channelFrame.payload as JsonValue;\n return payloads;\n },\n });\n // ponytail: a channel keeps only its latest payload; a package that needs every event must carry a sequence.\n self.on('hub', eventsOf(hub), (event, ctx) => {\n if (event.kind !== 'channel' || event.sessionId !== sessionId || !visible(event.frameType)) return;\n if (event.connectionId !== undefined && event.connectionId !== connection.connectionId) return;\n latest.change(ctx, (draft) => {\n draft[event.frameType] = event.payload as JsonValue;\n });\n });\n return {\n variant: 'default',\n latest,\n receive: async ({ type, payload }) => {\n if (!connection.authorizeSession(sessionId)) throw forbidden('This session belongs to Desktop.');\n hub.receiveChannel(\n sessionId,\n type,\n payload,\n connection.connectionId,\n connection.authorizeDesktop(),\n connection.authorizeComputerUse(sessionId),\n );\n },\n };\n });\n\n const clearSessionBindings = serveAgentSessions(host, {\n resolve(sessionId, principal): AgentSessionBinding | undefined {\n const connection = connectionOf(principal as Principal);\n const session = hub.session(sessionId);\n if (!session || !reachable(connection, session.id)) return undefined;\n connection.sessions.add(sessionId);\n const permitted = () => hub.session(session.id)?.host === session.host && connection.authorizeSession(session.id);\n // A mirror of a session another host runs forwards there; keyed by its host object, never by session id.\n const forward = session.host.agentSession;\n if (forward !== undefined)\n return { generation: generationOf(session.host), exited: session.host.runtime.exited, permitted, forward };\n return {\n generation: generationOf(session.host),\n exited: session.host.runtime.exited,\n permitted,\n options: {\n runtime: session.host.runtime,\n onPresentationFrame: (listen) =>\n session.host.onPresentationFrame((frame) => {\n if (permitted()) listen(frame);\n }),\n respondToExtensionUi: (frame) => {\n if (!permitted()) throw forbidden('This session belongs to Desktop.');\n return session.host.respondToExtensionUi(frame);\n },\n readThreadTranscript: (threadId, request, readContext) => {\n if (!permitted()) throw forbidden('This session belongs to Desktop.');\n return threads.readPage(session.id, threadId, request, readContext);\n },\n sessionId: session.id,\n sessionName: session.name,\n cwd: session.cwd,\n telemetry: options.telemetry,\n },\n };\n },\n });\n\n let closing: Promise<void> | undefined;\n return {\n accept(link, access = {}) {\n if (closing !== undefined) {\n link.close();\n return;\n }\n const connectionId = randomUUID();\n const authorizeSession = access.authorizeSession ?? ((id: string) => !hub.computerUse?.ownsSession?.(id));\n const authorizeDesktop = access.authorizeDesktop ?? (() => false);\n connections.set(connectionId, {\n mount: access.mount ?? { scope: 'global' },\n authorizeSession,\n authorizeDesktop,\n authorizeComputerUse: access.authorizeComputerUse ?? (() => authorizeDesktop()),\n sessions: new Set(),\n });\n link.onClose(() => {\n connections.delete(connectionId);\n hub.disconnectChannels(connectionId);\n });\n host.accept(reportingLargeFrames(link, options.onNotice, options.telemetry), {\n principal: { connectionId },\n kind: 'client',\n });\n },\n close() {\n closing ??= (async () => {\n stopClaims?.();\n threads.close();\n clearSessionBindings();\n await host.close();\n })();\n return closing;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;AAmCA,MAAM,sBAAsB;;AAE5B,MAAM,mBAAmB;AAEzB,SAAS,YAAY,SAA6C;CAChE,OAAO;EACL,IAAI,QAAQ;EACZ,GAAI,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,YAAY;EAChF,GAAI,QAAQ,mBAAmB,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,QAAQ,eAAe,EAAE;EAChG,GAAI,QAAQ,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,QAAQ,kBAAkB,EAAE;EACzG,MAAM,QAAQ;EACd,KAAK,QAAQ;EACb,WAAW,QAAQ;EACnB,WAAW,QAAQ,aAAa,QAAQ;EACxC,OAAO,QAAQ,SAAS;EACxB,YAAY,QAAQ,cAAc,QAAQ;EAC1C,QAAQ;EACR,qBAAqB,QAAQ,uBAAuB;EACpD,cAAc,QAAQ,gBAAgB;EACtC,eAAe,QAAQ,iBAAiB;EACxC,GAAI,QAAQ,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,QAAQ,cAAc;EAEtF,GAAI,QAAQ,wBAAwB,OAAO,CAAC,IAAI,EAAE,sBAAsB,QAAQ,qBAAqB;EACrG,GAAI,QAAQ,QAAQ,KAAA,IAAY,CAAC,IAAI,EAAE,KAAK;GAAE,QAAQ,QAAQ,IAAI;GAAQ,OAAO,QAAQ,IAAI;EAAM,EAAE;EACrG,GAAI,QAAQ,YAAY,KAAA,IACpB,CAAC,IACD,EACE,SAAS;GACP,MAAM,QAAQ,QAAQ;GACtB,GAAI,QAAQ,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,QAAQ,YAAY;GAChG,GAAI,QAAQ,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,QAAQ,YAAY;EAClG,EACF;EACJ,GAAI,QAAQ,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,QAAQ,gBAAgB;EAC5F,GAAI,QAAQ,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,QAAQ,kBAAkB;EAClG,GAAI,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,YAAY;EAChF,GAAI,QAAQ,WAAW,KAAA,KAAa,QAAQ,OAAO,WAAW,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,QAAQ,MAAM,EAAE;EACrG,GAAI,QAAQ,kBAAkB,KAAA,IAC1B,CAAC,IACD,EACE,eAAe,QAAQ,cAAc,KAAK,WAAW;GACnD,IAAI,MAAM;GACV,MAAM,MAAM;GACZ,WAAW,MAAM;GACjB,GAAI,MAAM,QAAQ,KAAA,IAAY,CAAC,IAAI,EAAE,KAAK,MAAM,IAAI;GACpD,GAAI,MAAM,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,MAAM,UAAU;GACtE,GAAI,MAAM,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,OAAO;GAC7D,GAAI,MAAM,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,MAAM,UAAU;EACxE,EAAE,EACJ;EACJ,GAAI,QAAQ,aAAa,KAAA,IACrB,CAAC,IACD,EACE,UAAU;GACR,OAAO,QAAQ,SAAS;GACxB,GAAI,QAAQ,SAAS,cAAc,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;GACjE,GAAI,QAAQ,SAAS,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,SAAS,MAAM;EAClF,EACF;EACJ,GAAI,QAAQ,yBAAyB,KAAA,IAAY,CAAC,IAAI,EAAE,sBAAsB,QAAQ,qBAAqB;CAC7G;AACF;;;;;;;AAQA,SAAS,YAAY,QAA2B,sBAA+C;CAC7F,OAAO;EACL,IAAI,OAAO;EACX,aAAa,OAAO;EACpB,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,WAAW,OAAO;EAClB,WAAW,OAAO;EAClB,OAAO;EACP,YAAY,OAAO;EACnB,QAAQ;EACR,qBAAqB;EACrB,cAAc;EACd,eAAe;EACf,SAAS;EACT,GAAI,yBAAyB,KAAA,IAAY,CAAC,IAAI,EAAE,qBAAqB;EACrE,GAAI,OAAO,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,OAAO,gBAAgB;EAC1F,GAAI,OAAO,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,OAAO,kBAAkB;EAChG,GAAI,OAAO,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,OAAO,YAAY;EAC9E,GAAI,OAAO,WAAW,KAAA,KAAa,OAAO,OAAO,WAAW,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,OAAO,MAAM,EAAE;CACpG;AACF;;AAGA,MAAM,8BAAc,IAAI,QAAwB;AAChD,IAAI,iBAAiB;AACrB,SAAS,aAAa,MAAsB;CAC1C,IAAI,aAAa,YAAY,IAAI,IAAI;CACrC,IAAI,eAAe,KAAA,GAAW;EAC5B,aAAa;EACb,YAAY,IAAI,MAAM,UAAU;CAClC;CACA,OAAO;AACT;AAEA,SAAS,eACP,KACA,OACA,WACA,kBAA2C,MAClC;CACT,MAAM,UAAU,IAAI,QAAQ,SAAS;CACrC,OACE,YAAY,KAAA,KACZ,UAAU,SAAS,MAClB,MAAM,UAAU,YACd,QAAQ,gBAAgB,MAAM,gBAAgB,MAAM,UAAU,eAAe,MAAM,cAAc;AAExG;AAEA,SAAS,eAAe,OAAsB,QAAoC;CAChF,IAAI,MAAM,UAAU,UAAU,OAAO;CACrC,IAAI,OAAO,gBAAgB,MAAM,aAAa,OAAO;CACrD,OAAO,MAAM,UAAU,eAAe,MAAM,cAAc,OAAO;AACnE;AA0BA,MAAM,YAAY,SAAsD,EACtE,YAAY,aAAa,IAAI,QAAQ,QAAQ,EAC/C;;AAGA,SAAgB,uBAAuB,SAMlB;CACnB,MAAM,MAAM,QAAQ;CACpB,MAAM,wBAAyB,QAAQ,oBAAoB,KAAA,IAAY,CAAC,IAAI,QAAQ,gBAAgB;CACpG,MAAM,8BAAc,IAAI,IAAwB;CAChD,MAAM,UAAU,qBAAqB,EACnC,UAAU,WAAW,aAAa,IAAI,YAAY,WAAW,QAAQ,EACvE,CAAC;CACD,MAAM,OAAO,WAAsB;EACjC,MAAM;EACN,MAAM,EAAE,cAAc,eAAe;EACrC,eAAe,cAAc,UAAU;EACvC,UAAU,UAAU,QAAQ,WAAW,4BAA4B,oBAAoB,KAAK,EAAE,EAAE;CAClG,CAAC;CACD,MAAM,gBAAgB,cAAgE;EACpF,MAAM,aAAa,YAAY,IAAI,UAAU,YAAY;EACzD,IAAI,eAAe,KAAA,GAAW,MAAM,UAAU,6BAA6B;EAC3E,OAAO;GAAE,GAAG;GAAY,cAAc,UAAU;EAAa;CAC/D;CACA,MAAM,aAAa,YAAwB,cACzC,eAAe,KAAK,WAAW,OAAO,YAAY,OAAO,WAAW,iBAAiB,EAAE,CAAC;CAG1F,MAAM,aAAa,IAAI,aAAa,kBAAkB;EACpD,KAAK,MAAM,CAAC,cAAc,eAAe,aAAa;GACpD,IAAI,UAAU;GACd,KAAK,MAAM,aAAa,WAAW,UAAU,IAAI,CAAC,WAAW,iBAAiB,SAAS,GAAG,UAAU;GACpG,IAAI,CAAC,SAAS;GACd,WAAW,SAAS,MAAM;GAC1B,KAAU,qBAAqB,cAAc,UAAU,iBAAiB,YAAY;EACtF;CACF,CAAC;CAED,KAAK,MAAM,gBAAgB,QAAQ,WAAW,SAAS;EACrD,MAAM,aAAa,aAAa,SAAS;EACzC,MAAM,EAAE,UAAU;EAClB,MAAM,wBAAwD;GAC5D,MAAM,QAAwC,CAAC;GAC/C,KAAK,MAAM,WAAW,IAAI,SAAS,GACjC,IAAI,UAAU,YAAY,QAAQ,EAAE,GAAG,MAAM,QAAQ,MAAM,YAAY,OAAO;GAEhF,MAAM,aAAa,IAAI,IAAI,IAAI,WAAW,CAAC,CAAC,KAAK,cAAc,UAAU,EAAE,CAAC;GAC5E,KAAK,MAAM,UAAU,gBAAgB,GACnC,IACE,MAAM,OAAO,eAAe,KAAA,KAC5B,WAAW,IAAI,OAAO,WAAW,KACjC,WAAW,iBAAiB,OAAO,SAAS,KAC5C,eAAe,OAAO,MAAM,GAE5B,MAAM,OAAO,aAAa,YAAY,QAAQ,IAAI,8BAA8B,OAAO,SAAS,CAAC;GACrG,OAAO;EACT;EACA,MAAM,0BAA4D;GAChE,MAAM,QAA0C,CAAC;GACjD,KAAK,MAAM,aAAa,IAAI,WAAW,GACrC,IAAI,MAAM,UAAU,YAAY,UAAU,OAAO,MAAM,aACrD,MAAM,UAAU,MAAM;IACpB,IAAI,UAAU;IACd,MAAM,UAAU;IAChB,GAAI,UAAU,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,UAAU,KAAK;IAC/D,GAAI,UAAU,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,UAAU,KAAK;IAC/D,GAAI,UAAU,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,UAAU,QAAQ;IACxE,GAAI,UAAU,iBAAiB,KAAA,IAAY,CAAC,IAAI,EAAE,cAAc,UAAU,aAAa;IACvF,GAAI,UAAU,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,UAAU,cAAc;IAC1F,WAAW,UAAU,cAAc;GACrC;GACJ,OAAO;EACT;EACA,MAAM,WAAW,KAAK,MAAM,YAAY,YAAY,KAAK,OAAO,KAAK,OAAO,GAAG,oBAAoB,CAAC,GAAG,EACrG,MAAM,gBACR,CAAC;EACD,MAAM,aAAa,KAAK,MAAM,cAAc,YAAY,KAAK,OAAO,KAAK,OAAO,GAAG,kBAAkB,CAAC,GAAG,EACvG,MAAM,kBACR,CAAC;EACD,MAAM,UAAU,KAAK,MAAM,WAAW,YAAY,KAAK,MAAM,eAAe,CAAC,GAAG,CAAC,CAAgB;EACjG,MAAM,4BAAoD;GACxD,MAAM,YAAY,IAAI,uBAAuB,KAAK,CAAC;GACnD,IAAI,MAAM,UAAU,UAAU,OAAO,EAAE,GAAG,UAAU;GACpD,MAAM,MAAM,aAAa,MAAM;GAC/B,OAAO,OAAO,YAAY,OAAO,QAAQ,SAAS,CAAC,CAAC,QAAQ,CAAC,SAAS,QAAQ,YAAY,QAAQ,GAAG,CAAC;EACxG;EACA,MAAM,eAAe,KAAK,MAAM,gBAAgB,YAAY,qBAAqB,GAAG,EAAE,MAAM,oBAAoB,CAAC;EACjH,KAAK,GAAG,OAAO,SAAS,GAAG,IAAI,OAAO,QAAQ;GAC5C,QAAQ,MAAM,MAAd;IACE,KAAK;IACL,KAAK;IACL,KAAK;KAEH,SAAS,QAAQ,KAAK,gBAAgB,GAAG,EAAE,MAAM,KAAK,CAAC;KACvD;IACF,KAAK;IACL,KAAK;KACH,WAAW,QAAQ,KAAK,kBAAkB,GAAG,EAAE,MAAM,KAAK,CAAC;KAC3D;IACF,KAAK;KACH,aAAa,QAAQ,KAAK,oBAAoB,GAAG,EAAE,MAAM,KAAK,CAAC;KAC/D;IACF,KAAK;KACH,IAAI,CAAC,UAAU,YAAY,MAAM,SAAS,GAAG;KAC7C,QAAQ,OAAO,MAAM,UAAU;MAC7B,MAAM,KAAK;OACT,IAAI,WAAW;OACf,WAAW,MAAM;OACjB,OAAO,MAAM;MACf,CAAC;MACD,IAAI,MAAM,SAAS,qBAAqB,MAAM,OAAO,GAAG,MAAM,SAAS,mBAAmB;KAC5F,CAAC;KACD;IACF,KAAK,WACH;GACJ;EACF,CAAC;EACD,OAAO;GACL,SAAS;GACT;GACA;GACA;GACA;GACA,UAAU,OAAO,YAAY;IAC3B,IAAI,CAAC,IAAI,UAAU,MAAM,IAAI,MAAM,2BAA2B;IAC9D,OAAO,IAAI,SAAS,UAAU,OAAO,UAAU,YAAY,EAAE,CAAC;GAChE;GACA,QAAQ,OAAO,MAAoB,QAAQ;IACzC,IAAI,KAAK,MAAM,UAAU,aAAa,CAAC,WAAW,iBAAiB,KAAK,MAAM,SAAS,GACrF,MAAM,UAAU,+CAA+C;IACjE,IAAI,MAAM,UAAU,UAOd;SAAA,EALF,KAAK,MAAM,UAAU,YACjB,eAAe,KAAK,OAAO,KAAK,MAAM,SAAS,IAC/C,MAAM,UAAU,eAChB,KAAK,MAAM,UAAU,eACrB,KAAK,MAAM,gBAAgB,MAAM,cACvB,MAAM,UAAU,yCAAyC;IAAA;IAE3E,OAAQ,MAAM,IAAI,aAAa,MAAM,oBAAoB;KACvD,cAAc,WAAW;KACzB,QAAQ,IAAI;IACd,CAAC;GACH;GACA,WAAW,OAAO,EAAE,MAAM,QAAQ;IAChC,QAAQ,OAAO,MAAM,UAAU,MAAM,QAAQ,WAAW,OAAO,OAAO,EAAE,CAAC;GAC3E;EACF;CACF,CAAC;CAED,KAAK,MAAM,yBAAyB,QAAQ,WAAW,SAAS;EAC9D,MAAM,EAAE,UAAU,aAAa,SAAS;EACxC,MAAM,yBAAiD;GACrD,MAAM,YAAY,IAAI,YAAY,KAAK,CAAC;GACxC,IAAI,MAAM,UAAU,UAAU,OAAO,EAAE,GAAG,UAAU;GACpD,MAAM,MAAM,aAAa,MAAM,YAAY;GAC3C,OAAO,OAAO,YACZ,OAAO,QAAQ,SAAS,CAAC,CAAC,QAAQ,CAAC,WAAW,MAAM,WAAW,SAAS,KAAK,MAAM,WAAW,GAAG,CAAC,CACpG;EACF;EACA,MAAM,YAAY,KAAK,MAAM,aAAa,YAAY,kBAAkB,GAAG,EAAE,MAAM,iBAAiB,CAAC;EACrG,KAAK,GAAG,OAAO,SAAS,GAAG,IAAI,OAAO,QAAQ;GAC5C,IAAI,MAAM,SAAS,aAAa,UAAU,QAAQ,KAAK,iBAAiB,GAAG,EAAE,MAAM,KAAK,CAAC;EAC3F,CAAC;EACD,OAAO;GAAE,SAAS;GAAW;EAAU;CACzC,CAAC;CAED,KAAK,MACH,mBACC,EAAE,WAAW,YAAY,WAAW,SAAS;EAC5C,MAAM,aAAa,aAAa,SAAS;EACzC,IAAI,CAAC,UAAU,YAAY,SAAS,GAAG,MAAM,UAAU,cAAc,WAAW;EAChF,WAAW,SAAS,IAAI,SAAS;EACjC,MAAM,OAAO,KAAK,SAAS,QAAQ;GACjC,SAAS;GACT,YAAY,QAAQ,UAAU,WAAW,QAAQ;GACjD,aAAa,QAAQ,YAAY,WAAW,QAAQ;EACtD,CAAC;EACD,MAAM,QAAQ,KAAK,MAAM,SAAS,YAAY,mBAAmB,GAAG,EAClE,YAAa,KAAK,OAAO,GAAG,EAAE,KAAK,KACrC,CAAC;EACD,KAAK,GACH,UACA,EAAE,YAAY,aAAa,QAAQ,QAAQ,QAAQ,EAAE,IAKpD,OAAO,QAAQ;GAEd,IAAI,MAAM,cAAc,aAAa,MAAM,aAAa,UACtD,MAAM,QAAQ,KAAK,MAAM,OAAgB,EAAE,MAAM,KAAK,CAAC;EAC3D,CACF;EACA,OAAO;GAAE,SAAS;GAAW;EAAM;CACrC,GACA,EAAE,QAAQ,iBAAiB,CAC7B;CAEA,KAAK,MAAM,qBAAqB,EAAE,aAAa,WAAW,SAAS;EACjE,MAAM,aAAa,aAAa,SAAS;EACzC,IAAI,CAAC,UAAU,YAAY,SAAS,GAAG,MAAM,UAAU,cAAc,WAAW;EAChF,WAAW,SAAS,IAAI,SAAS;EACjC,MAAM,WAAW,cACf,cAAc,wBAAwB,WAAW,qBAAqB,SAAS;EACjF,MAAM,SAAS,KAAK,MAAM,UAAU,YAAY,qBAAqB,GAAG,EACtE,YAAY;GACV,MAAM,WAAsC,CAAC;GAC7C,KAAK,MAAM,gBAAgB,IAAI,cAAc,SAAS,GACpD,IAAI,QAAQ,aAAa,IAAI,GAAG,SAAS,aAAa,QAAQ,aAAa;GAC7E,OAAO;EACT,EACF,CAAC;EAED,KAAK,GAAG,OAAO,SAAS,GAAG,IAAI,OAAO,QAAQ;GAC5C,IAAI,MAAM,SAAS,aAAa,MAAM,cAAc,aAAa,CAAC,QAAQ,MAAM,SAAS,GAAG;GAC5F,IAAI,MAAM,iBAAiB,KAAA,KAAa,MAAM,iBAAiB,WAAW,cAAc;GACxF,OAAO,OAAO,MAAM,UAAU;IAC5B,MAAM,MAAM,aAAa,MAAM;GACjC,CAAC;EACH,CAAC;EACD,OAAO;GACL,SAAS;GACT;GACA,SAAS,OAAO,EAAE,MAAM,cAAc;IACpC,IAAI,CAAC,WAAW,iBAAiB,SAAS,GAAG,MAAM,UAAU,kCAAkC;IAC/F,IAAI,eACF,WACA,MACA,SACA,WAAW,cACX,WAAW,iBAAiB,GAC5B,WAAW,qBAAqB,SAAS,CAC3C;GACF;EACF;CACF,CAAC;CAED,MAAM,uBAAuB,mBAAmB,MAAM,EACpD,QAAQ,WAAW,WAA4C;EAC7D,MAAM,aAAa,aAAa,SAAsB;EACtD,MAAM,UAAU,IAAI,QAAQ,SAAS;EACrC,IAAI,CAAC,WAAW,CAAC,UAAU,YAAY,QAAQ,EAAE,GAAG,OAAO,KAAA;EAC3D,WAAW,SAAS,IAAI,SAAS;EACjC,MAAM,kBAAkB,IAAI,QAAQ,QAAQ,EAAE,CAAC,EAAE,SAAS,QAAQ,QAAQ,WAAW,iBAAiB,QAAQ,EAAE;EAEhH,MAAM,UAAU,QAAQ,KAAK;EAC7B,IAAI,YAAY,KAAA,GACd,OAAO;GAAE,YAAY,aAAa,QAAQ,IAAI;GAAG,QAAQ,QAAQ,KAAK,QAAQ;GAAQ;GAAW;EAAQ;EAC3G,OAAO;GACL,YAAY,aAAa,QAAQ,IAAI;GACrC,QAAQ,QAAQ,KAAK,QAAQ;GAC7B;GACA,SAAS;IACP,SAAS,QAAQ,KAAK;IACtB,sBAAsB,WACpB,QAAQ,KAAK,qBAAqB,UAAU;KAC1C,IAAI,UAAU,GAAG,OAAO,KAAK;IAC/B,CAAC;IACH,uBAAuB,UAAU;KAC/B,IAAI,CAAC,UAAU,GAAG,MAAM,UAAU,kCAAkC;KACpE,OAAO,QAAQ,KAAK,qBAAqB,KAAK;IAChD;IACA,uBAAuB,UAAU,SAAS,gBAAgB;KACxD,IAAI,CAAC,UAAU,GAAG,MAAM,UAAU,kCAAkC;KACpE,OAAO,QAAQ,SAAS,QAAQ,IAAI,UAAU,SAAS,WAAW;IACpE;IACA,WAAW,QAAQ;IACnB,aAAa,QAAQ;IACrB,KAAK,QAAQ;IACb,WAAW,QAAQ;GACrB;EACF;CACF,EACF,CAAC;CAED,IAAI;CACJ,OAAO;EACL,OAAO,MAAM,SAAS,CAAC,GAAG;GACxB,IAAI,YAAY,KAAA,GAAW;IACzB,KAAK,MAAM;IACX;GACF;GACA,MAAM,eAAe,WAAW;GAChC,MAAM,mBAAmB,OAAO,sBAAsB,OAAe,CAAC,IAAI,aAAa,cAAc,EAAE;GACvG,MAAM,mBAAmB,OAAO,2BAA2B;GAC3D,YAAY,IAAI,cAAc;IAC5B,OAAO,OAAO,SAAS,EAAE,OAAO,SAAS;IACzC;IACA;IACA,sBAAsB,OAAO,+BAA+B,iBAAiB;IAC7E,0BAAU,IAAI,IAAI;GACpB,CAAC;GACD,KAAK,cAAc;IACjB,YAAY,OAAO,YAAY;IAC/B,IAAI,mBAAmB,YAAY;GACrC,CAAC;GACD,KAAK,OAAO,qBAAqB,MAAM,QAAQ,UAAU,QAAQ,SAAS,GAAG;IAC3E,WAAW,EAAE,aAAa;IAC1B,MAAM;GACR,CAAC;EACH;EACA,QAAQ;GACN,aAAa,YAAY;IACvB,aAAa;IACb,QAAQ,MAAM;IACd,qBAAqB;IACrB,MAAM,KAAK,MAAM;GACnB,EAAA,CAAG;GACH,OAAO;EACT;CACF;AACF"}
|