@sema-agent/client-core 0.94.0 → 0.96.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +521 -0
- package/README.md +104 -57
- package/dist/adapt/arms.js +12 -7
- package/dist/adapt/panelTasks.js +4 -10
- package/dist/adapt/toolCards.d.ts +1 -0
- package/dist/adapt/toolCards.js +18 -5
- package/dist/adapt/wireShapes.js +5 -24
- package/dist/adapter/activeRunSelfHeal.d.ts +12 -3
- package/dist/adapter/activeRunSelfHeal.js +50 -16
- package/dist/adapter/downstream/eventToSdkMessage.js +33 -18
- package/dist/adapter/downstream/terminalToSdkResult.js +19 -12
- package/dist/adapter/runStream.js +30 -46
- package/dist/adapter/types.d.ts +7 -0
- package/dist/adapter/types.js +15 -0
- package/dist/agentSession/backgroundView.js +5 -1
- package/dist/agentSession/engineAgentRegistryRead.js +7 -5
- package/dist/agentSession/engineSessionBackgroundStop.js +25 -17
- package/dist/agentsWireCaps.d.ts +2 -0
- package/dist/agentsWireCaps.js +13 -2
- package/dist/approvalDecidedByCapability.d.ts +0 -1
- package/dist/approvalDecidedByCapability.js +2 -7
- package/dist/approvalsStreamLiveCapability.d.ts +0 -1
- package/dist/approvalsStreamLiveCapability.js +2 -6
- package/dist/atMostOnce.d.ts +8 -0
- package/dist/atMostOnce.js +36 -0
- package/dist/attachmentSeatCapability.d.ts +0 -1
- package/dist/attachmentSeatCapability.js +0 -3
- package/dist/attachmentsWireCaps.js +11 -6
- package/dist/bashExitReading.d.ts +10 -0
- package/dist/bashExitReading.js +12 -0
- package/dist/callerCwdCapability.d.ts +0 -5
- package/dist/callerCwdCapability.js +2 -13
- package/dist/centerWiringCapability.d.ts +1 -7
- package/dist/centerWiringCapability.js +18 -27
- package/dist/classifierStatus.js +4 -4
- package/dist/classifierVerdictWire.js +4 -16
- package/dist/clientSlice.js +1 -1
- package/dist/cloudConfigWireCaps.d.ts +3 -3
- package/dist/cloudConfigWireCaps.js +85 -43
- package/dist/compensations.js +1 -1
- package/dist/coreValuePorts.d.ts +11 -7
- package/dist/coreValuePorts.js +5 -8
- package/dist/credentialProvenance.d.ts +28 -0
- package/dist/credentialProvenance.js +76 -0
- package/dist/cycleOrder.d.ts +15 -0
- package/dist/cycleOrder.js +45 -0
- package/dist/decideFailureNote.js +7 -2
- package/dist/decideReceipt.d.ts +2 -1
- package/dist/decideReceipt.js +39 -14
- package/dist/declared/supportFloorDeclared.d.ts +1 -0
- package/dist/declared/supportFloorDeclared.js +5 -0
- package/dist/deviceExecutorManagementCapability.d.ts +0 -1
- package/dist/deviceExecutorManagementCapability.js +7 -16
- package/dist/deviceRebind.d.ts +88 -0
- package/dist/deviceRebind.js +242 -0
- package/dist/displayUntrusted.d.ts +8 -3
- package/dist/displayUntrusted.js +661 -63
- package/dist/engineAgentAbsence.d.ts +2 -2
- package/dist/engineAgentPanelStore.d.ts +8 -18
- package/dist/engineAgentPanelStore.js +19 -537
- package/dist/engineCapReader.d.ts +6 -6
- package/dist/engineCapReader.js +30 -43
- package/dist/engineCapsCache.d.ts +13 -2
- package/dist/engineCapsCache.js +276 -44
- package/dist/engineCredentialRequirement.d.ts +9 -0
- package/dist/engineCredentialRequirement.js +23 -0
- package/dist/engineDirectory.d.ts +79 -0
- package/dist/engineDirectory.js +186 -0
- package/dist/engineEnvSourcing.d.ts +53 -0
- package/dist/engineEnvSourcing.js +81 -0
- package/dist/engineErrorCodes.d.ts +28 -4
- package/dist/engineErrorCodes.js +68 -25
- package/dist/engineIdentity.js +2 -0
- package/dist/engineNoticeCodes.d.ts +17 -0
- package/dist/engineNoticeCodes.js +57 -3
- package/dist/engineWireSdk.js +2 -2
- package/dist/engineWordRenames.d.ts +8 -0
- package/dist/engineWordRenames.js +13 -0
- package/dist/executionLaneCapability.d.ts +2 -3
- package/dist/executionLaneCapability.js +18 -23
- package/dist/fileHistoryCaptureCapability.d.ts +14 -1
- package/dist/fileHistoryCaptureCapability.js +72 -6
- package/dist/fileHistoryLegNotice.d.ts +3 -2
- package/dist/fileHistoryLegNotice.js +51 -2
- package/dist/fleet/bgSubagentRow.d.ts +15 -0
- package/dist/fleet/bgSubagentRow.js +67 -0
- package/dist/fleet/fleetLedger.d.ts +3 -0
- package/dist/fleet/fleetLedger.js +153 -122
- package/dist/fleet/fleetProjection.d.ts +1 -3
- package/dist/fleet/fleetProjection.js +19 -19
- package/dist/fleetAgentPanelProjection.d.ts +4 -17
- package/dist/fleetAgentPanelProjection.js +7 -197
- package/dist/fleetAgentRowLike.d.ts +16 -0
- package/dist/fleetAgentRowLike.js +1 -0
- package/dist/fleetTaskDesc.js +4 -17
- package/dist/gateOutcome.d.ts +12 -1
- package/dist/gateOutcome.js +87 -18
- package/dist/gateVocabulary.d.ts +7 -2
- package/dist/gateVocabulary.js +5 -1
- package/dist/generated/engineAskFaceTables.js +1 -1
- package/dist/generated/engineFactTables.d.ts +5 -3
- package/dist/generated/engineFactTables.js +17 -4
- package/dist/generated/engineNoticeTables.js +12 -3
- package/dist/generated/sdkFactTables.d.ts +2 -0
- package/dist/generated/sdkFactTables.js +17 -0
- package/dist/generated/settingsSchemaFns.d.ts +13 -0
- package/dist/generated/settingsSchemaFns.js +75 -0
- package/dist/generated/toolNameTables.d.ts +1 -0
- package/dist/generated/toolNameTables.js +1 -0
- package/dist/headlessPermissionModeWire.d.ts +1 -1
- package/dist/headlessPermissionModeWire.js +1 -1
- package/dist/headlessReconnectWire.js +49 -20
- package/dist/hitl/allowRuleShadow.d.ts +1 -1
- package/dist/hitl/allowRuleShadow.js +49 -8
- package/dist/hitl/approvalCompleteParked.d.ts +1 -0
- package/dist/hitl/approvalCompleteParked.js +14 -0
- package/dist/hitl/approvalEndingCause.d.ts +7 -0
- package/dist/hitl/approvalEndingCause.js +71 -0
- package/dist/hitl/approvalHolds.d.ts +12 -2
- package/dist/hitl/approvalHolds.js +53 -2
- package/dist/hitl/approvalsFeed.js +23 -11
- package/dist/hitl/askGateWire.d.ts +2 -1
- package/dist/hitl/askGateWire.js +26 -1
- package/dist/hitl/askParkRowRouting.js +1 -1
- package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
- package/dist/hitl/automaticAnswerVerdict.js +15 -10
- package/dist/hitl/crashConverged.js +2 -0
- package/dist/hitl/decisionConflict.d.ts +3 -0
- package/dist/hitl/decisionConflict.js +41 -0
- package/dist/hitl/decisionRefusal.d.ts +12 -0
- package/dist/hitl/decisionRefusal.js +63 -4
- package/dist/hitl/frameRouter.d.ts +0 -1
- package/dist/hitl/frameRouter.js +32 -57
- package/dist/hitl/gateLedger.d.ts +5 -0
- package/dist/hitl/gateLedger.js +21 -0
- package/dist/hitl/hitlBridge.d.ts +17 -2
- package/dist/hitl/hitlBridge.js +91 -55
- package/dist/hitl/hitlHostSurface.js +3 -11
- package/dist/hitl/livePendingAsk.d.ts +16 -6
- package/dist/hitl/livePendingAsk.js +36 -4
- package/dist/hitl/localAllowRule.d.ts +1 -0
- package/dist/hitl/localAllowRule.js +2 -2
- package/dist/hitl/noAllowCause.d.ts +2 -1
- package/dist/hitl/noAllowCause.js +3 -2
- package/dist/hitl/parkExpiryJudgements.d.ts +19 -0
- package/dist/hitl/parkExpiryJudgements.js +46 -0
- package/dist/hitl/parkResolver.d.ts +4 -7
- package/dist/hitl/parkResolver.js +12 -34
- package/dist/hitl/parkRowBirthWait.d.ts +1 -0
- package/dist/hitl/parkRowBirthWait.js +2 -2
- package/dist/hitl/persistedRulesWire.js +5 -1
- package/dist/hitl/planReviewWire.d.ts +3 -2
- package/dist/hitl/planReviewWire.js +154 -50
- package/dist/hitl/replayedApproval.d.ts +9 -0
- package/dist/hitl/replayedApproval.js +139 -10
- package/dist/hitl/resumeRunningCard.d.ts +2 -0
- package/dist/hitl/resumeRunningCard.js +15 -4
- package/dist/hitl/sessionPolicyDeliverable.js +8 -6
- package/dist/hitl/standingRows.d.ts +18 -0
- package/dist/hitl/standingRows.js +127 -0
- package/dist/hitl/toolApprovalWire.d.ts +39 -7
- package/dist/hitl/toolApprovalWire.js +351 -61
- package/dist/hookMatcherVerdict.d.ts +1 -9
- package/dist/hookMatcherVerdict.js +21 -61
- package/dist/hooksWireCaps.js +40 -8
- package/dist/host.d.ts +5 -0
- package/dist/host.js +3 -1
- package/dist/hostCallbackGuard.d.ts +2 -0
- package/dist/hostCallbackGuard.js +31 -0
- package/dist/index.d.ts +48 -17
- package/dist/index.js +36 -15
- package/dist/interactiveInterrupt.d.ts +8 -0
- package/dist/interactiveInterrupt.js +54 -0
- package/dist/limitsWire.d.ts +5 -0
- package/dist/limitsWire.js +49 -3
- package/dist/liveModelCatalog.d.ts +95 -0
- package/dist/liveModelCatalog.js +297 -32
- package/dist/mcpEngineLeg.d.ts +25 -0
- package/dist/mcpEngineLeg.js +71 -15
- package/dist/mcpPanel.js +2 -1
- package/dist/mcpProbeCapability.d.ts +0 -5
- package/dist/mcpProbeCapability.js +2 -12
- package/dist/mcpReconnect.d.ts +1 -3
- package/dist/mcpReconnect.js +10 -5
- package/dist/memoryComplianceCapability.d.ts +0 -5
- package/dist/memoryComplianceCapability.js +2 -12
- package/dist/memoryOriginCapability.d.ts +0 -5
- package/dist/memoryOriginCapability.js +2 -12
- package/dist/memorySpecWire.js +2 -2
- package/dist/memoryVerbsWire.d.ts +1 -1
- package/dist/memoryVerbsWire.js +4 -0
- package/dist/model/liveCatalogShape.d.ts +14 -0
- package/dist/model/liveCatalogShape.js +71 -0
- package/dist/model/modelSupplyRules.d.ts +1 -0
- package/dist/model/modelSupplyRules.js +30 -9
- package/dist/model/modelsPolicy.d.ts +21 -0
- package/dist/model/modelsPolicy.js +90 -0
- package/dist/modelIdentityResolvability.d.ts +2 -2
- package/dist/modelIdentityResolvability.js +14 -12
- package/dist/modelSwitchFallback.d.ts +69 -0
- package/dist/modelSwitchFallback.js +206 -0
- package/dist/noticePresentation.d.ts +68 -0
- package/dist/noticePresentation.js +247 -0
- package/dist/notifications.js +12 -11
- package/dist/outputStyleSeatCapability.d.ts +0 -2
- package/dist/outputStyleSeatCapability.js +2 -10
- package/dist/ownKey.d.ts +8 -0
- package/dist/ownKey.js +66 -0
- package/dist/panelReduce.d.ts +114 -0
- package/dist/panelReduce.js +1135 -0
- package/dist/panelStateHolder.d.ts +17 -0
- package/dist/panelStateHolder.js +201 -0
- package/dist/peerFrames.js +13 -9
- package/dist/peerLaneCapability.d.ts +0 -1
- package/dist/peerLaneCapability.js +2 -6
- package/dist/permissionModesCapability.d.ts +0 -5
- package/dist/permissionModesCapability.js +5 -16
- package/dist/permissionRuleIssue.js +0 -3
- package/dist/permissionRulesWriteCapability.d.ts +0 -1
- package/dist/permissionRulesWriteCapability.js +2 -6
- package/dist/permissionsAllowGrantCapability.d.ts +0 -1
- package/dist/permissionsAllowGrantCapability.js +3 -9
- package/dist/permissionsDeclaration.d.ts +8 -0
- package/dist/permissionsDeclaration.js +101 -41
- package/dist/printPermissionOutcome.d.ts +12 -0
- package/dist/printPermissionOutcome.js +50 -0
- package/dist/printToolResultFrame.d.ts +1 -0
- package/dist/printToolResultFrame.js +5 -17
- package/dist/promptBlockedCopy.d.ts +5 -0
- package/dist/promptBlockedCopy.js +35 -0
- package/dist/promptDelivery.js +0 -8
- package/dist/protocolSegment.d.ts +9 -6
- package/dist/protocolSegment.js +31 -21
- package/dist/providerRejection.d.ts +4 -0
- package/dist/providerRejection.js +75 -14
- package/dist/replayBody.d.ts +12 -0
- package/dist/replayBody.js +25 -0
- package/dist/resumeRefusalCopy.d.ts +18 -1
- package/dist/resumeRefusalCopy.js +127 -32
- package/dist/retryStatus.d.ts +9 -1
- package/dist/retryStatus.js +9 -2
- package/dist/rewindArchiveCapability.d.ts +5 -14
- package/dist/rewindArchiveCapability.js +18 -61
- package/dist/rewindArchiveReading.d.ts +15 -0
- package/dist/rewindArchiveReading.js +56 -0
- package/dist/rewindEngineAction.d.ts +21 -0
- package/dist/rewindEngineAction.js +36 -0
- package/dist/rewindWireCaps.d.ts +2 -1
- package/dist/rewindWireCaps.js +1 -0
- package/dist/ruleCompileVerdict.d.ts +9 -1
- package/dist/ruleCompileVerdict.js +29 -4
- package/dist/runTerminal.d.ts +15 -12
- package/dist/runTerminal.js +60 -35
- package/dist/sandboxWire.js +13 -0
- package/dist/sdkRegistryTransit.d.ts +2 -1
- package/dist/sdkRegistryTransit.js +1 -0
- package/dist/sealedKeyCapability.d.ts +0 -5
- package/dist/sealedKeyCapability.js +3 -15
- package/dist/seam.js +4 -2
- package/dist/seatContract.d.ts +125 -34
- package/dist/seatContract.js +583 -179
- package/dist/sessionIdSegment.d.ts +1 -0
- package/dist/sessionIdSegment.js +11 -0
- package/dist/sessionMemoryErase.d.ts +1 -1
- package/dist/sessionMemoryErase.js +6 -1
- package/dist/sessionMemoryStatus.js +3 -2
- package/dist/sessionPolicyCapability.d.ts +0 -1
- package/dist/sessionPolicyCapability.js +2 -6
- package/dist/sessionReadRedactionCapability.d.ts +0 -5
- package/dist/sessionReadRedactionCapability.js +2 -13
- package/dist/sessionSyncFileHistory.d.ts +4 -0
- package/dist/sessionSyncFileHistory.js +66 -0
- package/dist/sessionSyncFileHistoryCapability.d.ts +0 -2
- package/dist/sessionSyncFileHistoryCapability.js +2 -9
- package/dist/skillToolListsCapability.d.ts +0 -2
- package/dist/skillToolListsCapability.js +2 -9
- package/dist/skillsWireCaps.d.ts +4 -0
- package/dist/skillsWireCaps.js +66 -1
- package/dist/sqlEngineCapability.d.ts +0 -1
- package/dist/sqlEngineCapability.js +9 -14
- package/dist/steerPriorityCapability.d.ts +0 -2
- package/dist/steerPriorityCapability.js +3 -12
- package/dist/storePostureCapability.d.ts +1 -5
- package/dist/storePostureCapability.js +16 -22
- package/dist/streamDrainingLegs.d.ts +6 -0
- package/dist/streamDrainingLegs.js +23 -0
- package/dist/subagent/engineCompactWire.js +13 -38
- package/dist/subagent/engineDelegatedPrompt.js +10 -6
- package/dist/subagent/engineSubagentOutput.d.ts +0 -1
- package/dist/subagent/engineSubagentOutput.js +5 -20
- package/dist/subagent/engineSubagentSteer.js +7 -5
- package/dist/subagent/engineSubagentTail.d.ts +0 -1
- package/dist/subagent/engineSubagentTail.js +7 -32
- package/dist/subagentContentStore.js +7 -18
- package/dist/supportFloor.d.ts +1 -0
- package/dist/supportFloor.js +15 -14
- package/dist/systemReminderTag.d.ts +1 -0
- package/dist/systemReminderTag.js +8 -0
- package/dist/terminalStatuses.d.ts +30 -0
- package/dist/terminalStatuses.js +67 -0
- package/dist/toolHistoryMismatch.d.ts +0 -3
- package/dist/toolHistoryMismatch.js +3 -7
- package/dist/toolResult.d.ts +6 -1
- package/dist/toolResult.js +90 -37
- package/dist/toolResultContent.d.ts +2 -0
- package/dist/toolResultContent.js +63 -0
- package/dist/types/engineState.d.ts +2 -1
- package/dist/usageAnalytics.d.ts +146 -0
- package/dist/usageAnalytics.js +335 -0
- package/dist/userInvokedSkillsCapability.d.ts +0 -2
- package/dist/userInvokedSkillsCapability.js +2 -9
- package/dist/webSearchBackendCapability.d.ts +0 -1
- package/dist/webSearchBackendCapability.js +3 -7
- package/dist/webSearchWireCaps.js +3 -11
- package/dist/wireErrorTriage.d.ts +2 -0
- package/dist/wireErrorTriage.js +34 -5
- package/dist/wireFailureShape.d.ts +23 -2
- package/dist/wireFailureShape.js +88 -43
- package/dist/wireRefusalCopy.js +2 -18
- package/dist/workflowClient.js +7 -11
- package/dist/workflowsJournalCapability.d.ts +0 -1
- package/dist/workflowsJournalCapability.js +2 -6
- package/dist/writeProtectionCapability.d.ts +0 -1
- package/dist/writeProtectionCapability.js +5 -10
- package/docs/INTEGRATION-CLIENTS.md +2279 -27
- package/package.json +5 -5
- package/dist/engineCapsGenerationGuard.d.ts +0 -4
- package/dist/engineCapsGenerationGuard.js +0 -19
- package/dist/panelRunningHistory.d.ts +0 -22
- package/dist/panelRunningHistory.js +0 -82
- package/dist/registryConflict.d.ts +0 -3
- package/dist/registryConflict.js +0 -44
package/dist/seatContract.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { PERMISSION_MODE_WORDS, REASONING_EFFORT_WORDS } from "./taskRequestWords.js";
|
|
2
|
+
import { liveDefaultModelCopy, liveModelRowCopy } from "./model/liveCatalogShape.js";
|
|
3
|
+
import { REWIND_MODES } from "./rewindWireCaps.js";
|
|
4
|
+
import { guardedRead, ownDataField, ownDataRefusalKeyOf, ownSendableField, readOwnDataValue } from "./ownKey.js";
|
|
2
5
|
const bad = (reason, field) => field === undefined ? { reason } : { reason, field };
|
|
3
6
|
const nested = (prefix, verdict) => {
|
|
4
7
|
const path = verdict.field === undefined
|
|
@@ -10,9 +13,73 @@ const nested = (prefix, verdict) => {
|
|
|
10
13
|
return bad(reason, path);
|
|
11
14
|
};
|
|
12
15
|
const isObject = (v) => typeof v === "object" && v !== null;
|
|
16
|
+
const isPlainRecord = (v) => {
|
|
17
|
+
if (!isObject(v) || Array.isArray(v))
|
|
18
|
+
return false;
|
|
19
|
+
const proto = Object.getPrototypeOf(v);
|
|
20
|
+
return proto === Object.prototype || proto === null;
|
|
21
|
+
};
|
|
13
22
|
const isAbsent = (v) => typeof v === "undefined";
|
|
14
23
|
const optionalString = (v) => isAbsent(v) || typeof v === "string";
|
|
24
|
+
const isFolderPath = (v) => typeof v === "string" && v.length > 0;
|
|
15
25
|
const inTuple = (tuple, v) => tuple.includes(v);
|
|
26
|
+
const own = (o, k) => ownSendableField(o, k);
|
|
27
|
+
const ownItems = (a) => {
|
|
28
|
+
const n = ownDataField(a, "length");
|
|
29
|
+
const out = [];
|
|
30
|
+
if (typeof n !== "number")
|
|
31
|
+
return out;
|
|
32
|
+
for (let i = 0; i < n; i += 1)
|
|
33
|
+
out.push(own(a, String(i)));
|
|
34
|
+
return out;
|
|
35
|
+
};
|
|
36
|
+
const firstAccessorPath = (root) => {
|
|
37
|
+
const seen = new Set();
|
|
38
|
+
const stack = [[root, ""]];
|
|
39
|
+
while (stack.length > 0) {
|
|
40
|
+
const [v, path] = stack.pop();
|
|
41
|
+
if (typeof v !== "object" || v === null || seen.has(v))
|
|
42
|
+
continue;
|
|
43
|
+
seen.add(v);
|
|
44
|
+
for (const k of Reflect.ownKeys(v)) {
|
|
45
|
+
if (typeof k !== "string")
|
|
46
|
+
continue;
|
|
47
|
+
const d = Reflect.getOwnPropertyDescriptor(v, k);
|
|
48
|
+
if (d === undefined)
|
|
49
|
+
continue;
|
|
50
|
+
const at = path === "" ? k : `${path}.${k}`;
|
|
51
|
+
if (!Object.hasOwn(d, "value"))
|
|
52
|
+
return at;
|
|
53
|
+
stack.push([d.value, at]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
};
|
|
58
|
+
const NOT_PLAIN_DATA = "must be a plain enumerable data property (accessors are refused and never executed)";
|
|
59
|
+
const seatCheck = (fn) => (v) => {
|
|
60
|
+
try {
|
|
61
|
+
const at = firstAccessorPath(v);
|
|
62
|
+
if (at !== undefined)
|
|
63
|
+
return bad(NOT_PLAIN_DATA, at);
|
|
64
|
+
return fn(v);
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
const key = ownDataRefusalKeyOf(e);
|
|
68
|
+
return key !== undefined ? bad(NOT_PLAIN_DATA, key) : bad("payload could not be read");
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const seatCheckAt = (fn) => (v, field) => {
|
|
72
|
+
try {
|
|
73
|
+
const at = firstAccessorPath(v);
|
|
74
|
+
if (at !== undefined)
|
|
75
|
+
return bad(NOT_PLAIN_DATA, `${field}.${at}`);
|
|
76
|
+
return fn(v, field);
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
const key = ownDataRefusalKeyOf(e);
|
|
80
|
+
return key !== undefined ? bad(NOT_PLAIN_DATA, `${field}.${key}`) : bad("payload could not be read", field);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
16
83
|
export const TOOL_PERMISSION_REQUEST_ID_DOMAINS = Object.freeze([
|
|
17
84
|
"live:",
|
|
18
85
|
"durable:",
|
|
@@ -52,14 +119,16 @@ const SEAT_EVENT_TYPE_TUPLE = [
|
|
|
52
119
|
"error",
|
|
53
120
|
"tool_permission_resolved",
|
|
54
121
|
];
|
|
55
|
-
export const SEAT_EVENT_TYPES = SEAT_EVENT_TYPE_TUPLE;
|
|
122
|
+
export const SEAT_EVENT_TYPES = Object.freeze(SEAT_EVENT_TYPE_TUPLE);
|
|
56
123
|
const CHROME_EVENT_KIND_TUPLE = [
|
|
57
124
|
"panel_task",
|
|
58
125
|
"notification_terminal",
|
|
59
126
|
"prompt_suggestions",
|
|
60
127
|
"subagent_lifecycle",
|
|
128
|
+
"text_segment_end",
|
|
129
|
+
"thinking_segment_end",
|
|
61
130
|
];
|
|
62
|
-
export const CHROME_EVENT_KINDS = CHROME_EVENT_KIND_TUPLE;
|
|
131
|
+
export const CHROME_EVENT_KINDS = Object.freeze(CHROME_EVENT_KIND_TUPLE);
|
|
63
132
|
const LANE_PROOF_LANE_TUPLE = ["main", "subagent", "workflow"];
|
|
64
133
|
export const SEAT_CHROME_ENVELOPE_KEYS = ["kind", "laneProof"];
|
|
65
134
|
export const HITL_RESOLUTION_OUTCOMES = [
|
|
@@ -72,7 +141,7 @@ export const HITL_RESOLUTION_OUTCOMES = [
|
|
|
72
141
|
"decline",
|
|
73
142
|
"cancel",
|
|
74
143
|
];
|
|
75
|
-
export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder"]);
|
|
144
|
+
export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession"]);
|
|
76
145
|
const notReported = () => Object.freeze({ kind: "not_reported" });
|
|
77
146
|
const malformedReading = () => Object.freeze({ kind: "malformed" });
|
|
78
147
|
const reported = (available) => Object.freeze({ kind: "reported", available });
|
|
@@ -145,6 +214,8 @@ export function watchSeatCapability(store, name, onReading) {
|
|
|
145
214
|
}
|
|
146
215
|
const SEAT_CAPABILITY_PHRASES = Object.freeze({
|
|
147
216
|
pickFolder: Object.freeze({ action: "Opening a folder", ability: "show a folder picker", support: "folder picker support" }),
|
|
217
|
+
rewind: Object.freeze({ action: "Rewinding to an earlier message", ability: "rewind this session", support: "rewind support" }),
|
|
218
|
+
recents: Object.freeze({ action: "Remembering recent folders", ability: "remember recent folders", support: "recent folders support" }), patchSession: Object.freeze({ action: "Renaming or pinning a conversation", ability: "rename or pin conversations", support: "rename and pin support" }),
|
|
148
219
|
});
|
|
149
220
|
export function seatCapabilityUnavailableDetail(name, reading) {
|
|
150
221
|
const phrase = Object.hasOwn(SEAT_CAPABILITY_PHRASES, name)
|
|
@@ -167,355 +238,629 @@ export function seatCapabilityUnavailableDetail(name, reading) {
|
|
|
167
238
|
return `${phrase.action} isn't available: this app hasn't reported ${phrase.support}.`;
|
|
168
239
|
return `${phrase.action} isn't available: this app's support report couldn't be read.`;
|
|
169
240
|
}
|
|
241
|
+
const NO_TIME = Number.NEGATIVE_INFINITY;
|
|
242
|
+
const stampMs = (v) => {
|
|
243
|
+
if (typeof v !== "string")
|
|
244
|
+
return NO_TIME;
|
|
245
|
+
const t = Date.parse(v);
|
|
246
|
+
return Number.isFinite(t) ? t : NO_TIME;
|
|
247
|
+
};
|
|
248
|
+
const softField = (o, key) => typeof o === "object" && o !== null ? guardedRead(() => readOwnDataValue(o, key)) : undefined;
|
|
249
|
+
const softItems = (a) => {
|
|
250
|
+
const isArray = guardedRead(() => Array.isArray(a));
|
|
251
|
+
if (isArray !== true)
|
|
252
|
+
return undefined;
|
|
253
|
+
const n = softField(a, "length");
|
|
254
|
+
if (typeof n !== "number" || !Number.isSafeInteger(n) || n < 0)
|
|
255
|
+
return undefined;
|
|
256
|
+
const out = [];
|
|
257
|
+
for (let i = 0; i < n; i += 1)
|
|
258
|
+
out.push(softField(a, String(i)));
|
|
259
|
+
return out;
|
|
260
|
+
};
|
|
261
|
+
export function recentFoldersOf(input) {
|
|
262
|
+
const sessions = softItems(softField(input, "sessions"));
|
|
263
|
+
const registered = softItems(softField(input, "registered"));
|
|
264
|
+
if (sessions === undefined && registered === undefined)
|
|
265
|
+
return null;
|
|
266
|
+
const byPath = new Map();
|
|
267
|
+
let order = 0;
|
|
268
|
+
const place = (path, at) => {
|
|
269
|
+
const cur = byPath.get(path);
|
|
270
|
+
order += 1;
|
|
271
|
+
if (cur === undefined)
|
|
272
|
+
byPath.set(path, { at, order });
|
|
273
|
+
else if (at > cur.at)
|
|
274
|
+
cur.at = at;
|
|
275
|
+
};
|
|
276
|
+
for (const row of registered ?? []) {
|
|
277
|
+
const path = softField(row, "path");
|
|
278
|
+
if (isFolderPath(path))
|
|
279
|
+
place(path, stampMs(softField(row, "lastUsedAt")));
|
|
280
|
+
}
|
|
281
|
+
for (const rec of sessions ?? []) {
|
|
282
|
+
const cwd = softField(rec, "cwd");
|
|
283
|
+
if (!isFolderPath(cwd))
|
|
284
|
+
continue;
|
|
285
|
+
const active = stampMs(softField(rec, "lastActivityAt"));
|
|
286
|
+
place(cwd, active !== NO_TIME ? active : stampMs(softField(rec, "createdAt")));
|
|
287
|
+
}
|
|
288
|
+
return [...byPath.entries()]
|
|
289
|
+
.sort(([, x], [, y]) => (x.at === y.at ? x.order - y.order : x.at > y.at ? -1 : 1))
|
|
290
|
+
.map(([path]) => path);
|
|
291
|
+
}
|
|
292
|
+
export async function readRecentFolders(input) {
|
|
293
|
+
const capability = guardedRead(() => input.capability);
|
|
294
|
+
const list = guardedRead(() => input.list);
|
|
295
|
+
const sessions = guardedRead(() => input.sessions);
|
|
296
|
+
let registered;
|
|
297
|
+
let host = "skipped";
|
|
298
|
+
let unreadableRows = 0;
|
|
299
|
+
if (capability !== undefined && seatCapabilityUnavailableDetail("recents", capability) === undefined) {
|
|
300
|
+
try {
|
|
301
|
+
const items = softItems(softField(await list(), "folders"));
|
|
302
|
+
if (items === undefined) {
|
|
303
|
+
host = "unreadable";
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
const rows = [];
|
|
307
|
+
for (const item of items) {
|
|
308
|
+
const path = softField(item, "path");
|
|
309
|
+
if (!isFolderPath(path)) {
|
|
310
|
+
unreadableRows += 1;
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
const lastUsedAt = softField(item, "lastUsedAt");
|
|
314
|
+
rows.push(typeof lastUsedAt === "string" ? { path, lastUsedAt } : { path });
|
|
315
|
+
}
|
|
316
|
+
if (items.length > 0 && rows.length === 0) {
|
|
317
|
+
host = "unreadable";
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
registered = rows;
|
|
321
|
+
host = "listed";
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
host = "unreadable";
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return Object.freeze({ folders: recentFoldersOf({ sessions, registered }), host, unreadableRows });
|
|
330
|
+
}
|
|
170
331
|
export const PERMISSION_MODE_INTENTS = [...PERMISSION_MODE_WORDS];
|
|
171
332
|
export const ATTACHMENT_IDS_PER_TASK_CAP = 16;
|
|
172
333
|
export const SEAT_REASONING_EFFORTS = [...REASONING_EFFORT_WORDS];
|
|
173
334
|
export const SEAT_TURN_SETTINGS_KEYS = ["ultracode"];
|
|
335
|
+
export const SEAT_TURN_SETTINGS_ORIGINS = Object.freeze({
|
|
336
|
+
ultracode: Object.freeze({ carriedBy: "renderer" }),
|
|
337
|
+
webSearch: Object.freeze({ hostSupplied: "联网检索的每请求配置来自宿主的设置源(可能带检索服务的凭据与私网地址);渲染端没有设置文件,也不该持有凭据" }),
|
|
338
|
+
hooks: Object.freeze({ hostSupplied: "hooks 表来自宿主的设置文件(宿主经设置端口与 hooksForWire 投影);渲染端没有设置文件、也不执行本机 hook" }),
|
|
339
|
+
resolved: Object.freeze({ hostSupplied: "设置解析器的生效快照(hooks / env / model / 已解析权限)由宿主跑解析器得出;渲染端没有设置源可解析" }),
|
|
340
|
+
outputStyle: Object.freeze({ hostSupplied: "输出风格正文由宿主的兜底层随请求带(风格文件在宿主);渲染端只选名字,不持正文" }),
|
|
341
|
+
});
|
|
342
|
+
export const SEAT_REWIND_INTENT_KEYS = ["mode", "targetMessageUuid"];
|
|
174
343
|
export const ATTACHMENT_UPLOAD_REQUEST_KEYS = ["name", "mimeType", "bytes"];
|
|
344
|
+
export const SESSION_ROW_PATCH_REQUEST_KEYS = Object.freeze(["sessionId", "title", "pinned"]);
|
|
175
345
|
export const SESSION_SEARCH_RESULT_KEYS = ["sessionId", "title", "matches"];
|
|
176
346
|
export const GET_TRANSCRIPT_RESULT_KEYS = ["sessionId", "messages"];
|
|
177
|
-
const checkLocalSessionRecord = (s) => {
|
|
347
|
+
const checkLocalSessionRecord = seatCheck((s) => {
|
|
178
348
|
if (!isObject(s))
|
|
179
349
|
return bad("session record is not an object");
|
|
180
|
-
if (typeof s
|
|
350
|
+
if (typeof own(s, "sessionId") !== "string")
|
|
181
351
|
return bad("sessionId must be a string", "sessionId");
|
|
182
|
-
if (!optionalString(s
|
|
352
|
+
if (!optionalString(own(s, "engineSessionId")))
|
|
183
353
|
return bad("engineSessionId must be a string when present", "engineSessionId");
|
|
184
|
-
if (!optionalString(s
|
|
354
|
+
if (!optionalString(own(s, "model")))
|
|
185
355
|
return bad("model must be a string when present", "model");
|
|
186
|
-
if (!optionalString(s
|
|
356
|
+
if (!optionalString(own(s, "title")))
|
|
187
357
|
return bad("title must be a string when present", "title");
|
|
188
|
-
|
|
358
|
+
const cwd = own(s, "cwd");
|
|
359
|
+
if (!isAbsent(cwd) && !isFolderPath(cwd)) {
|
|
189
360
|
return bad("cwd must be a non-empty path string when present (absent = no folder chosen)", "cwd");
|
|
190
361
|
}
|
|
191
|
-
if (typeof s
|
|
362
|
+
if (typeof own(s, "isRunning") !== "boolean")
|
|
192
363
|
return bad("isRunning must be a boolean", "isRunning");
|
|
193
|
-
if (typeof s
|
|
364
|
+
if (typeof own(s, "createdAt") !== "string")
|
|
194
365
|
return bad("createdAt must be an ISO-8601 string", "createdAt");
|
|
195
|
-
if (!optionalString(s
|
|
366
|
+
if (!optionalString(own(s, "lastActivityAt")))
|
|
196
367
|
return bad("lastActivityAt must be a string when present", "lastActivityAt");
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const okQueue = Array.isArray(q) && q.every((row) => isObject(row) && typeof row
|
|
368
|
+
const q = own(s, "queuedMessages");
|
|
369
|
+
if (!isAbsent(q)) {
|
|
370
|
+
const okQueue = Array.isArray(q) && ownItems(q).every((row) => isObject(row) && typeof own(row, "uuid") === "string" && typeof own(row, "text") === "string");
|
|
200
371
|
if (!okQueue)
|
|
201
372
|
return bad("queuedMessages must be an array of {uuid,text}", "queuedMessages");
|
|
202
373
|
}
|
|
203
|
-
|
|
374
|
+
const parked = own(s, "parked");
|
|
375
|
+
if (!isAbsent(parked) && typeof parked !== "boolean") {
|
|
204
376
|
return bad("parked must be a boolean when present", "parked");
|
|
205
377
|
}
|
|
378
|
+
const pinned = own(s, "pinned");
|
|
379
|
+
if (!isAbsent(pinned) && typeof pinned !== "boolean") {
|
|
380
|
+
return bad("pinned must be a boolean when present (absent = not pinned or unknown)", "pinned");
|
|
381
|
+
}
|
|
206
382
|
return true;
|
|
207
|
-
};
|
|
383
|
+
});
|
|
208
384
|
export function isLocalSessionRecord(s) {
|
|
209
385
|
return checkLocalSessionRecord(s) === true;
|
|
210
386
|
}
|
|
211
|
-
const checkToctouBinding = (v) => {
|
|
387
|
+
const checkToctouBinding = seatCheck((v) => {
|
|
212
388
|
if (!isObject(v))
|
|
213
389
|
return bad("toctouBinding must be an object", "toctouBinding");
|
|
214
|
-
if (typeof v
|
|
390
|
+
if (typeof own(v, "callId") !== "string")
|
|
215
391
|
return bad("toctouBinding.callId must be a string", "toctouBinding.callId");
|
|
216
|
-
if (typeof v
|
|
392
|
+
if (typeof own(v, "inputHash") !== "string")
|
|
217
393
|
return bad("toctouBinding.inputHash must be a string", "toctouBinding.inputHash");
|
|
218
394
|
return true;
|
|
219
|
-
};
|
|
220
|
-
const checkToolPermissionRequest = (r) => {
|
|
395
|
+
});
|
|
396
|
+
const checkToolPermissionRequest = seatCheck((r) => {
|
|
221
397
|
if (!isObject(r))
|
|
222
398
|
return bad("tool permission request is not an object");
|
|
223
|
-
|
|
399
|
+
const requestId = own(r, "requestId");
|
|
400
|
+
if (typeof requestId !== "string")
|
|
224
401
|
return bad("requestId must be a string", "requestId");
|
|
225
|
-
if (toolPermissionRequestIdDomain(
|
|
402
|
+
if (toolPermissionRequestIdDomain(requestId) === undefined) {
|
|
226
403
|
return bad(`requestId must carry a registered domain prefix (${TOOL_PERMISSION_REQUEST_ID_DOMAINS.join("|")})`, "requestId");
|
|
227
404
|
}
|
|
228
|
-
if (typeof r
|
|
405
|
+
if (typeof own(r, "sessionId") !== "string")
|
|
229
406
|
return bad("sessionId must be a string", "sessionId");
|
|
230
|
-
|
|
407
|
+
const toolName = own(r, "toolName");
|
|
408
|
+
if (!isAbsent(toolName) && toolName !== null && typeof toolName !== "string") {
|
|
231
409
|
return bad("toolName must be a string or null when present", "toolName");
|
|
232
410
|
}
|
|
233
|
-
|
|
411
|
+
const toolCallId = own(r, "toolCallId");
|
|
412
|
+
if (!isAbsent(toolCallId) && toolCallId !== null && typeof toolCallId !== "string") {
|
|
234
413
|
return bad("toolCallId must be a string or null when present", "toolCallId");
|
|
235
414
|
}
|
|
236
|
-
if (!optionalString(r
|
|
415
|
+
if (!optionalString(own(r, "message")))
|
|
237
416
|
return bad("message must be a string when present", "message");
|
|
238
|
-
|
|
239
|
-
|
|
417
|
+
const toctouBinding = own(r, "toctouBinding");
|
|
418
|
+
if (!isAbsent(toctouBinding)) {
|
|
419
|
+
const verdict = checkToctouBinding(toctouBinding);
|
|
240
420
|
if (verdict !== true)
|
|
241
421
|
return verdict;
|
|
242
422
|
}
|
|
243
|
-
|
|
423
|
+
const createdAtMs = own(r, "createdAtMs");
|
|
424
|
+
if (!isAbsent(createdAtMs) && typeof createdAtMs !== "number") {
|
|
244
425
|
return bad("createdAtMs must be a number (epoch ms) when present", "createdAtMs");
|
|
245
426
|
}
|
|
246
427
|
return true;
|
|
247
|
-
};
|
|
428
|
+
});
|
|
248
429
|
export function isToolPermissionRequest(r) {
|
|
249
430
|
return checkToolPermissionRequest(r) === true;
|
|
250
431
|
}
|
|
251
|
-
const checkLaneProof = (v, field) => {
|
|
432
|
+
const checkLaneProof = seatCheckAt((v, field) => {
|
|
252
433
|
if (!isObject(v))
|
|
253
434
|
return bad("laneProof must be an object", field);
|
|
254
|
-
const lane = v
|
|
435
|
+
const lane = own(v, "lane");
|
|
255
436
|
if (typeof lane !== "string" || !inTuple(LANE_PROOF_LANE_TUPLE, lane)) {
|
|
256
437
|
return bad(`laneProof.lane must be one of ${LANE_PROOF_LANE_TUPLE.join("|")}`, `${field}.lane`);
|
|
257
438
|
}
|
|
258
|
-
if (lane === "subagent" && typeof v
|
|
439
|
+
if (lane === "subagent" && typeof own(v, "parentToolCallId") !== "string") {
|
|
259
440
|
return bad("subagent laneProof needs parentToolCallId", `${field}.parentToolCallId`);
|
|
260
441
|
}
|
|
261
|
-
if (lane === "workflow" && (typeof v
|
|
442
|
+
if (lane === "workflow" && (typeof own(v, "via") !== "string" || typeof own(v, "key") !== "string")) {
|
|
262
443
|
return bad("workflow laneProof needs via + key", `${field}.via`);
|
|
263
444
|
}
|
|
264
445
|
return true;
|
|
265
|
-
};
|
|
266
|
-
const checkSeatChromeEnvelope = (v, field) => {
|
|
446
|
+
});
|
|
447
|
+
const checkSeatChromeEnvelope = seatCheckAt((v, field) => {
|
|
267
448
|
if (!isObject(v))
|
|
268
449
|
return bad("chrome must be an object", field);
|
|
269
|
-
const kind = v
|
|
450
|
+
const kind = own(v, "kind");
|
|
270
451
|
if (typeof kind !== "string")
|
|
271
452
|
return bad("chrome.kind must be a string", `${field}.kind`);
|
|
272
453
|
if (!inTuple(CHROME_EVENT_KIND_TUPLE, kind)) {
|
|
273
454
|
return bad(`chrome.kind is not a renderer-wired arm (${CHROME_EVENT_KIND_TUPLE.join("|")})`, `${field}.kind`);
|
|
274
455
|
}
|
|
275
|
-
return checkLaneProof(v
|
|
276
|
-
};
|
|
277
|
-
const checkLocalSessionEvent = (v) => {
|
|
456
|
+
return checkLaneProof(own(v, "laneProof"), `${field}.laneProof`);
|
|
457
|
+
});
|
|
458
|
+
const checkLocalSessionEvent = seatCheck((v) => {
|
|
278
459
|
if (!isObject(v))
|
|
279
460
|
return bad("event is not an object");
|
|
280
|
-
const type = v
|
|
461
|
+
const type = own(v, "type");
|
|
281
462
|
if (typeof type !== "string")
|
|
282
463
|
return bad("type must be a string", "type");
|
|
283
464
|
if (!inTuple(SEAT_EVENT_TYPE_TUPLE, type)) {
|
|
284
465
|
return bad(`type is not a registered seat event name (${SEAT_EVENT_TYPE_TUPLE.join("|")})`, "type");
|
|
285
466
|
}
|
|
286
|
-
if (typeof v
|
|
467
|
+
if (typeof own(v, "sessionId") !== "string")
|
|
287
468
|
return bad("sessionId must be a string", "sessionId");
|
|
288
|
-
|
|
469
|
+
const messages = own(v, "messages");
|
|
470
|
+
if (!isAbsent(messages) && !Array.isArray(messages))
|
|
289
471
|
return bad("messages must be an array", "messages");
|
|
290
|
-
if (!optionalString(v
|
|
472
|
+
if (!optionalString(own(v, "error")))
|
|
291
473
|
return bad("error must be a string when present", "error");
|
|
292
|
-
if (!optionalString(v
|
|
474
|
+
if (!optionalString(own(v, "errorCategory")))
|
|
293
475
|
return bad("errorCategory must be a string when present", "errorCategory");
|
|
294
|
-
|
|
476
|
+
const code = own(v, "code");
|
|
477
|
+
if (!isAbsent(code) && typeof code !== "number")
|
|
295
478
|
return bad("code must be a number when present", "code");
|
|
296
|
-
|
|
297
|
-
|
|
479
|
+
const request = own(v, "request");
|
|
480
|
+
if (!isAbsent(request)) {
|
|
481
|
+
const verdict = checkToolPermissionRequest(request);
|
|
298
482
|
if (verdict !== true)
|
|
299
483
|
return nested("request", verdict);
|
|
300
484
|
}
|
|
301
|
-
if (!optionalString(v
|
|
485
|
+
if (!optionalString(own(v, "data")))
|
|
302
486
|
return bad("data must be a string when present", "data");
|
|
303
|
-
|
|
304
|
-
|
|
487
|
+
const sources = own(v, "sources");
|
|
488
|
+
if (!isAbsent(sources)) {
|
|
489
|
+
const okSources = Array.isArray(sources) && ownItems(sources).every((t) => typeof t === "string");
|
|
305
490
|
if (!okSources)
|
|
306
491
|
return bad("sources must be a string[]", "sources");
|
|
307
492
|
}
|
|
308
|
-
|
|
309
|
-
|
|
493
|
+
const mode = own(v, "permissionMode");
|
|
494
|
+
if (!isAbsent(mode)) {
|
|
310
495
|
if (typeof mode !== "string" || !inTuple(PERMISSION_MODE_INTENTS, mode)) {
|
|
311
496
|
return bad(`permissionMode must be one of ${PERMISSION_MODE_INTENTS.join("|")}`, "permissionMode");
|
|
312
497
|
}
|
|
313
498
|
}
|
|
314
|
-
|
|
315
|
-
|
|
499
|
+
const session = own(v, "session");
|
|
500
|
+
if (!isAbsent(session)) {
|
|
501
|
+
const verdict = checkLocalSessionRecord(session);
|
|
316
502
|
if (verdict !== true)
|
|
317
503
|
return nested("session", verdict);
|
|
318
504
|
}
|
|
319
|
-
if (!optionalString(v
|
|
505
|
+
if (!optionalString(own(v, "userMessageUuid")))
|
|
320
506
|
return bad("userMessageUuid must be a string when present", "userMessageUuid");
|
|
321
|
-
|
|
507
|
+
const hasPreClearSession = own(v, "hasPreClearSession");
|
|
508
|
+
if (!isAbsent(hasPreClearSession) && typeof hasPreClearSession !== "boolean") {
|
|
322
509
|
return bad("hasPreClearSession must be a boolean when present", "hasPreClearSession");
|
|
323
510
|
}
|
|
324
|
-
if (!optionalString(v
|
|
511
|
+
if (!optionalString(own(v, "requestId")))
|
|
325
512
|
return bad("requestId must be a string when present", "requestId");
|
|
326
|
-
|
|
513
|
+
const outcome = own(v, "outcome");
|
|
514
|
+
if (!optionalString(outcome))
|
|
327
515
|
return bad("outcome must be a string when present", "outcome");
|
|
328
|
-
|
|
329
|
-
|
|
516
|
+
const parked = own(v, "parked");
|
|
517
|
+
if (!isAbsent(parked)) {
|
|
518
|
+
if (parked !== true)
|
|
519
|
+
return bad("parked must be the literal true when present (absent = no park evidence)", "parked");
|
|
520
|
+
if (type !== "tool_permission_resolved" || outcome !== "expired") {
|
|
521
|
+
return bad('parked is only allowed on a tool_permission_resolved event whose outcome is "expired"', "parked");
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
const chrome = own(v, "chrome");
|
|
525
|
+
if (!isAbsent(chrome)) {
|
|
526
|
+
const verdict = checkSeatChromeEnvelope(chrome, "chrome");
|
|
330
527
|
if (verdict !== true)
|
|
331
528
|
return nested("chrome", verdict);
|
|
332
529
|
}
|
|
333
530
|
return true;
|
|
334
|
-
};
|
|
531
|
+
});
|
|
335
532
|
export function isLocalSessionEvent(v) {
|
|
336
533
|
return checkLocalSessionEvent(v) === true;
|
|
337
534
|
}
|
|
338
|
-
const checkAttachmentUploadReceipt = (v) => {
|
|
535
|
+
const checkAttachmentUploadReceipt = seatCheck((v) => {
|
|
339
536
|
if (!isObject(v))
|
|
340
537
|
return bad("upload receipt is not an object");
|
|
341
|
-
if (typeof v
|
|
538
|
+
if (typeof own(v, "id") !== "string")
|
|
342
539
|
return bad("id must be a string", "id");
|
|
343
|
-
if (typeof v
|
|
540
|
+
if (typeof own(v, "name") !== "string")
|
|
344
541
|
return bad("name must be a string", "name");
|
|
345
|
-
if (typeof v
|
|
542
|
+
if (typeof own(v, "mime") !== "string")
|
|
346
543
|
return bad("mime must be a string", "mime");
|
|
347
|
-
if (typeof v
|
|
544
|
+
if (typeof own(v, "sha256") !== "string")
|
|
348
545
|
return bad("sha256 must be a string", "sha256");
|
|
349
|
-
if (typeof v
|
|
546
|
+
if (typeof own(v, "sizeBytes") !== "number")
|
|
350
547
|
return bad("sizeBytes must be a number", "sizeBytes");
|
|
351
548
|
return true;
|
|
352
|
-
};
|
|
549
|
+
});
|
|
353
550
|
export function isAttachmentUploadReceipt(v) {
|
|
354
551
|
return checkAttachmentUploadReceipt(v) === true;
|
|
355
552
|
}
|
|
356
|
-
const
|
|
357
|
-
if (!isObject(m))
|
|
358
|
-
return bad(`models[${index}] is not an object`, "models");
|
|
359
|
-
if (typeof m.id !== "string")
|
|
360
|
-
return bad(`models[${index}].id must be a string`, "models");
|
|
361
|
-
if (!optionalString(m.name))
|
|
362
|
-
return bad(`models[${index}].name must be a string when present`, "models");
|
|
363
|
-
if (!optionalString(m.provider))
|
|
364
|
-
return bad(`models[${index}].provider must be a string when present`, "models");
|
|
365
|
-
if (!isAbsent(m.contextWindow) && typeof m.contextWindow !== "number") {
|
|
366
|
-
return bad(`models[${index}].contextWindow must be a number when present`, "models");
|
|
367
|
-
}
|
|
368
|
-
if (!isAbsent(m.maxOutputTokens) && typeof m.maxOutputTokens !== "number") {
|
|
369
|
-
return bad(`models[${index}].maxOutputTokens must be a number when present`, "models");
|
|
370
|
-
}
|
|
371
|
-
return true;
|
|
372
|
-
};
|
|
373
|
-
const checkApplyModelConfigResult = (v) => {
|
|
553
|
+
const checkApplyModelConfigResult = seatCheck((v) => {
|
|
374
554
|
if (!isObject(v))
|
|
375
555
|
return bad("applyModelConfig result is not an object");
|
|
376
|
-
|
|
556
|
+
const ok = own(v, "ok");
|
|
557
|
+
if (typeof ok !== "boolean")
|
|
377
558
|
return bad("ok must be a boolean", "ok");
|
|
378
|
-
if (typeof v
|
|
559
|
+
if (typeof own(v, "requiresRestart") !== "boolean")
|
|
379
560
|
return bad("requiresRestart must be a boolean", "requiresRestart");
|
|
380
|
-
|
|
561
|
+
const reason = own(v, "reason");
|
|
562
|
+
if (ok === false && (typeof reason !== "string" || reason.length === 0)) {
|
|
381
563
|
return bad("reason must be a non-empty string when ok is false", "reason");
|
|
382
564
|
}
|
|
383
|
-
if (
|
|
565
|
+
if (reason !== undefined && typeof reason !== "string")
|
|
384
566
|
return bad("reason must be a string when present", "reason");
|
|
385
567
|
return true;
|
|
386
|
-
};
|
|
387
|
-
const
|
|
388
|
-
if (!isObject(v))
|
|
568
|
+
});
|
|
569
|
+
const checkLiveModelCatalog = seatCheck((v) => {
|
|
570
|
+
if (!isObject(v) || Array.isArray(v))
|
|
389
571
|
return bad("model catalog is not an object");
|
|
390
|
-
const models = v
|
|
572
|
+
const models = own(v, "models");
|
|
391
573
|
if (!Array.isArray(models))
|
|
392
574
|
return bad("models must be an array", "models");
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
575
|
+
const rows = ownItems(models);
|
|
576
|
+
const names = new Set();
|
|
577
|
+
for (let i = 0; i < rows.length; i += 1) {
|
|
578
|
+
const row = liveModelRowCopy(rows[i]);
|
|
579
|
+
if (row === undefined)
|
|
580
|
+
return bad(`models[${i}] is not a catalog row (an object whose name is a non-empty string, JSON values only)`, `models[${i}]`);
|
|
581
|
+
if (names.has(row.name))
|
|
582
|
+
return bad(`models[${i}] repeats the name of an earlier row`, `models[${i}].name`);
|
|
583
|
+
names.add(row.name);
|
|
584
|
+
}
|
|
585
|
+
const dflt = own(v, "default");
|
|
586
|
+
if (typeof dflt !== "string" || dflt.length === 0)
|
|
587
|
+
return bad("default must be a non-empty string", "default");
|
|
588
|
+
const defaultModel = own(v, "defaultModel");
|
|
589
|
+
if (!isAbsent(defaultModel) && liveDefaultModelCopy(defaultModel) === undefined) {
|
|
590
|
+
return bad("defaultModel must be {id: non-empty string, name?: non-empty string} when present", "defaultModel");
|
|
397
591
|
}
|
|
398
|
-
if (!optionalString(v.defaultId))
|
|
399
|
-
return bad("defaultId must be a string when present", "defaultId");
|
|
400
592
|
return true;
|
|
401
|
-
};
|
|
402
|
-
|
|
403
|
-
|
|
593
|
+
});
|
|
594
|
+
const checkSeatRewindIntent = seatCheck((v) => {
|
|
595
|
+
if (!isObject(v) || Array.isArray(v))
|
|
596
|
+
return bad("rewind must be an object {mode, targetMessageUuid}");
|
|
597
|
+
for (const k of Object.keys(v)) {
|
|
598
|
+
if (!inTuple(SEAT_REWIND_INTENT_KEYS, k))
|
|
599
|
+
return bad(`unknown key (closed shape: ${SEAT_REWIND_INTENT_KEYS.join(", ")})`, k);
|
|
600
|
+
}
|
|
601
|
+
const mode = own(v, "mode");
|
|
602
|
+
if (typeof mode !== "string" || !inTuple(REWIND_MODES, mode))
|
|
603
|
+
return bad(`mode must be one of ${REWIND_MODES.join("|")}`, "mode");
|
|
604
|
+
const target = own(v, "targetMessageUuid");
|
|
605
|
+
if (typeof target !== "string" || target.length === 0) {
|
|
606
|
+
return bad("targetMessageUuid must be a non-empty string", "targetMessageUuid");
|
|
607
|
+
}
|
|
608
|
+
return true;
|
|
609
|
+
});
|
|
610
|
+
const checkSeatTurnSettings = seatCheck((v) => {
|
|
611
|
+
if (!isObject(v) || Array.isArray(v))
|
|
612
|
+
return bad("settings must be an object");
|
|
613
|
+
for (const k of Object.keys(v)) {
|
|
614
|
+
if (!inTuple(SEAT_TURN_SETTINGS_KEYS, k)) {
|
|
615
|
+
const host = Object.hasOwn(SEAT_TURN_SETTINGS_ORIGINS, k);
|
|
616
|
+
return bad(host ? "this settings key is supplied by the host, not carried by the seat" : `unknown key (closed shape: ${SEAT_TURN_SETTINGS_KEYS.join(", ")})`, k);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
const ultracode = own(v, "ultracode");
|
|
620
|
+
if (!isAbsent(ultracode) && typeof ultracode !== "boolean")
|
|
621
|
+
return bad("ultracode must be a boolean when present", "ultracode");
|
|
622
|
+
return true;
|
|
623
|
+
});
|
|
624
|
+
const checkRetainSubagentSessions = seatCheck((v) => {
|
|
625
|
+
if (typeof v === "boolean")
|
|
626
|
+
return true;
|
|
627
|
+
if (!isObject(v) || Array.isArray(v))
|
|
628
|
+
return bad("retainSubagentSessions must be a boolean or {ttlMs?, max?}");
|
|
629
|
+
for (const k of Object.keys(v)) {
|
|
630
|
+
if (k !== "ttlMs" && k !== "max")
|
|
631
|
+
return bad("unknown key (closed shape: ttlMs, max)", k);
|
|
632
|
+
const n = own(v, k);
|
|
633
|
+
if (!isAbsent(n) && (typeof n !== "number" || !Number.isSafeInteger(n) || n < 0))
|
|
634
|
+
return bad(`${k} must be a non-negative integer when present`, k);
|
|
635
|
+
}
|
|
636
|
+
return true;
|
|
637
|
+
});
|
|
638
|
+
export function checkSendMessageRequest(v) {
|
|
639
|
+
try {
|
|
640
|
+
if (!isObject(v) || Array.isArray(v))
|
|
641
|
+
return bad("sendMessage request is not an object");
|
|
642
|
+
const at = firstAccessorPath(v);
|
|
643
|
+
if (at !== undefined)
|
|
644
|
+
return bad(NOT_PLAIN_DATA, at);
|
|
645
|
+
const body = {};
|
|
646
|
+
for (const k of Object.keys(v)) {
|
|
647
|
+
if (!inTuple(SEND_MESSAGE_REQUEST_KEYS, k))
|
|
648
|
+
return bad(`unknown key (closed shape: ${SEND_MESSAGE_REQUEST_KEYS.join(", ")})`, k);
|
|
649
|
+
body[k] = own(v, k);
|
|
650
|
+
}
|
|
651
|
+
if (typeof body.sessionId !== "string" || body.sessionId.length === 0)
|
|
652
|
+
return bad("sessionId must be a non-empty string", "sessionId");
|
|
653
|
+
if (typeof body.text !== "string")
|
|
654
|
+
return bad("text must be a string", "text");
|
|
655
|
+
if (!optionalString(body.model))
|
|
656
|
+
return bad("model must be a string when present", "model");
|
|
657
|
+
if (!optionalString(body.userMessageUuid))
|
|
658
|
+
return bad("userMessageUuid must be a string when present", "userMessageUuid");
|
|
659
|
+
if (!isAbsent(body.permissionMode) && (typeof body.permissionMode !== "string" || !inTuple(PERMISSION_MODE_INTENTS, body.permissionMode))) {
|
|
660
|
+
return bad(`permissionMode must be one of ${PERMISSION_MODE_INTENTS.join("|")}`, "permissionMode");
|
|
661
|
+
}
|
|
662
|
+
if (!isAbsent(body.attachmentIds)) {
|
|
663
|
+
const raw = body.attachmentIds;
|
|
664
|
+
const ids = Array.isArray(raw) ? ownItems(raw) : undefined;
|
|
665
|
+
if (ids === undefined || !ids.every((id) => typeof id === "string" && id.length > 0)) {
|
|
666
|
+
return bad("attachmentIds must be an array of non-empty attachment ids", "attachmentIds");
|
|
667
|
+
}
|
|
668
|
+
if (ids.length > ATTACHMENT_IDS_PER_TASK_CAP)
|
|
669
|
+
return bad(`attachmentIds exceeds the per-task limit (${ATTACHMENT_IDS_PER_TASK_CAP})`, "attachmentIds");
|
|
670
|
+
}
|
|
671
|
+
if (!isAbsent(body.reasoningEffort) && (typeof body.reasoningEffort !== "string" || !inTuple(SEAT_REASONING_EFFORTS, body.reasoningEffort))) {
|
|
672
|
+
return bad(`reasoningEffort must be one of ${SEAT_REASONING_EFFORTS.join("|")}`, "reasoningEffort");
|
|
673
|
+
}
|
|
674
|
+
for (const k of ["retainBackgroundProcesses", "forwardSubagentEvents"]) {
|
|
675
|
+
if (!isAbsent(body[k]) && typeof body[k] !== "boolean")
|
|
676
|
+
return bad(`${k} must be a boolean when present`, k);
|
|
677
|
+
}
|
|
678
|
+
if (!isAbsent(body.retainSubagentSessions)) {
|
|
679
|
+
const verdict = checkRetainSubagentSessions(body.retainSubagentSessions);
|
|
680
|
+
if (verdict !== true)
|
|
681
|
+
return nested("retainSubagentSessions", verdict);
|
|
682
|
+
}
|
|
683
|
+
if (!isAbsent(body.settings)) {
|
|
684
|
+
const verdict = checkSeatTurnSettings(body.settings);
|
|
685
|
+
if (verdict !== true)
|
|
686
|
+
return nested("settings", verdict);
|
|
687
|
+
}
|
|
688
|
+
if (!optionalString(body.scenario))
|
|
689
|
+
return bad("scenario must be a string when present", "scenario");
|
|
690
|
+
if (!isAbsent(body.rewind)) {
|
|
691
|
+
const verdict = checkSeatRewindIntent(body.rewind);
|
|
692
|
+
if (verdict !== true)
|
|
693
|
+
return nested("rewind", verdict);
|
|
694
|
+
}
|
|
695
|
+
return true;
|
|
696
|
+
}
|
|
697
|
+
catch (e) {
|
|
698
|
+
const key = ownDataRefusalKeyOf(e);
|
|
699
|
+
return key !== undefined ? bad(NOT_PLAIN_DATA, key) : bad("sendMessage request could not be read");
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
export function isSendMessageRequest(v) {
|
|
703
|
+
return checkSendMessageRequest(v) === true;
|
|
404
704
|
}
|
|
405
|
-
const
|
|
705
|
+
export const checkSessionRowPatchRequest = seatCheck((v) => {
|
|
706
|
+
if (!isObject(v) || Array.isArray(v))
|
|
707
|
+
return bad("patchSession request is not an object");
|
|
708
|
+
const body = {};
|
|
709
|
+
for (const k of Object.keys(v)) {
|
|
710
|
+
if (!inTuple(SESSION_ROW_PATCH_REQUEST_KEYS, k))
|
|
711
|
+
return bad(`unknown key (closed shape: ${SESSION_ROW_PATCH_REQUEST_KEYS.join(", ")})`, k);
|
|
712
|
+
body[k] = own(v, k);
|
|
713
|
+
}
|
|
714
|
+
if (typeof body.sessionId !== "string" || body.sessionId.length === 0)
|
|
715
|
+
return bad("sessionId must be a non-empty string", "sessionId");
|
|
716
|
+
const { title, pinned } = body;
|
|
717
|
+
if (!isAbsent(title) && title !== null && (typeof title !== "string" || title.length === 0)) {
|
|
718
|
+
return bad('title must be a non-empty string, or null to clear it back to the automatic title (an empty string is not a way to clear)', "title");
|
|
719
|
+
}
|
|
720
|
+
if (!isAbsent(pinned) && typeof pinned !== "boolean")
|
|
721
|
+
return bad("pinned must be a boolean when present", "pinned");
|
|
722
|
+
if (isAbsent(title) && isAbsent(pinned))
|
|
723
|
+
return bad("nothing to change: carry at least one of title / pinned");
|
|
724
|
+
return true;
|
|
725
|
+
});
|
|
726
|
+
export function isSessionRowPatchRequest(v) {
|
|
727
|
+
return checkSessionRowPatchRequest(v) === true;
|
|
728
|
+
}
|
|
729
|
+
const checkSendMessageAck = seatCheck((v) => {
|
|
406
730
|
if (!isObject(v))
|
|
407
731
|
return bad("sendMessage ack is not an object");
|
|
408
|
-
if (typeof v
|
|
732
|
+
if (typeof own(v, "sessionId") !== "string")
|
|
409
733
|
return bad("sessionId must be a string", "sessionId");
|
|
410
|
-
if (typeof v
|
|
734
|
+
if (typeof own(v, "userMessageUuid") !== "string")
|
|
411
735
|
return bad("userMessageUuid must be a string", "userMessageUuid");
|
|
412
|
-
|
|
736
|
+
const queued = own(v, "queued");
|
|
737
|
+
if (!isAbsent(queued) && typeof queued !== "boolean")
|
|
413
738
|
return bad("queued must be a boolean when present", "queued");
|
|
414
739
|
return true;
|
|
415
|
-
};
|
|
740
|
+
});
|
|
416
741
|
export function isSendMessageAck(v) {
|
|
417
742
|
return checkSendMessageAck(v) === true;
|
|
418
743
|
}
|
|
419
|
-
const checkInterruptAck = (v) => isObject(v) && typeof v
|
|
420
|
-
const checkStopAck = (v) => isObject(v) && typeof v
|
|
421
|
-
const checkOkAck = (v) => isObject(v) && typeof v
|
|
744
|
+
const checkInterruptAck = seatCheck((v) => isObject(v) && typeof own(v, "interrupted") === "boolean" ? true : bad("interrupt ack needs boolean `interrupted`", "interrupted"));
|
|
745
|
+
const checkStopAck = seatCheck((v) => isObject(v) && typeof own(v, "stopped") === "boolean" ? true : bad("stop ack needs boolean `stopped`", "stopped"));
|
|
746
|
+
const checkOkAck = seatCheck((v) => isObject(v) && typeof own(v, "ok") === "boolean" ? true : bad("ack needs boolean `ok`", "ok"));
|
|
422
747
|
const checkBooleanAck = (v) => typeof v === "boolean" ? true : bad("expected a bare boolean result");
|
|
423
|
-
const checkGetTranscriptResult = (v) => {
|
|
748
|
+
const checkGetTranscriptResult = seatCheck((v) => {
|
|
424
749
|
if (!isObject(v))
|
|
425
750
|
return bad("transcript envelope is not an object");
|
|
426
|
-
if (typeof v
|
|
751
|
+
if (typeof own(v, "sessionId") !== "string")
|
|
427
752
|
return bad("sessionId must be a string", "sessionId");
|
|
428
|
-
if (!Array.isArray(v
|
|
753
|
+
if (!Array.isArray(own(v, "messages")))
|
|
429
754
|
return bad("messages must be an array", "messages");
|
|
430
755
|
return true;
|
|
431
|
-
};
|
|
432
|
-
const checkSessionSearchResult = (v) => {
|
|
756
|
+
});
|
|
757
|
+
const checkSessionSearchResult = seatCheck((v) => {
|
|
433
758
|
if (!isObject(v))
|
|
434
759
|
return bad("search result row is not an object");
|
|
435
|
-
if (typeof v
|
|
760
|
+
if (typeof own(v, "sessionId") !== "string")
|
|
436
761
|
return bad("sessionId must be a string", "sessionId");
|
|
437
|
-
if (!optionalString(v
|
|
762
|
+
if (!optionalString(own(v, "title")))
|
|
438
763
|
return bad("title must be a string when present", "title");
|
|
439
|
-
|
|
764
|
+
const matches = own(v, "matches");
|
|
765
|
+
if (!Array.isArray(matches))
|
|
440
766
|
return bad("matches must be an array", "matches");
|
|
441
|
-
const okMatches =
|
|
767
|
+
const okMatches = ownItems(matches).every((m) => isObject(m) && typeof own(m, "snippet") === "string");
|
|
442
768
|
if (!okMatches)
|
|
443
769
|
return bad("matches must be {snippet:string}[]", "matches");
|
|
444
770
|
return true;
|
|
445
|
-
};
|
|
446
|
-
const checkSessionSearchEnvelope = (v) => {
|
|
771
|
+
});
|
|
772
|
+
const checkSessionSearchEnvelope = seatCheck((v) => {
|
|
447
773
|
if (!isObject(v))
|
|
448
774
|
return bad("search envelope is not an object");
|
|
449
|
-
const results = v
|
|
775
|
+
const results = own(v, "results");
|
|
450
776
|
if (!Array.isArray(results))
|
|
451
777
|
return bad("results must be an array", "results");
|
|
452
|
-
|
|
453
|
-
|
|
778
|
+
const rows = ownItems(results);
|
|
779
|
+
for (let i = 0; i < rows.length; i += 1) {
|
|
780
|
+
const verdict = checkSessionSearchResult(rows[i]);
|
|
454
781
|
if (verdict !== true)
|
|
455
782
|
return nested(`results[${i}]`, verdict);
|
|
456
783
|
}
|
|
457
784
|
return true;
|
|
458
|
-
};
|
|
459
|
-
const checkSessionsState = (v) => {
|
|
785
|
+
});
|
|
786
|
+
const checkSessionsState = seatCheck((v) => {
|
|
460
787
|
if (!isObject(v))
|
|
461
788
|
return bad("sessions state is not an object");
|
|
462
|
-
const sessions = v
|
|
789
|
+
const sessions = own(v, "sessions");
|
|
463
790
|
if (!Array.isArray(sessions))
|
|
464
791
|
return bad("sessions must be an array", "sessions");
|
|
465
|
-
|
|
466
|
-
|
|
792
|
+
const rows = ownItems(sessions);
|
|
793
|
+
for (let i = 0; i < rows.length; i += 1) {
|
|
794
|
+
const verdict = checkLocalSessionRecord(rows[i]);
|
|
467
795
|
if (verdict !== true)
|
|
468
796
|
return nested(`sessions[${i}]`, verdict);
|
|
469
797
|
}
|
|
470
798
|
return true;
|
|
471
|
-
};
|
|
472
|
-
const checkFocusedSessionState = (v) => {
|
|
799
|
+
});
|
|
800
|
+
const checkFocusedSessionState = seatCheck((v) => {
|
|
473
801
|
if (!isObject(v))
|
|
474
802
|
return bad("focused session state is not an object");
|
|
475
|
-
|
|
803
|
+
const sessionId = own(v, "sessionId");
|
|
804
|
+
if (sessionId !== null && typeof sessionId !== "string") {
|
|
476
805
|
return bad("sessionId must be a string or null", "sessionId");
|
|
477
806
|
}
|
|
478
807
|
return true;
|
|
479
|
-
};
|
|
480
|
-
const checkSettingsState = (v) => {
|
|
481
|
-
if (!
|
|
482
|
-
return bad("settings state is not
|
|
483
|
-
if (
|
|
484
|
-
return bad("defaultModel
|
|
808
|
+
});
|
|
809
|
+
const checkSettingsState = seatCheck((v) => {
|
|
810
|
+
if (!isPlainRecord(v))
|
|
811
|
+
return bad("settings state is not a plain object");
|
|
812
|
+
if (Object.hasOwn(v, "defaultModel")) {
|
|
813
|
+
return bad("defaultModel is not carried in settings state: read the deployment default model from the model catalog (liveDefaultModelOf over the listModels() result)", "defaultModel");
|
|
485
814
|
}
|
|
486
|
-
if (!optionalString(v
|
|
815
|
+
if (!optionalString(own(v, "engineVersion")))
|
|
487
816
|
return bad("engineVersion must be a string when present", "engineVersion");
|
|
488
|
-
if (!optionalString(v
|
|
817
|
+
if (!optionalString(own(v, "dataRoot")))
|
|
489
818
|
return bad("dataRoot must be a string when present", "dataRoot");
|
|
490
819
|
return true;
|
|
491
|
-
};
|
|
492
|
-
const checkPickFolderResult = (v) => v === null || (
|
|
820
|
+
});
|
|
821
|
+
const checkPickFolderResult = (v) => v === null || isFolderPath(v)
|
|
493
822
|
? true
|
|
494
823
|
: bad("pickFolder result must be null (cancelled) or a non-empty path string");
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
824
|
+
const checkRecentFolderRow = seatCheck((v) => {
|
|
825
|
+
if (!isPlainRecord(v))
|
|
826
|
+
return bad("recent folder row is not a plain object");
|
|
827
|
+
if (!isFolderPath(own(v, "path")))
|
|
828
|
+
return bad("path must be a non-empty path string", "path");
|
|
829
|
+
if (!optionalString(own(v, "lastUsedAt")))
|
|
830
|
+
return bad("lastUsedAt must be a string when present", "lastUsedAt");
|
|
831
|
+
return true;
|
|
832
|
+
});
|
|
833
|
+
const checkRecentFoldersResult = seatCheck((v) => {
|
|
834
|
+
if (!isPlainRecord(v))
|
|
835
|
+
return bad("recent folders result is not a plain object");
|
|
836
|
+
const folders = own(v, "folders");
|
|
837
|
+
if (!Array.isArray(folders))
|
|
838
|
+
return bad("folders must be an array", "folders");
|
|
839
|
+
const rows = ownItems(folders);
|
|
840
|
+
for (let i = 0; i < rows.length; i += 1) {
|
|
841
|
+
const verdict = checkRecentFolderRow(rows[i]);
|
|
842
|
+
if (verdict !== true)
|
|
843
|
+
return nested(`folders[${i}]`, verdict);
|
|
514
844
|
}
|
|
515
|
-
|
|
516
|
-
|
|
845
|
+
return true;
|
|
846
|
+
});
|
|
847
|
+
const checkSeatCapabilitiesState = seatCheck((v) => {
|
|
848
|
+
if (!isObject(v) || Array.isArray(v))
|
|
849
|
+
return bad("seat capabilities state is not an object");
|
|
850
|
+
const proto = Object.getPrototypeOf(v);
|
|
851
|
+
if (proto !== Object.prototype && proto !== null)
|
|
852
|
+
return bad("seat capabilities state is not a plain object");
|
|
853
|
+
for (const k of Reflect.ownKeys(v)) {
|
|
854
|
+
const name = typeof k === "string" ? k : String(k);
|
|
855
|
+
if (typeof k !== "string" || !inTuple(SEAT_CAPABILITY_NAMES, k)) {
|
|
856
|
+
return bad(`${name} is not a registered seat capability (${SEAT_CAPABILITY_NAMES.join("|")})`, name);
|
|
857
|
+
}
|
|
858
|
+
const value = own(v, k);
|
|
859
|
+
if (!isAbsent(value) && typeof value !== "boolean")
|
|
860
|
+
return bad(`${k} must be a boolean when present`, k);
|
|
517
861
|
}
|
|
518
|
-
|
|
862
|
+
return true;
|
|
863
|
+
});
|
|
519
864
|
export const LOCAL_SESSIONS_SPEC = {
|
|
520
865
|
ns: "sema.web",
|
|
521
866
|
service: "LocalSessions",
|
|
@@ -533,9 +878,11 @@ export const LOCAL_SESSIONS_SPEC = {
|
|
|
533
878
|
getTranscript: { kind: "invoke", check: checkGetTranscriptResult },
|
|
534
879
|
searchSessions: { kind: "invoke", check: checkSessionSearchEnvelope },
|
|
535
880
|
uploadAttachment: { kind: "invoke", check: checkAttachmentUploadReceipt },
|
|
536
|
-
listModels: { kind: "invoke", check:
|
|
881
|
+
listModels: { kind: "invoke", check: checkLiveModelCatalog },
|
|
537
882
|
applyModelConfig: { kind: "invoke", check: checkApplyModelConfigResult },
|
|
538
883
|
pickFolder: { kind: "invoke", check: checkPickFolderResult },
|
|
884
|
+
listRecentFolders: { kind: "invoke", check: checkRecentFoldersResult },
|
|
885
|
+
noteRecentFolder: { kind: "invoke", check: checkOkAck }, patchSession: { kind: "invoke", check: checkLocalSessionRecord },
|
|
539
886
|
onEvent: { kind: "event", check: checkLocalSessionEvent },
|
|
540
887
|
onToolPermissionRequest: { kind: "event", check: checkToolPermissionRequest },
|
|
541
888
|
},
|
|
@@ -563,6 +910,8 @@ export const SEAT_METHOD_NAMES = [
|
|
|
563
910
|
"listModels",
|
|
564
911
|
"applyModelConfig",
|
|
565
912
|
"pickFolder",
|
|
913
|
+
"listRecentFolders",
|
|
914
|
+
"noteRecentFolder", "patchSession",
|
|
566
915
|
"onEvent",
|
|
567
916
|
"onToolPermissionRequest",
|
|
568
917
|
];
|
|
@@ -590,6 +939,7 @@ export const LOCAL_SESSION_EVENT_KEYS = [
|
|
|
590
939
|
"hasPreClearSession",
|
|
591
940
|
"requestId",
|
|
592
941
|
"outcome",
|
|
942
|
+
"parked",
|
|
593
943
|
"chrome",
|
|
594
944
|
];
|
|
595
945
|
export const TOOL_PERMISSION_REQUEST_KEYS = [
|
|
@@ -609,6 +959,7 @@ export const TOOL_PERMISSION_REQUEST_KEYS = [
|
|
|
609
959
|
"ruleOffersAbsence",
|
|
610
960
|
"askClass",
|
|
611
961
|
"classes",
|
|
962
|
+
"rememberRefused",
|
|
612
963
|
];
|
|
613
964
|
export const LOCAL_SESSION_RECORD_KEYS = [
|
|
614
965
|
"sessionId",
|
|
@@ -621,6 +972,7 @@ export const LOCAL_SESSION_RECORD_KEYS = [
|
|
|
621
972
|
"lastActivityAt",
|
|
622
973
|
"queuedMessages",
|
|
623
974
|
"parked",
|
|
975
|
+
"pinned",
|
|
624
976
|
];
|
|
625
977
|
export const SEND_MESSAGE_REQUEST_KEYS = [
|
|
626
978
|
"sessionId",
|
|
@@ -635,6 +987,7 @@ export const SEND_MESSAGE_REQUEST_KEYS = [
|
|
|
635
987
|
"retainSubagentSessions",
|
|
636
988
|
"settings",
|
|
637
989
|
"scenario",
|
|
990
|
+
"rewind",
|
|
638
991
|
];
|
|
639
992
|
export const SEAT_SEND_MESSAGE_KEY_ORIGINS = {
|
|
640
993
|
sessionId: { seatOnly: "座位会话句柄(渲染端持有的本地 id);引擎会话 id 由座位记录的 `engineSessionId` 承载 —— 与引擎请求体上的同名位**同名不同义**,绝不直传" },
|
|
@@ -649,6 +1002,7 @@ export const SEAT_SEND_MESSAGE_KEY_ORIGINS = {
|
|
|
649
1002
|
retainSubagentSessions: { taskRequestKey: "retainSubagentSessions" },
|
|
650
1003
|
settings: { taskRequestKey: "settings" },
|
|
651
1004
|
scenario: { taskRequestKey: "scenario" },
|
|
1005
|
+
rewind: { projectedBy: "rewindSpecForMode", taskRequestKeys: ["resumeAt", "resumeAtMode", "restoreFiles", "rewindFilesTo"] },
|
|
652
1006
|
};
|
|
653
1007
|
export const TOOL_PERMISSION_DECISION_KEYS = [
|
|
654
1008
|
"sessionId",
|
|
@@ -663,7 +1017,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
|
663
1017
|
LocalSessionRecord: {
|
|
664
1018
|
guard: "isLocalSessionRecord",
|
|
665
1019
|
check: checkLocalSessionRecord,
|
|
666
|
-
validated: ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked"],
|
|
1020
|
+
validated: ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked", "pinned"],
|
|
667
1021
|
unchecked: [],
|
|
668
1022
|
},
|
|
669
1023
|
ToolPermissionRequest: {
|
|
@@ -703,6 +1057,10 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
|
703
1057
|
key: "classes",
|
|
704
1058
|
why: "与 askClass 同一对(CC-284),同在同缺、同一只成对窄读(非空、每员非空串、无重复、首员等于 askClass;开集、原样顺序);座位门不设第二判官,理由同 askClass。",
|
|
705
1059
|
},
|
|
1060
|
+
{
|
|
1061
|
+
key: "rememberRefused",
|
|
1062
|
+
why: "展示增强位(CC-642),权威窄读在卡口两条腿与过境口 toolPermissionRequestAskBits(同一只 readApprovalRememberRefused:自有键 ∧ 严格 true 才上座,永不铸 false);座位门不设第二判官,理由同 mandated(为一个展示位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。消费端 `=== true` 读,其余(缺席 / 坏形)一律当缺席 ⇒ 照旧渲「本会话放行」。缺席 = 服务端没说(记得住或老服务端),不是 false。不经过境口自铸座位请求的宿主要自己按同一把窄读。",
|
|
1063
|
+
},
|
|
706
1064
|
{
|
|
707
1065
|
key: "ruleOffersAbsence",
|
|
708
1066
|
why: "喂强制判据口 approvalIsMandated 的位(CC-203;寄存行那条腿的强制只以缺席词 mandated 表达),按开集读(非空串原文字节、词表不校);权威窄读在卡口与过境口,座位门不设第二判官,理由同 mandated。坏形读成缺席 ⇒ 这一路不判强制(放宽方向:寄存行上的强制就丢了;另两路 mandated / mandate 照判);表外串只是不等于 mandated。不经过境口自铸座位请求的宿主要自己按同一把窄读。",
|
|
@@ -728,6 +1086,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
|
728
1086
|
"hasPreClearSession",
|
|
729
1087
|
"requestId",
|
|
730
1088
|
"outcome",
|
|
1089
|
+
"parked",
|
|
731
1090
|
"chrome",
|
|
732
1091
|
],
|
|
733
1092
|
unchecked: [
|
|
@@ -743,10 +1102,40 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
|
743
1102
|
validated: ["id", "name", "mime", "sha256", "sizeBytes"],
|
|
744
1103
|
unchecked: [],
|
|
745
1104
|
},
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
1105
|
+
LiveModelCatalog: {
|
|
1106
|
+
check: checkLiveModelCatalog,
|
|
1107
|
+
validated: ["models", "default", "defaultModel"],
|
|
1108
|
+
unchecked: [
|
|
1109
|
+
{
|
|
1110
|
+
key: "droppedEntries",
|
|
1111
|
+
why: "诊断面(哪些目录条目没被引擎收下),三态读法归 droppedModelEntriesOf(含坏形 malformed);出站门为它拒掉整份目录 = 选单为一行诊断整个消失。",
|
|
1112
|
+
},
|
|
1113
|
+
],
|
|
1114
|
+
},
|
|
1115
|
+
SendMessageRequest: {
|
|
1116
|
+
guard: "isSendMessageRequest",
|
|
1117
|
+
check: checkSendMessageRequest,
|
|
1118
|
+
validated: [
|
|
1119
|
+
"sessionId",
|
|
1120
|
+
"text",
|
|
1121
|
+
"model",
|
|
1122
|
+
"userMessageUuid",
|
|
1123
|
+
"permissionMode",
|
|
1124
|
+
"attachmentIds",
|
|
1125
|
+
"reasoningEffort",
|
|
1126
|
+
"retainBackgroundProcesses",
|
|
1127
|
+
"forwardSubagentEvents",
|
|
1128
|
+
"retainSubagentSessions",
|
|
1129
|
+
"settings",
|
|
1130
|
+
"scenario",
|
|
1131
|
+
"rewind",
|
|
1132
|
+
],
|
|
1133
|
+
unchecked: [],
|
|
1134
|
+
},
|
|
1135
|
+
SessionRowPatchRequest: {
|
|
1136
|
+
guard: "isSessionRowPatchRequest",
|
|
1137
|
+
check: checkSessionRowPatchRequest,
|
|
1138
|
+
validated: ["sessionId", "title", "pinned"],
|
|
750
1139
|
unchecked: [],
|
|
751
1140
|
},
|
|
752
1141
|
ApplyModelConfigResult: {
|
|
@@ -797,17 +1186,27 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
|
797
1186
|
},
|
|
798
1187
|
SettingsState: {
|
|
799
1188
|
check: checkSettingsState,
|
|
800
|
-
validated: ["
|
|
1189
|
+
validated: ["engineVersion", "dataRoot"],
|
|
801
1190
|
unchecked: [],
|
|
802
1191
|
},
|
|
803
1192
|
SeatCapabilitiesState: {
|
|
804
1193
|
check: checkSeatCapabilitiesState,
|
|
805
|
-
validated: ["pickFolder"],
|
|
1194
|
+
validated: ["pickFolder", "rewind", "recents", "patchSession"],
|
|
806
1195
|
unchecked: [],
|
|
807
1196
|
},
|
|
808
|
-
|
|
809
|
-
check:
|
|
810
|
-
validated: ["
|
|
1197
|
+
RecentFoldersResult: {
|
|
1198
|
+
check: checkRecentFoldersResult,
|
|
1199
|
+
validated: ["folders"],
|
|
1200
|
+
unchecked: [],
|
|
1201
|
+
},
|
|
1202
|
+
RecentFolderRow: {
|
|
1203
|
+
check: checkRecentFolderRow,
|
|
1204
|
+
validated: ["path", "lastUsedAt"],
|
|
1205
|
+
unchecked: [],
|
|
1206
|
+
},
|
|
1207
|
+
SeatRewindIntent: {
|
|
1208
|
+
check: checkSeatRewindIntent,
|
|
1209
|
+
validated: ["mode", "targetMessageUuid"],
|
|
811
1210
|
unchecked: [],
|
|
812
1211
|
},
|
|
813
1212
|
SessionSearchResult: {
|
|
@@ -864,5 +1263,10 @@ const _seatContractPins = [
|
|
|
864
1263
|
true, true, true, true, true, true, true, true,
|
|
865
1264
|
true, true, true, true, true, true, true, true,
|
|
866
1265
|
true, true, true, true, true,
|
|
1266
|
+
true, true, true, true, true, true, true, true,
|
|
1267
|
+
true, true,
|
|
1268
|
+
true, true,
|
|
1269
|
+
true, true, true, true,
|
|
1270
|
+
true, true, true, true, true, true,
|
|
867
1271
|
];
|
|
868
1272
|
void _seatContractPins;
|