flavor-code 1.3.3 → 1.3.6
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/dist/{app-NXOGWGSI.js → app-CJSBYZAD.js} +1 -1
- package/dist/{chunk-YY5H6GFN.js → chunk-BR3CWUYR.js} +299 -93
- package/dist/{chunk-JKJOQRAL.js → chunk-ZCEUFSHA.js} +1 -1
- package/dist/cli.js +3 -3
- package/dist/desktop/main.js +319 -113
- package/dist/desktop-renderer/assets/{index-CnGHSdJ6.js → index-bFGsR_uj.js} +2 -2
- package/dist/desktop-renderer/assets/{interactive-terminal-BpNgJ_fv.js → interactive-terminal-BwS6MvIe.js} +1 -1
- package/dist/desktop-renderer/index.html +1 -1
- package/dist/hooks/bus.d.ts +7 -0
- package/dist/sdk/index.js +2 -2
- package/dist/tools/ask-user-question.d.ts +4 -1
- package/dist/tools/types.d.ts +2 -0
- package/package.json +2 -2
package/dist/desktop/main.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/desktop/main.ts
|
|
2
2
|
import { appendFileSync } from "fs";
|
|
3
|
-
import { createHash as createHash27, randomUUID as
|
|
3
|
+
import { createHash as createHash27, randomUUID as randomUUID28 } from "crypto";
|
|
4
4
|
import { readFile as readFile39, stat as stat18, writeFile as writeFile19 } from "fs/promises";
|
|
5
5
|
import { basename as basename11, dirname as dirname24, join as join46, resolve as resolve40 } from "path";
|
|
6
6
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -4218,7 +4218,7 @@ ${summarizeReport(report2)}`).join("\n\n")
|
|
|
4218
4218
|
|
|
4219
4219
|
// src/production.ts
|
|
4220
4220
|
import { readFile as readFile27 } from "fs/promises";
|
|
4221
|
-
import { createHash as createHash20, randomUUID as
|
|
4221
|
+
import { createHash as createHash20, randomUUID as randomUUID24 } from "crypto";
|
|
4222
4222
|
import { homedir as homedir2, release as osRelease, tmpdir as tmpdir3, version as osVersion } from "os";
|
|
4223
4223
|
import { basename as basename8, join as join31, relative as relative23, resolve as resolve32, sep as sep23 } from "path";
|
|
4224
4224
|
|
|
@@ -7524,11 +7524,18 @@ var DEFAULT_TOOL_OUTPUT_LIMITS = Object.freeze({
|
|
|
7524
7524
|
perTurnChars: 2e5
|
|
7525
7525
|
});
|
|
7526
7526
|
var PreToolUsePayload = z14.object({
|
|
7527
|
+
// Optional for backwards-compatible hook updatedInput payloads; runtime
|
|
7528
|
+
// emissions always populate it.
|
|
7529
|
+
toolCallId: z14.string().optional(),
|
|
7527
7530
|
tool: z14.string(),
|
|
7528
7531
|
input: z14.unknown(),
|
|
7529
7532
|
agent: z14.enum(["main", "subagent"])
|
|
7530
7533
|
});
|
|
7531
|
-
var PermissionRequestPayload = PreToolUsePayload.extend({
|
|
7534
|
+
var PermissionRequestPayload = PreToolUsePayload.extend({
|
|
7535
|
+
reason: z14.string().optional(),
|
|
7536
|
+
toolCategory: z14.string(),
|
|
7537
|
+
allowAlways: z14.boolean()
|
|
7538
|
+
});
|
|
7532
7539
|
var PostToolUsePayload = PreToolUsePayload.extend({ output: z14.unknown() });
|
|
7533
7540
|
var PostToolUseFailurePayload = PreToolUsePayload.extend({
|
|
7534
7541
|
error: z14.object({ code: z14.string(), message: z14.string() })
|
|
@@ -7645,30 +7652,31 @@ var ToolRuntime = class {
|
|
|
7645
7652
|
const tool = this.#tools.get(call.name);
|
|
7646
7653
|
if (tool === void 0) return { ok: false, error: { code: "unknown_tool", message: `Unknown tool: ${call.name}` } };
|
|
7647
7654
|
const signal = context.signal ?? new AbortController().signal;
|
|
7655
|
+
const toolCallId = call.id ?? randomUUID7();
|
|
7648
7656
|
const validation = this.validate(call);
|
|
7649
7657
|
if (!validation.ok) {
|
|
7650
|
-
return this.#fail(call.name, call.input, context.agent, validation.error.code, validation.error.message);
|
|
7658
|
+
return this.#fail(toolCallId, call.name, call.input, context.agent, validation.error.code, validation.error.message);
|
|
7651
7659
|
}
|
|
7652
7660
|
let input = validation.input;
|
|
7653
7661
|
try {
|
|
7654
7662
|
const pre = await this.#hooks.emit({
|
|
7655
7663
|
version: 1,
|
|
7656
7664
|
type: "PreToolUse",
|
|
7657
|
-
payload: { tool: tool.name, input, agent: context.agent }
|
|
7665
|
+
payload: { toolCallId, tool: tool.name, input, agent: context.agent }
|
|
7658
7666
|
});
|
|
7659
7667
|
if (pre.updatedInput !== void 0) {
|
|
7660
7668
|
const payload = PreToolUsePayload.parse(pre.updatedInput);
|
|
7661
7669
|
if (payload.tool !== tool.name || payload.agent !== context.agent) {
|
|
7662
|
-
return this.#fail(tool.name, input, context.agent, "invalid_input", "PreToolUse cannot change the tool or agent");
|
|
7670
|
+
return this.#fail(toolCallId, tool.name, input, context.agent, "invalid_input", "PreToolUse cannot change the tool or agent");
|
|
7663
7671
|
}
|
|
7664
7672
|
try {
|
|
7665
7673
|
input = tool.inputSchema.parse(payload.input);
|
|
7666
7674
|
} catch (error) {
|
|
7667
|
-
return this.#fail(tool.name, payload.input, context.agent, "invalid_input", message(error));
|
|
7675
|
+
return this.#fail(toolCallId, tool.name, payload.input, context.agent, "invalid_input", message(error));
|
|
7668
7676
|
}
|
|
7669
7677
|
}
|
|
7670
7678
|
if (pre.decision === "deny") {
|
|
7671
|
-
return this.#fail(tool.name, input, context.agent, "hook_denied", pre.reason ?? "Tool use denied by hook");
|
|
7679
|
+
return this.#fail(toolCallId, tool.name, input, context.agent, "hook_denied", pre.reason ?? "Tool use denied by hook");
|
|
7672
7680
|
}
|
|
7673
7681
|
const request = {
|
|
7674
7682
|
agent: context.agent,
|
|
@@ -7679,13 +7687,13 @@ var ToolRuntime = class {
|
|
|
7679
7687
|
let permission = this.#permissions.decide(request);
|
|
7680
7688
|
const nonCacheableApproval = request.allowAlways === false || permission.allowAlways === false;
|
|
7681
7689
|
if (permission.decision === "deny") {
|
|
7682
|
-
return this.#fail(tool.name, input, context.agent, "permission_denied", permission.reason ?? "Tool use denied");
|
|
7690
|
+
return this.#fail(toolCallId, tool.name, input, context.agent, "permission_denied", permission.reason ?? "Tool use denied");
|
|
7683
7691
|
}
|
|
7684
7692
|
if (permission.decision === "ask" && context.agent === "main" && !nonCacheableApproval && this.#permissions.mode === "auto" && this.#permissions.profile === "standard" && this.#classify !== void 0) {
|
|
7685
7693
|
try {
|
|
7686
7694
|
const classified = await this.#classify(request, signal);
|
|
7687
7695
|
if (classified.decision === "deny") {
|
|
7688
|
-
return this.#fail(tool.name, input, context.agent, "permission_denied", classified.reason ?? "Auto classifier denied tool use");
|
|
7696
|
+
return this.#fail(toolCallId, tool.name, input, context.agent, "permission_denied", classified.reason ?? "Auto classifier denied tool use");
|
|
7689
7697
|
}
|
|
7690
7698
|
if (classified.decision === "allow") permission = classified;
|
|
7691
7699
|
else {
|
|
@@ -7702,13 +7710,21 @@ var ToolRuntime = class {
|
|
|
7702
7710
|
const requestDecision = await this.#hooks.emit({
|
|
7703
7711
|
version: 1,
|
|
7704
7712
|
type: "PermissionRequest",
|
|
7705
|
-
payload: {
|
|
7713
|
+
payload: {
|
|
7714
|
+
toolCallId,
|
|
7715
|
+
tool: tool.name,
|
|
7716
|
+
input: tool.permissionInput?.(input) ?? input,
|
|
7717
|
+
agent: context.agent,
|
|
7718
|
+
reason,
|
|
7719
|
+
toolCategory: getToolCategory(tool.name),
|
|
7720
|
+
allowAlways
|
|
7721
|
+
}
|
|
7706
7722
|
});
|
|
7707
7723
|
if (requestDecision.decision === "deny") {
|
|
7708
|
-
return this.#fail(tool.name, input, context.agent, "permission_denied", requestDecision.reason ?? "Permission request denied");
|
|
7724
|
+
return this.#fail(toolCallId, tool.name, input, context.agent, "permission_denied", requestDecision.reason ?? "Permission request denied");
|
|
7709
7725
|
}
|
|
7710
7726
|
if (requestDecision.updatedInput !== void 0) {
|
|
7711
|
-
return this.#fail(tool.name, input, context.agent, "invalid_input", "PermissionRequest cannot modify an already-authorized tool call");
|
|
7727
|
+
return this.#fail(toolCallId, tool.name, input, context.agent, "invalid_input", "PermissionRequest cannot modify an already-authorized tool call");
|
|
7712
7728
|
}
|
|
7713
7729
|
if (this.#hooks.hasListeners("PermissionRequest") && requestDecision.decision === "allow") {
|
|
7714
7730
|
const ctx = requestDecision.additionalContext ?? "";
|
|
@@ -7717,18 +7733,18 @@ var ToolRuntime = class {
|
|
|
7717
7733
|
if (allowAlways && category !== "destructive") this.#alwaysAllowed.add(category);
|
|
7718
7734
|
}
|
|
7719
7735
|
} else if (context.agent !== "main" && this.#permissions.mode !== "bubble") {
|
|
7720
|
-
return this.#fail(tool.name, input, context.agent, "approval_required", reason);
|
|
7736
|
+
return this.#fail(toolCallId, tool.name, input, context.agent, "approval_required", reason);
|
|
7721
7737
|
} else if (signal.aborted) {
|
|
7722
7738
|
throw signal.reason;
|
|
7723
7739
|
} else {
|
|
7724
7740
|
const category = getToolCategory(tool.name);
|
|
7725
7741
|
if (allowAlways && this.#alwaysAllowed.has(category)) {
|
|
7726
7742
|
} else if (this.#approve === void 0) {
|
|
7727
|
-
return this.#fail(tool.name, input, context.agent, "permission_denied", reason);
|
|
7743
|
+
return this.#fail(toolCallId, tool.name, input, context.agent, "permission_denied", reason);
|
|
7728
7744
|
} else {
|
|
7729
7745
|
const decision = await this.#approve({ ...request, reason, ...allowAlways ? {} : { allowAlways: false } }, signal);
|
|
7730
7746
|
if (decision === "deny") {
|
|
7731
|
-
return this.#fail(tool.name, input, context.agent, "user_denied", reason);
|
|
7747
|
+
return this.#fail(toolCallId, tool.name, input, context.agent, "user_denied", reason);
|
|
7732
7748
|
}
|
|
7733
7749
|
if (decision === "always" && allowAlways && category !== "destructive") {
|
|
7734
7750
|
this.#alwaysAllowed.add(category);
|
|
@@ -7742,7 +7758,7 @@ var ToolRuntime = class {
|
|
|
7742
7758
|
try {
|
|
7743
7759
|
rawOutput = tool.outputSchema === void 0 ? executed : tool.outputSchema.parse(executed);
|
|
7744
7760
|
} catch (error) {
|
|
7745
|
-
return this.#fail(tool.name, input, context.agent, "invalid_output", message(error));
|
|
7761
|
+
return this.#fail(toolCallId, tool.name, input, context.agent, "invalid_output", message(error));
|
|
7746
7762
|
}
|
|
7747
7763
|
const declaredPresentation = tool.presentResult?.(rawOutput, input);
|
|
7748
7764
|
const presentation = declaredPresentation ?? getToolPresentation(rawOutput);
|
|
@@ -7753,7 +7769,7 @@ var ToolRuntime = class {
|
|
|
7753
7769
|
await this.#hooks.emit({
|
|
7754
7770
|
version: 1,
|
|
7755
7771
|
type: "PostToolUse",
|
|
7756
|
-
payload: { tool: tool.name, input, agent: context.agent, output }
|
|
7772
|
+
payload: { toolCallId, tool: tool.name, input, agent: context.agent, output }
|
|
7757
7773
|
});
|
|
7758
7774
|
return {
|
|
7759
7775
|
ok: true,
|
|
@@ -7763,7 +7779,7 @@ var ToolRuntime = class {
|
|
|
7763
7779
|
...additionalContext === void 0 || additionalContext.length === 0 ? {} : { additionalContext }
|
|
7764
7780
|
};
|
|
7765
7781
|
} catch (error) {
|
|
7766
|
-
return this.#fail(tool.name, input, context.agent, "tool_error", message(error));
|
|
7782
|
+
return this.#fail(toolCallId, tool.name, input, context.agent, "tool_error", message(error));
|
|
7767
7783
|
}
|
|
7768
7784
|
}
|
|
7769
7785
|
async #limitOutput(tool, output) {
|
|
@@ -7811,13 +7827,13 @@ var ToolRuntime = class {
|
|
|
7811
7827
|
const limited = await this.#limitOutput(tool, content);
|
|
7812
7828
|
return typeof limited === "string" ? limited : serializeToolOutput(limited);
|
|
7813
7829
|
}
|
|
7814
|
-
async #fail(tool, input, agent, code, errorMessage3) {
|
|
7830
|
+
async #fail(toolCallId, tool, input, agent, code, errorMessage3) {
|
|
7815
7831
|
const result = { ok: false, error: { code, message: errorMessage3 } };
|
|
7816
7832
|
try {
|
|
7817
7833
|
await this.#hooks.emit({
|
|
7818
7834
|
version: 1,
|
|
7819
7835
|
type: "PostToolUseFailure",
|
|
7820
|
-
payload: { tool, input, agent, error: result.error }
|
|
7836
|
+
payload: { toolCallId, tool, input, agent, error: result.error }
|
|
7821
7837
|
});
|
|
7822
7838
|
} catch {
|
|
7823
7839
|
}
|
|
@@ -8025,7 +8041,7 @@ function toModelTool(tool) {
|
|
|
8025
8041
|
|
|
8026
8042
|
// src/harness/journal.ts
|
|
8027
8043
|
import { createHash as createHash6, randomUUID as randomUUID8 } from "crypto";
|
|
8028
|
-
import { closeSync, constants as constants2, existsSync as existsSync2, fsyncSync, mkdirSync, openSync, readFileSync, realpathSync as realpathSync2, statSync, truncateSync, writeSync } from "fs";
|
|
8044
|
+
import { closeSync, constants as constants2, existsSync as existsSync2, fsyncSync, mkdirSync, openSync, readFileSync, realpathSync as realpathSync2, renameSync, statSync, truncateSync, unlinkSync, writeSync } from "fs";
|
|
8029
8045
|
import { join as join8, relative as relative6, resolve as resolve8, sep as sep6 } from "path";
|
|
8030
8046
|
import { z as z15 } from "zod";
|
|
8031
8047
|
|
|
@@ -8036,8 +8052,10 @@ function harnessInvariantViolations(records) {
|
|
|
8036
8052
|
const tools = /* @__PURE__ */ new Set();
|
|
8037
8053
|
const models = /* @__PURE__ */ new Set();
|
|
8038
8054
|
const turns = /* @__PURE__ */ new Set();
|
|
8055
|
+
const firstSequence = records[0]?.sequence ?? 1;
|
|
8039
8056
|
records.forEach((record3, index) => {
|
|
8040
|
-
|
|
8057
|
+
const expectedSequence = firstSequence + index;
|
|
8058
|
+
if (record3.sequence !== expectedSequence) violations.push(`sequence ${record3.sequence} is not ${expectedSequence}`);
|
|
8041
8059
|
const id = typeof record3.payload.id === "string" ? record3.payload.id : "";
|
|
8042
8060
|
if (record3.type === "queue.admitted") {
|
|
8043
8061
|
if (queues.has(id)) violations.push(`queue ${id} was admitted twice`);
|
|
@@ -8053,13 +8071,13 @@ function harnessInvariantViolations(records) {
|
|
|
8053
8071
|
if (!tools.delete(id)) violations.push(`${record3.type} references unknown tool ${id}`);
|
|
8054
8072
|
} else if (record3.type === "model.requested") {
|
|
8055
8073
|
if (models.has(id)) violations.push(`model ${id} was requested twice`);
|
|
8056
|
-
if (!
|
|
8074
|
+
if (!isHash(record3.payload.messagesHash)) violations.push(`model ${id} has no valid messages hash`);
|
|
8057
8075
|
models.add(id);
|
|
8058
8076
|
} else if (record3.type === "model.completed") {
|
|
8059
8077
|
if (!models.delete(id)) violations.push(`model.completed references unknown model ${id}`);
|
|
8060
8078
|
} else if (record3.type === "turn.started") {
|
|
8061
8079
|
if (turns.has(id)) violations.push(`turn ${id} was started twice`);
|
|
8062
|
-
if (!(
|
|
8080
|
+
if (!isHash(record3.payload.promptHash)) violations.push(`turn ${id} has no valid prompt hash`);
|
|
8063
8081
|
turns.add(id);
|
|
8064
8082
|
} else if (record3.type === "turn.completed" || record3.type === "turn.interrupted") {
|
|
8065
8083
|
if (!turns.delete(id)) violations.push(`${record3.type} references unknown turn ${id}`);
|
|
@@ -8067,6 +8085,9 @@ function harnessInvariantViolations(records) {
|
|
|
8067
8085
|
});
|
|
8068
8086
|
return violations;
|
|
8069
8087
|
}
|
|
8088
|
+
function isHash(value) {
|
|
8089
|
+
return typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
|
|
8090
|
+
}
|
|
8070
8091
|
function assertHarnessInvariants(records) {
|
|
8071
8092
|
const violations = harnessInvariantViolations(records);
|
|
8072
8093
|
if (violations.length > 0) throw new Error(`Harness invariant violation: ${violations.join("; ")}`);
|
|
@@ -8147,7 +8168,7 @@ var HarnessJournal = class {
|
|
|
8147
8168
|
}
|
|
8148
8169
|
startTurn(config, prompt) {
|
|
8149
8170
|
const id = randomUUID8();
|
|
8150
|
-
this.#append("turn.started", { id,
|
|
8171
|
+
this.#append("turn.started", { id, configHash: hashJson(config), promptHash: hashJson(prompt) });
|
|
8151
8172
|
return id;
|
|
8152
8173
|
}
|
|
8153
8174
|
completeTurn(id) {
|
|
@@ -8158,7 +8179,14 @@ var HarnessJournal = class {
|
|
|
8158
8179
|
}
|
|
8159
8180
|
startModel(input) {
|
|
8160
8181
|
const id = randomUUID8();
|
|
8161
|
-
this.#append("model.requested", {
|
|
8182
|
+
this.#append("model.requested", {
|
|
8183
|
+
id,
|
|
8184
|
+
agent: input.agent,
|
|
8185
|
+
model: input.model,
|
|
8186
|
+
iteration: input.iteration,
|
|
8187
|
+
attempt: input.attempt,
|
|
8188
|
+
messagesHash: hashJson(input.messages)
|
|
8189
|
+
});
|
|
8162
8190
|
return id;
|
|
8163
8191
|
}
|
|
8164
8192
|
completeModel(id, completed, error) {
|
|
@@ -8166,11 +8194,11 @@ var HarnessJournal = class {
|
|
|
8166
8194
|
}
|
|
8167
8195
|
startTool(tool, input, retrySafe) {
|
|
8168
8196
|
const id = randomUUID8();
|
|
8169
|
-
this.#append("tool.started", { id, tool,
|
|
8197
|
+
this.#append("tool.started", { id, tool, inputHash: hashJson(input), retrySafe });
|
|
8170
8198
|
return id;
|
|
8171
8199
|
}
|
|
8172
8200
|
completeTool(id, result) {
|
|
8173
|
-
this.#append("tool.completed", { id,
|
|
8201
|
+
this.#append("tool.completed", { id, resultHash: hashJson(result) });
|
|
8174
8202
|
}
|
|
8175
8203
|
interruptTool(id, reason) {
|
|
8176
8204
|
this.#append("tool.interrupted", { id, reason });
|
|
@@ -8247,47 +8275,153 @@ var HarnessJournal = class {
|
|
|
8247
8275
|
const committed = raw.endsWith("\n") ? raw : raw.slice(0, Math.max(0, raw.lastIndexOf("\n") + 1));
|
|
8248
8276
|
if (committed.length !== raw.length) truncateSync(this.#path, Buffer.byteLength(committed));
|
|
8249
8277
|
const lines = committed.split("\n").filter(Boolean);
|
|
8250
|
-
let previousHash
|
|
8278
|
+
let previousHash;
|
|
8279
|
+
let expectedSequence;
|
|
8251
8280
|
for (const line of lines) {
|
|
8252
8281
|
const record3 = JournalRecordSchema.parse(JSON.parse(line));
|
|
8253
|
-
|
|
8282
|
+
expectedSequence ??= record3.sequence;
|
|
8283
|
+
previousHash ??= record3.previousHash;
|
|
8284
|
+
if (record3.sequence !== expectedSequence) throw new Error("Harness journal sequence is not contiguous");
|
|
8254
8285
|
if (record3.previousHash !== previousHash) throw new Error("Harness journal hash chain is broken");
|
|
8255
8286
|
if (record3.hash !== recordHash(record3)) throw new Error("Harness journal record hash is invalid");
|
|
8256
8287
|
this.#records.push(record3);
|
|
8257
8288
|
previousHash = record3.hash;
|
|
8289
|
+
expectedSequence += 1;
|
|
8258
8290
|
}
|
|
8259
|
-
this.#sequence = this.#records.
|
|
8260
|
-
this.#lastHash = previousHash;
|
|
8291
|
+
this.#sequence = this.#records.at(-1)?.sequence ?? 0;
|
|
8292
|
+
this.#lastHash = previousHash ?? null;
|
|
8261
8293
|
assertHarnessInvariants(this.#records);
|
|
8294
|
+
const hasRotatedPrefix = (this.#records[0]?.sequence ?? 1) !== 1;
|
|
8295
|
+
if (metadata.size > this.#maxBytes * 0.75 || hasRotatedPrefix || this.#records.some(hasLegacyPayload)) this.#compact();
|
|
8262
8296
|
}
|
|
8263
8297
|
#append(type, payload) {
|
|
8264
8298
|
const normalizedPayload = jsonSafeRecord(payload);
|
|
8299
|
+
let record3 = this.#createRecord(type, normalizedPayload);
|
|
8300
|
+
let line = `${JSON.stringify(record3)}
|
|
8301
|
+
`;
|
|
8302
|
+
let priorBytes = existsSync2(this.#path) ? statSync(this.#path).size : 0;
|
|
8303
|
+
if (priorBytes + Buffer.byteLength(line) > this.#maxBytes) {
|
|
8304
|
+
this.#compact();
|
|
8305
|
+
record3 = this.#createRecord(type, normalizedPayload);
|
|
8306
|
+
line = `${JSON.stringify(record3)}
|
|
8307
|
+
`;
|
|
8308
|
+
priorBytes = existsSync2(this.#path) ? statSync(this.#path).size : 0;
|
|
8309
|
+
if (priorBytes + Buffer.byteLength(line) > this.#maxBytes) {
|
|
8310
|
+
throw new Error(`Harness journal event exceeds the ${this.#maxBytes} byte bounded journal capacity`);
|
|
8311
|
+
}
|
|
8312
|
+
}
|
|
8313
|
+
const fd = openSync(this.#path, constants2.O_CREAT | constants2.O_APPEND | constants2.O_WRONLY, 384);
|
|
8314
|
+
try {
|
|
8315
|
+
writeSync(fd, line, void 0, "utf8");
|
|
8316
|
+
fsyncSync(fd);
|
|
8317
|
+
} finally {
|
|
8318
|
+
closeSync(fd);
|
|
8319
|
+
}
|
|
8320
|
+
this.#records.push(record3);
|
|
8321
|
+
this.#sequence = record3.sequence;
|
|
8322
|
+
this.#lastHash = record3.hash;
|
|
8323
|
+
}
|
|
8324
|
+
#createRecord(type, payload) {
|
|
8265
8325
|
const unsigned = {
|
|
8266
8326
|
version: HARNESS_JOURNAL_VERSION,
|
|
8267
8327
|
sequence: this.#sequence + 1,
|
|
8268
8328
|
id: randomUUID8(),
|
|
8269
8329
|
timestamp: this.#now(),
|
|
8270
8330
|
type,
|
|
8271
|
-
payload
|
|
8331
|
+
payload,
|
|
8272
8332
|
previousHash: this.#lastHash
|
|
8273
8333
|
};
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
const
|
|
8278
|
-
|
|
8279
|
-
const
|
|
8334
|
+
return JournalRecordSchema.parse({ ...unsigned, hash: hashJson(unsigned) });
|
|
8335
|
+
}
|
|
8336
|
+
#compact() {
|
|
8337
|
+
const queues = /* @__PURE__ */ new Map();
|
|
8338
|
+
const claims = /* @__PURE__ */ new Map();
|
|
8339
|
+
const tools = /* @__PURE__ */ new Map();
|
|
8340
|
+
const models = /* @__PURE__ */ new Map();
|
|
8341
|
+
const turns = /* @__PURE__ */ new Map();
|
|
8342
|
+
let savepoint;
|
|
8343
|
+
for (const record3 of this.#records) {
|
|
8344
|
+
const id = typeof record3.payload.id === "string" ? record3.payload.id : "";
|
|
8345
|
+
if (record3.type === "queue.admitted") queues.set(id, record3);
|
|
8346
|
+
else if (record3.type === "queue.claimed") claims.set(id, record3);
|
|
8347
|
+
else if (record3.type === "queue.released") claims.delete(id);
|
|
8348
|
+
else if (record3.type === "queue.acked") {
|
|
8349
|
+
queues.delete(id);
|
|
8350
|
+
claims.delete(id);
|
|
8351
|
+
} else if (record3.type === "tool.started") tools.set(id, record3);
|
|
8352
|
+
else if (record3.type === "tool.completed" || record3.type === "tool.interrupted") tools.delete(id);
|
|
8353
|
+
else if (record3.type === "model.requested") models.set(id, record3);
|
|
8354
|
+
else if (record3.type === "model.completed") models.delete(id);
|
|
8355
|
+
else if (record3.type === "turn.started") turns.set(id, record3);
|
|
8356
|
+
else if (record3.type === "turn.completed" || record3.type === "turn.interrupted") turns.delete(id);
|
|
8357
|
+
else if (record3.type === "savepoint.created") savepoint = record3;
|
|
8358
|
+
}
|
|
8359
|
+
const retained = [
|
|
8360
|
+
...queues.values(),
|
|
8361
|
+
...claims.values(),
|
|
8362
|
+
...tools.values(),
|
|
8363
|
+
...models.values(),
|
|
8364
|
+
...turns.values(),
|
|
8365
|
+
...savepoint === void 0 ? [] : [savepoint]
|
|
8366
|
+
].sort((left, right) => left.sequence - right.sequence);
|
|
8367
|
+
const compacted = [];
|
|
8368
|
+
let previousHash = null;
|
|
8369
|
+
for (const source of retained) {
|
|
8370
|
+
const unsigned = {
|
|
8371
|
+
version: HARNESS_JOURNAL_VERSION,
|
|
8372
|
+
sequence: compacted.length + 1,
|
|
8373
|
+
id: randomUUID8(),
|
|
8374
|
+
timestamp: source.timestamp,
|
|
8375
|
+
type: source.type,
|
|
8376
|
+
payload: compactPayload(source),
|
|
8377
|
+
previousHash
|
|
8378
|
+
};
|
|
8379
|
+
const record3 = JournalRecordSchema.parse({ ...unsigned, hash: hashJson(unsigned) });
|
|
8380
|
+
compacted.push(record3);
|
|
8381
|
+
previousHash = record3.hash;
|
|
8382
|
+
}
|
|
8383
|
+
const contents = compacted.map((record3) => `${JSON.stringify(record3)}
|
|
8384
|
+
`).join("");
|
|
8385
|
+
if (Buffer.byteLength(contents) > this.#maxBytes) return;
|
|
8386
|
+
const temporary = `${this.#path}.compact-${process.pid}-${randomUUID8()}`;
|
|
8387
|
+
const fd = openSync(temporary, constants2.O_CREAT | constants2.O_EXCL | constants2.O_WRONLY, 384);
|
|
8280
8388
|
try {
|
|
8281
|
-
writeSync(fd,
|
|
8389
|
+
writeSync(fd, contents, void 0, "utf8");
|
|
8282
8390
|
fsyncSync(fd);
|
|
8283
8391
|
} finally {
|
|
8284
8392
|
closeSync(fd);
|
|
8285
8393
|
}
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8394
|
+
try {
|
|
8395
|
+
renameSync(temporary, this.#path);
|
|
8396
|
+
} catch (error) {
|
|
8397
|
+
if (existsSync2(temporary)) unlinkSync(temporary);
|
|
8398
|
+
throw error;
|
|
8399
|
+
}
|
|
8400
|
+
this.#records = compacted;
|
|
8401
|
+
this.#sequence = compacted.length;
|
|
8402
|
+
this.#lastHash = previousHash;
|
|
8289
8403
|
}
|
|
8290
8404
|
};
|
|
8405
|
+
function compactPayload(record3) {
|
|
8406
|
+
const payload = record3.payload;
|
|
8407
|
+
if (record3.type === "queue.admitted") return payload;
|
|
8408
|
+
if (record3.type === "queue.claimed") return { id: payload.id };
|
|
8409
|
+
if (record3.type === "tool.started") return pick(payload, ["id", "tool", "inputHash", "retrySafe"]);
|
|
8410
|
+
if (record3.type === "model.requested") return pick(payload, ["id", "agent", "model", "iteration", "attempt", "messagesHash"]);
|
|
8411
|
+
if (record3.type === "turn.started") return pick(payload, ["id", "configHash", "promptHash"]);
|
|
8412
|
+
if (record3.type === "savepoint.created") return pick(payload, ["id", "phase", "configHash"]);
|
|
8413
|
+
return payload;
|
|
8414
|
+
}
|
|
8415
|
+
function hasLegacyPayload(record3) {
|
|
8416
|
+
if (record3.type === "turn.started") return "config" in record3.payload || "prompt" in record3.payload;
|
|
8417
|
+
if (record3.type === "model.requested") return "messages" in record3.payload;
|
|
8418
|
+
if (record3.type === "tool.started") return "input" in record3.payload;
|
|
8419
|
+
if (record3.type === "tool.completed") return "result" in record3.payload;
|
|
8420
|
+
return false;
|
|
8421
|
+
}
|
|
8422
|
+
function pick(source, keys) {
|
|
8423
|
+
return Object.fromEntries(keys.flatMap((key) => key in source ? [[key, source[key]]] : []));
|
|
8424
|
+
}
|
|
8291
8425
|
function jsonSafeRecord(value) {
|
|
8292
8426
|
const json = JSON.stringify(value, (_key, item) => typeof item === "bigint" ? `${item}n` : item);
|
|
8293
8427
|
return JSON.parse(json);
|
|
@@ -8320,6 +8454,7 @@ function isWithin2(root, target) {
|
|
|
8320
8454
|
|
|
8321
8455
|
// src/hooks/bus.ts
|
|
8322
8456
|
import { spawn } from "child_process";
|
|
8457
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
8323
8458
|
|
|
8324
8459
|
// src/hooks/types.ts
|
|
8325
8460
|
import { z as z16 } from "zod";
|
|
@@ -8386,6 +8521,11 @@ var DEFAULT_MAX_OUTPUT_BYTES = 1048576;
|
|
|
8386
8521
|
var HookBus = class {
|
|
8387
8522
|
#handlers = /* @__PURE__ */ new Map();
|
|
8388
8523
|
#payloadSchemas = /* @__PURE__ */ new Map();
|
|
8524
|
+
#options;
|
|
8525
|
+
#sequence = 0;
|
|
8526
|
+
constructor(options = {}) {
|
|
8527
|
+
this.#options = options;
|
|
8528
|
+
}
|
|
8389
8529
|
registerPayloadSchema(type, schema) {
|
|
8390
8530
|
const registrations = this.#payloadSchemas.get(type) ?? [];
|
|
8391
8531
|
const registration = { schema };
|
|
@@ -8422,7 +8562,9 @@ var HookBus = class {
|
|
|
8422
8562
|
async emit(rawEvent, externalSignal) {
|
|
8423
8563
|
externalSignal?.throwIfAborted();
|
|
8424
8564
|
let event = HookEventSchema.parse(rawEvent);
|
|
8425
|
-
|
|
8565
|
+
const validatedPayload = this.#validatePayload(event.type, event.payload);
|
|
8566
|
+
const envelope = this.#eventEnvelope();
|
|
8567
|
+
event = { ...event, payload: decoratePayload(validatedPayload, envelope) };
|
|
8426
8568
|
let aggregate2 = { decision: "allow" };
|
|
8427
8569
|
for (const registered of this.#handlers.get(event.type) ?? []) {
|
|
8428
8570
|
externalSignal?.throwIfAborted();
|
|
@@ -8437,8 +8579,8 @@ var HookBus = class {
|
|
|
8437
8579
|
externalSignal?.throwIfAborted();
|
|
8438
8580
|
if (decision.updatedInput !== void 0) {
|
|
8439
8581
|
const payload = this.#validatePayload(event.type, decision.updatedInput);
|
|
8440
|
-
event = HookEventSchema.parse({ ...event, payload });
|
|
8441
|
-
aggregate2 = { ...aggregate2, updatedInput:
|
|
8582
|
+
event = HookEventSchema.parse({ ...event, payload: decoratePayload(payload, envelope) });
|
|
8583
|
+
aggregate2 = { ...aggregate2, updatedInput: payload };
|
|
8442
8584
|
}
|
|
8443
8585
|
if (decision.additionalContext !== void 0) {
|
|
8444
8586
|
aggregate2 = {
|
|
@@ -8455,6 +8597,15 @@ var HookBus = class {
|
|
|
8455
8597
|
const schema = this.#payloadSchemas.get(type)?.at(-1)?.schema;
|
|
8456
8598
|
return schema ? schema.parse(payload) : zodRecord(payload);
|
|
8457
8599
|
}
|
|
8600
|
+
#eventEnvelope() {
|
|
8601
|
+
if (this.#options.eventContext === void 0) return void 0;
|
|
8602
|
+
return {
|
|
8603
|
+
...this.#options.eventContext(),
|
|
8604
|
+
eventId: (this.#options.eventId ?? randomUUID9)(),
|
|
8605
|
+
sequence: ++this.#sequence,
|
|
8606
|
+
timestamp: (this.#options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()))()
|
|
8607
|
+
};
|
|
8608
|
+
}
|
|
8458
8609
|
async #invoke(registered, event, externalSignal) {
|
|
8459
8610
|
const timeoutSignal = AbortSignal.timeout(registered.timeoutMs);
|
|
8460
8611
|
const signal = externalSignal === void 0 ? timeoutSignal : AbortSignal.any([timeoutSignal, externalSignal]);
|
|
@@ -8466,6 +8617,9 @@ var HookBus = class {
|
|
|
8466
8617
|
return HookDecisionSchema.parse(await Promise.race([invocation, timeout]));
|
|
8467
8618
|
}
|
|
8468
8619
|
};
|
|
8620
|
+
function decoratePayload(payload, envelope) {
|
|
8621
|
+
return envelope === void 0 ? payload : { ...payload, ...envelope };
|
|
8622
|
+
}
|
|
8469
8623
|
function runShellHandler(descriptor, event, signal) {
|
|
8470
8624
|
return new Promise((resolve41, reject) => {
|
|
8471
8625
|
const child = spawn(descriptor.command, [...descriptor.args ?? []], {
|
|
@@ -11862,7 +12016,7 @@ function formatPriorGaps(gaps) {
|
|
|
11862
12016
|
|
|
11863
12017
|
// src/goal/store.ts
|
|
11864
12018
|
import { constants as constants3 } from "fs";
|
|
11865
|
-
import { randomUUID as
|
|
12019
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
11866
12020
|
import { lstat as lstat5, mkdir as mkdir11, open as open5, rename as rename4, rm as rm6 } from "fs/promises";
|
|
11867
12021
|
import { dirname as dirname10, join as join15, relative as relative9, resolve as resolve11, sep as sep9 } from "path";
|
|
11868
12022
|
var DEFAULT_MAX_BYTES = 1024 * 1024;
|
|
@@ -11886,7 +12040,7 @@ var GoalStore = class {
|
|
|
11886
12040
|
if (Buffer.byteLength(body) > this.#maxBytes) {
|
|
11887
12041
|
throw new Error(`Goal state exceeds maximum size of ${this.#maxBytes} bytes`);
|
|
11888
12042
|
}
|
|
11889
|
-
const temporary = join15(this.#root, `.${state.id}.${process.pid}.${
|
|
12043
|
+
const temporary = join15(this.#root, `.${state.id}.${process.pid}.${randomUUID10()}.tmp`);
|
|
11890
12044
|
let handle;
|
|
11891
12045
|
try {
|
|
11892
12046
|
handle = await open5(temporary, constants3.O_CREAT | constants3.O_EXCL | constants3.O_WRONLY, 384);
|
|
@@ -11999,7 +12153,7 @@ async function ensureWorktreeDirectoryIgnored(root) {
|
|
|
11999
12153
|
import { constants as constants4 } from "fs";
|
|
12000
12154
|
import { lstat as lstat6, mkdir as mkdir13, open as open6, readFile as readFile12, realpath as realpath8, rename as rename5, rm as rm7, stat as stat6 } from "fs/promises";
|
|
12001
12155
|
import { dirname as dirname11, join as join17, relative as relative10, resolve as resolve13, sep as sep10 } from "path";
|
|
12002
|
-
import { randomUUID as
|
|
12156
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
12003
12157
|
var LOOP_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
12004
12158
|
var DEFAULT_MAX_BYTES2 = 5 * 1024 * 1024;
|
|
12005
12159
|
var LoopStore = class {
|
|
@@ -12030,7 +12184,7 @@ var LoopStore = class {
|
|
|
12030
12184
|
const body = `${JSON.stringify(state, null, 2)}
|
|
12031
12185
|
`;
|
|
12032
12186
|
if (Buffer.byteLength(body) > this.#maxBytes) throw new Error(`Loop state exceeds maximum size of ${this.#maxBytes} bytes`);
|
|
12033
|
-
const temporary = join17(directory, `.state.${process.pid}.${
|
|
12187
|
+
const temporary = join17(directory, `.state.${process.pid}.${randomUUID11()}.tmp`);
|
|
12034
12188
|
let handle;
|
|
12035
12189
|
try {
|
|
12036
12190
|
handle = await open6(temporary, constants4.O_CREAT | constants4.O_EXCL | constants4.O_WRONLY, 384);
|
|
@@ -12056,7 +12210,7 @@ var LoopStore = class {
|
|
|
12056
12210
|
return state;
|
|
12057
12211
|
} catch (error) {
|
|
12058
12212
|
if (isCode5(error, "ENOENT")) throw new Error(`Loop "${loopId}" was not found`);
|
|
12059
|
-
const quarantine = `${target}.corrupt-${Date.now()}-${
|
|
12213
|
+
const quarantine = `${target}.corrupt-${Date.now()}-${randomUUID11().slice(0, 8)}`;
|
|
12060
12214
|
await rename5(target, quarantine).catch(() => void 0);
|
|
12061
12215
|
throw new Error(`Loop "${loopId}" is corrupt and was quarantined: ${message(error)}`);
|
|
12062
12216
|
}
|
|
@@ -14915,7 +15069,7 @@ function createSkillResourceTool(registry) {
|
|
|
14915
15069
|
import { constants as constants6 } from "fs";
|
|
14916
15070
|
import { lstat as lstat8, mkdir as mkdir15, open as open7, readFile as readFile17, readdir as readdir6, realpath as realpath10, rename as rename6, rm as rm8, stat as stat7 } from "fs/promises";
|
|
14917
15071
|
import { basename as basename5, dirname as dirname15, join as join22, relative as relative13, resolve as resolve19, sep as sep13 } from "path";
|
|
14918
|
-
import { randomUUID as
|
|
15072
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
14919
15073
|
import { z as z27 } from "zod";
|
|
14920
15074
|
|
|
14921
15075
|
// src/ui/transcript.ts
|
|
@@ -15603,7 +15757,7 @@ var SessionStore = class {
|
|
|
15603
15757
|
const body = `${lines.join("\n")}
|
|
15604
15758
|
`;
|
|
15605
15759
|
if (Buffer.byteLength(body) > this.#maxBytes) throw new Error(`Session exceeds maximum size of ${this.#maxBytes} bytes`);
|
|
15606
|
-
const temporary = join22(this.#sessions, `.${document.sessionId}.${process.pid}.${
|
|
15760
|
+
const temporary = join22(this.#sessions, `.${document.sessionId}.${process.pid}.${randomUUID12()}.tmp`);
|
|
15607
15761
|
let handle;
|
|
15608
15762
|
try {
|
|
15609
15763
|
handle = await open7(temporary, constants6.O_CREAT | constants6.O_EXCL | constants6.O_WRONLY, 384);
|
|
@@ -15759,7 +15913,7 @@ var SessionStore = class {
|
|
|
15759
15913
|
if (!isWithin5(canonicalRoot, canonicalSessions)) throw new Error("Session directory escapes the workspace");
|
|
15760
15914
|
}
|
|
15761
15915
|
async #quarantine(path) {
|
|
15762
|
-
const target = `${path}.corrupt-${Date.now()}-${
|
|
15916
|
+
const target = `${path}.corrupt-${Date.now()}-${randomUUID12().slice(0, 8)}`;
|
|
15763
15917
|
await rename6(path, target);
|
|
15764
15918
|
return target;
|
|
15765
15919
|
}
|
|
@@ -15978,12 +16132,12 @@ function sanitize2(input, seen = /* @__PURE__ */ new WeakSet()) {
|
|
|
15978
16132
|
}
|
|
15979
16133
|
|
|
15980
16134
|
// src/session/tree.ts
|
|
15981
|
-
import { randomUUID as
|
|
16135
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
15982
16136
|
import { mkdir as mkdir17, readFile as readFile19, rename as rename8, writeFile as writeFile11 } from "fs/promises";
|
|
15983
16137
|
import { dirname as dirname17, join as join24, resolve as resolve21 } from "path";
|
|
15984
16138
|
|
|
15985
16139
|
// src/session/checkpoint.ts
|
|
15986
|
-
import { createHash as createHash14, randomUUID as
|
|
16140
|
+
import { createHash as createHash14, randomUUID as randomUUID13 } from "crypto";
|
|
15987
16141
|
import { execFile as execFile2 } from "child_process";
|
|
15988
16142
|
import { lstat as lstat9, mkdir as mkdir16, open as open8, readFile as readFile18, readdir as readdir7, rename as rename7, rm as rm9, writeFile as writeFile10 } from "fs/promises";
|
|
15989
16143
|
import { dirname as dirname16, join as join23, relative as relative14, resolve as resolve20, sep as sep14 } from "path";
|
|
@@ -16036,7 +16190,7 @@ var WorkspaceCheckpointStore = class {
|
|
|
16036
16190
|
}
|
|
16037
16191
|
const checkpoint = {
|
|
16038
16192
|
version: 1,
|
|
16039
|
-
id: `checkpoint-${Date.now()}-${
|
|
16193
|
+
id: `checkpoint-${Date.now()}-${randomUUID13().slice(0, 8)}`,
|
|
16040
16194
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16041
16195
|
...label === void 0 || label.trim().length === 0 ? {} : { label: label.trim() },
|
|
16042
16196
|
files
|
|
@@ -16073,7 +16227,7 @@ var WorkspaceCheckpointStore = class {
|
|
|
16073
16227
|
const target = contained(this.#workspace, file.path);
|
|
16074
16228
|
const object = objects.get(file.digest);
|
|
16075
16229
|
await mkdir16(dirname16(target), { recursive: true });
|
|
16076
|
-
const temporary = `${target}.${process.pid}.${
|
|
16230
|
+
const temporary = `${target}.${process.pid}.${randomUUID13()}.tmp`;
|
|
16077
16231
|
await writeFile10(temporary, object, { mode: file.mode });
|
|
16078
16232
|
await rename7(temporary, target);
|
|
16079
16233
|
}
|
|
@@ -16145,7 +16299,7 @@ function contained(workspace, path) {
|
|
|
16145
16299
|
}
|
|
16146
16300
|
async function atomicJson(path, value) {
|
|
16147
16301
|
await mkdir16(dirname16(path), { recursive: true });
|
|
16148
|
-
const temporary = `${path}.${process.pid}.${
|
|
16302
|
+
const temporary = `${path}.${process.pid}.${randomUUID13()}.tmp`;
|
|
16149
16303
|
await writeFile10(temporary, `${JSON.stringify(value)}
|
|
16150
16304
|
`, { encoding: "utf8", mode: 384 });
|
|
16151
16305
|
await rename7(temporary, path);
|
|
@@ -16190,7 +16344,7 @@ var SessionHistory = class _SessionHistory {
|
|
|
16190
16344
|
async append(input) {
|
|
16191
16345
|
const checkpoint = await this.#checkpoints.create(input.label);
|
|
16192
16346
|
const node = {
|
|
16193
|
-
id: `turn-${Date.now()}-${
|
|
16347
|
+
id: `turn-${Date.now()}-${randomUUID14().slice(0, 8)}`,
|
|
16194
16348
|
parentId: this.#leafId,
|
|
16195
16349
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16196
16350
|
prompt: input.prompt,
|
|
@@ -16248,7 +16402,7 @@ var SessionHistory = class _SessionHistory {
|
|
|
16248
16402
|
nodes: this.#nodes
|
|
16249
16403
|
};
|
|
16250
16404
|
await mkdir17(dirname17(this.#path), { recursive: true });
|
|
16251
|
-
const temporary = `${this.#path}.${process.pid}.${
|
|
16405
|
+
const temporary = `${this.#path}.${process.pid}.${randomUUID14()}.tmp`;
|
|
16252
16406
|
await writeFile11(temporary, `${JSON.stringify(document)}
|
|
16253
16407
|
`, { encoding: "utf8", mode: 384 });
|
|
16254
16408
|
await rename8(temporary, this.#path);
|
|
@@ -16274,7 +16428,7 @@ function isCode10(error, code) {
|
|
|
16274
16428
|
|
|
16275
16429
|
// src/sleep/organizer.ts
|
|
16276
16430
|
import { constants as constants7 } from "fs";
|
|
16277
|
-
import { randomUUID as
|
|
16431
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
16278
16432
|
import { lstat as lstat10, mkdir as mkdir18, open as open9, readdir as readdir8, realpath as realpath11, rename as rename9, rm as rm10 } from "fs/promises";
|
|
16279
16433
|
import { isAbsolute as isAbsolute10, join as join25, relative as relative15, resolve as resolve22, sep as sep15 } from "path";
|
|
16280
16434
|
import { z as z28 } from "zod";
|
|
@@ -16431,7 +16585,7 @@ Previous output was invalid. Repair it and return strict JSON only.`;
|
|
|
16431
16585
|
return (await readdir8(this.#sleepDirectory, { withFileTypes: true })).some((entry2) => entry2.isFile() && entry2.name.startsWith(prefix) && entry2.name.endsWith(".md"));
|
|
16432
16586
|
}
|
|
16433
16587
|
async #atomicWrite(path, content) {
|
|
16434
|
-
const temporary = join25(this.#sleepDirectory, `.${
|
|
16588
|
+
const temporary = join25(this.#sleepDirectory, `.${randomUUID15()}.tmp`);
|
|
16435
16589
|
let handle;
|
|
16436
16590
|
try {
|
|
16437
16591
|
handle = await open9(temporary, constants7.O_CREAT | constants7.O_EXCL | constants7.O_WRONLY, 384);
|
|
@@ -16807,7 +16961,7 @@ function computeSessionStats(documents) {
|
|
|
16807
16961
|
import { constants as constants8 } from "fs";
|
|
16808
16962
|
import { mkdir as mkdir19, open as open10, readFile as readFile20, realpath as realpath12, rename as rename10, rm as rm11, stat as stat8 } from "fs/promises";
|
|
16809
16963
|
import { dirname as dirname18, isAbsolute as isAbsolute11, relative as relative16, resolve as resolve23, sep as sep16 } from "path";
|
|
16810
|
-
import { randomUUID as
|
|
16964
|
+
import { randomUUID as randomUUID16 } from "crypto";
|
|
16811
16965
|
import { z as z29 } from "zod";
|
|
16812
16966
|
|
|
16813
16967
|
// src/tools/file-diff.ts
|
|
@@ -17160,7 +17314,7 @@ function createPathGuard(workspace) {
|
|
|
17160
17314
|
async function atomicWrite(path, content, signal, expectedVersion) {
|
|
17161
17315
|
abortIfNeeded(signal);
|
|
17162
17316
|
await mkdir19(dirname18(path), { recursive: true });
|
|
17163
|
-
const temporary = `${path}.${
|
|
17317
|
+
const temporary = `${path}.${randomUUID16()}.tmp`;
|
|
17164
17318
|
try {
|
|
17165
17319
|
const handle = await open10(temporary, constants8.O_CREAT | constants8.O_EXCL | constants8.O_WRONLY, 384);
|
|
17166
17320
|
try {
|
|
@@ -19222,18 +19376,40 @@ function hookAnswersFromUpdatedInput(updatedInput, questions) {
|
|
|
19222
19376
|
var QuestionBridge = class {
|
|
19223
19377
|
#pending;
|
|
19224
19378
|
#onChange;
|
|
19225
|
-
|
|
19379
|
+
#relay;
|
|
19380
|
+
#active = false;
|
|
19381
|
+
constructor(onChange, relay) {
|
|
19226
19382
|
this.#onChange = onChange;
|
|
19383
|
+
this.#relay = relay;
|
|
19227
19384
|
}
|
|
19228
19385
|
get pending() {
|
|
19229
19386
|
return this.#pending?.questions;
|
|
19230
19387
|
}
|
|
19231
19388
|
ask(questions, signal) {
|
|
19232
|
-
if (this.#
|
|
19389
|
+
if (this.#active) return Promise.reject(new Error("A question is already pending"));
|
|
19233
19390
|
if (signal.aborted) return Promise.reject(signal.reason);
|
|
19391
|
+
this.#active = true;
|
|
19392
|
+
if (this.#relay !== void 0) return this.#askRelayed(questions, signal);
|
|
19393
|
+
return this.#askLocally(questions, signal);
|
|
19394
|
+
}
|
|
19395
|
+
async #askRelayed(questions, signal) {
|
|
19396
|
+
try {
|
|
19397
|
+
const answers = await this.#relay(questions, signal);
|
|
19398
|
+
if (answers !== void 0) {
|
|
19399
|
+
this.#active = false;
|
|
19400
|
+
return answers;
|
|
19401
|
+
}
|
|
19402
|
+
return await this.#askLocally(questions, signal);
|
|
19403
|
+
} catch (error) {
|
|
19404
|
+
this.#active = false;
|
|
19405
|
+
throw error;
|
|
19406
|
+
}
|
|
19407
|
+
}
|
|
19408
|
+
#askLocally(questions, signal) {
|
|
19234
19409
|
return new Promise((resolve41, reject) => {
|
|
19235
19410
|
const onAbort = () => {
|
|
19236
19411
|
this.#pending = void 0;
|
|
19412
|
+
this.#active = false;
|
|
19237
19413
|
reject(signal.reason instanceof Error ? signal.reason : new Error(String(signal.reason)));
|
|
19238
19414
|
};
|
|
19239
19415
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
@@ -19242,12 +19418,14 @@ var QuestionBridge = class {
|
|
|
19242
19418
|
resolve: (answers) => {
|
|
19243
19419
|
signal.removeEventListener("abort", onAbort);
|
|
19244
19420
|
this.#pending = void 0;
|
|
19421
|
+
this.#active = false;
|
|
19245
19422
|
this.#onChange?.();
|
|
19246
19423
|
resolve41(answers);
|
|
19247
19424
|
},
|
|
19248
19425
|
reject: (error) => {
|
|
19249
19426
|
signal.removeEventListener("abort", onAbort);
|
|
19250
19427
|
this.#pending = void 0;
|
|
19428
|
+
this.#active = false;
|
|
19251
19429
|
this.#onChange?.();
|
|
19252
19430
|
reject(error);
|
|
19253
19431
|
}
|
|
@@ -19333,7 +19511,7 @@ function createTodoWriteTool() {
|
|
|
19333
19511
|
}
|
|
19334
19512
|
|
|
19335
19513
|
// src/tools/managed.ts
|
|
19336
|
-
import { randomUUID as
|
|
19514
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
19337
19515
|
import { link, lstat as lstat11, mkdir as mkdir20, readFile as readFile22, readdir as readdir9, unlink as unlink2, writeFile as writeFile12 } from "fs/promises";
|
|
19338
19516
|
import { dirname as dirname21, join as join26, resolve as resolve26 } from "path";
|
|
19339
19517
|
import { z as z37 } from "zod";
|
|
@@ -19620,7 +19798,7 @@ ${sourceUrl}`
|
|
|
19620
19798
|
}
|
|
19621
19799
|
async function writeExclusive(path, content) {
|
|
19622
19800
|
await mkdir20(dirname21(path), { recursive: true });
|
|
19623
|
-
const temporary = `${path}.${
|
|
19801
|
+
const temporary = `${path}.${randomUUID17()}.tmp`;
|
|
19624
19802
|
try {
|
|
19625
19803
|
await writeFile12(temporary, content, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
19626
19804
|
await link(temporary, path);
|
|
@@ -22848,7 +23026,7 @@ function relativeDisplay(workspace, filePath) {
|
|
|
22848
23026
|
}
|
|
22849
23027
|
|
|
22850
23028
|
// src/jobs/registry.ts
|
|
22851
|
-
import { randomUUID as
|
|
23029
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
22852
23030
|
var JobRegistry = class {
|
|
22853
23031
|
#jobs = /* @__PURE__ */ new Map();
|
|
22854
23032
|
#maxOutputChars;
|
|
@@ -22862,7 +23040,7 @@ var JobRegistry = class {
|
|
|
22862
23040
|
}
|
|
22863
23041
|
create(input) {
|
|
22864
23042
|
this.#pruneCompleted();
|
|
22865
|
-
const id = `job-${
|
|
23043
|
+
const id = `job-${randomUUID18().slice(0, 12)}`;
|
|
22866
23044
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22867
23045
|
let settle;
|
|
22868
23046
|
const done = new Promise((resolve41) => {
|
|
@@ -22988,7 +23166,7 @@ function snapshot2(job) {
|
|
|
22988
23166
|
}
|
|
22989
23167
|
|
|
22990
23168
|
// src/terminal/service.ts
|
|
22991
|
-
import { randomUUID as
|
|
23169
|
+
import { randomUUID as randomUUID19 } from "crypto";
|
|
22992
23170
|
import { createRequire as nodeCreateRequire } from "module";
|
|
22993
23171
|
import { isAbsolute as isAbsolute14, relative as relative22, resolve as resolve30, sep as sep22 } from "path";
|
|
22994
23172
|
var TerminalService = class {
|
|
@@ -23006,7 +23184,7 @@ var TerminalService = class {
|
|
|
23006
23184
|
open(input) {
|
|
23007
23185
|
const cwd = workspacePath(this.#root, input.cwd ?? ".");
|
|
23008
23186
|
const shell2 = input.shell ?? defaultShell();
|
|
23009
|
-
const id = `term-${
|
|
23187
|
+
const id = `term-${randomUUID19().slice(0, 12)}`;
|
|
23010
23188
|
const pty = this.#factory(shell2, input.args ?? [], {
|
|
23011
23189
|
cwd,
|
|
23012
23190
|
cols: input.columns ?? 100,
|
|
@@ -23239,13 +23417,13 @@ import { join as join30 } from "path";
|
|
|
23239
23417
|
import { spawn as spawn7 } from "child_process";
|
|
23240
23418
|
|
|
23241
23419
|
// src/pals/broker.ts
|
|
23242
|
-
import { createHash as createHash18, randomUUID as
|
|
23420
|
+
import { createHash as createHash18, randomUUID as randomUUID22, timingSafeEqual } from "crypto";
|
|
23243
23421
|
import { chmod as chmod2, lstat as lstat12, mkdir as mkdir23, unlink as unlink5 } from "fs/promises";
|
|
23244
23422
|
import { createServer as createServer3, Socket } from "net";
|
|
23245
23423
|
import { dirname as dirname23 } from "path";
|
|
23246
23424
|
|
|
23247
23425
|
// src/pals/auth.ts
|
|
23248
|
-
import { randomBytes as randomBytes3, randomUUID as
|
|
23426
|
+
import { randomBytes as randomBytes3, randomUUID as randomUUID20 } from "crypto";
|
|
23249
23427
|
import { chmod, link as link2, mkdir as mkdir21, open as open12, readFile as readFile25, unlink as unlink3 } from "fs/promises";
|
|
23250
23428
|
import { homedir } from "os";
|
|
23251
23429
|
import { join as join29 } from "path";
|
|
@@ -23257,7 +23435,7 @@ async function loadOrCreatePalAuthToken(options = {}) {
|
|
|
23257
23435
|
await mkdir21(directory, { recursive: true, mode: 448 });
|
|
23258
23436
|
await chmod(directory, 448);
|
|
23259
23437
|
const token = (options.random ?? randomBytes3)(PAL_AUTH_TOKEN_BYTES).toString("hex");
|
|
23260
|
-
const temporaryPath = join29(directory, `.auth-token-${process.pid}-${
|
|
23438
|
+
const temporaryPath = join29(directory, `.auth-token-${process.pid}-${randomUUID20()}.tmp`);
|
|
23261
23439
|
let handle;
|
|
23262
23440
|
try {
|
|
23263
23441
|
handle = await open12(temporaryPath, "wx", 384);
|
|
@@ -23291,7 +23469,7 @@ function validatePalAuthToken(token) {
|
|
|
23291
23469
|
}
|
|
23292
23470
|
|
|
23293
23471
|
// src/pals/lifecycle.ts
|
|
23294
|
-
import { randomUUID as
|
|
23472
|
+
import { randomUUID as randomUUID21 } from "crypto";
|
|
23295
23473
|
import { mkdir as mkdir22, open as open13, readFile as readFile26, rename as rename11, stat as stat11, unlink as unlink4 } from "fs/promises";
|
|
23296
23474
|
import { dirname as dirname22 } from "path";
|
|
23297
23475
|
function defaultProcessAlive(pid) {
|
|
@@ -23317,7 +23495,7 @@ async function acquirePalFileLock(options) {
|
|
|
23317
23495
|
await mkdir22(dirname22(options.path), { recursive: true, mode: 448 });
|
|
23318
23496
|
const pid = options.pid ?? process.pid;
|
|
23319
23497
|
const now = options.now ?? Date.now;
|
|
23320
|
-
const nonce =
|
|
23498
|
+
const nonce = randomUUID21();
|
|
23321
23499
|
const metadata = { pid, createdAt: now(), nonce };
|
|
23322
23500
|
let handle;
|
|
23323
23501
|
try {
|
|
@@ -23436,7 +23614,7 @@ async function ensureOnce(options) {
|
|
|
23436
23614
|
}
|
|
23437
23615
|
|
|
23438
23616
|
// src/pals/client.ts
|
|
23439
|
-
import { randomUUID as
|
|
23617
|
+
import { randomUUID as randomUUID23 } from "crypto";
|
|
23440
23618
|
import { Socket as Socket3 } from "net";
|
|
23441
23619
|
var DEFAULT_REQUEST_TIMEOUT_MS = 5e3;
|
|
23442
23620
|
var DEFAULT_HEARTBEAT_INTERVAL_MS = 1e4;
|
|
@@ -23512,7 +23690,7 @@ var PalClient = class {
|
|
|
23512
23690
|
return this.starting;
|
|
23513
23691
|
}
|
|
23514
23692
|
async list() {
|
|
23515
|
-
const data2 = await this.request({ version: 1, type: "list", requestId:
|
|
23693
|
+
const data2 = await this.request({ version: 1, type: "list", requestId: randomUUID23() });
|
|
23516
23694
|
return PalPresenceListSchema.parse(data2);
|
|
23517
23695
|
}
|
|
23518
23696
|
async rename(alias) {
|
|
@@ -23525,38 +23703,38 @@ var PalClient = class {
|
|
|
23525
23703
|
throw error;
|
|
23526
23704
|
}
|
|
23527
23705
|
}
|
|
23528
|
-
async sendTask(target, message2, messageId =
|
|
23529
|
-
const data2 = await this.request({ version: 1, type: "task", requestId:
|
|
23706
|
+
async sendTask(target, message2, messageId = randomUUID23()) {
|
|
23707
|
+
const data2 = await this.request({ version: 1, type: "task", requestId: randomUUID23(), messageId, target, goal: message2 });
|
|
23530
23708
|
return DeliveryReceiptSchema.parse(data2);
|
|
23531
23709
|
}
|
|
23532
|
-
async sendChat(target, message2, messageId =
|
|
23533
|
-
const data2 = await this.request({ version: 1, type: "chat", requestId:
|
|
23710
|
+
async sendChat(target, message2, messageId = randomUUID23()) {
|
|
23711
|
+
const data2 = await this.request({ version: 1, type: "chat", requestId: randomUUID23(), messageId, target, message: message2 });
|
|
23534
23712
|
return DeliveryReceiptSchema.parse(data2);
|
|
23535
23713
|
}
|
|
23536
23714
|
async startCoWork(input) {
|
|
23537
23715
|
const data2 = await this.request({
|
|
23538
23716
|
version: 1,
|
|
23539
23717
|
type: "cowork-propose",
|
|
23540
|
-
requestId:
|
|
23541
|
-
coWorkId: input.coWorkId ??
|
|
23718
|
+
requestId: randomUUID23(),
|
|
23719
|
+
coWorkId: input.coWorkId ?? randomUUID23(),
|
|
23542
23720
|
goal: input.goal,
|
|
23543
23721
|
participants: input.participants
|
|
23544
23722
|
});
|
|
23545
23723
|
return CoWorkSnapshotSchema.parse(data2);
|
|
23546
23724
|
}
|
|
23547
23725
|
async coWorkAction(action) {
|
|
23548
|
-
const request = { version: 1, requestId:
|
|
23726
|
+
const request = { version: 1, requestId: randomUUID23(), ...action };
|
|
23549
23727
|
return CoWorkSnapshotSchema.parse(await this.request(request));
|
|
23550
23728
|
}
|
|
23551
23729
|
async coWorkStatus(coWorkId) {
|
|
23552
|
-
const data2 = await this.request({ version: 1, type: "cowork-get", requestId:
|
|
23730
|
+
const data2 = await this.request({ version: 1, type: "cowork-get", requestId: randomUUID23(), coWorkId });
|
|
23553
23731
|
return CoWorkSnapshotSchema.parse(data2);
|
|
23554
23732
|
}
|
|
23555
23733
|
async integrateCoWork(input) {
|
|
23556
23734
|
return this.coWorkAction({ type: "cowork-integration", ...input });
|
|
23557
23735
|
}
|
|
23558
23736
|
async cancelCoWork(coWorkId, reason) {
|
|
23559
|
-
const data2 = await this.request({ version: 1, type: "cowork-cancel", requestId:
|
|
23737
|
+
const data2 = await this.request({ version: 1, type: "cowork-cancel", requestId: randomUUID23(), coWorkId, reason });
|
|
23560
23738
|
return CoWorkSnapshotSchema.parse(data2);
|
|
23561
23739
|
}
|
|
23562
23740
|
subscribe(listener) {
|
|
@@ -23568,7 +23746,7 @@ var PalClient = class {
|
|
|
23568
23746
|
if (this.registered && this.socket !== void 0) {
|
|
23569
23747
|
let disconnectTimer;
|
|
23570
23748
|
await Promise.race([
|
|
23571
|
-
this.request({ version: 1, type: "disconnect", requestId:
|
|
23749
|
+
this.request({ version: 1, type: "disconnect", requestId: randomUUID23() }).catch(() => void 0),
|
|
23572
23750
|
new Promise((resolve41) => {
|
|
23573
23751
|
disconnectTimer = setTimeout(resolve41, Math.min(this.requestTimeoutMs, 250));
|
|
23574
23752
|
})
|
|
@@ -23659,7 +23837,7 @@ var PalClient = class {
|
|
|
23659
23837
|
const data2 = await this.request({
|
|
23660
23838
|
version: 1,
|
|
23661
23839
|
type: "register",
|
|
23662
|
-
requestId:
|
|
23840
|
+
requestId: randomUUID23(),
|
|
23663
23841
|
authToken: this.authToken,
|
|
23664
23842
|
presence: { version: 1, ...this.registration, connectedAt: now, lastSeenAt: now }
|
|
23665
23843
|
});
|
|
@@ -23771,7 +23949,7 @@ var PalClient = class {
|
|
|
23771
23949
|
if (!this.registered) return;
|
|
23772
23950
|
if (this.heartbeatPending) return;
|
|
23773
23951
|
this.heartbeatPending = true;
|
|
23774
|
-
void this.request({ version: 1, type: "heartbeat", requestId:
|
|
23952
|
+
void this.request({ version: 1, type: "heartbeat", requestId: randomUUID23() }).catch(() => void 0).finally(() => {
|
|
23775
23953
|
this.heartbeatPending = false;
|
|
23776
23954
|
});
|
|
23777
23955
|
}, this.heartbeatIntervalMs);
|
|
@@ -24058,7 +24236,7 @@ var ApprovalBridge = class {
|
|
|
24058
24236
|
request(request, signal = new AbortController().signal) {
|
|
24059
24237
|
if (this.#settle !== void 0) return Promise.resolve("deny");
|
|
24060
24238
|
if (signal.aborted) return Promise.resolve("deny");
|
|
24061
|
-
this.#pending = { id:
|
|
24239
|
+
this.#pending = { id: randomUUID24(), ...request };
|
|
24062
24240
|
this.#onChange?.();
|
|
24063
24241
|
return new Promise((resolvePromise) => {
|
|
24064
24242
|
this.#settle = resolvePromise;
|
|
@@ -24177,7 +24355,14 @@ async function createProductionRuntime(options) {
|
|
|
24177
24355
|
environment.OPENAI_API_KEY,
|
|
24178
24356
|
environment.ANTHROPIC_API_KEY
|
|
24179
24357
|
].filter((value) => typeof value === "string" && value.length > 0);
|
|
24180
|
-
|
|
24358
|
+
let hookSessionId;
|
|
24359
|
+
const hooks = new HookBus({
|
|
24360
|
+
eventContext: () => ({
|
|
24361
|
+
protocolVersion: 2,
|
|
24362
|
+
workspace,
|
|
24363
|
+
...hookSessionId === void 0 ? {} : { sessionId: hookSessionId }
|
|
24364
|
+
})
|
|
24365
|
+
});
|
|
24181
24366
|
hooks.on(
|
|
24182
24367
|
"PostToolUseFailure",
|
|
24183
24368
|
createIncidentReporter({
|
|
@@ -24197,8 +24382,7 @@ async function createProductionRuntime(options) {
|
|
|
24197
24382
|
diagnostics.push(...permissionPolicy.diagnostics);
|
|
24198
24383
|
const approvals = new ApprovalBridge(options.onApprovalChange);
|
|
24199
24384
|
const resolveToolApproval = options.approvalPolicy === "deny" && options.rpcToolApprovals !== true ? () => "deny" : (request, signal) => approvals.request(request, signal);
|
|
24200
|
-
const
|
|
24201
|
-
const askUserQuestionHandler = async (qs, signal) => {
|
|
24385
|
+
const relayQuestions = async (qs, signal) => {
|
|
24202
24386
|
if (options.approvalPolicy === "deny") throw new Error("AskUserQuestion is not available in non-interactive mode");
|
|
24203
24387
|
if (hooks.hasListeners("PermissionRequest")) {
|
|
24204
24388
|
let decision;
|
|
@@ -24216,8 +24400,10 @@ async function createProductionRuntime(options) {
|
|
|
24216
24400
|
const hookAnswers = hookAnswersFromUpdatedInput(decision.updatedInput, qs);
|
|
24217
24401
|
if (hookAnswers !== void 0) return hookAnswers;
|
|
24218
24402
|
}
|
|
24219
|
-
return
|
|
24403
|
+
return void 0;
|
|
24220
24404
|
};
|
|
24405
|
+
const questions = new QuestionBridge(options.onApprovalChange, relayQuestions);
|
|
24406
|
+
const askUserQuestionHandler = (qs, signal) => questions.ask(qs, signal);
|
|
24221
24407
|
const executionEnvironment = createExecutionEnvironment(workspace, config.execution);
|
|
24222
24408
|
const jobs = new JobRegistry();
|
|
24223
24409
|
const terminals = new TerminalService(workspace, { jobs });
|
|
@@ -24541,7 +24727,8 @@ async function createProductionRuntime(options) {
|
|
|
24541
24727
|
let taskResults = { ...recovered?.tasks.results ?? {} };
|
|
24542
24728
|
const subagentStartedAt = {};
|
|
24543
24729
|
const subagentElapsedMs = {};
|
|
24544
|
-
let sessionId = recovered?.sessionId ?? `session-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "").slice(0, 17)}-${
|
|
24730
|
+
let sessionId = recovered?.sessionId ?? `session-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "").slice(0, 17)}-${randomUUID24().slice(0, 8)}`;
|
|
24731
|
+
hookSessionId = sessionId;
|
|
24545
24732
|
let harnessJournal = new HarnessJournal({ workspace, sessionId });
|
|
24546
24733
|
const harnessRecovery = harnessJournal.recover();
|
|
24547
24734
|
if (harnessRecovery.queue.length > 0 || harnessRecovery.incompleteTools.length > 0 || harnessRecovery.incompleteModelIds.length > 0 || harnessRecovery.interruptedTurnIds.length > 0) {
|
|
@@ -24625,7 +24812,13 @@ async function createProductionRuntime(options) {
|
|
|
24625
24812
|
const publishTaskState = async () => {
|
|
24626
24813
|
harness.main.context.updateTaskState(serializedTaskState());
|
|
24627
24814
|
await persist();
|
|
24628
|
-
|
|
24815
|
+
const snapshot4 = taskSnapshot();
|
|
24816
|
+
emitOutput({ type: "tasks", snapshot: snapshot4 });
|
|
24817
|
+
await hooks.emit({
|
|
24818
|
+
version: 1,
|
|
24819
|
+
type: "Notification",
|
|
24820
|
+
payload: { kind: "task_snapshot", taskSnapshot: snapshot4 }
|
|
24821
|
+
}).catch(() => void 0);
|
|
24629
24822
|
};
|
|
24630
24823
|
for (const tool of createTaskPlanTools({
|
|
24631
24824
|
getPlan: () => taskPlan,
|
|
@@ -25183,7 +25376,7 @@ async function createProductionRuntime(options) {
|
|
|
25183
25376
|
return answers[0] === "Continue" ? "approved" : "rejected";
|
|
25184
25377
|
},
|
|
25185
25378
|
fingerprint: workspaceFingerprint,
|
|
25186
|
-
idFactory: () => `loop-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "").slice(0, 17)}-${
|
|
25379
|
+
idFactory: () => `loop-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "").slice(0, 17)}-${randomUUID24().slice(0, 8)}`
|
|
25187
25380
|
});
|
|
25188
25381
|
const goalStore = new GoalStore({ workspace });
|
|
25189
25382
|
const goalOrchestrator = new GoalOrchestrator({
|
|
@@ -25202,7 +25395,7 @@ async function createProductionRuntime(options) {
|
|
|
25202
25395
|
executionEnvironment
|
|
25203
25396
|
),
|
|
25204
25397
|
now: () => (/* @__PURE__ */ new Date()).toISOString(),
|
|
25205
|
-
idFactory: () => `goal-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "").slice(0, 17)}-${
|
|
25398
|
+
idFactory: () => `goal-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "").slice(0, 17)}-${randomUUID24().slice(0, 8)}`,
|
|
25206
25399
|
runWorker: ({ workspace: goalWorkspace, prompt, signal }) => runLoopWorker({ workspace: goalWorkspace, prompt, signal })
|
|
25207
25400
|
});
|
|
25208
25401
|
let sessionHistory = await SessionHistory.open({
|
|
@@ -25315,7 +25508,7 @@ async function createProductionRuntime(options) {
|
|
|
25315
25508
|
runExplicitSkill(harness, skills, skill, prompt, signal, selectedModels.mainError),
|
|
25316
25509
|
persist
|
|
25317
25510
|
),
|
|
25318
|
-
runLoop: (goal, signal) => runLoopSession(loopOrchestrator, goal, signal),
|
|
25511
|
+
runLoop: (goal, signal) => runLoopSession(loopOrchestrator, hooks, goal, signal),
|
|
25319
25512
|
runGoal: (goal, signal) => persistEach(runGoalSession(goalOrchestrator, goal, signal), persist),
|
|
25320
25513
|
mcp: async (command, signal) => {
|
|
25321
25514
|
signal.throwIfAborted();
|
|
@@ -25473,7 +25666,8 @@ ${summary2}`;
|
|
|
25473
25666
|
for (const key of Object.keys(subagentStartedAt)) delete subagentStartedAt[key];
|
|
25474
25667
|
for (const key of Object.keys(subagentElapsedMs)) delete subagentElapsedMs[key];
|
|
25475
25668
|
const previousIdeSessionId = ideSessionId;
|
|
25476
|
-
sessionId = `session-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "").slice(0, 17)}-${
|
|
25669
|
+
sessionId = `session-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "").slice(0, 17)}-${randomUUID24().slice(0, 8)}`;
|
|
25670
|
+
hookSessionId = sessionId;
|
|
25477
25671
|
harnessJournal = new HarnessJournal({ workspace, sessionId });
|
|
25478
25672
|
setUsageSession(sessionId);
|
|
25479
25673
|
ideSessionId = sessionId;
|
|
@@ -25772,9 +25966,10 @@ function formatMcpReconnect(server) {
|
|
|
25772
25966
|
if (server.status === "disabled") return `MCP server "${server.name}" is disabled. Enable it before reconnecting.`;
|
|
25773
25967
|
return `Failed to reconnect MCP server "${server.name}": ${server.error ?? "unknown error"}`;
|
|
25774
25968
|
}
|
|
25775
|
-
async function* runLoopSession(orchestrator, goal, signal) {
|
|
25969
|
+
async function* runLoopSession(orchestrator, hooks, goal, signal) {
|
|
25776
25970
|
let totalInputTokens = 0;
|
|
25777
25971
|
let totalOutputTokens = 0;
|
|
25972
|
+
let latestVerification;
|
|
25778
25973
|
for await (const event of orchestrator.run({ goal, signal })) {
|
|
25779
25974
|
if (event.type === "worker-event") {
|
|
25780
25975
|
if (event.event.type === "usage") {
|
|
@@ -25788,8 +25983,19 @@ async function* runLoopSession(orchestrator, goal, signal) {
|
|
|
25788
25983
|
} else if (event.event.type !== "done") yield event.event;
|
|
25789
25984
|
continue;
|
|
25790
25985
|
}
|
|
25986
|
+
if (event.type === "loop-verification") latestVerification = event.evidence;
|
|
25791
25987
|
yield loopProgressEvent(event);
|
|
25792
25988
|
if (event.type === "loop-terminal") {
|
|
25989
|
+
await hooks.emit({
|
|
25990
|
+
version: 1,
|
|
25991
|
+
type: "LoopEnd",
|
|
25992
|
+
payload: {
|
|
25993
|
+
loopId: event.loopId,
|
|
25994
|
+
outcome: event.status,
|
|
25995
|
+
reason: event.reason,
|
|
25996
|
+
verification: latestVerification ?? null
|
|
25997
|
+
}
|
|
25998
|
+
}).catch(() => void 0);
|
|
25793
25999
|
yield { type: "done", usage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens } };
|
|
25794
26000
|
}
|
|
25795
26001
|
}
|
|
@@ -26503,7 +26709,7 @@ function memoryTranscriptHash(messages) {
|
|
|
26503
26709
|
return createHash20("sha256").update(visible, "utf8").digest("hex");
|
|
26504
26710
|
}
|
|
26505
26711
|
function createMemoryTaskId() {
|
|
26506
|
-
return `memory-${
|
|
26712
|
+
return `memory-${randomUUID24()}`;
|
|
26507
26713
|
}
|
|
26508
26714
|
|
|
26509
26715
|
// src/desktop/runtime-controller.ts
|
|
@@ -27487,13 +27693,13 @@ ${managed.output().slice(-4e3)}`);
|
|
|
27487
27693
|
}
|
|
27488
27694
|
|
|
27489
27695
|
// src/d2c/product.ts
|
|
27490
|
-
import { createHash as createHash23, randomUUID as
|
|
27696
|
+
import { createHash as createHash23, randomUUID as randomUUID26 } from "crypto";
|
|
27491
27697
|
import { copyFile as copyFile2, mkdir as mkdir25, readFile as readFile32, rename as rename13, stat as stat12, unlink as unlink6, writeFile as writeFile15 } from "fs/promises";
|
|
27492
27698
|
import { join as join36 } from "path";
|
|
27493
27699
|
import { z as z44 } from "zod";
|
|
27494
27700
|
|
|
27495
27701
|
// src/e2e/prd-governance.ts
|
|
27496
|
-
import { createHash as createHash22, randomUUID as
|
|
27702
|
+
import { createHash as createHash22, randomUUID as randomUUID25 } from "crypto";
|
|
27497
27703
|
import { readFile as readFile31, rename as rename12, rm as rm13, writeFile as writeFile14 } from "fs/promises";
|
|
27498
27704
|
function hashPrd(markdown) {
|
|
27499
27705
|
return createHash22("sha256").update(markdown, "utf8").digest("hex");
|
|
@@ -27593,7 +27799,7 @@ ${body}
|
|
|
27593
27799
|
|
|
27594
27800
|
`;
|
|
27595
27801
|
const markdown = `${current.slice(0, section.contentStart)}${replacement}${current.slice(section.contentEnd)}`;
|
|
27596
|
-
const temporary = `${path}.${process.pid}.${
|
|
27802
|
+
const temporary = `${path}.${process.pid}.${randomUUID25()}.tmp`;
|
|
27597
27803
|
try {
|
|
27598
27804
|
await writeFile14(temporary, markdown, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
27599
27805
|
await rename12(temporary, path);
|
|
@@ -27793,7 +27999,7 @@ async function writeD2cProductPlan(workspace, plan, operations = defaultPlanFile
|
|
|
27793
27999
|
const target = planPath(workspace, parsed.task);
|
|
27794
28000
|
await serializePlanWrite(target, async () => {
|
|
27795
28001
|
await mkdir25(taskDir(workspace, parsed.task), { recursive: true });
|
|
27796
|
-
const temporary = `${target}.${process.pid}.${
|
|
28002
|
+
const temporary = `${target}.${process.pid}.${randomUUID26()}.tmp`;
|
|
27797
28003
|
await writeFile15(temporary, `${JSON.stringify(parsed, null, 2)}
|
|
27798
28004
|
`, { encoding: "utf8", mode: 384 });
|
|
27799
28005
|
await replaceD2cProductPlanFile(temporary, target, operations);
|
|
@@ -30246,7 +30452,7 @@ function safeGitTarget(value) {
|
|
|
30246
30452
|
}
|
|
30247
30453
|
|
|
30248
30454
|
// src/desktop/worktree-manager.ts
|
|
30249
|
-
import { randomUUID as
|
|
30455
|
+
import { randomUUID as randomUUID27 } from "crypto";
|
|
30250
30456
|
import { mkdir as mkdir28, readFile as readFile37, readdir as readdir13, rm as rm17, stat as stat15, writeFile as writeFile18 } from "fs/promises";
|
|
30251
30457
|
import { basename as basename10, isAbsolute as isAbsolute19, join as join43, relative as relative27, resolve as resolve37, sep as sep27 } from "path";
|
|
30252
30458
|
var DesktopWorktreeManager = class {
|
|
@@ -30259,7 +30465,7 @@ var DesktopWorktreeManager = class {
|
|
|
30259
30465
|
async create(label) {
|
|
30260
30466
|
if (!await isGitRepository(this.#repository)) throw new Error("Task worktrees require a Git repository");
|
|
30261
30467
|
const safe = label.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 36) || "task";
|
|
30262
|
-
const suffix =
|
|
30468
|
+
const suffix = randomUUID27().slice(0, 8);
|
|
30263
30469
|
const id = `worktree-${safe}-${suffix}`;
|
|
30264
30470
|
const branch = `flavor/desktop-${safe}-${suffix}`;
|
|
30265
30471
|
const path = this.#safeStoragePath(id);
|
|
@@ -30723,7 +30929,7 @@ function emitManagedDesktopEvent(workspace, owner2, event) {
|
|
|
30723
30929
|
}
|
|
30724
30930
|
}
|
|
30725
30931
|
function createDesktopController(workspace, owner2) {
|
|
30726
|
-
const collaborationId =
|
|
30932
|
+
const collaborationId = randomUUID28();
|
|
30727
30933
|
return new DesktopRuntimeController({
|
|
30728
30934
|
emit: (event) => emitManagedDesktopEvent(workspace, owner2, event),
|
|
30729
30935
|
runD2cInteractionTests: (manifest, baseUrl, mockUrl) => d2cEmbedded.run(manifest, baseUrl, mockUrl),
|