@amalgm/tools 0.1.7-preview.34545371724 → 0.1.7-preview.34547452288

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/dist/cli.d.ts CHANGED
@@ -7,7 +7,12 @@ interface Parsed {
7
7
  loadout?: LoadoutInput;
8
8
  input: Record<string, unknown>;
9
9
  }
10
+ /** One call on the command surface: an MCP tool name and its arguments. */
11
+ interface Call {
12
+ name: string;
13
+ args: Record<string, unknown>;
14
+ }
10
15
  declare function parse(argv: string[]): Parsed;
11
16
  declare function runCli(argv: string[], io?: CliIo): Promise<number>;
12
17
  export { HELP, parse, runCli };
13
- export type { Parsed };
18
+ export type { Call, Parsed };
package/dist/cli.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { createToolboxCommands } from './commands.js';
2
+ import { id, mcpName } from './ids.js';
1
3
  import { loadDefinitions } from './module.js';
2
4
  import { Toolbox } from './toolbox.js';
3
5
  const HELP = `Usage: amalgm-tools [--state-dir DIR] [--loadout IDS] <command>
@@ -50,9 +52,44 @@ function required(value, label) {
50
52
  throw new Error(`${label} is required`);
51
53
  return value;
52
54
  }
55
+ /** Map one parsed command line to its calls; `apply` makes one call per definition. */
56
+ async function calls(parsed) {
57
+ const [first, second] = parsed.args;
58
+ const record = (name, label) => ({ name, args: { id: required(first, label) } });
59
+ switch (parsed.command) {
60
+ case 'apply': {
61
+ const definitions = await loadDefinitions(required(first, 'definition file'));
62
+ return definitions.map((tool) => ({ name: 'toolbox_tool_apply', args: { tool } }));
63
+ }
64
+ case 'list': return [{ name: 'toolbox_tools_selected', args: {} }];
65
+ case 'catalog': return [{ name: 'toolbox_tools_list', args: {} }];
66
+ case 'show': return [record('toolbox_tool_get', 'tool or action id')];
67
+ case 'enable': return [record('toolbox_record_enable', 'record id')];
68
+ case 'disable': return [record('toolbox_record_disable', 'record id')];
69
+ case 'remove': return [record('toolbox_record_remove', 'record id')];
70
+ case 'link': return [{
71
+ name: 'toolbox_tool_link',
72
+ args: { id: required(first, 'tool id'), app_id: required(second, 'app id') },
73
+ }];
74
+ case 'unlink': return [record('toolbox_tool_unlink', 'tool id')];
75
+ case 'run': return [{ name: mcpName({ id: id(first, 'action id') }), args: parsed.input }];
76
+ case 'connections': return [{ name: 'toolbox_mcp_connections', args: {} }];
77
+ default: throw new Error(`Unknown command: ${parsed.command}`);
78
+ }
79
+ }
80
+ function open(io, parsed) {
81
+ if (io.commands)
82
+ return { commands: io.commands, close() { } };
83
+ const toolbox = new Toolbox({ stateDir: parsed.stateDir });
84
+ return { commands: createToolboxCommands(toolbox, parsed.loadout), close: () => toolbox.close() };
85
+ }
53
86
  function write(output, value) {
54
87
  output.write(`${JSON.stringify(value, null, 2)}\n`);
55
88
  }
89
+ function fail(output, error) {
90
+ output.write(`${error instanceof Error ? error.message : String(error)}\n`);
91
+ return 1;
92
+ }
56
93
  async function runCli(argv, io = {}) {
57
94
  const stdout = io.stdout || process.stdout;
58
95
  const stderr = io.stderr || process.stderr;
@@ -61,71 +98,28 @@ async function runCli(argv, io = {}) {
61
98
  parsed = parse(argv);
62
99
  }
63
100
  catch (error) {
64
- stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
65
- return 1;
101
+ return fail(stderr, error);
66
102
  }
67
103
  if (!parsed.command || ['help', '-h', '--help'].includes(parsed.command)) {
68
104
  stdout.write(`${HELP}\n`);
69
105
  return 0;
70
106
  }
71
- const toolbox = io.toolbox || new Toolbox({ stateDir: parsed.stateDir });
72
107
  try {
73
- const recordId = parsed.args[0];
74
- switch (parsed.command) {
75
- case 'apply': {
76
- const definitions = await loadDefinitions(required(recordId, 'definition file'));
77
- const results = [];
78
- for (const definition of definitions)
79
- results.push(await toolbox.apply(definition));
80
- write(stdout, results.length === 1 ? results[0] : results);
81
- break;
82
- }
83
- case 'list':
84
- write(stdout, toolbox.list(parsed.loadout));
85
- break;
86
- case 'catalog':
87
- write(stdout, toolbox.catalog());
88
- break;
89
- case 'show': {
90
- const value = required(recordId, 'tool or action id');
91
- const result = toolbox.get(value) || toolbox.action(value);
92
- if (!result)
93
- throw new Error(`Unknown tool or action: ${value}`);
94
- write(stdout, result);
95
- break;
96
- }
97
- case 'enable':
98
- write(stdout, await toolbox.setStatus(required(recordId, 'record id'), 'enabled'));
99
- break;
100
- case 'disable':
101
- write(stdout, await toolbox.setStatus(required(recordId, 'record id'), 'disabled'));
102
- break;
103
- case 'remove':
104
- write(stdout, await toolbox.remove(required(recordId, 'record id')));
105
- break;
106
- case 'link':
107
- write(stdout, await toolbox.link(required(recordId, 'tool id'), required(parsed.args[1], 'app id')));
108
- break;
109
- case 'unlink':
110
- write(stdout, await toolbox.link(required(recordId, 'tool id'), null));
111
- break;
112
- case 'run':
113
- write(stdout, await toolbox.call(required(recordId, 'action id'), parsed.input, { loadout: parsed.loadout }));
114
- break;
115
- case 'connections':
116
- write(stdout, toolbox.connections(parsed.loadout));
117
- break;
118
- default: throw new Error(`Unknown command: ${parsed.command}`);
108
+ const planned = await calls(parsed);
109
+ const session = open(io, parsed);
110
+ try {
111
+ const results = [];
112
+ for (const call of planned)
113
+ results.push(await session.commands.execute(call.name, call.args));
114
+ write(stdout, results.length === 1 ? results[0] : results);
115
+ }
116
+ finally {
117
+ session.close();
119
118
  }
120
119
  return 0;
121
120
  }
122
121
  catch (error) {
123
- stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
124
- return 1;
125
- }
126
- finally {
127
- if (!io.toolbox)
128
- toolbox.close();
122
+ return fail(stderr, error);
129
123
  }
130
124
  }
131
125
  export { HELP, parse, runCli };
@@ -0,0 +1,27 @@
1
+ import type { Toolbox } from './toolbox.js';
2
+ import type { LoadoutInput } from './types.js';
3
+ /**
4
+ * The one command surface. The CLI speaks only this; a host forwards it to a
5
+ * running runtime's MCP over HTTP, and `createToolboxCommands` runs it against
6
+ * a local Toolbox through that Toolbox's own MCP tools.
7
+ *
8
+ * `name` is an MCP tool name from this package's MCP surface: a management
9
+ * tool (`toolbox_*`, single underscore) or an action tool (`toolbox__<id>`,
10
+ * from `mcpName`). `args` is the MCP `arguments` object for that tool.
11
+ *
12
+ * `execute` resolves to the tool's value, unwrapped from the MCP call result:
13
+ * - any result with `isError: true` rejects with an Error whose message is
14
+ * the result's text content (every `content[].text`, joined by newlines);
15
+ * - a management tool's value is `result.structuredContent` (its text
16
+ * content is the same value as JSON and is never consulted);
17
+ * - an action tool's value is the whole MCP result (`content`,
18
+ * `structuredContent`, `truncated`) exactly as the driver returned it.
19
+ * A remote implementation sends `name`/`args` as an MCP `tools/call` and
20
+ * applies these three rules to the response.
21
+ */
22
+ interface ToolCommands {
23
+ execute(name: string, args: Record<string, unknown>): Promise<unknown>;
24
+ }
25
+ declare function createToolboxCommands(toolbox: Toolbox, loadout?: LoadoutInput): ToolCommands;
26
+ export { createToolboxCommands };
27
+ export type { ToolCommands };
@@ -0,0 +1,15 @@
1
+ import { isActionMcpName } from './ids.js';
2
+ import { callMcpTool } from './mcp.js';
3
+ function unwrap(name, result) {
4
+ if (result.isError)
5
+ throw new Error(result.content.map((item) => item.text).join('\n'));
6
+ return isActionMcpName(name) ? result : result.structuredContent;
7
+ }
8
+ function createToolboxCommands(toolbox, loadout) {
9
+ return {
10
+ async execute(name, args) {
11
+ return unwrap(name, await callMcpTool(toolbox, name, args, { loadout }));
12
+ },
13
+ };
14
+ }
15
+ export { createToolboxCommands };
package/dist/ids.d.ts CHANGED
@@ -3,5 +3,7 @@ declare function id(value: unknown, label?: string, maximumLength?: number): str
3
3
  declare function actionName(value: unknown): string;
4
4
  declare function actionId(toolId: string, name: string): string;
5
5
  declare function mcpName(action: Pick<ActionRecord, 'id'>): string;
6
+ /** Action tools carry the double-underscore prefix; management tools never do. */
7
+ declare function isActionMcpName(name: string): boolean;
6
8
  declare function assertMcpNamesUnique(actions: Pick<ActionRecord, 'id'>[]): void;
7
- export { actionId, actionName, assertMcpNamesUnique, id, mcpName };
9
+ export { actionId, actionName, assertMcpNamesUnique, id, isActionMcpName, mcpName };
package/dist/ids.js CHANGED
@@ -21,8 +21,13 @@ function actionId(toolId, name) {
21
21
  function safeMcpName(value) {
22
22
  return value.replace(/[^A-Za-z0-9_-]+/g, '_').replace(/_+/g, '_');
23
23
  }
24
+ const MCP_ACTION_PREFIX = 'toolbox__';
24
25
  function mcpName(action) {
25
- return `toolbox__${safeMcpName(action.id)}`;
26
+ return `${MCP_ACTION_PREFIX}${safeMcpName(action.id)}`;
27
+ }
28
+ /** Action tools carry the double-underscore prefix; management tools never do. */
29
+ function isActionMcpName(name) {
30
+ return name.startsWith(MCP_ACTION_PREFIX);
26
31
  }
27
32
  function assertMcpNamesUnique(actions) {
28
33
  const names = new Map();
@@ -35,4 +40,4 @@ function assertMcpNamesUnique(actions) {
35
40
  names.set(name, action.id);
36
41
  }
37
42
  }
38
- export { actionId, actionName, assertMcpNamesUnique, id, mcpName };
43
+ export { actionId, actionName, assertMcpNamesUnique, id, isActionMcpName, mcpName };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  export { ArtifactFiles } from './artifact-files.js';
2
2
  export { LEGACY_TOOLBOX_BACKUP_FILE_NAME, LEGACY_TOOLBOX_FILE_NAME, TOOL_ARTIFACT_KIND, TOOL_ARTIFACT_SCHEMA_VERSION, TOOLBOX_INDEX_FILE_NAME, artifactDocument, catalogIndexDocument, isToolArtifactDocument, legacyMigrationPlan, safeToolId, toolboxIndexDocument, userArtifactFileName, } from './artifacts.js';
3
3
  export type { ArtifactFileWrite, LegacyMigrationPlan, ToolArtifactDocument, ToolboxIndexDocument, } from './artifacts.js';
4
+ export { runCli } from './cli.js';
5
+ export { createToolboxCommands } from './commands.js';
6
+ export type { ToolCommands } from './commands.js';
4
7
  export { defineTool, normalizeDefinition } from './definition.js';
5
8
  export { defineHostMcpTool } from './host-mcp-tool.js';
6
9
  export { TOOL_DEPLOYMENT_CONTRACT, TOOL_DEPLOYMENT_KIND, TOOL_DEPLOYMENT_SCHEMA_VERSION, assertToolDeploymentActivation, createToolDeployment, deploymentRevisionId, emptyToolDeploymentSnapshot, } from './deployments.js';
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  export { ArtifactFiles } from './artifact-files.js';
2
2
  export { LEGACY_TOOLBOX_BACKUP_FILE_NAME, LEGACY_TOOLBOX_FILE_NAME, TOOL_ARTIFACT_KIND, TOOL_ARTIFACT_SCHEMA_VERSION, TOOLBOX_INDEX_FILE_NAME, artifactDocument, catalogIndexDocument, isToolArtifactDocument, legacyMigrationPlan, safeToolId, toolboxIndexDocument, userArtifactFileName, } from './artifacts.js';
3
+ export { runCli } from './cli.js';
4
+ export { createToolboxCommands } from './commands.js';
3
5
  export { defineTool, normalizeDefinition } from './definition.js';
4
6
  export { defineHostMcpTool } from './host-mcp-tool.js';
5
7
  export { TOOL_DEPLOYMENT_CONTRACT, TOOL_DEPLOYMENT_KIND, TOOL_DEPLOYMENT_SCHEMA_VERSION, assertToolDeploymentActivation, createToolDeployment, deploymentRevisionId, emptyToolDeploymentSnapshot, } from './deployments.js';
package/dist/mcp.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { Toolbox } from './toolbox.js';
2
2
  import type { JsonSchema, McpOptions, McpTool } from './types.js';
3
3
  declare function portable(schema: JsonSchema): JsonSchema;
4
4
  declare function managementToolDescriptors(): Array<Omit<McpTool, 'handler'>>;
5
- declare function managementTools(toolbox: Toolbox): McpTool[];
5
+ declare function managementTools(toolbox: Toolbox, options?: McpOptions): McpTool[];
6
6
  declare function actionTools(toolbox: Toolbox, options?: McpOptions): McpTool[];
7
7
  declare function createMcpTools(toolbox: Toolbox, options?: McpOptions): McpTool[];
8
8
  declare function findMcpTool(toolbox: Toolbox, name: string, options?: McpOptions): McpTool | null;
package/dist/mcp.js CHANGED
@@ -29,7 +29,12 @@ function managementToolDescriptors() {
29
29
  inputSchema: { type: 'object', properties: {}, additionalProperties: false },
30
30
  },
31
31
  {
32
- name: 'toolbox_tool_get', description: 'Get one tool and its actions.',
32
+ name: 'toolbox_tools_selected',
33
+ description: 'List tools with their selected actions: the loadout, or every enabled action.',
34
+ inputSchema: { type: 'object', properties: {}, additionalProperties: false },
35
+ },
36
+ {
37
+ name: 'toolbox_tool_get', description: 'Get one tool and its actions, or one action.',
33
38
  inputSchema: { type: 'object', properties: idProperty, required: ['id'], additionalProperties: false },
34
39
  },
35
40
  {
@@ -68,14 +73,15 @@ function managementToolDescriptors() {
68
73
  },
69
74
  ];
70
75
  }
71
- function managementTools(toolbox) {
72
- const [list, get, apply, enable, disable, remove, link, unlink, connections] = managementToolDescriptors();
76
+ function managementTools(toolbox, options = {}) {
77
+ const [list, selected, get, apply, enable, disable, remove, link, unlink, connections,] = managementToolDescriptors();
73
78
  return [
74
79
  managed(list, () => toolbox.catalog()),
80
+ managed(selected, () => toolbox.list(options.loadout)),
75
81
  managed(get, ({ id }) => {
76
- const result = toolbox.get(String(id));
82
+ const result = toolbox.get(String(id)) || toolbox.action(String(id));
77
83
  if (!result)
78
- throw new Error(`Unknown tool: ${id}`);
84
+ throw new Error(`Unknown tool or action: ${id}`);
79
85
  return result;
80
86
  }),
81
87
  managed(apply, ({ tool }) => toolbox.apply(tool)),
@@ -84,7 +90,7 @@ function managementTools(toolbox) {
84
90
  managed(remove, ({ id }) => toolbox.remove(String(id))),
85
91
  managed(link, ({ id, app_id }) => toolbox.link(String(id), String(app_id))),
86
92
  managed(unlink, ({ id }) => toolbox.link(String(id), null)),
87
- managed(connections, () => toolbox.connections()),
93
+ managed(connections, () => toolbox.connections(options.loadout)),
88
94
  ];
89
95
  }
90
96
  function actionTools(toolbox, options = {}) {
@@ -104,7 +110,7 @@ function actionTools(toolbox, options = {}) {
104
110
  }
105
111
  function createMcpTools(toolbox, options = {}) {
106
112
  return [
107
- ...(options.includeManagement === false ? [] : managementTools(toolbox)),
113
+ ...(options.includeManagement === false ? [] : managementTools(toolbox, options)),
108
114
  ...actionTools(toolbox, options),
109
115
  ];
110
116
  }
package/dist/types.d.ts CHANGED
@@ -183,7 +183,7 @@ interface McpOptions extends CallOptions {
183
183
  interface CliIo {
184
184
  stdout?: Writable;
185
185
  stderr?: Writable;
186
- toolbox?: import('./toolbox.js').Toolbox;
186
+ commands?: import('./commands.js').ToolCommands;
187
187
  }
188
188
  export type { ActionDefinition, ActionRecord, ActionTarget, ApiSource, ApiTarget, ApplyResult, CallOptions, Catalog, CliIo, CliSource, CliTarget, DriverCall, JsonSchema, Loadout, LoadoutInput, McpOptions, McpSource, McpTarget, McpTool, Origin, SecretResolver, Status, ToolDefinition, ToolDriver, ToolboxOptions, ToolRecord, ToolResult, ToolPatch, ActionPatch, ToolQuery, ToolSource, ToolType, };
189
189
  export type { ToolDeployment, ToolDeploymentActivation, ToolDeploymentSnapshot, ToolDeploymentSurface, } from './deployment-types.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amalgm/tools",
3
- "version": "0.1.7-preview.34545371724",
3
+ "version": "0.1.7-preview.34547452288",
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": "53f469e2ce16c667c6883239cc3f98c0af6943fc",
90
+ "gitHead": "483f1a4def4b39cf8da719182291cf8df3076224",
91
91
  "amalgmSource": {
92
92
  "repository": "amalgm-inc/amalgm-tools",
93
93
  "branch": "preview",
94
- "commit": "53f469e2ce16c667c6883239cc3f98c0af6943fc",
95
- "occurrence": "34545371724"
94
+ "commit": "483f1a4def4b39cf8da719182291cf8df3076224",
95
+ "occurrence": "34547452288"
96
96
  }
97
97
  }