@amalgm/tools 0.1.7-preview.37556891038 → 0.1.7-preview.39065361112
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 +16 -15
- package/README.md +32 -33
- package/dist/artifacts.d.ts +9 -31
- package/dist/artifacts.js +8 -45
- package/dist/http.d.ts +5 -5
- package/dist/http.js +1 -6
- package/dist/index.d.ts +2 -6
- package/dist/index.js +1 -4
- package/dist/mcp-server.d.ts +5 -7
- package/dist/mcp-server.js +4 -26
- package/dist/results.d.ts +1 -4
- package/dist/results.js +1 -9
- package/dist/store.d.ts +0 -3
- package/dist/store.js +0 -13
- package/dist/tool-files.d.ts +40 -0
- package/dist/tool-files.js +136 -0
- package/dist/toolbox-deployments.d.ts +0 -3
- package/dist/toolbox-deployments.js +0 -17
- package/dist/toolbox-projection.d.ts +9 -5
- package/dist/toolbox-projection.js +27 -18
- package/dist/toolbox.d.ts +2 -1
- package/dist/toolbox.js +9 -12
- package/dist/types.d.ts +7 -11
- package/docs/SHELL_INTEGRATION.md +21 -7
- package/package.json +7 -14
- package/skills/tools/SKILL.md +28 -41
- package/dist/artifact-files.d.ts +0 -30
- package/dist/artifact-files.js +0 -123
- package/dist/bin/mcp.d.ts +0 -2
- package/dist/bin/mcp.js +0 -13
- package/dist/bin/tools.d.ts +0 -2
- package/dist/bin/tools.js +0 -3
- package/dist/cli.d.ts +0 -18
- package/dist/cli.js +0 -125
- package/dist/commands.d.ts +0 -27
- package/dist/commands.js +0 -16
- package/dist/deployment-files.d.ts +0 -10
- package/dist/deployment-files.js +0 -38
- package/dist/module.d.ts +0 -3
- package/dist/module.js +0 -22
- package/dist/toolbox-state-dir.d.ts +0 -2
- package/dist/toolbox-state-dir.js +0 -18
package/PURPOSE.md
CHANGED
|
@@ -7,7 +7,7 @@ standalone product or inside Amalgm. It serves people building agents,
|
|
|
7
7
|
automations, and applications that need one small local source of truth for
|
|
8
8
|
CLI, HTTP API, GraphQL, and MCP tools. When the product is healthy, every callable
|
|
9
9
|
action has one stable identity and one owning tool, a selected loadout exposes
|
|
10
|
-
only its granted capabilities, and the SDK,
|
|
10
|
+
only its granted capabilities, and the SDK, MCP, and HTTP surfaces all observe
|
|
11
11
|
and execute the same catalog.
|
|
12
12
|
|
|
13
13
|
Amalgm Shell is the active machine composition root. This repository owns the
|
|
@@ -22,8 +22,8 @@ and parity evidence only.
|
|
|
22
22
|
- A **tool** is a stable provider or connector identity and its execution
|
|
23
23
|
source.
|
|
24
24
|
- An **action** is one model-callable capability owned by exactly one tool.
|
|
25
|
-
- A **Toolbox** is the sole catalog and mutation authority for
|
|
26
|
-
|
|
25
|
+
- A **Toolbox** is the sole catalog and mutation authority for the folders its
|
|
26
|
+
host hands it.
|
|
27
27
|
- A **tool deployment** is one immutable definition of a stable tool identity,
|
|
28
28
|
including its complete authoritative action set; activation appends the
|
|
29
29
|
deployment and moves that tool's current pointer atomically.
|
|
@@ -75,13 +75,13 @@ locked dependency graph on the supported Node toolchain.
|
|
|
75
75
|
2. Tool ids are stable, globally unique within one Toolbox, and never change
|
|
76
76
|
as a side effect of renaming display text.
|
|
77
77
|
3. A tool's portable source of truth is its immutable deployment history and
|
|
78
|
-
current deployment pointer. SQLite tables, WAL files, catalog
|
|
79
|
-
|
|
78
|
+
current deployment pointer. SQLite tables, WAL files, the catalog index, and
|
|
79
|
+
each tool's `.amalgm-tool.json` are projections; SDK, CLI, MCP, HTTP, and UI
|
|
80
80
|
adapters never keep parallel registries.
|
|
81
81
|
4. Applying a semantically changed tool definition mints one deployment and
|
|
82
82
|
atomically activates its complete action set. Applying equal semantics is a
|
|
83
|
-
no-op; rollback and deletion mint new deployments rather than rewriting
|
|
84
|
-
|
|
83
|
+
no-op; rollback and deletion mint new deployments rather than rewriting
|
|
84
|
+
history.
|
|
85
85
|
5. Deleting a tool deletes all of its actions in the same transaction; an
|
|
86
86
|
orphan action can never be observed.
|
|
87
87
|
6. Disabled tools expose and execute no actions. Disabled actions are likewise
|
|
@@ -122,17 +122,19 @@ locked dependency graph on the supported Node toolchain.
|
|
|
122
122
|
official MCP descriptors or expose its explicitly legacy email adapter; it
|
|
123
123
|
never becomes a second durable delivery authority.
|
|
124
124
|
21. Reopening a Toolbox preserves the temporal fields of every semantically
|
|
125
|
-
unchanged system projection already present in its
|
|
126
|
-
|
|
125
|
+
unchanged system projection already present in its index; boot never
|
|
126
|
+
rewrites those bytes merely to stamp the current time.
|
|
127
127
|
22. The Toolbox exposes the versioned `deployment.activate` operation and its
|
|
128
128
|
exact definition through one Live surface; SQLite pages are never part of
|
|
129
129
|
that contract. A received activation materializes locally without echo,
|
|
130
130
|
retries are idempotent, and an existing deployment id can never acquire
|
|
131
131
|
different bytes.
|
|
132
|
-
23.
|
|
133
|
-
|
|
134
|
-
`
|
|
135
|
-
|
|
132
|
+
23. The host hands the Toolbox three folders and Tools never picks one. `root`
|
|
133
|
+
holds one `<Tool Name>/` folder per user tool with `.amalgm-tool.json`,
|
|
134
|
+
immutable `history/<deployment-id>.json` records, and a computer-only
|
|
135
|
+
`.private/`; `dir` holds `tools.db` and `index.json`; `parked` receives a
|
|
136
|
+
deleted tool's `.private/`. A tool's folder follows its name, and deleting
|
|
137
|
+
the tool removes the files Tools wrote there.
|
|
136
138
|
24. A Chat preparation selects one catalog `revisionId` derived from exact
|
|
137
139
|
current deployment ids and system projections. Preparation either resolves
|
|
138
140
|
that exact revision or fails; it never silently substitutes newer tools.
|
|
@@ -174,8 +176,7 @@ locked dependency graph on the supported Node toolchain.
|
|
|
174
176
|
|
|
175
177
|
Applying the same definition twice produces the same catalog and no second
|
|
176
178
|
deployment. Reopening the
|
|
177
|
-
same system projection
|
|
178
|
-
machine. Applying a changed action set replaces the old set atomically.
|
|
179
|
+
same system projection leaves the index bytes unchanged. Applying a changed action set replaces the old set atomically.
|
|
179
180
|
Selecting a whole tool
|
|
180
181
|
grants all of its enabled actions; selecting one action grants only that
|
|
181
182
|
action. Disabling or deleting a tool immediately removes all of its actions
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ into the machine product by `@amalgm/shell`.
|
|
|
8
8
|
```js
|
|
9
9
|
import { defineTool, Toolbox } from '@amalgm/tools';
|
|
10
10
|
|
|
11
|
-
const toolbox = new Toolbox({
|
|
11
|
+
const toolbox = new Toolbox({ root: './toolbox', dir: './.tools', parked: './.tools/parked' });
|
|
12
12
|
await toolbox.apply(defineTool({
|
|
13
13
|
id: 'hello',
|
|
14
14
|
name: 'Hello',
|
|
@@ -29,54 +29,53 @@ const result = await toolbox.call('hello.say', { name: 'Ada' });
|
|
|
29
29
|
toolbox.close();
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
##
|
|
32
|
+
## Folders
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
verbatim when set, then `AMALGM_DIR/toolbox`, then the scoped layout
|
|
37
|
-
`~/.amalgm/users/<scope>/toolbox`. Passing `stateDir` or `databaseFile`
|
|
38
|
-
bypasses resolution entirely.
|
|
39
|
-
|
|
40
|
-
Platform hosts should separate portable deployment documents from local
|
|
41
|
-
coordination state:
|
|
34
|
+
The Toolbox never picks a folder; its host hands it three. In Amalgm, Shell
|
|
35
|
+
passes the user's folders from `@amalgm/core/identity`:
|
|
42
36
|
|
|
43
37
|
```js
|
|
38
|
+
const user = userLayout(userRoot);
|
|
44
39
|
const toolbox = new Toolbox({
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
root: user.toolbox,
|
|
41
|
+
dir: user.computer.tools,
|
|
42
|
+
parked: user.computer.parked,
|
|
47
43
|
});
|
|
48
44
|
```
|
|
49
45
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
```
|
|
47
|
+
<root>/<Tool Name>/.amalgm-tool.json the tool and every action it owns
|
|
48
|
+
<root>/<Tool Name>/history/<id>.json one immutable record per deployment
|
|
49
|
+
<root>/<Tool Name>/.private/ computer-only files for the tool
|
|
50
|
+
<dir>/tools.db the catalog of record
|
|
51
|
+
<dir>/index.json the whole catalog, system tools included
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
A tool's folder is named for the tool and follows a rename; a second tool
|
|
55
|
+
with the same name gets `-2`. An intentional semantic change appends
|
|
56
|
+
`history/<deployment-id>.json` and atomically advances the local head.
|
|
57
|
+
Deleting a tool moves its `.private/` to `<parked>/tool/<id>/` and removes the
|
|
58
|
+
files Tools wrote. `tools.db`, its WAL and `index.json` stay on the computer.
|
|
59
|
+
`catalog()` exposes both a local numeric `revision` for presentation freshness
|
|
60
|
+
and the immutable `revisionId` that Chat must use for preparation.
|
|
56
61
|
|
|
57
62
|
`deploymentSurface()` implements the `amalgm.tools.deployments@1` Live
|
|
58
63
|
surface. Its operation is the shared `deployment.activate` envelope. Remote
|
|
59
64
|
application is idempotent and does not echo; `deploymentSnapshot()` and
|
|
60
65
|
`applyDeploymentSnapshot()` are the hydration/recovery boundary.
|
|
61
66
|
|
|
62
|
-
##
|
|
63
|
-
|
|
64
|
-
```sh
|
|
65
|
-
amalgm-tools apply ./tool.mjs
|
|
66
|
-
amalgm-tools list
|
|
67
|
-
amalgm-tools run hello.say --input '{"name":"Ada"}'
|
|
68
|
-
amalgm-tools disable hello.say
|
|
69
|
-
amalgm-tools link canvas app-3f1c
|
|
70
|
-
amalgm-tools connections
|
|
71
|
-
```
|
|
67
|
+
## App links
|
|
72
68
|
|
|
73
69
|
A tool may belong to an app: `appId` on the tool is the reverse edge of the
|
|
74
70
|
app manifest's `toolIds`, and sharing either side carries the other. The host
|
|
75
71
|
that composes Tools and Apps may pass `environment(tool)` so a linked tool
|
|
76
72
|
runs knowing where its app listens.
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
## MCP
|
|
75
|
+
|
|
76
|
+
`createMcpServer({ toolbox })` from `@amalgm/tools` answers MCP JSON-RPC
|
|
77
|
+
over the one Toolbox the host already holds. The Amalgm runtime serves it at
|
|
78
|
+
`/mcp/tools`, and the `amalgm tools …` command calls it there.
|
|
80
79
|
|
|
81
80
|
## HTTP
|
|
82
81
|
|
|
@@ -84,14 +83,14 @@ newline-delimited MCP stdio.
|
|
|
84
83
|
import { Toolbox } from '@amalgm/tools';
|
|
85
84
|
import { createToolboxHttpServer } from '@amalgm/tools/http';
|
|
86
85
|
|
|
87
|
-
const toolbox = new Toolbox({
|
|
86
|
+
const toolbox = new Toolbox({ root: './toolbox', dir: './.tools', parked: './.tools/parked' });
|
|
88
87
|
const server = createToolboxHttpServer({ toolbox });
|
|
89
88
|
await server.listen(8083);
|
|
90
89
|
```
|
|
91
90
|
|
|
92
91
|
The adapter serves `GET /toolbox`,
|
|
93
92
|
`GET /toolbox/tools?id=...`, and `GET /toolbox/actions?id=...` routes over
|
|
94
|
-
the same live Toolbox used by
|
|
93
|
+
the same live Toolbox used by MCP consumers. `POST /toolbox/tools`
|
|
95
94
|
connects a definition with optional write-only credentials. `PATCH /toolbox/tools`
|
|
96
95
|
with `{ id, status: "disabled" }` disconnects it. `DELETE /toolbox/tools` removes
|
|
97
96
|
it. `POST /toolbox/actions/call` invokes `{ id, input }`.
|
|
@@ -150,7 +149,7 @@ once, and installs that tarball on Linux, macOS and Windows before publication.
|
|
|
150
149
|
`preview` has no checks: a push to it builds, packs and publishes directly.
|
|
151
150
|
The `candidate-main`/`candidate-preview` tags are release-assembly inputs and
|
|
152
151
|
never select installed runtimes. `package.json` declares this owner's gates,
|
|
153
|
-
|
|
152
|
+
peer-only exports and lifecycle permissions. The standalone runner
|
|
154
153
|
under `scripts/release/` is intentionally copied across owners to preserve
|
|
155
154
|
private repository access boundaries. The final publish step uses the `NPM_TOKEN`
|
|
156
155
|
secret in the `npm-release` environment. Where npm trusted publishing is
|
package/dist/artifacts.d.ts
CHANGED
|
@@ -2,14 +2,13 @@ import type { ActionRecord, Catalog, ToolRecord } from './types.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Tool artifact format laws — the portable representation of a tool.
|
|
4
4
|
*
|
|
5
|
-
* One
|
|
6
|
-
* owns together; a file never carries a second tool.
|
|
7
|
-
* documents are the portable source of truth. These
|
|
8
|
-
*
|
|
9
|
-
* Engine/UI readers.
|
|
5
|
+
* One artifact (a tool folder's `.amalgm-tool.json`) holds one current tool
|
|
6
|
+
* and every action it owns together; a file never carries a second tool.
|
|
7
|
+
* Immutable deployment documents are the portable source of truth. These
|
|
8
|
+
* artifacts and the index are derived views of the Toolbox database.
|
|
10
9
|
*
|
|
11
|
-
* Pure laws only: nothing here touches the filesystem. `
|
|
12
|
-
*
|
|
10
|
+
* Pure laws only: nothing here touches the filesystem. `tool-files.ts`
|
|
11
|
+
* writes these documents.
|
|
13
12
|
*
|
|
14
13
|
* DELIBERATE DEVIATION: Engine recognizes system tools by its managed
|
|
15
14
|
* artifact list; this product's system tools are embedder projections
|
|
@@ -20,9 +19,7 @@ import type { ActionRecord, Catalog, ToolRecord } from './types.js';
|
|
|
20
19
|
*/
|
|
21
20
|
declare const TOOL_ARTIFACT_SCHEMA_VERSION = 1;
|
|
22
21
|
declare const TOOL_ARTIFACT_KIND = "amalgm-tool";
|
|
23
|
-
declare const
|
|
24
|
-
declare const LEGACY_TOOLBOX_BACKUP_FILE_NAME = "toolbox.legacy.json";
|
|
25
|
-
declare const TOOLBOX_INDEX_FILE_NAME = "toolbox.index.json";
|
|
22
|
+
declare const TOOLBOX_INDEX_FILE_NAME = "index.json";
|
|
26
23
|
type ArtifactRecord = Record<string, unknown>;
|
|
27
24
|
interface ToolArtifactDocument {
|
|
28
25
|
schemaVersion: typeof TOOL_ARTIFACT_SCHEMA_VERSION;
|
|
@@ -35,21 +32,7 @@ interface ToolboxIndexDocument {
|
|
|
35
32
|
tools: Record<string, unknown>;
|
|
36
33
|
toolActions: Record<string, unknown>;
|
|
37
34
|
}
|
|
38
|
-
interface ArtifactFileWrite {
|
|
39
|
-
fileName: string;
|
|
40
|
-
document: ToolArtifactDocument;
|
|
41
|
-
}
|
|
42
|
-
interface LegacyMigrationPlan {
|
|
43
|
-
migrated: boolean;
|
|
44
|
-
files: ArtifactFileWrite[];
|
|
45
|
-
index: ToolboxIndexDocument | null;
|
|
46
|
-
rename: {
|
|
47
|
-
from: string;
|
|
48
|
-
to: string;
|
|
49
|
-
} | null;
|
|
50
|
-
}
|
|
51
35
|
declare function safeToolId(value: unknown): string;
|
|
52
|
-
declare function userArtifactFileName(toolId: unknown): string;
|
|
53
36
|
declare function artifactDocument(input: {
|
|
54
37
|
tool: ToolRecord;
|
|
55
38
|
actions?: readonly ActionRecord[];
|
|
@@ -59,10 +42,5 @@ declare function toolboxIndexDocument(tools: Record<string, unknown>, toolAction
|
|
|
59
42
|
declare function catalogIndexDocument(catalog: Pick<Catalog, 'tools' | 'actions'>): ToolboxIndexDocument;
|
|
60
43
|
declare function portableRecordSemantic(value: ToolRecord | ActionRecord): string;
|
|
61
44
|
declare function preserveProjectionTime<T extends ToolRecord | ActionRecord>(candidate: T, previous: unknown): T;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
* catalog becomes the index, and the aggregate file is renamed out of the
|
|
65
|
-
* way only after each record has a per-tool replacement. */
|
|
66
|
-
declare function legacyMigrationPlan(legacy: unknown): LegacyMigrationPlan;
|
|
67
|
-
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, portableRecordSemantic, preserveProjectionTime, toolboxIndexDocument, userArtifactFileName, };
|
|
68
|
-
export type { ArtifactFileWrite, LegacyMigrationPlan, ToolArtifactDocument, ToolboxIndexDocument };
|
|
45
|
+
export { TOOL_ARTIFACT_KIND, TOOL_ARTIFACT_SCHEMA_VERSION, TOOLBOX_INDEX_FILE_NAME, artifactDocument, catalogIndexDocument, isToolArtifactDocument, safeToolId, portableRecordSemantic, preserveProjectionTime, toolboxIndexDocument, };
|
|
46
|
+
export type { ToolArtifactDocument, ToolboxIndexDocument };
|
package/dist/artifacts.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tool artifact format laws — the portable representation of a tool.
|
|
3
3
|
*
|
|
4
|
-
* One
|
|
5
|
-
* owns together; a file never carries a second tool.
|
|
6
|
-
* documents are the portable source of truth. These
|
|
7
|
-
*
|
|
8
|
-
* Engine/UI readers.
|
|
4
|
+
* One artifact (a tool folder's `.amalgm-tool.json`) holds one current tool
|
|
5
|
+
* and every action it owns together; a file never carries a second tool.
|
|
6
|
+
* Immutable deployment documents are the portable source of truth. These
|
|
7
|
+
* artifacts and the index are derived views of the Toolbox database.
|
|
9
8
|
*
|
|
10
|
-
* Pure laws only: nothing here touches the filesystem. `
|
|
11
|
-
*
|
|
9
|
+
* Pure laws only: nothing here touches the filesystem. `tool-files.ts`
|
|
10
|
+
* writes these documents.
|
|
12
11
|
*
|
|
13
12
|
* DELIBERATE DEVIATION: Engine recognizes system tools by its managed
|
|
14
13
|
* artifact list; this product's system tools are embedder projections
|
|
@@ -19,9 +18,7 @@
|
|
|
19
18
|
*/
|
|
20
19
|
const TOOL_ARTIFACT_SCHEMA_VERSION = 1;
|
|
21
20
|
const TOOL_ARTIFACT_KIND = 'amalgm-tool';
|
|
22
|
-
const
|
|
23
|
-
const LEGACY_TOOLBOX_BACKUP_FILE_NAME = 'toolbox.legacy.json';
|
|
24
|
-
const TOOLBOX_INDEX_FILE_NAME = 'toolbox.index.json';
|
|
21
|
+
const TOOLBOX_INDEX_FILE_NAME = 'index.json';
|
|
25
22
|
function safeToolId(value) {
|
|
26
23
|
return String(value || '')
|
|
27
24
|
.trim()
|
|
@@ -30,12 +27,6 @@ function safeToolId(value) {
|
|
|
30
27
|
.replace(/\.+/g, '.')
|
|
31
28
|
.replace(/^[._-]+|[._-]+$/g, '');
|
|
32
29
|
}
|
|
33
|
-
function userArtifactFileName(toolId) {
|
|
34
|
-
const id = safeToolId(toolId);
|
|
35
|
-
if (!id)
|
|
36
|
-
throw new Error('tool artifact requires a stable tool id');
|
|
37
|
-
return `tool-${id}.json`;
|
|
38
|
-
}
|
|
39
30
|
function artifactDocument(input) {
|
|
40
31
|
const { tool, actions = [] } = input;
|
|
41
32
|
if (!tool || typeof tool !== 'object' || !safeToolId(tool.id)) {
|
|
@@ -94,32 +85,4 @@ function preserveProjectionTime(candidate, previous) {
|
|
|
94
85
|
return candidate;
|
|
95
86
|
return { ...candidate, createdAt: record.createdAt, updatedAt: record.updatedAt };
|
|
96
87
|
}
|
|
97
|
-
|
|
98
|
-
* plan: every user tool becomes a per-tool artifact write, the whole legacy
|
|
99
|
-
* catalog becomes the index, and the aggregate file is renamed out of the
|
|
100
|
-
* way only after each record has a per-tool replacement. */
|
|
101
|
-
function legacyMigrationPlan(legacy) {
|
|
102
|
-
const parsed = legacy;
|
|
103
|
-
if (!parsed || typeof parsed !== 'object' || !parsed.tools || typeof parsed.tools !== 'object') {
|
|
104
|
-
return { migrated: false, files: [], index: null, rename: null };
|
|
105
|
-
}
|
|
106
|
-
const files = [];
|
|
107
|
-
for (const [rawId, rawTool] of Object.entries(parsed.tools)) {
|
|
108
|
-
const toolId = safeToolId(rawTool?.id || rawId);
|
|
109
|
-
if (!toolId || !rawTool || typeof rawTool !== 'object' || rawTool.origin === 'system')
|
|
110
|
-
continue;
|
|
111
|
-
const actions = Object.values(parsed.toolActions || {})
|
|
112
|
-
.filter((action) => action && action.toolId === toolId);
|
|
113
|
-
files.push({
|
|
114
|
-
fileName: userArtifactFileName(toolId),
|
|
115
|
-
document: artifactDocument({ tool: { ...rawTool, id: toolId }, actions }),
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
return {
|
|
119
|
-
migrated: true,
|
|
120
|
-
files,
|
|
121
|
-
index: toolboxIndexDocument(parsed.tools || {}, parsed.toolActions || {}),
|
|
122
|
-
rename: { from: LEGACY_TOOLBOX_FILE_NAME, to: LEGACY_TOOLBOX_BACKUP_FILE_NAME },
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
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, portableRecordSemantic, preserveProjectionTime, toolboxIndexDocument, userArtifactFileName, };
|
|
88
|
+
export { TOOL_ARTIFACT_KIND, TOOL_ARTIFACT_SCHEMA_VERSION, TOOLBOX_INDEX_FILE_NAME, artifactDocument, catalogIndexDocument, isToolArtifactDocument, safeToolId, portableRecordSemantic, preserveProjectionTime, toolboxIndexDocument, };
|
package/dist/http.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Toolbox } from './toolbox.js';
|
|
2
|
-
import type { Catalog
|
|
1
|
+
import type { Toolbox } from './toolbox.js';
|
|
2
|
+
import type { Catalog } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Toolbox read API.
|
|
5
5
|
*
|
|
@@ -13,7 +13,7 @@ import type { Catalog, ToolboxOptions } from './types.js';
|
|
|
13
13
|
* - domain errors are JSON with status 400; unknown routes are 404.
|
|
14
14
|
*
|
|
15
15
|
* Mutation routes consume current SDK definitions. The authenticated composing
|
|
16
|
-
* host supplies the Toolbox
|
|
16
|
+
* host supplies the one Toolbox it holds; request bodies cannot select one.
|
|
17
17
|
*/
|
|
18
18
|
type Json = Record<string, unknown>;
|
|
19
19
|
interface ToolboxHttpServer {
|
|
@@ -23,8 +23,8 @@ interface ToolboxHttpServer {
|
|
|
23
23
|
close(): Promise<void>;
|
|
24
24
|
}
|
|
25
25
|
declare function catalogDocument(catalog: Catalog): Json;
|
|
26
|
-
declare function createToolboxHttpServer(
|
|
27
|
-
toolbox
|
|
26
|
+
declare function createToolboxHttpServer({ toolbox }: {
|
|
27
|
+
toolbox: Toolbox;
|
|
28
28
|
}): ToolboxHttpServer;
|
|
29
29
|
export { catalogDocument, createToolboxHttpServer };
|
|
30
30
|
export type { ToolboxHttpServer };
|
package/dist/http.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createServer } from 'node:http';
|
|
2
2
|
import { toolboxIndexDocument } from './artifacts.js';
|
|
3
|
-
import { Toolbox } from './toolbox.js';
|
|
4
3
|
import { mutateToolbox } from './http-mutations.js';
|
|
5
4
|
function sourceWithoutType(source) {
|
|
6
5
|
const { type: _type, ...value } = source;
|
|
@@ -37,9 +36,7 @@ async function readBody(req) {
|
|
|
37
36
|
return {};
|
|
38
37
|
return JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
39
38
|
}
|
|
40
|
-
function createToolboxHttpServer(
|
|
41
|
-
const toolbox = options.toolbox ?? new Toolbox(options);
|
|
42
|
-
const ownsToolbox = options.toolbox === undefined;
|
|
39
|
+
function createToolboxHttpServer({ toolbox }) {
|
|
43
40
|
const server = createServer((req, res) => {
|
|
44
41
|
void (async () => {
|
|
45
42
|
const method = req.method ?? 'GET';
|
|
@@ -112,8 +109,6 @@ function createToolboxHttpServer(options = {}) {
|
|
|
112
109
|
close() {
|
|
113
110
|
return new Promise((resolve, reject) => {
|
|
114
111
|
server.close((error) => {
|
|
115
|
-
if (ownsToolbox)
|
|
116
|
-
toolbox.close();
|
|
117
112
|
if (error)
|
|
118
113
|
reject(error);
|
|
119
114
|
else
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
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';
|
|
1
|
+
export { TOOL_ARTIFACT_KIND, TOOL_ARTIFACT_SCHEMA_VERSION, TOOLBOX_INDEX_FILE_NAME, artifactDocument, catalogIndexDocument, isToolArtifactDocument, safeToolId, toolboxIndexDocument, } from './artifacts.js';
|
|
2
|
+
export type { ToolArtifactDocument, ToolboxIndexDocument } from './artifacts.js';
|
|
7
3
|
export { defineTool, normalizeDefinition } from './definition.js';
|
|
8
4
|
export { defineHostMcpTool } from './host-mcp-tool.js';
|
|
9
5
|
export { TOOL_DEPLOYMENT_CONTRACT, TOOL_DEPLOYMENT_KIND, TOOL_DEPLOYMENT_SCHEMA_VERSION, assertToolDeploymentActivation, createToolDeployment, deploymentRevisionId, emptyToolDeploymentSnapshot, } from './deployments.js';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
export {
|
|
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';
|
|
1
|
+
export { TOOL_ARTIFACT_KIND, TOOL_ARTIFACT_SCHEMA_VERSION, TOOLBOX_INDEX_FILE_NAME, artifactDocument, catalogIndexDocument, isToolArtifactDocument, safeToolId, toolboxIndexDocument, } from './artifacts.js';
|
|
5
2
|
export { defineTool, normalizeDefinition } from './definition.js';
|
|
6
3
|
export { defineHostMcpTool } from './host-mcp-tool.js';
|
|
7
4
|
export { TOOL_DEPLOYMENT_CONTRACT, TOOL_DEPLOYMENT_KIND, TOOL_DEPLOYMENT_SCHEMA_VERSION, assertToolDeploymentActivation, createToolDeployment, deploymentRevisionId, emptyToolDeploymentSnapshot, } from './deployments.js';
|
package/dist/mcp-server.d.ts
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { Readable, Writable } from 'node:stream';
|
|
3
|
-
import { Toolbox } from './toolbox.js';
|
|
1
|
+
import type { Toolbox } from './toolbox.js';
|
|
4
2
|
import type { ToolboxView } from './toolbox-view.js';
|
|
5
|
-
import type { McpOptions
|
|
3
|
+
import type { McpOptions } from './types.js';
|
|
6
4
|
interface Request {
|
|
7
5
|
jsonrpc?: string;
|
|
8
6
|
id?: string | number;
|
|
9
7
|
method: string;
|
|
10
8
|
params?: Record<string, any>;
|
|
11
9
|
}
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
/** MCP JSON-RPC over the one Toolbox (or prepared view) the host already holds. */
|
|
11
|
+
declare function createMcpServer<T extends Toolbox | ToolboxView>(options: {
|
|
12
|
+
toolbox: T;
|
|
14
13
|
mcp?: McpOptions;
|
|
15
14
|
}): {
|
|
16
15
|
toolbox: T;
|
|
17
16
|
handle: (request: Request, context?: unknown) => Promise<unknown>;
|
|
18
|
-
start: (input?: Readable, output?: Writable) => readline.Interface;
|
|
19
17
|
};
|
|
20
18
|
export { createMcpServer };
|
package/dist/mcp-server.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import readline from 'node:readline';
|
|
2
1
|
import { callMcpTool, createMcpTools } from './mcp.js';
|
|
3
|
-
import { Toolbox } from './toolbox.js';
|
|
4
2
|
function descriptor(tool) {
|
|
5
3
|
const { handler, ...definition } = tool;
|
|
6
4
|
return definition;
|
|
7
5
|
}
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
/** MCP JSON-RPC over the one Toolbox (or prepared view) the host already holds. */
|
|
7
|
+
function createMcpServer(options) {
|
|
8
|
+
const { toolbox } = options;
|
|
10
9
|
const mcpOptions = options.mcp || {};
|
|
11
10
|
/** Context is supplied by the trusted transport host, never parsed from MCP input. */
|
|
12
11
|
async function handle(request, context) {
|
|
@@ -37,27 +36,6 @@ function createMcpServer(options = {}) {
|
|
|
37
36
|
return undefined;
|
|
38
37
|
throw Object.assign(new Error(`Method not found: ${request.method}`), { code: -32601 });
|
|
39
38
|
}
|
|
40
|
-
|
|
41
|
-
const lines = readline.createInterface({ input, crlfDelay: Infinity });
|
|
42
|
-
lines.on('line', async (line) => {
|
|
43
|
-
let request;
|
|
44
|
-
try {
|
|
45
|
-
request = JSON.parse(line);
|
|
46
|
-
const result = await handle(request);
|
|
47
|
-
if (request.id !== undefined && result !== undefined)
|
|
48
|
-
output.write(`${JSON.stringify({ jsonrpc: '2.0', id: request.id, result })}\n`);
|
|
49
|
-
}
|
|
50
|
-
catch (error) {
|
|
51
|
-
if (request?.id === undefined)
|
|
52
|
-
return;
|
|
53
|
-
output.write(`${JSON.stringify({
|
|
54
|
-
jsonrpc: '2.0', id: request.id,
|
|
55
|
-
error: { code: error?.code || -32603, message: error instanceof Error ? error.message : String(error) },
|
|
56
|
-
})}\n`);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
return lines;
|
|
60
|
-
}
|
|
61
|
-
return { toolbox, handle, start };
|
|
39
|
+
return { toolbox, handle };
|
|
62
40
|
}
|
|
63
41
|
export { createMcpServer };
|
package/dist/results.d.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { ToolResult } from './types.js';
|
|
2
2
|
declare function textResult(value: unknown): ToolResult;
|
|
3
3
|
declare function structuredResult(value: unknown): ToolResult;
|
|
4
|
-
/** The inverse of `structuredResult`'s envelope: a value that is not a plain
|
|
5
|
-
* object is carried as `{ result: value }`, and this returns it unchanged. */
|
|
6
|
-
declare function structuredValue(structuredContent: ToolResult['structuredContent']): unknown;
|
|
7
4
|
declare function errorResult(value: unknown): ToolResult;
|
|
8
5
|
declare function boundedResult(result: ToolResult, maximum: number): ToolResult;
|
|
9
|
-
export { boundedResult, errorResult, structuredResult,
|
|
6
|
+
export { boundedResult, errorResult, structuredResult, textResult };
|
package/dist/results.js
CHANGED
|
@@ -7,14 +7,6 @@ function structuredResult(value) {
|
|
|
7
7
|
? value : { result: value ?? null };
|
|
8
8
|
return { ...textResult(value), structuredContent };
|
|
9
9
|
}
|
|
10
|
-
/** The inverse of `structuredResult`'s envelope: a value that is not a plain
|
|
11
|
-
* object is carried as `{ result: value }`, and this returns it unchanged. */
|
|
12
|
-
function structuredValue(structuredContent) {
|
|
13
|
-
return structuredContent
|
|
14
|
-
&& Object.keys(structuredContent).length === 1
|
|
15
|
-
&& 'result' in structuredContent
|
|
16
|
-
? structuredContent.result : structuredContent;
|
|
17
|
-
}
|
|
18
10
|
function errorResult(value) {
|
|
19
11
|
return { ...textResult(value instanceof Error ? value.message : value), isError: true };
|
|
20
12
|
}
|
|
@@ -29,4 +21,4 @@ function boundedResult(result, maximum) {
|
|
|
29
21
|
...(result.isError ? { isError: true } : {}), truncated: true,
|
|
30
22
|
};
|
|
31
23
|
}
|
|
32
|
-
export { boundedResult, errorResult, structuredResult,
|
|
24
|
+
export { boundedResult, errorResult, structuredResult, textResult };
|
package/dist/store.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ declare class Store {
|
|
|
6
6
|
revision(): number;
|
|
7
7
|
private bump;
|
|
8
8
|
getTool(id: string): ToolRecord | null;
|
|
9
|
-
getAction(id: string): ActionRecord | null;
|
|
10
9
|
actionsFor(toolId: string): ActionRecord[];
|
|
11
10
|
heads(): Record<string, string>;
|
|
12
11
|
catalog(): Catalog;
|
|
@@ -15,8 +14,6 @@ declare class Store {
|
|
|
15
14
|
deploymentsFor(toolId: string): ToolDeployment[];
|
|
16
15
|
allDeployments(): ToolDeployment[];
|
|
17
16
|
deploymentSnapshot(): ToolDeploymentSnapshot;
|
|
18
|
-
/** Add a baseline for a pre-deployment database without changing its catalog bytes. */
|
|
19
|
-
adoptDeployment(activation: ToolDeploymentActivation): void;
|
|
20
17
|
applyDeployment(activation: ToolDeploymentActivation): {
|
|
21
18
|
changed: boolean;
|
|
22
19
|
result: ApplyResult | null;
|
package/dist/store.js
CHANGED
|
@@ -26,9 +26,6 @@ class Store {
|
|
|
26
26
|
getTool(id) {
|
|
27
27
|
return parse(this.db.prepare('SELECT record_json FROM tools WHERE id = ?').get(id));
|
|
28
28
|
}
|
|
29
|
-
getAction(id) {
|
|
30
|
-
return parse(this.db.prepare('SELECT record_json FROM actions WHERE id = ?').get(id));
|
|
31
|
-
}
|
|
32
29
|
actionsFor(toolId) {
|
|
33
30
|
return this.db.prepare('SELECT record_json FROM actions WHERE tool_id = ? ORDER BY id')
|
|
34
31
|
.all(toolId).map((row) => parse(row)).filter(Boolean);
|
|
@@ -77,16 +74,6 @@ class Store {
|
|
|
77
74
|
heads: this.heads(),
|
|
78
75
|
};
|
|
79
76
|
}
|
|
80
|
-
/** Add a baseline for a pre-deployment database without changing its catalog bytes. */
|
|
81
|
-
adoptDeployment(activation) {
|
|
82
|
-
const deployment = activation.deployment;
|
|
83
|
-
this.db.transaction(() => {
|
|
84
|
-
if (this.getDeployment(deployment.id))
|
|
85
|
-
return;
|
|
86
|
-
this.insertDeployment(deployment);
|
|
87
|
-
this.setHead(deployment.subjectId, deployment.id);
|
|
88
|
-
})();
|
|
89
|
-
}
|
|
90
77
|
applyDeployment(activation) {
|
|
91
78
|
const deployment = activation.deployment;
|
|
92
79
|
return this.db.transaction(() => {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ToolboxIndexDocument } from './artifacts.js';
|
|
2
|
+
import type { ActionRecord, Catalog, ToolDeployment, ToolRecord } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* The Toolbox's files, written from `tools.db` (the catalog of record) and
|
|
5
|
+
* never read back as catalog:
|
|
6
|
+
*
|
|
7
|
+
* <root>/<Tool Name>/.amalgm-tool.json the tool and every action it owns
|
|
8
|
+
* <root>/<Tool Name>/history/<id>.json each of its deployments, immutable
|
|
9
|
+
* <root>/<Tool Name>/.private/ computer-only; parked when it is deleted
|
|
10
|
+
* <dir>/index.json the whole catalog, system tools included
|
|
11
|
+
*
|
|
12
|
+
* A tool's folder is found by the id in its identity file and follows the
|
|
13
|
+
* tool's name. Writes go through a temporary file and are skipped when the
|
|
14
|
+
* bytes are unchanged.
|
|
15
|
+
*/
|
|
16
|
+
declare class ToolFiles {
|
|
17
|
+
private readonly folders;
|
|
18
|
+
constructor(folders: {
|
|
19
|
+
root: string;
|
|
20
|
+
dir: string;
|
|
21
|
+
parked: string;
|
|
22
|
+
});
|
|
23
|
+
writeTool(entry: {
|
|
24
|
+
tool: ToolRecord;
|
|
25
|
+
actions: ActionRecord[];
|
|
26
|
+
}, history: readonly ToolDeployment[]): void;
|
|
27
|
+
/** Park the tool's `.private/`, then remove the files Tools wrote. The
|
|
28
|
+
* folder goes too unless the user keeps files of their own in it. */
|
|
29
|
+
removeTool(toolId: string): void;
|
|
30
|
+
writeIndex(catalog: Catalog): void;
|
|
31
|
+
readIndex(): ToolboxIndexDocument | null;
|
|
32
|
+
private indexFile;
|
|
33
|
+
/** The tool's folder, created or renamed to follow its name. */
|
|
34
|
+
private place;
|
|
35
|
+
private entries;
|
|
36
|
+
private folderOf;
|
|
37
|
+
/** Tool ids can be used again, so a second parking of one id gets "-2", "-3", …. */
|
|
38
|
+
private parkTarget;
|
|
39
|
+
}
|
|
40
|
+
export { ToolFiles };
|