agl 40.5.1 → 41.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +43 -0
- package/dist_serve/bundle.js +3514 -3357
- package/dist_serve/bundle.js.map +2 -2
- package/dist_serve/bundle.js.third-party-notices.json +58 -32
- package/dist_serve/bundle.js.third-party-notices.txt +108 -33
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/aglapi/aglapisurface.document.js +64 -37
- package/dist_ts/classes.aglhome.d.ts +5 -0
- package/dist_ts/classes.aglhome.js +2 -1
- package/dist_ts/classes.authstore.js +5 -1
- package/dist_ts/classes.controller.d.ts +8 -0
- package/dist_ts/classes.controller.js +119 -22
- package/dist_ts/classes.controllereventdelivery.d.ts +72 -0
- package/dist_ts/classes.controllereventdelivery.js +233 -0
- package/dist_ts/classes.flexmodels.public.js +4 -1
- package/dist_ts/classes.flexprojectionreader.d.ts +6 -0
- package/dist_ts/classes.flexprojectionreader.js +29 -5
- package/dist_ts/classes.flexservice.d.ts +2 -1
- package/dist_ts/classes.flexservice.js +34 -6
- package/dist_ts/classes.flexstore.d.ts +41 -4
- package/dist_ts/classes.flexstore.js +266 -203
- package/dist_ts/classes.inferencegateway.d.ts +35 -1
- package/dist_ts/classes.inferencegateway.js +86 -26
- package/dist_ts/classes.inferenceservice.d.ts +4 -2
- package/dist_ts/classes.inferenceservice.js +5 -4
- package/dist_ts/classes.proxycontrol.d.ts +58 -4
- package/dist_ts/classes.proxycontrol.js +23 -44
- package/dist_ts/classes.proxycontrolclient.d.ts +15 -5
- package/dist_ts/classes.proxycontrolclient.js +67 -17
- package/dist_ts/classes.proxydaemon.d.ts +22 -3
- package/dist_ts/classes.proxydaemon.js +73 -12
- package/dist_ts/classes.proxyleaseholder.d.ts +43 -14
- package/dist_ts/classes.proxyleaseholder.js +66 -22
- package/dist_ts/classes.proxystore.d.ts +9 -0
- package/dist_ts/classes.proxystore.js +15 -7
- package/dist_ts/classes.ticketnotifier.js +4 -2
- package/dist_ts/classes.ticketstore.d.ts +50 -2
- package/dist_ts/classes.ticketstore.js +195 -78
- package/dist_ts/classes.workercallerbindings.d.ts +66 -0
- package/dist_ts/classes.workercallerbindings.js +211 -0
- package/dist_ts/classes.workercallers.d.ts +63 -2
- package/dist_ts/classes.workercallers.js +430 -65
- package/dist_ts/driver/classes.drivereventrelay.d.ts +13 -1
- package/dist_ts/driver/classes.drivereventrelay.js +99 -6
- package/dist_ts/driver/functions.driverinstructions.d.ts +1 -1
- package/dist_ts/driver/functions.driverinstructions.js +1 -1
- package/dist_ts/driver/functions.drivertools.d.ts +11 -2
- package/dist_ts/driver/functions.drivertools.js +19 -9
- package/dist_ts/fleet/classes.boardpump.d.ts +8 -2
- package/dist_ts/fleet/classes.boardpump.js +38 -20
- package/dist_ts/fleet/classes.ticketeffects.d.ts +17 -2
- package/dist_ts/fleet/classes.ticketeffects.js +16 -10
- package/dist_ts/fleet/classes.workerlaunches.d.ts +12 -5
- package/dist_ts/fleet/classes.workerlaunches.js +25 -19
- package/dist_ts/fleet/classes.workers.d.ts +21 -0
- package/dist_ts/fleet/classes.workers.js +110 -17
- package/dist_ts/fleet/functions.workervalidation.js +2 -2
- package/dist_ts/functions.flexprivatesnapshot.d.ts +102 -0
- package/dist_ts/functions.flexprivatesnapshot.js +461 -0
- package/dist_ts/functions.inferencecli.d.ts +3 -2
- package/dist_ts/functions.inferencecli.js +67 -5
- package/dist_ts/functions.inferencecliarguments.d.ts +6 -2
- package/dist_ts/functions.inferencecliarguments.js +29 -2
- package/dist_ts/functions.inferencelaunch.d.ts +24 -0
- package/dist_ts/functions.inferencelaunch.js +42 -2
- package/dist_ts/functions.mcptickettools.d.ts +3 -0
- package/dist_ts/functions.mcptickettools.js +2 -2
- package/dist_ts/functions.proxycontract.d.ts +11 -0
- package/dist_ts/functions.proxycontract.js +12 -1
- package/dist_ts/functions.proxysocket.d.ts +6 -0
- package/dist_ts/functions.proxysocket.js +46 -0
- package/dist_ts/functions.ticketcli.d.ts +1 -1
- package/dist_ts/functions.ticketcli.js +8 -4
- package/dist_ts/functions.ticketvalidation.d.ts +3 -0
- package/dist_ts/functions.ticketvalidation.js +7 -4
- package/dist_ts/functions.workerprocessproof.d.ts +6 -0
- package/dist_ts/functions.workerprocessproof.js +28 -4
- package/dist_ts/interfaces.flexipc.d.ts +21 -2
- package/dist_ts/interfaces.flexipc.js +33 -16
- package/dist_ts_interfaces/fleetworkers.d.ts +6 -0
- package/dist_ts_interfaces/interfaces.d.ts +1 -1
- package/dist_ts_interfaces/interfaces.js +1 -1
- package/dist_ts_interfaces/requests.tickets.d.ts +8 -12
- package/dist_ts_interfaces/tickets.d.ts +37 -9
- package/dist_ts_interfaces/tickets.js +7 -1
- package/dist_ts_interfaces/workercallers.d.ts +43 -4
- package/package.json +7 -7
- package/readme.md +156 -23
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/aglapi/aglapisurface.document.ts +63 -36
- package/ts/classes.aglhome.ts +6 -0
- package/ts/classes.authstore.ts +4 -0
- package/ts/classes.controller.ts +141 -32
- package/ts/classes.controllereventdelivery.ts +289 -0
- package/ts/classes.flexmodels.public.ts +10 -0
- package/ts/classes.flexprojectionreader.ts +30 -3
- package/ts/classes.flexservice.ts +33 -5
- package/ts/classes.flexstore.ts +381 -246
- package/ts/classes.inferencegateway.ts +104 -23
- package/ts/classes.inferenceservice.ts +6 -3
- package/ts/classes.proxycontrol.ts +76 -39
- package/ts/classes.proxycontrolclient.ts +72 -20
- package/ts/classes.proxydaemon.ts +85 -15
- package/ts/classes.proxyleaseholder.ts +84 -28
- package/ts/classes.proxystore.ts +16 -5
- package/ts/classes.ticketnotifier.ts +3 -1
- package/ts/classes.ticketstore.ts +201 -75
- package/ts/classes.workercallerbindings.ts +147 -0
- package/ts/classes.workercallers.ts +410 -59
- package/ts/driver/classes.drivereventrelay.ts +89 -4
- package/ts/driver/functions.driverinstructions.ts +1 -1
- package/ts/driver/functions.drivertools.ts +22 -8
- package/ts/fleet/classes.boardpump.ts +51 -19
- package/ts/fleet/classes.ticketeffects.ts +25 -11
- package/ts/fleet/classes.workerlaunches.ts +23 -15
- package/ts/fleet/classes.workers.ts +79 -17
- package/ts/fleet/functions.workervalidation.ts +1 -1
- package/ts/functions.flexprivatesnapshot.ts +601 -0
- package/ts/functions.inferencecli.ts +61 -7
- package/ts/functions.inferencecliarguments.ts +32 -1
- package/ts/functions.inferencelaunch.ts +49 -2
- package/ts/functions.mcptickettools.ts +1 -1
- package/ts/functions.proxycontract.ts +12 -0
- package/ts/functions.proxysocket.ts +39 -0
- package/ts/functions.ticketcli.ts +7 -3
- package/ts/functions.ticketvalidation.ts +7 -3
- package/ts/functions.workerprocessproof.ts +27 -4
- package/ts/interfaces.flexipc.ts +50 -21
- package/ts_interfaces/fleetworkers.ts +6 -0
- package/ts_interfaces/interfaces.ts +1 -1
- package/ts_interfaces/requests.tickets.ts +9 -6
- package/ts_interfaces/tickets.ts +32 -1
- package/ts_interfaces/workercallers.ts +32 -4
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements.harnesscontrollerapp.ts +19 -8
- package/ts_web/elements.ticketboard.ts +16 -4
- package/ts_web/settings.general.ts +10 -4
|
@@ -1408,8 +1408,8 @@ export const AGL_API_SURFACE: plugins.flexTypedRequest.IFlexTypedRequestSurface
|
|
|
1408
1408
|
{
|
|
1409
1409
|
"method": "agl.mcp.ticket.get",
|
|
1410
1410
|
"path": "agl.agl_mcp_ticket_get",
|
|
1411
|
-
"summary": "Reads a ticket by its `AGL-<n>` key
|
|
1412
|
-
"description": "Reads a ticket by its `AGL-<n>` key
|
|
1411
|
+
"summary": "Reads a ticket by its `AGL-<n>` key with its source, links, all its questions and their answers, and the newest page of…",
|
|
1412
|
+
"description": "Reads a ticket by its `AGL-<n>` key with its source, links, all its questions and their answers,\nand the newest page of its history (up to `limit` entries, default 50, at most 500, within 256 KiB), oldest first: the\nactivity entries and the Markdown comments they name, a `commented` entry naming its comment by\nid. `historyBefore` is present while older history exists; pass it as `before` for the next page.\n`commentId` reads that one comment instead (`comments: [it]`, `activity: []`), without `before` or `limit`.",
|
|
1413
1413
|
"omitted": [
|
|
1414
1414
|
"ownerToken"
|
|
1415
1415
|
],
|
|
@@ -1419,6 +1419,18 @@ export const AGL_API_SURFACE: plugins.flexTypedRequest.IFlexTypedRequestSurface
|
|
|
1419
1419
|
"properties": {
|
|
1420
1420
|
"ticketId": {
|
|
1421
1421
|
"type": "string"
|
|
1422
|
+
},
|
|
1423
|
+
"before": {
|
|
1424
|
+
"type": "string",
|
|
1425
|
+
"description": "An activity id, as `historyBefore` returned it: the page holds only older entries."
|
|
1426
|
+
},
|
|
1427
|
+
"limit": {
|
|
1428
|
+
"type": "number",
|
|
1429
|
+
"description": "Entries on the page, 1 to 500 (`ticketHistoryPage.maximum`); 50 (`ticketHistoryPage.default`) when absent."
|
|
1430
|
+
},
|
|
1431
|
+
"commentId": {
|
|
1432
|
+
"type": "string",
|
|
1433
|
+
"description": "One comment of this ticket, by the id an activity entry or a fleet event names: the response holds the ticket, its questions and that comment alone (`comments: [it]`, `activity: []`, no `historyBefore`). Excludes `before` and `limit`."
|
|
1422
1434
|
}
|
|
1423
1435
|
},
|
|
1424
1436
|
"required": [
|
|
@@ -1426,39 +1438,9 @@ export const AGL_API_SURFACE: plugins.flexTypedRequest.IFlexTypedRequestSurface
|
|
|
1426
1438
|
]
|
|
1427
1439
|
},
|
|
1428
1440
|
"outputSchema": {
|
|
1429
|
-
"
|
|
1430
|
-
"properties": {
|
|
1431
|
-
"ticket": {
|
|
1432
|
-
"$ref": "#/$defs/ITicket"
|
|
1433
|
-
},
|
|
1434
|
-
"comments": {
|
|
1435
|
-
"type": "array",
|
|
1436
|
-
"items": {
|
|
1437
|
-
"$ref": "#/$defs/ITicketComment"
|
|
1438
|
-
}
|
|
1439
|
-
},
|
|
1440
|
-
"activity": {
|
|
1441
|
-
"type": "array",
|
|
1442
|
-
"items": {
|
|
1443
|
-
"$ref": "#/$defs/ITicketActivity"
|
|
1444
|
-
}
|
|
1445
|
-
},
|
|
1446
|
-
"questions": {
|
|
1447
|
-
"type": "array",
|
|
1448
|
-
"items": {
|
|
1449
|
-
"$ref": "#/$defs/ITicketQuestion"
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
},
|
|
1453
|
-
"required": [
|
|
1454
|
-
"ticket",
|
|
1455
|
-
"comments",
|
|
1456
|
-
"activity",
|
|
1457
|
-
"questions"
|
|
1458
|
-
],
|
|
1459
|
-
"additionalProperties": false
|
|
1441
|
+
"$ref": "#/$defs/ITicketDetail"
|
|
1460
1442
|
},
|
|
1461
|
-
"declaration": "/**\n * Reads a ticket by its `AGL-<n>` key
|
|
1443
|
+
"declaration": "/**\n * Reads a ticket by its `AGL-<n>` key with its source, links, all its questions and their answers,\n * and the newest page of its history (up to `limit` entries, default 50, at most 500, within 256 KiB), oldest first: the\n * activity entries and the Markdown comments they name, a `commented` entry naming its comment by\n * id. `historyBefore` is present while older history exists; pass it as `before` for the next page.\n * `commentId` reads that one comment instead (`comments: [it]`, `activity: []`), without `before` or `limit`.\n */\nfunction agl_mcp_ticket_get(params: ITicketGet): Promise<ITicketDetail>;"
|
|
1462
1444
|
},
|
|
1463
1445
|
{
|
|
1464
1446
|
"method": "agl.mcp.ticket.link",
|
|
@@ -3783,7 +3765,7 @@ export const AGL_API_SURFACE: plugins.flexTypedRequest.IFlexTypedRequestSurface
|
|
|
3783
3765
|
},
|
|
3784
3766
|
"protocolVersion": {
|
|
3785
3767
|
"type": "number",
|
|
3786
|
-
"const":
|
|
3768
|
+
"const": 46
|
|
3787
3769
|
},
|
|
3788
3770
|
"upgradeManagementVersion": {
|
|
3789
3771
|
"type": "number"
|
|
@@ -3905,7 +3887,7 @@ export const AGL_API_SURFACE: plugins.flexTypedRequest.IFlexTypedRequestSurface
|
|
|
3905
3887
|
],
|
|
3906
3888
|
"additionalProperties": false
|
|
3907
3889
|
},
|
|
3908
|
-
"declaration": "interface IControllerStatus {\n packageName: string;\n packageVersion: string;\n protocolVersion:
|
|
3890
|
+
"declaration": "interface IControllerStatus {\n packageName: string;\n packageVersion: string;\n protocolVersion: 46;\n upgradeManagementVersion: number;\n controllerPid: number;\n processGroupId: number;\n processFingerprint: string;\n processMode: TControllerProcessMode;\n lifecycleState: TControllerLifecycleState;\n startedAt: number;\n setupRequired: boolean;\n /** Present when the controller runs as the systemd user unit (`agl service install`); absent for a detached or foreground one. */\n serviceUnit?: \"agl-controller.service\";\n /** The TLS mode of the runtime configuration the controller runs with; absent until it is resolved. */\n tlsMode?: TControllerTlsMode;\n upgrade?: IControllerUpgradeStatus;\n /** AGL's inference proxy, by state only; details need a signed-in owner (`controller.proxy.status.get`). */\n proxy?: { state: TControllerProxyState };\n harnesses: Array<{\n harnessId: TControllerSessionHarnessId;\n pid?: number;\n state: TControllerHarnessLifecycleState;\n healthy: boolean;\n version?: string;\n supportsLocalAttachments?: boolean;\n connectionMode?: 'local' | 'shared' | 'remote';\n diagnostic?: IControllerCodexDiagnostic;\n /** Codex only: automatic reconnection of this entry's profile to the local shared app-server. */\n rejoin?: IControllerCodexRejoinStatus;\n /**\n * Codex only, on the controller status: every connected or required profile. The entry's\n * `healthy` is then true only when each of them is, apart from a profile on an account Codex\n * cannot run on now, listed `stopped` with an `account_unavailable` diagnostic that says why;\n * its other members describe the default profile.\n */\n profiles?: IControllerCodexProfileStatus[];\n }>;\n}"
|
|
3909
3891
|
},
|
|
3910
3892
|
{
|
|
3911
3893
|
"name": "IControllerTerminalResource",
|
|
@@ -4743,10 +4725,55 @@ export const AGL_API_SURFACE: plugins.flexTypedRequest.IFlexTypedRequestSurface
|
|
|
4743
4725
|
"name": "ITicketCreate",
|
|
4744
4726
|
"declaration": "interface ITicketCreate {\n project: string;\n kind?: TTicketKind;\n title: string;\n description?: string;\n columnId?: TTicketColumn;\n parentId?: string;\n priority?: TTicketPriority;\n assignee?: ITicketPerson;\n labels?: string[];\n sourceText?: string;\n attachments?: ITicketAttachment[];\n}"
|
|
4745
4727
|
},
|
|
4728
|
+
{
|
|
4729
|
+
"name": "ITicketDetail",
|
|
4730
|
+
"schema": {
|
|
4731
|
+
"type": "object",
|
|
4732
|
+
"properties": {
|
|
4733
|
+
"ticket": {
|
|
4734
|
+
"$ref": "#/$defs/ITicket"
|
|
4735
|
+
},
|
|
4736
|
+
"comments": {
|
|
4737
|
+
"type": "array",
|
|
4738
|
+
"items": {
|
|
4739
|
+
"$ref": "#/$defs/ITicketComment"
|
|
4740
|
+
}
|
|
4741
|
+
},
|
|
4742
|
+
"activity": {
|
|
4743
|
+
"type": "array",
|
|
4744
|
+
"items": {
|
|
4745
|
+
"$ref": "#/$defs/ITicketActivity"
|
|
4746
|
+
}
|
|
4747
|
+
},
|
|
4748
|
+
"questions": {
|
|
4749
|
+
"type": "array",
|
|
4750
|
+
"items": {
|
|
4751
|
+
"$ref": "#/$defs/ITicketQuestion"
|
|
4752
|
+
}
|
|
4753
|
+
},
|
|
4754
|
+
"historyBefore": {
|
|
4755
|
+
"type": "string"
|
|
4756
|
+
}
|
|
4757
|
+
},
|
|
4758
|
+
"required": [
|
|
4759
|
+
"ticket",
|
|
4760
|
+
"comments",
|
|
4761
|
+
"activity",
|
|
4762
|
+
"questions"
|
|
4763
|
+
],
|
|
4764
|
+
"additionalProperties": false,
|
|
4765
|
+
"description": "A ticket, all its questions and one page of its history, oldest first. `activity` is the page; `comments` are the comments its `commented` entries name, whose `changes.comment` holds only `{ after: { id } }` here (the stored entry keeps the whole comment). `historyBefore` is present while older entries exist: pass it as `before`."
|
|
4766
|
+
},
|
|
4767
|
+
"declaration": "/**\n * A ticket, all its questions and one page of its history, oldest first. `activity` is the page; `comments` are the\n * comments its `commented` entries name, whose `changes.comment` holds only `{ after: { id } }` here (the stored\n * entry keeps the whole comment). `historyBefore` is present while older entries exist: pass it as `before`.\n */\ninterface ITicketDetail {\n ticket: ITicket;\n comments: ITicketComment[];\n activity: ITicketActivity[];\n questions: ITicketQuestion[];\n historyBefore?: string;\n}"
|
|
4768
|
+
},
|
|
4746
4769
|
{
|
|
4747
4770
|
"name": "ITicketFilters",
|
|
4748
4771
|
"declaration": "interface ITicketFilters {\n mine?: boolean;\n project?: string;\n status?: TTicketColumn;\n /** Matches a hand label or an AutoLabel. */\n label?: string;\n text?: string;\n}"
|
|
4749
4772
|
},
|
|
4773
|
+
{
|
|
4774
|
+
"name": "ITicketGet",
|
|
4775
|
+
"declaration": "/** A ticket and one page of its history: the newest entries, or those older than the entry `before` names, within `ticketHistoryPage`. */\ninterface ITicketGet {\n ticketId: string;\n /** An activity id, as `historyBefore` returned it: the page holds only older entries. */\n before?: string;\n /** Entries on the page, 1 to 500 (`ticketHistoryPage.maximum`); 50 (`ticketHistoryPage.default`) when absent. */\n limit?: number;\n /**\n * One comment of this ticket, by the id an activity entry or a fleet event names: the response holds the ticket, its\n * questions and that comment alone (`comments: [it]`, `activity: []`, no `historyBefore`). Excludes `before` and `limit`.\n */\n commentId?: string;\n}"
|
|
4776
|
+
},
|
|
4750
4777
|
{
|
|
4751
4778
|
"name": "ITicketMove",
|
|
4752
4779
|
"declaration": "interface ITicketMove { ticketId: string; columnId: TTicketColumn; beforeTicketId?: string; }"
|
package/ts/classes.aglhome.ts
CHANGED
|
@@ -64,6 +64,11 @@ export interface IAGLHomePaths {
|
|
|
64
64
|
proxy: string;
|
|
65
65
|
/** The running proxy's private control socket. */
|
|
66
66
|
proxySocket: string;
|
|
67
|
+
/**
|
|
68
|
+
* The proxy's confined listener: a Unix socket alone in a private directory of its own, which a confined run mounts
|
|
69
|
+
* into its container, so the container sees nothing else of AGL. Only confined credentials are accepted on it.
|
|
70
|
+
*/
|
|
71
|
+
proxyConfinedSocket: string;
|
|
67
72
|
/** The credentials the proxy keeps in files, one per client with delivery `file` (OpenCode's `{file:...}`). */
|
|
68
73
|
proxyCredentials: string;
|
|
69
74
|
/** The credential command a harness routed through the proxy runs; the proxy writes it whenever it starts. */
|
|
@@ -211,6 +216,7 @@ export const resolveAGLHomePaths = (
|
|
|
211
216
|
claudeOnChatGpt: path.join(root, 'claude-gateway'),
|
|
212
217
|
proxy: path.join(root, 'proxy'),
|
|
213
218
|
proxySocket: path.join(sockets, 'agl-proxy.sock'),
|
|
219
|
+
proxyConfinedSocket: path.join(sockets, 'agl-proxy-confined', 'proxy.sock'),
|
|
214
220
|
proxyCredentials: path.join(root, 'proxy', 'credentials'),
|
|
215
221
|
proxyCredentialHelper: path.join(root, 'proxy', 'credential-helper'),
|
|
216
222
|
migration: path.join(root, 'migration'),
|
package/ts/classes.authstore.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { DriverModel } from './driver/classes.driverstore.js';
|
|
|
3
3
|
import { DirectReportModel } from './driver/classes.directreportstore.js';
|
|
4
4
|
import { SessionFeedAcknowledgementModel } from './classes.sessionfeedacknowledgements.js';
|
|
5
5
|
import { HarnessReleaseModel } from './classes.harnessreleases.js';
|
|
6
|
+
import { WorkerCallerBindingModel } from './classes.workercallerbindings.js';
|
|
6
7
|
import { FleetTicketEffectModel } from './fleet/classes.ticketeffects.js';
|
|
7
8
|
import { ControllerCodexOriginMigrationModel } from '../ts_migration/v29_codexorigins.js';
|
|
8
9
|
import { ControllerCodexConnectionStore } from './classes.codexconnectionstore.js';
|
|
@@ -781,6 +782,7 @@ const setAuthStoreModelManager = (
|
|
|
781
782
|
plugins.nosqldb.setDefaultManagerForDoc(managerArg, SessionFeedAcknowledgementModel);
|
|
782
783
|
plugins.nosqldb.setDefaultManagerForDoc(managerArg, FleetTicketEffectModel);
|
|
783
784
|
plugins.nosqldb.setDefaultManagerForDoc(managerArg, HarnessReleaseModel);
|
|
785
|
+
plugins.nosqldb.setDefaultManagerForDoc(managerArg, WorkerCallerBindingModel);
|
|
784
786
|
plugins.nosqldb.setDefaultManagerForDoc(managerArg, TicketModel);
|
|
785
787
|
plugins.nosqldb.setDefaultManagerForDoc(managerArg, TicketBoardModel);
|
|
786
788
|
plugins.nosqldb.setDefaultManagerForDoc(managerArg, TicketCommentModel);
|
|
@@ -1054,6 +1056,8 @@ export class SmartDataAuthStore implements IAuthStore, IAuthStoreSessionIdentity
|
|
|
1054
1056
|
await FleetTicketEffectModel.exact.prepare();
|
|
1055
1057
|
await HarnessReleaseModel.init();
|
|
1056
1058
|
await HarnessReleaseModel.exact.prepare();
|
|
1059
|
+
await WorkerCallerBindingModel.init();
|
|
1060
|
+
await WorkerCallerBindingModel.exact.prepare();
|
|
1057
1061
|
await TicketModel.init();
|
|
1058
1062
|
await TicketBoardModel.init();
|
|
1059
1063
|
await TicketCommentModel.init();
|
package/ts/classes.controller.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { FleetDispatchError } from './fleet/interfaces.workers.js';
|
|
|
5
5
|
import type { TFleetWorkerAction, TFleetWorkerRequest } from '../ts_interfaces/fleetworkers.js';
|
|
6
6
|
import { ControllerBrowserOperationAuthority } from './classes.browseroperationauthority.js';
|
|
7
7
|
import { ControllerWorkerCallers, type IWorkerCodexCallerOrigin } from './classes.workercallers.js';
|
|
8
|
+
import { WorkerCallerBindingStore } from './classes.workercallerbindings.js';
|
|
8
9
|
import { FleetWorkerLaunches } from './fleet/classes.workerlaunches.js';
|
|
9
10
|
import { workerCallerEnrollmentToolName } from './classes.mcpworkercaller.js';
|
|
10
11
|
import { readWorkerProcessSnapshot, readWorkerUnixSocketOwner, workerSnapshotsEqual, isWorkerCallerProofRefusal, type IWorkerCallerConnection } from './functions.workerprocessproof.js';
|
|
@@ -86,6 +87,7 @@ import {
|
|
|
86
87
|
} from './functions.canonicaldirectory.js';
|
|
87
88
|
import { commitinfo } from './00_commitinfo_data.js';
|
|
88
89
|
import { controllerFailureJournal } from './classes.failurejournal.js';
|
|
90
|
+
import { ControllerEventDelivery } from './classes.controllereventdelivery.js';
|
|
89
91
|
import {
|
|
90
92
|
controllerPackageName,
|
|
91
93
|
controllerBuiltinCommands,
|
|
@@ -928,6 +930,9 @@ const maxSessionArchiveReconciliationReads = 3;
|
|
|
928
930
|
const maxLatestOpenCodeToolExecutions = 512;
|
|
929
931
|
const maxLatestOpenCodeMessageUpdates = 512;
|
|
930
932
|
const maxPendingFlexControllerEvents = 512;
|
|
933
|
+
/** Events and serialized bytes one browser may have waiting before its queue collapses into a resync. */
|
|
934
|
+
const maxPendingControllerEventsPerViewer = 512;
|
|
935
|
+
const maxPendingControllerEventBytesPerViewer = 16 * 1024 * 1024;
|
|
931
936
|
const maxLatestFlexToolExecutions = 512;
|
|
932
937
|
const maxLatestFlexToolExecutionBytes = 8 * 1024 * 1024;
|
|
933
938
|
const maxLatestFlexMessageUpdateBytes = 16 * 1024 * 1024;
|
|
@@ -1351,6 +1356,12 @@ interface ILatestTextUpdate {
|
|
|
1351
1356
|
bytes?: number;
|
|
1352
1357
|
}
|
|
1353
1358
|
|
|
1359
|
+
/** A live Flex reasoning snapshot with the accounting its deltas extend. */
|
|
1360
|
+
type TLatestFlexReasoningUpdate = ILatestReasoningUpdate & IFlexLiveTextAccounting;
|
|
1361
|
+
|
|
1362
|
+
/** A live Flex text snapshot with the accounting its deltas extend. */
|
|
1363
|
+
type TLatestFlexTextUpdate = ILatestTextUpdate & IFlexLiveTextAccounting;
|
|
1364
|
+
|
|
1354
1365
|
type TControllerMessageDelta = IControllerReasoningDelta | IControllerTextDelta;
|
|
1355
1366
|
|
|
1356
1367
|
interface IControllerTextDeltaFragment {
|
|
@@ -1388,6 +1399,67 @@ const controllerTextAfterAppendUtf8Bytes = (
|
|
|
1388
1399
|
return Number.isSafeInteger(result) && result >= 0 ? result : undefined;
|
|
1389
1400
|
};
|
|
1390
1401
|
|
|
1402
|
+
const isHighSurrogate = (codeArg: number): boolean => codeArg >= 0xD800 && codeArg <= 0xDBFF;
|
|
1403
|
+
const isLowSurrogate = (codeArg: number): boolean => codeArg >= 0xDC00 && codeArg <= 0xDFFF;
|
|
1404
|
+
|
|
1405
|
+
/** The UTF-8 bytes `JSON.stringify` writes for a string's content (without its quotes), counted without serializing. */
|
|
1406
|
+
const controllerJsonStringContentBytes = (valueArg: string): number => {
|
|
1407
|
+
let bytes = 0;
|
|
1408
|
+
for (let index = 0; index < valueArg.length; index += 1) {
|
|
1409
|
+
const code = valueArg.charCodeAt(index);
|
|
1410
|
+
if (
|
|
1411
|
+
code === 0x22 || code === 0x5C
|
|
1412
|
+
|| code === 0x08 || code === 0x09 || code === 0x0A || code === 0x0C || code === 0x0D
|
|
1413
|
+
) bytes += 2;
|
|
1414
|
+
else if (code < 0x20) bytes += 6;
|
|
1415
|
+
else if (code < 0x80) bytes += 1;
|
|
1416
|
+
else if (code < 0x800) bytes += 2;
|
|
1417
|
+
else if (isHighSurrogate(code)) {
|
|
1418
|
+
if (index + 1 < valueArg.length && isLowSurrogate(valueArg.charCodeAt(index + 1))) {
|
|
1419
|
+
bytes += 4;
|
|
1420
|
+
index += 1;
|
|
1421
|
+
} else bytes += 6;
|
|
1422
|
+
} else if (isLowSurrogate(code)) bytes += 6;
|
|
1423
|
+
else bytes += 3;
|
|
1424
|
+
}
|
|
1425
|
+
return bytes;
|
|
1426
|
+
};
|
|
1427
|
+
|
|
1428
|
+
/**
|
|
1429
|
+
* What a live Flex snapshot's text costs, kept beside the text so a delta is accounted by its own length: the
|
|
1430
|
+
* cumulative text is never encoded, serialized or even read again on the append path.
|
|
1431
|
+
*/
|
|
1432
|
+
interface IFlexLiveTextAccounting {
|
|
1433
|
+
textUtf8Bytes: number;
|
|
1434
|
+
/** `JSON.stringify(text)` bytes without the quotes. */
|
|
1435
|
+
textJsonBytes: number;
|
|
1436
|
+
textEndsWithHighSurrogate: boolean;
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
const flexLiveTextAccounting = (textArg: string): IFlexLiveTextAccounting => ({
|
|
1440
|
+
textUtf8Bytes: Buffer.byteLength(textArg, 'utf8'),
|
|
1441
|
+
textJsonBytes: controllerJsonStringContentBytes(textArg),
|
|
1442
|
+
textEndsWithHighSurrogate: textArg.length > 0 && isHighSurrogate(textArg.charCodeAt(textArg.length - 1)),
|
|
1443
|
+
});
|
|
1444
|
+
|
|
1445
|
+
const flexLiveTextAccountingAfterAppend = (
|
|
1446
|
+
accountingArg: IFlexLiveTextAccounting,
|
|
1447
|
+
deltaArg: string,
|
|
1448
|
+
): IFlexLiveTextAccounting | undefined => {
|
|
1449
|
+
if (deltaArg.length === 0) return accountingArg;
|
|
1450
|
+
// A surrogate pair split across the append: two lone halves (3 + 3 UTF-8 bytes, `\uXXXX` + `\uXXXX` in JSON)
|
|
1451
|
+
// become one pair (4 bytes in both).
|
|
1452
|
+
const joinsPair = accountingArg.textEndsWithHighSurrogate && isLowSurrogate(deltaArg.charCodeAt(0));
|
|
1453
|
+
const textUtf8Bytes = accountingArg.textUtf8Bytes + Buffer.byteLength(deltaArg, 'utf8') - (joinsPair ? 2 : 0);
|
|
1454
|
+
const textJsonBytes = accountingArg.textJsonBytes + controllerJsonStringContentBytes(deltaArg) - (joinsPair ? 8 : 0);
|
|
1455
|
+
if (!Number.isSafeInteger(textUtf8Bytes) || !Number.isSafeInteger(textJsonBytes)) return undefined;
|
|
1456
|
+
return {
|
|
1457
|
+
textUtf8Bytes,
|
|
1458
|
+
textJsonBytes,
|
|
1459
|
+
textEndsWithHighSurrogate: isHighSurrogate(deltaArg.charCodeAt(deltaArg.length - 1)),
|
|
1460
|
+
};
|
|
1461
|
+
};
|
|
1462
|
+
|
|
1391
1463
|
const fragmentControllerTextDelta = (valueArg: string): IControllerTextDeltaFragment[] => {
|
|
1392
1464
|
const fragments: IControllerTextDeltaFragment[] = [];
|
|
1393
1465
|
let delta = '';
|
|
@@ -3030,8 +3102,8 @@ export class OpenCodeController {
|
|
|
3030
3102
|
private readonly latestOpenCodeReasoningUpdates = new Map<string, ILatestReasoningUpdate>();
|
|
3031
3103
|
private readonly latestOpenCodeTextUpdates = new Map<string, ILatestTextUpdate>();
|
|
3032
3104
|
private readonly latestFlexToolExecutions = new Map<string, ILatestToolExecution>();
|
|
3033
|
-
private readonly latestFlexReasoningUpdates = new Map<string,
|
|
3034
|
-
private readonly latestFlexTextUpdates = new Map<string,
|
|
3105
|
+
private readonly latestFlexReasoningUpdates = new Map<string, TLatestFlexReasoningUpdate>();
|
|
3106
|
+
private readonly latestFlexTextUpdates = new Map<string, TLatestFlexTextUpdate>();
|
|
3035
3107
|
private readonly pendingFlexControllerEvents = new Map<string, IControllerEvent>();
|
|
3036
3108
|
private readonly pendingFlexAutoAcceptSweeps = new Map<string, IFlexAutoAcceptSweep>();
|
|
3037
3109
|
private openCodeControllerEventDrainTask?: Promise<void>;
|
|
@@ -3048,6 +3120,7 @@ export class OpenCodeController {
|
|
|
3048
3120
|
private pendingFlexToolEventBytes = 0;
|
|
3049
3121
|
private pendingFlexMessageEventBytes = 0;
|
|
3050
3122
|
private flexControllerEventDrainTask?: Promise<void>;
|
|
3123
|
+
private controllerEventDelivery?: ControllerEventDelivery;
|
|
3051
3124
|
private flexAutoAcceptDrainTask?: Promise<void>;
|
|
3052
3125
|
/** Sweeps whose auto-accept failed, queued again when the retry timer fires. */
|
|
3053
3126
|
private readonly failedFlexAutoAcceptSweeps = new Map<string, IFlexAutoAcceptSweep>();
|
|
@@ -10555,7 +10628,12 @@ export class OpenCodeController {
|
|
|
10555
10628
|
readMaster: async () => {
|
|
10556
10629
|
const resource = await configurationAuthority.getResource();
|
|
10557
10630
|
return (await configurationAuthority.getMaster({ resourceId: resource.resourceId })).master;
|
|
10558
|
-
}, captureCodexOrigin: launch => this.captureWorkerCodexOrigin(launch)
|
|
10631
|
+
}, captureCodexOrigin: launch => this.captureWorkerCodexOrigin(launch),
|
|
10632
|
+
// Claude launches keep their bindings, so a fleet worker's bridge proves itself again after this restart and
|
|
10633
|
+
// after Claude Code continued its job in another process; the fleet reads the job's inventory for that proof.
|
|
10634
|
+
bindings: new WorkerCallerBindingStore(),
|
|
10635
|
+
observeClaudeJob: async (request) => this.fleetWorkers
|
|
10636
|
+
? await this.fleetWorkers.observeCallerJob(request) : { state: 'unproven', reason: 'the fleet is not running yet' } });
|
|
10559
10637
|
this.workerCallers = workerCallers;
|
|
10560
10638
|
const mcpControllerHost = new ControllerMcpHost({
|
|
10561
10639
|
controllerPort: runtimeConfig.controllerPort,
|
|
@@ -12955,6 +13033,9 @@ export class OpenCodeController {
|
|
|
12955
13033
|
}
|
|
12956
13034
|
};
|
|
12957
13035
|
|
|
13036
|
+
// Fleet jobs prepare, bind and revoke worker launches through the caller hooks: admit none and let the running
|
|
13037
|
+
// ones settle before the hooks go, so a stop or archive meets the fleet's own refusal, never missing hooks.
|
|
13038
|
+
await stopPart(async () => { await this.fleetWorkers?.closeAdmission(); });
|
|
12958
13039
|
await stopPart(async () => {
|
|
12959
13040
|
await this.workerCallers?.close();
|
|
12960
13041
|
this.workerCallers = undefined;
|
|
@@ -13221,6 +13302,7 @@ export class OpenCodeController {
|
|
|
13221
13302
|
...(this.openCodeControllerEventDrainTask ? [this.openCodeControllerEventDrainTask] : []),
|
|
13222
13303
|
...(this.flexControllerEventDrainTask ? [this.flexControllerEventDrainTask] : []),
|
|
13223
13304
|
]);
|
|
13305
|
+
await this.controllerEventDelivery?.stop();
|
|
13224
13306
|
|
|
13225
13307
|
if (this.flexProjectionReader) {
|
|
13226
13308
|
await stopPart(async () => {
|
|
@@ -16748,7 +16830,7 @@ export class OpenCodeController {
|
|
|
16748
16830
|
return { owner, ...(configuration.boardPump ? { configuration: configuration.boardPump } : {}) };
|
|
16749
16831
|
},
|
|
16750
16832
|
tickets: async () => (await this.ticketStore.execute('list', {}, undefined)).tickets,
|
|
16751
|
-
|
|
16833
|
+
history: (ticketKeyArg) => this.ticketStore.history(ticketKeyArg),
|
|
16752
16834
|
workers: (ownerArg) => this.requireFleetWorkers().views(ownerArg),
|
|
16753
16835
|
steer: (sessionIdArg, ticketKeyArg, textArg) => this.requireFleetWorkers().notify(sessionIdArg, ticketKeyArg, textArg),
|
|
16754
16836
|
publish: (eventArg, ownerArg) => this.requireFleetWorkers().events.publish(eventArg, ownerArg),
|
|
@@ -17622,6 +17704,7 @@ export class OpenCodeController {
|
|
|
17622
17704
|
driver: {
|
|
17623
17705
|
instructions: service.instructions(await this.readDriverConfiguration()),
|
|
17624
17706
|
notes: state.scratchpad.text,
|
|
17707
|
+
notesRevision: state.scratchpad.revision,
|
|
17625
17708
|
},
|
|
17626
17709
|
};
|
|
17627
17710
|
}
|
|
@@ -23842,7 +23925,8 @@ export class OpenCodeController {
|
|
|
23842
23925
|
let cursor: string | undefined;
|
|
23843
23926
|
for (let pages = 0; ; pages++) {
|
|
23844
23927
|
if (pages >= 1000) throw new Error('Flex delivery transcript exceeded its inspection limit.');
|
|
23845
|
-
|
|
23928
|
+
// Metadata pages: identity and state only, so a full scan never moves the transcript's text.
|
|
23929
|
+
const page = await supervisorArg.request('message.metadata.page', {
|
|
23846
23930
|
...payload, limit: 50, includeUndone: true, ...(cursor === undefined ? {} : { before: cursor }),
|
|
23847
23931
|
}, signal);
|
|
23848
23932
|
for (const message of page.messages) {
|
|
@@ -29179,7 +29263,7 @@ export class OpenCodeController {
|
|
|
29179
29263
|
|
|
29180
29264
|
private setLatestFlexReasoningUpdate(
|
|
29181
29265
|
keyArg: string,
|
|
29182
|
-
entryArg:
|
|
29266
|
+
entryArg: TLatestFlexReasoningUpdate,
|
|
29183
29267
|
bytesArg: number,
|
|
29184
29268
|
): void {
|
|
29185
29269
|
this.deleteLatestFlexReasoningUpdate(keyArg);
|
|
@@ -29189,7 +29273,7 @@ export class OpenCodeController {
|
|
|
29189
29273
|
|
|
29190
29274
|
private setLatestFlexTextUpdate(
|
|
29191
29275
|
keyArg: string,
|
|
29192
|
-
entryArg:
|
|
29276
|
+
entryArg: TLatestFlexTextUpdate,
|
|
29193
29277
|
bytesArg: number,
|
|
29194
29278
|
): void {
|
|
29195
29279
|
this.deleteLatestFlexTextUpdate(keyArg);
|
|
@@ -29712,7 +29796,7 @@ export class OpenCodeController {
|
|
|
29712
29796
|
{
|
|
29713
29797
|
projectId: eventArg.scopeId,
|
|
29714
29798
|
update,
|
|
29715
|
-
|
|
29799
|
+
...flexLiveTextAccounting(update.text),
|
|
29716
29800
|
},
|
|
29717
29801
|
eventBytes,
|
|
29718
29802
|
);
|
|
@@ -29779,7 +29863,7 @@ export class OpenCodeController {
|
|
|
29779
29863
|
{
|
|
29780
29864
|
projectId: eventArg.scopeId,
|
|
29781
29865
|
update,
|
|
29782
|
-
|
|
29866
|
+
...flexLiveTextAccounting(update.text),
|
|
29783
29867
|
},
|
|
29784
29868
|
eventBytes,
|
|
29785
29869
|
);
|
|
@@ -29827,13 +29911,11 @@ export class OpenCodeController {
|
|
|
29827
29911
|
this.advanceFlexMessageStreamEpoch(true);
|
|
29828
29912
|
return;
|
|
29829
29913
|
}
|
|
29830
|
-
const
|
|
29831
|
-
|
|
29832
|
-
entry.textUtf8Bytes,
|
|
29833
|
-
eventArg.delta,
|
|
29834
|
-
);
|
|
29914
|
+
const accounting = flexLiveTextAccountingAfterAppend(entry, eventArg.delta);
|
|
29915
|
+
const textUtf8Bytes = accounting?.textUtf8Bytes;
|
|
29835
29916
|
if (
|
|
29836
|
-
|
|
29917
|
+
accounting === undefined
|
|
29918
|
+
|| textUtf8Bytes === undefined
|
|
29837
29919
|
|| textUtf8Bytes <= entry.textUtf8Bytes
|
|
29838
29920
|
|| textUtf8Bytes !== eventArg.textUtf8Bytes
|
|
29839
29921
|
) {
|
|
@@ -29842,9 +29924,11 @@ export class OpenCodeController {
|
|
|
29842
29924
|
}
|
|
29843
29925
|
|
|
29844
29926
|
const revision = this.flexMessageStreamRevision + 1;
|
|
29927
|
+
// Measured with empty text first: the snapshot's size is that frame plus the text's tracked JSON bytes, so
|
|
29928
|
+
// the growing text is serialized only when a snapshot is served.
|
|
29845
29929
|
const update = {
|
|
29846
29930
|
...previous,
|
|
29847
|
-
text:
|
|
29931
|
+
text: '',
|
|
29848
29932
|
sourceUpdatedAt,
|
|
29849
29933
|
revision,
|
|
29850
29934
|
streamEpoch: this.flexMessageStreamEpoch,
|
|
@@ -29906,7 +29990,7 @@ export class OpenCodeController {
|
|
|
29906
29990
|
timestamp: sourceUpdatedAt,
|
|
29907
29991
|
};
|
|
29908
29992
|
const eventBytes = Buffer.byteLength(JSON.stringify(controllerEvent), 'utf8');
|
|
29909
|
-
const snapshotBytes = Buffer.byteLength(JSON.stringify(snapshotEvent), 'utf8');
|
|
29993
|
+
const snapshotBytes = Buffer.byteLength(JSON.stringify(snapshotEvent), 'utf8') + accounting.textJsonBytes;
|
|
29910
29994
|
if (
|
|
29911
29995
|
eventBytes > controllerMaxLiveMessageEventBytes
|
|
29912
29996
|
|| snapshotBytes > controllerMaxLiveMessageEventBytes
|
|
@@ -29917,6 +30001,7 @@ export class OpenCodeController {
|
|
|
29917
30001
|
return;
|
|
29918
30002
|
}
|
|
29919
30003
|
|
|
30004
|
+
update.text = `${previous.text}${eventArg.delta}`;
|
|
29920
30005
|
this.flexMessageStreamRevision = revision;
|
|
29921
30006
|
if (eventArg.partType === 'reasoning') {
|
|
29922
30007
|
this.setLatestFlexReasoningUpdate(
|
|
@@ -29924,7 +30009,7 @@ export class OpenCodeController {
|
|
|
29924
30009
|
{
|
|
29925
30010
|
projectId: eventArg.scopeId,
|
|
29926
30011
|
update: update as IControllerReasoningUpdate,
|
|
29927
|
-
|
|
30012
|
+
...accounting,
|
|
29928
30013
|
},
|
|
29929
30014
|
snapshotBytes,
|
|
29930
30015
|
);
|
|
@@ -29934,7 +30019,7 @@ export class OpenCodeController {
|
|
|
29934
30019
|
{
|
|
29935
30020
|
projectId: eventArg.scopeId,
|
|
29936
30021
|
update: update as IControllerTextUpdate,
|
|
29937
|
-
|
|
30022
|
+
...accounting,
|
|
29938
30023
|
},
|
|
29939
30024
|
snapshotBytes,
|
|
29940
30025
|
);
|
|
@@ -30625,7 +30710,7 @@ export class OpenCodeController {
|
|
|
30625
30710
|
{
|
|
30626
30711
|
projectId: eventArg.projectId,
|
|
30627
30712
|
update,
|
|
30628
|
-
|
|
30713
|
+
...flexLiveTextAccounting(update.text),
|
|
30629
30714
|
},
|
|
30630
30715
|
Buffer.byteLength(JSON.stringify(event), 'utf8'),
|
|
30631
30716
|
);
|
|
@@ -30653,7 +30738,7 @@ export class OpenCodeController {
|
|
|
30653
30738
|
{
|
|
30654
30739
|
projectId: eventArg.projectId,
|
|
30655
30740
|
update,
|
|
30656
|
-
|
|
30741
|
+
...flexLiveTextAccounting(update.text),
|
|
30657
30742
|
},
|
|
30658
30743
|
Buffer.byteLength(JSON.stringify(event), 'utf8'),
|
|
30659
30744
|
);
|
|
@@ -35065,20 +35150,44 @@ export class OpenCodeController {
|
|
|
35065
35150
|
));
|
|
35066
35151
|
}
|
|
35067
35152
|
|
|
35153
|
+
/** Every browser's own ordered event queue (`ControllerEventDelivery`), created with the first event. */
|
|
35154
|
+
private controllerEventDeliveryQueues(): ControllerEventDelivery {
|
|
35155
|
+
this.controllerEventDelivery ??= new ControllerEventDelivery({
|
|
35156
|
+
viewers: async () => {
|
|
35157
|
+
const typedSocket = this.typedServer?.typedsocket;
|
|
35158
|
+
if (!typedSocket) return [];
|
|
35159
|
+
const targets = await this.controllerEventViewers();
|
|
35160
|
+
return targets.map((targetArg) => ({
|
|
35161
|
+
peerId: targetArg.peer.id,
|
|
35162
|
+
send: async (eventArg: IControllerEvent) => {
|
|
35163
|
+
await typedSocket.createTypedRequest<IReq_ControllerEvent>(
|
|
35164
|
+
'controller.event',
|
|
35165
|
+
targetArg,
|
|
35166
|
+
{ timeoutMs: 2_000 },
|
|
35167
|
+
).fire(eventArg, { timeoutMs: 2_000, maxRetries: 0 });
|
|
35168
|
+
},
|
|
35169
|
+
}));
|
|
35170
|
+
},
|
|
35171
|
+
eventKey: (eventArg) => this.controllerEventKey(eventArg),
|
|
35172
|
+
mergeDelta: mergeControllerMessageDeltaEvents,
|
|
35173
|
+
limits: {
|
|
35174
|
+
events: maxPendingControllerEventsPerViewer,
|
|
35175
|
+
bytes: maxPendingControllerEventBytesPerViewer,
|
|
35176
|
+
mergedDeltaBytes: controllerMaxLiveMessageEventBytes,
|
|
35177
|
+
},
|
|
35178
|
+
});
|
|
35179
|
+
return this.controllerEventDelivery;
|
|
35180
|
+
}
|
|
35181
|
+
|
|
35182
|
+
/**
|
|
35183
|
+
* The driver and the session feed see every event once, in order, before any browser; each browser then gets it
|
|
35184
|
+
* through its own queue, so one that acknowledges slowly delays only itself. Resolves once every browser's queue
|
|
35185
|
+
* holds the event, never on an acknowledgement.
|
|
35186
|
+
*/
|
|
35068
35187
|
private async pushControllerEvent(eventArg: IControllerEvent): Promise<void> {
|
|
35069
35188
|
this.driverService?.observe(eventArg);
|
|
35070
35189
|
this.sessionFeed?.observe(eventArg);
|
|
35071
|
-
|
|
35072
|
-
if (!typedSocket) return;
|
|
35073
|
-
const targets = await this.controllerEventViewers();
|
|
35074
|
-
await Promise.allSettled(targets.map(async (targetArg) => {
|
|
35075
|
-
const request = typedSocket.createTypedRequest<IReq_ControllerEvent>(
|
|
35076
|
-
'controller.event',
|
|
35077
|
-
targetArg,
|
|
35078
|
-
{ timeoutMs: 2_000 },
|
|
35079
|
-
);
|
|
35080
|
-
await request.fire(eventArg, { timeoutMs: 2_000, maxRetries: 0 });
|
|
35081
|
-
}));
|
|
35190
|
+
await this.controllerEventDeliveryQueues().push(eventArg);
|
|
35082
35191
|
}
|
|
35083
35192
|
|
|
35084
35193
|
private runUpgradePreparationAdmission<T>(operationArg: () => Promise<T>): Promise<T> {
|