@sema-agent/client-core 0.93.0 → 0.94.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 (156) hide show
  1. package/CHANGELOG.md +261 -0
  2. package/README.md +31 -18
  3. package/dist/adapt/arms.js +8 -5
  4. package/dist/adapter/downstream/terminalToSdkResult.js +2 -3
  5. package/dist/agentSession/engineSessionBackgroundStop.js +2 -1
  6. package/dist/agentsWireCaps.d.ts +15 -0
  7. package/dist/agentsWireCaps.js +111 -1
  8. package/dist/approvalReachWire.d.ts +18 -0
  9. package/dist/approvalReachWire.js +58 -0
  10. package/dist/approvalsStreamLiveCapability.js +16 -11
  11. package/dist/callerCwdCapability.d.ts +16 -0
  12. package/dist/callerCwdCapability.js +47 -0
  13. package/dist/controlRouter.js +3 -10
  14. package/dist/coreValuePorts.d.ts +64 -1
  15. package/dist/coreValuePorts.js +30 -0
  16. package/dist/detachWire.d.ts +1 -4
  17. package/dist/detachWire.js +1 -1
  18. package/dist/deviceExecutorManagementCapability.js +39 -34
  19. package/dist/deviceFlowPolling.d.ts +5 -0
  20. package/dist/deviceFlowPolling.js +28 -0
  21. package/dist/displayUntrusted.js +652 -21
  22. package/dist/engineErrorCodes.d.ts +5 -1
  23. package/dist/engineErrorCodes.js +9 -12
  24. package/dist/engineNoticeCodes.d.ts +22 -2
  25. package/dist/engineNoticeCodes.js +73 -6
  26. package/dist/engineRefusedToolName.d.ts +1 -0
  27. package/dist/engineRefusedToolName.js +8 -0
  28. package/dist/executionLaneCapability.js +14 -9
  29. package/dist/fileHistoryCaptureCapability.js +14 -9
  30. package/dist/fileHistoryLegNotice.d.ts +11 -0
  31. package/dist/fileHistoryLegNotice.js +50 -13
  32. package/dist/fleet/fleetLedger.js +5 -0
  33. package/dist/gateOutcome.d.ts +2 -1
  34. package/dist/gateOutcome.js +3 -0
  35. package/dist/gateVocabulary.js +1 -1
  36. package/dist/generated/engineAskFaceTables.d.ts +3 -0
  37. package/dist/generated/engineAskFaceTables.js +12 -0
  38. package/dist/generated/engineFactTables.d.ts +4 -2
  39. package/dist/generated/engineFactTables.js +13 -0
  40. package/dist/generated/engineNoticeTables.d.ts +5 -0
  41. package/dist/generated/engineNoticeTables.js +7 -0
  42. package/dist/generated/sdkFactTables.d.ts +3 -0
  43. package/dist/generated/sdkFactTables.js +17 -0
  44. package/dist/generated/settingsSchemaTables.d.ts +3 -0
  45. package/dist/generated/settingsSchemaTables.js +3 -0
  46. package/dist/headlessPermissionModeWire.d.ts +2 -2
  47. package/dist/headlessPermissionModeWire.js +11 -21
  48. package/dist/hitl/approvalHolds.d.ts +36 -0
  49. package/dist/hitl/approvalHolds.js +89 -0
  50. package/dist/hitl/approvalOutcomeNote.js +2 -1
  51. package/dist/hitl/approvalResolution.d.ts +3 -2
  52. package/dist/hitl/approvalResolution.js +21 -0
  53. package/dist/hitl/approvalsFeed.js +5 -0
  54. package/dist/hitl/askGateWire.js +3 -0
  55. package/dist/hitl/automaticAnswerVerdict.d.ts +8 -2
  56. package/dist/hitl/automaticAnswerVerdict.js +69 -21
  57. package/dist/hitl/decisionRefusal.d.ts +19 -0
  58. package/dist/hitl/decisionRefusal.js +63 -0
  59. package/dist/hitl/frameRouter.d.ts +10 -0
  60. package/dist/hitl/frameRouter.js +59 -3
  61. package/dist/hitl/gateLedger.d.ts +3 -0
  62. package/dist/hitl/gateLedger.js +17 -0
  63. package/dist/hitl/hitlBridge.d.ts +2 -2
  64. package/dist/hitl/hitlBridge.js +8 -10
  65. package/dist/hitl/hitlHostSurface.d.ts +6 -0
  66. package/dist/hitl/hitlHostSurface.js +25 -4
  67. package/dist/hitl/localAllowRule.js +2 -1
  68. package/dist/hitl/noAllowCause.d.ts +9 -0
  69. package/dist/hitl/noAllowCause.js +26 -0
  70. package/dist/hitl/parkResolver.js +6 -3
  71. package/dist/hitl/parkRowBirthWait.js +2 -1
  72. package/dist/hitl/persistedRulesWire.d.ts +6 -1
  73. package/dist/hitl/persistedRulesWire.js +12 -4
  74. package/dist/hitl/planReviewWire.d.ts +0 -1
  75. package/dist/hitl/planReviewWire.js +30 -9
  76. package/dist/hitl/sessionPolicyDeliverable.d.ts +1 -1
  77. package/dist/hitl/sessionPolicyDeliverable.js +3 -8
  78. package/dist/hitl/sessionPolicyWire.js +1 -1
  79. package/dist/hitl/toolApprovalWire.d.ts +37 -2
  80. package/dist/hitl/toolApprovalWire.js +392 -13
  81. package/dist/humanTurnRead.d.ts +15 -1
  82. package/dist/humanTurnRead.js +28 -2
  83. package/dist/index.d.ts +18 -6
  84. package/dist/index.js +14 -5
  85. package/dist/limitsWire.d.ts +0 -1
  86. package/dist/limitsWire.js +2 -10
  87. package/dist/liveModelCatalog.d.ts +14 -0
  88. package/dist/liveModelCatalog.js +61 -0
  89. package/dist/mcpProbeCapability.js +14 -9
  90. package/dist/mcpReconnect.js +13 -8
  91. package/dist/memoryComplianceCapability.js +15 -10
  92. package/dist/memoryOriginCapability.js +15 -10
  93. package/dist/modelIdentityResolvability.d.ts +4 -2
  94. package/dist/modelIdentityResolvability.js +31 -4
  95. package/dist/outputStyleSeatCapability.d.ts +16 -0
  96. package/dist/outputStyleSeatCapability.js +47 -0
  97. package/dist/ownKey.d.ts +1 -0
  98. package/dist/ownKey.js +10 -0
  99. package/dist/peerLaneCapability.js +16 -11
  100. package/dist/permissionRuleIssue.js +1 -1
  101. package/dist/permissionRulesWriteCapability.js +16 -11
  102. package/dist/permissionsAllowGrantCapability.d.ts +2 -0
  103. package/dist/permissionsAllowGrantCapability.js +38 -16
  104. package/dist/permissionsDeclaration.d.ts +10 -1
  105. package/dist/permissionsDeclaration.js +97 -15
  106. package/dist/protocolSegment.d.ts +1 -0
  107. package/dist/protocolSegment.js +13 -1
  108. package/dist/request/taskRequest.d.ts +11 -3
  109. package/dist/request/taskRequest.js +13 -1
  110. package/dist/resultFrameKeys.d.ts +4 -0
  111. package/dist/resultFrameKeys.js +13 -0
  112. package/dist/resumeRefusalCopy.js +6 -16
  113. package/dist/retryStatus.js +6 -4
  114. package/dist/rewindArchiveCapability.js +13 -8
  115. package/dist/{hitl/rosterMountedNames.d.ts → rosterMountedNames.d.ts} +1 -1
  116. package/dist/runCancelContext.js +2 -1
  117. package/dist/sealedKeyCapability.js +19 -14
  118. package/dist/seatContract.d.ts +33 -5
  119. package/dist/seatContract.js +143 -2
  120. package/dist/sessionPolicyCapability.js +15 -10
  121. package/dist/sessionReadRedactionCapability.d.ts +16 -0
  122. package/dist/sessionReadRedactionCapability.js +47 -0
  123. package/dist/sessionSyncFileHistoryCapability.js +14 -9
  124. package/dist/skillToolListsCapability.js +14 -9
  125. package/dist/sqlEngineCapability.js +18 -13
  126. package/dist/steerPriorityCapability.js +21 -16
  127. package/dist/subagent/agentStateDetail.d.ts +1 -0
  128. package/dist/subagent/agentStateDetail.js +41 -0
  129. package/dist/subagent/engineCompactWire.d.ts +15 -0
  130. package/dist/subagent/engineCompactWire.js +75 -13
  131. package/dist/supportFloor.js +1 -1
  132. package/dist/taskRequestWords.d.ts +2 -4
  133. package/dist/taskRequestWords.js +3 -2
  134. package/dist/types/engineState.d.ts +1 -1
  135. package/dist/userAttachmentEnvelope.d.ts +22 -1
  136. package/dist/userAttachmentEnvelope.js +90 -2
  137. package/dist/userInvokedSkillsCapability.js +14 -9
  138. package/dist/webSearchBackendCapability.js +21 -16
  139. package/dist/wireErrorTriage.d.ts +11 -0
  140. package/dist/wireErrorTriage.js +35 -0
  141. package/dist/wireFailureShape.d.ts +6 -0
  142. package/dist/wireFailureShape.js +30 -3
  143. package/dist/wireRefusalCopy.d.ts +6 -1
  144. package/dist/wireRefusalCopy.js +22 -8
  145. package/dist/wiringInstructionsAttribution.d.ts +10 -0
  146. package/dist/wiringInstructionsAttribution.js +67 -0
  147. package/dist/workflowClient.js +22 -1
  148. package/dist/workflowsJournalCapability.js +14 -9
  149. package/dist/writeProtectionCapability.js +28 -23
  150. package/docs/INTEGRATION-CLIENTS.md +817 -45
  151. package/package.json +5 -5
  152. package/dist/askSurvivesStandingAnswer.d.ts +0 -13
  153. package/dist/askSurvivesStandingAnswer.js +0 -53
  154. package/dist/hitl/askSurvivesPosture.d.ts +0 -20
  155. package/dist/hitl/askSurvivesPosture.js +0 -48
  156. /package/dist/{hitl/rosterMountedNames.js → rosterMountedNames.js} +0 -0
