@sema-agent/client-core 0.104.1 → 0.105.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 (86) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/README.md +11 -4
  3. package/dist/adapt/arms.js +14 -6
  4. package/dist/adapter/activeRunSelfHeal.d.ts +1 -0
  5. package/dist/adapter/activeRunSelfHeal.js +10 -5
  6. package/dist/adapter/downstream/eventToSdkMessage.js +4 -4
  7. package/dist/adapter/downstream/wiringManifestView.d.ts +6 -0
  8. package/dist/adapter/downstream/wiringManifestView.js +25 -0
  9. package/dist/adapter/runStream.js +5 -1
  10. package/dist/cloudConfigWireCaps.js +3 -0
  11. package/dist/compensations.js +6 -6
  12. package/dist/coreValuePorts.d.ts +3 -1
  13. package/dist/coreValuePorts.js +4 -0
  14. package/dist/displayUntrusted.d.ts +4 -2
  15. package/dist/displayUntrusted.js +45 -22
  16. package/dist/engineGenerationPort.d.ts +11 -2
  17. package/dist/engineGenerationPort.js +63 -9
  18. package/dist/engineHealthFacts.d.ts +5 -0
  19. package/dist/engineHealthFacts.js +11 -0
  20. package/dist/eventLeg.d.ts +1 -1
  21. package/dist/eventLeg.js +23 -3
  22. package/dist/generated/engineFactTables.d.ts +1 -0
  23. package/dist/generated/engineFactTables.js +1 -0
  24. package/dist/generated/sdkFactTables.d.ts +2 -0
  25. package/dist/generated/sdkFactTables.js +9 -0
  26. package/dist/headlessReconnectWire.js +31 -4
  27. package/dist/hitl/askGateWire.js +26 -2
  28. package/dist/hitl/frameRouter.d.ts +4 -0
  29. package/dist/hitl/frameRouter.js +14 -0
  30. package/dist/hitl/gateIdentity.d.ts +1 -0
  31. package/dist/hitl/gateIdentity.js +3 -0
  32. package/dist/hitl/planReviewCard.d.ts +21 -0
  33. package/dist/hitl/planReviewCard.js +229 -0
  34. package/dist/hitl/planReviewWire.d.ts +38 -13
  35. package/dist/hitl/planReviewWire.js +355 -133
  36. package/dist/hostSettingsSource.d.ts +1 -1
  37. package/dist/hostSettingsSource.js +8 -4
  38. package/dist/hostTurnSettings.d.ts +1 -1
  39. package/dist/hostTurnSettings.js +29 -10
  40. package/dist/i18n/messages.en.d.ts +50 -0
  41. package/dist/i18n/messages.en.js +50 -0
  42. package/dist/i18n/messages.zh.js +51 -0
  43. package/dist/index.d.ts +15 -3
  44. package/dist/index.js +9 -1
  45. package/dist/mcpTransportKindsCapability.d.ts +18 -0
  46. package/dist/mcpTransportKindsCapability.js +75 -0
  47. package/dist/mcpWireCaps.d.ts +4 -1
  48. package/dist/mcpWireCaps.js +24 -13
  49. package/dist/notifications.d.ts +9 -0
  50. package/dist/notifications.js +11 -2
  51. package/dist/ownKey.d.ts +4 -0
  52. package/dist/ownKey.js +8 -0
  53. package/dist/permissionModeWriteCapability.d.ts +13 -0
  54. package/dist/permissionModeWriteCapability.js +35 -0
  55. package/dist/permissionsAllowGrantCapability.d.ts +3 -0
  56. package/dist/permissionsAllowGrantCapability.js +26 -3
  57. package/dist/permissionsDeclaration.d.ts +23 -1
  58. package/dist/permissionsDeclaration.js +60 -30
  59. package/dist/planReviewCardFacts.d.ts +116 -0
  60. package/dist/planReviewCardFacts.js +469 -0
  61. package/dist/reattachWindow.d.ts +8 -1
  62. package/dist/reattachWindow.js +44 -12
  63. package/dist/runFollow.d.ts +30 -0
  64. package/dist/runFollow.js +117 -0
  65. package/dist/runLedgerSnapshot.d.ts +20 -0
  66. package/dist/runLedgerSnapshot.js +272 -0
  67. package/dist/runPermissionModeSwitch.d.ts +57 -0
  68. package/dist/runPermissionModeSwitch.js +135 -0
  69. package/dist/runReattachPolicy.d.ts +13 -5
  70. package/dist/runReattachPolicy.js +58 -23
  71. package/dist/seam.d.ts +3 -0
  72. package/dist/seam.js +1 -1
  73. package/dist/seatContract.js +1 -0
  74. package/dist/sessionMemoryErase.d.ts +1 -1
  75. package/dist/sessionMemoryErase.js +5 -0
  76. package/dist/sessionMemoryStatus.d.ts +27 -1
  77. package/dist/sessionMemoryStatus.js +117 -0
  78. package/dist/sseIdleTriage.d.ts +3 -1
  79. package/dist/sseIdleTriage.js +19 -4
  80. package/dist/subagent/engineSubagentTail.js +2 -0
  81. package/dist/subagentContentStore.d.ts +3 -0
  82. package/dist/subagentContentStore.js +10 -1
  83. package/dist/turnFailurePresentation.d.ts +5 -2
  84. package/dist/turnFailurePresentation.js +12 -4
  85. package/docs/INTEGRATION-CLIENTS.md +493 -10
  86. package/package.json +2 -2
@@ -121,7 +121,7 @@ export interface HostSettingsAdoption {
121
121
  };
122
122
  readonly overflow?: true;
123
123
  }
124
- export declare function adoptHostSettingsRead(read: HostSettingsRead, session: HostSettingsSession, allowAdmitted?: (layer: AdoptedLayer) => boolean): HostSettingsAdoption;
124
+ export declare function adoptHostSettingsRead(read: HostSettingsRead, session: HostSettingsSession, allowAdmitted?: (layer: AdoptedLayer) => boolean, layeredRules?: boolean): HostSettingsAdoption;
125
125
  export type ManagedCommitVerdict = 'proceed' | 'refuse';
126
126
  export type ManagedRuleScopeVerdict = 'all-sources' | 'by-switch' | 'degrade';
127
127
  export type ManagedHooksRestrictionVerdict = 'use-read' | 'held-restrictions' | 'withhold';
@@ -524,7 +524,7 @@ function overflowOf(read, session) {
524
524
  return Object.freeze({ read, session: remintSameContent(session), trusted: false, clean: false, extraTighten: NO_EXTRA, allowByLayer: emptyByLayer(), overflow: true });
525
525
  }
526
526
  const carrierKeysOf = (read, layer) => read.layers[layer].carriers.map((c) => c.id);
