@inneranimalmedia/agentsam-sdk 2.6.8 → 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.
Files changed (203) hide show
  1. package/README.md +18 -0
  2. package/apps/README.md +25 -0
  3. package/apps/cad-creator/shared/cad/package.json +1 -1
  4. package/apps/client-cms-editor/backend/package.json +5 -7
  5. package/apps/client-cms-editor/frontend/package.json +5 -7
  6. package/apps/client-cms-editor/frontend/tsconfig.json +27 -8
  7. package/apps/client-cms-editor/package-lock.json +8 -8
  8. package/apps/client-cms-editor/package.json +1 -1
  9. package/apps/client-cms-editor/shared/cms/package.json +3 -5
  10. package/docs/LOCAL_ENGINE_COMPUTE_AUDIT_PLAN.md +299 -0
  11. package/docs/architecture/HOOKS-MODELS-SELF-HOSTING-PLAN.md +199 -0
  12. package/examples/hyperspace-demo/index.html +16 -0
  13. package/examples/hyperspace-demo/package.json +21 -0
  14. package/examples/hyperspace-demo/src/main.tsx +160 -0
  15. package/examples/hyperspace-demo/tsconfig.json +9 -0
  16. package/examples/hyperspace-demo/vite.config.ts +24 -0
  17. package/migrations/runtime/0005_agentsam_hooks.sql +87 -0
  18. package/package.json +37 -10
  19. package/packages/agentsam-brand/package.json +1 -1
  20. package/packages/agentsam-brand/src/core/v2/compile.js +1 -1
  21. package/packages/agentsam-brand/src/core/v2/schema.js +1 -1
  22. package/packages/agentsam-contracts/package.json +71 -20
  23. package/packages/agentsam-contracts/scripts/build.mjs +18 -0
  24. package/packages/agentsam-contracts/src/errors.ts +19 -10
  25. package/packages/agentsam-contracts/test/contracts.test.mjs +4 -1
  26. package/packages/agentsam-contracts/test/repository.test.mjs +4 -1
  27. package/packages/agentsam-contracts/tsconfig.build.json +10 -0
  28. package/packages/agentsam-errors/package.json +13 -4
  29. package/packages/agentsam-errors/protocol/agentsam.error.v2.schema.json +821 -0
  30. package/packages/agentsam-errors/protocol/error-catalog.json +3512 -0
  31. package/packages/agentsam-errors/src/envelope.js +63 -11
  32. package/packages/agentsam-errors/src/error.js +6 -0
  33. package/packages/agentsam-errors/src/fingerprint.js +9 -1
  34. package/packages/agentsam-errors/src/normalize.js +51 -6
  35. package/packages/agentsam-errors/src/recovery.js +9 -35
  36. package/packages/agentsam-errors/src/transport.js +6 -1
  37. package/packages/agentsam-errors/src/vocabulary.js +515 -126
  38. package/packages/agentsam-errors/test/catalog-v2.test.mjs +106 -0
  39. package/packages/agentsam-errors/types/index.d.ts +157 -0
  40. package/packages/agentsam-goap/package.json +2 -2
  41. package/packages/agentsam-hooks/README.md +206 -0
  42. package/packages/agentsam-hooks/bin/agentsam-hooks.mjs +64 -0
  43. package/packages/agentsam-hooks/bindings/go/command.go +55 -0
  44. package/packages/agentsam-hooks/bindings/go/errors_generated.go +402 -0
  45. package/packages/agentsam-hooks/bindings/go/go.mod +3 -0
  46. package/packages/agentsam-hooks/bindings/go/hooks.go +285 -0
  47. package/packages/agentsam-hooks/bindings/go/hooks_test.go +48 -0
  48. package/packages/agentsam-hooks/bindings/rust/Cargo.toml +11 -0
  49. package/packages/agentsam-hooks/bindings/rust/src/errors_generated.rs +396 -0
  50. package/packages/agentsam-hooks/bindings/rust/src/lib.rs +397 -0
  51. package/packages/agentsam-hooks/package.json +69 -0
  52. package/packages/agentsam-hooks/schema/manifest.json +54 -0
  53. package/packages/agentsam-hooks/scripts/clean-protocol.mjs +17 -0
  54. package/packages/agentsam-hooks/scripts/sync-protocol.mjs +27 -0
  55. package/packages/agentsam-hooks/src/adapters/agents.js +82 -0
  56. package/packages/agentsam-hooks/src/adapters/callback.js +4 -0
  57. package/packages/agentsam-hooks/src/adapters/capability.js +122 -0
  58. package/packages/agentsam-hooks/src/adapters/command.js +104 -0
  59. package/packages/agentsam-hooks/src/adapters/composite.js +31 -0
  60. package/packages/agentsam-hooks/src/adapters/http.js +58 -0
  61. package/packages/agentsam-hooks/src/adapters/lsp.js +116 -0
  62. package/packages/agentsam-hooks/src/adapters/mcp.js +76 -0
  63. package/packages/agentsam-hooks/src/adapters/provider.js +129 -0
  64. package/packages/agentsam-hooks/src/config.js +143 -0
  65. package/packages/agentsam-hooks/src/contracts.js +284 -0
  66. package/packages/agentsam-hooks/src/errors-generated.js +2732 -0
  67. package/packages/agentsam-hooks/src/index.d.ts +193 -0
  68. package/packages/agentsam-hooks/src/index.js +14 -0
  69. package/packages/agentsam-hooks/src/policy.js +34 -0
  70. package/packages/agentsam-hooks/src/runtime.js +312 -0
  71. package/packages/agentsam-hooks/src/store.js +264 -0
  72. package/packages/agentsam-hooks/test/adapters.test.mjs +216 -0
  73. package/packages/agentsam-hooks/test/runtime.test.mjs +258 -0
  74. package/packages/agentsam-knowledge/package.json +3 -2
  75. package/packages/agentsam-nav/package.json +1 -1
  76. package/packages/agentsam-queue-control/package.json +1 -1
  77. package/packages/agentsam-rapid-rust/src/main.rs +1 -0
  78. package/packages/agentsam-repository/package.json +3 -2
  79. package/packages/agentsam-vault/package.json +8 -5
  80. package/packages/agentsam-workbench/package.json +45 -18
  81. package/packages/connectors/cloudflare/package.json +1 -1
  82. package/packages/heuristic-theme/package.json +1 -1
  83. package/packages/identity/package.json +3 -2
  84. package/packages/identity/tests/lane1-packed-consumer.test.mjs +9 -1
  85. package/packages/providers/completeful/package.json +1 -1
  86. package/packages/theme-church-site/README.md +2 -2
  87. package/packages/theme-church-site/package.json +2 -3
  88. package/packages/theme-church-site/src/index.js +1 -1
  89. package/packages/theme-church-site/test/theme.test.mjs +1 -1
  90. package/packages/theme-companions-site/README.md +2 -2
  91. package/packages/theme-companions-site/package.json +2 -3
  92. package/packages/theme-companions-site/src/index.js +1 -1
  93. package/packages/theme-companions-site/test/theme.test.mjs +1 -1
  94. package/packages/theme-floors-site/README.md +2 -2
  95. package/packages/theme-floors-site/package.json +2 -3
  96. package/packages/theme-floors-site/src/index.js +1 -1
  97. package/packages/theme-floors-site/test/theme.test.mjs +1 -1
  98. package/packages/theme-fuelnfree-site/README.md +2 -2
  99. package/packages/theme-fuelnfree-site/package.json +2 -3
  100. package/packages/theme-fuelnfree-site/src/index.js +1 -1
  101. package/packages/theme-fuelnfree-site/test/theme.test.mjs +1 -1
  102. package/packages/theme-handyman-site/README.md +2 -2
  103. package/packages/theme-handyman-site/package.json +2 -3
  104. package/packages/theme-handyman-site/src/index.js +1 -1
  105. package/packages/theme-handyman-site/test/theme.test.mjs +1 -1
  106. package/packages/theme-insurance-site/README.md +2 -2
  107. package/packages/theme-insurance-site/package.json +2 -3
  108. package/packages/theme-insurance-site/src/index.js +1 -1
  109. package/packages/theme-insurance-site/test/theme.test.mjs +1 -1
  110. package/packages/theme-scenes/package.json +1 -1
  111. package/packages/theme-shinshu-site/README.md +2 -2
  112. package/packages/theme-shinshu-site/package.json +2 -3
  113. package/packages/theme-shinshu-site/src/index.js +1 -1
  114. package/packages/theme-shinshu-site/test/theme.test.mjs +1 -1
  115. package/packages/work-graph/package.json +3 -2
  116. package/protocol/apps/agentsam.app.v1.schema.json +1 -1
  117. package/protocol/apps/agentsam.host-install.v1.schema.json +1 -1
  118. package/protocol/assets/asset-record.v1.schema.json +1 -1
  119. package/protocol/brand/brandpack.v1.schema.json +1 -1
  120. package/protocol/capabilities/capability-manifest.schema.json +1 -1
  121. package/protocol/capabilities/knowledge-search-input.schema.json +1 -0
  122. package/protocol/credentials/issue.v1.schema.json +1 -1
  123. package/protocol/database/agentsam.schema-pack.v1.schema.json +1 -1
  124. package/protocol/database/connection.v1.schema.json +1 -1
  125. package/protocol/embeddings/embedding-profile.v1.schema.json +1 -1
  126. package/protocol/errors/README.md +36 -0
  127. package/protocol/errors/agentsam.error.v2.schema.json +821 -0
  128. package/protocol/errors/error-catalog.json +3506 -158
  129. package/protocol/errors/error-envelope.schema.json +195 -52
  130. package/protocol/errors/recovery.v1.schema.json +1 -1
  131. package/protocol/features/agentsam.feature.v1.schema.json +1 -1
  132. package/protocol/hooks/README.md +18 -0
  133. package/protocol/hooks/agentsam.hook.output.v1.schema.json +27 -0
  134. package/protocol/hooks/agentsam.hook.receipt.v1.schema.json +61 -0
  135. package/protocol/hooks/agentsam.hook.v1.schema.json +35 -0
  136. package/protocol/hooks/agentsam.hooks.config.v1.schema.json +78 -0
  137. package/protocol/local-engine/benchmark.v1.schema.json +14 -0
  138. package/protocol/local-engine/engine.v1.schema.json +17 -0
  139. package/protocol/models/model-inventory-v2.schema.json +1 -1
  140. package/protocol/models/provider-model-snapshot.v1.schema.json +22 -0
  141. package/protocol/rpc/v1/errors.proto +1 -0
  142. package/protocol/runtime/agentsam.runtime.v1.schema.json +1 -1
  143. package/protocol/runtime/workspace-fs.v1.schema.json +1 -1
  144. package/protocol/sam/activity.v1.schema.json +1 -1
  145. package/protocol/sam/answer.v1.schema.json +1 -1
  146. package/protocol/sam/calibration.v1.schema.json +1 -1
  147. package/protocol/sam/decision-receipt.v1.schema.json +1 -1
  148. package/protocol/sam/evaluation.v1.schema.json +1 -1
  149. package/protocol/sam/operation.schema.json +1 -1
  150. package/protocol/sam/outcome.v1.schema.json +1 -1
  151. package/protocol/sam/question.v1.schema.json +1 -1
  152. package/protocol/sam/result.schema.json +1 -1
  153. package/protocol/sam/state.v1.schema.json +1 -1
  154. package/protocol/scoring/scorecard.v1.schema.json +1 -1
  155. package/protocol/skills/agentsam.interaction.v1.schema.json +1 -1
  156. package/protocol/skills/agentsam.skill.v1.schema.json +1 -1
  157. package/protocol/theme-refinery/product-metadata.schema.json +1 -1
  158. package/protocol/theme-refinery/reconciliation-receipt.schema.json +1 -1
  159. package/protocol/ui/icon.v1.schema.json +1 -1
  160. package/python/README.md +20 -0
  161. package/python/agentsam_sdk/errors/__init__.py +4 -0
  162. package/python/agentsam_sdk/errors/vocabulary.py +2730 -0
  163. package/python/agentsam_sdk/hooks/__init__.py +32 -0
  164. package/python/agentsam_sdk/hooks/adapters.py +132 -0
  165. package/python/agentsam_sdk/hooks/contracts.py +121 -0
  166. package/python/agentsam_sdk/hooks/runtime.py +253 -0
  167. package/python/tests/test_hooks.py +115 -0
  168. package/src/agent/responses-runner.js +145 -1
  169. package/src/cli/command-catalog.js +2 -0
  170. package/src/cli.js +19 -0
  171. package/src/commands/app.js +10 -0
  172. package/src/commands/cheat-sheet.js +1 -0
  173. package/src/commands/engine.js +10 -0
  174. package/src/commands/hooks.js +260 -0
  175. package/src/commands/machine.js +71 -38
  176. package/src/commands/models.js +1 -1
  177. package/src/commands/package.js +10 -3
  178. package/src/commands/runtime.js +25 -10
  179. package/src/commands/setup.js +30 -6
  180. package/src/commands/shell.js +114 -9
  181. package/src/commands/terminal.js +20 -8
  182. package/src/errors/contract.js +4 -4
  183. package/src/errors/diagnostic.js +10 -10
  184. package/src/errors/index.js +1 -1
  185. package/src/index.js +52 -0
  186. package/src/indexing/ingest/materials.js +237 -30
  187. package/src/knowledge/service/grpc-codec.js +2 -0
  188. package/src/lib/setup/runtime.js +4 -2
  189. package/src/lib/slash-commands.js +1 -0
  190. package/src/local/runtime-store.js +46 -0
  191. package/src/local-engine/assets.js +37 -0
  192. package/src/local-engine/audit.js +133 -0
  193. package/src/local-engine/benchmark.js +26 -0
  194. package/src/local-engine/contracts.js +101 -0
  195. package/src/local-engine/engines.js +142 -0
  196. package/src/local-engine/index.js +18 -0
  197. package/src/local-engine/runtime.js +39 -0
  198. package/src/models/catalog.js +0 -49
  199. package/src/models/inventory-core.js +69 -0
  200. package/src/plugins/index.js +8 -1
  201. package/src/plugins/registry.js +56 -0
  202. package/src/rpc/generated/errors_pb.js +49 -1
  203. package/src/tools/runtime.js +13 -5
