@sema-agent/client-core 0.87.0 → 0.89.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 (56) hide show
  1. package/CHANGELOG.md +177 -0
  2. package/README.md +20 -15
  3. package/dist/adapter/activeRunSelfHeal.js +4 -2
  4. package/dist/adapter/downstream/eventToSdkMessage.js +17 -2
  5. package/dist/adapter/downstream/wiringManifestView.d.ts +11 -0
  6. package/dist/adapter/downstream/wiringManifestView.js +28 -0
  7. package/dist/controlRouter.d.ts +7 -1
  8. package/dist/controlRouter.js +43 -1
  9. package/dist/disableSkillsWire.d.ts +17 -0
  10. package/dist/disableSkillsWire.js +52 -0
  11. package/dist/displayUntrusted.d.ts +4 -0
  12. package/dist/displayUntrusted.js +1742 -591
  13. package/dist/engineErrorCodes.d.ts +2 -0
  14. package/dist/engineErrorCodes.js +1 -0
  15. package/dist/engineNoticeCodes.d.ts +44 -1
  16. package/dist/engineNoticeCodes.js +211 -39
  17. package/dist/engineWireFor.d.ts +1 -0
  18. package/dist/engineWireFor.js +1 -1
  19. package/dist/gateOutcome.d.ts +4 -0
  20. package/dist/gateOutcome.js +5 -0
  21. package/dist/generated/engineFactTables.d.ts +1 -0
  22. package/dist/generated/engineFactTables.js +3 -0
  23. package/dist/generated/engineNoticeTables.d.ts +3 -0
  24. package/dist/generated/engineNoticeTables.js +110 -0
  25. package/dist/hitl/crashConverged.d.ts +1 -1
  26. package/dist/hitl/crashConverged.js +6 -1
  27. package/dist/hitl/planReviewWire.js +30 -10
  28. package/dist/hitl/toolApprovalWire.d.ts +6 -2
  29. package/dist/hitl/toolApprovalWire.js +30 -0
  30. package/dist/hooksWireCaps.js +80 -12
  31. package/dist/index.d.ts +12 -3
  32. package/dist/index.js +8 -3
  33. package/dist/pluginHooksWire.d.ts +46 -4
  34. package/dist/pluginHooksWire.js +277 -24
  35. package/dist/promptDelivery.d.ts +20 -0
  36. package/dist/promptDelivery.js +153 -0
  37. package/dist/providerRejection.d.ts +6 -0
  38. package/dist/providerRejection.js +52 -0
  39. package/dist/registryConflict.d.ts +3 -0
  40. package/dist/registryConflict.js +44 -0
  41. package/dist/request/taskRequest.d.ts +3 -0
  42. package/dist/request/taskRequest.js +64 -8
  43. package/dist/resumeRefusalCopy.d.ts +7 -0
  44. package/dist/resumeRefusalCopy.js +45 -1
  45. package/dist/runTerminal.d.ts +6 -0
  46. package/dist/runTerminal.js +23 -0
  47. package/dist/seam.d.ts +4 -0
  48. package/dist/seatContract.d.ts +9 -1
  49. package/dist/seatContract.js +10 -0
  50. package/dist/sessionMemoryErase.d.ts +76 -0
  51. package/dist/sessionMemoryErase.js +432 -0
  52. package/dist/subagent/engineSubagentResume.js +2 -1
  53. package/dist/subagent/engineSubagentSteer.d.ts +8 -1
  54. package/dist/subagent/engineSubagentSteer.js +26 -3
  55. package/docs/INTEGRATION-CLIENTS.md +767 -14
  56. package/package.json +3 -3
@@ -1,5 +1,6 @@
1
1
  import { abortableSleep } from '../abortableSleep.js';
2
2
  import { corruptStoredRowContent, corruptStoredRowWhere, effectiveWireErrorCode } from '../wireErrorTriage.js';
