@sema-agent/client-core 0.102.0 → 0.104.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 (117) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/README.md +23 -17
  3. package/dist/adapt/toolCards.d.ts +2 -1
  4. package/dist/adapt/toolCards.js +3 -1
  5. package/dist/adapter/downstream/eventToSdkMessage.d.ts +5 -1
  6. package/dist/adapter/downstream/eventToSdkMessage.js +23 -3
  7. package/dist/adapter/downstream/terminalToSdkResult.d.ts +0 -1
  8. package/dist/adapter/downstream/terminalToSdkResult.js +3 -2
  9. package/dist/adapter/downstream/wiringManifestView.js +4 -1
  10. package/dist/agentSession/engineAgentRegistryRead.js +3 -0
  11. package/dist/cloudConfigWireCaps.js +6 -3
  12. package/dist/coreValuePorts.d.ts +3 -1
  13. package/dist/coreValuePorts.js +5 -0
  14. package/dist/credentialPlaneCapability.d.ts +22 -0
  15. package/dist/credentialPlaneCapability.js +75 -0
  16. package/dist/deviceExecutorManagementCapability.d.ts +1 -0
  17. package/dist/deviceExecutorManagementCapability.js +3 -1
  18. package/dist/deviceRebind.d.ts +17 -4
  19. package/dist/deviceRebind.js +43 -14
  20. package/dist/engineAgentAbsence.d.ts +1 -0
  21. package/dist/engineErrorCodes.d.ts +1 -0
  22. package/dist/engineErrorCodes.js +3 -1
  23. package/dist/engineNoticeCodes.d.ts +26 -0
  24. package/dist/engineNoticeCodes.js +121 -12
  25. package/dist/engineRowRef.js +1 -0
  26. package/dist/errorSupplementRoles.js +1 -3
  27. package/dist/eventLeg.js +2 -1
  28. package/dist/executionPlacementWords.d.ts +3 -0
  29. package/dist/executionPlacementWords.js +2 -0
  30. package/dist/fleet/fleetProjection.js +15 -9
  31. package/dist/gateOutcome.d.ts +20 -0
  32. package/dist/gateOutcome.js +89 -0
  33. package/dist/generated/engineAskFaceTables.js +2 -2
  34. package/dist/generated/engineFactTables.d.ts +8 -3
  35. package/dist/generated/engineFactTables.js +58 -2
  36. package/dist/generated/engineNoticeTables.js +30 -0
  37. package/dist/generated/settingsSchemaDefaultModel.d.ts +1 -1
  38. package/dist/generated/settingsSchemaDefaultModel.js +2 -2
  39. package/dist/generated/settingsSchemaFns.d.ts +15 -0
  40. package/dist/generated/settingsSchemaFns.js +25 -2
  41. package/dist/generated/settingsSchemaHooksClassifier.js +109 -29
  42. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
  43. package/dist/generated/settingsSchemaMcpRequestEntry.js +213 -93
  44. package/dist/generated/settingsSchemaMcpServerName.d.ts +1 -0
  45. package/dist/generated/settingsSchemaMcpServerName.js +8 -0
  46. package/dist/generated/settingsSchemaOwnKeyRead.d.ts +1 -0
  47. package/dist/generated/settingsSchemaOwnKeyRead.js +172 -0
  48. package/dist/generated/settingsSchemaPlainJsonObject.d.ts +1 -0
  49. package/dist/generated/settingsSchemaPlainJsonObject.js +28 -0
  50. package/dist/generated/settingsSchemaSafetyMergeSpec.js +10 -7
  51. package/dist/generated/settingsSchemaTierWords.d.ts +1 -0
  52. package/dist/generated/settingsSchemaTierWords.js +7 -0
  53. package/dist/generated/settingsSchemaTypes.d.ts +3 -1
  54. package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
  55. package/dist/hitl/automaticAnswerVerdict.js +47 -11
  56. package/dist/hitl/decisionConflict.js +11 -11
  57. package/dist/hitl/decisionRefusal.d.ts +1 -0
  58. package/dist/hitl/decisionRefusal.js +4 -2
  59. package/dist/hitl/editedRuleTextPrecheck.d.ts +1 -0
  60. package/dist/hitl/editedRuleTextPrecheck.js +26 -1
  61. package/dist/hitl/persistedRulesWire.js +1 -0
  62. package/dist/hitl/planReviewWire.d.ts +2 -1
  63. package/dist/hitl/planReviewWire.js +8 -12
  64. package/dist/hitl/sessionPolicyDeliverable.d.ts +0 -1
  65. package/dist/hitl/sessionPolicyDeliverable.js +31 -10
  66. package/dist/hitl/sessionPolicyWire.js +1 -1
  67. package/dist/hitl/toolApprovalWire.d.ts +20 -7
  68. package/dist/hitl/toolApprovalWire.js +171 -19
  69. package/dist/host.d.ts +0 -3
  70. package/dist/hostTurnSettings.js +3 -1
  71. package/dist/humanTurn.js +2 -2
  72. package/dist/i18n/messages.en.d.ts +5 -0
  73. package/dist/i18n/messages.en.js +6 -1
  74. package/dist/i18n/messages.zh.js +6 -1
  75. package/dist/index.d.ts +8 -4
  76. package/dist/index.js +3 -1
  77. package/dist/inheritEnvWire.d.ts +1 -0
  78. package/dist/inheritEnvWire.js +8 -5
  79. package/dist/jsonFaithful.js +5 -3
  80. package/dist/mcpEngineLeg.d.ts +3 -0
  81. package/dist/mcpEngineLeg.js +4 -1
  82. package/dist/mcpLiveness.d.ts +18 -0
  83. package/dist/mcpLiveness.js +48 -1
  84. package/dist/mcpReconnect.d.ts +3 -0
  85. package/dist/mcpReconnect.js +6 -0
  86. package/dist/mcpStatusSupersetKeys.js +24 -1
  87. package/dist/mcpWireCaps.d.ts +2 -3
  88. package/dist/mcpWireCaps.js +10 -9
  89. package/dist/memoryEntriesWire.d.ts +35 -1
  90. package/dist/memoryEntriesWire.js +110 -14
  91. package/dist/modsFace.js +7 -3
  92. package/dist/postureKnob.js +1 -1
  93. package/dist/prepareRefusal.d.ts +0 -1
  94. package/dist/prepareRefusal.js +0 -3
  95. package/dist/printModelStatus.d.ts +1 -0
  96. package/dist/printModelStatus.js +6 -2
  97. package/dist/promptProfileWireCaps.d.ts +1 -3
  98. package/dist/promptProfileWireCaps.js +2 -2
  99. package/dist/request/taskRequest.d.ts +1 -1
  100. package/dist/request/taskRequest.js +3 -3
  101. package/dist/retryStatus.d.ts +20 -1
  102. package/dist/retryStatus.js +31 -7
  103. package/dist/ruleCompileVerdict.d.ts +1 -0
  104. package/dist/ruleCompileVerdict.js +3 -1
  105. package/dist/seatContract.d.ts +7 -7
  106. package/dist/seatContract.js +49 -10
  107. package/dist/sessionMemoryErase.js +24 -2
  108. package/dist/sessionRowTag.d.ts +24 -0
  109. package/dist/sessionRowTag.js +77 -0
  110. package/dist/systemReminderTag.js +14 -4
  111. package/dist/turnFailurePresentation.js +8 -1
  112. package/dist/wireFailureShape.d.ts +12 -1
  113. package/dist/wireFailureShape.js +58 -24
  114. package/dist/wireRefusalCopy.d.ts +0 -3
  115. package/dist/wireRefusalCopy.js +0 -17
  116. package/docs/INTEGRATION-CLIENTS.md +400 -14
  117. package/package.json +5 -5
