stitchkit 0.90.3 → 0.90.5
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/CHANGELOG.md +142 -0
- package/dist/agent-runtime-coding-tools.js +4 -4
- package/dist/agent-runtime-harness.js +6 -6
- package/dist/agent-runtime-sandbox.js +4 -4
- package/dist/agent-runtime.js +9 -9
- package/dist/cli.d.ts +14 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +402 -11
- package/dist/{index-2hrfpw2c.js → index-1bnkzq95.js} +2 -2
- package/dist/{index-j7q0xj6d.js → index-3yqgj323.js} +3 -3
- package/dist/{index-gbqjt8jz.js → index-83fafqw8.js} +3 -3
- package/dist/{index-44ht2790.js → index-8pjqv3zh.js} +6 -6
- package/dist/{index-kc6h6hg0.js → index-8z9we758.js} +1 -1
- package/dist/{index-r159gjwy.js → index-fenaekmk.js} +94 -8
- package/dist/{index-1923shw9.js → index-fqg5mfk7.js} +339 -19
- package/dist/{index-f475yj00.js → index-s208wab5.js} +1 -1
- package/dist/{index-79hb1wyh.js → index-tgh3ksfh.js} +5 -5
- package/dist/{index-wb15909q.js → index-zsdgd1tz.js} +3 -3
- package/dist/index.js +7 -7
- package/dist/node.js +2 -2
- package/dist/observability/index.js +1 -1
- package/dist/remote.js +1 -1
- package/dist/server/index.js +6 -6
- package/dist/testing.js +3 -3
- package/dist/tool-invoker.js +6 -6
- package/dist/tools/cli-args.d.ts +30 -6
- package/dist/tools/cli-args.d.ts.map +1 -1
- package/dist/tools/cli-installer.d.ts +34 -0
- package/dist/tools/cli-installer.d.ts.map +1 -0
- package/dist/tools/cli-manifest.d.ts +83 -0
- package/dist/tools/cli-manifest.d.ts.map +1 -0
- package/dist/tools/cli-profile.d.ts +40 -0
- package/dist/tools/cli-profile.d.ts.map +1 -0
- package/dist/tools/cli-update.d.ts +64 -0
- package/dist/tools/cli-update.d.ts.map +1 -0
- package/dist/tools/cli-view.d.ts +12 -0
- package/dist/tools/cli-view.d.ts.map +1 -0
- package/dist/tools/cli.d.ts.map +1 -1
- package/dist/tools/connections/index.d.ts +2 -1
- package/dist/tools/connections/index.d.ts.map +1 -1
- package/dist/tools/connections/index.js +74 -14
- package/dist/tools/connections/mcp-envelope.d.ts +44 -0
- package/dist/tools/connections/mcp-envelope.d.ts.map +1 -0
- package/dist/tools/connections/mcp.d.ts +2 -1
- package/dist/tools/connections/mcp.d.ts.map +1 -1
- package/dist/tools/connections/mount.d.ts.map +1 -1
- package/dist/tools/connections/openapi.d.ts +2 -1
- package/dist/tools/connections/openapi.d.ts.map +1 -1
- package/dist/tools/connections/runtime.d.ts +17 -0
- package/dist/tools/connections/runtime.d.ts.map +1 -1
- package/dist/tools/connections/types.d.ts +18 -1
- package/dist/tools/connections/types.d.ts.map +1 -1
- package/dist/tools/json-schema-dialect.d.ts +17 -0
- package/dist/tools/json-schema-dialect.d.ts.map +1 -0
- package/dist/tools/presentation.d.ts +8 -1
- package/dist/tools/presentation.d.ts.map +1 -1
- package/dist/tools.js +13 -13
- package/dist/tracking.js +1 -1
- package/llms-full.txt +273 -3
- package/package.json +1 -1
- package/dist/{index-db51n3xr.js → index-ra6txecz.js} +3 -3
package/dist/cli.js
CHANGED
|
@@ -1,33 +1,424 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CliArgumentError,
|
|
2
3
|
DEFAULT_EXIT_CODES,
|
|
3
4
|
createCli,
|
|
4
5
|
defineCliCommand,
|
|
5
6
|
emitResult,
|
|
7
|
+
extractCliGlobalOptions,
|
|
8
|
+
fetchGuarded,
|
|
6
9
|
parseCliArgs,
|
|
7
|
-
pollUntilDone
|
|
8
|
-
|
|
10
|
+
pollUntilDone,
|
|
11
|
+
readCapped,
|
|
12
|
+
renderCliView,
|
|
13
|
+
routeCliArgv
|
|
14
|
+
} from "./index-fqg5mfk7.js";
|
|
9
15
|
import"./index-sbdmyz75.js";
|
|
10
|
-
import"./index-
|
|
11
|
-
import"./index-
|
|
12
|
-
import"./index-
|
|
16
|
+
import"./index-zsdgd1tz.js";
|
|
17
|
+
import"./index-1bnkzq95.js";
|
|
18
|
+
import"./index-8pjqv3zh.js";
|
|
13
19
|
import"./index-vsbzgd7b.js";
|
|
14
20
|
import"./index-f9mb610r.js";
|
|
15
21
|
import"./index-2hryh65w.js";
|
|
16
22
|
import"./index-kazec06k.js";
|
|
17
23
|
import"./index-6k1937bx.js";
|
|
18
|
-
import"./index-scs3f1eg.js";
|
|
19
24
|
import"./index-zcgf3gqf.js";
|
|
20
|
-
import
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
import"./index-
|
|
25
|
+
import {
|
|
26
|
+
coerceJsonArgs
|
|
27
|
+
} from "./index-7zbps32p.js";
|
|
28
|
+
import"./index-8z9we758.js";
|
|
29
|
+
import"./index-fenaekmk.js";
|
|
24
30
|
import"./index-cby4ar3v.js";
|
|
31
|
+
import {
|
|
32
|
+
AppError
|
|
33
|
+
} from "./index-scs3f1eg.js";
|
|
34
|
+
import {
|
|
35
|
+
safeJsonParse
|
|
36
|
+
} from "./index-kzfs85xp.js";
|
|
25
37
|
import"./index-77fekveh.js";
|
|
38
|
+
// src/tools/cli-installer.ts
|
|
39
|
+
function shellQuote(value) {
|
|
40
|
+
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
41
|
+
}
|
|
42
|
+
function renderCliInstaller(config) {
|
|
43
|
+
const binary = config.binaryName ?? config.manifest.name;
|
|
44
|
+
const installDir = config.installDir ?? "$HOME/.local/bin";
|
|
45
|
+
const assets = config.asset ? [config.asset] : config.manifest.assets;
|
|
46
|
+
if (assets.length === 0) {
|
|
47
|
+
throw new Error("[stitchkit] a build manifest with no assets installs nothing");
|
|
48
|
+
}
|
|
49
|
+
const selection = assets.length === 1 && assets[0] !== undefined ? singleTarget(assets[0]) : unameDispatch(assets);
|
|
50
|
+
return `#!/bin/sh
|
|
51
|
+
# ${binary} ${config.manifest.version} (${config.manifest.commit})
|
|
52
|
+
# Generated from the build manifest — it parses no JSON and needs no jq.
|
|
53
|
+
set -eu
|
|
54
|
+
|
|
55
|
+
binary=${shellQuote(binary)}
|
|
56
|
+
dir="\${INSTALL_DIR:-${installDir}}"
|
|
57
|
+
|
|
58
|
+
${selection}
|
|
59
|
+
|
|
60
|
+
fetch() {
|
|
61
|
+
if command -v curl >/dev/null 2>&1; then
|
|
62
|
+
curl -fsSL "$1" -o "$2"
|
|
63
|
+
elif command -v wget >/dev/null 2>&1; then
|
|
64
|
+
wget -q "$1" -O "$2"
|
|
65
|
+
else
|
|
66
|
+
echo "need curl or wget" >&2
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
digest() {
|
|
72
|
+
if command -v sha256sum >/dev/null 2>&1; then
|
|
73
|
+
sha256sum "$1" | cut -d' ' -f1
|
|
74
|
+
elif command -v shasum >/dev/null 2>&1; then
|
|
75
|
+
shasum -a 256 "$1" | cut -d' ' -f1
|
|
76
|
+
elif command -v openssl >/dev/null 2>&1; then
|
|
77
|
+
openssl dgst -sha256 "$1" | awk '{print $NF}'
|
|
78
|
+
else
|
|
79
|
+
echo "need sha256sum, shasum or openssl" >&2
|
|
80
|
+
exit 1
|
|
81
|
+
fi
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
tmp="$(mktemp -d)"
|
|
85
|
+
trap 'rm -rf "$tmp"' EXIT
|
|
86
|
+
|
|
87
|
+
fetch "$url" "$tmp/download"
|
|
88
|
+
if [ "$compression" = "gzip" ]; then
|
|
89
|
+
gzip -dc "$tmp/download" > "$tmp/binary"
|
|
90
|
+
else
|
|
91
|
+
mv "$tmp/download" "$tmp/binary"
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
actual="$(digest "$tmp/binary")"
|
|
95
|
+
if [ "$actual" != "$sha256" ]; then
|
|
96
|
+
echo "checksum mismatch: expected $sha256, got $actual" >&2
|
|
97
|
+
exit 1
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
actual_size="$(wc -c < "$tmp/binary" | tr -d ' ')"
|
|
101
|
+
if [ "$actual_size" != "$size" ]; then
|
|
102
|
+
echo "size mismatch: expected $size bytes, got $actual_size" >&2
|
|
103
|
+
exit 1
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
mkdir -p "$dir"
|
|
107
|
+
chmod 755 "$tmp/binary"
|
|
108
|
+
# A rename, never a write over the file in place: anything else can leave a
|
|
109
|
+
# half-written executable where a working one used to be.
|
|
110
|
+
mv "$tmp/binary" "$dir/$binary"
|
|
111
|
+
|
|
112
|
+
echo "installed $binary ${config.manifest.version} to $dir/$binary"
|
|
113
|
+
case ":$PATH:" in
|
|
114
|
+
*":$dir:"*) ;;
|
|
115
|
+
*) echo "note: $dir is not on your PATH" >&2 ;;
|
|
116
|
+
esac
|
|
117
|
+
`;
|
|
118
|
+
}
|
|
119
|
+
function singleTarget(asset) {
|
|
120
|
+
return [
|
|
121
|
+
`url=${shellQuote(asset.url)}`,
|
|
122
|
+
`sha256=${shellQuote(asset.sha256)}`,
|
|
123
|
+
`size=${shellQuote(String(asset.size))}`,
|
|
124
|
+
`compression=${shellQuote(asset.compression)}`
|
|
125
|
+
].join(`
|
|
126
|
+
`);
|
|
127
|
+
}
|
|
128
|
+
function unameDispatch(assets) {
|
|
129
|
+
const cases = assets.map((asset) => ` ${asset.platform}/${asset.arch})
|
|
130
|
+
url=${shellQuote(asset.url)}
|
|
131
|
+
sha256=${shellQuote(asset.sha256)}
|
|
132
|
+
size=${shellQuote(String(asset.size))}
|
|
133
|
+
compression=${shellQuote(asset.compression)}
|
|
134
|
+
;;`).join(`
|
|
135
|
+
`);
|
|
136
|
+
const published = assets.map((asset) => `${asset.platform}/${asset.arch}`).join(", ");
|
|
137
|
+
return `case "$(uname -s)" in
|
|
138
|
+
Darwin) platform=darwin ;;
|
|
139
|
+
Linux) platform=linux ;;
|
|
140
|
+
*) platform="$(uname -s)" ;;
|
|
141
|
+
esac
|
|
142
|
+
case "$(uname -m)" in
|
|
143
|
+
x86_64|amd64) arch=x64 ;;
|
|
144
|
+
aarch64|arm64) arch=arm64 ;;
|
|
145
|
+
*) arch="$(uname -m)" ;;
|
|
146
|
+
esac
|
|
147
|
+
|
|
148
|
+
case "$platform/$arch" in
|
|
149
|
+
${cases}
|
|
150
|
+
*)
|
|
151
|
+
echo "no published build for $platform/$arch — published: ${published}" >&2
|
|
152
|
+
exit 1
|
|
153
|
+
;;
|
|
154
|
+
esac`;
|
|
155
|
+
}
|
|
156
|
+
// src/tools/cli-manifest.ts
|
|
157
|
+
import { z } from "zod";
|
|
158
|
+
var CliBuildTargetSchema = z.object({
|
|
159
|
+
platform: z.string().min(1),
|
|
160
|
+
arch: z.string().min(1)
|
|
161
|
+
});
|
|
162
|
+
var CliBuildAssetSchema = CliBuildTargetSchema.extend({
|
|
163
|
+
url: z.url(),
|
|
164
|
+
compression: z.enum(["gzip", "none"]).default("none"),
|
|
165
|
+
size: z.int().positive(),
|
|
166
|
+
sha256: z.string().regex(/^[0-9a-f]{64}$/, "sha256 must be 64 lowercase hex characters")
|
|
167
|
+
});
|
|
168
|
+
var CliBuildManifestSchema = z.object({
|
|
169
|
+
name: z.string().min(1),
|
|
170
|
+
version: z.string().min(1),
|
|
171
|
+
commit: z.string().min(1),
|
|
172
|
+
builtAt: z.iso.datetime(),
|
|
173
|
+
assets: z.array(CliBuildAssetSchema)
|
|
174
|
+
});
|
|
175
|
+
var CliBuildStampSchema = z.object({
|
|
176
|
+
version: z.string().min(1),
|
|
177
|
+
commit: z.string().min(1),
|
|
178
|
+
builtAt: z.iso.datetime()
|
|
179
|
+
});
|
|
180
|
+
function formatCliBuildStamp(stamp, name) {
|
|
181
|
+
const prefix = name ? `${name} ` : "";
|
|
182
|
+
return `${prefix}${stamp.version} (${stamp.commit.slice(0, 12)}, built ${stamp.builtAt})`;
|
|
183
|
+
}
|
|
184
|
+
function currentCliBuildTarget() {
|
|
185
|
+
return { platform: process.platform, arch: process.arch };
|
|
186
|
+
}
|
|
187
|
+
function selectCliBuildAsset(manifest, target = currentCliBuildTarget()) {
|
|
188
|
+
return manifest.assets.find((asset) => asset.platform === target.platform && asset.arch === target.arch);
|
|
189
|
+
}
|
|
190
|
+
function assertCliPublishable(previous, next) {
|
|
191
|
+
if (!previous)
|
|
192
|
+
return;
|
|
193
|
+
if (previous.version !== next.version)
|
|
194
|
+
return;
|
|
195
|
+
if (previous.commit === next.commit)
|
|
196
|
+
return;
|
|
197
|
+
throw new Error(`[stitchkit] ${next.name} ${next.version} was already published from commit ${previous.commit}; ` + `refusing to republish it from ${next.commit} — bump the version instead`);
|
|
198
|
+
}
|
|
199
|
+
// src/tools/cli-profile.ts
|
|
200
|
+
import {
|
|
201
|
+
chmodSync,
|
|
202
|
+
existsSync,
|
|
203
|
+
mkdirSync,
|
|
204
|
+
readdirSync,
|
|
205
|
+
readFileSync,
|
|
206
|
+
statSync,
|
|
207
|
+
writeFileSync
|
|
208
|
+
} from "node:fs";
|
|
209
|
+
import { join } from "node:path";
|
|
210
|
+
var PROFILE_SUFFIX = ".json";
|
|
211
|
+
var FILE_MODE = 384;
|
|
212
|
+
var DIRECTORY_MODE = 448;
|
|
213
|
+
|
|
214
|
+
class CliProfileError extends AppError {
|
|
215
|
+
constructor(message, code = "NOT_FOUND") {
|
|
216
|
+
super(code, message, code === "NOT_FOUND" ? 404 : code === "FORBIDDEN" ? 403 : 400);
|
|
217
|
+
this.name = "CliProfileError";
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function assertProfileName(name) {
|
|
221
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(name)) {
|
|
222
|
+
throw new CliProfileError(`"${name}" is not a usable profile name — letters, digits, dot, dash and underscore`, "BAD_REQUEST");
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function createCliProfileStore(config) {
|
|
226
|
+
const announce = config.announce ?? ((line) => process.stderr.write(`${line}
|
|
227
|
+
`));
|
|
228
|
+
const pathFor = (name) => {
|
|
229
|
+
assertProfileName(name);
|
|
230
|
+
return join(config.directory, `${name}${PROFILE_SUFFIX}`);
|
|
231
|
+
};
|
|
232
|
+
const list = () => {
|
|
233
|
+
if (!existsSync(config.directory))
|
|
234
|
+
return [];
|
|
235
|
+
return readdirSync(config.directory).filter((entry) => entry.endsWith(PROFILE_SUFFIX)).map((entry) => entry.slice(0, -PROFILE_SUFFIX.length)).sort();
|
|
236
|
+
};
|
|
237
|
+
const read = (name) => {
|
|
238
|
+
const path = pathFor(name);
|
|
239
|
+
if (!existsSync(path)) {
|
|
240
|
+
throw new CliProfileError(missingMessage(name, path, config));
|
|
241
|
+
}
|
|
242
|
+
const mode = statSync(path).mode & 63;
|
|
243
|
+
if (mode !== 0) {
|
|
244
|
+
throw new CliProfileError(`profile "${name}" is readable by other users — run: chmod 600 ${path}`, "FORBIDDEN");
|
|
245
|
+
}
|
|
246
|
+
const parsed = safeJsonParse(readFileSync(path, "utf8"));
|
|
247
|
+
const result = config.schema.safeParse(parsed);
|
|
248
|
+
if (!result.success) {
|
|
249
|
+
const issue = result.error.issues[0];
|
|
250
|
+
const field = issue?.path.join(".");
|
|
251
|
+
throw new CliProfileError(`profile "${name}" (${path}) is not usable: ${field ? `${field}: ` : ""}${issue?.message ?? "invalid"}`, "BAD_REQUEST");
|
|
252
|
+
}
|
|
253
|
+
return result.data;
|
|
254
|
+
};
|
|
255
|
+
return {
|
|
256
|
+
directory: config.directory,
|
|
257
|
+
pathFor,
|
|
258
|
+
list,
|
|
259
|
+
read,
|
|
260
|
+
write(name, value) {
|
|
261
|
+
const path = pathFor(name);
|
|
262
|
+
mkdirSync(config.directory, { recursive: true, mode: DIRECTORY_MODE });
|
|
263
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
264
|
+
`, { mode: FILE_MODE });
|
|
265
|
+
chmodSync(path, FILE_MODE);
|
|
266
|
+
return path;
|
|
267
|
+
},
|
|
268
|
+
resolve(name) {
|
|
269
|
+
if (name !== undefined) {
|
|
270
|
+
const path = pathFor(name);
|
|
271
|
+
return { name, path, value: read(name), substituted: false };
|
|
272
|
+
}
|
|
273
|
+
const configured = list();
|
|
274
|
+
const only = configured[0];
|
|
275
|
+
if (configured.length === 1 && only !== undefined) {
|
|
276
|
+
const path = pathFor(only);
|
|
277
|
+
announce(`[${only}] using the only configured profile (${path})`);
|
|
278
|
+
return { name: only, path, value: read(only), substituted: true };
|
|
279
|
+
}
|
|
280
|
+
if (configured.length === 0) {
|
|
281
|
+
const example = join(config.directory, `<name>${PROFILE_SUFFIX}`);
|
|
282
|
+
throw new CliProfileError(`no profile is configured in ${config.directory}${config.createHint ? ` — ${config.createHint("<name>", example)}` : ""}`);
|
|
283
|
+
}
|
|
284
|
+
throw new CliProfileError(`several profiles are configured (${configured.join(", ")}) — name one`, "BAD_REQUEST");
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
function missingMessage(name, path, config) {
|
|
289
|
+
const hint = config.createHint ? ` — ${config.createHint(name, path)}` : "";
|
|
290
|
+
return `profile "${name}" is not configured; expected ${path}${hint}`;
|
|
291
|
+
}
|
|
292
|
+
// src/tools/cli-update.ts
|
|
293
|
+
import { createHash } from "node:crypto";
|
|
294
|
+
import { chmodSync as chmodSync2, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
295
|
+
import { basename, dirname, join as join2 } from "node:path";
|
|
296
|
+
import { gunzipSync } from "node:zlib";
|
|
297
|
+
var DEFAULT_CHECK_TIMEOUT_MS = 2000;
|
|
298
|
+
var DEFAULT_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
299
|
+
var DEFAULT_DOWNLOAD_TIMEOUT_MS = 120000;
|
|
300
|
+
var MANIFEST_MAX_BYTES = 256 * 1024;
|
|
301
|
+
var DEFAULT_MAX_ASSET_BYTES = 256 * 1024 * 1024;
|
|
302
|
+
function parseVersion(value) {
|
|
303
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/.exec(value.trim());
|
|
304
|
+
if (!match)
|
|
305
|
+
return;
|
|
306
|
+
const numbers = [match[1], match[2], match[3]].map((part) => Number(part));
|
|
307
|
+
if (numbers.some((part) => !Number.isFinite(part)))
|
|
308
|
+
return;
|
|
309
|
+
return { numbers, prerelease: match[4] };
|
|
310
|
+
}
|
|
311
|
+
function compareCliVersions(left, right) {
|
|
312
|
+
const a = parseVersion(left);
|
|
313
|
+
const b = parseVersion(right);
|
|
314
|
+
if (!a || !b)
|
|
315
|
+
return;
|
|
316
|
+
for (let index = 0;index < 3; index++) {
|
|
317
|
+
const difference = (a.numbers[index] ?? 0) - (b.numbers[index] ?? 0);
|
|
318
|
+
if (difference !== 0)
|
|
319
|
+
return difference < 0 ? -1 : 1;
|
|
320
|
+
}
|
|
321
|
+
if (a.prerelease === b.prerelease)
|
|
322
|
+
return 0;
|
|
323
|
+
if (a.prerelease === undefined)
|
|
324
|
+
return 1;
|
|
325
|
+
if (b.prerelease === undefined)
|
|
326
|
+
return -1;
|
|
327
|
+
return a.prerelease < b.prerelease ? -1 : 1;
|
|
328
|
+
}
|
|
329
|
+
async function checkCliUpdate(config) {
|
|
330
|
+
const now = config.now ?? Date.now();
|
|
331
|
+
const interval = config.intervalMs ?? DEFAULT_CHECK_INTERVAL_MS;
|
|
332
|
+
if (config.lastCheckedAt !== undefined && now - config.lastCheckedAt < interval) {
|
|
333
|
+
return { status: "skipped", nextCheckAt: config.lastCheckedAt + interval };
|
|
334
|
+
}
|
|
335
|
+
try {
|
|
336
|
+
const response = await fetchGuarded(new URL(config.manifestUrl), config.allowPrivateHosts ?? false, {
|
|
337
|
+
timeoutMs: config.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS,
|
|
338
|
+
bodyTimeoutMs: config.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS
|
|
339
|
+
});
|
|
340
|
+
if (!response.ok)
|
|
341
|
+
return { status: "unknown", reason: `manifest responded ${response.status}` };
|
|
342
|
+
const body = await readCapped(response, MANIFEST_MAX_BYTES);
|
|
343
|
+
if (!body)
|
|
344
|
+
return { status: "unknown", reason: "manifest is larger than expected" };
|
|
345
|
+
const parsed = CliBuildManifestSchema.safeParse(JSON.parse(body.toString("utf8")));
|
|
346
|
+
if (!parsed.success)
|
|
347
|
+
return { status: "unknown", reason: "manifest did not validate" };
|
|
348
|
+
const manifest = parsed.data;
|
|
349
|
+
const order = compareCliVersions(config.currentVersion, manifest.version);
|
|
350
|
+
if (order === undefined) {
|
|
351
|
+
return {
|
|
352
|
+
status: "unknown",
|
|
353
|
+
reason: `cannot compare ${config.currentVersion} with ${manifest.version}`
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
if (order >= 0)
|
|
357
|
+
return { status: "current", version: manifest.version };
|
|
358
|
+
const asset = selectCliBuildAsset(manifest, config.target ?? currentCliBuildTarget());
|
|
359
|
+
return {
|
|
360
|
+
status: "outdated",
|
|
361
|
+
version: manifest.version,
|
|
362
|
+
manifest,
|
|
363
|
+
...asset && { asset }
|
|
364
|
+
};
|
|
365
|
+
} catch (error) {
|
|
366
|
+
return {
|
|
367
|
+
status: "unknown",
|
|
368
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async function applyCliUpdate(config) {
|
|
373
|
+
const target = config.targetPath ?? process.execPath;
|
|
374
|
+
const response = await fetchGuarded(new URL(config.asset.url), config.allowPrivateHosts ?? false, {
|
|
375
|
+
timeoutMs: config.timeoutMs ?? DEFAULT_DOWNLOAD_TIMEOUT_MS,
|
|
376
|
+
bodyTimeoutMs: config.timeoutMs ?? DEFAULT_DOWNLOAD_TIMEOUT_MS
|
|
377
|
+
});
|
|
378
|
+
if (!response.ok) {
|
|
379
|
+
throw new Error(`[stitchkit] update download responded ${response.status}`);
|
|
380
|
+
}
|
|
381
|
+
const transferred = await readCapped(response, config.maxBytes ?? DEFAULT_MAX_ASSET_BYTES);
|
|
382
|
+
if (!transferred)
|
|
383
|
+
throw new Error("[stitchkit] update download exceeded the size ceiling");
|
|
384
|
+
const bytes = config.asset.compression === "gzip" ? gunzipSync(transferred) : transferred;
|
|
385
|
+
if (bytes.length !== config.asset.size) {
|
|
386
|
+
throw new Error(`[stitchkit] update is ${bytes.length} bytes, manifest says ${config.asset.size} — refusing to install it`);
|
|
387
|
+
}
|
|
388
|
+
const sha256 = createHash("sha256").update(bytes).digest("hex");
|
|
389
|
+
if (sha256 !== config.asset.sha256) {
|
|
390
|
+
throw new Error(`[stitchkit] update digest ${sha256} does not match the manifest — refusing to install it`);
|
|
391
|
+
}
|
|
392
|
+
const staged = join2(dirname(target), `.${basename(target)}.${process.pid}.${Date.now()}`);
|
|
393
|
+
writeFileSync2(staged, bytes, { mode: 493 });
|
|
394
|
+
chmodSync2(staged, 493);
|
|
395
|
+
renameSync(staged, target);
|
|
396
|
+
return { path: target, bytes: bytes.length, sha256 };
|
|
397
|
+
}
|
|
26
398
|
export {
|
|
399
|
+
selectCliBuildAsset,
|
|
400
|
+
routeCliArgv,
|
|
401
|
+
renderCliView,
|
|
402
|
+
renderCliInstaller,
|
|
27
403
|
pollUntilDone,
|
|
28
404
|
parseCliArgs,
|
|
405
|
+
formatCliBuildStamp,
|
|
406
|
+
extractCliGlobalOptions,
|
|
29
407
|
emitResult,
|
|
30
408
|
defineCliCommand,
|
|
409
|
+
currentCliBuildTarget,
|
|
410
|
+
createCliProfileStore,
|
|
31
411
|
createCli,
|
|
32
|
-
|
|
412
|
+
compareCliVersions,
|
|
413
|
+
coerceJsonArgs,
|
|
414
|
+
checkCliUpdate,
|
|
415
|
+
assertCliPublishable,
|
|
416
|
+
applyCliUpdate,
|
|
417
|
+
DEFAULT_EXIT_CODES,
|
|
418
|
+
CliProfileError,
|
|
419
|
+
CliBuildTargetSchema,
|
|
420
|
+
CliBuildStampSchema,
|
|
421
|
+
CliBuildManifestSchema,
|
|
422
|
+
CliBuildAssetSchema,
|
|
423
|
+
CliArgumentError
|
|
33
424
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
executeToolMethod
|
|
3
|
-
} from "./index-
|
|
3
|
+
} from "./index-8pjqv3zh.js";
|
|
4
4
|
import {
|
|
5
5
|
assertToolExtensionCompatible,
|
|
6
6
|
mergeSchemas,
|
|
7
7
|
projectToolSurface,
|
|
8
8
|
rebuildObject
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-fenaekmk.js";
|
|
10
10
|
|
|
11
11
|
// src/tools/mount.ts
|
|
12
12
|
import { z } from "zod";
|
|
@@ -18,13 +18,13 @@ import {
|
|
|
18
18
|
probeAgentProcessSandbox,
|
|
19
19
|
refuseMissingCodingPath
|
|
20
20
|
} from "./index-gte38nbm.js";
|
|
21
|
+
import {
|
|
22
|
+
defineRuntimeTool
|
|
23
|
+
} from "./index-8z9we758.js";
|
|
21
24
|
import {
|
|
22
25
|
conflict,
|
|
23
26
|
forbidden
|
|
24
27
|
} from "./index-scs3f1eg.js";
|
|
25
|
-
import {
|
|
26
|
-
defineRuntimeTool
|
|
27
|
-
} from "./index-kc6h6hg0.js";
|
|
28
28
|
|
|
29
29
|
// src/agent-runtime/coding-tool-contract.ts
|
|
30
30
|
import { z } from "zod";
|
|
@@ -4,16 +4,16 @@ import {
|
|
|
4
4
|
} from "./index-7rkhw9ec.js";
|
|
5
5
|
import {
|
|
6
6
|
collectToolSurface
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-zsdgd1tz.js";
|
|
8
8
|
import {
|
|
9
9
|
createToolRunner,
|
|
10
10
|
formatToolError
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-1bnkzq95.js";
|
|
12
12
|
import {
|
|
13
13
|
isToolExecutionControlError,
|
|
14
14
|
toolCauseFromResult,
|
|
15
15
|
toolResultFromError
|
|
16
|
-
} from "./index-
|
|
16
|
+
} from "./index-8pjqv3zh.js";
|
|
17
17
|
import {
|
|
18
18
|
isRecord
|
|
19
19
|
} from "./index-77fekveh.js";
|
|
@@ -7,20 +7,20 @@ import {
|
|
|
7
7
|
normalizeError,
|
|
8
8
|
validateDeclaredOutput
|
|
9
9
|
} from "./index-2hryh65w.js";
|
|
10
|
+
import {
|
|
11
|
+
coerceJsonArgs
|
|
12
|
+
} from "./index-7zbps32p.js";
|
|
13
|
+
import {
|
|
14
|
+
objectShapeKeys
|
|
15
|
+
} from "./index-fenaekmk.js";
|
|
10
16
|
import {
|
|
11
17
|
AppError,
|
|
12
18
|
STITCH_ERROR_STATUS,
|
|
13
19
|
isStitchErrorCode
|
|
14
20
|
} from "./index-scs3f1eg.js";
|
|
15
|
-
import {
|
|
16
|
-
coerceJsonArgs
|
|
17
|
-
} from "./index-7zbps32p.js";
|
|
18
21
|
import {
|
|
19
22
|
isUnsafeKey
|
|
20
23
|
} from "./index-kzfs85xp.js";
|
|
21
|
-
import {
|
|
22
|
-
objectShapeKeys
|
|
23
|
-
} from "./index-r159gjwy.js";
|
|
24
24
|
import {
|
|
25
25
|
isRecord
|
|
26
26
|
} from "./index-77fekveh.js";
|
|
@@ -667,6 +667,40 @@ function assertUniqueToolName(name, taken, surface) {
|
|
|
667
667
|
|
|
668
668
|
// src/tools/presentation.ts
|
|
669
669
|
import { z as z2 } from "zod";
|
|
670
|
+
|
|
671
|
+
// src/tools/json-schema-dialect.ts
|
|
672
|
+
var DRAFT_07_MARKER = "draft-07";
|
|
673
|
+
var DRAFT_07_KEYWORD = "definitions";
|
|
674
|
+
var DEFS_KEYWORD = "$defs";
|
|
675
|
+
function declaresDraft07(dialect) {
|
|
676
|
+
return typeof dialect === "string" && dialect.includes(DRAFT_07_MARKER);
|
|
677
|
+
}
|
|
678
|
+
function rewriteDefinitionPointers(value) {
|
|
679
|
+
if (Array.isArray(value))
|
|
680
|
+
return value.map(rewriteDefinitionPointers);
|
|
681
|
+
if (!isRecord(value))
|
|
682
|
+
return value;
|
|
683
|
+
const rewritten = {};
|
|
684
|
+
for (const [key, child] of Object.entries(value)) {
|
|
685
|
+
rewritten[key] = key === "$ref" && typeof child === "string" && child.startsWith(`#/${DRAFT_07_KEYWORD}/`) ? `#/${DEFS_KEYWORD}/${child.slice(`#/${DRAFT_07_KEYWORD}/`.length)}` : rewriteDefinitionPointers(child);
|
|
686
|
+
}
|
|
687
|
+
return rewritten;
|
|
688
|
+
}
|
|
689
|
+
function withDefsDialect(schema) {
|
|
690
|
+
const definitions = schema[DRAFT_07_KEYWORD];
|
|
691
|
+
if (!isRecord(definitions) || DEFS_KEYWORD in schema)
|
|
692
|
+
return schema;
|
|
693
|
+
const rewritten = {};
|
|
694
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
695
|
+
if (key === DRAFT_07_KEYWORD)
|
|
696
|
+
continue;
|
|
697
|
+
rewritten[key] = rewriteDefinitionPointers(value);
|
|
698
|
+
}
|
|
699
|
+
rewritten[DEFS_KEYWORD] = rewriteDefinitionPointers(definitions);
|
|
700
|
+
return rewritten;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// src/tools/presentation.ts
|
|
670
704
|
function withoutDialect(schema) {
|
|
671
705
|
const result = {};
|
|
672
706
|
for (const [key, value] of Object.entries(schema)) {
|
|
@@ -684,25 +718,59 @@ function hasLocalReference(value) {
|
|
|
684
718
|
return true;
|
|
685
719
|
return Object.values(value).some(hasLocalReference);
|
|
686
720
|
}
|
|
687
|
-
|
|
721
|
+
var NAMESPACE_SEPARATOR = "__";
|
|
722
|
+
var DEFINITION_KEYWORDS = ["definitions", "$defs"];
|
|
723
|
+
function rewriteReference(reference, namespace, targets) {
|
|
724
|
+
if (reference === "#" || reference === "#/") {
|
|
725
|
+
targets.rootReferenced = true;
|
|
726
|
+
return `#/definitions/${namespace}`;
|
|
727
|
+
}
|
|
728
|
+
const segments = reference.slice(2).split("/");
|
|
729
|
+
const [keyword, name, ...rest] = segments;
|
|
730
|
+
if (keyword !== undefined && name !== undefined && DEFINITION_KEYWORDS.includes(keyword)) {
|
|
731
|
+
const renamed = `${namespace}${NAMESPACE_SEPARATOR}${name}`;
|
|
732
|
+
return ["#", "definitions", renamed, ...rest].join("/");
|
|
733
|
+
}
|
|
734
|
+
targets.rootReferenced = true;
|
|
735
|
+
return `#/definitions/${namespace}/${segments.join("/")}`;
|
|
736
|
+
}
|
|
737
|
+
function rewriteLocalReferences(value, namespace, targets) {
|
|
688
738
|
if (Array.isArray(value)) {
|
|
689
|
-
return value.map((child) => rewriteLocalReferences(child, namespace));
|
|
739
|
+
return value.map((child) => rewriteLocalReferences(child, namespace, targets));
|
|
690
740
|
}
|
|
691
741
|
if (!isRecord(value))
|
|
692
742
|
return value;
|
|
693
743
|
const rewritten = {};
|
|
694
744
|
for (const [key, child] of Object.entries(value)) {
|
|
695
|
-
rewritten[key] = key === "$ref" && typeof child === "string" && child.startsWith("#") ?
|
|
745
|
+
rewritten[key] = key === "$ref" && typeof child === "string" && child.startsWith("#") ? rewriteReference(child, namespace, targets) : rewriteLocalReferences(child, namespace, targets);
|
|
696
746
|
}
|
|
697
747
|
return rewritten;
|
|
698
748
|
}
|
|
699
749
|
function namespaceLocalReferences(schema, namespace) {
|
|
700
750
|
if (!schema || !hasLocalReference(schema))
|
|
701
751
|
return schema;
|
|
702
|
-
const
|
|
752
|
+
const targets = { rootReferenced: false };
|
|
753
|
+
const rewritten = rewriteLocalReferences(schema, namespace, targets);
|
|
703
754
|
if (!isRecord(rewritten))
|
|
704
755
|
return schema;
|
|
705
|
-
|
|
756
|
+
const definitions = {};
|
|
757
|
+
const body = {};
|
|
758
|
+
for (const [key, value] of Object.entries(rewritten)) {
|
|
759
|
+
if (DEFINITION_KEYWORDS.includes(key)) {
|
|
760
|
+
if (isRecord(value)) {
|
|
761
|
+
for (const [name, definition] of Object.entries(value)) {
|
|
762
|
+
definitions[`${namespace}${NAMESPACE_SEPARATOR}${name}`] = definition;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
continue;
|
|
766
|
+
}
|
|
767
|
+
body[key] = value;
|
|
768
|
+
}
|
|
769
|
+
if (targets.rootReferenced)
|
|
770
|
+
definitions[namespace] = withoutDialect(body);
|
|
771
|
+
if (Object.keys(definitions).length === 0)
|
|
772
|
+
return body;
|
|
773
|
+
return { ...body, definitions };
|
|
706
774
|
}
|
|
707
775
|
function objectProperties(schema) {
|
|
708
776
|
return schema.type === "object" && isRecord(schema.properties) ? schema.properties : null;
|
|
@@ -710,11 +778,29 @@ function objectProperties(schema) {
|
|
|
710
778
|
function requiredKeys2(schema) {
|
|
711
779
|
return Array.isArray(schema.required) ? schema.required.filter((key) => typeof key === "string") : [];
|
|
712
780
|
}
|
|
781
|
+
function hoistDefinitions(schema) {
|
|
782
|
+
const branches = Array.isArray(schema.allOf) ? schema.allOf : [];
|
|
783
|
+
const definitions = {};
|
|
784
|
+
const lifted = branches.map((branch) => {
|
|
785
|
+
if (!isRecord(branch) || !isRecord(branch.definitions))
|
|
786
|
+
return branch;
|
|
787
|
+
Object.assign(definitions, branch.definitions);
|
|
788
|
+
const rest = {};
|
|
789
|
+
for (const [key, value] of Object.entries(branch)) {
|
|
790
|
+
if (key !== "definitions")
|
|
791
|
+
rest[key] = value;
|
|
792
|
+
}
|
|
793
|
+
return rest;
|
|
794
|
+
});
|
|
795
|
+
if (Object.keys(definitions).length === 0)
|
|
796
|
+
return schema;
|
|
797
|
+
return { ...schema, allOf: lifted, definitions };
|
|
798
|
+
}
|
|
713
799
|
function mergeObjectSchemas(left, right, rightOwnsUnknownKeys) {
|
|
714
800
|
const leftProperties = objectProperties(left);
|
|
715
801
|
const rightProperties = objectProperties(right);
|
|
716
802
|
if (!leftProperties || !rightProperties)
|
|
717
|
-
return { allOf: [left, right] };
|
|
803
|
+
return hoistDefinitions({ allOf: [left, right] });
|
|
718
804
|
const conflicts = Object.keys(leftProperties).filter((key) => (key in rightProperties));
|
|
719
805
|
if (conflicts.length > 0) {
|
|
720
806
|
throw new Error(`Schema merge conflict: ${conflicts.join(", ")} appear in both params and input`);
|
|
@@ -777,7 +863,7 @@ function isObjectPresentationSchema(schema) {
|
|
|
777
863
|
return schema.type === "object" && isRecord(schema.properties);
|
|
778
864
|
}
|
|
779
865
|
function presentationMetadata(schema) {
|
|
780
|
-
return withoutDialect(schema);
|
|
866
|
+
return withDefsDialect(withoutDialect(schema));
|
|
781
867
|
}
|
|
782
868
|
|
|
783
869
|
// src/tools/internal/surface-projector.ts
|
|
@@ -1027,4 +1113,4 @@ function prepareProjectedMcpTools(tools, config = {}) {
|
|
|
1027
1113
|
return prepared;
|
|
1028
1114
|
}
|
|
1029
1115
|
|
|
1030
|
-
export { objectShapeKeys, rebuildObject, mergeSchemas, validateMcpRoundPolicy, assertToolName, assertUniqueToolName, PORTABLE_JSON_SCHEMA_FORMATS, findNonPortableFormats, flattenToolJsonSchema, buildToolPresentationSchema, presentationMetadata, findUntypedProperties, assertToolExtensionCompatible, projectRuntimeTool, projectToolSurface, mcpProjectionCandidate, prepareProjectedMcpTools };
|
|
1116
|
+
export { objectShapeKeys, rebuildObject, mergeSchemas, validateMcpRoundPolicy, assertToolName, assertUniqueToolName, PORTABLE_JSON_SCHEMA_FORMATS, findNonPortableFormats, flattenToolJsonSchema, declaresDraft07, withDefsDialect, buildToolPresentationSchema, presentationMetadata, findUntypedProperties, assertToolExtensionCompatible, projectRuntimeTool, projectToolSurface, mcpProjectionCandidate, prepareProjectedMcpTools };
|