@@ -0,0 +1,258 @@
1
+ import assert from 'node:assert/strict';
2
+ import fs from 'node:fs';
3
+ import http from 'node:http';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import test from 'node:test';
7
+ import {
8
+ HOOK_PROTOCOL_SCHEMA,
9
+ AgentSamHooks,
10
+ HookPermissionError,
11
+ createCallbackHookAdapter,
12
+ createCommandHookAdapter,
13
+ createHookRuntime,
14
+ createHookedCapabilityAdapter,
15
+ createHookedProviderAdapter,
16
+ createHttpHookAdapter,
17
+ normalizeHookEvent,
18
+ normalizeHookOutput,
19
+ } from '../src/index.js';
20
+
21
+ const cwd = process.cwd();
22
+
23
+ test('contract accepts ergonomic event/output aliases but emits canonical fields', () => {
24
+ assert.equal(HOOK_PROTOCOL_SCHEMA, 'agentsam.hook.v1');
25
+ assert.equal(new AgentSamHooks().list().length, 0);
26
+ assert.equal(normalizeHookEvent('onPreToolUse'), 'pre_tool_use');
27
+ assert.deepEqual(normalizeHookOutput('session_start', { modifiedConfig: { auto_compact: false } }), { modified_config: { auto_compact: false } });
28
+ assert.deepEqual(normalizeHookOutput('pre_tool_use', {
29
+ permissionDecision: 'allow',
30
+ modifiedArgs: { timeout: 30 },
31
+ additionalContext: 'bounded context',
32
+ }), {
33
+ permission_decision: 'allow',
34
+ modified_args: { timeout: 30 },
35
+ additional_context: 'bounded context',
36
+ });
37
+ assert.throws(() => normalizeHookOutput('post_tool_use', { permission_decision: 'deny' }), /not_supported/);
38
+ assert.throws(() => normalizeHookOutput('pre_tool_use', { permissionDecison: 'allow' }), /unsupported_hook_output_field/);
39
+ });
40
+
41
+ test('runtime composes modifications in priority order and receipts exclude values', async () => {
42
+ const observed = [];
43
+ const hooks = createHookRuntime({
44
+ onReceipt: (receipt) => observed.push(receipt),
45
+ hooks: {
46
+ pre_tool_use: [
47
+ {
48
+ id: 'second', priority: 20,
49
+ handler: ({ input }) => ({
50
+ permission_decision: 'allow',
51
+ modified_args: { ...input.tool_args, second: true },
52
+ additional_context: 'second context',
53
+ }),
54
+ },
55
+ {
56
+ id: 'first', priority: 10,
57
+ handler: ({ input }) => ({
58
+ permission_decision: 'allow',
59
+ modified_args: { ...input.tool_args, secret: 'not-in-receipt' },
60
+ additional_context: 'first context',
61
+ }),
62
+ },
63
+ ],
64
+ },
65
+ });
66
+ const result = await hooks.dispatch('pre_tool_use', {
67
+ tool_name: 'example.read', tool_args: { value: 1 },
68
+ }, { session_id: 'session-test' }, { cwd });
69
+ assert.deepEqual(result.input.tool_args, { value: 1, secret: 'not-in-receipt', second: true });
70
+ assert.equal(result.output.additional_context, 'first context\n\nsecond context');
71
+ assert.deepEqual(result.receipts.map((row) => row.hook_id), ['first', 'second']);
72
+ assert.equal(JSON.stringify(observed).includes('not-in-receipt'), false);
73
+ });
74
+
75
+ test('session-start config patches compose without discarding prior or base keys', async () => {
76
+ const hooks = createHookRuntime({ hooks: {
77
+ session_start: [
78
+ { id: 'model', priority: 10, handler: () => ({ modified_config: { model_key: 'xai:grok-4' } }) },
79
+ { id: 'effort', priority: 20, handler: () => ({ modified_config: { reasoning_effort: 'high' } }) },
80
+ ],
81
+ } });
82
+ const result = await hooks.dispatch('session_start', { config: { auto_compact: true } });
83
+ assert.deepEqual(result.input.config, {
84
+ auto_compact: true,
85
+ model_key: 'xai:grok-4',
86
+ reasoning_effort: 'high',
87
+ });
88
+ assert.deepEqual(result.output.modified_config, {
89
+ model_key: 'xai:grok-4',
90
+ reasoning_effort: 'high',
91
+ });
92
+ });
93
+
94
+ test('pre hooks fail closed by default while observers fail open', async () => {
95
+ const pre = createHookRuntime({ hooks: { pre_tool_use: { id: 'policy', handler: () => { throw new Error('offline api_key=do-not-record'); } } } });
96
+ const denied = await pre.dispatch('pre_tool_use', { tool_name: 'x', tool_args: {} });
97
+ assert.equal(denied.output.permission_decision, 'deny');
98
+ assert.match(denied.output.permission_decision_reason, /failed closed/);
99
+ assert.doesNotMatch(JSON.stringify(denied), /do-not-record/);
100
+ assert.deepEqual({
101
+ code: denied.receipts[0].error.error_code,
102
+ reason: denied.receipts[0].error.reason,
103
+ domain: denied.receipts[0].error.domain,
104
+ behavior: denied.receipts[0].error.failure_behavior,
105
+ sideEffect: denied.receipts[0].error.side_effect_state,
106
+ retryable: denied.receipts[0].error.retryable,
107
+ }, {
108
+ code: 'INTERNAL', reason: 'hook_handler_failed', domain: 'hook', behavior: 'fail_closed',
109
+ sideEffect: 'not_started', retryable: false,
110
+ });
111
+ assert.match(denied.receipts[0].error.fingerprint, /^err_[a-f0-9]{16}$/);
112
+ assert.equal(denied.receipts[0].native_evidence.message.includes('do-not-record'), false);
113
+
114
+ const post = createHookRuntime({ hooks: { post_tool_use: { id: 'audit', handler: () => { throw new Error('hook_http_timeout:1000'); } } } });
115
+ const allowed = await post.dispatch('post_tool_use', { tool_name: 'x', tool_result: { ok: true } });
116
+ assert.deepEqual(allowed.input.tool_result, { ok: true });
117
+ assert.equal(allowed.errors.length, 1);
118
+ assert.equal(allowed.receipts[0].error.reason, 'hook_http_timeout');
119
+ assert.equal(allowed.receipts[0].error.error_code, 'DEADLINE_EXCEEDED');
120
+ assert.equal(allowed.receipts[0].error.failure_behavior, 'fail_open');
121
+ assert.equal(allowed.receipts[0].error.side_effect_state, 'confirmed_applied');
122
+ assert.equal(allowed.receipts[0].error.retryable, false);
123
+ });
124
+
125
+ test('callback adapter exposes input and invocation without changing wire envelope', async () => {
126
+ const handler = createCallbackHookAdapter((input, invocation, envelope) => ({
127
+ permission_decision: input.tool_name === 'read' ? 'allow' : 'deny',
128
+ metadata: { session: invocation.session_id, schema: envelope.schema },
129
+ }));
130
+ const hooks = createHookRuntime({ hooks: { pre_tool_use: handler } });
131
+ const result = await hooks.dispatch('pre_tool_use', { tool_name: 'read', tool_args: {} }, { session_id: 's1' });
132
+ assert.equal(result.output.permission_decision, 'allow');
133
+ assert.deepEqual(result.output.metadata, { session: 's1', schema: 'agentsam.hook.v1' });
134
+ });
135
+
136
+ test('command adapter uses JSON stdin/stdout without a shell', async () => {
137
+ const script = [
138
+ "let data='';",
139
+ "process.stdin.on('data', c => data += c);",
140
+ "process.stdin.on('end', () => { const row=JSON.parse(data); console.error('diagnostic'); console.log(JSON.stringify({permission_decision: row.input.tool_name === 'safe' ? 'allow' : 'deny'})); });",
141
+ ].join('');
142
+ const adapter = createCommandHookAdapter({ command: process.execPath, args: ['-e', script], cwd, timeout_ms: 2_000 });
143
+ const hooks = createHookRuntime({ hooks: { pre_tool_use: { id: 'external', handler: adapter } } });
144
+ const result = await hooks.dispatch('pre_tool_use', { tool_name: 'safe', tool_args: {} }, {}, { cwd });
145
+ assert.equal(result.output.permission_decision, 'allow');
146
+ });
147
+
148
+ test('HTTP adapter exchanges the canonical envelope with a portable service', async (t) => {
149
+ const server = http.createServer((request, response) => {
150
+ let body = '';
151
+ request.on('data', chunk => { body += chunk; });
152
+ request.on('end', () => {
153
+ const envelope = JSON.parse(body);
154
+ response.setHeader('content-type', 'application/json');
155
+ response.end(JSON.stringify({
156
+ permission_decision: envelope.schema === 'agentsam.hook.v1' ? 'allow' : 'deny',
157
+ }));
158
+ });
159
+ });
160
+ await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
161
+ t.after(() => server.close());
162
+ const address = server.address();
163
+ const handler = createHttpHookAdapter({ url: `http://127.0.0.1:${address.port}/hook`, timeout_ms: 2_000 });
164
+ const hooks = createHookRuntime({ hooks: { pre_tool_use: handler } });
165
+ const result = await hooks.dispatch('pre_tool_use', { tool_name: 'read', tool_args: {} });
166
+ assert.equal(result.output.permission_decision, 'allow');
167
+ });
168
+
169
+ test('capability wrapper enforces ask, argument modification, post transformation, and bounded retry', async () => {
170
+ let attempts = 0;
171
+ const hooks = createHookRuntime({ hooks: {
172
+ pre_tool_use: ({ input }) => ({
173
+ permission_decision: 'ask',
174
+ modified_args: { ...input.tool_args, approved: true },
175
+ }),
176
+ post_tool_use: ({ input }) => ({ modified_result: { ...input.tool_result, transformed: true } }),
177
+ error_occurred: ({ input }) => input.error_context === 'tool_execution'
178
+ ? { error_handling: 'retry', retry_count: 1 }
179
+ : null,
180
+ } });
181
+ const base = {
182
+ toolDescriptors: () => [{ name: 'example.write', input_schema: { type: 'object' } }],
183
+ async invoke(_id, input) {
184
+ attempts += 1;
185
+ if (attempts === 1) throw new Error('temporary');
186
+ return { input };
187
+ },
188
+ };
189
+ const adapter = createHookedCapabilityAdapter(base, {
190
+ hookRuntime: hooks,
191
+ requestPermission: async () => true,
192
+ maxRetries: 1,
193
+ });
194
+ const result = await adapter.invoke('example.write', { value: 1 });
195
+ assert.equal(attempts, 2);
196
+ assert.deepEqual(result, { input: { value: 1, approved: true }, transformed: true });
197
+
198
+ const noApproval = createHookedCapabilityAdapter(base, { hookRuntime: hooks, requestPermission: async () => false });
199
+ await assert.rejects(noApproval.invoke('example.write', {}), HookPermissionError);
200
+ });
201
+
202
+ test('provider wrapper modifies a provider-neutral request and result', async () => {
203
+ const hooks = createHookRuntime({ hooks: {
204
+ pre_model_use: ({ input }) => ({
205
+ permission_decision: 'allow',
206
+ modified_request: { ...input.request, model: 'portable-model', temperature: 0 },
207
+ }),
208
+ post_model_use: ({ input }) => ({ modified_result: { ...input.model_result, output_text: 'redacted' } }),
209
+ } });
210
+ let request;
211
+ const provider = createHookedProviderAdapter({
212
+ provider: 'fixture',
213
+ async create(value) { request = value; return { output_text: 'raw', tool_calls: [] }; },
214
+ async continueWithToolOutputs(value) { return this.create(value); },
215
+ }, { hookRuntime: hooks });
216
+ const result = await provider.create({ model: 'initial', input: 'hello' });
217
+ assert.equal(request.model, 'portable-model');
218
+ assert.equal(request.temperature, 0);
219
+ assert.equal(result.output_text, 'redacted');
220
+ });
221
+
222
+ test('post-hook failures never replay a completed side effect or paid model request', async () => {
223
+ const receipts = [];
224
+ const hooks = createHookRuntime({ onReceipt: (receipt) => receipts.push(receipt), hooks: {
225
+ post_tool_use: { id: 'tool-post', failure_mode: 'error', handler: () => { throw new Error('observer failed'); } },
226
+ post_model_use: { id: 'model-post', failure_mode: 'error', handler: () => { throw new Error('observer failed'); } },
227
+ error_occurred: () => ({ error_handling: 'retry', retry_count: 3 }),
228
+ } });
229
+ let toolCalls = 0;
230
+ const capability = createHookedCapabilityAdapter({
231
+ toolDescriptors: () => [{ name: 'write' }],
232
+ async invoke() { toolCalls += 1; return { ok: true }; },
233
+ }, { hookRuntime: hooks });
234
+ await assert.rejects(capability.invoke('write'), /hook_execution_failed:tool-post/);
235
+ assert.equal(toolCalls, 1);
236
+
237
+ let modelCalls = 0;
238
+ const provider = createHookedProviderAdapter({
239
+ provider: 'fixture',
240
+ async create() { modelCalls += 1; return { output_text: 'paid result', tool_calls: [] }; },
241
+ async continueWithToolOutputs() { throw new Error('unused'); },
242
+ }, { hookRuntime: hooks });
243
+ await assert.rejects(provider.create({ model: 'fixture' }), /hook_execution_failed:model-post/);
244
+ assert.equal(modelCalls, 1);
245
+ const failures = receipts.filter((receipt) => receipt.status === 'failed');
246
+ assert.equal(failures.length, 2);
247
+ for (const receipt of failures) {
248
+ assert.equal(receipt.error.failure_behavior, 'no_replay');
249
+ assert.equal(receipt.error.side_effect_state, 'confirmed_applied');
250
+ assert.equal(receipt.error.retryable, false);
251
+ }
252
+ });
253
+
254
+ test('runtime rejects duplicate hook ids', () => {
255
+ const runtime = createHookRuntime();
256
+ runtime.register('session_start', { id: 'same', handler: () => null });
257
+ assert.throws(() => runtime.register('session_start', { id: 'same', handler: () => null }), /duplicate_hook_id/);
258
+ });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-knowledge",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "description": "Portable AutoRAG discovery, adapter registries, probes, and company routing contracts for AgentSam.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -25,5 +25,6 @@
25
25
  },