@@ -1,4 +1,4 @@
1
- import { isMcpLivenessState } from './mcpLiveness.js';
1
+ import { isMcpLivenessState, readMcpAuthorization } from './mcpLiveness.js';
2
2
  import { mcpSectionDroppedNamedRowsOf } from './ownKey.js';
3
3
  void true;
4
4
  void true;
@@ -121,12 +121,15 @@ export function mcpEngineLegConnectionOf(serverName, rows) {
121
121
  const errorCode = readKey(row, 'errorCode');
122
122
  const delivered = readKey(row, 'delivered');
123
123
  const httpStatus = readKey(row, 'httpStatus');
124
+ const authorization = readMcpAuthorization(row);
125
+ const authorizationUnreadable = authorization.kind === 'unreadable' || readKey(row, 'authorizationUnreadable') === true;
124
126
  return {
125
127
  state: 'not_connected',
126
128
  cause: 'failed',
127
129
  ...(typeof errorCode === 'string' && errorCode !== '' ? { errorCode } : {}),
128
130
  ...(typeof delivered === 'string' && delivered !== '' ? { delivered } : {}),
129
131
  ...(typeof httpStatus === 'number' && Number.isFinite(httpStatus) ? { httpStatus } : {}),
132
+ ...(authorization.kind === 'record' ? { authorization: authorization.authorization } : authorizationUnreadable ? { authorizationUnreadable: true } : {}),
130
133
  };
131
134
  }
132
135
  const rosterReadingOf = (v) => {
@@ -1,4 +1,5 @@
1
1
  import type { McpLivenessState } from '@sema-agent/sdk';
2
+ import { CORE_MCP_FAILURE_KINDS } from './generated/engineFactTables.js';
2
3
  export declare const MCP_LIVENESS_STATES: readonly ["reachable", "unreachable", "unknown"];
3
4
  export type { McpLivenessState };
4
5
  export declare const isMcpLivenessState: (v: unknown) => v is McpLivenessState;
@@ -28,3 +29,20 @@ export interface McpEngineLegHealth {
28
29
  }
29
30
  export declare function mcpLivenessRollupOf(rows: readonly McpLivenessBearingRow[] | undefined): McpEngineLegHealth;
30
31
  export declare function mcpEngineLegHealthDetail(health: McpEngineLegHealth | undefined): string;
32
+ export declare const MCP_FAILURE_KINDS: readonly ["connect_refused", "connection_failed", "connection_closed", "unauthorized", "http_status", "not_mcp_response", "spawn_failed", "timeout", "protocol", "invalid_config", "credential_unavailable", "host_refused", "unknown"];
33
+ export declare const MCP_AUTHORIZATION_REASONS: readonly ["rejected", "scope", "none"];
34
+ export declare const MCP_FAILURE_UNAUTHORIZED: Extract<(typeof CORE_MCP_FAILURE_KINDS)[number], 'unauthorized'>;
35
+ export interface McpAuthorizationView {
36
+ readonly reason: string;
37
+ readonly authorizeUrl?: string;
38
+ readonly resourceMetadataUrl?: string;
39
+ }
40
+ export type McpAuthorizationCell = {
41
+ readonly kind: 'absent';
42
+ } | {
43
+ readonly kind: 'unreadable';
44
+ } | {
45
+ readonly kind: 'record';
46
+ readonly authorization: McpAuthorizationView;
47
+ };
48
+ export declare function readMcpAuthorization(row: {} | null | undefined): McpAuthorizationCell;
@@ -1,4 +1,4 @@
1
- import { CORE_MCP_LIVENESS_STATES } from './generated/engineFactTables.js';
1
+ import { CORE_MCP_AUTHORIZATION_REASONS, CORE_MCP_FAILURE_KINDS, CORE_MCP_LIVENESS_STATES } from './generated/engineFactTables.js';
2
2
  export const MCP_LIVENESS_STATES = CORE_MCP_LIVENESS_STATES;
3
3
  void MCP_LIVENESS_STATES;
4
4
  void true;
@@ -100,3 +100,50 @@ export function mcpEngineLegHealthDetail(health) {
100
100
  + ` cannot tell which cause applies)${unreadable}`;
101
101
  }
102
102
  }
