@sema-agent/client-core 0.99.0 → 0.100.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 (128) hide show
  1. package/CHANGELOG.md +177 -0
  2. package/README.md +32 -19
  3. package/dist/adapt/arms.js +60 -36
  4. package/dist/adapt/panelTasks.d.ts +2 -1
  5. package/dist/adapt/panelTasks.js +32 -9
  6. package/dist/adapt/textStream.d.ts +1 -1
  7. package/dist/adapt/textStream.js +51 -28
  8. package/dist/adapter/activeRunSelfHeal.d.ts +7 -0
  9. package/dist/adapter/activeRunSelfHeal.js +58 -11
  10. package/dist/adapter/downstream/eventToSdkMessage.d.ts +25 -6
  11. package/dist/adapter/downstream/eventToSdkMessage.js +125 -9
  12. package/dist/adapter/downstream/terminalToSdkResult.js +10 -0
  13. package/dist/adapter/downstream/wiringManifestView.d.ts +3 -1
  14. package/dist/adapter/downstream/wiringManifestView.js +1 -0
  15. package/dist/adapter/runStream.js +32 -5
  16. package/dist/adapter/types.d.ts +2 -0
  17. package/dist/agentsWireCaps.d.ts +7 -0
  18. package/dist/agentsWireCaps.js +100 -15
  19. package/dist/cloudConfigWireCaps.d.ts +10 -1
  20. package/dist/cloudConfigWireCaps.js +156 -62
  21. package/dist/compactionStatus.d.ts +34 -0
  22. package/dist/compactionStatus.js +196 -0
  23. package/dist/decideFailureNote.js +3 -3
  24. package/dist/displayUntrusted.js +150 -5
  25. package/dist/engineAgentPanelStore.d.ts +7 -4
  26. package/dist/engineErrorCodes.d.ts +9 -1
  27. package/dist/engineErrorCodes.js +9 -5
  28. package/dist/engineRowRef.js +1 -0
  29. package/dist/engineToolDirectory.d.ts +3 -0
  30. package/dist/engineToolDirectory.js +4 -2
  31. package/dist/eventLeg.d.ts +1 -7
  32. package/dist/eventLeg.js +7 -8
  33. package/dist/fileHistoryCaptureCapability.d.ts +0 -3
  34. package/dist/fileHistoryCaptureCapability.js +0 -4
  35. package/dist/generated/engineFactTables.d.ts +1 -0
  36. package/dist/generated/engineFactTables.js +27 -0
  37. package/dist/generated/engineNoticeTables.js +3 -0
  38. package/dist/generated/settingsSchemaFns.d.ts +12 -0
  39. package/dist/generated/settingsSchemaFns.js +13 -0
  40. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -0
  41. package/dist/generated/settingsSchemaMcpRequestEntry.js +162 -0
  42. package/dist/generated/settingsSchemaTables.d.ts +1 -0
  43. package/dist/generated/settingsSchemaTables.js +5 -0
  44. package/dist/generated/settingsSchemaTypes.d.ts +28 -0
  45. package/dist/hitl/allowRuleShadow.js +2 -2
  46. package/dist/hitl/approvalCardReasons.js +2 -2
  47. package/dist/hitl/approvalHolds.d.ts +14 -0
  48. package/dist/hitl/approvalHolds.js +41 -0
  49. package/dist/hitl/askClassPair.d.ts +2 -2
  50. package/dist/hitl/askClassPair.js +2 -2
  51. package/dist/hitl/attributionLadder.d.ts +23 -0
  52. package/dist/hitl/attributionLadder.js +67 -0
  53. package/dist/hitl/decisionLedger.d.ts +55 -0
  54. package/dist/hitl/decisionLedger.js +156 -0
  55. package/dist/hitl/decisionRefusal.d.ts +1 -0
  56. package/dist/hitl/decisionRefusal.js +1 -1
  57. package/dist/hitl/decisionSend.d.ts +113 -0
  58. package/dist/hitl/decisionSend.js +579 -0
  59. package/dist/hitl/hitlBridge.js +18 -6
  60. package/dist/hitl/planReviewWire.js +45 -76
  61. package/dist/hitl/sessionPolicyDeliverable.js +3 -6
  62. package/dist/hitl/toolApprovalWire.js +43 -109
  63. package/dist/hostTurnSettings.d.ts +46 -7
  64. package/dist/hostTurnSettings.js +408 -7
  65. package/dist/humanTurn.d.ts +2 -1
  66. package/dist/humanTurn.js +3 -3
  67. package/dist/i18n/messages.en.d.ts +131 -0
  68. package/dist/i18n/messages.en.js +143 -12
  69. package/dist/i18n/messages.zh.js +148 -12
  70. package/dist/index.d.ts +18 -2
  71. package/dist/index.js +10 -1
  72. package/dist/inheritEnvCapability.d.ts +1 -0
  73. package/dist/inheritEnvCapability.js +9 -2
  74. package/dist/inheritEnvWire.js +2 -2
  75. package/dist/injectionLaneNotice.d.ts +5 -0
  76. package/dist/injectionLaneNotice.js +46 -0
  77. package/dist/mcpPanel.js +2 -0
  78. package/dist/mcpReconnect.js +2 -2
  79. package/dist/mcpToolToggles.d.ts +6 -0
  80. package/dist/mcpToolToggles.js +46 -0
  81. package/dist/mcpWireCaps.d.ts +10 -4
  82. package/dist/mcpWireCaps.js +106 -71
  83. package/dist/mcpWireTransport.d.ts +4 -0
  84. package/dist/mcpWireTransport.js +18 -0
  85. package/dist/modelCapabilityProbe.d.ts +2 -1
  86. package/dist/modelCapabilityProbe.js +10 -9
  87. package/dist/modelIdentityResolvability.d.ts +2 -0
  88. package/dist/modelIdentityResolvability.js +23 -5
  89. package/dist/ownKey.d.ts +26 -0
  90. package/dist/ownKey.js +75 -0
  91. package/dist/panelReduce.d.ts +5 -0
  92. package/dist/panelReduce.js +45 -13
  93. package/dist/panelStateHolder.d.ts +1 -0
  94. package/dist/panelStateHolder.js +10 -1
  95. package/dist/permissionRuleIssue.d.ts +2 -1
  96. package/dist/permissionRuleIssue.js +22 -21
  97. package/dist/pluginHooksWire.js +12 -10
  98. package/dist/prepareRefusal.d.ts +8 -0
  99. package/dist/prepareRefusal.js +72 -0
  100. package/dist/request/taskRequest.d.ts +10 -10
  101. package/dist/request/taskRequest.js +106 -65
  102. package/dist/resumeRefusalCopy.d.ts +3 -1
  103. package/dist/resumeRefusalCopy.js +22 -4
  104. package/dist/retryStatus.d.ts +18 -0
  105. package/dist/retryStatus.js +76 -19
  106. package/dist/ruleRefusalSentence.d.ts +4 -0
  107. package/dist/ruleRefusalSentence.js +58 -0
  108. package/dist/sandboxWire.d.ts +2 -1
  109. package/dist/sandboxWire.js +55 -21
  110. package/dist/scenarioRefusal.d.ts +2 -1
  111. package/dist/scenarioRefusal.js +5 -5
  112. package/dist/seam.d.ts +24 -9
  113. package/dist/seam.js +44 -4
  114. package/dist/seatContract.d.ts +16 -8
  115. package/dist/seatContract.js +21 -6
  116. package/dist/settingsCredentialKeyPaths.d.ts +8 -0
  117. package/dist/settingsCredentialKeyPaths.js +219 -0
  118. package/dist/skillsWireCaps.d.ts +0 -3
  119. package/dist/skillsWireCaps.js +1 -2
  120. package/dist/subagentContentStore.d.ts +1 -0
  121. package/dist/subagentContentStore.js +135 -27
  122. package/dist/toolsFlagNames.d.ts +8 -0
  123. package/dist/toolsFlagNames.js +110 -0
  124. package/dist/turnFailurePresentation.js +15 -7
  125. package/dist/wireRefusalCopy.d.ts +51 -17
  126. package/dist/wireRefusalCopy.js +298 -135
  127. package/docs/INTEGRATION-CLIENTS.md +423 -26
  128. package/package.json +4 -4
