flavor-code 1.2.14 → 1.2.16
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 +8 -3
- package/README.zh-CN.md +8 -3
- package/dist/agent/planner.d.ts +2 -0
- package/dist/{app-UJAGMKD5.js → app-7ZCJ3UOI.js} +1 -1
- package/dist/auth/store.d.ts +7 -0
- package/dist/{chunk-4YXDGGIC.js → chunk-5SRARNAC.js} +640 -79
- package/dist/{chunk-KL6TR2KG.js → chunk-PGS3M32Y.js} +1 -1
- package/dist/cli.js +78 -16
- package/dist/desktop/main.js +965 -334
- package/dist/desktop/preload.cjs +2 -0
- package/dist/desktop-renderer/assets/index-BmXr_vX3.js +151 -0
- package/dist/desktop-renderer/assets/{index-CPxt3vFY.css → index-DEL8gXBO.css} +1 -1
- package/dist/desktop-renderer/index.html +2 -2
- package/dist/evolve/store.d.ts +26 -0
- package/dist/git/insights.d.ts +52 -0
- package/dist/git/service.d.ts +43 -0
- package/dist/git/tools.d.ts +9 -0
- package/dist/sdk/index.js +2 -2
- package/dist/session/store.d.ts +1 -0
- package/dist/tools/shell.d.ts +11 -0
- package/dist/ui/commands.d.ts +8 -2
- package/dist/ui/session.d.ts +3 -0
- package/package.json +1 -1
- package/dist/desktop-renderer/assets/index-CcD0D6x0.js +0 -151
package/dist/desktop/main.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/desktop/main.ts
|
|
2
2
|
import { appendFileSync } from "fs";
|
|
3
3
|
import { readFile as readFile34, stat as stat15, writeFile as writeFile18 } from "fs/promises";
|
|
4
|
-
import { dirname as dirname23, join as
|
|
4
|
+
import { dirname as dirname23, join as join41 } from "path";
|
|
5
5
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
6
6
|
import { app, BrowserWindow as BrowserWindow2, dialog, ipcMain, Menu, nativeImage, shell } from "electron";
|
|
7
7
|
|
|
@@ -505,6 +505,7 @@ var DESKTOP_CHANNELS = {
|
|
|
505
505
|
d2cRunQualityJudge: "desktop:d2c-run-quality-judge",
|
|
506
506
|
d2cResolveQualityIssue: "desktop:d2c-resolve-quality-issue",
|
|
507
507
|
d2cSetManualAcceptance: "desktop:d2c-set-manual-acceptance",
|
|
508
|
+
e2eGetDeliveryRun: "desktop:e2e-get-delivery-run",
|
|
508
509
|
event: "desktop:event"
|
|
509
510
|
};
|
|
510
511
|
|
|
@@ -2611,11 +2612,11 @@ function hexToLab(hex) {
|
|
|
2611
2612
|
const b = linearize(channels[2]);
|
|
2612
2613
|
const x = (0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / 0.95047;
|
|
2613
2614
|
const y = 0.2126729 * r + 0.7151522 * g + 0.072175 * b;
|
|
2614
|
-
const
|
|
2615
|
+
const z43 = (0.0193339 * r + 0.119192 * g + 0.9503041 * b) / 1.08883;
|
|
2615
2616
|
const f = (t) => t > 8856e-6 ? Math.cbrt(t) : 7.787 * t + 16 / 116;
|
|
2616
2617
|
const fx = f(x);
|
|
2617
2618
|
const fy = f(y);
|
|
2618
|
-
const fz = f(
|
|
2619
|
+
const fz = f(z43);
|
|
2619
2620
|
return [116 * fy - 16, 500 * (fx - fy), 200 * (fy - fz)];
|
|
2620
2621
|
}
|
|
2621
2622
|
function deltaE76(left, right) {
|
|
@@ -4230,7 +4231,10 @@ var TaskNodeSchema = z9.object({
|
|
|
4230
4231
|
description: z9.string().trim().min(1),
|
|
4231
4232
|
dependencies: z9.array(z9.string().trim().min(1)),
|
|
4232
4233
|
expectedOutputs: z9.array(z9.string().trim().min(1)),
|
|
4233
|
-
verification: z9.array(z9.string().trim().min(1))
|
|
4234
|
+
verification: z9.array(z9.string().trim().min(1)),
|
|
4235
|
+
files: z9.array(z9.string().trim().min(1)).describe(
|
|
4236
|
+
"Workspace files this task owns for writing. Tasks whose files overlap are never run in parallel, so declare every file this task may create or modify."
|
|
4237
|
+
).optional()
|
|
4234
4238
|
}).strict();
|
|
4235
4239
|
var TaskGraphSchema = z9.object({
|
|
4236
4240
|
nodes: z9.array(TaskNodeSchema)
|
|
@@ -4422,6 +4426,7 @@ var SubagentScheduler = class {
|
|
|
4422
4426
|
const states = new Map(graph.nodes.map((task) => [task.id, "pending"]));
|
|
4423
4427
|
const results = /* @__PURE__ */ new Map();
|
|
4424
4428
|
const running = /* @__PURE__ */ new Map();
|
|
4429
|
+
const runningFiles = /* @__PURE__ */ new Map();
|
|
4425
4430
|
const started = /* @__PURE__ */ new Set();
|
|
4426
4431
|
try {
|
|
4427
4432
|
while (statesHaveWork(states)) {
|
|
@@ -4430,7 +4435,9 @@ var SubagentScheduler = class {
|
|
|
4430
4435
|
for (const task of graph.nodes) {
|
|
4431
4436
|
if (running.size >= this.#options.maxSubagents) break;
|
|
4432
4437
|
if (states.get(task.id) !== "pending" || !isReady(task, states)) continue;
|
|
4438
|
+
if (conflictsWithRunning(task, runningFiles)) continue;
|
|
4433
4439
|
states.set(task.id, "running");
|
|
4440
|
+
if (task.files !== void 0) runningFiles.set(task.id, task.files.map(normalizeOwnedFile));
|
|
4434
4441
|
const execution = this.#runTask(task, signal);
|
|
4435
4442
|
running.set(task.id, execution);
|
|
4436
4443
|
started.add(execution);
|
|
@@ -4443,6 +4450,7 @@ var SubagentScheduler = class {
|
|
|
4443
4450
|
const completion = await Promise.race(running.values());
|
|
4444
4451
|
signal.throwIfAborted();
|
|
4445
4452
|
running.delete(completion.id);
|
|
4453
|
+
runningFiles.delete(completion.id);
|
|
4446
4454
|
results.set(completion.id, completion.result);
|
|
4447
4455
|
states.set(completion.id, completion.result.status);
|
|
4448
4456
|
await this.#options.onResult?.(completion.result);
|
|
@@ -4520,6 +4528,26 @@ var SubagentScheduler = class {
|
|
|
4520
4528
|
function isReady(task, states) {
|
|
4521
4529
|
return task.dependencies.every((dependency) => states.get(dependency) === "completed");
|
|
4522
4530
|
}
|
|
4531
|
+
function normalizeOwnedFile(value) {
|
|
4532
|
+
return value.replace(/\\/g, "/");
|
|
4533
|
+
}
|
|
4534
|
+
function ownedFilesConflict(left, right) {
|
|
4535
|
+
for (const one of left) {
|
|
4536
|
+
for (const other of right) {
|
|
4537
|
+
if (one === other) return true;
|
|
4538
|
+
if (other.startsWith(`${one}/`) || one.startsWith(`${other}/`)) return true;
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4541
|
+
return false;
|
|
4542
|
+
}
|
|
4543
|
+
function conflictsWithRunning(task, runningFiles) {
|
|
4544
|
+
if (task.files === void 0 || task.files.length === 0) return false;
|
|
4545
|
+
const owned = task.files.map(normalizeOwnedFile);
|
|
4546
|
+
for (const files of runningFiles.values()) {
|
|
4547
|
+
if (ownedFilesConflict(owned, files)) return true;
|
|
4548
|
+
}
|
|
4549
|
+
return false;
|
|
4550
|
+
}
|
|
4523
4551
|
function statesHaveWork(states) {
|
|
4524
4552
|
return [...states.values()].some((state) => state === "pending" || state === "running");
|
|
4525
4553
|
}
|
|
@@ -8686,23 +8714,45 @@ async function readJsonArray(file) {
|
|
|
8686
8714
|
return [];
|
|
8687
8715
|
}
|
|
8688
8716
|
}
|
|
8717
|
+
async function readRules(file) {
|
|
8718
|
+
try {
|
|
8719
|
+
const parsed = JSON.parse(await readFile7(file, "utf8"));
|
|
8720
|
+
if (!Array.isArray(parsed)) return [];
|
|
8721
|
+
return parsed.filter((item) => item !== null && typeof item === "object").filter((item) => typeof item.id === "string" && typeof item.text === "string").map((item) => ({
|
|
8722
|
+
id: item.id,
|
|
8723
|
+
text: item.text,
|
|
8724
|
+
addedAt: typeof item.addedAt === "string" ? item.addedAt : "",
|
|
8725
|
+
...typeof item.sourceId === "string" ? { sourceId: item.sourceId } : {}
|
|
8726
|
+
}));
|
|
8727
|
+
} catch {
|
|
8728
|
+
return [];
|
|
8729
|
+
}
|
|
8730
|
+
}
|
|
8731
|
+
async function writeRules(file, rules) {
|
|
8732
|
+
await mkdir8(dirname7(file), { recursive: true, mode: 448 });
|
|
8733
|
+
await writeFile6(file, JSON.stringify(rules, null, 2), { encoding: "utf8", mode: 384 });
|
|
8734
|
+
}
|
|
8689
8735
|
var EvolveStore = class {
|
|
8690
8736
|
dir;
|
|
8691
8737
|
signalsFile;
|
|
8692
8738
|
reflectionsFile;
|
|
8693
8739
|
doneFile;
|
|
8694
8740
|
verifiedFile;
|
|
8741
|
+
rulesFile;
|
|
8695
8742
|
maxSignals;
|
|
8743
|
+
maxRules;
|
|
8696
8744
|
// Serialize file mutations: tool hooks may fire in bursts.
|
|
8697
8745
|
#queue = Promise.resolve();
|
|
8698
8746
|
constructor(options) {
|
|
8699
|
-
const { workspace, maxSignals = 400 } = options;
|
|
8747
|
+
const { workspace, maxSignals = 400, maxRules = 20 } = options;
|
|
8700
8748
|
this.dir = join9(workspace, ".flavor", "evolve");
|
|
8701
8749
|
this.signalsFile = join9(this.dir, "signals.jsonl");
|
|
8702
8750
|
this.reflectionsFile = join9(this.dir, "reflections.jsonl");
|
|
8703
8751
|
this.doneFile = join9(this.dir, "done.json");
|
|
8704
8752
|
this.verifiedFile = join9(this.dir, "verified.json");
|
|
8753
|
+
this.rulesFile = join9(this.dir, "rules.json");
|
|
8705
8754
|
this.maxSignals = maxSignals;
|
|
8755
|
+
this.maxRules = maxRules;
|
|
8706
8756
|
}
|
|
8707
8757
|
#enqueue(operation) {
|
|
8708
8758
|
const next = this.#queue.then(operation, operation);
|
|
@@ -8848,6 +8898,43 @@ var EvolveStore = class {
|
|
|
8848
8898
|
}
|
|
8849
8899
|
});
|
|
8850
8900
|
}
|
|
8901
|
+
/** Learned guardrail rules, oldest first. */
|
|
8902
|
+
listRules() {
|
|
8903
|
+
return this.#enqueue(() => readRules(this.rulesFile));
|
|
8904
|
+
}
|
|
8905
|
+
/**
|
|
8906
|
+
* Add one guardrail rule. Dedupes by fingerprint of the normalized text and
|
|
8907
|
+
* keeps at most maxRules entries (oldest dropped first).
|
|
8908
|
+
*/
|
|
8909
|
+
addRule(input) {
|
|
8910
|
+
return this.#enqueue(async () => {
|
|
8911
|
+
const text = input.text.replace(/\s+/g, " ").trim().slice(0, 300);
|
|
8912
|
+
if (text === "") throw new Error("rule text must not be empty");
|
|
8913
|
+
const id = fingerprint("rule", void 0, text);
|
|
8914
|
+
const rules = await readRules(this.rulesFile);
|
|
8915
|
+
const existing = rules.find((rule2) => rule2.id === id);
|
|
8916
|
+
if (existing !== void 0) return { added: false, rule: existing };
|
|
8917
|
+
const rule = {
|
|
8918
|
+
id,
|
|
8919
|
+
text,
|
|
8920
|
+
addedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8921
|
+
...input.sourceId === void 0 ? {} : { sourceId: input.sourceId }
|
|
8922
|
+
};
|
|
8923
|
+
rules.push(rule);
|
|
8924
|
+
if (rules.length > this.maxRules) rules.splice(0, rules.length - this.maxRules);
|
|
8925
|
+
await writeRules(this.rulesFile, rules);
|
|
8926
|
+
return { added: true, rule };
|
|
8927
|
+
});
|
|
8928
|
+
}
|
|
8929
|
+
removeRule(id) {
|
|
8930
|
+
return this.#enqueue(async () => {
|
|
8931
|
+
const rules = await readRules(this.rulesFile);
|
|
8932
|
+
const next = rules.filter((rule) => rule.id !== id);
|
|
8933
|
+
if (next.length === rules.length) return { removed: false };
|
|
8934
|
+
await writeRules(this.rulesFile, next);
|
|
8935
|
+
return { removed: true };
|
|
8936
|
+
});
|
|
8937
|
+
}
|
|
8851
8938
|
};
|
|
8852
8939
|
|
|
8853
8940
|
// src/evolve/service.ts
|
|
@@ -8859,9 +8946,15 @@ a plugin, a memory rule, a tool wrapper, or a safer default), implement it in
|
|
|
8859
8946
|
this session when it is in scope; otherwise ignore them. Never act on them
|
|
8860
8947
|
without running the test suite afterwards.
|
|
8861
8948
|
|
|
8949
|
+
`;
|
|
8950
|
+
var GUARDRAILS_SECTION_HEADER = `# learned guardrails (evolve)
|
|
8951
|
+
|
|
8952
|
+
These rules were distilled from repeated tool failures in this workspace.
|
|
8953
|
+
Follow them unless the current task or the user explicitly contradicts one.
|
|
8954
|
+
|
|
8862
8955
|
`;
|
|
8863
8956
|
var USAGE = [
|
|
8864
|
-
"usage: /evolve <signals|suggest|improve <id>|verify <name>|reload <name>|test|revert <name>|done <id>|verified|clear>",
|
|
8957
|
+
"usage: /evolve <signals|suggest|improve <id>|verify <name>|reload <name>|test|revert <name>|done <id>|verified|trends [n]|rule <list|add|remove>|clear>",
|
|
8865
8958
|
" signals list recent failing tool results",
|
|
8866
8959
|
" suggest aggregate repeated failures into fix suggestions (trend-aware ordering)",
|
|
8867
8960
|
" improve scaffold a fix-<tool>/ plugin dir + PLAN.md for one suggestion",
|
|
@@ -8871,6 +8964,8 @@ var USAGE = [
|
|
|
8871
8964
|
" revert restore the last good snapshot of a plugin",
|
|
8872
8965
|
" done mark a suggestion as handled (no longer proposed)",
|
|
8873
8966
|
" verified list suggestions auto-verified by improving failure trends",
|
|
8967
|
+
" trends cross-run dashboard: tool calls, failures, signalDelta, per-tool movement",
|
|
8968
|
+
" rule manage learned guardrails injected into system prompts (list/add <text>/remove <id>)",
|
|
8874
8969
|
" clear reset signals, done markers, and verified markers"
|
|
8875
8970
|
].join("\n");
|
|
8876
8971
|
function runCommand(command, cwd, timeoutMs) {
|
|
@@ -8962,9 +9057,17 @@ function createEvolveService(options) {
|
|
|
8962
9057
|
}
|
|
8963
9058
|
async function refreshPromptCache() {
|
|
8964
9059
|
try {
|
|
8965
|
-
const suggestions = await openWithTrends(promptTop);
|
|
8966
|
-
|
|
8967
|
-
|
|
9060
|
+
const [suggestions, rules] = await Promise.all([openWithTrends(promptTop), store.listRules()]);
|
|
9061
|
+
const sections = [];
|
|
9062
|
+
if (rules.length > 0) {
|
|
9063
|
+
sections.push(`${GUARDRAILS_SECTION_HEADER}${rules.map((rule) => `- ${rule.text}`).join("\n")}
|
|
9064
|
+
`);
|
|
9065
|
+
}
|
|
9066
|
+
if (suggestions.length > 0) {
|
|
9067
|
+
sections.push(`${SUGGEST_SECTION_HEADER}${suggestions.map((suggestion) => `- [${suggestion.id}] ${suggestion.hint}`).join("\n")}
|
|
9068
|
+
`);
|
|
9069
|
+
}
|
|
9070
|
+
promptCache = sections.length === 0 ? void 0 : sections.join("\n");
|
|
8968
9071
|
} catch (error) {
|
|
8969
9072
|
logger.warn(`prompt section failed \u2014 ${error instanceof Error ? error.message : String(error)}`);
|
|
8970
9073
|
}
|
|
@@ -9144,6 +9247,41 @@ function createEvolveService(options) {
|
|
|
9144
9247
|
return signal === void 0 ? `[${id}] (signal no longer recorded)` : `[${id}] ${signal.tool} x${signal.count} \u2014 ${signal.error} (verified)`;
|
|
9145
9248
|
}).join("\n");
|
|
9146
9249
|
}
|
|
9250
|
+
if (arg === "trends" || arg.startsWith("trends ")) {
|
|
9251
|
+
const requested = Number.parseInt(arg.slice(6).trim(), 10);
|
|
9252
|
+
const count = Number.isNaN(requested) ? 5 : Math.min(Math.max(requested, 1), 50);
|
|
9253
|
+
const reflections = await store.reflections(count);
|
|
9254
|
+
if (reflections.length === 0) return "no reflections recorded yet \u2014 trends appear after runs end";
|
|
9255
|
+
const sign = (value) => value > 0 ? `+${value}` : String(value);
|
|
9256
|
+
const lines = [`evolve trends (last ${reflections.length} run(s), newest first)`];
|
|
9257
|
+
for (const reflection of reflections) {
|
|
9258
|
+
lines.push(`${reflection.at.replace("T", " ").slice(0, 19)} ${reflection.reason}: model calls ${reflection.iterations}, tool calls ${reflection.toolCalls} (${reflection.toolErrors} failed), failures ${reflection.totalFailures} (delta ${sign(reflection.signalDelta)})`);
|
|
9259
|
+
const moved = Object.entries(reflection.perTool ?? {}).filter(([, trend]) => trend.delta !== 0);
|
|
9260
|
+
for (const [tool, trend] of moved) {
|
|
9261
|
+
lines.push(` - ${tool}: ${trend.failures} failure(s) this run (${sign(trend.delta)} vs previous)`);
|
|
9262
|
+
}
|
|
9263
|
+
}
|
|
9264
|
+
return lines.join("\n");
|
|
9265
|
+
}
|
|
9266
|
+
if (arg === "rule" || arg === "rule list") {
|
|
9267
|
+
const rules = await store.listRules();
|
|
9268
|
+
if (rules.length === 0) return "no guardrail rules yet \u2014 add one with /evolve rule add <text>";
|
|
9269
|
+
return rules.map((rule) => `[${rule.id}] ${rule.text}`).join("\n");
|
|
9270
|
+
}
|
|
9271
|
+
if (arg.startsWith("rule add ")) {
|
|
9272
|
+
const text = arg.slice(9).trim();
|
|
9273
|
+
if (text === "") return "usage: /evolve rule add <text>";
|
|
9274
|
+
const { added, rule } = await store.addRule({ text });
|
|
9275
|
+
await refreshPromptCache();
|
|
9276
|
+
return added ? `added guardrail [${rule.id}]: ${rule.text}` : `guardrail already exists [${rule.id}]: ${rule.text}`;
|
|
9277
|
+
}
|
|
9278
|
+
if (arg.startsWith("rule remove ")) {
|
|
9279
|
+
const id = arg.slice(12).trim();
|
|
9280
|
+
if (id === "") return "usage: /evolve rule remove <id>";
|
|
9281
|
+
const { removed } = await store.removeRule(id);
|
|
9282
|
+
await refreshPromptCache();
|
|
9283
|
+
return removed ? `removed guardrail ${id}` : `no guardrail with id "${id}"`;
|
|
9284
|
+
}
|
|
9147
9285
|
if (arg.startsWith("improve ")) {
|
|
9148
9286
|
const suggestionId = arg.slice(8).trim();
|
|
9149
9287
|
const suggestions = await openWithTrends(100);
|
|
@@ -9215,18 +9353,31 @@ ${result.stderr.slice(-4e3)}` : ""}`;
|
|
|
9215
9353
|
toolDefinition() {
|
|
9216
9354
|
const inputSchema = z17.object({
|
|
9217
9355
|
suggestionId: z17.string().min(1).describe("Signal id from the evolve suggestions"),
|
|
9218
|
-
implementation: z17.string().min(1).describe("Concise description of the
|
|
9356
|
+
implementation: z17.string().min(1).describe("Concise description of the fix to implement (plugin plan, or the guardrail rule text when kind is prompt_rule)"),
|
|
9357
|
+
kind: z17.enum(["plugin", "prompt_rule"]).optional().describe(
|
|
9358
|
+
"plugin (default): scaffold a fix plugin; prompt_rule: store a guardrail rule that is injected into future system prompts"
|
|
9359
|
+
)
|
|
9219
9360
|
});
|
|
9220
9361
|
return {
|
|
9221
9362
|
name: "evolve_improve",
|
|
9222
|
-
description: "Implement a fix for one repeated tool failure
|
|
9363
|
+
description: "Implement a fix for one repeated tool failure. Default kind=plugin scaffolds the fix-<tool>/ plugin dir and writes PLAN.md with instructions for implementing, verifying, reloading, and testing it. kind=prompt_rule instead stores a concise guardrail rule (from `implementation`) that is injected into future system prompts and closes the suggestion. Use when the model proposes a concrete fix for a suggestion in the system prompt.",
|
|
9223
9364
|
inputSchema,
|
|
9224
9365
|
paths: () => [],
|
|
9225
9366
|
execute: async (input) => {
|
|
9226
|
-
const { suggestionId, implementation } = input;
|
|
9367
|
+
const { suggestionId, implementation, kind } = input;
|
|
9227
9368
|
const suggestions = await openWithTrends(100);
|
|
9228
9369
|
const suggestion = suggestions.find((item) => item.id === suggestionId);
|
|
9229
9370
|
if (suggestion === void 0) throw new Error(`No open suggestion with id "${suggestionId}".`);
|
|
9371
|
+
if (kind === "prompt_rule") {
|
|
9372
|
+
const { added, rule } = await store.addRule({ text: implementation, sourceId: suggestionId });
|
|
9373
|
+
await store.markSuggestionDone(suggestionId);
|
|
9374
|
+
await refreshPromptCache();
|
|
9375
|
+
return [
|
|
9376
|
+
added ? `Stored guardrail rule [${rule.id}]: ${rule.text}` : `Guardrail already exists [${rule.id}]: ${rule.text}`,
|
|
9377
|
+
`Suggestion [${suggestion.id}] marked done. The rule is injected into the system prompt of future runs.`,
|
|
9378
|
+
"Review rules with /evolve rule list; remove one with /evolve rule remove <id>."
|
|
9379
|
+
].join("\n");
|
|
9380
|
+
}
|
|
9230
9381
|
const name = sanitizePluginName(suggestion.tool);
|
|
9231
9382
|
const dir = await scaffoldFixPlugin(workspace, name);
|
|
9232
9383
|
await writeFile7(join10(dir, "PLAN.md"), buildPlan(suggestion, name, implementation), "utf8");
|
|
@@ -11060,7 +11211,7 @@ import { readFile as readFile12 } from "fs/promises";
|
|
|
11060
11211
|
import { join as join17 } from "path";
|
|
11061
11212
|
|
|
11062
11213
|
// src/tools/shell.ts
|
|
11063
|
-
import { spawn as spawn3 } from "child_process";
|
|
11214
|
+
import { spawn as spawn3, spawnSync } from "child_process";
|
|
11064
11215
|
import { isAbsolute as isAbsolute8, relative as relative11, resolve as resolve13, sep as sep10 } from "path";
|
|
11065
11216
|
import { z as z21 } from "zod";
|
|
11066
11217
|
|
|
@@ -11190,6 +11341,29 @@ function tokenizeCommandLine(command) {
|
|
|
11190
11341
|
function unquoteToken(token) {
|
|
11191
11342
|
return token.length >= 2 && token.startsWith('"') && token.endsWith('"') ? token.slice(1, -1) : token;
|
|
11192
11343
|
}
|
|
11344
|
+
var cachedWindowsShell;
|
|
11345
|
+
function hasExecutable(name) {
|
|
11346
|
+
try {
|
|
11347
|
+
return spawnSync("where", [name], { stdio: "ignore", windowsHide: true }).status === 0;
|
|
11348
|
+
} catch {
|
|
11349
|
+
return false;
|
|
11350
|
+
}
|
|
11351
|
+
}
|
|
11352
|
+
function detectWindowsShell() {
|
|
11353
|
+
if (cachedWindowsShell !== void 0) return cachedWindowsShell;
|
|
11354
|
+
cachedWindowsShell = hasExecutable("pwsh") ? "pwsh" : hasExecutable("powershell") ? "powershell" : "cmd";
|
|
11355
|
+
return cachedWindowsShell;
|
|
11356
|
+
}
|
|
11357
|
+
function psQuote(token) {
|
|
11358
|
+
return `'${token.replace(/'/g, "''")}'`;
|
|
11359
|
+
}
|
|
11360
|
+
function buildWindowsCommandLine(kind, commandLine, command, args) {
|
|
11361
|
+
if (kind === "cmd") return `chcp 65001>nul & ${commandLine}`;
|
|
11362
|
+
const executable = kind === "pwsh" ? "pwsh" : "powershell";
|
|
11363
|
+
const script = `& ${psQuote(command)}${args.length > 0 ? ` ${args.map(psQuote).join(" ")}` : ""}; exit $LASTEXITCODE`;
|
|
11364
|
+
const encoded = Buffer.from(script, "utf16le").toString("base64");
|
|
11365
|
+
return `chcp 65001>nul & ${executable} -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${encoded}`;
|
|
11366
|
+
}
|
|
11193
11367
|
function createShellTool(workspace, options = {}) {
|
|
11194
11368
|
const root = resolve13(workspace);
|
|
11195
11369
|
const maxBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES2;
|
|
@@ -11310,7 +11484,7 @@ async function executeShell(root, input, cancellation, maxBytes, onOutput) {
|
|
|
11310
11484
|
const quoteArg = (s) => s.includes(" ") ? `"${s.replace(/"/g, '""')}"` : s;
|
|
11311
11485
|
const quoted = input.args.map(quoteArg).join(" ");
|
|
11312
11486
|
const commandLine = quoted.length > 0 ? `${quoteArg(input.command)} ${quoted}` : quoteArg(input.command);
|
|
11313
|
-
const shellCommandLine = process.platform === "win32" ?
|
|
11487
|
+
const shellCommandLine = process.platform === "win32" ? buildWindowsCommandLine(detectWindowsShell(), commandLine, input.command, input.args) : commandLine;
|
|
11314
11488
|
const child = spawn3(shellCommandLine, {
|
|
11315
11489
|
cwd,
|
|
11316
11490
|
shell: true,
|
|
@@ -12940,6 +13114,11 @@ function escapeHtml(text) {
|
|
|
12940
13114
|
|
|
12941
13115
|
// src/auth/store.ts
|
|
12942
13116
|
import { dirname as dirname13 } from "path";
|
|
13117
|
+
async function retainOnlyCredentials(store, keepCredentialId) {
|
|
13118
|
+
const tokens2 = await store.load();
|
|
13119
|
+
const retained = Object.fromEntries(Object.entries(tokens2).filter(([id]) => id === keepCredentialId));
|
|
13120
|
+
await store.save(retained);
|
|
13121
|
+
}
|
|
12943
13122
|
function createFileTokenStore(filePath) {
|
|
12944
13123
|
let baseline = {};
|
|
12945
13124
|
const store = {
|
|
@@ -13100,11 +13279,11 @@ Treat the assigned task as self-contained. The caller may not share its full con
|
|
|
13100
13279
|
Own the user's request end to end. Collaborate when a choice materially changes the result, but use sound judgment for ordinary in-scope implementation details. Keep the user informed at meaningful milestones, synthesize any child-agent results yourself, and do not stop while safe, relevant work remains. A forked child receives an explicit Subagent directive after the inherited conversation; in that case, follow that narrower directive for the child assignment.`;
|
|
13101
13280
|
}
|
|
13102
13281
|
function environmentSection(options) {
|
|
13103
|
-
const
|
|
13282
|
+
const git3 = options.environment.isGitRepository === "unknown" ? "unknown" : options.environment.isGitRepository ? "yes" : "no";
|
|
13104
13283
|
return `# Environment
|
|
13105
13284
|
|
|
13106
13285
|
- Working directory: ${data(options.workspace)}
|
|
13107
|
-
- Git repository: ${
|
|
13286
|
+
- Git repository: ${git3}
|
|
13108
13287
|
- Platform: ${data(options.environment.platform)}
|
|
13109
13288
|
- OS version: ${data(options.environment.osVersion)}
|
|
13110
13289
|
- Shell: ${data(options.environment.shell)}`;
|
|
@@ -17559,19 +17738,255 @@ function severityLabel(severity) {
|
|
|
17559
17738
|
}
|
|
17560
17739
|
}
|
|
17561
17740
|
|
|
17562
|
-
// src/
|
|
17741
|
+
// src/git/service.ts
|
|
17742
|
+
async function git2(workspace, args, timeoutMs = 3e4) {
|
|
17743
|
+
const result = await execFileNoThrow("git", ["-C", workspace, ...args], { timeout: timeoutMs, useCwd: false });
|
|
17744
|
+
return { ok: result.code === 0, stdout: result.stdout, stderr: result.stderr, code: result.code };
|
|
17745
|
+
}
|
|
17746
|
+
async function isGitRepository(workspace) {
|
|
17747
|
+
const result = await git2(workspace, ["rev-parse", "--is-inside-work-tree"], 2e3);
|
|
17748
|
+
return result.ok && result.stdout.trim() === "true";
|
|
17749
|
+
}
|
|
17750
|
+
function gitFailure(result, action) {
|
|
17751
|
+
const detail = result.stderr.trim() || result.stdout.trim() || `exit code ${result.code}`;
|
|
17752
|
+
return new Error(`git ${action} failed: ${detail.split("\n")[0]}`);
|
|
17753
|
+
}
|
|
17754
|
+
async function changeSummary(workspace) {
|
|
17755
|
+
const branch = await git2(workspace, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
17756
|
+
const head = await git2(workspace, ["rev-parse", "--short", "HEAD"]);
|
|
17757
|
+
const status = await git2(workspace, ["status", "--porcelain"]);
|
|
17758
|
+
if (!status.ok) throw gitFailure(status, "status");
|
|
17759
|
+
const statusLines = status.stdout.split("\n").map((line) => line.trimEnd()).filter((line) => line.length > 0);
|
|
17760
|
+
const stagedFiles = [];
|
|
17761
|
+
const unstagedFiles = [];
|
|
17762
|
+
const untrackedFiles = [];
|
|
17763
|
+
for (const line of statusLines) {
|
|
17764
|
+
const index = line[0] ?? " ";
|
|
17765
|
+
const worktree = line[1] ?? " ";
|
|
17766
|
+
const file = line.slice(3);
|
|
17767
|
+
if (index === "?" && worktree === "?") {
|
|
17768
|
+
untrackedFiles.push(file);
|
|
17769
|
+
continue;
|
|
17770
|
+
}
|
|
17771
|
+
if (index !== " " && index !== "?") stagedFiles.push(file);
|
|
17772
|
+
if (worktree !== " " && worktree !== "?") unstagedFiles.push(file);
|
|
17773
|
+
}
|
|
17774
|
+
return {
|
|
17775
|
+
branch: branch.ok ? branch.stdout.trim() : "HEAD",
|
|
17776
|
+
head: head.ok ? head.stdout.trim() : "unknown",
|
|
17777
|
+
statusLines,
|
|
17778
|
+
stagedFiles: [...new Set(stagedFiles)],
|
|
17779
|
+
unstagedFiles: [...new Set(unstagedFiles)],
|
|
17780
|
+
untrackedFiles
|
|
17781
|
+
};
|
|
17782
|
+
}
|
|
17783
|
+
async function stagedDiff(workspace, maxChars = 96e3) {
|
|
17784
|
+
const stat16 = await git2(workspace, ["diff", "--staged", "--stat"]);
|
|
17785
|
+
const diff = await git2(workspace, ["diff", "--staged", "--no-ext-diff", "--no-color"]);
|
|
17786
|
+
if (!diff.ok) throw gitFailure(diff, "diff --staged");
|
|
17787
|
+
const text = diff.stdout;
|
|
17788
|
+
return {
|
|
17789
|
+
diff: text.length > maxChars ? `${text.slice(0, maxChars)}
|
|
17790
|
+
\u2026[diff truncated]` : text,
|
|
17791
|
+
stat: stat16.stdout.trim(),
|
|
17792
|
+
truncated: text.length > maxChars
|
|
17793
|
+
};
|
|
17794
|
+
}
|
|
17795
|
+
async function uncommittedDiff(workspace, maxChars = 96e3) {
|
|
17796
|
+
const stat16 = await git2(workspace, ["diff", "HEAD", "--stat"]);
|
|
17797
|
+
const diff = await git2(workspace, ["diff", "HEAD", "--no-ext-diff", "--no-color"]);
|
|
17798
|
+
if (!diff.ok && !diff.stderr.includes("unknown revision")) throw gitFailure(diff, "diff HEAD");
|
|
17799
|
+
const summary2 = await changeSummary(workspace);
|
|
17800
|
+
const text = diff.stdout;
|
|
17801
|
+
return {
|
|
17802
|
+
diff: text.length > maxChars ? `${text.slice(0, maxChars)}
|
|
17803
|
+
\u2026[diff truncated]` : text,
|
|
17804
|
+
stat: stat16.stdout.trim(),
|
|
17805
|
+
untracked: summary2.untrackedFiles
|
|
17806
|
+
};
|
|
17807
|
+
}
|
|
17808
|
+
async function stageAll(workspace) {
|
|
17809
|
+
const result = await git2(workspace, ["add", "-A"]);
|
|
17810
|
+
if (!result.ok) throw gitFailure(result, "add");
|
|
17811
|
+
}
|
|
17812
|
+
async function commit(workspace, commitMessage) {
|
|
17813
|
+
const result = await execFileNoThrow("git", ["-C", workspace, "commit", "-F", "-"], {
|
|
17814
|
+
timeout: 3e4,
|
|
17815
|
+
useCwd: false,
|
|
17816
|
+
input: commitMessage
|
|
17817
|
+
});
|
|
17818
|
+
if (result.code !== 0) {
|
|
17819
|
+
const detail = result.stderr.trim() || result.stdout.trim() || `exit code ${result.code}`;
|
|
17820
|
+
throw new Error(`git commit failed: ${detail.split("\n")[0]}`);
|
|
17821
|
+
}
|
|
17822
|
+
const head = await git2(workspace, ["log", "-1", "--pretty=%h %s"]);
|
|
17823
|
+
return head.stdout.trim() || "committed";
|
|
17824
|
+
}
|
|
17825
|
+
async function fileHistory(workspace, path, limit) {
|
|
17826
|
+
const args = [
|
|
17827
|
+
"log",
|
|
17828
|
+
`--max-count=${limit}`,
|
|
17829
|
+
"--date=short",
|
|
17830
|
+
"--pretty=format:%h%x1f%ad%x1f%an%x1f%s",
|
|
17831
|
+
...path === void 0 ? [] : ["--follow", "--", path]
|
|
17832
|
+
];
|
|
17833
|
+
const result = await git2(workspace, args, 15e3);
|
|
17834
|
+
if (!result.ok) throw gitFailure(result, "log");
|
|
17835
|
+
return result.stdout.split("\n").filter((line) => line.trim().length > 0).map((line) => {
|
|
17836
|
+
const [hash = "", date = "", author = "", ...subject] = line.split("");
|
|
17837
|
+
return { hash, date, author, subject: subject.join("") };
|
|
17838
|
+
});
|
|
17839
|
+
}
|
|
17840
|
+
async function gitMarker(workspace) {
|
|
17841
|
+
try {
|
|
17842
|
+
if (!await isGitRepository(workspace)) return void 0;
|
|
17843
|
+
const summary2 = await changeSummary(workspace);
|
|
17844
|
+
if (summary2.head === "unknown") return void 0;
|
|
17845
|
+
const dirty = summary2.statusLines.length > 0 ? "-dirty" : "";
|
|
17846
|
+
return `${summary2.branch}@${summary2.head}${dirty}`;
|
|
17847
|
+
} catch {
|
|
17848
|
+
return void 0;
|
|
17849
|
+
}
|
|
17850
|
+
}
|
|
17851
|
+
|
|
17852
|
+
// src/git/insights.ts
|
|
17563
17853
|
import { z as z30 } from "zod";
|
|
17564
|
-
|
|
17565
|
-
|
|
17566
|
-
|
|
17854
|
+
async function suggestCommitMessage(options, input, signal) {
|
|
17855
|
+
const prompt = [
|
|
17856
|
+
"Write a git commit message for the staged changes below.",
|
|
17857
|
+
"Rules: Conventional Commits style (feat/fix/refactor/docs/test/chore scope); a short imperative subject line <= 72 chars; an optional body only when the change needs explanation; no code fences; reply with the commit message only.",
|
|
17858
|
+
...input.hint === void 0 || input.hint.trim() === "" ? [] : [`The user added this context: ${input.hint.trim()}`],
|
|
17859
|
+
"",
|
|
17860
|
+
`Change summary:
|
|
17861
|
+
${input.stat}`,
|
|
17862
|
+
"",
|
|
17863
|
+
`Diff:
|
|
17864
|
+
${input.diff}`
|
|
17865
|
+
].join("\n");
|
|
17866
|
+
const { adapter, model } = options.registry.get(options.modelId());
|
|
17867
|
+
let text = "";
|
|
17868
|
+
for await (const event of adapter.stream({
|
|
17869
|
+
model,
|
|
17870
|
+
messages: [{ role: "user", content: prompt }],
|
|
17871
|
+
tools: [],
|
|
17872
|
+
signal
|
|
17873
|
+
})) {
|
|
17874
|
+
if (event.type === "text") text += event.text;
|
|
17875
|
+
else if (event.type === "error") throw new Error(`commit message generation failed: ${event.error.message}`);
|
|
17876
|
+
else if (event.type === "done") break;
|
|
17877
|
+
}
|
|
17878
|
+
const cleaned = cleanCommitMessage(text);
|
|
17879
|
+
if (cleaned === "") throw new Error("commit message generation returned no text");
|
|
17880
|
+
return cleaned;
|
|
17881
|
+
}
|
|
17882
|
+
function cleanCommitMessage(raw) {
|
|
17883
|
+
const trimmed = raw.trim().replace(/^```[a-z]*\s*/iu, "").replace(/```$/u, "").trim();
|
|
17884
|
+
const lines = trimmed.split("\n");
|
|
17885
|
+
const kept = [];
|
|
17886
|
+
for (const line of lines) {
|
|
17887
|
+
if (/^(here('|’)s|notes?:|explanation:)/iu.test(line.trim()) && kept.length > 0) break;
|
|
17888
|
+
kept.push(line);
|
|
17889
|
+
}
|
|
17890
|
+
return kept.join("\n").trim().slice(0, 2e3);
|
|
17891
|
+
}
|
|
17892
|
+
var ReviewFindingSchema = z30.object({
|
|
17893
|
+
severity: z30.enum(["critical", "warning", "nit"]),
|
|
17894
|
+
file: z30.string(),
|
|
17895
|
+
line: z30.string().describe('Line number or hunk header the finding refers to, e.g. "42" or "@@ -10,4 +10,6 @@"'),
|
|
17896
|
+
issue: z30.string(),
|
|
17897
|
+
suggestion: z30.string()
|
|
17898
|
+
}).strict();
|
|
17899
|
+
var ReviewReportSchema = z30.object({
|
|
17900
|
+
summary: z30.string().describe("One-paragraph overall assessment of the change"),
|
|
17901
|
+
verdict: z30.enum(["ship", "ship-with-fixes", "needs-work"]),
|
|
17902
|
+
findings: z30.array(ReviewFindingSchema).max(20)
|
|
17903
|
+
}).strict();
|
|
17904
|
+
async function reviewDiff(options, input, signal) {
|
|
17905
|
+
const prompt = [
|
|
17906
|
+
"You are reviewing uncommitted local changes before the user commits them.",
|
|
17907
|
+
"Focus on: correctness bugs, broken error handling, security issues (secrets, injection, path traversal), missing edge cases, and obvious test gaps.",
|
|
17908
|
+
"Do not comment on formatting or style unless it hides a bug. Report at most the 10 most important findings.",
|
|
17909
|
+
...input.focus === void 0 || input.focus.trim() === "" ? [] : [`The user specifically wants attention on: ${input.focus.trim()}`],
|
|
17910
|
+
...input.untracked.length === 0 ? [] : [`Untracked files not shown in the diff: ${input.untracked.join(", ")}`],
|
|
17911
|
+
"",
|
|
17912
|
+
`Change summary:
|
|
17913
|
+
${input.stat}`,
|
|
17914
|
+
"",
|
|
17915
|
+
`Diff:
|
|
17916
|
+
${input.diff}`
|
|
17917
|
+
].join("\n");
|
|
17918
|
+
const structured = withStructuredOutput({
|
|
17919
|
+
registry: options.registry,
|
|
17920
|
+
modelId: options.modelId(),
|
|
17921
|
+
name: "report_review",
|
|
17922
|
+
description: "Structured review report for uncommitted changes",
|
|
17923
|
+
schema: ReviewReportSchema
|
|
17924
|
+
});
|
|
17925
|
+
const { value } = await structured.invoke({
|
|
17926
|
+
messages: [{ role: "user", content: prompt }],
|
|
17927
|
+
signal
|
|
17928
|
+
});
|
|
17929
|
+
return value;
|
|
17930
|
+
}
|
|
17931
|
+
function formatReviewReport(report) {
|
|
17932
|
+
const lines = [`Review verdict: ${report.verdict}`, "", report.summary.trim()];
|
|
17933
|
+
if (report.findings.length > 0) {
|
|
17934
|
+
lines.push("", "Findings:");
|
|
17935
|
+
for (const finding of report.findings) {
|
|
17936
|
+
lines.push(`- [${finding.severity}] ${finding.file}${finding.line === "" ? "" : `:${finding.line}`} \u2014 ${finding.issue}`);
|
|
17937
|
+
if (finding.suggestion.trim() !== "") lines.push(` fix: ${finding.suggestion}`);
|
|
17938
|
+
}
|
|
17939
|
+
} else {
|
|
17940
|
+
lines.push("", "No issues found.");
|
|
17941
|
+
}
|
|
17942
|
+
return lines.join("\n");
|
|
17943
|
+
}
|
|
17944
|
+
|
|
17945
|
+
// src/git/tools.ts
|
|
17946
|
+
import { z as z31 } from "zod";
|
|
17947
|
+
var GitHistoryInput = z31.object({
|
|
17948
|
+
path: z31.string().describe("File to inspect; omit for the whole repository history").optional(),
|
|
17949
|
+
limit: z31.number().int().min(1).max(50).describe("Maximum number of commits to return (default 20)").optional()
|
|
17950
|
+
});
|
|
17951
|
+
function createGitHistoryTool(workspace) {
|
|
17952
|
+
return {
|
|
17953
|
+
name: "GitHistory",
|
|
17954
|
+
description: "Show git commit history for the repository or for one file (follows renames). Use to understand when and why code changed.",
|
|
17955
|
+
inputSchema: GitHistoryInput,
|
|
17956
|
+
readOnly: true,
|
|
17957
|
+
paths: (input) => input.path === void 0 ? [] : [input.path],
|
|
17958
|
+
summarize: (input) => input.path ?? "repository",
|
|
17959
|
+
renderForModel: (output) => output,
|
|
17960
|
+
async execute(input, signal) {
|
|
17961
|
+
signal.throwIfAborted();
|
|
17962
|
+
if (!await isGitRepository(workspace)) throw new Error("Not a git repository");
|
|
17963
|
+
const limit = input.limit ?? 20;
|
|
17964
|
+
const entries = await fileHistory(workspace, input.path, limit);
|
|
17965
|
+
if (entries.length === 0) {
|
|
17966
|
+
return input.path === void 0 ? "No commits found." : `No commits found for ${input.path} (the file may be untracked).`;
|
|
17967
|
+
}
|
|
17968
|
+
const scope2 = input.path === void 0 ? "repository" : input.path;
|
|
17969
|
+
return [
|
|
17970
|
+
`git history for ${scope2} (${entries.length} commits):`,
|
|
17971
|
+
...entries.map((entry2) => `${entry2.hash} ${entry2.date} ${entry2.author}: ${entry2.subject}`)
|
|
17972
|
+
].join("\n");
|
|
17973
|
+
}
|
|
17974
|
+
};
|
|
17975
|
+
}
|
|
17976
|
+
|
|
17977
|
+
// src/tools/ask-user-question.ts
|
|
17978
|
+
import { z as z32 } from "zod";
|
|
17979
|
+
var QuestionOptionSchema = z32.object({
|
|
17980
|
+
label: z32.string().trim().min(1),
|
|
17981
|
+
description: z32.string().trim().min(1)
|
|
17567
17982
|
});
|
|
17568
|
-
var QuestionSchema =
|
|
17569
|
-
question:
|
|
17570
|
-
header:
|
|
17571
|
-
options:
|
|
17983
|
+
var QuestionSchema = z32.object({
|
|
17984
|
+
question: z32.string().trim().min(1),
|
|
17985
|
+
header: z32.string().trim().min(1),
|
|
17986
|
+
options: z32.array(QuestionOptionSchema).min(1).max(4)
|
|
17572
17987
|
});
|
|
17573
|
-
var AskUserQuestionInput =
|
|
17574
|
-
questions:
|
|
17988
|
+
var AskUserQuestionInput = z32.object({
|
|
17989
|
+
questions: z32.array(QuestionSchema).min(1).max(4)
|
|
17575
17990
|
});
|
|
17576
17991
|
function hookAnswersFromUpdatedInput(updatedInput, questions) {
|
|
17577
17992
|
if (typeof updatedInput !== "object" || updatedInput === null) return void 0;
|
|
@@ -17655,20 +18070,20 @@ function createAskUserQuestionTool(handler) {
|
|
|
17655
18070
|
}
|
|
17656
18071
|
|
|
17657
18072
|
// src/tools/todo-write.ts
|
|
17658
|
-
import { z as
|
|
17659
|
-
var TodoStatusSchema =
|
|
18073
|
+
import { z as z33 } from "zod";
|
|
18074
|
+
var TodoStatusSchema = z33.enum([
|
|
17660
18075
|
"pending",
|
|
17661
18076
|
"in_progress",
|
|
17662
18077
|
"completed",
|
|
17663
18078
|
"cancelled"
|
|
17664
18079
|
]);
|
|
17665
|
-
var TodoItemSchema =
|
|
17666
|
-
content:
|
|
18080
|
+
var TodoItemSchema = z33.object({
|
|
18081
|
+
content: z33.string().trim().min(1),
|
|
17667
18082
|
status: TodoStatusSchema,
|
|
17668
|
-
activeForm:
|
|
18083
|
+
activeForm: z33.string().trim().min(1)
|
|
17669
18084
|
});
|
|
17670
|
-
var TodoWriteInput =
|
|
17671
|
-
todos:
|
|
18085
|
+
var TodoWriteInput = z33.object({
|
|
18086
|
+
todos: z33.array(TodoItemSchema).min(1).max(50)
|
|
17672
18087
|
});
|
|
17673
18088
|
function createTodoWriteTool() {
|
|
17674
18089
|
return {
|
|
@@ -17705,36 +18120,36 @@ function createTodoWriteTool() {
|
|
|
17705
18120
|
import { randomUUID as randomUUID14 } from "crypto";
|
|
17706
18121
|
import { link, lstat as lstat11, mkdir as mkdir20, readFile as readFile20, readdir as readdir10, unlink as unlink2, writeFile as writeFile12 } from "fs/promises";
|
|
17707
18122
|
import { dirname as dirname20, join as join24, resolve as resolve24 } from "path";
|
|
17708
|
-
import { z as
|
|
18123
|
+
import { z as z34 } from "zod";
|
|
17709
18124
|
var MANAGED_TOOL_VERSION = 1;
|
|
17710
18125
|
var MAX_RECORD_BYTES = 256 * 1024;
|
|
17711
18126
|
var TOOL_NAME = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
|
|
17712
|
-
var JsonSchemaObject =
|
|
18127
|
+
var JsonSchemaObject = z34.record(z34.string(), z34.unknown()).superRefine((schema, context) => {
|
|
17713
18128
|
if (schema.type !== "object") {
|
|
17714
18129
|
context.addIssue({ code: "custom", message: "Tool input JSON Schema must have type object" });
|
|
17715
18130
|
}
|
|
17716
18131
|
});
|
|
17717
|
-
var RegisterManagedToolInputSchema =
|
|
17718
|
-
name:
|
|
17719
|
-
description:
|
|
18132
|
+
var RegisterManagedToolInputSchema = z34.object({
|
|
18133
|
+
name: z34.string().regex(TOOL_NAME).describe("Unique callable tool name using letters, digits, and underscores"),
|
|
18134
|
+
description: z34.string().min(1).max(4096).describe("Purpose and appropriate use of the generated tool"),
|
|
17720
18135
|
inputSchema: JsonSchemaObject.describe("Provider-facing JSON Schema with an object at the root"),
|
|
17721
|
-
implementation:
|
|
18136
|
+
implementation: z34.string().min(1).max(64 * 1024).describe(
|
|
17722
18137
|
"Async JavaScript function body, or complete function/arrow expression, receiving input, signal, and context; return the tool result"
|
|
17723
18138
|
),
|
|
17724
|
-
scope:
|
|
18139
|
+
scope: z34.enum(["project", "global"]).default("project").describe(
|
|
17725
18140
|
"Project persists in the current workspace; global persists for every workspace"
|
|
17726
18141
|
),
|
|
17727
|
-
agents:
|
|
18142
|
+
agents: z34.array(z34.enum(["main", "subagent"])).min(1).max(2).optional().describe(
|
|
17728
18143
|
"Agent roles allowed to call the generated tool; omit to allow both"
|
|
17729
18144
|
)
|
|
17730
18145
|
}).strict();
|
|
17731
|
-
var RemoveManagedToolInputSchema =
|
|
17732
|
-
name:
|
|
17733
|
-
scope:
|
|
18146
|
+
var RemoveManagedToolInputSchema = z34.object({
|
|
18147
|
+
name: z34.string().regex(TOOL_NAME).describe("Managed tool name to remove"),
|
|
18148
|
+
scope: z34.enum(["project", "global"]).optional().describe("Required only when the same name exists in both scopes")
|
|
17734
18149
|
}).strict();
|
|
17735
18150
|
var ManagedToolRecordSchema = RegisterManagedToolInputSchema.extend({
|
|
17736
|
-
version:
|
|
17737
|
-
createdAt:
|
|
18151
|
+
version: z34.literal(MANAGED_TOOL_VERSION),
|
|
18152
|
+
createdAt: z34.string().datetime()
|
|
17738
18153
|
}).strict();
|
|
17739
18154
|
var AsyncFunction = Object.getPrototypeOf(async function() {
|
|
17740
18155
|
}).constructor;
|
|
@@ -17921,7 +18336,7 @@ function createManagedToolManagementTools(options) {
|
|
|
17921
18336
|
const listTools = {
|
|
17922
18337
|
name: "ListRegisteredTools",
|
|
17923
18338
|
description: "List durable tools created through RegisterTool, including scope, path, and active precedence",
|
|
17924
|
-
inputSchema:
|
|
18339
|
+
inputSchema: z34.object({}).strict(),
|
|
17925
18340
|
agents: mainOnly,
|
|
17926
18341
|
paths: () => [],
|
|
17927
18342
|
execute: async (_input, signal) => {
|
|
@@ -17934,7 +18349,7 @@ function createManagedToolManagementTools(options) {
|
|
|
17934
18349
|
function compileDefinition(record3, scope2, workspace) {
|
|
17935
18350
|
let inputSchema;
|
|
17936
18351
|
try {
|
|
17937
|
-
inputSchema =
|
|
18352
|
+
inputSchema = z34.fromJSONSchema(record3.inputSchema);
|
|
17938
18353
|
} catch (error) {
|
|
17939
18354
|
throw new Error(`Invalid input schema for managed tool "${record3.name}": ${message(error)}`);
|
|
17940
18355
|
}
|
|
@@ -18034,7 +18449,7 @@ function isMissing4(error) {
|
|
|
18034
18449
|
}
|
|
18035
18450
|
|
|
18036
18451
|
// src/pals/protocol.ts
|
|
18037
|
-
import { z as
|
|
18452
|
+
import { z as z35 } from "zod";
|
|
18038
18453
|
var PROTOCOL_VERSION = 1;
|
|
18039
18454
|
var MAX_ALIAS_LENGTH = 64;
|
|
18040
18455
|
var MAX_MESSAGE_BYTES = 32 * 1024;
|
|
@@ -18051,65 +18466,65 @@ var MIN_UUID_PREFIX_LENGTH = 8;
|
|
|
18051
18466
|
function normalizePalIdentity(value) {
|
|
18052
18467
|
return value.trim().toLocaleLowerCase("en-US");
|
|
18053
18468
|
}
|
|
18054
|
-
var VersionSchema =
|
|
18055
|
-
var UuidSchema =
|
|
18056
|
-
var PrintableIdentitySchema =
|
|
18469
|
+
var VersionSchema = z35.literal(PROTOCOL_VERSION);
|
|
18470
|
+
var UuidSchema = z35.uuid();
|
|
18471
|
+
var PrintableIdentitySchema = z35.string().trim().min(1).max(MAX_ALIAS_LENGTH).refine(
|
|
18057
18472
|
(value) => !/[\p{Cc}\uD800-\uDFFF]/u.test(value),
|
|
18058
18473
|
"Identity must contain only printable non-control Unicode"
|
|
18059
18474
|
);
|
|
18060
18475
|
var PalAliasSchema = PrintableIdentitySchema;
|
|
18061
18476
|
var PalTargetSchema = PrintableIdentitySchema;
|
|
18062
|
-
var BoundedTextSchema =
|
|
18477
|
+
var BoundedTextSchema = z35.string().refine(
|
|
18063
18478
|
(value) => Buffer.byteLength(value, "utf8") <= MAX_MESSAGE_BYTES,
|
|
18064
18479
|
`Text must not exceed ${MAX_MESSAGE_BYTES} UTF-8 bytes`
|
|
18065
18480
|
);
|
|
18066
18481
|
var NonEmptyBoundedTextSchema = BoundedTextSchema.refine((value) => value.length > 0, "Text must not be empty");
|
|
18067
|
-
var CompletionDetailSchema =
|
|
18482
|
+
var CompletionDetailSchema = z35.string().trim().min(1).refine(
|
|
18068
18483
|
(value) => Buffer.byteLength(value, "utf8") <= MAX_COMPLETION_DETAIL_BYTES,
|
|
18069
18484
|
`Completion evidence must not exceed ${MAX_COMPLETION_DETAIL_BYTES} UTF-8 bytes`
|
|
18070
18485
|
);
|
|
18071
|
-
var PalPresenceSchema =
|
|
18486
|
+
var PalPresenceSchema = z35.object({
|
|
18072
18487
|
version: VersionSchema,
|
|
18073
18488
|
id: UuidSchema,
|
|
18074
18489
|
alias: PalAliasSchema,
|
|
18075
|
-
projectPath:
|
|
18490
|
+
projectPath: z35.string().min(1).refine(
|
|
18076
18491
|
(value) => Buffer.byteLength(value, "utf8") <= MAX_PROJECT_PATH_BYTES,
|
|
18077
18492
|
`Project path must not exceed ${MAX_PROJECT_PATH_BYTES} UTF-8 bytes`
|
|
18078
18493
|
),
|
|
18079
|
-
connectedAt:
|
|
18080
|
-
lastSeenAt:
|
|
18494
|
+
connectedAt: z35.iso.datetime(),
|
|
18495
|
+
lastSeenAt: z35.iso.datetime()
|
|
18081
18496
|
}).strict();
|
|
18082
|
-
var PalPresenceListSchema =
|
|
18083
|
-
var PalTaskMessageSchema =
|
|
18497
|
+
var PalPresenceListSchema = z35.array(PalPresenceSchema).max(MAX_ACTIVE_PALS);
|
|
18498
|
+
var PalTaskMessageSchema = z35.object({
|
|
18084
18499
|
version: VersionSchema,
|
|
18085
|
-
type:
|
|
18500
|
+
type: z35.literal("task"),
|
|
18086
18501
|
messageId: UuidSchema,
|
|
18087
18502
|
target: PalTargetSchema,
|
|
18088
18503
|
goal: NonEmptyBoundedTextSchema
|
|
18089
18504
|
}).strict();
|
|
18090
|
-
var PalTaskEventSchema =
|
|
18505
|
+
var PalTaskEventSchema = z35.object({
|
|
18091
18506
|
version: VersionSchema,
|
|
18092
|
-
type:
|
|
18507
|
+
type: z35.literal("task-event"),
|
|
18093
18508
|
messageId: UuidSchema,
|
|
18094
18509
|
taskId: UuidSchema,
|
|
18095
18510
|
senderId: UuidSchema,
|
|
18096
18511
|
recipientId: UuidSchema,
|
|
18097
|
-
status:
|
|
18512
|
+
status: z35.enum(["accepted", "started", "progress", "completed", "failed", "cancelled"]),
|
|
18098
18513
|
detail: BoundedTextSchema.optional()
|
|
18099
18514
|
}).strict();
|
|
18100
|
-
var DeliveryReceiptSchema =
|
|
18515
|
+
var DeliveryReceiptSchema = z35.object({
|
|
18101
18516
|
version: VersionSchema,
|
|
18102
|
-
type:
|
|
18517
|
+
type: z35.literal("delivery-receipt"),
|
|
18103
18518
|
messageId: UuidSchema,
|
|
18104
|
-
status:
|
|
18105
|
-
recipientIds:
|
|
18519
|
+
status: z35.enum(["delivered", "duplicate", "rejected"]),
|
|
18520
|
+
recipientIds: z35.array(UuidSchema).max(MAX_PARTICIPANTS),
|
|
18106
18521
|
error: BoundedTextSchema.optional()
|
|
18107
18522
|
}).strict();
|
|
18108
|
-
var CoWorkParticipantSchema =
|
|
18523
|
+
var CoWorkParticipantSchema = z35.object({
|
|
18109
18524
|
palId: UuidSchema,
|
|
18110
|
-
required:
|
|
18525
|
+
required: z35.boolean()
|
|
18111
18526
|
}).strict();
|
|
18112
|
-
var CoWorkProposalParticipantsSchema =
|
|
18527
|
+
var CoWorkProposalParticipantsSchema = z35.array(CoWorkParticipantSchema).min(2).max(MAX_PARTICIPANTS).superRefine((participants, context) => {
|
|
18113
18528
|
const seen = /* @__PURE__ */ new Set();
|
|
18114
18529
|
for (const [index, participant] of participants.entries()) {
|
|
18115
18530
|
const id = participant.palId.toLowerCase();
|
|
@@ -18119,19 +18534,19 @@ var CoWorkProposalParticipantsSchema = z33.array(CoWorkParticipantSchema).min(2)
|
|
|
18119
18534
|
seen.add(id);
|
|
18120
18535
|
}
|
|
18121
18536
|
});
|
|
18122
|
-
var CoWorkPlanTaskSchema =
|
|
18123
|
-
id:
|
|
18537
|
+
var CoWorkPlanTaskSchema = z35.object({
|
|
18538
|
+
id: z35.string().min(1).max(128),
|
|
18124
18539
|
assigneeId: UuidSchema,
|
|
18125
18540
|
description: NonEmptyBoundedTextSchema,
|
|
18126
|
-
dependsOn:
|
|
18541
|
+
dependsOn: z35.array(z35.string().min(1).max(128)).max(MAX_PLAN_TASKS)
|
|
18127
18542
|
}).strict();
|
|
18128
|
-
var CoWorkPlanSchema =
|
|
18543
|
+
var CoWorkPlanSchema = z35.object({
|
|
18129
18544
|
version: VersionSchema,
|
|
18130
18545
|
coWorkId: UuidSchema,
|
|
18131
|
-
epoch:
|
|
18546
|
+
epoch: z35.number().int().positive(),
|
|
18132
18547
|
goal: NonEmptyBoundedTextSchema,
|
|
18133
|
-
participants:
|
|
18134
|
-
tasks:
|
|
18548
|
+
participants: z35.array(CoWorkParticipantSchema).min(1).max(MAX_PARTICIPANTS),
|
|
18549
|
+
tasks: z35.array(CoWorkPlanTaskSchema).min(1).max(MAX_PLAN_TASKS)
|
|
18135
18550
|
}).strict().superRefine((plan, context) => {
|
|
18136
18551
|
if (Buffer.byteLength(JSON.stringify(plan), "utf8") > MAX_PLAN_ENCODED_BYTES) {
|
|
18137
18552
|
context.addIssue({ code: "custom", message: `Encoded plan must not exceed ${MAX_PLAN_ENCODED_BYTES} UTF-8 bytes` });
|
|
@@ -18181,7 +18596,7 @@ var CoWorkPlanSchema = z33.object({
|
|
|
18181
18596
|
}
|
|
18182
18597
|
}
|
|
18183
18598
|
});
|
|
18184
|
-
var CoWorkPhaseSchema =
|
|
18599
|
+
var CoWorkPhaseSchema = z35.enum([
|
|
18185
18600
|
"proposed",
|
|
18186
18601
|
"planning",
|
|
18187
18602
|
"prepared",
|
|
@@ -18191,30 +18606,30 @@ var CoWorkPhaseSchema = z33.enum([
|
|
|
18191
18606
|
"failed",
|
|
18192
18607
|
"cancelled"
|
|
18193
18608
|
]);
|
|
18194
|
-
var IntegrationResultSchema =
|
|
18195
|
-
passed:
|
|
18609
|
+
var IntegrationResultSchema = z35.object({
|
|
18610
|
+
passed: z35.boolean(),
|
|
18196
18611
|
evidence: CompletionDetailSchema
|
|
18197
18612
|
}).strict();
|
|
18198
|
-
var CoWorkCompletionAssertionSchema =
|
|
18613
|
+
var CoWorkCompletionAssertionSchema = z35.object({
|
|
18199
18614
|
participantId: UuidSchema,
|
|
18200
|
-
passed:
|
|
18615
|
+
passed: z35.boolean(),
|
|
18201
18616
|
detail: CompletionDetailSchema.optional()
|
|
18202
18617
|
}).strict();
|
|
18203
|
-
var CoWorkSnapshotSchema =
|
|
18618
|
+
var CoWorkSnapshotSchema = z35.object({
|
|
18204
18619
|
version: VersionSchema,
|
|
18205
18620
|
coWorkId: UuidSchema,
|
|
18206
|
-
epoch:
|
|
18621
|
+
epoch: z35.number().int().positive(),
|
|
18207
18622
|
phase: CoWorkPhaseSchema,
|
|
18208
18623
|
goal: NonEmptyBoundedTextSchema,
|
|
18209
|
-
participants:
|
|
18624
|
+
participants: z35.array(CoWorkParticipantSchema).min(1).max(MAX_PARTICIPANTS),
|
|
18210
18625
|
integrationOwnerId: UuidSchema,
|
|
18211
|
-
acceptedParticipantIds:
|
|
18212
|
-
planHash:
|
|
18626
|
+
acceptedParticipantIds: z35.array(UuidSchema).max(MAX_PARTICIPANTS),
|
|
18627
|
+
planHash: z35.string().regex(/^[a-f0-9]{64}$/).nullable(),
|
|
18213
18628
|
plan: CoWorkPlanSchema.nullable(),
|
|
18214
|
-
planAcceptedParticipantIds:
|
|
18215
|
-
readyParticipantIds:
|
|
18216
|
-
completedParticipantIds:
|
|
18217
|
-
completionAssertions:
|
|
18629
|
+
planAcceptedParticipantIds: z35.array(UuidSchema).max(MAX_PARTICIPANTS),
|
|
18630
|
+
readyParticipantIds: z35.array(UuidSchema).max(MAX_PARTICIPANTS),
|
|
18631
|
+
completedParticipantIds: z35.array(UuidSchema).max(MAX_PARTICIPANTS),
|
|
18632
|
+
completionAssertions: z35.array(CoWorkCompletionAssertionSchema).max(MAX_PARTICIPANTS),
|
|
18218
18633
|
integration: IntegrationResultSchema.nullable()
|
|
18219
18634
|
}).strict().superRefine((snapshot4, context) => {
|
|
18220
18635
|
if (Buffer.byteLength(JSON.stringify(snapshot4), "utf8") > MAX_SNAPSHOT_ENCODED_BYTES) {
|
|
@@ -18245,87 +18660,87 @@ var RequestBase = {
|
|
|
18245
18660
|
version: VersionSchema,
|
|
18246
18661
|
requestId: UuidSchema
|
|
18247
18662
|
};
|
|
18248
|
-
var RegisterRequestSchema =
|
|
18663
|
+
var RegisterRequestSchema = z35.object({
|
|
18249
18664
|
...RequestBase,
|
|
18250
|
-
type:
|
|
18251
|
-
authToken:
|
|
18665
|
+
type: z35.literal("register"),
|
|
18666
|
+
authToken: z35.string().regex(/^[a-f0-9]{64}$/).optional(),
|
|
18252
18667
|
presence: PalPresenceSchema
|
|
18253
18668
|
}).strict();
|
|
18254
|
-
var HeartbeatRequestSchema =
|
|
18255
|
-
var ListRequestSchema =
|
|
18256
|
-
var DisconnectRequestSchema =
|
|
18257
|
-
var ChatRequestSchema =
|
|
18669
|
+
var HeartbeatRequestSchema = z35.object({ ...RequestBase, type: z35.literal("heartbeat") }).strict();
|
|
18670
|
+
var ListRequestSchema = z35.object({ ...RequestBase, type: z35.literal("list") }).strict();
|
|
18671
|
+
var DisconnectRequestSchema = z35.object({ ...RequestBase, type: z35.literal("disconnect") }).strict();
|
|
18672
|
+
var ChatRequestSchema = z35.object({
|
|
18258
18673
|
...RequestBase,
|
|
18259
|
-
type:
|
|
18674
|
+
type: z35.literal("chat"),
|
|
18260
18675
|
messageId: UuidSchema,
|
|
18261
18676
|
target: PalTargetSchema,
|
|
18262
18677
|
message: NonEmptyBoundedTextSchema
|
|
18263
18678
|
}).strict();
|
|
18264
|
-
var TaskRequestSchema =
|
|
18679
|
+
var TaskRequestSchema = z35.object({
|
|
18265
18680
|
...RequestBase,
|
|
18266
|
-
type:
|
|
18681
|
+
type: z35.literal("task"),
|
|
18267
18682
|
messageId: UuidSchema,
|
|
18268
18683
|
target: PalTargetSchema,
|
|
18269
18684
|
goal: NonEmptyBoundedTextSchema
|
|
18270
18685
|
}).strict();
|
|
18271
|
-
var CoWorkProposeRequestSchema =
|
|
18686
|
+
var CoWorkProposeRequestSchema = z35.object({
|
|
18272
18687
|
...RequestBase,
|
|
18273
|
-
type:
|
|
18688
|
+
type: z35.literal("cowork-propose"),
|
|
18274
18689
|
coWorkId: UuidSchema,
|
|
18275
18690
|
goal: NonEmptyBoundedTextSchema,
|
|
18276
18691
|
participants: CoWorkProposalParticipantsSchema
|
|
18277
18692
|
}).strict();
|
|
18278
|
-
var CoWorkAcceptanceRequestSchema =
|
|
18693
|
+
var CoWorkAcceptanceRequestSchema = z35.object({
|
|
18279
18694
|
...RequestBase,
|
|
18280
|
-
type:
|
|
18695
|
+
type: z35.literal("cowork-accept"),
|
|
18281
18696
|
coWorkId: UuidSchema,
|
|
18282
|
-
epoch:
|
|
18697
|
+
epoch: z35.number().int().positive()
|
|
18283
18698
|
}).strict();
|
|
18284
|
-
var CoWorkPlanRequestSchema =
|
|
18285
|
-
var CoWorkPlanAcceptanceRequestSchema =
|
|
18699
|
+
var CoWorkPlanRequestSchema = z35.object({ ...RequestBase, type: z35.literal("cowork-plan"), plan: CoWorkPlanSchema }).strict();
|
|
18700
|
+
var CoWorkPlanAcceptanceRequestSchema = z35.object({
|
|
18286
18701
|
...RequestBase,
|
|
18287
|
-
type:
|
|
18702
|
+
type: z35.literal("cowork-plan-accept"),
|
|
18288
18703
|
coWorkId: UuidSchema,
|
|
18289
|
-
epoch:
|
|
18290
|
-
planHash:
|
|
18704
|
+
epoch: z35.number().int().positive(),
|
|
18705
|
+
planHash: z35.string().regex(/^[a-f0-9]{64}$/)
|
|
18291
18706
|
}).strict();
|
|
18292
|
-
var CoWorkReadyRequestSchema =
|
|
18707
|
+
var CoWorkReadyRequestSchema = z35.object({
|
|
18293
18708
|
...RequestBase,
|
|
18294
|
-
type:
|
|
18709
|
+
type: z35.literal("cowork-ready"),
|
|
18295
18710
|
coWorkId: UuidSchema,
|
|
18296
|
-
epoch:
|
|
18297
|
-
planHash:
|
|
18711
|
+
epoch: z35.number().int().positive(),
|
|
18712
|
+
planHash: z35.string().regex(/^[a-f0-9]{64}$/)
|
|
18298
18713
|
}).strict();
|
|
18299
|
-
var CoWorkCompleteRequestSchema =
|
|
18714
|
+
var CoWorkCompleteRequestSchema = z35.object({
|
|
18300
18715
|
...RequestBase,
|
|
18301
|
-
type:
|
|
18716
|
+
type: z35.literal("cowork-complete"),
|
|
18302
18717
|
coWorkId: UuidSchema,
|
|
18303
|
-
epoch:
|
|
18304
|
-
planHash:
|
|
18305
|
-
passed:
|
|
18718
|
+
epoch: z35.number().int().positive(),
|
|
18719
|
+
planHash: z35.string().regex(/^[a-f0-9]{64}$/),
|
|
18720
|
+
passed: z35.boolean(),
|
|
18306
18721
|
detail: CompletionDetailSchema.optional()
|
|
18307
18722
|
}).strict();
|
|
18308
|
-
var CoWorkIntegrationRequestSchema =
|
|
18723
|
+
var CoWorkIntegrationRequestSchema = z35.object({
|
|
18309
18724
|
...RequestBase,
|
|
18310
|
-
type:
|
|
18725
|
+
type: z35.literal("cowork-integration"),
|
|
18311
18726
|
coWorkId: UuidSchema,
|
|
18312
|
-
epoch:
|
|
18313
|
-
planHash:
|
|
18314
|
-
passed:
|
|
18727
|
+
epoch: z35.number().int().positive(),
|
|
18728
|
+
planHash: z35.string().regex(/^[a-f0-9]{64}$/),
|
|
18729
|
+
passed: z35.boolean(),
|
|
18315
18730
|
evidence: CompletionDetailSchema
|
|
18316
18731
|
}).strict();
|
|
18317
|
-
var CoWorkGetRequestSchema =
|
|
18732
|
+
var CoWorkGetRequestSchema = z35.object({
|
|
18318
18733
|
...RequestBase,
|
|
18319
|
-
type:
|
|
18734
|
+
type: z35.literal("cowork-get"),
|
|
18320
18735
|
coWorkId: UuidSchema
|
|
18321
18736
|
}).strict();
|
|
18322
|
-
var CoWorkCancelRequestSchema =
|
|
18737
|
+
var CoWorkCancelRequestSchema = z35.object({
|
|
18323
18738
|
...RequestBase,
|
|
18324
|
-
type:
|
|
18739
|
+
type: z35.literal("cowork-cancel"),
|
|
18325
18740
|
coWorkId: UuidSchema,
|
|
18326
18741
|
reason: NonEmptyBoundedTextSchema
|
|
18327
18742
|
}).strict();
|
|
18328
|
-
var BrokerRequestSchema =
|
|
18743
|
+
var BrokerRequestSchema = z35.discriminatedUnion("type", [
|
|
18329
18744
|
RegisterRequestSchema,
|
|
18330
18745
|
HeartbeatRequestSchema,
|
|
18331
18746
|
ListRequestSchema,
|
|
@@ -18342,49 +18757,49 @@ var BrokerRequestSchema = z33.discriminatedUnion("type", [
|
|
|
18342
18757
|
CoWorkGetRequestSchema,
|
|
18343
18758
|
CoWorkCancelRequestSchema
|
|
18344
18759
|
]);
|
|
18345
|
-
var BrokerOkResponseSchema =
|
|
18760
|
+
var BrokerOkResponseSchema = z35.object({
|
|
18346
18761
|
version: VersionSchema,
|
|
18347
|
-
type:
|
|
18762
|
+
type: z35.literal("ok"),
|
|
18348
18763
|
requestId: UuidSchema,
|
|
18349
|
-
data:
|
|
18764
|
+
data: z35.unknown()
|
|
18350
18765
|
}).strict();
|
|
18351
|
-
var BrokerErrorResponseSchema =
|
|
18766
|
+
var BrokerErrorResponseSchema = z35.object({
|
|
18352
18767
|
version: VersionSchema,
|
|
18353
|
-
type:
|
|
18768
|
+
type: z35.literal("error"),
|
|
18354
18769
|
requestId: UuidSchema,
|
|
18355
|
-
code:
|
|
18770
|
+
code: z35.enum(["invalid-request", "authentication-failed", "not-found", "ambiguous-target", "alias-conflict", "invalid-transition", "stale-epoch", "duplicate"]),
|
|
18356
18771
|
message: BoundedTextSchema
|
|
18357
18772
|
}).strict();
|
|
18358
|
-
var ChatEventSchema =
|
|
18773
|
+
var ChatEventSchema = z35.object({
|
|
18359
18774
|
version: VersionSchema,
|
|
18360
|
-
type:
|
|
18775
|
+
type: z35.literal("chat-event"),
|
|
18361
18776
|
messageId: UuidSchema,
|
|
18362
18777
|
senderId: UuidSchema,
|
|
18363
18778
|
recipientId: UuidSchema,
|
|
18364
18779
|
message: NonEmptyBoundedTextSchema
|
|
18365
18780
|
}).strict();
|
|
18366
|
-
var CoWorkEventSchema =
|
|
18781
|
+
var CoWorkEventSchema = z35.object({
|
|
18367
18782
|
version: VersionSchema,
|
|
18368
|
-
type:
|
|
18369
|
-
action:
|
|
18783
|
+
type: z35.literal("cowork-event"),
|
|
18784
|
+
action: z35.enum(["PROPOSE", "PLAN", "START", "END", "FAIL", "CANCEL"]),
|
|
18370
18785
|
actorId: UuidSchema,
|
|
18371
18786
|
coWorkId: UuidSchema,
|
|
18372
|
-
epoch:
|
|
18373
|
-
planHash:
|
|
18787
|
+
epoch: z35.number().int().positive(),
|
|
18788
|
+
planHash: z35.string().regex(/^[a-f0-9]{64}$/).nullable(),
|
|
18374
18789
|
snapshot: CoWorkSnapshotSchema
|
|
18375
18790
|
}).strict();
|
|
18376
|
-
var BrokerEventSchema =
|
|
18377
|
-
var BrokerEventResponseSchema =
|
|
18791
|
+
var BrokerEventSchema = z35.union([ChatEventSchema, PalTaskEventSchema, DeliveryReceiptSchema, CoWorkEventSchema]);
|
|
18792
|
+
var BrokerEventResponseSchema = z35.object({
|
|
18378
18793
|
version: VersionSchema,
|
|
18379
|
-
type:
|
|
18794
|
+
type: z35.literal("event"),
|
|
18380
18795
|
event: BrokerEventSchema
|
|
18381
18796
|
}).strict();
|
|
18382
|
-
var BrokerResponseSchema =
|
|
18797
|
+
var BrokerResponseSchema = z35.discriminatedUnion("type", [
|
|
18383
18798
|
BrokerOkResponseSchema,
|
|
18384
18799
|
BrokerErrorResponseSchema,
|
|
18385
18800
|
BrokerEventResponseSchema
|
|
18386
18801
|
]);
|
|
18387
|
-
var ControlFrameSchema =
|
|
18802
|
+
var ControlFrameSchema = z35.string().refine(
|
|
18388
18803
|
(frame) => Buffer.byteLength(frame, "utf8") <= MAX_CONTROL_FRAME_BYTES,
|
|
18389
18804
|
`Control frame must not exceed ${MAX_CONTROL_FRAME_BYTES} UTF-8 bytes`
|
|
18390
18805
|
);
|
|
@@ -18403,6 +18818,7 @@ var MVP_COMMANDS = [
|
|
|
18403
18818
|
"init",
|
|
18404
18819
|
"config",
|
|
18405
18820
|
"login",
|
|
18821
|
+
"logout",
|
|
18406
18822
|
"permissions",
|
|
18407
18823
|
"skills",
|
|
18408
18824
|
"plugins",
|
|
@@ -18419,6 +18835,8 @@ var MVP_COMMANDS = [
|
|
|
18419
18835
|
"goal",
|
|
18420
18836
|
"evolve",
|
|
18421
18837
|
"mcp",
|
|
18838
|
+
"commit",
|
|
18839
|
+
"review",
|
|
18422
18840
|
"ide",
|
|
18423
18841
|
"memory",
|
|
18424
18842
|
"remember",
|
|
@@ -18469,6 +18887,14 @@ function parseSlashCommand(input, dynamicCommands = [], skillCommands = []) {
|
|
|
18469
18887
|
if (name === "evolve") {
|
|
18470
18888
|
return { name, args };
|
|
18471
18889
|
}
|
|
18890
|
+
if (name === "commit") {
|
|
18891
|
+
const hint = args.join(" ").trim();
|
|
18892
|
+
return hint.length === 0 ? { name } : { name, hint };
|
|
18893
|
+
}
|
|
18894
|
+
if (name === "review") {
|
|
18895
|
+
const focus = args.join(" ").trim();
|
|
18896
|
+
return focus.length === 0 ? { name } : { name, focus };
|
|
18897
|
+
}
|
|
18472
18898
|
if (name === "loop") {
|
|
18473
18899
|
const goal = args.join(" ").trim();
|
|
18474
18900
|
if (!goal) return { name: "invalid", command: name, message: "Use /loop <goal>." };
|
|
@@ -18670,12 +19096,15 @@ var HELP = [
|
|
|
18670
19096
|
"/model <main|subagent> <provider:model> switch any configured model",
|
|
18671
19097
|
"/permissions <default|acceptEdits|plan|bypassPermissions|auto|bubble>",
|
|
18672
19098
|
"/login authenticate via OAuth PKCE",
|
|
19099
|
+
"/logout clear stored OAuth credentials",
|
|
18673
19100
|
"/init /config /skills /plugins /hooks /tasks",
|
|
18674
19101
|
"/memory /remember [type] <text> /forget <text-or-id> /forget-cold /finish",
|
|
18675
19102
|
"/checkpoint [label] /tree /rewind <node> /unrevert /fork <node>",
|
|
18676
19103
|
"/compact /clear /help /exit",
|
|
18677
19104
|
"/loop <goal> run a verified autonomous loop",
|
|
18678
19105
|
"/goal <objective> run a goal pipeline with adversarial verification",
|
|
19106
|
+
"/commit [hint] draft a commit message for staged changes and commit",
|
|
19107
|
+
"/review [focus] review uncommitted changes before committing",
|
|
18679
19108
|
"/evolve <signals|suggest|improve <id>|verify <name>|reload <name>|test|revert <name>|done <id>> self-improvement loop",
|
|
18680
19109
|
"/mcp [status|tools|reconnect|enable|disable] manage MCP servers",
|
|
18681
19110
|
"/ide show VS Code connection and cursor/selection",
|
|
@@ -19016,6 +19445,10 @@ var FlavorSession = class {
|
|
|
19016
19445
|
for await (const event of this.#services.runLoop(command.goal, signal)) this.#services.output(event);
|
|
19017
19446
|
} else if (command.name === "goal") {
|
|
19018
19447
|
for await (const event of this.#services.runGoal(command.goal, signal)) this.#services.output(event);
|
|
19448
|
+
} else if (command.name === "commit") {
|
|
19449
|
+
this.#notice(await required(this.#services.gitCommit, "commit")(command.hint, signal));
|
|
19450
|
+
} else if (command.name === "review") {
|
|
19451
|
+
this.#notice(await required(this.#services.gitReview, "review")(command.focus, signal));
|
|
19019
19452
|
} else if (command.name === "mcp") {
|
|
19020
19453
|
this.#notice(await this.#services.mcp(command, signal));
|
|
19021
19454
|
} else if (command.name === "pals") {
|
|
@@ -19078,6 +19511,8 @@ var FlavorSession = class {
|
|
|
19078
19511
|
} else if (command.name === "login") {
|
|
19079
19512
|
this.#notice("Opening browser for authentication...");
|
|
19080
19513
|
this.#notice(await this.#services.login());
|
|
19514
|
+
} else if (command.name === "logout") {
|
|
19515
|
+
this.#notice(await this.#services.logout());
|
|
19081
19516
|
} else if (command.name === "help") this.#notice(HELP);
|
|
19082
19517
|
else if (command.name === "exit") this.#services.output({ type: "exit" });
|
|
19083
19518
|
}
|
|
@@ -19285,7 +19720,7 @@ var LANG_LABELS = /* @__PURE__ */ new Map([
|
|
|
19285
19720
|
]);
|
|
19286
19721
|
|
|
19287
19722
|
// src/hallucination/confidence.ts
|
|
19288
|
-
import { z as
|
|
19723
|
+
import { z as z36 } from "zod";
|
|
19289
19724
|
|
|
19290
19725
|
// src/hallucination/types.ts
|
|
19291
19726
|
var DEFAULT_SLIDING_WINDOW_SIZE = 20;
|
|
@@ -19298,12 +19733,12 @@ var DEFAULT_EVALUATION_TIMEOUT_MS = 2e3;
|
|
|
19298
19733
|
var MAX_QUERY_CHARS = 5e3;
|
|
19299
19734
|
var MAX_OUTPUT_CHARS = 1e4;
|
|
19300
19735
|
var MAX_EVIDENCE_CHARS = 6e3;
|
|
19301
|
-
var ConfidenceSchema =
|
|
19302
|
-
taskAlignment:
|
|
19303
|
-
evidenceGrounding:
|
|
19304
|
-
processReliability:
|
|
19305
|
-
reason:
|
|
19306
|
-
unsupportedClaims:
|
|
19736
|
+
var ConfidenceSchema = z36.object({
|
|
19737
|
+
taskAlignment: z36.number(),
|
|
19738
|
+
evidenceGrounding: z36.number(),
|
|
19739
|
+
processReliability: z36.number(),
|
|
19740
|
+
reason: z36.string(),
|
|
19741
|
+
unsupportedClaims: z36.array(z36.string()).max(3)
|
|
19307
19742
|
});
|
|
19308
19743
|
var PROMPT = `You are a fast, evidence-aware task-completion verifier.
|
|
19309
19744
|
|
|
@@ -21396,15 +21831,15 @@ function workspacePath(root, input) {
|
|
|
21396
21831
|
}
|
|
21397
21832
|
|
|
21398
21833
|
// src/tools/terminal.ts
|
|
21399
|
-
import { z as
|
|
21834
|
+
import { z as z37 } from "zod";
|
|
21400
21835
|
import { resolve as resolve29 } from "path";
|
|
21401
|
-
var Id =
|
|
21402
|
-
var OpenInput =
|
|
21403
|
-
var OptionalBoolean =
|
|
21404
|
-
var WriteInput2 =
|
|
21405
|
-
var ReadInput3 =
|
|
21406
|
-
var ResizeInput =
|
|
21407
|
-
var CloseInput =
|
|
21836
|
+
var Id = z37.string().regex(/^term-[a-f0-9-]+$/);
|
|
21837
|
+
var OpenInput = z37.object({ cwd: z37.string().optional(), shell: z37.string().optional(), args: z37.array(z37.string()).optional(), columns: z37.coerce.number().int().min(10).max(500).optional(), rows: z37.coerce.number().int().min(2).max(300).optional() });
|
|
21838
|
+
var OptionalBoolean = z37.union([z37.boolean(), z37.string().refine((value) => value === "true" || value === "false")]);
|
|
21839
|
+
var WriteInput2 = z37.object({ id: Id, data: z37.string().max(1e5), enter: OptionalBoolean.optional() });
|
|
21840
|
+
var ReadInput3 = z37.object({ id: Id, cursor: z37.coerce.number().int().min(0).optional() });
|
|
21841
|
+
var ResizeInput = z37.object({ id: Id, columns: z37.coerce.number().int().min(10).max(500), rows: z37.coerce.number().int().min(2).max(300) });
|
|
21842
|
+
var CloseInput = z37.object({ id: Id });
|
|
21408
21843
|
function createTerminalTools(terminals, workspace = process.cwd()) {
|
|
21409
21844
|
const tools = [
|
|
21410
21845
|
{
|
|
@@ -21480,7 +21915,7 @@ function createTerminalTools(terminals, workspace = process.cwd()) {
|
|
|
21480
21915
|
{
|
|
21481
21916
|
name: "TerminalList",
|
|
21482
21917
|
description: "List persistent terminals owned by this agent",
|
|
21483
|
-
inputSchema:
|
|
21918
|
+
inputSchema: z37.object({}),
|
|
21484
21919
|
paths: () => [],
|
|
21485
21920
|
execute: async (_input, _signal, context) => terminals.list(owner(context))
|
|
21486
21921
|
}
|
|
@@ -22056,7 +22491,7 @@ var PalClient = class {
|
|
|
22056
22491
|
};
|
|
22057
22492
|
|
|
22058
22493
|
// src/pals/tools.ts
|
|
22059
|
-
import { z as
|
|
22494
|
+
import { z as z38 } from "zod";
|
|
22060
22495
|
var DEFAULT_SHARE_BUDGET_BYTES = 128 * 1024;
|
|
22061
22496
|
var CollaborationShareGuard = class {
|
|
22062
22497
|
redact;
|
|
@@ -22077,25 +22512,25 @@ var CollaborationShareGuard = class {
|
|
|
22077
22512
|
return redacted;
|
|
22078
22513
|
}
|
|
22079
22514
|
};
|
|
22080
|
-
var Uuid =
|
|
22081
|
-
var Hash =
|
|
22515
|
+
var Uuid = z38.uuid();
|
|
22516
|
+
var Hash = z38.string().regex(/^[a-f0-9]{64}$/);
|
|
22082
22517
|
var Target = PalTargetSchema;
|
|
22083
|
-
var BoundedText =
|
|
22518
|
+
var BoundedText = z38.string().trim().min(1).refine(
|
|
22084
22519
|
(value) => Buffer.byteLength(value, "utf8") <= MAX_MESSAGE_BYTES,
|
|
22085
22520
|
`Text must not exceed ${MAX_MESSAGE_BYTES} UTF-8 bytes`
|
|
22086
22521
|
);
|
|
22087
|
-
var CompletionEvidence =
|
|
22522
|
+
var CompletionEvidence = z38.string().trim().min(1).refine(
|
|
22088
22523
|
(value) => Buffer.byteLength(value, "utf8") <= MAX_COMPLETION_DETAIL_BYTES,
|
|
22089
22524
|
`Completion evidence must not exceed ${MAX_COMPLETION_DETAIL_BYTES} UTF-8 bytes`
|
|
22090
22525
|
);
|
|
22091
|
-
var EmptyInput =
|
|
22092
|
-
var StateInput =
|
|
22093
|
-
var TokenInput =
|
|
22094
|
-
var SendInput =
|
|
22095
|
-
var PlanInput =
|
|
22096
|
-
var ProgressInput =
|
|
22097
|
-
var CompleteInput = TokenInput.extend({ passed:
|
|
22098
|
-
var IntegrateInput = TokenInput.extend({ passed:
|
|
22526
|
+
var EmptyInput = z38.object({}).strict();
|
|
22527
|
+
var StateInput = z38.object({ coWorkId: Uuid }).strict();
|
|
22528
|
+
var TokenInput = z38.object({ coWorkId: Uuid, epoch: z38.number().int().positive(), planHash: Hash }).strict();
|
|
22529
|
+
var SendInput = z38.object({ target: Target, message: BoundedText, coWorkId: Uuid.optional() }).strict();
|
|
22530
|
+
var PlanInput = z38.object({ plan: CoWorkPlanSchema }).strict();
|
|
22531
|
+
var ProgressInput = z38.object({ coWorkId: Uuid, target: Target, detail: BoundedText }).strict();
|
|
22532
|
+
var CompleteInput = TokenInput.extend({ passed: z38.boolean(), detail: CompletionEvidence }).strict();
|
|
22533
|
+
var IntegrateInput = TokenInput.extend({ passed: z38.boolean(), evidence: CompletionEvidence }).strict();
|
|
22099
22534
|
var sharedBytes = (...values) => values.reduce((total, value) => total + Buffer.byteLength(value, "utf8"), 0);
|
|
22100
22535
|
function resolvePresence(presences, target) {
|
|
22101
22536
|
const normalized = normalizePalIdentity(target);
|
|
@@ -22448,6 +22883,7 @@ async function createProductionRuntime(options) {
|
|
|
22448
22883
|
createApplyPatchTool(workspace, fileMutationOptions),
|
|
22449
22884
|
createGlobTool(workspace),
|
|
22450
22885
|
createGrepTool(workspace),
|
|
22886
|
+
createGitHistoryTool(workspace),
|
|
22451
22887
|
createShellTool(workspace, {
|
|
22452
22888
|
jobs,
|
|
22453
22889
|
...executionEnvironment === void 0 ? {} : { executionEnvironment }
|
|
@@ -22764,7 +23200,10 @@ async function createProductionRuntime(options) {
|
|
|
22764
23200
|
states: { ...taskStates },
|
|
22765
23201
|
results: { ...taskResults }
|
|
22766
23202
|
},
|
|
22767
|
-
|
|
23203
|
+
// Persist the resolved decision, not the harness snapshot: after logout the
|
|
23204
|
+
// harness may still hold the old login model, and resuming from that stale
|
|
23205
|
+
// value is what made the welcome card show a previous service.
|
|
23206
|
+
models: { main: mainModel, subagent: childModel },
|
|
22768
23207
|
permissionMode: harness.permissionMode,
|
|
22769
23208
|
memory: memoryLifecycle,
|
|
22770
23209
|
timeline: { version: 1, state: timelineState }
|
|
@@ -22824,7 +23263,7 @@ async function createProductionRuntime(options) {
|
|
|
22824
23263
|
})) tools.push(tool);
|
|
22825
23264
|
const taskTool = {
|
|
22826
23265
|
name: "Task",
|
|
22827
|
-
description: "Validate a task graph and execute its nodes with isolated child agents",
|
|
23266
|
+
description: "Validate a task graph and execute its nodes with isolated child agents. Declare each node's `files` (the workspace files it may create or modify) whenever a task writes files; nodes with overlapping files are serialized automatically to prevent concurrent write conflicts.",
|
|
22828
23267
|
inputSchema: TaskGraphSchema,
|
|
22829
23268
|
paths: () => [],
|
|
22830
23269
|
execute: async (input, signal) => {
|
|
@@ -23405,8 +23844,8 @@ async function createProductionRuntime(options) {
|
|
|
23405
23844
|
const services = {
|
|
23406
23845
|
hooks,
|
|
23407
23846
|
workspace,
|
|
23408
|
-
mainModel: () =>
|
|
23409
|
-
subagentModel: () =>
|
|
23847
|
+
mainModel: () => mainModel,
|
|
23848
|
+
subagentModel: () => childModel,
|
|
23410
23849
|
llmServiceName: () => effectiveLlm?.serviceName,
|
|
23411
23850
|
permissionMode: () => harness.permissionMode,
|
|
23412
23851
|
...palServices === void 0 ? {} : { pals: palServices },
|
|
@@ -23480,6 +23919,8 @@ async function createProductionRuntime(options) {
|
|
|
23480
23919
|
}
|
|
23481
23920
|
}
|
|
23482
23921
|
harness.setModel(role, id);
|
|
23922
|
+
if (role === "main") mainModel = id;
|
|
23923
|
+
else childModel = id;
|
|
23483
23924
|
await persist();
|
|
23484
23925
|
},
|
|
23485
23926
|
setPermissionMode: async (mode) => {
|
|
@@ -23512,6 +23953,19 @@ async function createProductionRuntime(options) {
|
|
|
23512
23953
|
hooksStatus: () => HOOK_EVENT_NAMES.map((name) => ({ name, pluginHandlers: pluginHooks.filter((item) => item === name).length })),
|
|
23513
23954
|
tasks: () => ({ plan: taskPlan, graph: taskGraph, states: taskStates, results: taskResults }),
|
|
23514
23955
|
evolve: (args) => evolveService.handleCommand(args),
|
|
23956
|
+
gitCommit: (hint, signal) => runGitCommit({
|
|
23957
|
+
workspace,
|
|
23958
|
+
registry,
|
|
23959
|
+
questions,
|
|
23960
|
+
modelId: () => harness.subagentModelId,
|
|
23961
|
+
notify: (message2) => emitOutput({ type: "notice", message: message2 })
|
|
23962
|
+
}, hint, signal),
|
|
23963
|
+
gitReview: (focus, signal) => runGitReview({
|
|
23964
|
+
workspace,
|
|
23965
|
+
registry,
|
|
23966
|
+
modelId: () => harness.subagentModelId,
|
|
23967
|
+
notify: (message2) => emitOutput({ type: "notice", message: message2 })
|
|
23968
|
+
}, focus, signal),
|
|
23515
23969
|
audit: async (toolFilter) => {
|
|
23516
23970
|
try {
|
|
23517
23971
|
const raw = await readFile25(auditLogger.path, "utf8");
|
|
@@ -23599,7 +24053,11 @@ ${summary2}`;
|
|
|
23599
24053
|
},
|
|
23600
24054
|
ide: () => ide.status(),
|
|
23601
24055
|
ideContext: () => ide.editorContext(),
|
|
23602
|
-
checkpoint: (label) =>
|
|
24056
|
+
checkpoint: async (label) => {
|
|
24057
|
+
const marker = await gitMarker(workspace);
|
|
24058
|
+
const tagged = marker === void 0 ? label : label === void 0 ? `git: ${marker}` : `${label} (git: ${marker})`;
|
|
24059
|
+
return sessionHistory.checkpoint(tagged, harness.main.context.snapshot());
|
|
24060
|
+
},
|
|
23603
24061
|
tree: () => sessionHistory.tree(),
|
|
23604
24062
|
rewind: async (nodeId) => {
|
|
23605
24063
|
await sessionHistory.rewind(nodeId, harness.main.context.snapshot());
|
|
@@ -23709,12 +24167,48 @@ ${renderMemoryDocument(entries)}`;
|
|
|
23709
24167
|
goalOrchestrator.setModels(mainModel, mainModel);
|
|
23710
24168
|
delete selectedModels.mainError;
|
|
23711
24169
|
delete selectedModels.childError;
|
|
24170
|
+
await retainOnlyCredentials(tokenStore, credentialId);
|
|
23712
24171
|
if (!secrets.includes(next.accessToken)) secrets.push(next.accessToken);
|
|
23713
24172
|
await persist();
|
|
23714
24173
|
return `Authenticated to "${next.serviceName}". Main model ${mainModel}; subagent ${childModel}; gateway ${next.baseURL}. Configuration is active now.`;
|
|
23715
24174
|
} catch (error) {
|
|
23716
24175
|
return `Login failed: ${message(error)}`;
|
|
23717
24176
|
}
|
|
24177
|
+
},
|
|
24178
|
+
async logout() {
|
|
24179
|
+
const tokenStore = createFileTokenStore(join29(home, ".flavor-code", "auth.json"));
|
|
24180
|
+
const tokens2 = await tokenStore.load();
|
|
24181
|
+
const hadCredentials = Object.keys(tokens2).length > 0 || effectiveLlm !== void 0;
|
|
24182
|
+
if (!hadCredentials) {
|
|
24183
|
+
return "Not authenticated \u2014 no stored OAuth credentials to clear.";
|
|
24184
|
+
}
|
|
24185
|
+
for (let i = registeredProviders.length - 1; i >= 0; i -= 1) {
|
|
24186
|
+
const provider = registeredProviders[i];
|
|
24187
|
+
if (provider !== void 0 && provider.pkceManaged === true) {
|
|
24188
|
+
registry.unregister(provider.name);
|
|
24189
|
+
registeredProviders.splice(i, 1);
|
|
24190
|
+
}
|
|
24191
|
+
}
|
|
24192
|
+
if (effectiveLlm !== void 0) {
|
|
24193
|
+
registry.unregister(effectiveLlm.providerId);
|
|
24194
|
+
effectiveLlm = void 0;
|
|
24195
|
+
}
|
|
24196
|
+
await tokenStore.save({});
|
|
24197
|
+
const fallback = selectModels(config, registeredProviders, diagnostics);
|
|
24198
|
+
mainModel = fallback.main;
|
|
24199
|
+
childModel = fallback.child;
|
|
24200
|
+
if (fallback.mainError === void 0) delete selectedModels.mainError;
|
|
24201
|
+
else selectedModels.mainError = fallback.mainError;
|
|
24202
|
+
if (fallback.childError === void 0) delete selectedModels.childError;
|
|
24203
|
+
else selectedModels.childError = fallback.childError;
|
|
24204
|
+
if (fallback.mainError === void 0 && registry.has(safeProvider(mainModel)) && registry.has(safeProvider(childModel))) {
|
|
24205
|
+
harness.setModel("main", mainModel);
|
|
24206
|
+
harness.setModel("subagent", childModel);
|
|
24207
|
+
hallucinationGuard.setModel(childModel);
|
|
24208
|
+
goalOrchestrator.setModels(mainModel, mainModel);
|
|
24209
|
+
}
|
|
24210
|
+
await persist();
|
|
24211
|
+
return fallback.mainError === void 0 ? `Logged out. Cleared OAuth credentials. Main model ${mainModel}; subagent ${childModel}.` : `Logged out. Cleared OAuth credentials. ${fallback.mainError}`;
|
|
23718
24212
|
}
|
|
23719
24213
|
};
|
|
23720
24214
|
if (config.sleep) {
|
|
@@ -24031,6 +24525,70 @@ async function* persistEach(source, persist) {
|
|
|
24031
24525
|
await persist();
|
|
24032
24526
|
}
|
|
24033
24527
|
}
|
|
24528
|
+
async function runGitCommit(deps, hint, signal) {
|
|
24529
|
+
if (!await isGitRepository(deps.workspace)) return "Not a git repository \u2014 /commit needs git.";
|
|
24530
|
+
let summary2 = await changeSummary(deps.workspace);
|
|
24531
|
+
if (summary2.statusLines.length === 0) return "Working tree clean \u2014 nothing to commit.";
|
|
24532
|
+
if (summary2.stagedFiles.length === 0) {
|
|
24533
|
+
if (deps.questions === void 0) throw new Error("Nothing is staged. Run `git add` on the files you want to commit first.");
|
|
24534
|
+
const stageAnswers = await deps.questions.ask([{
|
|
24535
|
+
header: "Staging",
|
|
24536
|
+
question: `Nothing is staged, but ${summary2.statusLines.length} change(s) exist. Stage everything before committing?`,
|
|
24537
|
+
options: [
|
|
24538
|
+
{ label: "Stage all", description: "Run git add -A, then generate the commit message." },
|
|
24539
|
+
{ label: "Cancel", description: "Abort /commit and leave the working tree as-is." }
|
|
24540
|
+
]
|
|
24541
|
+
}], signal);
|
|
24542
|
+
if (stageAnswers[0] !== "Stage all") return "/commit cancelled \u2014 nothing was staged.";
|
|
24543
|
+
await stageAll(deps.workspace);
|
|
24544
|
+
summary2 = await changeSummary(deps.workspace);
|
|
24545
|
+
if (summary2.stagedFiles.length === 0) return "Nothing ended up staged \u2014 /commit aborted.";
|
|
24546
|
+
}
|
|
24547
|
+
const staged = await stagedDiff(deps.workspace);
|
|
24548
|
+
signal.throwIfAborted();
|
|
24549
|
+
deps.notify?.("Generating commit message\u2026");
|
|
24550
|
+
let commitMessage;
|
|
24551
|
+
try {
|
|
24552
|
+
commitMessage = await suggestCommitMessage(
|
|
24553
|
+
{ registry: deps.registry, modelId: deps.modelId },
|
|
24554
|
+
{ stat: staged.stat, diff: staged.diff, ...hint === void 0 ? {} : { hint } },
|
|
24555
|
+
signal
|
|
24556
|
+
);
|
|
24557
|
+
} catch (error) {
|
|
24558
|
+
signal.throwIfAborted();
|
|
24559
|
+
const scope2 = summary2.stagedFiles.length === 1 ? summary2.stagedFiles[0] ?? "1 file" : `${summary2.stagedFiles.length} files`;
|
|
24560
|
+
commitMessage = `chore: update ${scope2}`;
|
|
24561
|
+
deps.notify?.(`Commit message generation failed (${message(error)}); using a fallback message.`);
|
|
24562
|
+
}
|
|
24563
|
+
deps.notify?.(`Proposed commit message:
|
|
24564
|
+
${commitMessage}`);
|
|
24565
|
+
if (deps.questions !== void 0) {
|
|
24566
|
+
const confirmAnswers = await deps.questions.ask([{
|
|
24567
|
+
header: "Commit",
|
|
24568
|
+
question: `Commit ${summary2.stagedFiles.length} staged file(s) on ${summary2.branch} with the message above?`,
|
|
24569
|
+
options: [
|
|
24570
|
+
{ label: "Commit", description: "Run git commit with the proposed message." },
|
|
24571
|
+
{ label: "Cancel", description: "Abort; the staged changes stay as-is." }
|
|
24572
|
+
]
|
|
24573
|
+
}], signal);
|
|
24574
|
+
if (confirmAnswers[0] !== "Commit") return "/commit cancelled \u2014 staged changes left untouched.";
|
|
24575
|
+
}
|
|
24576
|
+
const result = await commit(deps.workspace, commitMessage);
|
|
24577
|
+
return `Committed: ${result}`;
|
|
24578
|
+
}
|
|
24579
|
+
async function runGitReview(deps, focus, signal) {
|
|
24580
|
+
if (!await isGitRepository(deps.workspace)) return "Not a git repository \u2014 /review needs git.";
|
|
24581
|
+
const changes = await uncommittedDiff(deps.workspace);
|
|
24582
|
+
if (changes.diff.trim() === "" && changes.untracked.length === 0) return "No uncommitted changes to review.";
|
|
24583
|
+
signal.throwIfAborted();
|
|
24584
|
+
deps.notify?.("Reviewing uncommitted changes\u2026");
|
|
24585
|
+
const report = await reviewDiff(
|
|
24586
|
+
{ registry: deps.registry, modelId: deps.modelId },
|
|
24587
|
+
{ stat: changes.stat, diff: changes.diff, untracked: changes.untracked, ...focus === void 0 ? {} : { focus } },
|
|
24588
|
+
signal
|
|
24589
|
+
);
|
|
24590
|
+
return formatReviewReport(report);
|
|
24591
|
+
}
|
|
24034
24592
|
async function runChild(harness, skills, task, attempt, signal, parentContext) {
|
|
24035
24593
|
return harness.runSubagent(task, async (child, childSignal) => {
|
|
24036
24594
|
const skill = await skills.match(task.description);
|
|
@@ -24043,6 +24601,7 @@ ${await skills.loadBody(skill)}`;
|
|
|
24043
24601
|
`Complete task ${task.id}: ${task.description}`,
|
|
24044
24602
|
`Expected outputs: ${task.expectedOutputs.join("; ")}`,
|
|
24045
24603
|
`Verification: ${task.verification.join("; ")}`,
|
|
24604
|
+
...task.files === void 0 || task.files.length === 0 ? [] : [`Owned files: ${task.files.join(", ")}. Restrict your file writes to these paths; concurrent tasks own everything else.`],
|
|
24046
24605
|
`For completed work, finish by calling TaskOutput. Otherwise return only JSON matching these fields: ${Object.keys(SubagentResultSchema.shape).join(", ")}.${repair}`
|
|
24047
24606
|
].join("\n");
|
|
24048
24607
|
for await (const event of child.loop.run({ prompt, signal: childSignal })) {
|
|
@@ -24478,7 +25037,7 @@ import { basename as basename9, join as join39, resolve as resolve33 } from "pat
|
|
|
24478
25037
|
// src/d2c/workflow.ts
|
|
24479
25038
|
import { createHash as createHash17 } from "crypto";
|
|
24480
25039
|
import { join as join30 } from "path";
|
|
24481
|
-
import { z as
|
|
25040
|
+
import { z as z39 } from "zod";
|
|
24482
25041
|
|
|
24483
25042
|
// src/d2c/workflow-shared.ts
|
|
24484
25043
|
function reviewProgress(workflow) {
|
|
@@ -24501,91 +25060,91 @@ function buildD2cQualityRepairPrompt(task, issue) {
|
|
|
24501
25060
|
}
|
|
24502
25061
|
|
|
24503
25062
|
// src/d2c/workflow.ts
|
|
24504
|
-
var ReviewSchema2 =
|
|
24505
|
-
fingerprint:
|
|
24506
|
-
pageId:
|
|
24507
|
-
reportId:
|
|
24508
|
-
signature:
|
|
24509
|
-
label:
|
|
24510
|
-
decision:
|
|
24511
|
-
instruction:
|
|
24512
|
-
moduleId:
|
|
24513
|
-
moduleSourceFiles:
|
|
24514
|
-
updatedAt:
|
|
25063
|
+
var ReviewSchema2 = z39.object({
|
|
25064
|
+
fingerprint: z39.string().min(1).max(256),
|
|
25065
|
+
pageId: z39.string().min(1).max(128),
|
|
25066
|
+
reportId: z39.string().min(1).max(128),
|
|
25067
|
+
signature: z39.string().regex(/^[a-f0-9]{64}$/),
|
|
25068
|
+
label: z39.string().min(1).max(1e3),
|
|
25069
|
+
decision: z39.enum(["pending", "accepted", "needs-fix"]),
|
|
25070
|
+
instruction: z39.string().max(1e4).optional(),
|
|
25071
|
+
moduleId: z39.string().min(1).max(128).optional(),
|
|
25072
|
+
moduleSourceFiles: z39.array(z39.string().min(1).max(2048)).max(64).optional(),
|
|
25073
|
+
updatedAt: z39.iso.datetime()
|
|
24515
25074
|
}).strict();
|
|
24516
|
-
var InteractionRunSchema =
|
|
24517
|
-
schema:
|
|
24518
|
-
runAt:
|
|
24519
|
-
baseUrl:
|
|
24520
|
-
passed:
|
|
24521
|
-
total:
|
|
24522
|
-
failures:
|
|
24523
|
-
apiRequestCount:
|
|
24524
|
-
scenarios:
|
|
24525
|
-
id:
|
|
24526
|
-
pageUrl:
|
|
24527
|
-
passed:
|
|
24528
|
-
durationMs:
|
|
24529
|
-
apiRequestCount:
|
|
24530
|
-
failure:
|
|
24531
|
-
requests:
|
|
25075
|
+
var InteractionRunSchema = z39.object({
|
|
25076
|
+
schema: z39.literal(1),
|
|
25077
|
+
runAt: z39.iso.datetime(),
|
|
25078
|
+
baseUrl: z39.string().url().max(2048),
|
|
25079
|
+
passed: z39.boolean(),
|
|
25080
|
+
total: z39.number().int().nonnegative().max(5e4),
|
|
25081
|
+
failures: z39.number().int().nonnegative().max(5e4),
|
|
25082
|
+
apiRequestCount: z39.number().int().nonnegative().max(1e7),
|
|
25083
|
+
scenarios: z39.array(z39.object({
|
|
25084
|
+
id: z39.string().min(1).max(128),
|
|
25085
|
+
pageUrl: z39.string().url().max(2048),
|
|
25086
|
+
passed: z39.boolean(),
|
|
25087
|
+
durationMs: z39.number().int().nonnegative().max(864e5),
|
|
25088
|
+
apiRequestCount: z39.number().int().nonnegative().max(1e7),
|
|
25089
|
+
failure: z39.string().max(2e4).optional(),
|
|
25090
|
+
requests: z39.array(z39.object({ method: z39.string().min(1).max(16), path: z39.string().min(1).max(2048), status: z39.number().int().min(0).max(599) }).strict()).max(1e4).optional()
|
|
24532
25091
|
}).strict()).max(5e4),
|
|
24533
|
-
evidenceMode:
|
|
25092
|
+
evidenceMode: z39.enum(["contract", "autonomous", "contract-fallback"]).optional()
|
|
24534
25093
|
}).strict();
|
|
24535
|
-
var QualityJudgmentSchema =
|
|
24536
|
-
schema:
|
|
24537
|
-
runAt:
|
|
24538
|
-
model:
|
|
24539
|
-
visualScore:
|
|
24540
|
-
interactionScore:
|
|
24541
|
-
rawVisualScore:
|
|
24542
|
-
rawInteractionScore:
|
|
24543
|
-
staticVisualScore:
|
|
24544
|
-
deterministicInteractionPassed:
|
|
24545
|
-
overallScore:
|
|
24546
|
-
threshold:
|
|
24547
|
-
verdict:
|
|
24548
|
-
confidence:
|
|
24549
|
-
summary:
|
|
24550
|
-
strengths:
|
|
24551
|
-
evidenceMode:
|
|
24552
|
-
issues:
|
|
24553
|
-
category:
|
|
24554
|
-
severity:
|
|
24555
|
-
description:
|
|
24556
|
-
evidence:
|
|
24557
|
-
recommendation:
|
|
24558
|
-
selector:
|
|
24559
|
-
scoreImpact:
|
|
24560
|
-
id:
|
|
24561
|
-
decision:
|
|
24562
|
-
updatedAt:
|
|
25094
|
+
var QualityJudgmentSchema = z39.object({
|
|
25095
|
+
schema: z39.literal(1),
|
|
25096
|
+
runAt: z39.iso.datetime(),
|
|
25097
|
+
model: z39.string().min(1).max(256),
|
|
25098
|
+
visualScore: z39.number().min(0).max(100),
|
|
25099
|
+
interactionScore: z39.number().min(0).max(100),
|
|
25100
|
+
rawVisualScore: z39.number().min(0).max(100).optional(),
|
|
25101
|
+
rawInteractionScore: z39.number().min(0).max(100).optional(),
|
|
25102
|
+
staticVisualScore: z39.number().min(0).max(100),
|
|
25103
|
+
deterministicInteractionPassed: z39.boolean(),
|
|
25104
|
+
overallScore: z39.number().min(0).max(100),
|
|
25105
|
+
threshold: z39.number().min(0).max(100),
|
|
25106
|
+
verdict: z39.enum(["pass", "fail"]),
|
|
25107
|
+
confidence: z39.enum(["high", "medium", "low"]),
|
|
25108
|
+
summary: z39.string().min(1).max(4e3),
|
|
25109
|
+
strengths: z39.array(z39.string().min(1).max(1e3)).max(20),
|
|
25110
|
+
evidenceMode: z39.enum(["contract", "autonomous", "contract-fallback"]).optional(),
|
|
25111
|
+
issues: z39.array(z39.object({
|
|
25112
|
+
category: z39.enum(["visual", "interaction", "accessibility", "reliability"]),
|
|
25113
|
+
severity: z39.enum(["minor", "major", "critical"]),
|
|
25114
|
+
description: z39.string().min(1).max(2e3),
|
|
25115
|
+
evidence: z39.string().min(1).max(2e3).optional(),
|
|
25116
|
+
recommendation: z39.string().min(1).max(2e3),
|
|
25117
|
+
selector: z39.string().min(1).max(2048).optional(),
|
|
25118
|
+
scoreImpact: z39.number().min(0).max(30).optional(),
|
|
25119
|
+
id: z39.string().regex(/^quality-[a-f0-9]{20}$/).optional(),
|
|
25120
|
+
decision: z39.enum(["pending", "skipped", "fixing"]).optional(),
|
|
25121
|
+
updatedAt: z39.iso.datetime().optional()
|
|
24563
25122
|
}).strict()).max(100)
|
|
24564
25123
|
}).strict();
|
|
24565
|
-
var WorkflowSchema =
|
|
24566
|
-
schema:
|
|
24567
|
-
task:
|
|
24568
|
-
revision:
|
|
24569
|
-
stage:
|
|
24570
|
-
framework:
|
|
24571
|
-
activeReportId:
|
|
24572
|
-
activeBatchId:
|
|
24573
|
-
implementationDir:
|
|
24574
|
-
reviews:
|
|
24575
|
-
openapi:
|
|
24576
|
-
sourceName:
|
|
24577
|
-
importedAt:
|
|
24578
|
-
hash:
|
|
24579
|
-
version:
|
|
24580
|
-
title:
|
|
24581
|
-
baseUrl:
|
|
25124
|
+
var WorkflowSchema = z39.object({
|
|
25125
|
+
schema: z39.literal(1),
|
|
25126
|
+
task: z39.string().regex(D2C_TASK_PATTERN),
|
|
25127
|
+
revision: z39.number().int().nonnegative(),
|
|
25128
|
+
stage: z39.enum(["visual-review", "api-mapping", "integrating", "interaction-review", "quality-judge", "completed"]),
|
|
25129
|
+
framework: z39.enum(["vue", "react"]),
|
|
25130
|
+
activeReportId: z39.string().min(1).max(128),
|
|
25131
|
+
activeBatchId: z39.string().min(1).max(128).optional(),
|
|
25132
|
+
implementationDir: z39.string().min(1).max(32768),
|
|
25133
|
+
reviews: z39.array(ReviewSchema2).max(1e4),
|
|
25134
|
+
openapi: z39.object({
|
|
25135
|
+
sourceName: z39.string().min(1).max(255),
|
|
25136
|
+
importedAt: z39.iso.datetime(),
|
|
25137
|
+
hash: z39.string().regex(/^[a-f0-9]{64}$/),
|
|
25138
|
+
version: z39.string().min(1).max(32),
|
|
25139
|
+
title: z39.string().min(1).max(500),
|
|
25140
|
+
baseUrl: z39.string().max(4096).optional()
|
|
24582
25141
|
}).strict().optional(),
|
|
24583
|
-
mappings:
|
|
24584
|
-
integrationFiles:
|
|
24585
|
-
interaction:
|
|
25142
|
+
mappings: z39.array(z39.unknown()).max(5e3).optional(),
|
|
25143
|
+
integrationFiles: z39.array(z39.string().min(1).max(2048)).max(1e3).optional(),
|
|
25144
|
+
interaction: z39.object({ manualDecision: z39.enum(["pending", "accepted"]), automated: InteractionRunSchema.optional(), updatedAt: z39.iso.datetime() }).strict().optional(),
|
|
24586
25145
|
quality: QualityJudgmentSchema.optional(),
|
|
24587
|
-
qualityWaivers:
|
|
24588
|
-
updatedAt:
|
|
25146
|
+
qualityWaivers: z39.array(z39.object({ issueId: z39.string().regex(/^quality-[a-f0-9]{20}$/), updatedAt: z39.iso.datetime() }).strict()).max(100).optional(),
|
|
25147
|
+
updatedAt: z39.iso.datetime()
|
|
24589
25148
|
}).strict();
|
|
24590
25149
|
function pageId(report) {
|
|
24591
25150
|
return report.page?.id ?? "index";
|
|
@@ -25002,16 +25561,16 @@ function confirmApiMapping(mapping, operationKey, operations) {
|
|
|
25002
25561
|
// src/d2c/modules.ts
|
|
25003
25562
|
import { readFile as readFile26 } from "fs/promises";
|
|
25004
25563
|
import { isAbsolute as isAbsolute15, join as join31, normalize as normalize2, posix, sep as sep23, win32 as win322 } from "path";
|
|
25005
|
-
import { z as
|
|
25006
|
-
var ModuleSchema =
|
|
25007
|
-
id:
|
|
25008
|
-
label:
|
|
25009
|
-
sourceFiles:
|
|
25010
|
-
keywords:
|
|
25011
|
-
dataNeeds:
|
|
25012
|
-
actions:
|
|
25564
|
+
import { z as z40 } from "zod";
|
|
25565
|
+
var ModuleSchema = z40.object({
|
|
25566
|
+
id: z40.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
|
|
25567
|
+
label: z40.string().trim().min(1).max(200),
|
|
25568
|
+
sourceFiles: z40.array(z40.string().trim().min(1).max(2048)).min(1).max(64),
|
|
25569
|
+
keywords: z40.array(z40.string().trim().min(1).max(100)).max(100).optional(),
|
|
25570
|
+
dataNeeds: z40.array(z40.string().trim().min(1).max(100)).max(100).optional(),
|
|
25571
|
+
actions: z40.array(z40.string().trim().min(1).max(100)).max(100).optional()
|
|
25013
25572
|
}).strict();
|
|
25014
|
-
var ManifestSchema3 =
|
|
25573
|
+
var ManifestSchema3 = z40.object({ schema: z40.literal(1), modules: z40.array(ModuleSchema).min(1).max(500) }).passthrough();
|
|
25015
25574
|
function safeSource(path) {
|
|
25016
25575
|
if (isAbsolute15(path) || posix.isAbsolute(path) || win322.isAbsolute(path) || path.includes("\0")) return false;
|
|
25017
25576
|
const value = normalize2(path);
|
|
@@ -25453,7 +26012,7 @@ ${managed.output().slice(-4e3)}`);
|
|
|
25453
26012
|
import { createHash as createHash19, randomUUID as randomUUID23 } from "crypto";
|
|
25454
26013
|
import { copyFile as copyFile2, mkdir as mkdir25, readFile as readFile30, rename as rename13, stat as stat12, unlink as unlink6, writeFile as writeFile15 } from "fs/promises";
|
|
25455
26014
|
import { join as join34 } from "path";
|
|
25456
|
-
import { z as
|
|
26015
|
+
import { z as z41 } from "zod";
|
|
25457
26016
|
|
|
25458
26017
|
// src/e2e/prd-governance.ts
|
|
25459
26018
|
import { createHash as createHash18, randomUUID as randomUUID22 } from "crypto";
|
|
@@ -25572,38 +26131,38 @@ var RelativePrototypePath = "product/prototype/index.html";
|
|
|
25572
26131
|
var RelativeInteractionPath = "product/prototype/interaction-manifest.json";
|
|
25573
26132
|
var defaultPlanFileOperations = { rename: rename13, copyFile: copyFile2, unlink: unlink6 };
|
|
25574
26133
|
var planWriteQueues = /* @__PURE__ */ new Map();
|
|
25575
|
-
var PlanSchema2 =
|
|
25576
|
-
schema:
|
|
25577
|
-
task:
|
|
25578
|
-
revision:
|
|
25579
|
-
phase:
|
|
25580
|
-
framework:
|
|
25581
|
-
technology:
|
|
25582
|
-
frontend:
|
|
25583
|
-
backend:
|
|
25584
|
-
frontendSource:
|
|
25585
|
-
backendSource:
|
|
26134
|
+
var PlanSchema2 = z41.object({
|
|
26135
|
+
schema: z41.literal(1),
|
|
26136
|
+
task: z41.string().regex(D2C_TASK_PATTERN),
|
|
26137
|
+
revision: z41.number().int().nonnegative(),
|
|
26138
|
+
phase: z41.enum(["prd-generating", "prd-review", "design-generating", "design-review", "ready-for-d2c"]),
|
|
26139
|
+
framework: z41.enum(["vue", "react"]),
|
|
26140
|
+
technology: z41.object({
|
|
26141
|
+
frontend: z41.string().trim().min(1).max(64),
|
|
26142
|
+
backend: z41.string().trim().min(1).max(64),
|
|
26143
|
+
frontendSource: z41.enum(["default", "requirement"]),
|
|
26144
|
+
backendSource: z41.enum(["default", "requirement"])
|
|
25586
26145
|
}).strict().optional(),
|
|
25587
|
-
requirement:
|
|
25588
|
-
prd:
|
|
25589
|
-
approvedPrd:
|
|
25590
|
-
hash:
|
|
25591
|
-
approvedAt:
|
|
25592
|
-
criteria:
|
|
26146
|
+
requirement: z41.string().trim().min(2).max(5e4),
|
|
26147
|
+
prd: z41.object({ path: z41.literal(RelativePrdPath), updatedAt: z41.iso.datetime(), contentHash: z41.string().regex(/^[a-f0-9]{64}$/).optional() }).strict().optional(),
|
|
26148
|
+
approvedPrd: z41.object({
|
|
26149
|
+
hash: z41.string().regex(/^[a-f0-9]{64}$/),
|
|
26150
|
+
approvedAt: z41.iso.datetime(),
|
|
26151
|
+
criteria: z41.array(z41.object({ id: z41.string().regex(/^AC-\d{3,}$/), text: z41.string().trim().min(1).max(4e3) }).strict()).min(1).max(1e4)
|
|
25593
26152
|
}).strict().optional(),
|
|
25594
|
-
prototype:
|
|
25595
|
-
entryHtml:
|
|
25596
|
-
interactionManifest:
|
|
25597
|
-
updatedAt:
|
|
25598
|
-
contentHash:
|
|
26153
|
+
prototype: z41.object({
|
|
26154
|
+
entryHtml: z41.literal(RelativePrototypePath),
|
|
26155
|
+
interactionManifest: z41.literal(RelativeInteractionPath),
|
|
26156
|
+
updatedAt: z41.iso.datetime(),
|
|
26157
|
+
contentHash: z41.string().regex(/^[a-f0-9]{64}$/).optional()
|
|
25599
26158
|
}).strict().optional(),
|
|
25600
|
-
feedback:
|
|
25601
|
-
stage:
|
|
25602
|
-
message:
|
|
25603
|
-
updatedAt:
|
|
26159
|
+
feedback: z41.object({
|
|
26160
|
+
stage: z41.enum(["prd", "design"]),
|
|
26161
|
+
message: z41.string().trim().min(1).max(1e4),
|
|
26162
|
+
updatedAt: z41.iso.datetime()
|
|
25604
26163
|
}).strict().optional(),
|
|
25605
|
-
createdAt:
|
|
25606
|
-
updatedAt:
|
|
26164
|
+
createdAt: z41.iso.datetime(),
|
|
26165
|
+
updatedAt: z41.iso.datetime()
|
|
25607
26166
|
}).strict();
|
|
25608
26167
|
function d2cProductDirectory(workspace, task) {
|
|
25609
26168
|
if (!D2C_TASK_PATTERN.test(task)) throw new Error("Invalid D2C task name");
|
|
@@ -25764,10 +26323,10 @@ async function writeD2cProductPlan(workspace, plan, operations = defaultPlanFile
|
|
|
25764
26323
|
return parsed;
|
|
25765
26324
|
}
|
|
25766
26325
|
async function createD2cProductPlan(workspace, input, now = () => /* @__PURE__ */ new Date()) {
|
|
25767
|
-
const parsed =
|
|
25768
|
-
task:
|
|
25769
|
-
framework:
|
|
25770
|
-
requirement:
|
|
26326
|
+
const parsed = z41.object({
|
|
26327
|
+
task: z41.string().regex(D2C_TASK_PATTERN),
|
|
26328
|
+
framework: z41.enum(["vue", "react"]),
|
|
26329
|
+
requirement: z41.string().trim().min(2).max(5e4)
|
|
25771
26330
|
}).strict().parse(input);
|
|
25772
26331
|
const timestamp2 = now().toISOString();
|
|
25773
26332
|
if (await readD2cProductPlan(workspace, parsed.task) !== void 0) {
|
|
@@ -25999,31 +26558,31 @@ function createAcceptanceEvidence(coverage, run, now = /* @__PURE__ */ new Date(
|
|
|
25999
26558
|
// src/e2e/delivery-run.ts
|
|
26000
26559
|
import { createHash as createHash21 } from "crypto";
|
|
26001
26560
|
import { join as join35 } from "path";
|
|
26002
|
-
import { z as
|
|
26561
|
+
import { z as z42 } from "zod";
|
|
26003
26562
|
var DELIVERY_NODE_IDS = ["requirement", "prd", "design", "d2c", "api", "acceptance", "delivery"];
|
|
26004
|
-
var ArtifactSchema =
|
|
26005
|
-
path:
|
|
26006
|
-
hash:
|
|
26007
|
-
bytes:
|
|
26008
|
-
createdAt:
|
|
26563
|
+
var ArtifactSchema = z42.object({
|
|
26564
|
+
path: z42.string().min(1).max(32768),
|
|
26565
|
+
hash: z42.string().regex(/^[a-f0-9]{64}$/),
|
|
26566
|
+
bytes: z42.number().int().nonnegative(),
|
|
26567
|
+
createdAt: z42.iso.datetime()
|
|
26009
26568
|
}).strict();
|
|
26010
|
-
var NodeSchema =
|
|
26011
|
-
id:
|
|
26012
|
-
status:
|
|
26013
|
-
attempt:
|
|
26014
|
-
inputs:
|
|
26015
|
-
outputs:
|
|
26016
|
-
startedAt:
|
|
26017
|
-
completedAt:
|
|
26018
|
-
error:
|
|
26569
|
+
var NodeSchema = z42.object({
|
|
26570
|
+
id: z42.enum(DELIVERY_NODE_IDS),
|
|
26571
|
+
status: z42.enum(["pending", "running", "waiting-approval", "succeeded", "failed", "stale"]),
|
|
26572
|
+
attempt: z42.number().int().nonnegative(),
|
|
26573
|
+
inputs: z42.array(ArtifactSchema).max(1e4),
|
|
26574
|
+
outputs: z42.array(ArtifactSchema).max(1e4),
|
|
26575
|
+
startedAt: z42.iso.datetime().optional(),
|
|
26576
|
+
completedAt: z42.iso.datetime().optional(),
|
|
26577
|
+
error: z42.string().max(2e4).optional()
|
|
26019
26578
|
}).strict();
|
|
26020
|
-
var DeliveryRunSchema =
|
|
26021
|
-
schema:
|
|
26022
|
-
task:
|
|
26023
|
-
revision:
|
|
26024
|
-
nodes:
|
|
26025
|
-
createdAt:
|
|
26026
|
-
updatedAt:
|
|
26579
|
+
var DeliveryRunSchema = z42.object({
|
|
26580
|
+
schema: z42.literal(1),
|
|
26581
|
+
task: z42.string().regex(D2C_TASK_PATTERN),
|
|
26582
|
+
revision: z42.number().int().nonnegative(),
|
|
26583
|
+
nodes: z42.record(z42.enum(DELIVERY_NODE_IDS), NodeSchema),
|
|
26584
|
+
createdAt: z42.iso.datetime(),
|
|
26585
|
+
updatedAt: z42.iso.datetime()
|
|
26027
26586
|
}).strict();
|
|
26028
26587
|
var dependencies = {
|
|
26029
26588
|
requirement: [],
|
|
@@ -27253,11 +27812,12 @@ var DesktopRuntimeController = class {
|
|
|
27253
27812
|
].join("\n");
|
|
27254
27813
|
const delivery = await readDeliveryRun(workspace, task);
|
|
27255
27814
|
if (delivery?.nodes.api.status === "running") {
|
|
27815
|
+
const apiArtifacts = await Promise.all(generated.files.map(async (file) => artifactRef(file, await readFile33(join39(project, file)))));
|
|
27256
27816
|
const completed = await updateDeliveryRun(
|
|
27257
27817
|
workspace,
|
|
27258
27818
|
task,
|
|
27259
27819
|
delivery.revision,
|
|
27260
|
-
(run) => completeDeliveryNode(run, "api",
|
|
27820
|
+
(run) => completeDeliveryNode(run, "api", apiArtifacts)
|
|
27261
27821
|
);
|
|
27262
27822
|
await updateDeliveryRun(
|
|
27263
27823
|
workspace,
|
|
@@ -27533,6 +28093,12 @@ VITE_API_BASE_URL=${running.url}
|
|
|
27533
28093
|
});
|
|
27534
28094
|
return readD2cProductPlanView(workspace, task).then((view) => view);
|
|
27535
28095
|
}
|
|
28096
|
+
/** Read-only snapshot of the seven-node E2E delivery run; undefined when the task never started a delivery. */
|
|
28097
|
+
async getE2eDeliveryRun(task) {
|
|
28098
|
+
const workspace = this.#workspace;
|
|
28099
|
+
if (workspace === void 0) return void 0;
|
|
28100
|
+
return readDeliveryRun(workspace, task);
|
|
28101
|
+
}
|
|
27536
28102
|
async #assertProductPrdLocked(workspace, task) {
|
|
27537
28103
|
const current = await readD2cProductPlanView(workspace, task);
|
|
27538
28104
|
if (current?.plan.approvedPrd === void 0) return;
|
|
@@ -27862,7 +28428,69 @@ function desktopWindowChrome(platform = process.platform) {
|
|
|
27862
28428
|
};
|
|
27863
28429
|
}
|
|
27864
28430
|
|
|
28431
|
+
// src/utils/crash-guard.ts
|
|
28432
|
+
import { mkdirSync as mkdirSync2, writeFileSync } from "fs";
|
|
28433
|
+
import { join as join40 } from "path";
|
|
28434
|
+
var installed = false;
|
|
28435
|
+
function installCrashGuard(options = {}) {
|
|
28436
|
+
if (installed) return;
|
|
28437
|
+
installed = true;
|
|
28438
|
+
const crashLogDir = () => {
|
|
28439
|
+
try {
|
|
28440
|
+
return join40((options.workspace ?? process.cwd)(), ".flavor");
|
|
28441
|
+
} catch {
|
|
28442
|
+
return process.cwd();
|
|
28443
|
+
}
|
|
28444
|
+
};
|
|
28445
|
+
const writeCrashLog = (kind, detail) => {
|
|
28446
|
+
try {
|
|
28447
|
+
const dir = crashLogDir();
|
|
28448
|
+
mkdirSync2(dir, { recursive: true });
|
|
28449
|
+
const path = join40(dir, `crash-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "")}-${process.pid}.log`);
|
|
28450
|
+
writeFileSync(path, [
|
|
28451
|
+
`kind: ${kind}`,
|
|
28452
|
+
`version: ${process.version}`,
|
|
28453
|
+
`platform: ${process.platform}`,
|
|
28454
|
+
`time: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
28455
|
+
"",
|
|
28456
|
+
detail
|
|
28457
|
+
].join("\n"), { encoding: "utf8", mode: 384 });
|
|
28458
|
+
return path;
|
|
28459
|
+
} catch {
|
|
28460
|
+
return void 0;
|
|
28461
|
+
}
|
|
28462
|
+
};
|
|
28463
|
+
const restoreTerminal = () => {
|
|
28464
|
+
try {
|
|
28465
|
+
if (process.stdout.isTTY === true) process.stdout.write("\x1B[?25h\x1B[?1049l");
|
|
28466
|
+
} catch {
|
|
28467
|
+
}
|
|
28468
|
+
};
|
|
28469
|
+
const describe = (reason) => {
|
|
28470
|
+
if (reason instanceof Error) return `${reason.name}: ${reason.message}
|
|
28471
|
+
${reason.stack ?? ""}`;
|
|
28472
|
+
return String(reason);
|
|
28473
|
+
};
|
|
28474
|
+
const crash = (kind, reason) => {
|
|
28475
|
+
const detail = describe(reason);
|
|
28476
|
+
const logPath = writeCrashLog(kind, detail);
|
|
28477
|
+
restoreTerminal();
|
|
28478
|
+
try {
|
|
28479
|
+
const safe = redactErrorText(detail.split("\n").slice(0, 3).join("\n"));
|
|
28480
|
+
process.stderr.write(`flavor crashed (${kind}): ${safe}
|
|
28481
|
+
`);
|
|
28482
|
+
if (logPath !== void 0) process.stderr.write(`crash log: ${logPath}
|
|
28483
|
+
`);
|
|
28484
|
+
} catch {
|
|
28485
|
+
}
|
|
28486
|
+
process.exit(1);
|
|
28487
|
+
};
|
|
28488
|
+
process.on("unhandledRejection", (reason) => crash("unhandledRejection", reason));
|
|
28489
|
+
process.on("uncaughtException", (error) => crash("uncaughtException", error));
|
|
28490
|
+
}
|
|
28491
|
+
|
|
27865
28492
|
// src/desktop/main.ts
|
|
28493
|
+
installCrashGuard();
|
|
27866
28494
|
var moduleDirectory = dirname23(fileURLToPath4(import.meta.url));
|
|
27867
28495
|
var developmentUrl = process.env.FLAVOR_DESKTOP_DEV_URL;
|
|
27868
28496
|
var mainWindow;
|
|
@@ -27870,7 +28498,7 @@ var appMenu;
|
|
|
27870
28498
|
var quitting = false;
|
|
27871
28499
|
function logStartup(step, detail) {
|
|
27872
28500
|
try {
|
|
27873
|
-
const logPath =
|
|
28501
|
+
const logPath = join41(dirname23(process.execPath), "flavor-code-startup.log");
|
|
27874
28502
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
27875
28503
|
appendFileSync(logPath, `[${ts}] ${step}${detail ? ` | ${detail}` : ""}
|
|
27876
28504
|
`);
|
|
@@ -27895,7 +28523,7 @@ var d2cEmbedded = createEmbeddedD2cAutomation(() => {
|
|
|
27895
28523
|
};
|
|
27896
28524
|
});
|
|
27897
28525
|
var d2cJudgeClient = createD2cJudgeClient();
|
|
27898
|
-
var judgeStore = () => createD2cJudgeConfigStore(
|
|
28526
|
+
var judgeStore = () => createD2cJudgeConfigStore(join41(app.getPath("userData"), "d2c-judge.json"));
|
|
27899
28527
|
function judgeImage(png) {
|
|
27900
28528
|
const image = nativeImage.createFromBuffer(png);
|
|
27901
28529
|
const size = image.getSize();
|
|
@@ -27945,7 +28573,7 @@ var controller = new DesktopRuntimeController({
|
|
|
27945
28573
|
})
|
|
27946
28574
|
});
|
|
27947
28575
|
function statePath() {
|
|
27948
|
-
return
|
|
28576
|
+
return join41(app.getPath("userData"), "desktop-state.json");
|
|
27949
28577
|
}
|
|
27950
28578
|
async function loadPersistedWorkspace() {
|
|
27951
28579
|
try {
|
|
@@ -27980,7 +28608,7 @@ async function chooseAndOpenWorkspace() {
|
|
|
27980
28608
|
var cachedAppIconDataUrl;
|
|
27981
28609
|
function appIconDataUrl() {
|
|
27982
28610
|
if (cachedAppIconDataUrl !== void 0) return cachedAppIconDataUrl;
|
|
27983
|
-
const icon = nativeImage.createFromPath(
|
|
28611
|
+
const icon = nativeImage.createFromPath(join41(app.getAppPath(), "assets", "icon.png"));
|
|
27984
28612
|
if (icon.isEmpty()) return void 0;
|
|
27985
28613
|
cachedAppIconDataUrl = icon.toDataURL();
|
|
27986
28614
|
return cachedAppIconDataUrl;
|
|
@@ -28195,6 +28823,9 @@ function installIpcHandlers() {
|
|
|
28195
28823
|
const input = D2cQualityIssueDecisionInputSchema.parse(value);
|
|
28196
28824
|
return controller.resolveD2cQualityIssue(input.task, input.issueId, input.decision);
|
|
28197
28825
|
});
|
|
28826
|
+
ipcMain.handle(DESKTOP_CHANNELS.e2eGetDeliveryRun, async (_event, value) => {
|
|
28827
|
+
return controller.getE2eDeliveryRun(D2cTaskActionInputSchema.parse(value).task);
|
|
28828
|
+
});
|
|
28198
28829
|
}
|
|
28199
28830
|
function applicationMenu() {
|
|
28200
28831
|
return Menu.buildFromTemplate([
|
|
@@ -28225,7 +28856,7 @@ function applicationMenu() {
|
|
|
28225
28856
|
]);
|
|
28226
28857
|
}
|
|
28227
28858
|
async function createWindow() {
|
|
28228
|
-
const rendererPath =
|
|
28859
|
+
const rendererPath = join41(app.getAppPath(), "dist", "desktop-renderer", "index.html");
|
|
28229
28860
|
mainWindow = new BrowserWindow2({
|
|
28230
28861
|
title: "Flavor Code",
|
|
28231
28862
|
width: 1280,
|
|
@@ -28236,14 +28867,14 @@ async function createWindow() {
|
|
|
28236
28867
|
show: false,
|
|
28237
28868
|
...desktopWindowChrome(),
|
|
28238
28869
|
webPreferences: {
|
|
28239
|
-
preload:
|
|
28870
|
+
preload: join41(moduleDirectory, "preload.cjs"),
|
|
28240
28871
|
contextIsolation: true,
|
|
28241
28872
|
nodeIntegration: false,
|
|
28242
28873
|
sandbox: false,
|
|
28243
28874
|
webSecurity: true
|
|
28244
28875
|
}
|
|
28245
28876
|
});
|
|
28246
|
-
const iconPath =
|
|
28877
|
+
const iconPath = join41(app.getAppPath(), "assets", "icon.png");
|
|
28247
28878
|
const icon = nativeImage.createFromPath(iconPath);
|
|
28248
28879
|
if (!icon.isEmpty()) {
|
|
28249
28880
|
mainWindow.setIcon(icon);
|