103
+ export const MCP_FAILURE_KINDS = CORE_MCP_FAILURE_KINDS;
104
+ export const MCP_AUTHORIZATION_REASONS = CORE_MCP_AUTHORIZATION_REASONS;
105
+ export const MCP_FAILURE_UNAUTHORIZED = 'unauthorized';
106
+ const ABSENT_AUTHORIZATION = Object.freeze({ kind: 'absent' });
107
+ const UNREADABLE_AUTHORIZATION = Object.freeze({ kind: 'unreadable' });
108
+ function ownDataCell(o, key) {
109
+ try {
110
+ const d = Object.getOwnPropertyDescriptor(o, key);
111
+ if (d === undefined)
112
+ return { kind: 'absent' };
113
+ if (!Object.hasOwn(d, 'value'))
114
+ return { kind: 'unreadable' };
115
+ return { kind: 'value', value: d.value };
116
+ }
117
+ catch {
118
+ return { kind: 'unreadable' };
119
+ }
120
+ }
121
+ const nonEmptyString = (c) => c.kind === 'value' && typeof c.value === 'string' && c.value.length > 0 ? c.value : undefined;
122
+ export function readMcpAuthorization(row) {
123
+ try {
124
+ if (!isRecord(row))
125
+ return UNREADABLE_AUTHORIZATION;
126
+ const cell = ownDataCell(row, 'authorization');
127
+ if (cell.kind === 'absent')
128
+ return ABSENT_AUTHORIZATION;
129
+ if (cell.kind === 'unreadable' || !isRecord(cell.value))
130
+ return UNREADABLE_AUTHORIZATION;
131
+ const rec = cell.value;
132
+ const reason = nonEmptyString(ownDataCell(rec, 'reason'));
133
+ if (reason === undefined)
134
+ return UNREADABLE_AUTHORIZATION;
135
+ const authorizeUrl = nonEmptyString(ownDataCell(rec, 'authorizeUrl'));
136
+ const resourceMetadataUrl = nonEmptyString(ownDataCell(rec, 'resourceMetadataUrl'));
137
+ return Object.freeze({
138
+ kind: 'record',
139
+ authorization: Object.freeze({
140
+ reason,
141
+ ...(authorizeUrl !== undefined ? { authorizeUrl } : {}),
142
+ ...(resourceMetadataUrl !== undefined ? { resourceMetadataUrl } : {}),
143
+ }),
144
+ });
145
+ }
146
+ catch {
147
+ return UNREADABLE_AUTHORIZATION;
148
+ }
149
+ }
@@ -1,3 +1,4 @@
1
+ import { type McpAuthorizationView } from './mcpLiveness.js';
1
2
  export declare const MCP_RECONNECT_OUTCOMES: readonly string[];
2
3
  export declare const MCP_RECONNECT_TRANSACTION_NOTICE: string;
3
4
  export declare const MCP_RECONNECT_UNSETTLED_NOTICE: string;
@@ -13,6 +14,8 @@ export interface McpReconnectStatusView {
13
14
  };
14
15
  error?: string;
15
16
  transportClosed?: true;
17
+ authorization?: McpAuthorizationView;
18
+ authorizationUnreadable?: true;
16
19
  }
