@amalgm/tools 0.1.7-main.34436367218 → 0.1.7-main.34746904064

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/PURPOSE.md CHANGED
@@ -133,6 +133,10 @@ locked dependency graph on the supported Node toolchain.
133
133
  when a first-party release currently maps them one-to-one.
134
134
  26. A scoped Toolbox MCP server advertises and calls only the selected loadout;
135
135
  management actions are included only when the composing host asks for them.
136
+ 27. Preparing an exact catalog revision captures a read-only loadout whose
137
+ definitions and scope cannot change. Later catalog edits affect future
138
+ preparation; already prepared calls use their captured definitions and the
139
+ host's current credential and execution effects.
136
140
 
137
141
  ## Predictable behavior
138
142
 
package/dist/index.d.ts CHANGED
@@ -14,4 +14,5 @@ export type { EmailDelivery, EmailDeliveryReceipt, EmailNotificationRequest, Not
14
14
  export { createProxyEmailDelivery } from './proxy-email.js';
15
15
  export type { ProxyEmailDeliveryOptions } from './proxy-email.js';
16
16
  export { Toolbox } from './toolbox.js';
17
+ export type { ToolboxView as PreparedToolbox } from './toolbox-view.js';
17
18
  export type * from './types.js';
@@ -1,6 +1,7 @@
1
1
  import readline from 'node:readline';
2
2
  import type { Readable, Writable } from 'node:stream';
3
3
  import { Toolbox } from './toolbox.js';
4
+ import type { ToolboxView } from './toolbox-view.js';
4
5
  import type { McpOptions, ToolboxOptions } from './types.js';
5
6
  interface Request {
6
7
  jsonrpc?: string;
@@ -8,11 +9,11 @@ interface Request {
8
9
  method: string;
9
10
  params?: Record<string, any>;
10
11
  }
11
- declare function createMcpServer(options?: ToolboxOptions & {
12
- toolbox?: Toolbox;
12
+ declare function createMcpServer<T extends Toolbox | ToolboxView = Toolbox>(options?: ToolboxOptions & {
13
+ toolbox?: T;
13
14
  mcp?: McpOptions;
14
15
  }): {
15
- toolbox: Toolbox;
16
+ toolbox: T;
16
17
  handle: (request: Request) => Promise<unknown>;
17
18
  start: (input?: Readable, output?: Writable) => readline.Interface;
18
19
  };
package/dist/mcp.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import type { Toolbox } from './toolbox.js';
2
+ import type { ToolboxView } from './toolbox-view.js';
2
3
  import type { JsonSchema, McpOptions, McpTool } from './types.js';
3
4
  declare function portable(schema: JsonSchema): JsonSchema;
4
5
  declare function managementToolDescriptors(): Array<Omit<McpTool, 'handler'>>;
5
6
  declare function managementTools(toolbox: Toolbox): McpTool[];
6
- declare function actionTools(toolbox: Toolbox, options?: McpOptions): McpTool[];
7
- declare function createMcpTools(toolbox: Toolbox, options?: McpOptions): McpTool[];
8
- declare function findMcpTool(toolbox: Toolbox, name: string, options?: McpOptions): McpTool | null;
9
- declare function callMcpTool(toolbox: Toolbox, name: string, input?: Record<string, unknown>, options?: McpOptions): Promise<import("./types.js").ToolResult>;
7
+ declare function actionTools(toolbox: Toolbox | ToolboxView, options?: McpOptions): McpTool[];
8
+ declare function createMcpTools(toolbox: Toolbox | ToolboxView, options?: McpOptions): McpTool[];
9
+ declare function findMcpTool(toolbox: Toolbox | ToolboxView, name: string, options?: McpOptions): McpTool | null;
10
+ declare function callMcpTool(toolbox: Toolbox | ToolboxView, name: string, input?: Record<string, unknown>, options?: McpOptions): Promise<import("./types.js").ToolResult>;
10
11
  export { actionTools, callMcpTool, createMcpTools, findMcpTool, managementTools, managementToolDescriptors, portable, };
package/dist/mcp.js CHANGED
@@ -90,6 +90,9 @@ function actionTools(toolbox, options = {}) {
90
90
  }));
91
91
  }
92
92
  function createMcpTools(toolbox, options = {}) {
93
+ if (options.includeManagement !== false && !('apply' in toolbox)) {
94
+ throw new Error('A prepared Toolbox does not expose management actions');
95
+ }
93
96
  return [
94
97
  ...(options.includeManagement === false ? [] : managementTools(toolbox)),
95
98
  ...actionTools(toolbox, options),
@@ -0,0 +1,3 @@
1
+ import type { Catalog, LoadoutInput } from './types.js';
2
+ /** Capture exact definitions; a caller cannot expand a prepared loadout later. */
3
+ export declare function preparedCatalog(catalog: Catalog, revisionId: string, loadout: LoadoutInput): Catalog;
@@ -0,0 +1,25 @@
1
+ import { selected } from './selection.js';
2
+ /** Capture exact definitions; a caller cannot expand a prepared loadout later. */
3
+ export function preparedCatalog(catalog, revisionId, loadout) {
4
+ if (catalog.revisionId !== revisionId) {
5
+ throw new Error(`Toolbox deployment revision changed: expected ${revisionId}, current ${catalog.revisionId}`);
6
+ }
7
+ const ids = new Set(Array.isArray(loadout) ? loadout : loadout.toolIds);
8
+ for (const id of ids) {
9
+ const action = catalog.actions.find((item) => item.id === id);
10
+ const tool = catalog.tools.find((item) => item.id === (action?.toolId || id));
11
+ if (!tool)
12
+ throw new Error(`Selected tool is not installed: ${id}`);
13
+ if (tool.status !== 'enabled')
14
+ throw new Error(`Selected tool is disabled: ${id}`);
15
+ if (action && action.status !== 'enabled')
16
+ throw new Error(`Selected tool action is disabled: ${id}`);
17
+ }
18
+ const actions = selected(catalog, loadout).map(({ action }) => action);
19
+ const owners = new Set(actions.map((action) => action.toolId));
20
+ return structuredClone({
21
+ ...catalog,
22
+ tools: catalog.tools.filter((tool) => ids.has(tool.id) || owners.has(tool.id)),
23
+ actions,
24
+ });
25
+ }
@@ -0,0 +1,2 @@
1
+ import type { ToolboxOptions } from './types.js';
2
+ export declare function defaultDatabase(options: ToolboxOptions): string;
@@ -0,0 +1,18 @@
1
+ import os from 'node:os';
2
+ import path from 'node:path';
3
+ import { resolveProductStateDir } from '@amalgm/core/identity';
4
+ export function defaultDatabase(options) {
5
+ if (options.databaseFile)
6
+ return path.resolve(options.databaseFile);
7
+ // The state-dir LAW lives in @amalgm/core; only the effectful reads
8
+ // (process.env, os.homedir) happen here at the construction boundary.
9
+ // Precedence: AMALGM_TOOLS_DIR, then AMALGM_DIR/toolbox, then the
10
+ // scoped layout <home>/.amalgm/users/<scope>/toolbox.
11
+ const state = options.stateDir || resolveProductStateDir({
12
+ product: 'tools',
13
+ primitive: 'toolbox',
14
+ env: process.env,
15
+ homedir: path.join(os.homedir(), '.amalgm'),
16
+ });
17
+ return path.join(path.resolve(state), 'tools.db');
18
+ }
package/dist/toolbox.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ToolboxView } from './toolbox-view.js';
1
2
  import type { ActionDefinition, ActionPatch, ActionRecord, ApplyResult, CallOptions, Catalog, LoadoutInput, ToolDefinition, ToolboxOptions, ToolDeployment, ToolDeploymentActivation, ToolDeploymentSnapshot, ToolDeploymentSurface, ToolPatch, ToolQuery, ToolRecord, ToolResult } from './types.js';
2
3
  declare class Toolbox {
3
4
  private readonly store;
@@ -12,6 +13,8 @@ declare class Toolbox {
12
13
  tool: ToolRecord;
13
14
  actions: ActionRecord[];
14
15
  }>;
16
+ /** Pin one exact deployment revision and loadout for an execution. */
17
+ prepare(revisionId: string, loadout: LoadoutInput): ToolboxView;
15
18
  query(filters?: ToolQuery): {
16
19
  tool: ToolRecord;
17
20
  actions: ActionRecord[];
package/dist/toolbox.js CHANGED
@@ -1,6 +1,5 @@
1
- import os from 'node:os';
2
1
  import path from 'node:path';
3
- import { resolveProductStateDir } from '@amalgm/core/identity';
2
+ import { defaultDatabase } from './toolbox-state-dir.js';
4
3
  import { apiDriver } from './api-driver.js';
5
4
  import { applyDefinition } from './apply-definition.js';
6
5
  import { ArtifactFiles } from './artifact-files.js';
@@ -9,27 +8,13 @@ import { cliDriver } from './cli-driver.js';
9
8
  import { DeploymentFiles } from './deployment-files.js';
10
9
  import { deploymentRevisionId } from './deployments.js';
11
10
  import { normalizeDefinition } from './definition.js';
11
+ import { preparedCatalog } from './prepared-catalog.js';
12
12
  import { assertMcpNamesUnique, id } from './ids.js';
13
13
  import { Store } from './store.js';
14
14
  import { ToolboxDeployments } from './toolbox-deployments.js';
15
15
  import { ToolboxProjection } from './toolbox-projection.js';
16
16
  import { ToolboxView } from './toolbox-view.js';
17
17
  import { removeAction, updateAction, updateTool, upsertAction } from './updates.js';
18
- function defaultDatabase(options) {
19
- if (options.databaseFile)
20
- return path.resolve(options.databaseFile);
21
- // The state-dir LAW lives in @amalgm/core; only the effectful reads
22
- // (process.env, os.homedir) happen here at the construction boundary.
23
- // Precedence: AMALGM_TOOLS_DIR, then AMALGM_DIR/toolbox, then the
24
- // scoped layout <home>/.amalgm/users/<scope>/toolbox.
25
- const state = options.stateDir || resolveProductStateDir({
26
- product: 'tools',
27
- primitive: 'toolbox',
28
- env: process.env,
29
- homedir: path.join(os.homedir(), '.amalgm'),
30
- });
31
- return path.join(path.resolve(state), 'tools.db');
32
- }
33
18
  class Toolbox {
34
19
  store;
35
20
  deploymentService;
@@ -97,6 +82,11 @@ class Toolbox {
97
82
  return catalog;
98
83
  }
99
84
  list(loadout) { return this.view.list(loadout); }
85
+ /** Pin one exact deployment revision and loadout for an execution. */
86
+ prepare(revisionId, loadout) {
87
+ const catalog = preparedCatalog(this.catalog(), revisionId, loadout);
88
+ return new ToolboxView(() => structuredClone(catalog), new Map(this.drivers));
89
+ }
100
90
  query(filters = {}) { return this.view.query(filters); }
101
91
  callable(loadout, filters = {}) { return this.view.callable(loadout, filters); }
102
92
  get(toolId) { return this.view.get(toolId); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amalgm/tools",
3
- "version": "0.1.7-main.34436367218",
3
+ "version": "0.1.7-main.34746904064",
4
4
  "description": "Local-first tool definitions, Toolbox registry, and agent execution surfaces.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -87,11 +87,11 @@
87
87
  "package.json"
88
88
  ]
89
89
  },
90
- "gitHead": "6cb5d2097ad78d31dedf44872f9b843a8007d225",
90
+ "gitHead": "717394b057c4db6911f9e99e2ebfc8f3d438891a",
91
91
  "amalgmSource": {
92
92
  "repository": "amalgm-inc/amalgm-tools",
93
93
  "branch": "main",
94
- "commit": "6cb5d2097ad78d31dedf44872f9b843a8007d225",
95
- "occurrence": "34436367218"
94
+ "commit": "717394b057c4db6911f9e99e2ebfc8f3d438891a",
95
+ "occurrence": "34746904064"
96
96
  }
97
97
  }