@sema-agent/client-core 0.107.0 → 0.109.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.
Files changed (165) hide show
  1. package/CHANGELOG.md +239 -0
  2. package/README.md +54 -36
  3. package/dist/adapt/arms.js +23 -8
  4. package/dist/adapt/textStream.d.ts +2 -0
  5. package/dist/adapt/textStream.js +37 -16
  6. package/dist/adapter/activeRunSelfHeal.d.ts +2 -0
  7. package/dist/adapter/activeRunSelfHeal.js +21 -4
  8. package/dist/adapter/downstream/eventToSdkMessage.js +2 -1
  9. package/dist/agentSession/engineAgentRegistryRead.js +2 -0
  10. package/dist/bashExitReading.d.ts +12 -0
  11. package/dist/bashExitReading.js +44 -0
  12. package/dist/checkpointRowVerdict.d.ts +6 -1
  13. package/dist/checkpointRowVerdict.js +30 -2
  14. package/dist/cloudConfigWireCaps.d.ts +10 -0
  15. package/dist/cloudConfigWireCaps.js +33 -0
  16. package/dist/compensations.js +1 -1
  17. package/dist/coreValuePorts.d.ts +17 -1
  18. package/dist/coreValuePorts.js +5 -0
  19. package/dist/decideReceipt.js +2 -1
  20. package/dist/engineAgentAbsence.d.ts +2 -0
  21. package/dist/engineAgentAbsence.js +28 -0
  22. package/dist/engineErrorCodes.d.ts +9 -0
  23. package/dist/engineErrorCodes.js +9 -0
  24. package/dist/engineHealthFacts.d.ts +17 -0
  25. package/dist/engineHealthFacts.js +42 -3
  26. package/dist/engineNoticeCodes.d.ts +147 -1
  27. package/dist/engineNoticeCodes.js +694 -57
  28. package/dist/engineTargetSeat.js +1 -0
  29. package/dist/errorSupplementRoles.js +6 -1
  30. package/dist/eventLeg.js +1 -1
  31. package/dist/executionLaneWords.js +2 -1
  32. package/dist/fleetTaskDesc.js +3 -3
  33. package/dist/gateOutcome.d.ts +10 -1
  34. package/dist/gateOutcome.js +48 -1
  35. package/dist/generated/engineFactTables.d.ts +2 -0
  36. package/dist/generated/engineFactTables.js +11 -0
  37. package/dist/generated/engineNoticeTables.js +6 -0
  38. package/dist/generated/settingsSchemaFns.d.ts +4 -2
  39. package/dist/generated/settingsSchemaFns.js +9 -3
  40. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
  41. package/dist/generated/settingsSchemaMcpRequestEntry.js +9 -18
  42. package/dist/generated/settingsSchemaReservedMemberName.d.ts +1 -0
  43. package/dist/generated/settingsSchemaReservedMemberName.js +7 -0
  44. package/dist/generated/settingsSchemaTables.d.ts +2 -0
  45. package/dist/generated/settingsSchemaTables.js +10 -0
  46. package/dist/generated/settingsSchemaWireName.d.ts +1 -0
  47. package/dist/generated/settingsSchemaWireName.js +8 -0
  48. package/dist/headlessReconnectWire.js +12 -7
  49. package/dist/hitl/approvalAskers.d.ts +13 -0
  50. package/dist/hitl/approvalAskers.js +79 -0
  51. package/dist/hitl/approvalCardReasons.js +22 -4
  52. package/dist/hitl/approvalRequestFrameReading.d.ts +14 -0
  53. package/dist/hitl/approvalRequestFrameReading.js +79 -0
  54. package/dist/hitl/approvalResolution.d.ts +3 -0
  55. package/dist/hitl/approvalResolution.js +22 -4
  56. package/dist/hitl/approvalsFeed.js +4 -13
  57. package/dist/hitl/askParkRowRouting.js +10 -3
  58. package/dist/hitl/automaticAnswerVerdict.d.ts +5 -2
  59. package/dist/hitl/automaticAnswerVerdict.js +16 -2
  60. package/dist/hitl/decisionConflict.d.ts +2 -1
  61. package/dist/hitl/decisionConflict.js +4 -1
  62. package/dist/hitl/decisionRefusal.d.ts +1 -0
  63. package/dist/hitl/decisionRefusal.js +5 -2
  64. package/dist/hitl/decisionSend.js +2 -6
  65. package/dist/hitl/frameRouter.d.ts +3 -2
  66. package/dist/hitl/frameRouter.js +37 -7
  67. package/dist/hitl/gateLedger.d.ts +2 -0
  68. package/dist/hitl/gateLedger.js +3 -1
  69. package/dist/hitl/hitlBridge.d.ts +4 -0
  70. package/dist/hitl/hitlBridge.js +11 -8
  71. package/dist/hitl/livePendingAsk.js +17 -16
  72. package/dist/hitl/localAllowRule.js +2 -1
  73. package/dist/hitl/noAllowCause.d.ts +1 -1
  74. package/dist/hitl/noAllowCause.js +4 -2
  75. package/dist/hitl/parkExpiryJudgements.js +26 -1
  76. package/dist/hitl/parkOwnership.d.ts +2 -0
  77. package/dist/hitl/parkOwnership.js +48 -8
  78. package/dist/hitl/parkResolver.js +39 -30
  79. package/dist/hitl/parkRowBirthWait.d.ts +2 -0
  80. package/dist/hitl/parkRowBirthWait.js +8 -1
  81. package/dist/hitl/parkedUnresumable.d.ts +13 -0
  82. package/dist/hitl/parkedUnresumable.js +80 -0
  83. package/dist/hitl/permissionRuleScope.d.ts +4 -0
  84. package/dist/hitl/permissionRuleScope.js +31 -0
  85. package/dist/hitl/persistedRulesWire.d.ts +7 -1
  86. package/dist/hitl/persistedRulesWire.js +25 -8
  87. package/dist/hitl/planReviewWire.js +12 -16
  88. package/dist/hitl/policyDenyCause.d.ts +3 -0
  89. package/dist/hitl/policyDenyCause.js +16 -0
  90. package/dist/hitl/sessionAllowRoute.js +5 -4
  91. package/dist/hitl/sessionPolicyDeliverable.js +1 -1
  92. package/dist/hitl/standingRows.d.ts +1 -5
  93. package/dist/hitl/standingRows.js +15 -14
  94. package/dist/hitl/toolApprovalWire.d.ts +16 -4
  95. package/dist/hitl/toolApprovalWire.js +57 -17
  96. package/dist/hooksReaderGenerations.d.ts +1 -0
  97. package/dist/hooksReaderGenerations.js +12 -0
  98. package/dist/hooksWireCaps.js +12 -7
  99. package/dist/hostSettingsSource.js +2 -0
  100. package/dist/i18n/messages.en.d.ts +206 -1
  101. package/dist/i18n/messages.en.js +209 -4
  102. package/dist/i18n/messages.zh.js +214 -4
  103. package/dist/index.d.ts +35 -8
  104. package/dist/index.js +20 -5
  105. package/dist/liveModelCatalog.d.ts +4 -2
  106. package/dist/liveModelCatalog.js +164 -26
  107. package/dist/localEngineJudge.d.ts +75 -0
  108. package/dist/localEngineJudge.js +242 -0
  109. package/dist/localEngineOccupancy.d.ts +88 -0
  110. package/dist/localEngineOccupancy.js +269 -0
  111. package/dist/localEngineSeatReading.d.ts +29 -0
  112. package/dist/localEngineSeatReading.js +294 -0
  113. package/dist/localEngineSpawn.d.ts +113 -0
  114. package/dist/localEngineSpawn.js +486 -0
  115. package/dist/localEngineStep.d.ts +286 -0
  116. package/dist/localEngineStep.js +1086 -0
  117. package/dist/localEngineStopLadder.d.ts +29 -0
  118. package/dist/localEngineStopLadder.js +139 -0
  119. package/dist/localEngineSwapCard.d.ts +43 -0
  120. package/dist/localEngineSwapCard.js +205 -0
  121. package/dist/localEngineTiming.d.ts +8 -0
  122. package/dist/localEngineTiming.js +8 -0
  123. package/dist/mcpReconnect.js +12 -5
  124. package/dist/mcpWireCaps.js +2 -2
  125. package/dist/memoryEntriesWire.d.ts +1 -1
  126. package/dist/memoryEntriesWire.js +5 -0
  127. package/dist/model/catalogDefault.d.ts +25 -0
  128. package/dist/model/catalogDefault.js +44 -0
  129. package/dist/noticePresentation.d.ts +2 -0
  130. package/dist/noticePresentation.js +79 -1
  131. package/dist/ownKey.d.ts +10 -0
  132. package/dist/ownKey.js +15 -1
  133. package/dist/permissionWireCaps.d.ts +1 -0
  134. package/dist/permissionWireCaps.js +11 -0
  135. package/dist/pluginHooksWire.d.ts +5 -3
  136. package/dist/pluginHooksWire.js +116 -7
  137. package/dist/queuedDelivery.d.ts +1 -0
  138. package/dist/queuedDelivery.js +12 -0
  139. package/dist/resultFrameKeys.js +4 -2
  140. package/dist/resumeRefusalCopy.js +15 -8
  141. package/dist/ruleReadings.js +1 -1
  142. package/dist/runPermissionModeSwitch.d.ts +2 -1
  143. package/dist/runPermissionModeSwitch.js +16 -6
  144. package/dist/seam.d.ts +13 -2
  145. package/dist/seam.js +8 -1
  146. package/dist/seatContract.d.ts +103 -12
  147. package/dist/seatContract.js +344 -14
  148. package/dist/sessionBackground.js +2 -0
  149. package/dist/sessionEngine.d.ts +2 -1
  150. package/dist/sessionEngine.js +5 -0
  151. package/dist/settingsHooksSalvage.d.ts +5 -0
  152. package/dist/settingsHooksSalvage.js +54 -0
  153. package/dist/subagentContentStore.d.ts +12 -0
  154. package/dist/subagentContentStore.js +73 -12
  155. package/dist/supportFloor.js +2 -0
  156. package/dist/taskNotificationAdmission.d.ts +19 -0
  157. package/dist/taskNotificationAdmission.js +84 -0
  158. package/dist/toolResult.js +20 -6
  159. package/dist/webSearchWireCaps.js +9 -4
  160. package/dist/wireFailureShape.d.ts +20 -0
  161. package/dist/wireFailureShape.js +37 -6
  162. package/dist/wireRefusalCopy.d.ts +23 -2
  163. package/dist/wireRefusalCopy.js +93 -4
  164. package/docs/INTEGRATION-CLIENTS.md +1959 -15
  165. package/package.json +4 -4