17
20
  export interface McpReconnectListingIncompleteView {
18
21
  reason: string;
@@ -1,6 +1,7 @@
1
1
  import { capForDisplay } from './fleetTaskDesc.js';
2
2
  import { ownDataField } from './ownKey.js';
3
3
  import { isSessionIdPathSegment } from './sessionIdSegment.js';
4
+ import { readMcpAuthorization } from './mcpLiveness.js';
4
5
  export const MCP_RECONNECT_OUTCOMES = Object.freeze(['accepted', 'refused', 'unsupported']);
5
6
  export const MCP_RECONNECT_TRANSACTION_NOTICE = 'Reconnecting closes the current connection before dialing again. On a healthy server this is a transaction, ' +
6
7
  'not a refresh: a failed re-dial leaves the server down and withdraws its tools from the model until a later re-dial succeeds.';
@@ -33,6 +34,11 @@ function projectStatus(raw) {
33
34
  view.error = capForDisplay(raw.error, RECONNECT_TEXT_MAX);
34
35
  if (raw.transportClosed === true)
35
36
  view.transportClosed = true;
37
+ const authorization = readMcpAuthorization(raw);
38
+ if (authorization.kind === 'record')
39
+ view.authorization = authorization.authorization;
40
+ else if (authorization.kind === 'unreadable')
41
+ view.authorizationUnreadable = true;
36
42
  return view;
37
43
  }
38
44
  function projectListingIncomplete(raw) {
@@ -1,3 +1,4 @@
1
+ import { readMcpAuthorization } from './mcpLiveness.js';
1
2
  import { guardedRead, readOwnDataValue } from './ownKey.js';
2
3
  function slot(input, key) {
3
4
  return guardedRead(() => readOwnDataValue(input, key));
@@ -13,6 +14,9 @@ function shellConnectionOf(input) {
13
14
  ...(typeof error === 'string' && error !== '' ? { error } : {}),
14
15
  });
15
16
  }
17
+ const _legStructuralKeysPin = true;
18
+ void _legStructuralKeysPin;
19
+ const AUTHORIZATION_SEATS = new Set(['authorization', 'authorizationUnreadable']);
16
20
  function frozenCopyOfEngineLeg(leg) {
17
21
  if (typeof leg !== 'object' || leg === null)
18
22
  return undefined;
@@ -24,11 +28,30 @@ function frozenCopyOfEngineLeg(leg) {
24
28
  catch {
25
29
  return undefined;
26
30
  }
31
+ const put = (k, v) => {
32
+ Object.defineProperty(copy, k, { value: v, enumerable: true, writable: true, configurable: true });
33
+ };
34
+ const authorization = readMcpAuthorization(leg);
35
+ let authorizationPlaced = false;
36
+ const placeAuthorization = () => {
37
+ if (authorizationPlaced)
38
+ return;
39
+ authorizationPlaced = true;
40
+ if (authorization.kind === 'record')
41
+ put('authorization', authorization.authorization);
42
+ else if (authorization.kind === 'unreadable' || slot(leg, 'authorizationUnreadable') === true)
43
+ put('authorizationUnreadable', true);
44
+ };
27
45
  for (const k of keys) {
46
+ if (AUTHORIZATION_SEATS.has(k)) {
47
+ placeAuthorization();
48
+ continue;
49
+ }
28
50
  const v = slot(leg, k);
29
51
  if (typeof v === 'string' || typeof v === 'boolean' || (typeof v === 'number' && Number.isFinite(v)))
30
- Object.defineProperty(copy, k, { value: v, enumerable: true, writable: true, configurable: true });
52
+ put(k, v);
31
53
  }
54
+ placeAuthorization();
32
55
  return typeof copy['state'] === 'string' ? Object.freeze(copy) : undefined;
33
56
  }
34
57
  export function mcpStatusSupersetKeys(input) {
@@ -37,7 +37,6 @@ export type McpHttpIdentityHeaders = {
37
37
  export declare function readMcpHttpIdentityHeaders(transport: object): McpHttpIdentityHeaders;
38
38
  export declare function mcpConfigToSpec(name: string, c: McpConfigLike): McpServerSpec | null;
39
39
  export declare function mcpTransportVerdict(entry: McpTransportEntryLike | null | undefined): McpTransportVerdict;
40
- export declare function mcpConfigsToSpecs(servers: Record<string, McpConfigLike> | undefined): McpServerSpec[];
41
40
  export type McpToolAxesVerdict = {
42
41
  readonly kind: 'ok';
43
42
  readonly toolAxes?: Readonly<Record<string, object>>;
@@ -73,8 +72,8 @@ export type McpAllowToolsVerdict = {
73
72
  readonly problem: string;
74
73
  };
75
74
  export declare function mcpAllowToolsVerdict(read: () => {} | null | undefined, keyPrefix?: string): McpAllowToolsVerdict;
76
- export type McpConfigDropReason = 'name_blank' | 'name_edge_whitespace' | 'name_collides_after_trim' | 'name_too_long' | 'transport_invalid' | 'identity_headers_both_set' | 'tool_axes_invalid' | 'tool_faces_invalid' | 'elicitation_invalid' | 'allow_tools_invalid' | 'entry_not_object' | 'entry_unreadable';
77
- export type McpServerNameUnusableReason = 'name_blank' | 'name_edge_whitespace' | 'name_collides_after_trim' | 'name_too_long';
75
+ export type McpConfigDropReason = 'name_blank' | 'name_edge_whitespace' | 'name_collides_after_trim' | 'name_too_long' | 'name_reserved' | 'transport_invalid' | 'identity_headers_both_set' | 'tool_axes_invalid' | 'tool_faces_invalid' | 'elicitation_invalid' | 'allow_tools_invalid' | 'entry_not_object' | 'entry_unreadable';
76
+ export type McpServerNameUnusableReason = 'name_blank' | 'name_edge_whitespace' | 'name_collides_after_trim' | 'name_too_long' | 'name_reserved';
78
77
  export type McpServerNameVerdict = {
79
78
  readonly usable: true;
80
79
  } | {
@@ -1,4 +1,4 @@
1
- import { SETTINGS_DESCRIBE_BAD_WIRE_NAME, SETTINGS_IS_USABLE_WIRE_NAME, SETTINGS_READ_MCP_IDENTITY_HEADERS, SETTINGS_READ_REQUEST_MCP_TRANSPORT, } from './generated/settingsSchemaFns.js';
1
+ import { SETTINGS_DESCRIBE_BAD_MCP_SERVER_NAME, SETTINGS_IS_USABLE_MCP_SERVER_NAME, SETTINGS_IS_USABLE_WIRE_NAME, SETTINGS_READ_MCP_IDENTITY_HEADERS, SETTINGS_READ_REQUEST_MCP_TRANSPORT, } from './generated/settingsSchemaFns.js';
2
2
  import { snapshotArgs, wireTransportOf } from './mcpWireTransport.js';
3
3
  import { appendOwnElement, guardedRead } from './ownKey.js';
4
4
  import { readMcpToolAxes, readToolFaces } from './coreValuePorts.js';
@@ -173,9 +173,6 @@ export function mcpTransportVerdict(entry) {
173
173
  function transportBadVerdict(key, detail) {
174
174
  return Object.freeze({ kind: 'bad', key, detail });
175
175
  }
176
- export function mcpConfigsToSpecs(servers) {
177
- return projectMcpConfigs(servers).specs;
178
- }
179
176
  export function mcpToolAxesVerdict(declared) {
180
177
  if (declared === undefined)
181
178
  return Object.freeze({ kind: 'ok' });
@@ -252,11 +249,13 @@ export function mcpAllowToolsVerdict(read, keyPrefix = '') {
252
249
  return bad('allowTools', 'config.mcp.allowToolsUnreadable');
253
250
  }
254
251
  }
255
- const nameUsable = (name) => SETTINGS_IS_USABLE_WIRE_NAME(name);
252
+ const nameUsable = (name) => SETTINGS_IS_USABLE_MCP_SERVER_NAME(name);
256
253
  function mcpNameDropReasonOf(name) {
257
254
  if (typeof name !== 'string' || name.trim().length === 0)
258
255
  return 'name_blank';
259
- return name.trim() !== name ? 'name_edge_whitespace' : 'name_too_long';
256
+ if (name.trim() !== name)
257
+ return 'name_edge_whitespace';
258
+ return SETTINGS_IS_USABLE_WIRE_NAME(name) ? 'name_reserved' : 'name_too_long';
260
259
  }
261
260
  const _nameReasonsPin = true;
262
261
  void _nameReasonsPin;
@@ -316,7 +315,7 @@ function dropNotice(name, reason, problem, opts, path) {
316
315
  }
317
316
  const where = typeof label === 'string' && label.length > 0 ? ` (${capForDisplay(label, DROP_LABEL_SHOWN)})` : '';
318
317
  const quoted = `"${capForDisplay(name, DROP_NAME_SHOWN)}"`;
319
- const badName = () => capForDisplay(SETTINGS_DESCRIBE_BAD_WIRE_NAME(name), DROP_BAD_NAME_SHOWN);
318
+ const badName = () => capForDisplay(SETTINGS_DESCRIBE_BAD_MCP_SERVER_NAME(name), DROP_BAD_NAME_SHOWN);
320
319
  const ref = reason === 'entry_not_object'
321
320
  ? msg('config.mcp.entryNotObject', { name: quoted, where })
322
321
  : reason === 'entry_unreadable'
@@ -339,7 +338,9 @@ function dropNotice(name, reason, problem, opts, path) {
339
338
  ? msg('config.mcp.nameCollides', { name: badName(), where })
340
339
  : reason === 'name_too_long'
341
340
  ? msg('config.mcp.nameTooLong', { name: badName(), where })
342
- : msg('config.mcp.nameEdgeWhitespace', { name: badName(), where });
341
+ : reason === 'name_reserved'
342
+ ? msg('config.mcp.nameReserved', { name: badName(), where })
343
+ : msg('config.mcp.nameEdgeWhitespace', { name: badName(), where });
343
344
  return renderMessage(ref, opts?.lang);
344
345
  }
345
346
  function degradedNotice(name, lost, opts) {
@@ -436,6 +437,6 @@ export function mcpAssertionHeaderNotSentNotice(specs) {
436
437
  const parts = distinct.slice(0, ASSERTION_NOTICE_NAMES_SHOWN).map((x) => `"${x}"`);
437
438
  if (distinct.length > ASSERTION_NOTICE_NAMES_SHOWN)
438
439
  parts.push(`+${distinct.length - ASSERTION_NOTICE_NAMES_SHOWN} more`);
439
- return (`MCP servers that declare an assertion header (assertionHeader): ${parts.join(', ')} — server versions up to 7.134.0 accept this setting but do not send the header, ` +
440
+ return (`MCP servers that declare an assertion header (assertionHeader): ${parts.join(', ')} — server versions up to 7.139.0 accept this setting but do not send the header, ` +
440
441
  'and this client cannot tell whether the engine it uses sends it; a connector that requires the header will refuse requests from these servers');
441
442
  }
@@ -38,10 +38,17 @@ export declare function scopeExternalOriginVerdict(reading: MemoryExportReading,
38
38
  originAware: boolean;
39
39
  }): ScopeExternalOriginVerdict;
40
40
  export type { MemoryErasedBinding };
41
+ export type MemoryErasedBindingReading = Exclude<MemoryErasedBinding, {
42
+ state: 'bound';
43
+ }> | (Omit<Extract<MemoryErasedBinding, {
44
+ state: 'bound';
45
+ }>, 'slug'> & {
46
+ slug?: string;
47
+ });
41
48
  export interface MemoryErasedRow {
42
49
  id: string;
43
50
  rev: string;
44
- binding: MemoryErasedBinding | null;
51
+ binding: MemoryErasedBindingReading | null;
45
52
  }
46
53
  export interface MemoryEraseNotFoundRow {
47
54
  id: string;
@@ -54,6 +61,31 @@ export interface MemoryEraseConflictRow {
54
61
  id: string;
55
62
  reason: string;
56
63
  }
64
+ declare const MEMORY_ERASE_CARRIER_CLASSES: readonly ["projection", "shadow", "indexLine", "quarantineCopy", "planArchive", "planWorkbook", "evidenceBinding", "backendDerived"];
65
+ export type MemoryEraseCarrierClass = (typeof MEMORY_ERASE_CARRIER_CLASSES)[number];
66
+ export type MemoryEraseCarrierReading = {
67
+ removed: number;
68
+ remaining: number;
69
+ } | {
70
+ unverified: true;
71
+ };
72
+ declare const ERASE_REPLAY_OF_LANE: Readonly<{
73
+ readonly journal: "converges";
74
+ readonly none: "unsupported";
75
+ }>;
76
+ export interface MemoryEraseResidualsReading {
77
+ carriers: Record<MemoryEraseCarrierClass, MemoryEraseCarrierReading>;
78
+ replay: (typeof ERASE_REPLAY_OF_LANE)[keyof typeof ERASE_REPLAY_OF_LANE];
79
+ propagation: 'local-store-only';
80
+ }
81
+ export type MemoryErasePartialCause = {
82
+ kind: 'entries_pending';
83
+ } | {
84
+ kind: 'carriers_residual';
85
+ carriers: MemoryEraseCarrierClass[];
86
+ } | {
87
+ kind: 'unknown';
88
+ };
57
89
  export type MemoryEraseUnreadableCause = 'body_unreadable' | 'envelope_absent' | 'version_absent' | 'unsupported_version' | 'envelope_unreadable' | 'too_many_rows' | 'erased_rows_unreadable' | 'not_found_rows_unreadable' | 'conflict_rows_unreadable' | 'erased_previously_rows_unreadable';
58
90
  export type MemoryEraseReceiptReading = {
59
91
  kind: 'malformed';
@@ -73,6 +105,8 @@ export type MemoryEraseReceiptReading = {
73
105
  erasedPreviouslyDropped: number;
74
106
  conflicts: MemoryEraseConflictRow[];
75
107
  conflictsDropped: number;
108
+ residuals: MemoryEraseResidualsReading | null;
109
+ partialCause: MemoryErasePartialCause | null;
76
110
  };
77
111
  export declare function readMemoryEraseReceipt(body: unknown): MemoryEraseReceiptReading;
78
112
  export type MemoryEraseCounts = {
@@ -38,12 +38,6 @@ function snapshotArray(v) {
38
38
  }
39
39
  return { items, unreadable, tooLarge: false };
40
40
  }
41
- function arrayLengthOrNull(v) {
42
- const snap = snapshotArray(v);
43
- if (snap === null || snap.tooLarge)
44
- return null;
45
- return snap.items.length + snap.unreadable;
46
- }
47
41
  function originMarkOf(row) {
48
42
  if (ownPresent(row, 'origin'))
49
43
  return 'marked';
@@ -175,7 +169,24 @@ export function scopeExternalOriginVerdict(reading, asked) {
175
169
  }
176
170
  return { kind: 'none_in_this_scope', scope: reading.scope };
177
171
  }
178
- const MEMORY_ERASE_RECEIPT_VERSION = 1;
172
+ const MEMORY_ERASE_CARRIER_CLASSES = Object.freeze([
173
+ 'projection',
174
+ 'shadow',
175
+ 'indexLine',
176
+ 'quarantineCopy',
177
+ 'planArchive',
178
+ 'planWorkbook',
179
+ 'evidenceBinding',
180
+ 'backendDerived',
181
+ ]);
182
+ const MEMORY_ERASE_CARRIER_CLASS_SET = new Set(MEMORY_ERASE_CARRIER_CLASSES);
183
+ const ERASE_REPLAY_OF_LANE = Object.freeze({ journal: 'converges', none: 'unsupported' });
184
+ const _eraseResidualsPin = true;
185
+ void _eraseResidualsPin;
186
+ const ERASE_RECEIPT_VERSIONS = new Map([
187
+ [1, Object.freeze({ boundSlug: 'required', carrierTable: false })],
188
+ [2, Object.freeze({ boundSlug: 'optional', carrierTable: true })],
189
+ ]);
179
190
  function eraseStatusOf(v) {
180
191
  return v === 'complete' || v === 'partial' ? v : null;
181
192
  }
@@ -185,7 +196,7 @@ function eraseEvidenceCapabilityOf(v) {
185
196
  function eraseCustodyStateOf(v) {
186
197
  return v === 'complete' || v === 'damaged' || v === 'capability-absent' ? v : null;
187
198
  }
188
- function erasedBindingOf(v) {
199
+ function erasedBindingOf(v, slugRule) {
189
200
  if (!plainObject(v))
190
201
  return null;
191
202
  const state = v.state;
@@ -194,10 +205,75 @@ function erasedBindingOf(v) {
194
205
  if (state !== 'bound')
195
206
  return null;
196
207
  const scope = v.scope;
208
+ if (!nonEmptyString(scope))
209
+ return null;
210
+ const slugPresent = Object.hasOwn(v, 'slug');
211
+ if (!slugPresent)
212
+ return slugRule === 'optional' ? { state: 'bound', scope } : null;
197
213
  const slug = v.slug;
198
- if (!nonEmptyString(scope) || !nonEmptyString(slug))
214
+ return nonEmptyString(slug) ? { state: 'bound', scope, slug } : null;
215
+ }
216
+ function carrierAnswerOf(v) {
217
+ if (!plainObject(v))
218
+ return null;
219
+ const unverified = readThrownSlot(v, 'unverified', 'data');
220
+ const removed = readThrownSlot(v, 'removed', 'data');
221
+ const remaining = readThrownSlot(v, 'remaining', 'data');
222
+ if (unverified !== undefined)
223
+ return unverified === true && removed === undefined && remaining === undefined ? { unverified: true } : null;
224
+ return nonNegativeInt(removed) && nonNegativeInt(remaining) ? { removed, remaining } : null;
225
+ }
226
+ function eraseResidualsOf(o, lane) {
227
+ try {
228
+ const raw = readThrownSlot(o, 'residuals', 'data');
229
+ if (!plainObject(raw))
230
+ return null;
231
+ const rawCarriers = readThrownSlot(raw, 'carriers', 'data');
232
+ const replay = readThrownSlot(raw, 'replay', 'data');
233
+ const propagation = readThrownSlot(raw, 'propagation', 'data');
234
+ if (!plainObject(rawCarriers) || replay !== ERASE_REPLAY_OF_LANE[lane] || propagation !== 'local-store-only')
235
+ return null;
236
+ if (Reflect.ownKeys(rawCarriers).some((k) => typeof k !== 'string' || !MEMORY_ERASE_CARRIER_CLASS_SET.has(k)))
237
+ return null;
238
+ const carriers = {};
239
+ for (const cls of MEMORY_ERASE_CARRIER_CLASSES) {
240
+ const answer = carrierAnswerOf(readThrownSlot(rawCarriers, cls, 'data'));
241
+ if (answer === null)
242
+ return null;
243
+ carriers[cls] = answer;
244
+ }
245
+ return { carriers, replay: ERASE_REPLAY_OF_LANE[lane], propagation };
246
+ }
247
+ catch {
199
248
  return null;
200
- return { state: 'bound', scope, slug };
249
+ }
250
+ }
251
+ function erasePartialCauseOf(f) {
252
+ if (f.status === 'complete')
253
+ return null;
254
+ if (f.conflicts.length > 0)
255
+ return { kind: 'entries_pending' };
256
+ if (f.dropped > 0 || f.pinnedIds === null)
257
+ return { kind: 'unknown' };
258
+ const claimed = new Set([...f.erased.map((r) => r.id), ...(f.erasedPreviously ?? []).map((r) => r.id)]);
259
+ const notFound = new Set(f.notFound.map((r) => r.id));
260
+ let historyUnknown = false;
261
+ for (const id of f.pinnedIds) {
262
+ if (claimed.has(id))
263
+ continue;
264
+ if (!notFound.has(id))
265
+ return { kind: 'entries_pending' };
266
+ if (f.custodyState !== 'complete')
267
+ historyUnknown = true;
268
+ }
269
+ if (historyUnknown || f.residuals === null)
270
+ return { kind: 'unknown' };
271
+ const carriers = f.residuals.carriers;
272
+ const residual = MEMORY_ERASE_CARRIER_CLASSES.filter((c) => {
273
+ const a = carriers[c];
274
+ return 'unverified' in a || a.remaining > 0;
275
+ });
276
+ return residual.length > 0 ? { kind: 'carriers_residual', carriers: residual } : { kind: 'unknown' };
201
277
  }
202
278
  export function readMemoryEraseReceipt(body) {
203
279
  let o;
@@ -229,8 +305,10 @@ export function readMemoryEraseReceipt(body) {
229
305
  return { kind: 'malformed', why: 'envelope_absent' };
230
306
  if (rawV === undefined)
231
307
  return { kind: 'malformed', why: 'version_absent' };
232
- if (rawV !== MEMORY_ERASE_RECEIPT_VERSION)
308
+ const rule = ERASE_RECEIPT_VERSIONS.get(rawV);
309
+ if (rule === undefined)
233
310
  return { kind: 'malformed', why: 'unsupported_version' };
311
+ const slugRule = rule.boundSlug;
234
312
  const status = eraseStatusOf(rawStatus);
235
313
  const evidenceCapability = eraseEvidenceCapabilityOf(rawEvidence);
236
314
  const custodyState = eraseCustodyStateOf(rawCustody);
@@ -241,13 +319,13 @@ export function readMemoryEraseReceipt(body) {
241
319
  let notFoundSnap;
242
320
  let conflictsSnap;
243
321
  let previouslySnap;
244
- let selectedIds;
322
+ let selectedSnap;
245
323
  try {
246
324
  erasedSnap = snapshotArray(rawErased);
247
325
  notFoundSnap = snapshotArray(rawNotFound);
248
326
  conflictsSnap = snapshotArray(rawConflicts);
249
327
  previouslySnap = rawPreviously === undefined ? null : snapshotArray(rawPreviously);
250
- selectedIds = arrayLengthOrNull(rawSelected);
328
+ selectedSnap = snapshotArray(rawSelected);
251
329
  }
252
330
  catch {
253
331
  return { kind: 'malformed', why: 'body_unreadable' };
@@ -255,6 +333,10 @@ export function readMemoryEraseReceipt(body) {
255
333
  if (erasedSnap === null || notFoundSnap === null || conflictsSnap === null) {
256
334
  return { kind: 'malformed', why: 'envelope_unreadable' };
257
335
  }
336
+ const selectedIds = selectedSnap === null || selectedSnap.tooLarge ? null : selectedSnap.items.length + selectedSnap.unreadable;
337
+ const pinnedIds = selectedSnap !== null && !selectedSnap.tooLarge && selectedSnap.unreadable === 0 && selectedSnap.items.every(nonEmptyString)
338
+ ? selectedSnap.items
339
+ : null;
258
340
  if (rawPreviously !== undefined && previouslySnap === null) {
259
341
  return { kind: 'malformed', why: 'envelope_unreadable' };
260
342
  }
@@ -277,7 +359,7 @@ export function readMemoryEraseReceipt(body) {
277
359
  continue;
278
360
  }
279
361
  erasedSeen.add(id);
280
- erased.push({ id, rev, binding: erasedBindingOf(item.binding) });
362
+ erased.push({ id, rev, binding: erasedBindingOf(item.binding, slugRule) });
281
363
  }
282
364
  catch {
283
365
  erasedDropped++;
@@ -367,6 +449,18 @@ export function readMemoryEraseReceipt(body) {
367
449
  }
368
450
  erasedPreviously = rows;
369
451
  }
452
+ const residuals = rule.carrierTable ? eraseResidualsOf(o, evidenceCapability) : null;
453
+ const partialCause = erasePartialCauseOf({
454
+ status,
455
+ custodyState,
456
+ pinnedIds,
457
+ erased,
458
+ erasedPreviously,
459
+ notFound,
460
+ conflicts,
461
+ dropped: erasedDropped + notFoundDropped + erasedPreviouslyDropped + conflictsDropped,
462
+ residuals,
463
+ });
370
464
  return {
371
465
  kind: 'present',
372
466
  requestId: rawRequestId,
@@ -382,6 +476,8 @@ export function readMemoryEraseReceipt(body) {
382
476
  erasedPreviouslyDropped,
383
477
  conflicts,
384
478
  conflictsDropped,
479
+ residuals,
480
+ partialCause,
385
481
  };
386
482
  }
387
483
  export function memoryEraseCounts(reading) {
package/dist/modsFace.js CHANGED
@@ -2,7 +2,7 @@ import { modRowsOf } from './adapter/downstream/wiringManifestView.js';
2
2
  import { msg, renderMessage } from './i18n/translate.js';
3
3
  import { displayUntrusted } from './displayUntrusted.js';
4
4
  import { WIRE_FAILURE_UNRENDERABLE_TEXT, wireFailureTextsOf } from './wireFailureShape.js';
5
- import { gateOutcomeOf, isDeniedGate } from './gateOutcome.js';
5
+ import { gateOutcomeOf, isDeniedGate, rewriteExtensionNamesOf, toolInputRewriteOf } from './gateOutcome.js';
6
6
  import { guardedRead, readOwnDataNonEmptyString, readOwnDataValue, toolResultBlockOf } from './ownKey.js';
7
7
  const isCardRecordObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
8
8
  export const MOD_LOADER_VERBS = Object.freeze(['list', 'load', 'unload', 'status']);
@@ -31,8 +31,12 @@ export function modCardSentence(input, lang) {
31
31
  return undefined;
32
32
  if (toolResultBlockOf(input) !== undefined) {
33
33
  const by = readOwnDataNonEmptyString(input, '_sema_answered_by');
34
- if (by === undefined)
35
- return undefined;
34
+ if (by === undefined) {
35
+ const names = rewriteExtensionNamesOf(toolInputRewriteOf({ rewrite: readOwnDataValue(input, '_sema_rewrite') }));
36
+ if (names.length === 0)
37
+ return undefined;
38
+ return renderMessage(msg('config.mods.rewrite.inputBy', { by: names.map(shownName).join(', ') }), lang);
39
+ }
36
40
  const gate = gateOutcomeOf({ gate: readOwnDataValue(input, '_sema_gate') });
37
41
  return isDeniedGate(gate)
38
42
  ? renderMessage(msg('config.mods.refusal.by', { by: shownName(by) }), lang)
@@ -1,5 +1,5 @@
1
1
  import { capForDisplay } from './fleetTaskDesc.js';
2
- export const POSTURE_SOURCE_WORDS = Object.freeze(['env', 'center', 'posture', 'engine-default']);
2
+ export const POSTURE_SOURCE_WORDS = Object.freeze(['env', 'center', 'lane', 'posture', 'engine-default']);
3
3
  export function postureSourceIsOperatorPinned(source) {
4
4
  return source === 'env' || source === 'center';
5
5
  }
@@ -6,4 +6,3 @@ export interface PrepareRefusalNoteFacts {
6
6
  }
7
7
  export declare function prepareRefusalNoteOf(code: string | undefined, facts?: PrepareRefusalNoteFacts): string | undefined;
8
8
  export declare function prepareRefusalCodeOf(failure: {} | null | undefined): PrepareRefusalCode | undefined;
9
- export declare function imageInvalidFailureNoteOf(code: string | undefined): string | undefined;
@@ -85,6 +85,3 @@ export function prepareRefusalCodeOf(failure) {
85
85
  return undefined;
86
86
  }
87
87
  }
88
- export function imageInvalidFailureNoteOf(code) {
89
- return code === CONFIG_IMAGE_INVALID ? prepareRefusalNoteOf(code) : undefined;
90
- }
@@ -20,6 +20,7 @@ export interface PrintModelStatusPayload {
20
20
  readonly elapsed_ms?: number;
21
21
  readonly timeout_ms?: number;
22
22
  readonly model?: string;
23
+ readonly seat?: string;
23
24
  readonly phase: RetryStatusNotice['phase'];
24
25
  readonly recourse?: NonNullable<RetryStatusNotice['recourse']>;
25
26
  readonly message: string;
@@ -41,6 +41,7 @@ function modelStatusPayload(status, ctx) {
41
41
  ...(elapsed !== undefined ? { elapsed_ms: elapsed } : {}),
42
42
  ...(ceiling !== undefined ? { timeout_ms: ceiling } : {}),
43
43
  ...(model !== undefined ? { model } : {}),
44
+ ...(typeof status.seat === 'string' ? { seat: status.seat } : {}),
44
45
  phase: notice.phase,
45
46
  ...(notice.recourse !== undefined ? { recourse: notice.recourse } : {}),
46
47
  message: notice.line,
@@ -49,6 +50,8 @@ function modelStatusPayload(status, ctx) {
49
50
  function apiRetryKeyOf(status) {
50
51
  const terminal = 'terminal' in status && status.terminal === true;
51
52
  const ok = (v) => typeof v === 'number' && Number.isInteger(v) && v >= 0;
53
+ if (status.seat !== undefined)
54
+ return null;
52
55
  if (status.kind === 'waiting' || terminal || !ok(status.attempt) || !ok(status.maxRetries))
53
56
  return null;
54
57
  return `${String(status.attempt)}/${String(status.maxRetries)}/${String(status.errClass ?? '')}/${String(status.errorStatus ?? '')}`;
@@ -126,12 +129,13 @@ export function createPrintModelStatusTracker() {
126
129
  clear();
127
130
  return null;
128
131
  }
129
- const model = readOwnDataNonEmptyString(ctx, 'model');
132
+ const model = status.seat === undefined ? readOwnDataNonEmptyString(ctx, 'model') : undefined;
130
133
  const key = apiRetryKeyOf(status);
131
134
  const refresh = key !== null && key === lastApiRetryKey;
132
135
  const safeCtx = { sessionId, nowMs, mintUuid, ...(model !== undefined ? { model } : {}) };
133
136
  const frame = statusFrameOf(status, safeCtx, mintUuid(), refresh);
134
- lastApiRetryKey = key;
137
+ if (status.seat === undefined)
138
+ lastApiRetryKey = key;
135
139
  last = { status, model };
136
140
  return frame;
137
141
  }
@@ -1,4 +1,2 @@
1
- import type { TaskRequest } from '@sema-agent/sdk';
2
1
  import { type EnvLike } from './hostEnv.js';
3
- export type PromptProfile = NonNullable<TaskRequest['promptProfile']>;
4
- export declare function promptProfileFromEnv(env?: EnvLike): PromptProfile | undefined;
2
+ export declare function promptLeanFromEnv(env?: EnvLike): false | undefined;
@@ -1,7 +1,7 @@
1
1
  import { hostEnv } from './hostEnv.js';
2
2
  const PROMPT_PROFILE_ENV = 'SEMA_PROMPT_PROFILE';
3
- export function promptProfileFromEnv(env = hostEnv()) {
3
+ export function promptLeanFromEnv(env = hostEnv()) {
4
4
  const raw = env[PROMPT_PROFILE_ENV];
5
5
  const s = typeof raw === 'string' ? raw.trim().toLowerCase() : '';
6
- return s === 'simple' || s === 'classic' ? s : undefined;
6
+ return s === 'classic' ? false : undefined;
7
7
  }
@@ -39,7 +39,7 @@ export interface TaskRequestInput {
39
39
  selfOrchestration?: boolean;
40
40
  deferTools?: readonly string[];
41
41
  retainBackgroundProcesses?: boolean;
42
- promptProfile?: string;
42
+ promptLean?: boolean;
43
43
  enableFork?: boolean;
44
44
  attachments?: Record<string, unknown>;
45
45
  attachmentIds?: readonly string[];