package/dist/ownKey.js CHANGED
@@ -189,3 +189,78 @@ export function mcpSectionDroppedNamedRowsOf(rows, name) {
189
189
  return 0;
190
190
  }
191
191
  }
192
+ export function promptManifestSectionViewOf(row) {
193
+ const o = row;
194
+ const str = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
195
+ const id = str(o.id);
196
+ const chars = typeof o.chars === 'number' && Number.isFinite(o.chars) && o.chars >= 0 ? o.chars : undefined;
197
+ if (id === undefined || chars === undefined)
198
+ return undefined;
199
+ const band = str(o.band);
200
+ const locale = str(o.locale);
201
+ const variant = str(o.variant);
202
+ const contentHash = band !== undefined ? str(o.contentHash) : undefined;
203
+ const slot = str(o.slot);
204
+ return {
205
+ id,
206
+ chars,
207
+ ...(band !== undefined ? { band } : {}),
208
+ ...(locale !== undefined ? { locale } : {}),
209
+ ...(variant !== undefined ? { variant } : {}),
210
+ ...(contentHash !== undefined ? { contentHash } : {}),
211
+ ...(slot !== undefined ? { slot } : {}),
212
+ };
213
+ }
214
+ export function promptManifestIdentityOfFrame(frame) {
215
+ let raw;
216
+ try {
217
+ raw = frame.identity;
218
+ }
219
+ catch {
220
+ return undefined;
221
+ }
222
+ return promptManifestIdentityOf(typeof raw === 'object' && raw !== null ? raw : undefined);
223
+ }
224
+ export function promptManifestIdentityOf(raw) {
225
+ try {
226
+ const plain = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
227
+ const str = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
228
+ if (!plain(raw))
229
+ return undefined;
230
+ const artifact = str(raw.artifact);
231
+ const activatedBy = str(raw.activatedBy);
232
+ const epochRaw = raw.epoch;
233
+ const epoch = typeof epochRaw === 'number' && Number.isInteger(epochRaw) && epochRaw >= 0 ? epochRaw : undefined;
234
+ const layersRaw = raw.layers;
235
+ if (artifact === undefined || activatedBy === undefined || epoch === undefined || !plain(layersRaw))
236
+ return undefined;
237
+ const catalog = str(layersRaw.catalog);
238
+ const binding = str(layersRaw.binding);
239
+ if (catalog === undefined || binding === undefined)
240
+ return undefined;
241
+ const optional = {};
242
+ for (const k of ['center', 'deploy', 'task']) {
243
+ const v = layersRaw[k];
244
+ if (v === undefined)
245
+ continue;
246
+ const t = str(v);
247
+ if (t === undefined)
248
+ return undefined;
249
+ optional[k] = t;
250
+ }
251
+ const renderersRaw = layersRaw.renderers;
252
+ if (!plain(renderersRaw))
253
+ return undefined;
254
+ const entries = [];
255
+ for (const [k, v] of Object.entries(renderersRaw)) {
256
+ if (typeof v !== 'number' || !Number.isFinite(v))
257
+ return undefined;
258
+ entries.push([k, v]);
259
+ }
260
+ const renderers = Object.fromEntries(entries);
261
+ return { artifact, layers: { catalog, renderers, ...optional, binding }, epoch, activatedBy };
262
+ }
263
+ catch {
264
+ return undefined;
265
+ }
266
+ }
@@ -116,6 +116,11 @@ export declare function reducePanelFrame(state: PanelReduceState, frame: PanelFr
116
116
  };