@@ -4,10 +4,13 @@ import { REWIND_MODES } from "./rewindWireCaps.js";
4
4
  import { SETTINGS_MODEL_API_WORDS } from "./generated/settingsSchemaTables.js";
5
5
  import { PROBE_VERDICTS } from "./modelCapabilityProbe.js";
6
6
  import { guardedRead, ownDataField, ownDataRefusalKeyOf, ownSendableField, readOwnDataValue } from "./ownKey.js";
7
+ import { isPlainRecord as isJsonPlainRecord } from "./jsonFaithful.js";
8
+ import { displayUntrustedMarks, quoteUntrustedForSentence } from "./displayUntrusted.js";
7
9
  import { MCP_LIVENESS_STATES } from "./mcpLiveness.js";
8
10
  import { THINKING_LATCH_EVENTS, THINKING_LATCH_ROW_WORDS } from "./thinkingLatchWords.js";
9
11
  import { EXECUTION_PLACEMENT_ROLES } from "./executionPlacementWords.js";
10
12
  import { isSessionEngineView } from "./sessionEngine.js";
13
+ import { LOCAL_ENGINE_SWAP_CAUSES } from "./localEngineSwapCard.js";
11
14
  const bad = (reason, field) => field === undefined ? { reason } : { reason, field };
12
15
  const nested = (prefix, verdict) => {
13
16
  const path = verdict.field === undefined
@@ -18,12 +21,7 @@ const nested = (prefix, verdict) => {
18
21
  const reason = verdict.reason.startsWith(`${prefix}:`) ? verdict.reason : `${prefix}: ${verdict.reason}`;
19
22
  return bad(reason, path);
20
23
  };
21
- const isPlainRecord = (v) => {
22
- if (typeof v !== "object" || v === null || Array.isArray(v))
23
- return false;
24
- const proto = Object.getPrototypeOf(v);
25
- return proto === null || (typeof proto === "object" && Object.getPrototypeOf(proto) === null);
26
- };
24
+ const isPlainRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v) && isJsonPlainRecord(v);
27
25
  const isAbsent = (v) => typeof v === "undefined";
