@sema-agent/client-core 0.109.0 → 0.111.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 +342 -0
- package/README.md +88 -32
- package/dist/abortableSleep.d.ts +7 -0
- package/dist/abortableSleep.js +37 -0
- package/dist/adapt/arms.js +45 -11
- package/dist/adapt/toolCards.d.ts +3 -1
- package/dist/adapt/toolCards.js +4 -2
- package/dist/adapter/activeRunSelfHeal.d.ts +39 -0
- package/dist/adapter/activeRunSelfHeal.js +171 -3
- package/dist/adapter/downstream/eventToSdkMessage.js +20 -15
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +2 -0
- package/dist/adapter/downstream/terminalToSdkResult.js +11 -0
- package/dist/adapter/runStream.d.ts +5 -0
- package/dist/adapter/runStream.js +15 -3
- package/dist/attachmentRoute.d.ts +20 -0
- package/dist/attachmentRoute.js +39 -0
- package/dist/attachmentsWireCaps.js +1 -1
- package/dist/builtinOutputStyles.d.ts +12 -0
- package/dist/builtinOutputStyles.js +147 -0
- package/dist/compactionStatus.d.ts +9 -0
- package/dist/compactionStatus.js +29 -5
- package/dist/controlRouter.js +2 -1
- package/dist/coreValuePorts.d.ts +39 -1
- package/dist/coreValuePorts.js +10 -0
- package/dist/declared/supportFloorDeclared.js +1 -1
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +138 -14
- package/dist/engineErrorCodes.d.ts +3 -0
- package/dist/engineErrorCodes.js +3 -0
- package/dist/engineHealthFacts.d.ts +20 -0
- package/dist/engineHealthFacts.js +42 -1
- package/dist/engineHealthProbeVerdict.d.ts +23 -0
- package/dist/engineHealthProbeVerdict.js +115 -0
- package/dist/engineInlineTaskStats.d.ts +4 -3
- package/dist/engineInlineTaskStats.js +18 -2
- package/dist/engineNoticeCodes.d.ts +10 -0
- package/dist/engineNoticeCodes.js +36 -6
- package/dist/engineRepoint.d.ts +147 -0
- package/dist/engineRepoint.js +310 -0
- package/dist/engineRowRef.d.ts +3 -0
- package/dist/engineRowRef.js +13 -1
- package/dist/engineSessionMessages.d.ts +2 -1
- package/dist/engineSessionMessages.js +5 -0
- package/dist/engineSwapCrossing.d.ts +57 -0
- package/dist/engineSwapCrossing.js +297 -0
- package/dist/engineUnavailable.d.ts +44 -0
- package/dist/engineUnavailable.js +492 -0
- package/dist/errorSupplementRoles.js +2 -1
- package/dist/eventLeg.js +3 -3
- package/dist/fleet/fleetProjection.js +3 -2
- package/dist/generated/engineFactTables.d.ts +2 -0
- package/dist/generated/engineFactTables.js +12 -0
- package/dist/generated/sdkFactTables.d.ts +2 -1
- package/dist/generated/sdkFactTables.js +5 -0
- package/dist/generated/settingsSchemaTables.d.ts +4 -0
- package/dist/generated/settingsSchemaTables.js +1 -0
- package/dist/hitl/approvalAskers.d.ts +6 -0
- package/dist/hitl/approvalAskers.js +30 -0
- package/dist/hitl/approvalCardReasons.js +6 -3
- package/dist/hitl/approvalDelivery.d.ts +1 -0
- package/dist/hitl/approvalDelivery.js +1 -1
- package/dist/hitl/approvalRequestFrameReading.d.ts +7 -0
- package/dist/hitl/approvalRequestFrameReading.js +11 -0
- package/dist/hitl/approvalResolution.d.ts +9 -2
- package/dist/hitl/approvalResolution.js +6 -1
- package/dist/hitl/askGateWire.js +5 -8
- package/dist/hitl/automaticAnswerVerdict.js +2 -2
- package/dist/hitl/decisionConflict.js +6 -3
- package/dist/hitl/decisionRefusal.d.ts +2 -0
- package/dist/hitl/decisionRefusal.js +8 -8
- package/dist/hitl/decisionRefusalCarrier.d.ts +3 -0
- package/dist/hitl/decisionRefusalCarrier.js +348 -0
- package/dist/hitl/decisionSend.d.ts +10 -0
- package/dist/hitl/decisionSend.js +57 -17
- package/dist/hitl/editedApprovalAcceptance.d.ts +25 -0
- package/dist/hitl/editedApprovalAcceptance.js +26 -0
- package/dist/hitl/elicitationRefusal.d.ts +4 -0
- package/dist/hitl/elicitationRefusal.js +23 -0
- package/dist/hitl/frameRouter.d.ts +2 -2
- package/dist/hitl/frameRouter.js +12 -33
- package/dist/hitl/gateIdentity.d.ts +5 -0
- package/dist/hitl/gateIdentity.js +23 -0
- package/dist/hitl/gateLedger.d.ts +0 -4
- package/dist/hitl/gateLedger.js +0 -19
- package/dist/hitl/hitlBridge.d.ts +7 -0
- package/dist/hitl/hitlBridge.js +14 -8
- package/dist/hitl/hitlHostSurface.d.ts +3 -1
- package/dist/hitl/hitlHostSurface.js +14 -4
- package/dist/hitl/hostWithdrawal.d.ts +15 -0
- package/dist/hitl/hostWithdrawal.js +38 -0
- package/dist/hitl/localAllowRedemption.d.ts +67 -0
- package/dist/hitl/localAllowRedemption.js +256 -0
- package/dist/hitl/parkResolver.js +32 -13
- package/dist/hitl/persistedRulesWire.d.ts +16 -0
- package/dist/hitl/persistedRulesWire.js +72 -2
- package/dist/hitl/planReviewWire.d.ts +3 -0
- package/dist/hitl/planReviewWire.js +37 -10
- package/dist/hitl/policyDenyCause.d.ts +1 -1
- package/dist/hitl/policyDenyCause.js +1 -1
- package/dist/hitl/resumeRunningCard.d.ts +1 -0
- package/dist/hitl/resumeRunningCard.js +1 -0
- package/dist/hitl/screenCardCarriers.d.ts +15 -0
- package/dist/hitl/screenCardCarriers.js +41 -0
- package/dist/hitl/screenDecisionCards.d.ts +98 -0
- package/dist/hitl/screenDecisionCards.js +362 -0
- package/dist/hitl/sessionPolicyWire.js +6 -4
- package/dist/hitl/standingRows.d.ts +4 -1
- package/dist/hitl/standingRows.js +33 -1
- package/dist/hitl/toolApprovalWire.d.ts +64 -15
- package/dist/hitl/toolApprovalWire.js +470 -125
- package/dist/hooksWireCaps.js +31 -1
- package/dist/hostSettingNoticeArm.d.ts +3 -0
- package/dist/hostSettingNoticeArm.js +12 -0
- package/dist/hostTurnSettings.d.ts +13 -4
- package/dist/hostTurnSettings.js +150 -10
- package/dist/humanTurnRead.js +11 -1
- package/dist/i18n/messages.en.d.ts +212 -0
- package/dist/i18n/messages.en.js +217 -5
- package/dist/i18n/messages.zh.js +235 -5
- package/dist/i18n/translate.d.ts +3 -0
- package/dist/i18n/translate.js +78 -10
- package/dist/i18n/zh.d.ts +1 -0
- package/dist/i18n/zh.js +1 -0
- package/dist/index.d.ts +56 -16
- package/dist/index.js +40 -12
- package/dist/inheritEnvCapability.js +2 -0
- package/dist/inputAuthor.d.ts +16 -0
- package/dist/inputAuthor.js +44 -0
- package/dist/interactiveHalt.js +2 -1
- package/dist/interactiveInterrupt.js +20 -2
- package/dist/interruptRefusalNote.d.ts +2 -0
- package/dist/interruptRefusalNote.js +17 -0
- package/dist/liveModelCatalog.d.ts +2 -0
- package/dist/liveModelCatalog.js +23 -9
- package/dist/liveQuestionStore.d.ts +4 -1
- package/dist/liveQuestionStore.js +12 -3
- package/dist/localEngineSeatReading.d.ts +2 -2
- package/dist/localEngineSeatReading.js +5 -3
- package/dist/localEngineSpawn.d.ts +0 -7
- package/dist/localEngineSpawn.js +0 -92
- package/dist/localEngineStep.d.ts +2 -2
- package/dist/localEngineStep.js +2 -0
- package/dist/mcpEngineLeg.d.ts +3 -0
- package/dist/mcpEngineLeg.js +38 -1
- package/dist/mcpPanel.js +2 -0
- package/dist/mcpReconnect.d.ts +9 -1
- package/dist/mcpReconnect.js +124 -19
- package/dist/mcpWireCaps.js +1 -1
- package/dist/model/engineModelWords.d.ts +3 -0
- package/dist/model/engineModelWords.js +13 -0
- package/dist/model/subagentModelWord.d.ts +21 -2
- package/dist/model/subagentModelWord.js +100 -29
- package/dist/modelCapabilityProbe.js +7 -43
- package/dist/modsFace.d.ts +8 -1
- package/dist/modsFace.js +27 -0
- package/dist/notifications.d.ts +36 -6
- package/dist/notifications.js +170 -20
- package/dist/ownKey.d.ts +6 -5
- package/dist/ownKey.js +31 -7
- package/dist/peerFrames.d.ts +40 -2
- package/dist/peerFrames.js +158 -3
- package/dist/pendingUserRow.d.ts +4 -0
- package/dist/pendingUserRow.js +16 -0
- package/dist/permissionsDeclaration.d.ts +1 -0
- package/dist/permissionsDeclaration.js +11 -1
- package/dist/planReviewCardFacts.d.ts +3 -0
- package/dist/planReviewCardFacts.js +52 -2
- package/dist/pluginHooksWire.d.ts +10 -1
- package/dist/pluginHooksWire.js +96 -7
- package/dist/printToolResultFrame.js +4 -2
- package/dist/promptBlockedCopy.js +11 -6
- package/dist/promptSuggestionBatch.d.ts +7 -0
- package/dist/promptSuggestionBatch.js +9 -0
- package/dist/promptSuggestionsTail.d.ts +39 -0
- package/dist/promptSuggestionsTail.js +116 -0
- package/dist/replayBody.js +10 -2
- package/dist/request/taskRequest.d.ts +5 -0
- package/dist/request/taskRequest.js +142 -21
- package/dist/requestCoordinate.d.ts +1 -0
- package/dist/requestCoordinate.js +13 -0
- package/dist/resumeRefusalCopy.d.ts +1 -3
- package/dist/resumeRefusalCopy.js +2 -1
- package/dist/retryStatus.d.ts +2 -2
- package/dist/retryStatus.js +2 -0
- package/dist/rewindArchiveReading.js +4 -4
- package/dist/runCancelContext.d.ts +2 -1
- package/dist/runCancelContext.js +1 -0
- package/dist/runPermissionModeSwitch.js +2 -2
- package/dist/scenarioRefusal.js +11 -13
- package/dist/scenarioSkills.js +11 -6
- package/dist/seam.d.ts +27 -2
- package/dist/seam.js +17 -1
- package/dist/seatContract.d.ts +189 -12
- package/dist/seatContract.js +401 -9
- package/dist/sessionBackground.js +2 -1
- package/dist/sessionBackgroundHandoff.js +2 -1
- package/dist/sessionCostReading.d.ts +70 -0
- package/dist/sessionCostReading.js +150 -0
- package/dist/sessionEngine.d.ts +2 -0
- package/dist/sessionEngine.js +111 -0
- package/dist/sessionHooksRoster.d.ts +4 -0
- package/dist/sessionHooksRoster.js +158 -0
- package/dist/sessionMemoryStatus.d.ts +2 -1
- package/dist/sessionMemoryStatus.js +2 -2
- package/dist/sessionReadRedaction.d.ts +7 -0
- package/dist/sessionReadRedaction.js +26 -0
- package/dist/sessionSyncFileHistory.d.ts +4 -0
- package/dist/sessionSyncFileHistory.js +27 -0
- package/dist/settingsHooksSalvage.js +2 -1
- package/dist/sseIdleTriage.d.ts +13 -1
- package/dist/sseIdleTriage.js +25 -6
- package/dist/storeDurabilityWord.d.ts +15 -0
- package/dist/storeDurabilityWord.js +18 -0
- package/dist/storePostureCapability.d.ts +7 -3
- package/dist/storePostureCapability.js +69 -39
- package/dist/subagent/engineSubagentResume.js +2 -2
- package/dist/subagent/engineSubagentTail.js +8 -1
- package/dist/subagentContentStore.d.ts +11 -0
- package/dist/subagentContentStore.js +28 -2
- package/dist/terminalStatuses.d.ts +1 -0
- package/dist/terminalStatuses.js +4 -1
- package/dist/toolResult.d.ts +1 -0
- package/dist/toolResult.js +2 -0
- package/dist/turnFailurePresentation.js +9 -2
- package/dist/typePins.d.ts +11 -0
- package/dist/usageAnalytics.d.ts +17 -0
- package/dist/usageAnalytics.js +44 -2
- package/dist/userAttachmentEnvelope.d.ts +2 -1
- package/dist/userAttachmentEnvelope.js +10 -0
- package/dist/wireErrorTriage.js +2 -1
- package/dist/wireFailureShape.d.ts +6 -5
- package/dist/wireFailureShape.js +150 -38
- package/dist/wireRefusalCopy.d.ts +16 -5
- package/dist/wireRefusalCopy.js +119 -86
- package/docs/INTEGRATION-CLIENTS.md +4228 -21
- package/package.json +7 -3
package/dist/seatContract.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PERMISSION_MODE_WORDS, REASONING_EFFORT_WORDS } from "./taskRequestWords.js";
|
|
2
|
+
import { CC_TOOL_DENIAL_KINDS } from "./gateVocabulary.js";
|
|
2
3
|
import { liveDefaultModelCopy, liveModelRowCopy } from "./model/liveCatalogShape.js";
|
|
3
4
|
import { REWIND_MODES } from "./rewindWireCaps.js";
|
|
4
5
|
import { SETTINGS_MODEL_API_WORDS } from "./generated/settingsSchemaTables.js";
|
|
@@ -11,6 +12,10 @@ import { THINKING_LATCH_EVENTS, THINKING_LATCH_ROW_WORDS } from "./thinkingLatch
|
|
|
11
12
|
import { EXECUTION_PLACEMENT_ROLES } from "./executionPlacementWords.js";
|
|
12
13
|
import { isSessionEngineView } from "./sessionEngine.js";
|
|
13
14
|
import { LOCAL_ENGINE_SWAP_CAUSES } from "./localEngineSwapCard.js";
|
|
15
|
+
import { HOOK_ENTRY_TYPE_WORDS, PLUGIN_HOOK_EXCLUSION_REASONS, PLUGIN_HOOK_REASONS, SETTINGS_HOOK_DROP_REASONS, } from "./pluginHooksWire.js";
|
|
16
|
+
import { HTTP_POLICY_DROP_REASONS } from "./httpHookPolicy.js";
|
|
17
|
+
import { HOOK_SETTINGS_SOURCE_TEXT } from "./settingsHooksSalvage.js";
|
|
18
|
+
import { SETTINGS_HOOK_EVENTS, SETTINGS_HOOKS_DROPPED_PIECE_CODES, SETTINGS_HOOKS_REJECTION_CODES } from "./generated/settingsSchemaFns.js";
|
|
14
19
|
const bad = (reason, field) => field === undefined ? { reason } : { reason, field };
|
|
15
20
|
const nested = (prefix, verdict) => {
|
|
16
21
|
const path = verdict.field === undefined
|
|
@@ -310,6 +315,9 @@ const CHROME_ARM_SEAT_ROUTE = {
|
|
|
310
315
|
compaction_outcome: "seat",
|
|
311
316
|
engine_notice: "seat",
|
|
312
317
|
subagent_alias: "seat",
|
|
318
|
+
session_box_notice: "seat",
|
|
319
|
+
resupply_truncated: "seat",
|
|
320
|
+
host_setting_notice: "seat",
|
|
313
321
|
workflow_notification_enqueue: "host",
|
|
314
322
|
plan_review_park: "host",
|
|
315
323
|
approval_request: "host",
|
|
@@ -398,7 +406,7 @@ export function readSeatStreamDelta(message) {
|
|
|
398
406
|
return Object.freeze({ kind: "malformed" });
|
|
399
407
|
}
|
|
400
408
|
}
|
|
401
|
-
export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions"]);
|
|
409
|
+
export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions", "notificationLevels", "modsView", "quickEntryShortcut", "hooksRoster"]);
|
|
402
410
|
const notReported = () => Object.freeze({ kind: "not_reported" });
|
|
403
411
|
const malformedReading = () => Object.freeze({ kind: "malformed" });
|
|
404
412
|
const reported = (available) => Object.freeze({ kind: "reported", available });
|
|
@@ -478,6 +486,10 @@ const SEAT_CAPABILITY_PHRASES = Object.freeze({
|
|
|
478
486
|
computerUseSwitch: Object.freeze({ action: "Computer use", ability: "be switched", support: "switch support" }),
|
|
479
487
|
engineModeDefaultOnly: Object.freeze({ action: "Default-only engine switching", ability: "keep existing sessions on their engine", support: "default-only engine switching" }),
|
|
480
488
|
seatActions: Object.freeze({ action: "App menu actions", ability: "send actions to this window", support: "app action support" }),
|
|
489
|
+
notificationLevels: Object.freeze({ action: "Choosing notification levels", ability: "keep notification levels", support: "notification-level support" }),
|
|
490
|
+
modsView: Object.freeze({ action: "Showing mods", ability: "show mods", support: "mods support" }),
|
|
491
|
+
quickEntryShortcut: Object.freeze({ action: "Changing the Quick Entry shortcut", ability: "change the Quick Entry shortcut", support: "Quick Entry shortcut support" }),
|
|
492
|
+
hooksRoster: Object.freeze({ action: "Showing hooks", ability: "show hooks", support: "hooks support" }),
|
|
481
493
|
});
|
|
482
494
|
export function seatCapabilityUnavailableDetail(name, reading) {
|
|
483
495
|
const phrase = Object.hasOwn(SEAT_CAPABILITY_PHRASES, name)
|
|
@@ -600,6 +612,7 @@ export const SEAT_TURN_SETTINGS_ORIGINS = Object.freeze({
|
|
|
600
612
|
hooks: Object.freeze({ hostSupplied: "settings.hooks" }),
|
|
601
613
|
resolved: Object.freeze({ hostSupplied: "settings.resolved" }),
|
|
602
614
|
outputStyle: Object.freeze({ hostSupplied: "settings.outputStyle" }),
|
|
615
|
+
env: Object.freeze({ hostSupplied: "settings.env" }),
|
|
603
616
|
});
|
|
604
617
|
export const SEAT_REWIND_INTENT_KEYS = ["mode", "targetMessageUuid"];
|
|
605
618
|
export const ATTACHMENT_UPLOAD_REQUEST_KEYS = ["name", "mimeType", "bytes"];
|
|
@@ -711,6 +724,7 @@ export const LOCAL_ENGINE_DOWN_REASONS = Object.freeze([
|
|
|
711
724
|
"stop-failed",
|
|
712
725
|
"crash-loop",
|
|
713
726
|
"high-water-unreadable",
|
|
727
|
+
"exited-once",
|
|
714
728
|
"principal-unknown",
|
|
715
729
|
]);
|
|
716
730
|
export const LOCAL_ENGINE_WAITING_REASONS = Object.freeze(["starting", "dormant", "draining", "unanswered", "peer"]);
|
|
@@ -845,7 +859,7 @@ const R_UNANSWERED_ONLY = ruleOf("unanswered-only", () => false);
|
|
|
845
859
|
const ENGINE_TARGET_LOCAL_SPEC = {
|
|
846
860
|
lastBootError: optF(R_STR),
|
|
847
861
|
mcp: optF(SEAT_LOCAL_MCP_READING),
|
|
848
|
-
lifecycle:
|
|
862
|
+
lifecycle: reqF(LOCAL_ENGINE_SEAT_READING),
|
|
849
863
|
};
|
|
850
864
|
const ENGINE_TARGET_LOCAL = {
|
|
851
865
|
label: "local",
|
|
@@ -855,8 +869,6 @@ const ENGINE_TARGET_LOCAL = {
|
|
|
855
869
|
return verdict;
|
|
856
870
|
const rec = v;
|
|
857
871
|
const lifecycle = own(rec, "lifecycle");
|
|
858
|
-
if (isAbsent(lifecycle))
|
|
859
|
-
return true;
|
|
860
872
|
const phase = own(lifecycle, "phase");
|
|
861
873
|
const bootError = !isAbsent(own(rec, "lastBootError"));
|
|
862
874
|
if (bootError !== (phase === "down"))
|
|
@@ -872,7 +884,7 @@ const ENGINE_TARGET_STATE = shapeRule("engine target", {
|
|
|
872
884
|
mode: reqF(R_ENGINE_LANE),
|
|
873
885
|
generation: reqF(R_INT0),
|
|
874
886
|
cloud: reqF(ENGINE_TARGET_CLOUD),
|
|
875
|
-
local:
|
|
887
|
+
local: optF(ENGINE_TARGET_LOCAL),
|
|
876
888
|
});
|
|
877
889
|
const checkEngineTargetState = seatShapeCheck(ENGINE_TARGET_STATE);
|
|
878
890
|
const okArmsRule = (label, okSpec, refusedSpec) => ({
|
|
@@ -1074,6 +1086,118 @@ const checkSessionMcpPanelResult = seatCheck((v) => {
|
|
|
1074
1086
|
return checkSessionMcpPanelFailure(v);
|
|
1075
1087
|
return Object.hasOwn(v, "scenarioRefusal") ? checkSessionMcpPanelRefusalView(v) : checkSessionMcpPanelServersView(v);
|
|
1076
1088
|
});
|
|
1089
|
+
const MOD_ROW_SKIP = shapeRule("mod skip", {
|
|
1090
|
+
registration: reqF(R_NONEMPTY),
|
|
1091
|
+
cause: reqF(R_NONEMPTY),
|
|
1092
|
+
reason: reqF(R_NONEMPTY),
|
|
1093
|
+
});
|
|
1094
|
+
const MOD_ROW_MOUNTED_SPEC = {
|
|
1095
|
+
name: reqF(R_NONEMPTY),
|
|
1096
|
+
seat: reqF(R_NONEMPTY),
|
|
1097
|
+
tier: reqF(R_NONEMPTY),
|
|
1098
|
+
provenance: optF(R_NONEMPTY),
|
|
1099
|
+
events: reqF(arrayRule(R_STR)),
|
|
1100
|
+
observe: optF(arrayRule(R_STR)),
|
|
1101
|
+
skipped: optF(arrayRule(MOD_ROW_SKIP, true)),
|
|
1102
|
+
};
|
|
1103
|
+
const MOD_ROW_REFUSED_SPEC = {
|
|
1104
|
+
name: reqF(R_NONEMPTY),
|
|
1105
|
+
seat: reqF(R_NONEMPTY),
|
|
1106
|
+
tier: reqF(R_NONEMPTY),
|
|
1107
|
+
provenance: optF(R_NONEMPTY),
|
|
1108
|
+
refusedBy: reqF(R_NONEMPTY),
|
|
1109
|
+
reason: reqF(R_NONEMPTY),
|
|
1110
|
+
};
|
|
1111
|
+
const MOD_ROW = {
|
|
1112
|
+
label: "mod row",
|
|
1113
|
+
test: (v, path) => {
|
|
1114
|
+
if (!isPlainRecord(v))
|
|
1115
|
+
return bad("not object", path);
|
|
1116
|
+
return Object.hasOwn(v, "refusedBy") || Object.hasOwn(v, "reason") ? shapeVerdict(MOD_ROW_REFUSED_SPEC, v, path) : shapeVerdict(MOD_ROW_MOUNTED_SPEC, v, path);
|
|
1117
|
+
},
|
|
1118
|
+
};
|
|
1119
|
+
const checkSessionModsFailure = seatShapeCheck(armsRule("readSessionMods failure", "kind", {
|
|
1120
|
+
unreadable: DEVICE_UNREADABLE_SPEC,
|
|
1121
|
+
unarmed: {},
|
|
1122
|
+
}));
|
|
1123
|
+
const checkSessionModsView = seatShapeCheck(shapeRule("mods view", { rows: reqF(arrayRule(MOD_ROW)) }));
|
|
1124
|
+
const checkSessionModsResult = seatCheck((v) => {
|
|
1125
|
+
if (!isPlainRecord(v))
|
|
1126
|
+
return bad("not object");
|
|
1127
|
+
return Object.hasOwn(v, "kind") ? checkSessionModsFailure(v) : checkSessionModsView(v);
|
|
1128
|
+
});
|
|
1129
|
+
export const SESSION_HOOKS_ROSTER_STATUSES = Object.freeze(["engine", "shell", "not_run"]);
|
|
1130
|
+
const HOOKS_ROSTER_CLOSED_BY = Object.freeze(["workspace_untrusted", "governance_unreadable", "policy_disable_all"]);
|
|
1131
|
+
const HOOKS_ROSTER_REASONS = Object.freeze([...new Set([...PLUGIN_HOOK_REASONS, ...PLUGIN_HOOK_EXCLUSION_REASONS, ...SETTINGS_HOOK_DROP_REASONS])]);
|
|
1132
|
+
const R_HOOK_SOURCE = ruleOf("hook source", (v) => typeof v === "string" && Object.hasOwn(HOOK_SETTINGS_SOURCE_TEXT, v));
|
|
1133
|
+
const R_HOOK_EVENT = oneOfRule("hook event", SETTINGS_HOOK_EVENTS);
|
|
1134
|
+
const HOOKS_ROSTER_ROW_SHAPE = shapeRule("hooks roster row", {
|
|
1135
|
+
source: reqF(R_HOOK_SOURCE),
|
|
1136
|
+
event: reqF(R_HOOK_EVENT),
|
|
1137
|
+
groupIndex: reqF(R_INT0),
|
|
1138
|
+
hookIndex: reqF(R_INT0),
|
|
1139
|
+
type: optF(oneOfRule("hook type", HOOK_ENTRY_TYPE_WORDS)),
|
|
1140
|
+
status: reqF(oneOfRule("hooks roster status", SESSION_HOOKS_ROSTER_STATUSES)),
|
|
1141
|
+
reason: reqF(oneOfRule("hooks roster reason", HOOKS_ROSTER_REASONS)),
|
|
1142
|
+
});
|
|
1143
|
+
const HOOKS_ROSTER_ROW = {
|
|
1144
|
+
label: HOOKS_ROSTER_ROW_SHAPE.label,
|
|
1145
|
+
test: (v, path) => {
|
|
1146
|
+
const verdict = HOOKS_ROSTER_ROW_SHAPE.test(v, path);
|
|
1147
|
+
if (verdict !== true)
|
|
1148
|
+
return verdict;
|
|
1149
|
+
const rec = v;
|
|
1150
|
+
const status = own(rec, "status");
|
|
1151
|
+
const reason = own(rec, "reason");
|
|
1152
|
+
if (status === "engine" && !PLUGIN_HOOK_REASONS.includes(reason))
|
|
1153
|
+
return bad("status conflict", pathAt(path, "reason"));
|
|
1154
|
+
return true;
|
|
1155
|
+
},
|
|
1156
|
+
};
|
|
1157
|
+
const HOOKS_ROSTER_LAYER = armsRule("hooks roster layer", "state", {
|
|
1158
|
+
"loaded-partial": { source: reqF(R_HOOK_SOURCE), codes: reqF(arrayRule(oneOfRule("hooks drop code", SETTINGS_HOOKS_DROPPED_PIECE_CODES), true)) },
|
|
1159
|
+
rejected: { source: reqF(R_HOOK_SOURCE), codes: reqF(arrayRule(oneOfRule("hooks rejection code", SETTINGS_HOOKS_REJECTION_CODES), true)) },
|
|
1160
|
+
trust_withheld: { source: reqF(R_HOOK_SOURCE) },
|
|
1161
|
+
});
|
|
1162
|
+
const HOOKS_ROSTER_HTTP_ROW = shapeRule("hooks roster http row", {
|
|
1163
|
+
source: reqF(R_HOOK_SOURCE),
|
|
1164
|
+
event: reqF(R_HOOK_EVENT),
|
|
1165
|
+
reason: reqF(oneOfRule("http policy reason", HTTP_POLICY_DROP_REASONS)),
|
|
1166
|
+
});
|
|
1167
|
+
const HOOKS_ROSTER_SHAPE = shapeRule("hooks roster", {
|
|
1168
|
+
closedBy: reqF(ruleOf("closedBy", (v) => v === null || (typeof v === "string" && inTuple(HOOKS_ROSTER_CLOSED_BY, v)))),
|
|
1169
|
+
sources: optF(arrayRule(R_HOOK_SOURCE)),
|
|
1170
|
+
rows: reqF(arrayRule(HOOKS_ROSTER_ROW)),
|
|
1171
|
+
layers: reqF(arrayRule(HOOKS_ROSTER_LAYER)),
|
|
1172
|
+
http: reqF(arrayRule(HOOKS_ROSTER_HTTP_ROW)),
|
|
1173
|
+
unlisted: reqF(R_INT0),
|
|
1174
|
+
});
|
|
1175
|
+
const checkSessionHooksRosterView = seatShapeCheck({
|
|
1176
|
+
label: HOOKS_ROSTER_SHAPE.label,
|
|
1177
|
+
test: (v, path) => {
|
|
1178
|
+
const verdict = HOOKS_ROSTER_SHAPE.test(v, path);
|
|
1179
|
+
if (verdict !== true)
|
|
1180
|
+
return verdict;
|
|
1181
|
+
const rec = v;
|
|
1182
|
+
if (own(rec, "closedBy") === null)
|
|
1183
|
+
return true;
|
|
1184
|
+
const rows = ownItems(own(rec, "rows"));
|
|
1185
|
+
for (let i = 0; i < rows.length; i += 1) {
|
|
1186
|
+
if (own(rows[i], "status") !== "not_run")
|
|
1187
|
+
return bad("status conflict", pathAt(path, `rows[${i}].status`));
|
|
1188
|
+
}
|
|
1189
|
+
return true;
|
|
1190
|
+
},
|
|
1191
|
+
});
|
|
1192
|
+
const checkSessionHooksRosterFailure = seatShapeCheck(armsRule("readSessionHooksRoster failure", "kind", {
|
|
1193
|
+
unreadable: DEVICE_UNREADABLE_SPEC,
|
|
1194
|
+
unarmed: {},
|
|
1195
|
+
}));
|
|
1196
|
+
const checkSessionHooksRosterResult = seatCheck((v) => {
|
|
1197
|
+
if (!isPlainRecord(v))
|
|
1198
|
+
return bad("not object");
|
|
1199
|
+
return Object.hasOwn(v, "kind") ? checkSessionHooksRosterFailure(v) : checkSessionHooksRosterView(v);
|
|
1200
|
+
});
|
|
1077
1201
|
const MCP_TOOL_TOGGLE_KEY = shapeRule("toggle key", {
|
|
1078
1202
|
server: reqF(R_NONEMPTY),
|
|
1079
1203
|
tool: reqF(R_NONEMPTY),
|
|
@@ -1169,7 +1293,144 @@ export function planSetComputerUse(request, lockedByEnv) {
|
|
|
1169
1293
|
return Object.freeze({ kind: "refused", reason: "confirmation-required" });
|
|
1170
1294
|
return Object.freeze({ kind: "apply", enabled: intent.kind === "enable" });
|
|
1171
1295
|
}
|
|
1172
|
-
export const
|
|
1296
|
+
export const NOTIFICATION_LEVEL_TYPES = Object.freeze(["permission", "question", "idle"]);
|
|
1297
|
+
export const NOTIFICATION_LEVELS = Object.freeze(["off", "badge", "banner"]);
|
|
1298
|
+
export const NOTIFICATION_LEVEL_REFUSAL_REASONS = Object.freeze(["invalid-request", "unsupported-level", "write-failed"]);
|
|
1299
|
+
const R_NOTIFICATION_LEVEL = oneOfRule("notification level", NOTIFICATION_LEVELS);
|
|
1300
|
+
const NOTIFICATION_SUPPORTED_ITEMS = arrayRule(R_NOTIFICATION_LEVEL, true);
|
|
1301
|
+
const NOTIFICATION_SUPPORTED_ORDER = "bad value (supported levels: off first, closed-set order, no repeats)";
|
|
1302
|
+
const R_NOTIFICATION_SUPPORTED = {
|
|
1303
|
+
label: "supported levels",
|
|
1304
|
+
test: (v, path) => {
|
|
1305
|
+
const verdict = NOTIFICATION_SUPPORTED_ITEMS.test(v, path);
|
|
1306
|
+
if (verdict !== true)
|
|
1307
|
+
return verdict;
|
|
1308
|
+
const rank = (x) => NOTIFICATION_LEVELS.indexOf(x);
|
|
1309
|
+
const rows = ownItems(v);
|
|
1310
|
+
if (rows[0] !== "off")
|
|
1311
|
+
return bad(NOTIFICATION_SUPPORTED_ORDER, path);
|
|
1312
|
+
for (let i = 1; i < rows.length; i += 1)
|
|
1313
|
+
if (rank(rows[i]) <= rank(rows[i - 1]))
|
|
1314
|
+
return bad(NOTIFICATION_SUPPORTED_ORDER, `${path}[${i}]`);
|
|
1315
|
+
return true;
|
|
1316
|
+
},
|
|
1317
|
+
};
|
|
1318
|
+
const NOTIFICATION_LEVELS_STATE_SHAPE = shapeRule("notification levels state", {
|
|
1319
|
+
levels: reqF(shapeRule("notification levels", {
|
|
1320
|
+
permission: reqF(R_NOTIFICATION_LEVEL),
|
|
1321
|
+
question: reqF(R_NOTIFICATION_LEVEL),
|
|
1322
|
+
idle: reqF(R_NOTIFICATION_LEVEL),
|
|
1323
|
+
})),
|
|
1324
|
+
supported: reqF(R_NOTIFICATION_SUPPORTED),
|
|
1325
|
+
});
|
|
1326
|
+
const NOTIFICATION_LEVELS_STATE = {
|
|
1327
|
+
label: NOTIFICATION_LEVELS_STATE_SHAPE.label,
|
|
1328
|
+
test: (v, path) => {
|
|
1329
|
+
const verdict = NOTIFICATION_LEVELS_STATE_SHAPE.test(v, path);
|
|
1330
|
+
if (verdict !== true)
|
|
1331
|
+
return verdict;
|
|
1332
|
+
const rec = v;
|
|
1333
|
+
const levels = own(rec, "levels");
|
|
1334
|
+
const supported = ownItems(own(rec, "supported"));
|
|
1335
|
+
for (const t of NOTIFICATION_LEVEL_TYPES)
|
|
1336
|
+
if (!supported.includes(own(levels, t)))
|
|
1337
|
+
return bad("unsupported level", pathAt(path, `levels.${t}`));
|
|
1338
|
+
return true;
|
|
1339
|
+
},
|
|
1340
|
+
};
|
|
1341
|
+
const checkNotificationLevelsState = seatShapeCheck(NOTIFICATION_LEVELS_STATE);
|
|
1342
|
+
const checkSetNotificationLevelResult = seatShapeCheck(okArmsRule("setNotificationLevel result", { state: reqF(NOTIFICATION_LEVELS_STATE) }, {
|
|
1343
|
+
reason: reqF(oneOfRule("notification level refusal", NOTIFICATION_LEVEL_REFUSAL_REASONS)),
|
|
1344
|
+
state: reqF(NOTIFICATION_LEVELS_STATE),
|
|
1345
|
+
}));
|
|
1346
|
+
export function planSetNotificationLevel(type, level, supported) {
|
|
1347
|
+
if (typeof type !== "string" || !inTuple(NOTIFICATION_LEVEL_TYPES, type) || typeof level !== "string" || !inTuple(NOTIFICATION_LEVELS, level)) {
|
|
1348
|
+
return Object.freeze({ kind: "refused", reason: "invalid-request" });
|
|
1349
|
+
}
|
|
1350
|
+
let delivers = false;
|
|
1351
|
+
try {
|
|
1352
|
+
const n = Array.isArray(supported) ? ownDataField(supported, "length") : undefined;
|
|
1353
|
+
if (typeof n === "number" && Number.isSafeInteger(n) && n <= NOTIFICATION_LEVELS.length) {
|
|
1354
|
+
for (let i = 0; i < n && !delivers; i += 1)
|
|
1355
|
+
delivers = own(supported, String(i)) === level;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
catch {
|
|
1359
|
+
delivers = false;
|
|
1360
|
+
}
|
|
1361
|
+
if (!delivers)
|
|
1362
|
+
return Object.freeze({ kind: "refused", reason: "unsupported-level" });
|
|
1363
|
+
return Object.freeze({ kind: "apply", type, level });
|
|
1364
|
+
}
|
|
1365
|
+
export const QUICK_ENTRY_SHORTCUT_FAILURES = Object.freeze(["invalid-accelerator", "registration-failed"]);
|
|
1366
|
+
export const QUICK_ENTRY_SHORTCUT_REFUSAL_REASONS = Object.freeze(["invalid-request", "invalid-accelerator", "registration-failed", "write-failed"]);
|
|
1367
|
+
const QUICK_ENTRY_ACCELERATOR_SPEC = { accelerator: reqF(R_NONEMPTY) };
|
|
1368
|
+
const R_QUICK_ENTRY_SHORTCUT = {
|
|
1369
|
+
label: "quick entry shortcut",
|
|
1370
|
+
test: (v, path) => (v === "off" ? true : shapeVerdict(QUICK_ENTRY_ACCELERATOR_SPEC, v, path)),
|
|
1371
|
+
};
|
|
1372
|
+
const QUICK_ENTRY_STATE_SHAPE = shapeRule("quick entry shortcut state", {
|
|
1373
|
+
saved: reqF(R_QUICK_ENTRY_SHORTCUT),
|
|
1374
|
+
active: reqF(ruleOf("active accelerator", (v) => v === null || (typeof v === "string" && v.length > 0))),
|
|
1375
|
+
savedFailure: reqF(ruleOf("saved failure", (v) => v === null || (typeof v === "string" && inTuple(QUICK_ENTRY_SHORTCUT_FAILURES, v)))),
|
|
1376
|
+
});
|
|
1377
|
+
const QUICK_ENTRY_STATE = {
|
|
1378
|
+
label: QUICK_ENTRY_STATE_SHAPE.label,
|
|
1379
|
+
test: (v, path) => {
|
|
1380
|
+
const verdict = QUICK_ENTRY_STATE_SHAPE.test(v, path);
|
|
1381
|
+
if (verdict !== true)
|
|
1382
|
+
return verdict;
|
|
1383
|
+
const rec = v;
|
|
1384
|
+
if (own(rec, "savedFailure") === null)
|
|
1385
|
+
return true;
|
|
1386
|
+
const saved = own(rec, "saved");
|
|
1387
|
+
if (saved === "off")
|
|
1388
|
+
return bad("failure conflict", pathAt(path, "savedFailure"));
|
|
1389
|
+
if (own(rec, "active") === own(saved, "accelerator"))
|
|
1390
|
+
return bad("failure conflict", pathAt(path, "active"));
|
|
1391
|
+
return true;
|
|
1392
|
+
},
|
|
1393
|
+
};
|
|
1394
|
+
const checkQuickEntryShortcutState = seatShapeCheck(QUICK_ENTRY_STATE);
|
|
1395
|
+
const SET_QUICK_ENTRY_SHORTCUT_RESULT = okArmsRule("setQuickEntryShortcut result", { state: reqF(QUICK_ENTRY_STATE) }, {
|
|
1396
|
+
reason: reqF(oneOfRule("quick entry refusal", QUICK_ENTRY_SHORTCUT_REFUSAL_REASONS)),
|
|
1397
|
+
state: reqF(QUICK_ENTRY_STATE),
|
|
1398
|
+
});
|
|
1399
|
+
const checkSetQuickEntryShortcutResult = seatShapeCheck({
|
|
1400
|
+
label: SET_QUICK_ENTRY_SHORTCUT_RESULT.label,
|
|
1401
|
+
test: (v, path) => {
|
|
1402
|
+
const verdict = SET_QUICK_ENTRY_SHORTCUT_RESULT.test(v, path);
|
|
1403
|
+
if (verdict !== true)
|
|
1404
|
+
return verdict;
|
|
1405
|
+
const rec = v;
|
|
1406
|
+
if (own(rec, "ok") === true && own(own(rec, "state"), "savedFailure") !== null)
|
|
1407
|
+
return bad("failure conflict", pathAt(path, "state.savedFailure"));
|
|
1408
|
+
return true;
|
|
1409
|
+
},
|
|
1410
|
+
});
|
|
1411
|
+
export function planSetQuickEntryShortcut(request) {
|
|
1412
|
+
const refused = Object.freeze({ kind: "refused", reason: "invalid-request" });
|
|
1413
|
+
if (request === "off")
|
|
1414
|
+
return Object.freeze({ kind: "apply", next: "off" });
|
|
1415
|
+
try {
|
|
1416
|
+
if (!isPlainRecord(request) || firstAccessorPath(request) !== undefined)
|
|
1417
|
+
return refused;
|
|
1418
|
+
const snap = new Map();
|
|
1419
|
+
for (const k of Reflect.ownKeys(request))
|
|
1420
|
+
if (typeof k === "string")
|
|
1421
|
+
snap.set(k, own(request, k));
|
|
1422
|
+
if (snap.size !== 1 || !snap.has("accelerator"))
|
|
1423
|
+
return refused;
|
|
1424
|
+
const accelerator = snap.get("accelerator");
|
|
1425
|
+
if (typeof accelerator !== "string" || accelerator.length === 0)
|
|
1426
|
+
return refused;
|
|
1427
|
+
return Object.freeze({ kind: "apply", next: Object.freeze({ accelerator }) });
|
|
1428
|
+
}
|
|
1429
|
+
catch {
|
|
1430
|
+
return refused;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
export const SEAT_ACTION_NAMES = Object.freeze(["new-project", "prefill-composer", "open-local-setup"]);
|
|
1173
1434
|
const SEAT_PREFILL_TEXT_MAX = 14336;
|
|
1174
1435
|
const SEAT_PREFILL_CWD_MAX = 4096;
|
|
1175
1436
|
const SEAT_ACTIONS_CLAIM_MAX = 16;
|
|
@@ -1182,6 +1443,7 @@ const R_PREFILL_CWD = ruleOf(`folder path (1–${SEAT_PREFILL_CWD_MAX} chars, no
|
|
|
1182
1443
|
const SEAT_ACTION_ARMS = {
|
|
1183
1444
|
"new-project": {},
|
|
1184
1445
|
"prefill-composer": { text: reqF(R_PREFILL_TEXT), cwd: optF(R_PREFILL_CWD) },
|
|
1446
|
+
"open-local-setup": {},
|
|
1185
1447
|
};
|
|
1186
1448
|
export const checkSeatAction = seatShapeCheck(armsRule("seat action", "action", SEAT_ACTION_ARMS));
|
|
1187
1449
|
const seatActionMalformed = (reason) => Object.freeze({ kind: "malformed", reason });
|
|
@@ -1200,6 +1462,8 @@ export function readSeatAction(ev) {
|
|
|
1200
1462
|
}
|
|
1201
1463
|
if (name === "new-project")
|
|
1202
1464
|
return Object.freeze({ kind: "action", action: Object.freeze({ action: "new-project" }) });
|
|
1465
|
+
if (name === "open-local-setup")
|
|
1466
|
+
return Object.freeze({ kind: "action", action: Object.freeze({ action: "open-local-setup" }) });
|
|
1203
1467
|
const text = own(ev, "text");
|
|
1204
1468
|
const cwd = own(ev, "cwd");
|
|
1205
1469
|
if (R_PREFILL_TEXT.test(text, "text") !== true || typeof text !== "string")
|
|
@@ -1652,6 +1916,8 @@ const SUBAGENT_CONTENT_SHAPE = shapeRule("subagent content", {
|
|
|
1652
1916
|
output: optF(R_STR),
|
|
1653
1917
|
isError: optF(R_BOOL),
|
|
1654
1918
|
notExecuted: optF(R_TRUE),
|
|
1919
|
+
denialKind: optF(oneOfRule("denial kind", CC_TOOL_DENIAL_KINDS)),
|
|
1920
|
+
refusalNoted: optF(R_TRUE),
|
|
1655
1921
|
});
|
|
1656
1922
|
export function readSeatSubagentContent(event) {
|
|
1657
1923
|
try {
|
|
@@ -1919,7 +2185,73 @@ export function isSendMessageAck(v) {
|
|
|
1919
2185
|
}
|
|
1920
2186
|
const checkInterruptAck = seatCheck((v) => isPlainRecord(v) && typeof own(v, "interrupted") === "boolean" ? true : bad("interrupt ack needs a plain object with boolean `interrupted`", "interrupted"));
|
|
1921
2187
|
const checkStopAck = seatCheck((v) => isPlainRecord(v) && typeof own(v, "stopped") === "boolean" ? true : bad("stop ack needs a plain object with boolean `stopped`", "stopped"));
|
|
1922
|
-
const
|
|
2188
|
+
const okAckVerdict = (v) => isPlainRecord(v) && typeof own(v, "ok") === "boolean" ? true : bad("ack needs a plain object with boolean `ok`", "ok");
|
|
2189
|
+
const checkOkAck = seatCheck(okAckVerdict);
|
|
2190
|
+
const TOOL_PERMISSION_SETTLED_WORDS = Object.freeze(["allow", "deny"]);
|
|
2191
|
+
const R_SETTLED_ELSEWHERE = shapeRule("settled elsewhere", {
|
|
2192
|
+
firstDecision: reqF(oneOfRule("decision word", TOOL_PERMISSION_SETTLED_WORDS)),
|
|
2193
|
+
contrary: reqF(R_BOOL),
|
|
2194
|
+
});
|
|
2195
|
+
const TOOL_PERMISSION_UNCONFIRMED_CAUSES = Object.freeze(["transport", "server_error", "local_error", "aborted", "gone_after_retry", "registry_unreadable"]);
|
|
2196
|
+
const R_UNCONFIRMED = shapeRule("unconfirmed", {
|
|
2197
|
+
cause: reqF(oneOfRule("cause word", TOOL_PERMISSION_UNCONFIRMED_CAUSES)),
|
|
2198
|
+
});
|
|
2199
|
+
const R_TOOL_PERMISSION_ACK = shapeRule("permission ack", {
|
|
2200
|
+
ok: reqF(R_BOOL),
|
|
2201
|
+
settledElsewhere: optF(R_SETTLED_ELSEWHERE),
|
|
2202
|
+
unconfirmed: optF(R_UNCONFIRMED),
|
|
2203
|
+
});
|
|
2204
|
+
const TOOL_PERMISSION_ACK_SLOTS = [["settledElsewhere"], ["unconfirmed"]];
|
|
2205
|
+
const R_FALSE = ruleOf("false", (v) => v === false);
|
|
2206
|
+
function toolPermissionAckVerdict(v) {
|
|
2207
|
+
if (!isPlainRecord(v))
|
|
2208
|
+
return okAckVerdict(v);
|
|
2209
|
+
const shape = R_TOOL_PERMISSION_ACK.test(v, "");
|
|
2210
|
+
if (shape !== true)
|
|
2211
|
+
return shape;
|
|
2212
|
+
const ack = v;
|
|
2213
|
+
const groups = keyGroupsVerdict(TOOL_PERMISSION_ACK_SLOTS, ack, "");
|
|
2214
|
+
if (groups !== true)
|
|
2215
|
+
return groups;
|
|
2216
|
+
const ok = own(ack, "ok");
|
|
2217
|
+
if (!isAbsent(own(ack, "unconfirmed")))
|
|
2218
|
+
return R_FALSE.test(ok, "ok");
|
|
2219
|
+
const settled = own(ack, "settledElsewhere");
|
|
2220
|
+
if (isAbsent(settled))
|
|
2221
|
+
return true;
|
|
2222
|
+
return own(settled, "contrary") === true ? R_FALSE.test(ok, "ok") : R_TRUE.test(ok, "ok");
|
|
2223
|
+
}
|
|
2224
|
+
const checkToolPermissionAck = seatShapeCheck({ label: "permission ack", test: (v) => toolPermissionAckVerdict(v) });
|
|
2225
|
+
export function readToolPermissionSettledElsewhere(ack) {
|
|
2226
|
+
try {
|
|
2227
|
+
if (checkToolPermissionAck(ack) !== true)
|
|
2228
|
+
return undefined;
|
|
2229
|
+
const slot = own(ack, "settledElsewhere");
|
|
2230
|
+
if (isAbsent(slot))
|
|
2231
|
+
return undefined;
|
|
2232
|
+
const first = own(slot, "firstDecision");
|
|
2233
|
+
return Object.freeze({ firstDecision: first === "allow" ? "allow" : "deny", contrary: own(slot, "contrary") === true });
|
|
2234
|
+
}
|
|
2235
|
+
catch {
|
|
2236
|
+
return undefined;
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
export function readToolPermissionAckState(ack) {
|
|
2240
|
+
try {
|
|
2241
|
+
if (checkToolPermissionAck(ack) !== true)
|
|
2242
|
+
return undefined;
|
|
2243
|
+
const un = own(ack, "unconfirmed");
|
|
2244
|
+
if (!isAbsent(un)) {
|
|
2245
|
+
const word = own(un, "cause");
|
|
2246
|
+
const cause = TOOL_PERMISSION_UNCONFIRMED_CAUSES.find((w) => w === word);
|
|
2247
|
+
return cause === undefined ? undefined : Object.freeze({ kind: "unconfirmed", cause });
|
|
2248
|
+
}
|
|
2249
|
+
return own(ack, "ok") === true ? Object.freeze({ kind: "applied" }) : Object.freeze({ kind: "not_applied" });
|
|
2250
|
+
}
|
|
2251
|
+
catch {
|
|
2252
|
+
return undefined;
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
1923
2255
|
const checkBooleanAck = (v) => typeof v === "boolean" ? true : bad("expected a bare boolean result");
|
|
1924
2256
|
const checkGetTranscriptResult = seatCheck((v) => {
|
|
1925
2257
|
if (!isPlainRecord(v))
|
|
@@ -2042,7 +2374,7 @@ export const LOCAL_SESSIONS_SPEC = {
|
|
|
2042
2374
|
sendMessage: { kind: "invoke", check: checkSendMessageAck },
|
|
2043
2375
|
interrupt: { kind: "invoke", check: checkInterruptAck },
|
|
2044
2376
|
stop: { kind: "invoke", check: checkStopAck },
|
|
2045
|
-
respondToToolPermission: { kind: "invoke", check:
|
|
2377
|
+
respondToToolPermission: { kind: "invoke", check: checkToolPermissionAck },
|
|
2046
2378
|
cancelQueuedMessage: { kind: "invoke", check: checkBooleanAck },
|
|
2047
2379
|
reorderQueuedMessage: { kind: "invoke", check: checkBooleanAck },
|
|
2048
2380
|
promoteQueuedMessage: { kind: "invoke", check: checkBooleanAck },
|
|
@@ -2078,7 +2410,13 @@ export const LOCAL_SESSIONS_SPEC = {
|
|
|
2078
2410
|
setThinkingLatch: { kind: "invoke", check: checkOkAck },
|
|
2079
2411
|
getComputerUse: { kind: "invoke", check: checkComputerUseState },
|
|
2080
2412
|
setComputerUse: { kind: "invoke", check: checkSetComputerUseResult },
|
|
2413
|
+
getNotificationLevels: { kind: "invoke", check: checkNotificationLevelsState },
|
|
2414
|
+
setNotificationLevel: { kind: "invoke", check: checkSetNotificationLevelResult },
|
|
2415
|
+
getQuickEntryShortcut: { kind: "invoke", check: checkQuickEntryShortcutState },
|
|
2416
|
+
setQuickEntryShortcut: { kind: "invoke", check: checkSetQuickEntryShortcutResult },
|
|
2081
2417
|
claimSeatActions: { kind: "invoke", check: checkOkAck },
|
|
2418
|
+
readSessionMods: { kind: "invoke", check: checkSessionModsResult },
|
|
2419
|
+
readSessionHooksRoster: { kind: "invoke", check: checkSessionHooksRosterResult },
|
|
2082
2420
|
onEvent: { kind: "event", check: checkLocalSessionEvent },
|
|
2083
2421
|
onToolPermissionRequest: { kind: "event", check: checkToolPermissionRequest },
|
|
2084
2422
|
onSeatAction: { kind: "event", check: checkSeatAction },
|
|
@@ -2132,7 +2470,13 @@ export const SEAT_METHOD_NAMES = [
|
|
|
2132
2470
|
"setThinkingLatch",
|
|
2133
2471
|
"getComputerUse",
|
|
2134
2472
|
"setComputerUse",
|
|
2473
|
+
"getNotificationLevels",
|
|
2474
|
+
"setNotificationLevel",
|
|
2475
|
+
"getQuickEntryShortcut",
|
|
2476
|
+
"setQuickEntryShortcut",
|
|
2135
2477
|
"claimSeatActions",
|
|
2478
|
+
"readSessionMods",
|
|
2479
|
+
"readSessionHooksRoster",
|
|
2136
2480
|
"onEvent",
|
|
2137
2481
|
"onToolPermissionRequest",
|
|
2138
2482
|
"onSeatAction",
|
|
@@ -2179,6 +2523,12 @@ export const TOOL_PERMISSION_REQUEST_KEYS = [
|
|
|
2179
2523
|
"askClass",
|
|
2180
2524
|
"classes",
|
|
2181
2525
|
"sessionRow",
|
|
2526
|
+
"probeReason",
|
|
2527
|
+
"probeCause",
|
|
2528
|
+
"feedbackCapable",
|
|
2529
|
+
"requestedBy",
|
|
2530
|
+
"frameReading",
|
|
2531
|
+
"inputSource",
|
|
2182
2532
|
];
|
|
2183
2533
|
export const LOCAL_SESSION_RECORD_KEYS = [
|
|
2184
2534
|
"sessionId",
|
|
@@ -2236,6 +2586,7 @@ export const TOOL_PERMISSION_DECISION_KEYS = [
|
|
|
2236
2586
|
"answer",
|
|
2237
2587
|
"updatedInput",
|
|
2238
2588
|
"remember",
|
|
2589
|
+
"feedback",
|
|
2239
2590
|
];
|
|
2240
2591
|
export const START_SESSION_OPTION_KEYS = ["model", "title", "cwd", "excludeTools", "engine"];
|
|
2241
2592
|
export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
@@ -2286,10 +2637,34 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
|
2286
2637
|
key: "sessionRow",
|
|
2287
2638
|
why: "放宽方向的展示位(CC-699),判官在过境口 toolPermissionRequestAskBits(card, requestId):卡上「本会话放行」判官 standingRowsOf 的会话行同一前提 ∧ 本请求 requestId 的域带得走(live: / durable:),严格 true 才上座、永不铸 false;座位门不设第二判官,理由同 mandated(为一个展示位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。消费端 `=== true` 才渲「本会话放行」,其余(缺席 / 坏形)一律不渲 —— 缺席是闭合失败,不是「没说就照渲」。不经过境口自铸座位请求的宿主拿不到这一位,座位卡就不给那一档。",
|
|
2288
2639
|
},
|
|
2640
|
+
{
|
|
2641
|
+
key: "feedbackCapable",
|
|
2642
|
+
why: "放宽方向的展示位(CC-585),判官在过境口 toolPermissionRequestAskBits(card, requestId):卡判官 answerCarriage(card) 答 model(卡带耐久待决行腿的正向事实 parkRow)∧ 本请求 requestId 的域恰是 durable:(只有 /decide 收放行反馈位),严格 true 才上座、永不铸 false;座位门不设第二判官,理由同 sessionRow(为一个展示位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。消费端 `=== true` 才渲「Yes + 告诉 agent 下一步」那一格输入,其余(缺席 / 坏形)一律不渲 —— 缺席是闭合失败。不经过境口自铸座位请求的宿主拿不到这一位,座位卡就不给那一格。",
|
|
2643
|
+
},
|
|
2289
2644
|
{
|
|
2290
2645
|
key: "ruleOffersAbsence",
|
|
2291
2646
|
why: "喂强制判据口 approvalIsMandated 的位(CC-203;寄存行那条腿的强制只以缺席词 mandated 表达),按开集读(非空串原文字节、词表不校);权威窄读在卡口与过境口,座位门不设第二判官,理由同 mandated。坏形读成缺席 ⇒ 这一路不判强制(放宽方向:寄存行上的强制就丢了;另两路 mandated / mandate 照判);表外串只是不等于 mandated。不经过境口自铸座位请求的宿主要自己按同一把窄读。",
|
|
2292
2647
|
},
|
|
2648
|
+
{
|
|
2649
|
+
key: "probeReason",
|
|
2650
|
+
why: "展示位(CC-1316),权威窄读在过境口 toolPermissionRequestAskBits,与「为什么问」那一句的读口 askProbeReasonDetail 同一个读点(自有数据属性、取值器不执行;串且去两端空白后非空才在场,原文字节);座位门不设第二判官,理由同 mandated(为一个展示位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。坏形读成缺席 ⇒ 卡上不显示这一句,不改决断;缺席不是「没有原因」。不经过境口自铸座位请求的宿主要自己按同一把窄读。",
|
|
2651
|
+
},
|
|
2652
|
+
{
|
|
2653
|
+
key: "probeCause",
|
|
2654
|
+
why: "展示位(CC-1316),与 probeReason 同一对、同一个读点;载体层判(自有数据属性、非 null 非数组对象)才在场,同一引用原样搬运,内部成员不校(成员的窄读归 askProbeReasonDetail / probeCauseRowsOf);座位门不设第二判官,理由同 probeReason。坏形读成缺席 ⇒ 不显示因由行,不改决断。两位按键隔离:一位读不出不连坐另一位。",
|
|
2655
|
+
},
|
|
2656
|
+
{
|
|
2657
|
+
key: "requestedBy",
|
|
2658
|
+
why: "展示位(CC-1341),权威窄读在过境口 toolPermissionRequestAskBits,读点是卡口的唯一载体级读口 approvalRequestedByOf(载体顶层的自有数据属性、取值器不执行;kind 恰 extension 且 name 非空串才在场,出冻结的新铸副本);原始耐久待决行不读(上游不在行上铸这一位);座位门不设第二判官,理由同 mandated(为一个展示位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。坏形读成缺席 ⇒ 卡上不显示发起者行,不改决断;缺席不是「模型发起」。不经过境口自铸座位请求的宿主要自己按同一把窄读。",
|
|
2659
|
+
},
|
|
2660
|
+
{
|
|
2661
|
+
key: "frameReading",
|
|
2662
|
+
why: "展示位(CC-1345),权威窄读在过境口 toolPermissionRequestAskBits,读点是包内唯一读口 cardPayloadReadingOf(卡上 cardPayloadUnreadable 严格 true ∧ cardPayloadUnreadableWhy 是判因闭集三词之一才在场;卡面通用卡第一行按因选句同读它);座位门不设第二判官,理由同 mandated(为一个展示位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。表外词 / 游离判因词 / 判因未知读成缺席 ⇒ 卡上回落不分因的原句,不改决断;缺席不是「帧读得出」。不经过境口自铸座位请求的宿主要自己按同一把窄读。",
|
|
2663
|
+
},
|
|
2664
|
+
{
|
|
2665
|
+
key: "inputSource",
|
|
2666
|
+
why: "展示位(CC-1366),权威窄读在过境口 toolPermissionRequestAskBits,读点是包内唯一窄读 approvalInputSourceOf(载体顶层的自有数据属性、取值器不执行;闭集 record / stream 两词精确字节才在场);来源位本身只有一个铸点(卡入参读法的读数 → 位),过境口只抄卡上已铸的位、不拿 input 重判来源,原始帧 / 原始耐久待决行直交恒缺席;座位门不设第二判官,理由同 mandated(为一个展示位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。表外词 / 近义词 / 非串读成缺席 ⇒ 壳按来源不明处置,不改决断;缺席不是 record。不经过境口自铸座位请求的宿主要自己按同一把窄读。",
|
|
2667
|
+
},
|
|
2293
2668
|
],
|
|
2294
2669
|
},
|
|
2295
2670
|
LocalSessionEvent: {
|
|
@@ -2421,6 +2796,11 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
|
2421
2796
|
validated: ["ok"],
|
|
2422
2797
|
unchecked: [],
|
|
2423
2798
|
},
|
|
2799
|
+
ToolPermissionAck: {
|
|
2800
|
+
check: checkToolPermissionAck,
|
|
2801
|
+
validated: ["ok", "settledElsewhere", "unconfirmed"],
|
|
2802
|
+
unchecked: [],
|
|
2803
|
+
},
|
|
2424
2804
|
GetTranscriptResult: {
|
|
2425
2805
|
check: checkGetTranscriptResult,
|
|
2426
2806
|
validated: ["sessionId", "messages"],
|
|
@@ -2448,7 +2828,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
|
2448
2828
|
},
|
|
2449
2829
|
SeatCapabilitiesState: {
|
|
2450
2830
|
check: checkSeatCapabilitiesState,
|
|
2451
|
-
validated: ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions"],
|
|
2831
|
+
validated: ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions", "notificationLevels", "modsView", "quickEntryShortcut", "hooksRoster"],
|
|
2452
2832
|
unchecked: [],
|
|
2453
2833
|
},
|
|
2454
2834
|
RecentFoldersResult: {
|
|
@@ -2514,9 +2894,15 @@ export const SEAT_VALIDATOR_COVERAGE_EXEMPT = [
|
|
|
2514
2894
|
["ComputerUseState", checkComputerUseState],
|
|
2515
2895
|
["SetComputerUseResult", checkSetComputerUseResult],
|
|
2516
2896
|
["SetComputerUseRequest", checkSetComputerUseRequest],
|
|
2897
|
+
["NotificationLevelsState", checkNotificationLevelsState],
|
|
2898
|
+
["SetNotificationLevelResult", checkSetNotificationLevelResult],
|
|
2517
2899
|
["SeatAction", checkSeatAction],
|
|
2518
2900
|
["EngineSwapAnswerOutcome", checkEngineSwapAnswerOutcome],
|
|
2519
2901
|
["SelfUpgradeOutcome", checkSelfUpgradeOutcome],
|
|
2902
|
+
["SessionModsResult", checkSessionModsResult],
|
|
2903
|
+
["QuickEntryShortcutState", checkQuickEntryShortcutState],
|
|
2904
|
+
["SetQuickEntryShortcutResult", checkSetQuickEntryShortcutResult],
|
|
2905
|
+
["SessionHooksRosterResult", checkSessionHooksRosterResult],
|
|
2520
2906
|
].map(([label, check]) => ({
|
|
2521
2907
|
label,
|
|
2522
2908
|
check,
|
|
@@ -2581,5 +2967,11 @@ const _seatContractPins = [
|
|
|
2581
2967
|
true, true,
|
|
2582
2968
|
true, true, true, true, true, true, true,
|
|
2583
2969
|
true, true, true, true, true, true, true, true,
|
|
2970
|
+
true, true, true, true, true,
|
|
2971
|
+
true, true, true,
|
|
2972
|
+
true, true, true, true,
|
|
2973
|
+
true, true, true, true,
|
|
2974
|
+
true, true, true, true, true, true,
|
|
2975
|
+
true, true, true, true, true,
|
|
2584
2976
|
];
|
|
2585
2977
|
void _seatContractPins;
|
|
@@ -6,6 +6,7 @@ import { isLoopbackWireUrl } from './engineWireSdk.js';
|
|
|
6
6
|
import { hostEnv } from './hostEnv.js';
|
|
7
7
|
import { approvalDecisionHolds } from './hitl/approvalHolds.js';
|
|
8
8
|
import { readRunTerminal } from './runTerminal.js';
|
|
9
|
+
import { isReplayedTerminal } from './replayBody.js';
|
|
9
10
|
import { appendOwnElement, ownDataField, putOwnKey, readOwnDataFiniteNumber, readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
|
|
10
11
|
import { msg, renderMessage } from './i18n/translate.js';
|
|
11
12
|
export function projectSessionBackgroundable(caps) {
|
|
@@ -418,7 +419,7 @@ function observeFrame(rec, ev) {
|
|
|
418
419
|
}
|
|
419
420
|
else {
|
|
420
421
|
rec.phase = 'ended-unstarted';
|
|
421
|
-
rec.replay = type === 'done' &&
|
|
422
|
+
rec.replay = type === 'done' && isReplayedTerminal(ev);
|
|
422
423
|
}
|
|
423
424
|
return;
|
|
424
425
|
}
|
|
@@ -4,6 +4,7 @@ import { REATTACH_WINDOW_MS, reattachBackoffMs } from './reattachWindow.js';
|
|
|
4
4
|
import { terminalEventFromRunRow } from './headlessReconnectWire.js';
|
|
5
5
|
import { RUN_CANCELLED_CODE } from './runCancelContext.js';
|
|
6
6
|
import { readRunTerminal } from './runTerminal.js';
|
|
7
|
+
import { isReplayedTerminal } from './replayBody.js';
|
|
7
8
|
import { readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
|
|
8
9
|
import { backgroundHandoffSentence, judgeHandoff, ownSlotOf, wireStateOf, } from './sessionBackground.js';
|
|
9
10
|
export const BACKGROUND_HANDOFF_ABORT_REASON = 'background';
|
|
@@ -34,7 +35,7 @@ function executionSettlementOf(ev) {
|
|
|
34
35
|
return { runEnded: true, kind: 'cancelled', status: 'failed' };
|
|
35
36
|
return { runEnded: true, kind: 'failed', status: 'failed', ...(code !== undefined ? { errorCode: code } : {}) };
|
|
36
37
|
}
|
|
37
|
-
if (type !== 'done' ||
|
|
38
|
+
if (type !== 'done' || isReplayedTerminal(ev))
|
|
38
39
|
return undefined;
|
|
39
40
|
const read = readRunTerminal(slot(ev, 'result'));
|
|
40
41
|
if (read === null)
|