26
26
  "files": [
27
27
  "src"
28
- ]
28
+ ],
29
+ "license": "MIT"
29
30
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-nav",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "private": false,
5
5
  "description": "Reusable responsive navigation primitives for AgentSam dashboard-family applications.",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-queue-control",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "description": "Portable AgentSam queue, job-routing, batching, and execution-control primitives with Cloudflare-first adapters.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -14,6 +14,7 @@ const COMPATIBILITY_DATE: &str = "2026-09-27";
14
14
  #[derive(Parser, Debug)]
15
15
  #[command(
16
16
  name = "agentsam-rapid-rust",
17
+ bin_name = "agentsam rust",
17
18
  version,
18
19
  about = "Scaffold, teach, verify, build, and explicitly deploy Cloudflare Rust/Wasm Workers"
19
20
  )]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-repository",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "description": "Portable AgentSam repository identity, Merkle, semantic file metadata, persistence, and repository graph runtime contracts.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -31,5 +31,6 @@
31
31
  },
32
32
  "files": [
33
33
  "src"
34
- ]
34
+ ],
35
+ "license": "MIT"
35
36
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-vault",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "type": "module",
5
5
  "description": "AgentSam credential vault core — contracts, AES-GCM crypto, provider registry, resolver. UI lives in agentsam-key-manager.",
