@adhdev/mesh-shared 1.0.60-rc.60 → 1.0.60-rc.62
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/index.js +41 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -10
- package/dist/index.mjs.map +1 -1
- package/dist/turn-ipc.d.ts +68 -2
- package/package.json +1 -1
- package/src/turn-ipc.ts +116 -16
package/dist/turn-ipc.d.ts
CHANGED
|
@@ -333,6 +333,16 @@ export interface MissionListQueryRequest {
|
|
|
333
333
|
withStats?: boolean;
|
|
334
334
|
limit?: number;
|
|
335
335
|
historyIdLimit?: number;
|
|
336
|
+
/**
|
|
337
|
+
* The mesh_status mission projection, computed in the daemon (the MCP no longer
|
|
338
|
+
* opens the daemon's store for it): 'compact' = `getMeshStatusMissionsCompact`
|
|
339
|
+
* (live missions goal-elided + folded history), 'verbose' =
|
|
340
|
+
* `getMeshStatusMissionSummaries({verbose: true})` (live + capped history, full
|
|
341
|
+
* goal, no stats — stats ride one batched `task_stats_query`). Rows then also
|
|
342
|
+
* carry `createdAt`/`updatedAt`/`closeCandidateEmittedAt`. When set, every other
|
|
343
|
+
* option except `historyIdLimit` is ignored. An older daemon rejects the key.
|
|
344
|
+
*/
|
|
345
|
+
meshStatusView?: 'compact' | 'verbose';
|
|
336
346
|
}
|
|
337
347
|
export interface MeshMissionTaskAggregateWire {
|
|
338
348
|
total: number;
|
|
@@ -366,6 +376,10 @@ export interface MissionListSummaryVerboseWire {
|
|
|
366
376
|
stats?: MeshMissionStatsWire;
|
|
367
377
|
/** H2: absent = no brief attached. */
|
|
368
378
|
brief?: MissionBriefWire;
|
|
379
|
+
/** `meshStatusView` rows only. */
|
|
380
|
+
createdAt?: string;
|
|
381
|
+
updatedAt?: string;
|
|
382
|
+
closeCandidateEmittedAt?: string | null;
|
|
369
383
|
}
|
|
370
384
|
/** Compact (default) mission row. `goalPreview`/`goalTruncated` present, `goal` absent. */
|
|
371
385
|
export interface MissionListSummarySlimWire {
|
|
@@ -380,6 +394,10 @@ export interface MissionListSummarySlimWire {
|
|
|
380
394
|
stats?: MeshMissionStatsWire;
|
|
381
395
|
/** H2: absent = no brief attached. */
|
|
382
396
|
brief?: MissionBriefWire;
|
|
397
|
+
/** `meshStatusView` rows only. */
|
|
398
|
+
createdAt?: string;
|
|
399
|
+
updatedAt?: string;
|
|
400
|
+
closeCandidateEmittedAt?: string | null;
|
|
383
401
|
}
|
|
384
402
|
export type MissionListSummaryWire = MissionListSummaryVerboseWire | MissionListSummarySlimWire;
|
|
385
403
|
export interface MeshMissionHistoryFoldWire {
|
|
@@ -545,9 +563,36 @@ export interface QueueQueryRequest {
|
|
|
545
563
|
taskId?: string;
|
|
546
564
|
/** Project for a VIEW surface: the persisted input envelope → `inputSummary` (summarizeQueueEntryInputForView). */
|
|
547
565
|
view?: boolean;
|
|
566
|
+
/**
|
|
567
|
+
* Also return the per-status row counts of the WHOLE mesh queue (columns only,
|
|
568
|
+
* no payload parse) — lets a view read only the rows it shows yet report
|
|
569
|
+
* mesh-wide counts. An older daemon rejects the key.
|
|
570
|
+
*/
|
|
571
|
+
withCounts?: boolean;
|
|
572
|
+
/** With `withCounts`: also count terminal rows whose `updated_at` is older than this age. */
|
|
573
|
+
historicalOlderThanMs?: number;
|
|
574
|
+
/**
|
|
575
|
+
* Also return `dependencyHeads`: id/status/blockedReason/cancelReason of every
|
|
576
|
+
* row the returned entries list in `dependsOn` that is not itself returned —
|
|
577
|
+
* enough to annotate dependency state without reading the whole queue.
|
|
578
|
+
*/
|
|
579
|
+
withDependencyHeads?: boolean;
|
|
580
|
+
}
|
|
581
|
+
/** A dependency row reduced to the fields dependency-state annotation reads. */
|
|
582
|
+
export interface QueueDependencyHeadWire {
|
|
583
|
+
id: string;
|
|
584
|
+
status: string;
|
|
585
|
+
blockedReason?: string;
|
|
586
|
+
cancelReason?: string;
|
|
548
587
|
}
|
|
549
588
|
export interface QueueQueryResponse {
|
|
550
589
|
entries: readonly QueueEntryWire[];
|
|
590
|
+
/** `withCounts`: row count per status over the whole mesh queue. */
|
|
591
|
+
counts?: Record<string, number>;
|
|
592
|
+
/** `withCounts` + `historicalOlderThanMs`: terminal rows older than that age. */
|
|
593
|
+
oldHistoricalCount?: number;
|
|
594
|
+
/** `withDependencyHeads`. */
|
|
595
|
+
dependencyHeads?: readonly QueueDependencyHeadWire[];
|
|
551
596
|
}
|
|
552
597
|
export declare function isQueueQueryRequest(value: unknown): value is QueueQueryRequest;
|
|
553
598
|
export declare function decodeQueueQueryRequest(value: unknown): QueueQueryRequest | null;
|
|
@@ -675,7 +720,12 @@ export interface ActiveWorkQueryRequest {
|
|
|
675
720
|
includeInputs?: boolean;
|
|
676
721
|
includeSummary?: boolean;
|
|
677
722
|
includeSchedulingRuntime?: boolean;
|
|
678
|
-
/**
|
|
723
|
+
/**
|
|
724
|
+
* The caller's mesh snapshot for the scheduling runtime, JSON passthrough.
|
|
725
|
+
* Optional since the daemon resolves its own mesh record when it is absent;
|
|
726
|
+
* an older daemon rejects `includeSchedulingRuntime` without it (the caller's
|
|
727
|
+
* feature-detect signal to resend with the mesh).
|
|
728
|
+
*/
|
|
679
729
|
mesh?: Record<string, unknown>;
|
|
680
730
|
}
|
|
681
731
|
export interface ActiveWorkQueryResponse {
|
|
@@ -697,9 +747,17 @@ export interface RecoveryContextQueryRequest {
|
|
|
697
747
|
nodeId?: string;
|
|
698
748
|
sessionId?: string;
|
|
699
749
|
maxRetries?: number;
|
|
750
|
+
/**
|
|
751
|
+
* Batch: one context per node id, computed over ONE record read (answers
|
|
752
|
+
* `contexts`). Exclusive with `nodeId`/`sessionId`. An older daemon rejects it.
|
|
753
|
+
*/
|
|
754
|
+
nodeIds?: readonly string[];
|
|
700
755
|
}
|
|
701
756
|
export interface RecoveryContextQueryResponse {
|
|
702
|
-
|
|
757
|
+
/** Single mode (nodeId/sessionId). */
|
|
758
|
+
context?: Record<string, unknown>;
|
|
759
|
+
/** Batch mode (`nodeIds`): context per node id. */
|
|
760
|
+
contexts?: Record<string, Record<string, unknown>>;
|
|
703
761
|
}
|
|
704
762
|
export declare function isRecoveryContextQueryRequest(value: unknown): value is RecoveryContextQueryRequest;
|
|
705
763
|
export declare function decodeRecoveryContextQueryRequest(value: unknown): RecoveryContextQueryRequest | null;
|
|
@@ -844,12 +902,20 @@ export interface TaskStatsQueryRequest {
|
|
|
844
902
|
tail?: number;
|
|
845
903
|
/** Also compute `computeMeshMissionStats` — requires `missionId`. */
|
|
846
904
|
rollup?: boolean;
|
|
905
|
+
/**
|
|
906
|
+
* Batch rollups: `computeMeshMissionStats` for every id, over ONE queue read and
|
|
907
|
+
* ONE record read (answers `missions`, `tasks` empty). Exclusive with
|
|
908
|
+
* `taskIds`/`missionId`. An older daemon rejects the key.
|
|
909
|
+
*/
|
|
910
|
+
missionIds?: readonly string[];
|
|
847
911
|
}
|
|
848
912
|
export interface TaskStatsQueryResponse {
|
|
849
913
|
/** `MeshTaskStats[]`, JSON passthrough. */
|
|
850
914
|
tasks: readonly Record<string, unknown>[];
|
|
851
915
|
/** `MeshMissionStats`, JSON passthrough; present only when `rollup: true` was requested and satisfiable. */
|
|
852
916
|
mission?: Record<string, unknown>;
|
|
917
|
+
/** Batch mode: `MeshMissionStats` per requested mission id, JSON passthrough. */
|
|
918
|
+
missions?: Record<string, Record<string, unknown>>;
|
|
853
919
|
}
|
|
854
920
|
export declare function isTaskStatsQueryRequest(value: unknown): value is TaskStatsQueryRequest;
|
|
855
921
|
export declare function decodeTaskStatsQueryRequest(value: unknown): TaskStatsQueryRequest | null;
|
package/package.json
CHANGED
package/src/turn-ipc.ts
CHANGED
|
@@ -748,6 +748,16 @@ export interface MissionListQueryRequest {
|
|
|
748
748
|
withStats?: boolean
|
|
749
749
|
limit?: number
|
|
750
750
|
historyIdLimit?: number
|
|
751
|
+
/**
|
|
752
|
+
* The mesh_status mission projection, computed in the daemon (the MCP no longer
|
|
753
|
+
* opens the daemon's store for it): 'compact' = `getMeshStatusMissionsCompact`
|
|
754
|
+
* (live missions goal-elided + folded history), 'verbose' =
|
|
755
|
+
* `getMeshStatusMissionSummaries({verbose: true})` (live + capped history, full
|
|
756
|
+
* goal, no stats — stats ride one batched `task_stats_query`). Rows then also
|
|
757
|
+
* carry `createdAt`/`updatedAt`/`closeCandidateEmittedAt`. When set, every other
|
|
758
|
+
* option except `historyIdLimit` is ignored. An older daemon rejects the key.
|
|
759
|
+
*/
|
|
760
|
+
meshStatusView?: 'compact' | 'verbose'
|
|
751
761
|
}
|
|
752
762
|
|
|
753
763
|
export interface MeshMissionTaskAggregateWire {
|
|
@@ -784,6 +794,10 @@ export interface MissionListSummaryVerboseWire {
|
|
|
784
794
|
stats?: MeshMissionStatsWire
|
|
785
795
|
/** H2: absent = no brief attached. */
|
|
786
796
|
brief?: MissionBriefWire
|
|
797
|
+
/** `meshStatusView` rows only. */
|
|
798
|
+
createdAt?: string
|
|
799
|
+
updatedAt?: string
|
|
800
|
+
closeCandidateEmittedAt?: string | null
|
|
787
801
|
}
|
|
788
802
|
|
|
789
803
|
/** Compact (default) mission row. `goalPreview`/`goalTruncated` present, `goal` absent. */
|
|
@@ -799,6 +813,10 @@ export interface MissionListSummarySlimWire {
|
|
|
799
813
|
stats?: MeshMissionStatsWire
|
|
800
814
|
/** H2: absent = no brief attached. */
|
|
801
815
|
brief?: MissionBriefWire
|
|
816
|
+
/** `meshStatusView` rows only. */
|
|
817
|
+
createdAt?: string
|
|
818
|
+
updatedAt?: string
|
|
819
|
+
closeCandidateEmittedAt?: string | null
|
|
802
820
|
}
|
|
803
821
|
|
|
804
822
|
export type MissionListSummaryWire = MissionListSummaryVerboseWire | MissionListSummarySlimWire
|
|
@@ -819,7 +837,8 @@ export interface MissionListQueryResponse {
|
|
|
819
837
|
}
|
|
820
838
|
|
|
821
839
|
export function isMissionListQueryRequest(value: unknown): value is MissionListQueryRequest {
|
|
822
|
-
if (!isRecord(value) || !hasOnlyKeys(value, ['v', 'meshId', 'statuses', 'verbose', 'includeMagi', 'withStats', 'limit', 'historyIdLimit'])) return false
|
|
840
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ['v', 'meshId', 'statuses', 'verbose', 'includeMagi', 'withStats', 'limit', 'historyIdLimit', 'meshStatusView'])) return false
|
|
841
|
+
if (value.meshStatusView !== undefined && value.meshStatusView !== 'compact' && value.meshStatusView !== 'verbose') return false
|
|
823
842
|
if (value.v !== TURN_IPC_PROTOCOL_VERSION) return false
|
|
824
843
|
if (!isEvidenceIdentifier(value.meshId)) return false
|
|
825
844
|
if (value.statuses !== undefined) {
|
|
@@ -864,7 +883,7 @@ function isMissionListSummaryWire(value: unknown): value is MissionListSummaryWi
|
|
|
864
883
|
const hasGoal = 'goal' in value
|
|
865
884
|
const hasPreview = 'goalPreview' in value && 'goalTruncated' in value
|
|
866
885
|
if (hasGoal === hasPreview) return false // exactly one of the two shapes
|
|
867
|
-
const baseKeys = ['id', 'meshId', 'title', 'status', 'source', 'tasks', 'stats', 'brief'] as const
|
|
886
|
+
const baseKeys = ['id', 'meshId', 'title', 'status', 'source', 'tasks', 'stats', 'brief', 'createdAt', 'updatedAt', 'closeCandidateEmittedAt'] as const
|
|
868
887
|
const allowed = hasGoal ? [...baseKeys, 'goal'] : [...baseKeys, 'goalPreview', 'goalTruncated']
|
|
869
888
|
if (!hasOnlyKeys(value, allowed)) return false
|
|
870
889
|
if (!isEvidenceIdentifier(value.id) || !isEvidenceIdentifier(value.meshId)) return false
|
|
@@ -876,6 +895,9 @@ function isMissionListSummaryWire(value: unknown): value is MissionListSummaryWi
|
|
|
876
895
|
if (value.brief !== undefined && !isMissionBriefWire(value.brief)) return false
|
|
877
896
|
if (hasGoal && typeof value.goal !== 'string') return false
|
|
878
897
|
if (hasPreview && (typeof value.goalPreview !== 'string' || typeof value.goalTruncated !== 'boolean')) return false
|
|
898
|
+
if (value.createdAt !== undefined && typeof value.createdAt !== 'string') return false
|
|
899
|
+
if (value.updatedAt !== undefined && typeof value.updatedAt !== 'string') return false
|
|
900
|
+
if (value.closeCandidateEmittedAt !== undefined && value.closeCandidateEmittedAt !== null && typeof value.closeCandidateEmittedAt !== 'string') return false
|
|
879
901
|
return true
|
|
880
902
|
}
|
|
881
903
|
|
|
@@ -1288,25 +1310,67 @@ export interface QueueQueryRequest {
|
|
|
1288
1310
|
taskId?: string
|
|
1289
1311
|
/** Project for a VIEW surface: the persisted input envelope → `inputSummary` (summarizeQueueEntryInputForView). */
|
|
1290
1312
|
view?: boolean
|
|
1313
|
+
/**
|
|
1314
|
+
* Also return the per-status row counts of the WHOLE mesh queue (columns only,
|
|
1315
|
+
* no payload parse) — lets a view read only the rows it shows yet report
|
|
1316
|
+
* mesh-wide counts. An older daemon rejects the key.
|
|
1317
|
+
*/
|
|
1318
|
+
withCounts?: boolean
|
|
1319
|
+
/** With `withCounts`: also count terminal rows whose `updated_at` is older than this age. */
|
|
1320
|
+
historicalOlderThanMs?: number
|
|
1321
|
+
/**
|
|
1322
|
+
* Also return `dependencyHeads`: id/status/blockedReason/cancelReason of every
|
|
1323
|
+
* row the returned entries list in `dependsOn` that is not itself returned —
|
|
1324
|
+
* enough to annotate dependency state without reading the whole queue.
|
|
1325
|
+
*/
|
|
1326
|
+
withDependencyHeads?: boolean
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
/** A dependency row reduced to the fields dependency-state annotation reads. */
|
|
1330
|
+
export interface QueueDependencyHeadWire {
|
|
1331
|
+
id: string
|
|
1332
|
+
status: string
|
|
1333
|
+
blockedReason?: string
|
|
1334
|
+
cancelReason?: string
|
|
1291
1335
|
}
|
|
1292
1336
|
|
|
1293
1337
|
export interface QueueQueryResponse {
|
|
1294
1338
|
entries: readonly QueueEntryWire[]
|
|
1339
|
+
/** `withCounts`: row count per status over the whole mesh queue. */
|
|
1340
|
+
counts?: Record<string, number>
|
|
1341
|
+
/** `withCounts` + `historicalOlderThanMs`: terminal rows older than that age. */
|
|
1342
|
+
oldHistoricalCount?: number
|
|
1343
|
+
/** `withDependencyHeads`. */
|
|
1344
|
+
dependencyHeads?: readonly QueueDependencyHeadWire[]
|
|
1295
1345
|
}
|
|
1296
1346
|
|
|
1297
1347
|
export function isQueueQueryRequest(value: unknown): value is QueueQueryRequest {
|
|
1298
|
-
if (!isRecord(value) || !hasOnlyKeys(value, ['v', 'meshId', 'statuses', 'taskId', 'view'])) return false
|
|
1348
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ['v', 'meshId', 'statuses', 'taskId', 'view', 'withCounts', 'historicalOlderThanMs', 'withDependencyHeads'])) return false
|
|
1299
1349
|
if (value.v !== TURN_IPC_PROTOCOL_VERSION || !isEvidenceIdentifier(value.meshId)) return false
|
|
1300
1350
|
if (value.statuses !== undefined && (!Array.isArray(value.statuses) || !value.statuses.every(isEvidenceIdentifier))) return false
|
|
1351
|
+
if (value.historicalOlderThanMs !== undefined && !isNonNegativeInt(value.historicalOlderThanMs)) return false
|
|
1301
1352
|
return isOptionalId(value.taskId) && isOptionalBoolean(value.view)
|
|
1353
|
+
&& isOptionalBoolean(value.withCounts) && isOptionalBoolean(value.withDependencyHeads)
|
|
1302
1354
|
}
|
|
1303
1355
|
|
|
1304
1356
|
export function decodeQueueQueryRequest(value: unknown): QueueQueryRequest | null {
|
|
1305
1357
|
return isQueueQueryRequest(value) ? value : null
|
|
1306
1358
|
}
|
|
1307
1359
|
|
|
1360
|
+
function isQueueDependencyHeadWire(value: unknown): value is QueueDependencyHeadWire {
|
|
1361
|
+
return isRecord(value) && hasOnlyKeys(value, ['id', 'status', 'blockedReason', 'cancelReason'])
|
|
1362
|
+
&& typeof value.id === 'string' && typeof value.status === 'string'
|
|
1363
|
+
&& (value.blockedReason === undefined || typeof value.blockedReason === 'string')
|
|
1364
|
+
&& (value.cancelReason === undefined || typeof value.cancelReason === 'string')
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1308
1367
|
export function isQueueQueryResponse(value: unknown): value is QueueQueryResponse {
|
|
1309
|
-
|
|
1368
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ['entries', 'counts', 'oldHistoricalCount', 'dependencyHeads'])) return false
|
|
1369
|
+
if (!Array.isArray(value.entries) || !value.entries.every(isQueueEntryWire)) return false
|
|
1370
|
+
if (value.counts !== undefined && (!isRecord(value.counts) || !Object.values(value.counts).every(isNonNegativeInt))) return false
|
|
1371
|
+
if (value.oldHistoricalCount !== undefined && !isNonNegativeInt(value.oldHistoricalCount)) return false
|
|
1372
|
+
if (value.dependencyHeads !== undefined && (!Array.isArray(value.dependencyHeads) || !value.dependencyHeads.every(isQueueDependencyHeadWire))) return false
|
|
1373
|
+
return true
|
|
1310
1374
|
}
|
|
1311
1375
|
|
|
1312
1376
|
export function decodeQueueQueryResponse(value: unknown): QueueQueryResponse | null {
|
|
@@ -1592,7 +1656,12 @@ export interface ActiveWorkQueryRequest {
|
|
|
1592
1656
|
includeInputs?: boolean
|
|
1593
1657
|
includeSummary?: boolean
|
|
1594
1658
|
includeSchedulingRuntime?: boolean
|
|
1595
|
-
/**
|
|
1659
|
+
/**
|
|
1660
|
+
* The caller's mesh snapshot for the scheduling runtime, JSON passthrough.
|
|
1661
|
+
* Optional since the daemon resolves its own mesh record when it is absent;
|
|
1662
|
+
* an older daemon rejects `includeSchedulingRuntime` without it (the caller's
|
|
1663
|
+
* feature-detect signal to resend with the mesh).
|
|
1664
|
+
*/
|
|
1596
1665
|
mesh?: Record<string, unknown>
|
|
1597
1666
|
}
|
|
1598
1667
|
|
|
@@ -1612,7 +1681,6 @@ export function isActiveWorkQueryRequest(value: unknown): value is ActiveWorkQue
|
|
|
1612
1681
|
if (value.nodes !== undefined && !isRecordArray(value.nodes)) return false
|
|
1613
1682
|
if (value.queue !== undefined && !isRecordArray(value.queue)) return false
|
|
1614
1683
|
if (value.recordTail !== undefined && !isNonNegativeInt(value.recordTail)) return false
|
|
1615
|
-
if (value.includeSchedulingRuntime === true && !isRecord(value.mesh)) return false
|
|
1616
1684
|
return isOptionalBoolean(value.includeTerminalDirect) && isOptionalBoolean(value.compute) && isOptionalBoolean(value.includeInputs)
|
|
1617
1685
|
&& isOptionalBoolean(value.includeSummary) && isOptionalBoolean(value.includeSchedulingRuntime) && isOptionalRecord(value.mesh)
|
|
1618
1686
|
}
|
|
@@ -1643,27 +1711,46 @@ export interface RecoveryContextQueryRequest {
|
|
|
1643
1711
|
nodeId?: string
|
|
1644
1712
|
sessionId?: string
|
|
1645
1713
|
maxRetries?: number
|
|
1714
|
+
/**
|
|
1715
|
+
* Batch: one context per node id, computed over ONE record read (answers
|
|
1716
|
+
* `contexts`). Exclusive with `nodeId`/`sessionId`. An older daemon rejects it.
|
|
1717
|
+
*/
|
|
1718
|
+
nodeIds?: readonly string[]
|
|
1646
1719
|
}
|
|
1647
1720
|
|
|
1648
1721
|
export interface RecoveryContextQueryResponse {
|
|
1649
|
-
|
|
1722
|
+
/** Single mode (nodeId/sessionId). */
|
|
1723
|
+
context?: Record<string, unknown>
|
|
1724
|
+
/** Batch mode (`nodeIds`): context per node id. */
|
|
1725
|
+
contexts?: Record<string, Record<string, unknown>>
|
|
1650
1726
|
}
|
|
1651
1727
|
|
|
1652
1728
|
export function isRecoveryContextQueryRequest(value: unknown): value is RecoveryContextQueryRequest {
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1729
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ['v', 'meshId', 'nodeId', 'sessionId', 'maxRetries', 'nodeIds'])) return false
|
|
1730
|
+
if (value.v !== TURN_IPC_PROTOCOL_VERSION || !isEvidenceIdentifier(value.meshId)) return false
|
|
1731
|
+
if (!isOptionalId(value.nodeId) || !isOptionalId(value.sessionId)) return false
|
|
1732
|
+
if (value.maxRetries !== undefined && !isNonNegativeInt(value.maxRetries)) return false
|
|
1733
|
+
if (value.nodeIds !== undefined) {
|
|
1734
|
+
if (!Array.isArray(value.nodeIds) || value.nodeIds.length === 0 || !value.nodeIds.every(isEvidenceIdentifier)) return false
|
|
1735
|
+
return value.nodeId === undefined && value.sessionId === undefined
|
|
1736
|
+
}
|
|
1737
|
+
return value.nodeId !== undefined || value.sessionId !== undefined
|
|
1658
1738
|
}
|
|
1659
1739
|
|
|
1660
1740
|
export function decodeRecoveryContextQueryRequest(value: unknown): RecoveryContextQueryRequest | null {
|
|
1661
1741
|
return isRecoveryContextQueryRequest(value) ? value : null
|
|
1662
1742
|
}
|
|
1663
1743
|
|
|
1744
|
+
function isRecoveryContextWire(value: unknown): boolean {
|
|
1745
|
+
return isRecord(value) && typeof value.consecutiveNodeFailures === 'number'
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1664
1748
|
export function isRecoveryContextQueryResponse(value: unknown): value is RecoveryContextQueryResponse {
|
|
1665
|
-
|
|
1666
|
-
|
|
1749
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ['context', 'contexts'])) return false
|
|
1750
|
+
if (value.context === undefined && value.contexts === undefined) return false
|
|
1751
|
+
if (value.context !== undefined && !isRecoveryContextWire(value.context)) return false
|
|
1752
|
+
if (value.contexts !== undefined && (!isRecord(value.contexts) || !Object.values(value.contexts).every(isRecoveryContextWire))) return false
|
|
1753
|
+
return true
|
|
1667
1754
|
}
|
|
1668
1755
|
|
|
1669
1756
|
export function decodeRecoveryContextQueryResponse(value: unknown): RecoveryContextQueryResponse | null {
|
|
@@ -1967,6 +2054,12 @@ export interface TaskStatsQueryRequest {
|
|
|
1967
2054
|
tail?: number
|
|
1968
2055
|
/** Also compute `computeMeshMissionStats` — requires `missionId`. */
|
|
1969
2056
|
rollup?: boolean
|
|
2057
|
+
/**
|
|
2058
|
+
* Batch rollups: `computeMeshMissionStats` for every id, over ONE queue read and
|
|
2059
|
+
* ONE record read (answers `missions`, `tasks` empty). Exclusive with
|
|
2060
|
+
* `taskIds`/`missionId`. An older daemon rejects the key.
|
|
2061
|
+
*/
|
|
2062
|
+
missionIds?: readonly string[]
|
|
1970
2063
|
}
|
|
1971
2064
|
|
|
1972
2065
|
export interface TaskStatsQueryResponse {
|
|
@@ -1974,16 +2067,22 @@ export interface TaskStatsQueryResponse {
|
|
|
1974
2067
|
tasks: readonly Record<string, unknown>[]
|
|
1975
2068
|
/** `MeshMissionStats`, JSON passthrough; present only when `rollup: true` was requested and satisfiable. */
|
|
1976
2069
|
mission?: Record<string, unknown>
|
|
2070
|
+
/** Batch mode: `MeshMissionStats` per requested mission id, JSON passthrough. */
|
|
2071
|
+
missions?: Record<string, Record<string, unknown>>
|
|
1977
2072
|
}
|
|
1978
2073
|
|
|
1979
2074
|
export function isTaskStatsQueryRequest(value: unknown): value is TaskStatsQueryRequest {
|
|
1980
|
-
if (!isRecord(value) || !hasOnlyKeys(value, ['v', 'meshId', 'taskIds', 'missionId', 'tail', 'rollup'])) return false
|
|
2075
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ['v', 'meshId', 'taskIds', 'missionId', 'tail', 'rollup', 'missionIds'])) return false
|
|
1981
2076
|
if (value.v !== TURN_IPC_PROTOCOL_VERSION || !isEvidenceIdentifier(value.meshId)) return false
|
|
1982
2077
|
if (value.taskIds !== undefined) {
|
|
1983
2078
|
if (!Array.isArray(value.taskIds) || value.taskIds.length === 0 || !value.taskIds.every(isEvidenceIdentifier)) return false
|
|
1984
2079
|
}
|
|
1985
2080
|
if (value.missionId !== undefined && !isEvidenceIdentifier(value.missionId)) return false
|
|
1986
2081
|
if (value.tail !== undefined && !isNonNegativeInt(value.tail)) return false
|
|
2082
|
+
if (value.missionIds !== undefined) {
|
|
2083
|
+
if (!Array.isArray(value.missionIds) || value.missionIds.length === 0 || !value.missionIds.every(isEvidenceIdentifier)) return false
|
|
2084
|
+
if (value.taskIds !== undefined || value.missionId !== undefined) return false
|
|
2085
|
+
}
|
|
1987
2086
|
if (value.rollup === true && value.missionId === undefined) return false
|
|
1988
2087
|
return isOptionalBoolean(value.rollup)
|
|
1989
2088
|
}
|
|
@@ -1993,7 +2092,8 @@ export function decodeTaskStatsQueryRequest(value: unknown): TaskStatsQueryReque
|
|
|
1993
2092
|
}
|
|
1994
2093
|
|
|
1995
2094
|
export function isTaskStatsQueryResponse(value: unknown): value is TaskStatsQueryResponse {
|
|
1996
|
-
return isRecord(value) && hasOnlyKeys(value, ['tasks', 'mission']) && isRecordArray(value.tasks) && isOptionalRecord(value.mission)
|
|
2095
|
+
return isRecord(value) && hasOnlyKeys(value, ['tasks', 'mission', 'missions']) && isRecordArray(value.tasks) && isOptionalRecord(value.mission)
|
|
2096
|
+
&& (value.missions === undefined || (isRecord(value.missions) && Object.values(value.missions).every(isRecord)))
|
|
1997
2097
|
}
|
|
1998
2098
|
|
|
1999
2099
|
export function decodeTaskStatsQueryResponse(value: unknown): TaskStatsQueryResponse | null {
|