@miakapp/cli 4.0.0-alpha.0 → 4.0.0-alpha.3
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/package.json +4 -3
- package/dist/agent-pack.d.ts +0 -78
- package/dist/agent-pack.d.ts.map +0 -1
- package/dist/agent-pack.js +0 -193
- package/dist/agent-pack.js.map +0 -1
- package/dist/artifact.d.ts +0 -32
- package/dist/artifact.d.ts.map +0 -1
- package/dist/artifact.js +0 -328
- package/dist/artifact.js.map +0 -1
- package/dist/control-plane.d.ts +0 -37
- package/dist/control-plane.d.ts.map +0 -1
- package/dist/control-plane.js +0 -127
- package/dist/control-plane.js.map +0 -1
- package/dist/discovery.d.ts +0 -95
- package/dist/discovery.d.ts.map +0 -1
- package/dist/discovery.js +0 -389
- package/dist/discovery.js.map +0 -1
- package/dist/errors.d.ts +0 -37
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -56
- package/dist/errors.js.map +0 -1
- package/dist/internal/http.d.ts +0 -35
- package/dist/internal/http.d.ts.map +0 -1
- package/dist/internal/http.js +0 -125
- package/dist/internal/http.js.map +0 -1
- package/dist/internal/json.d.ts +0 -15
- package/dist/internal/json.d.ts.map +0 -1
- package/dist/internal/json.js +0 -227
- package/dist/internal/json.js.map +0 -1
- package/dist/internal/names.d.ts +0 -45
- package/dist/internal/names.d.ts.map +0 -1
- package/dist/internal/names.js +0 -98
- package/dist/internal/names.js.map +0 -1
- package/dist/internal/requirements.d.ts +0 -10
- package/dist/internal/requirements.d.ts.map +0 -1
- package/dist/internal/requirements.js +0 -50
- package/dist/internal/requirements.js.map +0 -1
- package/dist/internal/yaml.d.ts +0 -26
- package/dist/internal/yaml.d.ts.map +0 -1
- package/dist/internal/yaml.js +0 -184
- package/dist/internal/yaml.js.map +0 -1
- package/dist/main.d.ts +0 -86
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js +0 -666
- package/dist/main.js.map +0 -1
- package/dist/mcp.d.ts +0 -93
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js +0 -524
- package/dist/mcp.js.map +0 -1
- package/dist/project.d.ts +0 -25
- package/dist/project.d.ts.map +0 -1
- package/dist/project.js +0 -90
- package/dist/project.js.map +0 -1
- package/dist/publication.d.ts +0 -95
- package/dist/publication.d.ts.map +0 -1
- package/dist/publication.js +0 -408
- package/dist/publication.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@miakapp/cli",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.3",
|
|
4
4
|
"description": "Agent-first Miakapp command line: check, build, publish, activate and roll back home components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"node": ">=22.9"
|
|
9
9
|
},
|
|
10
10
|
"bin": {
|
|
11
|
-
"miakapp": "
|
|
11
|
+
"miakapp": "bin/miakapp.js"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"assets",
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"directory": "packages/cli"
|
|
31
31
|
},
|
|
32
32
|
"publishConfig": {
|
|
33
|
-
"access": "public"
|
|
33
|
+
"access": "public",
|
|
34
|
+
"tag": "latest"
|
|
34
35
|
},
|
|
35
36
|
"keywords": [
|
|
36
37
|
"Miakapp",
|
package/dist/agent-pack.d.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/** Directory the pack owns inside the owner's repository. */
|
|
2
|
-
export declare const PACK_DIRECTORY = ".miakapp";
|
|
3
|
-
/** The guide, copied out of the package so it is readable offline. */
|
|
4
|
-
export declare const GUIDE_FILE = ".miakapp/agent-guide.md";
|
|
5
|
-
/** Project-scope MCP configuration. Claude Code reads this file by name. */
|
|
6
|
-
export declare const MCP_FILE = ".mcp.json";
|
|
7
|
-
/** The name the server is registered under, and the tool-name prefix. */
|
|
8
|
-
export declare const SERVER_NAME = "miakapp";
|
|
9
|
-
/**
|
|
10
|
-
* Instruction files, by the client that reads each one. Both are written:
|
|
11
|
-
* a repository is handed to whichever agent the owner has, and an unused
|
|
12
|
-
* pointer costs a paragraph.
|
|
13
|
-
*/
|
|
14
|
-
export declare const INSTRUCTION_FILES: readonly {
|
|
15
|
-
readonly path: string;
|
|
16
|
-
readonly client: string;
|
|
17
|
-
}[];
|
|
18
|
-
export declare const BEGIN_MARKER = "<!-- miakapp:begin -->";
|
|
19
|
-
export declare const END_MARKER = "<!-- miakapp:end -->";
|
|
20
|
-
/** What happened to one file, reported per file rather than summed. */
|
|
21
|
-
export type PackAction = 'created' | 'updated' | 'unchanged';
|
|
22
|
-
export interface PackedFile {
|
|
23
|
-
readonly path: string;
|
|
24
|
-
readonly action: PackAction;
|
|
25
|
-
}
|
|
26
|
-
export interface FileStore {
|
|
27
|
-
read(path: string): Promise<Uint8Array>;
|
|
28
|
-
write(path: string, bytes: Uint8Array): Promise<void>;
|
|
29
|
-
replace(path: string, bytes: Uint8Array): Promise<void>;
|
|
30
|
-
exists(path: string): Promise<boolean>;
|
|
31
|
-
makeDirectory(path: string): Promise<void>;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* The block written into each instruction file.
|
|
35
|
-
*
|
|
36
|
-
* It is short on purpose. Everything an agent needs to know is in the guide,
|
|
37
|
-
* and a summary that drifts from the guide is worse than no summary: the agent
|
|
38
|
-
* would believe the stale copy it read first.
|
|
39
|
-
*/
|
|
40
|
-
export declare function instructionBlock(client: string): string;
|
|
41
|
-
/**
|
|
42
|
-
* Merges the block into an instruction file.
|
|
43
|
-
*
|
|
44
|
-
* Three cases, and the owner's prose survives all three: no file, a file with
|
|
45
|
-
* no block, and a file with a block from an earlier run. The block is appended
|
|
46
|
-
* rather than prepended because the top of an instruction file is where the
|
|
47
|
-
* owner put what matters to them.
|
|
48
|
-
*/
|
|
49
|
-
export declare function mergeInstructions(existing: string | undefined, block: string): string;
|
|
50
|
-
/**
|
|
51
|
-
* The server entry, as a client expects to find it.
|
|
52
|
-
*
|
|
53
|
-
* `command` is the bare binary name: the pack is written into a repository that
|
|
54
|
-
* may be opened on another machine, where an absolute path from this one would
|
|
55
|
-
* resolve to nothing.
|
|
56
|
-
*/
|
|
57
|
-
export declare function serverEntry(): Record<string, unknown>;
|
|
58
|
-
/**
|
|
59
|
-
* Merges the server entry into an existing `.mcp.json`.
|
|
60
|
-
*
|
|
61
|
-
* Parsed and re-serialized rather than patched as text: every other server in
|
|
62
|
-
* the file is carried across by name, and a file that does not parse is refused
|
|
63
|
-
* instead of being overwritten with a valid one. An owner who hand-edited that
|
|
64
|
-
* file into a syntax error still wants their edit back.
|
|
65
|
-
*/
|
|
66
|
-
export declare function mergeMcpConfig(existing: string | undefined): string;
|
|
67
|
-
export interface PackResult {
|
|
68
|
-
readonly root: string;
|
|
69
|
-
readonly files: readonly PackedFile[];
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Installs the pack under `root`.
|
|
73
|
-
*
|
|
74
|
-
* `guide` is passed in rather than read here so the caller decides where the
|
|
75
|
-
* guide comes from: the packaged asset in production, a fixture in a test.
|
|
76
|
-
*/
|
|
77
|
-
export declare function installPack(files: FileStore, root: string, guide: string): Promise<PackResult>;
|
|
78
|
-
//# sourceMappingURL=agent-pack.d.ts.map
|
package/dist/agent-pack.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-pack.d.ts","sourceRoot":"","sources":["../src/agent-pack.ts"],"names":[],"mappings":"AAqBA,6DAA6D;AAC7D,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC,sEAAsE;AACtE,eAAO,MAAM,UAAU,4BAAqC,CAAC;AAE7D,4EAA4E;AAC5E,eAAO,MAAM,QAAQ,cAAc,CAAC;AAEpC,yEAAyE;AACzE,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAG1F,CAAC;AAEF,eAAO,MAAM,YAAY,2BAA2B,CAAC;AACrD,eAAO,MAAM,UAAU,yBAAyB,CAAC;AAEjD,uEAAuE;AACvE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAE7D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C;AAoCD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA8BvD;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBrF;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMrD;AAMD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CA+BnE;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CACvC;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,UAAU,CAAC,CAiBrB"}
|
package/dist/agent-pack.js
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The installable pack.
|
|
3
|
-
*
|
|
4
|
-
* A coding agent handed someone's house does not arrive knowing how a Miakapp
|
|
5
|
-
* home is built. It arrives in the owner's repository, with whatever files are
|
|
6
|
-
* already there. This command puts three things in that repository:
|
|
7
|
-
*
|
|
8
|
-
* - the guide, as a file, so the knowledge survives without a network;
|
|
9
|
-
* - a pointer to it in the instruction file each client actually reads —
|
|
10
|
-
* `AGENTS.md` for Codex, `CLAUDE.md` for Claude Code;
|
|
11
|
-
* - the MCP server entry, so the tools are wired rather than described.
|
|
12
|
-
*
|
|
13
|
-
* The repository belongs to the owner, and the CLI's rule that it never
|
|
14
|
-
* rewrites what it did not generate holds here too. That rule is what shapes
|
|
15
|
-
* every merge below: the guide is a file this command owns outright, the
|
|
16
|
-
* instruction files are edited only between markers this command wrote, and
|
|
17
|
-
* `.mcp.json` is edited as a structure — one key, by name — never as text.
|
|
18
|
-
* Bytes outside those regions are copied through untouched.
|
|
19
|
-
*/
|
|
20
|
-
import { projectError } from './errors.js';
|
|
21
|
-
/** Directory the pack owns inside the owner's repository. */
|
|
22
|
-
export const PACK_DIRECTORY = '.miakapp';
|
|
23
|
-
/** The guide, copied out of the package so it is readable offline. */
|
|
24
|
-
export const GUIDE_FILE = `${PACK_DIRECTORY}/agent-guide.md`;
|
|
25
|
-
/** Project-scope MCP configuration. Claude Code reads this file by name. */
|
|
26
|
-
export const MCP_FILE = '.mcp.json';
|
|
27
|
-
/** The name the server is registered under, and the tool-name prefix. */
|
|
28
|
-
export const SERVER_NAME = 'miakapp';
|
|
29
|
-
/**
|
|
30
|
-
* Instruction files, by the client that reads each one. Both are written:
|
|
31
|
-
* a repository is handed to whichever agent the owner has, and an unused
|
|
32
|
-
* pointer costs a paragraph.
|
|
33
|
-
*/
|
|
34
|
-
export const INSTRUCTION_FILES = [
|
|
35
|
-
{ path: 'AGENTS.md', client: 'Codex' },
|
|
36
|
-
{ path: 'CLAUDE.md', client: 'Claude Code' },
|
|
37
|
-
];
|
|
38
|
-
export const BEGIN_MARKER = '<!-- miakapp:begin -->';
|
|
39
|
-
export const END_MARKER = '<!-- miakapp:end -->';
|
|
40
|
-
const encoder = new TextEncoder();
|
|
41
|
-
function decode(bytes, path) {
|
|
42
|
-
try {
|
|
43
|
-
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
throw projectError(`${path} is not readable as UTF-8 text`, 'The pack edits text files in place; move this one aside and run the command again.');
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Writes `bytes` at `path`, creating or replacing.
|
|
51
|
-
*
|
|
52
|
-
* Returns `unchanged` when the bytes already on disk are identical, so a second
|
|
53
|
-
* run of the pack reports honestly instead of claiming work it did not do.
|
|
54
|
-
*/
|
|
55
|
-
async function put(files, path, content) {
|
|
56
|
-
const bytes = encoder.encode(content);
|
|
57
|
-
if (!await files.exists(path)) {
|
|
58
|
-
await files.write(path, bytes);
|
|
59
|
-
return { path, action: 'created' };
|
|
60
|
-
}
|
|
61
|
-
if (decode(await files.read(path), path) === content)
|
|
62
|
-
return { path, action: 'unchanged' };
|
|
63
|
-
await files.replace(path, bytes);
|
|
64
|
-
return { path, action: 'updated' };
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* The block written into each instruction file.
|
|
68
|
-
*
|
|
69
|
-
* It is short on purpose. Everything an agent needs to know is in the guide,
|
|
70
|
-
* and a summary that drifts from the guide is worse than no summary: the agent
|
|
71
|
-
* would believe the stale copy it read first.
|
|
72
|
-
*/
|
|
73
|
-
export function instructionBlock(client) {
|
|
74
|
-
return `${BEGIN_MARKER}
|
|
75
|
-
## Miakapp
|
|
76
|
-
|
|
77
|
-
This repository is a Miakapp home: a coordinator that runs on the owner's
|
|
78
|
-
machine and owns state, events and authorization, and a component that runs
|
|
79
|
-
sandboxed in the household's browser and owns nothing but the interface.
|
|
80
|
-
|
|
81
|
-
**Read \`${GUIDE_FILE}\` before writing or publishing anything here.** It is the
|
|
82
|
-
full guide, copied into this repository so it is readable offline, and it is the
|
|
83
|
-
source of truth for the rules below.
|
|
84
|
-
|
|
85
|
-
The \`${SERVER_NAME}\` MCP server in \`${MCP_FILE}\` exposes the toolchain to ${client}:
|
|
86
|
-
inventory an existing installation, validate the project, publish, and roll back.
|
|
87
|
-
The same commands exist as \`${SERVER_NAME}\` on the command line; they are one
|
|
88
|
-
implementation, so neither surface can drift from the other.
|
|
89
|
-
|
|
90
|
-
Three rules the guide explains and this file repeats because getting them wrong
|
|
91
|
-
is expensive:
|
|
92
|
-
|
|
93
|
-
- \`publish\`, \`activate\` and \`rollback\` change what every device in the home
|
|
94
|
-
runs. Over MCP they refuse to act without \`confirm: true\`. Set it when the
|
|
95
|
-
owner asked for that publication, never to get past an error.
|
|
96
|
-
- Every failure carries a stable \`kind\`. Branch on it, not on the message.
|
|
97
|
-
\`conflict\` means re-read the pointer; \`unknown_outcome\` means the effect is
|
|
98
|
-
undetermined — reconcile with \`${SERVER_NAME} release\` or \`${SERVER_NAME} upload\`
|
|
99
|
-
before acting again, and never retry it.
|
|
100
|
-
- The Home Key lives in \`MIAKAPP_HOME_KEY\` in the environment. No command
|
|
101
|
-
accepts it as an argument, and it belongs in no file in this repository.
|
|
102
|
-
${END_MARKER}`;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Merges the block into an instruction file.
|
|
106
|
-
*
|
|
107
|
-
* Three cases, and the owner's prose survives all three: no file, a file with
|
|
108
|
-
* no block, and a file with a block from an earlier run. The block is appended
|
|
109
|
-
* rather than prepended because the top of an instruction file is where the
|
|
110
|
-
* owner put what matters to them.
|
|
111
|
-
*/
|
|
112
|
-
export function mergeInstructions(existing, block) {
|
|
113
|
-
if (existing === undefined || existing.trim() === '')
|
|
114
|
-
return `${block}\n`;
|
|
115
|
-
const start = existing.indexOf(BEGIN_MARKER);
|
|
116
|
-
if (start === -1) {
|
|
117
|
-
const separator = existing.endsWith('\n') ? '\n' : '\n\n';
|
|
118
|
-
return `${existing}${separator}${block}\n`;
|
|
119
|
-
}
|
|
120
|
-
const end = existing.indexOf(END_MARKER, start);
|
|
121
|
-
if (end === -1) {
|
|
122
|
-
throw projectError(`An unterminated ${BEGIN_MARKER} block is open in this file`, `Close it with ${END_MARKER}, or delete the block and run the pack again.`);
|
|
123
|
-
}
|
|
124
|
-
return existing.slice(0, start) + block + existing.slice(end + END_MARKER.length);
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* The server entry, as a client expects to find it.
|
|
128
|
-
*
|
|
129
|
-
* `command` is the bare binary name: the pack is written into a repository that
|
|
130
|
-
* may be opened on another machine, where an absolute path from this one would
|
|
131
|
-
* resolve to nothing.
|
|
132
|
-
*/
|
|
133
|
-
export function serverEntry() {
|
|
134
|
-
return {
|
|
135
|
-
type: 'stdio',
|
|
136
|
-
command: SERVER_NAME,
|
|
137
|
-
args: ['mcp'],
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
function isPlainObject(value) {
|
|
141
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Merges the server entry into an existing `.mcp.json`.
|
|
145
|
-
*
|
|
146
|
-
* Parsed and re-serialized rather than patched as text: every other server in
|
|
147
|
-
* the file is carried across by name, and a file that does not parse is refused
|
|
148
|
-
* instead of being overwritten with a valid one. An owner who hand-edited that
|
|
149
|
-
* file into a syntax error still wants their edit back.
|
|
150
|
-
*/
|
|
151
|
-
export function mergeMcpConfig(existing) {
|
|
152
|
-
let document = {};
|
|
153
|
-
if (existing !== undefined && existing.trim() !== '') {
|
|
154
|
-
let parsed;
|
|
155
|
-
try {
|
|
156
|
-
parsed = JSON.parse(existing);
|
|
157
|
-
}
|
|
158
|
-
catch (error) {
|
|
159
|
-
throw projectError(`${MCP_FILE} is not valid JSON: ${error instanceof Error ? error.message : 'parse failed'}`, 'The pack merges one entry into this file and will not replace it. Fix the JSON first.');
|
|
160
|
-
}
|
|
161
|
-
if (!isPlainObject(parsed)) {
|
|
162
|
-
throw projectError(`${MCP_FILE} must hold a JSON object`, 'The pack merges one entry into this file and will not replace it.');
|
|
163
|
-
}
|
|
164
|
-
document = parsed;
|
|
165
|
-
}
|
|
166
|
-
const servers = document['mcpServers'];
|
|
167
|
-
if (servers !== undefined && !isPlainObject(servers)) {
|
|
168
|
-
throw projectError(`${MCP_FILE} has an "mcpServers" key that is not an object`, 'The pack merges one entry into this file and will not replace it.');
|
|
169
|
-
}
|
|
170
|
-
const merged = { ...(servers ?? {}), [SERVER_NAME]: serverEntry() };
|
|
171
|
-
return `${JSON.stringify({ ...document, mcpServers: merged }, null, 2)}\n`;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Installs the pack under `root`.
|
|
175
|
-
*
|
|
176
|
-
* `guide` is passed in rather than read here so the caller decides where the
|
|
177
|
-
* guide comes from: the packaged asset in production, a fixture in a test.
|
|
178
|
-
*/
|
|
179
|
-
export async function installPack(files, root, guide) {
|
|
180
|
-
const written = [];
|
|
181
|
-
await files.makeDirectory(`${root}/${PACK_DIRECTORY}`);
|
|
182
|
-
written.push(await put(files, `${root}/${GUIDE_FILE}`, guide));
|
|
183
|
-
for (const { path, client } of INSTRUCTION_FILES) {
|
|
184
|
-
const full = `${root}/${path}`;
|
|
185
|
-
const existing = await files.exists(full) ? decode(await files.read(full), full) : undefined;
|
|
186
|
-
written.push(await put(files, full, mergeInstructions(existing, instructionBlock(client))));
|
|
187
|
-
}
|
|
188
|
-
const mcpPath = `${root}/${MCP_FILE}`;
|
|
189
|
-
const config = await files.exists(mcpPath) ? decode(await files.read(mcpPath), mcpPath) : undefined;
|
|
190
|
-
written.push(await put(files, mcpPath, mergeMcpConfig(config)));
|
|
191
|
-
return { root, files: written };
|
|
192
|
-
}
|
|
193
|
-
//# sourceMappingURL=agent-pack.js.map
|
package/dist/agent-pack.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-pack.js","sourceRoot":"","sources":["../src/agent-pack.ts"],"names":[],"mappings":"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"}
|
package/dist/artifact.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export interface Artifact {
|
|
2
|
-
/** Exact bytes that will be uploaded; nothing re-encodes them later. */
|
|
3
|
-
readonly bytes: Uint8Array;
|
|
4
|
-
/** SHA-256 of those bytes as unpadded base64url, per RFC 0002 §7.1. */
|
|
5
|
-
readonly sha256: string;
|
|
6
|
-
readonly size: number;
|
|
7
|
-
readonly tokens: number;
|
|
8
|
-
}
|
|
9
|
-
export type ArtifactFindingKind = 'module_syntax' | 'dynamic_import' | 'source_map_directive' | 'token_ceiling' | 'unterminated';
|
|
10
|
-
export interface ArtifactFinding {
|
|
11
|
-
readonly kind: ArtifactFindingKind;
|
|
12
|
-
readonly line: number;
|
|
13
|
-
readonly detail: string;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Publisher pre-check for the RFC 0002 §7.2 artifact rules.
|
|
17
|
-
*
|
|
18
|
-
* RFC 0002 makes the broker's pinned platform parser authoritative; this scan
|
|
19
|
-
* exists so an agent learns about module syntax, a dynamic import, a source-map
|
|
20
|
-
* directive or an oversized program before spending an upload capability. It
|
|
21
|
-
* reports findings rather than throwing, so one run can show every problem.
|
|
22
|
-
*/
|
|
23
|
-
export declare function scanArtifactSource(source: string): {
|
|
24
|
-
tokens: number;
|
|
25
|
-
findings: readonly ArtifactFinding[];
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Verifies the exact bytes an upload would deliver and derives the digest and
|
|
29
|
-
* size that bind the upload capability.
|
|
30
|
-
*/
|
|
31
|
-
export declare function prepareArtifact(bytes: Uint8Array): Artifact;
|
|
32
|
-
//# sourceMappingURL=artifact.d.ts.map
|
package/dist/artifact.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"artifact.d.ts","sourceRoot":"","sources":["../src/artifact.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,QAAQ;IACvB,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,gBAAgB,GAChB,sBAAsB,GACtB,eAAe,GACf,cAAc,CAAC;AAEnB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAwBD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;CACtC,CAsIA;AAiHD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CA8B3D"}
|
package/dist/artifact.js
DELETED
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
import { artifactError } from './errors.js';
|
|
3
|
-
import { MAXIMUM_ARTIFACT_BYTES, MAXIMUM_PROGRAM_TOKENS, } from './internal/names.js';
|
|
4
|
-
const IDENTIFIER_START = /[$_\p{ID_Start}]/u;
|
|
5
|
-
const IDENTIFIER_PART = /[$_\u200c\u200d\p{ID_Continue}]/u;
|
|
6
|
-
/**
|
|
7
|
-
* Tokens after which a `/` starts a regular expression rather than a division.
|
|
8
|
-
* The list is deliberately conservative: a wrong guess only changes how the
|
|
9
|
-
* scanner counts, never whether the broker's pinned parser accepts the program.
|
|
10
|
-
*/
|
|
11
|
-
const REGEX_ALLOWED_AFTER = new Set([
|
|
12
|
-
'case', 'delete', 'do', 'else', 'in', 'instanceof', 'new', 'of', 'return',
|
|
13
|
-
'throw', 'typeof', 'void', 'yield',
|
|
14
|
-
]);
|
|
15
|
-
function isRegexPosition(previous) {
|
|
16
|
-
if (previous === undefined)
|
|
17
|
-
return true;
|
|
18
|
-
if (REGEX_ALLOWED_AFTER.has(previous))
|
|
19
|
-
return true;
|
|
20
|
-
if (/^[A-Za-z_$]/.test(previous))
|
|
21
|
-
return false;
|
|
22
|
-
if (/^[0-9]/.test(previous))
|
|
23
|
-
return false;
|
|
24
|
-
return previous !== ')' && previous !== ']' && previous !== '}' && previous !== '++'
|
|
25
|
-
&& previous !== '--' && previous[0] !== '"' && previous[0] !== "'" && previous[0] !== '`';
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Publisher pre-check for the RFC 0002 §7.2 artifact rules.
|
|
29
|
-
*
|
|
30
|
-
* RFC 0002 makes the broker's pinned platform parser authoritative; this scan
|
|
31
|
-
* exists so an agent learns about module syntax, a dynamic import, a source-map
|
|
32
|
-
* directive or an oversized program before spending an upload capability. It
|
|
33
|
-
* reports findings rather than throwing, so one run can show every problem.
|
|
34
|
-
*/
|
|
35
|
-
export function scanArtifactSource(source) {
|
|
36
|
-
const findings = [];
|
|
37
|
-
let index = 0;
|
|
38
|
-
let line = 1;
|
|
39
|
-
let tokens = 0;
|
|
40
|
-
let previous;
|
|
41
|
-
let lineStartOnlyWhitespace = true;
|
|
42
|
-
const record = (kind, detail) => {
|
|
43
|
-
if (findings.some((finding) => finding.kind === kind && finding.line === line))
|
|
44
|
-
return;
|
|
45
|
-
findings.push({ kind, line, detail });
|
|
46
|
-
};
|
|
47
|
-
const advanceLines = (text) => {
|
|
48
|
-
for (const character of text)
|
|
49
|
-
if (character === '\n')
|
|
50
|
-
line += 1;
|
|
51
|
-
};
|
|
52
|
-
while (index < source.length) {
|
|
53
|
-
const character = source[index];
|
|
54
|
-
if (character === '\n') {
|
|
55
|
-
line += 1;
|
|
56
|
-
lineStartOnlyWhitespace = true;
|
|
57
|
-
index += 1;
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
if (character === ' ' || character === '\t' || character === '\r' || character === '\f'
|
|
61
|
-
|| character === '\v' || character === '\u00a0' || character === '\ufeff') {
|
|
62
|
-
index += 1;
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
if (character === '/' && source[index + 1] === '/') {
|
|
66
|
-
const end = source.indexOf('\n', index);
|
|
67
|
-
const comment = source.slice(index, end === -1 ? source.length : end);
|
|
68
|
-
if (/^\/\/[#@]\s*sourceMappingURL=/.test(comment)) {
|
|
69
|
-
record('source_map_directive', comment.trim());
|
|
70
|
-
}
|
|
71
|
-
index = end === -1 ? source.length : end;
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
if (character === '/' && source[index + 1] === '*') {
|
|
75
|
-
const end = source.indexOf('*/', index + 2);
|
|
76
|
-
if (end === -1) {
|
|
77
|
-
record('unterminated', 'Unterminated block comment');
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
const comment = source.slice(index, end + 2);
|
|
81
|
-
if (/^\/\*[#@]\s*sourceMappingURL=/.test(comment)) {
|
|
82
|
-
record('source_map_directive', comment.slice(0, 64));
|
|
83
|
-
}
|
|
84
|
-
advanceLines(comment);
|
|
85
|
-
index = end + 2;
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
if (character === '"' || character === "'") {
|
|
89
|
-
const end = scanQuoted(source, index, character);
|
|
90
|
-
if (end === -1) {
|
|
91
|
-
record('unterminated', 'Unterminated string literal');
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
advanceLines(source.slice(index, end));
|
|
95
|
-
previous = `${character}string`;
|
|
96
|
-
tokens += 1;
|
|
97
|
-
index = end;
|
|
98
|
-
lineStartOnlyWhitespace = false;
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
if (character === '`') {
|
|
102
|
-
const end = scanTemplate(source, index);
|
|
103
|
-
if (end === -1) {
|
|
104
|
-
record('unterminated', 'Unterminated template literal');
|
|
105
|
-
break;
|
|
106
|
-
}
|
|
107
|
-
advanceLines(source.slice(index, end));
|
|
108
|
-
previous = '`template';
|
|
109
|
-
tokens += 1;
|
|
110
|
-
index = end;
|
|
111
|
-
lineStartOnlyWhitespace = false;
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
if (character === '/' && isRegexPosition(previous)) {
|
|
115
|
-
const end = scanRegex(source, index);
|
|
116
|
-
if (end === -1) {
|
|
117
|
-
record('unterminated', 'Unterminated regular expression literal');
|
|
118
|
-
break;
|
|
119
|
-
}
|
|
120
|
-
previous = '/regex';
|
|
121
|
-
tokens += 1;
|
|
122
|
-
index = end;
|
|
123
|
-
lineStartOnlyWhitespace = false;
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
if (IDENTIFIER_START.test(character)) {
|
|
127
|
-
let end = index + 1;
|
|
128
|
-
while (end < source.length && IDENTIFIER_PART.test(source[end]))
|
|
129
|
-
end += 1;
|
|
130
|
-
const word = source.slice(index, end);
|
|
131
|
-
if (word === 'import') {
|
|
132
|
-
const next = nextSignificant(source, end);
|
|
133
|
-
if (next === '(')
|
|
134
|
-
record('dynamic_import', 'import( expression');
|
|
135
|
-
else if (next === '.')
|
|
136
|
-
record('dynamic_import', 'import.meta reference');
|
|
137
|
-
else
|
|
138
|
-
record('module_syntax', 'import declaration');
|
|
139
|
-
}
|
|
140
|
-
else if (word === 'export' && lineStartOnlyWhitespace) {
|
|
141
|
-
record('module_syntax', 'export declaration');
|
|
142
|
-
}
|
|
143
|
-
previous = word;
|
|
144
|
-
tokens += 1;
|
|
145
|
-
index = end;
|
|
146
|
-
lineStartOnlyWhitespace = false;
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
if (character >= '0' && character <= '9') {
|
|
150
|
-
let end = index + 1;
|
|
151
|
-
while (end < source.length && /[0-9a-fA-FxXoObBn._]/.test(source[end]))
|
|
152
|
-
end += 1;
|
|
153
|
-
previous = source.slice(index, end);
|
|
154
|
-
tokens += 1;
|
|
155
|
-
index = end;
|
|
156
|
-
lineStartOnlyWhitespace = false;
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
const punctuator = scanPunctuator(source, index);
|
|
160
|
-
previous = punctuator;
|
|
161
|
-
tokens += 1;
|
|
162
|
-
index += punctuator.length;
|
|
163
|
-
lineStartOnlyWhitespace = false;
|
|
164
|
-
if (tokens > MAXIMUM_PROGRAM_TOKENS)
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
if (tokens > MAXIMUM_PROGRAM_TOKENS) {
|
|
168
|
-
findings.push({
|
|
169
|
-
kind: 'token_ceiling',
|
|
170
|
-
line,
|
|
171
|
-
detail: `Program exceeds the ABI 1 ceiling of ${MAXIMUM_PROGRAM_TOKENS} lexical tokens`,
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
return { tokens, findings };
|
|
175
|
-
}
|
|
176
|
-
function scanQuoted(source, start, quote) {
|
|
177
|
-
let index = start + 1;
|
|
178
|
-
while (index < source.length) {
|
|
179
|
-
const character = source[index];
|
|
180
|
-
if (character === '\\') {
|
|
181
|
-
index += 2;
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
if (character === quote)
|
|
185
|
-
return index + 1;
|
|
186
|
-
if (character === '\n')
|
|
187
|
-
return -1;
|
|
188
|
-
index += 1;
|
|
189
|
-
}
|
|
190
|
-
return -1;
|
|
191
|
-
}
|
|
192
|
-
function scanTemplate(source, start) {
|
|
193
|
-
let index = start + 1;
|
|
194
|
-
while (index < source.length) {
|
|
195
|
-
const character = source[index];
|
|
196
|
-
if (character === '\\') {
|
|
197
|
-
index += 2;
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
if (character === '`')
|
|
201
|
-
return index + 1;
|
|
202
|
-
if (character === '$' && source[index + 1] === '{') {
|
|
203
|
-
let depth = 1;
|
|
204
|
-
index += 2;
|
|
205
|
-
while (index < source.length && depth > 0) {
|
|
206
|
-
const inner = source[index];
|
|
207
|
-
if (inner === '{')
|
|
208
|
-
depth += 1;
|
|
209
|
-
else if (inner === '}')
|
|
210
|
-
depth -= 1;
|
|
211
|
-
else if (inner === '`') {
|
|
212
|
-
const nested = scanTemplate(source, index);
|
|
213
|
-
if (nested === -1)
|
|
214
|
-
return -1;
|
|
215
|
-
index = nested;
|
|
216
|
-
continue;
|
|
217
|
-
}
|
|
218
|
-
else if (inner === '"' || inner === "'") {
|
|
219
|
-
const nested = scanQuoted(source, index, inner);
|
|
220
|
-
if (nested === -1)
|
|
221
|
-
return -1;
|
|
222
|
-
index = nested;
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
index += 1;
|
|
226
|
-
}
|
|
227
|
-
continue;
|
|
228
|
-
}
|
|
229
|
-
index += 1;
|
|
230
|
-
}
|
|
231
|
-
return -1;
|
|
232
|
-
}
|
|
233
|
-
function scanRegex(source, start) {
|
|
234
|
-
let index = start + 1;
|
|
235
|
-
let inClass = false;
|
|
236
|
-
while (index < source.length) {
|
|
237
|
-
const character = source[index];
|
|
238
|
-
if (character === '\\') {
|
|
239
|
-
index += 2;
|
|
240
|
-
continue;
|
|
241
|
-
}
|
|
242
|
-
if (character === '\n')
|
|
243
|
-
return -1;
|
|
244
|
-
if (character === '[')
|
|
245
|
-
inClass = true;
|
|
246
|
-
else if (character === ']')
|
|
247
|
-
inClass = false;
|
|
248
|
-
else if (character === '/' && !inClass) {
|
|
249
|
-
index += 1;
|
|
250
|
-
while (index < source.length && IDENTIFIER_PART.test(source[index]))
|
|
251
|
-
index += 1;
|
|
252
|
-
return index;
|
|
253
|
-
}
|
|
254
|
-
index += 1;
|
|
255
|
-
}
|
|
256
|
-
return -1;
|
|
257
|
-
}
|
|
258
|
-
const PUNCTUATORS = [
|
|
259
|
-
'>>>=', '...', '===', '!==', '**=', '<<=', '>>=', '>>>', '&&=', '||=', '??=',
|
|
260
|
-
'=>', '==', '!=', '<=', '>=', '&&', '||', '??', '?.', '++', '--', '+=', '-=',
|
|
261
|
-
'*=', '/=', '%=', '&=', '|=', '^=', '<<', '>>', '**',
|
|
262
|
-
];
|
|
263
|
-
function scanPunctuator(source, index) {
|
|
264
|
-
for (const punctuator of PUNCTUATORS) {
|
|
265
|
-
if (source.startsWith(punctuator, index))
|
|
266
|
-
return punctuator;
|
|
267
|
-
}
|
|
268
|
-
return source[index];
|
|
269
|
-
}
|
|
270
|
-
function nextSignificant(source, from) {
|
|
271
|
-
let index = from;
|
|
272
|
-
while (index < source.length) {
|
|
273
|
-
const character = source[index];
|
|
274
|
-
if (/\s/.test(character)) {
|
|
275
|
-
index += 1;
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
if (character === '/' && source[index + 1] === '/') {
|
|
279
|
-
const end = source.indexOf('\n', index);
|
|
280
|
-
if (end === -1)
|
|
281
|
-
return undefined;
|
|
282
|
-
index = end + 1;
|
|
283
|
-
continue;
|
|
284
|
-
}
|
|
285
|
-
if (character === '/' && source[index + 1] === '*') {
|
|
286
|
-
const end = source.indexOf('*/', index + 2);
|
|
287
|
-
if (end === -1)
|
|
288
|
-
return undefined;
|
|
289
|
-
index = end + 2;
|
|
290
|
-
continue;
|
|
291
|
-
}
|
|
292
|
-
return character;
|
|
293
|
-
}
|
|
294
|
-
return undefined;
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Verifies the exact bytes an upload would deliver and derives the digest and
|
|
298
|
-
* size that bind the upload capability.
|
|
299
|
-
*/
|
|
300
|
-
export function prepareArtifact(bytes) {
|
|
301
|
-
if (bytes.byteLength === 0)
|
|
302
|
-
throw artifactError('Artifact is empty');
|
|
303
|
-
if (bytes.byteLength > MAXIMUM_ARTIFACT_BYTES) {
|
|
304
|
-
throw artifactError(`Artifact is ${bytes.byteLength} bytes, above the ABI 1 ceiling of ${MAXIMUM_ARTIFACT_BYTES}`);
|
|
305
|
-
}
|
|
306
|
-
let source;
|
|
307
|
-
try {
|
|
308
|
-
source = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
309
|
-
}
|
|
310
|
-
catch {
|
|
311
|
-
throw artifactError('Artifact is not valid UTF-8');
|
|
312
|
-
}
|
|
313
|
-
const { tokens, findings } = scanArtifactSource(source);
|
|
314
|
-
if (findings.length > 0) {
|
|
315
|
-
const detail = findings
|
|
316
|
-
.map((finding) => ` line ${finding.line}: ${finding.kind} — ${finding.detail}`)
|
|
317
|
-
.join('\n');
|
|
318
|
-
throw artifactError(`Artifact violates the RFC 0002 §7.2 artifact rules:\n${detail}`, 'Bundle to one self-contained classic Worker program with no module syntax, '
|
|
319
|
-
+ 'no dynamic import and no source map.');
|
|
320
|
-
}
|
|
321
|
-
return Object.freeze({
|
|
322
|
-
bytes,
|
|
323
|
-
sha256: createHash('sha256').update(bytes).digest('base64url'),
|
|
324
|
-
size: bytes.byteLength,
|
|
325
|
-
tokens,
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
//# sourceMappingURL=artifact.js.map
|