@sema-agent/client-core 0.85.2 → 0.86.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 (57) hide show
  1. package/CHANGELOG.md +208 -0
  2. package/README.md +20 -13
  3. package/dist/adapt/arms.js +5 -1
  4. package/dist/adapter/downstream/terminalToSdkResult.d.ts +3 -3
  5. package/dist/agentSession/backgroundView.js +7 -1
  6. package/dist/agentSession/contract.d.ts +1 -1
  7. package/dist/centerWiringCapability.d.ts +38 -0
  8. package/dist/centerWiringCapability.js +202 -0
  9. package/dist/decideFailureNote.js +3 -0
  10. package/dist/engineCapReader.d.ts +8 -0
  11. package/dist/engineCapReader.js +15 -0
  12. package/dist/engineErrorCodes.d.ts +3 -0
  13. package/dist/engineErrorCodes.js +8 -0
  14. package/dist/engineNoticeCodes.d.ts +62 -0
  15. package/dist/engineNoticeCodes.js +247 -29
  16. package/dist/executionLaneCapability.d.ts +6 -0
  17. package/dist/executionLaneCapability.js +55 -2
  18. package/dist/fleet/fleetProjection.js +6 -8
  19. package/dist/fleet/workflowSizeWarning.js +2 -5
  20. package/dist/gateOutcome.d.ts +13 -0
  21. package/dist/gateOutcome.js +48 -1
  22. package/dist/gateVocabulary.d.ts +6 -3
  23. package/dist/gateVocabulary.js +7 -15
  24. package/dist/generated/engineFactTables.d.ts +10 -0
  25. package/dist/generated/engineFactTables.js +113 -0
  26. package/dist/generated/engineNoticeTables.js +14 -0
  27. package/dist/hitl/refusedToolNameProse.d.ts +4 -0
  28. package/dist/hitl/refusedToolNameProse.js +7 -0
  29. package/dist/hitl/sessionPolicyDeliverable.js +9 -5
  30. package/dist/hitl/sessionPolicyWire.d.ts +16 -0
  31. package/dist/hitl/sessionPolicyWire.js +49 -1
  32. package/dist/index.d.ts +5 -1
  33. package/dist/index.js +5 -1
  34. package/dist/inheritEnvWire.d.ts +22 -0
  35. package/dist/inheritEnvWire.js +84 -0
  36. package/dist/peerFrames.js +2 -10
  37. package/dist/printInitToolFace.d.ts +6 -0
  38. package/dist/printInitToolFace.js +115 -2
  39. package/dist/readCredentialRefusal.d.ts +2 -0
  40. package/dist/readCredentialRefusal.js +7 -0
  41. package/dist/request/taskRequest.d.ts +4 -5
  42. package/dist/request/taskRequest.js +33 -23
  43. package/dist/runTerminal.js +2 -6
  44. package/dist/sqlEngineCapability.js +15 -2
  45. package/dist/storePostureCapability.d.ts +25 -0
  46. package/dist/storePostureCapability.js +132 -0
  47. package/dist/toolResult.js +2 -47
  48. package/dist/wireErrorTriage.d.ts +1 -0
  49. package/dist/wireErrorTriage.js +3 -0
  50. package/dist/wireFailureShape.d.ts +3 -0
  51. package/dist/wireFailureShape.js +44 -0
  52. package/dist/wireRefusalCopy.d.ts +39 -1
  53. package/dist/wireRefusalCopy.js +350 -2
  54. package/dist/workflowClient.d.ts +4 -0
  55. package/dist/workflowClient.js +12 -4
  56. package/docs/INTEGRATION-CLIENTS.md +716 -14
  57. package/package.json +2 -2