117
117
  export declare function panelRowSnapshot(state: PanelReduceState): PanelDelta[];
118
118
  export declare function panelResolveTaskId(state: PanelReduceState, wireTaskId: string): EnginePanelTaskIdentity;
119
+ export interface PanelSubagentIdentity {
120
+ readonly key: string;
121
+ readonly ids: readonly string[];
122
+ }
123
+ export declare function panelSubagentOf(state: PanelReduceState, id: string): PanelSubagentIdentity | undefined;
119
124
  export declare function panelIsResident(state: PanelReduceState, taskId: string): boolean;
120
125
  export declare function panelAnchorOf(state: PanelReduceState, taskId: string): string | undefined;
121
126
  export declare function panelPresenceSize(state: PanelReduceState, sessionKey: string): number;
@@ -1,6 +1,6 @@
1
1
  import { rowIdTail } from './workflow.js';
2
2
  import { isSdkFleetTaskTerminal, isSdkFleetTaskTerminalNotSuccess } from './terminalStatuses.js';
3
- import { carryCycle, cycleEmpty, cycleKeysChanged, cycleOf, cycleOrder, mergeCycle, } from './cycleOrder.js';
3
+ import { carryCycle, cycleEmpty, cycleKeysChanged, cycleOf, cycleOrder, cycleSeqValue, mergeCycle, } from './cycleOrder.js';
4
4
  export function isStaleEngineAgentPanelEnd(end, current) {
5
5
  return cycleOrder(end, current) === 'before';
6
6
  }
@@ -575,10 +575,26 @@ function fullUsage(key, row) {
575
575
  return undefined;
576
576
  return usageDelta(key, { ...(row.totalTokens !== undefined ? { totalTokens: row.totalTokens } : {}), ...(row.toolUses !== undefined ? { toolUses: row.toolUses } : {}), ...(fin !== undefined ? { final: fin } : {}) });
577
577
  }
578
+ function ownDataOf(o, key) {
579
+ if (typeof o !== 'object' || o === null)
580
+ return undefined;
581
+ try {
582
+ const d = Object.getOwnPropertyDescriptor(o, key);
583
+ return d !== undefined && 'value' in d ? d.value : undefined;
584
+ }
585
+ catch {
586
+ return undefined;
587
+ }
588
+ }
589
+ function publisherFinality(f) {
590
+ return { ...(ownDataOf(f, 'totalTokens') === true ? { totalTokens: true } : {}), ...(ownDataOf(f, 'toolUses') === true ? { toolUses: true } : {}) };
591
+ }
578
592
  function fleetCarrier(ev) {
579
- const f = ev.final;
580
- const final = { ...(f?.totalTokens === true ? { totalTokens: true } : {}), ...(f?.toolUses === true ? { toolUses: true } : {}) };
581
- return { totalTokens: ev.totalTokens, toolUses: ev.toolUses, final };
593
+ return { totalTokens: ev.totalTokens, toolUses: ev.toolUses, final: publisherFinality(ownDataOf(ev, 'final')) };
594
+ }
595
+ function tickCycleOf(ev) {
596
+ const c = cycleSeqValue(ownDataOf(ev, 'cycleSeq'));
597
+ return c === undefined ? undefined : { cycleSeq: c };
582
598
  }