6
6
  "main": "./src/index.js",
@@ -20,13 +20,14 @@
20
20
  "default": "./src/crypto/aes-gcm.js"
21
21
  },
22
22
  "./resolver": "./src/runtime/resolver.js",
23
- "./oauth": "./src/crypto/oauth-envelope.js"
23
+ "./oauth": "./src/crypto/oauth-envelope.js",
24
+ "./package.json": "./package.json"
24
25
  },
25
26
  "scripts": {
26
27
  "test": "node --test tests/*.test.mjs"
27
28
  },
28
29
  "engines": {
29
- "node": ">=20"
30
+ "node": ">=22 <25"
30
31
  },
31
32
  "publishConfig": {
32
33
  "access": "public"
@@ -37,6 +38,8 @@
37
38
  "directory": "packages/agentsam-vault"
38
39
  },
39
40
  "files": [
40
- "src"
41
- ]
41
+ "src",
42
+ "README.md"
43
+ ],
44
+ "license": "MIT"
42
45
  }
@@ -1,28 +1,51 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-workbench",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "description": "Reusable AgentSam workbench primitives for agent threads, composer, browser, terminal and resizable work surfaces.",
5
5
  "type": "module",
6
- "main": "./src/index.ts",
6
+ "main": "./dist/index.js",
7
7
  "exports": {
8
- ".": "./src/index.ts",
9
- "./agent": "./src/agent/index.ts",
10
- "./agent/mini-agentsam.css": "./src/agent/mini-agentsam.css",
11
- "./agent/contextual-composer.css": "./src/agent/contextual-composer.css",
12
- "./agent/tool-permission.css": "./src/agent/tool-permission.css",
13
- "./shell": "./src/shell/index.ts",
14
- "./browser": "./src/browser/index.ts",
15
- "./terminal": "./src/terminal/index.ts",
16
- "./projects": "./src/projects/index.ts",
17
- "./timeline": "./src/timeline/index.ts",
18
- "./project-control.css": "./src/project-control.css"
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ },
12
+ "./agent": {
13
+ "types": "./dist/agent/index.d.ts",
14
+ "import": "./dist/agent/index.js"
15
+ },
16
+ "./shell": {
17
+ "types": "./dist/shell/index.d.ts",
18
+ "import": "./dist/shell/index.js"
19
+ },
20
+ "./browser": {
21
+ "types": "./dist/browser/index.d.ts",
22
+ "import": "./dist/browser/index.js"
23
+ },
24
+ "./terminal": {
25
+ "types": "./dist/terminal/index.d.ts",
26
+ "import": "./dist/terminal/index.js"
27
+ },
28
+ "./projects": {
29
+ "types": "./dist/projects/index.d.ts",
30
+ "import": "./dist/projects/index.js"
31
+ },
32
+ "./timeline": {
33
+ "types": "./dist/timeline/index.d.ts",
34
+ "import": "./dist/timeline/index.js"
35
+ },
36
+ "./agent/mini-agentsam.css": "./dist/agent/mini-agentsam.css",
37
+ "./agent/contextual-composer.css": "./dist/agent/contextual-composer.css",
38
+ "./agent/tool-permission.css": "./dist/agent/tool-permission.css",
39
+ "./project-control.css": "./dist/project-control.css"
19
40
  },
