@amalgm/tools 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/PURPOSE.md +87 -0
  2. package/README.md +62 -0
  3. package/dist/api-driver.d.ts +3 -0
  4. package/dist/api-driver.js +92 -0
  5. package/dist/artifact-files.d.ts +28 -0
  6. package/dist/artifact-files.js +115 -0
  7. package/dist/artifacts.d.ts +66 -0
  8. package/dist/artifacts.js +112 -0
  9. package/dist/bin/mcp.d.ts +2 -0
  10. package/dist/bin/mcp.js +13 -0
  11. package/dist/bin/tools.d.ts +2 -0
  12. package/dist/bin/tools.js +3 -0
  13. package/dist/cli-driver.d.ts +3 -0
  14. package/dist/cli-driver.js +52 -0
  15. package/dist/cli.d.ts +13 -0
  16. package/dist/cli.js +123 -0
  17. package/dist/definition.d.ts +7 -0
  18. package/dist/definition.js +170 -0
  19. package/dist/ids.d.ts +7 -0
  20. package/dist/ids.js +38 -0
  21. package/dist/index.d.ts +9 -0
  22. package/dist/index.js +7 -0
  23. package/dist/input.d.ts +4 -0
  24. package/dist/input.js +43 -0
  25. package/dist/mcp-server.d.ts +18 -0
  26. package/dist/mcp-server.js +61 -0
  27. package/dist/mcp.d.ts +9 -0
  28. package/dist/mcp.js +95 -0
  29. package/dist/module.d.ts +3 -0
  30. package/dist/module.js +22 -0
  31. package/dist/process.d.ts +22 -0
  32. package/dist/process.js +46 -0
  33. package/dist/query.d.ts +23 -0
  34. package/dist/query.js +36 -0
  35. package/dist/results.d.ts +6 -0
  36. package/dist/results.js +27 -0
  37. package/dist/schema.d.ts +3 -0
  38. package/dist/schema.js +26 -0
  39. package/dist/secrets.d.ts +3 -0
  40. package/dist/secrets.js +13 -0
  41. package/dist/selection.d.ts +10 -0
  42. package/dist/selection.js +18 -0
  43. package/dist/store.d.ts +17 -0
  44. package/dist/store.js +96 -0
  45. package/dist/toolbox.d.ts +46 -0
  46. package/dist/toolbox.js +204 -0
  47. package/dist/types.d.ts +172 -0
  48. package/dist/types.js +1 -0
  49. package/dist/updates.d.ts +7 -0
  50. package/dist/updates.js +57 -0
  51. package/docs/ENGINE_INTEGRATION.md +57 -0
  52. package/package.json +57 -0
