flavor-code 1.2.18 → 1.2.20
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/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/dist/{app-YE3I7JMR.js → app-5D5RSGQX.js} +1 -1
- package/dist/{chunk-JB57IX2A.js → chunk-A7PMQ22O.js} +1 -1
- package/dist/{chunk-STZQ3Y3P.js → chunk-AXLUVJKC.js} +701 -366
- package/dist/cli.js +3 -3
- package/dist/desktop/main.js +1000 -665
- package/dist/desktop/plugin-worker-entry.js +230 -0
- package/dist/evolve/loader.d.ts +1 -1
- package/dist/plugin-worker-entry.js +233 -0
- package/dist/plugins/host.d.ts +2 -3
- package/dist/plugins/sandbox-protocol.d.ts +72 -0
- package/dist/plugins/types.d.ts +3 -0
- package/dist/plugins/worker-host.d.ts +19 -0
- package/dist/sdk/index.js +2 -2
- package/dist/skills/arguments.d.ts +8 -0
- package/dist/skills/tool.d.ts +5 -0
- package/dist/ui/session.d.ts +1 -0
- package/package.json +5 -4
|
@@ -3449,7 +3449,8 @@ var FlavorSession = class {
|
|
|
3449
3449
|
version: 1,
|
|
3450
3450
|
type: "SessionStart",
|
|
3451
3451
|
payload: { workspace: this.#services.workspace }
|
|
3452
|
-
}).then(() => {
|
|
3452
|
+
}).then(async (decision) => {
|
|
3453
|
+
if (decision.additionalContext !== void 0) await this.#services.addContext?.(decision.additionalContext);
|
|
3453
3454
|
this.#started = true;
|
|
3454
3455
|
});
|
|
3455
3456
|
return this.#startPromise;
|
|
@@ -8057,7 +8058,7 @@ function createIncidentReporter(options) {
|
|
|
8057
8058
|
import { spawn as spawn5 } from "child_process";
|
|
8058
8059
|
import { writeFile as writeFile8 } from "fs/promises";
|
|
8059
8060
|
import { join as join10 } from "path";
|
|
8060
|
-
import { z as
|
|
8061
|
+
import { z as z13 } from "zod";
|
|
8061
8062
|
|
|
8062
8063
|
// src/evolve/loader.ts
|
|
8063
8064
|
import { cp, mkdir as mkdir8, mkdtemp, readdir as readdir4, rm as rm2, stat as stat4, writeFile as writeFile6 } from "fs/promises";
|
|
@@ -8066,9 +8067,10 @@ import { join as join8, resolve as resolve9 } from "path";
|
|
|
8066
8067
|
|
|
8067
8068
|
// src/plugins/host.ts
|
|
8068
8069
|
import { lstatSync, realpathSync as realpathSync2 } from "fs";
|
|
8069
|
-
import { lstat as lstat5, open as open5, readdir as readdir3, realpath as
|
|
8070
|
+
import { lstat as lstat5, open as open5, readdir as readdir3, realpath as realpath4, stat as stat3, writeFile as writeFile5 } from "fs/promises";
|
|
8070
8071
|
import { isAbsolute as isAbsolute5, relative as relative7, resolve as resolve8, sep as sep7 } from "path";
|
|
8071
8072
|
import { pathToFileURL } from "url";
|
|
8073
|
+
import { z as z12 } from "zod";
|
|
8072
8074
|
|
|
8073
8075
|
// src/plugins/types.ts
|
|
8074
8076
|
import { z as z11 } from "zod";
|
|
@@ -8098,10 +8100,188 @@ var PluginManifestSchema = z11.object({
|
|
|
8098
8100
|
}).strict()
|
|
8099
8101
|
}).strict();
|
|
8100
8102
|
|
|
8103
|
+
// src/plugins/worker-host.ts
|
|
8104
|
+
import { realpath as realpath3 } from "fs/promises";
|
|
8105
|
+
import { dirname as dirname10 } from "path";
|
|
8106
|
+
import { Worker } from "worker_threads";
|
|
8107
|
+
var DEFAULT_ACTIVATION_TIMEOUT_MS = 1e4;
|
|
8108
|
+
var DEFAULT_INVOCATION_TIMEOUT_MS = 3e4;
|
|
8109
|
+
var DEFAULT_MAX_OLD_SPACE_MB = 128;
|
|
8110
|
+
var DEFAULT_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
8111
|
+
async function startPluginSandbox(options) {
|
|
8112
|
+
const entryPath = await realpath3(options.entryPath);
|
|
8113
|
+
const pluginRoot = await realpath3(options.pluginRoot ?? dirname10(entryPath));
|
|
8114
|
+
const activationTimeoutMs = options.activationTimeoutMs ?? DEFAULT_ACTIVATION_TIMEOUT_MS;
|
|
8115
|
+
const invocationTimeoutMs = options.invocationTimeoutMs ?? DEFAULT_INVOCATION_TIMEOUT_MS;
|
|
8116
|
+
let configJson;
|
|
8117
|
+
try {
|
|
8118
|
+
configJson = JSON.stringify(options.config ?? {});
|
|
8119
|
+
} catch (error) {
|
|
8120
|
+
throw new Error(`Plugin sandbox config is not serializable: ${String(error)}`);
|
|
8121
|
+
}
|
|
8122
|
+
const workerEntry = new URL(import.meta.url.endsWith(".ts") ? "./plugin-worker-entry.ts" : "./plugin-worker-entry.js", import.meta.url);
|
|
8123
|
+
const worker = new Worker(workerEntry, {
|
|
8124
|
+
workerData: { entryPath, pluginRoot, pluginName: options.pluginName, pluginVersion: options.pluginVersion, configJson },
|
|
8125
|
+
execArgv: ["--experimental-vm-modules", "--no-warnings"],
|
|
8126
|
+
resourceLimits: {
|
|
8127
|
+
maxOldGenerationSizeMb: options.maxOldSpaceMb ?? DEFAULT_MAX_OLD_SPACE_MB,
|
|
8128
|
+
maxYoungGenerationSizeMb: 16,
|
|
8129
|
+
codeRangeSizeMb: 16,
|
|
8130
|
+
stackSizeMb: 4
|
|
8131
|
+
}
|
|
8132
|
+
});
|
|
8133
|
+
let closed = false;
|
|
8134
|
+
let nextId = 1;
|
|
8135
|
+
const pending = /* @__PURE__ */ new Map();
|
|
8136
|
+
let disposeResolve;
|
|
8137
|
+
let disposeReject;
|
|
8138
|
+
let failWorker;
|
|
8139
|
+
const ready = await new Promise((resolveReady, rejectReady) => {
|
|
8140
|
+
let settled = false;
|
|
8141
|
+
const timer = setTimeout(() => {
|
|
8142
|
+
settled = true;
|
|
8143
|
+
closed = true;
|
|
8144
|
+
void worker.terminate();
|
|
8145
|
+
rejectReady(new Error(`Plugin activation sandbox timed out after ${activationTimeoutMs}ms`));
|
|
8146
|
+
}, activationTimeoutMs);
|
|
8147
|
+
const fail = (error) => {
|
|
8148
|
+
if (closed && settled) return;
|
|
8149
|
+
closed = true;
|
|
8150
|
+
clearTimeout(timer);
|
|
8151
|
+
for (const request of pending.values()) {
|
|
8152
|
+
clearTimeout(request.timer);
|
|
8153
|
+
request.reject(error);
|
|
8154
|
+
}
|
|
8155
|
+
pending.clear();
|
|
8156
|
+
disposeReject?.(error);
|
|
8157
|
+
if (!settled) {
|
|
8158
|
+
settled = true;
|
|
8159
|
+
rejectReady(error);
|
|
8160
|
+
}
|
|
8161
|
+
void worker.terminate();
|
|
8162
|
+
};
|
|
8163
|
+
failWorker = fail;
|
|
8164
|
+
worker.on("message", (raw) => {
|
|
8165
|
+
if (!isWorkerMessage(raw)) {
|
|
8166
|
+
fail(new Error("Plugin sandbox sent an invalid protocol message"));
|
|
8167
|
+
return;
|
|
8168
|
+
}
|
|
8169
|
+
const message2 = raw;
|
|
8170
|
+
if (message2.type === "fatal") {
|
|
8171
|
+
fail(new Error(message2.error));
|
|
8172
|
+
return;
|
|
8173
|
+
}
|
|
8174
|
+
if (message2.type === "ready") {
|
|
8175
|
+
if (settled || !isSandboxResult(message2.result)) {
|
|
8176
|
+
fail(new Error("Plugin sandbox sent an invalid or duplicate ready message"));
|
|
8177
|
+
return;
|
|
8178
|
+
}
|
|
8179
|
+
settled = true;
|
|
8180
|
+
clearTimeout(timer);
|
|
8181
|
+
resolveReady(message2.result);
|
|
8182
|
+
return;
|
|
8183
|
+
}
|
|
8184
|
+
if (!settled) {
|
|
8185
|
+
fail(new Error(`Plugin sandbox sent ${message2.type} before ready`));
|
|
8186
|
+
return;
|
|
8187
|
+
}
|
|
8188
|
+
if (message2.type === "response") {
|
|
8189
|
+
const request = pending.get(message2.id);
|
|
8190
|
+
if (request === void 0) {
|
|
8191
|
+
fail(new Error("Plugin sandbox sent a response for an unknown request"));
|
|
8192
|
+
return;
|
|
8193
|
+
}
|
|
8194
|
+
pending.delete(message2.id);
|
|
8195
|
+
clearTimeout(request.timer);
|
|
8196
|
+
if (message2.ok) {
|
|
8197
|
+
try {
|
|
8198
|
+
request.resolve(JSON.parse(message2.valueJson));
|
|
8199
|
+
} catch {
|
|
8200
|
+
fail(new Error("Plugin sandbox returned invalid JSON"));
|
|
8201
|
+
}
|
|
8202
|
+
} else request.reject(new Error(message2.error));
|
|
8203
|
+
return;
|
|
8204
|
+
}
|
|
8205
|
+
if (message2.type === "disposed") {
|
|
8206
|
+
closed = true;
|
|
8207
|
+
disposeResolve?.();
|
|
8208
|
+
void worker.terminate();
|
|
8209
|
+
}
|
|
8210
|
+
});
|
|
8211
|
+
worker.once("error", fail);
|
|
8212
|
+
worker.once("exit", (code) => {
|
|
8213
|
+
if (!closed) fail(new Error(`Plugin worker exited with code ${code}`));
|
|
8214
|
+
});
|
|
8215
|
+
});
|
|
8216
|
+
return {
|
|
8217
|
+
result: ready,
|
|
8218
|
+
invoke(kind, name, args) {
|
|
8219
|
+
if (closed) return Promise.reject(new Error("Plugin sandbox is closed"));
|
|
8220
|
+
let argsJson;
|
|
8221
|
+
try {
|
|
8222
|
+
argsJson = JSON.stringify(args);
|
|
8223
|
+
} catch (error) {
|
|
8224
|
+
return Promise.reject(new Error(`Plugin sandbox arguments are not serializable: ${String(error)}`));
|
|
8225
|
+
}
|
|
8226
|
+
const id = nextId++;
|
|
8227
|
+
return new Promise((resolveInvoke, rejectInvoke) => {
|
|
8228
|
+
const timer = setTimeout(() => {
|
|
8229
|
+
const error = new Error(`Plugin sandbox invocation timed out after ${invocationTimeoutMs}ms`);
|
|
8230
|
+
failWorker(error);
|
|
8231
|
+
}, invocationTimeoutMs);
|
|
8232
|
+
pending.set(id, { resolve: (value) => resolveInvoke(value), reject: rejectInvoke, timer });
|
|
8233
|
+
worker.postMessage({ type: "invoke", id, kind, name, argsJson });
|
|
8234
|
+
});
|
|
8235
|
+
},
|
|
8236
|
+
dispose() {
|
|
8237
|
+
if (closed) return Promise.resolve();
|
|
8238
|
+
return new Promise((resolveDispose, rejectDispose) => {
|
|
8239
|
+
const timer = setTimeout(() => {
|
|
8240
|
+
const error = new Error(`Plugin sandbox shutdown timed out after ${DEFAULT_SHUTDOWN_TIMEOUT_MS}ms`);
|
|
8241
|
+
failWorker(error);
|
|
8242
|
+
}, DEFAULT_SHUTDOWN_TIMEOUT_MS);
|
|
8243
|
+
disposeResolve = () => {
|
|
8244
|
+
clearTimeout(timer);
|
|
8245
|
+
resolveDispose();
|
|
8246
|
+
};
|
|
8247
|
+
disposeReject = (error) => {
|
|
8248
|
+
clearTimeout(timer);
|
|
8249
|
+
rejectDispose(error);
|
|
8250
|
+
};
|
|
8251
|
+
worker.postMessage({ type: "shutdown" });
|
|
8252
|
+
});
|
|
8253
|
+
}
|
|
8254
|
+
};
|
|
8255
|
+
}
|
|
8256
|
+
function isWorkerMessage(value) {
|
|
8257
|
+
if (typeof value !== "object" || value === null || !("type" in value)) return false;
|
|
8258
|
+
const type = value.type;
|
|
8259
|
+
if (type === "disposed") return true;
|
|
8260
|
+
if (type === "fatal") return typeof value.error === "string";
|
|
8261
|
+
if (type === "ready") return "result" in value;
|
|
8262
|
+
if (type !== "response") return false;
|
|
8263
|
+
const response = value;
|
|
8264
|
+
return Number.isSafeInteger(response.id) && typeof response.ok === "boolean" && (response.ok ? typeof response.valueJson === "string" : typeof response.error === "string");
|
|
8265
|
+
}
|
|
8266
|
+
function isSandboxResult(value) {
|
|
8267
|
+
if (typeof value !== "object" || value === null) return false;
|
|
8268
|
+
const result = value;
|
|
8269
|
+
if (!(result.ok === true && typeof result.name === "string" && typeof result.version === "string" && Array.isArray(result.registeredTools) && result.registeredTools.every((item) => typeof item === "string") && Array.isArray(result.registeredCommands) && result.registeredCommands.every((item) => typeof item === "string") && Array.isArray(result.registeredHooks) && result.registeredHooks.every((item) => typeof item === "string") && Array.isArray(result.registeredSkillRoots) && result.registeredSkillRoots.every((item) => typeof item === "string") && Array.isArray(result.registeredModelAdapters) && result.registeredModelAdapters.every((item) => typeof item === "string") && typeof result.contributions === "object" && result.contributions !== null)) return false;
|
|
8270
|
+
const contributions = result.contributions;
|
|
8271
|
+
const named = (item) => typeof item === "object" && item !== null && typeof item.name === "string";
|
|
8272
|
+
if (!Array.isArray(contributions.commands) || !contributions.commands.every((item) => named(item) && (item.description === void 0 || typeof item.description === "string"))) return false;
|
|
8273
|
+
if (!Array.isArray(contributions.tools) || !contributions.tools.every((item) => named(item) && typeof item.toolName === "string" && typeof item.description === "string" && (item.modelInputSchema === void 0 || typeof item.modelInputSchema === "object" && item.modelInputSchema !== null) && (item.readOnly === void 0 || typeof item.readOnly === "boolean"))) return false;
|
|
8274
|
+
if (!Array.isArray(contributions.hooks) || !contributions.hooks.every(named)) return false;
|
|
8275
|
+
if (!Array.isArray(contributions.skillRoots) || !contributions.skillRoots.every((item) => named(item) && typeof item.root === "string")) return false;
|
|
8276
|
+
if (!Array.isArray(contributions.modelAdapters) || !contributions.modelAdapters.every(named)) return false;
|
|
8277
|
+
const same = (left, right) => left.length === right.length && left.every((name, index) => name === right[index]?.name);
|
|
8278
|
+
return same(result.registeredCommands, contributions.commands) && same(result.registeredTools, contributions.tools) && same(result.registeredHooks, contributions.hooks) && same(result.registeredSkillRoots, contributions.skillRoots) && same(result.registeredModelAdapters, contributions.modelAdapters);
|
|
8279
|
+
}
|
|
8280
|
+
|
|
8101
8281
|
// src/plugins/host.ts
|
|
8102
8282
|
var MANIFEST = "flavor-plugin.json";
|
|
8103
8283
|
var MAX_MANIFEST_BYTES2 = 64 * 1024;
|
|
8104
|
-
var
|
|
8284
|
+
var DEFAULT_ACTIVATION_TIMEOUT_MS2 = 1e4;
|
|
8105
8285
|
var DEFAULT_UNLOAD_TIMEOUT_MS = 5e3;
|
|
8106
8286
|
var silentLogger = { debug() {
|
|
8107
8287
|
}, info() {
|
|
@@ -8118,7 +8298,7 @@ var PluginHost = class {
|
|
|
8118
8298
|
#loaded = false;
|
|
8119
8299
|
constructor(options) {
|
|
8120
8300
|
this.#options = options;
|
|
8121
|
-
this.#activationTimeoutMs = positiveTimeout(options.activationTimeoutMs,
|
|
8301
|
+
this.#activationTimeoutMs = positiveTimeout(options.activationTimeoutMs, DEFAULT_ACTIVATION_TIMEOUT_MS2, "activationTimeoutMs");
|
|
8122
8302
|
this.#unloadTimeoutMs = positiveTimeout(options.unloadTimeoutMs, DEFAULT_UNLOAD_TIMEOUT_MS, "unloadTimeoutMs");
|
|
8123
8303
|
}
|
|
8124
8304
|
get diagnostics() {
|
|
@@ -8232,7 +8412,7 @@ var PluginHost = class {
|
|
|
8232
8412
|
try {
|
|
8233
8413
|
const rootInfo = await lstat5(inputRoot);
|
|
8234
8414
|
if (!rootInfo.isDirectory() || rootInfo.isSymbolicLink()) throw new Error("Plugin root must be a static directory");
|
|
8235
|
-
const root = await
|
|
8415
|
+
const root = await realpath4(inputRoot);
|
|
8236
8416
|
const rawManifest = await readManifest(resolve8(root, MANIFEST));
|
|
8237
8417
|
if (typeof rawManifest === "object" && rawManifest !== null && "name" in rawManifest && typeof rawManifest.name === "string") {
|
|
8238
8418
|
diagnosticLabel = rawManifest.name;
|
|
@@ -8252,18 +8432,79 @@ var PluginHost = class {
|
|
|
8252
8432
|
const claimed = [];
|
|
8253
8433
|
const state = { active: true, controller: new AbortController() };
|
|
8254
8434
|
let activation;
|
|
8435
|
+
const useSandbox = this.#options.sandbox === true;
|
|
8255
8436
|
try {
|
|
8256
8437
|
await verifyEntry(candidate.root, candidate.entry, candidate.entrySnapshot);
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
|
|
8265
|
-
|
|
8266
|
-
|
|
8438
|
+
if (useSandbox) {
|
|
8439
|
+
const session = await bounded(
|
|
8440
|
+
startPluginSandbox({
|
|
8441
|
+
entryPath: candidate.entrySnapshot.physicalPath,
|
|
8442
|
+
pluginRoot: candidate.root,
|
|
8443
|
+
pluginName: plugin,
|
|
8444
|
+
pluginVersion: candidate.manifest.version,
|
|
8445
|
+
config: redactConfig(this.#options.config ?? {}),
|
|
8446
|
+
activationTimeoutMs: this.#activationTimeoutMs
|
|
8447
|
+
}),
|
|
8448
|
+
this.#activationTimeoutMs + 1e3,
|
|
8449
|
+
"Plugin sandbox activation"
|
|
8450
|
+
);
|
|
8451
|
+
disposers.push(() => session.dispose());
|
|
8452
|
+
const result = session.result;
|
|
8453
|
+
if (!result.ok) throw new Error(result.error ?? `Plugin "${plugin}" sandbox execution failed`);
|
|
8454
|
+
const context = this.#context(candidate, disposers, claimed, state);
|
|
8455
|
+
for (const command of result.contributions.commands) {
|
|
8456
|
+
context.registerCommand(command.name, (args, commandContext) => session.invoke("command", command.name, [
|
|
8457
|
+
args,
|
|
8458
|
+
{ workspace: commandContext.workspace }
|
|
8459
|
+
]), command.description);
|
|
8460
|
+
}
|
|
8461
|
+
for (const contribution of result.contributions.tools) {
|
|
8462
|
+
const tool = {
|
|
8463
|
+
name: contribution.toolName,
|
|
8464
|
+
description: contribution.description,
|
|
8465
|
+
inputSchema: z12.unknown(),
|
|
8466
|
+
...contribution.modelInputSchema === void 0 ? {} : { modelInputSchema: contribution.modelInputSchema },
|
|
8467
|
+
...contribution.readOnly === void 0 ? {} : { readOnly: contribution.readOnly },
|
|
8468
|
+
paths: () => [],
|
|
8469
|
+
execute: (input, _signal, toolContext) => session.invoke("tool", contribution.name, [
|
|
8470
|
+
input,
|
|
8471
|
+
toolContext === void 0 ? void 0 : { agent: toolContext.agent, ownerId: toolContext.ownerId }
|
|
8472
|
+
])
|
|
8473
|
+
};
|
|
8474
|
+
context.registerTool(contribution.name, tool);
|
|
8475
|
+
}
|
|
8476
|
+
for (const hook of result.contributions.hooks) {
|
|
8477
|
+
context.registerHook(
|
|
8478
|
+
hook.name,
|
|
8479
|
+
(event) => session.invoke("hook", hook.name, [event]),
|
|
8480
|
+
hook.options
|
|
8481
|
+
);
|
|
8482
|
+
}
|
|
8483
|
+
for (const skill of result.contributions.skillRoots) {
|
|
8484
|
+
context.registerSkillRoot(skill.name, skill.root);
|
|
8485
|
+
}
|
|
8486
|
+
for (const adapter of result.contributions.modelAdapters) {
|
|
8487
|
+
context.registerModelAdapter(adapter.name, {
|
|
8488
|
+
async *stream(request) {
|
|
8489
|
+
const safeRequest = { ...request, signal: void 0 };
|
|
8490
|
+
const events = await session.invoke("modelAdapter", adapter.name, [safeRequest]);
|
|
8491
|
+
for (const event of events) yield event;
|
|
8492
|
+
}
|
|
8493
|
+
});
|
|
8494
|
+
}
|
|
8495
|
+
await verifyEntry(candidate.root, candidate.entry, candidate.entrySnapshot);
|
|
8496
|
+
} else {
|
|
8497
|
+
const imported = import(`${pathToFileURL(candidate.entrySnapshot.physicalPath).href}?flavor=${encodeURIComponent(plugin)}&v=${Date.now()}`);
|
|
8498
|
+
const module = await bounded(imported, this.#activationTimeoutMs, "Plugin import");
|
|
8499
|
+
await verifyEntry(candidate.root, candidate.entry, candidate.entrySnapshot);
|
|
8500
|
+
if (typeof module.activate !== "function") throw new Error("Plugin entry must export activate(context)");
|
|
8501
|
+
const context = this.#context(candidate, disposers, claimed, state);
|
|
8502
|
+
activation = Promise.resolve().then(() => module.activate(context));
|
|
8503
|
+
const deactivate = await bounded(activation, this.#activationTimeoutMs, "Plugin activation");
|
|
8504
|
+
if (deactivate !== void 0) {
|
|
8505
|
+
if (typeof deactivate !== "function") throw new Error("Plugin activate result must be a disposer or undefined");
|
|
8506
|
+
disposers.push(deactivate);
|
|
8507
|
+
}
|
|
8267
8508
|
}
|
|
8268
8509
|
this.#assertAllDeclaredRegistered(candidate, claimed);
|
|
8269
8510
|
const metadata = { name: plugin, version: candidate.manifest.version, source: candidate.source, root: candidate.root };
|
|
@@ -8427,7 +8668,7 @@ async function readManifest(path) {
|
|
|
8427
8668
|
async function snapshotEntry(root, entry2) {
|
|
8428
8669
|
const lexicalStats = await lstat5(entry2, { bigint: true });
|
|
8429
8670
|
if (!lexicalStats.isFile() && !lexicalStats.isSymbolicLink()) throw new Error("Plugin entry must be a file");
|
|
8430
|
-
const physicalPath = await
|
|
8671
|
+
const physicalPath = await realpath4(entry2);
|
|
8431
8672
|
assertContained(root, physicalPath, "Plugin entry symlink");
|
|
8432
8673
|
const physicalStats = await stat3(physicalPath, { bigint: true });
|
|
8433
8674
|
if (!physicalStats.isFile()) throw new Error("Plugin entry must resolve to a regular file");
|
|
@@ -8543,6 +8784,8 @@ var SCAFFOLD_ENTRY = (name) => `// ${name} \u2014 generated by /evolve improve <
|
|
|
8543
8784
|
// - context: { signal, config, logger, services, registerCommand,
|
|
8544
8785
|
// registerTool, registerHook, registerSkillRoot, registerModelAdapter }
|
|
8545
8786
|
// - every contribution you register MUST be declared in contributes
|
|
8787
|
+
// - sandbox verification only permits relative JS modules inside this plugin root;
|
|
8788
|
+
// Node.js built-ins, package imports, filesystem, and network APIs are unavailable
|
|
8546
8789
|
//
|
|
8547
8790
|
// Implement your fix here. Example \u2014 observe tool failures:
|
|
8548
8791
|
// ctx.registerHook("PostToolUseFailure", (event) => {
|
|
@@ -8582,7 +8825,9 @@ async function verifyFixPlugin(workspace, name) {
|
|
|
8582
8825
|
await cp(pluginRoot, join8(sandbox, name), { recursive: true });
|
|
8583
8826
|
const host = new PluginHost({
|
|
8584
8827
|
projectPluginDirs: [sandbox],
|
|
8828
|
+
sandbox: true,
|
|
8585
8829
|
config: {},
|
|
8830
|
+
activationTimeoutMs: 5e3,
|
|
8586
8831
|
registrations: {
|
|
8587
8832
|
command: (commandName) => {
|
|
8588
8833
|
collected.commands.push(commandName);
|
|
@@ -8596,12 +8841,11 @@ async function verifyFixPlugin(workspace, name) {
|
|
|
8596
8841
|
skillRoot: () => () => void 0,
|
|
8597
8842
|
modelAdapter: () => () => void 0
|
|
8598
8843
|
},
|
|
8599
|
-
logger: {
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
}
|
|
8844
|
+
logger: { debug() {
|
|
8845
|
+
}, info() {
|
|
8846
|
+
}, warn() {
|
|
8847
|
+
}, error() {
|
|
8848
|
+
} }
|
|
8605
8849
|
});
|
|
8606
8850
|
await host.loadAll();
|
|
8607
8851
|
const loaded = host.loadedPlugins;
|
|
@@ -8660,7 +8904,7 @@ async function revertFixPlugin(workspace, name) {
|
|
|
8660
8904
|
// src/evolve/store.ts
|
|
8661
8905
|
import { createHash as createHash5 } from "crypto";
|
|
8662
8906
|
import { appendFile, mkdir as mkdir9, readFile as readFile7, rm as rm3, writeFile as writeFile7 } from "fs/promises";
|
|
8663
|
-
import { dirname as
|
|
8907
|
+
import { dirname as dirname11, join as join9 } from "path";
|
|
8664
8908
|
function normalizeError(message2) {
|
|
8665
8909
|
return String(message2 ?? "").replace(/\s+/g, " ").replace(/"[^"]*"/g, '"\u2026"').replace(/`[^`]*`/g, '"\u2026"').trim().slice(0, 160);
|
|
8666
8910
|
}
|
|
@@ -8689,7 +8933,7 @@ async function readJsonLines(file) {
|
|
|
8689
8933
|
}
|
|
8690
8934
|
}
|
|
8691
8935
|
async function writeJsonLines(file, records) {
|
|
8692
|
-
await mkdir9(
|
|
8936
|
+
await mkdir9(dirname11(file), { recursive: true, mode: 448 });
|
|
8693
8937
|
const body = records.map((record) => JSON.stringify(record)).join("\n");
|
|
8694
8938
|
await writeFile7(file, body.length > 0 ? `${body}
|
|
8695
8939
|
` : "", { encoding: "utf8", mode: 384 });
|
|
@@ -8717,7 +8961,7 @@ async function readRules(file) {
|
|
|
8717
8961
|
}
|
|
8718
8962
|
}
|
|
8719
8963
|
async function writeRules(file, rules) {
|
|
8720
|
-
await mkdir9(
|
|
8964
|
+
await mkdir9(dirname11(file), { recursive: true, mode: 448 });
|
|
8721
8965
|
await writeFile7(file, JSON.stringify(rules, null, 2), { encoding: "utf8", mode: 384 });
|
|
8722
8966
|
}
|
|
8723
8967
|
var EvolveStore = class {
|
|
@@ -9339,10 +9583,10 @@ ${result.stderr.slice(-4e3)}` : ""}`;
|
|
|
9339
9583
|
return USAGE;
|
|
9340
9584
|
},
|
|
9341
9585
|
toolDefinition() {
|
|
9342
|
-
const inputSchema =
|
|
9343
|
-
suggestionId:
|
|
9344
|
-
implementation:
|
|
9345
|
-
kind:
|
|
9586
|
+
const inputSchema = z13.object({
|
|
9587
|
+
suggestionId: z13.string().min(1).describe("Signal id from the evolve suggestions"),
|
|
9588
|
+
implementation: z13.string().min(1).describe("Concise description of the fix to implement (plugin plan, or the guardrail rule text when kind is prompt_rule)"),
|
|
9589
|
+
kind: z13.enum(["plugin", "prompt_rule"]).optional().describe(
|
|
9346
9590
|
"plugin (default): scaffold a fix plugin; prompt_rule: store a guardrail rule that is injected into future system prompts"
|
|
9347
9591
|
)
|
|
9348
9592
|
});
|
|
@@ -9408,8 +9652,8 @@ function buildLoopCyclePrompt(input) {
|
|
|
9408
9652
|
}
|
|
9409
9653
|
|
|
9410
9654
|
// src/loop/types.ts
|
|
9411
|
-
import { z as
|
|
9412
|
-
var LoopStatusSchema =
|
|
9655
|
+
import { z as z14 } from "zod";
|
|
9656
|
+
var LoopStatusSchema = z14.enum([
|
|
9413
9657
|
"running",
|
|
9414
9658
|
"succeeded",
|
|
9415
9659
|
"failed",
|
|
@@ -9419,65 +9663,65 @@ var LoopStatusSchema = z13.enum([
|
|
|
9419
9663
|
"no_progress",
|
|
9420
9664
|
"needs_human"
|
|
9421
9665
|
]);
|
|
9422
|
-
var LoopApprovalSchema =
|
|
9423
|
-
dimension:
|
|
9424
|
-
previousCheckpoint:
|
|
9425
|
-
newCheckpoint:
|
|
9426
|
-
usage:
|
|
9427
|
-
approvedAt:
|
|
9666
|
+
var LoopApprovalSchema = z14.object({
|
|
9667
|
+
dimension: z14.enum(["cycles", "tokens"]),
|
|
9668
|
+
previousCheckpoint: z14.number().int().nonnegative(),
|
|
9669
|
+
newCheckpoint: z14.number().int().positive(),
|
|
9670
|
+
usage: z14.number().int().nonnegative(),
|
|
9671
|
+
approvedAt: z14.string().datetime({ offset: true })
|
|
9428
9672
|
}).strict();
|
|
9429
|
-
var LoopVerificationCommandSchema =
|
|
9430
|
-
command:
|
|
9431
|
-
args:
|
|
9432
|
-
exitCode:
|
|
9433
|
-
stdout:
|
|
9434
|
-
stderr:
|
|
9435
|
-
truncated:
|
|
9673
|
+
var LoopVerificationCommandSchema = z14.object({
|
|
9674
|
+
command: z14.string().min(1),
|
|
9675
|
+
args: z14.array(z14.string()),
|
|
9676
|
+
exitCode: z14.number().int().nullable(),
|
|
9677
|
+
stdout: z14.string(),
|
|
9678
|
+
stderr: z14.string(),
|
|
9679
|
+
truncated: z14.boolean()
|
|
9436
9680
|
}).strict();
|
|
9437
|
-
var LoopVerificationEvidenceSchema =
|
|
9438
|
-
passed:
|
|
9439
|
-
commands:
|
|
9440
|
-
summary:
|
|
9681
|
+
var LoopVerificationEvidenceSchema = z14.object({
|
|
9682
|
+
passed: z14.boolean(),
|
|
9683
|
+
commands: z14.array(LoopVerificationCommandSchema),
|
|
9684
|
+
summary: z14.string()
|
|
9441
9685
|
}).strict();
|
|
9442
|
-
var LoopCycleEvidenceSchema =
|
|
9443
|
-
cycle:
|
|
9444
|
-
startedAt:
|
|
9445
|
-
completedAt:
|
|
9446
|
-
inputTokens:
|
|
9447
|
-
outputTokens:
|
|
9448
|
-
workspaceFingerprint:
|
|
9686
|
+
var LoopCycleEvidenceSchema = z14.object({
|
|
9687
|
+
cycle: z14.number().int().positive(),
|
|
9688
|
+
startedAt: z14.string().datetime({ offset: true }),
|
|
9689
|
+
completedAt: z14.string().datetime({ offset: true }),
|
|
9690
|
+
inputTokens: z14.number().int().nonnegative(),
|
|
9691
|
+
outputTokens: z14.number().int().nonnegative(),
|
|
9692
|
+
workspaceFingerprint: z14.string(),
|
|
9449
9693
|
verification: LoopVerificationEvidenceSchema
|
|
9450
9694
|
}).strict();
|
|
9451
|
-
var LoopStateSchema =
|
|
9452
|
-
version:
|
|
9453
|
-
loopId:
|
|
9454
|
-
goal:
|
|
9455
|
-
workspace:
|
|
9456
|
-
createdAt:
|
|
9457
|
-
updatedAt:
|
|
9695
|
+
var LoopStateSchema = z14.object({
|
|
9696
|
+
version: z14.literal(1),
|
|
9697
|
+
loopId: z14.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
|
|
9698
|
+
goal: z14.string().trim().min(1),
|
|
9699
|
+
workspace: z14.string().min(1),
|
|
9700
|
+
createdAt: z14.string().datetime({ offset: true }),
|
|
9701
|
+
updatedAt: z14.string().datetime({ offset: true }),
|
|
9458
9702
|
status: LoopStatusSchema,
|
|
9459
|
-
config:
|
|
9460
|
-
cycleStep:
|
|
9461
|
-
tokenStep:
|
|
9462
|
-
isolation:
|
|
9703
|
+
config: z14.object({
|
|
9704
|
+
cycleStep: z14.number().int().positive(),
|
|
9705
|
+
tokenStep: z14.number().int().positive(),
|
|
9706
|
+
isolation: z14.literal("auto")
|
|
9463
9707
|
}).strict(),
|
|
9464
|
-
budget:
|
|
9465
|
-
cyclesUsed:
|
|
9466
|
-
inputTokens:
|
|
9467
|
-
outputTokens:
|
|
9468
|
-
cycleCheckpoint:
|
|
9469
|
-
tokenCheckpoint:
|
|
9470
|
-
approvals:
|
|
9708
|
+
budget: z14.object({
|
|
9709
|
+
cyclesUsed: z14.number().int().nonnegative(),
|
|
9710
|
+
inputTokens: z14.number().int().nonnegative(),
|
|
9711
|
+
outputTokens: z14.number().int().nonnegative(),
|
|
9712
|
+
cycleCheckpoint: z14.number().int().positive(),
|
|
9713
|
+
tokenCheckpoint: z14.number().int().positive(),
|
|
9714
|
+
approvals: z14.array(LoopApprovalSchema)
|
|
9471
9715
|
}).strict(),
|
|
9472
|
-
cycles:
|
|
9473
|
-
terminalReason:
|
|
9716
|
+
cycles: z14.array(LoopCycleEvidenceSchema),
|
|
9717
|
+
terminalReason: z14.string().optional()
|
|
9474
9718
|
}).strict();
|
|
9475
|
-
var LoopEventSchema =
|
|
9476
|
-
version:
|
|
9477
|
-
type:
|
|
9478
|
-
timestamp:
|
|
9479
|
-
loopId:
|
|
9480
|
-
payload:
|
|
9719
|
+
var LoopEventSchema = z14.object({
|
|
9720
|
+
version: z14.literal(1),
|
|
9721
|
+
type: z14.enum(["created", "cycle_started", "cycle_completed", "verification", "budget_approved", "terminal"]),
|
|
9722
|
+
timestamp: z14.string().datetime({ offset: true }),
|
|
9723
|
+
loopId: z14.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
|
|
9724
|
+
payload: z14.record(z14.string(), z14.unknown())
|
|
9481
9725
|
}).strict();
|
|
9482
9726
|
|
|
9483
9727
|
// src/loop/budget.ts
|
|
@@ -9793,15 +10037,15 @@ import { writeFile as writeFile9, mkdir as mkdir10 } from "fs/promises";
|
|
|
9793
10037
|
import { join as join12 } from "path";
|
|
9794
10038
|
|
|
9795
10039
|
// src/goal/types.ts
|
|
9796
|
-
import { z as
|
|
9797
|
-
var GoalPhaseSchema =
|
|
10040
|
+
import { z as z15 } from "zod";
|
|
10041
|
+
var GoalPhaseSchema = z15.enum([
|
|
9798
10042
|
"idle",
|
|
9799
10043
|
"planning",
|
|
9800
10044
|
"executing",
|
|
9801
10045
|
"verifying",
|
|
9802
10046
|
"complete"
|
|
9803
10047
|
]);
|
|
9804
|
-
var GoalStatusSchema =
|
|
10048
|
+
var GoalStatusSchema = z15.enum([
|
|
9805
10049
|
"active",
|
|
9806
10050
|
"paused",
|
|
9807
10051
|
"achieved",
|
|
@@ -9809,43 +10053,43 @@ var GoalStatusSchema = z14.enum([
|
|
|
9809
10053
|
"blocked",
|
|
9810
10054
|
"failed"
|
|
9811
10055
|
]);
|
|
9812
|
-
var AcceptanceCriterionSchema =
|
|
9813
|
-
id:
|
|
9814
|
-
description:
|
|
9815
|
-
type:
|
|
10056
|
+
var AcceptanceCriterionSchema = z15.object({
|
|
10057
|
+
id: z15.number().int().positive(),
|
|
10058
|
+
description: z15.string().min(1),
|
|
10059
|
+
type: z15.enum(["gating", "evidence"])
|
|
9816
10060
|
}).strict();
|
|
9817
|
-
var PlanSchema =
|
|
9818
|
-
kind:
|
|
9819
|
-
criteria:
|
|
9820
|
-
verificationPlan:
|
|
9821
|
-
nonGoals:
|
|
9822
|
-
assumedScope:
|
|
9823
|
-
approach:
|
|
9824
|
-
checklist:
|
|
10061
|
+
var PlanSchema = z15.object({
|
|
10062
|
+
kind: z15.enum(["code-change", "analysis", "research"]),
|
|
10063
|
+
criteria: z15.array(AcceptanceCriterionSchema).min(1).max(32),
|
|
10064
|
+
verificationPlan: z15.string().min(1),
|
|
10065
|
+
nonGoals: z15.array(z15.string()).max(16),
|
|
10066
|
+
assumedScope: z15.array(z15.string()).max(16),
|
|
10067
|
+
approach: z15.string().optional(),
|
|
10068
|
+
checklist: z15.array(z15.string()).max(32).optional()
|
|
9825
10069
|
}).strict();
|
|
9826
|
-
var GapSchema =
|
|
9827
|
-
criterion:
|
|
9828
|
-
description:
|
|
9829
|
-
blocking:
|
|
10070
|
+
var GapSchema = z15.object({
|
|
10071
|
+
criterion: z15.string().min(1),
|
|
10072
|
+
description: z15.string().min(1),
|
|
10073
|
+
blocking: z15.enum(["model_fixable", "contradiction", "unverifiable"])
|
|
9830
10074
|
}).strict();
|
|
9831
|
-
var VerdictSchema =
|
|
9832
|
-
refuted:
|
|
9833
|
-
gaps:
|
|
10075
|
+
var VerdictSchema = z15.object({
|
|
10076
|
+
refuted: z15.boolean(),
|
|
10077
|
+
gaps: z15.array(GapSchema)
|
|
9834
10078
|
}).strict();
|
|
9835
|
-
var GoalStateSchema =
|
|
9836
|
-
id:
|
|
9837
|
-
objective:
|
|
10079
|
+
var GoalStateSchema = z15.object({
|
|
10080
|
+
id: z15.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
|
|
10081
|
+
objective: z15.string().min(1),
|
|
9838
10082
|
phase: GoalPhaseSchema,
|
|
9839
10083
|
status: GoalStatusSchema,
|
|
9840
10084
|
plan: PlanSchema.nullable(),
|
|
9841
|
-
planPath:
|
|
9842
|
-
verifyRounds:
|
|
9843
|
-
workerRounds:
|
|
9844
|
-
lastGaps:
|
|
9845
|
-
gapFingerprint:
|
|
9846
|
-
stallStreak:
|
|
9847
|
-
createdAt:
|
|
9848
|
-
updatedAt:
|
|
10085
|
+
planPath: z15.string().nullable(),
|
|
10086
|
+
verifyRounds: z15.number().int().min(0),
|
|
10087
|
+
workerRounds: z15.number().int().min(0),
|
|
10088
|
+
lastGaps: z15.array(GapSchema),
|
|
10089
|
+
gapFingerprint: z15.string(),
|
|
10090
|
+
stallStreak: z15.number().int().min(0),
|
|
10091
|
+
createdAt: z15.string().datetime({ offset: true }),
|
|
10092
|
+
updatedAt: z15.string().datetime({ offset: true })
|
|
9849
10093
|
}).strict();
|
|
9850
10094
|
|
|
9851
10095
|
// src/goal/planner.ts
|
|
@@ -10406,7 +10650,7 @@ function formatPriorGaps(gaps) {
|
|
|
10406
10650
|
import { constants } from "fs";
|
|
10407
10651
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
10408
10652
|
import { lstat as lstat6, mkdir as mkdir11, open as open6, rename as rename4, rm as rm4 } from "fs/promises";
|
|
10409
|
-
import { dirname as
|
|
10653
|
+
import { dirname as dirname12, join as join13, relative as relative9, resolve as resolve10, sep as sep8 } from "path";
|
|
10410
10654
|
var DEFAULT_MAX_BYTES = 1024 * 1024;
|
|
10411
10655
|
var GoalStore = class {
|
|
10412
10656
|
#workspace;
|
|
@@ -10419,7 +10663,7 @@ var GoalStore = class {
|
|
|
10419
10663
|
}
|
|
10420
10664
|
async save(input) {
|
|
10421
10665
|
const state = GoalStateSchema.parse(input);
|
|
10422
|
-
await assertNoSymlink(this.#workspace,
|
|
10666
|
+
await assertNoSymlink(this.#workspace, dirname12(this.#root));
|
|
10423
10667
|
await mkdir11(this.#root, { recursive: true, mode: 448 });
|
|
10424
10668
|
await assertNoSymlink(this.#workspace, this.#root);
|
|
10425
10669
|
const target = join13(this.#root, `${state.id}.json`);
|
|
@@ -10453,7 +10697,7 @@ async function assertNoSymlink(root, target) {
|
|
|
10453
10697
|
const chain = [];
|
|
10454
10698
|
while (cursor !== stop) {
|
|
10455
10699
|
chain.push(cursor);
|
|
10456
|
-
cursor =
|
|
10700
|
+
cursor = dirname12(cursor);
|
|
10457
10701
|
}
|
|
10458
10702
|
for (const path of chain.reverse()) {
|
|
10459
10703
|
try {
|
|
@@ -10539,8 +10783,8 @@ async function ensureWorktreeDirectoryIgnored(root) {
|
|
|
10539
10783
|
|
|
10540
10784
|
// src/loop/store.ts
|
|
10541
10785
|
import { constants as constants2 } from "fs";
|
|
10542
|
-
import { lstat as lstat7, mkdir as mkdir13, open as open7, readFile as readFile10, realpath as
|
|
10543
|
-
import { dirname as
|
|
10786
|
+
import { lstat as lstat7, mkdir as mkdir13, open as open7, readFile as readFile10, realpath as realpath5, rename as rename5, rm as rm5, stat as stat5 } from "fs/promises";
|
|
10787
|
+
import { dirname as dirname13, join as join15, relative as relative10, resolve as resolve12, sep as sep9 } from "path";
|
|
10544
10788
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
10545
10789
|
var LOOP_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
10546
10790
|
var DEFAULT_MAX_BYTES2 = 5 * 1024 * 1024;
|
|
@@ -10622,7 +10866,7 @@ var LoopStore = class {
|
|
|
10622
10866
|
}
|
|
10623
10867
|
async #prepare(loopId) {
|
|
10624
10868
|
validateId(loopId);
|
|
10625
|
-
await assertNoSymlink2(this.#workspace,
|
|
10869
|
+
await assertNoSymlink2(this.#workspace, dirname13(this.#root));
|
|
10626
10870
|
await mkdir13(this.#root, { recursive: true, mode: 448 });
|
|
10627
10871
|
await assertNoSymlink2(this.#workspace, this.#root);
|
|
10628
10872
|
const directory = join15(this.#root, loopId);
|
|
@@ -10655,7 +10899,7 @@ async function assertNoSymlink2(root, target) {
|
|
|
10655
10899
|
const chain = [];
|
|
10656
10900
|
while (cursor !== stop) {
|
|
10657
10901
|
chain.push(cursor);
|
|
10658
|
-
cursor =
|
|
10902
|
+
cursor = dirname13(cursor);
|
|
10659
10903
|
}
|
|
10660
10904
|
for (const path of chain.reverse()) {
|
|
10661
10905
|
try {
|
|
@@ -10671,7 +10915,7 @@ function isWithin2(root, path) {
|
|
|
10671
10915
|
}
|
|
10672
10916
|
async function canonical(path) {
|
|
10673
10917
|
try {
|
|
10674
|
-
return await
|
|
10918
|
+
return await realpath5(resolve12(path));
|
|
10675
10919
|
} catch {
|
|
10676
10920
|
return resolve12(path);
|
|
10677
10921
|
}
|
|
@@ -10687,19 +10931,19 @@ import { join as join16 } from "path";
|
|
|
10687
10931
|
// src/tools/shell.ts
|
|
10688
10932
|
import { spawn as spawn6, spawnSync } from "child_process";
|
|
10689
10933
|
import { isAbsolute as isAbsolute6, relative as relative11, resolve as resolve13, sep as sep10 } from "path";
|
|
10690
|
-
import { z as
|
|
10934
|
+
import { z as z17 } from "zod";
|
|
10691
10935
|
|
|
10692
10936
|
// src/tools/jobs.ts
|
|
10693
|
-
import { z as
|
|
10694
|
-
var JobId =
|
|
10695
|
-
var ReadInput =
|
|
10696
|
-
var IdInput =
|
|
10937
|
+
import { z as z16 } from "zod";
|
|
10938
|
+
var JobId = z16.string().regex(/^job-[a-f0-9-]+$/);
|
|
10939
|
+
var ReadInput = z16.object({ id: JobId, cursor: z16.coerce.number().int().min(0).optional() });
|
|
10940
|
+
var IdInput = z16.object({ id: JobId });
|
|
10697
10941
|
function createJobTools(registry) {
|
|
10698
10942
|
const tools = [
|
|
10699
10943
|
{
|
|
10700
10944
|
name: "JobList",
|
|
10701
10945
|
description: "List background jobs owned by this agent",
|
|
10702
|
-
inputSchema:
|
|
10946
|
+
inputSchema: z16.object({}),
|
|
10703
10947
|
paths: () => [],
|
|
10704
10948
|
execute: async (_input, _signal, context) => registry.list(owner(context)),
|
|
10705
10949
|
presentResult: (output) => jobListPresentation(output)
|
|
@@ -10774,14 +11018,14 @@ var ELLIPSIS = "\u2026";
|
|
|
10774
11018
|
var TERMINATION_GRACE_MS = 250;
|
|
10775
11019
|
var TERMINATION_FAILURE_MS = 5e3;
|
|
10776
11020
|
var STREAM_CLOSE_GRACE_MS = 500;
|
|
10777
|
-
var ShellInput =
|
|
10778
|
-
command:
|
|
10779
|
-
args:
|
|
10780
|
-
cwd:
|
|
10781
|
-
timeoutMs:
|
|
11021
|
+
var ShellInput = z17.object({
|
|
11022
|
+
command: z17.string().min(1),
|
|
11023
|
+
args: z17.array(z17.string()),
|
|
11024
|
+
cwd: z17.string().min(1).nullable().optional(),
|
|
11025
|
+
timeoutMs: z17.coerce.number().int().positive().max(864e5).nullable().optional(),
|
|
10782
11026
|
// Accepts booleans and their string forms (weak-typed models emit "true");
|
|
10783
11027
|
// kept transform-free so the schema converts to JSON Schema for providers.
|
|
10784
|
-
background:
|
|
11028
|
+
background: z17.union([z17.boolean(), z17.string().refine((value) => value === "true" || value === "false")]).optional()
|
|
10785
11029
|
});
|
|
10786
11030
|
function normalizeShellCommand(input) {
|
|
10787
11031
|
const { command, args } = input;
|
|
@@ -11950,7 +12194,7 @@ var ModelRegistry = class {
|
|
|
11950
12194
|
|
|
11951
12195
|
// src/mcp/client.ts
|
|
11952
12196
|
import { createHash as createHash7 } from "crypto";
|
|
11953
|
-
import { z as
|
|
12197
|
+
import { z as z18 } from "zod";
|
|
11954
12198
|
var McpManager = class {
|
|
11955
12199
|
#workspace;
|
|
11956
12200
|
#clientFactory;
|
|
@@ -12086,7 +12330,7 @@ async function listAllTools(client) {
|
|
|
12086
12330
|
function createMcpToolDefinition(serverName, timeoutMs, client, remote) {
|
|
12087
12331
|
if (remote.name.length === 0) throw new Error("MCP tool name must not be empty");
|
|
12088
12332
|
if (!isRecord3(remote.inputSchema)) throw new Error(`MCP tool "${remote.name}" has no JSON object input schema`);
|
|
12089
|
-
const inputSchema =
|
|
12333
|
+
const inputSchema = z18.fromJSONSchema(
|
|
12090
12334
|
remote.inputSchema
|
|
12091
12335
|
);
|
|
12092
12336
|
return {
|
|
@@ -12496,7 +12740,7 @@ function escapeHtml(text) {
|
|
|
12496
12740
|
}
|
|
12497
12741
|
|
|
12498
12742
|
// src/auth/store.ts
|
|
12499
|
-
import { dirname as
|
|
12743
|
+
import { dirname as dirname14 } from "path";
|
|
12500
12744
|
async function retainOnlyCredentials(store, keepCredentialId) {
|
|
12501
12745
|
const tokens = await store.load();
|
|
12502
12746
|
const retained = Object.fromEntries(Object.entries(tokens).filter(([id]) => id === keepCredentialId));
|
|
@@ -12507,7 +12751,7 @@ function createFileTokenStore(filePath) {
|
|
|
12507
12751
|
const store = {
|
|
12508
12752
|
tokens: {},
|
|
12509
12753
|
async load() {
|
|
12510
|
-
const key = await loadOrCreateConfigKey(
|
|
12754
|
+
const key = await loadOrCreateConfigKey(dirname14(filePath));
|
|
12511
12755
|
const result = await readRecoverableFile(filePath, (raw) => parseTokens(decryptDocument(raw, key)));
|
|
12512
12756
|
const tokens = result?.value ?? {};
|
|
12513
12757
|
baseline = { ...tokens };
|
|
@@ -12515,7 +12759,7 @@ function createFileTokenStore(filePath) {
|
|
|
12515
12759
|
return tokens;
|
|
12516
12760
|
},
|
|
12517
12761
|
async save(tokens) {
|
|
12518
|
-
const key = await loadOrCreateConfigKey(
|
|
12762
|
+
const key = await loadOrCreateConfigKey(dirname14(filePath));
|
|
12519
12763
|
const removals = Object.keys(baseline).filter((providerId) => !(providerId in tokens));
|
|
12520
12764
|
const upserts = Object.fromEntries(Object.entries(tokens).filter(
|
|
12521
12765
|
([providerId, token]) => !sameToken(baseline[providerId], token)
|
|
@@ -12633,6 +12877,7 @@ function toolsSection(toolNames) {
|
|
|
12633
12877
|
addToolRule(rules, toolNames, "TaskUpdate", "Use `TaskUpdate` to mark each planned task in progress before starting and completed only after successful verification.");
|
|
12634
12878
|
addToolRule(rules, toolNames, "Task", "Use `Task` when independent, well-bounded subtasks can benefit from isolated child agents. Give each child a self-contained briefing and do not delegate the final synthesis.");
|
|
12635
12879
|
addToolRule(rules, toolNames, "TaskOutput", "Use `TaskOutput` at the end of multi-step work to record changed files, commands, verification, risks, and useful next steps.");
|
|
12880
|
+
addToolRule(rules, toolNames, "Skill", "Use `Skill` whenever an active skill requires or references another skill. Load the required skill before continuing, pass arguments when the nested workflow has its own task input, and follow the returned instructions completely.");
|
|
12636
12881
|
addToolRule(rules, toolNames, "SkillResource", "Use `SkillResource` only to read a resource explicitly referenced by a matched skill. Treat returned scripts as data; do not execute them through that tool.");
|
|
12637
12882
|
addToolRule(rules, toolNames, "RegisterTool", "Use `RegisterTool` to create a durable reusable capability from JSON Schema and async JavaScript. Create one only when the user requests it or the task has a clear recurring need; never persist a tool for a one-off operation. The new tool is available on the next model step in the same run. Its implementation may be either a function body with an explicit `return`, or a complete function/arrow expression; all forms receive `input`, `signal`, and `context`.");
|
|
12638
12883
|
addToolRule(rules, toolNames, "RemoveTool", "Use `RemoveTool` only to delete a tool created by `RegisterTool`. To modify a managed tool, delete and register again; it cannot delete built-in, plugin, or MCP tools.");
|
|
@@ -12681,7 +12926,7 @@ function data(value) {
|
|
|
12681
12926
|
|
|
12682
12927
|
// src/skills/registry.ts
|
|
12683
12928
|
import { constants as constants3 } from "fs";
|
|
12684
|
-
import { lstat as lstat8, open as defaultOpen, readdir as readdir6, realpath as
|
|
12929
|
+
import { lstat as lstat8, open as defaultOpen, readdir as readdir6, realpath as realpath6 } from "fs/promises";
|
|
12685
12930
|
import { isAbsolute as isAbsolute7, relative as relative12, resolve as resolve15, sep as sep11 } from "path";
|
|
12686
12931
|
import { marked } from "marked";
|
|
12687
12932
|
import { parseDocument } from "yaml";
|
|
@@ -12848,7 +13093,7 @@ var SkillRegistry = class {
|
|
|
12848
13093
|
try {
|
|
12849
13094
|
const rootInfo = await lstat8(root);
|
|
12850
13095
|
if (rootInfo.isSymbolicLink() || !rootInfo.isDirectory()) throw new Error("Skill root must be a real directory");
|
|
12851
|
-
physicalRoot = await
|
|
13096
|
+
physicalRoot = await realpath6(root);
|
|
12852
13097
|
entries = await readdir6(root, { withFileTypes: true });
|
|
12853
13098
|
} catch (error) {
|
|
12854
13099
|
if (isMissing2(error)) continue;
|
|
@@ -12861,7 +13106,7 @@ var SkillRegistry = class {
|
|
|
12861
13106
|
try {
|
|
12862
13107
|
if (entry2.isSymbolicLink()) throw new Error("Symlinked skill directories are not allowed");
|
|
12863
13108
|
if (!entry2.isDirectory()) continue;
|
|
12864
|
-
const physicalSkillRoot = await
|
|
13109
|
+
const physicalSkillRoot = await realpath6(skillRoot);
|
|
12865
13110
|
if (!isWithin3(physicalRoot, physicalSkillRoot)) throw new Error("Skill directory escapes its registry root");
|
|
12866
13111
|
const skillFile = resolve15(skillRoot, "SKILL.md");
|
|
12867
13112
|
const parsed = await readFrontmatterFile(
|
|
@@ -13003,7 +13248,7 @@ async function openVerifiedFile(path, root, label, opener, expected) {
|
|
|
13003
13248
|
const initial = await lstat8(path, { bigint: true });
|
|
13004
13249
|
if (initial.isSymbolicLink()) throw new Error(`${label} symlinks are not allowed`);
|
|
13005
13250
|
assertRegular(initial, label);
|
|
13006
|
-
const canonical3 = await
|
|
13251
|
+
const canonical3 = await realpath6(path);
|
|
13007
13252
|
if (!isWithin3(root, canonical3)) throw new Error(`${label} escapes the skill root`);
|
|
13008
13253
|
const noFollow = typeof constants3.O_NOFOLLOW === "number" ? constants3.O_NOFOLLOW : 0;
|
|
13009
13254
|
const handle = await opener(canonical3, constants3.O_RDONLY | noFollow);
|
|
@@ -13112,11 +13357,97 @@ function score(metadata, query) {
|
|
|
13112
13357
|
}
|
|
13113
13358
|
|
|
13114
13359
|
// src/skills/tool.ts
|
|
13115
|
-
import { z as
|
|
13116
|
-
|
|
13117
|
-
|
|
13118
|
-
|
|
13360
|
+
import { z as z19 } from "zod";
|
|
13361
|
+
|
|
13362
|
+
// src/skills/arguments.ts
|
|
13363
|
+
function expandSkillArguments(body, argumentsText) {
|
|
13364
|
+
const values = splitSkillArguments(argumentsText);
|
|
13365
|
+
const hasPlaceholder = /\$ARGUMENTS(?:\[\d+\])?|\$\d+/.test(body);
|
|
13366
|
+
let expanded = body.replace(/\$ARGUMENTS\[(\d+)\]/g, (_match, index) => values[Number(index)] ?? "");
|
|
13367
|
+
expanded = expanded.replace(/\$(\d+)/g, (_match, index) => values[Number(index)] ?? "");
|
|
13368
|
+
expanded = expanded.replace(/\$ARGUMENTS/g, argumentsText);
|
|
13369
|
+
if (!hasPlaceholder && argumentsText.trim() !== "") {
|
|
13370
|
+
expanded = `${expanded.trimEnd()}
|
|
13371
|
+
|
|
13372
|
+
ARGUMENTS: ${argumentsText}`;
|
|
13373
|
+
}
|
|
13374
|
+
return expanded;
|
|
13375
|
+
}
|
|
13376
|
+
function splitSkillArguments(input) {
|
|
13377
|
+
const result = [];
|
|
13378
|
+
let current = "";
|
|
13379
|
+
let quote;
|
|
13380
|
+
let started = false;
|
|
13381
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
13382
|
+
const character = input[index] ?? "";
|
|
13383
|
+
const next = input[index + 1];
|
|
13384
|
+
if (character === "\\" && quote !== "'" && next !== void 0 && (/\s/u.test(next) || next === "\\" || next === '"' || quote === void 0 && next === "'")) {
|
|
13385
|
+
current += next;
|
|
13386
|
+
index += 1;
|
|
13387
|
+
started = true;
|
|
13388
|
+
continue;
|
|
13389
|
+
}
|
|
13390
|
+
if (quote !== void 0) {
|
|
13391
|
+
if (character === quote) quote = void 0;
|
|
13392
|
+
else current += character;
|
|
13393
|
+
started = true;
|
|
13394
|
+
continue;
|
|
13395
|
+
}
|
|
13396
|
+
if (character === "'" || character === '"') {
|
|
13397
|
+
quote = character;
|
|
13398
|
+
started = true;
|
|
13399
|
+
continue;
|
|
13400
|
+
}
|
|
13401
|
+
if (/\s/u.test(character)) {
|
|
13402
|
+
if (started) {
|
|
13403
|
+
result.push(current);
|
|
13404
|
+
current = "";
|
|
13405
|
+
started = false;
|
|
13406
|
+
}
|
|
13407
|
+
continue;
|
|
13408
|
+
}
|
|
13409
|
+
current += character;
|
|
13410
|
+
started = true;
|
|
13411
|
+
}
|
|
13412
|
+
if (started) result.push(current);
|
|
13413
|
+
return result;
|
|
13414
|
+
}
|
|
13415
|
+
|
|
13416
|
+
// src/skills/tool.ts
|
|
13417
|
+
var SkillInput = z19.object({
|
|
13418
|
+
skill: z19.string().min(1),
|
|
13419
|
+
arguments: z19.string().optional()
|
|
13119
13420
|
}).strict();
|
|
13421
|
+
var SkillResourceInput = z19.object({
|
|
13422
|
+
skill: z19.string().min(1),
|
|
13423
|
+
reference: z19.string().min(1)
|
|
13424
|
+
}).strict();
|
|
13425
|
+
function createSkillTool(registry) {
|
|
13426
|
+
return {
|
|
13427
|
+
name: "Skill",
|
|
13428
|
+
description: "Load another discovered skill by name so composable workflows can follow its complete instructions; optional arguments use Claude-compatible $ARGUMENTS substitution",
|
|
13429
|
+
inputSchema: SkillInput,
|
|
13430
|
+
readOnly: true,
|
|
13431
|
+
paths: () => [],
|
|
13432
|
+
summarize: ({ skill }) => skill,
|
|
13433
|
+
renderForModel: (output) => {
|
|
13434
|
+
const value = output;
|
|
13435
|
+
return `Matched skill: ${value.skill}
|
|
13436
|
+
${value.content}`;
|
|
13437
|
+
},
|
|
13438
|
+
execute: async (input, signal) => {
|
|
13439
|
+
signal.throwIfAborted();
|
|
13440
|
+
const discovered = await registry.discover();
|
|
13441
|
+
const requested = input.skill.trim();
|
|
13442
|
+
const alias = requested.includes(":") ? requested.slice(requested.lastIndexOf(":") + 1) : requested;
|
|
13443
|
+
const skill = discovered.find((candidate) => candidate.name === requested) ?? discovered.find((candidate) => candidate.name === alias);
|
|
13444
|
+
if (skill === void 0) throw new Error(`Unknown skill: ${input.skill}`);
|
|
13445
|
+
const content = expandSkillArguments(await registry.loadBody(skill), input.arguments ?? "");
|
|
13446
|
+
signal.throwIfAborted();
|
|
13447
|
+
return { skill: skill.name, content };
|
|
13448
|
+
}
|
|
13449
|
+
};
|
|
13450
|
+
}
|
|
13120
13451
|
function createSkillResourceTool(registry) {
|
|
13121
13452
|
return {
|
|
13122
13453
|
name: "SkillResource",
|
|
@@ -13142,97 +13473,97 @@ function createSkillResourceTool(registry) {
|
|
|
13142
13473
|
|
|
13143
13474
|
// src/session/store.ts
|
|
13144
13475
|
import { constants as constants4 } from "fs";
|
|
13145
|
-
import { lstat as lstat9, mkdir as mkdir14, open as open8, readFile as readFile14, readdir as readdir7, realpath as
|
|
13146
|
-
import { basename as basename3, dirname as
|
|
13476
|
+
import { lstat as lstat9, mkdir as mkdir14, open as open8, readFile as readFile14, readdir as readdir7, realpath as realpath7, rename as rename6, rm as rm6, stat as stat6 } from "fs/promises";
|
|
13477
|
+
import { basename as basename3, dirname as dirname15, join as join17, relative as relative13, resolve as resolve16, sep as sep12 } from "path";
|
|
13147
13478
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
13148
|
-
import { z as
|
|
13479
|
+
import { z as z20 } from "zod";
|
|
13149
13480
|
var SESSION_VERSION = 3;
|
|
13150
13481
|
var DEFAULT_MAX_SESSION_BYTES = 5 * 1024 * 1024;
|
|
13151
|
-
var SessionIdSchema =
|
|
13152
|
-
var IsoDateSchema =
|
|
13153
|
-
var ToolCallSchema =
|
|
13154
|
-
id:
|
|
13155
|
-
name:
|
|
13156
|
-
input:
|
|
13482
|
+
var SessionIdSchema = z20.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/, "Invalid session id");
|
|
13483
|
+
var IsoDateSchema = z20.string().datetime({ offset: true });
|
|
13484
|
+
var ToolCallSchema = z20.object({
|
|
13485
|
+
id: z20.string().min(1).max(256),
|
|
13486
|
+
name: z20.string().min(1).max(256),
|
|
13487
|
+
input: z20.unknown()
|
|
13157
13488
|
}).strict();
|
|
13158
|
-
var TextContentBlockSchema =
|
|
13159
|
-
type:
|
|
13160
|
-
text:
|
|
13489
|
+
var TextContentBlockSchema = z20.object({
|
|
13490
|
+
type: z20.literal("text"),
|
|
13491
|
+
text: z20.string().max(DEFAULT_MAX_SESSION_BYTES)
|
|
13161
13492
|
}).strict();
|
|
13162
|
-
var ImageContentBlockSchema =
|
|
13163
|
-
type:
|
|
13164
|
-
source:
|
|
13165
|
-
mediaType:
|
|
13166
|
-
sha256:
|
|
13167
|
-
bytes:
|
|
13168
|
-
name:
|
|
13493
|
+
var ImageContentBlockSchema = z20.object({
|
|
13494
|
+
type: z20.literal("image"),
|
|
13495
|
+
source: z20.object({ type: z20.literal("file"), path: z20.string().min(1).max(32768) }).strict(),
|
|
13496
|
+
mediaType: z20.enum(["image/png", "image/jpeg", "image/webp"]),
|
|
13497
|
+
sha256: z20.string().regex(/^[a-f0-9]{64}$/),
|
|
13498
|
+
bytes: z20.number().int().positive().max(20 * 1024 * 1024),
|
|
13499
|
+
name: z20.string().min(1).max(255).optional()
|
|
13169
13500
|
}).strict();
|
|
13170
|
-
var UserContentSchema =
|
|
13171
|
-
|
|
13172
|
-
|
|
13501
|
+
var UserContentSchema = z20.union([
|
|
13502
|
+
z20.string().max(DEFAULT_MAX_SESSION_BYTES),
|
|
13503
|
+
z20.array(z20.discriminatedUnion("type", [TextContentBlockSchema, ImageContentBlockSchema])).min(1).max(100)
|
|
13173
13504
|
]);
|
|
13174
13505
|
var MessageMetadataShape = {
|
|
13175
|
-
toolCallId:
|
|
13176
|
-
toolCalls:
|
|
13506
|
+
toolCallId: z20.string().min(1).max(256).optional(),
|
|
13507
|
+
toolCalls: z20.array(ToolCallSchema).max(1e3).optional()
|
|
13177
13508
|
};
|
|
13178
|
-
var MessageSchema =
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
|
|
13509
|
+
var MessageSchema = z20.discriminatedUnion("role", [
|
|
13510
|
+
z20.object({ role: z20.literal("user"), content: UserContentSchema, ...MessageMetadataShape }).strict(),
|
|
13511
|
+
z20.object({ role: z20.literal("assistant"), content: z20.string().max(DEFAULT_MAX_SESSION_BYTES), ...MessageMetadataShape }).strict(),
|
|
13512
|
+
z20.object({ role: z20.literal("tool"), content: z20.string().max(DEFAULT_MAX_SESSION_BYTES), ...MessageMetadataShape }).strict()
|
|
13182
13513
|
]);
|
|
13183
|
-
var LegacySummarySchema =
|
|
13184
|
-
var CompactBoundarySchema =
|
|
13185
|
-
summary:
|
|
13514
|
+
var LegacySummarySchema = z20.object({ role: z20.literal("system"), content: z20.string().max(DEFAULT_MAX_SESSION_BYTES) }).strict();
|
|
13515
|
+
var CompactBoundarySchema = z20.object({
|
|
13516
|
+
summary: z20.string().min(1).max(DEFAULT_MAX_SESSION_BYTES),
|
|
13186
13517
|
compactedAt: IsoDateSchema
|
|
13187
13518
|
}).strict();
|
|
13188
|
-
var StateSchema =
|
|
13189
|
-
var MemoryLifecycleSchema =
|
|
13190
|
-
status:
|
|
13191
|
-
taskId:
|
|
13192
|
-
messageStart:
|
|
13519
|
+
var StateSchema = z20.enum(["pending", "running", "completed", "failed", "blocked", "cancelled"]);
|
|
13520
|
+
var MemoryLifecycleSchema = z20.object({
|
|
13521
|
+
status: z20.enum(["active", "completed", "abandoned"]),
|
|
13522
|
+
taskId: z20.string().regex(/^memory-[A-Za-z0-9._-]{1,120}$/).optional(),
|
|
13523
|
+
messageStart: z20.number().int().min(0).max(5e4).optional(),
|
|
13193
13524
|
finalizedAt: IsoDateSchema.optional(),
|
|
13194
|
-
transcriptHash:
|
|
13525
|
+
transcriptHash: z20.string().regex(/^[a-f0-9]{64}$/).optional()
|
|
13195
13526
|
}).strict();
|
|
13196
|
-
var SessionBaseSchema =
|
|
13527
|
+
var SessionBaseSchema = z20.object({
|
|
13197
13528
|
sessionId: SessionIdSchema,
|
|
13198
13529
|
createdAt: IsoDateSchema,
|
|
13199
13530
|
updatedAt: IsoDateSchema,
|
|
13200
|
-
workspace:
|
|
13201
|
-
tasks:
|
|
13531
|
+
workspace: z20.object({ path: z20.string().min(1).max(32768) }).strict(),
|
|
13532
|
+
tasks: z20.object({
|
|
13202
13533
|
plan: TaskPlanSchema.optional(),
|
|
13203
13534
|
graph: TaskGraphSchema.optional(),
|
|
13204
|
-
states:
|
|
13205
|
-
results:
|
|
13535
|
+
states: z20.record(z20.string(), StateSchema),
|
|
13536
|
+
results: z20.record(z20.string(), SubagentResultSchema)
|
|
13206
13537
|
}).strict(),
|
|
13207
|
-
models:
|
|
13538
|
+
models: z20.object({ main: z20.string().min(1).max(1024), subagent: z20.string().min(1).max(1024) }).strict(),
|
|
13208
13539
|
permissionMode: PermissionModeSchema,
|
|
13209
13540
|
memory: MemoryLifecycleSchema.optional()
|
|
13210
13541
|
}).strict();
|
|
13211
13542
|
var SessionDocumentV1Schema = SessionBaseSchema.extend({
|
|
13212
|
-
version:
|
|
13213
|
-
conversation:
|
|
13543
|
+
version: z20.literal(1),
|
|
13544
|
+
conversation: z20.object({
|
|
13214
13545
|
summary: LegacySummarySchema.optional(),
|
|
13215
|
-
messages:
|
|
13546
|
+
messages: z20.array(MessageSchema).max(5e4)
|
|
13216
13547
|
}).strict()
|
|
13217
13548
|
}).strict();
|
|
13218
|
-
var ConversationSchema =
|
|
13549
|
+
var ConversationSchema = z20.object({
|
|
13219
13550
|
compact: CompactBoundarySchema.optional(),
|
|
13220
|
-
messages:
|
|
13551
|
+
messages: z20.array(MessageSchema).max(5e4)
|
|
13221
13552
|
}).strict();
|
|
13222
13553
|
var SessionDocumentV2Schema = SessionBaseSchema.extend({
|
|
13223
|
-
version:
|
|
13554
|
+
version: z20.literal(2),
|
|
13224
13555
|
conversation: ConversationSchema
|
|
13225
13556
|
}).strict();
|
|
13226
|
-
var TranscriptStateSchema =
|
|
13227
|
-
var TimelineSchema =
|
|
13228
|
-
version:
|
|
13557
|
+
var TranscriptStateSchema = z20.custom(isTranscriptState, "Invalid transcript state");
|
|
13558
|
+
var TimelineSchema = z20.object({
|
|
13559
|
+
version: z20.literal(1),
|
|
13229
13560
|
state: TranscriptStateSchema
|
|
13230
13561
|
}).strict();
|
|
13231
13562
|
var SessionDocumentSchema = SessionBaseSchema.extend({
|
|
13232
|
-
version:
|
|
13233
|
-
conversation:
|
|
13563
|
+
version: z20.literal(SESSION_VERSION),
|
|
13564
|
+
conversation: z20.object({
|
|
13234
13565
|
compact: CompactBoundarySchema.optional(),
|
|
13235
|
-
messages:
|
|
13566
|
+
messages: z20.array(MessageSchema).max(5e4)
|
|
13236
13567
|
}).strict(),
|
|
13237
13568
|
timeline: TimelineSchema
|
|
13238
13569
|
}).strict();
|
|
@@ -13408,14 +13739,14 @@ var SessionStore = class {
|
|
|
13408
13739
|
}
|
|
13409
13740
|
}
|
|
13410
13741
|
async #prepareDirectory() {
|
|
13411
|
-
await assertNoSymlink3(this.#workspace,
|
|
13742
|
+
await assertNoSymlink3(this.#workspace, dirname15(this.#sessions));
|
|
13412
13743
|
await mkdir14(this.#sessions, { recursive: true, mode: 448 });
|
|
13413
13744
|
await this.#assertSafeExistingDirectory();
|
|
13414
13745
|
}
|
|
13415
13746
|
async #assertSafeExistingDirectory() {
|
|
13416
13747
|
await assertNoSymlink3(this.#workspace, this.#sessions);
|
|
13417
|
-
const canonicalRoot = await
|
|
13418
|
-
const canonicalSessions = await
|
|
13748
|
+
const canonicalRoot = await realpath7(this.#workspace);
|
|
13749
|
+
const canonicalSessions = await realpath7(this.#sessions);
|
|
13419
13750
|
if (!isWithin4(canonicalRoot, canonicalSessions)) throw new Error("Session directory escapes the workspace");
|
|
13420
13751
|
}
|
|
13421
13752
|
async #quarantine(path) {
|
|
@@ -13572,7 +13903,7 @@ async function assertNoSymlink3(root, target) {
|
|
|
13572
13903
|
const chain = [];
|
|
13573
13904
|
while (cursor !== stop) {
|
|
13574
13905
|
chain.push(cursor);
|
|
13575
|
-
cursor =
|
|
13906
|
+
cursor = dirname15(cursor);
|
|
13576
13907
|
}
|
|
13577
13908
|
for (const path of chain.reverse()) {
|
|
13578
13909
|
try {
|
|
@@ -13588,7 +13919,7 @@ function isWithin4(root, path) {
|
|
|
13588
13919
|
}
|
|
13589
13920
|
async function canonical2(path) {
|
|
13590
13921
|
try {
|
|
13591
|
-
return await
|
|
13922
|
+
return await realpath7(resolve16(path));
|
|
13592
13923
|
} catch {
|
|
13593
13924
|
return resolve16(path);
|
|
13594
13925
|
}
|
|
@@ -13617,45 +13948,45 @@ function sanitize2(input, seen = /* @__PURE__ */ new WeakSet()) {
|
|
|
13617
13948
|
// src/sleep/organizer.ts
|
|
13618
13949
|
import { constants as constants5 } from "fs";
|
|
13619
13950
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
13620
|
-
import { lstat as lstat10, mkdir as mkdir15, open as open9, readdir as readdir8, realpath as
|
|
13951
|
+
import { lstat as lstat10, mkdir as mkdir15, open as open9, readdir as readdir8, realpath as realpath8, rename as rename7, rm as rm7 } from "fs/promises";
|
|
13621
13952
|
import { isAbsolute as isAbsolute8, join as join18, relative as relative14, resolve as resolve17, sep as sep13 } from "path";
|
|
13622
|
-
import { z as
|
|
13623
|
-
var DateKeySchema =
|
|
13624
|
-
var ReviewSchema =
|
|
13625
|
-
title:
|
|
13626
|
-
taskSummary:
|
|
13627
|
-
executionReflection:
|
|
13628
|
-
decisionsAndLearnings:
|
|
13629
|
-
openQuestionsAndRisks:
|
|
13630
|
-
tomorrowPlan:
|
|
13631
|
-
toolUsage:
|
|
13632
|
-
totalCalls:
|
|
13633
|
-
shell:
|
|
13634
|
-
fileRead:
|
|
13635
|
-
fileWrite:
|
|
13636
|
-
search:
|
|
13637
|
-
lsp:
|
|
13638
|
-
subagent:
|
|
13639
|
-
other:
|
|
13953
|
+
import { z as z21 } from "zod";
|
|
13954
|
+
var DateKeySchema = z21.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
13955
|
+
var ReviewSchema = z21.object({
|
|
13956
|
+
title: z21.string().min(1).max(120),
|
|
13957
|
+
taskSummary: z21.array(z21.string().min(1)).min(1).max(20),
|
|
13958
|
+
executionReflection: z21.array(z21.string().min(1)).min(1).max(20),
|
|
13959
|
+
decisionsAndLearnings: z21.array(z21.string().min(1)).max(20),
|
|
13960
|
+
openQuestionsAndRisks: z21.array(z21.string().min(1)).max(20),
|
|
13961
|
+
tomorrowPlan: z21.array(z21.string().min(1)).min(1).max(20),
|
|
13962
|
+
toolUsage: z21.object({
|
|
13963
|
+
totalCalls: z21.number().int().min(0),
|
|
13964
|
+
shell: z21.number().int().min(0),
|
|
13965
|
+
fileRead: z21.number().int().min(0),
|
|
13966
|
+
fileWrite: z21.number().int().min(0),
|
|
13967
|
+
search: z21.number().int().min(0),
|
|
13968
|
+
lsp: z21.number().int().min(0),
|
|
13969
|
+
subagent: z21.number().int().min(0),
|
|
13970
|
+
other: z21.number().int().min(0)
|
|
13640
13971
|
}).strict(),
|
|
13641
|
-
tokenEstimate:
|
|
13642
|
-
estimatedInput:
|
|
13643
|
-
estimatedOutput:
|
|
13644
|
-
notes:
|
|
13972
|
+
tokenEstimate: z21.object({
|
|
13973
|
+
estimatedInput: z21.number().int().min(0),
|
|
13974
|
+
estimatedOutput: z21.number().int().min(0),
|
|
13975
|
+
notes: z21.string().max(200)
|
|
13645
13976
|
}).strict(),
|
|
13646
|
-
humanIntervention:
|
|
13647
|
-
approvalRequests:
|
|
13648
|
-
questionsAsked:
|
|
13649
|
-
summary:
|
|
13977
|
+
humanIntervention: z21.object({
|
|
13978
|
+
approvalRequests: z21.number().int().min(0),
|
|
13979
|
+
questionsAsked: z21.number().int().min(0),
|
|
13980
|
+
summary: z21.string().max(300)
|
|
13650
13981
|
}).strict(),
|
|
13651
|
-
qualityIndicators:
|
|
13652
|
-
hallucinationAlerts:
|
|
13653
|
-
failuresAndRetries:
|
|
13654
|
-
codeChangeSummary:
|
|
13655
|
-
overallAssessment:
|
|
13982
|
+
qualityIndicators: z21.object({
|
|
13983
|
+
hallucinationAlerts: z21.array(z21.string().min(1)).max(10),
|
|
13984
|
+
failuresAndRetries: z21.array(z21.string().min(1)).max(10),
|
|
13985
|
+
codeChangeSummary: z21.string().max(500),
|
|
13986
|
+
overallAssessment: z21.string().max(200)
|
|
13656
13987
|
}).strict(),
|
|
13657
|
-
knowledgeDeposits:
|
|
13658
|
-
worthRemembering:
|
|
13988
|
+
knowledgeDeposits: z21.object({
|
|
13989
|
+
worthRemembering: z21.array(z21.string().min(1)).max(10)
|
|
13659
13990
|
}).strict()
|
|
13660
13991
|
}).strict();
|
|
13661
13992
|
function localDateKey(date) {
|
|
@@ -13764,8 +14095,8 @@ Previous output was invalid. Repair it and return strict JSON only.`;
|
|
|
13764
14095
|
await mkdir15(flavorDirectory, { recursive: true, mode: 448 });
|
|
13765
14096
|
await assertNotSymlink(this.#sleepDirectory);
|
|
13766
14097
|
await mkdir15(this.#sleepDirectory, { recursive: true, mode: 448 });
|
|
13767
|
-
const root = await
|
|
13768
|
-
const target = await
|
|
14098
|
+
const root = await realpath8(this.#workspace);
|
|
14099
|
+
const target = await realpath8(this.#sleepDirectory);
|
|
13769
14100
|
if (!isWithin5(root, target)) throw new Error("Sleep directory escapes the workspace");
|
|
13770
14101
|
}
|
|
13771
14102
|
async #hasReport(date) {
|
|
@@ -14147,10 +14478,10 @@ function computeSessionStats(documents) {
|
|
|
14147
14478
|
|
|
14148
14479
|
// src/tools/files.ts
|
|
14149
14480
|
import { constants as constants6 } from "fs";
|
|
14150
|
-
import { mkdir as mkdir16, open as open10, readFile as readFile15, realpath as
|
|
14151
|
-
import { dirname as
|
|
14481
|
+
import { mkdir as mkdir16, open as open10, readFile as readFile15, realpath as realpath9, rename as rename8, rm as rm8, stat as stat7 } from "fs/promises";
|
|
14482
|
+
import { dirname as dirname16, isAbsolute as isAbsolute9, relative as relative15, resolve as resolve18, sep as sep14 } from "path";
|
|
14152
14483
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
14153
|
-
import { z as
|
|
14484
|
+
import { z as z22 } from "zod";
|
|
14154
14485
|
|
|
14155
14486
|
// src/tools/file-diff.ts
|
|
14156
14487
|
var MAX_DIFF_PREVIEW_LINES = 120;
|
|
@@ -14256,18 +14587,18 @@ function truncateLines(lines) {
|
|
|
14256
14587
|
|
|
14257
14588
|
// src/tools/files.ts
|
|
14258
14589
|
var MAX_READ_BYTES = 1048576;
|
|
14259
|
-
var ReadInput2 =
|
|
14260
|
-
path:
|
|
14261
|
-
maxBytes:
|
|
14262
|
-
startLine:
|
|
14263
|
-
endLine:
|
|
14590
|
+
var ReadInput2 = z22.object({
|
|
14591
|
+
path: z22.string().min(1),
|
|
14592
|
+
maxBytes: z22.coerce.number().int().positive().max(MAX_READ_BYTES).nullable().optional(),
|
|
14593
|
+
startLine: z22.coerce.number().int().positive().nullable().optional(),
|
|
14594
|
+
endLine: z22.coerce.number().int().positive().nullable().optional(),
|
|
14264
14595
|
// Accepts booleans and their string forms (weak-typed models emit "true");
|
|
14265
14596
|
// kept transform-free so the schema converts to JSON Schema for providers.
|
|
14266
|
-
force:
|
|
14597
|
+
force: z22.union([z22.boolean(), z22.string().refine((value) => value === "true" || value === "false")]).nullable().optional()
|
|
14267
14598
|
});
|
|
14268
|
-
var WriteInput =
|
|
14269
|
-
var EditInput =
|
|
14270
|
-
var ApplyPatchInput =
|
|
14599
|
+
var WriteInput = z22.object({ path: z22.string().min(1), content: z22.string() });
|
|
14600
|
+
var EditInput = z22.object({ path: z22.string().min(1), oldText: z22.string().min(1), newText: z22.string() });
|
|
14601
|
+
var ApplyPatchInput = z22.object({ patch: z22.string().min(1) });
|
|
14271
14602
|
var FileObservationStore = class {
|
|
14272
14603
|
#versions = /* @__PURE__ */ new Map();
|
|
14273
14604
|
get(path) {
|
|
@@ -14475,22 +14806,22 @@ function createPathGuard(workspace) {
|
|
|
14475
14806
|
lexical,
|
|
14476
14807
|
existing: async (input) => {
|
|
14477
14808
|
const candidate = lexical(input);
|
|
14478
|
-
const physical = await
|
|
14479
|
-
if (!within2(await
|
|
14809
|
+
const physical = await realpath9(candidate);
|
|
14810
|
+
if (!within2(await realpath9(root), physical)) throw new Error("Path escapes the workspace through a symlink");
|
|
14480
14811
|
return physical;
|
|
14481
14812
|
},
|
|
14482
14813
|
destination: async (input) => {
|
|
14483
14814
|
const candidate = lexical(input);
|
|
14484
|
-
const physicalRoot = await
|
|
14815
|
+
const physicalRoot = await realpath9(root);
|
|
14485
14816
|
let ancestor = candidate;
|
|
14486
14817
|
while (true) {
|
|
14487
14818
|
try {
|
|
14488
|
-
const physical = await
|
|
14819
|
+
const physical = await realpath9(ancestor);
|
|
14489
14820
|
if (!within2(physicalRoot, physical)) throw new Error("Path escapes the workspace through a symlink");
|
|
14490
14821
|
break;
|
|
14491
14822
|
} catch (error) {
|
|
14492
14823
|
if (!isMissing3(error)) throw error;
|
|
14493
|
-
const parent =
|
|
14824
|
+
const parent = dirname16(ancestor);
|
|
14494
14825
|
if (parent === ancestor) throw error;
|
|
14495
14826
|
ancestor = parent;
|
|
14496
14827
|
}
|
|
@@ -14501,7 +14832,7 @@ function createPathGuard(workspace) {
|
|
|
14501
14832
|
}
|
|
14502
14833
|
async function atomicWrite(path, content, signal, expectedVersion) {
|
|
14503
14834
|
abortIfNeeded(signal);
|
|
14504
|
-
await mkdir16(
|
|
14835
|
+
await mkdir16(dirname16(path), { recursive: true });
|
|
14505
14836
|
const temporary = `${path}.${randomUUID11()}.tmp`;
|
|
14506
14837
|
try {
|
|
14507
14838
|
const handle = await open10(temporary, constants6.O_CREAT | constants6.O_EXCL | constants6.O_WRONLY, 384);
|
|
@@ -14863,22 +15194,22 @@ import { lookup } from "dns/promises";
|
|
|
14863
15194
|
import { isIP } from "net";
|
|
14864
15195
|
import { request as httpRequest } from "http";
|
|
14865
15196
|
import { request as httpsRequest } from "https";
|
|
14866
|
-
import { z as
|
|
14867
|
-
var WebFetchInput =
|
|
14868
|
-
url:
|
|
14869
|
-
timeoutMs:
|
|
14870
|
-
maxBytes:
|
|
15197
|
+
import { z as z23 } from "zod";
|
|
15198
|
+
var WebFetchInput = z23.object({
|
|
15199
|
+
url: z23.string().url().max(8192),
|
|
15200
|
+
timeoutMs: z23.coerce.number().int().positive().max(12e4).optional(),
|
|
15201
|
+
maxBytes: z23.coerce.number().int().positive().max(10 * 1024 * 1024).optional()
|
|
14871
15202
|
});
|
|
14872
|
-
var WebSearchInput =
|
|
14873
|
-
query:
|
|
14874
|
-
maxResults:
|
|
15203
|
+
var WebSearchInput = z23.object({
|
|
15204
|
+
query: z23.string().trim().min(1).max(1e3),
|
|
15205
|
+
maxResults: z23.coerce.number().int().min(1).max(20).optional()
|
|
14875
15206
|
});
|
|
14876
15207
|
function createWebFetchTool() {
|
|
14877
15208
|
return {
|
|
14878
15209
|
name: "WebFetch",
|
|
14879
15210
|
description: "Fetch a public HTTP(S) page with SSRF protection and return readable text",
|
|
14880
15211
|
inputSchema: WebFetchInput,
|
|
14881
|
-
outputSchema:
|
|
15212
|
+
outputSchema: z23.object({ url: z23.string(), status: z23.number(), contentType: z23.string(), content: z23.string(), truncated: z23.boolean() }),
|
|
14882
15213
|
paths: () => [],
|
|
14883
15214
|
summarize: (input) => input.url,
|
|
14884
15215
|
presentCall: (input) => ({ kind: "web", title: `Fetching ${new URL(input.url).hostname}`, url: input.url }),
|
|
@@ -14904,7 +15235,7 @@ function createWebSearchTool(provider = createDefaultWebSearchProvider()) {
|
|
|
14904
15235
|
name: "WebSearch",
|
|
14905
15236
|
description: "Search the public web and return titles, URLs, and snippets",
|
|
14906
15237
|
inputSchema: WebSearchInput,
|
|
14907
|
-
outputSchema:
|
|
15238
|
+
outputSchema: z23.object({ query: z23.string(), results: z23.array(z23.object({ title: z23.string(), url: z23.string(), snippet: z23.string() })) }),
|
|
14908
15239
|
paths: () => [],
|
|
14909
15240
|
summarize: (input) => input.query,
|
|
14910
15241
|
presentCall: (input) => ({ kind: "web", title: `Searching: ${input.query}` }),
|
|
@@ -15170,9 +15501,9 @@ function charset(contentType) {
|
|
|
15170
15501
|
import { spawn as spawn7 } from "child_process";
|
|
15171
15502
|
import { existsSync as existsSync2 } from "fs";
|
|
15172
15503
|
import { access, constants as constants7, readFile as readFile16 } from "fs/promises";
|
|
15173
|
-
import { basename as basename4, dirname as
|
|
15504
|
+
import { basename as basename4, dirname as dirname17, extname, isAbsolute as isAbsolute10, relative as relative16, resolve as resolve19, sep as sep15 } from "path";
|
|
15174
15505
|
import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
|
|
15175
|
-
import { z as
|
|
15506
|
+
import { z as z24 } from "zod";
|
|
15176
15507
|
var LSP_REQUEST_TIMEOUT_MS = 15e3;
|
|
15177
15508
|
var LspConnection = class {
|
|
15178
15509
|
#process;
|
|
@@ -15387,7 +15718,7 @@ var LspBuffer = class {
|
|
|
15387
15718
|
}
|
|
15388
15719
|
};
|
|
15389
15720
|
var TYPESCRIPT_CLI = resolve19(
|
|
15390
|
-
|
|
15721
|
+
dirname17(fileURLToPath3(import.meta.resolve("typescript/package.json"))),
|
|
15391
15722
|
"lib",
|
|
15392
15723
|
"tsc.js"
|
|
15393
15724
|
);
|
|
@@ -15506,18 +15837,18 @@ var RealLspManager = class {
|
|
|
15506
15837
|
return connection;
|
|
15507
15838
|
}
|
|
15508
15839
|
};
|
|
15509
|
-
var LspFindRefsInput =
|
|
15510
|
-
file:
|
|
15511
|
-
line:
|
|
15512
|
-
character:
|
|
15840
|
+
var LspFindRefsInput = z24.object({
|
|
15841
|
+
file: z24.string().min(1),
|
|
15842
|
+
line: z24.coerce.number().int().nonnegative(),
|
|
15843
|
+
character: z24.coerce.number().int().nonnegative()
|
|
15513
15844
|
});
|
|
15514
|
-
var LspHoverInput =
|
|
15515
|
-
file:
|
|
15516
|
-
line:
|
|
15517
|
-
character:
|
|
15845
|
+
var LspHoverInput = z24.object({
|
|
15846
|
+
file: z24.string().min(1),
|
|
15847
|
+
line: z24.coerce.number().int().nonnegative(),
|
|
15848
|
+
character: z24.coerce.number().int().nonnegative()
|
|
15518
15849
|
});
|
|
15519
|
-
var LspDiagnosticsInput =
|
|
15520
|
-
file:
|
|
15850
|
+
var LspDiagnosticsInput = z24.object({
|
|
15851
|
+
file: z24.string().min(1)
|
|
15521
15852
|
});
|
|
15522
15853
|
function createLspTools(workspace, options = {}) {
|
|
15523
15854
|
const root = resolve19(workspace);
|
|
@@ -15743,7 +16074,7 @@ async function gitMarker(workspace) {
|
|
|
15743
16074
|
}
|
|
15744
16075
|
|
|
15745
16076
|
// src/git/insights.ts
|
|
15746
|
-
import { z as
|
|
16077
|
+
import { z as z25 } from "zod";
|
|
15747
16078
|
async function suggestCommitMessage(options, input, signal) {
|
|
15748
16079
|
const prompt = [
|
|
15749
16080
|
"Write a git commit message for the staged changes below.",
|
|
@@ -15782,17 +16113,17 @@ function cleanCommitMessage(raw) {
|
|
|
15782
16113
|
}
|
|
15783
16114
|
return kept.join("\n").trim().slice(0, 2e3);
|
|
15784
16115
|
}
|
|
15785
|
-
var ReviewFindingSchema =
|
|
15786
|
-
severity:
|
|
15787
|
-
file:
|
|
15788
|
-
line:
|
|
15789
|
-
issue:
|
|
15790
|
-
suggestion:
|
|
16116
|
+
var ReviewFindingSchema = z25.object({
|
|
16117
|
+
severity: z25.enum(["critical", "warning", "nit"]),
|
|
16118
|
+
file: z25.string(),
|
|
16119
|
+
line: z25.string().describe('Line number or hunk header the finding refers to, e.g. "42" or "@@ -10,4 +10,6 @@"'),
|
|
16120
|
+
issue: z25.string(),
|
|
16121
|
+
suggestion: z25.string()
|
|
15791
16122
|
}).strict();
|
|
15792
|
-
var ReviewReportSchema =
|
|
15793
|
-
summary:
|
|
15794
|
-
verdict:
|
|
15795
|
-
findings:
|
|
16123
|
+
var ReviewReportSchema = z25.object({
|
|
16124
|
+
summary: z25.string().describe("One-paragraph overall assessment of the change"),
|
|
16125
|
+
verdict: z25.enum(["ship", "ship-with-fixes", "needs-work"]),
|
|
16126
|
+
findings: z25.array(ReviewFindingSchema).max(20)
|
|
15796
16127
|
}).strict();
|
|
15797
16128
|
async function reviewDiff(options, input, signal) {
|
|
15798
16129
|
const prompt = [
|
|
@@ -15836,10 +16167,10 @@ function formatReviewReport(report) {
|
|
|
15836
16167
|
}
|
|
15837
16168
|
|
|
15838
16169
|
// src/git/tools.ts
|
|
15839
|
-
import { z as
|
|
15840
|
-
var GitHistoryInput =
|
|
15841
|
-
path:
|
|
15842
|
-
limit:
|
|
16170
|
+
import { z as z26 } from "zod";
|
|
16171
|
+
var GitHistoryInput = z26.object({
|
|
16172
|
+
path: z26.string().describe("File to inspect; omit for the whole repository history").optional(),
|
|
16173
|
+
limit: z26.number().int().min(1).max(50).describe("Maximum number of commits to return (default 20)").optional()
|
|
15843
16174
|
});
|
|
15844
16175
|
function createGitHistoryTool(workspace) {
|
|
15845
16176
|
return {
|
|
@@ -15868,18 +16199,18 @@ function createGitHistoryTool(workspace) {
|
|
|
15868
16199
|
}
|
|
15869
16200
|
|
|
15870
16201
|
// src/tools/ask-user-question.ts
|
|
15871
|
-
import { z as
|
|
15872
|
-
var QuestionOptionSchema =
|
|
15873
|
-
label:
|
|
15874
|
-
description:
|
|
16202
|
+
import { z as z27 } from "zod";
|
|
16203
|
+
var QuestionOptionSchema = z27.object({
|
|
16204
|
+
label: z27.string().trim().min(1),
|
|
16205
|
+
description: z27.string().trim().min(1)
|
|
15875
16206
|
});
|
|
15876
|
-
var QuestionSchema =
|
|
15877
|
-
question:
|
|
15878
|
-
header:
|
|
15879
|
-
options:
|
|
16207
|
+
var QuestionSchema = z27.object({
|
|
16208
|
+
question: z27.string().trim().min(1),
|
|
16209
|
+
header: z27.string().trim().min(1),
|
|
16210
|
+
options: z27.array(QuestionOptionSchema).min(1).max(4)
|
|
15880
16211
|
});
|
|
15881
|
-
var AskUserQuestionInput =
|
|
15882
|
-
questions:
|
|
16212
|
+
var AskUserQuestionInput = z27.object({
|
|
16213
|
+
questions: z27.array(QuestionSchema).min(1).max(4)
|
|
15883
16214
|
});
|
|
15884
16215
|
function hookAnswersFromUpdatedInput(updatedInput, questions) {
|
|
15885
16216
|
if (typeof updatedInput !== "object" || updatedInput === null) return void 0;
|
|
@@ -15963,20 +16294,20 @@ function createAskUserQuestionTool(handler) {
|
|
|
15963
16294
|
}
|
|
15964
16295
|
|
|
15965
16296
|
// src/tools/todo-write.ts
|
|
15966
|
-
import { z as
|
|
15967
|
-
var TodoStatusSchema =
|
|
16297
|
+
import { z as z28 } from "zod";
|
|
16298
|
+
var TodoStatusSchema = z28.enum([
|
|
15968
16299
|
"pending",
|
|
15969
16300
|
"in_progress",
|
|
15970
16301
|
"completed",
|
|
15971
16302
|
"cancelled"
|
|
15972
16303
|
]);
|
|
15973
|
-
var TodoItemSchema =
|
|
15974
|
-
content:
|
|
16304
|
+
var TodoItemSchema = z28.object({
|
|
16305
|
+
content: z28.string().trim().min(1),
|
|
15975
16306
|
status: TodoStatusSchema,
|
|
15976
|
-
activeForm:
|
|
16307
|
+
activeForm: z28.string().trim().min(1)
|
|
15977
16308
|
});
|
|
15978
|
-
var TodoWriteInput =
|
|
15979
|
-
todos:
|
|
16309
|
+
var TodoWriteInput = z28.object({
|
|
16310
|
+
todos: z28.array(TodoItemSchema).min(1).max(50)
|
|
15980
16311
|
});
|
|
15981
16312
|
function createTodoWriteTool() {
|
|
15982
16313
|
return {
|
|
@@ -16012,37 +16343,37 @@ function createTodoWriteTool() {
|
|
|
16012
16343
|
// src/tools/managed.ts
|
|
16013
16344
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
16014
16345
|
import { link as link2, lstat as lstat11, mkdir as mkdir17, readFile as readFile17, readdir as readdir9, unlink as unlink4, writeFile as writeFile10 } from "fs/promises";
|
|
16015
|
-
import { dirname as
|
|
16016
|
-
import { z as
|
|
16346
|
+
import { dirname as dirname18, join as join19, resolve as resolve20 } from "path";
|
|
16347
|
+
import { z as z29 } from "zod";
|
|
16017
16348
|
var MANAGED_TOOL_VERSION = 1;
|
|
16018
16349
|
var MAX_RECORD_BYTES = 256 * 1024;
|
|
16019
16350
|
var TOOL_NAME = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
|
|
16020
|
-
var JsonSchemaObject =
|
|
16351
|
+
var JsonSchemaObject = z29.record(z29.string(), z29.unknown()).superRefine((schema, context) => {
|
|
16021
16352
|
if (schema.type !== "object") {
|
|
16022
16353
|
context.addIssue({ code: "custom", message: "Tool input JSON Schema must have type object" });
|
|
16023
16354
|
}
|
|
16024
16355
|
});
|
|
16025
|
-
var RegisterManagedToolInputSchema =
|
|
16026
|
-
name:
|
|
16027
|
-
description:
|
|
16356
|
+
var RegisterManagedToolInputSchema = z29.object({
|
|
16357
|
+
name: z29.string().regex(TOOL_NAME).describe("Unique callable tool name using letters, digits, and underscores"),
|
|
16358
|
+
description: z29.string().min(1).max(4096).describe("Purpose and appropriate use of the generated tool"),
|
|
16028
16359
|
inputSchema: JsonSchemaObject.describe("Provider-facing JSON Schema with an object at the root"),
|
|
16029
|
-
implementation:
|
|
16360
|
+
implementation: z29.string().min(1).max(64 * 1024).describe(
|
|
16030
16361
|
"Async JavaScript function body, or complete function/arrow expression, receiving input, signal, and context; return the tool result"
|
|
16031
16362
|
),
|
|
16032
|
-
scope:
|
|
16363
|
+
scope: z29.enum(["project", "global"]).default("project").describe(
|
|
16033
16364
|
"Project persists in the current workspace; global persists for every workspace"
|
|
16034
16365
|
),
|
|
16035
|
-
agents:
|
|
16366
|
+
agents: z29.array(z29.enum(["main", "subagent"])).min(1).max(2).optional().describe(
|
|
16036
16367
|
"Agent roles allowed to call the generated tool; omit to allow both"
|
|
16037
16368
|
)
|
|
16038
16369
|
}).strict();
|
|
16039
|
-
var RemoveManagedToolInputSchema =
|
|
16040
|
-
name:
|
|
16041
|
-
scope:
|
|
16370
|
+
var RemoveManagedToolInputSchema = z29.object({
|
|
16371
|
+
name: z29.string().regex(TOOL_NAME).describe("Managed tool name to remove"),
|
|
16372
|
+
scope: z29.enum(["project", "global"]).optional().describe("Required only when the same name exists in both scopes")
|
|
16042
16373
|
}).strict();
|
|
16043
16374
|
var ManagedToolRecordSchema = RegisterManagedToolInputSchema.extend({
|
|
16044
|
-
version:
|
|
16045
|
-
createdAt:
|
|
16375
|
+
version: z29.literal(MANAGED_TOOL_VERSION),
|
|
16376
|
+
createdAt: z29.string().datetime()
|
|
16046
16377
|
}).strict();
|
|
16047
16378
|
var AsyncFunction = Object.getPrototypeOf(async function() {
|
|
16048
16379
|
}).constructor;
|
|
@@ -16229,7 +16560,7 @@ function createManagedToolManagementTools(options) {
|
|
|
16229
16560
|
const listTools = {
|
|
16230
16561
|
name: "ListRegisteredTools",
|
|
16231
16562
|
description: "List durable tools created through RegisterTool, including scope, path, and active precedence",
|
|
16232
|
-
inputSchema:
|
|
16563
|
+
inputSchema: z29.object({}).strict(),
|
|
16233
16564
|
agents: mainOnly,
|
|
16234
16565
|
paths: () => [],
|
|
16235
16566
|
execute: async (_input, signal) => {
|
|
@@ -16242,7 +16573,7 @@ function createManagedToolManagementTools(options) {
|
|
|
16242
16573
|
function compileDefinition(record, scope2, workspace) {
|
|
16243
16574
|
let inputSchema;
|
|
16244
16575
|
try {
|
|
16245
|
-
inputSchema =
|
|
16576
|
+
inputSchema = z29.fromJSONSchema(record.inputSchema);
|
|
16246
16577
|
} catch (error) {
|
|
16247
16578
|
throw new Error(`Invalid input schema for managed tool "${record.name}": ${message(error)}`);
|
|
16248
16579
|
}
|
|
@@ -16296,7 +16627,7 @@ ${sourceUrl}`
|
|
|
16296
16627
|
}
|
|
16297
16628
|
}
|
|
16298
16629
|
async function writeExclusive(path, content) {
|
|
16299
|
-
await mkdir17(
|
|
16630
|
+
await mkdir17(dirname18(path), { recursive: true });
|
|
16300
16631
|
const temporary = `${path}.${randomUUID12()}.tmp`;
|
|
16301
16632
|
try {
|
|
16302
16633
|
await writeFile10(temporary, content, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
@@ -16342,7 +16673,7 @@ function isMissing4(error) {
|
|
|
16342
16673
|
}
|
|
16343
16674
|
|
|
16344
16675
|
// src/hallucination/confidence.ts
|
|
16345
|
-
import { z as
|
|
16676
|
+
import { z as z30 } from "zod";
|
|
16346
16677
|
|
|
16347
16678
|
// src/hallucination/types.ts
|
|
16348
16679
|
var DEFAULT_SLIDING_WINDOW_SIZE = 20;
|
|
@@ -16355,12 +16686,12 @@ var DEFAULT_EVALUATION_TIMEOUT_MS = 2e3;
|
|
|
16355
16686
|
var MAX_QUERY_CHARS = 5e3;
|
|
16356
16687
|
var MAX_OUTPUT_CHARS = 1e4;
|
|
16357
16688
|
var MAX_EVIDENCE_CHARS = 6e3;
|
|
16358
|
-
var ConfidenceSchema =
|
|
16359
|
-
taskAlignment:
|
|
16360
|
-
evidenceGrounding:
|
|
16361
|
-
processReliability:
|
|
16362
|
-
reason:
|
|
16363
|
-
unsupportedClaims:
|
|
16689
|
+
var ConfidenceSchema = z30.object({
|
|
16690
|
+
taskAlignment: z30.number(),
|
|
16691
|
+
evidenceGrounding: z30.number(),
|
|
16692
|
+
processReliability: z30.number(),
|
|
16693
|
+
reason: z30.string(),
|
|
16694
|
+
unsupportedClaims: z30.array(z30.string()).max(3)
|
|
16364
16695
|
});
|
|
16365
16696
|
var PROMPT = `You are a fast, evidence-aware task-completion verifier.
|
|
16366
16697
|
|
|
@@ -18359,15 +18690,15 @@ function workspacePath(root, input) {
|
|
|
18359
18690
|
}
|
|
18360
18691
|
|
|
18361
18692
|
// src/tools/terminal.ts
|
|
18362
|
-
import { z as
|
|
18693
|
+
import { z as z31 } from "zod";
|
|
18363
18694
|
import { resolve as resolve24 } from "path";
|
|
18364
|
-
var Id =
|
|
18365
|
-
var OpenInput =
|
|
18366
|
-
var OptionalBoolean =
|
|
18367
|
-
var WriteInput2 =
|
|
18368
|
-
var ReadInput3 =
|
|
18369
|
-
var ResizeInput =
|
|
18370
|
-
var CloseInput =
|
|
18695
|
+
var Id = z31.string().regex(/^term-[a-f0-9-]+$/);
|
|
18696
|
+
var OpenInput = z31.object({ cwd: z31.string().optional(), shell: z31.string().optional(), args: z31.array(z31.string()).optional(), columns: z31.coerce.number().int().min(10).max(500).optional(), rows: z31.coerce.number().int().min(2).max(300).optional() });
|
|
18697
|
+
var OptionalBoolean = z31.union([z31.boolean(), z31.string().refine((value) => value === "true" || value === "false")]);
|
|
18698
|
+
var WriteInput2 = z31.object({ id: Id, data: z31.string().max(1e5), enter: OptionalBoolean.optional() });
|
|
18699
|
+
var ReadInput3 = z31.object({ id: Id, cursor: z31.coerce.number().int().min(0).optional() });
|
|
18700
|
+
var ResizeInput = z31.object({ id: Id, columns: z31.coerce.number().int().min(10).max(500), rows: z31.coerce.number().int().min(2).max(300) });
|
|
18701
|
+
var CloseInput = z31.object({ id: Id });
|
|
18371
18702
|
function createTerminalTools(terminals, workspace = process.cwd()) {
|
|
18372
18703
|
const tools = [
|
|
18373
18704
|
{
|
|
@@ -18443,7 +18774,7 @@ function createTerminalTools(terminals, workspace = process.cwd()) {
|
|
|
18443
18774
|
{
|
|
18444
18775
|
name: "TerminalList",
|
|
18445
18776
|
description: "List persistent terminals owned by this agent",
|
|
18446
|
-
inputSchema:
|
|
18777
|
+
inputSchema: z31.object({}),
|
|
18447
18778
|
paths: () => [],
|
|
18448
18779
|
execute: async (_input, _signal, context) => terminals.list(owner(context))
|
|
18449
18780
|
}
|
|
@@ -18822,7 +19153,7 @@ var PalClient = class {
|
|
|
18822
19153
|
};
|
|
18823
19154
|
|
|
18824
19155
|
// src/pals/tools.ts
|
|
18825
|
-
import { z as
|
|
19156
|
+
import { z as z32 } from "zod";
|
|
18826
19157
|
var DEFAULT_SHARE_BUDGET_BYTES = 128 * 1024;
|
|
18827
19158
|
var CollaborationShareGuard = class {
|
|
18828
19159
|
redact;
|
|
@@ -18843,25 +19174,25 @@ var CollaborationShareGuard = class {
|
|
|
18843
19174
|
return redacted;
|
|
18844
19175
|
}
|
|
18845
19176
|
};
|
|
18846
|
-
var Uuid =
|
|
18847
|
-
var Hash =
|
|
19177
|
+
var Uuid = z32.uuid();
|
|
19178
|
+
var Hash = z32.string().regex(/^[a-f0-9]{64}$/);
|
|
18848
19179
|
var Target = PalTargetSchema;
|
|
18849
|
-
var BoundedText =
|
|
19180
|
+
var BoundedText = z32.string().trim().min(1).refine(
|
|
18850
19181
|
(value) => Buffer.byteLength(value, "utf8") <= MAX_MESSAGE_BYTES,
|
|
18851
19182
|
`Text must not exceed ${MAX_MESSAGE_BYTES} UTF-8 bytes`
|
|
18852
19183
|
);
|
|
18853
|
-
var CompletionEvidence =
|
|
19184
|
+
var CompletionEvidence = z32.string().trim().min(1).refine(
|
|
18854
19185
|
(value) => Buffer.byteLength(value, "utf8") <= MAX_COMPLETION_DETAIL_BYTES,
|
|
18855
19186
|
`Completion evidence must not exceed ${MAX_COMPLETION_DETAIL_BYTES} UTF-8 bytes`
|
|
18856
19187
|
);
|
|
18857
|
-
var EmptyInput =
|
|
18858
|
-
var StateInput =
|
|
18859
|
-
var TokenInput =
|
|
18860
|
-
var SendInput =
|
|
18861
|
-
var PlanInput =
|
|
18862
|
-
var ProgressInput =
|
|
18863
|
-
var CompleteInput = TokenInput.extend({ passed:
|
|
18864
|
-
var IntegrateInput = TokenInput.extend({ passed:
|
|
19188
|
+
var EmptyInput = z32.object({}).strict();
|
|
19189
|
+
var StateInput = z32.object({ coWorkId: Uuid }).strict();
|
|
19190
|
+
var TokenInput = z32.object({ coWorkId: Uuid, epoch: z32.number().int().positive(), planHash: Hash }).strict();
|
|
19191
|
+
var SendInput = z32.object({ target: Target, message: BoundedText, coWorkId: Uuid.optional() }).strict();
|
|
19192
|
+
var PlanInput = z32.object({ plan: CoWorkPlanSchema }).strict();
|
|
19193
|
+
var ProgressInput = z32.object({ coWorkId: Uuid, target: Target, detail: BoundedText }).strict();
|
|
19194
|
+
var CompleteInput = TokenInput.extend({ passed: z32.boolean(), detail: CompletionEvidence }).strict();
|
|
19195
|
+
var IntegrateInput = TokenInput.extend({ passed: z32.boolean(), evidence: CompletionEvidence }).strict();
|
|
18865
19196
|
var sharedBytes = (...values) => values.reduce((total, value) => total + Buffer.byteLength(value, "utf8"), 0);
|
|
18866
19197
|
function resolvePresence(presences, target) {
|
|
18867
19198
|
const normalized = normalizePalIdentity(target);
|
|
@@ -19478,7 +19809,7 @@ async function createProductionRuntime(options) {
|
|
|
19478
19809
|
});
|
|
19479
19810
|
const skillsReady = skills.discover();
|
|
19480
19811
|
skillsReady.catch(() => void 0);
|
|
19481
|
-
tools.push(createSkillResourceTool(skills));
|
|
19812
|
+
tools.push(createSkillTool(skills), createSkillResourceTool(skills));
|
|
19482
19813
|
if (options.extraTools !== void 0) tools.push(...options.extraTools);
|
|
19483
19814
|
const flavor = await optionalText2(join22(workspace, "FLAVOR.md"));
|
|
19484
19815
|
const instructionBaseline = await workspaceInstructions.baseline();
|
|
@@ -20180,6 +20511,10 @@ async function createProductionRuntime(options) {
|
|
|
20180
20511
|
subagentModel: () => childModel,
|
|
20181
20512
|
llmServiceName: () => effectiveLlm?.serviceName,
|
|
20182
20513
|
permissionMode: () => harness.permissionMode,
|
|
20514
|
+
addContext: (content) => {
|
|
20515
|
+
const duplicate = harness.main.context.snapshot().messages.some((entry2) => entry2.role === "system" && entry2.content === content);
|
|
20516
|
+
if (!duplicate) harness.main.context.append({ role: "system", content });
|
|
20517
|
+
},
|
|
20183
20518
|
...palServices === void 0 ? {} : { pals: palServices },
|
|
20184
20519
|
run: (prompt, signal, runOptions) => {
|
|
20185
20520
|
interruptedTaskPlanNeedsReassessment = false;
|
|
@@ -20793,7 +21128,7 @@ async function* runMain(harness, skills, prompt, signal, setupError, memory, get
|
|
|
20793
21128
|
if (ideContext !== void 0) contexts.push(ideContext);
|
|
20794
21129
|
const skill = await skills.match(prompt);
|
|
20795
21130
|
if (skill !== void 0) contexts.push(`Matched skill: ${skill.name}
|
|
20796
|
-
${await skills.loadBody(skill)}`);
|
|
21131
|
+
${expandSkillArguments(await skills.loadBody(skill), prompt)}`);
|
|
20797
21132
|
const additionalContext = contexts.length === 0 ? void 0 : contexts.join("\n\n");
|
|
20798
21133
|
for await (const event of harness.main.loop.run({
|
|
20799
21134
|
prompt,
|
|
@@ -20828,7 +21163,7 @@ async function* runExplicitSkill(harness, skills, skillName, prompt, signal, set
|
|
|
20828
21163
|
}
|
|
20829
21164
|
const userPrompt = prompt || `Apply the ${skillName} skill.`;
|
|
20830
21165
|
const additionalContext = `Matched skill: ${skill.name}
|
|
20831
|
-
${await skills.loadBody(skill)}`;
|
|
21166
|
+
${expandSkillArguments(await skills.loadBody(skill), prompt)}`;
|
|
20832
21167
|
yield* harness.main.loop.run({ prompt: userPrompt, signal, additionalContext });
|
|
20833
21168
|
} catch (error) {
|
|
20834
21169
|
yield { type: "error", error: { code: "unknown", message: message(error) } };
|