20
41
  "scripts": {
21
- "typecheck": "tsc --noEmit -p tsconfig.json",
22
- "test": "node --test test/*.test.mjs"
42
+ "typecheck": "node scripts/ensure-local-deps.mjs && tsc --noEmit -p tsconfig.json",
43
+ "test": "node --test test/*.test.mjs",
44
+ "build": "node scripts/build.mjs",
45
+ "prepack": "npm run build"
23
46
  },
24
47
  "dependencies": {
25
- "@inneranimalmedia/agentsam-contracts": "2.6.7"
48
+ "@inneranimalmedia/agentsam-contracts": "2.6.10"
26
49
  },
27
50
  "peerDependencies": {
28
51
  "react": ">=18",
@@ -31,6 +54,7 @@
31
54
  "devDependencies": {
32
55
  "@types/react": "^19.2.0",
33
56
  "@types/react-dom": "^19.2.0",
57
+ "esbuild": "^0.28.1",
34
58
  "react": "^19.2.0",
35
59
  "react-dom": "^19.2.0",
36
60
  "typescript": "^5.9.3"
@@ -44,6 +68,9 @@
44
68
  "directory": "packages/agentsam-workbench"
45
69
  },
46
70
  "files": [
47
- "src"
48
- ]
71
+ "dist",
72
+ "README.md"
73
+ ],
74
+ "license": "MIT",
75
+ "types": "./dist/index.d.ts"
49
76
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-connector-cloudflare",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "type": "module",
5
5
  "main": "./src/index.js",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/theme-heuristic",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "description": "Stock AgentSam CMS storefront shell theme contract (heuristic-theme).",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-identity",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "type": "module",
