@sema-agent/client-core 0.112.0 → 0.113.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 (182) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/README.md +37 -24
  3. package/dist/adapt/arms.js +7 -1
  4. package/dist/adapt/textStream.d.ts +2 -0
  5. package/dist/adapt/textStream.js +27 -1
  6. package/dist/adapter/activeRunSelfHeal.d.ts +7 -5
  7. package/dist/adapter/activeRunSelfHeal.js +38 -66
  8. package/dist/adapter/downstream/eventToSdkMessage.js +4 -0
  9. package/dist/adapter/downstream/terminalToSdkResult.d.ts +8 -0
  10. package/dist/adapter/downstream/terminalToSdkResult.js +36 -1
  11. package/dist/adapter/runStream.d.ts +2 -12
  12. package/dist/adapter/runStream.js +46 -19
  13. package/dist/agentSession/engineAgentRegistryRead.js +2 -1
  14. package/dist/agentSession/engineSessionBackgroundStop.js +2 -2
  15. package/dist/attachmentOutcome.d.ts +35 -0
  16. package/dist/attachmentOutcome.js +192 -0
  17. package/dist/attachmentPathPlan.d.ts +67 -0
  18. package/dist/attachmentPathPlan.js +203 -0
  19. package/dist/attachmentRoute.d.ts +9 -1
  20. package/dist/attachmentRoute.js +23 -2
  21. package/dist/declared/supportFloorDeclared.d.ts +1 -1
  22. package/dist/declared/supportFloorDeclared.js +1 -0
  23. package/dist/deviceRebind.js +2 -3
  24. package/dist/displayUntrusted.js +126 -19
  25. package/dist/engineAddress.d.ts +1 -1
  26. package/dist/engineAddress.js +9 -6
  27. package/dist/engineErrorCodes.d.ts +3 -0
  28. package/dist/engineErrorCodes.js +4 -0
  29. package/dist/engineNoticeCodes.d.ts +34 -4
  30. package/dist/engineNoticeCodes.js +133 -6
  31. package/dist/engineUnavailable.d.ts +4 -2
  32. package/dist/engineUnavailable.js +99 -17
  33. package/dist/fleet/fleetLedger.d.ts +9 -3
  34. package/dist/fleet/fleetLedger.js +112 -16
  35. package/dist/fleet/fleetProjection.d.ts +5 -0
  36. package/dist/fleet/fleetProjection.js +9 -1
  37. package/dist/gateVocabulary.d.ts +7 -0
  38. package/dist/gateVocabulary.js +40 -14
  39. package/dist/generated/engineFactTables.d.ts +4 -2
  40. package/dist/generated/engineFactTables.js +198 -2
  41. package/dist/generated/engineNoticeTables.js +56 -8
  42. package/dist/generated/settingsSchemaFns.d.ts +7 -0
  43. package/dist/generated/settingsSchemaFns.js +11 -0
  44. package/dist/generated/settingsSchemaHash.d.ts +1 -0
  45. package/dist/generated/settingsSchemaHash.js +58 -0
  46. package/dist/generated/settingsSchemaOwnKeyRead.js +6 -1
  47. package/dist/generated/settingsSchemaTables.d.ts +3 -2
  48. package/dist/generated/settingsSchemaTables.js +14 -0
  49. package/dist/generated/settingsSchemaTightenVerdict.d.ts +1 -0
  50. package/dist/generated/settingsSchemaTightenVerdict.js +125 -0
  51. package/dist/headlessPermissionModeWire.d.ts +7 -2
  52. package/dist/headlessPermissionModeWire.js +77 -8
  53. package/dist/hitl/approvalDecisionDoor.d.ts +24 -0
  54. package/dist/hitl/approvalDecisionDoor.js +77 -0
  55. package/dist/hitl/approvalDelivery.d.ts +6 -0
  56. package/dist/hitl/approvalDelivery.js +57 -7
  57. package/dist/hitl/approvalResolution.d.ts +6 -3
  58. package/dist/hitl/approvalResolution.js +24 -2
  59. package/dist/hitl/approvalsFeed.js +1 -1
  60. package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
  61. package/dist/hitl/decisionSend.d.ts +7 -4
  62. package/dist/hitl/decisionSend.js +90 -41
  63. package/dist/hitl/frameRouter.d.ts +3 -3
  64. package/dist/hitl/frameRouter.js +5 -0
  65. package/dist/hitl/hitlBridge.d.ts +1 -0
  66. package/dist/hitl/hitlBridge.js +17 -4
  67. package/dist/hitl/hitlHostSurface.d.ts +3 -2
  68. package/dist/hitl/hitlHostSurface.js +5 -3
  69. package/dist/hitl/legacyApprovalShapes.d.ts +142 -0
  70. package/dist/hitl/legacyApprovalShapes.js +1 -0
  71. package/dist/hitl/livePendingAsk.d.ts +4 -4
  72. package/dist/hitl/livePendingAsk.js +5 -3
  73. package/dist/hitl/parkResolver.js +1 -1
  74. package/dist/hitl/persistedRulesWire.js +2 -2
  75. package/dist/hitl/planReviewCard.d.ts +4 -2
  76. package/dist/hitl/planReviewCard.js +66 -1
  77. package/dist/hitl/planReviewWire.d.ts +34 -2
  78. package/dist/hitl/planReviewWire.js +326 -150
  79. package/dist/hitl/sessionPolicyWire.js +16 -7
  80. package/dist/hitl/subagentSource.d.ts +1 -0
  81. package/dist/hitl/subagentSource.js +11 -0
  82. package/dist/hitl/toolApprovalWire.d.ts +34 -10
  83. package/dist/hitl/toolApprovalWire.js +182 -33
  84. package/dist/hookMatcherVerdict.d.ts +2 -1
  85. package/dist/hookMatcherVerdict.js +3 -2
  86. package/dist/hooksReaderGenerations.d.ts +8 -0
  87. package/dist/hooksReaderGenerations.js +49 -0
  88. package/dist/hooksWireCaps.js +43 -18
  89. package/dist/hostSettingsSource.d.ts +1 -1
  90. package/dist/hostSettingsSource.js +2 -2
  91. package/dist/hostTurnSettings.d.ts +2 -2
  92. package/dist/hostTurnSettings.js +87 -47
  93. package/dist/humanTurn.d.ts +2 -1
  94. package/dist/humanTurn.js +44 -13
  95. package/dist/humanTurnRead.d.ts +7 -0
  96. package/dist/humanTurnRead.js +23 -14
  97. package/dist/humanTurnSentences.js +3 -0
  98. package/dist/i18n/messages.en.d.ts +93 -5
  99. package/dist/i18n/messages.en.js +100 -12
  100. package/dist/i18n/messages.zh.js +110 -15
  101. package/dist/index.d.ts +29 -15
  102. package/dist/index.js +17 -9
  103. package/dist/liveModelCatalog.js +1 -0
  104. package/dist/liveQuestionStore.d.ts +2 -0
  105. package/dist/liveQuestionStore.js +7 -2
  106. package/dist/localConfig/kernel.d.ts +2 -1
  107. package/dist/localConfig/kernel.js +12 -18
  108. package/dist/localConfig/mcp/edit.js +25 -27
  109. package/dist/localConfig/mcp/servers.js +5 -8
  110. package/dist/localConfig/modelPool.d.ts +6 -1
  111. package/dist/localConfig/modelPool.js +104 -27
  112. package/dist/localConfig/modelPoolWords.d.ts +2 -0
  113. package/dist/localConfig/modelPoolWords.js +1 -0
  114. package/dist/localConfig/settingsWrite.js +1 -14
  115. package/dist/localConfig/skills.js +9 -16
  116. package/dist/localEngineSpawn.d.ts +29 -1
  117. package/dist/localEngineSpawn.js +62 -1
  118. package/dist/mcpLiveness.d.ts +1 -1
  119. package/dist/mcpProbeWire.js +2 -2
  120. package/dist/mcpReconnect.js +2 -2
  121. package/dist/model/catalogLoader.js +3 -17
  122. package/dist/model/onboardJudgement.d.ts +8 -0
  123. package/dist/model/onboardJudgement.js +8 -3
  124. package/dist/model/onboardSteps.d.ts +19 -0
  125. package/dist/model/onboardSteps.js +76 -0
  126. package/dist/notifications.js +20 -12
  127. package/dist/ownKey.d.ts +4 -0
  128. package/dist/ownKey.js +61 -0
  129. package/dist/pathShape.d.ts +14 -0
  130. package/dist/pathShape.js +44 -0
  131. package/dist/planReviewCardFacts.d.ts +3 -0
  132. package/dist/planReviewCardFacts.js +20 -3
  133. package/dist/planReviewOutcomeCause.d.ts +2 -0
  134. package/dist/planReviewOutcomeCause.js +12 -0
  135. package/dist/pluginHooksWire.d.ts +20 -8
  136. package/dist/pluginHooksWire.js +204 -86
  137. package/dist/prepareRefusal.d.ts +2 -0
  138. package/dist/prepareRefusal.js +11 -1
  139. package/dist/request/taskRequest.js +3 -1
  140. package/dist/resultFrameKeys.d.ts +1 -0
  141. package/dist/resultFrameKeys.js +3 -0
  142. package/dist/resumeRefusalCopy.js +3 -1
  143. package/dist/retryStatus.d.ts +11 -1
  144. package/dist/retryStatus.js +15 -4
  145. package/dist/runTerminal.d.ts +1 -0
  146. package/dist/runTerminal.js +15 -1
  147. package/dist/sdkWireTransit.d.ts +1 -1
  148. package/dist/seatContract.d.ts +12 -3
  149. package/dist/seatContract.js +24 -13
  150. package/dist/sessionEngine.js +1 -1
  151. package/dist/sessionHooksRoster.js +8 -6
  152. package/dist/sessionIdSegment.d.ts +0 -1
  153. package/dist/sessionIdSegment.js +1 -3
  154. package/dist/sessionMemoryErase.js +2 -2
  155. package/dist/sessionMemoryStatus.js +2 -1
  156. package/dist/sessionOccupant.d.ts +29 -0
  157. package/dist/sessionOccupant.js +78 -0
  158. package/dist/settingsHooksSalvage.d.ts +4 -1
  159. package/dist/settingsHooksSalvage.js +22 -9
  160. package/dist/skillOverrideChain.d.ts +3 -0
  161. package/dist/skillOverrideChain.js +31 -4
  162. package/dist/skillsWireCaps.d.ts +16 -2
  163. package/dist/skillsWireCaps.js +47 -20
  164. package/dist/subagent/agentStateDetail.js +32 -8
  165. package/dist/subagent/engineCompactWire.js +48 -36
  166. package/dist/subagent/engineDelegatedPrompt.d.ts +3 -2
  167. package/dist/subagent/engineDelegatedPrompt.js +65 -28
  168. package/dist/subagentEditOutcomes.d.ts +9 -0
  169. package/dist/subagentEditOutcomes.js +43 -0
  170. package/dist/supportFloor.d.ts +2 -1
  171. package/dist/supportFloor.js +1 -1
  172. package/dist/toolResult.js +4 -2
  173. package/dist/toolRoster.d.ts +1 -0
  174. package/dist/toolRoster.js +1 -0
  175. package/dist/usageAnalytics.js +2 -1
  176. package/dist/userAttachmentEnvelope.d.ts +11 -0
  177. package/dist/userAttachmentEnvelope.js +7 -2
  178. package/dist/userAttachmentSeat.d.ts +7 -1
  179. package/dist/userAttachmentSeat.js +44 -7
  180. package/dist/wiringInstructionsAttribution.js +8 -2
  181. package/docs/INTEGRATION-CLIENTS.md +1654 -16
  182. package/package.json +5 -5
