@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
@@ -1,6 +1,9 @@
1
1
  import { SETTINGS_CLASSIFY_HOOKS_CONFIG } from './generated/settingsSchemaFns.js';
2
2
  import { hooksWirePlanShapeOf } from './pluginHooksWire.js';
3
- export const HOST_SUPPLIED_KEYS = Object.freeze(['settings.hooks', 'settings.resolved', 'settings.webSearch', 'settings.outputStyle']);
3
+ import { resolveWebSearchVerdict, webSearchVerdictMessage } from './webSearchWireCaps.js';
4
+ import { fileHistoryTightenVerdict, fileHistoryUnjudgedRefusal } from './fileHistoryCaptureCapability.js';
5
+ import { msg, renderMessage } from './i18n/translate.js';
6
+ export const HOST_SUPPLIED_KEYS = Object.freeze(['settings.hooks', 'settings.resolved', 'settings.webSearch', 'settings.outputStyle', 'memory', 'fileHistory']);
4
7
  export const HOST_SETTING_CAUSES = Object.freeze([
5
8
  'carried',
6
9
  'entries_dropped',
@@ -10,6 +13,7 @@ export const HOST_SETTING_CAUSES = Object.freeze([
10
13
  'empty',
11
14
  'no_source',
12
15
  'host_port_missing',
16
+ 'value_malformed',
13
17
  ]);
14
18
  export const HOST_SETTING_DISPOSITIONS = Object.freeze(['carry', 'carry_partial', 'withhold_notice', 'refuse_turn', 'unwired', 'nothing_to_carry']);
15
19
  const HOST_SETTING_NOTICE_TEXT = {
@@ -17,12 +21,17 @@ const HOST_SETTING_NOTICE_TEXT = {
17
21
  'HS-MANAGED-REJECTED': () => 'Managed settings: the hooks your administrator configured could not be loaded, so requests are not sent until the managed settings are fixed.',
18
22
  'HS-PROJECTION': () => 'The hooks for this request could not be checked before sending, so the request is not sent. Reload your settings and try again.',
19
23
  'HS-SOURCE-UNREADABLE': (what) => `This app could not read ${what} from your settings, so the request is not sent. Reload your settings and try again.`,
24
+ 'HS-WEBSEARCH-MALFORMED': (sentence) => sentence,
25
+ 'HS-SWITCH-MALFORMED': () => renderMessage(msg('session.hostSettings.memorySwitchMalformed')),
26
+ 'HS-FILEHISTORY-UNJUDGED': (sentence) => sentence,
20
27
  };
21
28
  const KEY_NOUN = {
22
29
  'settings.hooks': 'the hooks',
23
30
  'settings.resolved': 'the permission rules',
24
31
  'settings.webSearch': 'the web search setup',
25
32
  'settings.outputStyle': 'the output style',
33
+ memory: 'auto-memory',
34
+ fileHistory: 'file checkpoints',
26
35
  };
27
36
  const BASE_DISPOSITION = {
28
37
  carried: 'carry',
@@ -33,6 +42,7 @@ const BASE_DISPOSITION = {
33
42
  empty: 'nothing_to_carry',
34
43
  no_source: 'nothing_to_carry',
35
44
  host_port_missing: 'unwired',
45
+ value_malformed: 'refuse_turn',
36
46
  };
37
47
  const freeze = (o) => Object.freeze(o);
38
48
  const mint = (o) => o;
@@ -69,8 +79,11 @@ function hooksPassJudge(wire) {
69
79
  return false;
70
80
  }
71
81
  }
82
+ class HostSourceShapeError extends TypeError {
83
+ code = 'host_source_shape';
84
+ }
72
85
  function badSource(key, want) {
73
- return new TypeError(`hostTurnSettings: sources.${key.replace(/^settings\./, '')} must be 'none' or ${want} — got something else (the value is not echoed).`);
86
+ return new HostSourceShapeError(`hostTurnSettings: sources.${key.replace(/^settings\./, '')} must be 'none' or ${want} — got something else (the value is not echoed).`);
74
87
  }
75
88
  const missingArm = (key) => ({
76
89
  row: freeze({ key, cause: 'host_port_missing', disposition: BASE_DISPOSITION.host_port_missing }),
@@ -132,6 +145,131 @@ function hooksArm(src) {
132
145
  return { row: freeze({ key, cause: 'empty', disposition: BASE_DISPOSITION.empty }), notices: [], plan };
133
146
  return { ...carriedArm(key, carried), plan };
134
147
  }
148
+ function webSearchArm(src) {
149
+ const key = 'settings.webSearch';
150
+ if (src.kind === 'missing')
151
+ return missingArm(key);
152
+ if (src.kind === 'threw')
153
+ return unreadableArm(key);
154
+ const v = src.value;
155
+ if (v === 'none')
156
+ return noSourceArm(key);
157
+ let section;
158
+ let env;
159
+ let apiKeyFor;
160
+ try {
161
+ if (!isRecordShape(v) || !Object.hasOwn(v, 'env') || Object.hasOwn(v, 'settings'))
162
+ throw badSource(key, "{ section, env } with the raw webSearch section of the settings and the environment (since 0.100.0 the entry judges it; do not pass the judged settings)");
163
+ section = v.section;
164
+ env = v.env;
165
+ apiKeyFor = v.apiKeyFor;
166
+ }
167
+ catch (e) {
168
+ if (e instanceof HostSourceShapeError)
169
+ throw e;
170
+ return unreadableArm(key);
171
+ }
172
+ if (!isRecordShape(env))
173
+ throw badSource(key, '{ section, env } where env is the environment record (pass {} where there is none)');
174
+ if (apiKeyFor !== undefined && typeof apiKeyFor !== 'function')
175
+ throw badSource(key, '{ section, env, apiKeyFor? } where apiKeyFor is a function');
176
+ const verdict = resolveWebSearchVerdict(env, section, apiKeyFor);
177
+ if (verdict.kind === 'absent')
178
+ return { row: freeze({ key, cause: 'empty', disposition: BASE_DISPOSITION.empty }), notices: [] };
179
+ if (verdict.kind === 'honored')
180
+ return carriedArm(key, freeze({ ...verdict.settings }));
181
+ return {
182
+ row: freeze({ key, cause: 'value_malformed', disposition: BASE_DISPOSITION.value_malformed }),
183
+ notices: [notice('HS-WEBSEARCH-MALFORMED', 'turn', webSearchVerdictMessage(verdict, 'submit') ?? '')],
184
+ };
185
+ }
186
+ function memoryArm(src, judge) {
187
+ const key = 'memory';
188
+ if (src.kind === 'missing')
189
+ return missingArm(key);
190
+ if (src.kind === 'threw')
191
+ return unreadableArm(key);
192
+ const v = src.value;
193
+ if (v === 'none')
194
+ return noSourceArm(key);
195
+ let flag;
196
+ let settingsMemory;
197
+ try {
198
+ if (!isRecordShape(v))
199
+ throw badSource(key, '{ flag?, settingsMemory? } with the --memory flag word and the memory section of the settings');
200
+ flag = v.flag;
201
+ settingsMemory = v.settingsMemory;
202
+ }
203
+ catch (e) {
204
+ if (e instanceof HostSourceShapeError)
205
+ throw e;
206
+ return unreadableArm(key);
207
+ }
208
+ if (judge({ flag }))
209
+ return carriedArm(key, 'off');
210
+ let bySettings;
211
+ try {
212
+ bySettings = judge({ settingsMemory });
213
+ }
214
+ catch {
215
+ return { row: freeze({ key, cause: 'value_malformed', disposition: 'withhold_notice' }), notices: [notice('HS-SWITCH-MALFORMED', 'session')] };
216
+ }
217
+ if (bySettings)
218
+ return carriedArm(key, 'off');
219
+ return { row: freeze({ key, cause: 'empty', disposition: BASE_DISPOSITION.empty }), notices: [] };
220
+ }
221
+ const UNOBSERVED_READING = Object.freeze({ kind: 'unobserved' });
222
+ function fileHistoryReadingSnapshot(reading) {
223
+ try {
224
+ if (typeof reading !== 'object' || reading === null)
225
+ return UNOBSERVED_READING;
226
+ const kind = reading.kind;
227
+ if (kind === 'present') {
228
+ const word = reading.word;
229
+ return Object.freeze({ kind, word });
230
+ }
231
+ return Object.freeze({ kind });
232
+ }
233
+ catch {
234
+ return UNOBSERVED_READING;
235
+ }
236
+ }
237
+ function fileHistoryArm(src) {
238
+ const key = 'fileHistory';
239
+ if (src.kind === 'missing')
240
+ return missingArm(key);
241
+ if (src.kind === 'threw')
242
+ return unreadableArm(key);
243
+ const v = src.value;
244
+ if (v === 'none')
245
+ return noSourceArm(key);
246
+ let reading;
247
+ let captureOff;
248
+ try {
249
+ if (!isRecordShape(v) || !Object.hasOwn(v, 'captureOff'))
250
+ throw badSource(key, '{ reading, captureOff } with the engine capability reading and the switch');
251
+ reading = v.reading;
252
+ captureOff = v.captureOff;
253
+ }
254
+ catch (e) {
255
+ if (e instanceof HostSourceShapeError)
256
+ throw e;
257
+ return unreadableArm(key);
258
+ }
259
+ if (typeof captureOff !== 'boolean')
260
+ throw badSource(key, '{ reading, captureOff } where captureOff is a boolean');
261
+ const snap = fileHistoryReadingSnapshot(reading);
262
+ const verdict = fileHistoryTightenVerdict(snap, captureOff);
263
+ if (verdict === 'declare')
264
+ return carriedArm(key, 'disabled');
265
+ if (verdict === 'unjudged') {
266
+ return {
267
+ row: freeze({ key, cause: 'value_malformed', disposition: 'refuse_turn' }),
268
+ notices: [notice('HS-FILEHISTORY-UNJUDGED', 'turn', fileHistoryUnjudgedRefusal(snap, true) ?? fileHistoryUnjudgedRefusal(UNOBSERVED_READING, true) ?? '')],
269
+ };
270
+ }
271
+ return { row: freeze({ key, cause: 'empty', disposition: BASE_DISPOSITION.empty }), notices: [] };
272
+ }
135
273
  function passArm(key, field, src, want) {
136
274
  if (src.kind === 'missing')
137
275
  return missingArm(key);
@@ -155,7 +293,8 @@ export function rethrowHostResolvedDeferred(product) {
155
293
  if (box !== undefined)
156
294
  throw box.error;
157
295
  }
158
- export function buildHostTurnSettings(input, materialize) {
296
+ export function buildHostTurnSettings(input, judges) {
297
+ const materialize = judges.materialize;
159
298
  let sources;
160
299
  let sourcesThrew = false;
161
300
  try {
@@ -177,9 +316,11 @@ export function buildHostTurnSettings(input, materialize) {
177
316
  }
178
317
  }
179
318
  const hooks = hooksArm(read('hooks'));
180
- const webSearch = passArm('settings.webSearch', 'settings', read('webSearch'), '{ settings } with the web search settings');
319
+ const webSearch = webSearchArm(read('webSearch'));
181
320
  const outputStyle = passArm('settings.outputStyle', 'name', read('outputStyle'), '{ name } with the output style name');
182
- const arms = [hooks, resolved, webSearch, outputStyle];
321
+ const memory = memoryArm(read('memory'), judges.memoryOffDeclared);
322
+ const fileHistory = fileHistoryArm(read('fileHistory'));
323
+ const arms = [hooks, resolved, webSearch, outputStyle, memory, fileHistory];
183
324
  const rows = freeze(arms.map((a) => a.row));
184
325
  const notices = freeze(arms.flatMap((a) => a.notices));
185
326
  const refusal = arms.find((a) => a.row.disposition === 'refuse_turn');
@@ -189,6 +330,8 @@ export function buildHostTurnSettings(input, materialize) {
189
330
  ...(resolvedCarried !== undefined ? { resolved: resolvedCarried } : {}),
190
331
  ...(webSearch.carried !== undefined ? { webSearch: webSearch.carried } : {}),
191
332
  ...(outputStyle.carried !== undefined ? { outputStyle: outputStyle.carried } : {}),
333
+ ...(memory.carried !== undefined ? { memory: 'off' } : {}),
334
+ ...(fileHistory.carried !== undefined ? { fileHistory: 'disabled' } : {}),
192
335
  });
193
336
  const product = { verdict, rows, notices, hooks: hooks.plan, carried };
194
337
  if (resolvedError !== undefined)
@@ -218,6 +361,7 @@ export function hostSettingsSelfCheck(product) {
218
361
  return HOST_SUPPLIED_KEYS;
219
362
  }
220
363
  }
364
+ export const hostProjectionNotice = () => notice('HS-PROJECTION', 'turn');
221
365
  export class HostSettingsRefused extends Error {
222
366
  notice;
223
367
  constructor(n) {
@@ -260,9 +404,13 @@ export function hostTurnSettingsOf(v, depth = 'full') {
260
404
  const p = view;
261
405
  const rows = p.rows;
262
406
  const carried = p.carried;
263
- const subs = HOST_SUPPLIED_KEYS.map((k) => k.slice('settings.'.length));
407
+ const subs = HOST_SUPPLIED_KEYS.map(carriedKeyOf);
264
408
  if (Object.keys(carried).some((k) => !subs.includes(k)))
265
409
  return undefined;
410
+ if (carried.memory !== undefined && carried.memory !== 'off')
411
+ return undefined;
412
+ if (carried.fileHistory !== undefined && carried.fileHistory !== 'disabled')
413
+ return undefined;
266
414
  let refuses = false;
267
415
  for (const [i, r] of rows.entries()) {
268
416
  const disposition = r.disposition;
@@ -288,4 +436,257 @@ export function hostTurnSettingsOf(v, depth = 'full') {
288
436
  return undefined;
289
437
  }
290
438
  }
291
- export const UNWIRED_HOST_TURN_SETTINGS = buildHostTurnSettings({ sources: {} }, (snapshot) => snapshot);
439
+ function wireFormOf(v) {
440
+ const text = JSON.stringify(v);
441
+ return text === undefined ? undefined : JSON.parse(text);
442
+ }
443
+ function sameJson(a, b) {
444
+ if (a === b)
445
+ return true;
446
+ if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
447
+ return false;
448
+ if (Array.isArray(a) !== Array.isArray(b))
449
+ return false;
450
+ if (Array.isArray(a) && Array.isArray(b))
451
+ return a.length === b.length && a.every((x, i) => sameJson(x, b[i]));
452
+ const ra = a;
453
+ const rb = b;
454
+ const ka = Object.keys(ra);
455
+ if (ka.length !== Object.keys(rb).length)
456
+ return false;
457
+ return ka.every((k) => Object.hasOwn(rb, k) && sameJson(ra[k], rb[k]));
458
+ }
459
+ function groupHead(g) {
460
+ if (!isRecordShape(g))
461
+ return undefined;
462
+ const head = {};
463
+ for (const k of Object.keys(g))
464
+ if (k !== 'hooks')
465
+ head[k] = g[k];
466
+ return head;
467
+ }
468
+ export function intersectHostHooks(sent, now) {
469
+ try {
470
+ return intersectHostHooksUnguarded(sent, now);
471
+ }
472
+ catch {
473
+ return { hooks: undefined, dropped: 0, judged: false };
474
+ }
475
+ }
476
+ function intersectHostHooksUnguarded(sentIn, nowIn) {
477
+ const sent = wireFormOf(sentIn);
478
+ const now = nowIn === undefined ? undefined : wireFormOf(nowIn);
479
+ const entriesOf = (cfg) => {
480
+ if (!isRecordShape(cfg))
481
+ return 0;
482
+ let n = 0;
483
+ for (const ev of Object.keys(cfg)) {
484
+ const groups = cfg[ev];
485
+ if (!Array.isArray(groups))
486
+ continue;
487
+ for (const g of groups)
488
+ if (isRecordShape(g) && Array.isArray(g.hooks))
489
+ n += g.hooks.length;
490
+ }
491
+ return n;
492
+ };
493
+ const total = entriesOf(sent);
494
+ if (!isRecordShape(sent))
495
+ return { hooks: undefined, dropped: 0, judged: true };
496
+ if (!isRecordShape(now))
497
+ return { hooks: undefined, dropped: total, judged: true };
498
+ const out = {};
499
+ let kept = 0;
500
+ for (const ev of Object.keys(sent)) {
501
+ const groups = sent[ev];
502
+ const nowGroups = now[ev];
503
+ if (!Array.isArray(groups) || !Array.isArray(nowGroups))
504
+ continue;
505
+ const pool = nowGroups.map((g) => ({ head: groupHead(g), left: isRecordShape(g) && Array.isArray(g.hooks) ? [...g.hooks] : [] }));
506
+ const evOut = [];
507
+ for (const g of groups) {
508
+ const head = groupHead(g);
509
+ if (head === undefined || !isRecordShape(g) || !Array.isArray(g.hooks))
510
+ continue;
511
+ const keep = [];
512
+ for (const entry of g.hooks) {
513
+ for (const slot of pool) {
514
+ if (slot.head === undefined || !sameJson(slot.head, head))
515
+ continue;
516
+ const at = slot.left.findIndex((x) => sameJson(x, entry));
517
+ if (at < 0)
518
+ continue;
519
+ slot.left.splice(at, 1);
520
+ keep.push(entry);
521
+ break;
522
+ }
523
+ }
524
+ if (keep.length > 0)
525
+ evOut.push({ ...head, hooks: keep });
526
+ kept += keep.length;
527
+ }
528
+ if (evOut.length > 0)
529
+ out[ev] = evOut;
530
+ }
531
+ const hooks = Object.keys(out).length > 0 ? out : undefined;
532
+ return { hooks, dropped: total - kept, judged: hooks === undefined || hooksPassJudge(hooks) };
533
+ }
534
+ function ownDataOf(o, k) {
535
+ try {
536
+ if (typeof o !== 'object' || o === null)
537
+ return { ok: false };
538
+ const d = Object.getOwnPropertyDescriptor(o, k);
539
+ if (d === undefined)
540
+ return { ok: true, value: undefined };
541
+ if (!('value' in d))
542
+ return { ok: false };
543
+ return { ok: true, value: d.value };
544
+ }
545
+ catch {
546
+ return { ok: false };
547
+ }
548
+ }
549
+ function noticeCopyOf(n) {
550
+ const id = ownDataOf(n, 'id');
551
+ const plane = ownDataOf(n, 'plane');
552
+ const text = ownDataOf(n, 'text');
553
+ if (!id.ok || !plane.ok || !text.ok || typeof id.value !== 'string' || typeof plane.value !== 'string' || typeof text.value !== 'string')
554
+ return undefined;
555
+ return freeze({ id: id.value, plane: plane.value, text: text.value });
556
+ }
557
+ function turnNoticesOf(product) {
558
+ try {
559
+ return turnNoticesUnguarded(product);
560
+ }
561
+ catch {
562
+ return undefined;
563
+ }
564
+ }
565
+ function turnNoticesUnguarded(product) {
566
+ const ns = ownDataOf(product, 'notices');
567
+ if (!ns.ok || !Array.isArray(ns.value))
568
+ return undefined;
569
+ const len = ownDataOf(ns.value, 'length');
570
+ if (!len.ok || typeof len.value !== 'number')
571
+ return undefined;
572
+ const out = [];
573
+ for (let i = 0; i < len.value; i++) {
574
+ const e = ownDataOf(ns.value, String(i));
575
+ const copy = e.ok ? noticeCopyOf(e.value) : undefined;
576
+ if (copy === undefined)
577
+ return undefined;
578
+ if (copy.plane === 'turn')
579
+ out.push(copy);
580
+ }
581
+ return freeze(out);
582
+ }
583
+ function deepFreeze(v) {
584
+ if (typeof v === 'object' && v !== null) {
585
+ for (const x of Object.values(v))
586
+ deepFreeze(x);
587
+ Object.freeze(v);
588
+ }
589
+ return v;
590
+ }
591
+ export function hostIntakeSnapshotOf(product, onResolved) {
592
+ try {
593
+ return intakeSnapshotUnguarded(product, onResolved);
594
+ }
595
+ catch {
596
+ return undefined;
597
+ }
598
+ }
599
+ function intakeSnapshotUnguarded(product, onResolved) {
600
+ if (product === UNWIRED_HOST_TURN_SETTINGS) {
601
+ return freeze({
602
+ carried: freeze({}),
603
+ refuses: false,
604
+ dispositions: freeze(Object.fromEntries(HOST_SUPPLIED_KEYS.map((k) => [k, 'unwired']))),
605
+ refusingKeys: freeze([]),
606
+ turnNotices: freeze([]),
607
+ notice: undefined,
608
+ });
609
+ }
610
+ const c = ownDataOf(product, 'carried');
611
+ if (!c.ok || !isRecordShape(c.value))
612
+ return undefined;
613
+ const carriedIn = c.value;
614
+ const subs = HOST_SUPPLIED_KEYS.map(carriedKeyOf);
615
+ let keys;
616
+ try {
617
+ keys = Reflect.ownKeys(carriedIn);
618
+ }
619
+ catch {
620
+ return undefined;
621
+ }
622
+ if (keys.some((k) => typeof k !== 'string' || !subs.includes(k)))
623
+ return undefined;
624
+ const values = {};
625
+ const resolvedR = ownDataOf(carriedIn, 'resolved');
626
+ if (!resolvedR.ok)
627
+ return undefined;
628
+ onResolved?.(resolvedR.value);
629
+ if (resolvedR.value !== undefined)
630
+ values.resolved = resolvedR.value;
631
+ for (const sub of subs.filter((x) => x !== 'resolved')) {
632
+ const r = ownDataOf(carriedIn, sub);
633
+ if (!r.ok)
634
+ return undefined;
635
+ const copy = deepFreeze(wireFormOf(r.value));
636
+ if (copy !== undefined)
637
+ values[sub] = copy;
638
+ }
639
+ const rowsR = ownDataOf(product, 'rows');
640
+ if (!rowsR.ok || !Array.isArray(rowsR.value) || rowsR.value.length !== HOST_SUPPLIED_KEYS.length)
641
+ return undefined;
642
+ let refuses = false;
643
+ const refusingKeys = [];
644
+ const dispositions = {};
645
+ for (const [i, key] of HOST_SUPPLIED_KEYS.entries()) {
646
+ const rowR = ownDataOf(rowsR.value, String(i));
647
+ if (!rowR.ok)
648
+ return undefined;
649
+ const k = ownDataOf(rowR.value, 'key');
650
+ const d = ownDataOf(rowR.value, 'disposition');
651
+ if (!k.ok || !d.ok || k.value !== key || !HOST_SETTING_DISPOSITIONS.includes(d.value))
652
+ return undefined;
653
+ if (d.value === 'refuse_turn') {
654
+ refuses = true;
655
+ refusingKeys.push(key);
656
+ }
657
+ dispositions[key] = d.value;
658
+ if ((values[carriedKeyOf(key)] !== undefined) !== CARRYING.has(d.value))
659
+ return undefined;
660
+ }
661
+ if (values.memory !== undefined && values.memory !== 'off')
662
+ return undefined;
663
+ if (values.fileHistory !== undefined && values.fileHistory !== 'disabled')
664
+ return undefined;
665
+ if (values.hooks !== undefined && !hooksPassJudge(values.hooks))
666
+ return undefined;
667
+ const v = ownDataOf(product, 'verdict');
668
+ if (!v.ok)
669
+ return undefined;
670
+ const kind = ownDataOf(v.value, 'kind');
671
+ if (!kind.ok || kind.value !== (refuses ? 'refuse' : 'send'))
672
+ return undefined;
673
+ const noticeR = refuses ? ownDataOf(v.value, 'notice') : undefined;
674
+ const notice = noticeR === undefined ? undefined : ((noticeR.ok ? noticeCopyOf(noticeR.value) : undefined) ?? hostProjectionNotice());
675
+ return freeze({
676
+ carried: freeze(values),
677
+ refuses,
678
+ dispositions: freeze(dispositions),
679
+ refusingKeys: freeze(refusingKeys),
680
+ turnNotices: turnNoticesOf(product),
681
+ notice,
682
+ });
683
+ }
684
+ export const UNWIRED_HOST_TURN_SETTINGS = buildHostTurnSettings({ sources: {} }, {
685
+ materialize: (snapshot) => snapshot,
686
+ memoryOffDeclared: () => false,
687
+ });
688
+ function carriedKeyOf(k) {
689
+ return k.startsWith('settings.') ? k.slice('settings.'.length) : k;
690
+ }
691
+ const _armsPin = [true, true, true, true];
692
+ void _armsPin;
@@ -3,6 +3,7 @@ import type { ImageInput } from './imagesWireCaps.js';
3
3
  import type { ImageVision } from './liveModelCatalog.js';
4
4
  import { type UserAttachmentDescriptor } from './userAttachmentEnvelope.js';
5
5
  import type { UserAttachmentSeatReading } from './userAttachmentSeat.js';
6
+ import type { UiLanguage } from './env/uiLanguage.js';
6
7
  export interface HumanTurnRider {
7
8
  readonly uuid: string;
8
9
  readonly role: 'image_meta' | 'attachment' | 'skill_body' | (string & {});
@@ -98,7 +99,7 @@ export interface HumanTurnDelivered {
98
99
  readonly full: readonly string[];
99
100
  readonly partial: readonly string[];
100
101
  }
101
- export declare function imageSentOnUnknownVision(notices: readonly HumanTurnNotice[] | undefined): string | undefined;
102
+ export declare function imageSentOnUnknownVision(notices: readonly HumanTurnNotice[] | undefined, lang?: UiLanguage): string | undefined;
102
103
  export declare function encodeHumanTurn(input: HumanTurnInput): HumanTurnEncoding;
103
104
  export declare function deliveredUuidsOf(encoding: HumanTurnEncoding): HumanTurnDelivered;
104
105
  export {};
package/dist/humanTurn.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { CORE_MAX_PENDING_STEER_CHARS, CORE_MCP_IMAGE_MAX_BASE64, CORE_USER_ATTACHMENT_LABEL_MAX } from './generated/engineFactTables.js';
2
2
  import { mintEnvelopeOf, mintReferenceOf, seatTextOf } from './userAttachmentEnvelope.js';
3
3
  import { readEncodingShares, readHumanTurnInput } from './humanTurnRead.js';
4
+ import { msg, renderMessage } from './i18n/translate.js';
4
5
  const REQUEST_BODY_MAX_BYTES = 8 * 1024 * 1024;
5
6
  const IMAGE_SEAT_MAX_COUNT = 20;
6
7
  const IMAGE_SEAT_MAX_BASE64_CHARS_TOTAL = 6 * 1024 * 1024;
@@ -172,7 +173,7 @@ function noticesKey(v, items, placements) {
172
173
  }
173
174
  return notices.length > 0 ? { notices } : {};
174
175
  }
175
- export function imageSentOnUnknownVision(notices) {
176
+ export function imageSentOnUnknownVision(notices, lang) {
176
177
  let n = 0;
177
178
  try {
178
179
  if (!Array.isArray(notices))
@@ -186,8 +187,7 @@ export function imageSentOnUnknownVision(notices) {
186
187
  }
187
188
  if (n === 0)
188
189
  return undefined;
189
- const what = n === 1 ? 'An @-mentioned image was' : `${n} @-mentioned images were`;
190
- return `${what} sent with this message, although the engine's model list does not say whether the model this message uses accepts image input — if it does not, the images may be dropped or the message may be refused`;
190
+ return renderMessage(n === 1 ? msg('session.humanTurn.imageUnknownVision.one') : msg('session.humanTurn.imageUnknownVision.other', { count: n }), lang);
191
191
  }
192
192
  function encodeObjective(v) {
193
193
  const { items } = v;