5
5
  "description": "Identity module for @inneranimalmedia/agentsam-sdk (workspace — publish via root SDK)",
6
6
  "agentsam": {
@@ -59,5 +59,6 @@
59
59
  "migrations",
60
60
  "schema",
61
61
  "scripts"
62
- ]
62
+ ],
63
+ "license": "MIT"
63
64
  }
@@ -34,6 +34,14 @@ describe('Lane 1 packed identity consumer proof', () => {
34
34
  const work = fs.mkdtempSync(path.join(os.tmpdir(), 'lane1-pack-'));
35
35
  const artifacts = path.join(work, 'artifacts');
36
36
  fs.mkdirSync(artifacts);
37
+ const errorsRoot = path.join(REPO, 'packages', 'agentsam-errors');
38
+ const errorsPackOut = run('npm', ['pack', '--json', '--ignore-scripts', '--pack-destination', artifacts], errorsRoot);
39
+ const errorsPacked = JSON.parse(errorsPackOut);
40
+ const errorsTarballName = errorsPacked[0]?.filename || errorsPacked.filename;
41
+ assert.ok(errorsTarballName, 'agentsam-errors npm pack must emit a tarball name');
42
+ const errorsTarballDest = path.join(artifacts, errorsTarballName);
43
+ assert.ok(fs.existsSync(errorsTarballDest), errorsTarballDest);
44
+
37
45
  const packOut = run('npm', ['pack', '--json', '--ignore-scripts', '--pack-destination', artifacts], REPO);
38
46
  const packed = JSON.parse(packOut);
39
47
  const tarballName = packed[0]?.filename || packed.filename;
@@ -54,7 +62,7 @@ describe('Lane 1 packed identity consumer proof', () => {
54
62
  );
55
63
  run(
56
64
  'npm',
57
- ['install', tarballDest, '--ignore-scripts', '--no-audit', '--no-fund'],
65
+ ['install', errorsTarballDest, tarballDest, '--ignore-scripts', '--no-audit', '--no-fund'],
58
66
  consumer,
59
67
  );
60
68
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-provider-completeful",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "private": false,
5
5
  "description": "Portable Completeful provider adapter and AgentSam tool definitions.",
6
6
  "type": "module",
@@ -1,10 +1,10 @@
1
- # @inneranimalmedia/theme-church-site
1
+ # @inneranimalmedia/theme-cypress
2
2
 
3
3
  Installable AgentSam theme: **New Iberia Church of Christ**.
4
4
 
5
5
  Gallery preview source: `apps/theme-gallery-preview/themes/church-site`.
6
6
 
7
7
  ```js
8
- import { createTheme } from "@inneranimalmedia/theme-church-site";
8
+ import { createTheme } from "@inneranimalmedia/theme-cypress";
9
9
  const theme = createTheme();
10
10
  ```
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/theme-cypress",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "description": "Real New Iberia Church of Christ public pages — visit, groups, mission, and giving.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -37,6 +37,5 @@
37
37
  "type": "git",
38
38
  "url": "git+https://github.com/SamPrimeaux/agentsam-sdk.git",
39
39
  "directory": "packages/theme-church-site"
40
- },
41
- "private": true
40
+ }
42
41
  }