@@ -1,3 +1,4 @@
1
+ import { CORE_DENIED_BY_VALUES } from './generated/engineFactTables.js';
1
2
  export const CC_TOOL_DENIAL_KINDS = Object.freeze([
2
3
  'user-rejected',
3
4
  'permission-rule',
@@ -20,18 +21,10 @@ export function ccToolDenialKindForSettledBy(settledBy) {
20
21
  return 'permission-rule';
21
22
  return undefined;
22
23
  }
23
- export const GATE_DENIED_BY_WORDS = Object.freeze([
24
- 'policy',
25
- 'hook',
26
- 'org',
27
- 'persisted_rule',
28
- 'classifier',
29
- 'plan_mode',
30
- 'compliance',
31
- 'write_protection',
32
- 'ask_resolution',
33
- 'read_boundary',
34
- ]);
24
+ const RETIRED_DENIED_BY_WORDS = Object.freeze(['plan_mode']);
25
+ export const GATE_DENIED_BY_WORDS = Object.freeze([...CORE_DENIED_BY_VALUES, ...RETIRED_DENIED_BY_WORDS]);
26
+ const _deniedByWordsPin = true;
27
+ void _deniedByWordsPin;
35
28
  const DENIED_BY_SENTENCES = Object.freeze({
36
29
  policy: "denied by this deployment's permission policy",
37
30
  hook: 'denied by a PreToolUse hook',
@@ -43,6 +36,7 @@ const DENIED_BY_SENTENCES = Object.freeze({
43
36
  write_protection: 'denied because the write landed on a write-protected path',
44
37
  ask_resolution: 'denied when the approval was resolved',
45
38
  read_boundary: 'denied by the read boundary',
39
+ mode: "denied by this session's permission mode",
46
40
  });
47
41
  export function isGateDeniedByWord(v) {
48
42
  return typeof v === 'string' && GATE_DENIED_BY_WORDS.includes(v);
@@ -63,7 +57,7 @@ const ASK_ORIGIN_SENTENCES = Object.freeze({
63
57
  hook: 'a PreToolUse hook asked about this call',
64
58
  ask_rule: 'a persisted ask rule matches this call',
65
59
  denial_limit_fallback: 'the auto-mode classifier hit its denial limit and handed this call back to you',
66
- shell_gate_tighten: 'this deployment asks about shell commands the coarse shell gate rates above this tier',
60
+ shell_gate_tighten: 'the coarse shell check rates this command above the tier it lets through, so it asks',
67
61
  safety_tighten: 'the gate tightened on this call’s own facts (network egress, irreversibility, or a protected write)',
68
62
  policy: 'this deployment’s permission policy asks about this call',
69
63
  });
@@ -82,8 +76,6 @@ export function askOriginDetail(origin, message) {
82
76
  const word = typeof origin === 'string' && origin.length > 0 ? origin : '(none)';
83
77
  return `this call asks; its origin ${word} is a word newer than this client, so answer it as usual`;
84
78
  }
85
- const _deniedByWordsPin = GATE_DENIED_BY_WORDS;
86
- void _deniedByWordsPin;
87
79
  export const RULE_STORE_UNREADABLE_KINDS = Object.freeze(['store', 'call']);
88
80
  const RULE_STORE_UNREADABLE_SET = new Set(RULE_STORE_UNREADABLE_KINDS);
89
81
  export function isRuleStoreUnreadableKind(v) {
@@ -0,0 +1,10 @@
1
+ export declare const CORE_ASK_UNRESOLVABLE_CAUSES: readonly string[];
2
+ export declare const CORE_DURABLE_MANDATE_SOURCES: readonly string[];
3
+ export declare const CORE_TERMINAL_CAUSE_KINDS: readonly ["completed", "failed", "blocked", "paused"];
4
+ export declare const CORE_RESERVED_AGENT_NAMES: readonly string[];
5
+ export declare const CORE_WORKFLOW_SIZE_GUIDELINE_AGENT_CAPS: Readonly<Record<"small" | "medium" | "large", number>>;
6
+ export declare const CORE_ENGINE_AUTHORITY_ENVELOPE_TAGS: readonly string[];
7
+ export declare const CORE_DENIED_BY_VALUES: readonly ["policy", "hook", "org", "persisted_rule", "classifier", "compliance", "write_protection", "ask_resolution", "read_boundary", "mode"];
8
+ export declare const CORE_PERMISSION_MODE_FOLD_REASONS: readonly string[];
9
+ export declare const CORE_ENGINE_CARD_TYPES: readonly string[];
10
+ export declare const CORE_TOOL_DECLARATION_CODES: readonly string[];
@@ -0,0 +1,113 @@
1
+ export const CORE_ASK_UNRESOLVABLE_CAUSES = Object.freeze([
2
+ "approver_unavailable",
3
+ "no_approver_wired",
4
+ "mandate_unreconstructible",
5
+ ]);
6
+ export const CORE_DURABLE_MANDATE_SOURCES = Object.freeze([
7
+ "force_durable_gate",
8
+ "durable_approval",
9
+ ]);
10
+ export const CORE_TERMINAL_CAUSE_KINDS = Object.freeze([
11
+ "completed",
12
+ "failed",
13
+ "blocked",
14
+ "paused",
15
+ ]);
16
+ export const CORE_RESERVED_AGENT_NAMES = Object.freeze([
17
+ "StructuredOutput",
18
+ "ToolSearch",
19
+ "ReadToolResult",
20
+ "ReportBlocked",
21
+ "Agent",
22
+ ]);
23
+ export const CORE_WORKFLOW_SIZE_GUIDELINE_AGENT_CAPS = Object.freeze({
24
+ "small": 5,
25
+ "medium": 15,
26
+ "large": 50,
27
+ });
28
+ export const CORE_ENGINE_AUTHORITY_ENVELOPE_TAGS = Object.freeze([
29
+ "system-reminder",
30
+ "task-notification",
31
+ "new-diagnostics",
32
+ "user_memory",
33
+ "scope",
34
+ "skills",
35
+ "total_tokens",
36
+ "instruction-files",
37
+ ]);
38
+ export const CORE_DENIED_BY_VALUES = Object.freeze([
39
+ "policy",
40
+ "hook",
41
+ "org",
42
+ "persisted_rule",
43
+ "classifier",
44
+ "compliance",
45
+ "write_protection",
46
+ "ask_resolution",
47
+ "read_boundary",
48
+ "mode",
49
+ ]);
50
+ export const CORE_PERMISSION_MODE_FOLD_REASONS = Object.freeze([
51
+ "operator_deny",
52
+ "face_absent",
53
+ "inherited_ceiling",
54
+ ]);
55
+ export const CORE_ENGINE_CARD_TYPES = Object.freeze([
56
+ "mcp",
57
+ "a2a",
58
+ "path_not_in_root",
59
+ "read_path_denied",
60
+ "readonly_out_of_root",
61
+ "read_unestablished",
62
+ "text",
63
+ "notebook",
64
+ "file_unchanged",
65
+ "image",
66
+ "document",
67
+ "edit",
68
+ "create",
69
+ "update",
70
+ "notebook-edit",
71
+ "bash",
72
+ "bash_invalid_timeout",
73
+ "grep",
74
+ "glob",
75
+ "repo-map",
76
+ "artifact",
77
+ "worktree",
78
+ "task-output",
79
+ "task-stop",
80
+ "monitor-start",
81
+ "send-message",
82
+ "agent-transcript",
83
+ "list-agents",
84
+ "read-inbox",
85
+ "workflow-run",
86
+ "report-findings",
87
+ "tool-search",
88
+ "ask-question",
89
+ "exit-plan-mode",
90
+ "enter-plan-mode",
91
+ "cron-create",
92
+ "cron-delete",
93
+ "cron-list",
94
+ "schedule-wakeup",
95
+ "web-fetch",
96
+ "web-search",
97
+ "todo",
98
+ "task",
99
+ "task-list",
100
+ "agent",
101
+ "fork",
102
+ ]);
103
+ export const CORE_TOOL_DECLARATION_CODES = Object.freeze([
104
+ "config.tool_mount_denied",
105
+ "config.tool_roster_bound",
106
+ "config.tool_name_too_long",
107
+ "config.tool_contract_too_long",
108
+ "config.tool_schema_bound",
109
+ "config.tool_face_invalid",
110
+ "config.tool_name_invalid",
111
+ "config.egress_requires_write_effect",
112
+ "config.reserved_tool_name",
113
+ ]);
@@ -24,6 +24,11 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
24
24
  "config.peer_admission_out_of_range",
25
25
  "config.peer_lane_unmounted",
26
26
  "config.secret_env_scrubbed",
27
+ "config.permission_mode_unavailable",
28
+ "permission.ask_released_by_mode",
29
+ "permission.read_deny_unapplied",
30
+ "permission.rule_store_unavailable",
31
+ "resume.legacy_mode_seed_migrated",
27
32
  "peer.inbound_disposition",
28
33
  "peer.held_settled",
29
34
  "peer.idle_subscription",
@@ -31,6 +36,7 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
31
36
  "classifier.fallback",
32
37
  "classifier.role_defaulted",
33
38
  "classifier.contract_broken",
39
+ "classifier.unavailable",
34
40
  "checkpoint.execution_outcome_unrecorded",
35
41
  "delegation.transcript_integrity",
36
42
  "delegation.ask_unresolvable",
@@ -58,6 +64,7 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
58
64
  "route.classifier_unroutable",
59
65
  "route.base_url_changed_key_unchanged",
60
66
  "route.response_model_mismatch",
67
+ "route.tool_call_id_folded",
61
68
  "task.user_steer_undrained",
62
69
  "task.user_followup_undrained",
63
70
  "steering.parked_input_blocked",
@@ -99,6 +106,11 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
99
106
  "config.peer_admission_out_of_range": "operator",
100
107
  "config.peer_lane_unmounted": "operator",
101
108
  "config.secret_env_scrubbed": "operator",
109
+ "config.permission_mode_unavailable": "user",
110
+ "permission.ask_released_by_mode": "user",
111
+ "permission.read_deny_unapplied": "user",
112
+ "permission.rule_store_unavailable": "user",
113
+ "resume.legacy_mode_seed_migrated": "operator",
102
114
  "peer.inbound_disposition": "user",
103
115
  "peer.held_settled": "user",
104
116
  "peer.idle_subscription": "user",
@@ -106,6 +118,7 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
106
118
  "classifier.fallback": "operator",
107
119
  "classifier.role_defaulted": "operator",
108
120
  "classifier.contract_broken": "operator",
121
+ "classifier.unavailable": "user",
109
122
  "checkpoint.execution_outcome_unrecorded": "operator",
110
123
  "delegation.transcript_integrity": "operator",
111
124
  "delegation.ask_unresolvable": "user",
@@ -133,6 +146,7 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
133
146
  "route.classifier_unroutable": "operator",
134
147
  "route.base_url_changed_key_unchanged": "operator",
135
148
  "route.response_model_mismatch": "operator",
149
+ "route.tool_call_id_folded": "operator",
136
150
  "task.user_steer_undrained": "user",
137
151
  "task.user_followup_undrained": "user",
138
152
  "steering.parked_input_blocked": "user",
@@ -0,0 +1,4 @@
1
+ export declare const PREFIXES_IN_PROSE: string;
2
+ export declare const REFUSED_NAME_CLASSES: string;
3
+ export declare const REFUSED_NAME_FIX: string;
4
+ export declare const RULES_LEGACY_TOOL_NAME_WRITE_NOTE: string;
@@ -0,0 +1,7 @@
1
+ import { CORE_PROTOCOL_PREFIXES } from '../generated/toolNameTables.js';
2
+ export const PREFIXES_IN_PROSE = CORE_PROTOCOL_PREFIXES.map((prefix) => `"${prefix}"`).join(' or ');
3
+ export const REFUSED_NAME_CLASSES = `a retired tool name, or a name that contains "__" but does not start with ${PREFIXES_IN_PROSE}`;
4
+ export const REFUSED_NAME_FIX = `If the tool still exists, use its current name; a server or agent-peer tool name starts with ${PREFIXES_IN_PROSE}.`;
5
+ export const RULES_LEGACY_TOOL_NAME_WRITE_NOTE = `The engine refused to write these session rules, and the stored record was not changed at all: they name a tool the engine refuses — ${REFUSED_NAME_CLASSES} (the engine's own error text names the entry). ` +
6
+ `${REFUSED_NAME_FIX} Then write the rules again. ` +
7
+ 'If that entry was already in this session’s rule record, it has to be removed from the record before the record can be written again.';
@@ -1,16 +1,16 @@
1
- import { CONFIG_LEGACY_TOOL_NAME } from '../engineErrorCodes.js';
1
+ import { CONFIG_LEGACY_TOOL_NAME, RULES_LEGACY_TOOL_NAME } from '../engineErrorCodes.js';
2
2
  import { rosterMountedNames } from './rosterMountedNames.js';
3
+ import { PREFIXES_IN_PROSE, REFUSED_NAME_CLASSES, REFUSED_NAME_FIX, RULES_LEGACY_TOOL_NAME_WRITE_NOTE } from './refusedToolNameProse.js';
3
4
  import { CORE_PROTOCOL_PREFIXES, CORE_RETIRED_TOOL_CURRENT_NAMES } from '../generated/toolNameTables.js';
4
5
  const COVERING_NAMESPACE_PREFIXES = CORE_PROTOCOL_PREFIXES;
5
6
  const ENGINE_RETIRED_TOOL_NAMES = CORE_RETIRED_TOOL_CURRENT_NAMES;
6
- const PREFIXES_IN_PROSE = COVERING_NAMESPACE_PREFIXES.map((prefix) => `"${prefix}"`).join(' or ');
7
7
  const WITHHELD_NOTICE = {
8
8
  ask_no_bucket: 'Not written to this session’s rule record: that record only holds rules that block outright, and this rule asks before running instead — recording it as a block would change what it means.',
9
9
  qualified_deny: 'Not written to this session’s rule record: that record holds whole tool names and command names only, and this rule has a part in parentheses it cannot carry — recording just the name could block more than this rule does.',
10
10
  peer_wide: 'Not written to this session’s rule record: this rule names a server or agent peer without naming one of its tools, and an engine that matches that record by exact tool name would block none of that peer’s tools.',
11
11
  wildcard: 'Not written to this session’s rule record: this rule uses a wildcard (*), and an engine that matches that record by exact tool name would block none of the tools it covers.',
12
12
  not_a_tool_name: 'Not written to this session’s rule record: this entry is not exactly one tool name — it is empty, not text, or has spaces around the name.',
13
- legacy_tool_name: `Not written to this session’s rule record: unless a tool by exactly this name is available, the engine refuses it — it is a retired tool name, or it contains "__" but does not start with ${PREFIXES_IN_PROSE} — and with it in that record every later run of this session would fail at startup until that entry is removed from the record. If the tool still exists, use its current name; a server or agent-peer tool name starts with ${PREFIXES_IN_PROSE}.`,
13
+ legacy_tool_name: `Not written to this session’s rule record: unless a tool by exactly this name is available, the engine refuses it — it is a retired tool name, or it contains "__" but does not start with ${PREFIXES_IN_PROSE} — and with it in that record every later run of this session would fail at startup until that entry is removed from the record. ${REFUSED_NAME_FIX}`,
14
14
  not_in_roster: 'Not written to this session’s rule record: the tool roster supplied for this check has no tool by exactly this name, as a name or an alias, with letter case counted — it may be misspelled, or name a tool this deployment does not provide — so recorded as it is it would block nothing here.',
15
15
  };
16
16
  export const SESSION_POLICY_WITHHELD_WHY = Object.freeze(Object.keys(WITHHELD_NOTICE));
@@ -114,8 +114,12 @@ export function sessionPolicyWithheldNotice(why) {
114
114
  ? WITHHELD_NOTICE[why]
115
115
  : 'Not written to this session’s rule record.';
116
116
  }
117
- const LEGACY_TOOL_NAME_FAILURE_NOTE = `This run did not start: a tool rule applied to it names a tool the engine refuses — a retired tool name, or a name that contains "__" but does not start with ${PREFIXES_IN_PROSE} (the engine's own error text names the entry). ` +
117
+ const LEGACY_TOOL_NAME_FAILURE_NOTE = `This run did not start: a tool rule applied to it names a tool the engine refuses — ${REFUSED_NAME_CLASSES} (the engine's own error text names the entry). ` +
118
118
  '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.';
119
119
  export function legacyToolNameFailureNoteOf(code) {
120
- return code === CONFIG_LEGACY_TOOL_NAME ? LEGACY_TOOL_NAME_FAILURE_NOTE : undefined;
120
+ if (code === CONFIG_LEGACY_TOOL_NAME)
121
+ return LEGACY_TOOL_NAME_FAILURE_NOTE;
122
+ if (code === RULES_LEGACY_TOOL_NAME)
123
+ return RULES_LEGACY_TOOL_NAME_WRITE_NOTE;
124
+ return undefined;
121
125
  }
@@ -38,6 +38,11 @@ export type SessionPolicyFailure = {
38
38
  } | {
39
39
  kind: 'request-rejected';
40
40
  message: string;
41
+ } | {
42
+ kind: 'legacy-tool-name';
43
+ message: string;
44
+ field?: SessionPolicyRemovedEntry['field'];
45
+ name?: string;
41
46
  } | {
42
47
  kind: 'unauthorized';
43
48
  message: string;
@@ -85,6 +90,12 @@ export type SessionPolicyTightenOutcome = {
85
90
  } | {
86
91
  kind: 'capability_absent';
87
92
  why: 'not_reported' | 'absent';
93
+ } | {
94
+ kind: 'legacy_tool_name';
95
+ message: string;
96
+ field?: SessionPolicyRemovedEntry['field'];
97
+ name?: string;
98
+ alreadyInRecord?: boolean;
88
99
  } | {
89
100
  kind: 'unknown';
90
101
  why: SessionPolicyTightenUnknownWhy;
@@ -127,6 +138,11 @@ export type SessionPolicyRemovalOutcome = {
127
138
  kind: 'write_unconfirmed';
128
139
  why: Extract<SessionPolicyTightenUnknownWhy, 'write_indeterminate' | 'write_receipt_unreadable' | 'write_receipt_mismatch'>;
129
140
  message?: string;
141
+ } | {
142
+ kind: 'legacy_tool_name';
143
+ message: string;
144
+ field?: SessionPolicyRemovedEntry['field'];
145
+ name?: string;
130
146
  };
131
147
  export type SessionPolicyRosterRequiredWhy = 'absent' | 'unreadable';
132
148
  export declare function removeRefusedSessionRules(facade: SessionPolicyFacade, sessionId: string, roster: ToolRosterView | undefined, opts?: {
@@ -1,6 +1,8 @@
1
1
  import { wireFailureShapeOf } from '../wireFailureShape.js';
2
2
  import { hostLog } from '../host.js';
3
3
  import { isEngineRefusedToolName } from './sessionPolicyDeliverable.js';
4
+ import { RULES_LEGACY_TOOL_NAME_WRITE_NOTE } from './refusedToolNameProse.js';
5
+ import { RULES_LEGACY_TOOL_NAME, isRulesRefusalCode } from '../engineErrorCodes.js';
4
6
  import { rosterMountedNames } from './rosterMountedNames.js';
5
7
  const RULE_FIELD_PRESENCE = {
6
8
  toolAllow: true,
@@ -12,9 +14,19 @@ const RULE_FIELD_PRESENCE = {
12
14
  export const SESSION_POLICY_RULE_FIELDS = Object.freeze(Object.keys(RULE_FIELD_PRESENCE));
13
15
  const MAX_RULE_ENTRIES = 10_000;
14
16
  export function classifySessionPolicyFailure(e) {
15
- const { status, errorCode, message } = wireFailureShapeOf(e);
17
+ const { status, errorCode, message, bodyField, bodyName } = wireFailureShapeOf(e);
16
18
  if (errorCode === undefined || errorCode === '')
17
19
  return { kind: 'no-verdict', message };
20
+ if (errorCode === RULES_LEGACY_TOOL_NAME) {
21
+ return {
22
+ kind: 'legacy-tool-name',
23
+ message,
24
+ ...(bodyField === 'toolDeny' || bodyField === 'toolAllow' ? { field: bodyField } : {}),
25
+ ...(bodyName !== undefined && bodyName !== '' ? { name: bodyName } : {}),
26
+ };
27
+ }
28
+ if (isRulesRefusalCode(errorCode) && status !== undefined && status >= 400 && status < 500)
29
+ return { kind: 'error', message };
18
30
  if (status === 501 || errorCode === 'capability.session_store_required') {
19
31
  return { kind: 'face-unavailable', message };
20
32
  }
@@ -209,10 +221,30 @@ function unknownFrom(failure, leg) {
209
221
  return { kind: 'unknown', why: leg === 'read' ? 'read_failed' : 'write_indeterminate', message };
210
222
  case 'loosen-forbidden':
211
223
  case 'cas-conflict':
224
+ case 'legacy-tool-name':
212
225
  case 'error':
213
226
  return { kind: 'unknown', why: leg === 'read' ? 'read_failed' : 'write_refused', message };
214
227
  }
215
228
  }
229
+ function legacyToolNameOutcome(failure, prior, add) {
230
+ const { field, name } = failure;
231
+ let alreadyInRecord;
232
+ if (field !== undefined && name !== undefined) {
233
+ const inPrior = Object.hasOwn(prior, field) ? prior[field] : undefined;
234
+ const inAdd = Object.hasOwn(add, field) ? add[field] : undefined;
235
+ if (inPrior !== undefined && inPrior.includes(name))
236
+ alreadyInRecord = true;
237
+ else if (inAdd !== undefined && inAdd.includes(name))
238
+ alreadyInRecord = false;
239
+ }
240
+ return {
241
+ kind: 'legacy_tool_name',
242
+ message: failure.message,
243
+ ...(field !== undefined ? { field } : {}),
244
+ ...(name !== undefined ? { name } : {}),
245
+ ...(alreadyInRecord !== undefined ? { alreadyInRecord } : {}),
246
+ };
247
+ }
216
248
  async function attemptTighten(facade, req, opts) {
217
249
  const read = await readSessionPolicy(facade, req.sessionId, opts);
218
250
  if (read.kind === 'failed')
@@ -231,6 +263,8 @@ async function attemptTighten(facade, req, opts) {
231
263
  return { done: { kind: 'loosen_forbidden', message: failure.message } };
232
264
  if (failure.kind === 'cas-conflict')
233
265
  return { retryAtRev: read.rev };
266
+ if (failure.kind === 'legacy-tool-name')
267
+ return { done: legacyToolNameOutcome(failure, read.rules, req.add) };
234
268
  return { done: unknownFrom(failure, 'write') };
235
269
  }
236
270
  let narrowed;
@@ -279,6 +313,8 @@ export function sessionPolicyTightenNotice(outcome) {
279
313
  return outcome.why === 'absent'
280
314
  ? 'This deployment does not keep per-session tool rules, so there is nothing to tighten here.'
281
315
  : 'This engine does not say whether it keeps per-session tool rules — it predates that answer — so the tightening entry stays hidden rather than being written blind.';
316
+ case 'legacy_tool_name':
317
+ return RULES_LEGACY_TOOL_NAME_WRITE_NOTE;
282
318
  case 'unknown':
283
319
  switch (outcome.why) {
284
320
  case 'face_unavailable':
@@ -382,6 +418,16 @@ async function attemptRemoval(facade, sessionId, mounted, opts) {
382
418
  return { done: { kind: 'loosen_forbidden', message: failure.message, refused: removed } };
383
419
  if (failure.kind === 'cas-conflict')
384
420
  return { retryAtRev: read.rev };
421
+ if (failure.kind === 'legacy-tool-name') {
422
+ return {
423
+ done: {
424
+ kind: 'legacy_tool_name',
425
+ message: failure.message,
426
+ ...(failure.field !== undefined ? { field: failure.field } : {}),
427
+ ...(failure.name !== undefined ? { name: failure.name } : {}),
428
+ },
429
+ };
430
+ }
385
431
  return { done: removalFailed(failure, 'write') };
386
432
  }
387
433
  let narrowed;
@@ -475,6 +521,8 @@ export function sessionPolicyRemovalNotice(outcome) {
475
521
  }
476
522
  case 'write_unconfirmed':
477
523
  return 'The removal was sent but no clear answer came back from the engine — it may already be in effect. Run the removal again: it re-reads the record, and reports nothing left to remove if it did take effect.';
524
+ case 'legacy_tool_name':
525
+ return 'Nothing was changed: the engine refused to write this session’s rule record back, because an entry this removal keeps is a name the engine no longer accepts in that record (the engine\'s own error text names the entry). The removal keeps it on purpose — the supplied roster mounts a tool by exactly that name, or this version does not yet recognise the name as one the engine refuses. While the record holds that entry it cannot be written, so the entries this removal meant to take out stay in it as well.';
478
526
  default:
479
527
  return generic;
480
528
  }
package/dist/index.d.ts CHANGED
@@ -72,7 +72,7 @@ export * from './engineWireSdk.js';
72
72
  export * from './classifierVerdictWire.js';
73
73
  export { stripSystemReminderBlocks, unwrapSystemReminder } from './systemReminderTag.js';
74
74
  export { findSystemReminderOpenTag, type SystemReminderOpenTagSpan } from './systemReminderTag.js';
75
- export { ACTIVE_RUN_BUSY_ERROR_CODE, asModelFallbackReason, CAPABILITY_SELF_ORCHESTRATION_REQUIRED, CONFIG_DELEGATION_ENTRY_CAPS, CONFIG_LEGACY_TOOL_NAME, CONFIG_LIMIT_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_MEMORY_PROJECT_KEY_SPELLING, CONFIG_MEMORY_WRITE_SCOPE_MISMATCH, CONFIG_REFUSAL_CODES, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CORRUPT_SESSION_ERROR_CODE, DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_PARK_MOVED_CODES, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, DELEGATION_CAP_CODES, DELEGATION_CONCURRENCY_CAP, DELEGATION_SESSION_CAP, delegationCapDispositionOf, DRAINING_ERROR_CODE, ENGINE_STOP_REASONS, engineStopReasonToCc, ENV_LIFETIME_EXPIRED, GATE_PARKED_ERROR_CODE, isConfigRefusalCode, isCorruptSessionCode, isDecideParkMovedCode, isDelegationCapCode, isInterruptedToolEndCode, isLimitsExceededCode, isRewindFamilyCode, isStatusDerivedCoarseCode, isWorkflowParkRefusalCode, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, MCP_SERVER_REVOKED, MODEL_FALLBACK_INHERIT_NO_TIER_BINDING, OUTPUT_INVALID, PARKED_RESUME_STARTUP_FAILED, RESUME_AT_ERROR_CODE_PREFIX, RESUME_CONTEXT_UNAVAILABLE, RESUME_ENV_FAILED, RESUME_PLACEMENT_MISMATCH, RESUME_POLICY_FOLD_CODE, RESUME_PREFLIGHT_REJECTED, RESUME_REOPEN_CODES, RESUME_RETRY_LATER_CODES, RESUME_TOOL_CONTRACT_MISMATCH, RESUME_TOOL_UNAVAILABLE, RESUME_USAGE_WINDOW_EXHAUSTED, REWIND_ERROR_CODE_PREFIXES, SCENARIO_NOT_ALLOWED_ERROR_CODE, STATUS_DERIVED_COARSE_CODES, STOP_CONFLICT_CODES, STREAM_MAX_DURATION, TOOL_END_INTERRUPTED_NEVER_STARTED, TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN, USAGE_WINDOW_EXHAUSTED, WORKFLOW_PARK_REFUSAL_CODES, } from './engineErrorCodes.js';
75
+ export { ACTIVE_RUN_BUSY_ERROR_CODE, asModelFallbackReason, CAPABILITY_SELF_ORCHESTRATION_REQUIRED, CONFIG_DELEGATION_ENTRY_CAPS, CONFIG_LEGACY_TOOL_NAME, CONFIG_LIMIT_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_MEMORY_PROJECT_KEY_SPELLING, CONFIG_MEMORY_WRITE_SCOPE_MISMATCH, CONFIG_REFUSAL_CODES, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CORRUPT_SESSION_ERROR_CODE, DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_PARK_MOVED_CODES, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, DELEGATION_CAP_CODES, DELEGATION_CONCURRENCY_CAP, DELEGATION_SESSION_CAP, delegationCapDispositionOf, DRAINING_ERROR_CODE, ENGINE_STOP_REASONS, engineStopReasonToCc, ENV_LIFETIME_EXPIRED, FLEET_LEASE_UNAVAILABLE, GATE_PARKED_ERROR_CODE, isConfigRefusalCode, isCorruptSessionCode, isDecideParkMovedCode, isDelegationCapCode, isInterruptedToolEndCode, isLimitsExceededCode, isRewindFamilyCode, isRulesRefusalCode, isStatusDerivedCoarseCode, isWorkflowParkRefusalCode, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, MCP_SERVER_REVOKED, MODEL_FALLBACK_INHERIT_NO_TIER_BINDING, OUTPUT_INVALID, PARKED_RESUME_STARTUP_FAILED, RESUME_AT_ERROR_CODE_PREFIX, RESUME_CONTEXT_UNAVAILABLE, RESUME_ENV_FAILED, RESUME_PLACEMENT_MISMATCH, RESUME_POLICY_FOLD_CODE, RESUME_PREFLIGHT_REJECTED, RESUME_REOPEN_CODES, RESUME_RETRY_LATER_CODES, RESUME_TOOL_CONTRACT_MISMATCH, RESUME_TOOL_UNAVAILABLE, RESUME_USAGE_WINDOW_EXHAUSTED, REWIND_ERROR_CODE_PREFIXES, RULES_LEGACY_TOOL_NAME, SCENARIO_NOT_ALLOWED_ERROR_CODE, STATUS_DERIVED_COARSE_CODES, STOP_CONFLICT_CODES, STREAM_MAX_DURATION, TOOL_END_INTERRUPTED_NEVER_STARTED, TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN, USAGE_WINDOW_EXHAUSTED, WORKFLOW_PARK_REFUSAL_CODES, } from './engineErrorCodes.js';
76
76
  export type { DelegationCapDisposition, ModelFallbackReason, } from './engineErrorCodes.js';
77
77
  export * from './agentsWireCaps.js';
78
78
  export * from './attachmentsWireCaps.js';
@@ -90,6 +90,8 @@ export * from './rewindWireCaps.js';
90
90
  export * from './rewindArchiveCapability.js';
91
91
  export * from './fileHistoryCaptureCapability.js';
92
92
  export * from './sealedKeyCapability.js';
93
+ export * from './storePostureCapability.js';
94
+ export * from './centerWiringCapability.js';
93
95
  export * from './registryQuotaUsage.js';
94
96
  export * from './selfOrchestrationWireCaps.js';
95
97
  export * from './skillsWireCaps.js';
@@ -145,6 +147,7 @@ export * from './corruptSession.js';
145
147
  export * from './corruptSessionCopy.js';
146
148
  export * from './resumeRefusalCopy.js';
147
149
  export * from './wireRefusalCopy.js';
150
+ export * from './inheritEnvWire.js';
148
151
  export * from './decideReceipt.js';
149
152
  export * from './sessionMap.js';
150
153
  export * from './detachWire.js';
@@ -189,6 +192,7 @@ export * from './request/printNotification.js';
189
192
  export * from './seatContract.js';
190
193
  export * from './agentSession/contract.js';
191
194
  export * from './agentSession/backgroundView.js';
195
+ export { READ_CREDENTIAL_NOT_ACCEPTED_NOTICE } from './readCredentialRefusal.js';
192
196
  export { readEngineAgentRegistry, isEngineAgentRegistryListingSuperseded } from './agentSession/engineAgentRegistryRead.js';
193
197
  export type { EngineAgentRegistryClient } from './agentSession/engineAgentRegistryRead.js';
194
198
  export { stopEngineSessionBackground, engineSessionBackgroundReceiptReadingOf, ENGINE_SESSION_BACKGROUND_RECEIPT_STATES, } from './agentSession/engineSessionBackgroundStop.js';
package/dist/index.js CHANGED
@@ -65,7 +65,7 @@ export * from './engineWireSdk.js';
65
65
  export * from './classifierVerdictWire.js';
66
66
  export { stripSystemReminderBlocks, unwrapSystemReminder } from './systemReminderTag.js';
67
67
  export { findSystemReminderOpenTag } from './systemReminderTag.js';
68
- export { ACTIVE_RUN_BUSY_ERROR_CODE, asModelFallbackReason, CAPABILITY_SELF_ORCHESTRATION_REQUIRED, CONFIG_DELEGATION_ENTRY_CAPS, CONFIG_LEGACY_TOOL_NAME, CONFIG_LIMIT_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_MEMORY_PROJECT_KEY_SPELLING, CONFIG_MEMORY_WRITE_SCOPE_MISMATCH, CONFIG_REFUSAL_CODES, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CORRUPT_SESSION_ERROR_CODE, DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_PARK_MOVED_CODES, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, DELEGATION_CAP_CODES, DELEGATION_CONCURRENCY_CAP, DELEGATION_SESSION_CAP, delegationCapDispositionOf, DRAINING_ERROR_CODE, ENGINE_STOP_REASONS, engineStopReasonToCc, ENV_LIFETIME_EXPIRED, GATE_PARKED_ERROR_CODE, isConfigRefusalCode, isCorruptSessionCode, isDecideParkMovedCode, isDelegationCapCode, isInterruptedToolEndCode, isLimitsExceededCode, isRewindFamilyCode, isStatusDerivedCoarseCode, isWorkflowParkRefusalCode, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, MCP_SERVER_REVOKED, MODEL_FALLBACK_INHERIT_NO_TIER_BINDING, OUTPUT_INVALID, PARKED_RESUME_STARTUP_FAILED, RESUME_AT_ERROR_CODE_PREFIX, RESUME_CONTEXT_UNAVAILABLE, RESUME_ENV_FAILED, RESUME_PLACEMENT_MISMATCH, RESUME_POLICY_FOLD_CODE, RESUME_PREFLIGHT_REJECTED, RESUME_REOPEN_CODES, RESUME_RETRY_LATER_CODES, RESUME_TOOL_CONTRACT_MISMATCH, RESUME_TOOL_UNAVAILABLE, RESUME_USAGE_WINDOW_EXHAUSTED, REWIND_ERROR_CODE_PREFIXES, SCENARIO_NOT_ALLOWED_ERROR_CODE, STATUS_DERIVED_COARSE_CODES, STOP_CONFLICT_CODES, STREAM_MAX_DURATION, TOOL_END_INTERRUPTED_NEVER_STARTED, TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN, USAGE_WINDOW_EXHAUSTED, WORKFLOW_PARK_REFUSAL_CODES, } from './engineErrorCodes.js';
68
+ export { ACTIVE_RUN_BUSY_ERROR_CODE, asModelFallbackReason, CAPABILITY_SELF_ORCHESTRATION_REQUIRED, CONFIG_DELEGATION_ENTRY_CAPS, CONFIG_LEGACY_TOOL_NAME, CONFIG_LIMIT_INVALID, CONFIG_LIMIT_UNKNOWN_KEY, CONFIG_MEMORY_PROJECT_KEY_SPELLING, CONFIG_MEMORY_WRITE_SCOPE_MISMATCH, CONFIG_REFUSAL_CODES, CONFIG_STRATEGY_FIND_LIMIT_INVALID, CONFIG_STRATEGY_MAX_SIZE_INVALID, CORRUPT_SESSION_ERROR_CODE, DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_PARK_MOVED_CODES, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, DELEGATION_CAP_CODES, DELEGATION_CONCURRENCY_CAP, DELEGATION_SESSION_CAP, delegationCapDispositionOf, DRAINING_ERROR_CODE, ENGINE_STOP_REASONS, engineStopReasonToCc, ENV_LIFETIME_EXPIRED, FLEET_LEASE_UNAVAILABLE, GATE_PARKED_ERROR_CODE, isConfigRefusalCode, isCorruptSessionCode, isDecideParkMovedCode, isDelegationCapCode, isInterruptedToolEndCode, isLimitsExceededCode, isRewindFamilyCode, isRulesRefusalCode, isStatusDerivedCoarseCode, isWorkflowParkRefusalCode, LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, MCP_SERVER_REVOKED, MODEL_FALLBACK_INHERIT_NO_TIER_BINDING, OUTPUT_INVALID, PARKED_RESUME_STARTUP_FAILED, RESUME_AT_ERROR_CODE_PREFIX, RESUME_CONTEXT_UNAVAILABLE, RESUME_ENV_FAILED, RESUME_PLACEMENT_MISMATCH, RESUME_POLICY_FOLD_CODE, RESUME_PREFLIGHT_REJECTED, RESUME_REOPEN_CODES, RESUME_RETRY_LATER_CODES, RESUME_TOOL_CONTRACT_MISMATCH, RESUME_TOOL_UNAVAILABLE, RESUME_USAGE_WINDOW_EXHAUSTED, REWIND_ERROR_CODE_PREFIXES, RULES_LEGACY_TOOL_NAME, SCENARIO_NOT_ALLOWED_ERROR_CODE, STATUS_DERIVED_COARSE_CODES, STOP_CONFLICT_CODES, STREAM_MAX_DURATION, TOOL_END_INTERRUPTED_NEVER_STARTED, TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN, USAGE_WINDOW_EXHAUSTED, WORKFLOW_PARK_REFUSAL_CODES, } from './engineErrorCodes.js';
69
69
  export * from './agentsWireCaps.js';
70
70
  export * from './attachmentsWireCaps.js';
71
71
  export * from './clientContextWireCaps.js';
@@ -82,6 +82,8 @@ export * from './rewindWireCaps.js';
82
82
  export * from './rewindArchiveCapability.js';
83
83
  export * from './fileHistoryCaptureCapability.js';
84
84
  export * from './sealedKeyCapability.js';
85
+ export * from './storePostureCapability.js';
86
+ export * from './centerWiringCapability.js';
85
87
  export * from './registryQuotaUsage.js';
86
88
  export * from './selfOrchestrationWireCaps.js';
87
89
  export * from './skillsWireCaps.js';
@@ -133,6 +135,7 @@ export * from './corruptSession.js';
133
135
  export * from './corruptSessionCopy.js';
134
136
  export * from './resumeRefusalCopy.js';
135
137
  export * from './wireRefusalCopy.js';
138
+ export * from './inheritEnvWire.js';
136
139
  export * from './decideReceipt.js';
137
140
  export * from './sessionMap.js';
138
141
  export * from './detachWire.js';
@@ -175,6 +178,7 @@ export * from './request/printNotification.js';
175
178
  export * from './seatContract.js';
176
179
  export * from './agentSession/contract.js';
177
180
  export * from './agentSession/backgroundView.js';
181
+ export { READ_CREDENTIAL_NOT_ACCEPTED_NOTICE } from './readCredentialRefusal.js';
178
182
  export { readEngineAgentRegistry, isEngineAgentRegistryListingSuperseded } from './agentSession/engineAgentRegistryRead.js';
179
183
  export { stopEngineSessionBackground, engineSessionBackgroundReceiptReadingOf, ENGINE_SESSION_BACKGROUND_RECEIPT_STATES, } from './agentSession/engineSessionBackgroundStop.js';
180
184
  export * from './model/catalog.js';
@@ -0,0 +1,22 @@
1
+ import { type InheritEnvWord, type TaskRequestLike } from './request/taskRequest.js';
2
+ export declare const INHERIT_ENV_MIN_SERVER: readonly [number, number, number];
3
+ export type InheritEnvServerSupport = 'supported' | 'unsupported' | 'unknown';
4
+ export declare function inheritEnvServerSupport(version: string | undefined): InheritEnvServerSupport;
5
+ export type InheritEnvWithheldCause = 'server_version_unknown' | 'server_too_old';
6
+ export interface InheritEnvWithheld {
7
+ readonly cause: InheritEnvWithheldCause;
8
+ readonly word: InheritEnvWord;
9
+ }
10
+ export interface InheritEnvDeclaration {
11
+ readonly field: {
12
+ readonly inheritEnv?: InheritEnvWord;
13
+ };
14
+ readonly withheld?: InheritEnvWithheld;
15
+ }
16
+ export declare function inheritEnvDeclaration(word: unknown, serverVersion: string | undefined): InheritEnvDeclaration;
17
+ export declare function inheritEnvWithheldNotice(withheld: InheritEnvWithheld): string;
18
+ export interface InheritEnvRefusalDetail {
19
+ readonly code: string;
20
+ }
21
+ export declare function inheritEnvRefusalFromError(err: unknown, sentRequest: TaskRequestLike | undefined): InheritEnvRefusalDetail | null;
22
+ export declare function inheritEnvRefusalContent(_detail: InheritEnvRefusalDetail): string;
@@ -0,0 +1,84 @@
1
+ import { INHERIT_ENV_WORDS, isInheritEnvWord } from './request/taskRequest.js';
2
+ import { settingsPermissionBucketRefusalFromError } from './wireRefusalCopy.js';
3
+ export const INHERIT_ENV_MIN_SERVER = Object.freeze([7, 106, 0]);
4
+ export function inheritEnvServerSupport(version) {
5
+ const mm = typeof version === 'string' ? /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.exec(version) : null;
6
+ if (!mm)
7
+ return 'unknown';
8
+ const got = [Number(mm[1]), Number(mm[2]), Number(mm[3])];
9
+ for (let i = 0; i < 3; i++) {
10
+ const g = got[i];
11
+ const need = INHERIT_ENV_MIN_SERVER[i];
12
+ if (g !== need)
13
+ return g > need ? 'supported' : 'unsupported';
14
+ }
15
+ return 'supported';
16
+ }
17
+ const EMPTY_DECLARATION = Object.freeze({ field: Object.freeze({}) });
18
+ export function inheritEnvDeclaration(word, serverVersion) {
19
+ if (word === undefined || word === null)
20
+ return EMPTY_DECLARATION;
21
+ if (!isInheritEnvWord(word)) {
22
+ throw new TypeError(`inheritEnvDeclaration: inheritEnv 只接受 ${INHERIT_ENV_WORDS.map((w) => `'${w}'`).join(' / ')} 或缺席 —— 收到 ${Array.isArray(word) ? 'typeof=object / array' : `typeof=${typeof word}`}。坏词在版本判定之前就拒:「这一次不发」不许顺手吞掉一个打错字的声明。错误文本只报形状,不回显值。`);
23
+ }
24
+ const support = inheritEnvServerSupport(serverVersion);
25
+ if (support === 'supported')
26
+ return Object.freeze({ field: Object.freeze({ inheritEnv: word }) });
27
+ const cause = support === 'unsupported' ? 'server_too_old' : 'server_version_unknown';
28
+ return Object.freeze({ field: Object.freeze({}), withheld: Object.freeze({ cause, word }) });
29
+ }
30
+ const WITHHELD_NOTICES = Object.freeze({
31
+ server_too_old: Object.freeze({
32
+ all: "Not sent with this request: this engine is too old to accept the setting that lets the shell inherit this machine's whole environment, so this run's shell gets the default environment, with credential-like variables removed.",
33
+ scrub: 'Not sent with this request: this engine is too old to accept the default-environment setting, so it was left out; that has the same effect, because the default environment (credential-like variables removed) is what this run gets anyway.',
34
+ }),
35
+ server_version_unknown: Object.freeze({
36
+ all: "Not sent with this request: the engine's version is not known yet, and an engine that does not know the setting that lets the shell inherit this machine's whole environment refuses the whole request, so it was held back; this run's shell gets the default environment, with credential-like variables removed, and on an engine that does know the setting, leaving it out also clears an earlier whole-environment choice for this session.",
37
+ scrub: "Not sent with this request: the engine's version is not known yet, so the default-environment setting was left out; that has the same effect, because leaving it out also gives this run the default environment (credential-like variables removed).",
38
+ }),
39
+ });
40
+ const WITHHELD_UNKNOWN_NOTICE = 'Not sent with this request: the shell-environment setting was held back for a reason this version does not recognize.';
41
+ export function inheritEnvWithheldNotice(withheld) {
42
+ try {
43
+ if (typeof withheld !== 'object' || withheld === null)
44
+ return WITHHELD_UNKNOWN_NOTICE;
45
+ const cause = withheld.cause;
46
+ const word = withheld.word;
47
+ if (typeof cause !== 'string' || !Object.hasOwn(WITHHELD_NOTICES, cause) || !isInheritEnvWord(word))
48
+ return WITHHELD_UNKNOWN_NOTICE;
49
+ return WITHHELD_NOTICES[cause][word];
50
+ }
51
+ catch {
52
+ return WITHHELD_UNKNOWN_NOTICE;
53
+ }
54
+ }
55
+ const FIELD_INVALID = 'request.field_invalid';
56
+ function readGuarded(o, key) {
57
+ if (typeof o !== 'object' || o === null)
58
+ return undefined;
59
+ try {
60
+ return o[key];
61
+ }
62
+ catch {
63
+ return undefined;
64
+ }
65
+ }
66
+ export function inheritEnvRefusalFromError(err, sentRequest) {
67
+ try {
68
+ if (readGuarded(sentRequest, 'inheritEnv') !== 'all')
69
+ return null;
70
+ if (readGuarded(err, 'errorCode') !== FIELD_INVALID)
71
+ return null;
72
+ if (settingsPermissionBucketRefusalFromError(err) !== null)
73
+ return null;
74
+ return Object.freeze({ code: FIELD_INVALID });
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ const REFUSAL_NOT_ACCEPTED = 'The engine refused this request as invalid without naming the field · ' +
81
+ "This request asked for the shell to inherit this machine's whole environment, which the engine accepts only when tools run directly on its own machine and the request belongs to a session; if that is what it refused, send it again without that setting (or with the default)";
82
+ export function inheritEnvRefusalContent(_detail) {
83
+ return REFUSAL_NOT_ACCEPTED;
84
+ }
@@ -1,4 +1,5 @@
1
1
  import { applyDisplayFace, LEGACY_NAME_FACE } from './displayUntrusted.js';
2
+ import { CORE_ENGINE_AUTHORITY_ENVELOPE_TAGS } from './generated/engineFactTables.js';
2
3
  const WIRE_KEY_FROM = 'from';
3
4
  const WIRE_KEY_BODY = 'body';
4
5
  const WIRE_KEY_KIND = 'kind';
@@ -107,16 +108,7 @@ export function classifyPeerNotification(n) {
107
108
  }
108
109
  return null;
109
110
  }
110
- const AUTHORITY_ENVELOPE_TAGS = Object.freeze([
111
- 'system-reminder',
112
- 'task-notification',
113
- 'new-diagnostics',
114
- 'user_memory',
115
- 'scope',
116
- 'skills',
117
- 'total_tokens',
118
- 'instruction-files',
119
- ]);
111
+ const AUTHORITY_ENVELOPE_TAGS = CORE_ENGINE_AUTHORITY_ENVELOPE_TAGS;
120
112
  const ZWSP = String.fromCharCode(0x200b);
121
113
  const AUTHORITY_BREAKOUT_RE = new RegExp(`<\\s*\\/?\\s*(?:${AUTHORITY_ENVELOPE_TAGS.map(t => t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|')})(?:\\s[^>]*)?>`, 'gi');
122
114
  function neutralizeAuthorityTags(text) {