@sema-agent/client-core 0.106.0 → 0.108.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 (114) hide show
  1. package/CHANGELOG.md +199 -0
  2. package/README.md +35 -26
  3. package/dist/adapter/activeRunSelfHeal.d.ts +10 -0
  4. package/dist/adapter/activeRunSelfHeal.js +68 -23
  5. package/dist/checkpointRowVerdict.d.ts +11 -0
  6. package/dist/checkpointRowVerdict.js +35 -0
  7. package/dist/cloudConfigWireCaps.d.ts +10 -0
  8. package/dist/cloudConfigWireCaps.js +33 -0
  9. package/dist/coreValuePorts.d.ts +17 -1
  10. package/dist/coreValuePorts.js +5 -0
  11. package/dist/decideReceipt.js +2 -1
  12. package/dist/displayUntrusted.d.ts +5 -3
  13. package/dist/displayUntrusted.js +50 -41
  14. package/dist/engineErrorCodes.d.ts +5 -0
  15. package/dist/engineErrorCodes.js +5 -0
  16. package/dist/engineNoticeCodes.d.ts +31 -1
  17. package/dist/engineNoticeCodes.js +182 -9
  18. package/dist/engineTargetSeat.js +1 -0
  19. package/dist/errorSupplementRoles.js +4 -1
  20. package/dist/eventLeg.js +1 -1
  21. package/dist/executionLaneCapability.js +3 -2
  22. package/dist/executionLaneWords.d.ts +1 -0
  23. package/dist/executionLaneWords.js +4 -0
  24. package/dist/gateOutcome.d.ts +10 -1
  25. package/dist/gateOutcome.js +48 -1
  26. package/dist/generated/engineFactTables.d.ts +1 -0
  27. package/dist/generated/engineFactTables.js +5 -0
  28. package/dist/generated/engineNoticeTables.js +12 -3
  29. package/dist/generated/settingsSchemaFns.d.ts +4 -2
  30. package/dist/generated/settingsSchemaFns.js +9 -3
  31. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
  32. package/dist/generated/settingsSchemaMcpRequestEntry.js +9 -18
  33. package/dist/generated/settingsSchemaReservedMemberName.d.ts +1 -0
  34. package/dist/generated/settingsSchemaReservedMemberName.js +7 -0
  35. package/dist/generated/settingsSchemaTables.d.ts +2 -0
  36. package/dist/generated/settingsSchemaTables.js +10 -0
  37. package/dist/generated/settingsSchemaWireName.d.ts +1 -0
  38. package/dist/generated/settingsSchemaWireName.js +8 -0
  39. package/dist/headlessReconnectWire.js +12 -7
  40. package/dist/hitl/approvalAskers.d.ts +13 -0
  41. package/dist/hitl/approvalAskers.js +79 -0
  42. package/dist/hitl/approvalResolution.d.ts +8 -1
  43. package/dist/hitl/approvalResolution.js +37 -2
  44. package/dist/hitl/approvalsFeed.js +5 -13
  45. package/dist/hitl/askParkRowRouting.js +17 -1
  46. package/dist/hitl/decisionRefusal.d.ts +1 -0
  47. package/dist/hitl/decisionRefusal.js +5 -2
  48. package/dist/hitl/decisionSend.d.ts +2 -0
  49. package/dist/hitl/decisionSend.js +22 -12
  50. package/dist/hitl/frameRouter.d.ts +3 -2
  51. package/dist/hitl/frameRouter.js +28 -6
  52. package/dist/hitl/gateLedger.d.ts +2 -0
  53. package/dist/hitl/gateLedger.js +3 -1
  54. package/dist/hitl/hitlBridge.d.ts +5 -1
  55. package/dist/hitl/hitlBridge.js +26 -2
  56. package/dist/hitl/livePendingAsk.js +4 -2
  57. package/dist/hitl/parkOwnership.js +4 -5
  58. package/dist/hitl/parkResolver.js +34 -21
  59. package/dist/hitl/parkRowBirthWait.d.ts +9 -0
  60. package/dist/hitl/parkRowBirthWait.js +8 -1
  61. package/dist/hitl/parkRowDelegation.d.ts +6 -0
  62. package/dist/hitl/parkRowDelegation.js +33 -0
  63. package/dist/hitl/persistedRulesWire.d.ts +19 -3
  64. package/dist/hitl/persistedRulesWire.js +118 -20
  65. package/dist/hitl/planReviewWire.js +16 -18
  66. package/dist/hitl/policyDenyCause.d.ts +3 -0
  67. package/dist/hitl/policyDenyCause.js +16 -0
  68. package/dist/hitl/sessionAllowRoute.d.ts +5 -0
  69. package/dist/hitl/sessionAllowRoute.js +42 -0
  70. package/dist/hitl/sessionPolicyDeliverable.js +1 -1
  71. package/dist/hitl/standingRows.js +10 -10
  72. package/dist/hitl/toolApprovalWire.d.ts +8 -2
  73. package/dist/hitl/toolApprovalWire.js +44 -11
  74. package/dist/hooksReaderGenerations.d.ts +1 -0
  75. package/dist/hooksReaderGenerations.js +12 -0
  76. package/dist/hooksWireCaps.js +8 -4
  77. package/dist/i18n/messages.en.d.ts +43 -0
  78. package/dist/i18n/messages.en.js +47 -4
  79. package/dist/i18n/messages.zh.js +53 -4
  80. package/dist/index.d.ts +7 -1
  81. package/dist/index.js +5 -1
  82. package/dist/injectionLaneNotice.js +2 -1
  83. package/dist/liveModelCatalog.d.ts +4 -2
  84. package/dist/liveModelCatalog.js +164 -26
  85. package/dist/model/catalogDefault.d.ts +25 -0
  86. package/dist/model/catalogDefault.js +44 -0
  87. package/dist/noticePresentation.js +2 -0
  88. package/dist/permissionWireCaps.d.ts +1 -0
  89. package/dist/permissionWireCaps.js +11 -0
  90. package/dist/pluginHooksWire.d.ts +5 -3
  91. package/dist/pluginHooksWire.js +116 -7
  92. package/dist/queuedDelivery.d.ts +1 -0
  93. package/dist/queuedDelivery.js +12 -0
  94. package/dist/resultFrameKeys.js +4 -2
  95. package/dist/resumeRefusalCopy.js +15 -8
  96. package/dist/runPermissionModeSwitch.d.ts +2 -1
  97. package/dist/runPermissionModeSwitch.js +16 -6
  98. package/dist/sdkWireTransit.d.ts +1 -1
  99. package/dist/seatContract.d.ts +64 -10
  100. package/dist/seatContract.js +167 -12
  101. package/dist/sessionEngine.d.ts +2 -1
  102. package/dist/sessionEngine.js +5 -0
  103. package/dist/settingsHooksSalvage.d.ts +5 -0
  104. package/dist/settingsHooksSalvage.js +54 -0
  105. package/dist/subagentContentStore.js +1 -1
  106. package/dist/supportFloor.js +2 -0
  107. package/dist/taskNotificationAdmission.d.ts +19 -0
  108. package/dist/taskNotificationAdmission.js +84 -0
  109. package/dist/toolResult.js +2 -1
  110. package/dist/webSearchWireCaps.js +9 -4
  111. package/dist/wireRefusalCopy.d.ts +7 -1
  112. package/dist/wireRefusalCopy.js +7 -1
  113. package/docs/INTEGRATION-CLIENTS.md +1189 -18
  114. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -209,6 +209,7 @@ export { encodeHumanTurn, deliveredUuidsOf, imageSentOnUnknownVision, otherBodyB
209
209
  export { batchCompatible, planQueuedDelivery, humanTurnCapsOf, humanTextForKeywordScan, selfHealSteerEligible } from './queuedDelivery.js';
210
210
  export { SUBMISSION_SURFACES, SUBMISSION_ORIGINS, SUBMISSION_TOOLS, SUBMISSION_KINDS, submissionProvenanceOf, submissionIdentityOf, requestLaneOf, submissionOriginOf, } from './request/submissionIdentity.js';
211
211
  export { taskNotificationOf, taskNotificationQueueCommand } from './notifications.js';
212
+ export { taskNotificationAdmissionOf } from './taskNotificationAdmission.js';
212
213
  export { resultErrorCodeInTextOf } from './resultFrameKeys.js';
213
214
  export { humanTurnRefusalSentence, humanTurnDegradedSentence, printImageVisionSentence } from './humanTurnSentences.js';
214
215
  export { observedUserAttachmentSeat, projectUserAttachmentSeatCapability, userAttachmentSeatAdmits } from './userAttachmentSeat.js';
@@ -295,6 +296,8 @@ export { noAllowCauseOf } from './hitl/noAllowCause.js';
295
296
  export { policyDenyReason } from './hitl/frameRouter.js';
296
297
  export { readApprovalAllowRuleShadow, approvalAllowRuleShadowed, allowRuleShadowSentence, } from './hitl/allowRuleShadow.js';
297
298
  export { projectCrashConverged } from './hitl/crashConverged.js';
299
+ export { checkpointQueueRowSortOf } from './hitl/approvalQueueRow.js';
300
+ export { subagentSourceSessionOf } from './hitl/subagentSource.js';
298
301
  export * from './hitl/crashConvergedNotice.js';
299
302
  export { approvalCompleteParked } from './hitl/approvalCompleteParked.js';
300
303
  export { approvalCompleteCauseOf } from './hitl/approvalEndingCause.js';
@@ -322,6 +325,7 @@ export * from './agentSession/contract.js';
322
325
  export * from './agentSession/backgroundView.js';
323
326
  export { readAssistantInbox } from './assistantInbox.js';
324
327
  export { checkpointRowVerdictOf } from './checkpointRowVerdict.js';
328
+ export { checkpointRowBarOf, checkpointRowBarSentence } from './checkpointRowVerdict.js';
325
329
  export { checkpointRequirementsDamagedOf } from './checkpointRowVerdict.js';
326
330
  export { READ_CREDENTIAL_NOT_ACCEPTED_NOTICE, isReadCredentialRefusal } from './readCredentialRefusal.js';
327
331
  export { readEngineAgentRegistry, isEngineAgentRegistryListingSuperseded } from './agentSession/engineAgentRegistryRead.js';
@@ -357,5 +361,5 @@ export { PROJECT_MEMORY_WORDS, projectMemoryOf, observedProjectMemoryCapability,
357
361
  export { sessionRulesChildrenReadLiveOf } from './sessionRulesChildrenReadLive.js';
358
362
  export { scenarioSkillsOf, observedScenarioSkillsCapability } from './scenarioSkills.js';
359
363
  export { observedApprovalFrameFamilies, approvalFrameFamiliesDeclaration } from './approvalFrameFamilies.js';
360
- export { sessionEngineBindingFor, commitSessionEngine, readSessionEngine, sessionDispatchTarget } from './sessionEngine.js';
364
+ export { sessionEngineBindingFor, commitSessionEngine, readSessionEngine, sessionDispatchTarget, sessionDispatchRefusedFor } from './sessionEngine.js';
361
365
  export { foldSessionPlacement } from './deviceRebind.js';
@@ -1,3 +1,4 @@
1
+ import { executionLaneWordIsNone } from './executionLaneWords.js';
1
2
  import { capForDisplay } from './fleetTaskDesc.js';
2
3
  import { msg, renderMessage } from './i18n/translate.js';
3
4
  export const INJECTION_SOURCES = Object.freeze(['stdio_mcp', 'credentialed_mcp', 'task_hooks']);
@@ -16,7 +17,7 @@ function remoteLaneWordOf(lane) {
16
17
  return undefined;
17
18
  if (view.toolsOnThisHost !== false)
18
19
  return undefined;
19
- if (view.isolatedAbsent === 'no_hands' || view.provider === 'in-process')
20
+ if (view.isolatedAbsent === 'no_hands' || executionLaneWordIsNone(view.provider))
20
21
  return undefined;
21
22
  if (typeof view.provider !== 'string' || view.provider === '')
22
23
  return undefined;
@@ -23,6 +23,7 @@ export interface LiveModelCatalog {
23
23
  droppedEntries?: readonly LiveModelDroppedEntry[];
24
24
  candidateRejected?: unknown;
25
25
  modelPlane?: {} | null;
26
+ aliases?: {} | null;
26
27
  }
27
28
  export declare function setLiveModelCatalog(next: LiveModelCatalog | null): void;
28
29
  export declare function setLiveModelCatalogRefresher(fn: (() => Promise<LiveModelCatalog | null>) | null): void;
@@ -51,12 +52,12 @@ export declare function effortLevelHonored(reading: EffortLevelsReading, level:
51
52
  export declare function liveDefaultModelName(): string | null;
52
53
  export type ModelAcceptanceReading = {
53
54
  readonly verdict: 'accepted';
54
- readonly why: 'listed';
55
+ readonly why: 'listed' | 'aliased';
55
56
  readonly model: string;
56
57
  readonly defaultModel?: string;
57
58
  } | {
58
59
  readonly verdict: 'refused';
59
- readonly why: 'not_listed' | 'disabled';
60
+ readonly why: 'not_listed' | 'disabled' | 'not_at_mentionable';
60
61
  readonly model: string;
61
62
  readonly defaultModel?: string;
62
63
  } | {
@@ -118,6 +119,7 @@ export type ModelPlaneReading = {
118
119
  readonly kind: 'unreadable';
119
120
  };
120
121
  export declare function modelPlaneOf(catalog?: LiveModelCatalog | null): ModelPlaneReading;
122
+ export declare function modelPlaneSentence(reading: ModelPlaneReading, lang?: UiLanguage): string | undefined;
121
123
  export declare function modelCandidateRejectedContent(reading: ModelCandidateRejectedReading, lang?: UiLanguage): string | undefined;
122
124
  export interface RoutePairingVerdict {
123
125
  verdict: 'ok' | 'broken' | 'unknown';
@@ -189,6 +189,45 @@ function rowIdentityUnreadable(row) {
189
189
  return true;
190
190
  }
191
191
  }
192
+ function aliasesOf(cat) {
193
+ const ALIASES_ABSENT = Object.freeze({ kind: 'absent' });
194
+ const ALIASES_UNREADABLE = Object.freeze({ kind: 'unreadable' });
195
+ try {
196
+ const d = Object.getOwnPropertyDescriptor(cat, 'aliases');
197
+ if (d === undefined)
198
+ return ALIASES_ABSENT;
199
+ if (!Object.hasOwn(d, 'value'))
200
+ return ALIASES_UNREADABLE;
201
+ const raw = d.value;
202
+ if (raw === undefined)
203
+ return ALIASES_ABSENT;
204
+ if (!Array.isArray(raw))
205
+ return ALIASES_UNREADABLE;
206
+ const n = ownDataOf(raw, 'length');
207
+ if (typeof n !== 'number' || !Number.isSafeInteger(n) || n < 0)
208
+ return ALIASES_UNREADABLE;
209
+ const entries = [];
210
+ for (let i = 0; i < n; i += 1) {
211
+ const ed = Object.getOwnPropertyDescriptor(raw, String(i));
212
+ if (ed === undefined || !Object.hasOwn(ed, 'value'))
213
+ return ALIASES_UNREADABLE;
214
+ const e = ed.value;
215
+ if (e === null || typeof e !== 'object' || !isPlainRecord(e))
216
+ return ALIASES_UNREADABLE;
217
+ const nd = Object.getOwnPropertyDescriptor(e, 'name');
218
+ if (nd === undefined || !Object.hasOwn(nd, 'value') || typeof nd.value !== 'string' || nd.value.length === 0)
219
+ return ALIASES_UNREADABLE;
220
+ const bit = atMentionBitOf(e);
221
+ if (bit === 'malformed' || bit === 'unreadable')
222
+ return ALIASES_UNREADABLE;
223
+ appendOwnElement(entries, Object.freeze({ name: nd.value, bit }));
224
+ }
225
+ return Object.freeze({ kind: 'listed', entries: Object.freeze(entries) });
226
+ }
227
+ catch {
228
+ return ALIASES_UNREADABLE;
229
+ }
230
+ }
192
231
  export function modelAcceptanceOf(model, catalog = getLiveModelCatalog()) {
193
232
  const name = typeof model === 'string' && model.length > 0 ? model : undefined;
194
233
  try {
@@ -211,22 +250,45 @@ export function modelAcceptanceOf(model, catalog = getLiveModelCatalog()) {
211
250
  defaultModel = undefined;
212
251
  }
213
252
  const withDefault = defaultModel === undefined ? {} : { defaultModel };
253
+ const cannotSay = () => Object.freeze({ verdict: 'unknown', why: 'catalog_unreadable', model: name });
214
254
  const reservedReading = () => Object.freeze({ verdict: 'unknown', why: 'reserved_word', model: name, ...withDefault });
215
- if (reserved)
216
- return reservedReading();
217
- const row = liveModelRowOf(catalog, name);
218
- if (row !== undefined) {
219
- const normalized = ownDataOf(row, 'name');
220
- if (typeof normalized !== 'string' || normalized.length === 0)
221
- return Object.freeze({ verdict: 'unknown', why: 'catalog_unreadable', model: name });
222
- if (isReservedModelWord(normalized))
255
+ const notMentionable = () => Object.freeze({ verdict: 'refused', why: 'not_at_mentionable', model: name, ...withDefault });
256
+ const byRow = (row) => {
257
+ if (ownDataOf(row, 'enabled') === false)
258
+ return Object.freeze({ verdict: 'refused', why: 'disabled', model: name, ...withDefault });
259
+ const bit = atMentionBitOf(row);
260
+ if (bit === 'refused')
261
+ return notMentionable();
262
+ if (bit === 'malformed' || bit === 'unreadable')
263
+ return cannotSay();
264
+ return Object.freeze({ verdict: 'accepted', why: 'listed', model: name, ...withDefault });
265
+ };
266
+ const aliases = aliasesOf(catalog);
267
+ if (aliases.kind === 'absent') {
268
+ if (reserved)
223
269
  return reservedReading();
224
- return ownDataOf(row, 'enabled') === false
225
- ? Object.freeze({ verdict: 'refused', why: 'disabled', model: name, ...withDefault })
226
- : Object.freeze({ verdict: 'accepted', why: 'listed', model: name, ...withDefault });
270
+ const row = liveModelRowOf(catalog, name);
271
+ if (row !== undefined) {
272
+ const normalized = ownDataOf(row, 'name');
273
+ if (typeof normalized !== 'string' || normalized.length === 0)
274
+ return cannotSay();
275
+ if (isReservedModelWord(normalized))
276
+ return reservedReading();
277
+ return byRow(row);
278
+ }
279
+ }
280
+ else {
281
+ const row = rows.find((r) => ownDataOf(r, 'name') === name);
282
+ if (row !== undefined)
283
+ return byRow(row);
284
+ if (aliases.kind === 'unreadable')
285
+ return cannotSay();
286
+ const alias = aliases.entries.find((a) => a.name === name);
287
+ if (alias !== undefined)
288
+ return alias.bit === 'refused' ? notMentionable() : Object.freeze({ verdict: 'accepted', why: 'aliased', model: name, ...withDefault });
227
289
  }
228
290
  if (rows.some(rowIdentityUnreadable))
229
- return Object.freeze({ verdict: 'unknown', why: 'catalog_unreadable', model: name });
291
+ return cannotSay();
230
292
  const dropped = droppedModelEntriesOf(catalog);
231
293
  if (droppedDisabledNamed(dropped, name))
232
294
  return Object.freeze({ verdict: 'refused', why: 'disabled', model: name, ...withDefault });
@@ -246,7 +308,7 @@ export function modelNotServedNotice(reading, lang) {
246
308
  if (ownDataOf(reading, 'verdict') !== 'refused')
247
309
  return undefined;
248
310
  const why = ownDataOf(reading, 'why');
249
- if (why !== 'not_listed' && why !== 'disabled')
311
+ if (why !== 'not_listed' && why !== 'disabled' && why !== 'not_at_mentionable')
250
312
  return undefined;
251
313
  const model = ownDataOf(reading, 'model');
252
314
  const shown = typeof model === 'string' && model.length > 0 ? quoteUntrustedForSentence(model, NOT_SERVED_NAME_MAX) : undefined;
@@ -254,6 +316,11 @@ export function modelNotServedNotice(reading, lang) {
254
316
  return undefined;
255
317
  const dm = ownDataOf(reading, 'defaultModel');
256
318
  const fallback = typeof dm === 'string' && dm.length > 0 ? quoteUntrustedForSentence(dm, NOT_SERVED_NAME_MAX) : undefined;
319
+ if (why === 'not_at_mentionable') {
320
+ return fallback === undefined
321
+ ? renderMessage(msg('model.notMentionable.noDefault', { model: shown }), lang)
322
+ : renderMessage(msg('model.notMentionable.withDefault', { model: shown, default: fallback }), lang);
323
+ }
257
324
  return fallback === undefined
258
325
  ? renderMessage(msg('model.notServed.noDefault', { model: shown }), lang)
259
326
  : renderMessage(msg('model.notServed.withDefault', { model: shown, default: fallback }), lang);
@@ -420,6 +487,24 @@ export function modelPlaneOf(catalog = getLiveModelCatalog()) {
420
487
  return unreadable;
421
488
  }
422
489
  }
490
+ export function modelPlaneSentence(reading, lang) {
491
+ try {
492
+ if (reading === null || typeof reading !== 'object' || Array.isArray(reading))
493
+ return undefined;
494
+ if (ownDataOf(reading, 'kind') !== 'read')
495
+ return undefined;
496
+ const served = ownDataOf(reading, 'servedTable');
497
+ const stance = ownDataOf(reading, 'catalog');
498
+ if (served !== 'env')
499
+ return undefined;
500
+ if (stance !== 'absent' && stance !== 'refused')
501
+ return undefined;
502
+ return renderMessage(msg('model.catalog.envServed', { stance }), lang);
503
+ }
504
+ catch {
505
+ return undefined;
506
+ }
507
+ }
423
508
  const CONFIG_DOMAIN_WORD = /^[a-z][a-z0-9_.-]{0,63}$/;
424
509
  export function modelCandidateRejectedContent(reading, lang) {
425
510
  try {
@@ -467,6 +552,7 @@ export function readLiveModelCatalog(body) {
467
552
  const droppedKey = envelopeKey(body, 'droppedEntries');
468
553
  const candidateKey = envelopeKey(body, 'candidateRejected');
469
554
  const planeKey = envelopeKey(body, 'modelPlane');
555
+ const aliasesKey = envelopeKey(body, 'aliases');
470
556
  const raw = modelsKey.present ? modelsKey.value : undefined;
471
557
  if (!Array.isArray(raw))
472
558
  return unreadableCatalog('models_not_array');
@@ -479,7 +565,7 @@ export function readLiveModelCatalog(body) {
479
565
  let unreadableRows = 0;
480
566
  for (let i = 0; i < len; i += 1) {
481
567
  const d = Object.getOwnPropertyDescriptor(raw, String(i));
482
- const row = d !== undefined && Object.hasOwn(d, 'value') ? liveModelRowCopy(d.value) : undefined;
568
+ const row = d !== undefined && Object.hasOwn(d, 'value') ? modelRowTransitCopy(d.value) : undefined;
483
569
  if (row === undefined || names.has(row.name)) {
484
570
  unreadableRows += 1;
485
571
  continue;
@@ -504,12 +590,60 @@ export function readLiveModelCatalog(body) {
504
590
  out.candidateRejected = frozenJsonCopyOf(candidateKey.value) ?? null;
505
591
  if (planeKey.present && planeKey.value !== undefined)
506
592
  out.modelPlane = frozenJsonCopyOf(planeKey.value) ?? null;
593
+ if (aliasesKey.present && aliasesKey.value !== undefined)
594
+ out.aliases = aliasesTransitCopy(aliasesKey.value);
507
595
  return Object.freeze({ kind: 'read', catalog: Object.freeze(out), unreadableRows, ...(defaultModelMalformed ? { defaultModelMalformed: true } : {}) });
508
596
  }
509
597
  catch {
510
598
  return unreadableCatalog('unreadable');
511
599
  }
512
600
  }
601
+ function aliasesTransitCopy(v) {
602
+ const copy = frozenJsonCopyOf(v);
603
+ if (copy === undefined)
604
+ return null;
605
+ const before = aliasesOf({ aliases: v });
606
+ const after = aliasesOf({ aliases: copy });
607
+ if (before.kind !== after.kind)
608
+ return null;
609
+ if (before.kind === 'listed' && after.kind === 'listed') {
610
+ if (before.entries.length !== after.entries.length)
611
+ return null;
612
+ for (let i = 0; i < before.entries.length; i += 1) {
613
+ const b = before.entries[i];
614
+ const a = after.entries[i];
615
+ if (b === undefined || a === undefined || b.name !== a.name || b.bit !== a.bit)
616
+ return null;
617
+ }
618
+ }
619
+ return copy;
620
+ }
621
+ const ACCEPTANCE_ROW_KEYS = Object.freeze(['id', 'enabled', 'atMentionable']);
622
+ function modelRowTransitCopy(row) {
623
+ const copy = liveModelRowCopy(row);
624
+ if (copy === undefined || row === null || typeof row !== 'object')
625
+ return copy;
626
+ let restated;
627
+ for (const key of ACCEPTANCE_ROW_KEYS) {
628
+ if (Object.hasOwn(copy, key))
629
+ continue;
630
+ let value;
631
+ try {
632
+ const d = Object.getOwnPropertyDescriptor(row, key);
633
+ if (d === undefined)
634
+ continue;
635
+ value = Object.hasOwn(d, 'value') ? (d.value === undefined ? undefined : (frozenJsonCopyOf(d.value) ?? null)) : null;
636
+ }
637
+ catch {
638
+ value = null;
639
+ }
640
+ if (value === undefined)
641
+ continue;
642
+ restated ??= { ...copy };
643
+ Object.defineProperty(restated, key, { value, enumerable: true, writable: true, configurable: true });
644
+ }
645
+ return restated === undefined ? copy : Object.freeze(restated);
646
+ }
513
647
  function droppedEntriesCopy(v) {
514
648
  if (!Array.isArray(v))
515
649
  return frozenJsonCopyOf(v) ?? null;
@@ -544,23 +678,27 @@ export function liveDefaultModelOf(catalog = getLiveModelCatalog()) {
544
678
  return Object.freeze({ kind: 'unknown', why: 'unreadable' });
545
679
  }
546
680
  }
681
+ function atMentionBitOf(o) {
682
+ const d = Object.getOwnPropertyDescriptor(o, 'atMentionable');
683
+ if (d === undefined)
684
+ return 'not_governed';
685
+ if (!(Object.hasOwn(d, 'value')))
686
+ return 'unreadable';
687
+ if (d.value === undefined)
688
+ return 'not_governed';
689
+ if (d.value === true)
690
+ return 'allowed';
691
+ if (d.value === false)
692
+ return 'refused';
693
+ return 'malformed';
694
+ }
547
695
  export function atMentionOf(model, catalog = getLiveModelCatalog()) {
548
696
  try {
549
697
  const target = targetRowOf(model, catalog);
550
698
  if (target.kind !== 'row')
551
699
  return Object.freeze({ kind: 'unknown', why: target.why });
552
- const d = Object.getOwnPropertyDescriptor(target.row, 'atMentionable');
553
- if (d === undefined)
554
- return Object.freeze({ kind: 'not_governed' });
555
- if (!(Object.hasOwn(d, 'value')))
556
- return Object.freeze({ kind: 'unknown', why: 'unreadable' });
557
- if (d.value === undefined)
558
- return Object.freeze({ kind: 'not_governed' });
559
- if (d.value === true)
560
- return Object.freeze({ kind: 'allowed' });
561
- if (d.value === false)
562
- return Object.freeze({ kind: 'refused' });
563
- return Object.freeze({ kind: 'unknown', why: 'malformed' });
700
+ const bit = atMentionBitOf(target.row);
701
+ return bit === 'malformed' || bit === 'unreadable' ? Object.freeze({ kind: 'unknown', why: bit }) : Object.freeze({ kind: bit });
564
702
  }
565
703
  catch {
566
704
  return Object.freeze({ kind: 'unknown', why: 'unreadable' });
@@ -1,4 +1,6 @@
1
1
  import { SETTINGS_RESOLVE_CATALOG_DEFAULT_MODEL, type SETTINGS_DEFAULT_ROLE_TIER_LADDER } from '../generated/settingsSchemaFns.js';
2
+ import { SETTINGS_MODEL_PLANE_REFUSAL_CODES } from '../generated/settingsSchemaTables.js';
3
+ import type { UiLanguage } from '../env/uiLanguage.js';
2
4
  export type CatalogDefaultModelsInput = Parameters<typeof SETTINGS_RESOLVE_CATALOG_DEFAULT_MODEL>[0];
3
5
  export type CatalogDefaultSource = 'roles.default' | 'fallback' | `tierGroup.${(typeof SETTINGS_DEFAULT_ROLE_TIER_LADDER)[number]}`;
4
6
  export interface CatalogDefaultDangling {
@@ -22,3 +24,26 @@ export interface CatalogDefaultSelect {
22
24
  }
23
25
  export type CatalogDefaultModel = CatalogDefaultNamed | CatalogDefaultSelect;
24
26
  export declare function resolveCatalogDefaultModel(models: CatalogDefaultModelsInput, has: (name: string) => boolean, fallback: string): CatalogDefaultModel;
27
+ export type CatalogDefaultRefusalCode = Extract<(typeof SETTINGS_MODEL_PLANE_REFUSAL_CODES)[number], 'config.default_model_missing'>;
28
+ export interface CatalogDefaultModelVerdictInput {
29
+ readonly models: CatalogDefaultModelsInput;
30
+ readonly has: (name: string) => boolean;
31
+ readonly fallback: string;
32
+ readonly face: object;
33
+ }
34
+ export interface CatalogDefaultResolvable {
35
+ readonly ok: true;
36
+ readonly default: CatalogDefaultModel;
37
+ }
38
+ export interface CatalogDefaultRefused {
39
+ readonly ok: false;
40
+ readonly code: CatalogDefaultRefusalCode;
41
+ readonly default: CatalogDefaultModel;
42
+ readonly detail: {
43
+ readonly cause: string;
44
+ readonly role: string;
45
+ };
46
+ }
47
+ export type CatalogDefaultModelVerdict = CatalogDefaultResolvable | CatalogDefaultRefused;
48
+ export declare function catalogDefaultModelVerdict(input: CatalogDefaultModelVerdictInput): CatalogDefaultModelVerdict | undefined;
49
+ export declare function catalogDefaultRefusalContent(verdict: CatalogDefaultModelVerdict, lang?: UiLanguage): string | undefined;
@@ -1,4 +1,48 @@
1
1
  import { SETTINGS_RESOLVE_CATALOG_DEFAULT_MODEL } from '../generated/settingsSchemaFns.js';
2
+ import { modelFaceResolvable } from '../coreValuePorts.js';
3
+ import { slotReadOf } from '../wireFailureShape.js';
4
+ import { displayUntrusted } from '../displayUntrusted.js';
5
+ import { msg, renderMessage } from '../i18n/translate.js';
2
6
  export function resolveCatalogDefaultModel(models, has, fallback) {
3
7
  return SETTINGS_RESOLVE_CATALOG_DEFAULT_MODEL(models, has, fallback);
4
8
  }
9
+ const CATALOG_DEFAULT_REFUSAL_CODE = 'config.default_model_missing';
10
+ export function catalogDefaultModelVerdict(input) {
11
+ const { models, has, fallback, face } = input;
12
+ const chain = resolveCatalogDefaultModel(models, has, fallback);
13
+ const verdict = modelFaceResolvable(face, { spec: { modelRole: 'default' } });
14
+ if (verdict === undefined || typeof verdict !== 'object' || verdict === null)
15
+ return undefined;
16
+ const okSlot = slotReadOf(verdict, 'ok');
17
+ if (okSlot.presence !== 'present')
18
+ return undefined;
19
+ if (okSlot.value === true)
20
+ return Object.freeze({ ok: true, default: chain });
21
+ if (okSlot.value !== false)
22
+ return undefined;
23
+ const codeSlot = slotReadOf(verdict, 'code');
24
+ const roleSlot = slotReadOf(verdict, 'role');
25
+ const code = codeSlot.presence === 'present' ? codeSlot.value : undefined;
26
+ const role = roleSlot.presence === 'present' ? roleSlot.value : undefined;
27
+ if (typeof code !== 'string' || code.length === 0 || typeof role !== 'string' || role.length === 0)
28
+ return undefined;
29
+ return Object.freeze({
30
+ ok: false,
31
+ code: CATALOG_DEFAULT_REFUSAL_CODE,
32
+ default: chain,
33
+ detail: Object.freeze({ cause: code, role }),
34
+ });
35
+ }
36
+ export function catalogDefaultRefusalContent(verdict, lang) {
37
+ if (typeof verdict !== 'object' || verdict === null || verdict.ok !== false)
38
+ return undefined;
39
+ const d = verdict.default;
40
+ if (typeof d !== 'object' || d === null)
41
+ return undefined;
42
+ if (d.kind === 'named' && typeof d.name === 'string') {
43
+ return renderMessage(msg('model.catalogDefault.refused.named', { name: displayUntrusted(d.name, { max: 64 }) }), lang);
44
+ }
45
+ if (d.kind === 'select')
46
+ return renderMessage(msg('model.catalogDefault.refused.select'), lang);
47
+ return undefined;
48
+ }
@@ -102,6 +102,8 @@ const OCCURRENCE_KEY_BY_CODE = Object.freeze({
102
102
  'memory.hold_released': 'reportId',
103
103
  'memory.hold_disposed': 'reportId',
104
104
  'memory.consolidation_recommended': 'reportId',
105
+ 'memory.harvest_refused': 'reportId',
106
+ 'memory.harvest_conflict': 'reportId',
105
107
  'memory.capture_opted_out': 'sessionId',
106
108
  'memory.delegation_static_mark_waived': 'runId',
107
109
  });
@@ -4,6 +4,7 @@ export type { PermissionMode };
4
4
  export interface PermissionModeField {
5
5
  permissionMode?: PermissionMode;
6
6
  }
7
+ export declare function permissionModeTitle(word: string): string | undefined;
7
8
  export declare function permissionModeField(mode: string | undefined, opts?: {
8
9
  stampDefault?: boolean;
9
10
  permissionModes?: PermissionModesReading | undefined;
@@ -2,6 +2,17 @@ import { PERMISSION_MODE_WORDS } from './taskRequestWords.js';
2
2
  import { permissionModeAdmitted } from './permissionModesCapability.js';
3
3
  const _permissionModePin = true;
4
4
  void _permissionModePin;
5
+ const PERMISSION_MODE_TITLES = {
6
+ default: 'Manual',
7
+ acceptEdits: 'Accept edits',
8
+ plan: 'Plan',
9
+ auto: 'Auto',
10
+ bypassPermissions: 'Bypass Permissions',
11
+ dontAsk: "Don't Ask",
12
+ };
13
+ export function permissionModeTitle(word) {
14
+ return typeof word === 'string' && Object.hasOwn(PERMISSION_MODE_TITLES, word) ? PERMISSION_MODE_TITLES[word] : undefined;
15
+ }
5
16
  const BIT_GATED_MODE = 'dontAsk';
6
17
  const KNOWN = new Set(PERMISSION_MODE_WORDS.filter((w) => w !== BIT_GATED_MODE));
7
18
  export function permissionModeField(mode, opts) {
@@ -8,11 +8,11 @@ export declare const ENGINE_FIRED_HOOK_EVENTS: readonly ["PreToolUse", "PostTool
8
8
  export type EngineFiredHookEvent = (typeof ENGINE_FIRED_HOOK_EVENTS)[number];
9
9
  export declare const PLUGIN_HOOK_DISPOSITIONS: readonly ["engine", "shell", "not_run"];
10
10
  export type PluginHookDisposition = (typeof PLUGIN_HOOK_DISPOSITIONS)[number];
11
- export declare const PLUGIN_HOOK_REASONS: readonly ["projected", "shell_event", "no_executor", "engine_not_local", "engine_locality_unknown", "engine_capability_absent", "engine_capability_unknown", "not_command", "sensitive_options", "engine_limit", "shell_form_user_config", "user_config_unset", "malformed_entry", "engine_hooks_off", "engine_hooks_unknown", "engine_type_skipped", "engine_llm_limit", "engine_unconfirmed", "engine_elsewhere", "hooks_module", "scope_unsupported", "source_incomplete", "compaction_local_fallback"];
11
+ export declare const PLUGIN_HOOK_REASONS: readonly ["projected", "shell_event", "no_executor", "engine_not_local", "engine_locality_unknown", "engine_capability_absent", "engine_capability_unknown", "not_command", "sensitive_options", "engine_limit", "shell_form_user_config", "user_config_unset", "malformed_entry", "engine_hooks_off", "engine_hooks_unknown", "engine_type_skipped", "engine_llm_limit", "engine_unconfirmed", "engine_elsewhere", "hooks_module", "scope_unsupported", "source_incomplete", "compaction_local_fallback", "key_not_read", "source_not_authored"];
12
12
  export type PluginHookReason = (typeof PLUGIN_HOOK_REASONS)[number];
13
13
  export declare const PLUGIN_HOOK_EXCLUSION_REASONS: readonly ["workspace_untrusted", "governance_unreadable", "policy_disable_all", "startup_mode", "managed_plugins_only", "prompt_not_user_authored"];
14
14
  export type PluginHookExclusionReason = (typeof PLUGIN_HOOK_EXCLUSION_REASONS)[number];
15
- export declare const SETTINGS_HOOK_DROP_REASONS: readonly ["exec_form_unsupported", "mcp_tool_unsupported"];
15
+ export declare const SETTINGS_HOOK_DROP_REASONS: readonly ["exec_form_unsupported", "mcp_tool_unsupported", "key_not_read", "source_not_authored"];
16
16
  export type SettingsHookDropReason = (typeof SETTINGS_HOOK_DROP_REASONS)[number];
17
17
  export type HookSettingsSource = 'policySettings' | 'userSettings' | 'projectSettings' | 'localSettings' | 'flagSettings';
18
18
  export interface PluginHookKey {
@@ -36,6 +36,7 @@ export interface SettingsHookDrop {
36
36
  readonly hookIndex: number;
37
37
  readonly reason: SettingsHookDropReason;
38
38
  readonly notRun: boolean;
39
+ readonly unreadKeys?: readonly (readonly (string | number)[])[];
39
40
  }
40
41
  export interface SettingsHookVerdict {
41
42
  readonly source: HookSettingsSource;
@@ -147,6 +148,7 @@ export interface PluginHookDecisionInput {
147
148
  readonly promptAuthoredByUser: boolean;
148
149
  readonly occupied: ReadonlyMap<string, EventOccupancy>;
149
150
  readonly suppressedLocally?: ReadonlySet<string>;
151
+ readonly readerNotRead: readonly string[];
150
152
  }
151
153
  export interface PluginHookDecision {
152
154
  readonly verdicts: readonly PluginHookVerdict[];
@@ -166,7 +168,7 @@ export declare function decideSessionHooks(input: SessionHookDecisionInput): {
166
168
  readonly verdicts: readonly SessionHookVerdict[];
167
169
  readonly unreadable: number;
168
170
  };
169
- export declare function filterSettingsHookGroups(source: HookSettingsSource, event: string, groups: readonly WireHookGroup[], execFormCapable: boolean, shellRunsType: (type: string | undefined) => boolean, judge: SettingsHookJudge, mask?: HooksSalvageMask): SettingsHookFilterResult;
171
+ export declare function filterSettingsHookGroups(source: HookSettingsSource, event: string, groups: readonly WireHookGroup[], execFormCapable: boolean, shellRunsType: (type: string | undefined) => boolean, judge: SettingsHookJudge, readerNotRead: readonly string[], mask?: HooksSalvageMask): SettingsHookFilterResult;
170
172
  export interface SettingsHookFilterResult {
171
173
  readonly groups: WireHookGroup[];
172
174
  readonly drops: SettingsHookDrop[];