@@ -8,7 +8,7 @@ const THEME = {
8
8
  "version": "0.1.0",
9
9
  "kind": "gallery-theme",
10
10
  "icon": "theme",
11
- "package": "@inneranimalmedia/theme-church-site",
11
+ "package": "@inneranimalmedia/theme-cypress",
12
12
  "category": "Community",
13
13
  "industries": [
14
14
  "Church",
@@ -8,7 +8,7 @@ test('church-site theme package exports harvested (not installable) contract', (
8
8
  assert.equal(theme.installable, false);
9
9
  assert.equal(theme.lineage, "nic");
10
10
  assert.equal(theme.family, "community-faith");
11
- assert.equal(theme.package, "@inneranimalmedia/theme-church-site");
11
+ assert.equal(theme.package, "@inneranimalmedia/theme-cypress");
12
12
  assert.ok(Array.isArray(theme.pages));
13
13
  });
14
14
 
@@ -1,10 +1,10 @@
1
- # @inneranimalmedia/theme-companions-site
1
+ # @inneranimalmedia/theme-violet
2
2
 
3
3
  Installable AgentSam theme: **Companions of Caddo**.
4
4
 
5
5
  Gallery preview source: `apps/theme-gallery-preview/themes/companions-site`.
6
6
 
7
7
  ```js
8
- import { createTheme } from "@inneranimalmedia/theme-companions-site";
8
+ import { createTheme } from "@inneranimalmedia/theme-violet";
9
9
  const theme = createTheme();
10
10
  ```
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/theme-violet",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "description": "Real Companions of Caddo public static surface — mission, campaigns, and involvement paths.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -37,6 +37,5 @@
37
37
  "type": "git",
38
38
  "url": "git+https://github.com/SamPrimeaux/agentsam-sdk.git",
39
39
  "directory": "packages/theme-companions-site"
40
- },
41
- "private": true
40
+ }
42
41
  }
