@sema-agent/client-core 0.102.0 → 0.103.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 (95) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +8 -5
  3. package/dist/adapt/toolCards.d.ts +2 -1
  4. package/dist/adapt/toolCards.js +3 -1
  5. package/dist/adapter/downstream/eventToSdkMessage.d.ts +5 -1
  6. package/dist/adapter/downstream/eventToSdkMessage.js +21 -3
  7. package/dist/adapter/downstream/terminalToSdkResult.js +0 -1
  8. package/dist/adapter/downstream/wiringManifestView.js +4 -1
  9. package/dist/cloudConfigWireCaps.js +6 -3
  10. package/dist/credentialPlaneCapability.d.ts +22 -0
  11. package/dist/credentialPlaneCapability.js +75 -0
  12. package/dist/deviceExecutorManagementCapability.d.ts +1 -0
  13. package/dist/deviceExecutorManagementCapability.js +3 -1
  14. package/dist/engineErrorCodes.d.ts +1 -0
  15. package/dist/engineErrorCodes.js +3 -1
  16. package/dist/engineNoticeCodes.d.ts +26 -0
  17. package/dist/engineNoticeCodes.js +121 -12
  18. package/dist/engineRowRef.js +1 -0
  19. package/dist/errorSupplementRoles.js +1 -3
  20. package/dist/eventLeg.js +2 -1
  21. package/dist/fleet/fleetProjection.js +15 -9
  22. package/dist/gateOutcome.d.ts +20 -0
  23. package/dist/gateOutcome.js +89 -0
  24. package/dist/generated/engineAskFaceTables.js +2 -2
  25. package/dist/generated/engineFactTables.d.ts +6 -2
  26. package/dist/generated/engineFactTables.js +41 -1
  27. package/dist/generated/engineNoticeTables.js +18 -0
  28. package/dist/generated/settingsSchemaDefaultModel.d.ts +1 -1
  29. package/dist/generated/settingsSchemaDefaultModel.js +2 -2
  30. package/dist/generated/settingsSchemaFns.d.ts +15 -0
  31. package/dist/generated/settingsSchemaFns.js +25 -2
  32. package/dist/generated/settingsSchemaHooksClassifier.js +109 -29
  33. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
  34. package/dist/generated/settingsSchemaMcpRequestEntry.js +213 -93
  35. package/dist/generated/settingsSchemaMcpServerName.d.ts +1 -0
  36. package/dist/generated/settingsSchemaMcpServerName.js +8 -0
  37. package/dist/generated/settingsSchemaOwnKeyRead.d.ts +1 -0
  38. package/dist/generated/settingsSchemaOwnKeyRead.js +172 -0
  39. package/dist/generated/settingsSchemaPlainJsonObject.d.ts +1 -0
  40. package/dist/generated/settingsSchemaPlainJsonObject.js +28 -0
  41. package/dist/generated/settingsSchemaSafetyMergeSpec.js +10 -7
  42. package/dist/generated/settingsSchemaTierWords.d.ts +1 -0
  43. package/dist/generated/settingsSchemaTierWords.js +7 -0
  44. package/dist/generated/settingsSchemaTypes.d.ts +3 -1
  45. package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
  46. package/dist/hitl/decisionConflict.js +11 -11
  47. package/dist/hitl/decisionRefusal.d.ts +1 -0
  48. package/dist/hitl/decisionRefusal.js +4 -2
  49. package/dist/hitl/editedRuleTextPrecheck.d.ts +1 -0
  50. package/dist/hitl/editedRuleTextPrecheck.js +26 -1
  51. package/dist/hitl/persistedRulesWire.js +1 -0
  52. package/dist/hitl/planReviewWire.d.ts +2 -1
  53. package/dist/hitl/planReviewWire.js +8 -12
  54. package/dist/hitl/sessionPolicyDeliverable.d.ts +0 -1
  55. package/dist/hitl/sessionPolicyDeliverable.js +0 -5
  56. package/dist/hitl/sessionPolicyWire.js +1 -1
  57. package/dist/hitl/toolApprovalWire.d.ts +18 -6
  58. package/dist/hitl/toolApprovalWire.js +9 -4
  59. package/dist/i18n/messages.en.d.ts +5 -0
  60. package/dist/i18n/messages.en.js +6 -1
  61. package/dist/i18n/messages.zh.js +6 -1
  62. package/dist/index.d.ts +3 -2
  63. package/dist/index.js +2 -1
  64. package/dist/inheritEnvWire.d.ts +1 -0
  65. package/dist/inheritEnvWire.js +8 -5
  66. package/dist/mcpEngineLeg.d.ts +3 -0
  67. package/dist/mcpEngineLeg.js +4 -1
  68. package/dist/mcpLiveness.d.ts +18 -0
  69. package/dist/mcpLiveness.js +48 -1
  70. package/dist/mcpReconnect.d.ts +3 -0
  71. package/dist/mcpReconnect.js +6 -0
  72. package/dist/mcpStatusSupersetKeys.js +24 -1
  73. package/dist/mcpWireCaps.d.ts +2 -3
  74. package/dist/mcpWireCaps.js +9 -8
  75. package/dist/memoryEntriesWire.d.ts +35 -1
  76. package/dist/memoryEntriesWire.js +110 -14
  77. package/dist/modsFace.js +7 -3
  78. package/dist/postureKnob.js +1 -1
  79. package/dist/prepareRefusal.d.ts +0 -1
  80. package/dist/prepareRefusal.js +0 -3
  81. package/dist/promptProfileWireCaps.d.ts +1 -3
  82. package/dist/promptProfileWireCaps.js +2 -2
  83. package/dist/request/taskRequest.d.ts +1 -1
  84. package/dist/request/taskRequest.js +3 -3
  85. package/dist/retryStatus.d.ts +13 -1
  86. package/dist/retryStatus.js +20 -5
  87. package/dist/seatContract.js +10 -0
  88. package/dist/sessionMemoryErase.js +24 -2
  89. package/dist/turnFailurePresentation.js +8 -1
  90. package/dist/wireFailureShape.d.ts +12 -1
  91. package/dist/wireFailureShape.js +58 -24
  92. package/dist/wireRefusalCopy.d.ts +0 -3
  93. package/dist/wireRefusalCopy.js +0 -17
  94. package/docs/INTEGRATION-CLIENTS.md +155 -10
  95. package/package.json +5 -5
@@ -7,6 +7,6 @@ export const CORE_SHELL_FACE_TOOL_NAMES = Object.freeze([
7
7
  "Monitor",
8
8
  ]);
