@wire-runtime/cli 0.0.0-stage → 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Wire contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,35 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ export interface IssuerKeyFiles {
4
+ /** PKCS#8 PEM private key. Never copy this to the runtime host. */
5
+ privateFile: string;
6
+ /** Raw 32-byte public key as lowercase hex, plus a trailing newline. */
7
+ publicFile: string;
8
+ /** Raw 32-byte public key as lowercase hex. */
9
+ publicKey: string;
10
+ }
11
+ export interface BudgetClaims {
12
+ keyId: number;
13
+ sessionId: string;
14
+ maxToolCalls: number;
15
+ expiresAt: number;
16
+ nonce: string;
17
+ }
18
+ /**
19
+ * Create a dedicated issuer key pair. The target directory must not exist, so an
20
+ * existing private key can never be overwritten by an accidental rerun.
21
+ */
22
+ export declare function keygen(dir: string): Promise<IssuerKeyFiles>;
23
+ /**
24
+ * Mint one 112-byte token. Fields are big-endian:
25
+ * key_id[0..4], session[4..20], calls[20..24], expiry[24..32], nonce[32..48],
26
+ * Ed25519 signature[48..112] over the exact first 48 bytes.
27
+ */
28
+ export declare function mint(privateKey: string | Buffer, session: Buffer, maxToolCalls: number, expiresAt: number, keyId: number, nonce: Buffer): Buffer;
29
+ /** Read the raw claims without implying that the signature was verified. */
30
+ export declare function claims(token: Buffer): BudgetClaims;
31
+ export declare function readToken(file: string): Promise<Buffer>;
32
+ /** Parse the independently authenticated session as exactly 16 bytes. */
33
+ export declare function sessionBytes(hex: string): Buffer;
34
+ /** Strict unsigned 32-bit decimal argument parser. */
35
+ export declare function unsigned32(value: unknown, label: string, min?: number): number;
package/dist/budget.js ADDED
@@ -0,0 +1,93 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ import { generateKeyPairSync, sign } from "node:crypto";
4
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
5
+ import path from "node:path";
6
+ /** Signed payload bytes, excluding the Ed25519 signature. */
7
+ const PAYLOAD_LEN = 48;
8
+ /** Exact flat token length: 48-byte payload + 64-byte signature. */
9
+ const TOKEN_LEN = 112;
10
+ const SESSION_LEN = 16;
11
+ const NONCE_LEN = 16;
12
+ const MAX_U32 = 0xffff_ffff;
13
+ function unsigned(value, label, min, max) {
14
+ if (!Number.isSafeInteger(value) || value < min || value > max)
15
+ throw new Error(`${label} must be an integer between ${min} and ${max}`);
16
+ return value;
17
+ }
18
+ function rawPublicKey(publicKey) {
19
+ const der = publicKey.export({ format: "der", type: "spki" });
20
+ if (der.length < 32)
21
+ throw new Error("Generated Ed25519 public key is malformed");
22
+ return der.subarray(der.length - 32);
23
+ }
24
+ /**
25
+ * Create a dedicated issuer key pair. The target directory must not exist, so an
26
+ * existing private key can never be overwritten by an accidental rerun.
27
+ */
28
+ export async function keygen(dir) {
29
+ await mkdir(dir, { recursive: false, mode: 0o700 });
30
+ const { privateKey, publicKey } = generateKeyPairSync("ed25519");
31
+ const privateFile = path.join(dir, "private.pem");
32
+ const publicFile = path.join(dir, "public.hex");
33
+ const hex = rawPublicKey(publicKey).toString("hex");
34
+ await writeFile(privateFile, privateKey.export({ format: "pem", type: "pkcs8" }), {
35
+ flag: "wx",
36
+ mode: 0o600,
37
+ });
38
+ await writeFile(publicFile, `${hex}\n`, { flag: "wx", mode: 0o644 });
39
+ return { privateFile, publicFile, publicKey: hex };
40
+ }
41
+ /**
42
+ * Mint one 112-byte token. Fields are big-endian:
43
+ * key_id[0..4], session[4..20], calls[20..24], expiry[24..32], nonce[32..48],
44
+ * Ed25519 signature[48..112] over the exact first 48 bytes.
45
+ */
46
+ export function mint(privateKey, session, maxToolCalls, expiresAt, keyId, nonce) {
47
+ if (session.length !== SESSION_LEN)
48
+ throw new Error(`Session must be exactly ${SESSION_LEN} bytes`);
49
+ if (nonce.length !== NONCE_LEN)
50
+ throw new Error(`Nonce must be exactly ${NONCE_LEN} bytes`);
51
+ const payload = Buffer.alloc(PAYLOAD_LEN);
52
+ payload.writeUInt32BE(unsigned(keyId, "Key id", 0, MAX_U32), 0);
53
+ session.copy(payload, 4);
54
+ payload.writeUInt32BE(unsigned(maxToolCalls, "Calls", 1, MAX_U32), 20);
55
+ payload.writeBigUInt64BE(BigInt(unsigned(expiresAt, "Expiry", 0, Number.MAX_SAFE_INTEGER)), 24);
56
+ nonce.copy(payload, 32);
57
+ const signature = sign(null, payload, privateKey);
58
+ if (signature.length !== TOKEN_LEN - PAYLOAD_LEN)
59
+ throw new Error("Ed25519 signature length is invalid");
60
+ return Buffer.concat([payload, signature]);
61
+ }
62
+ /** Read the raw claims without implying that the signature was verified. */
63
+ export function claims(token) {
64
+ if (token.length !== TOKEN_LEN)
65
+ throw new Error(`Budget token must be exactly ${TOKEN_LEN} bytes`);
66
+ return {
67
+ keyId: token.readUInt32BE(0),
68
+ sessionId: token.subarray(4, 20).toString("hex"),
69
+ maxToolCalls: token.readUInt32BE(20),
70
+ expiresAt: Number(token.readBigUInt64BE(24)),
71
+ nonce: token.subarray(32, 48).toString("hex"),
72
+ };
73
+ }
74
+ export async function readToken(file) {
75
+ const token = await readFile(file);
76
+ if (token.length !== TOKEN_LEN)
77
+ throw new Error(`${file} is not a ${TOKEN_LEN}-byte Wire budget token`);
78
+ return token;
79
+ }
80
+ /** Parse the independently authenticated session as exactly 16 bytes. */
81
+ export function sessionBytes(hex) {
82
+ if (!/^[0-9a-f]{32}$/.test(hex))
83
+ throw new Error("Session must be exactly 32 lowercase hex characters");
84
+ return Buffer.from(hex, "hex");
85
+ }
86
+ /** Strict unsigned 32-bit decimal argument parser. */
87
+ export function unsigned32(value, label, min = 0) {
88
+ if (typeof value !== "string" || !/^\d+$/.test(value))
89
+ throw new Error(`${label} must be a decimal unsigned 32-bit integer`);
90
+ const parsed = Number(value);
91
+ return unsigned(parsed, label, min, MAX_U32);
92
+ }
93
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ declare const _default: import("citty").CommandDef<import("citty").ArgsDef>;
4
+ export default _default;
@@ -0,0 +1,79 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ import { defineCommand } from "citty";
4
+ import { readFile, writeFile } from "node:fs/promises";
5
+ import { randomBytes } from "node:crypto";
6
+ import path from "node:path";
7
+ import { loadNativeEngine } from "@wire-runtime/sdk";
8
+ import { keygen, mint, claims, readToken, sessionBytes, unsigned32, } from "../budget.js";
9
+ function arg(value, label) {
10
+ if (typeof value !== "string" || !value)
11
+ throw new Error(`Missing ${label}`);
12
+ return value;
13
+ }
14
+ export default defineCommand({
15
+ meta: {
16
+ name: "budget",
17
+ description: "Generate keys, mint or inspect signed 112-byte budgets",
18
+ },
19
+ subCommands: {
20
+ keygen: defineCommand({
21
+ args: {
22
+ out: {
23
+ type: "string",
24
+ default: ".wire/keys",
25
+ description: "New key directory",
26
+ },
27
+ },
28
+ async run({ args }) {
29
+ process.stdout.write(JSON.stringify(await keygen(path.resolve(arg(args.out, "out")))) +
30
+ "\n");
31
+ },
32
+ }),
33
+ mint: defineCommand({
34
+ args: {
35
+ key: { type: "string", required: true },
36
+ session: { type: "string", required: true },
37
+ calls: { type: "string", required: true },
38
+ ttl: { type: "string", default: "3600" },
39
+ "key-id": { type: "string", default: "1" },
40
+ out: { type: "string", required: true },
41
+ },
42
+ async run({ args }) {
43
+ const t = mint(await readFile(arg(args.key, "key")), sessionBytes(arg(args.session, "session")), unsigned32(args.calls, "calls", 1), Math.floor(Date.now() / 1000) + unsigned32(args.ttl, "TTL", 1), unsigned32(args["key-id"], "key id"), randomBytes(16));
44
+ await writeFile(arg(args.out, "out"), t, { flag: "wx", mode: 0o600 });
45
+ process.stdout.write(JSON.stringify({ file: args.out, ...claims(t) }) + "\n");
46
+ },
47
+ }),
48
+ inspect: defineCommand({
49
+ args: {
50
+ token: { type: "string", required: true },
51
+ session: { type: "string" },
52
+ "public-key": { type: "string" },
53
+ },
54
+ async run({ args }) {
55
+ const t = await readToken(arg(args.token, "token"));
56
+ const info = claims(t);
57
+ let verified = false;
58
+ if (args.session || args["public-key"]) {
59
+ if (!args.session || !args["public-key"])
60
+ throw new Error("Verification requires --session and --public-key together");
61
+ const pub = (await readFile(arg(args["public-key"], "public-key"), "utf8")).trim();
62
+ if (!/^[0-9a-f]{64}$/.test(pub))
63
+ throw new Error("Public key must be raw 32-byte hex");
64
+ const native = loadNativeEngine();
65
+ const result = native.verifyBudget(t, sessionBytes(arg(args.session, "session")), Buffer.from(pub, "hex"), info.keyId);
66
+ if (result !== 0)
67
+ throw new Error(`Rust token verification rejected (${result})`);
68
+ verified = true;
69
+ }
70
+ process.stdout.write(JSON.stringify({
71
+ ...info,
72
+ verified,
73
+ accounting: "Signed limit only; live remaining calls belong to the running native session",
74
+ }) + "\n");
75
+ },
76
+ }),
77
+ },
78
+ });
79
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../../src/commands/budget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ declare const _default: import("citty").CommandDef<{
4
+ cwd: {
5
+ type: "string";
6
+ default: string;
7
+ description: string;
8
+ };
9
+ }>;
10
+ export default _default;
@@ -0,0 +1,18 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ import { defineCommand } from "citty";
4
+ import path from "node:path";
5
+ import { buildProject } from "../project.js";
6
+ export default defineCommand({
7
+ meta: {
8
+ name: "build",
9
+ description: "Build a production Node deployment bundle",
10
+ },
11
+ args: {
12
+ cwd: { type: "string", default: ".", description: "Project directory" },
13
+ },
14
+ async run({ args }) {
15
+ process.stdout.write(`Built ${await buildProject(path.resolve(args.cwd))}\n`);
16
+ },
17
+ });
18
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,uCAAuC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,eAAe,aAAa,CAAC;IAC3B,IAAI,EAAE;QACJ,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,2CAA2C;KACzD;IACD,IAAI,EAAE;QACJ,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,mBAAmB,EAAE;KACxE;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,SAAS,MAAM,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CACxD,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ declare const _default: import("citty").CommandDef<{
4
+ cwd: {
5
+ type: "string";
6
+ default: string;
7
+ };
8
+ port: {
9
+ type: "string";
10
+ default: string;
11
+ };
12
+ calls: {
13
+ type: "string";
14
+ default: string;
15
+ };
16
+ metrics: {
17
+ type: "boolean";
18
+ default: false;
19
+ description: string;
20
+ };
21
+ }>;
22
+ export default _default;
@@ -0,0 +1,36 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ import { defineCommand } from "citty";
4
+ import path from "node:path";
5
+ import { devServer } from "../dev.js";
6
+ import { unsigned32 } from "../budget.js";
7
+ export default defineCommand({
8
+ meta: {
9
+ name: "dev",
10
+ description: "Loopback dev server, hot reload and native budget simulation",
11
+ },
12
+ args: {
13
+ cwd: { type: "string", default: "." },
14
+ port: { type: "string", default: "3000" },
15
+ calls: { type: "string", default: "100" },
16
+ metrics: {
17
+ type: "boolean",
18
+ default: false,
19
+ description: "Use the instrumented prebuilt addon",
20
+ },
21
+ },
22
+ async run({ args }) {
23
+ const port = unsigned32(args.port, "port");
24
+ if (port > 65535)
25
+ throw new Error("Invalid port");
26
+ const server = await devServer(path.resolve(args.cwd), port, unsigned32(args.calls, "calls", 1), args.metrics);
27
+ const stop = () => {
28
+ process.off("SIGINT", stop);
29
+ process.off("SIGTERM", stop);
30
+ void server.close();
31
+ };
32
+ process.once("SIGINT", stop);
33
+ process.once("SIGTERM", stop);
34
+ },
35
+ });
36
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,uCAAuC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,eAAe,aAAa,CAAC;IAC3B,IAAI,EAAE;QACJ,IAAI,EAAE,KAAK;QACX,WAAW,EAAE,8DAA8D;KAC5E;IACD,IAAI,EAAE;QACJ,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE;QACrC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE;QACzC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;QACzC,OAAO,EAAE;YACP,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,qCAAqC;SACnD;KACF;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3C,IAAI,IAAI,GAAG,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,MAAM,SAAS,CAC5B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EACtB,IAAI,EACJ,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,EAClC,IAAI,CAAC,OAAO,CACb,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAC7B,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ export declare function scaffold(directory: string, name: string): Promise<string>;
4
+ declare const _default: import("citty").CommandDef<{
5
+ name: {
6
+ type: "positional";
7
+ description: string;
8
+ };
9
+ yes: {
10
+ type: "boolean";
11
+ description: string;
12
+ default: false;
13
+ };
14
+ }>;
15
+ export default _default;
@@ -0,0 +1,105 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ import { defineCommand } from "citty";
4
+ import * as prompt from "@clack/prompts";
5
+ import { mkdir, readdir, writeFile, readFile } from "node:fs/promises";
6
+ import path from "node:path";
7
+ export async function scaffold(directory, name) {
8
+ if (!/^[a-z][a-z0-9-]{0,63}$/.test(name))
9
+ throw new Error("Use a lowercase project name with letters, numbers and hyphens");
10
+ try {
11
+ if ((await readdir(directory)).length)
12
+ throw new Error("Refusing to overwrite a nonempty directory");
13
+ }
14
+ catch (error) {
15
+ if (!(error instanceof Error) ||
16
+ !("code" in error) ||
17
+ error.code !== "ENOENT")
18
+ throw error;
19
+ }
20
+ await mkdir(path.join(directory, "tools"), { recursive: true });
21
+ const files = {
22
+ LICENSE: await readFile(new URL("../../LICENSE", import.meta.url), "utf8"),
23
+ "package.json": JSON.stringify({
24
+ name,
25
+ version: "0.1.0",
26
+ private: true,
27
+ license: "MIT",
28
+ type: "module",
29
+ engines: { node: ">=20" },
30
+ scripts: {
31
+ dev: "wire dev",
32
+ build: "wire build",
33
+ start: "node dist/server.mjs",
34
+ },
35
+ dependencies: {
36
+ "@wire-runtime/sdk": "1.0.0",
37
+ "@sinclair/typebox": "0.34.52",
38
+ },
39
+ devDependencies: { "@wire-runtime/cli": "1.0.0", typescript: "5.9.3" },
40
+ }, null, 2) + "\n",
41
+ "wire.config.json": JSON.stringify({
42
+ entry: "tools/index.ts",
43
+ rateLimit: { requestsPerSecond: 100, burst: 100 },
44
+ cacheEntries: 64,
45
+ maxRequestBytes: 16384,
46
+ }, null, 2) + "\n",
47
+ "tools/index.ts": `// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 Wire contributors\nimport { createTool } from '@wire-runtime/sdk';\nimport { Type } from '@sinclair/typebox';\nexport const tools=[createTool({name:'echo',input:Type.Object({text:Type.String()},{additionalProperties:false}),output:Type.String(),cache:{pure:true,ttlMs:1000},handler:({text})=>text})];\n`,
48
+ "tsconfig.json": JSON.stringify({
49
+ compilerOptions: {
50
+ target: "ES2022",
51
+ module: "NodeNext",
52
+ moduleResolution: "NodeNext",
53
+ strict: true,
54
+ noEmit: true,
55
+ },
56
+ include: ["tools"],
57
+ }, null, 2) + "\n",
58
+ ".gitignore": "node_modules/\ndist/\n.wire/\n.env\n",
59
+ "README.md": "# " +
60
+ name +
61
+ "\n\nInstall dependencies, then run `npm run dev`. Development budgets are temporary simulations.\nFor production run `npm run build` and provide WIRE_BUDGET_FILE (raw token), WIRE_SESSION_ID\n(32 hex characters), and WIRE_TRUSTED_KEYS (JSON object of key IDs to raw public-key hex).\nUse `wire budget --help` for key generation, minting and Rust verification.\n",
62
+ };
63
+ for (const [file, data] of Object.entries(files))
64
+ await writeFile(path.join(directory, file), data, { flag: "wx" });
65
+ return directory;
66
+ }
67
+ export default defineCommand({
68
+ meta: { name: "init", description: "Create a typed Wire tool project" },
69
+ args: {
70
+ name: { type: "positional", description: "Project name" },
71
+ yes: {
72
+ type: "boolean",
73
+ description: "Use explicit name without prompts",
74
+ default: false,
75
+ },
76
+ },
77
+ async run({ args }) {
78
+ let name = args.name;
79
+ if (!args.yes) {
80
+ if (!process.stdin.isTTY)
81
+ throw new Error("Non-interactive scaffolding requires a name and --yes");
82
+ prompt.intro("Create a Wire project");
83
+ const answer = await prompt.text({
84
+ message: "Project name",
85
+ initialValue: name ?? "wire-tools",
86
+ validate: (v) => /^[a-z][a-z0-9-]{0,63}$/.test(v ?? "")
87
+ ? undefined
88
+ : "Use lowercase letters, digits and hyphens",
89
+ });
90
+ if (prompt.isCancel(answer)) {
91
+ prompt.cancel("Cancelled");
92
+ return;
93
+ }
94
+ name = answer;
95
+ }
96
+ if (!name)
97
+ throw new Error("Project name required");
98
+ const directory = await scaffold(path.resolve(name), path.basename(name));
99
+ if (!args.yes)
100
+ prompt.outro(`Created ${directory}`);
101
+ else
102
+ process.stdout.write(directory + "\n");
103
+ },
104
+ });
105
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ export {};
@@ -0,0 +1,64 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ import { randomBytes, generateKeyPairSync } from "node:crypto";
4
+ import { pathToFileURL } from "node:url";
5
+ import { Runtime } from "@wire-runtime/sdk";
6
+ import { mint } from "./budget.js";
7
+ const [filename, configText, callsText] = process.argv.slice(2);
8
+ if (!filename || !configText || !callsText)
9
+ throw new Error("Missing dev worker configuration");
10
+ const config = JSON.parse(configText);
11
+ const { privateKey, publicKey } = generateKeyPairSync("ed25519");
12
+ const session = randomBytes(16);
13
+ const expires = Math.floor(Date.now() / 1000) + 3600;
14
+ const pem = privateKey.export({ format: "pem", type: "pkcs8" });
15
+ const token = mint(pem, session, Number(callsText), expires, 1, randomBytes(16));
16
+ const exported = (await import(pathToFileURL(filename).href));
17
+ if (!Array.isArray(exported.tools))
18
+ throw new Error("Tool entry must export tools[]");
19
+ const runtime = Runtime.create({
20
+ tools: exported.tools,
21
+ transport: { kind: "stdio" },
22
+ budget: {
23
+ token,
24
+ sessionId: session,
25
+ trustedKeys: new Map([
26
+ [1, publicKey.export({ type: "spki", format: "der" }).subarray(-32)],
27
+ ]),
28
+ },
29
+ ...config,
30
+ });
31
+ // No private key is persisted or returned over IPC.
32
+ process.on("message", (message) => {
33
+ const m = message;
34
+ void (async () => {
35
+ try {
36
+ if (m.kind === "close") {
37
+ await runtime.close();
38
+ process.disconnect();
39
+ return;
40
+ }
41
+ const result = m.kind === "request"
42
+ ? await runtime.request(Buffer.from(m.body ?? ""))
43
+ : runtime.diagnostics();
44
+ process.send?.({
45
+ id: m.id,
46
+ result: Buffer.isBuffer(result) ? result.toString() : result,
47
+ });
48
+ }
49
+ catch {
50
+ process.send?.({ id: m.id, error: "Development worker failed" });
51
+ }
52
+ })();
53
+ });
54
+ process.on("disconnect", () => {
55
+ void runtime.close().finally(() => process.exit(0));
56
+ });
57
+ process.send?.({
58
+ ready: true,
59
+ sessionId: session.toString("hex"),
60
+ expiresAt: expires,
61
+ maxToolCalls: Number(callsText),
62
+ telemetry: runtime.diagnostics().telemetry,
63
+ });
64
+ //# sourceMappingURL=dev-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-worker.js","sourceRoot":"","sources":["../src/dev-worker.ts"],"names":[],"mappings":"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"}
package/dist/dev.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ export declare function devServer(cwd: string, port: number, calls: number, telemetry?: boolean): Promise<{
4
+ close(): Promise<void>;
5
+ }>;
package/dist/dev.js ADDED
@@ -0,0 +1,314 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ import { createServer } from "node:http";
4
+ import { fork } from "node:child_process";
5
+ import { watch } from "node:fs";
6
+ import { mkdir } from "node:fs/promises";
7
+ import { fileURLToPath } from "node:url";
8
+ import path from "node:path";
9
+ import { context } from "esbuild";
10
+ import { readProject } from "./project.js";
11
+ function startWorker(file, config, calls, telemetry) {
12
+ return new Promise((resolve, reject) => {
13
+ const child = fork(fileURLToPath(new URL("./dev-worker.js", import.meta.url)), [file, JSON.stringify(config), String(calls)], {
14
+ serialization: "advanced",
15
+ stdio: ["ignore", "inherit", "inherit", "ipc"],
16
+ env: { ...process.env, WIRE_TELEMETRY: telemetry ? "1" : "0" },
17
+ });
18
+ const pending = new Map();
19
+ let next = 1;
20
+ let ready = false;
21
+ const timeout = setTimeout(() => {
22
+ child.kill();
23
+ reject(new Error("Development worker startup timed out"));
24
+ }, 10000);
25
+ child.on("error", (error) => {
26
+ clearTimeout(timeout);
27
+ if (!ready)
28
+ reject(error);
29
+ for (const p of pending.values()) {
30
+ clearTimeout(p.timer);
31
+ p.reject(error);
32
+ }
33
+ pending.clear();
34
+ });
35
+ child.on("exit", () => {
36
+ clearTimeout(timeout);
37
+ if (!ready)
38
+ reject(new Error("New worker failed; previous worker retained"));
39
+ for (const p of pending.values()) {
40
+ clearTimeout(p.timer);
41
+ p.reject(new Error("Development worker exited"));
42
+ }
43
+ pending.clear();
44
+ });
45
+ child.on("message", (value) => {
46
+ const m = value;
47
+ if (m.ready) {
48
+ clearTimeout(timeout);
49
+ ready = true;
50
+ resolve({
51
+ child,
52
+ ready: m,
53
+ call(kind, body) {
54
+ if (pending.size >= 32)
55
+ return Promise.reject(new Error("Development worker busy"));
56
+ return new Promise((resolve, reject) => {
57
+ const id = next++;
58
+ const timer = setTimeout(() => {
59
+ pending.delete(id);
60
+ reject(new Error("Development request timed out"));
61
+ }, 30000);
62
+ pending.set(id, { resolve, reject, timer });
63
+ child.send({ id, kind, body }, (error) => {
64
+ if (error) {
65
+ clearTimeout(timer);
66
+ pending.delete(id);
67
+ reject(error);
68
+ }
69
+ });
70
+ });
71
+ },
72
+ stop() {
73
+ if (child.connected)
74
+ child.send({ id: 0, kind: "close" }, () => { });
75
+ const t = setTimeout(() => child.kill(), 5000);
76
+ t.unref();
77
+ },
78
+ });
79
+ return;
80
+ }
81
+ if (m.id !== undefined) {
82
+ const p = pending.get(m.id);
83
+ if (p) {
84
+ clearTimeout(p.timer);
85
+ pending.delete(m.id);
86
+ if (m.error)
87
+ p.reject(new Error(m.error));
88
+ else
89
+ p.resolve(m.result);
90
+ }
91
+ }
92
+ });
93
+ });
94
+ }
95
+ async function body(req, max) {
96
+ return new Promise((resolve, reject) => {
97
+ const chunks = [];
98
+ let size = 0;
99
+ req.on("data", (c) => {
100
+ size += c.length;
101
+ if (size <= max)
102
+ chunks.push(c);
103
+ });
104
+ req.on("end", () => size > max
105
+ ? reject(new Error("Request body too large"))
106
+ : resolve(Buffer.concat(chunks).toString()));
107
+ req.on("error", reject);
108
+ });
109
+ }
110
+ function send(res, code, value) {
111
+ res.writeHead(code, {
112
+ "content-type": "application/json",
113
+ "cache-control": "no-store",
114
+ });
115
+ res.end(JSON.stringify(value));
116
+ }
117
+ export async function devServer(cwd, port, calls, telemetry = false) {
118
+ const config = await readProject(cwd);
119
+ const dir = path.join(cwd, ".wire/dev");
120
+ await mkdir(dir, { recursive: true });
121
+ let active;
122
+ let stopped = false;
123
+ let generation = 0;
124
+ let initialResolve = () => { };
125
+ let initialReject = () => { };
126
+ const initial = new Promise((resolve, reject) => {
127
+ initialResolve = resolve;
128
+ initialReject = reject;
129
+ });
130
+ const buildContext = await context({
131
+ absWorkingDir: cwd,
132
+ entryPoints: [config.entry],
133
+ outfile: path.join(dir, "tools.mjs"),
134
+ bundle: true,
135
+ packages: "external",
136
+ platform: "node",
137
+ format: "esm",
138
+ target: "node20",
139
+ banner: { js: "// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 Wire contributors" },
140
+ sourcemap: true,
141
+ logLevel: "silent",
142
+ plugins: [
143
+ {
144
+ name: "wire-reload",
145
+ setup(build) {
146
+ build.onEnd(async (result) => {
147
+ if (result.errors.length) {
148
+ if (!active)
149
+ initialReject(new Error("Initial tool build failed"));
150
+ process.stderr.write(JSON.stringify({
151
+ event: "build_error",
152
+ errors: result.errors.map((e) => e.text),
153
+ }) + "\n");
154
+ return;
155
+ }
156
+ try {
157
+ const nextConfig = await readProject(cwd);
158
+ if (nextConfig.entry !== config.entry)
159
+ throw new Error("Entry changes require restarting wire dev");
160
+ const next = await startWorker(path.join(dir, "tools.mjs"), nextConfig, calls, telemetry);
161
+ if (stopped) {
162
+ next.stop();
163
+ return;
164
+ }
165
+ const old = active;
166
+ active = next;
167
+ generation++;
168
+ old?.stop();
169
+ initialResolve();
170
+ process.stdout.write(JSON.stringify({
171
+ event: "wire_worker_ready",
172
+ generation,
173
+ ...next.ready,
174
+ }) + "\n");
175
+ }
176
+ catch (error) {
177
+ if (!active)
178
+ initialReject(error instanceof Error ? error : new Error(String(error)));
179
+ process.stderr.write(JSON.stringify({
180
+ event: "reload_error",
181
+ message: String(error),
182
+ }) + "\n");
183
+ }
184
+ });
185
+ },
186
+ },
187
+ ],
188
+ });
189
+ await buildContext.watch();
190
+ try {
191
+ await initial;
192
+ }
193
+ catch (error) {
194
+ await buildContext.dispose();
195
+ throw error;
196
+ }
197
+ const server = createServer((req, res) => {
198
+ void (async () => {
199
+ const host = req.headers.host ?? "";
200
+ const address = server.address();
201
+ const actualPort = typeof address === "object" && address ? address.port : port;
202
+ if (![`127.0.0.1:${actualPort}`, `localhost:${actualPort}`].includes(host)) {
203
+ send(res, 403, { error: "Loopback host required" });
204
+ return;
205
+ }
206
+ if (req.headers.origin && req.headers.origin !== `http://${host}`) {
207
+ send(res, 403, { error: "Origin denied" });
208
+ return;
209
+ }
210
+ const worker = active;
211
+ const workerGeneration = generation;
212
+ if (!worker) {
213
+ send(res, 503, { error: "Worker unavailable" });
214
+ return;
215
+ }
216
+ if (req.method === "GET" && req.url === "/__wire/budget") {
217
+ const d = (await worker.call("diagnostics"));
218
+ send(res, 200, {
219
+ ...worker.ready,
220
+ remaining: d.remaining,
221
+ generation: workerGeneration,
222
+ });
223
+ return;
224
+ }
225
+ if (req.method === "GET" && req.url === "/metrics") {
226
+ const d = (await worker.call("diagnostics"));
227
+ res.writeHead(200, {
228
+ "content-type": "text/plain; version=0.0.4; charset=utf-8",
229
+ });
230
+ res.end(d.prometheus);
231
+ return;
232
+ }
233
+ if (req.method === "GET" && req.url === "/") {
234
+ res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
235
+ res.end(`<title>Wire development</title><h1>Wire development</h1><p>Temporary signed budget; requests are enforced in Rust.</p><pre id="budget"></pre><textarea id="request" rows="7" cols="72">{"jsonrpc":"2.0","id":1,"method":"echo","params":{"text":"hello"}}</textarea><p><button id="send">Execute</button></p><pre id="result"></pre><script>async function refresh(){document.querySelector('#budget').textContent=JSON.stringify(await(await fetch('/__wire/budget')).json(),null,2)}document.querySelector('#send').onclick=async()=>{document.querySelector('#result').textContent=await(await fetch('/rpc',{method:'POST',headers:{'content-type':'application/json'},body:document.querySelector('#request').value})).text();refresh()};refresh();setInterval(refresh,2000)</script>`);
236
+ return;
237
+ }
238
+ if (req.method !== "POST" || req.url !== "/rpc") {
239
+ send(res, 404, { error: "Not found" });
240
+ return;
241
+ }
242
+ if (!req.headers["content-type"]?.startsWith("application/json")) {
243
+ send(res, 415, { error: "application/json required" });
244
+ return;
245
+ }
246
+ const text = await body(req, config.maxRequestBytes);
247
+ const start = performance.now();
248
+ const result = (await worker.call("request", text));
249
+ let method = "<invalid>";
250
+ let errorCode;
251
+ try {
252
+ const parsed = JSON.parse(text);
253
+ if (typeof parsed.method === "string" &&
254
+ /^[A-Za-z0-9_-]{1,64}$/.test(parsed.method))
255
+ method = parsed.method;
256
+ const response = result
257
+ ? JSON.parse(result)
258
+ : undefined;
259
+ errorCode = response?.error?.code;
260
+ }
261
+ catch {
262
+ /* No request payload enters logs. */
263
+ }
264
+ process.stderr.write(JSON.stringify({
265
+ event: "request",
266
+ method,
267
+ durationMs: performance.now() - start,
268
+ errorCode,
269
+ generation: workerGeneration,
270
+ }) + "\n");
271
+ if (result === null) {
272
+ res.writeHead(204);
273
+ res.end();
274
+ }
275
+ else {
276
+ res.writeHead(200, { "content-type": "application/json" });
277
+ res.end(result);
278
+ }
279
+ })().catch((error) => {
280
+ if (!res.headersSent)
281
+ send(res, 503, { error: String(error) });
282
+ else
283
+ res.end();
284
+ });
285
+ });
286
+ await new Promise((resolve, reject) => {
287
+ server.once("error", reject);
288
+ server.listen(port, "127.0.0.1", resolve);
289
+ });
290
+ const bound = server.address();
291
+ process.stdout.write(JSON.stringify({
292
+ event: "wire_dev_ready",
293
+ url: `http://127.0.0.1:${typeof bound === "object" && bound ? bound.port : port}`,
294
+ }) + "\n");
295
+ const configWatcher = watch(cwd, (_event, name) => {
296
+ if (name?.toString() === "wire.config.json")
297
+ void buildContext
298
+ .rebuild()
299
+ .catch((error) => process.stderr.write(String(error) + "\n"));
300
+ });
301
+ return {
302
+ async close() {
303
+ if (stopped)
304
+ return;
305
+ stopped = true;
306
+ configWatcher.close();
307
+ await buildContext.dispose();
308
+ active?.stop();
309
+ server.closeAllConnections();
310
+ await new Promise((resolve) => server.close(() => resolve()));
311
+ },
312
+ };
313
+ }
314
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../src/dev.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) 2026 Wire contributors
4
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) 2026 Wire contributors
4
+ import { defineCommand, runMain } from "citty";
5
+ const main = defineCommand({
6
+ meta: { name: "wire", version: "1.0.0", description: "@wire-runtime CLI" },
7
+ subCommands: {
8
+ init: () => import("./commands/init.js").then((m) => m.default),
9
+ dev: () => import("./commands/dev.js").then((m) => m.default),
10
+ build: () => import("./commands/build.js").then((m) => m.default),
11
+ budget: () => import("./commands/budget.js").then((m) => m.default),
12
+ },
13
+ });
14
+ void runMain(main);
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,+BAA+B;AAC/B,uCAAuC;AACvC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAE/C,MAAM,IAAI,GAAG,aAAa,CAAC;IACzB,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE;IAC1E,WAAW,EAAE;QACX,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC/D,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7D,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACjE,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;KACpE;CACF,CAAC,CAAC;AAEH,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ export interface Project {
4
+ entry: string;
5
+ rateLimit: {
6
+ requestsPerSecond: number;
7
+ burst: number;
8
+ };
9
+ maxRequestBytes: number;
10
+ cacheEntries: number;
11
+ }
12
+ export declare function readProject(cwd: string): Promise<Project>;
13
+ export declare function compileTools(cwd: string, outfile: string): Promise<void>;
14
+ export declare function atomicWrite(filename: string, data: string | Buffer): Promise<void>;
15
+ export declare function buildProject(cwd: string): Promise<string>;
@@ -0,0 +1,79 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 Wire contributors
3
+ import { readFile, mkdir, writeFile, rename } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { build } from "esbuild";
6
+ export async function readProject(cwd) {
7
+ const data = await readFile(path.join(cwd, "wire.config.json"));
8
+ if (data.length > 65536)
9
+ throw new Error("wire.config.json exceeds 64 KiB");
10
+ const value = JSON.parse(data.toString());
11
+ if (Object.keys(value).some((k) => !["entry", "rateLimit", "maxRequestBytes", "cacheEntries"].includes(k)))
12
+ throw new Error("Unknown Wire config field");
13
+ const entry = value.entry ?? "tools/index.ts";
14
+ if (typeof entry !== "string" ||
15
+ path.isAbsolute(entry) ||
16
+ path.relative(cwd, path.resolve(cwd, entry)).startsWith(".."))
17
+ throw new Error("Entry must be inside the project");
18
+ const rate = value.rateLimit;
19
+ const result = {
20
+ entry,
21
+ rateLimit: rate ?? { requestsPerSecond: 100, burst: 100 },
22
+ maxRequestBytes: Number(value.maxRequestBytes ?? 16384),
23
+ cacheEntries: Number(value.cacheEntries ?? 64),
24
+ };
25
+ if (!Number.isFinite(result.rateLimit.requestsPerSecond) ||
26
+ result.rateLimit.requestsPerSecond <= 0 ||
27
+ !Number.isInteger(result.rateLimit.burst) ||
28
+ result.rateLimit.burst < 1 ||
29
+ !Number.isInteger(result.maxRequestBytes) ||
30
+ result.maxRequestBytes < 256 ||
31
+ result.maxRequestBytes > 1048576 ||
32
+ !Number.isInteger(result.cacheEntries) ||
33
+ result.cacheEntries < 0 ||
34
+ result.cacheEntries > 4096)
35
+ throw new Error("Invalid Wire limits");
36
+ return result;
37
+ }
38
+ export async function compileTools(cwd, outfile) {
39
+ await build({
40
+ absWorkingDir: cwd,
41
+ entryPoints: [(await readProject(cwd)).entry],
42
+ outfile,
43
+ bundle: true,
44
+ packages: "external",
45
+ platform: "node",
46
+ format: "esm",
47
+ target: "node20",
48
+ banner: { js: "// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 Wire contributors" },
49
+ sourcemap: true,
50
+ logLevel: "silent",
51
+ });
52
+ }
53
+ export async function atomicWrite(filename, data) {
54
+ await mkdir(path.dirname(filename), { recursive: true });
55
+ const temp = `${filename}.${process.pid}.tmp`;
56
+ await writeFile(temp, data, { mode: 0o600 });
57
+ await rename(temp, filename);
58
+ }
59
+ export async function buildProject(cwd) {
60
+ const config = await readProject(cwd);
61
+ const dist = path.join(cwd, "dist");
62
+ await mkdir(dist, { recursive: true });
63
+ await compileTools(cwd, path.join(dist, "tools.mjs"));
64
+ const server = `// SPDX-License-Identifier: MIT
65
+ // Copyright (c) 2026 Wire contributors
66
+ import { Runtime } from '@wire-runtime/sdk';
67
+ import { serveMcp } from '@wire-runtime/sdk/mcp';
68
+ import { credentialsFromEnv, claimSessionLease } from '@wire-runtime/sdk/credentials';
69
+ import { tools } from './tools.mjs';
70
+ const budget=credentialsFromEnv();
71
+ if(process.env.WIRE_SESSION_GUARD_DIR)claimSessionLease(budget,process.env.WIRE_SESSION_GUARD_DIR);
72
+ if(process.env.WIRE_PROTOCOL && !['mcp','wire'].includes(process.env.WIRE_PROTOCOL))throw new Error('Invalid WIRE_PROTOCOL');
73
+ const serve=process.env.WIRE_PROTOCOL === 'mcp' ? serveMcp : Runtime.serve;
74
+ await serve({tools,transport:{kind:'stdio'},budget,rateLimit:${JSON.stringify(config.rateLimit)},cacheEntries:${config.cacheEntries},maxRequestBytes:${config.maxRequestBytes}});
75
+ `;
76
+ await atomicWrite(path.join(dist, "server.mjs"), server);
77
+ return dist;
78
+ }
79
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,42 @@
1
1
  {
2
2
  "name": "@wire-runtime/cli",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "private": false,
5
+ "description": "Wire CLI: scaffold, build and run bounded MCP servers on the native Wire runtime.",
6
+ "keywords": [
7
+ "mcp",
8
+ "model-context-protocol",
9
+ "cli",
10
+ "native",
11
+ "budget"
12
+ ],
13
+ "type": "module",
14
+ "bin": {
15
+ "wire": "dist/index.js"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "LICENSE"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsc -p tsconfig.build.json && node ../../scripts/native.mjs license-output dist",
23
+ "typecheck": "tsc -p tsconfig.json --noEmit",
24
+ "test": "vitest run --maxWorkers=1 --no-file-parallelism"
25
+ },
26
+ "dependencies": {
27
+ "@wire-runtime/sdk": "workspace:*",
28
+ "citty": "0.1.6",
29
+ "@clack/prompts": "0.11.0",
30
+ "esbuild": "0.25.12"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "22.20.5",
34
+ "typescript": "5.9.3",
35
+ "vitest": "5.0.5",
36
+ "vite": "8.3.5"
37
+ },
38
+ "engines": {
39
+ "node": ">=20"
40
+ },
41
+ "license": "MIT"
42
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.