@@ -15,6 +15,8 @@ export type RetryStatus = {
15
15
  sleptMs?: number;
16
16
  waitSegment?: BrainStatusWaitSegment | (string & {});
17
17
  seat?: BrainStatusSeat | (string & {});
18
+ providerMessage?: string;
19
+ toolCallId?: string;
18
20
  detail?: string;
19
21
  } | {
20
22
  kind: 'error';
@@ -33,6 +35,8 @@ export type RetryStatus = {
33
35
  sleptMs?: number;
34
36
  waitSegment?: BrainStatusWaitSegment | (string & {});
35
37
  seat?: BrainStatusSeat | (string & {});
38
+ providerMessage?: string;
39
+ toolCallId?: string;
36
40
  } | {
37
41
  kind: 'waiting';
38
42
  deadline: number;
@@ -48,6 +52,8 @@ export type RetryStatus = {
48
52
  sleptMs?: number;
49
53
  waitSegment?: BrainStatusWaitSegment | (string & {});
50
54
  seat?: BrainStatusSeat | (string & {});
55
+ providerMessage?: string;
56
+ toolCallId?: string;
51
57
  terminal?: never;
52
58
  error: RetryStatusErrorPayload;
53
59
  };
@@ -82,12 +88,14 @@ export interface BrainStatusPayload {
82
88
  sleptMs?: number;
83
89
  waitSegment?: BrainStatusWaitSegment | (string & {});
84
90
  seat?: BrainStatusSeat | (string & {});
91
+ providerMessage?: string;
92
+ toolCallId?: string;
85
93
  }
86
94
  export declare const BRAIN_STATUS_WAIT_SEGMENTS: readonly ["response_headers", "first_token"];
87
95
  export type BrainStatusWaitSegment = (typeof BRAIN_STATUS_WAIT_SEGMENTS)[number];
88
96
  export declare const BRAIN_STATUS_SEATS: readonly ["classifier"];
89
97
  type BrainStatusSeat = (typeof BRAIN_STATUS_SEATS)[number];
90
- export declare const BRAIN_STATUS_PAYLOAD_KEYS: readonly ["phase", "detail", "retryInSec", "retryInMs", "attempt", "maxRetries", "errClass", "retryAtMs", "errorStatus", "elapsedMs", "timeoutMs", "providerCondition", "providerConditionSource", "sleptMs", "waitSegment", "seat"];
98
+ export declare const BRAIN_STATUS_PAYLOAD_KEYS: readonly ["phase", "detail", "retryInSec", "retryInMs", "attempt", "maxRetries", "errClass", "retryAtMs", "errorStatus", "elapsedMs", "timeoutMs", "providerCondition", "providerConditionSource", "sleptMs", "waitSegment", "seat", "providerMessage", "toolCallId"];
91
99
  export declare function mapBrainStatusToRetry(p: BrainStatusPayload, nowMs: number): RetryStatus | null;
92
100
  export interface RetryStatusArmLike {
93
101
  readonly phase?: string;
@@ -106,6 +114,8 @@ export interface RetryStatusArmLike {
106
114
  readonly sleptMs?: number;
107
115
  readonly waitSegment?: string;
108
116
  readonly seat?: string;
117
+ readonly providerMessage?: string;
118
+ readonly toolCallId?: string;
109
119
  readonly parentToolCallId?: string;
110
120
  }
111
121
  export declare function retryStatusFromArm(arm: RetryStatusArmLike | null | undefined, nowMs: number): RetryStatus | null | undefined;
@@ -36,6 +36,8 @@ export const BRAIN_STATUS_PAYLOAD_KEYS = [
36
36
  'sleptMs',
37
37
  'waitSegment',
38
38
  'seat',
39
+ 'providerMessage',
40
+ 'toolCallId',
39
41
  ];
40
42
  const _brainStatusKeyPin = [true, true];
41
43
  void _brainStatusKeyPin;
@@ -73,10 +75,17 @@ export function mapBrainStatusToRetry(p, nowMs) {
73
75
  ...(typeof waitSegment === 'string' && waitSegment.length > 0 ? { waitSegment } : {}),
74
76
  ...(typeof seat === 'string' && seat.length > 0 ? { seat } : {}),
75
77
  };
78
+ const providerMessageRaw = p.providerMessage;
79
+ const providerShown = typeof providerMessageRaw === 'string' && providerMessageRaw.length > 0 ? displayUntrusted(providerMessageRaw) : '';
80
+ const judgedCall = p.toolCallId;
81
+ const callFacts = {
82
+ ...(providerShown.length > 0 ? { providerMessage: providerShown } : {}),
83
+ ...(typeof judgedCall === 'string' && judgedCall.length > 0 ? { toolCallId: judgedCall } : {}),
84
+ };
76
85
  const stalledShown = typeof p.detail === 'string' && p.detail.length > 0 ? displayUntrusted(p.detail) : '';
77
86
  const stalledDetail = stalledShown.length > 0 ? { detail: stalledShown } : {};
78
87
  const shown = (absent) => (typeof p.detail === 'string' ? displayUntrusted(p.detail) : absent);
79
- const extra = { ...counts, ...cause, ...producerTiming, ...failureStatus, ...providerJudged, ...waitProgress, ...waitFacts };
88
+ const extra = { ...counts, ...cause, ...producerTiming, ...failureStatus, ...providerJudged, ...waitProgress, ...waitFacts, ...callFacts };
80
89
  switch (p.phase) {
81
90
  case 'recovered':
82
91
  return null;
@@ -98,7 +107,7 @@ export function mapBrainStatusToRetry(p, nowMs) {
98
107
  case 'retrying':
99
108
  return { kind: 'error', deadline, ...extra, error: { formatted: shown('') } };
100
109
  default:
101
- return { kind: 'error', deadline, ...extra, error: { formatted: '' } };
110
+ return null;
102
111
  }
103
112
  }
104
113
  export function retryStatusFromArm(arm, nowMs) {
@@ -120,8 +129,8 @@ export function retryStatusFromArm(arm, nowMs) {
120
129
  const v = str(key);
121
130
  return v !== undefined && v.length > 0 ? v : undefined;
122
131
  };
123
- const [detail, retryInSec, retryInMs, attempt, maxRetries, errClass, retryAtMs, errorStatus, elapsedMs, timeoutMs, providerCondition, providerConditionSource, sleptMs, waitSegment, seat] = [
124
- str('detail'), num('retryInSec'), num('retryInMs'), num('attempt'), num('maxRetries'), str('errClass'), num('retryAtMs'), num('errorStatus'), num('elapsedMs'), num('timeoutMs'), word('providerCondition'), word('providerConditionSource'), num('sleptMs'), word('waitSegment'), word('seat'),
132
+ const [detail, retryInSec, retryInMs, attempt, maxRetries, errClass, retryAtMs, errorStatus, elapsedMs, timeoutMs, providerCondition, providerConditionSource, sleptMs, waitSegment, seat, providerMessage, toolCallId] = [
133
+ str('detail'), num('retryInSec'), num('retryInMs'), num('attempt'), num('maxRetries'), str('errClass'), num('retryAtMs'), num('errorStatus'), num('elapsedMs'), num('timeoutMs'), word('providerCondition'), word('providerConditionSource'), num('sleptMs'), word('waitSegment'), word('seat'), word('providerMessage'), word('toolCallId'),
125
134
  ];
126
135
  const phase = str('phase');
127
136
  if (phase === undefined)
@@ -143,6 +152,8 @@ export function retryStatusFromArm(arm, nowMs) {
143
152
  ...(sleptMs !== undefined ? { sleptMs } : {}),
144
153
  ...(waitSegment !== undefined ? { waitSegment } : {}),
145
154
  ...(seat !== undefined ? { seat } : {}),
155
+ ...(providerMessage !== undefined ? { providerMessage } : {}),
156
+ ...(toolCallId !== undefined ? { toolCallId } : {}),
146
157
  }, nowMs);
147
158
  }
148
159
  const WAIT_SWITCH_FRACTION = 0.5;
@@ -43,6 +43,7 @@ export interface RunTerminalProviderRejectedDetail {
43
43
  providerConditionSource?: string;
44
44
  providerResetAtMs?: number;
45
45
  route?: RunTerminalRequestRoute;
46
+ providerMessage?: string;
46
47
  }
47
48
  export interface RunTerminalRequestRoute {
48
49
  credentialSource: string;
@@ -2,7 +2,7 @@ import { CORE_PROMPT_BLOCK_CAUSES } from './generated/engineFactTables.js';
2
2
  import { isSdkRunParked } from './terminalStatuses.js';
3
3
  import { runRowSentenceOf, terminalLayerOf } from './replayBody.js';
4
4
  import { readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
5
- import { washCredentials } from './displayUntrusted.js';
5
+ import { displayUntrusted, washCredentials } from './displayUntrusted.js';
6
6
  export const PROMPT_BLOCK_CAUSES = CORE_PROMPT_BLOCK_CAUSES;
7
7
  const _promptBlockTablePin = true;
8
8
  void _promptBlockTablePin;
@@ -213,6 +213,7 @@ function failureDetailOf(cause) {
213
213
  const code = str(own(v, 'code'));
214
214
  const providerCondition = optionalDetailString(v, 'providerCondition');
215
215
  const providerConditionSource = optionalDetailString(v, 'providerConditionSource');
216
+ const providerMessage = providerMessageOf(v);
216
217
  let providerResetAtMs;
217
218
  try {
218
219
  const r = ownData(v, 'providerResetAtMs');
@@ -229,6 +230,7 @@ function failureDetailOf(cause) {
229
230
  ...(providerCondition !== undefined ? { providerCondition } : {}),
230
231
  ...(providerConditionSource !== undefined ? { providerConditionSource } : {}),
231
232
  ...(providerResetAtMs !== undefined ? { providerResetAtMs } : {}),
233
+ ...(providerMessage !== undefined ? { providerMessage } : {}),
232
234
  ...(route !== undefined ? { route } : {}),
233
235
  };
234
236
  }
@@ -258,6 +260,18 @@ function optionalDetailString(d, key) {
258
260
  return undefined;
259
261
  }
260
262
  }
263
+ function providerMessageOf(d) {
264
+ try {
265
+ const raw = optionalDetailString(d, 'providerMessage');
266
+ if (raw === undefined)
267
+ return undefined;
268
+ const shown = displayUntrusted(raw);
269
+ return shown.length > 0 ? shown : undefined;
270
+ }
271
+ catch {
272
+ return undefined;
273
+ }
274
+ }
261
275
  const FINISH_REASON_UNKNOWN_DETAIL_KIND = 'finish_reason_unknown';
262
276
  function completedDetailOf(cause) {
263
277
  try {
@@ -2,4 +2,4 @@ export { AgentClient } from '@sema-agent/sdk';
2
2
  export { isApprovalRequestFrameV1, isApprovalRevokeFrameV1 } from '@sema-agent/sdk';
3
3
  export { pushSessionBundle, pullSessionBundle, importSessionBundle, APIError } from '@sema-agent/sdk';
4
4
  export { APPROVAL_DECIDE_GATE_KINDS, PLAN_REVIEW_GATE_KINDS } from '@sema-agent/sdk';
5
- export type { TaskRequest, SessionPermissionRules, SemaSettings, SkillSpec, AgentEvent, RunReceipt, CancelAck, RunRecord, ToolApprovalRespondAck, FleetTaskRow, FleetWorkflowRow, ApprovalCard, ApprovalRequestFrame, ApprovalRiskAxes, AskDecisionAck, AskDecisionBody, PolicyInfo, CcImportLayer, CcImportPrepareResult, CcImportSettingsLayer, CcImportSkippedRule, PersistedRule, RuleRevokeRequest, RuleRevokeResult, ApprovalDecideGateKind, PlanReviewGateKind, } from '@sema-agent/sdk';
5
+ export type { TaskRequest, SessionPermissionRules, SemaSettings, SkillSpec, AgentEvent, RunReceipt, CancelAck, RunRecord, FleetTaskRow, FleetWorkflowRow, ApprovalCard, ApprovalRequestFrame, ApprovalRiskAxes, AskDecisionAck, AskDecisionBody, PolicyInfo, CcImportLayer, CcImportPrepareResult, CcImportSettingsLayer, CcImportSkippedRule, PersistedRule, RuleRevokeRequest, RuleRevokeResult, ApprovalDecideGateKind, PlanReviewGateKind, } from '@sema-agent/sdk';
@@ -231,7 +231,7 @@ export type SeatStreamReading = {
231
231
  };
232
232
  export declare function seatStreamDeltaMessage(event: SeatStreamDeltaSource, ids: SeatStreamDeltaIds): SeatStreamEventMessage | undefined;
233
233
  export declare function readSeatStreamDelta(message: object): SeatStreamReading;
234
- export declare const SEAT_CAPABILITY_NAMES: readonly ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions", "notificationLevels", "modsView", "quickEntryShortcut", "hooksRoster", "mcpServers", "mcpServerEdit", "skills", "skillsEdit", "modelPool", "modelPoolEdit"];
234
+ export declare const SEAT_CAPABILITY_NAMES: readonly ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions", "notificationLevels", "modsView", "quickEntryShortcut", "hooksRoster", "mcpServers", "mcpServerEdit", "skills", "skillsEdit", "modelPool", "modelPoolEdit", "pickFile"];
235
235
  export type SeatCapabilityName = (typeof SEAT_CAPABILITY_NAMES)[number];
236
236
  export interface SeatCapabilitiesState {
237
237
  pickFolder?: boolean;
@@ -256,6 +256,7 @@ export interface SeatCapabilitiesState {
256
256
  skillsEdit?: boolean;
257
257
  modelPool?: boolean;
258
258
  modelPoolEdit?: boolean;
259
+ pickFile?: boolean;
259
260
  }
260
261
  export type SeatCapabilityReading = {
261
262
  readonly kind: "reported";
@@ -841,6 +842,9 @@ export type SessionHooksRosterLayer = {
841
842
  } | {
842
843
  readonly source: HookSettingsSource;
843
844
  readonly state: "trust_withheld";
845
+ } | {
846
+ readonly source: HookSettingsSource;
847
+ readonly state: "layer_degraded";
844
848
  };
845
849
  export interface SessionHooksRosterHttpRow {
846
850
  readonly source: HookSettingsSource;
@@ -1003,6 +1007,7 @@ export interface LocalSessionsApi {
1003
1007
  listModels(scope?: SeatResourceScope): Promise<LiveModelCatalog>;
1004
1008
  applyModelConfig(req: ApplyModelConfigRequest): Promise<ApplyModelConfigResult>;
1005
1009
  pickFolder(): Promise<string | null>;
1010
+ pickFile(): Promise<string | null>;
1006
1011
  listRecentFolders(): Promise<RecentFoldersResult>;
1007
1012
  noteRecentFolder(path: string): Promise<OkAck>;
1008
1013
  patchSession(req: SessionRowPatchRequest): Promise<LocalSessionRecord>;
@@ -1105,7 +1110,7 @@ export declare function isSendMessageAck(v: unknown): v is SendMessageAck;
1105
1110
  export declare function readToolPermissionSettledElsewhere(ack: object | null | undefined): ToolPermissionSettledElsewhere | undefined;
1106
1111
  export declare function readToolPermissionAckState(ack: ToolPermissionAck | null | undefined): ToolPermissionAckState | undefined;
1107
1112
  export declare const LOCAL_SESSIONS_SPEC: EipcServiceSpec;
1108
- export declare const SEAT_METHOD_NAMES: readonly ["start", "sendMessage", "interrupt", "stop", "respondToToolPermission", "cancelQueuedMessage", "reorderQueuedMessage", "promoteQueuedMessage", "setFocusedSession", "setModel", "getTranscript", "searchSessions", "uploadAttachment", "listModels", "applyModelConfig", "pickFolder", "listRecentFolders", "noteRecentFolder", "patchSession", "listDevices", "readSessionBinding", "rebindSession", "issueEnrollToken", "revokeDevice", "setEngineMode", "startCloudLogin", "cancelCloudLogin", "connectCloudEngine", "configureCloudEngine", "clearCloudEngine", "answerEngineSwap", "beginSelfUpgrade", "listOnboardProviders", "probeOnboardEntry", "applyOnboardEntry", "listModelPool", "editModelPool", "discoverModels", "readSessionMcpPanel", "listMcpToolToggles", "setMcpToolToggle", "setThinkingLatch", "getComputerUse", "setComputerUse", "getNotificationLevels", "setNotificationLevel", "getQuickEntryShortcut", "setQuickEntryShortcut", "claimSeatActions", "readSessionMods", "readSessionHooksRoster", "listMcpServers", "probeMcpServerEntry", "editMcpServer", "listSkills", "editSkills", "onEvent", "onToolPermissionRequest", "onSeatAction"];
1113
+ export declare const SEAT_METHOD_NAMES: readonly ["start", "sendMessage", "interrupt", "stop", "respondToToolPermission", "cancelQueuedMessage", "reorderQueuedMessage", "promoteQueuedMessage", "setFocusedSession", "setModel", "getTranscript", "searchSessions", "uploadAttachment", "listModels", "applyModelConfig", "pickFolder", "pickFile", "listRecentFolders", "noteRecentFolder", "patchSession", "listDevices", "readSessionBinding", "rebindSession", "issueEnrollToken", "revokeDevice", "setEngineMode", "startCloudLogin", "cancelCloudLogin", "connectCloudEngine", "configureCloudEngine", "clearCloudEngine", "answerEngineSwap", "beginSelfUpgrade", "listOnboardProviders", "probeOnboardEntry", "applyOnboardEntry", "listModelPool", "editModelPool", "discoverModels", "readSessionMcpPanel", "listMcpToolToggles", "setMcpToolToggle", "setThinkingLatch", "getComputerUse", "setComputerUse", "getNotificationLevels", "setNotificationLevel", "getQuickEntryShortcut", "setQuickEntryShortcut", "claimSeatActions", "readSessionMods", "readSessionHooksRoster", "listMcpServers", "probeMcpServerEntry", "editMcpServer", "listSkills", "editSkills", "onEvent", "onToolPermissionRequest", "onSeatAction"];
1109
1114
  export declare const SEAT_STORE_PROPS: readonly ["sessionsStateStore", "focusedSessionStateStore", "settingsStateStore", "seatCapabilitiesStateStore", "engineTargetStateStore"];
1110
1115
  export declare const SEAT_EVENT_METHOD_NAMES: readonly ["onEvent", "onToolPermissionRequest", "onSeatAction"];
1111
1116
  export declare const LOCAL_SESSION_EVENT_KEYS: readonly ["type", "sessionId", "message", "error", "errorCategory", "code", "session", "userMessageUuid", "requestId", "outcome", "parked", "chrome", "_sema_turnFailure", "subagentContent"];
@@ -1346,7 +1351,7 @@ export declare const SEAT_VALIDATOR_KEY_COVERAGE: {
1346
1351
  };
1347
1352
  readonly SeatCapabilitiesState: {
1348
1353
  readonly check: (v: unknown) => SeatValidation;
1349
- readonly validated: readonly ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions", "notificationLevels", "modsView", "quickEntryShortcut", "hooksRoster", "mcpServers", "mcpServerEdit", "skills", "skillsEdit", "modelPool", "modelPoolEdit"];
1354
+ readonly validated: readonly ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions", "notificationLevels", "modsView", "quickEntryShortcut", "hooksRoster", "mcpServers", "mcpServerEdit", "skills", "skillsEdit", "modelPool", "modelPoolEdit", "pickFile"];
1350
1355
  readonly unchecked: readonly [];
1351
1356
  };
1352
1357
  readonly RecentFoldersResult: {
@@ -1393,6 +1398,10 @@ export declare const SEAT_VALIDATOR_COVERAGE_EXEMPT: readonly [...{
1393
1398
  readonly label: "PickFolderResult";
1394
1399
  readonly check: (v: unknown) => SeatValidation;
1395
1400
  readonly why: "载荷是**串或 null**(选中的路径 / 用户取消,CC-469),没有键面 ⇒ `keyof` 覆盖表在它身上无从谈起。判别力由对应的座位契约测试套承担:认 null 与非空串、拒空串 / 数 / undefined / 对象 / 布尔五形。";
1401
+ }, {
1402
+ readonly label: "PickFileResult";
1403
+ readonly check: (v: unknown) => SeatValidation;
1404
+ readonly why: "载荷是**串或 null**(选中的文件路径 / 用户取消,CC-575),没有键面 ⇒ `keyof` 覆盖表在它身上无从谈起;与 `PickFolderResult` 同形、路径判据同一只。判别力由座位契约测试套承担(run-seat-wave2-test.mjs ST7):认 null 与非空串(原文字节)、拒空串 / 数 / 零 / undefined / 对象 / 布尔 / 数组,拒句点名 pickFile,且与 pickFolder 的回执出站门在同一批输入上放行 / 拒绝一致。";
1396
1405
  }, {
1397
1406
  readonly label: "BooleanAck";
1398
1407
  readonly check: (v: unknown) => SeatValidation;
@@ -4,13 +4,14 @@ import { liveDefaultModelCopy, liveModelRowCopy } from "./model/liveCatalogShape
4
4
  import { REWIND_MODES } from "./rewindWireCaps.js";
5
5
  import { SETTINGS_MODEL_API_WORDS } from "./generated/settingsSchemaTables.js";
6
6
  import { PROBE_VERDICTS } from "./modelCapabilityProbe.js";
7
- import { MODEL_POOL_CHANNEL_SOURCES, MODEL_POOL_COMPLETENESS, MODEL_POOL_MAX_BATCH, MODEL_POOL_PROBE_STATES } from "./localConfig/modelPoolWords.js";
7
+ import { MODEL_POOL_CHANNEL_SOURCES, MODEL_POOL_COMPLETENESS, MODEL_POOL_MAX_BATCH, MODEL_POOL_PROBE_STATES, MODEL_POOL_READINGS } from "./localConfig/modelPoolWords.js";
8
8
  import { LOCAL_CONFIG_REFUSALS } from "./localConfig/kernel.js";
9
9
  import { localConfigDisclosureShapeOf, localConfigReceiptShapeOf, localConfigUnavailableShapeOf } from "./localConfig/receiptShape.js";
10
10
  import { TIER_ORDER } from "./model/tierVocabulary.js";
11
11
  import { guardedRead, ownDataField, ownDataRefusalKeyOf, ownSendableField, readOwnDataValue } from "./ownKey.js";
12
12
  import { isPlainRecord as isJsonPlainRecord } from "./jsonFaithful.js";
13
13
  import { displayUntrustedMarks, quoteUntrustedForSentence } from "./displayUntrusted.js";
14
+ import { carriesNoCredentialSlots, tupleOriginUrlOf } from "./engineAddress.js";
14
15
  import { MCP_LIVENESS_STATES } from "./mcpLiveness.js";
15
16
  import { checkMcpServerReportView, checkMcpServerEditOutcomeView, checkMcpServerProbeView } from "./localConfig/mcp/views.js";
16
17
  import { THINKING_LATCH_EVENTS, THINKING_LATCH_ROW_WORDS } from "./thinkingLatchWords.js";
@@ -413,7 +414,7 @@ export function readSeatStreamDelta(message) {
413
414
  return Object.freeze({ kind: "malformed" });
414
415
  }
415
416
  }
416
- export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions", "notificationLevels", "modsView", "quickEntryShortcut", "hooksRoster", "mcpServers", "mcpServerEdit", "skills", "skillsEdit", "modelPool", "modelPoolEdit"]);
417
+ export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions", "notificationLevels", "modsView", "quickEntryShortcut", "hooksRoster", "mcpServers", "mcpServerEdit", "skills", "skillsEdit", "modelPool", "modelPoolEdit", "pickFile"]);
417
418
  const notReported = () => Object.freeze({ kind: "not_reported" });
418
419
  const malformedReading = () => Object.freeze({ kind: "malformed" });
419
420
  const reported = (available) => Object.freeze({ kind: "reported", available });
@@ -503,6 +504,7 @@ const SEAT_CAPABILITY_PHRASES = Object.freeze({
503
504
  skillsEdit: Object.freeze({ action: "Changing skills", ability: "change skills", support: "skill editing support" }),
504
505
  modelPool: Object.freeze({ action: "Showing your models", ability: "show your models", support: "model list support" }),
505
506
  modelPoolEdit: Object.freeze({ action: "Editing your models", ability: "edit your models", support: "model editing support" }),
507
+ pickFile: Object.freeze({ action: "Adding a file", ability: "show a file picker", support: "file picker support" }),
506
508
  });
507
509
  export function seatCapabilityUnavailableDetail(name, reading) {
508
510
  const phrase = Object.hasOwn(SEAT_CAPABILITY_PHRASES, name)
@@ -748,14 +750,8 @@ const R_LOGIN_FAILURE = oneOfRule("login failure", CLOUD_LOGIN_FAILURES);
748
750
  const R_DISPLAY_URL = ruleOf("display url", (v) => {
749
751
  if (typeof v !== "string" || v.length === 0)
750
752
  return false;
751
- let u;
752
- try {
753
- u = new URL(v);
754
- }
755
- catch {
756
- return false;
757
- }
758
- return (u.protocol === "https:" || u.protocol === "http:") && u.username === "" && u.password === "" && u.search === "" && u.hash === "";
753
+ const u = tupleOriginUrlOf(v);
754
+ return u !== undefined && (u.protocol === "https:" || u.protocol === "http:") && carriesNoCredentialSlots(v);
759
755
  });
760
756
  const R_VERIFICATION_URI_COMPLETE = ruleOf("verification uri", (v) => {
761
757
  if (typeof v !== "string" || v.length === 0)
@@ -1156,6 +1152,8 @@ const R_POOL_VIEW = shapeRule("pool view", {
1156
1152
  legacyTierSettings: reqF(R_BOOL),
1157
1153
  orphanKeySlots: reqF(R_INT0),
1158
1154
  envModels: reqF(arrayRule(R_NONEMPTY)),
1155
+ effectiveEnv: optF(oneOfRule("effectiveEnv", MODEL_POOL_READINGS)),
1156
+ userSettings: optF(oneOfRule("userSettings", MODEL_POOL_READINGS)),
1159
1157
  providers: reqF(arrayRule(shapeRule("pool provider", {
1160
1158
  id: reqF(R_NONEMPTY),
1161
1159
  name: reqF(R_NONEMPTY),
@@ -1315,6 +1313,7 @@ const HOOKS_ROSTER_LAYER = armsRule("hooks roster layer", "state", {
1315
1313
  "loaded-partial": { source: reqF(R_HOOK_SOURCE), codes: reqF(arrayRule(oneOfRule("hooks drop code", SETTINGS_HOOKS_DROPPED_PIECE_CODES), true)) },
1316
1314
  rejected: { source: reqF(R_HOOK_SOURCE), codes: reqF(arrayRule(oneOfRule("hooks rejection code", SETTINGS_HOOKS_REJECTION_CODES), true)) },
1317
1315
  trust_withheld: { source: reqF(R_HOOK_SOURCE) },
1316
+ layer_degraded: { source: reqF(R_HOOK_SOURCE) },
1318
1317
  });
1319
1318
  const HOOKS_ROSTER_HTTP_ROW = shapeRule("hooks roster http row", {
1320
1319
  source: reqF(R_HOOK_SOURCE),
@@ -1957,6 +1956,8 @@ const RETRY_COMMON_SPEC = {
1957
1956
  sleptMs: optF(R_NUM0),
1958
1957
  waitSegment: optF(R_NONEMPTY),
1959
1958
  seat: optF(R_NONEMPTY),
1959
+ providerMessage: optF(R_NONEMPTY),
1960
+ toolCallId: optF(R_NONEMPTY),
1960
1961
  };
1961
1962
  const RETRY_STATUS = armsRule("retry status", "kind", {
1962
1963
  stalled: { ...RETRY_COMMON_SPEC, detail: optF(R_STR) },
@@ -2519,9 +2520,11 @@ const checkSettingsState = seatCheck((v) => {
2519
2520
  return bad("dataRoot must be a string when present", "dataRoot");
2520
2521
  return true;
2521
2522
  });
2522
- const checkPickFolderResult = (v) => v === null || isFolderPath(v)
2523
+ const pickedPathResultCheck = (verb) => (v) => v === null || isFolderPath(v)
2523
2524
  ? true
2524
- : bad("pickFolder result must be null (cancelled) or a non-empty path string");
2525
+ : bad(`${verb} result must be null (cancelled) or a non-empty path string`);
2526
+ const checkPickFolderResult = pickedPathResultCheck("pickFolder");
2527
+ const checkPickFileResult = pickedPathResultCheck("pickFile");
2525
2528
  const checkRecentFolderRow = seatCheck((v) => {
2526
2529
  if (!isPlainRecord(v))
2527
2530
  return bad("recent folder row is not a plain object");
@@ -2579,6 +2582,7 @@ export const LOCAL_SESSIONS_SPEC = {
2579
2582
  listModels: { kind: "invoke", check: checkLiveModelCatalog },
2580
2583
  applyModelConfig: { kind: "invoke", check: checkApplyModelConfigResult },
2581
2584
  pickFolder: { kind: "invoke", check: checkPickFolderResult },
2585
+ pickFile: { kind: "invoke", check: checkPickFileResult },
2582
2586
  listRecentFolders: { kind: "invoke", check: checkRecentFoldersResult },
2583
2587
  noteRecentFolder: { kind: "invoke", check: checkOkAck }, patchSession: { kind: "invoke", check: checkLocalSessionRecord },
2584
2588
  listDevices: { kind: "invoke", check: checkDeviceListOutcome },
@@ -2647,6 +2651,7 @@ export const SEAT_METHOD_NAMES = [
2647
2651
  "listModels",
2648
2652
  "applyModelConfig",
2649
2653
  "pickFolder",
2654
+ "pickFile",
2650
2655
  "listRecentFolders",
2651
2656
  "noteRecentFolder", "patchSession",
2652
2657
  "listDevices",
@@ -3041,7 +3046,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
3041
3046
  },
3042
3047
  SeatCapabilitiesState: {
3043
3048
  check: checkSeatCapabilitiesState,
3044
- validated: ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions", "notificationLevels", "modsView", "quickEntryShortcut", "hooksRoster", "mcpServers", "mcpServerEdit", "skills", "skillsEdit", "modelPool", "modelPoolEdit"],
3049
+ validated: ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions", "notificationLevels", "modsView", "quickEntryShortcut", "hooksRoster", "mcpServers", "mcpServerEdit", "skills", "skillsEdit", "modelPool", "modelPoolEdit", "pickFile"],
3045
3050
  unchecked: [],
3046
3051
  },
3047
3052
  RecentFoldersResult: {
@@ -3136,6 +3141,11 @@ export const SEAT_VALIDATOR_COVERAGE_EXEMPT = [
3136
3141
  check: checkPickFolderResult,
3137
3142
  why: "载荷是**串或 null**(选中的路径 / 用户取消,CC-469),没有键面 ⇒ `keyof` 覆盖表在它身上无从谈起。判别力由对应的座位契约测试套承担:认 null 与非空串、拒空串 / 数 / undefined / 对象 / 布尔五形。",
3138
3143
  },
3144
+ {
3145
+ label: "PickFileResult",
3146
+ check: checkPickFileResult,
3147
+ why: "载荷是**串或 null**(选中的文件路径 / 用户取消,CC-575),没有键面 ⇒ `keyof` 覆盖表在它身上无从谈起;与 `PickFolderResult` 同形、路径判据同一只。判别力由座位契约测试套承担(run-seat-wave2-test.mjs ST7):认 null 与非空串(原文字节)、拒空串 / 数 / 零 / undefined / 对象 / 布尔 / 数组,拒句点名 pickFile,且与 pickFolder 的回执出站门在同一批输入上放行 / 拒绝一致。",
3148
+ },
3139
3149
  {
3140
3150
  label: "BooleanAck",
3141
3151
  check: checkBooleanAck,
@@ -3177,6 +3187,7 @@ const _seatContractPins = [
3177
3187
  true, true, true, true,
3178
3188
  true, true, true,
3179
3189
  true, true, true, true,
3190
+ true, true,
3180
3191
  true,
3181
3192
  true, true, true,
3182
3193
  true, true, true, true, true, true,
@@ -52,7 +52,7 @@ function declaredBinding(center, scope, name, viaCenter) {
52
52
  }
53
53
  function addressBinding(raw) {
54
54
  const u = tupleOriginUrlOf(raw);
55
- if (u === undefined || !carriesNoCredentialSlots(u))
55
+ if (u === undefined || !carriesNoCredentialSlots(raw))
56
56
  return fail('address-invalid');
57
57
  const address = engineNamespaceKeyFor(raw);
58
58
  return Object.freeze({
@@ -1,4 +1,4 @@
1
- import { HOOK_ENTRY_TYPE_WORDS, PLUGIN_HOOK_DISPOSITIONS, PLUGIN_HOOK_EXCLUSION_REASONS, PLUGIN_HOOK_REASONS, SETTINGS_HOOK_DROP_REASONS, hooksWirePlanShapeOf, isEngineFiredHookEvent, } from './pluginHooksWire.js';
1
+ import { HOOK_ENTRY_TYPE_WORDS, PLUGIN_HOOK_DISPOSITIONS, PLUGIN_HOOK_EXCLUSION_REASONS, PLUGIN_HOOK_REASONS, SETTINGS_HOOK_DROP_REASONS, engineLaneOf, hooksWirePlanShapeOf, planSettingsContractOf, } from './pluginHooksWire.js';
2
2
  import { HTTP_POLICY_DROP_REASONS } from './httpHookPolicy.js';
3
3
  import { HOOK_SETTINGS_SOURCE_TEXT } from './settingsHooksSalvage.js';
4
4
  import { SETTINGS_HOOK_EVENTS, SETTINGS_HOOKS_DROPPED_PIECE_CODES, SETTINGS_HOOKS_REJECTION_CODES } from './generated/settingsSchemaFns.js';
@@ -37,10 +37,10 @@ function coordOf(row) {
37
37
  }
38
38
  return { source, event, groupIndex, hookIndex, ...typed };
39
39
  }
40
- function droppedStatusOf(event, notRun) {
40
+ function droppedStatusOf(event, notRun, engineEvent) {
41
41
  if (notRun)
42
42
  return 'not_run';
43
- return isEngineFiredHookEvent(event) ? 'shell' : undefined;
43
+ return engineEvent(event) ? 'shell' : undefined;
44
44
  }
45
45
  const rosterUnreadable = () => Object.freeze({ kind: 'unreadable', why: renderMessage(msg('config.hooks.roster.unreadable')) });
46
46
  export function sessionHooksRosterOf(plan) {
@@ -61,11 +61,12 @@ export function sessionHooksRosterOf(plan) {
61
61
  const reason = field(r, 'reason');
62
62
  addRow(at !== undefined && inWords(PLUGIN_HOOK_DISPOSITIONS, disposition) && inWords(PLUGIN_HOOK_REASONS, reason) ? { ...at, status: disposition, reason } : undefined);
63
63
  }
64
+ const engineEvent = engineLaneOf(planSettingsContractOf(plan));
64
65
  for (const r of ownRowsOf(plan, 'settingsDropped') ?? []) {
65
66
  const at = coordOf(r);
66
67
  const reason = field(r, 'reason');
67
68
  const notRun = field(r, 'notRun');
68
- const status = at !== undefined && typeof notRun === 'boolean' ? droppedStatusOf(at.event, notRun) : undefined;
69
+ const status = at !== undefined && typeof notRun === 'boolean' ? droppedStatusOf(at.event, notRun, engineEvent) : undefined;
69
70
  addRow(at !== undefined && status !== undefined && inWords(SETTINGS_HOOK_DROP_REASONS, reason) ? { ...at, status, reason } : undefined);
70
71
  }
71
72
  for (const r of ownRowsOf(plan, 'settingsExcluded') ?? []) {
@@ -83,8 +84,9 @@ export function sessionHooksRosterOf(plan) {
83
84
  }
84
85
  for (const r of ownRowsOf(plan, 'settingsWithheld') ?? []) {
85
86
  const source = field(r, 'source');
86
- if (isSource(source) && field(r, 'cause') === 'trust_withheld')
87
- appendOwnElement(layers, Object.freeze({ source, state: 'trust_withheld' }));
87
+ const cause = field(r, 'cause');
88
+ if (isSource(source) && (cause === 'trust_withheld' || cause === 'layer_degraded'))
89
+ appendOwnElement(layers, Object.freeze({ source, state: cause }));
88
90
  else
89
91
  unlisted += 1;
90
92
  }
@@ -1,4 +1,3 @@
1
- export declare function isDotSegment(seg: string): boolean;
2
1
  export declare function isSessionIdPathSegment(id: unknown): id is string;
3
2
  export type SessionIdRefusalWhy = 'not_string' | 'bad_shape' | 'bad_version' | 'bad_variant';
4
3
  export interface SessionIdRefusal {
@@ -1,6 +1,4 @@
1
- export function isDotSegment(seg) {
2
- return seg === '.' || seg === '..';
3
- }
1
+ import { isDotSegment } from './pathShape.js';
4
2
  export function isSessionIdPathSegment(id) {
5
3
  if (typeof id !== 'string' || id === '' || isDotSegment(id))
6
4
  return false;
@@ -2,7 +2,7 @@ import { isLoopbackWireUrl, resolveWireAuth } from './engineWireSdk.js';
2
2
  import { INJECTED_WIRE_SETTLE_MS, connectionLostDetail, noAnswerDetailFrom, noAnswerKindOf, provablyNotSent, settleInjected } from './engineWireFor.js';
3
3
  import { memoryEraseReplayPosture, readMemoryEraseReceipt } from './memoryEntriesWire.js';
4
4
  import { normalizeWirePrincipal } from './principalWire.js';
5
- import { MEMORY_CONTROL_PLANE_CORRUPT } from './engineErrorCodes.js';
5
+ import { MEMORY_CONTROL_PLANE_CORRUPT, ROUTE_NOT_FOUND } from './engineErrorCodes.js';
6
6
  import { isSessionIdPathSegment } from './sessionIdSegment.js';
7
7
  import { msg, renderMessage } from './i18n/translate.js';
8
8
  const PRINCIPAL_HEADER = 'x-agent-principal';
@@ -340,7 +340,7 @@ function bandOfCode(code) {
340
340
  return { refused: 'memory_engine_absent' };
341
341
  case 'not_found.session':
342
342
  return { refused: 'session_not_found' };
343
- case 'not_found.route':
343
+ case ROUTE_NOT_FOUND:
344
344
  return { refused: 'route_absent' };
345
345
  case 'request.path_malformed':
346
346
  case 'request.body_shape':
@@ -2,6 +2,7 @@ import { isSessionIdPathSegment } from './sessionIdSegment.js';
2
2
  import { readThrownSlot, THROWN_SLOT_UNREADABLE } from './wireFailureShape.js';
3
3
  import { isUiLanguage } from './env/uiLanguage.js';
4
4
  import { msg, renderLanguageOf, renderMessage } from './i18n/translate.js';
5
+ import { ROUTE_NOT_FOUND } from './engineErrorCodes.js';
5
6
  export const MEMORY_SYNC_WAY_OUT_DELETE_CURSOR = 'delete_cursor';
6
7
  const MEMORY_SYNC_PARKED_READ_MAX = 256;
7
8
  export function classifyMemoryStatusFailure(e) {
@@ -16,7 +17,7 @@ export function classifyMemoryStatusFailure(e) {
16
17
  return { kind: 'unsupported', reason: 'capability' };
17
18
  if (code.startsWith('feature.'))
18
19
  return { kind: 'unsupported', reason: 'feature' };
19
- if (code === 'not_found.route')
20
+ if (code === ROUTE_NOT_FOUND)
20
21
  return { kind: 'unsupported', reason: 'route' };
21
22
  if (code === 'not_found.session')
22
23
  return { kind: 'not_found' };
@@ -0,0 +1,29 @@
1
+ import type { UiLanguage } from './env/uiLanguage.js';
2
+ export interface ActiveRunPendingGate {
3
+ readonly kind: string | null;
4
+ readonly decidePath: string | null;
5
+ readonly governanceForced?: true;
6
+ readonly checkpointId?: string;
7
+ }
8
+ export type SessionOccupant = 'running' | 'parked' | 'unreadable' | 'released';
9
+ export declare function sessionOccupantOf(activeTaskId: string | null | undefined, activeTaskStatus: string | undefined, stale: boolean): SessionOccupant;
10
+ export interface ActiveRunBusySignal {
11
+ readonly activeTaskId: string | null;
12
+ readonly activeTaskStatus: string | null;
13
+ readonly pendingGate: ActiveRunPendingGate | null;
14
+ readonly occupancy?: SessionOccupant;
15
+ readonly msSinceLastActivity?: number;
16
+ }
17
+ export type BusyRowFace = 'interactive' | 'scripted';
18
+ export interface BusyRowSlots {
19
+ readonly endRun?: string;
20
+ readonly freshSession?: string;
21
+ }
22
+ export declare function gateKindPhraseOf(kind: string | null | undefined, lang?: UiLanguage): string;
23
+ export declare function endRunClauseOf(copy: BusyRowSlots | undefined, taskId: string | null | undefined, lang?: UiLanguage, face?: BusyRowFace): string;
24
+ export declare function governanceOriginClauseOf(signal: {
25
+ readonly pendingGate?: {
26
+ readonly governanceForced?: true;
27
+ } | null;
28
+ } | null | undefined, lang?: UiLanguage): string;
29
+ export declare function sessionBusyRowOf(signal: ActiveRunBusySignal, face: BusyRowFace, copy?: BusyRowSlots, lang?: UiLanguage): string;
@@ -0,0 +1,78 @@
1
+ import { displayUntrusted } from './displayUntrusted.js';
2
+ import { guardedRead } from './ownKey.js';
3
+ import { msg, renderMessage } from './i18n/translate.js';
4
+ import { isSdkRunParked } from './terminalStatuses.js';
5
+ export function sessionOccupantOf(activeTaskId, activeTaskStatus, stale) {
6
+ if (activeTaskId === null)
7
+ return 'released';
8
+ if (typeof activeTaskId !== 'string' || activeTaskId.length === 0)
9
+ return 'unreadable';
10
+ if (stale === true)
11
+ return 'unreadable';
12
+ if (activeTaskStatus === 'running')
13
+ return 'running';
14
+ return isSdkRunParked(activeTaskStatus) ? 'parked' : 'unreadable';
15
+ }
16
+ const sayOf = (lang, key, params) => renderMessage(msg(key, params), lang);
17
+ const BUSY_WORD_SHOWN_MAX = 120;
18
+ function shownOf(raw, max) {
19
+ return typeof raw === 'string' ? displayUntrusted(raw, max === undefined ? {} : { max }) : '';
20
+ }
21
+ export function gateKindPhraseOf(kind, lang) {
22
+ return kind ? sayOf(lang, 'session.selfHeal.gate.kind', { kind }) : sayOf(lang, 'session.selfHeal.gate.generic');
23
+ }
24
+ export function endRunClauseOf(copy, taskId, lang, face = 'scripted') {
25
+ let host;
26
+ try {
27
+ host = copy?.endRun;
28
+ }
29
+ catch {
30
+ host = undefined;
31
+ }
32
+ const phrase = typeof host === 'string' ? host.trim().replace(/[\s.;。;!!??]+$/u, '') : '';
33
+ if (/[\p{L}\p{N}]/u.test(phrase))
34
+ return phrase;
35
+ if (face === 'interactive') {
36
+ return taskId ? sayOf(lang, 'session.selfHeal.endRun.engineInteractive', { taskId }) : sayOf(lang, 'session.selfHeal.endRun.engineInteractive.noId');
37
+ }
38
+ return sayOf(lang, 'session.selfHeal.endRun.engine', { cancelPath: `POST /v1/runs/${taskId ? taskId : '<id>'}/cancel` });
39
+ }
40
+ export function governanceOriginClauseOf(signal, lang) {
41
+ return signal?.pendingGate?.governanceForced === true ? sayOf(lang, 'session.selfHeal.governanceOrigin') : '';
42
+ }
43
+ export function sessionBusyRowOf(signal, face, copy, lang) {
44
+ const raw = guardedRead(() => signal.occupancy);
45
+ const occupancy = raw === 'running' || raw === 'parked' || raw === 'released' ? raw : 'unreadable';
46
+ if (occupancy === 'released')
47
+ return sayOf(lang, 'session.busy.released');
48
+ const activeTaskId = signal.activeTaskId;
49
+ const handle = activeTaskId ? msg('session.selfHeal.handle.run', { taskId: activeTaskId }) : '';
50
+ const endRun = endRunClauseOf(copy, activeTaskId, lang, face);
51
+ let hostFresh;
52
+ try {
53
+ hostFresh = copy?.freshSession;
54
+ }
55
+ catch {
56
+ hostFresh = undefined;
57
+ }
58
+ const freshSession = typeof hostFresh === 'string' ? hostFresh : sayOf(lang, face === 'interactive' ? 'session.busy.freshSession.interactive' : 'session.selfHeal.freshSession.default');
59
+ if (occupancy === 'running')
60
+ return sayOf(lang, 'session.busy.running', { handle, endRun, freshSession });
61
+ if (occupancy === 'parked') {
62
+ const decidePath = signal.pendingGate?.decidePath ?? null;
63
+ if (face === 'scripted' && decidePath) {
64
+ const status = shownOf(signal.activeTaskStatus, BUSY_WORD_SHOWN_MAX);
65
+ return sayOf(lang, 'session.busy.parkedDecide', {
66
+ handle,
67
+ status: status !== '' ? msg('session.selfHeal.headless.status', { status }) : '',
68
+ gate: gateKindPhraseOf(shownOf(signal.pendingGate?.kind, BUSY_WORD_SHOWN_MAX), lang),
69
+ decidePath: shownOf(decidePath),
70
+ endRun,
71
+ freshSession,
72
+ governance: governanceOriginClauseOf(signal, lang),
73
+ });
74
+ }
75
+ return sayOf(lang, 'session.busy.parked', { handle, endRun, freshSession });
76
+ }
77
+ return sayOf(lang, 'session.busy.unreadable', { handle, endRun, freshSession });
78
+ }
@@ -1,5 +1,6 @@
1
1
  import type { WireHooksConfig } from './finalVerifyWire.js';
2
2
  import type { SettingsDocument } from './host.js';
3
+ import type { HooksEntryKeyReader } from './hooksReaderGenerations.js';
3
4
  import type { HookSettingsSource } from './pluginHooksWire.js';
4
5
  export type HooksSalvageOutcome = 'loaded' | 'loaded-partial' | 'rejected';
5
6
  export type HooksSalvageDropCode = 'hooks-not-object' | 'unknown-event' | 'event-not-array' | 'matcher-invalid' | 'entry-invalid';
@@ -43,7 +44,9 @@ export declare function salvageSettingsHooksEntries(doc: SettingsDocument | null
43
44
  export declare function hooksGroupUnreadKeys(event: string, group: object): readonly string[] | undefined;
44
45
  export type HooksGroupAuthoredSource = 'absent' | 'present' | 'unreadable';
45
46
  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 hooksEntryContractView(event: string, entry: object): object | undefined;
48
+ export declare function hooksEntryUnreadKeys(event: string, entry: object, reader: HooksEntryKeyReader): readonly string[] | undefined;
49
+ export declare function isGuardHookEvent(event: string): boolean;
47
50
  export declare function hooksKeyCoordinateText(path: readonly (string | number)[]): string;
48
51
  export declare const HOOK_SETTINGS_SOURCE_TEXT: Readonly<Record<HookSettingsSource, string>>;
49
52
  export declare function layerNotAppliedRefusesTurn(source: HookSettingsSource): boolean;