9
9
  export const CORE_RELEASABLE_ASK_CLASSES_BY_FACE = Object.freeze({
10
- "shell": Object.freeze(["transcript_write", "target_unresolved", "probe", "write_protection", "tool_marks_mcp", "tool_marks_a2a", "artifact_shared_read", "mode", "unstated", "ordinary"]),
11
- "other": Object.freeze(["transcript_write", "probe", "write_protection", "tool_marks_mcp", "tool_marks_a2a", "artifact_shared_read", "mode", "unstated", "ordinary"]),
10
+ "shell": Object.freeze(["transcript_write", "target_unresolved", "probe", "write_protection_on_disk", "write_protection", "tool_marks_mcp", "tool_marks_a2a", "artifact_shared_read", "mode", "unstated", "ordinary"]),
11
+ "other": Object.freeze(["transcript_write", "probe", "write_protection_on_disk", "write_protection", "tool_marks_mcp", "tool_marks_a2a", "artifact_shared_read", "mode", "unstated", "ordinary"]),
12
12
  });
@@ -14,7 +14,7 @@ export declare const CORE_ASK_EVIDENCE_ABSENCE_VALUES: readonly ["not_wired", "n
14
14
  export declare const CORE_SYSTEM_INJECTION_PRIORITIES: readonly ["now", "next", "later"];
15
15
  export declare const CORE_READ_DENY_BUILTIN_TIERS: readonly ["credentials", "shell-history", "browser", "wallet", "agent-config"];
16
16
  export declare const CORE_READ_DENY_DEFAULT_TIERS: readonly ["credentials", "agent-config"];
17
- export declare const CORE_ASK_CLASSES: readonly ["content_question", "hook", "ancestor", "dangerous_delete", "unverifiable_delete", "unverifiable_shell_text", "transcript_write", "org_rule", "rule_unreadable", "ask_rule", "denial_limit_fallback", "classifier_no_ruling", "requires_user_interaction", "cross_boundary", "operator_forced", "shell_floor", "target_unresolved", "probe", "write_protection", "tool_marks_mcp", "tool_marks_a2a", "policy_rra", "artifact_shared_read", "mode", "unstated", "ordinary"];
17
+ export declare const CORE_ASK_CLASSES: readonly ["content_question", "hook", "ancestor", "dangerous_delete", "unverifiable_delete", "unverifiable_shell_text", "transcript_write", "org_rule", "rule_unreadable", "ask_rule", "denial_limit_fallback", "classifier_no_ruling", "requires_user_interaction", "cross_boundary", "operator_forced", "shell_floor", "target_unresolved", "probe", "write_protection_on_disk", "write_protection", "tool_marks_mcp", "tool_marks_a2a", "policy_rra", "artifact_shared_read", "mode", "unstated", "ordinary"];
18
18
  export interface CoreModeArbitrationRow {
19
19
  readonly bypassImmune: boolean;
20
20
  readonly classifierEligible: boolean;
@@ -22,7 +22,7 @@ export interface CoreModeArbitrationRow {
22
22
  readonly ruleMayClear: boolean;
23
23
  readonly hookAskFloor: boolean;
24
24
  }
25
- export declare const CORE_MODE_ARBITRATION: Readonly<Record<"content_question" | "hook" | "ancestor" | "dangerous_delete" | "unverifiable_delete" | "unverifiable_shell_text" | "transcript_write" | "org_rule" | "rule_unreadable" | "ask_rule" | "denial_limit_fallback" | "classifier_no_ruling" | "requires_user_interaction" | "cross_boundary" | "operator_forced" | "shell_floor" | "target_unresolved" | "probe" | "write_protection" | "tool_marks_mcp" | "tool_marks_a2a" | "policy_rra" | "artifact_shared_read" | "mode" | "unstated" | "ordinary", CoreModeArbitrationRow>>;
25
+ export declare const CORE_MODE_ARBITRATION: Readonly<Record<"content_question" | "hook" | "ancestor" | "dangerous_delete" | "unverifiable_delete" | "unverifiable_shell_text" | "transcript_write" | "org_rule" | "rule_unreadable" | "ask_rule" | "denial_limit_fallback" | "classifier_no_ruling" | "requires_user_interaction" | "cross_boundary" | "operator_forced" | "shell_floor" | "target_unresolved" | "probe" | "write_protection_on_disk" | "write_protection" | "tool_marks_mcp" | "tool_marks_a2a" | "policy_rra" | "artifact_shared_read" | "mode" | "unstated" | "ordinary", CoreModeArbitrationRow>>;
26
26
  export declare const CORE_SKILL_GRANT_ORIGINS: readonly ["model", "user", "inherited"];
27
27
  export declare const CORE_ALLOW_ENTRY_INERT_REASONS: readonly ["wildcard_all", "namespace_wildcard", "content_unsupported", "grammar", "tool_name", "near_miss", "earlier_grammar"];
28
28
  export declare const CORE_ALLOW_RULE_MEMBERS: readonly ["hook", "deployment", "persisted", "skill", "request"];
@@ -48,6 +48,10 @@ export declare const CORE_RESUME_STARTUP_CAUSES: readonly ["environment", "sessi
48
48
  export declare const CORE_BUILTIN_SUBAGENT_TYPES: readonly ["Explore", "Plan", "fork", "general-purpose"];
49
49
  export declare const CORE_RULE_OFFERS_ABSENCES: readonly ["mandated", "allow_outranked", "ask_rule_matched", "lane_cannot_speak"];
50
50
  export declare const CORE_TOOL_APPROVAL_CARDS: readonly ["file-edit", "file-write", "notebook-edit", "shell", "fetch", "skill", "workflow", "plan", "question", "generic"];
51
+ export declare const CORE_MCP_FAILURE_KINDS: readonly ["connect_refused", "connection_failed", "connection_closed", "unauthorized", "http_status", "not_mcp_response", "spawn_failed", "timeout", "protocol", "invalid_config", "credential_unavailable", "unknown"];
52
+ export declare const CORE_MCP_AUTHORIZATION_REASONS: readonly ["rejected", "scope", "none"];
53
+ export declare const CORE_PERSISTED_RULE_MATCHES: readonly ["exact", "prefix", "wildcard", "pattern", "subpath", "path", "name", "name_prefix", "host", "subdomain", "tool"];
54
+ export declare const CORE_APPROVAL_REMEDY_KINDS: readonly ["approver", "permission_mode"];
51
55
  export declare const CORE_ASK_CLASSES_WITHOUT_REASON_ROW: readonly ["probe"];
52
56
  export declare const CORE_ASK_CLASS_REASONS: Readonly<Record<Exclude<(typeof CORE_ASK_CLASSES)[number], (typeof CORE_ASK_CLASSES_WITHOUT_REASON_ROW)[number]>, string>>;
53
57
  export declare const CORE_USER_ATTACHMENT_KINDS: readonly ["text", "notebook", "image", "pdf", "directory", "client_text", "client_image"];
@@ -59,6 +59,7 @@ export const CORE_ENGINE_CARD_TYPES = Object.freeze([
59
59
  "read_path_denied",
60
60
  "readonly_out_of_root",
61
61
  "read_unestablished",
62
+ "bash_self_kill_refused",
62
63
  "text",
63
64
  "notebook",
64
65
  "file_unchanged",
@@ -160,6 +161,7 @@ export const CORE_ASK_CLASSES = Object.freeze([
160
161
  "shell_floor",
161
162
  "target_unresolved",
162
163
  "probe",
164
+ "write_protection_on_disk",
163
165
  "write_protection",
164
166
  "tool_marks_mcp",
165
167
  "tool_marks_a2a",
@@ -188,6 +190,7 @@ export const CORE_MODE_ARBITRATION = Object.freeze({
188
190
  "shell_floor": Object.freeze({ bypassImmune: true, classifierEligible: true, sandboxAdmission: true, ruleMayClear: false, hookAskFloor: false }),
189
191
  "target_unresolved": Object.freeze({ bypassImmune: true, classifierEligible: false, sandboxAdmission: true, ruleMayClear: false, hookAskFloor: true }),
190
192
  "probe": Object.freeze({ bypassImmune: false, classifierEligible: true, sandboxAdmission: false, ruleMayClear: false, hookAskFloor: false }),
193
+ "write_protection_on_disk": Object.freeze({ bypassImmune: false, classifierEligible: false, sandboxAdmission: true, ruleMayClear: false, hookAskFloor: true }),
191
194
  "write_protection": Object.freeze({ bypassImmune: false, classifierEligible: true, sandboxAdmission: true, ruleMayClear: false, hookAskFloor: true }),
192
195
  "tool_marks_mcp": Object.freeze({ bypassImmune: false, classifierEligible: true, sandboxAdmission: true, ruleMayClear: false, hookAskFloor: false }),
193
196
  "tool_marks_a2a": Object.freeze({ bypassImmune: false, classifierEligible: true, sandboxAdmission: true, ruleMayClear: false, hookAskFloor: false }),
@@ -349,12 +352,48 @@ export const CORE_TOOL_APPROVAL_CARDS = Object.freeze([
349
352
  "question",
350
353
  "generic",
351
354
  ]);
355
+ export const CORE_MCP_FAILURE_KINDS = Object.freeze([
356
+ "connect_refused",
357
+ "connection_failed",
358
+ "connection_closed",
359
+ "unauthorized",
360
+ "http_status",
361
+ "not_mcp_response",
362
+ "spawn_failed",
363
+ "timeout",
364
+ "protocol",
365
+ "invalid_config",
366
+ "credential_unavailable",
367
+ "unknown",
368
+ ]);
369
+ export const CORE_MCP_AUTHORIZATION_REASONS = Object.freeze([
370
+ "rejected",
371
+ "scope",
372
+ "none",
373
+ ]);
374
+ export const CORE_PERSISTED_RULE_MATCHES = Object.freeze([
375
+ "exact",
376
+ "prefix",
377
+ "wildcard",
378
+ "pattern",
379
+ "subpath",
380
+ "path",
381
+ "name",
382
+ "name_prefix",
383
+ "host",
384
+ "subdomain",
385
+ "tool",
386
+ ]);
387
+ export const CORE_APPROVAL_REMEDY_KINDS = Object.freeze([
388
+ "approver",
389
+ "permission_mode",
390
+ ]);
352
391
  export const CORE_ASK_CLASSES_WITHOUT_REASON_ROW = Object.freeze([
353
392
  "probe",
354
393
  ]);
355
394
  export const CORE_ASK_CLASS_REASONS = Object.freeze({
356
395
  "content_question": "the call is the engine's own question to a person",
357
- "hook": "a PreToolUse hook asks about this call — the deployment's own screening is answered by a person",
396
+ "hook": "an extension's screening asks about this call (a PreToolUse hook or a tool.check station) — the deployment's own screening is answered by a person",
358
397
  "ancestor": "the task that delegated this one owns this question",
359
398
  "dangerous_delete": "this removal targets a protected location (the filesystem root, a top-level directory, a home directory, or a workspace directory or one of its ancestors) — it is cleared by confirming this call, never by an allow rule",
360
399
  "unverifiable_delete": "this removal could not be verified safe — it is cleared by confirming this call, never by an allow rule",
@@ -370,6 +409,7 @@ export const CORE_ASK_CLASS_REASONS = Object.freeze({
370
409
  "operator_forced": "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule",
371
410
  "shell_floor": "this deployment mandates per-call confirmation for shell commands (shellGate: always)",
372
411
  "target_unresolved": "where this write leads on disk could not be determined (a link on the way could not be examined, or the environment could not resolve the target), so whether it lands on a guarded path is unknown — it is cleared by confirming this call: no standing rule and no automatic decider answers for it, though a wired approver seat can",
412
+ "write_protection_on_disk": "this write's target is on the deployment's write-protection table (the agent's own configuration is guarded one look per write) — it is cleared by confirming this call, never by a standing allow rule",
373
413
  "write_protection": "this write's target is on the deployment's write-protection table (the agent's own configuration is guarded one look per write) — it is cleared by confirming this call, never by a standing allow rule",
374
414
  "tool_marks_mcp": "this tool carries egress/irreversibility/interaction marks (a mandated confirmation a rule cannot clear)",
375
415
  "tool_marks_a2a": "this tool carries egress/irreversibility/interaction marks (a mandated confirmation a rule cannot clear)",
@@ -25,6 +25,7 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
25
25
  "config.peer_admission_out_of_range",
26
26
  "config.peer_lane_unmounted",
27
27
  "config.secret_env_scrubbed",
28
+ "inherit_env.names_withheld",
28
29
  "config.credential_not_withheld",
29
30
  "config.cross_boundary_posture_undeclared",
30
31
  "config.cross_boundary_record_unwritten",
@@ -50,6 +51,7 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
50
51
  "mcp.injection_dropped",
51
52
  "mcp.revocation_probe_failed",
52
53
  "mcp.server_redialed",
54
+ "mcp.authorization_required",
53
55
  "workflow.governance_key_stripped",
54
56
  "workflow.agent_option_ignored",
55
57
  "memory.session_polluted",
@@ -72,12 +74,16 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
72
74
  "route.seat_detached",
73
75
  "advisor.not_attached",
74
76
  "route.credential_origin_mismatch",
77
+ "route.credential_rebound",
75
78
  "route.response_model_mismatch",
76
79
  "route.tool_call_id_folded",
77
80
  "route.finish_reason_unknown",
78
81
  "route.stream_end_ignored",
79
82
  "route.extra_body_reserved_dropped",
83
+ "model.capability_downgraded",
84
+ "model.role_defaulted",
80
85
  "context.tool_turn_repaired",
86
+ "context.image_removed",
81
87
  "task.user_steer_undrained",
82
88
  "task.user_followup_undrained",
83
89
  "steering.parked_input_blocked",
@@ -127,6 +133,7 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
127
133
  "config.peer_admission_out_of_range": "operator",
128
134
  "config.peer_lane_unmounted": "operator",
129
135
  "config.secret_env_scrubbed": "operator",
136
+ "inherit_env.names_withheld": "user",
130
137
  "config.credential_not_withheld": "operator",
131
138
  "config.cross_boundary_posture_undeclared": "operator",
132
139
  "config.cross_boundary_record_unwritten": "operator",
@@ -152,6 +159,7 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
152
159
  "mcp.injection_dropped": "user",
153
160
  "mcp.revocation_probe_failed": "operator",
154
161
  "mcp.server_redialed": "operator",
162
+ "mcp.authorization_required": "user",
155
163
  "workflow.governance_key_stripped": "operator",
156
164
  "workflow.agent_option_ignored": "operator",
157
165
  "memory.session_polluted": "user",
@@ -174,12 +182,16 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
174
182
  "route.seat_detached": "operator",
175
183
  "advisor.not_attached": "user",
176
184
  "route.credential_origin_mismatch": "user",
185
+ "route.credential_rebound": "operator",
177
186
  "route.response_model_mismatch": "operator",
178
187
  "route.tool_call_id_folded": "operator",
179
188
  "route.finish_reason_unknown": "user",
180
189
  "route.stream_end_ignored": "user",
181
190
  "route.extra_body_reserved_dropped": "operator",
191
+ "model.capability_downgraded": "user",
192
+ "model.role_defaulted": "operator",
182
193
  "context.tool_turn_repaired": "operator",
194
+ "context.image_removed": "user",
183
195
  "task.user_steer_undrained": "user",
184
196
  "task.user_followup_undrained": "user",
185
197
  "steering.parked_input_blocked": "user",
@@ -235,6 +247,7 @@ export const CORE_NOTICE_MINTER = Object.freeze({
235
247
  "config.peer_admission_out_of_range": "engine",
236
248
  "config.peer_lane_unmounted": "engine",
237
249
  "config.secret_env_scrubbed": "engine",
250
+ "inherit_env.names_withheld": "engine",
238
251
  "config.credential_not_withheld": "engine",
239
252
  "config.cross_boundary_posture_undeclared": "engine",
240
253
  "config.cross_boundary_record_unwritten": "engine",
@@ -260,6 +273,7 @@ export const CORE_NOTICE_MINTER = Object.freeze({
260
273
  "mcp.injection_dropped": "engine",
261
274
  "mcp.revocation_probe_failed": "engine",
262
275
  "mcp.server_redialed": "engine",
276
+ "mcp.authorization_required": "engine",
263
277
  "workflow.governance_key_stripped": "engine",
264
278
  "workflow.agent_option_ignored": "engine",
265
279
  "memory.session_polluted": "engine",
@@ -282,12 +296,16 @@ export const CORE_NOTICE_MINTER = Object.freeze({
282
296
  "route.seat_detached": "engine",
283
297
  "advisor.not_attached": "engine",
284
298
  "route.credential_origin_mismatch": "engine",
299
+ "route.credential_rebound": "engine",
285
300
  "route.response_model_mismatch": "engine",
286
301
  "route.tool_call_id_folded": "engine",
287
302
  "route.finish_reason_unknown": "engine",
288
303
  "route.stream_end_ignored": "engine",
289
304
  "route.extra_body_reserved_dropped": "engine",
305
+ "model.capability_downgraded": "engine",
306
+ "model.role_defaulted": "engine",
290
307
  "context.tool_turn_repaired": "engine",
308
+ "context.image_removed": "engine",
291
309
  "task.user_steer_undrained": "engine",
292
310
  "task.user_followup_undrained": "engine",
293
311
  "steering.parked_input_blocked": "engine",
@@ -8,4 +8,4 @@ export declare const SETTINGS_DEFAULT_MODEL_CLOSURE: (resolveActiveTiers: (model
8
8
  readonly activeTierGroup?: string | undefined;
9
9
  }) => {
10
10
  [tier: string]: string;
11
- } | undefined) => any;
11
+ } | undefined, tierLadderFrom: (tier: string) => string[]) => any;
@@ -1,5 +1,5 @@
1
- export const SETTINGS_DEFAULT_MODEL_CLOSURE = (resolveActiveTiers) => {
2
- const DEFAULT_ROLE_TIER_LADDER = ["pro", "flash", "lite"];
1
+ export const SETTINGS_DEFAULT_MODEL_CLOSURE = (resolveActiveTiers, tierLadderFrom) => {
2
+ const DEFAULT_ROLE_TIER_LADDER = tierLadderFrom("pro");
3
3
  function resolveCatalogDefaultModel(models, has, fallback) {
4
4
  const target = models.roles?.default;
5
5
  const named = target !== undefined && "model" in target ? target.model : undefined;
@@ -22,6 +22,18 @@ export declare const SETTINGS_CLASSIFY_HOOKS_CONFIG: (settingsDoc: unknown) => H
22
22
  export declare const SETTINGS_STRIP_CONTROL_AND_BIDI: (text: string) => string;
23
23
  export declare const SETTINGS_CONTROL_AND_BIDI_CHARS: string;
24
24
  export declare const SETTINGS_ECHO_CALLER_TEXT: (text: string) => string;
25
+ export declare const SETTINGS_IS_JSON_ARRAY: (v: unknown) => v is unknown[];
26
+ export declare const SETTINGS_JSON_SHAPE_OF: (v: unknown) => "plain" | "non_plain_object" | "array" | "null" | "primitive" | "uninspectable";
27
+ export declare const SETTINGS_CAPTURE_STRING_ARRAY: (v: unknown, classification: "strict" | "wide") => string[] | undefined;
28
+ export declare const SETTINGS_UNINSPECTABLE: "an object that could not be inspected (a proxy trap threw)";
29
+ export declare const SETTINGS_DATA_DESCRIPTOR: (value: unknown) => PropertyDescriptor;
30
+ export declare const SETTINGS_INSPECT: (read: () => unknown) => object;
31
+ export declare const SETTINGS_OWN_FIELDS_OF: (record: object, keys: readonly string[]) => object;
32
+ export declare const SETTINGS_OWN_VALUE_OF: (record: object, key: string) => object;
33
+ export declare const SETTINGS_READ_KEY: (record: object, key: PropertyKey) => object;
34
+ export declare const SETTINGS_IS_RESERVED_MCP_SERVER_NAME: (name: string) => boolean;
35
+ export declare const SETTINGS_REMOTE_MCP_SERVER_NAME_PREFIX: "remote-";
36
+ export declare const SETTINGS_RESERVED_MCP_SERVER_NAME_REASON: "the \"remote-\" prefix is reserved for the remote MCP servers a device executor offers";
25
37
  export declare const SETTINGS_READ_REQUEST_MCP_TRANSPORT: (t: unknown) => RequestMcpTransportRead;
26
38
  export declare const SETTINGS_READ_MCP_IDENTITY_HEADERS: (transport: Record<string, unknown>) => {
27
39
  principalHeader?: string;
@@ -29,6 +41,8 @@ export declare const SETTINGS_READ_MCP_IDENTITY_HEADERS: (transport: Record<stri
29
41
  };
30
42
  export declare const SETTINGS_IS_USABLE_WIRE_NAME: (v: unknown) => v is string;
31
43
  export declare const SETTINGS_DESCRIBE_BAD_WIRE_NAME: (v: unknown) => string;
44
+ export declare const SETTINGS_IS_USABLE_MCP_SERVER_NAME: (v: unknown) => v is string;
45
+ export declare const SETTINGS_DESCRIBE_BAD_MCP_SERVER_NAME: (v: unknown) => string;
32
46
  export declare const SETTINGS_IS_CONTENT_ORIGIN_WORD: (v: unknown) => v is McpContentOrigin;
33
47
  export declare const SETTINGS_DESCRIBE_BAD_CONTENT_ORIGIN: (v: unknown) => string;
34
48
  export declare const SETTINGS_TOOL_WIRE_NAME_MAX_CHARS: 128;
@@ -48,6 +62,7 @@ export declare const SETTINGS_RESOLVE_ACTIVE_TIERS: (models: {
48
62
  }) => {
49
63
  [tier: string]: string;
50
64
  } | undefined;
65
+ export declare const SETTINGS_TIER_LADDER_FROM: (tier: string) => string[];
51
66
  export declare const SETTINGS_RESOLVE_CATALOG_DEFAULT_MODEL: (models: {
52
67
  readonly roles?: {
53
68
  readonly default?: {
@@ -1,6 +1,9 @@
1
1
  import { SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE } from './settingsSchemaHooksClassifier.js';
2
2
  import { SETTINGS_CONTROL_AND_BIDI_CLOSURE } from './settingsSchemaControlAndBidi.js';
3
3
  import { SETTINGS_CALLER_TEXT_ECHO_CLOSURE } from './settingsSchemaCallerTextEcho.js';
4
+ import { SETTINGS_PLAIN_JSON_OBJECT_CLOSURE } from './settingsSchemaPlainJsonObject.js';
5
+ import { SETTINGS_OWN_KEY_READ_CLOSURE } from './settingsSchemaOwnKeyRead.js';
6
+ import { SETTINGS_MCP_SERVER_NAME_CLOSURE } from './settingsSchemaMcpServerName.js';
4
7
  import { SETTINGS_MCP_REQUEST_ENTRY_CLOSURE } from './settingsSchemaMcpRequestEntry.js';
5
8
  import { SETTINGS_MCP_CONTENT_ORIGINS } from './settingsSchemaTables.js';
6
9
  import { SETTINGS_URL_ALLOW_PATTERN_MATCHES_CLOSURE } from './settingsSchemaUrlPattern.js';
@@ -8,6 +11,7 @@ import { SETTINGS_SAFETY_MERGE_CLOSURE } from './settingsSchemaSafetyMergeSpec.j
8
11
  import { SETTINGS_MIN_TRUST_WORDS } from './settingsSchemaTables.js';
9
12
  import { SETTINGS_LAYER_SOURCES_CLOSURE } from './settingsSchemaSettingsSources.js';
10
13
  import { SETTINGS_ACTIVE_TIERS_CLOSURE } from './settingsSchemaActiveTiers.js';
14
+ import { SETTINGS_TIER_WORDS_CLOSURE } from './settingsSchemaTierWords.js';
11
15
  import { SETTINGS_DEFAULT_MODEL_CLOSURE } from './settingsSchemaDefaultModel.js';
12
16
  export const SETTINGS_AT_MENTION_MODES = Object.freeze([
13
17
  "all",
@@ -148,11 +152,28 @@ export const SETTINGS_STRIP_CONTROL_AND_BIDI = SETTINGS_CONTROL_AND_BIDI.stripCo
148
152
  export const SETTINGS_CONTROL_AND_BIDI_CHARS = SETTINGS_CONTROL_AND_BIDI.CONTROL_AND_BIDI_CHARS;
149
153
  const SETTINGS_CALLER_TEXT_ECHO = SETTINGS_CALLER_TEXT_ECHO_CLOSURE(SETTINGS_STRIP_CONTROL_AND_BIDI);
150
154
  export const SETTINGS_ECHO_CALLER_TEXT = SETTINGS_CALLER_TEXT_ECHO.echoCallerText;
151
- const SETTINGS_MCP_REQUEST_ENTRY = SETTINGS_MCP_REQUEST_ENTRY_CLOSURE(SETTINGS_MCP_CONTENT_ORIGINS, SETTINGS_STARTS_WITH_HTTP_SCHEME, SETTINGS_ECHO_CALLER_TEXT);
155
+ const SETTINGS_PLAIN_JSON_OBJECT = SETTINGS_PLAIN_JSON_OBJECT_CLOSURE();
156
+ export const SETTINGS_IS_JSON_ARRAY = SETTINGS_PLAIN_JSON_OBJECT.isJsonArray;
157
+ export const SETTINGS_JSON_SHAPE_OF = SETTINGS_PLAIN_JSON_OBJECT.jsonShapeOf;
158
+ const SETTINGS_OWN_KEY_READ = SETTINGS_OWN_KEY_READ_CLOSURE(SETTINGS_IS_JSON_ARRAY);
159
+ export const SETTINGS_CAPTURE_STRING_ARRAY = SETTINGS_OWN_KEY_READ.captureStringArray;
160
+ export const SETTINGS_UNINSPECTABLE = SETTINGS_OWN_KEY_READ.UNINSPECTABLE;
161
+ export const SETTINGS_DATA_DESCRIPTOR = SETTINGS_OWN_KEY_READ.dataDescriptor;
162
+ export const SETTINGS_INSPECT = SETTINGS_OWN_KEY_READ.inspect;
163
+ export const SETTINGS_OWN_FIELDS_OF = SETTINGS_OWN_KEY_READ.ownFieldsOf;
164
+ export const SETTINGS_OWN_VALUE_OF = SETTINGS_OWN_KEY_READ.ownValueOf;
165
+ export const SETTINGS_READ_KEY = SETTINGS_OWN_KEY_READ.readKey;
166
+ const SETTINGS_MCP_SERVER_NAME = SETTINGS_MCP_SERVER_NAME_CLOSURE();
167
+ export const SETTINGS_IS_RESERVED_MCP_SERVER_NAME = SETTINGS_MCP_SERVER_NAME.isReservedMcpServerName;
168
+ export const SETTINGS_REMOTE_MCP_SERVER_NAME_PREFIX = SETTINGS_MCP_SERVER_NAME.REMOTE_MCP_SERVER_NAME_PREFIX;
169
+ export const SETTINGS_RESERVED_MCP_SERVER_NAME_REASON = SETTINGS_MCP_SERVER_NAME.RESERVED_MCP_SERVER_NAME_REASON;
170
+ const SETTINGS_MCP_REQUEST_ENTRY = SETTINGS_MCP_REQUEST_ENTRY_CLOSURE(SETTINGS_MCP_CONTENT_ORIGINS, SETTINGS_STARTS_WITH_HTTP_SCHEME, SETTINGS_ECHO_CALLER_TEXT, SETTINGS_UNINSPECTABLE, SETTINGS_CAPTURE_STRING_ARRAY, SETTINGS_DATA_DESCRIPTOR, SETTINGS_INSPECT, SETTINGS_OWN_FIELDS_OF, SETTINGS_OWN_VALUE_OF, SETTINGS_READ_KEY, SETTINGS_IS_JSON_ARRAY, SETTINGS_JSON_SHAPE_OF, SETTINGS_IS_RESERVED_MCP_SERVER_NAME, SETTINGS_RESERVED_MCP_SERVER_NAME_REASON);
152
171
  export const SETTINGS_READ_REQUEST_MCP_TRANSPORT = SETTINGS_MCP_REQUEST_ENTRY.readRequestMcpTransport;
153
172
  export const SETTINGS_READ_MCP_IDENTITY_HEADERS = SETTINGS_MCP_REQUEST_ENTRY.readMcpIdentityHeaders;
154
173
  export const SETTINGS_IS_USABLE_WIRE_NAME = SETTINGS_MCP_REQUEST_ENTRY.isUsableWireName;
155
174
  export const SETTINGS_DESCRIBE_BAD_WIRE_NAME = SETTINGS_MCP_REQUEST_ENTRY.describeBadWireName;
175
+ export const SETTINGS_IS_USABLE_MCP_SERVER_NAME = SETTINGS_MCP_REQUEST_ENTRY.isUsableMcpServerName;
176
+ export const SETTINGS_DESCRIBE_BAD_MCP_SERVER_NAME = SETTINGS_MCP_REQUEST_ENTRY.describeBadMcpServerName;
156
177
  export const SETTINGS_IS_CONTENT_ORIGIN_WORD = SETTINGS_MCP_REQUEST_ENTRY.isContentOriginWord;
157
178
  export const SETTINGS_DESCRIBE_BAD_CONTENT_ORIGIN = SETTINGS_MCP_REQUEST_ENTRY.describeBadContentOrigin;
158
179
  export const SETTINGS_TOOL_WIRE_NAME_MAX_CHARS = SETTINGS_MCP_REQUEST_ENTRY.TOOL_WIRE_NAME_MAX_CHARS;
@@ -165,6 +186,8 @@ const SETTINGS_LAYER_SOURCES = SETTINGS_LAYER_SOURCES_CLOSURE(SETTINGS_SAFETY_ME
165
186
  export const SETTINGS_LAYER_ADMISSION = SETTINGS_LAYER_SOURCES.layerAdmission;
166
187
  const SETTINGS_ACTIVE_TIERS = SETTINGS_ACTIVE_TIERS_CLOSURE();
167
188
  export const SETTINGS_RESOLVE_ACTIVE_TIERS = SETTINGS_ACTIVE_TIERS.resolveActiveTiers;
168
- const SETTINGS_DEFAULT_MODEL = SETTINGS_DEFAULT_MODEL_CLOSURE(SETTINGS_RESOLVE_ACTIVE_TIERS);
189
+ const SETTINGS_TIER_WORDS = SETTINGS_TIER_WORDS_CLOSURE();
190
+ export const SETTINGS_TIER_LADDER_FROM = SETTINGS_TIER_WORDS.tierLadderFrom;
191
+ const SETTINGS_DEFAULT_MODEL = SETTINGS_DEFAULT_MODEL_CLOSURE(SETTINGS_RESOLVE_ACTIVE_TIERS, SETTINGS_TIER_LADDER_FROM);
169
192
  export const SETTINGS_RESOLVE_CATALOG_DEFAULT_MODEL = SETTINGS_DEFAULT_MODEL.resolveCatalogDefaultModel;
170
193
  export const SETTINGS_DEFAULT_ROLE_TIER_LADDER = SETTINGS_DEFAULT_MODEL.DEFAULT_ROLE_TIER_LADDER;
@@ -9,18 +9,64 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
9
9
  http: { url: "text", headers: "stringRecord?", allowedEnvVars: "stringList?", ...HOOK_ENTRY_COMMON_FIELDS },
10
10
  mcp_tool: { server: "string", tool: "string", input: "record?", ...HOOK_ENTRY_COMMON_FIELDS },
11
11
  };
12
- function hookIsRecord(value) {
13
- if (value === null || typeof value !== "object" || Array.isArray(value))
12
+ function hookShapeOf(v) {
13
+ try {
14
+ if (v === null)
15
+ return "null";
16
+ if (Array.isArray(v))
17
+ return "array";
18
+ if (typeof v === "function")
19
+ return "non_plain_object";
20
+ if (typeof v !== "object")
21
+ return "primitive";
22
+ const proto = Object.getPrototypeOf(v);
23
+ return proto === null || Object.getPrototypeOf(proto) === null ? "plain" : "non_plain_object";
24
+ }
25
+ catch {
26
+ return "uninspectable";
27
+ }
28
+ }
29
+ function hookIsRecord(v) {
30
+ const shape = hookShapeOf(v);
31
+ return shape === "plain";
32
+ }
33
+ function hookIsObjectLike(v) {
34
+ const shape = hookShapeOf(v);
35
+ switch (shape) {
36
+ case "null":
37
+ case "primitive":
38
+ return false;
39
+ case "plain":
40
+ case "non_plain_object":
41
+ case "array":
42
+ case "uninspectable":
43
+ return true;
44
+ default: {
45
+ const unhandled = shape;
46
+ throw new Error(`hookIsObjectLike: unhandled shape ${String(unhandled)}`);
47
+ }
48
+ }
49
+ }
50
+ function hookIsArray(v) {
51
+ try {
52
+ return Array.isArray(v);
53
+ }
54
+ catch {
14
55
  return false;
15
- const proto = Object.getPrototypeOf(value);
16
- return proto === Object.prototype || proto === null;
56
+ }
17
57
  }
58
+ const HOOK_ITERATOR_SYMBOL = (() => {
59
+ const found = Object.getOwnPropertySymbols(Array.prototype).find((s) => s.description === "Symbol.iterator");
60
+ if (found === undefined)
61
+ throw new Error("hooks classifier: Array.prototype has no Symbol.iterator");
62
+ return found;
63
+ })();
18
64
  function hookGuardKeyOf(node) {
19
65
  for (const key of Object.keys(node)) {
20
66
  if (!HOOK_GUARD_EVENTS.includes(key))
21
67
  continue;
22
68
  const value = node[key];
23
- if (value !== null && value !== undefined && !(Array.isArray(value) && value.length === 0))
69
+ if (value !== null && value !== undefined && !(hookIsArray(value) && value.length === 0))
24
70
  return key;
25
71
  }
26
72
  return undefined;
@@ -29,9 +75,9 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
29
75
  if (!hookIsRecord(value))
30
76
  return false;
31
77
  const inner = Object.hasOwn(value, "hooks") ? value.hooks : undefined;
32
- if (Array.isArray(inner))
78
+ if (hookIsArray(inner))
33
79
  return inner.length > 0;
34
- return hookIsRecord(inner) && (Object.hasOwn(value, "matcher") || typeof inner.type === "string");
80
+ return hookIsRecord(inner) && (Object.hasOwn(value, "matcher") || (Object.hasOwn(inner, "type") && typeof inner.type === "string"));
35
81
  }
36
82
  function hookGuardSignIn(root, rootPath, place) {
37
83
  const frames = [];
@@ -45,25 +91,49 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
45
91
  };
46
92
  while (pending.length > 0) {
47
93
  const [node, frame, at] = pending.pop();
48
- if (node === null || typeof node !== "object" || seen[at].has(node))
94
+ const shape = hookShapeOf(node);
95
+ let isList = false;
96
+ switch (shape) {
97
+ case "null":
98
+ case "primitive":
99
+ continue;
100
+ case "uninspectable":
101
+ return pathTo(frame, []);
102
+ case "array":
103
+ isList = true;
104
+ break;
105
+ case "plain":
106
+ break;
107
+ case "non_plain_object":
108
+ if (HOOK_ITERATOR_SYMBOL in node)
109
+ return pathTo(frame, []);
110
+ break;
111
+ default: {
112
+ const unhandled = shape;
113
+ throw new Error(`hookGuardSignIn: unhandled shape ${String(unhandled)}`);
114
+ }
115
+ }
116
+ const visited = node;
117
+ if (seen[at].has(visited))
49
118
  continue;
50
- seen[at].add(node);
51
- if (Array.isArray(node)) {
52
- for (let i = node.length - 1; i >= 0; i--) {
119
+ seen[at].add(visited);
120
+ if (isList) {
121
+ const list = node;
122
+ for (let i = list.length - 1; i >= 0; i--) {
53
123
  frames.push({ key: i, parent: frame });
54
- pending.push([node[i], frames.length - 1, at === "matcherList" ? "matcher" : "other"]);
124
+ pending.push([list[i], frames.length - 1, at === "matcherList" ? "matcher" : "other"]);
55
125
  }
56
126
  continue;
57
127
  }
58
- const guardKey = hookGuardKeyOf(node);
128
+ const guardKey = hookGuardKeyOf(visited);
59
129
  if (guardKey !== undefined)
60
130
  return pathTo(frame, [guardKey]);
61
- if (at !== "matcher" && hookLooksLikeMatcher(node))
131
+ if (at !== "matcher" && hookLooksLikeMatcher(visited))
62
132
  return pathTo(frame, []);
63
- const keys = Object.keys(node);
133
+ const keys = Object.keys(visited);
64
134
  for (let i = keys.length - 1; i >= 0; i--) {
65
135
  frames.push({ key: keys[i], parent: frame });
66
- pending.push([node[keys[i]], frames.length - 1, "other"]);
136
+ pending.push([visited[keys[i]], frames.length - 1, "other"]);
67
137
  }
68
138
  }
69
139
  return undefined;
@@ -87,7 +157,7 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
87
157
  case "stringRecord":
88
158
  return hookIsRecord(value) && Object.values(value).every((v) => typeof v === "string");
89
159
  case "stringList":
90
- if (!Array.isArray(value))
160
+ if (!hookIsArray(value))
91
161
  return false;
92
162
  for (let i = 0; i < value.length; i++)
93
163
  if (typeof value[i] !== "string")
@@ -121,7 +191,7 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
121
191
  const base = (optional ? kind.slice(0, -1) : kind);
122
192
  if (!hookFieldFits(base, value))
123
193
  return { field };
124
- out[field] = Array.isArray(value) ? value.slice() : hookIsRecord(value) ? Object.fromEntries(Object.entries(value)) : value;
194
+ out[field] = hookIsArray(value) ? value.slice() : hookIsRecord(value) ? Object.fromEntries(Object.entries(value)) : value;
125
195
  }
126
196
  return { entry: out };
127
197
  }
@@ -135,18 +205,18 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
135
205
  }
136
206
  const entries = Object.hasOwn(matcher, "hooks") ? matcher.hooks : undefined;
137
207
  const signField = hookGuardKeyOf(matcher) ??
138
- Object.keys(matcher).find((key) => !(key === "hooks" && Array.isArray(entries)) && hookGuardSignIn(matcher[key], [...at, key], "other") !== undefined);
208
+ Object.keys(matcher).find((key) => !(key === "hooks" && hookIsArray(entries)) && hookGuardSignIn(matcher[key], [...at, key], "other") !== undefined);
139
209
  if (signField !== undefined) {
140
210
  reject("guard-matcher-invalid", at, signField);
141
211
  return undefined;
142
212
  }
143
213
  const entrySigns = [];
144
- if (Array.isArray(entries))
214
+ if (hookIsArray(entries))
145
215
  for (let j = 0; j < entries.length; j++)
146
216
  entrySigns.push(hookGuardSignIn(entries[j], [...at, "hooks", j], "other"));
147
217
  const name = Object.hasOwn(matcher, "matcher") ? matcher.matcher : undefined;
148
- const badField = name !== undefined && typeof name !== "string" ? "matcher" : !Array.isArray(entries) ? "hooks" : undefined;
149
- if (badField !== undefined || !Array.isArray(entries)) {
218
+ const badField = name !== undefined && typeof name !== "string" ? "matcher" : !hookIsArray(entries) ? "hooks" : undefined;
219
+ if (badField !== undefined || !hookIsArray(entries)) {
150
220
  if (guardEvent || entrySigns.some((sign) => sign !== undefined))
151
221
  reject("guard-matcher-invalid", at, badField);
152
222
  else
@@ -173,13 +243,15 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
173
243
  }
174
244
  function hookBlockRead(hooks, reject, drop) {
175
245
  if (!hookIsRecord(hooks)) {
176
- if (Array.isArray(hooks) && hooks.some((x) => x !== null && typeof x === "object"))
246
+ if (hookIsArray(hooks) && hooks.some(hookIsObjectLike))
247
+ reject("hooks-is-matcher", ["hooks"]);
248
+ else if (hookGuardSignIn(hooks, ["hooks"], "other") !== undefined)
177
249
  reject("hooks-is-matcher", ["hooks"]);
178
250
  else
179
251
  drop("hooks-not-object", ["hooks"]);
180
252
  return undefined;
181
253
  }
182
- if (hookLooksLikeMatcher(hooks) || typeof hooks.type === "string") {
254
+ if (hookLooksLikeMatcher(hooks) || (Object.hasOwn(hooks, "type") && typeof hooks.type === "string")) {
183
255
  reject("hooks-is-matcher", ["hooks"]);
184
256
  return undefined;
185
257
  }
@@ -188,14 +260,14 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
188
260
  const value = hooks[event];
189
261
  const at = ["hooks", event];
190
262
  if (!HOOK_EVENTS.includes(event)) {
191
- if (hookGuardSignIn(value, at, Array.isArray(value) ? "matcherList" : "other") !== undefined)
263
+ if (hookGuardSignIn(value, at, hookIsArray(value) ? "matcherList" : "other") !== undefined)
192
264
  reject("guard-under-unknown-event", at);
193
265
  else
194
266
  drop("unknown-event", at);
195
267
  continue;
196
268
  }
197
269
  const guardEvent = HOOK_GUARD_EVENTS.includes(event);
198
- if (!Array.isArray(value)) {
270
+ if (!hookIsArray(value)) {
199
271
  if ((guardEvent && value !== null) || hookGuardSignIn(value, at, "other") !== undefined)
200
272
  reject("guard-event-not-array", at);
201
273
  else
@@ -212,7 +284,7 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
212
284
  }
213
285
  return loaded;
214
286
  }
215
- function classifyHooksConfig(settingsDoc) {
287
+ function hookClassify(settingsDoc) {
216
288
  const rejections = [];
217
289
  const dropped = [];
218
290
  const reject = (code, path, field) => {
@@ -222,7 +294,7 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
222
294
  dropped.push(field === undefined ? { code, path } : { code, path, field });
223
295
  };
224
296
  let hooks;
225
- if (settingsDoc !== null && typeof settingsDoc === "object" && !Array.isArray(settingsDoc)) {
297
+ if (hookIsRecord(settingsDoc)) {
226
298
  const doc = settingsDoc;
227
299
  for (const key of Object.keys(doc)) {
228
300
  const value = doc[key];
@@ -232,7 +304,7 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
232
304
  }
233
305
  const sign = key === "matcher" && hookLooksLikeMatcher(doc)
234
306
  ? [key]
235
- : HOOK_GUARD_EVENTS.includes(key) && value !== null && value !== undefined && !(Array.isArray(value) && value.length === 0)
307
+ : HOOK_GUARD_EVENTS.includes(key) && value !== null && value !== undefined && !(hookIsArray(value) && value.length === 0)
236
308
  ? [key]
237
309
  : hookGuardSignIn(value, [key], "other");
238
310
  if (sign !== undefined)
@@ -250,5 +322,13 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
250
322
  return { outcome: "loaded-partial", hooks, dropped, rejections: [] };
251
323
  return { outcome: "loaded", hooks, dropped: [], rejections: [] };
252
324
  }
325
+ function classifyHooksConfig(settingsDoc) {
326
+ try {
327
+ return hookClassify(settingsDoc);
328
+ }
329
+ catch {
330
+ return { outcome: "rejected", hooks: undefined, dropped: [], rejections: [{ code: "guard-outside-hooks", path: [] }] };
331
+ }
332
+ }
253
333
  return classifyHooksConfig;
254
334
  };
@@ -1 +1 @@
1
- export declare const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE: (MCP_CONTENT_ORIGINS: readonly ["local", "execution", "external"], startsWithHttpScheme: (raw: string) => boolean, echoCallerText: (text: string) => string) => any;
1
+ export declare const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE: (MCP_CONTENT_ORIGINS: readonly ["local", "execution", "external"], startsWithHttpScheme: (raw: string) => boolean, echoCallerText: (text: string) => string, UNINSPECTABLE: "an object that could not be inspected (a proxy trap threw)", captureStringArray: (v: unknown, classification: "strict" | "wide") => string[] | undefined, dataDescriptor: (value: unknown) => PropertyDescriptor, inspect: (read: () => unknown) => object, ownFieldsOf: (record: object, keys: readonly string[]) => object, ownValueOf: (record: object, key: string) => object, readKey: (record: object, key: PropertyKey) => object, isJsonArray: (v: unknown) => v is unknown[], jsonShapeOf: (v: unknown) => "plain" | "non_plain_object" | "array" | "null" | "primitive" | "uninspectable", isReservedMcpServerName: (name: string) => boolean, RESERVED_MCP_SERVER_NAME_REASON: "the \"remote-\" prefix is reserved for the remote MCP servers a device executor offers") => any;