@inneranimalmedia/agentsam-sdk 2.6.9 → 2.6.10
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.
- package/README.md +18 -0
- package/apps/cad-creator/shared/cad/package.json +1 -1
- package/apps/client-cms-editor/backend/package.json +3 -3
- package/apps/client-cms-editor/frontend/package.json +4 -4
- package/apps/client-cms-editor/package-lock.json +8 -8
- package/apps/client-cms-editor/package.json +1 -1
- package/apps/client-cms-editor/shared/cms/package.json +2 -2
- package/docs/architecture/HOOKS-MODELS-SELF-HOSTING-PLAN.md +199 -0
- package/examples/hyperspace-demo/index.html +16 -0
- package/examples/hyperspace-demo/package.json +21 -0
- package/examples/hyperspace-demo/src/main.tsx +160 -0
- package/examples/hyperspace-demo/tsconfig.json +9 -0
- package/examples/hyperspace-demo/vite.config.ts +24 -0
- package/migrations/runtime/0005_agentsam_hooks.sql +87 -0
- package/package.json +23 -7
- package/packages/agentsam-brand/package.json +1 -1
- package/packages/agentsam-brand/src/core/v2/compile.js +1 -1
- package/packages/agentsam-brand/src/core/v2/schema.js +1 -1
- package/packages/agentsam-contracts/package.json +1 -1
- package/packages/agentsam-contracts/src/errors.ts +19 -10
- package/packages/agentsam-errors/package.json +11 -3
- package/packages/agentsam-errors/protocol/agentsam.error.v2.schema.json +821 -0
- package/packages/agentsam-errors/protocol/error-catalog.json +3512 -0
- package/packages/agentsam-errors/src/envelope.js +63 -11
- package/packages/agentsam-errors/src/error.js +6 -0
- package/packages/agentsam-errors/src/fingerprint.js +9 -1
- package/packages/agentsam-errors/src/normalize.js +51 -6
- package/packages/agentsam-errors/src/recovery.js +9 -35
- package/packages/agentsam-errors/src/transport.js +6 -1
- package/packages/agentsam-errors/src/vocabulary.js +515 -126
- package/packages/agentsam-errors/test/catalog-v2.test.mjs +106 -0
- package/packages/agentsam-errors/types/index.d.ts +157 -0
- package/packages/agentsam-goap/package.json +2 -2
- package/packages/agentsam-hooks/README.md +206 -0
- package/packages/agentsam-hooks/bin/agentsam-hooks.mjs +64 -0
- package/packages/agentsam-hooks/bindings/go/command.go +55 -0
- package/packages/agentsam-hooks/bindings/go/errors_generated.go +402 -0
- package/packages/agentsam-hooks/bindings/go/go.mod +3 -0
- package/packages/agentsam-hooks/bindings/go/hooks.go +285 -0
- package/packages/agentsam-hooks/bindings/go/hooks_test.go +48 -0
- package/packages/agentsam-hooks/bindings/rust/Cargo.toml +11 -0
- package/packages/agentsam-hooks/bindings/rust/src/errors_generated.rs +396 -0
- package/packages/agentsam-hooks/bindings/rust/src/lib.rs +397 -0
- package/packages/agentsam-hooks/package.json +69 -0
- package/packages/agentsam-hooks/schema/manifest.json +54 -0
- package/packages/agentsam-hooks/scripts/clean-protocol.mjs +17 -0
- package/packages/agentsam-hooks/scripts/sync-protocol.mjs +27 -0
- package/packages/agentsam-hooks/src/adapters/agents.js +82 -0
- package/packages/agentsam-hooks/src/adapters/callback.js +4 -0
- package/packages/agentsam-hooks/src/adapters/capability.js +122 -0
- package/packages/agentsam-hooks/src/adapters/command.js +104 -0
- package/packages/agentsam-hooks/src/adapters/composite.js +31 -0
- package/packages/agentsam-hooks/src/adapters/http.js +58 -0
- package/packages/agentsam-hooks/src/adapters/lsp.js +116 -0
- package/packages/agentsam-hooks/src/adapters/mcp.js +76 -0
- package/packages/agentsam-hooks/src/adapters/provider.js +129 -0
- package/packages/agentsam-hooks/src/config.js +143 -0
- package/packages/agentsam-hooks/src/contracts.js +284 -0
- package/packages/agentsam-hooks/src/errors-generated.js +2732 -0
- package/packages/agentsam-hooks/src/index.d.ts +193 -0
- package/packages/agentsam-hooks/src/index.js +14 -0
- package/packages/agentsam-hooks/src/policy.js +34 -0
- package/packages/agentsam-hooks/src/runtime.js +312 -0
- package/packages/agentsam-hooks/src/store.js +264 -0
- package/packages/agentsam-hooks/test/adapters.test.mjs +216 -0
- package/packages/agentsam-hooks/test/runtime.test.mjs +258 -0
- package/packages/agentsam-knowledge/package.json +1 -1
- package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
- package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
- package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
- package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
- package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
- package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
- package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
- package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
- package/packages/agentsam-nav/dist/browser.d.ts +11 -0
- package/packages/agentsam-nav/dist/browser.global.js +135 -0
- package/packages/agentsam-nav/dist/browser.js +7290 -0
- package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
- package/packages/agentsam-nav/dist/index.d.ts +11 -0
- package/packages/agentsam-nav/dist/index.js +7291 -0
- package/packages/agentsam-nav/dist/legacy.css +83 -0
- package/packages/agentsam-nav/dist/shell.css +113 -0
- package/packages/agentsam-nav/dist/theme.css +113 -0
- package/packages/agentsam-nav/dist/utils.d.ts +1 -0
- package/packages/agentsam-nav/package.json +1 -1
- package/packages/agentsam-queue-control/package.json +1 -1
- package/packages/agentsam-repository/package.json +1 -1
- package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
- package/packages/agentsam-vault/package.json +1 -1
- package/packages/agentsam-workbench/package.json +3 -3
- package/packages/connectors/cloudflare/package.json +1 -1
- package/packages/heuristic-theme/package.json +1 -1
- package/packages/identity/package.json +2 -2
- package/packages/providers/completeful/package.json +1 -1
- package/packages/theme-church-site/package.json +2 -2
- package/packages/theme-companions-site/package.json +2 -2
- package/packages/theme-floors-site/package.json +2 -2
- package/packages/theme-fuelnfree-site/package.json +2 -2
- package/packages/theme-handyman-site/package.json +2 -2
- package/packages/theme-insurance-site/package.json +2 -2
- package/packages/theme-scenes/package.json +1 -1
- package/packages/theme-shinshu-site/package.json +2 -2
- package/packages/work-graph/package.json +1 -1
- package/protocol/apps/agentsam.app.v1.schema.json +1 -1
- package/protocol/apps/agentsam.host-install.v1.schema.json +1 -1
- package/protocol/assets/asset-record.v1.schema.json +1 -1
- package/protocol/brand/brandpack.v1.schema.json +1 -1
- package/protocol/capabilities/capability-manifest.schema.json +1 -1
- package/protocol/capabilities/knowledge-search-input.schema.json +1 -0
- package/protocol/credentials/issue.v1.schema.json +1 -1
- package/protocol/database/agentsam.schema-pack.v1.schema.json +1 -1
- package/protocol/database/connection.v1.schema.json +1 -1
- package/protocol/embeddings/embedding-profile.v1.schema.json +1 -1
- package/protocol/errors/README.md +36 -0
- package/protocol/errors/agentsam.error.v2.schema.json +821 -0
- package/protocol/errors/error-catalog.json +3506 -158
- package/protocol/errors/error-envelope.schema.json +195 -52
- package/protocol/errors/recovery.v1.schema.json +1 -1
- package/protocol/features/agentsam.feature.v1.schema.json +1 -1
- package/protocol/hooks/README.md +18 -0
- package/protocol/hooks/agentsam.hook.output.v1.schema.json +27 -0
- package/protocol/hooks/agentsam.hook.receipt.v1.schema.json +61 -0
- package/protocol/hooks/agentsam.hook.v1.schema.json +35 -0
- package/protocol/hooks/agentsam.hooks.config.v1.schema.json +78 -0
- package/protocol/local-engine/benchmark.v1.schema.json +1 -1
- package/protocol/local-engine/engine.v1.schema.json +1 -1
- package/protocol/models/model-inventory-v2.schema.json +1 -1
- package/protocol/models/provider-model-snapshot.v1.schema.json +22 -0
- package/protocol/rpc/v1/errors.proto +1 -0
- package/protocol/runtime/agentsam.runtime.v1.schema.json +1 -1
- package/protocol/runtime/workspace-fs.v1.schema.json +1 -1
- package/protocol/sam/activity.v1.schema.json +1 -1
- package/protocol/sam/answer.v1.schema.json +1 -1
- package/protocol/sam/calibration.v1.schema.json +1 -1
- package/protocol/sam/decision-receipt.v1.schema.json +1 -1
- package/protocol/sam/evaluation.v1.schema.json +1 -1
- package/protocol/sam/operation.schema.json +1 -1
- package/protocol/sam/outcome.v1.schema.json +1 -1
- package/protocol/sam/question.v1.schema.json +1 -1
- package/protocol/sam/result.schema.json +1 -1
- package/protocol/sam/state.v1.schema.json +1 -1
- package/protocol/scoring/scorecard.v1.schema.json +1 -1
- package/protocol/skills/agentsam.interaction.v1.schema.json +1 -1
- package/protocol/skills/agentsam.skill.v1.schema.json +1 -1
- package/protocol/theme-refinery/product-metadata.schema.json +1 -1
- package/protocol/theme-refinery/reconciliation-receipt.schema.json +1 -1
- package/protocol/ui/icon.v1.schema.json +1 -1
- package/python/README.md +20 -0
- package/python/agentsam_sdk/errors/__init__.py +4 -0
- package/python/agentsam_sdk/errors/vocabulary.py +2730 -0
- package/python/agentsam_sdk/hooks/__init__.py +32 -0
- package/python/agentsam_sdk/hooks/adapters.py +132 -0
- package/python/agentsam_sdk/hooks/contracts.py +121 -0
- package/python/agentsam_sdk/hooks/runtime.py +253 -0
- package/python/tests/test_hooks.py +115 -0
- package/src/agent/responses-runner.js +145 -1
- package/src/cli/command-catalog.js +1 -0
- package/src/cli.js +9 -0
- package/src/commands/cheat-sheet.js +1 -0
- package/src/commands/hooks.js +260 -0
- package/src/commands/models.js +1 -1
- package/src/commands/shell.js +114 -9
- package/src/errors/diagnostic.js +9 -9
- package/src/index.js +32 -0
- package/src/knowledge/service/grpc-codec.js +2 -0
- package/src/lib/slash-commands.js +1 -0
- package/src/local/runtime-store.js +46 -0
- package/src/models/catalog.js +0 -49
- package/src/models/inventory-core.js +69 -0
- package/src/plugins/index.js +8 -1
- package/src/plugins/registry.js +56 -0
- package/src/rpc/generated/errors_pb.js +49 -1
- package/src/tools/runtime.js +13 -5
|
@@ -2,11 +2,15 @@ import {
|
|
|
2
2
|
DEFAULT_HTTP_STATUS,
|
|
3
3
|
ERROR_CODE,
|
|
4
4
|
ERROR_DOMAIN,
|
|
5
|
+
ERROR_FAILURE_BEHAVIOR,
|
|
6
|
+
ERROR_FAILURE_CLASS,
|
|
5
7
|
ERROR_REASON_POLICY,
|
|
6
8
|
ERROR_RESOLUTION_OWNER,
|
|
7
9
|
ERROR_SCHEMA_VERSION,
|
|
8
10
|
ERROR_SEVERITY,
|
|
11
|
+
ERROR_SIDE_EFFECT_STATE,
|
|
9
12
|
ERROR_SOURCE_KIND,
|
|
13
|
+
ERROR_STAGE,
|
|
10
14
|
GRPC_STATUS,
|
|
11
15
|
REMEDIATION_ACTION,
|
|
12
16
|
} from './vocabulary.js';
|
|
@@ -20,7 +24,19 @@ const SEVERITY_VALUES = VALUES(ERROR_SEVERITY);
|
|
|
20
24
|
const SOURCE_VALUES = VALUES(ERROR_SOURCE_KIND);
|
|
21
25
|
const OWNER_VALUES = VALUES(ERROR_RESOLUTION_OWNER);
|
|
22
26
|
const DOMAIN_VALUES = VALUES(ERROR_DOMAIN);
|
|
27
|
+
const FAILURE_CLASS_VALUES = VALUES(ERROR_FAILURE_CLASS);
|
|
28
|
+
const STAGE_VALUES = VALUES(ERROR_STAGE);
|
|
29
|
+
const FAILURE_BEHAVIOR_VALUES = VALUES(ERROR_FAILURE_BEHAVIOR);
|
|
30
|
+
const SIDE_EFFECT_STATE_VALUES = VALUES(ERROR_SIDE_EFFECT_STATE);
|
|
23
31
|
const ACTION_VALUES = VALUES(REMEDIATION_ACTION);
|
|
32
|
+
const FEATURE_PATTERN = /^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/;
|
|
33
|
+
const STAGE_ALIASES = new Map([
|
|
34
|
+
['discovery', 'discover'], ['configuration', 'configure'], ['request', 'execute'], ['run', 'execute'],
|
|
35
|
+
['dispatch', 'execute'], ['adapter', 'execute'], ['spawn', 'start'], ['parse', 'transform'],
|
|
36
|
+
['render', 'transform'], ['compaction', 'transform'], ['persistence', 'persist'],
|
|
37
|
+
['persistence_read', 'load'], ['persistence_write', 'persist'], ['search', 'discover'],
|
|
38
|
+
['inventory', 'discover'], ['approve', 'authorize'],
|
|
39
|
+
]);
|
|
24
40
|
const GRPC_CODE_BY_NUMBER = new Map(Object.entries(GRPC_STATUS).map(([name, value]) => [value, ERROR_CODE[name]]));
|
|
25
41
|
const HTTP_OVERRIDES = new Map([
|
|
26
42
|
[400, ERROR_CODE.INVALID_ARGUMENT], [401, ERROR_CODE.UNAUTHENTICATED], [403, ERROR_CODE.PERMISSION_DENIED],
|
|
@@ -51,6 +67,11 @@ const USER_ACTIONS = new Set([
|
|
|
51
67
|
REMEDIATION_ACTION.SELECT_MODEL,
|
|
52
68
|
REMEDIATION_ACTION.CHANGE_REGION,
|
|
53
69
|
REMEDIATION_ACTION.RESTART_RUNTIME,
|
|
70
|
+
REMEDIATION_ACTION.RESTART_SERVICE,
|
|
71
|
+
REMEDIATION_ACTION.REPAIR_SCHEMA,
|
|
72
|
+
REMEDIATION_ACTION.RUN_MIGRATION,
|
|
73
|
+
REMEDIATION_ACTION.UPDATE_LOCKFILE,
|
|
74
|
+
REMEDIATION_ACTION.REINSTALL_WORKSPACE,
|
|
54
75
|
]);
|
|
55
76
|
|
|
56
77
|
function clean(value) { return value == null ? '' : String(value).trim(); }
|
|
@@ -107,6 +128,21 @@ export function canonicalCodeFromGrpcStatus(status) { return GRPC_CODE_BY_NUMBER
|
|
|
107
128
|
export function defaultHttpStatusForCode(code) { return DEFAULT_HTTP_STATUS[code] ?? 500; }
|
|
108
129
|
export function grpcStatusForCode(code) { return GRPC_STATUS[code] ?? GRPC_STATUS.UNKNOWN; }
|
|
109
130
|
|
|
131
|
+
function normalizeStage(value, fallback) {
|
|
132
|
+
const requested = clean(value);
|
|
133
|
+
if (!requested) return { stage: fallback, nativeStage: null };
|
|
134
|
+
if (STAGE_VALUES.has(requested)) return { stage: requested, nativeStage: null };
|
|
135
|
+
const generic = STAGE_ALIASES.get(requested);
|
|
136
|
+
return { stage: generic || fallback, nativeStage: requested };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function vocabularyValue(value, allowed, label, fallback = null) {
|
|
140
|
+
const normalized = clean(value || fallback);
|
|
141
|
+
if (!normalized && fallback == null) return null;
|
|
142
|
+
if (!allowed.has(normalized)) throw new TypeError(`Unknown AgentSam error ${label}: ${normalized}`);
|
|
143
|
+
return normalized;
|
|
144
|
+
}
|
|
145
|
+
|
|
110
146
|
export function createErrorEnvelope(input = {}) {
|
|
111
147
|
const reason = clean(input.reason || 'unknown');
|
|
112
148
|
if (!REASON_PATTERN.test(reason)) throw new TypeError(`Invalid AgentSam error reason: ${reason}`);
|
|
@@ -121,8 +157,19 @@ export function createErrorEnvelope(input = {}) {
|
|
|
121
157
|
const retryable = input.retryable == null ? Boolean(policy.retryable) : Boolean(input.retryable);
|
|
122
158
|
const resolutionOwner = clean(input.resolution_owner || policy.resolution_owner);
|
|
123
159
|
if (!OWNER_VALUES.has(resolutionOwner)) throw new TypeError(`Unknown AgentSam error resolution owner: ${resolutionOwner}`);
|
|
124
|
-
const domain =
|
|
125
|
-
|
|
160
|
+
const domain = vocabularyValue(input.domain, DOMAIN_VALUES, 'domain', policy.domain || ERROR_DOMAIN.RUNTIME);
|
|
161
|
+
const failureClass = vocabularyValue(input.failure_class, FAILURE_CLASS_VALUES, 'failure class', policy.failure_class || 'internal');
|
|
162
|
+
const normalizedStage = normalizeStage(input.stage, policy.default_stage || ERROR_STAGE.EXECUTE);
|
|
163
|
+
const nativeStage = optional(input.native_stage, 256) || normalizedStage.nativeStage;
|
|
164
|
+
const feature = optional(input.feature, 256);
|
|
165
|
+
if (feature && !FEATURE_PATTERN.test(feature)) throw new TypeError(`Invalid AgentSam error feature: ${feature}`);
|
|
166
|
+
const failureBehavior = vocabularyValue(input.failure_behavior, FAILURE_BEHAVIOR_VALUES, 'failure behavior');
|
|
167
|
+
const sideEffectState = vocabularyValue(
|
|
168
|
+
input.side_effect_state || input.operation?.side_effect_state,
|
|
169
|
+
SIDE_EFFECT_STATE_VALUES,
|
|
170
|
+
'side effect state',
|
|
171
|
+
input.operation ? ERROR_SIDE_EFFECT_STATE.UNKNOWN : ERROR_SIDE_EFFECT_STATE.NONE,
|
|
172
|
+
);
|
|
126
173
|
const remediation = normalizeRemediation(input.remediation, policy);
|
|
127
174
|
if (severity === ERROR_SEVERITY.TRANSIENT && !retryable) throw new TypeError('transient AgentSam errors must be retryable');
|
|
128
175
|
if ((remediation.action === REMEDIATION_ACTION.RETRY || remediation.action === REMEDIATION_ACTION.RETRY_LATER) && !retryable) {
|
|
@@ -139,14 +186,22 @@ export function createErrorEnvelope(input = {}) {
|
|
|
139
186
|
schema_version: ERROR_SCHEMA_VERSION,
|
|
140
187
|
code,
|
|
141
188
|
reason,
|
|
189
|
+
domain,
|
|
190
|
+
failure_class: failureClass,
|
|
191
|
+
stage: normalizedStage.stage,
|
|
192
|
+
native_stage: nativeStage,
|
|
193
|
+
feature,
|
|
194
|
+
failure_behavior: failureBehavior,
|
|
142
195
|
severity,
|
|
143
|
-
|
|
196
|
+
retryable,
|
|
197
|
+
side_effect_state: sideEffectState,
|
|
144
198
|
resolution_owner: resolutionOwner,
|
|
145
|
-
|
|
199
|
+
source,
|
|
200
|
+
adapter: optional(input.adapter, 256),
|
|
201
|
+
protocol: optional(input.protocol, 256),
|
|
202
|
+
transport: optional(input.transport, 256),
|
|
146
203
|
tool: optional(input.tool, 256),
|
|
147
|
-
stage: optional(input.stage, 256),
|
|
148
204
|
message: redactString(input.message || 'Operation failed', 4_000),
|
|
149
|
-
retryable,
|
|
150
205
|
retry_after_ms: input.retry_after_ms == null ? null : Math.max(0, Math.round(Number(input.retry_after_ms) || 0)),
|
|
151
206
|
remediation,
|
|
152
207
|
resource: normalizeResource(input.resource),
|
|
@@ -154,7 +209,6 @@ export function createErrorEnvelope(input = {}) {
|
|
|
154
209
|
environment,
|
|
155
210
|
http_status: input.http_status == null ? defaultHttpStatusForCode(code) : Number(input.http_status),
|
|
156
211
|
grpc_status: input.grpc_status == null ? grpcStatusForCode(code) : Number(input.grpc_status),
|
|
157
|
-
transport: optional(input.transport, 256),
|
|
158
212
|
provider: optional(input.provider, 256),
|
|
159
213
|
provider_code: optional(input.provider_code, 512),
|
|
160
214
|
request_id: optional(input.request_id, 512),
|
|
@@ -167,9 +221,7 @@ export function createErrorEnvelope(input = {}) {
|
|
|
167
221
|
if (!Number.isInteger(envelope.grpc_status) || envelope.grpc_status < 0 || envelope.grpc_status > 16) envelope.grpc_status = null;
|
|
168
222
|
envelope.fingerprint = optional(input.fingerprint, 128) || fingerprintError(envelope);
|
|
169
223
|
|
|
170
|
-
// Optional recovery
|
|
171
|
-
const failureClass = input.failure_class || null;
|
|
172
|
-
if (failureClass) envelope.failure_class = clean(failureClass);
|
|
224
|
+
// Optional recovery plans remain orthogonal to the canonical v2 failure dimensions.
|
|
173
225
|
if (input.operation && typeof input.operation === 'object') {
|
|
174
226
|
envelope.operation = Object.freeze({
|
|
175
227
|
kind: optional(input.operation.kind, 256),
|
|
@@ -178,7 +230,7 @@ export function createErrorEnvelope(input = {}) {
|
|
|
178
230
|
resource_id: optional(input.operation.resource_id, 512),
|
|
179
231
|
read_only: input.operation.read_only === true,
|
|
180
232
|
idempotent: input.operation.idempotent === true,
|
|
181
|
-
side_effect_state:
|
|
233
|
+
side_effect_state: sideEffectState,
|
|
182
234
|
});
|
|
183
235
|
}
|
|
184
236
|
if (input.retry && typeof input.retry === 'object') {
|
|
@@ -11,8 +11,14 @@ export class AgentSamError extends Error {
|
|
|
11
11
|
this.diagnostic = normalized;
|
|
12
12
|
this.code = normalized.code;
|
|
13
13
|
this.reason = normalized.reason;
|
|
14
|
+
this.domain = normalized.domain;
|
|
15
|
+
this.failure_class = normalized.failure_class;
|
|
16
|
+
this.stage = normalized.stage;
|
|
17
|
+
this.feature = normalized.feature;
|
|
18
|
+
this.failure_behavior = normalized.failure_behavior;
|
|
14
19
|
this.severity = normalized.severity;
|
|
15
20
|
this.retryable = normalized.retryable;
|
|
21
|
+
this.side_effect_state = normalized.side_effect_state;
|
|
16
22
|
this.status = normalized.http_status;
|
|
17
23
|
this.fingerprint = normalized.fingerprint;
|
|
18
24
|
}
|
|
@@ -10,8 +10,16 @@ function stableFields(value = {}) {
|
|
|
10
10
|
value.source?.service,
|
|
11
11
|
value.resolution_owner,
|
|
12
12
|
value.domain,
|
|
13
|
-
value.
|
|
13
|
+
value.failure_class,
|
|
14
14
|
value.stage,
|
|
15
|
+
value.native_stage,
|
|
16
|
+
value.feature,
|
|
17
|
+
value.failure_behavior,
|
|
18
|
+
value.side_effect_state,
|
|
19
|
+
value.adapter,
|
|
20
|
+
value.protocol,
|
|
21
|
+
value.transport,
|
|
22
|
+
value.tool,
|
|
15
23
|
value.provider,
|
|
16
24
|
value.provider_code,
|
|
17
25
|
value.native?.code,
|
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
import { AgentSamError } from './error.js';
|
|
2
2
|
import { canonicalCodeFromHttpStatus, createErrorEnvelope, isErrorEnvelope } from './envelope.js';
|
|
3
|
-
import { ERROR_REASON } from './vocabulary.js';
|
|
3
|
+
import { ERROR_REASON, ERROR_REASON_ALIASES, ERROR_REASON_POLICY } from './vocabulary.js';
|
|
4
4
|
|
|
5
5
|
function clean(value) { return value == null ? '' : String(value).trim(); }
|
|
6
|
+
function token(value) { return clean(value).split(':', 1)[0]; }
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Resolves canonical reasons and legacy/native aliases without discarding the
|
|
10
|
+
* original evidence. Adapter context disambiguates old generic hook codes.
|
|
11
|
+
*/
|
|
12
|
+
export function canonicalizeErrorReason(value, context = {}) {
|
|
13
|
+
const values = value && typeof value === 'object'
|
|
14
|
+
? [value.reason, value.code, value.message]
|
|
15
|
+
: [value];
|
|
16
|
+
for (const raw of values) {
|
|
17
|
+
const candidate = token(raw);
|
|
18
|
+
if (!candidate) continue;
|
|
19
|
+
if (ERROR_REASON_POLICY[candidate]) return candidate;
|
|
20
|
+
const lowered = candidate.toLowerCase();
|
|
21
|
+
if (ERROR_REASON_POLICY[lowered]) return lowered;
|
|
22
|
+
if (candidate === 'AGENTSAM_HOOK_TIMEOUT' && context.adapter) {
|
|
23
|
+
const specific = `hook_${clean(context.adapter).toLowerCase()}_timeout`;
|
|
24
|
+
if (ERROR_REASON_POLICY[specific]) return specific;
|
|
25
|
+
}
|
|
26
|
+
const alias = ERROR_REASON_ALIASES[candidate] || ERROR_REASON_ALIASES[lowered] || ERROR_REASON_ALIASES[candidate.toUpperCase()];
|
|
27
|
+
if (alias) return alias;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function reasonFromHttpStatus(status) {
|
|
33
|
+
if (status === 400 || status === 422) return ERROR_REASON.INPUT_INVALID;
|
|
34
|
+
if (status === 401) return ERROR_REASON.AUTH_INVALID;
|
|
35
|
+
if (status === 403) return ERROR_REASON.PERMISSION_DENIED;
|
|
36
|
+
if (status === 404) return ERROR_REASON.TARGET_NOT_FOUND;
|
|
37
|
+
if (status === 408 || status === 504) return ERROR_REASON.TRANSPORT_TIMEOUT;
|
|
38
|
+
if (status === 409) return ERROR_REASON.CONFLICT;
|
|
39
|
+
if (status === 412) return ERROR_REASON.PRECONDITION_FAILED;
|
|
40
|
+
if (status === 429) return ERROR_REASON.RATE_LIMITED;
|
|
41
|
+
if (status === 501) return ERROR_REASON.UNSUPPORTED_OPERATION;
|
|
42
|
+
if ([502, 503, 520, 521, 522, 523, 525, 526, 530].includes(status)) return ERROR_REASON.TRANSPORT_UNREACHABLE;
|
|
43
|
+
return ERROR_REASON.INTERNAL;
|
|
44
|
+
}
|
|
6
45
|
|
|
7
46
|
export function normalizeError(error, context = {}) {
|
|
8
47
|
if (isErrorEnvelope(error)) return error;
|
|
@@ -10,11 +49,17 @@ export function normalizeError(error, context = {}) {
|
|
|
10
49
|
if (isErrorEnvelope(error?.envelope)) return error.envelope;
|
|
11
50
|
if (isErrorEnvelope(error?.error)) return error.error;
|
|
12
51
|
const status = Number(error?.status || error?.http_status || context.http_status || 0) || null;
|
|
13
|
-
const
|
|
52
|
+
const recoveredReason = canonicalizeErrorReason(context.reason, context)
|
|
53
|
+
|| canonicalizeErrorReason(error, context);
|
|
54
|
+
const reason = recoveredReason || (status ? reasonFromHttpStatus(status) : ERROR_REASON.INTERNAL);
|
|
55
|
+
// A known reason owns its broad canonical code. HTTP status only selects a
|
|
56
|
+
// broad fallback reason when no machine reason or alias was recovered.
|
|
57
|
+
const canonical = clean(context.code)
|
|
58
|
+
|| (ERROR_REASON_POLICY[reason] ? undefined : (status ? canonicalCodeFromHttpStatus(status) : undefined));
|
|
14
59
|
return createErrorEnvelope({
|
|
15
60
|
...context,
|
|
16
61
|
code: canonical,
|
|
17
|
-
reason
|
|
62
|
+
reason,
|
|
18
63
|
message: context.message || error?.message || String(error || 'Unknown error'),
|
|
19
64
|
http_status: status,
|
|
20
65
|
native: context.native || {
|
|
@@ -23,8 +68,8 @@ export function normalizeError(error, context = {}) {
|
|
|
23
68
|
stack: error?.stack || null,
|
|
24
69
|
},
|
|
25
70
|
source: context.source || { kind: 'agentsam', name: 'agentsam-sdk' },
|
|
26
|
-
resolution_owner: context.resolution_owner
|
|
27
|
-
severity: context.severity
|
|
28
|
-
remediation: context.remediation
|
|
71
|
+
resolution_owner: context.resolution_owner,
|
|
72
|
+
severity: context.severity,
|
|
73
|
+
remediation: context.remediation,
|
|
29
74
|
});
|
|
30
75
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ERROR_FAILURE_CLASS, ERROR_SIDE_EFFECT_STATE } from './vocabulary.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Recovery policy — separates "what failed" from "what to do".
|
|
3
5
|
*
|
|
@@ -6,39 +8,10 @@
|
|
|
6
8
|
* Critical rule: unknown side_effect_state ⇒ reconcile before retry.
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
POLICY: 'policy',
|
|
14
|
-
DISCOVERY: 'discovery',
|
|
15
|
-
RESOLUTION: 'resolution',
|
|
16
|
-
TRANSPORT: 'transport',
|
|
17
|
-
PROTOCOL: 'protocol',
|
|
18
|
-
TIMEOUT: 'timeout',
|
|
19
|
-
RATE_LIMIT: 'rate_limit',
|
|
20
|
-
CAPACITY: 'capacity',
|
|
21
|
-
RESOURCE: 'resource',
|
|
22
|
-
FILESYSTEM: 'filesystem',
|
|
23
|
-
PERSISTENCE: 'persistence',
|
|
24
|
-
CONSISTENCY: 'consistency',
|
|
25
|
-
CONFLICT: 'conflict',
|
|
26
|
-
DEPENDENCY: 'dependency',
|
|
27
|
-
PROCESS: 'process',
|
|
28
|
-
IPC: 'ipc',
|
|
29
|
-
DATA_INTEGRITY: 'data_integrity',
|
|
30
|
-
CANCELLED: 'cancelled',
|
|
31
|
-
UNKNOWN: 'unknown',
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
export const SIDE_EFFECT_STATE = Object.freeze({
|
|
35
|
-
NONE: 'none',
|
|
36
|
-
NOT_STARTED: 'not_started',
|
|
37
|
-
CONFIRMED_NOT_APPLIED: 'confirmed_not_applied',
|
|
38
|
-
CONFIRMED_APPLIED: 'confirmed_applied',
|
|
39
|
-
PARTIALLY_APPLIED: 'partially_applied',
|
|
40
|
-
UNKNOWN: 'unknown',
|
|
41
|
-
});
|
|
11
|
+
// Compatibility names now project the generated v2 vocabulary instead of
|
|
12
|
+
// maintaining a second recovery-only taxonomy.
|
|
13
|
+
export const FAILURE_CLASS = ERROR_FAILURE_CLASS;
|
|
14
|
+
export const SIDE_EFFECT_STATE = ERROR_SIDE_EFFECT_STATE;
|
|
42
15
|
|
|
43
16
|
export const RECOVERY_SCHEMA = 'agentsam.recovery.v1';
|
|
44
17
|
|
|
@@ -85,6 +58,7 @@ export function inferFailureClass(error = {}) {
|
|
|
85
58
|
* @param {object} [operationContext]
|
|
86
59
|
*/
|
|
87
60
|
export function inferSideEffectState(error = {}, operationContext = {}) {
|
|
61
|
+
if (error.side_effect_state && Object.values(SIDE_EFFECT_STATE).includes(error.side_effect_state)) return error.side_effect_state;
|
|
88
62
|
const op = error.operation || operationContext.operation || {};
|
|
89
63
|
if (op.side_effect_state) return op.side_effect_state;
|
|
90
64
|
if (op.read_only === true || op.side_effect_state === SIDE_EFFECT_STATE.NONE) {
|
|
@@ -148,7 +122,7 @@ export function planRecovery(error = {}, operationContext = {}) {
|
|
|
148
122
|
};
|
|
149
123
|
|
|
150
124
|
// Cancellations are not defects
|
|
151
|
-
if (failure_class === FAILURE_CLASS.CANCELLED) {
|
|
125
|
+
if (failure_class === FAILURE_CLASS.CANCELLED || failure_class === FAILURE_CLASS.CANCELLATION) {
|
|
152
126
|
return freezePlan({
|
|
153
127
|
...plan,
|
|
154
128
|
disposition: 'abort',
|
|
@@ -195,7 +169,7 @@ export function planRecovery(error = {}, operationContext = {}) {
|
|
|
195
169
|
});
|
|
196
170
|
}
|
|
197
171
|
|
|
198
|
-
if (
|
|
172
|
+
if ([FAILURE_CLASS.INPUT, FAILURE_CLASS.VALIDATION, FAILURE_CLASS.CONFLICT].includes(failure_class)) {
|
|
199
173
|
const disposition = failure_class === FAILURE_CLASS.CONFLICT && error.retryable
|
|
200
174
|
? 'retry'
|
|
201
175
|
: 'await_user';
|
|
@@ -30,7 +30,12 @@ export function fromHttpError({ status, body, headers, source, provider, domain
|
|
|
30
30
|
: code === 'RESOURCE_EXHAUSTED' ? ERROR_REASON.RATE_LIMITED
|
|
31
31
|
: code === 'UNAVAILABLE' ? ERROR_REASON.TRANSPORT_UNREACHABLE
|
|
32
32
|
: code === 'DEADLINE_EXCEEDED' ? ERROR_REASON.TRANSPORT_TIMEOUT
|
|
33
|
-
: ERROR_REASON.
|
|
33
|
+
: code === 'INTERNAL' ? ERROR_REASON.INTERNAL
|
|
34
|
+
: code === 'INVALID_ARGUMENT' ? ERROR_REASON.INPUT_INVALID
|
|
35
|
+
: code === 'NOT_FOUND' ? ERROR_REASON.TARGET_NOT_FOUND
|
|
36
|
+
: code === 'FAILED_PRECONDITION' ? ERROR_REASON.PRECONDITION_FAILED
|
|
37
|
+
: code === 'UNIMPLEMENTED' ? ERROR_REASON.UNSUPPORTED_OPERATION
|
|
38
|
+
: ERROR_REASON.UNKNOWN,
|
|
34
39
|
message: candidate?.message || candidate?.error || `HTTP ${status || 500} request failed`,
|
|
35
40
|
retryable: Number(status) === 429 || Number(status) >= 500,
|
|
36
41
|
retry_after_ms: (() => {
|