@@ -149,13 +149,13 @@ export function resumeContextUnavailableFromError(err) {
149
149
  }
150
150
  export function resumeContextUnavailableContent(d) {
151
151
  const sec = d.staleAfterSec;
152
- const retention = typeof sec === 'number' && Number.isSafeInteger(sec) && sec >= 1 ? `(本部署的会话保留时长为 ${sec} 秒)` : '';
152
+ const retention = typeof sec === 'number' && Number.isSafeInteger(sec) && sec >= 1 ? ` (this deployment keeps conversations for ${sec} seconds)` : '';
153
153
  const third = (d.runId !== undefined
154
- ? '错误里带了这条运行的 id,请用它自己恢复这条运行再决;调大会话保留时长只能避免以后再发生,救不回这一次'
155
- : '错误里没有带运行 id,请回到运行列表找到这条运行自己恢复它再决;调大会话保留时长只能避免以后再发生,救不回这一次') + retention;
154
+ ? "The error carries this run's id: use it to recover the run yourself, then decide again; raising the conversation retention time only prevents this from happening again and cannot rescue this one"
155
+ : 'The error carries no run id: go back to the run list, find this run and recover it yourself, then decide again; raising the conversation retention time only prevents this from happening again and cannot rescue this one') + retention;
156
156
  return [
157
- '这个批准无处投递:发起这次运行的会话当前没有可用的上下文来继续它',
158
- '什么都没有被决定,你的决定没有被消费,这张卡仍在等待',
157
+ 'This approval has nowhere to be delivered: the conversation that started this run has no usable context to continue it right now',
158
+ 'Nothing was decided and your decision was not consumed; this card is still waiting',
159
159
  third,
160
160
  ].join(' · ');