28
26
  const optionalString = (v) => isAbsent(v) || typeof v === "string";
29
27
  const isFolderPath = (v) => typeof v === "string" && v.length > 0;
@@ -185,6 +183,23 @@ const R_NUM = ruleOf("finite number", (v) => typeof v === "number" && Number.isF
185
183
  const R_NUM0 = ruleOf("finite non-negative number", (v) => typeof v === "number" && Number.isFinite(v) && v >= 0);
186
184
  const R_INT0 = ruleOf("non-negative integer", (v) => typeof v === "number" && Number.isSafeInteger(v) && v >= 0);
187
185
  const R_INT1 = ruleOf("positive integer", (v) => typeof v === "number" && Number.isSafeInteger(v) && v > 0);
186
+ const SESSION_ENGINE_KIND_WORDS = Object.freeze(["local", "cloud"]);
187
+ const R_ENGINE_LANE = oneOfRule("engine lane", SESSION_ENGINE_KIND_WORDS);
188
+ const R_ROW_BAR = armsRule("row verdict", "kind", {
189
+ lacking: { code: reqF(R_NONEMPTY), reason: optF(R_NONEMPTY), requires: optF(arrayRule(R_NONEMPTY)), sentence: reqF(R_NONEMPTY) },
190
+ damaged: { code: reqF(R_NONEMPTY), reason: optF(R_NONEMPTY), requires: optF(arrayRule(R_NONEMPTY)), sentence: reqF(R_NONEMPTY) },
191
+ unknown: { word: reqF(R_NONEMPTY), sentence: optF(R_NONEMPTY) },
192
+ unreadable: {},
193
+ });
194
+ const PARKED_ROW_DEADLINE_WORDS = Object.freeze(["armed", "none"]);
195
+ const R_PARKED_ROW = shapeRule("parked row", {
196
+ rowVerdict: reqF(R_ROW_BAR),
197
+ rowKey: optF(R_NONEMPTY),
198
+ taskId: optF(R_NONEMPTY),
199
+ toolName: optF(R_NONEMPTY),
200
+ rowDeadline: optF(oneOfRule("deadline word", PARKED_ROW_DEADLINE_WORDS)),
201
+ });
202
+ const R_PARKED_UNRESUMABLE = arrayRule(R_PARKED_ROW, true);
188
203
  const keyWords = (k) => k
189
204
  .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
190
205
  .toLowerCase()
@@ -294,6 +309,7 @@ const CHROME_ARM_SEAT_ROUTE = {
294
309
  compaction_started: "seat",
295
310
  compaction_outcome: "seat",
296
311
  engine_notice: "seat",
312
+ subagent_alias: "seat",
297
313
  workflow_notification_enqueue: "host",
298
314
  plan_review_park: "host",
299
315
  approval_request: "host",
@@ -333,6 +349,7 @@ export const HITL_RESOLUTION_OUTCOMES = [
333
349
  "accept",
334
350
  "decline",
335
351
  "cancel",
352
+ "engine_unavailable",
336
353
  ];
337
354
  export const SEAT_STREAM_DELTA_TYPE_OF_CHANNEL = Object.freeze({ text: "text_delta", thinking: "thinking_delta" });
338
355
  export function seatStreamDeltaMessage(event, ids) {
@@ -381,7 +398,7 @@ export function readSeatStreamDelta(message) {
381
398
  return Object.freeze({ kind: "malformed" });
382
399
  }
383
400
  }
384
- export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly"]);
401
+ export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions"]);
385
402
  const notReported = () => Object.freeze({ kind: "not_reported" });
386
403
  const malformedReading = () => Object.freeze({ kind: "malformed" });
387
404
  const reported = (available) => Object.freeze({ kind: "reported", available });
@@ -460,6 +477,7 @@ const SEAT_CAPABILITY_PHRASES = Object.freeze({
460
477
  thinkingLatch: Object.freeze({ action: "Switching thinking", ability: "switch thinking", support: "thinking-switch support" }),
461
478
  computerUseSwitch: Object.freeze({ action: "Computer use", ability: "be switched", support: "switch support" }),
462
479
  engineModeDefaultOnly: Object.freeze({ action: "Default-only engine switching", ability: "keep existing sessions on their engine", support: "default-only engine switching" }),
480
+ seatActions: Object.freeze({ action: "App menu actions", ability: "send actions to this window", support: "app action support" }),
463
481
  });
464
482
  export function seatCapabilityUnavailableDetail(name, reading) {
465
483
  const phrase = Object.hasOwn(SEAT_CAPABILITY_PHRASES, name)
@@ -668,6 +686,7 @@ export const ENGINE_TARGET_REFUSALS = Object.freeze([
668
686
  "not_configured",
669
687
  "not_signed_in",
670
688
  "probe_failed",
689
+ "cloud_unreachable",
671
690
  "org_policy",
672
691
  "url_refused",
673
692
  "login_failed",
@@ -685,6 +704,18 @@ export const CLOUD_LOGIN_FAILURES = Object.freeze([
685
704
  "no_tokens",
686
705
  "other",
687
706
  ]);
707
+ export const LOCAL_ENGINE_DOWN_REASONS = Object.freeze([
708
+ "lock-unavailable",
709
+ "spawn-failed",
710
+ "spawn-refused",
711
+ "stop-failed",
712
+ "crash-loop",
713
+ "high-water-unreadable",
714
+ "principal-unknown",
715
+ ]);
716
+ export const LOCAL_ENGINE_WAITING_REASONS = Object.freeze(["starting", "dormant", "draining", "unanswered", "peer"]);
717
+ export const ENGINE_SWAP_ANSWER_OUTCOMES = Object.freeze(["started", "stale-card", "nothing-pending"]);
718
+ export const SELF_UPGRADE_OUTCOMES = Object.freeze(["started", "unavailable"]);
688
719
  const R_ISO = R_NONEMPTY;
689
720
  const R_LOGIN_FAILURE = oneOfRule("login failure", CLOUD_LOGIN_FAILURES);
690
721
  const R_DISPLAY_URL = ruleOf("display url", (v) => {
@@ -761,12 +792,84 @@ const ENGINE_TARGET_CLOUD = shapeRule("cloud", {
761
792
  })),
762
793
  orgEngine: optF(shapeRule("org engine", { url: reqF(R_DISPLAY_URL), required: reqF(R_BOOL) })),
763
794
  });
764
- const ENGINE_TARGET_LOCAL = shapeRule("local", {
795
+ const R_FINITE_TIME = ruleOf("non-negative integer", (v) => typeof v === "number" && Number.isSafeInteger(v) && v >= 0);
796
+ const SWAP_CARD_IDENTITY = shapeRule("engine identity", {
797
+ pid: optF(R_INT1),
798
+ instanceId: optF(R_NONEMPTY),
799
+ startedAt: optF(R_FINITE_TIME),
800
+ });
801
+ const SWAP_CARD_REF_SPEC = {
802
+ pid: reqF(R_INT1),
803
+ port: reqF(ruleOf("port", (v) => typeof v === "number" && Number.isInteger(v) && v >= 1 && v <= 65535)),
804
+ identity: reqF(SWAP_CARD_IDENTITY),
805
+ version: optF(R_NONEMPTY),
806
+ };
807
+ const SWAP_CARD_PROCESS_SPEC = { pid: reqF(R_INT1), startedAt: optF(R_INT1) };
808
+ const R_SWAP_CARD_TARGET = {
809
+ label: "card target",
810
+ test: (v, path) => {
811
+ if (!isPlainRecord(v))
812
+ return bad("not object", path === "" ? undefined : path);
813
+ return shapeVerdict(isAbsent(own(v, "identity")) ? SWAP_CARD_PROCESS_SPEC : SWAP_CARD_REF_SPEC, v, path);
814
+ },
815
+ };
816
+ const SWAP_CARD = shapeRule("swap card", {
817
+ cause: reqF(oneOfRule("swap cause", LOCAL_ENGINE_SWAP_CAUSES)),
818
+ target: reqF(R_SWAP_CARD_TARGET),
819
+ running: optF(R_NONEMPTY),
820
+ own: optF(R_NONEMPTY),
821
+ others: reqF(ruleOf("others count|null", (v) => {
822
+ if (v === null)
823
+ return true;
824
+ if (!isPlainRecord(v))
825
+ return false;
826
+ return shapeVerdict({ total: reqF(R_INT0), midTurn: reqF(R_INT0) }, v, "") === true;
827
+ })),
828
+ inflight: reqF(ruleOf("count|null", (v) => v === null || (typeof v === "number" && Number.isSafeInteger(v) && v >= 0))),
829
+ bgLive: reqF(ruleOf("count|null", (v) => v === null || (typeof v === "number" && Number.isSafeInteger(v) && v >= 0))),
830
+ unknown: reqF(arrayRule(oneOfRule("card unknown", ["others", "inflight", "bg", "self"]))),
831
+ forcedWithinMs: reqF(R_INT0),
832
+ fingerprint: reqF(R_NONEMPTY),
833
+ });
834
+ const LOCAL_ENGINE_SEAT_READING = armsRule("engine lifecycle", "phase", {
835
+ waiting: { why: reqF(oneOfRule("waiting reason", LOCAL_ENGINE_WAITING_REASONS)), unverifiable: optF(R_TRUE) },
836
+ attached: {},
837
+ pending: { serving: reqF(R_BOOL), card: optF(SWAP_CARD) },
838
+ swapping: { mode: reqF(oneOfRule("swap mode", ["idle", "forced"])) },
839
+ down: { reason: reqF(oneOfRule("down reason", LOCAL_ENGINE_DOWN_REASONS)) },
840
+ behind: { running: reqF(R_NONEMPTY), own: reqF(R_NONEMPTY), upgrade: reqF(oneOfRule("upgrade entry", ["available", "unavailable"])) },
841
+ });
842
+ const R_LIFECYCLE_DERIVED = ruleOf("lifecycle-derived", () => false);
843
+ const R_LIFECYCLE_WITHDRAWN = ruleOf("lifecycle-withdrawn", () => false);
844
+ const R_UNANSWERED_ONLY = ruleOf("unanswered-only", () => false);
845
+ const ENGINE_TARGET_LOCAL_SPEC = {
765
846
  lastBootError: optF(R_STR),
766
847
  mcp: optF(SEAT_LOCAL_MCP_READING),
767
- });
848
+ lifecycle: optF(LOCAL_ENGINE_SEAT_READING),
849
+ };
850
+ const ENGINE_TARGET_LOCAL = {
851
+ label: "local",
852
+ test: (v, path) => {
853
+ const verdict = shapeVerdict(ENGINE_TARGET_LOCAL_SPEC, v, path);
854
+ if (verdict !== true)
855
+ return verdict;
856
+ const rec = v;
857
+ const lifecycle = own(rec, "lifecycle");
858
+ if (isAbsent(lifecycle))
859
+ return true;
860
+ const phase = own(lifecycle, "phase");
861
+ const bootError = !isAbsent(own(rec, "lastBootError"));
862
+ if (bootError !== (phase === "down"))
863
+ return R_LIFECYCLE_DERIVED.test(undefined, pathAt(path, "lastBootError"));
864
+ if (phase !== "attached" && phase !== "pending" && !isAbsent(own(rec, "mcp")))
865
+ return R_LIFECYCLE_WITHDRAWN.test(undefined, pathAt(path, "mcp"));
866
+ if (phase === "waiting" && own(lifecycle, "why") !== "unanswered" && !isAbsent(own(lifecycle, "unverifiable")))
867
+ return R_UNANSWERED_ONLY.test(undefined, pathAt(pathAt(path, "lifecycle"), "unverifiable"));
868
+ return true;
869
+ },
870
+ };
768
871
  const ENGINE_TARGET_STATE = shapeRule("engine target", {
769
- mode: reqF(oneOfRule("engine mode", ["local", "cloud"])),
872
+ mode: reqF(R_ENGINE_LANE),
770
873
  generation: reqF(R_INT0),
771
874
  cloud: reqF(ENGINE_TARGET_CLOUD),
772
875
  local: reqF(ENGINE_TARGET_LOCAL),
@@ -792,6 +895,8 @@ const ENGINE_TARGET_REFUSED_SPEC = {
792
895
  detail: optF(R_STR),
793
896
  };
794
897
  const checkEngineTargetResult = seatShapeCheck(okArmsRule("engineTarget result", {}, ENGINE_TARGET_REFUSED_SPEC));
898
+ const checkEngineSwapAnswerOutcome = seatShapeCheck(oneOfRule("swap answer", ENGINE_SWAP_ANSWER_OUTCOMES));
899
+ const checkSelfUpgradeOutcome = seatShapeCheck(oneOfRule("self upgrade", SELF_UPGRADE_OUTCOMES));
795
900
  const checkCancelCloudLogin = seatShapeCheck(shapeRule("cancel ack", { ok: reqF(R_BOOL) }));
796
901
  const checkCloudLoginStart = seatShapeCheck(okArmsRule("startCloudLogin result", {
797
902
  verificationUri: reqF(R_DISPLAY_URL),
@@ -1064,6 +1169,119 @@ export function planSetComputerUse(request, lockedByEnv) {
1064
1169
  return Object.freeze({ kind: "refused", reason: "confirmation-required" });
1065
1170
  return Object.freeze({ kind: "apply", enabled: intent.kind === "enable" });
1066
1171
  }
1172
+ export const SEAT_ACTION_NAMES = Object.freeze(["new-project", "prefill-composer"]);
1173
+ const SEAT_PREFILL_TEXT_MAX = 14336;
1174
+ const SEAT_PREFILL_CWD_MAX = 4096;
1175
+ const SEAT_ACTIONS_CLAIM_MAX = 16;
1176
+ const SEAT_ACTION_WORD_MAX = 64;
1177
+ const SEAT_TEXT_FACE = Object.freeze({ foldLines: false, keepLayout: "crlf", credentialUrls: false, credentialWords: false });
1178
+ const SEAT_PATH_FACE = Object.freeze({ foldLines: false, credentialUrls: false, credentialWords: false });
1179
+ const faceClean = (v, face) => displayUntrustedMarks(v, face).marks.length === 0;
1180
+ const R_PREFILL_TEXT = ruleOf(`prefill text (1–${SEAT_PREFILL_TEXT_MAX} chars, no control, bidi or other invisible characters)`, (v) => typeof v === "string" && v.length > 0 && v.length <= SEAT_PREFILL_TEXT_MAX && faceClean(v, SEAT_TEXT_FACE));
1181
+ const R_PREFILL_CWD = ruleOf(`folder path (1–${SEAT_PREFILL_CWD_MAX} chars, no control, bidi or other invisible characters)`, (v) => isFolderPath(v) && v.length <= SEAT_PREFILL_CWD_MAX && faceClean(v, SEAT_PATH_FACE));
1182
+ const SEAT_ACTION_ARMS = {
1183
+ "new-project": {},
1184
+ "prefill-composer": { text: reqF(R_PREFILL_TEXT), cwd: optF(R_PREFILL_CWD) },
1185
+ };
1186
+ export const checkSeatAction = seatShapeCheck(armsRule("seat action", "action", SEAT_ACTION_ARMS));
1187
+ const seatActionMalformed = (reason) => Object.freeze({ kind: "malformed", reason });
1188
+ export function readSeatAction(ev) {
1189
+ try {
1190
+ if (!isPlainRecord(ev))
1191
+ return seatActionMalformed("not a plain object");
1192
+ const name = own(ev, "action");
1193
+ if (typeof name !== "string")
1194
+ return seatActionMalformed("action must be a string");
1195
+ if (!inTuple(SEAT_ACTION_NAMES, name))
1196
+ return Object.freeze({ kind: "unknown", name: name.slice(0, SEAT_ACTION_WORD_MAX) });
1197
+ const verdict = checkSeatAction(ev);
1198
+ if (verdict !== true) {
1199
+ return seatActionMalformed(`${verdict.field ? `${verdict.field}: ` : ""}${verdict.reason}`);
1200
+ }
1201
+ if (name === "new-project")
1202
+ return Object.freeze({ kind: "action", action: Object.freeze({ action: "new-project" }) });
1203
+ const text = own(ev, "text");
1204
+ const cwd = own(ev, "cwd");
1205
+ if (R_PREFILL_TEXT.test(text, "text") !== true || typeof text !== "string")
1206
+ return seatActionMalformed("text: payload changed while being read");
1207
+ if (!isAbsent(cwd) && (R_PREFILL_CWD.test(cwd, "cwd") !== true || typeof cwd !== "string"))
1208
+ return seatActionMalformed("cwd: payload changed while being read");
1209
+ return Object.freeze({
1210
+ kind: "action",
1211
+ action: Object.freeze({ action: "prefill-composer", text, ...(typeof cwd === "string" ? { cwd } : {}) }),
1212
+ });
1213
+ }
1214
+ catch {
1215
+ return seatActionMalformed("payload could not be read");
1216
+ }
1217
+ }
1218
+ const quoteSeatWord = (w) => quoteUntrustedForSentence(w, SEAT_ACTION_WORD_MAX) ?? '""';
1219
+ const R_CLAIM_WORD = {
1220
+ label: "action word",
1221
+ test: (v, path) => typeof v === "string"
1222
+ ? inTuple(SEAT_ACTION_NAMES, v)
1223
+ ? true
1224
+ : bad(`unknown action word ${quoteSeatWord(v)} (closed set: ${SEAT_ACTION_NAMES.join("|")})`, path)
1225
+ : bad("bad value (action word)", path),
1226
+ };
1227
+ const claimListOnce = (v, path) => {
1228
+ const n = ownDataField(v, "length");
1229
+ if (typeof n !== "number" || !Number.isSafeInteger(n) || n < 0)
1230
+ return bad("bad value (action list)", path);
1231
+ if (n > SEAT_ACTIONS_CLAIM_MAX)
1232
+ return bad(`bad value (at most ${SEAT_ACTIONS_CLAIM_MAX} actions)`, path);
1233
+ for (const k of Reflect.ownKeys(v)) {
1234
+ if (typeof k === "string" && !isArraySlotKey(k, n))
1235
+ return bad("unknown key", pathAt(path, k));
1236
+ }
1237
+ const words = [];
1238
+ for (let i = 0; i < n; i += 1)
1239
+ words.push(own(v, String(i)));
1240
+ return words;
1241
+ };
1242
+ const R_CLAIM_LIST = {
1243
+ label: `action list (at most ${SEAT_ACTIONS_CLAIM_MAX})`,
1244
+ test: (v, path) => {
1245
+ if (!Array.isArray(v))
1246
+ return bad("bad value (action list)", path);
1247
+ const words = claimListOnce(v, path);
1248
+ if (!Array.isArray(words))
1249
+ return words;
1250
+ for (let i = 0; i < words.length; i += 1) {
1251
+ const verdict = R_CLAIM_WORD.test(words[i], `${path}[${i}]`);
1252
+ if (verdict !== true)
1253
+ return verdict;
1254
+ }
1255
+ return true;
1256
+ },
1257
+ };
1258
+ const checkSeatActionsClaimShape = seatShapeCheck(shapeRule("seat actions claim", { actions: reqF(R_CLAIM_LIST) }));
1259
+ export const checkSeatActionsClaim = seatCheck((v) => isPlainRecord(v) ? checkSeatActionsClaimShape(v) : bad("claimSeatActions request is not a plain object"));
1260
+ export function claimedSeatActionsOf(claim) {
1261
+ try {
1262
+ if (!isPlainRecord(claim))
1263
+ return Object.freeze([]);
1264
+ const snap = Object.create(null);
1265
+ for (const k of Reflect.ownKeys(claim)) {
1266
+ if (typeof k === "string")
1267
+ snap[k] = own(claim, k);
1268
+ }
1269
+ const list = snap.actions;
1270
+ if (Array.isArray(list)) {
1271
+ const words = claimListOnce(list, "actions");
1272
+ if (!Array.isArray(words))
1273
+ return Object.freeze([]);
1274
+ snap.actions = words;
1275
+ }
1276
+ if (checkSeatActionsClaim(snap) !== true)
1277
+ return Object.freeze([]);
1278
+ const taken = snap.actions;
1279
+ return Object.freeze(SEAT_ACTION_NAMES.filter((name) => taken.includes(name)));
1280
+ }
1281
+ catch {
1282
+ return Object.freeze([]);
1283
+ }
1284
+ }
1067
1285
  const checkLocalSessionRecord = seatCheck((s) => {
1068
1286
  if (!isPlainRecord(s))
1069
1287
  return bad("session record is not a plain object");
@@ -1125,11 +1343,77 @@ const checkLocalSessionRecord = seatCheck((s) => {
1125
1343
  if (!isAbsent(lane) && (typeof lane !== "string" || lane.length === 0)) {
1126
1344
  return bad("executionLane must be a non-empty string when present (absent = no writer lane reading)", "executionLane");
1127
1345
  }
1346
+ const parkedRows = own(s, "parkedUnresumable");
1347
+ if (!isAbsent(parkedRows)) {
1348
+ const verdict = R_PARKED_UNRESUMABLE.test(parkedRows, "parkedUnresumable");
1349
+ if (verdict !== true)
1350
+ return verdict;
1351
+ if (parked === false)
1352
+ return bad("bad value (parked:false)", "parkedUnresumable");
1353
+ }
1128
1354
  return true;
1129
1355
  });
1130
1356
  export function isLocalSessionRecord(s) {
1131
1357
  return checkLocalSessionRecord(s) === true;
1132
1358
  }
1359
+ const checkParkedUnresumableSlot = seatCheck((v) => R_PARKED_UNRESUMABLE.test(v, "parkedUnresumable"));
1360
+ const parkedVerdictCopy = (rv) => {
1361
+ const kind = own(rv, "kind");
1362
+ const str = (k) => {
1363
+ const x = own(rv, k);
1364
+ return typeof x === "string" ? x : undefined;
1365
+ };
1366
+ const sentence = str("sentence");
1367
+ if (kind === "lacking" || kind === "damaged") {
1368
+ const reason = str("reason");
1369
+ const requires = own(rv, "requires");
1370
+ return Object.freeze({
1371
+ kind,
1372
+ code: str("code") ?? "",
1373
+ ...(reason !== undefined ? { reason } : {}),
1374
+ ...(Array.isArray(requires) ? { requires: Object.freeze(ownItems(requires).filter((w) => typeof w === "string")) } : {}),
1375
+ sentence: sentence ?? "",
1376
+ });
1377
+ }
1378
+ if (kind === "unknown")
1379
+ return Object.freeze({ kind, word: str("word") ?? "", ...(sentence !== undefined ? { sentence } : {}) });
1380
+ return Object.freeze({ kind: "unreadable" });
1381
+ };
1382
+ const parkedRowCopy = (item) => {
1383
+ const str = (k) => {
1384
+ const x = own(item, k);
1385
+ return typeof x === "string" ? x : undefined;
1386
+ };
1387
+ const rv = own(item, "rowVerdict");
1388
+ const rowKey = str("rowKey");
1389
+ const taskId = str("taskId");
1390
+ const toolName = str("toolName");
1391
+ const rowDeadline = str("rowDeadline");
1392
+ return Object.freeze({
1393
+ rowVerdict: parkedVerdictCopy(typeof rv === "object" && rv !== null ? rv : {}),
1394
+ ...(rowKey !== undefined ? { rowKey } : {}),
1395
+ ...(taskId !== undefined ? { taskId } : {}),
1396
+ ...(toolName !== undefined ? { toolName } : {}),
1397
+ ...(rowDeadline === "armed" || rowDeadline === "none" ? { rowDeadline } : {}),
1398
+ });
1399
+ };
1400
+ export function readSeatParkedUnresumable(record) {
1401
+ try {
1402
+ if (typeof record !== "object" || record === null)
1403
+ return undefined;
1404
+ const v = own(record, "parkedUnresumable");
1405
+ if (isAbsent(v))
1406
+ return undefined;
1407
+ if (own(record, "parked") === false)
1408
+ return undefined;
1409
+ if (checkParkedUnresumableSlot(v) !== true)
1410
+ return undefined;
1411
+ return Object.freeze(ownItems(v).map((item) => parkedRowCopy(item)));
1412
+ }
1413
+ catch {
1414
+ return undefined;
1415
+ }
1416
+ }
1133
1417
  const checkToctouBinding = seatCheck((v) => {
1134
1418
  if (!isPlainRecord(v))
1135
1419
  return bad("toctouBinding must be a plain object", "toctouBinding");
@@ -1608,6 +1892,16 @@ export const checkSetThinkingLatchRequest = seatCheck((v) => isPlainRecord(v) ?
1608
1892
  export function isSetThinkingLatchRequest(v) {
1609
1893
  return checkSetThinkingLatchRequest(v) === true;
1610
1894
  }
1895
+ const checkStartSessionOptionsShape = seatShapeCheck(shapeRule("start options", {
1896
+ model: optF(R_STR),
1897
+ title: optF(R_STR),
1898
+ cwd: optF(R_STR),
1899
+ excludeTools: optF(arrayRule(R_STR)),
1900
+ engine: optF(R_ENGINE_LANE),
1901
+ }));
1902
+ export const checkStartSessionOptions = seatCheck((v) => isAbsent(v) ? true : isPlainRecord(v) ? checkStartSessionOptionsShape(v) : bad("start options are not a plain object"));
1903
+ const checkSeatResourceScopeShape = seatShapeCheck(shapeRule("resource scope", { sessionId: reqF(R_NONEMPTY) }));
1904
+ export const checkSeatResourceScope = seatCheck((v) => isAbsent(v) ? true : isPlainRecord(v) ? checkSeatResourceScopeShape(v) : bad("resource scope is not a plain object"));
1611
1905
  const checkSendMessageAck = seatCheck((v) => {
1612
1906
  if (!isPlainRecord(v))
1613
1907
  return bad("sendMessage ack is not a plain object");
@@ -1773,6 +2067,8 @@ export const LOCAL_SESSIONS_SPEC = {
1773
2067
  connectCloudEngine: { kind: "invoke", check: checkCloudConnectResult },
1774
2068
  configureCloudEngine: { kind: "invoke", check: checkCloudConnectResult },
1775
2069
  clearCloudEngine: { kind: "invoke", check: checkEngineTargetResult },
2070
+ answerEngineSwap: { kind: "invoke", check: checkEngineSwapAnswerOutcome },
2071
+ beginSelfUpgrade: { kind: "invoke", check: checkSelfUpgradeOutcome },
1776
2072
  listOnboardProviders: { kind: "invoke", check: checkOnboardProvidersResult },
1777
2073
  probeOnboardEntry: { kind: "invoke", check: checkOnboardProbeResult },
1778
2074
  applyOnboardEntry: { kind: "invoke", check: checkOnboardApplyResult },
@@ -1782,8 +2078,10 @@ export const LOCAL_SESSIONS_SPEC = {
1782
2078
  setThinkingLatch: { kind: "invoke", check: checkOkAck },
1783
2079
  getComputerUse: { kind: "invoke", check: checkComputerUseState },
1784
2080
  setComputerUse: { kind: "invoke", check: checkSetComputerUseResult },
2081
+ claimSeatActions: { kind: "invoke", check: checkOkAck },
1785
2082
  onEvent: { kind: "event", check: checkLocalSessionEvent },
1786
2083
  onToolPermissionRequest: { kind: "event", check: checkToolPermissionRequest },
2084
+ onSeatAction: { kind: "event", check: checkSeatAction },
1787
2085
  },
1788
2086
  stores: {
1789
2087
  sessionsState: { check: checkSessionsState },
@@ -1823,6 +2121,8 @@ export const SEAT_METHOD_NAMES = [
1823
2121
  "connectCloudEngine",
1824
2122
  "configureCloudEngine",
1825
2123
  "clearCloudEngine",
2124
+ "answerEngineSwap",
2125
+ "beginSelfUpgrade",
1826
2126
  "listOnboardProviders",
1827
2127
  "probeOnboardEntry",
1828
2128
  "applyOnboardEntry",
@@ -1832,8 +2132,10 @@ export const SEAT_METHOD_NAMES = [
1832
2132
  "setThinkingLatch",
1833
2133
  "getComputerUse",
1834
2134
  "setComputerUse",
2135
+ "claimSeatActions",
1835
2136
  "onEvent",
1836
2137
  "onToolPermissionRequest",
2138
+ "onSeatAction",
1837
2139
  ];
1838
2140
  export const SEAT_STORE_PROPS = [
1839
2141
  "sessionsStateStore",
@@ -1842,7 +2144,7 @@ export const SEAT_STORE_PROPS = [
1842
2144
  "seatCapabilitiesStateStore",
1843
2145
  "engineTargetStateStore",
1844
2146
  ];
1845
- export const SEAT_EVENT_METHOD_NAMES = ["onEvent", "onToolPermissionRequest"];
2147
+ export const SEAT_EVENT_METHOD_NAMES = ["onEvent", "onToolPermissionRequest", "onSeatAction"];
1846
2148
  export const LOCAL_SESSION_EVENT_KEYS = [
1847
2149
  "type",
1848
2150
  "sessionId",
@@ -1895,6 +2197,7 @@ export const LOCAL_SESSION_RECORD_KEYS = [
1895
2197
  "thinkingLatch",
1896
2198
  "engine",
1897
2199
  "executionLane",
2200
+ "parkedUnresumable",
1898
2201
  ];
1899
2202
  export const SEND_MESSAGE_REQUEST_KEYS = [
1900
2203
  "sessionId",
@@ -1934,12 +2237,12 @@ export const TOOL_PERMISSION_DECISION_KEYS = [
1934
2237
  "updatedInput",
1935
2238
  "remember",
1936
2239
  ];
1937
- export const START_SESSION_OPTION_KEYS = ["model", "title", "cwd", "excludeTools"];
2240
+ export const START_SESSION_OPTION_KEYS = ["model", "title", "cwd", "excludeTools", "engine"];
1938
2241
  export const SEAT_VALIDATOR_KEY_COVERAGE = {
1939
2242
  LocalSessionRecord: {
1940
2243
  guard: "isLocalSessionRecord",
1941
2244
  check: checkLocalSessionRecord,
1942
- validated: ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked", "pinned", "rowTag", "unreadable", "thinkingLatch", "engine", "executionLane"],
2245
+ validated: ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked", "pinned", "rowTag", "unreadable", "thinkingLatch", "engine", "executionLane", "parkedUnresumable"],
1943
2246
  unchecked: [],
1944
2247
  },
1945
2248
  ToolPermissionRequest: {
@@ -2039,6 +2342,10 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
2039
2342
  key: "modelPlane",
2040
2343
  why: "诊断面(0.106.0 CC-1156;这台引擎服务的是哪张模型表 / 最近一份目录候选的结局),三态读法归 modelPlaneOf(含坏形 unreadable、表外词整位不给);出站门为它拒掉整份目录 = 选单为一行诊断整个消失。",
2041
2344
  },
2345
+ {
2346
+ key: "aliases",
2347
+ why: "受理面(0.108.0 CC-944;除行名之外引擎还认的模型词),读法归 modelAcceptanceOf(缺席 = 更早的服务端,照旧判;在场而坏形 ⇒ 没找到行的词读 catalog_unreadable);出站门为它拒掉整份目录 = 选单为一份受理数据整个消失。",
2348
+ },
2042
2349
  ],
2043
2350
  },
2044
2351
  SendMessageRequest: {
@@ -2073,6 +2380,21 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
2073
2380
  validated: ["sessionId", "event"],
2074
2381
  unchecked: [],
2075
2382
  },
2383
+ StartSessionOptions: {
2384
+ check: checkStartSessionOptions,
2385
+ validated: ["model", "title", "cwd", "excludeTools", "engine"],
2386
+ unchecked: [],
2387
+ },
2388
+ SeatResourceScope: {
2389
+ check: checkSeatResourceScope,
2390
+ validated: ["sessionId"],
2391
+ unchecked: [],
2392
+ },
2393
+ SeatActionsClaim: {
2394
+ check: checkSeatActionsClaim,
2395
+ validated: ["actions"],
2396
+ unchecked: [],
2397
+ },
2076
2398
  ApplyModelConfigResult: {
2077
2399
  check: checkApplyModelConfigResult,
2078
2400
  validated: ["ok", "requiresRestart", "reason", "detail"],
@@ -2126,7 +2448,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
2126
2448
  },
2127
2449
  SeatCapabilitiesState: {
2128
2450
  check: checkSeatCapabilitiesState,
2129
- validated: ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly"],
2451
+ validated: ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions"],
2130
2452
  unchecked: [],
2131
2453
  },
2132
2454
  RecentFoldersResult: {
@@ -2192,6 +2514,9 @@ export const SEAT_VALIDATOR_COVERAGE_EXEMPT = [
2192
2514
  ["ComputerUseState", checkComputerUseState],
2193
2515
  ["SetComputerUseResult", checkSetComputerUseResult],
2194
2516
  ["SetComputerUseRequest", checkSetComputerUseRequest],
2517
+ ["SeatAction", checkSeatAction],
2518
+ ["EngineSwapAnswerOutcome", checkEngineSwapAnswerOutcome],
2519
+ ["SelfUpgradeOutcome", checkSelfUpgradeOutcome],
2195
2520
  ].map(([label, check]) => ({
2196
2521
  label,
2197
2522
  check,
@@ -2251,5 +2576,10 @@ const _seatContractPins = [
2251
2576
  true, true,
2252
2577
  true, true, true, true,
2253
2578
  true, true,
2579
+ true, true, true,
2580
+ true, true, true, true,
2581
+ true, true,
2582
+ true, true, true, true, true, true, true,
2583
+ true, true, true, true, true, true, true, true,
2254
2584
  ];
2255
2585
  void _seatContractPins;
@@ -34,6 +34,8 @@ export function readSessionBackgroundable(baseUrl = engineWireTargetBaseUrl()) {
34
34
  return Object.freeze({ kind: 'unobserved' });
35
35
  }
36
36
  }
37
+ const localEngineLanePin = true;
38
+ void localEngineLanePin;
37
39
  export const OPENING_RECORD_CAP = 256;
38
40
  const wireStates = new WeakMap();
39
41
  const isObj = (v) => (typeof v === 'object' && v !== null) || typeof v === 'function';
@@ -134,7 +134,7 @@ export interface SessionEngineWiring {
134
134
  readonly auth: EngineTargetCloudAuth | undefined;
135
135
  readonly explicitAddresses?: readonly string[];
136
136
  }
137
- export type SessionDispatchRefusal = 'not-wired' | 'scope-mismatch' | 'scope-unproven' | 'unresolved';
137
+ export type SessionDispatchRefusal = 'not-wired' | 'scope-mismatch' | 'scope-unproven' | 'unresolved' | 'session-ambiguous';
138
138
  export type SessionDispatchDecision = {
139
139
  readonly kind: 'self';
140
140
  readonly wiringSnapshotId: string;
@@ -153,4 +153,5 @@ export declare function sessionEngineBindingFor(input: SessionEngineBindingInput
153
153
  export declare function isSessionEngineView(v: {} | null | undefined): boolean;
154
154
  export declare function readSessionEngine(record: SessionMapRecord | undefined): SessionEngineReading;
155
155
  export declare function commitSessionEngine(store: SessionMapStorePort, session: SessionEngineSessionRef, request: SessionEngineCommitRequest): SessionEngineCommitResult;
156
+ export declare function sessionDispatchRefusedFor(refusal: SessionDispatchRefusal): SessionDispatchRefused;
156
157
  export declare function sessionDispatchTarget(reading: SessionEngineReading, ctx: SessionEngineWiring): SessionDispatchDecision;
@@ -382,8 +382,13 @@ const REFUSAL_KEYS = {
382
382
  'scope-mismatch': 'session.engine.dispatch.scopeMismatch',
383
383
  'scope-unproven': 'session.engine.dispatch.scopeUnproven',
384
384
  unresolved: 'session.engine.dispatch.unresolved',
385
+ 'session-ambiguous': 'session.engine.dispatch.sessionAmbiguous',
385
386
  };
386
387
  const refused = (refusal) => Object.freeze({ kind: 'refused', refusal, message: msg(REFUSAL_KEYS[refusal]) });
388
+ export function sessionDispatchRefusedFor(refusal) {
389
+ const word = Object.keys(REFUSAL_KEYS).find((w) => w === refusal);
390
+ return refused(word ?? 'unresolved');
391
+ }
387
392
  function authOf(ctx) {
388
393
  const slot = slotReadOf(ctx, 'auth');
389
394
  if (slot.presence === 'absent' || (slot.presence === 'present' && slot.value === undefined))
@@ -40,6 +40,11 @@ export declare function hooksSalvageMaskOf(dropped: readonly {
40
40
  readonly path: readonly (string | number)[];
41
41
  }[]): HooksSalvageMask;
42
42
  export declare function salvageSettingsHooksEntries(doc: SettingsDocument | null | undefined): HooksSalvage;
43
+ export declare function hooksGroupUnreadKeys(event: string, group: object): readonly string[] | undefined;
44
+ export type HooksGroupAuthoredSource = 'absent' | 'present' | 'unreadable';
45
+ export declare function hooksGroupAuthoredSource(group: object): HooksGroupAuthoredSource;
46
+ export declare function hooksEntryUnreadKeys(event: string, entry: object, notRead: readonly string[]): readonly string[] | undefined;
47
+ export declare function hooksKeyCoordinateText(path: readonly (string | number)[]): string;
43
48
  export declare const HOOK_SETTINGS_SOURCE_TEXT: Readonly<Record<HookSettingsSource, string>>;
44
49
  export declare function layerNotAppliedRefusesTurn(source: HookSettingsSource): boolean;
45
50
  export declare function settingsHooksSalvageNotice(salvage: HooksSalvage, source: HookSettingsSource, doc?: SettingsDocument | null): string | undefined;