@@ -0,0 +1,172 @@
1
+ import type { Writable } from 'node:stream';
2
+ type JsonSchema = {
3
+ type: 'object';
4
+ properties?: Record<string, {
5
+ type?: string;
6
+ description?: string;
7
+ [key: string]: unknown;
8
+ }>;
9
+ required?: string[];
10
+ additionalProperties?: boolean;
11
+ description?: string;
12
+ [key: string]: unknown;
13
+ };
14
+ type ToolType = 'cli' | 'api' | 'mcp';
15
+ type Origin = 'user' | 'catalog' | 'system';
16
+ type Status = 'enabled' | 'disabled';
17
+ type SecretReferences = Record<string, string>;
18
+ interface BaseSource {
19
+ timeoutMs?: number;
20
+ maxOutputBytes?: number;
21
+ }
22
+ interface CliSource extends BaseSource {
23
+ type: 'cli';
24
+ command: string;
25
+ args?: string[];
26
+ cwd?: string;
27
+ inputMode?: 'json-stdin' | 'argv' | 'none';
28
+ outputMode?: 'json' | 'text';
29
+ secretEnv?: SecretReferences;
30
+ }
31
+ interface ApiSource extends BaseSource {
32
+ type: 'api';
33
+ baseUrl: string;
34
+ secretHeaders?: SecretReferences;
35
+ }
36
+ interface McpSource extends BaseSource {
37
+ type: 'mcp';
38
+ transport: 'http' | 'sse' | 'stdio' | 'host';
39
+ url?: string;
40
+ command?: string;
41
+ args?: string[];
42
+ cwd?: string;
43
+ serverName?: string;
44
+ secretHeaders?: SecretReferences;
45
+ secretEnv?: SecretReferences;
46
+ }
47
+ type ToolSource = CliSource | ApiSource | McpSource;
48
+ interface CliTarget {
49
+ args?: string[];
50
+ }
51
+ interface ApiTarget {
52
+ method: string;
53
+ path: string;
54
+ }
55
+ interface McpTarget {
56
+ name: string;
57
+ }
58
+ type ActionTarget = CliTarget | ApiTarget | McpTarget;
59
+ interface ActionDefinition {
60
+ name: string;
61
+ id?: string;
62
+ displayName?: string;
63
+ description?: string;
64
+ inputSchema?: JsonSchema;
65
+ outputSchema?: Record<string, unknown>;
66
+ status?: Status;
67
+ target?: ActionTarget;
68
+ policy?: Record<string, unknown>;
69
+ metadata?: Record<string, unknown>;
70
+ }
71
+ interface ToolDefinition {
72
+ id: string;
73
+ name: string;
74
+ description?: string;
75
+ owner?: string;
76
+ origin?: Origin;
77
+ status?: Status;
78
+ source: ToolSource;
79
+ actions?: ActionDefinition[];
80
+ display?: Record<string, unknown>;
81
+ policy?: Record<string, unknown>;
82
+ metadata?: Record<string, unknown>;
83
+ }
84
+ interface ToolQuery {
85
+ type?: ToolType;
86
+ owner?: string;
87
+ origin?: Origin;
88
+ origins?: Origin[];
89
+ status?: Status;
90
+ }
91
+ type ToolPatch = Omit<Partial<ToolDefinition>, 'id' | 'source'> & {
92
+ source?: Partial<CliSource> | Partial<ApiSource> | Partial<McpSource>;
93
+ };
94
+ type ActionPatch = Omit<Partial<ActionDefinition>, 'id'>;
95
+ interface ToolRecord extends Omit<ToolDefinition, 'actions'> {
96
+ origin: Origin;
97
+ status: Status;
98
+ owner: string;
99
+ createdAt: string;
100
+ updatedAt: string;
101
+ }
102
+ interface ActionRecord extends Omit<ActionDefinition, 'id' | 'status' | 'inputSchema'> {
103
+ id: string;
104
+ toolId: string;
105
+ status: Status;
106
+ inputSchema: JsonSchema;
107
+ createdAt: string;
108
+ updatedAt: string;
109
+ }
110
+ interface Catalog {
111
+ version: 1;
112
+ revision: number;
113
+ tools: ToolRecord[];
114
+ actions: ActionRecord[];
115
+ }
116
+ interface ApplyResult {
117
+ tool: ToolRecord;
118
+ actions: ActionRecord[];
119
+ }
120
+ interface Loadout {
121
+ toolIds: string[];
122
+ }
123
+ type LoadoutInput = Loadout | string[];
124
+ interface ToolResult {
125
+ content: Array<{
126
+ type: 'text';
127
+ text: string;
128
+ }>;
129
+ structuredContent?: unknown;
130
+ isError?: boolean;
131
+ truncated?: boolean;
132
+ }
133
+ type SecretResolver = (reference: string) => string | undefined | Promise<string | undefined>;
134
+ interface CallOptions {
135
+ loadout?: LoadoutInput;
136
+ signal?: AbortSignal;
137
+ resolveSecret?: SecretResolver;
138
+ context?: unknown;
139
+ }
140
+ interface DriverCall {
141
+ tool: ToolRecord;
142
+ action: ActionRecord;
143
+ input: Record<string, unknown>;
144
+ options: CallOptions;
145
+ }
146
+ interface ToolDriver {
147
+ type: ToolType;
148
+ supports?(tool: ToolRecord): boolean;
149
+ call(request: DriverCall): Promise<ToolResult>;
150
+ }
151
+ interface ToolboxOptions {
152
+ stateDir?: string;
153
+ databaseFile?: string;
154
+ systemTools?: ToolDefinition[];
155
+ drivers?: ToolDriver[];
156
+ onChange?: (catalog: Catalog) => void | Promise<void>;
157
+ }
158
+ interface McpTool {
159
+ name: string;
160
+ description: string;
161
+ inputSchema: JsonSchema;
162
+ handler(input?: Record<string, unknown>): Promise<ToolResult>;
163
+ }
164
+ interface McpOptions extends CallOptions {
165
+ includeManagement?: boolean;
166
+ }
167
+ interface CliIo {
168
+ stdout?: Writable;
169
+ stderr?: Writable;
170
+ toolbox?: import('./toolbox.js').Toolbox;
171
+ }
172
+ 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, };
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { Toolbox } from './toolbox.js';
2
+ import type { ActionDefinition, ActionPatch, ActionRecord, ApplyResult, ToolPatch } from './types.js';
3
+ type UpdatePort = Pick<Toolbox, 'action' | 'apply' | 'get'>;
4
+ declare function updateTool(toolbox: UpdatePort, toolId: string, patch: ToolPatch): Promise<ApplyResult>;
5
+ declare function upsertAction(toolbox: UpdatePort, toolId: string, definition: ActionDefinition): Promise<ActionRecord>;
6
+ declare function updateAction(toolbox: UpdatePort, actionId: string, patch: ActionPatch): Promise<ActionRecord>;
7
+ export { updateAction, updateTool, upsertAction };
@@ -0,0 +1,57 @@
1
+ function actionDefinition(action) {
2
+ const { id, toolId: _toolId, createdAt: _createdAt, updatedAt: _updatedAt, ...definition } = action;
3
+ return { ...structuredClone(definition), id };
4
+ }
5
+ function toolDefinition(result) {
6
+ const { createdAt: _createdAt, updatedAt: _updatedAt, ...tool } = result.tool;
7
+ return { ...structuredClone(tool), actions: result.actions.map(actionDefinition) };
8
+ }
9
+ function mergedObject(current, patch) {
10
+ return patch === undefined ? current : { ...(current || {}), ...patch };
11
+ }
12
+ async function updateTool(toolbox, toolId, patch) {
13
+ const current = toolbox.get(toolId);
14
+ if (!current)
15
+ throw new Error(`Unknown tool: ${toolId}`);
16
+ const definition = toolDefinition(current);
17
+ return toolbox.apply({
18
+ ...definition,
19
+ ...patch,
20
+ id: definition.id,
21
+ source: mergedObject(definition.source, patch.source),
22
+ display: mergedObject(definition.display, patch.display),
23
+ policy: mergedObject(definition.policy, patch.policy),
24
+ metadata: mergedObject(definition.metadata, patch.metadata),
25
+ actions: patch.actions === undefined ? definition.actions : patch.actions,
26
+ });
27
+ }
28
+ async function upsertAction(toolbox, toolId, definition) {
29
+ const current = toolbox.get(toolId);
30
+ if (!current)
31
+ throw new Error(`Unknown tool: ${toolId}`);
32
+ const actions = current.actions.map(actionDefinition);
33
+ const canonicalId = `${current.tool.id}.${definition.name}`;
34
+ const index = actions.findIndex((action) => action.id === canonicalId);
35
+ if (index === -1)
36
+ actions.push(definition);
37
+ else
38
+ actions[index] = definition;
39
+ const result = await toolbox.apply({ ...toolDefinition(current), actions });
40
+ return result.actions.find((action) => action.id === canonicalId);
41
+ }
42
+ async function updateAction(toolbox, actionId, patch) {
43
+ const current = toolbox.action(actionId);
44
+ if (!current)
45
+ throw new Error(`Unknown action: ${actionId}`);
46
+ const definition = actionDefinition(current);
47
+ return upsertAction(toolbox, current.toolId, {
48
+ ...definition,
49
+ ...patch,
50
+ id: definition.id,
51
+ name: definition.name,
52
+ target: mergedObject(definition.target, patch.target),
53
+ policy: mergedObject(definition.policy, patch.policy),
54
+ metadata: mergedObject(definition.metadata, patch.metadata),
55
+ });
56
+ }
57
+ export { updateAction, updateTool, upsertAction };
@@ -0,0 +1,57 @@
1
+ # Engine integration
2
+
3
+ `@amalgm/tools` is the canonical Tools and Toolbox product. Amalgm Engine is a
4
+ composition root and must adapt this public service rather than maintain a
5
+ second registry.
6
+
7
+ ## Tools owns
8
+
9
+ - tool and action definition, validation, identity, and persistence;
10
+ - atomic apply, enable, disable, and removal behavior;
11
+ - loadout selection semantics and deterministic MCP action names;
12
+ - CLI and HTTP API execution drivers and output bounds;
13
+ - SDK, CLI, Toolbox management MCP tools, and action MCP projection;
14
+ - the connection projection consumed by an MCP session host.
15
+
16
+ ## Engine owns
17
+
18
+ - first-party action implementations supplied as `systemTools` and drivers;
19
+ - authenticated capability context and the execution-time secret resolver;
20
+ - the long-lived MCP connection/session host;
21
+ - state-event projection, REST shape translation, UI composition, and one-time
22
+ import from Engine's superseded Toolbox tables or JSON file.
23
+
24
+ Agents owns agent records and their loadout ids. Tools treats those ids as
25
+ input to product-owned selection. Neither product is allowed to rewrite the
26
+ other through a Core adapter.
27
+
28
+ Engine adapters call one `Toolbox` instance. They do not write its SQLite
29
+ database or independently normalize, select, name, or execute tool actions.
30
+ An absent loadout must be passed as `undefined`; an explicitly empty loadout
31
+ must be passed as `[]`.
32
+
33
+ For external MCP tools, Engine supplies a `ToolDriver` with type `mcp`. That
34
+ driver delegates to Engine's existing MCP session owner. The Toolbox exposes
35
+ connection definitions through `connections(loadout)` but never starts a
36
+ parallel client or owns the same remote session twice.
37
+
38
+ System tools are injected at construction and remain outside user storage.
39
+ Engine can therefore update its built-in catalog with its own release while
40
+ all standalone Toolbox behavior remains canonical in this package.
41
+
42
+ ## Source flow and completed cutover
43
+
44
+ Engine now consumes Tools as follows:
45
+
46
+ 1. Build this repository.
47
+ 2. Copy generated `dist/`, `PURPOSE.md`, and package metadata into
48
+ `runtime/products/tools/` with a deterministic source manifest.
49
+ 3. Mount the package CLI and MCP definitions over Engine's single Toolbox
50
+ service.
51
+ 4. Import existing records once, preserving canonical ids and status.
52
+ 5. Remove Engine's superseded Toolbox tables after successful import.
53
+
54
+ Product changes begin here. Generated Engine copies are never edited by hand.
55
+ Engine runtime readers and writers use only this product database. The importer
56
+ is the only module allowed to understand the superseded storage shapes, and
57
+ malformed source data blocks destructive cleanup.
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@amalgm/tools",
3
+ "version": "0.1.0",
4
+ "description": "Local-first tool definitions, Toolbox registry, and agent execution surfaces.",
5
+ "license": "UNLICENSED",
6
+ "private": false,
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/amalgm-inc/amalgm-tools.git"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "type": "module",
15
+ "main": "dist/index.js",
16
+ "types": "dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.js"
21
+ },
22
+ "./mcp": {
23
+ "types": "./dist/mcp.d.ts",
24
+ "default": "./dist/mcp.js"
25
+ }
26
+ },
27
+ "bin": {
28
+ "amalgm-tools": "./dist/bin/tools.js",
29
+ "amalgm-tools-mcp": "./dist/bin/mcp.js"
30
+ },
31
+ "files": [
32
+ "docs",
33
+ "dist",
34
+ "PURPOSE.md",
35
+ "README.md"
36
+ ],
37
+ "scripts": {
38
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && tsx scripts/mark-executables.ts",
39
+ "check": "tsx scripts/check-tree.ts && tsc -p tsconfig.json && tsc -p tsconfig.test.json",
40
+ "test": "tsx --test --test-concurrency=1 --test-timeout=30000 test/*.test.ts",
41
+ "verify": "npm run check && npm run build && npm test",
42
+ "prepack": "npm run build"
43
+ },
44
+ "engines": {
45
+ "node": ">=20"
46
+ },
47
+ "dependencies": {
48
+ "@amalgm/core": "^0.1.0",
49
+ "better-sqlite3": "^12.6.2"
50
+ },
51
+ "devDependencies": {
52
+ "@types/better-sqlite3": "^7.6.13",
53
+ "@types/node": "^20.19.43",
54
+ "tsx": "^4.23.1",
55
+ "typescript": "^5.9.3"
56
+ }
57
+ }