3
+ import { steeringRefusedBeforeEngine, steeringStatusIs4xx } from '../controlRouter.js';
3
4
  export const PLAN_REVIEW_GATE_KIND = 'plan_review';
4
5
  export const PLAN_REVIEW_GATE_KINDS = Object.freeze([PLAN_REVIEW_GATE_KIND, 'dry_run_review']);
5
6
  export const ASK_PARK_GATE_KINDS = Object.freeze(['human', 'irreversible_ask', 'policy_ask', 'tool_approval']);
@@ -260,8 +261,9 @@ function reopenedOfOutcome(outcome) {
260
261
  }
261
262
  }
262
263
  export function atMostOnceFailureClass(e) {
263
- const status = errorSlot(e, 'status');
264
- return typeof status === 'number' && status >= 400 && status < 500 ? 'rejected' : 'unknown';
264
+ if (typeof e === 'object' && e !== null && steeringStatusIs4xx(e))
265
+ return 'rejected';
266
+ return typeof e === 'object' && e !== null && steeringRefusedBeforeEngine(e) !== undefined ? 'rejected' : 'unknown';
265
267
  }
266
268
  export function readSteerDelivery(receipt) {
267
269
  try {
@@ -1,4 +1,4 @@
1
- import { wiringManifestViewOf } from './wiringManifestView.js';
1
+ import { readInstructionsSegment, wiringManifestViewOf } from './wiringManifestView.js';
2
2
  import { stamp, snapshotSegmentIdentity, } from '../types.js';
3
3
  import { turnUsageToModelUsage } from './turnUsageToModelUsage.js';
4
4
  import { ccToolDenialKindForToolEnd, gateOutcomeOf } from '../../gateOutcome.js';
@@ -549,7 +549,9 @@ function wiringManifestSupersetBody(ev) {
549
549
  const autoConsolidation = projectAutoConsolidationSection(ev.autoConsolidation);
550
550
  const readDeny = projectReadDenySection(ev.readDeny);
551
551
  const hands = projectHandsSection(ev);
552
- if (modelGate === undefined && autoMode === undefined && mcp === undefined && tools === undefined && hooks === undefined && lsp === undefined && writeProtection === undefined && autoConsolidation === undefined && readDeny === undefined && hands === undefined)
552
+ const fileHistory = projectFileHistorySection(ev);
553
+ const instructions = readInstructionsSegment(ev, 'instructions');
554
+ if (modelGate === undefined && autoMode === undefined && mcp === undefined && tools === undefined && hooks === undefined && lsp === undefined && writeProtection === undefined && autoConsolidation === undefined && readDeny === undefined && hands === undefined && fileHistory === undefined && instructions === undefined)
553
555
  return undefined;
554
556
  return {
555
557
  ...(modelGate !== undefined ? { _sema_modelGate: modelGate } : {}),
@@ -562,8 +564,21 @@ function wiringManifestSupersetBody(ev) {
562
564
  ...(autoConsolidation !== undefined ? { _sema_autoConsolidation: autoConsolidation } : {}),
563
565
  ...(readDeny !== undefined ? { _sema_readDeny: readDeny } : {}),
564
566
  ...(hands !== undefined ? { _sema_hands: hands } : {}),
567
+ ...(fileHistory !== undefined ? { _sema_fileHistory: fileHistory } : {}),
568
+ ...(instructions !== undefined ? { _sema_instructions: instructions } : {}),
565
569
  };
566
570
  }
571
+ function projectFileHistorySection(holder) {
572
+ try {
573
+ if (!Object.hasOwn(holder, 'fileHistory'))
574
+ return undefined;
575
+ const raw = holder.fileHistory;
576
+ return typeof raw === 'string' && raw.length > 0 ? raw : undefined;
577
+ }
578
+ catch {
579
+ return undefined;
580
+ }
581
+ }
567
582
  function projectWriteProtectionSection(raw) {
568
583
  if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
569
584
  return undefined;
@@ -11,6 +11,10 @@ export type WiringManifestSections = {
11
11
  _sema_autoConsolidation?: WiringManifestAutoConsolidationView;
12
12
  _sema_readDeny?: WiringManifestReadDenyView;
13
13
  _sema_hands?: WiringManifestHandsView;
14
+ _sema_fileHistory?: string;
15
+ _sema_instructions?: {
16
+ readonly selected: readonly string[];
17
+ };
14
18
  eventId?: string;
15
19
  };
16
20
  export interface WiringManifestView {
@@ -24,6 +28,13 @@ export interface WiringManifestView {
24
28
  autoConsolidation?: WiringManifestAutoConsolidationView;
25
29
  readDeny?: WiringManifestReadDenyView;
26
30
  hands?: WiringManifestHandsView;
31
+ fileHistory?: string;
32
+ instructions?: {
33
+ readonly selected: readonly string[];
34
+ };
27
35
  eventId?: string;
28
36
  }
37
+ export declare function readInstructionsSegment(holder: object, key: 'instructions' | '_sema_instructions'): {
38
+ readonly selected: readonly string[];
39
+ } | undefined;
29
40
  export declare function wiringManifestViewOf(s: WiringManifestSections): WiringManifestView | undefined;
@@ -2,8 +2,34 @@ const _viewPin = true;
2
2
  void _viewPin;
3
3
  const _viewKeysPin = true;
4
4
  void _viewKeysPin;
5
+ export function readInstructionsSegment(holder, key) {
6
+ try {
7
+ if (!Object.hasOwn(holder, key))
8
+ return undefined;
9
+ const raw = holder[key];
10
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw) || !Object.hasOwn(raw, 'selected'))
11
+ return undefined;
12
+ const sel = raw.selected;
13
+ if (!Array.isArray(sel))
14
+ return undefined;
15
+ const out = [];
16
+ for (let i = 0; i < sel.length; i++) {
17
+ if (!Object.hasOwn(sel, i))
18
+ return undefined;
19
+ const v = sel[i];
20
+ if (typeof v !== 'string' || v.length === 0)
21
+ return undefined;
22
+ out.push(v);
23
+ }
24
+ return Object.freeze({ selected: Object.freeze(out) });
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ }
5
30
  const isObj = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
6
31
  export function wiringManifestViewOf(s) {
32
+ const instructions = readInstructionsSegment(s, '_sema_instructions');
7
33
  const view = {
8
34
  ...(isObj(s._sema_modelGate) ? { modelGate: s._sema_modelGate } : {}),
9
35
  ...(isObj(s._sema_autoMode) ? { autoMode: s._sema_autoMode } : {}),
@@ -15,6 +41,8 @@ export function wiringManifestViewOf(s) {
15
41
  ...(isObj(s._sema_autoConsolidation) ? { autoConsolidation: s._sema_autoConsolidation } : {}),
16
42
  ...(isObj(s._sema_readDeny) ? { readDeny: s._sema_readDeny } : {}),
17
43
  ...(isObj(s._sema_hands) && typeof s._sema_hands.mounted === 'boolean' ? { hands: s._sema_hands } : {}),
44
+ ...(typeof s._sema_fileHistory === 'string' && s._sema_fileHistory.length > 0 ? { fileHistory: s._sema_fileHistory } : {}),
45
+ ...(instructions !== undefined ? { instructions } : {}),
18
46
  };
19
47
  if (Object.keys(view).length === 0)
20
48
  return undefined;
@@ -17,7 +17,7 @@ export interface RunsResourceLike {
17
17
  export interface ControlClientLike {
18
18
  runs: RunsResourceLike;
19
19
  }
20
- export type ControlSafetyCode = 'not_running' | 'invalid_content' | 'queue_full' | 'duplicate_input_id' | 'ambiguous_target' | 'still_running' | 'blocked_by_hook' | 'steering_other' | 'cancel_lost_race' | 'cancel_run_not_running' | 'not_found';
20
+ export type ControlSafetyCode = 'not_running' | 'invalid_content' | 'queue_full' | 'duplicate_input_id' | 'ambiguous_target' | 'still_running' | 'blocked_by_hook' | 'ledger_unavailable' | 'steering_other' | 'cancel_lost_race' | 'cancel_run_not_running' | 'not_found';
21
21
  export declare class ControlSafetyError extends Error {
22
22
  readonly code: ControlSafetyCode;
23
23
  readonly cause?: unknown | undefined;
@@ -71,3 +71,9 @@ export interface ErrCodes {
71
71
  status?: number | undefined;
72
72
  }
73
73
  export declare function errCodes(e: unknown): ErrCodes;
74
+ export declare function steeringStatusIs4xx(e: object): boolean;
75
+ export interface SteeringRefusedBeforeEngine {
76
+ safety: ControlSafetyCode;
77
+ advice: string;
78
+ }
79
+ export declare function steeringRefusedBeforeEngine(e: object): SteeringRefusedBeforeEngine | undefined;
@@ -64,8 +64,9 @@ export class ControlRouter {
64
64
  catch (e) {
65
65
  const verdict = steeringVerdict(e);
66
66
  if (verdict !== undefined) {
67
+ const safety = steeringSafetyOf(e, verdict);
67
68
  const wireCode = errCodes(e).code ?? errCodes(e).name ?? 'steering.<unknown>';
68
- throw new ControlSafetyError(`${wireCode} — ${STEERING_ADVICE.get(verdict) ?? 'steering refused'}`, verdict, e);
69
+ throw new ControlSafetyError(`${wireCode} — ${steeringAdviceOf(e, safety) ?? 'steering refused'}`, safety, e);
69
70
  }
70
71
  throw e;
71
72
  }
@@ -138,12 +139,14 @@ const STEERING_CODE_TO_SAFETY = new Map([
138
139
  ['steering.ambiguous_label', 'ambiguous_target'],
139
140
  ['steering.still_running', 'still_running'],
140
141
  ['steering.blocked_by_hook', 'blocked_by_hook'],
142
+ ['steering.ledger_unavailable', 'ledger_unavailable'],
141
143
  ]);
142
144
  const STEERING_NAME_TO_SAFETY = new Map([
143
145
  ['SteeringNotRunningError', 'not_running'],
144
146
  ['SteeringInvalidContentError', 'invalid_content'],
145
147
  ['SteeringAmbiguousTargetError', 'ambiguous_target'],
146
148
  ['SteeringStillRunningError', 'still_running'],
149
+ ['SteeringLedgerUnavailableError', 'ledger_unavailable'],
147
150
  ['SteeringError', 'steering_other'],
148
151
  ]);
149
152
  const STEERING_ADVICE = new Map([
@@ -154,8 +157,47 @@ const STEERING_ADVICE = new Map([
154
157
  ['ambiguous_target', 'more than one live target matches — address it uniquely (sub-agent: parentToolCallId; workflow: a more specific label); retrying verbatim yields the same result'],
155
158
  ['still_running', 'the target is STILL RUNNING — steer it instead of resuming, or wait for it to settle (this is the exact opposite of not_running: never collapse the two)'],
156
159
  ['blocked_by_hook', "this deployment's userPromptSubmit gate refused the input (block, timeout and crash all report this one code, fail-closed) — the input was NOT accepted: no human_input frame, the inputId is not on the ledger, so editing the text and sending again is a normal retry, not a duplicate"],
160
+ ['ledger_unavailable', 'the server could not record this steer in its user-input ledger and refused it before anything reached the engine — the input was NOT delivered; resend the same text later (the same Idempotency-Key is fine)'],
157
161
  ['steering_other', 'an unrecognized steering.* refusal (open set) — the steer did NOT land; log the errorCode verbatim, do not guess its meaning'],
158
162
  ]);
163
+ const STEERING_OTHER_UNKNOWN_ADVICE = 'an unrecognized steering.* refusal (open set) — treat delivery as unknown (do not resend as if it had certainly been dropped); log the errorCode verbatim, do not guess its meaning';
164
+ export function steeringStatusIs4xx(e) {
165
+ let status;
166
+ try {
167
+ status = errCodes(e).status;
168
+ }
169
+ catch {
170
+ return false;
171
+ }
172
+ return status !== undefined && status >= 400 && status < 500;
173
+ }
174
+ function steeringAdviceOf(e, safety) {
175
+ if (safety === 'steering_other' && !(typeof e === 'object' && e !== null && steeringStatusIs4xx(e)))
176
+ return STEERING_OTHER_UNKNOWN_ADVICE;
177
+ return STEERING_ADVICE.get(safety);
178
+ }
179
+ const STEERING_REFUSED_BEFORE_ENGINE = new Map([['ledger_unavailable', 503]]);
180
+ export function steeringRefusedBeforeEngine(e) {
181
+ try {
182
+ const { status } = errCodes(e);
183
+ if (status === undefined)
184
+ return undefined;
185
+ const safety = steeringVerdict(e);
186
+ if (safety === undefined || STEERING_REFUSED_BEFORE_ENGINE.get(safety) !== status)
187
+ return undefined;
188
+ const advice = STEERING_ADVICE.get(safety);
189
+ return advice === undefined ? undefined : { safety, advice };
190
+ }
191
+ catch {
192
+ return undefined;
193
+ }
194
+ }
195
+ function steeringSafetyOf(e, verdict) {
196
+ if (!STEERING_REFUSED_BEFORE_ENGINE.has(verdict))
197
+ return verdict;
198
+ const refused = typeof e === 'object' && e !== null ? steeringRefusedBeforeEngine(e) : undefined;
199
+ return refused !== undefined && refused.safety === verdict ? verdict : 'steering_other';
200
+ }
159
201
  function steeringVerdict(e) {
160
202
  const { code, name } = errCodes(e);
161
203
  if (typeof code === 'string' && code.startsWith('steering.')) {
@@ -0,0 +1,17 @@
1
+ export declare function refuseBadDisableSkills(v: unknown, who: string): void;
2
+ export declare function refuseDisableSkillsConflict(disableSkills: unknown, skills: unknown, agents: unknown, who: string): void;
3
+ type DisableSkillsWithheldCause = 'not_reported' | 'unsupported' | 'unprobed' | 'unreadable';
4
+ export type DisableSkillsDeclaration = {
5
+ readonly field: {
6
+ readonly disableSkills: true;
7
+ };
8
+ readonly withheld?: undefined;
9
+ } | {
10
+ readonly field: Readonly<Record<string, never>>;
11
+ readonly withheld?: {
12
+ readonly cause: DisableSkillsWithheldCause;
13
+ readonly text: string;
14
+ };
15
+ };
16
+ export declare function disableSkillsDeclaration(want: unknown, baseUrl: string | undefined): DisableSkillsDeclaration;
17
+ export {};
@@ -0,0 +1,52 @@
1
+ import { engineCapState } from './engineCapsCache.js';
2
+ const KEY = 'disableSkills';
3
+ const shapeOf = (v) => {
4
+ try {
5
+ return v === null ? 'null' : Array.isArray(v) ? 'typeof=object / array' : typeof v === 'string' ? `typeof=string(长 ${v.length})` : `typeof=${typeof v}`;
6
+ }
7
+ catch {
8
+ return `typeof=${typeof v} / unreadable`;
9
+ }
10
+ };
11
+ export function refuseBadDisableSkills(v, who) {
12
+ if (v === undefined || v === null || v === true || v === false)
13
+ return;
14
+ throw new TypeError(`${who}: disableSkills 只接受布尔或缺席(undefined/null)—— 收到 ${shapeOf(v)}。` +
15
+ '这一位是「这一发一只技能都不装」的声明:本层若把坏值折成缺席,这一次运行会照常装上技能而声明人不会知道;' +
16
+ '上游对非布尔值同样拒收。错误文本只报形状,不回显值。');
17
+ }
18
+ const nonEmptyArray = (v) => Array.isArray(v) && v.length > 0;
19
+ const anyAgentCarriesSkills = (agents) => Array.isArray(agents) && agents.some((a) => typeof a === 'object' && a !== null && nonEmptyArray(a.skills));
20
+ export function refuseDisableSkillsConflict(disableSkills, skills, agents, who) {
21
+ if (disableSkills !== true)
22
+ return;
23
+ const inSkills = nonEmptyArray(skills);
24
+ const inAgents = anyAgentCarriesSkills(agents);
25
+ if (!inSkills && !inAgents)
26
+ return;
27
+ const which = inSkills && inAgents ? 'skills 与 agents[].skills' : inSkills ? 'skills' : 'agents[].skills';
28
+ throw new TypeError(`${who}: disableSkills: true(这一发一只技能都不装)与非空的 ${which} 同在 —— 二选一:要关技能就别交技能,要交技能就别带 disableSkills。` +
29
+ '上游对这一组合同样拒收(在任何东西跑起来之前);本层在装配前拒,不让它走一次往返。错误文本只报键名,不回显技能名。');
30
+ }
31
+ const WITHHELD_TEXT = Object.freeze({
32
+ not_reported: 'Skills were not turned off for this request: the connected engine does not report that it can turn them off, and an engine that does not know this setting rejects the whole request, so the setting was left out and this run keeps its usual skills.',
33
+ unsupported: 'Skills were not turned off for this request: the connected engine reports that it cannot turn them off, so the setting was left out and this run keeps its usual skills.',
34
+ unprobed: 'Skills were not turned off for this request: what the connected engine supports has not been read yet, and an engine that does not know this setting rejects the whole request, so the setting was held back and this run keeps its usual skills.',
35
+ unreadable: 'Skills were not turned off for this request: the connected engine reported whether it can turn them off in a form this version cannot read, so the setting was left out and this run keeps its usual skills.',
36
+ });
37
+ const WITHHELD_CAUSE_OF = {
38
+ absent: 'not_reported',
39
+ false: 'unsupported',
40
+ unprobed: 'unprobed',
41
+ non_boolean: 'unreadable',
42
+ };
43
+ export function disableSkillsDeclaration(want, baseUrl) {
44
+ refuseBadDisableSkills(want, 'disableSkillsDeclaration');
45
+ if (want !== true)
46
+ return Object.freeze({ field: Object.freeze({}) });
47
+ const state = engineCapState(baseUrl, KEY);
48
+ if (state === 'true')
49
+ return Object.freeze({ field: Object.freeze({ disableSkills: true }) });
50
+ const cause = WITHHELD_CAUSE_OF[state];
51
+ return Object.freeze({ field: Object.freeze({}), withheld: Object.freeze({ cause, text: WITHHELD_TEXT[cause] }) });
52
+ }
@@ -33,5 +33,9 @@ export interface DisplayUntrustedMarked {
33
33
  readonly text: string;
34
34
  readonly marks: readonly DisplayMarkSpan[];
35
35
  }
36
+ export declare function credentialWashPasses(text: string, opts?: DisplayUntrustedOptions | null): {
37
+ passes: number;
38
+ capped: boolean;
39
+ };
36
40
  export declare function displayUntrusted(text: string, opts?: DisplayUntrustedOptions): string;
37
41
  export declare function displayUntrustedMarks(text: string, opts?: DisplayUntrustedOptions): DisplayUntrustedMarked;