@quantiya/codevibe-claude-plugin 2.0.74 → 2.0.76
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/.claude-plugin/plugin.json +1 -1
- package/dist/server.js +18 -18
- package/node_modules/@quantiya/codevibe-core/dist/appsync/appsync-client.d.ts +23 -24
- package/node_modules/@quantiya/codevibe-core/dist/appsync/queries.d.ts +6 -12
- package/node_modules/@quantiya/codevibe-core/dist/appsync/sync-event-client.d.ts +3 -3
- package/node_modules/@quantiya/codevibe-core/dist/appsync/sync-inbound-journal.d.ts +2 -0
- package/node_modules/@quantiya/codevibe-core/dist/appsync/sync-live-connection.d.ts +6 -1
- package/node_modules/@quantiya/codevibe-core/dist/appsync/sync-operation-journal.d.ts +5 -0
- package/node_modules/@quantiya/codevibe-core/dist/appsync/sync-workspace-outcome.d.ts +5 -3
- package/node_modules/@quantiya/codevibe-core/dist/index.js +503 -516
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.d.ts +1 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.js +397 -390
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/decision-attempt-recovery.d.ts +2 -2
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/gate-decision-submit.d.ts +2 -2
- package/node_modules/@quantiya/codevibe-core/dist/substrate/sandbox-exec.d.ts +7 -0
- package/node_modules/@quantiya/codevibe-core/dist/tool-activity/consolidator.d.ts +5 -1
- package/node_modules/@quantiya/codevibe-core/package.json +1 -1
- package/package.json +2 -2
|
@@ -2799,6 +2799,7 @@ var queries = {
|
|
|
2799
2799
|
items {
|
|
2800
2800
|
eventId
|
|
2801
2801
|
sessionId
|
|
2802
|
+
sessionGenerationId
|
|
2802
2803
|
type
|
|
2803
2804
|
source
|
|
2804
2805
|
content
|
|
@@ -2902,14 +2903,6 @@ var queries = {
|
|
|
2902
2903
|
}
|
|
2903
2904
|
`
|
|
2904
2905
|
),
|
|
2905
|
-
getGateResolutionV2: (
|
|
2906
|
-
/* GraphQL */
|
|
2907
|
-
`
|
|
2908
|
-
query GetGateResolutionV2($input: GetGateResolutionV2Input!) {
|
|
2909
|
-
getGateResolutionV2(input: $input)
|
|
2910
|
-
}
|
|
2911
|
-
`
|
|
2912
|
-
),
|
|
2913
2906
|
getGateResolution: (
|
|
2914
2907
|
/* GraphQL */
|
|
2915
2908
|
`
|
|
@@ -3253,27 +3246,17 @@ var queries = {
|
|
|
3253
3246
|
}
|
|
3254
3247
|
`
|
|
3255
3248
|
),
|
|
3256
|
-
|
|
3257
|
-
/* GraphQL */
|
|
3258
|
-
`
|
|
3259
|
-
mutation CreateEventV2($input: CreateEventV2Input!) {
|
|
3260
|
-
createEventV2(input: $input)
|
|
3261
|
-
}
|
|
3262
|
-
`
|
|
3263
|
-
),
|
|
3264
|
-
recordWorkspaceOutcomeV2: (
|
|
3249
|
+
updateEvent: (
|
|
3265
3250
|
/* GraphQL */
|
|
3266
3251
|
`
|
|
3267
|
-
mutation
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
mutation UpdateEventV2($input: UpdateEventV2Input!) {
|
|
3276
|
-
updateEventV2(input: $input)
|
|
3252
|
+
mutation UpdateEvent($input: UpdateEventInput!) {
|
|
3253
|
+
updateEvent(input: $input) {
|
|
3254
|
+
eventId sessionId sessionGenerationId type source timestamp emittedBy
|
|
3255
|
+
content metadata promptId deliveryStatus deliveredAt executedAt
|
|
3256
|
+
attachments { id type filename s3Key size width height }
|
|
3257
|
+
isEncrypted encryptionVersion writerAuthenticated writerEventNonce
|
|
3258
|
+
writerEventKind writerSessionGenerationId
|
|
3259
|
+
}
|
|
3277
3260
|
}
|
|
3278
3261
|
`
|
|
3279
3262
|
),
|
|
@@ -3317,35 +3300,19 @@ var queries = {
|
|
|
3317
3300
|
}
|
|
3318
3301
|
`
|
|
3319
3302
|
),
|
|
3320
|
-
|
|
3321
|
-
/* GraphQL */
|
|
3322
|
-
`
|
|
3323
|
-
mutation RefreshOpenPromptTtlV2($promptId: ID!) {
|
|
3324
|
-
refreshOpenPromptTtlV2(promptId: $promptId)
|
|
3325
|
-
}
|
|
3326
|
-
`
|
|
3327
|
-
),
|
|
3328
|
-
resolveOpenPromptV2: (
|
|
3303
|
+
reportSecurityPosture: (
|
|
3329
3304
|
/* GraphQL */
|
|
3330
3305
|
`
|
|
3331
|
-
mutation
|
|
3332
|
-
|
|
3306
|
+
mutation ReportSecurityPosture($input: AWSJSON!) {
|
|
3307
|
+
reportSecurityPosture(input: $input)
|
|
3333
3308
|
}
|
|
3334
3309
|
`
|
|
3335
3310
|
),
|
|
3336
|
-
|
|
3311
|
+
confirmSessionRetirement: (
|
|
3337
3312
|
/* GraphQL */
|
|
3338
3313
|
`
|
|
3339
|
-
mutation
|
|
3340
|
-
|
|
3341
|
-
}
|
|
3342
|
-
`
|
|
3343
|
-
),
|
|
3344
|
-
confirmSessionRetirementV2: (
|
|
3345
|
-
/* GraphQL */
|
|
3346
|
-
`
|
|
3347
|
-
mutation ConfirmSessionRetirementV2($input: ConfirmSessionRetirementV2Input!) {
|
|
3348
|
-
confirmSessionRetirementV2(input: $input)
|
|
3314
|
+
mutation ConfirmSessionRetirement($input: ConfirmSessionRetirementInput!) {
|
|
3315
|
+
confirmSessionRetirement(input: $input)
|
|
3349
3316
|
}
|
|
3350
3317
|
`
|
|
3351
3318
|
),
|
|
@@ -3356,6 +3323,7 @@ var queries = {
|
|
|
3356
3323
|
updateEventStatus(input: $input) {
|
|
3357
3324
|
eventId
|
|
3358
3325
|
sessionId
|
|
3326
|
+
sessionGenerationId
|
|
3359
3327
|
type
|
|
3360
3328
|
source
|
|
3361
3329
|
content
|
|
@@ -3369,14 +3337,6 @@ var queries = {
|
|
|
3369
3337
|
}
|
|
3370
3338
|
`
|
|
3371
3339
|
),
|
|
3372
|
-
updateEventStatusV2: (
|
|
3373
|
-
/* GraphQL */
|
|
3374
|
-
`
|
|
3375
|
-
mutation UpdateEventStatusV2($input: UpdateEventStatusV2Input!) {
|
|
3376
|
-
updateEventStatusV2(input: $input)
|
|
3377
|
-
}
|
|
3378
|
-
`
|
|
3379
|
-
),
|
|
3380
3340
|
registerDeviceKey: (
|
|
3381
3341
|
/* GraphQL */
|
|
3382
3342
|
`
|
|
@@ -3591,11 +3551,11 @@ var queries = {
|
|
|
3591
3551
|
}
|
|
3592
3552
|
`
|
|
3593
3553
|
),
|
|
3594
|
-
|
|
3554
|
+
submitGateDecision: (
|
|
3595
3555
|
/* GraphQL */
|
|
3596
3556
|
`
|
|
3597
|
-
mutation
|
|
3598
|
-
|
|
3557
|
+
mutation SubmitGateDecision($input: SubmitGateDecisionInput!) {
|
|
3558
|
+
submitGateDecision(input: $input) {
|
|
3599
3559
|
decisionAttemptId
|
|
3600
3560
|
acceptanceStatus
|
|
3601
3561
|
decisionClaimId
|
|
@@ -3610,11 +3570,11 @@ var queries = {
|
|
|
3610
3570
|
}
|
|
3611
3571
|
`
|
|
3612
3572
|
),
|
|
3613
|
-
|
|
3573
|
+
submitGroupDecision: (
|
|
3614
3574
|
/* GraphQL */
|
|
3615
3575
|
`
|
|
3616
|
-
mutation
|
|
3617
|
-
|
|
3576
|
+
mutation SubmitGroupDecision($input: SubmitGroupDecisionInput!) {
|
|
3577
|
+
submitGroupDecision(input: $input) {
|
|
3618
3578
|
decisionAttemptId
|
|
3619
3579
|
acceptanceStatus
|
|
3620
3580
|
decisionClaimId
|
|
@@ -3707,11 +3667,11 @@ var queries = {
|
|
|
3707
3667
|
}
|
|
3708
3668
|
`
|
|
3709
3669
|
),
|
|
3710
|
-
|
|
3670
|
+
commitGroupDecision: (
|
|
3711
3671
|
/* GraphQL */
|
|
3712
3672
|
`
|
|
3713
|
-
mutation
|
|
3714
|
-
|
|
3673
|
+
mutation CommitGroupDecision($input: CommitGroupDecisionInput!) {
|
|
3674
|
+
commitGroupDecision(input: $input) {
|
|
3715
3675
|
taskGroupId decisionClaimId commitStatus workflowStatus groupStatus committedAt
|
|
3716
3676
|
}
|
|
3717
3677
|
}
|
|
@@ -3893,6 +3853,9 @@ var queries = {
|
|
|
3893
3853
|
onEventCreated(sessionId: $sessionId) {
|
|
3894
3854
|
eventId
|
|
3895
3855
|
sessionId
|
|
3856
|
+
sessionGenerationId
|
|
3857
|
+
syncEventRevision
|
|
3858
|
+
syncImmutableIdentityDigest
|
|
3896
3859
|
type
|
|
3897
3860
|
source
|
|
3898
3861
|
content
|
|
@@ -4151,22 +4114,6 @@ function signDesktopSyncInput(action, data, userId, keys, issuedAtEpochMs) {
|
|
|
4151
4114
|
desktopProof: Object.freeze({ ...proof, signature })
|
|
4152
4115
|
});
|
|
4153
4116
|
}
|
|
4154
|
-
function parseSyncEventMutationResponse(value, expected) {
|
|
4155
|
-
let bad3 = () => {
|
|
4156
|
-
throw new SyncEventClientError("INVALID_SYNC_RECEIPT");
|
|
4157
|
-
};
|
|
4158
|
-
if (typeof value == "string") {
|
|
4159
|
-
Buffer.byteLength(value) > 2048 && bad3();
|
|
4160
|
-
try {
|
|
4161
|
-
value = JSON.parse(value);
|
|
4162
|
-
} catch {
|
|
4163
|
-
bad3();
|
|
4164
|
-
}
|
|
4165
|
-
}
|
|
4166
|
-
plain(value) || bad3();
|
|
4167
|
-
let row3 = value, refreshSyncState = own(row3, "refreshSyncState");
|
|
4168
|
-
return refreshSyncState && row3.refreshSyncState !== !0 && bad3(), { receipt: parseSyncEventReceipt(Object.fromEntries(Object.entries(row3).filter(([field2]) => field2 !== "refreshSyncState")), expected), refreshSyncState };
|
|
4169
|
-
}
|
|
4170
4117
|
function parseSyncEventReceipt(value, expected) {
|
|
4171
4118
|
let bad3 = () => {
|
|
4172
4119
|
throw new SyncEventClientError("INVALID_SYNC_RECEIPT");
|
|
@@ -4213,8 +4160,8 @@ function parseSyncPromptRetentionReceipt(value, promptId2) {
|
|
|
4213
4160
|
}
|
|
4214
4161
|
}
|
|
4215
4162
|
plain(value) || bad3();
|
|
4216
|
-
let row3 = value, keys = row3.status === "REFRESHED" ? ["expiresAt", "promptId", "status"] : ["promptId", "status"];
|
|
4217
|
-
return (Object.keys(row3).sort().join(",") !== keys.join(",") || row3.promptId !== promptId2 || !ID.test(promptId2) || !["REFRESHED", "RERAISE_REQUIRED"].includes(row3.status) || row3.status === "REFRESHED" && (typeof row3.expiresAt != "number" || !Number.isSafeInteger(row3.expiresAt) || row3.expiresAt <= 0 || row3.expiresAt > 253402300799)) && bad3(), Object.freeze({ ...row3 });
|
|
4163
|
+
let row3 = value, keys = row3.status === "REFRESHED" && own(row3, "expiresAt") ? ["expiresAt", "promptId", "status"] : ["promptId", "status"];
|
|
4164
|
+
return (Object.keys(row3).sort().join(",") !== keys.join(",") || row3.promptId !== promptId2 || !ID.test(promptId2) || !["REFRESHED", "RERAISE_REQUIRED"].includes(row3.status) || row3.status === "REFRESHED" && own(row3, "expiresAt") && (typeof row3.expiresAt != "number" || !Number.isSafeInteger(row3.expiresAt) || row3.expiresAt <= 0 || row3.expiresAt > 253402300799)) && bad3(), Object.freeze({ ...row3 });
|
|
4218
4165
|
}
|
|
4219
4166
|
|
|
4220
4167
|
// src/appsync/sync-state.ts
|
|
@@ -4291,7 +4238,7 @@ function parseCompanionSyncState(value, environment, now = Date.now()) {
|
|
|
4291
4238
|
let committed = count(value.usage[`${meter}Committed`]);
|
|
4292
4239
|
count(value.usage[`${meter}Reserved`]);
|
|
4293
4240
|
let limit = count(value.usage[`${meter}Limit`]), pausedAtLimit = count(value.usage[`${meter}PauseLimit`]);
|
|
4294
|
-
pausedAtLimit > 0n && gap2 === 0n && invalid2(), value.usage[`${meter}Limit`] !== value.limits[meter] && invalid2(), committed >= limit || pausedAtLimit >= limit ? state = "PAUSED" : committed * 5n >= limit * 4n && state !== "PAUSED" && (state = "WARNING");
|
|
4241
|
+
pausedAtLimit > 0n && gap2 === 0n && invalid2(), value.usage[`${meter}Limit`] !== value.limits[meter] && invalid2(), meter === "syncUnits" && (committed >= limit || pausedAtLimit >= limit) ? state = "PAUSED" : committed * 5n >= limit * 4n && state !== "PAUSED" && (state = "WARNING");
|
|
4295
4242
|
}
|
|
4296
4243
|
value.usage.syncState !== state && invalid2();
|
|
4297
4244
|
} else (value.protocol === "SYNC_V2" && value.mode !== "SHADOW" || value.mode === "ROLLBACK_FREEZE" && value.protocol !== "FROZEN" || value.usage !== null || value.periodId !== null || value.resetAtEpochMs !== null) && invalid2();
|
|
@@ -4389,7 +4336,7 @@ function parseWorkspaceOutcomeReceipt(value, expected) {
|
|
|
4389
4336
|
}
|
|
4390
4337
|
return !exact(value, RECEIPT2) || Buffer.byteLength(JSON.stringify(value)) > 2048 || value.schemaVersion !== 1 || value.kind !== "WORKSPACE_OUTCOME" || value.state !== "ACKED" || value.sessionId !== expected.sessionId || value.sessionGenerationId !== expected.writerSessionGenerationId || value.writerEventNonce !== expected.writerAttestation?.writerEventNonce || typeof value.eventId != "string" || !UUID3.test(value.eventId) || typeof value.timestamp != "string" || !Number.isFinite(Date.parse(value.timestamp)) || new Date(value.timestamp).toISOString() !== value.timestamp || !["ADMITTED", "OMITTED_QUOTA", "LEGACY_COMMITTED"].includes(value.syncDisposition) ? bad("INVALID_SYNC_RECEIPT") : Object.freeze({ ...value });
|
|
4391
4338
|
}
|
|
4392
|
-
function
|
|
4339
|
+
function workspaceOutcomeEventReceipt(event, expected) {
|
|
4393
4340
|
return !event || event.sessionId !== expected.sessionId || event.type !== "NOTIFICATION" || event.source !== "DESKTOP" || event.writerAuthenticated !== !0 || event.writerEventKind !== "WORKSPACE_OUTCOME" || event.writerEventNonce !== expected.writerAttestation?.writerEventNonce || event.writerSessionGenerationId !== expected.writerSessionGenerationId ? bad("INVALID_SYNC_RECEIPT") : parseWorkspaceOutcomeReceipt({
|
|
4394
4341
|
schemaVersion: 1,
|
|
4395
4342
|
kind: "WORKSPACE_OUTCOME",
|
|
@@ -4399,7 +4346,7 @@ function legacyWorkspaceOutcomeReceipt(event, expected) {
|
|
|
4399
4346
|
writerEventNonce: event.writerEventNonce,
|
|
4400
4347
|
eventId: event.eventId,
|
|
4401
4348
|
timestamp: event.timestamp,
|
|
4402
|
-
syncDisposition: "
|
|
4349
|
+
syncDisposition: "ADMITTED"
|
|
4403
4350
|
}, expected);
|
|
4404
4351
|
}
|
|
4405
4352
|
|
|
@@ -7327,6 +7274,7 @@ function createDesktopInbound(options) {
|
|
|
7327
7274
|
uncertain: row3.entries.filter((e) => e.state === "UNCERTAIN" && !e.localExecuted).length
|
|
7328
7275
|
};
|
|
7329
7276
|
})),
|
|
7277
|
+
retainedCoordinates: () => options.locked(async () => Object.freeze((await read()).entries.map((e) => Object.freeze({ ...e.target })))),
|
|
7330
7278
|
pendingAcknowledgements: () => options.locked(async () => {
|
|
7331
7279
|
let row3 = await read();
|
|
7332
7280
|
return Object.freeze(row3.entries.filter((e) => e.state === "HANDED_OFF" || e.state === "UNCERTAIN").map((e) => Object.freeze({ ...e.target })));
|
|
@@ -7555,12 +7503,12 @@ function decodePromptRetention(value) {
|
|
|
7555
7503
|
return row3;
|
|
7556
7504
|
}
|
|
7557
7505
|
function createPromptRetentionJournal(store) {
|
|
7558
|
-
return Object.freeze({ run: (values, refresh, reRaise
|
|
7506
|
+
return Object.freeze({ run: (values, refresh, reRaise) => {
|
|
7559
7507
|
let promptIds = [...new Set(import_zod7.z.array(id4).max(4096).parse(values))].sort();
|
|
7560
7508
|
return store.runExclusive(async (fence) => {
|
|
7561
|
-
let row3 = await store.read(),
|
|
7509
|
+
let row3 = await store.read(), save = async () => {
|
|
7562
7510
|
await fence(), await store.write(decodePromptRetention(row3)), await fence();
|
|
7563
|
-
}, retained = row3.entries.filter((e) =>
|
|
7511
|
+
}, retained = row3.entries.filter((e) => e.status === "RERAISE_REQUIRED");
|
|
7564
7512
|
retained.length !== row3.entries.length && (row3.entries = retained, await save());
|
|
7565
7513
|
let settle = async (promptId2) => {
|
|
7566
7514
|
await fence();
|
|
@@ -7572,8 +7520,7 @@ function createPromptRetentionJournal(store) {
|
|
|
7572
7520
|
row3.entries = row3.entries.filter((e) => e.promptId !== promptId2), await save();
|
|
7573
7521
|
}, split = row3.cursor === null ? 0 : promptIds.findIndex((promptId2) => promptId2 > row3.cursor), start = split < 0 ? 0 : split, ordered = [...promptIds.slice(start), ...promptIds.slice(0, start)];
|
|
7574
7522
|
for (let promptId2 of ordered) {
|
|
7575
|
-
let
|
|
7576
|
-
if (prior?.status === "REFRESHED" && at >= prior.checkedAt && at < prior.checkAfter) continue;
|
|
7523
|
+
let prior = row3.entries.find((e) => e.promptId === promptId2);
|
|
7577
7524
|
if (!prior && row3.entries.length >= 4096) throw Error("SYNC_JOURNAL_FULL");
|
|
7578
7525
|
if (row3.cursor = promptId2, await save(), prior?.status === "RERAISE_REQUIRED") {
|
|
7579
7526
|
await settle(promptId2);
|
|
@@ -7581,13 +7528,7 @@ function createPromptRetentionJournal(store) {
|
|
|
7581
7528
|
}
|
|
7582
7529
|
await fence();
|
|
7583
7530
|
let receipt2 = parseSyncPromptRetentionReceipt(await refresh(promptId2), promptId2);
|
|
7584
|
-
await fence();
|
|
7585
|
-
let checkedAt = time4.parse(now()), next = receipt2.status === "RERAISE_REQUIRED" ? { ...receipt2, reRaiseToken: (0, import_node_crypto11.randomUUID)() } : {
|
|
7586
|
-
...receipt2,
|
|
7587
|
-
checkedAt,
|
|
7588
|
-
checkAfter: Math.max(checkedAt, Math.min(checkedAt + 864e5, receipt2.expiresAt * 1e3 - 864e5))
|
|
7589
|
-
};
|
|
7590
|
-
row3.entries = row3.entries.filter((e) => e.promptId !== promptId2), row3.entries.push(next), await save(), receipt2.status === "RERAISE_REQUIRED" && await settle(promptId2);
|
|
7531
|
+
await fence(), receipt2.status === "RERAISE_REQUIRED" && (row3.entries.push({ ...receipt2, reRaiseToken: (0, import_node_crypto11.randomUUID)() }), await save(), await settle(promptId2));
|
|
7591
7532
|
}
|
|
7592
7533
|
});
|
|
7593
7534
|
}, remove: () => store.runExclusive(async (fence) => {
|
|
@@ -7985,7 +7926,7 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
|
|
|
7985
7926
|
});
|
|
7986
7927
|
}
|
|
7987
7928
|
async shellSources() {
|
|
7988
|
-
return this.withStore(async (key) => {
|
|
7929
|
+
return this.options.assertAccount(), await this.ensureDirectory(), (await this.recordNames(".shell")).length ? this.withStore(async (key) => {
|
|
7989
7930
|
let result = [];
|
|
7990
7931
|
for (let name of await this.recordNames(".shell")) {
|
|
7991
7932
|
let id5 = name.slice(0, -6), row3 = await this.readShellSource(id5, key);
|
|
@@ -7998,7 +7939,7 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
|
|
|
7998
7939
|
});
|
|
7999
7940
|
}
|
|
8000
7941
|
return result.sort((a, b) => a.sourceId.localeCompare(b.sourceId));
|
|
8001
|
-
});
|
|
7942
|
+
}) : (this.options.assertAccount(), []);
|
|
8002
7943
|
}
|
|
8003
7944
|
/** One encrypted intent/credential record per original desktop incarnation.
|
|
8004
7945
|
* This uses the account journal's existing 256-file / 32-MiB total bound. */
|
|
@@ -8272,7 +8213,7 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
|
|
|
8272
8213
|
if (errorCode(error) !== "ENOENT") throw error;
|
|
8273
8214
|
return this.options.assertAccount(), [];
|
|
8274
8215
|
}
|
|
8275
|
-
return this.withStore(async (key) => {
|
|
8216
|
+
return await this.ensureDirectory(), (await this.recordNames(".prompt")).length ? this.withStore(async (key) => {
|
|
8276
8217
|
let results = [];
|
|
8277
8218
|
for (let name of await this.recordNames(".prompt")) {
|
|
8278
8219
|
let id5 = name.slice(0, -7), row3 = await this.readValue(id5, key, ".prompt", (value) => decodePromptPublication(value, invalid7));
|
|
@@ -8288,6 +8229,34 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
|
|
|
8288
8229
|
});
|
|
8289
8230
|
}
|
|
8290
8231
|
return results;
|
|
8232
|
+
}) : (this.options.assertAccount(), []);
|
|
8233
|
+
}
|
|
8234
|
+
/** Metadata-only inventory for preserving pre-consolidation re-raise owners.
|
|
8235
|
+
* These generations identify local receipts, never a cloud API or tier. */
|
|
8236
|
+
async promptRetentionScopes() {
|
|
8237
|
+
this.options.assertAccount();
|
|
8238
|
+
try {
|
|
8239
|
+
await import_node_fs2.promises.lstat(this.directory);
|
|
8240
|
+
} catch (error) {
|
|
8241
|
+
if (errorCode(error) !== "ENOENT") throw error;
|
|
8242
|
+
return this.options.assertAccount(), [];
|
|
8243
|
+
}
|
|
8244
|
+
return this.withStore(async (key) => {
|
|
8245
|
+
let scopes = [];
|
|
8246
|
+
for (let name of await this.recordNames(".retention")) {
|
|
8247
|
+
let id5 = name.slice(0, -10), row3 = await this.readValue(id5, key, ".retention", decodePromptRetention);
|
|
8248
|
+
if (!row3 || row3.operationId !== id5 || id5 !== stableUuid(
|
|
8249
|
+
"codevibe-sync-prompt-retention-v1\0",
|
|
8250
|
+
[row3.sessionId, row3.sessionGenerationId]
|
|
8251
|
+
)) return invalid7();
|
|
8252
|
+
let promptIds = row3.entries.filter((entry5) => entry5.status === "RERAISE_REQUIRED").map((entry5) => entry5.promptId);
|
|
8253
|
+
this.matchesScope(row3) && promptIds.length && scopes.push({
|
|
8254
|
+
sessionId: row3.sessionId,
|
|
8255
|
+
sessionGenerationId: row3.sessionGenerationId,
|
|
8256
|
+
promptIds
|
|
8257
|
+
});
|
|
8258
|
+
}
|
|
8259
|
+
return scopes;
|
|
8291
8260
|
});
|
|
8292
8261
|
}
|
|
8293
8262
|
promptRetention() {
|
|
@@ -8428,10 +8397,19 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
|
|
|
8428
8397
|
scope,
|
|
8429
8398
|
locked: (fn) => locked(`inbound-record-${id5}.lockdir`, fn),
|
|
8430
8399
|
dispatchLocked: (fn) => locked(`inbound-dispatch-${id5}.lockdir`, fn),
|
|
8431
|
-
read:
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
|
|
8400
|
+
read: async () => {
|
|
8401
|
+
this.options.assertAccount();
|
|
8402
|
+
try {
|
|
8403
|
+
await import_node_fs2.promises.lstat(this.file(id5, ".inbox"));
|
|
8404
|
+
} catch (error) {
|
|
8405
|
+
if (errorCode(error) === "ENOENT") return null;
|
|
8406
|
+
throw error;
|
|
8407
|
+
}
|
|
8408
|
+
return this.withStore((key) => this.readValue(id5, key, ".inbox", (value) => {
|
|
8409
|
+
let row3 = decodeDesktopInbound(value);
|
|
8410
|
+
return row3.operationId !== id5 ? invalid7() : (this.requireScope(row3), row3);
|
|
8411
|
+
}));
|
|
8412
|
+
},
|
|
8435
8413
|
write: (row3) => this.withStore(async (key) => {
|
|
8436
8414
|
let sealed = this.seal(row3, key);
|
|
8437
8415
|
await this.checkCapacity(Buffer.byteLength(sealed), id5 + ".inbox"), await this.write(id5, sealed, ".inbox");
|
|
@@ -9077,6 +9055,31 @@ var count3 = import_zod9.z.string().regex(/^(0|[1-9][0-9]{0,18})$/).refine((s) =
|
|
|
9077
9055
|
sameScope(value) {
|
|
9078
9056
|
return value.sessionId === this.scope.sessionId && value.sessionGenerationId === this.scope.sessionGenerationId;
|
|
9079
9057
|
}
|
|
9058
|
+
/** One finite upgrade recovery pass, not a live delivery transport. Recover
|
|
9059
|
+
* saved coordinates and previously accepted lifecycle inputs whose hints
|
|
9060
|
+
* never reached this host. Ordinary canonical Events have no lifecycle stamp
|
|
9061
|
+
* and are left to AppSync. No socket, history scan, maintenance or timer. */
|
|
9062
|
+
recoverAcceptedInputs(onCoordinate) {
|
|
9063
|
+
return this.starting || this.phase !== "new" ? Promise.reject(failure()) : (this.phase = "ready", this.starting = Promise.resolve().then(async () => {
|
|
9064
|
+
this.fence();
|
|
9065
|
+
let recovery = await this.deps.inbound.recoverable();
|
|
9066
|
+
this.fence();
|
|
9067
|
+
for (let target2 of await this.deps.inbound.pendingAcknowledgements())
|
|
9068
|
+
await this.reconcileAcknowledgement(target2);
|
|
9069
|
+
for (let target2 of recovery.pending)
|
|
9070
|
+
this.fence(), await this.reconcileReceived(await this.deps.reader.recoverCurrent(target2, this.abort.signal), target2);
|
|
9071
|
+
let cursor;
|
|
9072
|
+
do {
|
|
9073
|
+
let page = await this.deps.reader.pendingInputs(cursor, this.abort.signal);
|
|
9074
|
+
this.fence();
|
|
9075
|
+
for (let coordinate2 of page.items)
|
|
9076
|
+
await this.discoverCoordinate(coordinate2, { retainedLifecycleOnly: !0, onCoordinate });
|
|
9077
|
+
cursor = page.nextToken ?? void 0;
|
|
9078
|
+
} while (cursor);
|
|
9079
|
+
let remaining = await this.deps.inbound.recoverable();
|
|
9080
|
+
this.fence(), remaining.uncertain && this.deps.onUncertain?.(remaining.uncertain);
|
|
9081
|
+
}), this.starting);
|
|
9082
|
+
}
|
|
9080
9083
|
start() {
|
|
9081
9084
|
if (this.starting) return this.starting;
|
|
9082
9085
|
if (this.phase !== "new") return Promise.reject(failure());
|
|
@@ -9301,11 +9304,15 @@ var count3 = import_zod9.z.string().regex(/^(0|[1-9][0-9]{0,18})$/).refine((s) =
|
|
|
9301
9304
|
this.fence(), status.uncertain && this.deps.onUncertain?.(status.uncertain), this.recoveryPages = 0, this.scheduleDiscovery(PING);
|
|
9302
9305
|
}
|
|
9303
9306
|
}
|
|
9304
|
-
async discoverCoordinate(coordinate2) {
|
|
9307
|
+
async discoverCoordinate(coordinate2, upgrade) {
|
|
9305
9308
|
let retained = await this.deps.inbound.pendingAcknowledgements();
|
|
9306
9309
|
if (this.fence(), retained.some((item2) => item2.eventId === coordinate2.eventId && item2.timestamp === coordinate2.timestamp)) return;
|
|
9307
9310
|
let event = await this.deps.reader.pendingInput(coordinate2, this.abort.signal);
|
|
9308
|
-
this.fence(), event
|
|
9311
|
+
if (this.fence(), !event) {
|
|
9312
|
+
if (upgrade) throw new SyncReadClientError("SYNC_READ_UNAVAILABLE", "EVENT_FETCH_UNAVAILABLE");
|
|
9313
|
+
return;
|
|
9314
|
+
}
|
|
9315
|
+
upgrade && (event.syncLifecycleVersion !== 1 || event.syncLegacyProjection === 1) || (upgrade?.onCoordinate?.(coordinate2), event.deliveryStatus === "EXECUTED" ? await this.deps.inbound.acknowledgeExecuted({ ...event, deliveryStatus: "EXECUTED" }) : await this.deps.inbound.stageDiscovered(event) === "RECEIVED" && await this.deliver(event, { timestamp: event.timestamp, eventRevision: event.syncEventRevision }));
|
|
9309
9316
|
}
|
|
9310
9317
|
startPings() {
|
|
9311
9318
|
this.pingTimer = setInterval(() => {
|
|
@@ -10968,11 +10975,11 @@ function parseGroupOperationResult(raw, operation) {
|
|
|
10968
10975
|
}
|
|
10969
10976
|
function parseGroupDecisionCommitResult(raw) {
|
|
10970
10977
|
if (!raw || typeof raw != "object" || Array.isArray(raw))
|
|
10971
|
-
throw new Error("
|
|
10978
|
+
throw new Error("commitGroupDecision: malformed result");
|
|
10972
10979
|
let value = raw;
|
|
10973
|
-
if (typeof value.taskGroupId != "string" || typeof value.decisionClaimId != "string" || !["COMMITTED", "ALREADY_COMMITTED", "PENDING_RECOVERY"].includes(String(value.commitStatus)) || !["COMPLETE", "PENDING_ERROR"].includes(String(value.workflowStatus))) throw new Error("
|
|
10980
|
+
if (typeof value.taskGroupId != "string" || typeof value.decisionClaimId != "string" || !["COMMITTED", "ALREADY_COMMITTED", "PENDING_RECOVERY"].includes(String(value.commitStatus)) || !["COMPLETE", "PENDING_ERROR"].includes(String(value.workflowStatus))) throw new Error("commitGroupDecision: malformed identity or status");
|
|
10974
10981
|
let pending = value.commitStatus === "PENDING_RECOVERY";
|
|
10975
|
-
if (pending !== (value.workflowStatus === "PENDING_ERROR") || pending && (value.groupStatus !== null || value.committedAt !== null) || !pending && (!["COMPLETE", "HALTED"].includes(String(value.groupStatus)) || typeof value.committedAt != "string" || !Number.isFinite(Date.parse(value.committedAt)))) throw new Error("
|
|
10982
|
+
if (pending !== (value.workflowStatus === "PENDING_ERROR") || pending && (value.groupStatus !== null || value.committedAt !== null) || !pending && (!["COMPLETE", "HALTED"].includes(String(value.groupStatus)) || typeof value.committedAt != "string" || !Number.isFinite(Date.parse(value.committedAt)))) throw new Error("commitGroupDecision: contradictory result state");
|
|
10976
10983
|
return value;
|
|
10977
10984
|
}
|
|
10978
10985
|
function optionalCount(source2, key) {
|
|
@@ -11613,14 +11620,11 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
11613
11620
|
throw [
|
|
11614
11621
|
mutations.createEvent,
|
|
11615
11622
|
mutations.updateEventStatus,
|
|
11616
|
-
mutations.
|
|
11617
|
-
mutations.
|
|
11618
|
-
mutations.recordWorkspaceOutcomeV2,
|
|
11619
|
-
mutations.reportSecurityPostureV2,
|
|
11623
|
+
mutations.updateEvent,
|
|
11624
|
+
mutations.reportSecurityPosture,
|
|
11620
11625
|
queries.listEvents,
|
|
11621
11626
|
queries.listSupervisionEvents,
|
|
11622
|
-
queries.getGateResolution
|
|
11623
|
-
queries.getGateResolutionV2
|
|
11627
|
+
queries.getGateResolution
|
|
11624
11628
|
].includes(query) && syncUserId === this.currentUserId && syncEpoch === this.syncDisplayEpoch && ["UPDATE_REQUIRED", "AUTHORITY_UNAVAILABLE", "SYNC_BLOCKED"].includes(first.errorType ?? "") && this.resetCompanionSyncDisplay(), new AppSyncGraphQLError({
|
|
11625
11629
|
message: first.message,
|
|
11626
11630
|
errorType: first.errorType,
|
|
@@ -11738,19 +11742,6 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
11738
11742
|
throw this.publishCompanionSyncDisplay(userId, null, epoch, sequence), error;
|
|
11739
11743
|
}
|
|
11740
11744
|
}
|
|
11741
|
-
/** Reuse only the server-unexpired protocol selection, never its entitlement
|
|
11742
|
-
* or usage as admission authority. Every selected cloud operation still
|
|
11743
|
-
* authorizes itself. Explicit status/quota refreshes remain fresh reads. */
|
|
11744
|
-
async getCompanionSyncRoute(signal) {
|
|
11745
|
-
let userId = this.getCurrentUserId(), epoch = this.syncDisplayEpoch, check = () => {
|
|
11746
|
-
if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), epoch !== this.syncDisplayEpoch) throw new SyncEventClientError("INVALID_SYNC_STATE");
|
|
11747
|
-
};
|
|
11748
|
-
check();
|
|
11749
|
-
let cached = this.companionSyncStatusSnapshot(userId);
|
|
11750
|
-
if (cached) return { protocol: cached.protocol };
|
|
11751
|
-
let state = await this.getCompanionSyncState(signal);
|
|
11752
|
-
return check(), { protocol: state.protocol };
|
|
11753
|
-
}
|
|
11754
11745
|
/** Subscribe to validated reads already performed by this client. No new
|
|
11755
11746
|
* request, persistent journal, producer grant or retry is created here. */
|
|
11756
11747
|
subscribeCompanionSyncState(userId, listener) {
|
|
@@ -11800,8 +11791,8 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
11800
11791
|
for (let entry5 of this.syncDisplayListeners) this.notifyCompanionSyncDisplay(entry5);
|
|
11801
11792
|
return state;
|
|
11802
11793
|
}
|
|
11803
|
-
/** Signed closed safety fact
|
|
11804
|
-
*
|
|
11794
|
+
/** Signed closed safety fact. The cloud owns availability/accounting policy;
|
|
11795
|
+
* no client status read or transport selection precedes this operation.
|
|
11805
11796
|
* Success confirms canonical persistence, never phone/render delivery. */
|
|
11806
11797
|
async reportSecurityPostureIfSelected(sessionScope, posture, signal) {
|
|
11807
11798
|
let scope = {
|
|
@@ -11810,11 +11801,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
11810
11801
|
expectedSessionKeyGen: sessionScope.sessionKeyGen ?? SESSION_KEY_GEN_ABSENT_SENTINEL,
|
|
11811
11802
|
posture
|
|
11812
11803
|
}, userId = this.getCurrentUserId();
|
|
11813
|
-
this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
|
|
11814
|
-
let state = await this.getCompanionSyncRoute(signal);
|
|
11815
|
-
if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), state.protocol === "LEGACY") return null;
|
|
11816
|
-
if (state.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
|
|
11817
|
-
if (!scope.sessionGenerationId) throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
|
|
11804
|
+
if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), !scope.sessionGenerationId) throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
|
|
11818
11805
|
let input = makeSyncSecurityPostureInput(userId, { ...scope, sessionGenerationId: scope.sessionGenerationId }), identity = await keychainManager.getDeviceIdentity();
|
|
11819
11806
|
if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), !identity) throw new SyncEventClientError("SYNC_IDENTITY_UNAVAILABLE");
|
|
11820
11807
|
if (this.tokens && this.tokens.expiresAt <= Date.now() && await this.refreshTokens(this.tokens, signal), this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), getConfig().environment !== this.environment) throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
@@ -11825,22 +11812,20 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
11825
11812
|
{ privateKeyB64: identity.privateKey, publicKeyB64: identity.publicKey },
|
|
11826
11813
|
Date.now()
|
|
11827
11814
|
), response = await this.graphqlRequest(
|
|
11828
|
-
mutations.
|
|
11815
|
+
mutations.reportSecurityPosture,
|
|
11829
11816
|
{ input: JSON.stringify(signed) },
|
|
11830
11817
|
!0,
|
|
11831
11818
|
signal,
|
|
11832
11819
|
userId,
|
|
11833
11820
|
8192
|
|
11834
11821
|
);
|
|
11835
|
-
return this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), parseSyncSecurityPostureReceipt(response?.data?.
|
|
11822
|
+
return this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), parseSyncSecurityPostureReceipt(response?.data?.reportSecurityPosture, input);
|
|
11836
11823
|
}
|
|
11837
11824
|
/** Explicit bounded read plane. No registration, paging or legacy fallback
|
|
11838
11825
|
* occurs at construction; lifecycle owners persist and supply credentials. */
|
|
11839
11826
|
async desktopSyncReadClient(sessionScope, signal) {
|
|
11840
11827
|
let scope = { ...sessionScope }, userId = this.getCurrentUserId();
|
|
11841
11828
|
this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
|
|
11842
|
-
let state = await this.getCompanionSyncRoute(signal);
|
|
11843
|
-
if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), state.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
|
|
11844
11829
|
let config = getConfig();
|
|
11845
11830
|
if (config.environment !== this.environment || !config.aws.syncHttpUrl) throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
11846
11831
|
return new DesktopSyncReadClient({
|
|
@@ -11853,15 +11838,8 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
11853
11838
|
if (this.assertSyncAccount(userId), !identity) throw new SyncEventClientError("SYNC_IDENTITY_UNAVAILABLE");
|
|
11854
11839
|
return { privateKeyB64: identity.privateKey, publicKeyB64: identity.publicKey };
|
|
11855
11840
|
},
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
try {
|
|
11859
|
-
let response = await this.graphqlRequest(queries.getGateResolutionV2, { input }, !0, requestSignal, userId, 8192);
|
|
11860
|
-
return this.assertSyncAccount(userId), this.assertSyncReadAdmission(scope.sessionId), _AppSyncClient.throwIfAborted(requestSignal), response?.data?.getGateResolutionV2;
|
|
11861
|
-
} catch (error) {
|
|
11862
|
-
throw this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(requestSignal), error instanceof AppSyncGraphQLError ? syncReadResponseError({ ok: !1, errorCode: error.responseMessage }) : error;
|
|
11863
|
-
}
|
|
11864
|
-
},
|
|
11841
|
+
// Retained Event-coordinate reads only. Product gate recovery uses the
|
|
11842
|
+
// canonical getGateResolution; no removed V2 query is wired here.
|
|
11865
11843
|
getToken: async (requestSignal) => {
|
|
11866
11844
|
if (this.assertSyncAccount(userId), this.tokens && this.tokens.expiresAt <= Date.now() && await this.refreshTokens(this.tokens, requestSignal), this.assertSyncAccount(userId), !this.tokens?.accessToken) throw new SyncEventClientError("SYNC_IDENTITY_UNAVAILABLE");
|
|
11867
11845
|
return this.tokens.accessToken;
|
|
@@ -11963,13 +11941,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
11963
11941
|
},
|
|
11964
11942
|
send: (action, input, signal) => (this.assertSyncAccount(userId), this.mutateDesktopSyncEvent(action, input, signal)),
|
|
11965
11943
|
isQuotaDenial: (error) => error instanceof AppSyncGraphQLError && error.errorType === "SYNC_QUOTA_EXHAUSTED",
|
|
11966
|
-
omitNewPayload: async (signal) =>
|
|
11967
|
-
this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
|
|
11968
|
-
let observed = this.companionSyncStatusSnapshot(userId), state = observed?.mode === "SHADOW" ? observed : await this.getCompanionSyncState(signal);
|
|
11969
|
-
if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), state.protocol !== "SYNC_V2" && !(state.mode === "SHADOW" && state.protocol === "LEGACY"))
|
|
11970
|
-
throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
|
|
11971
|
-
return state.usage?.syncState === "PAUSED";
|
|
11972
|
-
}
|
|
11944
|
+
omitNewPayload: async (signal) => (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), !1)
|
|
11973
11945
|
});
|
|
11974
11946
|
}
|
|
11975
11947
|
/** Closed metered tool producer; native source settlement owns journal acknowledgment. */
|
|
@@ -12142,56 +12114,64 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12142
12114
|
} }), this.assertSyncAccount(userId);
|
|
12143
12115
|
}
|
|
12144
12116
|
/**
|
|
12145
|
-
*
|
|
12146
|
-
*
|
|
12147
|
-
*
|
|
12148
|
-
* sealed source windows as a different protocol.
|
|
12117
|
+
* Both producer formats use the existing createEvent API. Retained signed
|
|
12118
|
+
* sources keep their original generation and bytes; legacy sessions keep
|
|
12119
|
+
* their supported request shape. Neither format selects accounting policy.
|
|
12149
12120
|
*/
|
|
12150
12121
|
async selectToolActivityTransport(options) {
|
|
12151
12122
|
let { sessionId, root, legacyTransport } = options;
|
|
12152
12123
|
if (typeof sessionId != "string" || !/^[A-Za-z0-9_-]{1,256}$/.test(sessionId) || legacyTransport.protocol !== void 0 && legacyTransport.protocol !== "LEGACY")
|
|
12153
12124
|
throw new SyncEventClientError("INVALID_SYNC_INPUT");
|
|
12154
12125
|
let selected = await this.selectCompanionSourceTransport({ sessionId, root });
|
|
12155
|
-
|
|
12126
|
+
if (selected.protocol === "LEGACY") return legacyTransport;
|
|
12127
|
+
let signed = this.toolActivitySyncTransport({
|
|
12156
12128
|
root,
|
|
12157
12129
|
sessionScope: selected.sessionScope,
|
|
12158
12130
|
getEncryptionContext: selected.getEncryptionContext
|
|
12159
12131
|
});
|
|
12132
|
+
return Object.freeze({ ...signed, sendRetainedLegacy: async (id5, envelope) => {
|
|
12133
|
+
if (id5 !== sessionId || envelope.backendSessionId !== sessionId || envelope.syncSessionGenerationId !== void 0)
|
|
12134
|
+
throw new SyncEventClientError("INVALID_SYNC_INPUT");
|
|
12135
|
+
if (await legacyTransport.send(id5, envelope) !== void 0) throw new SyncEventClientError("INVALID_SYNC_RECEIPT");
|
|
12136
|
+
} });
|
|
12160
12137
|
}
|
|
12161
|
-
/**
|
|
12138
|
+
/** Prepare request format from session identity, never quota/control mode.
|
|
12139
|
+
* SDK tags remain temporarily for existing source owners. They identify
|
|
12140
|
+
* journal formats, not different APIs or accounting policies. */
|
|
12162
12141
|
async selectCompanionSourceTransport(options) {
|
|
12163
12142
|
let { sessionId, root } = options;
|
|
12164
12143
|
if (typeof sessionId != "string" || !/^[A-Za-z0-9_-]{1,256}$/.test(sessionId)) throw new SyncEventClientError("INVALID_SYNC_INPUT");
|
|
12165
12144
|
let userId = this.getCurrentUserId();
|
|
12166
12145
|
this.assertSyncAccount(userId);
|
|
12167
|
-
let
|
|
12168
|
-
if (
|
|
12169
|
-
|
|
12170
|
-
|
|
12171
|
-
if (this.companionSyncStatusSnapshot(userId)?.mode !== "SHADOW") {
|
|
12172
|
-
if (existingGeneration === void 0) return Object.freeze({ protocol: "LEGACY" });
|
|
12173
|
-
throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
|
|
12174
|
-
}
|
|
12175
|
-
if (existingGeneration === void 0) {
|
|
12176
|
-
let generations = new Set([...this.syncRegistrations.get(sessionId)?.values() ?? []].filter((row3) => row3.userId === userId && (row3.scope.root ?? null) === (root ?? null)).map((row3) => row3.scope.sessionGenerationId));
|
|
12177
|
-
if (!generations.size) return Object.freeze({ protocol: "LEGACY" });
|
|
12178
|
-
if (generations.size !== 1) throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
|
|
12179
|
-
existingGeneration = [...generations][0];
|
|
12180
|
-
}
|
|
12181
|
-
}
|
|
12146
|
+
let existingGeneration = options.existingSessionGenerationId, generations = new Set([...this.syncRegistrations.get(sessionId)?.values() ?? []].filter((row3) => row3.userId === userId && row3.signedProducer !== !1 && (row3.scope.root ?? null) === (root ?? null)).map((row3) => row3.scope.sessionGenerationId));
|
|
12147
|
+
if (generations.size > 1 || existingGeneration !== void 0 && [...generations].some((value) => value !== existingGeneration))
|
|
12148
|
+
throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
|
|
12149
|
+
existingGeneration ??= [...generations][0];
|
|
12182
12150
|
let readSession = async () => {
|
|
12183
12151
|
this.assertSyncAccount(userId);
|
|
12184
12152
|
let session3 = await this.getSession(sessionId);
|
|
12185
|
-
if (this.assertSyncAccount(userId), !session3 || session3.sessionId !== sessionId || session3.userId !== userId || session3.status !== "ACTIVE" || session3.
|
|
12153
|
+
if (this.assertSyncAccount(userId), !session3 || session3.sessionId !== sessionId || session3.userId !== userId || session3.status !== "ACTIVE" || session3.sessionGenerationId != null && (typeof session3.sessionGenerationId != "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(session3.sessionGenerationId)))
|
|
12186
12154
|
throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
12187
12155
|
return session3;
|
|
12188
|
-
}, session2 = await readSession()
|
|
12156
|
+
}, session2 = await readSession();
|
|
12157
|
+
if (session2.sessionGenerationId == null || session2.isEncrypted !== !0) {
|
|
12158
|
+
if (existingGeneration !== void 0) throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
|
|
12159
|
+
return Object.freeze({ protocol: "LEGACY" });
|
|
12160
|
+
}
|
|
12161
|
+
let scope = Object.freeze({ sessionId, sessionGenerationId: session2.sessionGenerationId.toLowerCase() });
|
|
12189
12162
|
if (existingGeneration !== void 0 && existingGeneration !== scope.sessionGenerationId)
|
|
12190
12163
|
throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
|
|
12164
|
+
if (!await this.canSignDesktopSession(session2, userId)) {
|
|
12165
|
+
if (existingGeneration !== void 0) throw new SyncEventClientError("SYNC_IDENTITY_UNAVAILABLE");
|
|
12166
|
+
return Object.freeze({ protocol: "LEGACY" });
|
|
12167
|
+
}
|
|
12191
12168
|
let getEncryptionContext = async () => {
|
|
12192
12169
|
let current = await readSession();
|
|
12170
|
+
if (current.isEncrypted !== !0 || typeof current.sessionGenerationId != "string")
|
|
12171
|
+
throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
12193
12172
|
if (current.sessionGenerationId.toLowerCase() !== scope.sessionGenerationId)
|
|
12194
12173
|
throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
|
|
12174
|
+
if (!await this.canSignDesktopSession(current, userId)) throw new SyncEventClientError("SYNC_IDENTITY_UNAVAILABLE");
|
|
12195
12175
|
let sessionKeyGen = current.sessionKeyGen ?? null, sessionKey = await keychainManager.getSessionKey(sessionId, current.encryptedKeys ?? [], sessionKeyGen);
|
|
12196
12176
|
if (this.assertSyncAccount(userId), !sessionKey) throw new SyncEventClientError("SYNC_SESSION_KEY_UNAVAILABLE");
|
|
12197
12177
|
return { ...scope, sessionKey, sessionKeyGen };
|
|
@@ -12225,6 +12205,20 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12225
12205
|
}
|
|
12226
12206
|
});
|
|
12227
12207
|
}
|
|
12208
|
+
/** An ordinary subscription/reader is not authority to sign as the creator.
|
|
12209
|
+
* Read the existing identity only; never mint a replacement for this check. */
|
|
12210
|
+
async canSignDesktopSession(session2, userId) {
|
|
12211
|
+
if (session2.writerAttestationEligible !== !0 || !/^[a-f0-9]{64}$/.test(session2.creatorSigningKeySha256 ?? "")) return !1;
|
|
12212
|
+
let identity;
|
|
12213
|
+
try {
|
|
12214
|
+
identity = await keychainManager.getDeviceIdentity();
|
|
12215
|
+
} catch {
|
|
12216
|
+
return this.assertSyncAccount(userId), !1;
|
|
12217
|
+
}
|
|
12218
|
+
if (this.assertSyncAccount(userId), !identity?.privateKey || typeof identity.publicKey != "string") return !1;
|
|
12219
|
+
let raw = Buffer.from(identity.publicKey, "base64");
|
|
12220
|
+
return raw.length === 64 && raw.toString("base64") === identity.publicKey && (0, import_node_crypto17.createHash)("sha256").update(raw).digest("hex") === session2.creatorSigningKeySha256;
|
|
12221
|
+
}
|
|
12228
12222
|
/** Shared E1 producer adapter. The legacy encryption factory runs only after
|
|
12229
12223
|
* affirmative cloud LEGACY selection. V2 encrypts inside the durable source
|
|
12230
12224
|
* factory and never maps a quota omission to a successful cloud publication. */
|
|
@@ -12310,14 +12304,14 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12310
12304
|
producerKind: "PLUGIN_APPROVAL",
|
|
12311
12305
|
ownerToken: input.ownerToken
|
|
12312
12306
|
});
|
|
12313
|
-
return this.
|
|
12307
|
+
return this.resolveOwnedPrompt(control, () => control, async () => (await this.createEvent({
|
|
12314
12308
|
sessionId: input.sessionId,
|
|
12315
12309
|
type: "NOTIFICATION" /* NOTIFICATION */,
|
|
12316
12310
|
source: "DESKTOP" /* DESKTOP */,
|
|
12317
12311
|
resolvedPromptId: input.promptId,
|
|
12318
12312
|
ownerToken: input.ownerToken,
|
|
12319
12313
|
...input.resolutionAt !== void 0 && { resolutionAt: input.resolutionAt }
|
|
12320
|
-
}))?.promptId === input.promptId, { root });
|
|
12314
|
+
}))?.promptId === input.promptId, { root }, !0);
|
|
12321
12315
|
}
|
|
12322
12316
|
/** Core resolution carries the generation already bound to the session
|
|
12323
12317
|
* owner. Never fetch a newer Session/key to clear an older offer. */
|
|
@@ -12325,15 +12319,15 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12325
12319
|
if (!value || typeof value != "object" || Array.isArray(value) || typeof legacy != "function" || Reflect.ownKeys(value).some((field2) => typeof field2 != "string" || !["sessionId", "promptId", "sessionGenerationId", "sessionKeyGen"].includes(field2)) || Object.values(Object.getOwnPropertyDescriptors(value)).some((d) => !d.enumerable || !("value" in d) || d.value !== void 0 && d.value !== null && typeof d.value != "string"))
|
|
12326
12320
|
return Promise.reject(new SyncEventClientError("INVALID_SYNC_INPUT"));
|
|
12327
12321
|
let input = { ...value }, userId = this.getCurrentUserId();
|
|
12328
|
-
return this.
|
|
12322
|
+
return this.resolveOwnedPrompt({ sessionId: input.sessionId, promptId: input.promptId }, () => makeSyncPromptResolutionInput(userId, {
|
|
12329
12323
|
sessionId: input.sessionId,
|
|
12330
12324
|
promptId: input.promptId,
|
|
12331
12325
|
producerKind: "CORE_OFFER",
|
|
12332
12326
|
sessionGenerationId: input.sessionGenerationId,
|
|
12333
12327
|
expectedSessionKeyGen: input.sessionKeyGen ?? SESSION_KEY_GEN_ABSENT_SENTINEL
|
|
12334
|
-
}), legacy, options);
|
|
12328
|
+
}), legacy, options, input.sessionGenerationId != null);
|
|
12335
12329
|
}
|
|
12336
|
-
|
|
12330
|
+
resolveOwnedPrompt(scope, prepareControl, legacy, options, hasOriginalProof) {
|
|
12337
12331
|
let userId = this.getCurrentUserId(), input = { sessionId: scope.sessionId, promptId: scope.promptId };
|
|
12338
12332
|
if (typeof input.sessionId != "string" || !/^[A-Za-z0-9_-]{1,256}$/.test(input.sessionId) || typeof input.promptId != "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(input.promptId))
|
|
12339
12333
|
return Promise.reject(new SyncEventClientError("INVALID_SYNC_INPUT"));
|
|
@@ -12342,17 +12336,12 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12342
12336
|
check();
|
|
12343
12337
|
let resolutions = await writer.promptResolutions();
|
|
12344
12338
|
check();
|
|
12345
|
-
let
|
|
12346
|
-
|
|
12347
|
-
|
|
12348
|
-
|
|
12349
|
-
return
|
|
12350
|
-
|
|
12351
|
-
throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
|
|
12352
|
-
return check(), legacy();
|
|
12353
|
-
}, options);
|
|
12354
|
-
if (state.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
|
|
12355
|
-
return durable(prepareV2());
|
|
12339
|
+
let knownSigned = [...publications, ...resolutions].some((row3) => row3.sessionId === input.sessionId && row3.promptId === input.promptId), durable = (control) => writer.runPromptResolution(control, async (saved, fence) => (await fence(), this.finishPromptResolution(saved, options, fence)));
|
|
12340
|
+
return knownSigned || hasOriginalProof ? durable(prepareControl()) : this.resolvePromptPublication(input, async (hasV2Publication) => {
|
|
12341
|
+
if (hasV2Publication || (await writer.promptResolutions()).some((row3) => row3.sessionId === input.sessionId && row3.promptId === input.promptId))
|
|
12342
|
+
throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
|
|
12343
|
+
return check(), legacy();
|
|
12344
|
+
}, options);
|
|
12356
12345
|
})();
|
|
12357
12346
|
return this.trackSyncClosure(input.sessionId, work.then(() => {
|
|
12358
12347
|
}, () => {
|
|
@@ -12440,8 +12429,8 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12440
12429
|
userId,
|
|
12441
12430
|
{ privateKeyB64: identity.privateKey, publicKeyB64: identity.publicKey },
|
|
12442
12431
|
Date.now()
|
|
12443
|
-
), response = await this.graphqlRequest(mutations.
|
|
12444
|
-
return this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), parseSyncSessionRetirementReceipt(response?.data?.
|
|
12432
|
+
), response = await this.graphqlRequest(mutations.confirmSessionRetirement, { input: prepared }, !1, signal, userId);
|
|
12433
|
+
return this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), parseSyncSessionRetirementReceipt(response?.data?.confirmSessionRetirement, data);
|
|
12445
12434
|
}
|
|
12446
12435
|
/** Explicit terminal owner boundary. quiesce must stop AND join native,
|
|
12447
12436
|
* shell, prompt and source-recovery producers; a daemon handoff is not a
|
|
@@ -12557,8 +12546,22 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12557
12546
|
Date.now()
|
|
12558
12547
|
);
|
|
12559
12548
|
}
|
|
12560
|
-
let response = await this.graphqlRequest(mutations.
|
|
12561
|
-
|
|
12549
|
+
let response = await this.graphqlRequest(mutations.createEvent, { input: {
|
|
12550
|
+
...prepared,
|
|
12551
|
+
type: "NOTIFICATION",
|
|
12552
|
+
source: "DESKTOP",
|
|
12553
|
+
resolvedPromptId: data.promptId
|
|
12554
|
+
} }, !1, signal, userId);
|
|
12555
|
+
this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
|
|
12556
|
+
let ack = response?.data?.createEvent;
|
|
12557
|
+
if (!ack || typeof ack != "object" || Array.isArray(ack) || typeof ack.sessionId != "string" || !/^__blocked__[0-9a-f-]{36}$/.test(ack.sessionId) || ack.type !== "NOTIFICATION" || ack.source !== "DESKTOP" || ack.emittedBy !== "SYSTEM" || ack.promptId !== data.promptId)
|
|
12558
|
+
throw new SyncEventClientError("INVALID_SYNC_RECEIPT");
|
|
12559
|
+
return parseSyncPromptResolutionReceipt({
|
|
12560
|
+
sessionId: data.sessionId,
|
|
12561
|
+
promptId: ack.promptId,
|
|
12562
|
+
state: "RESOLVED",
|
|
12563
|
+
controlClass: "PROMPT_OWNERSHIP"
|
|
12564
|
+
}, data);
|
|
12562
12565
|
}
|
|
12563
12566
|
/** Monotonic control transition; safe retry means re-read canonical status,
|
|
12564
12567
|
* not retrying the provider input or manufacturing a full Event response. */
|
|
@@ -12574,52 +12577,71 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12574
12577
|
userId,
|
|
12575
12578
|
{ privateKeyB64: identity.privateKey, publicKeyB64: identity.publicKey },
|
|
12576
12579
|
Date.now()
|
|
12577
|
-
), response = await this.graphqlRequest(mutations.
|
|
12578
|
-
|
|
12580
|
+
), response = await this.graphqlRequest(mutations.updateEventStatus, { input: prepared }, !1, signal, userId);
|
|
12581
|
+
this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
|
|
12582
|
+
let event = response?.data?.updateEventStatus;
|
|
12583
|
+
if (!event || typeof event != "object" || Array.isArray(event)) throw new SyncEventClientError("INVALID_SYNC_RECEIPT");
|
|
12584
|
+
return parseSyncStatusReceipt({
|
|
12585
|
+
sessionId: event.sessionId,
|
|
12586
|
+
sessionGenerationId: event.sessionGenerationId ?? data.sessionGenerationId,
|
|
12587
|
+
eventId: event.eventId,
|
|
12588
|
+
timestamp: event.timestamp,
|
|
12589
|
+
type: event.type,
|
|
12590
|
+
source: event.source,
|
|
12591
|
+
deliveryStatus: event.deliveryStatus,
|
|
12592
|
+
deliveredAt: event.deliveredAt,
|
|
12593
|
+
...event.executedAt !== void 0 && event.executedAt !== null && { executedAt: event.executedAt }
|
|
12594
|
+
}, data);
|
|
12579
12595
|
}
|
|
12580
|
-
/**
|
|
12581
|
-
* must persist each receipt/progress before advancing its refresh batch. */
|
|
12596
|
+
/** Compatibility helper over the existing batch API; no expiry is invented. */
|
|
12582
12597
|
async refreshDesktopSyncPrompt(promptId2, signal) {
|
|
12583
12598
|
if (_AppSyncClient.throwIfAborted(signal), typeof promptId2 != "string" || !/^[A-Za-z0-9_-]{1,256}$/.test(promptId2))
|
|
12584
12599
|
throw new SyncEventClientError("INVALID_SYNC_INPUT");
|
|
12585
|
-
let
|
|
12586
|
-
|
|
12587
|
-
|
|
12588
|
-
|
|
12600
|
+
let missing = await this.refreshOpenPromptTtl([promptId2], signal);
|
|
12601
|
+
return parseSyncPromptRetentionReceipt({
|
|
12602
|
+
promptId: promptId2,
|
|
12603
|
+
status: missing.includes(promptId2) ? "RERAISE_REQUIRED" : "REFRESHED"
|
|
12604
|
+
}, promptId2);
|
|
12589
12605
|
}
|
|
12590
|
-
/**
|
|
12591
|
-
*
|
|
12606
|
+
/** One canonical batch route. Retained generations identify only the local
|
|
12607
|
+
* re-raise journal; they cannot select a cloud API or accounting policy. */
|
|
12592
12608
|
async refreshSessionOpenPromptTtl(options, reRaise) {
|
|
12593
12609
|
let { sessionId, root } = options, promptIds = [...options.promptIds];
|
|
12594
12610
|
if (!promptIds.length) return;
|
|
12595
12611
|
let userId = this.getCurrentUserId();
|
|
12596
12612
|
this.assertSyncAccount(userId), this.assertSyncReadAdmission(sessionId);
|
|
12597
|
-
let
|
|
12598
|
-
|
|
12599
|
-
let missing = await this.refreshOpenPromptTtl(promptIds);
|
|
12600
|
-
this.assertSyncAccount(userId);
|
|
12601
|
-
for (let promptId2 of missing) {
|
|
12602
|
-
if (this.assertSyncReadAdmission(sessionId), await reRaise(promptId2) === "RETRY") throw new Error("SYNC_PROMPT_RERAISE_PENDING");
|
|
12603
|
-
this.assertSyncAccount(userId);
|
|
12604
|
-
}
|
|
12605
|
-
return;
|
|
12606
|
-
}
|
|
12607
|
-
this.rememberSyncRegistration({ ...selected.sessionScope, root });
|
|
12613
|
+
let retained = await this.desktopSyncWriter({ root }).promptRetentionScopes(), generations = new Set([...this.syncRegistrations.get(sessionId)?.values() ?? []].filter((row3) => row3.userId === userId && (row3.scope.root ?? null) === (root ?? null)).map((row3) => row3.scope.sessionGenerationId));
|
|
12614
|
+
this.assertSyncAccount(userId), this.assertSyncReadAdmission(sessionId);
|
|
12608
12615
|
let check = () => {
|
|
12609
12616
|
this.assertSyncAccount(userId), this.assertSyncReadAdmission(sessionId);
|
|
12610
|
-
},
|
|
12611
|
-
promptIds
|
|
12612
|
-
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
|
|
12616
|
-
|
|
12617
|
-
|
|
12618
|
-
|
|
12619
|
-
|
|
12620
|
-
|
|
12621
|
-
|
|
12622
|
-
|
|
12617
|
+
}, batch, refresh = async (promptId2) => {
|
|
12618
|
+
check(), batch ??= this.refreshOpenPromptTtl(promptIds).then((missing2) => new Set(missing2));
|
|
12619
|
+
let missing = await batch;
|
|
12620
|
+
return check(), { promptId: promptId2, status: missing.has(promptId2) ? "RERAISE_REQUIRED" : "REFRESHED" };
|
|
12621
|
+
}, raise = async (promptId2, token4) => {
|
|
12622
|
+
check();
|
|
12623
|
+
let result = await reRaise(promptId2, token4);
|
|
12624
|
+
return check(), result;
|
|
12625
|
+
}, work = (async () => {
|
|
12626
|
+
let handled = /* @__PURE__ */ new Set();
|
|
12627
|
+
for (let owner of retained.filter((scope) => scope.sessionId === sessionId)) {
|
|
12628
|
+
let owned = promptIds.filter((id5) => owner.promptIds.includes(id5));
|
|
12629
|
+
if (!owned.length) continue;
|
|
12630
|
+
let sessionScope = { sessionId, sessionGenerationId: owner.sessionGenerationId };
|
|
12631
|
+
await this.desktopSyncWriter({ root, sessionScope }).promptRetention().run(owned, refresh, raise);
|
|
12632
|
+
for (let id5 of owned) handled.add(id5);
|
|
12633
|
+
}
|
|
12634
|
+
let remaining = promptIds.filter((id5) => !handled.has(id5));
|
|
12635
|
+
if (remaining.length)
|
|
12636
|
+
if (generations.size === 1) {
|
|
12637
|
+
let sessionScope = { sessionId, sessionGenerationId: [...generations][0] };
|
|
12638
|
+
await this.desktopSyncWriter({ root, sessionScope }).promptRetention().run(remaining, refresh, raise);
|
|
12639
|
+
} else {
|
|
12640
|
+
let missing = await this.refreshOpenPromptTtl(remaining);
|
|
12641
|
+
check();
|
|
12642
|
+
for (let id5 of missing) if (await raise(id5) === "RETRY") throw new Error("SYNC_PROMPT_RERAISE_PENDING");
|
|
12643
|
+
}
|
|
12644
|
+
})();
|
|
12623
12645
|
this.trackSyncClosure(sessionId, work.then(() => {
|
|
12624
12646
|
}, () => {
|
|
12625
12647
|
})), await work;
|
|
@@ -12644,7 +12666,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12644
12666
|
userId,
|
|
12645
12667
|
{ privateKeyB64: identity.privateKey, publicKeyB64: identity.publicKey },
|
|
12646
12668
|
Date.now()
|
|
12647
|
-
), field2 = action === "CREATE_EVENT" ? "
|
|
12669
|
+
), field2 = action === "CREATE_EVENT" ? "createEvent" : "updateEvent", response;
|
|
12648
12670
|
try {
|
|
12649
12671
|
response = await this.graphqlRequest(mutations[field2], { input: prepared }, !1, signal, userId, void 0, check);
|
|
12650
12672
|
} catch (error) {
|
|
@@ -12668,15 +12690,13 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12668
12690
|
throw error;
|
|
12669
12691
|
}
|
|
12670
12692
|
this.assertSyncAccount(userId);
|
|
12671
|
-
let
|
|
12672
|
-
if (
|
|
12673
|
-
|
|
12674
|
-
|
|
12675
|
-
|
|
12676
|
-
|
|
12677
|
-
|
|
12678
|
-
}
|
|
12679
|
-
return result.receipt;
|
|
12693
|
+
let value = response?.data?.[field2];
|
|
12694
|
+
if (!value || typeof value != "object" || Array.isArray(value))
|
|
12695
|
+
throw new SyncEventClientError("INVALID_SYNC_RECEIPT");
|
|
12696
|
+
return parseSyncEventReceipt(
|
|
12697
|
+
Object.fromEntries(["eventId", "sessionId", "type", "source", "timestamp", "emittedBy"].map((key) => [key, value[key]])),
|
|
12698
|
+
data
|
|
12699
|
+
);
|
|
12680
12700
|
}
|
|
12681
12701
|
/**
|
|
12682
12702
|
* Create a session
|
|
@@ -12802,27 +12822,13 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12802
12822
|
// MARK: - Event Operations
|
|
12803
12823
|
/** The workspace owner retains its existing durable outbox. Never put a
|
|
12804
12824
|
* second journal around it, re-encrypt it, or choose the current generation.
|
|
12805
|
-
*
|
|
12825
|
+
* Existing createEvent owns cloud policy and returns its authenticated Event.
|
|
12806
12826
|
*/
|
|
12807
12827
|
async submitWorkspaceOutcome(value, options = {}) {
|
|
12808
12828
|
let input = snapshotWorkspaceOutcomeInput(value), userId = this.getCurrentUserId();
|
|
12809
|
-
this.assertSyncAccount(userId);
|
|
12810
|
-
let
|
|
12811
|
-
|
|
12812
|
-
if (route.protocol === "LEGACY") {
|
|
12813
|
-
if (options.requiresV2) throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
|
|
12814
|
-
let result = await this.createEvent(input);
|
|
12815
|
-
return this.assertSyncAccount(userId), legacyWorkspaceOutcomeReceipt(result, input);
|
|
12816
|
-
}
|
|
12817
|
-
await options.beforeV2?.(), this.assertSyncAccount(userId);
|
|
12818
|
-
let response = await this.graphqlRequest(
|
|
12819
|
-
mutations.recordWorkspaceOutcomeV2,
|
|
12820
|
-
{ input: JSON.stringify(input) },
|
|
12821
|
-
!1,
|
|
12822
|
-
void 0,
|
|
12823
|
-
userId
|
|
12824
|
-
);
|
|
12825
|
-
return this.assertSyncAccount(userId), parseWorkspaceOutcomeReceipt(response?.data?.recordWorkspaceOutcomeV2, input);
|
|
12829
|
+
this.assertSyncAccount(userId), await options.beforeV2?.(), this.assertSyncAccount(userId);
|
|
12830
|
+
let event = await this.createEvent(input);
|
|
12831
|
+
return this.assertSyncAccount(userId), workspaceOutcomeEventReceipt(event, input);
|
|
12826
12832
|
}
|
|
12827
12833
|
/**
|
|
12828
12834
|
* Create an event
|
|
@@ -12882,14 +12888,20 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12882
12888
|
* row/Event had already aged out — the caller re-raises those (§6a-4
|
|
12883
12889
|
* return-driven re-raise). No-ops on an empty list (no network call).
|
|
12884
12890
|
*/
|
|
12885
|
-
async refreshOpenPromptTtl(promptIds) {
|
|
12886
|
-
|
|
12887
|
-
|
|
12888
|
-
|
|
12889
|
-
|
|
12890
|
-
let
|
|
12891
|
-
|
|
12892
|
-
|
|
12891
|
+
async refreshOpenPromptTtl(promptIds, signal) {
|
|
12892
|
+
let ids = [...new Set(promptIds)];
|
|
12893
|
+
if (ids.length > 4096 || ids.some((id5) => typeof id5 != "string" || !/^[A-Za-z0-9_-]{1,256}$/.test(id5)))
|
|
12894
|
+
throw new SyncEventClientError("INVALID_SYNC_INPUT");
|
|
12895
|
+
if (_AppSyncClient.throwIfAborted(signal), ids.length === 0) return [];
|
|
12896
|
+
let userId = this.getCurrentUserId();
|
|
12897
|
+
this.assertSyncAccount(userId);
|
|
12898
|
+
let MAX_BATCH = 100, agedOut = [];
|
|
12899
|
+
for (let i = 0; i < ids.length; i += MAX_BATCH) {
|
|
12900
|
+
let chunk = ids.slice(i, i + MAX_BATCH), response = await this.graphqlRequest(mutations.refreshOpenPromptTtl, { promptIds: chunk }, !1, signal, userId);
|
|
12901
|
+
this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
|
|
12902
|
+
let returned = response.data?.refreshOpenPromptTtl;
|
|
12903
|
+
if (!Array.isArray(returned) || new Set(returned).size !== returned.length || returned.some((id5) => typeof id5 != "string" || !chunk.includes(id5)))
|
|
12904
|
+
throw new SyncEventClientError("INVALID_SYNC_RECEIPT");
|
|
12893
12905
|
returned.length > 0 && agedOut.push(...returned);
|
|
12894
12906
|
}
|
|
12895
12907
|
return agedOut;
|
|
@@ -12911,19 +12923,19 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12911
12923
|
source: "MOBILE" /* MOBILE */,
|
|
12912
12924
|
type: expected.type
|
|
12913
12925
|
}), this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal));
|
|
12914
|
-
let
|
|
12915
|
-
if (
|
|
12916
|
-
if (requiredSessionGenerationId !== void 0 && route.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
|
|
12917
|
-
if (route.protocol === "LEGACY") {
|
|
12926
|
+
let scopes = [...this.syncRegistrations.get(input.sessionId)?.values() ?? []].filter((row3) => row3.userId === userId);
|
|
12927
|
+
if (requiredSessionGenerationId === void 0 && !scopes.some((row3) => row3.signedProducer !== !1)) {
|
|
12918
12928
|
let response = await this.graphqlRequest(mutations.updateEventStatus, { input }, !1, signal, userId);
|
|
12919
12929
|
return this.assertSyncAccount(userId), response.data.updateEventStatus;
|
|
12920
12930
|
}
|
|
12921
12931
|
if (input.deliveryStatus !== "DELIVERED" && input.deliveryStatus !== "EXECUTED") throw new SyncEventClientError("INVALID_SYNC_INPUT");
|
|
12922
12932
|
let session2 = await this.getSession(input.sessionId);
|
|
12923
12933
|
if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), !session2 || session2.sessionId !== input.sessionId || session2.userId !== userId || session2.status !== "ACTIVE" || typeof session2.sessionGenerationId != "string") throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
12924
|
-
let
|
|
12934
|
+
let generation = session2.sessionGenerationId.toLowerCase();
|
|
12925
12935
|
if (requiredSessionGenerationId !== void 0 && generation !== requiredSessionGenerationId) throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
|
|
12926
12936
|
if (scopes.length && !scopes.some((row3) => row3.scope.sessionGenerationId === generation)) throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
|
|
12937
|
+
if (!await this.canSignDesktopSession(session2, userId)) throw new SyncEventClientError("SYNC_IDENTITY_UNAVAILABLE");
|
|
12938
|
+
_AppSyncClient.throwIfAborted(signal);
|
|
12927
12939
|
let receipt2 = await this.updateDesktopSyncEventStatus({
|
|
12928
12940
|
...input,
|
|
12929
12941
|
clientOperationId: (0, import_uuid5.v4)(),
|
|
@@ -12939,13 +12951,16 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12939
12951
|
* List events for a session
|
|
12940
12952
|
*/
|
|
12941
12953
|
async listEvents(sessionId, source2, limit) {
|
|
12942
|
-
let
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
|
|
12947
|
-
|
|
12948
|
-
|
|
12954
|
+
let userId = this.getCurrentUserId(), epoch = this.syncReadEpoch;
|
|
12955
|
+
this.assertSyncAccount(userId), this.assertSyncReadAdmission(sessionId);
|
|
12956
|
+
let response = await this.graphqlRequest(queries.listEvents, { sessionId, source: source2, limit }, !1, void 0, userId);
|
|
12957
|
+
if (this.assertSyncAccount(userId), this.assertSyncReadAdmission(sessionId), epoch !== this.syncReadEpoch) throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
12958
|
+
let items = response.data?.listEvents?.items;
|
|
12959
|
+
if (!Array.isArray(items)) throw new Error("listEvents returned an invalid page");
|
|
12960
|
+
let expectedGeneration = this.activeSubscriptions.get(sessionId)?.syncSessionGenerationId;
|
|
12961
|
+
if (items.some((item2) => !item2 || item2.sessionId !== sessionId || expectedGeneration && item2.sessionGenerationId != null && item2.sessionGenerationId !== expectedGeneration))
|
|
12962
|
+
throw new SyncReadClientError("INVALID_SYNC_READ_RESPONSE");
|
|
12963
|
+
return items;
|
|
12949
12964
|
}
|
|
12950
12965
|
/**
|
|
12951
12966
|
* Strongly-consistent, paginated supervision history used to close the
|
|
@@ -12953,13 +12968,11 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
12953
12968
|
* can merge each page through the same strict event classifier as live data.
|
|
12954
12969
|
*/
|
|
12955
12970
|
async listSupervisionEvents(input) {
|
|
12956
|
-
let
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
|
|
12960
|
-
|
|
12961
|
-
}
|
|
12962
|
-
let page = (await this.graphqlRequest(queries.listSupervisionEvents, input)).data?.listSupervisionEvents;
|
|
12971
|
+
let expected = { ...input }, userId = this.getCurrentUserId(), epoch = this.syncReadEpoch;
|
|
12972
|
+
this.assertSyncAccount(userId), this.assertSyncReadAdmission(expected.sessionId);
|
|
12973
|
+
let response = await this.graphqlRequest(queries.listSupervisionEvents, expected, !1, void 0, userId);
|
|
12974
|
+
if (this.assertSyncAccount(userId), this.assertSyncReadAdmission(expected.sessionId), epoch !== this.syncReadEpoch) throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
12975
|
+
let page = response.data?.listSupervisionEvents;
|
|
12963
12976
|
if (!page || !Array.isArray(page.items))
|
|
12964
12977
|
throw new Error("listSupervisionEvents returned an invalid page");
|
|
12965
12978
|
if (page.nextToken !== void 0 && page.nextToken !== null && typeof page.nextToken != "string")
|
|
@@ -13397,18 +13410,18 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
13397
13410
|
* result is deliberately not subscribed: it fences the submitting client but
|
|
13398
13411
|
* never stands in for the durable GATE_RESOLUTION Event.
|
|
13399
13412
|
*/
|
|
13400
|
-
async
|
|
13401
|
-
let { promptKind: _promptKind, ...semanticInput } = request3, response = await this.graphqlRequest(mutations.
|
|
13413
|
+
async submitGateDecision(request3, canonicalRequestHash) {
|
|
13414
|
+
let { promptKind: _promptKind, ...semanticInput } = request3, response = await this.graphqlRequest(mutations.submitGateDecision, {
|
|
13402
13415
|
input: { ...semanticInput, canonicalRequestHash }
|
|
13403
13416
|
});
|
|
13404
|
-
return parseDecisionSubmissionResult(response.data?.
|
|
13417
|
+
return parseDecisionSubmissionResult(response.data?.submitGateDecision);
|
|
13405
13418
|
}
|
|
13406
13419
|
/** P16/P20 TaskGroup-native decision admission (CLAIM, not workflow COMMIT). */
|
|
13407
|
-
async
|
|
13408
|
-
let { promptKind: _promptKind, ...semanticInput } = request3, response = await this.graphqlRequest(mutations.
|
|
13420
|
+
async submitGroupDecision(request3, canonicalRequestHash) {
|
|
13421
|
+
let { promptKind: _promptKind, ...semanticInput } = request3, response = await this.graphqlRequest(mutations.submitGroupDecision, {
|
|
13409
13422
|
input: { ...semanticInput, canonicalRequestHash }
|
|
13410
13423
|
});
|
|
13411
|
-
return parseDecisionSubmissionResult(response.data?.
|
|
13424
|
+
return parseDecisionSubmissionResult(response.data?.submitGroupDecision);
|
|
13412
13425
|
}
|
|
13413
13426
|
async authorizeGroupTerminalOperation(input) {
|
|
13414
13427
|
let response = await this.graphqlRequest(mutations.authorizeGroupTerminalOperation, { input });
|
|
@@ -13434,46 +13447,29 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
13434
13447
|
let response = await this.graphqlRequest(mutations.prepareGroupKeep, { input });
|
|
13435
13448
|
return parseGroupOperationResult(response.data?.prepareGroupKeep, "prepareGroupKeep");
|
|
13436
13449
|
}
|
|
13437
|
-
async
|
|
13438
|
-
let response = await this.graphqlRequest(mutations.
|
|
13439
|
-
return parseGroupDecisionCommitResult(response.data?.
|
|
13450
|
+
async commitGroupDecision(input) {
|
|
13451
|
+
let response = await this.graphqlRequest(mutations.commitGroupDecision, { input });
|
|
13452
|
+
return parseGroupDecisionCommitResult(response.data?.commitGroupDecision);
|
|
13440
13453
|
}
|
|
13441
13454
|
/** Owner-scoped recovery point-read for a locally durable attempt receipt. */
|
|
13442
13455
|
async getDecisionAttempt(input) {
|
|
13443
13456
|
let response = await this.graphqlRequest(queries.getDecisionAttempt, { input });
|
|
13444
13457
|
return parseDecisionAttemptResult(response.data?.getDecisionAttempt);
|
|
13445
13458
|
}
|
|
13446
|
-
/**
|
|
13447
|
-
*
|
|
13459
|
+
/** One canonical recovery API. The cloud verifies owner/history authority
|
|
13460
|
+
* and, when supplied, the exact generation. No accounting-route/status read
|
|
13461
|
+
* or second delivery transport may block decision recovery. */
|
|
13448
13462
|
async getGateResolution(input) {
|
|
13449
13463
|
let expected = { ...input }, userId = this.getCurrentUserId(), epoch = this.syncReadEpoch;
|
|
13450
|
-
this.assertSyncAccount(userId), this.assertSyncReadAdmission(expected.sessionId)
|
|
13451
|
-
|
|
13464
|
+
this.assertSyncAccount(userId), this.assertSyncReadAdmission(expected.sessionId), expected.sessionGenerationId !== void 0 && validateSyncResolutionScope(
|
|
13465
|
+
{ ...expected, sessionGenerationId: expected.sessionGenerationId },
|
|
13466
|
+
() => {
|
|
13467
|
+
throw new SyncReadClientError("INVALID_SYNC_READ_INPUT");
|
|
13468
|
+
}
|
|
13469
|
+
);
|
|
13470
|
+
let response = await this.graphqlRequest(queries.getGateResolution, { input: expected }, !1, void 0, userId);
|
|
13452
13471
|
if (this.assertSyncAccount(userId), this.assertSyncReadAdmission(expected.sessionId), epoch !== this.syncReadEpoch) throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
13453
|
-
|
|
13454
|
-
let response = await this.graphqlRequest(
|
|
13455
|
-
queries.getGateResolution,
|
|
13456
|
-
{ input: { sessionId: expected.sessionId, promptId: expected.promptId } },
|
|
13457
|
-
!1,
|
|
13458
|
-
void 0,
|
|
13459
|
-
userId
|
|
13460
|
-
);
|
|
13461
|
-
if (this.assertSyncAccount(userId), this.assertSyncReadAdmission(expected.sessionId), epoch !== this.syncReadEpoch) throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
13462
|
-
return response.data?.getGateResolution;
|
|
13463
|
-
}
|
|
13464
|
-
if (route.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
|
|
13465
|
-
if (!expected.sessionGenerationId) throw new SyncReadClientError("INVALID_SYNC_READ_INPUT");
|
|
13466
|
-
validateSyncResolutionScope({ ...expected, sessionGenerationId: expected.sessionGenerationId }, () => {
|
|
13467
|
-
throw new SyncReadClientError("INVALID_SYNC_READ_INPUT");
|
|
13468
|
-
});
|
|
13469
|
-
let reader = await this.desktopSyncReadSession({ sessionId: expected.sessionId, sessionGenerationId: expected.sessionGenerationId });
|
|
13470
|
-
try {
|
|
13471
|
-
let result = await reader.gateResolution(expected.promptId);
|
|
13472
|
-
if (this.assertSyncAccount(userId), this.assertSyncReadAdmission(expected.sessionId), epoch !== this.syncReadEpoch) throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
13473
|
-
return result;
|
|
13474
|
-
} finally {
|
|
13475
|
-
await reader.close();
|
|
13476
|
-
}
|
|
13472
|
+
return response.data?.getGateResolution;
|
|
13477
13473
|
}
|
|
13478
13474
|
async applyUserDecision(input, sessionKeyBase64) {
|
|
13479
13475
|
let encryptedNotes = null;
|
|
@@ -14378,12 +14374,12 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
14378
14374
|
assertSyncReadAdmission(sessionId) {
|
|
14379
14375
|
if (this.syncRetiringSessions.has(sessionId)) throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
14380
14376
|
}
|
|
14381
|
-
rememberSyncRegistration(scope) {
|
|
14382
|
-
let userId = this.getCurrentUserId(), rows = this.syncRegistrations.get(scope.sessionId) ?? /* @__PURE__ */ new Map();
|
|
14383
|
-
rows.set(
|
|
14377
|
+
rememberSyncRegistration(scope, signedProducer = !0) {
|
|
14378
|
+
let userId = this.getCurrentUserId(), rows = this.syncRegistrations.get(scope.sessionId) ?? /* @__PURE__ */ new Map(), key = JSON.stringify([userId, scope.sessionGenerationId, scope.root ?? null]);
|
|
14379
|
+
rows.set(key, { userId, scope: { ...scope }, signedProducer: signedProducer || rows.get(key)?.signedProducer === !0 }), this.syncRegistrations.set(scope.sessionId, rows);
|
|
14384
14380
|
}
|
|
14385
14381
|
ownSyncReader(scope, reader) {
|
|
14386
|
-
this.rememberSyncRegistration(scope);
|
|
14382
|
+
this.rememberSyncRegistration(scope, !1);
|
|
14387
14383
|
let owners = this.syncReadOwners.get(scope.sessionId) ?? /* @__PURE__ */ new Set();
|
|
14388
14384
|
this.syncReadOwners.set(scope.sessionId, owners);
|
|
14389
14385
|
let closing, owner = Object.freeze({ ...reader, close: () => closing || (closing = reader.close().finally(() => {
|
|
@@ -14402,20 +14398,6 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
14402
14398
|
let pending = this.syncSubscriptionClosures.get(sessionId);
|
|
14403
14399
|
pending && await Promise.all([...pending]);
|
|
14404
14400
|
}
|
|
14405
|
-
async syncHistoryForSession(sessionId, sessionGenerationId, nextToken) {
|
|
14406
|
-
this.assertSyncReadAdmission(sessionId);
|
|
14407
|
-
let userId = this.getCurrentUserId(), session2 = await this.getSession(sessionId);
|
|
14408
|
-
if (this.assertSyncAccount(userId), this.assertSyncReadAdmission(sessionId), session2?.sessionId !== sessionId || !session2.sessionGenerationId || session2.userId !== userId || sessionGenerationId !== void 0 && sessionGenerationId !== session2.sessionGenerationId)
|
|
14409
|
-
throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
14410
|
-
let scope = { sessionId, sessionGenerationId: session2.sessionGenerationId }, state = this.activeSubscriptions.get(sessionId), live = !state?.destroyed && state?.syncSessionGenerationId === scope.sessionGenerationId ? state.syncConnection : void 0, reader = live ?? await this.desktopSyncReadSession(scope);
|
|
14411
|
-
try {
|
|
14412
|
-
let page = await reader.history(nextToken);
|
|
14413
|
-
if (this.assertSyncAccount(userId), this.assertSyncReadAdmission(sessionId), page.sessionId !== scope.sessionId || page.sessionGenerationId !== scope.sessionGenerationId) throw new SyncReadClientError("INVALID_SYNC_READ_RESPONSE");
|
|
14414
|
-
return { items: page.items.map((event) => this.syncEventForConsumer(event)), nextToken: page.nextToken };
|
|
14415
|
-
} finally {
|
|
14416
|
-
live || await reader.close();
|
|
14417
|
-
}
|
|
14418
|
-
}
|
|
14419
14401
|
/**
|
|
14420
14402
|
* Subscribe to events for a session
|
|
14421
14403
|
*/
|
|
@@ -14480,41 +14462,49 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
14480
14462
|
createSubscription(state) {
|
|
14481
14463
|
let abort = state.setupAbort = new AbortController(), current = () => !state.destroyed && !abort.signal.aborted && this.activeSubscriptions.get(state.sessionId) === state, setup = (async () => {
|
|
14482
14464
|
if (await this.joinSyncSubscriptionClosures(state.sessionId), !current()) return;
|
|
14483
|
-
let userId = this.getCurrentUserId()
|
|
14484
|
-
|
|
14485
|
-
if (this.assertSyncAccount(userId), route.protocol === "FROZEN") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
|
|
14486
|
-
if (route.protocol === "LEGACY") {
|
|
14487
|
-
this.createLegacySubscription(state);
|
|
14488
|
-
return;
|
|
14489
|
-
}
|
|
14465
|
+
let userId = this.getCurrentUserId();
|
|
14466
|
+
this.assertSyncAccount(userId);
|
|
14490
14467
|
let session2 = await this.getSession(state.sessionId);
|
|
14491
14468
|
if (!current()) return;
|
|
14492
|
-
if (this.assertSyncAccount(userId), !session2
|
|
14493
|
-
|
|
14494
|
-
|
|
14495
|
-
|
|
14496
|
-
|
|
14497
|
-
|
|
14498
|
-
|
|
14499
|
-
|
|
14469
|
+
if (this.assertSyncAccount(userId), !session2 || session2.userId !== userId || !["ACTIVE" /* ACTIVE */, "PAUSED" /* PAUSED */].includes(session2.status))
|
|
14470
|
+
throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
|
|
14471
|
+
let retainedIds = /* @__PURE__ */ new Set();
|
|
14472
|
+
state.mobileInputRecoveryHeld = !1, session2.sessionGenerationId && (state.compatibilityInboundIds = retainedIds, state.syncSessionGenerationId = session2.sessionGenerationId), this.createLegacySubscription(state), !(!session2.sessionGenerationId || !current()) && (async () => {
|
|
14473
|
+
try {
|
|
14474
|
+
let scope = { sessionId: state.sessionId, sessionGenerationId: session2.sessionGenerationId }, coordinates = await this.desktopSyncWriter({ sessionScope: scope }).inbound().retainedCoordinates();
|
|
14475
|
+
if (!current()) return;
|
|
14476
|
+
this.assertSyncAccount(userId);
|
|
14477
|
+
for (let target2 of coordinates) retainedIds.add(target2.eventId);
|
|
14478
|
+
state.mobileInputRecoveryHeld = !1;
|
|
14479
|
+
} catch {
|
|
14480
|
+
current() && (state.mobileInputRecoveryHeld = !0, logger.warn("[AppSyncClient] Mobile inputs held: retained journal requires recovery; desktop connection remains available", { sessionId: state.sessionId }), state.onError?.(new SyncEventClientError("SYNC_INBOUND_RECOVERY_REQUIRED")));
|
|
14481
|
+
return;
|
|
14482
|
+
}
|
|
14483
|
+
let connection = await this.desktopSyncLiveSession(
|
|
14484
|
+
{
|
|
14485
|
+
sessionId: state.sessionId,
|
|
14486
|
+
sessionGenerationId: session2.sessionGenerationId
|
|
14500
14487
|
},
|
|
14501
|
-
|
|
14502
|
-
current() && state.
|
|
14503
|
-
}
|
|
14504
|
-
|
|
14505
|
-
|
|
14506
|
-
|
|
14507
|
-
|
|
14508
|
-
(
|
|
14509
|
-
|
|
14510
|
-
|
|
14511
|
-
|
|
14512
|
-
|
|
14513
|
-
|
|
14514
|
-
|
|
14515
|
-
|
|
14516
|
-
|
|
14517
|
-
|
|
14488
|
+
(event) => {
|
|
14489
|
+
if (current() && shouldDeliverSubscribedEvent(event, !!state.receiveDesktopEvents)) return state.onEvent(event);
|
|
14490
|
+
},
|
|
14491
|
+
() => {
|
|
14492
|
+
},
|
|
14493
|
+
abort.signal
|
|
14494
|
+
);
|
|
14495
|
+
if (!current()) {
|
|
14496
|
+
await connection.close();
|
|
14497
|
+
return;
|
|
14498
|
+
}
|
|
14499
|
+
state.syncConnection = connection;
|
|
14500
|
+
try {
|
|
14501
|
+
await connection.recoverAcceptedInputs((coordinate2) => retainedIds.add(coordinate2.eventId));
|
|
14502
|
+
} finally {
|
|
14503
|
+
await connection.close();
|
|
14504
|
+
}
|
|
14505
|
+
})().catch(() => {
|
|
14506
|
+
current() && (logger.warn("[AppSyncClient] Retained mobile input recovery incomplete; original journal preserved", { sessionId: state.sessionId }), state.onError?.(new SyncEventClientError("SYNC_INPUT_RECOVERY_INCOMPLETE")));
|
|
14507
|
+
});
|
|
14518
14508
|
})().catch((error) => {
|
|
14519
14509
|
current() && this.handleSubscriptionError(state, error instanceof Error ? error : new Error("Sync connection failed"));
|
|
14520
14510
|
});
|
|
@@ -14530,7 +14520,9 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
14530
14520
|
receiveDesktopEvents
|
|
14531
14521
|
} = state;
|
|
14532
14522
|
try {
|
|
14533
|
-
let wsUrl = this.buildRealtimeUrl(),
|
|
14523
|
+
let wsUrl = this.buildRealtimeUrl(), owner = this.getCurrentUserId();
|
|
14524
|
+
this.assertSyncAccount(owner);
|
|
14525
|
+
let ws = new import_ws2.default(wsUrl, ["graphql-ws"]), pendingAcks = /* @__PURE__ */ new Set([
|
|
14534
14526
|
subscriptionId,
|
|
14535
14527
|
...state.supervisionSubscriptionId ? [state.supervisionSubscriptionId] : []
|
|
14536
14528
|
]);
|
|
@@ -14538,6 +14530,8 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
14538
14530
|
logger.info("[AppSyncClient] WebSocket connected", { sessionId }), ws.send(JSON.stringify({ type: "connection_init" }));
|
|
14539
14531
|
}), ws.on("message", (data) => {
|
|
14540
14532
|
try {
|
|
14533
|
+
if (state.destroyed || this.activeSubscriptions.get(sessionId) !== state || state.ws !== ws) return;
|
|
14534
|
+
this.assertSyncAccount(owner);
|
|
14541
14535
|
let message = JSON.parse(data.toString());
|
|
14542
14536
|
switch (message.type) {
|
|
14543
14537
|
case "connection_ack":
|
|
@@ -14553,8 +14547,8 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
14553
14547
|
supervisionEvent?.sessionId === sessionId && state.onSupervisionEvent?.(supervisionEvent);
|
|
14554
14548
|
break;
|
|
14555
14549
|
}
|
|
14556
|
-
let event = message.payload?.data?.onEventCreated;
|
|
14557
|
-
event && shouldDeliverSubscribedEvent(event, !!receiveDesktopEvents) && onEvent(event);
|
|
14550
|
+
let event = message.payload?.data?.onEventCreated, retainedInput = event?.source === "MOBILE" /* MOBILE */ && ["USER_PROMPT" /* USER_PROMPT */, "PROMPT_RESPONSE" /* PROMPT_RESPONSE */].includes(event.type) && (event.syncEventRevision != null || event.syncImmutableIdentityDigest != null);
|
|
14551
|
+
event && event.sessionId === sessionId && (event.sessionGenerationId == null || state.syncSessionGenerationId == null || event.sessionGenerationId === state.syncSessionGenerationId) && !(state.mobileInputRecoveryHeld && event.source === "MOBILE" /* MOBILE */ && ["USER_PROMPT" /* USER_PROMPT */, "PROMPT_RESPONSE" /* PROMPT_RESPONSE */].includes(event.type)) && !retainedInput && !state.compatibilityInboundIds?.has(event.eventId) && shouldDeliverSubscribedEvent(event, !!receiveDesktopEvents) && onEvent(event);
|
|
14558
14552
|
break;
|
|
14559
14553
|
case "ka":
|
|
14560
14554
|
this.resetKeepAliveTimer(state);
|
|
@@ -58924,6 +58918,11 @@ function buildSeatbeltProfile(workdir, execPath = process.execPath, extraReadDir
|
|
|
58924
58918
|
'(deny mach-lookup (global-name "com.apple.SecurityServer"))',
|
|
58925
58919
|
'(deny mach-lookup (global-name "com.apple.securityd"))',
|
|
58926
58920
|
'(deny mach-lookup (global-name "com.apple.securityd.xpc"))',
|
|
58921
|
+
// POSIX shared memory: grant read-data on CoreFoundation preferences shared
|
|
58922
|
+
// memory published by cfprefsd (apple.cfprefs.<uid>v1, apple.cfprefs.daemonv1).
|
|
58923
|
+
// Without this, CFPreferencesAppSynchronize fails with EPERM, breaking native
|
|
58924
|
+
// macOS agents like Codex CLI during configuration/preference synchronization.
|
|
58925
|
+
'(allow ipc-posix-shm-read-data (ipc-posix-name-prefix "apple.cfprefs."))',
|
|
58927
58926
|
// The ANCESTOR DIR ENTRIES of the workdir — each as a `(literal ...)` read,
|
|
58928
58927
|
// NOT a subpath (Stage-2 HIGH — the `/private/tmp` narrowing). When node runs
|
|
58929
58928
|
// `node <workdir>/script.js`, `Module._findPath` → `realpathSync` `lstat`s
|
|
@@ -69407,8 +69406,8 @@ async function submitGateDecision(deps, promptEntryId, payload) {
|
|
|
69407
69406
|
);
|
|
69408
69407
|
return;
|
|
69409
69408
|
}
|
|
69410
|
-
let
|
|
69411
|
-
if (!
|
|
69409
|
+
let submitDurable = client.submitGateDecision;
|
|
69410
|
+
if (!submitDurable) {
|
|
69412
69411
|
dispatchVisibleSubmitFailure(
|
|
69413
69412
|
store,
|
|
69414
69413
|
promptEntryId,
|
|
@@ -69457,9 +69456,9 @@ async function submitGateDecision(deps, promptEntryId, payload) {
|
|
|
69457
69456
|
canonicalRequestHash: receipt2.canonicalRequestHash,
|
|
69458
69457
|
decisionClaimId: null
|
|
69459
69458
|
});
|
|
69460
|
-
let result = await
|
|
69459
|
+
let result = await submitDurable.call(client, request3, receipt2.canonicalRequestHash);
|
|
69461
69460
|
if (result.decisionAttemptId !== decisionAttemptId || result.promptId !== payload.gateId)
|
|
69462
|
-
throw new Error("
|
|
69461
|
+
throw new Error("submitGateDecision returned a mismatched attempt or prompt identity");
|
|
69463
69462
|
if (result.acceptanceStatus === "REJECTED") {
|
|
69464
69463
|
let terminal = await receiptStore.markTerminal(receipt2, {
|
|
69465
69464
|
state: "REJECTED",
|
|
@@ -69702,8 +69701,8 @@ async function submitGroupGateDecision(deps, entry5, optionId, notes) {
|
|
|
69702
69701
|
return;
|
|
69703
69702
|
}
|
|
69704
69703
|
if (groupEscalation.protocolVersion === 2) {
|
|
69705
|
-
let
|
|
69706
|
-
if (!
|
|
69704
|
+
let submitDurable = deps.appsyncClient.submitGroupDecision;
|
|
69705
|
+
if (!submitDurable || groupEscalation.groupGeneration === void 0) {
|
|
69707
69706
|
dispatchVisibleSubmitFailure(
|
|
69708
69707
|
store,
|
|
69709
69708
|
entry5.id,
|
|
@@ -69753,13 +69752,13 @@ async function submitGroupGateDecision(deps, entry5, optionId, notes) {
|
|
|
69753
69752
|
canonicalRequestHash: receipt2.canonicalRequestHash,
|
|
69754
69753
|
decisionClaimId: null
|
|
69755
69754
|
});
|
|
69756
|
-
let result2 = await
|
|
69755
|
+
let result2 = await submitDurable.call(
|
|
69757
69756
|
deps.appsyncClient,
|
|
69758
69757
|
request3,
|
|
69759
69758
|
receipt2.canonicalRequestHash
|
|
69760
69759
|
);
|
|
69761
69760
|
if (result2.decisionAttemptId !== decisionAttemptId || result2.promptId !== request3.promptId)
|
|
69762
|
-
throw new Error("
|
|
69761
|
+
throw new Error("submitGroupDecision returned a mismatched attempt or prompt identity");
|
|
69763
69762
|
if (result2.acceptanceStatus === "REJECTED") {
|
|
69764
69763
|
let terminal = await receiptStore.markTerminal(receipt2, {
|
|
69765
69764
|
state: "REJECTED",
|
|
@@ -74407,7 +74406,7 @@ function createDurableResolutionAttemptHandoff(args) {
|
|
|
74407
74406
|
}, handoff;
|
|
74408
74407
|
}
|
|
74409
74408
|
async function retryExactSubmission(client, receipt2) {
|
|
74410
|
-
let result = receipt2.request.promptKind === "GATE" ? await client.
|
|
74409
|
+
let result = receipt2.request.promptKind === "GATE" ? await client.submitGateDecision?.(receipt2.request, receipt2.canonicalRequestHash) : await client.submitGroupDecision?.(receipt2.request, receipt2.canonicalRequestHash);
|
|
74411
74410
|
if (!result) throw new Error(`No ${receipt2.request.promptKind} v2 recovery transport configured`);
|
|
74412
74411
|
if (result.decisionAttemptId !== receipt2.request.decisionAttemptId || result.promptId !== promptId(receipt2)) throw new Error("Decision-attempt retry returned mismatched identity");
|
|
74413
74412
|
}
|
|
@@ -78929,6 +78928,14 @@ async function runOrchestrationShell(args) {
|
|
|
78929
78928
|
// an event actually arrives (async) — never during this synchronous setup.
|
|
78930
78929
|
subscribedEventDispatcher,
|
|
78931
78930
|
(err) => {
|
|
78931
|
+
if (err instanceof SyncEventClientError && (err.code === "SYNC_INBOUND_RECOVERY_REQUIRED" || err.code === "SYNC_INPUT_RECOVERY_INCOMPLETE")) {
|
|
78932
|
+
logger.warn("[orchestration-shell] mobile input recovery notice; connection remains available", { code: err.code }), store.dispatch({
|
|
78933
|
+
type: "SHELL_ADVISORY",
|
|
78934
|
+
source: "shell",
|
|
78935
|
+
text: err.code === "SYNC_INBOUND_RECOVERY_REQUIRED" ? "Mobile input is paused for this session because its recovery journal could not be read. Desktop remains available. Messages sent during this pause are not automatically delivered later; recovery or explicit disposition is required." : "Previously accepted mobile input recovery is incomplete. Desktop and ordinary live events remain available. Retained inputs were preserved and uncertain inputs were not replayed."
|
|
78936
|
+
});
|
|
78937
|
+
return;
|
|
78938
|
+
}
|
|
78932
78939
|
initialSubscriptionSettled || logStartupFailure("subscription", err), initialCatchUpStarted && rejectInitialSubscription(err), logger.warn("[orchestration-shell] subscribeToEvents error", {
|
|
78933
78940
|
error: err.message
|
|
78934
78941
|
});
|
|
@@ -79666,7 +79673,7 @@ async function runOrchestrationShell(args) {
|
|
|
79666
79673
|
if (prepared.callStatus === "REJECTED" || prepared.authorizationState !== "READY_TO_COMMIT" || prepared.operationReceiptHash !== receiptHash2) throw new Error(`TaskGroup keep preparation failed (${prepared.rejectionCode ?? prepared.callStatus})`);
|
|
79667
79674
|
if (await workspaceTerminalCoordinator.prepareGroupOutcome(taskGroupId, "kept", {
|
|
79668
79675
|
filesRetained
|
|
79669
|
-
}), (await args.appsyncClient.
|
|
79676
|
+
}), (await args.appsyncClient.commitGroupDecision({
|
|
79670
79677
|
sessionId: resolution.sessionId,
|
|
79671
79678
|
taskGroupId,
|
|
79672
79679
|
decisionClaimId: resolution.decisionClaimId,
|
|
@@ -79712,7 +79719,7 @@ async function runOrchestrationShell(args) {
|
|
|
79712
79719
|
taskGroupId,
|
|
79713
79720
|
filesConflicted > 0 ? "partially_reverted" : "reverted",
|
|
79714
79721
|
{ filesReverted, filesConflicted }
|
|
79715
|
-
), (await args.appsyncClient.
|
|
79722
|
+
), (await args.appsyncClient.commitGroupDecision({
|
|
79716
79723
|
sessionId: resolution.sessionId,
|
|
79717
79724
|
taskGroupId,
|
|
79718
79725
|
decisionClaimId: resolution.decisionClaimId,
|