@@ -8,7 +8,7 @@ const THEME = {
8
8
  "version": "0.1.0",
9
9
  "kind": "gallery-theme",
10
10
  "icon": "theme",
11
- "package": "@inneranimalmedia/theme-companions-site",
11
+ "package": "@inneranimalmedia/theme-violet",
12
12
  "category": "Community",
13
13
  "industries": [
14
14
  "Nonprofit",
@@ -8,7 +8,7 @@ test('companions-site theme package exports harvested (not installable) contract
8
8
  assert.equal(theme.installable, false);
9
9
  assert.equal(theme.lineage, "coc");
10
10
  assert.equal(theme.family, "nonprofit-campaign");
11
- assert.equal(theme.package, "@inneranimalmedia/theme-companions-site");
11
+ assert.equal(theme.package, "@inneranimalmedia/theme-violet");
12
12
  assert.ok(Array.isArray(theme.pages));
13
13
  });
14
14
 
@@ -1,10 +1,10 @@
1
- # @inneranimalmedia/theme-floors-site
1
+ # @inneranimalmedia/theme-grove
2
2
 
3
3
  Installable AgentSam theme: **Anything Floors & More**.
4
4
 
5
5
  Gallery preview source: `apps/theme-gallery-preview/themes/floors-site`.
6
6
 
7
7
  ```js
8
- import { createTheme } from "@inneranimalmedia/theme-floors-site";
8
+ import { createTheme } from "@inneranimalmedia/theme-grove";
9
9
  const theme = createTheme();
10
10
  ```
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/theme-grove",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "description": "Real Anything Floors & More public site — services, gallery, process, and contact.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -37,6 +37,5 @@
37
37
  "type": "git",
38
38
  "url": "git+https://github.com/SamPrimeaux/agentsam-sdk.git",
39
39
  "directory": "packages/theme-floors-site"
40
- },
41
- "private": true
40
+ }
42
41
  }
@@ -8,7 +8,7 @@ const THEME = {
8
8
  "version": "0.1.0",
9
9
  "kind": "gallery-theme",
10
10
  "icon": "theme",
11
- "package": "@inneranimalmedia/theme-floors-site",
11
+ "package": "@inneranimalmedia/theme-grove",
12
12
  "category": "Services",
13
13
  "industries": [
14
14
  "Contractor",