527
- export function adoptHostSettingsRead(read, session, allowAdmitted = () => true) {
527
+ export function adoptHostSettingsRead(read, session, allowAdmitted = () => true, layeredRules = false) {
528
528
  const B = session.baseline;
529
529
  const stackIssues = ADOPTED_LAYERS.flatMap((l) => read.layers[l].issues.map((x) => `${l}|${x}`));
530
530
  const loadedNow = ADOPTED_LAYERS.flatMap((l) => read.layers[l].malformed ? [] : read.layers[l].carriers.filter((c) => LOADED.has(c.status) || (c.status === 'empty' && c.emptyKind === 'empty-object')).map((c) => `${l}|${c.id}`));
@@ -627,9 +627,13 @@ export function adoptHostSettingsRead(read, session, allowAdmitted = () => true)
627
627
  effectiveLayers[l] = l === 'policySettings' ? snap : Object.freeze({ ...snap, doc: base.docs[l] });
628
628
  }
629
629
  const effective = Object.freeze({ ...read, layers: Object.freeze(effectiveLayers), current: read, debug: Object.freeze([]) });
630
- const sentNow = (bucket) => new Set([...ADOPTED_LAYERS.flatMap((l) => permissionRulesOf(base.docs[l], bucket)), ...extraTighten[bucket].map((r) => r.rule)]);
631
- const readNow = (bucket) => new Set(ADOPTED_LAYERS.flatMap((l) => permissionRulesOf(read.layers[l].doc, bucket)));
632
- const drop = (bucket) => Object.freeze([...sentNow(bucket)].filter((r) => !readNow(bucket).has(r)).sort());
630
+ const idOf = (layer, rule) => (layeredRules ? JSON.stringify([layer, rule]) : rule);
631
+ const sentNow = (bucket) => [...ADOPTED_LAYERS.flatMap((l) => permissionRulesOf(base.docs[l], bucket).map((rule) => ({ layer: l, rule }))), ...extraTighten[bucket]];
632
+ const readNow = (bucket) => new Set(ADOPTED_LAYERS.flatMap((l) => permissionRulesOf(read.layers[l].doc, bucket).map((rule) => idOf(l, rule))));
633
+ const drop = (bucket) => {
634
+ const now = readNow(bucket);
635
+ return Object.freeze([...new Set(sentNow(bucket).filter((r) => !now.has(idOf(r.layer, r.rule))).map((r) => r.rule))].sort());
636
+ };
633
637
  const wouldDrop = Object.freeze({ deny: drop('deny'), ask: drop('ask') });
634
638
  const acceptable = !stackIssues.some((x) => !base.issues.includes(x)) && !anyMalformed && !ADOPTED_LAYERS.some((l) => read.layers[l].carriers.some((c) => c.status === 'unreadable' || c.status === 'not-loaded'));
635
639
  const s = mintHostSettingsSession(parentVersionOf(session), session.consented, baseline);
@@ -8,7 +8,7 @@ import { type HostSettingsSession, type HostSettingsSource } from './hostSetting
8
8
  import { type SubmissionIdentity } from './request/submissionIdentity.js';
9
9
  import { type WebSearchApiKeyFor } from './webSearchWireCaps.js';
10
10
  import { type FileHistoryCaptureReading } from './fileHistoryCaptureCapability.js';
11
- import type { PermissionsAllowGrantReading } from './permissionsAllowGrantCapability.js';
11
+ import { type PermissionsAllowGrantReading } from './permissionsAllowGrantCapability.js';
12
12
  export declare const HOST_SUPPLIED_KEYS: readonly ["settings.hooks", "settings.resolved", "settings.webSearch", "settings.outputStyle", "memory", "fileHistory"];
13
13
  export type HostSuppliedKey = (typeof HOST_SUPPLIED_KEYS)[number];
14
14
  export declare const HOST_SETTING_CAUSES: readonly ["carried", "entries_dropped", "source_rejected", "projection_failed", "source_unreadable", "empty", "no_source", "host_port_missing", "value_malformed", "held_previous", "policy_withheld"];
@@ -10,6 +10,7 @@ import { fileHistoryTightenVerdict, fileHistoryUnjudgedRefusal } from './fileHis
10
10
  import { msg, renderMessage } from './i18n/translate.js';
11
11
  import { newRulePortsProjection, projectPermissionsDeclaration, rulePortsMissingOf, WIRE_RULE_TRUST_ORDER } from './permissionsDeclaration.js';
12
12
  import { assemblyRefusalOf } from './wireFailureShape.js';
13
+ import { permissionRuleLayersOn } from './permissionsAllowGrantCapability.js';
13
14
  import { layerAdmitted } from './settingsLayerAdmission.js';
14
15
  import { appendOwnElement, ownDataField } from './ownKey.js';
15
16
  export const HOST_SUPPLIED_KEYS = Object.freeze(['settings.hooks', 'settings.resolved', 'settings.webSearch', 'settings.outputStyle', 'memory', 'fileHistory']);
@@ -388,15 +389,15 @@ function allowAdmittedFor(read) {
388
389
  function badPermissionsSource() {
389
390
  return new HostSourceShapeError(`hostTurnSettings: sources.resolved must be 'none' or { allowGrantReading, cliArg?, session?, clientOwnedServers?, serverVersion? } — since 0.101.0 the permission rules of the settings files come from the settings the entry reads; do not pass snapshot — got something else (the value is not echoed).`);
390
391
  }
391
- function permissionsArm(src, side, adoption) {
392
+ function readPermissionSource(src) {
392
393
  const key = 'settings.resolved';
393
394
  if (src.kind === 'missing')
394
- return missingArm(key);
395
+ return { kind: 'arm', arm: missingArm(key) };
395
396
  if (src.kind === 'threw')
396
- return unreadableArm(key);
397
+ return { kind: 'arm', arm: unreadableArm(key) };
397
398
  const v = src.value;
398
399
  if (v === 'none')
399
- return noSourceArm(key);
400
+ return { kind: 'arm', arm: noSourceArm(key) };
400
401
  let allowGrantReading;
401
402
  let cliAllow;
402
403
  let cliDeny;
@@ -415,7 +416,7 @@ function permissionsArm(src, side, adoption) {
415
416
  const se = ownDataOf(v, 'session');
416
417
  const o = ownDataOf(v, 'clientOwnedServers');
417
418
  if (!g.ok || !c.ok || !se.ok || !o.ok)
418
- return unreadableArm(key);
419
+ return { kind: 'arm', arm: unreadableArm(key) };
419
420
  allowGrantReading = g.value;
420
421
  const cv = c.value;
421
422
  const sv = se.value;
@@ -428,7 +429,7 @@ function permissionsArm(src, side, adoption) {
428
429
  const sd = sv === undefined ? { ok: true, value: undefined } : ownDataOf(sv, 'deny');
429
430
  const sa = sv === undefined ? { ok: true, value: undefined } : ownDataOf(sv, 'ask');
430
431
  if (!ca.ok || !cd.ok || !sd.ok || !sa.ok)
431
- return unreadableArm(key);
432
+ return { kind: 'arm', arm: unreadableArm(key) };
432
433
  cliAllow = stringListOf(ca.value);
433
434
  cliDeny = stringListOf(cd.value);
434
435
  sesDeny = stringListOf(sd.value);
@@ -439,16 +440,32 @@ function permissionsArm(src, side, adoption) {
439
440
  catch (e) {
440
441
  if (e instanceof HostSourceShapeError)
441
442
  throw e;
442
- return unreadableArm(key);
443
+ return { kind: 'arm', arm: unreadableArm(key) };
443
444
  }
444
445
  if (cliAllow === undefined || cliDeny === undefined || sesDeny === undefined || sesAsk === undefined || (owned === undefined && ownedRaw !== undefined))
445
446
  throw badPermissionsSource();
447
+ return { kind: 'facts', allowGrantReading, cliAllow, cliDeny, sesDeny, sesAsk, owned, serverVersion };
448
+ }
449
+ function permissionsArm(facts, side, adoption, layered) {
450
+ const key = 'settings.resolved';
451
+ if (facts.kind === 'arm')
452
+ return facts.arm;
453
+ const { allowGrantReading, cliAllow, cliDeny, sesDeny, sesAsk, owned, serverVersion } = facts;
446
454
  if (side.kind === 'missing')
447
455
  return missingArm(key);
448
456
  const buckets = { deny: [], ask: [], allow: [] };
449
457
  const origins = { deny: new Map(), ask: new Map(), allow: new Map() };
450
458
  const rank = (o) => WIRE_RULE_TRUST_ORDER.indexOf(o);
459
+ const contributions = { deny: [], ask: [] };
460
+ const contributed = { deny: new Set(), ask: new Set() };
451
461
  const add = (bucket, rule, origin) => {
462
+ if (bucket !== 'allow') {
463
+ const k = JSON.stringify([origin, rule]);
464
+ if (!contributed[bucket].has(k)) {
465
+ contributed[bucket].add(k);
466
+ appendOwnElement(contributions[bucket], freeze({ rule, origin }));
467
+ }
468
+ }
452
469
  const prev = origins[bucket].get(rule);
453
470
  if (prev === undefined) {
454
471
  appendOwnElement(buckets[bucket], rule);
@@ -504,7 +521,7 @@ function permissionsArm(src, side, adoption) {
504
521
  let declared;
505
522
  if (projectionError === undefined) {
506
523
  try {
507
- const d = projectPermissionsDeclaration({ deny: buckets.deny, ask: buckets.ask, allow: buckets.allow, origins, cliDeny, settingsRead: 'clean', ...(owned !== undefined && owned.length > 0 ? { clientOwnedServers: owned } : {}), ...(serverVersion !== undefined ? { serverVersion } : {}) }, allowGrantReading, portsProjection);
524
+ const d = projectPermissionsDeclaration({ deny: buckets.deny, ask: buckets.ask, allow: buckets.allow, origins, cliDeny, settingsRead: 'clean', ...(owned !== undefined && owned.length > 0 ? { clientOwnedServers: owned } : {}), ...(serverVersion !== undefined ? { serverVersion } : {}) }, allowGrantReading, portsProjection, layered ? freeze({ deny: freeze([...contributions.deny]), ask: freeze([...contributions.ask]) }) : undefined);
508
525
  declared = d.permissions !== undefined ? { permissions: d.permissions } : undefined;
509
526
  }
510
527
  catch (error) {
@@ -615,10 +632,12 @@ export function buildHostTurnSettings(input, judges) {
615
632
  if (rawSide.kind === 'read')
616
633
  for (const line of rawSide.read.debug)
617
634
  hostLog('debug', line);
618
- const adoption = rawSide.kind === 'read' ? adoptHostSettingsRead(rawSide.read, session, allowAdmittedFor(rawSide.read)) : undefined;
635
+ const permissionSource = readPermissionSource(read('resolved'));
636
+ const layeredRules = permissionSource.kind === 'facts' && permissionRuleLayersOn(permissionSource.allowGrantReading);
637
+ const adoption = rawSide.kind === 'read' ? adoptHostSettingsRead(rawSide.read, session, allowAdmittedFor(rawSide.read), layeredRules) : undefined;
619
638
  const side = adoption !== undefined ? { kind: 'read', read: adoption.read } : rawSide;
620
639
  const nextSession = adoption?.session ?? remintSameContent(session);
621
- const resolvedArm = permissionsArm(read('resolved'), side, adoption);
640
+ const resolvedArm = permissionsArm(permissionSource, side, adoption, layeredRules);
622
641
  let resolvedCarried = resolvedArm.carried;
623
642
  let resolvedError;
624
643
  if (resolvedCarried !== undefined) {
@@ -187,6 +187,8 @@ declare const EN: {
187
187
  'config.mcp.nameReserved': string;
188
188
  'config.mcp.identityHeadersBothSet': string;
189
189
  'config.mcp.transportUnreadable': string;
190
+ 'config.mcp.transportNotAdvertised': string;
191
+ 'config.mcp.transportsNone': string;
190
192
  'config.mcp.transportInvalid': string;
191
193
  'config.mcp.transportDegraded': string;
192
194
  'config.mcp.toolAxesInvalid': string;
@@ -547,6 +549,13 @@ declare const EN: {
547
549
  'session.fileHistoryRefusal.notSaid': string;
548
550
  'session.fileHistoryRefusal.unrecognized': string;
549
551
  'session.fileHistoryRefusal.unreadable': string;
552
+ 'session.memoryErase.personalStoreUnjudged': string;
553
+ 'session.memorySync.parked.one': string;
554
+ 'session.memorySync.parked.other': string;
555
+ 'session.memorySync.parkedUnnamed.one': string;
556
+ 'session.memorySync.parkedUnnamed.other': string;
557
+ 'session.memorySync.wayOut.deleteCursor': string;
558
+ 'session.memorySync.wayOut.unrecognized': string;
550
559
  'session.hostSettings.memorySwitchMalformed': string;
551
560
  'session.hostSettings.fileHistoryRestoreConflict': string;
552
561
  'session.hostSettings.projectionUnchecked': string;
@@ -670,6 +679,18 @@ declare const EN: {
670
679
  'session.steerRefusal.advice': string;
671
680
  'session.steerRefusal.hostQueue.queued': string;
672
681
  'session.steerRefusal.hostQueue.dropped': string;
682
+ 'session.permissionModeSwitch.applied': string;
683
+ 'session.permissionModeSwitch.folded': string;
684
+ 'session.permissionModeSwitch.reason.entryFloor': string;
685
+ 'session.permissionModeSwitch.reason.disableAutoMode': string;
686
+ 'session.permissionModeSwitch.reason.engine': string;
687
+ 'session.permissionModeSwitch.notPersisted': string;
688
+ 'session.permissionModeSwitch.notRunning': string;
689
+ 'session.permissionModeSwitch.notFound': string;
690
+ 'session.permissionModeSwitch.refused': string;
691
+ 'session.permissionModeSwitch.refusedWithCode': string;
692
+ 'session.permissionModeSwitch.unconfirmed': string;
693
+ 'session.permissionModeSwitch.unavailable': string;
673
694
  'notice.capability.subject.userInvokedSkills': string;
674
695
  'notice.capability.subject.skillToolLists': string;
675
696
  'notice.capability.subject.permissionRulesWrite': string;
@@ -1053,6 +1074,35 @@ declare const EN: {
1053
1074
  'config.mods.refusal.by': string;
1054
1075
  'config.mods.rewrite.resultInPlace': string;
1055
1076
  'config.mods.rewrite.inputBy': string;
1077
+ 'follow.notFollowed.headRun': string;
1078
+ 'follow.notFollowed.headTurn': string;
1079
+ 'follow.notFollowed.reason.exhaustedDraining': string;
1080
+ 'follow.notFollowed.reason.exhaustedConnectionLost': string;
1081
+ 'follow.notFollowed.reason.exhaustedStreamCap': string;
1082
+ 'follow.notFollowed.reason.exhausted': string;
1083
+ 'follow.notFollowed.reason.badInput': string;
1084
+ 'follow.notFollowed.reason.noRunId': string;
1085
+ 'follow.notFollowed.reason.runUnknown': string;
1086
+ 'follow.notFollowed.reason.unspecified': string;
1087
+ 'follow.notFollowed.endingUnknown': string;
1088
+ 'follow.notFollowed.exit.reattach': string;
1089
+ 'follow.notFollowed.exit.checkRuns': string;
1090
+ 'follow.notFollowed.exit.runUnknown': string;
1091
+ 'follow.notFollowed.idleTear': string;
1092
+ 'follow.notFollowed.idleGrace': string;
1093
+ 'approval.planReview.note.empty': string;
1094
+ 'approval.planReview.note.marked': string;
1095
+ 'approval.planReview.note.tooLarge': string;
1096
+ 'approval.planReview.note.notCarried': string;
1097
+ 'approval.planReview.note.unknown': string;
1098
+ 'approval.planReview.askAgain.shown': string;
1099
+ 'approval.planReview.askAgain.marked': string;
1100
+ 'approval.planReview.askAgain.tooLarge': string;
1101
+ 'approval.planReview.askAgain.notCarried': string;
1102
+ 'approval.planReview.askAgain.unknown': string;
1103
+ 'approval.planReview.askAgain.withNote': string;
1104
+ 'approval.planReview.option.askAgain.label': string;
1105
+ 'approval.planReview.option.askAgain.description': string;
1056
1106
  };
1057
1107
  export declare const EN_MESSAGES: Readonly<typeof EN>;
1058
1108
  export type MessageKey = keyof typeof EN;
@@ -187,6 +187,8 @@ const EN = {
187
187
  'config.mcp.nameReserved': 'MCP server name {name}{where} cannot be used, so the server was not started: names starting with "remote-" are kept for the MCP servers a connected device offers. Rename the server.',
188
188
  'config.mcp.identityHeadersBothSet': 'MCP server {name}{where} was not started: it sets both principalHeader and assertionHeader, which name the same identity header — keep only one of the two. The other MCP servers are unaffected.',
189
189
  'config.mcp.transportUnreadable': 'could not be read (a getter or proxy trap on the declaration threw)',
190
+ 'config.mcp.transportNotAdvertised': 'MCP server {name}{where} was not started: it uses the {kind} transport, which the engine in use says it does not support (it supports: {supported}). The other MCP servers are unaffected.',
191
+ 'config.mcp.transportsNone': 'none',
190
192
  'config.mcp.transportInvalid': 'MCP server {name}{where} was not started: its transport setting cannot be used — {path} {problem}. Fix that setting for this server (or remove the server); the other MCP servers are unaffected.',
191
193
  'config.mcp.transportDegraded': 'MCP server {name}{where} was started without part of its transport settings, which cannot be used as written: {lost}. The rest of its settings are applied; fix the settings named above to get them applied too.',
192
194
  'config.mcp.toolAxesInvalid': 'MCP server {name}{where} was not started: its toolAxes setting is not valid — {problem}. Fix the toolAxes entry for this server (or remove it); the other MCP servers are unaffected.',
@@ -547,6 +549,13 @@ const EN = {
547
549
  'session.fileHistoryRefusal.notSaid': 'Nothing was sent: file checkpointing is turned off in your settings, but this engine did not report whether it can stop recording file history for a session, so sending now could record it anyway. Trying again will not change that while this engine reports the same; to send and let file history be recorded this time, turn file checkpointing back on in your settings.',
548
550
  'session.fileHistoryRefusal.unrecognized': 'Nothing was sent: file checkpointing is turned off in your settings, but this engine reported a file-history capture mode this client does not recognize, so whether it can stop recording file history for a session is unknown and sending now could record it anyway. Trying again will not change that while this engine reports the same; to send and let file history be recorded this time, turn file checkpointing back on in your settings.',
549
551
  'session.fileHistoryRefusal.unreadable': "Nothing was sent: file checkpointing is turned off in your settings, but this engine's report on whether it can stop recording file history for a session could not be read by this client, so sending now could record it anyway. Trying again will not change that while this engine reports the same; to send and let file history be recorded this time, turn file checkpointing back on in your settings.",
552
+ 'session.memoryErase.personalStoreUnjudged': "Nothing was erased: part of this session's memory is kept in a personal memory store that this deployment cannot erase yet, so the erase was declined before anything changed.",
553
+ 'session.memorySync.parked.one': 'Memory sync is paused on this deployment for the "{scope}" layer: its sync cursor could not be used. {wayOut}',
554
+ 'session.memorySync.parked.other': 'Memory sync is paused on this deployment for {count} layers ({scopes}): their sync cursors could not be used. {wayOut}',
555
+ 'session.memorySync.parkedUnnamed.one': 'Memory sync is paused on this deployment for 1 layer: its sync cursor could not be used. {wayOut}',
556
+ 'session.memorySync.parkedUnnamed.other': 'Memory sync is paused on this deployment for {count} layers: their sync cursors could not be used. {wayOut}',
557
+ 'session.memorySync.wayOut.deleteCursor': 'Syncing resumes once an operator deletes the sync cursor of each paused layer on the server; entries deleted on only one side since the last sync will come back and need to be deleted again.',
558
+ 'session.memorySync.wayOut.unrecognized': 'The deployment named a way out that this client does not recognize, so none is suggested here.',
550
559
  'session.hostSettings.memorySwitchMalformed': 'The memory setting in your settings file could not be read, so turning memory off was not applied: this request was sent with memory available. Fix the memory section (memory.enabled must be true or false) to turn it off.',
551
560
  'session.hostSettings.fileHistoryRestoreConflict': 'Nothing was sent: file checkpointing was turned off in your settings after this request was prepared, but this request also restores files from a checkpoint, and a request cannot do both. To restore the files, turn file checkpointing back on in your settings; otherwise send the request without the file restore.',
552
561
  'session.hostSettings.projectionUnchecked': 'The settings for this request could not be checked before sending, so the request is not sent. Reload your settings and try again.',
@@ -670,6 +679,18 @@ const EN = {
670
679
  'session.steerRefusal.advice': '{happened} — {nextStep}',
671
680
  'session.steerRefusal.hostQueue.queued': 'it stays queued and will be submitted as-is when this turn ends',
672
681
  'session.steerRefusal.hostQueue.dropped': 'it was not kept; {nextStep}',
682
+ 'session.permissionModeSwitch.applied': 'The running turn now uses the {mode} permission mode.',
683
+ 'session.permissionModeSwitch.folded': 'The running turn now uses the {mode} permission mode instead of the one you chose — {reason}.',
684
+ 'session.permissionModeSwitch.reason.entryFloor': 'this deployment does not allow a looser mode than its floor',
685
+ 'session.permissionModeSwitch.reason.disableAutoMode': "this task's settings turn auto mode off",
686
+ 'session.permissionModeSwitch.reason.engine': 'the engine does not allow the chosen mode for this run',
687
+ 'session.permissionModeSwitch.notPersisted': '{line} The switch was not saved with the run: if the run pauses and later resumes, it resumes in the mode it had before, so switch again after it resumes.',
688
+ 'session.permissionModeSwitch.notRunning': 'This run is not running a turn right now (it is paused waiting on a decision, has finished, or is running elsewhere), so its mode was not switched.',
689
+ 'session.permissionModeSwitch.notFound': 'No such run is visible to you, so no mode was switched.',
690
+ 'session.permissionModeSwitch.refused': 'The engine refused to switch the mode of this run ({status}), so it keeps the mode it had.',
691
+ 'session.permissionModeSwitch.refusedWithCode': 'The engine refused to switch the mode of this run ({status} {code}), so it keeps the mode it had.',
692
+ 'session.permissionModeSwitch.unconfirmed': 'The switch was sent but no readable answer came back, so whether the mode changed is not known — switch again to be sure.',
693
+ 'session.permissionModeSwitch.unavailable': 'Switching the mode of a running turn is not available here, so the mode was not changed.',
673
694
  'notice.capability.subject.userInvokedSkills': 'user-invoked skills',
674
695
  'notice.capability.subject.skillToolLists': 'skill tool lists',
675
696
  'notice.capability.subject.permissionRulesWrite': 'permission-rule write entry',
@@ -1053,5 +1074,34 @@ const EN = {
1053
1074
  'config.mods.refusal.by': 'Refused by {by}',
1054
1075
  'config.mods.rewrite.resultInPlace': 'Answered by {by} in place of the tool',
1055
1076
  'config.mods.rewrite.inputBy': 'Arguments changed by {by} before the call was let through',
1077
+ 'follow.notFollowed.headRun': 'This screen is no longer following run {taskId}{reason}{ending}{exit}',
1078
+ 'follow.notFollowed.headTurn': "This screen is no longer following this turn's run{reason}{ending}{exit}",
1079
+ 'follow.notFollowed.reason.exhaustedDraining': ": the engine instance serving it was going down when its last event stream closed, and this client's re-attach allowance has run out.",
1080
+ 'follow.notFollowed.reason.exhaustedConnectionLost': ": the connection dropped on the last attempt, and this client's re-attach allowance has run out.",
1081
+ 'follow.notFollowed.reason.exhaustedStreamCap': ": its event stream hit the engine's time limit on the last attempt, and this client's re-attach allowance has run out.",
1082
+ 'follow.notFollowed.reason.exhausted': ": this client's re-attach allowance has run out.",
1083
+ 'follow.notFollowed.reason.badInput': ': this client hit an internal error while re-attaching.',
1084
+ 'follow.notFollowed.reason.noRunId': ': this client never learned which run it was, so there is nothing to re-attach to.',
1085
+ 'follow.notFollowed.reason.runUnknown': ': the engine answered that it does not know that run — it may have been cleaned up, or this client asked with the wrong identity.',
1086
+ 'follow.notFollowed.reason.unspecified': '.',
1087
+ 'follow.notFollowed.endingUnknown': ' The engine has not said how that run ended — it may still be going.',
1088
+ 'follow.notFollowed.exit.reattach': ' What it does next shows up here only after this client re-attaches to it.',
1089
+ 'follow.notFollowed.exit.checkRuns': " Check this session's runs before sending the work again.",
1090
+ 'follow.notFollowed.exit.runUnknown': " Re-attaching will not bring it back here; check this session's runs before sending the work again.",
1091
+ 'follow.notFollowed.idleTear': "This turn's event stream went silent for {secs}s. {notice} {grace}",
1092
+ 'follow.notFollowed.idleGrace': 'If the run legitimately goes quiet this long (e.g. a long build), raising the idle grace may help next time: set {env} (settings env, integer ms, {min}-{max}; default {default}).',
1093
+ 'approval.planReview.note.empty': 'The plan is empty.',
1094
+ 'approval.planReview.note.marked': 'This plan contains characters that cannot be shown as written, so it cannot be approved from this card. Reject it, or ask for the plan to be presented again.',
1095
+ 'approval.planReview.note.tooLarge': 'This plan is too large to be shown in full ({length} characters), so it cannot be approved from this card. Reject it, or ask for a shorter plan.',
1096
+ 'approval.planReview.note.notCarried': "The engine did not bring this plan's text up to this card (it may be too long), so it cannot be approved from this card. Reject it, or ask for the plan to be presented again.",
1097
+ 'approval.planReview.note.unknown': 'This card cannot show the plan it would approve, so it cannot be approved from this card. Reject it, or ask for the plan to be presented again.',
1098
+ 'approval.planReview.askAgain.shown': 'The user asked for the plan to be presented again.',
1099
+ 'approval.planReview.askAgain.marked': 'The user could not approve this plan: it contains characters that cannot be shown as written. Present the plan again without those characters.',
1100
+ 'approval.planReview.askAgain.tooLarge': 'The user could not approve this plan: it is too large to be shown in full. Present a shorter plan.',
1101
+ 'approval.planReview.askAgain.notCarried': 'The user could not approve this plan: its text did not reach the approval card (it may be too long). Present a shorter plan.',
1102
+ 'approval.planReview.askAgain.unknown': 'The user could not approve this plan: the approval card could not show it. Present the plan again.',
1103
+ 'approval.planReview.askAgain.withNote': '{sentence} The user added: {note}',
1104
+ 'approval.planReview.option.askAgain.label': 'No, ask for the plan to be presented again',
1105
+ 'approval.planReview.option.askAgain.description': 'Do not approve; ask the model to present the plan again',
1056
1106
  };
1057
1107
  export const EN_MESSAGES = Object.freeze(EN);
@@ -187,6 +187,8 @@ const ZH = {
187
187
  'config.mcp.nameReserved': 'MCP 服务器名 {name}{where} 不可用,所以没有启动:以 "remote-" 开头的名字留给已连接设备提供的 MCP 服务器。请给这台服务器换个名字。',
188
188
  'config.mcp.identityHeadersBothSet': 'MCP 服务器 {name}{where} 没有启动:它同时设置了 principalHeader 和 assertionHeader,而这两项指的是同一个身份头 —— 只保留其中一项。其他 MCP 服务器不受影响。',
189
189
  'config.mcp.transportUnreadable': '读不出(声明上的取值器或代理陷阱抛了错)',
190
+ 'config.mcp.transportNotAdvertised': 'MCP 服务器 {name}{where} 没有启动:它用的是 {kind} 传输,而这台引擎说它不支持这种传输(它支持:{supported})。其他 MCP 服务器不受影响。',
191
+ 'config.mcp.transportsNone': '无',
190
192
  'config.mcp.transportInvalid': 'MCP 服务器 {name}{where} 没有启动:它的传输设置不可用 —— {path} {problem}。请修正这台服务器的这项设置(或删掉这台服务器);其他 MCP 服务器不受影响。',
191
193
  'config.mcp.transportDegraded': 'MCP 服务器 {name}{where} 已启动,但它的部分传输设置不能照原样使用、被略去了:{lost}。其余设置照常生效;请修正上面点名的设置,让它们也生效。',
192
194
  'config.mcp.toolAxesInvalid': 'MCP 服务器 {name}{where} 没有启动:它的 toolAxes 设置不合法 —— {problem}。请修正这台服务器的 toolAxes(或删掉它);其他 MCP 服务器不受影响。',
@@ -547,6 +549,13 @@ const ZH = {
547
549
  'session.fileHistoryRefusal.notSaid': '没有发送:你的设置里已关闭文件检查点,但这台引擎没有报告它能否按会话停止记录文件历史,所以现在发送仍可能把它记录下来。只要这台引擎还是同样的报告,重试也不会改变这一点;要发送并让这一次的文件历史被记录,请在设置里把文件检查点重新打开。',
548
550
  'session.fileHistoryRefusal.unrecognized': '没有发送:你的设置里已关闭文件检查点,但这台引擎报告了一个本客户端不认识的文件历史捕获模式,所以不知道它能否按会话停止记录文件历史,现在发送仍可能把它记录下来。只要这台引擎还是同样的报告,重试也不会改变这一点;要发送并让这一次的文件历史被记录,请在设置里把文件检查点重新打开。',
549
551
  'session.fileHistoryRefusal.unreadable': '没有发送:你的设置里已关闭文件检查点,但这台引擎关于能否按会话停止记录文件历史的报告,本客户端读不出来,所以现在发送仍可能把它记录下来。只要这台引擎还是同样的报告,重试也不会改变这一点;要发送并让这一次的文件历史被记录,请在设置里把文件检查点重新打开。',
552
+ 'session.memoryErase.personalStoreUnjudged': '什么都没有抹除:这条会话的记忆有一部分存放在这台部署目前还抹除不了的个人记忆库里,所以抹除在任何改动之前就被拒绝了。',
553
+ 'session.memorySync.parked.one': '这台部署上「{scope}」这一层的记忆同步已暂停:它的同步游标用不了。{wayOut}',
554
+ 'session.memorySync.parked.other': '这台部署上 {count} 层的记忆同步已暂停({scopes}):它们的同步游标用不了。{wayOut}',
555
+ 'session.memorySync.parkedUnnamed.one': '这台部署上 1 层的记忆同步已暂停:它的同步游标用不了。{wayOut}',
556
+ 'session.memorySync.parkedUnnamed.other': '这台部署上 {count} 层的记忆同步已暂停:它们的同步游标用不了。{wayOut}',
557
+ 'session.memorySync.wayOut.deleteCursor': '运维在服务器上删掉每个暂停层的同步游标后,同步即恢复;自上次同步以来只在一侧删掉的条目会回来,需要再删一次。',
558
+ 'session.memorySync.wayOut.unrecognized': '部署给出的出路本客户端认不出,这里不给建议。',
550
559
  'session.hostSettings.memorySwitchMalformed': '设置文件里的记忆设置读不出,所以「关闭记忆」没有生效:这一次请求照常带着记忆发出。改好记忆那一段(memory.enabled 只能是 true 或 false)即可关闭。',
551
560
  'session.hostSettings.fileHistoryRestoreConflict': '没有发送:这次请求准备好之后,你在设置里关闭了文件检查点,但这次请求同时要从检查点还原文件,两者不能放在同一个请求里。要还原文件,请在设置里把文件检查点重新打开;否则请去掉文件还原再发送。',
552
561
  'session.hostSettings.projectionUnchecked': '这一次请求要带的设置在发出前没法核对,所以没有发送。请重新载入设置后再试。',
@@ -670,6 +679,18 @@ const ZH = {
670
679
  'session.steerRefusal.advice': '{happened} —— {nextStep}',
671
680
  'session.steerRefusal.hostQueue.queued': '它留在队列里,在这个 turn 结束时会原样提交',
672
681
  'session.steerRefusal.hostQueue.dropped': '它没有被保留;{nextStep}',
682
+ 'session.permissionModeSwitch.applied': '正在跑的这一轮现在用 {mode} 权限模式。',
683
+ 'session.permissionModeSwitch.folded': '正在跑的这一轮现在用 {mode} 权限模式,不是你选的那一档 —— {reason}。',
684
+ 'session.permissionModeSwitch.reason.entryFloor': '这台部署不允许比它的下限更宽松的模式',
685
+ 'session.permissionModeSwitch.reason.disableAutoMode': '这个任务的设置关掉了 auto 模式',
686
+ 'session.permissionModeSwitch.reason.engine': '引擎不允许这条 run 用你选的模式',
687
+ 'session.permissionModeSwitch.notPersisted': '{line}这次切档没有随 run 存下:run 停下后再续跑时会回到切档前的模式,续跑后请再切一次。',
688
+ 'session.permissionModeSwitch.notRunning': '这条 run 此刻没在跑一轮(停在等决断上、已经结束,或在别处跑),所以没有切它的模式。',
689
+ 'session.permissionModeSwitch.notFound': '你看不到这条 run,没有切任何模式。',
690
+ 'session.permissionModeSwitch.refused': '引擎拒绝切这条 run 的模式({status}),它保持原来的模式。',
691
+ 'session.permissionModeSwitch.refusedWithCode': '引擎拒绝切这条 run 的模式({status} {code}),它保持原来的模式。',
692
+ 'session.permissionModeSwitch.unconfirmed': '切档请求已发出,但没有收到读得懂的答复,不知道模式变没变 —— 请再切一次以确认。',
693
+ 'session.permissionModeSwitch.unavailable': '这里不能切正在跑的这一轮的模式,模式没有变。',
673
694
  'notice.capability.subject.userInvokedSkills': '用户点名的技能',
674
695
  'notice.capability.subject.skillToolLists': '技能工具清单',
675
696
  'notice.capability.subject.permissionRulesWrite': '权限规则写入口',
@@ -1053,10 +1074,40 @@ const ZH = {
1053
1074
  'config.mods.refusal.by': '被 {by} 拒绝',
1054
1075
  'config.mods.rewrite.resultInPlace': '由 {by} 代替工具作答',
1055
1076
  'config.mods.rewrite.inputBy': '参数在放行前被 {by} 改过',
1077
+ 'follow.notFollowed.headRun': '这块屏已不再跟着 run {taskId}{reason}{ending}{exit}',
1078
+ 'follow.notFollowed.headTurn': '这块屏已不再跟着这一轮的 run{reason}{ending}{exit}',
1079
+ 'follow.notFollowed.reason.exhaustedDraining': ':服务它的那台引擎实例在它最后一条事件流关闭时正在下线,而这个客户端的重新附着次数已经用完。',
1080
+ 'follow.notFollowed.reason.exhaustedConnectionLost': ':最后一次尝试时连接断了,而这个客户端的重新附着次数已经用完。',
1081
+ 'follow.notFollowed.reason.exhaustedStreamCap': ':最后一次尝试时它的事件流撞上了引擎的时长上限,而这个客户端的重新附着次数已经用完。',
1082
+ 'follow.notFollowed.reason.exhausted': ':这个客户端的重新附着次数已经用完。',
1083
+ 'follow.notFollowed.reason.badInput': ':这个客户端在重新附着时出了内部错误。',
1084
+ 'follow.notFollowed.reason.noRunId': ':这个客户端始终不知道它是哪一次 run,所以没有可以重新附着的对象。',
1085
+ 'follow.notFollowed.reason.runUnknown': ':引擎答复说它不认识那次 run —— 它可能已被清理,也可能是这个客户端用错了身份去问。',
1086
+ 'follow.notFollowed.reason.unspecified': '。',
1087
+ 'follow.notFollowed.endingUnknown': '引擎没有说那次 run 是怎么结束的 —— 它可能还在跑。',
1088
+ 'follow.notFollowed.exit.reattach': '它接下来的动作,只有在这个客户端重新附着到它之后才会显示在这里。',
1089
+ 'follow.notFollowed.exit.checkRuns': '再发一次这件工作之前,先查一下这个会话的 run。',
1090
+ 'follow.notFollowed.exit.runUnknown': '重新附着也不会把它带回这里;再发一次这件工作之前,先查一下这个会话的 run。',
1091
+ 'follow.notFollowed.idleTear': '这一轮的事件流静默了 {secs} 秒。{notice}{grace}',
1092
+ 'follow.notFollowed.idleGrace': '如果这次 run 本来就会安静这么久(比如一次长构建),下次可以调大空闲宽限:设置 {env}(settings 的 env 块,整数毫秒,{min}-{max};默认 {default})。',
1093
+ 'approval.planReview.note.empty': '计划为空。',
1094
+ 'approval.planReview.note.marked': '这份计划里有不能照原样显示的字符,不能在这张卡上批准。可以拒绝,或要模型重新呈一次计划。',
1095
+ 'approval.planReview.note.tooLarge': '这份计划太长,卡上显示不全({length} 个字符),不能在这张卡上批准。可以拒绝,或要一份更短的计划。',
1096
+ 'approval.planReview.note.notCarried': '引擎没有把这份计划的正文带到卡上(可能过长),不能在这张卡上批准。可以拒绝,或要模型重新呈一次计划。',
1097
+ 'approval.planReview.note.unknown': '这张卡给不出它要批的计划正文,不能在这张卡上批准。可以拒绝,或要模型重新呈一次计划。',
1098
+ 'approval.planReview.askAgain.shown': '用户要求重新呈上这份计划。',
1099
+ 'approval.planReview.askAgain.marked': '用户没法批准这份计划:里面有不能照原样显示的字符。请去掉这些字符后重新呈上计划。',
1100
+ 'approval.planReview.askAgain.tooLarge': '用户没法批准这份计划:它太长,显示不全。请呈上一份更短的计划。',
1101
+ 'approval.planReview.askAgain.notCarried': '用户没法批准这份计划:计划正文没有到达审批卡(可能过长)。请呈上一份更短的计划。',
1102
+ 'approval.planReview.askAgain.unknown': '用户没法批准这份计划:审批卡显示不了它。请重新呈上计划。',
1103
+ 'approval.planReview.askAgain.withNote': '{sentence} 用户补充:{note}',
1104
+ 'approval.planReview.option.askAgain.label': '不,要模型重新呈上计划',
1105
+ 'approval.planReview.option.askAgain.description': '不批准;要模型重新呈上计划',
1056
1106
  };
1057
1107
  export const ZH_MESSAGES = Object.freeze(ZH);
1058
1108
  export const TERM_SLOTS = Object.freeze({
1059
1109
  'session.background.refusal.envOff': ['SEMA_HEADLESS_DETACH'],
1110
+ 'session.permissionModeSwitch.reason.disableAutoMode': ['auto'],
1060
1111
  'session.thinking.offWithUltracodeOnBody': ['Ultracode'],
1061
1112
  'config.mcp.toolAxesInvalid': ['toolAxes'],
1062
1113
  'config.mcp.toolFacesInvalid': ['toolFaces'],
package/dist/index.d.ts CHANGED
@@ -77,6 +77,11 @@ export * from './steerPriorityCapability.js';
77
77
  export * from './permissionModesCapability.js';
78
78
  export * from './approvalDecidedByCapability.js';
79
79
  export * from './outputStyleSeatCapability.js';
80
+ export * from './permissionModeWriteCapability.js';
81
+ export { setRunPermissionMode, runPermissionModeSwitchLine } from './runPermissionModeSwitch.js';
82
+ export type { RunPermissionModeSwitchOutcome, RunPermissionModeSwitchRuns, RunPermissionModeSwitchOptions, PermissionModeAdmissionView, PermissionModeReceiptView, } from './runPermissionModeSwitch.js';
83
+ export { observedMcpTransportKinds, projectMcpTransportKindsCapability } from './mcpTransportKindsCapability.js';
84
+ export type { McpRequestTransportKind, McpTransportKindsReading } from './mcpTransportKindsCapability.js';
80
85
  export * from './mcpProbeWire.js';
81
86
  export * from './connectorStatus.js';
82
87
  export * from './effectiveFacts.js';
@@ -84,7 +89,7 @@ export * from './gateOutcome.js';
84
89
  export * from './postureKnob.js';
85
90
  export * from './engineIdentity.js';
86
91
  export { readEngineHealthFacts } from './engineHealthFacts.js';
87
- export type { EngineHealthFacts, EngineHealthCenterFacts, EngineHealthAuthFacts, EngineHealthDrainingFacts } from './engineHealthFacts.js';
92
+ export type { EngineHealthFacts, EngineHealthCenterFacts, EngineHealthAuthFacts, EngineHealthDrainingFacts, EngineHealthLeaseFacts } from './engineHealthFacts.js';
88
93
  export { transportFailureScene } from './engineWireFor.js';
89
94
  export type { EngineWireNoAnswerKind, TransportFailureChainEnd, TransportFailureLayer, TransportFailureScene, TransportFailureSocket } from './engineWireFor.js';
90
95
  export { engineUrlTransportVerdict, normalizeEngineBaseUrl } from './engineUrl.js';
@@ -105,6 +110,7 @@ export * from './engineToolLabelStore.js';
105
110
  export * from './fleetTaskDesc.js';
106
111
  export { displayUntrusted, displayUntrustedMarks, displayConfiguredUrl, queryCarriesCredential, cleanUntrustedScalar } from './displayUntrusted.js';
107
112
  export type { DisplayUntrustedOptions, DisplayMark, DisplayMarkSpan, DisplayUntrustedMarked } from './displayUntrusted.js';
113
+ export { DISPLAY_DECISION_BODY } from './displayUntrusted.js';
108
114
  export { isDiagnosticValueWord } from './displayUntrusted.js';
109
115
  export type * from './types/engineState.js';
110
116
  export * from './hostEnv.js';
@@ -222,7 +228,8 @@ export { guardedRead, readOwnDataFiniteNumber, readOwnDataNonEmptyString } from
222
228
  export { contextUsageReadingOf, type ContextUsageReading } from './ownKey.js';
223
229
  export { TURN_FAILURE_CATEGORIES, turnFailurePresentation, type TurnFailureCategory, type TurnFailurePresentation, type TurnFailureRetry } from './turnFailurePresentation.js';
224
230
  export { readSeatTurnFailure, seatTurnFailureOf, type SeatTurnFailure } from './turnFailurePresentation.js';
225
- export { REATTACH_BUDGET_FRESH, REATTACH_MAX_TRIES, runReattachPolicy, type ReattachBudget, type ReattachDecision, type ReattachEvent, type ReattachGiveUp, } from './runReattachPolicy.js';
231
+ export { REATTACH_BUDGET_FRESH, REATTACH_BUDGET_NONE, REATTACH_MAX_TRIES, runReattachPolicy, type ReattachBudget, type ReattachDecision, type ReattachDrainingEvent, type ReattachEvent, } from './runReattachPolicy.js';
232
+ export { runNotFollowedNotice, runNotFollowedOf, type ReattachBreak, type RunNotFollowed, type RunNotFollowedCause } from './runFollow.js';
226
233
  export * from './corruptSession.js';
227
234
  export * from './corruptSessionCopy.js';
228
235
  export { SEMA_TOOL_HISTORY_ACCEPTED_KEY, classifyToolHistoryMismatch, readToolHistoryAcceptedKey, readToolHistoryMismatchKey, resolveToolHistoryRewindTarget } from './toolHistoryMismatch.js';
@@ -260,7 +267,7 @@ export type { InterruptedRunRow, InterruptedRunSettleDeps, InterruptedRunSettleV
260
267
  export { ENGINE_GENERATION_WINDOW_MARGIN_MS, ENGINE_STOPPED_CALL_PHASES, approvalWindowLeftMs, convergeEndedEngineGeneration } from './engineGenerationConvergence.js';
261
268
  export type { ApprovalWindowAnchor, EndedGenerationCard, EndedGenerationFacts, EndedGenerationOpenedCall, EndedGenerationPhaseChange, EndedGenerationPhaseHold, EngineGenerationConvergence, EngineStoppedCallPhase, } from './engineGenerationConvergence.js';
262
269
  export { AWAIT_ENGINE_INSTALL_POLL_MS, REATTACH_AWAIT_NEXT_ENGINE_MS, REATTACH_RUN_STATES, approvalFrameGenerationVerdict, awaitNextEngineInstalled, endedGenerationSettleStep, engineGenerationEnded, engineGenerationOfPort, engineGenerationReadingOf, unreachableForSettle, } from './engineGenerationPort.js';
263
- export type { ApprovalFrameGenerationFacts, AwaitNextEngineDeps, EndedGenerationMaterials, EndedGenerationSettleFacts, EndedGenerationSettleStep, EngineGenerationEndedFacts, EngineGenerationPort, EngineGenerationReading, ReattachLivenessReading, ReattachOutageStopLine, ReattachOutageStopLineParts, ReattachRunState, } from './engineGenerationPort.js';
270
+ export type { ApprovalFrameGenerationFacts, AwaitNextEngineDeps, EndedGenerationMaterials, EndedGenerationSettleFacts, EndedGenerationSettleStep, EndedGenerationWaitReading, EngineGenerationEndFact, EngineGenerationEndedFacts, EngineGenerationPort, EngineGenerationReading, ReattachLivenessReading, ReattachOutageStopLine, ReattachOutageStopLineParts, ReattachRunState, } from './engineGenerationPort.js';
264
271
  export { POISON_FRAME_RAW_MAX, REATTACH_BACKOFF_CAP_MS, REATTACH_BACKOFF_START_MS, REATTACH_NOT_FOUND_CONFIRM, REATTACH_NOT_FOUND_MIN_ELAPSED_MS, REATTACH_WINDOW_MS, malformedFrameErrorOf, poisonFrameInitial, poisonFrameStep, reattachBackoffMs, reattachWindowOpen, reattachWindowStep, } from './reattachWindow.js';
265
272
  export type { PoisonFrameDecision, PoisonFrameEvent, PoisonFrameState, PoisonFrameStep, ReattachProbeResult, ReattachWindowDecision, ReattachWindowEvent, ReattachWindowState, ReattachWindowStep, ReattachWindowTuning, } from './reattachWindow.js';
266
273
  export * from './inheritEnvWire.js';
@@ -310,6 +317,11 @@ export { ruleToolNameVerdictOf } from './protocolSegment.js';
310
317
  export type { RuleToolNameReading } from './protocolSegment.js';
311
318
  export * from './hitl/askGateWire.js';
312
319
  export * from './hitl/planReviewWire.js';
320
+ export type { PlanReviewCardFacts, PlanReviewBody, PlanBodyUnknownCause } from './planReviewCardFacts.js';
321
+ export { planReviewBodyOf } from './planReviewCardFacts.js';
322
+ export { planReviewCardNote } from './hitl/planReviewCard.js';
323
+ export { readRunLedgerSnapshot } from './runLedgerSnapshot.js';
324
+ export type { RunLedgerSnapshot, RunLedgerFold, RunLedgerSnapshotDeps } from './runLedgerSnapshot.js';
313
325
  export { decisionInFlightOf, decisionReadMark } from './hitl/decisionLedger.js';
314
326
  export { ASK_PARK_AUTO_REOPEN_BLOCKS, askParkAutoReopenBlockedContent, askParkAutoReopenBlockOf, askParkRefusalBlockOf, claimAskParkAutoReopenBlockNotice, clearAskParkAutoReopenBlocks, } from './hitl/askParkAutoReopenBlock.js';
315
327
  export type { AskParkAutoReopenBlock, AskParkAutoReopenBlockNotice, AskParkGate } from './hitl/askParkAutoReopenBlock.js';
package/dist/index.js CHANGED
@@ -66,6 +66,9 @@ export * from './steerPriorityCapability.js';
66
66
  export * from './permissionModesCapability.js';
67
67
  export * from './approvalDecidedByCapability.js';
68
68
  export * from './outputStyleSeatCapability.js';
69
+ export * from './permissionModeWriteCapability.js';
70
+ export { setRunPermissionMode, runPermissionModeSwitchLine } from './runPermissionModeSwitch.js';
71
+ export { observedMcpTransportKinds, projectMcpTransportKindsCapability } from './mcpTransportKindsCapability.js';
69
72
  export * from './mcpProbeWire.js';
70
73
  export * from './connectorStatus.js';
71
74
  export * from './effectiveFacts.js';
@@ -88,6 +91,7 @@ export * from './classifierStatus.js';
88
91
  export * from './engineToolLabelStore.js';
89
92
  export * from './fleetTaskDesc.js';
90
93
  export { displayUntrusted, displayUntrustedMarks, displayConfiguredUrl, queryCarriesCredential, cleanUntrustedScalar } from './displayUntrusted.js';
94
+ export { DISPLAY_DECISION_BODY } from './displayUntrusted.js';
91
95
  export { isDiagnosticValueWord } from './displayUntrusted.js';
92
96
  export * from './hostEnv.js';
93
97
  export * from './unrefTimer.js';
@@ -191,7 +195,8 @@ export { guardedRead, readOwnDataFiniteNumber, readOwnDataNonEmptyString } from
191
195
  export { contextUsageReadingOf } from './ownKey.js';
192
196
  export { TURN_FAILURE_CATEGORIES, turnFailurePresentation } from './turnFailurePresentation.js';
193
197
  export { readSeatTurnFailure, seatTurnFailureOf } from './turnFailurePresentation.js';
194
- export { REATTACH_BUDGET_FRESH, REATTACH_MAX_TRIES, runReattachPolicy, } from './runReattachPolicy.js';
198
+ export { REATTACH_BUDGET_FRESH, REATTACH_BUDGET_NONE, REATTACH_MAX_TRIES, runReattachPolicy, } from './runReattachPolicy.js';
199
+ export { runNotFollowedNotice, runNotFollowedOf } from './runFollow.js';
195
200
  export * from './corruptSession.js';
196
201
  export * from './corruptSessionCopy.js';
197
202
  export { SEMA_TOOL_HISTORY_ACCEPTED_KEY, classifyToolHistoryMismatch, readToolHistoryAcceptedKey, readToolHistoryMismatchKey, resolveToolHistoryRewindTarget } from './toolHistoryMismatch.js';
@@ -254,6 +259,9 @@ export * from './coreValuePorts.js';
254
259
  export { ruleToolNameVerdictOf } from './protocolSegment.js';
255
260
  export * from './hitl/askGateWire.js';
256
261
  export * from './hitl/planReviewWire.js';
262
+ export { planReviewBodyOf } from './planReviewCardFacts.js';
263
+ export { planReviewCardNote } from './hitl/planReviewCard.js';
264
+ export { readRunLedgerSnapshot } from './runLedgerSnapshot.js';
257
265
  export { decisionInFlightOf, decisionReadMark } from './hitl/decisionLedger.js';
258
266
  export { ASK_PARK_AUTO_REOPEN_BLOCKS, askParkAutoReopenBlockedContent, askParkAutoReopenBlockOf, askParkRefusalBlockOf, claimAskParkAutoReopenBlockNotice, clearAskParkAutoReopenBlocks, } from './hitl/askParkAutoReopenBlock.js';
259
267
  export { HITL_DECISION_FAMILIES, HITL_DECISION_NOT_APPLIED_CAUSES, HITL_DECISION_NOT_SENT_CAUSES, HITL_DECISION_UNCONFIRMED_CAUSES, sendHitlDecision, hitlDecisionOutcomeContent, } from './hitl/decisionSend.js';
@@ -0,0 +1,18 @@
1
+ import type { McpServerSpec } from '@sema-agent/sdk';
2
+ export type McpRequestTransportKind = McpServerSpec['transport']['kind'];
3
+ export declare const MCP_TRANSPORT_KINDS_WHEN_NOT_STATED: readonly ["stdio", "http"];
4
+ export type McpTransportKindsReading = {
5
+ readonly kind: 'stated';
6
+ readonly kinds: readonly McpRequestTransportKind[];
7
+ readonly unrecognized: readonly string[];
8
+ } | {
9
+ readonly kind: 'not_stated';
10
+ readonly kinds: readonly McpRequestTransportKind[];
11
+ } | {
12
+ readonly kind: 'unreadable';
13
+ } | {
14
+ readonly kind: 'unobserved';
15
+ };
16
+ export declare function projectMcpTransportKindsCapability(caps: unknown): McpTransportKindsReading | undefined;
17
+ export declare function observedMcpTransportKinds(baseUrl?: string | undefined): McpTransportKindsReading;
18
+ export declare function mcpTransportNotAdvertised(reading: McpTransportKindsReading | undefined, transportKind: string): readonly McpRequestTransportKind[] | undefined;
@@ -0,0 +1,75 @@
1
+ import { engineWireTargetBaseUrl } from './engineWireTarget.js';
2
+ import { createEngineCapReader } from './engineCapReader.js';
3
+ import { appendOwnElement, ownDataField } from './ownKey.js';
4
+ export const MCP_TRANSPORT_KINDS_WHEN_NOT_STATED = Object.freeze(['stdio', 'http']);
5
+ const _kindsEqRequestFace = true;
6
+ void _kindsEqRequestFace;
7
+ const KNOWN = new Set(MCP_TRANSPORT_KINDS_WHEN_NOT_STATED);
8
+ export function projectMcpTransportKindsCapability(caps) {
9
+ try {
10
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
11
+ return undefined;
12
+ const v = ownDataField(caps, 'mcpTransportKinds');
13
+ if (v === undefined)
14
+ return { kind: 'not_stated', kinds: MCP_TRANSPORT_KINDS_WHEN_NOT_STATED };
15
+ if (!Array.isArray(v))
16
+ return undefined;
17
+ const len = ownDataField(v, 'length');
18
+ if (typeof len !== 'number' || !Number.isSafeInteger(len) || len < 0 || len > 1000)
19
+ return undefined;
20
+ const kinds = [];
21
+ const unrecognized = [];
22
+ for (let i = 0; i < len; i++) {
23
+ if (!Object.hasOwn(v, i))
24
+ return undefined;
25
+ const w = ownDataField(v, String(i));
26
+ if (typeof w !== 'string')
27
+ return undefined;
28
+ if (KNOWN.has(w)) {
29
+ if (!kinds.includes(w))
30
+ appendOwnElement(kinds, w);
31
+ }
32
+ else if (!unrecognized.includes(w))
33
+ appendOwnElement(unrecognized, w);
34
+ }
35
+ return { kind: 'stated', kinds, unrecognized };
36
+ }
37
+ catch {
38
+ return undefined;
39
+ }
40
+ }
41
+ const reader = createEngineCapReader({
42
+ name: 'mcpTransportKinds',
43
+ project: projectMcpTransportKindsCapability,
44
+ });
45
+ export function observedMcpTransportKinds(baseUrl = engineWireTargetBaseUrl()) {
46
+ return reader.observed(baseUrl);
47
+ }
48
+ export function mcpTransportNotAdvertised(reading, transportKind) {
49
+ try {
50
+ if (reading === null || reading === undefined || typeof reading !== 'object' || Array.isArray(reading))
51
+ return undefined;
52
+ if (ownDataField(reading, 'kind') !== 'stated')
53
+ return undefined;
54
+ const kinds = ownDataField(reading, 'kinds');
55
+ if (!Array.isArray(kinds))
56
+ return undefined;
57
+ const len = ownDataField(kinds, 'length');
58
+ if (typeof len !== 'number' || !Number.isSafeInteger(len) || len < 0 || len > MCP_TRANSPORT_KINDS_WHEN_NOT_STATED.length)
59
+ return undefined;
60
+ const list = [];
61
+ for (let i = 0; i < len; i++) {
62
+ if (!Object.hasOwn(kinds, i))
63
+ return undefined;
64
+ const k = ownDataField(kinds, String(i));
65
+ if (typeof k !== 'string' || !KNOWN.has(k))
66
+ return undefined;
67
+ if (!list.includes(k))
68
+ appendOwnElement(list, k);
69
+ }
70
+ return list.includes(transportKind) ? undefined : Object.freeze([...list]);
71
+ }
72
+ catch {
73
+ return undefined;
74
+ }
75
+ }