583
599
  function finalityOf(tokens, toolUses) {
584
600
  if (tokens === undefined && toolUses === undefined)
@@ -638,17 +654,20 @@ function announce(d, rid) {
638
654
  if (row.phase === 'ended')
639
655
  mintTerminal(d, key, row.isError === true, row.report, 'end');
640
656
  }
641
- function foldTick(d, rid, ev, cardBound) {
657
+ function foldTick(d, rid, ev, cardBound, final) {
642
658
  const r = d.rec(rid);
643
659
  if (r === undefined)
644
660
  return;
645
661
  const row = r.row;
646
662
  const gate = cardBound ? { gateBound: true } : {};
647
663
  const wireId = ev.wireTaskId ?? ev.taskId;
648
- const attributable = !hasCycleSeq(r.cycle) && (r.currentRun === undefined || r.currentRun === wireId);
664
+ const tickCycle = tickCycleOf(ev);
665
+ const attributable = hasCycleSeq(r.cycle)
666
+ ? tickCycle !== undefined && cycleOrder(tickCycle, r.cycle) === 'same'
667
+ : r.currentRun === undefined || r.currentRun === wireId;
649
668
  if (!attributable)
650
669
  d.counts.unattributedTicks++;
651
- const carrier = attributable ? { totalTokens: ev.totalTokens, toolUses: ev.toolUses } : {};
670
+ const carrier = attributable ? { totalTokens: ev.totalTokens, toolUses: ev.toolUses, final } : {};
652
671
  if (row === undefined || !row.announced) {
653
672
  const base = row !== undefined
654
673
  ? { ...row, ...gate, tickSeen: true, fields: { ...row.fields, ...tickFields(ev) } }
@@ -789,28 +808,37 @@ function foldAbsence(d, rid, a) {
789
808
  d.deltas.push({ op: 'upsert', canonicalId: keyOf(r), fields: { absence } });
790
809
  d.put(rid, { row: { ...row, fields: { ...row.fields, absence } } });
791
810
  }
792
- function stripCardBound(ev) {
793
- const { cardBound: _cardBound, ...rest } = ev;
794
- void _cardBound;
795
- return rest;
811
+ function tickFactBase(ev) {
812
+ const out = {};
813
+ for (const k of Reflect.ownKeys(ev)) {
814
+ if (typeof k !== 'string' || k === 'cardBound' || k === 'final' || k === 'cycleSeq')
815
+ continue;
816
+ if (!Object.prototype.propertyIsEnumerable.call(ev, k))
817
+ continue;
818
+ out[k] = Reflect.get(ev, k);
819
+ }
820
+ return out;
796
821
  }
797
822
  function emitTick(d, ev) {
798
823
  const found = d.find(ev.taskId);
799
824
  const fr = found !== undefined ? d.rec(found) : undefined;
800
825
  if (fr !== undefined && formerGeneration(fr, ev.taskId))
801
826
  return;
827
+ const tickCycle = tickCycleOf(ev);
828
+ if (fr !== undefined && tickCycle !== undefined && cycleOrder(tickCycle, genOf(fr)) === 'before')
829
+ return;
802
830
  const rid = found ?? d.create({ id: ev.taskId });
803
831
  d.records.touch(rid);
804
832
  const r = d.rec(rid);
805
833
  if (r === undefined)
806
834
  return;
807
835
  const key = keyOf(r);
808
- const plain = stripCardBound(ev);
836
+ const plain = { ...tickFactBase(ev), ...(tickCycle !== undefined ? { cycleSeq: tickCycle.cycleSeq } : {}) };
809
837
  const fact = key === ev.taskId
810
838
  ? { ...plain, taskIdOrigin: 'wire' }
811
839
  : { ...plain, taskId: key, wireTaskId: ev.taskId, taskIdOrigin: key === r.tail ? 'fleet-row' : 'wire' };
812
840
  d.facts.push({ ch: 'event', ev: fact });
813
- foldTick(d, rid, fact, ev.cardBound === true);
841
+ foldTick(d, rid, fact, ev.cardBound === true, publisherFinality(ownDataOf(ev, 'final')));
814
842
  }
815
843
  function flushHeld(d, wireTaskId) {
816
844
  const held = d.pending.get(wireTaskId);
@@ -1278,6 +1306,10 @@ export function panelResolveTaskId(state, wireTaskId) {
1278
1306
  return { taskId: wireTaskId, origin: 'wire' };
1279
1307
  return { taskId: r.tail, origin: 'fleet-row', ...cycleOf(bindingOf(r, wireTaskId)?.gen) };
1280
1308
  }
1309
+ export function panelSubagentOf(state, id) {
1310
+ const r = recordOfId(state, id);
1311
+ return r === undefined ? undefined : { key: keyOf(r), ids: idsOf(r) };
1312
+ }
1281
1313
  export function panelIsResident(state, taskId) {
1282
1314
  return recordOfId(state, taskId)?.resident === true;
1283
1315
  }
@@ -1,5 +1,6 @@
1
1
  import { type PanelDelta, type PanelFact, type PanelFrame, type PanelReduceState } from './panelReduce.js';
2
2
  export declare function panelStateNow(): PanelReduceState;
3
+ export declare function panelSubagentIdsNow(id: string): readonly string[] | undefined;
3
4
  export declare function stepEnginePanel(frame: PanelFrame): void;
4
5
  export declare function replaceEnginePanelState(fn: (s: PanelReduceState) => PanelReduceState): void;
5
6
  export declare function clearEnginePanelIdentity(): void;
@@ -1,9 +1,17 @@
1
- import { createPanelReduceState, panelClearAnchors, panelClearIdentity, panelClearRows, panelRowSnapshot, stepPanelFrame, } from './panelReduce.js';
1
+ import { createPanelReduceState, panelClearAnchors, panelClearIdentity, panelClearRows, panelRowSnapshot, panelSubagentOf, stepPanelFrame, } from './panelReduce.js';
2
+ import { bindSubagentIdentityReader } from './subagentContentStore.js';
2
3
  let state = createPanelReduceState();
3
4
  export function panelStateNow() {
4
5
  return state;
5
6
  }
7
+ export function panelSubagentIdsNow(id) {
8
+ return panelSubagentOf(state, id)?.ids;
9
+ }
10
+ function bindIdentityReader() {
11
+ bindSubagentIdentityReader(panelSubagentIdsNow);
12
+ }
6
13
  export function stepEnginePanel(frame) {
14
+ bindIdentityReader();
7
15
  const r = stepPanelFrame(state, frame);
8
16
  state = r.state;
9
17
  if (rowListener !== null)
@@ -18,6 +26,7 @@ export function stepEnginePanel(frame) {
18
26
  }
19
27
  }
20
28
  export function replaceEnginePanelState(fn) {
29
+ bindIdentityReader();
21
30
  state = fn(state);
22
31
  }
23
32
  export function clearEnginePanelIdentity() {
@@ -1,3 +1,4 @@
1
+ import type { UiLanguage } from './env/uiLanguage.js';
1
2
  export declare const PERMISSION_RULE_ISSUE_CODES: readonly string[];
2
3
  export declare const RETIRED_PERMISSION_RULE_ISSUE_CODES: readonly string[];
3
- export declare function permissionRuleIssueDetail(code: unknown, message: unknown, rule?: string): string;
4
+ export declare function permissionRuleIssueDetail(code: unknown, message: unknown, rule?: string, lang?: UiLanguage): string;
@@ -1,4 +1,5 @@
1
1
  import { capForDisplay, escapeDisplayControlChars } from './fleetTaskDesc.js';
2
+ import { msg, renderMessage } from './i18n/translate.js';
2
3
  export const PERMISSION_RULE_ISSUE_CODES = Object.freeze([
3
4
  'invalid.empty_tool',
4
5
  'invalid.paren',
@@ -20,25 +21,25 @@ export const PERMISSION_RULE_ISSUE_CODES = Object.freeze([
20
21
  export const RETIRED_PERMISSION_RULE_ISSUE_CODES = Object.freeze(['unsupported.unknown_param']);
21
22
  const ISSUE_MESSAGE_MAX = 200;
22
23
  const ISSUE_SENTENCES = Object.freeze({
23
- 'invalid.empty_tool': 'this rule is invalid: it names no tool',
24
- 'invalid.paren': 'this rule is invalid: its parentheses do not parse (escape a literal one as \\( or \\))',
25
- 'invalid.tool_name': "this rule is invalid: its tool name is not spelled as a tool name (blanks around the rule, an invisible or disallowed character in the name or before the parenthesis, a leading '-', or the wildcard '*', which names no tool), so it would reach no tool or the wrong one",
26
- 'invalid.param_split': 'this rule is invalid: its parentheses do not hold a parameter rule written name:pattern',
27
- 'invalid.primary_field': "this rule is invalid: it patterns the tool's primary field, which matches the whole trimmed string rather than a prefix",
28
- 'invalid.cap_exceeded': 'this rule set is invalid: it is over one of the deployment caps (rule count, rule length, pattern length, or star count); this client cannot tell which from the code alone',
29
- 'invalid.behavior': 'this rule is invalid: its behavior is neither deny nor ask, so it would never fire',
30
- 'invalid.command_rule': 'this rule is invalid: the command pattern was rejected by the command-rule validator',
31
- 'invalid.entry_type': 'this allow list is invalid: it must be a list of rule strings, and it or one of its entries is not a string',
32
- 'unsupported.allow': 'an allow rule is not supported in a rule set that only says deny or ask — a standing approval belongs on the allow list instead',
33
- 'unsupported.param_unknown': 'this parameter rule is not supported: the tool carries no such parameter, so it could never match',
34
- 'unsupported.param_non_scalar': 'this parameter rule is not supported: that parameter holds an object or an array, so it could never match',
35
- 'unsupported.tool_unknown': "this rule is not supported on this leg: the resolver it supplied does not know the tool, so the rule's face cannot be checked",
36
- 'unsupported.path_base': 'this path rule is not supported as spelled: the base it is relative to is missing or is not a usable absolute path, so it would reach nothing and is refused rather than compiled',
37
- 'unsupported.mcp_paren': 'a parenthesised parameter rule is not supported on an MCP tool name',
38
- 'unsupported.covering_paren': 'a parenthesised parameter rule is not supported on a covering protocol name — the parameter grammar is keyed by an exact tool name, so no mounted tool could ever bear it',
24
+ 'invalid.empty_tool': 'rules.issue.emptyTool',
25
+ 'invalid.paren': 'rules.issue.paren',
26
+ 'invalid.tool_name': 'rules.issue.toolName',
27
+ 'invalid.param_split': 'rules.issue.paramSplit',
28
+ 'invalid.primary_field': 'rules.issue.primaryField',
29
+ 'invalid.cap_exceeded': 'rules.issue.capExceeded',
30
+ 'invalid.behavior': 'rules.issue.behavior',
31
+ 'invalid.command_rule': 'rules.issue.commandRule',
32
+ 'invalid.entry_type': 'rules.issue.entryType',
33
+ 'unsupported.allow': 'rules.issue.allowRule',
34
+ 'unsupported.param_unknown': 'rules.issue.paramUnknown',
35
+ 'unsupported.param_non_scalar': 'rules.issue.paramNonScalar',
36
+ 'unsupported.tool_unknown': 'rules.issue.toolUnknown',
37
+ 'unsupported.path_base': 'rules.issue.pathBase',
38
+ 'unsupported.mcp_paren': 'rules.issue.mcpParen',
39
+ 'unsupported.covering_paren': 'rules.issue.coveringParen',
39
40
  });
40
- const PARAM_SPLIT_WITH_COLON = 'this rule is invalid: a parameter rule is written name:pattern, and the name before the colon or the pattern after it is empty';
41
- const PARAM_SPLIT_NO_COLON = 'this rule is invalid: there is no colon inside the parentheses, so this is not a parameter rule (a parameter rule is written name:pattern)';
41
+ const PARAM_SPLIT_WITH_COLON = 'rules.issue.paramSplitWithColon';
42
+ const PARAM_SPLIT_NO_COLON = 'rules.issue.paramSplitNoColon';
42
43
  function colonInsideParens(rule) {
43
44
  if (typeof rule !== 'string')
44
45
  return undefined;
@@ -53,7 +54,7 @@ function colonInsideParens(rule) {
53
54
  }
54
55
  return undefined;
55
56
  }
56
- export function permissionRuleIssueDetail(code, message, rule) {
57
+ export function permissionRuleIssueDetail(code, message, rule, lang) {
57
58
  const colon = code === 'invalid.param_split' ? colonInsideParens(rule) : undefined;
58
59
  const known = colon !== undefined
59
60
  ? colon ? PARAM_SPLIT_WITH_COLON : PARAM_SPLIT_NO_COLON
@@ -63,7 +64,7 @@ export function permissionRuleIssueDetail(code, message, rule) {
63
64
  : '';
64
65
  const codeWord = typeof code === 'string' && code.length > 0 ? escapeDisplayControlChars(code) : '(no code)';
65
66
  const head = known !== undefined
66
- ? known
67
- : `this rule was refused with ${codeWord}, a code newer than this client`;
67
+ ? renderMessage(msg(known), lang)
68
+ : renderMessage(msg('rules.issue.newerCode', { code: codeWord }), lang);
68
69
  return text.length > 0 ? `${head} — ${text}` : head;
69
70
  }
@@ -51,8 +51,8 @@ export function hooksWirePlanShapeOf(v) {
51
51
  return Array.isArray(o.verdicts) &&
52
52
  Array.isArray(o.excluded) &&
53
53
  Array.isArray(o.settingsDropped) &&
54
- arrayOrAbsent('settingsVerdicts') &&
55
- arrayOrAbsent('settingsExcluded') &&
54
+ Array.isArray(o.settingsVerdicts) &&
55
+ Array.isArray(o.settingsExcluded) &&
56
56
  arrayOrAbsent('settingsSalvage') &&
57
57
  arrayOrAbsent('moduleVerdicts') &&
58
58
  arrayOrAbsent('sessionVerdicts') &&
@@ -70,7 +70,7 @@ export function hooksWirePlanShapeOf(v) {
70
70
  }
71
71
  }
72
72
  const PLAN_KEYS = ['engine', 'pluginReader', 'verdicts', 'excluded', 'settingsDropped', 'settingsVerdicts', 'settingsExcluded', 'settingsSalvage', 'moduleVerdicts', 'sessionVerdicts', 'sessionReader', 'closedBy', 'wire'];
73
- const LATER_PLAN_KEYS = new Set(['settingsVerdicts', 'settingsExcluded', 'settingsSalvage', 'moduleVerdicts', 'sessionVerdicts', 'sessionReader', 'closedBy']);
73
+ const LATER_PLAN_KEYS = new Set(['settingsSalvage', 'moduleVerdicts', 'sessionVerdicts', 'sessionReader', 'closedBy']);
74
74
  const _planKeysPin = [true, true];
75
75
  void _planKeysPin;
76
76
  export const ENGINE_HOOK_LIMITS = { maxGroupsPerEvent: 16, maxEntriesPerEvent: 32, maxCommandChars: 8192, maxLlmEntriesPerEvent: 4 };
@@ -694,7 +694,7 @@ export function settingsHooksKeptLocally(plan, event, group, opts) {
694
694
  const planRec = plan;
695
695
  if (!isRecord(planRec))
696
696
  return hooks;
697
- const excludedList = Object.hasOwn(planRec, 'settingsExcluded') ? planRec.settingsExcluded : [];
697
+ const excludedList = Object.hasOwn(planRec, 'settingsExcluded') ? planRec.settingsExcluded : undefined;
698
698
  const wire = ownField(planRec, 'wire');
699
699
  if (!Array.isArray(excludedList) || (wire !== undefined && !isRecord(wire)))
700
700
  return hooks;
@@ -973,13 +973,15 @@ export function userPromptSubmitExecutorOf(plan) {
973
973
  if (!Array.isArray(verdicts))
974
974
  return 'unknown';
975
975
  const rows = [...verdicts];
976
- for (const k of ['settingsVerdicts', 'sessionVerdicts']) {
977
- const v = ownField(p, k);
978
- if (v === undefined)
979
- continue;
980
- if (!Array.isArray(v))
976
+ const settingsRows = ownField(p, 'settingsVerdicts');
977
+ if (!Array.isArray(settingsRows))
978
+ return 'unknown';
979
+ rows.push(...settingsRows);
980
+ const sessionRows = ownField(p, 'sessionVerdicts');
981
+ if (sessionRows !== undefined) {
982
+ if (!Array.isArray(sessionRows))
981
983
  return 'unknown';
982
- rows.push(...v);
984
+ rows.push(...sessionRows);
983
985
  }
984
986
  const ups = rows.filter((r) => isRecord(r) && ownField(r, 'event') === 'UserPromptSubmit').map((r) => ownField(r, 'disposition'));
985
987
  if (ups.length === 0)
@@ -0,0 +1,8 @@
1
+ import { CONFIG_AGENT_UNKNOWN_TOOL, CONFIG_IMAGE_INVALID, CONFIG_LEGACY_TOOL_NAME, CONFIG_TOOL_FACE_CONTROL, PROMPT_ASSEMBLED_ROLE_REFUSED, USER_ATTACHMENT_INVALID_ERROR_CODE, USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE } from './engineErrorCodes.js';
2
+ export type PrepareRefusalCode = typeof CONFIG_LEGACY_TOOL_NAME | typeof CONFIG_IMAGE_INVALID | typeof CONFIG_AGENT_UNKNOWN_TOOL | typeof PROMPT_ASSEMBLED_ROLE_REFUSED | typeof USER_ATTACHMENT_INVALID_ERROR_CODE | typeof USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE | typeof CONFIG_TOOL_FACE_CONTROL;
3
+ export interface PrepareRefusalNoteFacts {
4
+ readonly index?: number;
5
+ }
6
+ export declare function prepareRefusalNoteOf(code: string | undefined, facts?: PrepareRefusalNoteFacts): string | undefined;
7
+ export declare function prepareRefusalCodeOf(failure: {} | null | undefined): PrepareRefusalCode | undefined;
8
+ export declare function imageInvalidFailureNoteOf(code: string | undefined): string | undefined;
@@ -0,0 +1,72 @@
1
+ import { CONFIG_AGENT_UNKNOWN_TOOL, CONFIG_IMAGE_INVALID, CONFIG_LEGACY_TOOL_NAME, CONFIG_TOOL_FACE_CONTROL, PROMPT_ASSEMBLED_ROLE_REFUSED, USER_ATTACHMENT_INVALID_ERROR_CODE, USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE, } from './engineErrorCodes.js';
2
+ import { REFUSED_NAME_CLASSES } from './hitl/refusedToolNameProse.js';
3
+ import { readOwnDataValue } from './ownKey.js';
4
+ import { effectiveWireErrorCode } from './wireErrorTriage.js';
5
+ const nonNegInt = (v) => (typeof v === 'number' && Number.isSafeInteger(v) && v >= 0 ? v : undefined);
6
+ const PREPARE_REFUSAL_NOTES = Object.freeze({
7
+ [CONFIG_LEGACY_TOOL_NAME]: () => `The engine refused this run at setup: a tool rule applied to it names a tool the engine refuses — ${REFUSED_NAME_CLASSES} (the engine's own error text names the entry). ` +
8
+ 'Every later run fails the same way until that entry is removed from wherever it is set: this session’s rule record, the settings sent with the run, a parent session’s rule record, or the deployment’s own tool rules.',
9
+ [CONFIG_IMAGE_INVALID]: () => 'The engine refused this run at setup: an image sent with the message was not accepted — the engine’s own error text says which image and what is wrong with it. ' +
10
+ 'Remove or replace that image, then send the message again.',
11
+ [CONFIG_AGENT_UNKNOWN_TOOL]: () => 'The engine refused this run at setup: a subagent tool list (in a subagent definition sent with it, or on a delegation tool) is not a list of tool names, or has an entry that names no tool or uses a form that list does not accept — ' +
12
+ 'the engine’s own error text says which list, and which entry when it is one entry · Sending the same request again is refused the same way; fix what it names, then send it',
13
+ [PROMPT_ASSEMBLED_ROLE_REFUSED]: () => 'The engine refused this run at setup: the role text sent with it contains the engine’s own prompt sections word for word — the engine’s own error text names the field · ' +
14
+ 'Send only your own role text (the engine assembles the rest), then send it again',
15
+ [USER_ATTACHMENT_INVALID_ERROR_CODE]: (facts) => {
16
+ const index = nonNegInt(facts.index);
17
+ return index !== undefined
18
+ ? `The engine refused attachment ${index + 1} of this message: it is in a form the engine does not accept, or larger than it takes · Your draft is kept · Remove or replace that attachment, then send it again`
19
+ : 'The engine refused the files attached to this message: together with the message they are more than it can take in one request on this model, or one of them is in a form it does not accept · ' +
20
+ 'Your draft is kept · Remove some attachments or attach smaller parts, then send it again';
21
+ },
22
+ [USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE]: () => 'The engine refused this run at setup: a skill named for it is not one this run has loaded, or skills are turned off for this run · ' +
23
+ 'Your draft is kept · Check the skill name, or load that skill, then send it again',
24
+ [CONFIG_TOOL_FACE_CONTROL]: () => 'The engine refused this run at setup: its tool set could not be put together as asked — usually a tool list on the request or one it inherits (allowed or excluded tools) names something no tool answers to, ' +
25
+ 'uses a form those lists do not accept, or excludes a tool this run depends on; it can also be the deployment’s own tool mounts — the engine’s own error text says what it refused and where · ' +
26
+ 'Sending the same request again is refused the same way; fix what it names (or ask whoever operates the engine, if it names the deployment’s tools), then send it',
27
+ });
28
+ function isPrepareRefusalCode(code) {
29
+ return typeof code === 'string' && Object.hasOwn(PREPARE_REFUSAL_NOTES, code);
30
+ }
31
+ export function prepareRefusalNoteOf(code, facts) {
32
+ try {
33
+ if (!isPrepareRefusalCode(code))
34
+ return undefined;
35
+ let index;
36
+ try {
37
+ index = facts === undefined || facts === null ? undefined : facts.index;
38
+ }
39
+ catch {
40
+ index = undefined;
41
+ }
42
+ const i = nonNegInt(index);
43
+ return PREPARE_REFUSAL_NOTES[code](i !== undefined ? { index: i } : {});
44
+ }
45
+ catch {
46
+ return undefined;
47
+ }
48
+ }
49
+ export function prepareRefusalCodeOf(failure) {
50
+ try {
51
+ if (typeof failure !== 'object' || failure === null)
52
+ return undefined;
53
+ const kind = readOwnDataValue(failure, 'kind');
54
+ const plane = readOwnDataValue(failure, 'plane');
55
+ if (kind === 'failed' && (plane === 'cause' || plane === 'flat')) {
56
+ const code = readOwnDataValue(failure, 'code');
57
+ return isPrepareRefusalCode(code) ? code : undefined;
58
+ }
59
+ if (readOwnDataValue(failure, 'type') === 'result') {
60
+ const code = readOwnDataValue(failure, '_sema_error_code');
61
+ return isPrepareRefusalCode(code) ? code : undefined;
62
+ }
63
+ const code = effectiveWireErrorCode(failure);
64
+ return isPrepareRefusalCode(code) ? code : undefined;
65
+ }
66
+ catch {
67
+ return undefined;
68
+ }
69
+ }
70
+ export function imageInvalidFailureNoteOf(code) {
71
+ return code === CONFIG_IMAGE_INVALID ? prepareRefusalNoteOf(code) : undefined;
72
+ }
@@ -1,7 +1,7 @@
1
1
  import type { TaskRequest, UserAttachment } from '@sema-agent/sdk';
2
2
  import { type OutputStyleSeatReading } from '../outputStyleSeatCapability.js';
3
3
  import { type ApprovalReachWord } from '../approvalReachWire.js';
4
- import { type HostTurnSettings, type HostTurnSettingsInput } from '../hostTurnSettings.js';
4
+ import { type HostSettingNotice, type HostTurnSettings, type HostTurnSettingsInput } from '../hostTurnSettings.js';
5
5
  export type RequestLane = 'interactive' | 'print' | 'utility';
6
6
  export type TaskRequestLike = Record<string, unknown>;
7
7
  export interface RequestFieldSpec {
@@ -54,8 +54,6 @@ export interface TaskRequestInput {
54
54
  fallbackModel?: string;
55
55
  maxThinkingTokens?: number;
56
56
  memoryCapture?: 'off';
57
- memory?: 'off';
58
- fileHistory?: TaskRequest['fileHistory'];
59
57
  inheritEnv?: InheritEnvWord;
60
58
  requireExistingSession?: TaskRequest['requireExistingSession'];
61
59
  disableSkills?: TaskRequest['disableSkills'];
@@ -63,11 +61,7 @@ export interface TaskRequestInput {
63
61
  repo?: string;
64
62
  hostSettings: HostTurnSettings;
65
63
  settings?: {
66
- resolved?: never;
67
- webSearch?: never;
68
64
  ultracode?: boolean;
69
- hooks?: never;
70
- outputStyle?: never;
71
65
  };
72
66
  }
73
67
  export declare const TASK_REQUEST_OMISSION_CAUSES: readonly ["upstream_absent", "other_channel", "off_lane", "not_live"];
@@ -101,14 +95,20 @@ export declare const UPSTREAM_ABSENT_REQUEST_INTENTS: readonly UpstreamAbsentReq
101
95
  export declare const REQUEST_LANES: readonly RequestLane[];
102
96
  export declare function taskRequestSeatOf(key: string, lane: RequestLane): TaskRequestSeatReading;
103
97
  export declare function hostTurnSettings(input: HostTurnSettingsInput): HostTurnSettings;
98
+ export type HostSettingsRefilterResult = {
99
+ readonly kind: 'send';
100
+ readonly request: TaskRequestLike;
101
+ readonly hooksDropped: number;
102
+ } | {
103
+ readonly kind: 'refuse';
104
+ readonly notice: HostSettingNotice;
105
+ };
106
+ export declare function refilterHostSettings(request: TaskRequestLike, fresh: HostTurnSettings, lane: RequestLane): HostSettingsRefilterResult;
104
107
  export declare const MEMORY_CAPTURE_OFF: "off";
105
108
  export declare function memoryCaptureDeclarationField(declared: boolean): {
106
109
  memoryCapture: 'off';
107
110
  } | Record<string, never>;
108
111
  export declare const MEMORY_OFF: "off";
109
- export declare function memoryOffDeclarationField(declared: boolean): {
110
- memory: 'off';
111
- } | Record<string, never>;
112
112
  export declare const FILE_HISTORY_DISABLED: "disabled";
113
113
  export declare const INHERIT_ENV_WORDS: readonly ["all", "scrub"];
114
114
  export type InheritEnvWord = (typeof INHERIT_ENV_WORDS)[number];