161
161
  }
@@ -167,17 +167,7 @@ function parkedResumeStartupCauseWord(err) {
167
167
  catch {
168
168
  named = undefined;
169
169
  }
170
- if (named !== undefined)
171
- return named;
172
- try {
173
- const extra = err.extra;
174
- if (typeof extra !== 'object' || extra === null || Array.isArray(extra))
175
- return undefined;
176
- return readOwnDataNonEmptyString(extra, 'cause');
177
- }
178
- catch {
179
- return undefined;
180
- }
170
+ return named;
181
171
  }
182
172
  export function parkedResumeStartupFromError(err, decision) {
183
173
  if (typeof err !== 'object' || err === null)
@@ -1,3 +1,4 @@
1
+ import { displayUntrusted } from './displayUntrusted.js';
1
2
  export const BRAIN_STATUS_PHASES = [
2
3
  'rate_limited',
3
4
  'retrying',
@@ -40,6 +41,7 @@ export function mapBrainStatusToRetry(p, nowMs) {
40
41
  ...(timeoutMs !== undefined ? { timeoutMs } : {}),
41
42
  };
42
43
  const stalledDetail = typeof p.detail === 'string' && p.detail.length > 0 ? { detail: p.detail } : {};
44
+ const shown = (absent) => (typeof p.detail === 'string' ? displayUntrusted(p.detail) : absent);
43
45
  const extra = { ...counts, ...cause, ...producerTiming, ...failureStatus, ...waitProgress };
44
46
  switch (p.phase) {
45
47
  case 'recovered':
@@ -47,20 +49,20 @@ export function mapBrainStatusToRetry(p, nowMs) {
47
49
  case 'reconnecting':
48
50
  return { kind: 'stalled', deadline, ...extra, ...stalledDetail };
49
51
  case 'rate_limited':
50
- return { kind: 'error', deadline, ...extra, error: { formatted: p.detail ?? '', rateLimits: null } };
52
+ return { kind: 'error', deadline, ...extra, error: { formatted: shown(''), rateLimits: null } };
51
53
  case 'circuit_open':
52
54
  return {
53
55
  kind: 'error',
54
56
  deadline,
55
57
  ...extra,
56
- error: { formatted: p.detail ?? 'Service temporarily unavailable', isNetworkDown: true },
58
+ error: { formatted: shown('Service temporarily unavailable'), isNetworkDown: true },
57
59
  };
58
60
  case 'gave_up':
59
- return { kind: 'error', deadline, terminal: true, ...extra, error: { formatted: p.detail ?? '' } };
61
+ return { kind: 'error', deadline, terminal: true, ...extra, error: { formatted: shown('') } };
60
62
  case 'waiting_first_token':
61
63
  return { kind: 'waiting', deadline, ...extra, error: { formatted: '' } };
62
64
  case 'retrying':
63
- return { kind: 'error', deadline, ...extra, error: { formatted: p.detail ?? '' } };
65
+ return { kind: 'error', deadline, ...extra, error: { formatted: shown('') } };
64
66
  default:
65
67
  return { kind: 'error', deadline, ...extra, error: { formatted: '' } };
66
68
  }
@@ -22,15 +22,20 @@ function bitOf(caps, key) {
22
22
  return 'malformed';
23
23
  }
24
24
  export function projectRewindArchiveCapability(caps) {
25
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
25
+ try {
26
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
27
+ return undefined;
28
+ return {
29
+ kind: 'present',
30
+ conversationAnchor: bitOf(caps, CAPS_KEYS.conversationAnchor),
31
+ forkRestore: bitOf(caps, CAPS_KEYS.forkRestore),
32
+ codeOnly: bitOf(caps, CAPS_KEYS.codeOnly),
33
+ restoreFilesEpoch: bitOf(caps, CAPS_KEYS.restoreFilesEpoch),
34
+ };
35
+ }
36
+ catch {
26
37
  return undefined;
27
- return {
28
- kind: 'present',
29
- conversationAnchor: bitOf(caps, CAPS_KEYS.conversationAnchor),
30
- forkRestore: bitOf(caps, CAPS_KEYS.forkRestore),
31
- codeOnly: bitOf(caps, CAPS_KEYS.codeOnly),
32
- restoreFilesEpoch: bitOf(caps, CAPS_KEYS.restoreFilesEpoch),
33
- };
38
+ }
34
39
  }
35
40
  const reader = createEngineCapReader({
36
41
  name: 'rewindArchive',
@@ -1,2 +1,2 @@
1
- import type { ToolRosterView } from '../toolRoster.js';
1
+ import type { ToolRosterView } from './toolRoster.js';
2
2
  export declare function rosterMountedNames(roster: ToolRosterView | null | undefined): ReadonlySet<string> | 'absent' | 'unreadable';
@@ -34,6 +34,7 @@ export function readRunCancelContext(record) {
34
34
  };
35
35
  }
36
36
  import { readRunTerminal } from './runTerminal.js';
37
+ import { SDK_ABORT_CAUSES } from './generated/sdkFactTables.js';
37
38
  export const RUN_CANCELLED_CODE = 'cancelled';
38
39
  const LIVE_STATUSES = new Set(['running', 'queued', 'suspended', 'needs_review']);
39
40
  export function classifyRunAbortCause(record) {
@@ -56,7 +57,7 @@ export function classifyRunAbortCause(record) {
56
57
  return { kind: 'run_still_live', status };
57
58
  return { kind: 'unknown', ...(read !== null ? { terminal: read.kind } : {}) };
58
59
  }
59
- export const ABORT_CAUSES = Object.freeze(['client_disconnected', 'ask_park_grace_exhausted', 'cancel_verb']);
60
+ export const ABORT_CAUSES = SDK_ABORT_CAUSES;
60
61
  function ownDataOf(o, key) {
61
62
  const d = Object.getOwnPropertyDescriptor(o, key);
62
63
  return d !== undefined && Object.hasOwn(d, 'value') ? d.value : undefined;
@@ -7,21 +7,26 @@ function ownNonEmpty(seg, key) {
7
7
  return typeof v === 'string' && v.length > 0 ? v : undefined;
8
8
  }
9
9
  export function projectSealedKeyCapability(caps) {
10
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
10
+ try {
11
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
12
+ return undefined;
13
+ if (!Object.hasOwn(caps, 'sealedKey'))
14
+ return { kind: 'not_reported' };
15
+ const seg = caps.sealedKey;
16
+ if (seg === undefined)
17
+ return { kind: 'not_reported' };
18
+ if (seg === null || typeof seg !== 'object' || Array.isArray(seg))
19
+ return undefined;
20
+ const alg = ownNonEmpty(seg, 'alg');
21
+ const publicKeyId = ownNonEmpty(seg, 'publicKeyId');
22
+ const publicKey = ownNonEmpty(seg, 'publicKey');
23
+ if (alg === undefined || publicKeyId === undefined || publicKey === undefined)
24
+ return undefined;
25
+ return { kind: 'present', alg, publicKeyId, publicKey };
26
+ }
27
+ catch {
11
28
  return undefined;
12
- if (!Object.hasOwn(caps, 'sealedKey'))
13
- return { kind: 'not_reported' };
14
- const seg = caps.sealedKey;
15
- if (seg === undefined)
16
- return { kind: 'not_reported' };
17
- if (seg === null || typeof seg !== 'object' || Array.isArray(seg))
18
- return undefined;
19
- const alg = ownNonEmpty(seg, 'alg');
20
- const publicKeyId = ownNonEmpty(seg, 'publicKeyId');
21
- const publicKey = ownNonEmpty(seg, 'publicKey');
22
- if (alg === undefined || publicKeyId === undefined || publicKey === undefined)
23
- return undefined;
24
- return { kind: 'present', alg, publicKeyId, publicKey };
29
+ }
25
30
  }
26
31
  const reader = createEngineCapReader({
27
32
  name: 'sealedKey',
@@ -29,6 +29,7 @@ export interface LocalSessionRecord {
29
29
  engineSessionId?: string;
30
30
  model?: string;
31
31
  title?: string;
32
+ cwd?: string;
32
33
  isRunning: boolean;
33
34
  createdAt: string;
34
35
  lastActivityAt?: string;
@@ -99,6 +100,22 @@ export interface LocalSessionEvent {
99
100
  chrome?: SeatChromeEnvelope;
100
101
  }
101
102
  export declare const HITL_RESOLUTION_OUTCOMES: readonly string[];
103
+ export declare const SEAT_CAPABILITY_NAMES: readonly ["pickFolder"];
104
+ export type SeatCapabilityName = (typeof SEAT_CAPABILITY_NAMES)[number];
105
+ export interface SeatCapabilitiesState {
106
+ pickFolder?: boolean;
107
+ }
108
+ export type SeatCapabilityReading = {
109
+ readonly kind: "reported";
110
+ readonly available: boolean;
111
+ } | {
112
+ readonly kind: "not_reported";
113
+ } | {
114
+ readonly kind: "malformed";
115
+ };
116
+ export declare function seatCapability(state: unknown, name: SeatCapabilityName): SeatCapabilityReading;
117
+ export declare function watchSeatCapability(store: EipcStoreClient<SeatCapabilitiesState> | undefined, name: SeatCapabilityName, onReading: (reading: SeatCapabilityReading) => void): () => void;
118
+ export declare function seatCapabilityUnavailableDetail(name: SeatCapabilityName, reading: SeatCapabilityReading): string | undefined;
102
119
  export interface StartSessionOptions {
103
120
  model?: string;
104
121
  title?: string;
@@ -227,11 +244,13 @@ export interface LocalSessionsApi {
227
244
  uploadAttachment(req: AttachmentUploadRequest): Promise<AttachmentUploadReceipt>;
228
245
  listModels(): Promise<SeatModelCatalog>;
229
246
  applyModelConfig(req: ApplyModelConfigRequest): Promise<ApplyModelConfigResult>;
247
+ pickFolder(): Promise<string | null>;
230
248
  onEvent(cb: (ev: LocalSessionEvent) => void): () => void;
231
249
  onToolPermissionRequest(cb: (req: ToolPermissionRequest) => void): () => void;
232
250
  sessionsStateStore: EipcStoreClient<SessionsState>;
233
251
  focusedSessionStateStore: EipcStoreClient<FocusedSessionState>;
234
252
  settingsStateStore: EipcStoreClient<SettingsState>;
253
+ seatCapabilitiesStateStore: EipcStoreClient<SeatCapabilitiesState>;
235
254
  }
236
255
  export declare function isLocalSessionRecord(s: unknown): s is LocalSessionRecord;
237
256
  export declare function isToolPermissionRequest(r: unknown): r is ToolPermissionRequest;
@@ -260,12 +279,12 @@ export interface ApplyModelConfigResult {
260
279
  export declare function isSeatModelCatalog(v: unknown): v is SeatModelCatalog;
261
280
  export declare function isSendMessageAck(v: unknown): v is SendMessageAck;
262
281
  export declare const LOCAL_SESSIONS_SPEC: EipcServiceSpec;
263
- export declare const SEAT_METHOD_NAMES: readonly ["start", "sendMessage", "interrupt", "stop", "respondToToolPermission", "cancelQueuedMessage", "reorderQueuedMessage", "promoteQueuedMessage", "setFocusedSession", "setModel", "getTranscript", "searchSessions", "uploadAttachment", "listModels", "applyModelConfig", "onEvent", "onToolPermissionRequest"];
264
- export declare const SEAT_STORE_PROPS: readonly ["sessionsStateStore", "focusedSessionStateStore", "settingsStateStore"];
282
+ export declare const SEAT_METHOD_NAMES: readonly ["start", "sendMessage", "interrupt", "stop", "respondToToolPermission", "cancelQueuedMessage", "reorderQueuedMessage", "promoteQueuedMessage", "setFocusedSession", "setModel", "getTranscript", "searchSessions", "uploadAttachment", "listModels", "applyModelConfig", "pickFolder", "onEvent", "onToolPermissionRequest"];
283
+ export declare const SEAT_STORE_PROPS: readonly ["sessionsStateStore", "focusedSessionStateStore", "settingsStateStore", "seatCapabilitiesStateStore"];
265
284
  export declare const SEAT_EVENT_METHOD_NAMES: readonly ["onEvent", "onToolPermissionRequest"];
266
285
  export declare const LOCAL_SESSION_EVENT_KEYS: readonly ["type", "sessionId", "message", "messages", "error", "errorCategory", "code", "request", "data", "sources", "permissionMode", "session", "userMessageUuid", "hasPreClearSession", "requestId", "outcome", "chrome"];
267
286
  export declare const TOOL_PERMISSION_REQUEST_KEYS: readonly ["requestId", "sessionId", "toolName", "toolCallId", "input", "message", "toctouBinding", "createdAtMs", "governanceForced", "delegation", "mandated", "mandate", "origin", "ruleOffersAbsence", "askClass", "classes"];
268
- export declare const LOCAL_SESSION_RECORD_KEYS: readonly ["sessionId", "engineSessionId", "model", "title", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked"];
287
+ export declare const LOCAL_SESSION_RECORD_KEYS: readonly ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked"];
269
288
  export declare const SEND_MESSAGE_REQUEST_KEYS: readonly ["sessionId", "text", "model", "userMessageUuid", "permissionMode", "attachmentIds", "reasoningEffort", "retainBackgroundProcesses", "forwardSubagentEvents", "retainSubagentSessions", "settings", "scenario"];
270
289
  export declare const SEAT_SEND_MESSAGE_KEY_ORIGINS: {
271
290
  readonly sessionId: {
@@ -311,7 +330,7 @@ export declare const SEAT_VALIDATOR_KEY_COVERAGE: {
311
330
  readonly LocalSessionRecord: {
312
331
  readonly guard: "isLocalSessionRecord";
313
332
  readonly check: (s: unknown) => SeatValidation;
314
- readonly validated: readonly ["sessionId", "engineSessionId", "model", "title", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked"];
333
+ readonly validated: readonly ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked"];
315
334
  readonly unchecked: readonly [];
316
335
  };
317
336
  readonly ToolPermissionRequest: {
@@ -335,7 +354,7 @@ export declare const SEAT_VALIDATOR_KEY_COVERAGE: {
335
354
  readonly why: "展示增强位(CC-203),权威窄读在卡口与过境口(闭集六词精确字节,表外不上座);座位门不设第二判官,理由同 mandated。消费端经 readApprovalMandate 读,表外值读成缺席。";
336
355
  }, {
337
356
  readonly key: "origin";
338
- readonly why: "喂姿态谓词 askSurvivesPosture 的安全位(CC-203),按开集读(非空串原文字节、词表不校);权威窄读在卡口与过境口 toolPermissionRequestAskBits,座位门不设第二判官(为一个位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。坏形的两种失效方向:非串 / 空串读成缺席 ⇒ 宿主报了没命中时姿态谓词可答可以放(放宽方向:真出身若是必问词就丢了);表外串读成不认识的词 ⇒ 答 unknown,宿主退回自己的规则(不放宽)。不经过境口自铸座位请求的宿主要自己按同一把窄读。";
357
+ readonly why: "喂自动车道单一判定 automaticAnswerVerdict 的出身位(CC-203),按开集读(非空串原文字节、词表不校);权威窄读在卡口与过境口 toolPermissionRequestAskBits,座位门不设第二判官(为一个位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。坏形的两种失效方向:非串 / 空串读成缺席 ⇒ 判定少一路必问证据(放宽方向:真出身若是收词、而卡上的类集恰没带它对应的类,这一路就丢了);表外串 ⇒ 不是收词,出身这一路不起作用(类集照读,不放宽)。不经过境口自铸座位请求的宿主要自己按同一把窄读。";
339
358
  }, {
340
359
  readonly key: "askClass";
341
360
  readonly why: "展示位(CC-284),权威成对窄读在卡口与过境口 toolPermissionRequestAskBits(与 classes 同在同缺、首员等于 askClass、不判成员、不重排);座位门不设第二判官,理由同 mandated(为一个展示位拒掉整条 request = 把安全 ask 丢给引擎超时拒)。坏形读成缺席 ⇒ 卡上不显示问类,不改决断;缺席不是「普通问」。不经过境口自铸座位请求的宿主要自己按同一把成对窄读。";
@@ -419,6 +438,11 @@ export declare const SEAT_VALIDATOR_KEY_COVERAGE: {
419
438
  readonly validated: readonly ["defaultModel", "engineVersion", "dataRoot"];
420
439
  readonly unchecked: readonly [];
421
440
  };
441
+ readonly SeatCapabilitiesState: {
442
+ readonly check: (v: unknown) => SeatValidation;
443
+ readonly validated: readonly ["pickFolder"];
444
+ readonly unchecked: readonly [];
445
+ };
422
446
  readonly SeatModelInfo: {
423
447
  readonly check: (v: unknown) => SeatValidation;
424
448
  readonly validated: readonly ["id", "name", "provider", "contextWindow", "maxOutputTokens"];
@@ -441,6 +465,10 @@ export declare const SEAT_VALIDATOR_KEY_COVERAGE: {
441
465
  };
442
466
  };
443
467
  export declare const SEAT_VALIDATOR_COVERAGE_EXEMPT: readonly [{
468
+ readonly label: "PickFolderResult";
469
+ readonly check: (v: unknown) => SeatValidation;
470
+ readonly why: "载荷是**串或 null**(选中的路径 / 用户取消,CC-469),没有键面 ⇒ `keyof` 覆盖表在它身上无从谈起。判别力由 run-seat-wave2-test.mjs ST1-1 承担:认 null 与非空串、拒空串 / 数 / undefined / 对象 / 布尔五形。";
471
+ }, {
444
472
  readonly label: "BooleanAck";
445
473
  readonly check: (v: unknown) => SeatValidation;
446
474
  readonly why: "载荷是**裸布尔**(queue 三件 + setModel 的 CC 形回执,false = too-late/no-op),没有键面 ⇒ `keyof` 覆盖表在它身上无从谈起。判别力由 J 段承担:认 true/false、拒非布尔(对象 / 字符串 'true' / null / undefined 四形逐一投毒)。";
@@ -72,6 +72,101 @@ export const HITL_RESOLUTION_OUTCOMES = [
72
72
  "decline",
73
73
  "cancel",
74
74
  ];
75
+ export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder"]);
76
+ const notReported = () => Object.freeze({ kind: "not_reported" });
77
+ const malformedReading = () => Object.freeze({ kind: "malformed" });
78
+ const reported = (available) => Object.freeze({ kind: "reported", available });
79
+ export function seatCapability(state, name) {
80
+ if (state === undefined)
81
+ return notReported();
82
+ try {
83
+ if (typeof state !== "object" || state === null || Array.isArray(state))
84
+ return malformedReading();
85
+ const proto = Object.getPrototypeOf(state);
86
+ if (proto !== Object.prototype && proto !== null)
87
+ return malformedReading();
88
+ const desc = Object.getOwnPropertyDescriptor(state, name);
89
+ if (desc === undefined)
90
+ return notReported();
91
+ if (!("value" in desc))
92
+ return malformedReading();
93
+ const v = desc.value;
94
+ if (v === undefined)
95
+ return notReported();
96
+ if (typeof v === "boolean")
97
+ return reported(v);
98
+ return malformedReading();
99
+ }
100
+ catch {
101
+ return malformedReading();
102
+ }
103
+ }
104
+ export function watchSeatCapability(store, name, onReading) {
105
+ if (store === undefined || store === null) {
106
+ onReading(notReported());
107
+ return () => { };
108
+ }
109
+ let active = true;
110
+ let off;
111
+ try {
112
+ if (typeof store !== "object" || typeof store.onStateChange !== "function" || typeof store.getStateSync !== "function") {
113
+ onReading(malformedReading());
114
+ return () => { };
115
+ }
116
+ off = store.onStateChange((state) => {
117
+ if (active)
118
+ onReading(seatCapability(state, name));
119
+ });
120
+ }
121
+ catch {
122
+ onReading(malformedReading());
123
+ return () => { };
124
+ }
125
+ let current;
126
+ try {
127
+ current = seatCapability(store.getStateSync(), name);
128
+ }
129
+ catch {
130
+ current = malformedReading();
131
+ }
132
+ if (active)
133
+ onReading(current);
134
+ return () => {
135
+ if (!active)
136
+ return;
137
+ active = false;
138
+ try {
139
+ if (typeof off === "function")
140
+ off();
141
+ }
142
+ catch {
143
+ }
144
+ };
145
+ }
146
+ const SEAT_CAPABILITY_PHRASES = Object.freeze({
147
+ pickFolder: Object.freeze({ action: "Opening a folder", ability: "show a folder picker", support: "folder picker support" }),
148
+ });
149
+ export function seatCapabilityUnavailableDetail(name, reading) {
150
+ const phrase = Object.hasOwn(SEAT_CAPABILITY_PHRASES, name)
151
+ ? SEAT_CAPABILITY_PHRASES[name]
152
+ : { action: "This action", ability: "do this", support: "support for it" };
153
+ let kind;
154
+ let available;
155
+ try {
156
+ kind = reading?.kind;
157
+ available = reading?.available;
158
+ }
159
+ catch {
160
+ kind = undefined;
161
+ }
162
+ if (kind === "reported" && available === true)
163
+ return undefined;
164
+ if (kind === "reported" && available === false)
165
+ return `${phrase.action} isn't available: this app reports it can't ${phrase.ability}.`;
166
+ if (kind === "not_reported")
167
+ return `${phrase.action} isn't available: this app hasn't reported ${phrase.support}.`;
168
+ return `${phrase.action} isn't available: this app's support report couldn't be read.`;
169
+ }
75
170
  export const PERMISSION_MODE_INTENTS = [...PERMISSION_MODE_WORDS];
76
171
  export const ATTACHMENT_IDS_PER_TASK_CAP = 16;
77
172
  export const SEAT_REASONING_EFFORTS = [...REASONING_EFFORT_WORDS];
@@ -90,6 +185,9 @@ const checkLocalSessionRecord = (s) => {
90
185
  return bad("model must be a string when present", "model");
91
186
  if (!optionalString(s.title))
92
187
  return bad("title must be a string when present", "title");
188
+ if (!isAbsent(s.cwd) && (typeof s.cwd !== "string" || s.cwd.length === 0)) {
189
+ return bad("cwd must be a non-empty path string when present (absent = no folder chosen)", "cwd");
190
+ }
93
191
  if (typeof s.isRunning !== "boolean")
94
192
  return bad("isRunning must be a boolean", "isRunning");
95
193
  if (typeof s.createdAt !== "string")
@@ -391,6 +489,33 @@ const checkSettingsState = (v) => {
391
489
  return bad("dataRoot must be a string when present", "dataRoot");
392
490
  return true;
393
491
  };
492
+ const checkPickFolderResult = (v) => v === null || (typeof v === "string" && v.length > 0)
493
+ ? true
494
+ : bad("pickFolder result must be null (cancelled) or a non-empty path string");
495
+ const checkSeatCapabilitiesState = (v) => {
496
+ try {
497
+ if (!isObject(v) || Array.isArray(v))
498
+ return bad("seat capabilities state is not an object");
499
+ const proto = Object.getPrototypeOf(v);
500
+ if (proto !== Object.prototype && proto !== null)
501
+ return bad("seat capabilities state is not a plain object");
502
+ for (const k of Reflect.ownKeys(v)) {
503
+ const name = typeof k === "string" ? k : String(k);
504
+ if (typeof k !== "string" || !inTuple(SEAT_CAPABILITY_NAMES, k)) {
505
+ return bad(`${name} is not a registered seat capability (${SEAT_CAPABILITY_NAMES.join("|")})`, name);
506
+ }
507
+ const desc = Object.getOwnPropertyDescriptor(v, k);
508
+ if (desc === undefined || !("value" in desc))
509
+ return bad(`${k} must be a plain data property (accessors are refused)`, k);
510
+ if (!isAbsent(desc.value) && typeof desc.value !== "boolean")
511
+ return bad(`${k} must be a boolean when present`, k);
512
+ }
513
+ return true;
514
+ }
515
+ catch {
516
+ return bad("seat capabilities state could not be read");
517
+ }
518
+ };
394
519
  export const LOCAL_SESSIONS_SPEC = {
395
520
  ns: "sema.web",
396
521
  service: "LocalSessions",
@@ -410,6 +535,7 @@ export const LOCAL_SESSIONS_SPEC = {
410
535
  uploadAttachment: { kind: "invoke", check: checkAttachmentUploadReceipt },
411
536
  listModels: { kind: "invoke", check: checkSeatModelCatalog },
412
537
  applyModelConfig: { kind: "invoke", check: checkApplyModelConfigResult },
538
+ pickFolder: { kind: "invoke", check: checkPickFolderResult },
413
539
  onEvent: { kind: "event", check: checkLocalSessionEvent },
414
540
  onToolPermissionRequest: { kind: "event", check: checkToolPermissionRequest },
415
541
  },
@@ -417,6 +543,7 @@ export const LOCAL_SESSIONS_SPEC = {
417
543
  sessionsState: { check: checkSessionsState },
418
544
  focusedSessionState: { check: checkFocusedSessionState },
419
545
  settingsState: { check: checkSettingsState },
546
+ seatCapabilitiesState: { check: checkSeatCapabilitiesState },
420
547
  },
421
548
  };
422
549
  export const SEAT_METHOD_NAMES = [
@@ -435,6 +562,7 @@ export const SEAT_METHOD_NAMES = [
435
562
  "uploadAttachment",
436
563
  "listModels",
437
564
  "applyModelConfig",
565
+ "pickFolder",
438
566
  "onEvent",
439
567
  "onToolPermissionRequest",
440
568
  ];
@@ -442,6 +570,7 @@ export const SEAT_STORE_PROPS = [
442
570
  "sessionsStateStore",
443
571
  "focusedSessionStateStore",
444
572
  "settingsStateStore",
573
+ "seatCapabilitiesStateStore",
445
574
  ];
446
575
  export const SEAT_EVENT_METHOD_NAMES = ["onEvent", "onToolPermissionRequest"];
447
576
  export const LOCAL_SESSION_EVENT_KEYS = [
@@ -486,6 +615,7 @@ export const LOCAL_SESSION_RECORD_KEYS = [
486
615
  "engineSessionId",
487
616
  "model",
488
617
  "title",
618
+ "cwd",
489
619
  "isRunning",
490
620
  "createdAt",
491
621
  "lastActivityAt",
@@ -533,7 +663,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
533
663
  LocalSessionRecord: {
534
664
  guard: "isLocalSessionRecord",
535
665
  check: checkLocalSessionRecord,
536
- validated: ["sessionId", "engineSessionId", "model", "title", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked"],
666
+ validated: ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked"],
537
667
  unchecked: [],
538
668
  },
539
669
  ToolPermissionRequest: {
@@ -563,7 +693,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
563
693
  },
564
694
  {
565
695
  key: "origin",
566
- why: "喂姿态谓词 askSurvivesPosture 的安全位(CC-203),按开集读(非空串原文字节、词表不校);权威窄读在卡口与过境口 toolPermissionRequestAskBits,座位门不设第二判官(为一个位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。坏形的两种失效方向:非串 / 空串读成缺席 ⇒ 宿主报了没命中时姿态谓词可答可以放(放宽方向:真出身若是必问词就丢了);表外串读成不认识的词 ⇒ 答 unknown,宿主退回自己的规则(不放宽)。不经过境口自铸座位请求的宿主要自己按同一把窄读。",
696
+ why: "喂自动车道单一判定 automaticAnswerVerdict 的出身位(CC-203),按开集读(非空串原文字节、词表不校);权威窄读在卡口与过境口 toolPermissionRequestAskBits,座位门不设第二判官(为一个位拒掉整条 request = 把安全 ask 丢给引擎 TTL deny)。坏形的两种失效方向:非串 / 空串读成缺席 ⇒ 判定少一路必问证据(放宽方向:真出身若是收词、而卡上的类集恰没带它对应的类,这一路就丢了);表外串 ⇒ 不是收词,出身这一路不起作用(类集照读,不放宽)。不经过境口自铸座位请求的宿主要自己按同一把窄读。",
567
697
  },
568
698
  {
569
699
  key: "askClass",
@@ -670,6 +800,11 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
670
800
  validated: ["defaultModel", "engineVersion", "dataRoot"],
671
801
  unchecked: [],
672
802
  },
803
+ SeatCapabilitiesState: {
804
+ check: checkSeatCapabilitiesState,
805
+ validated: ["pickFolder"],
806
+ unchecked: [],
807
+ },
673
808
  SeatModelInfo: {
674
809
  check: (v) => checkSeatModelInfo(v, 0),
675
810
  validated: ["id", "name", "provider", "contextWindow", "maxOutputTokens"],
@@ -692,6 +827,11 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
692
827
  },
693
828
  };
694
829
  export const SEAT_VALIDATOR_COVERAGE_EXEMPT = [
830
+ {
831
+ label: "PickFolderResult",
832
+ check: checkPickFolderResult,
833
+ why: "载荷是**串或 null**(选中的路径 / 用户取消,CC-469),没有键面 ⇒ `keyof` 覆盖表在它身上无从谈起。判别力由 run-seat-wave2-test.mjs ST1-1 承担:认 null 与非空串、拒空串 / 数 / undefined / 对象 / 布尔五形。",
834
+ },
695
835
  {
696
836
  label: "BooleanAck",
697
837
  check: checkBooleanAck,
@@ -723,5 +863,6 @@ const _seatContractPins = [
723
863
  true, true, true, true, true, true, true, true,
724
864
  true, true, true, true, true, true, true, true,
725
865
  true, true, true, true, true, true, true, true,
866
+ true, true, true, true, true,
726
867
  ];
727
868
  void _seatContractPins;
@@ -1,17 +1,22 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
3
  export function projectSessionPolicyCapability(caps) {
4
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
5
- return undefined;
6
- const c = caps;
7
- if (!Object.hasOwn(c, 'sessionPolicy'))
8
- return { kind: 'not_reported' };
9
- const v = c.sessionPolicy;
10
- if (v === undefined)
11
- return { kind: 'not_reported' };
12
- if (typeof v !== 'boolean')
4
+ try {
5
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
6
+ return undefined;
7
+ const c = caps;
8
+ if (!Object.hasOwn(c, 'sessionPolicy'))
9
+ return { kind: 'not_reported' };
10
+ const v = c.sessionPolicy;
11
+ if (v === undefined)
12
+ return { kind: 'not_reported' };
13
+ if (typeof v !== 'boolean')
14
+ return undefined;
15
+ return v ? { kind: 'present' } : { kind: 'absent' };
16
+ }
17
+ catch {
13
18
  return undefined;
14
- return v ? { kind: 'present' } : { kind: 'absent' };
19
+ }
15
20
  }
16
21
  const reader = createEngineCapReader({
17
22
  name: 'sessionPolicy',
@@ -0,0 +1,16 @@
1
+ export type SessionReadRedactionReading = {
2
+ kind: 'unobserved';
3
+ } | {
4
+ kind: 'not_reported';
5
+ } | {
6
+ kind: 'present';
7
+ value: true;
8
+ };
9
+ export declare function projectSessionReadRedactionCapability(caps: unknown): SessionReadRedactionReading | undefined;
10
+ export declare function noteEngineCapsForSessionReadRedaction(baseUrl: string, caps: unknown, opts?: {
11
+ generation?: number;
12
+ }): void;
13
+ export declare function observedSessionReadRedaction(baseUrl?: string | undefined): SessionReadRedactionReading;
14
+ export declare function sessionReadRedactionAdmitted(reading: SessionReadRedactionReading | undefined): boolean;
15
+ export declare function forgetSessionReadRedactionReading(baseUrl: string | undefined): void;
16
+ export declare function __resetSessionReadRedactionReadingsForTests(): void;
@@ -0,0 +1,47 @@
1
+ import { engineWireTarget } from './engineWireTarget.js';
2
+ import { createEngineCapReader } from './engineCapReader.js';
3
+ import { readOwnDataValue } from './ownKey.js';
4
+ export function projectSessionReadRedactionCapability(caps) {
5
+ try {
6
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
7
+ return undefined;
8
+ if (!Object.hasOwn(caps, 'sessionReadRedaction'))
9
+ return { kind: 'not_reported' };
10
+ const v = caps.sessionReadRedaction;
11
+ if (v === undefined)
12
+ return { kind: 'not_reported' };
13
+ return v === true ? { kind: 'present', value: true } : undefined;
14
+ }
15
+ catch {
16
+ return undefined;
17
+ }
18
+ }
19
+ const reader = createEngineCapReader({
20
+ name: 'sessionReadRedaction',
21
+ project: projectSessionReadRedactionCapability,
22
+ makeUnobserved: () => ({ kind: 'unobserved' }),
23
+ });
24
+ export function noteEngineCapsForSessionReadRedaction(baseUrl, caps, opts) {
25
+ reader.note(baseUrl, caps, opts);
26
+ }
27
+ export function observedSessionReadRedaction(baseUrl = engineWireTarget()?.baseUrl) {
28
+ return reader.observed(baseUrl);
29
+ }
30
+ export function sessionReadRedactionAdmitted(reading) {
31
+ try {
32
+ if (reading === null || reading === undefined || typeof reading !== 'object' || Array.isArray(reading))
33
+ return false;
34
+ if (readOwnDataValue(reading, 'kind') !== 'present')
35
+ return false;
36
+ return readOwnDataValue(reading, 'value') === true;
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ export function forgetSessionReadRedactionReading(baseUrl) {
43
+ reader.forget(baseUrl);
44
+ }
45
+ export function __resetSessionReadRedactionReadingsForTests() {
46
+ reader.__resetForTests();
47
+ }
@@ -1,16 +1,21 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
3
  export function projectSessionSyncFileHistoryCapability(caps) {
4
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
5
- return undefined;
6
- if (!Object.hasOwn(caps, 'sessionSyncFileHistory'))
7
- return { kind: 'not_reported' };
8
- const v = caps.sessionSyncFileHistory;
9
- if (v === undefined)
10
- return { kind: 'not_reported' };
11
- if (typeof v !== 'boolean')
4
+ try {
5
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
6
+ return undefined;
7
+ if (!Object.hasOwn(caps, 'sessionSyncFileHistory'))
8
+ return { kind: 'not_reported' };
9
+ const v = caps.sessionSyncFileHistory;
10
+ if (v === undefined)
11
+ return { kind: 'not_reported' };
12
+ if (typeof v !== 'boolean')
13
+ return undefined;
14
+ return v ? { kind: 'present' } : { kind: 'absent' };
15
+ }
16
+ catch {
12
17
  return undefined;
13
- return v ? { kind: 'present' } : { kind: 'absent' };
18
+ }
14
19
  }
15
20
  const reader = createEngineCapReader({
16
21
  name: 'sessionSyncFileHistory',