@cydm/pie 1.0.11 → 1.0.12
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/builtin/extensions/ask-user/index.js +2 -2
- package/dist/builtin/extensions/plan-mode/index.js +2 -2
- package/dist/builtin/extensions/subagent/index.js +3 -3
- package/dist/builtin/extensions/todo/index.js +2 -2
- package/dist/chunks/{chunk-QACYLY3B.js → chunk-D7NAXU7F.js} +143 -24
- package/dist/chunks/{chunk-H6PTIABA.js → chunk-SW6G4XW2.js} +236 -51
- package/dist/chunks/{chunk-GNHANWYT.js → chunk-YLOLJRLJ.js} +2 -2
- package/dist/chunks/{src-M32UEGIU.js → src-LZC56DRG.js} +1 -1
- package/dist/cli.js +5 -5
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
createAskUserCapability
|
|
4
|
-
} from "../../../chunks/chunk-
|
|
5
|
-
import "../../../chunks/chunk-
|
|
4
|
+
} from "../../../chunks/chunk-SW6G4XW2.js";
|
|
5
|
+
import "../../../chunks/chunk-D7NAXU7F.js";
|
|
6
6
|
import "../../../chunks/chunk-TG2EQLX2.js";
|
|
7
7
|
|
|
8
8
|
// builtin/extensions/ask-user/index.ts
|
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
isPlanModeSafeCommand,
|
|
8
8
|
markCompletedPlanSteps,
|
|
9
9
|
restoreExecutionState
|
|
10
|
-
} from "../../../chunks/chunk-
|
|
11
|
-
import "../../../chunks/chunk-
|
|
10
|
+
} from "../../../chunks/chunk-SW6G4XW2.js";
|
|
11
|
+
import "../../../chunks/chunk-D7NAXU7F.js";
|
|
12
12
|
import "../../../chunks/chunk-TG2EQLX2.js";
|
|
13
13
|
|
|
14
14
|
// builtin/extensions/plan-mode/index.ts
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
createCliHostCapabilities
|
|
4
|
-
} from "../../../chunks/chunk-
|
|
4
|
+
} from "../../../chunks/chunk-YLOLJRLJ.js";
|
|
5
5
|
import {
|
|
6
6
|
createSharedFileSystemTools,
|
|
7
7
|
createSubagentCapability
|
|
8
|
-
} from "../../../chunks/chunk-
|
|
9
|
-
import "../../../chunks/chunk-
|
|
8
|
+
} from "../../../chunks/chunk-SW6G4XW2.js";
|
|
9
|
+
import "../../../chunks/chunk-D7NAXU7F.js";
|
|
10
10
|
import "../../../chunks/chunk-TG2EQLX2.js";
|
|
11
11
|
|
|
12
12
|
// builtin/extensions/subagent/index.ts
|
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
executeManageTodoList,
|
|
8
8
|
executionStateToTodos,
|
|
9
9
|
restoreExecutionState
|
|
10
|
-
} from "../../../chunks/chunk-
|
|
11
|
-
import "../../../chunks/chunk-
|
|
10
|
+
} from "../../../chunks/chunk-SW6G4XW2.js";
|
|
11
|
+
import "../../../chunks/chunk-D7NAXU7F.js";
|
|
12
12
|
import "../../../chunks/chunk-TG2EQLX2.js";
|
|
13
13
|
|
|
14
14
|
// builtin/extensions/todo/index.ts
|
|
@@ -3758,6 +3758,7 @@ var NodeHttpClient = class {
|
|
|
3758
3758
|
async request(url, options = {}) {
|
|
3759
3759
|
const requestStartTime = Date.now();
|
|
3760
3760
|
const requestId = `${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
3761
|
+
const requestTimeoutMs = options.timeoutMs ?? 6e4;
|
|
3761
3762
|
logHttp("DEBUG", `Request [${requestId}] started`, {
|
|
3762
3763
|
url: url.slice(0, 100),
|
|
3763
3764
|
method: options.method || "GET",
|
|
@@ -3857,13 +3858,32 @@ var NodeHttpClient = class {
|
|
|
3857
3858
|
let done = false;
|
|
3858
3859
|
let error = null;
|
|
3859
3860
|
let waiting = null;
|
|
3860
|
-
const
|
|
3861
|
+
const wake = (value) => {
|
|
3862
|
+
if (!waiting) return;
|
|
3863
|
+
const w = waiting;
|
|
3864
|
+
waiting = null;
|
|
3865
|
+
w(value);
|
|
3866
|
+
};
|
|
3867
|
+
const failStream = (e) => {
|
|
3868
|
+
if (done && error) return;
|
|
3869
|
+
error = e;
|
|
3870
|
+
done = true;
|
|
3871
|
+
wake({ done: true, value: void 0 });
|
|
3872
|
+
logHttp("ERROR", `Request [${requestId}] SSE stream error`, { error: e.message });
|
|
3873
|
+
};
|
|
3874
|
+
const flushBuffer = (final = false) => {
|
|
3861
3875
|
if (bufferLength === 0) return;
|
|
3862
3876
|
const buffer = Buffer.concat(bufferChunks, bufferLength);
|
|
3863
3877
|
const bufferStr = buffer.toString("utf-8");
|
|
3864
3878
|
const lines = bufferStr.split("\n");
|
|
3865
3879
|
const lastLine = lines.pop();
|
|
3866
|
-
if (
|
|
3880
|
+
if (final) {
|
|
3881
|
+
if (lastLine !== void 0 && lastLine.length > 0) {
|
|
3882
|
+
lines.push(lastLine);
|
|
3883
|
+
}
|
|
3884
|
+
bufferChunks = [];
|
|
3885
|
+
bufferLength = 0;
|
|
3886
|
+
} else if (lastLine !== void 0) {
|
|
3867
3887
|
bufferChunks = [Buffer.from(lastLine)];
|
|
3868
3888
|
bufferLength = lastLine.length;
|
|
3869
3889
|
} else {
|
|
@@ -3874,10 +3894,17 @@ var NodeHttpClient = class {
|
|
|
3874
3894
|
lineQueue.push(line);
|
|
3875
3895
|
}
|
|
3876
3896
|
};
|
|
3897
|
+
let abortHandler = null;
|
|
3877
3898
|
if (signal) {
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3899
|
+
abortHandler = () => {
|
|
3900
|
+
failStream(new Error("Request was aborted"));
|
|
3901
|
+
res.destroy(new Error("Request was aborted"));
|
|
3902
|
+
};
|
|
3903
|
+
if (signal.aborted) {
|
|
3904
|
+
abortHandler();
|
|
3905
|
+
} else {
|
|
3906
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
3907
|
+
}
|
|
3881
3908
|
}
|
|
3882
3909
|
res.on("data", (chunk) => {
|
|
3883
3910
|
totalBytes += chunk.length;
|
|
@@ -3886,22 +3913,18 @@ var NodeHttpClient = class {
|
|
|
3886
3913
|
if (bufferLength > 16384 || chunk.includes(10)) {
|
|
3887
3914
|
flushBuffer();
|
|
3888
3915
|
}
|
|
3889
|
-
|
|
3890
|
-
const w = waiting;
|
|
3891
|
-
waiting = null;
|
|
3892
|
-
w({ done: false, value: void 0 });
|
|
3893
|
-
}
|
|
3916
|
+
wake({ done: false, value: void 0 });
|
|
3894
3917
|
});
|
|
3895
3918
|
res.on("end", () => {
|
|
3896
3919
|
if (bufferLength > 0) {
|
|
3897
|
-
flushBuffer();
|
|
3920
|
+
flushBuffer(true);
|
|
3898
3921
|
}
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
waiting = null;
|
|
3903
|
-
w({ done: true, value: void 0 });
|
|
3922
|
+
if (!res.complete) {
|
|
3923
|
+
failStream(new Error("SSE stream ended before response completed"));
|
|
3924
|
+
return;
|
|
3904
3925
|
}
|
|
3926
|
+
done = true;
|
|
3927
|
+
wake({ done: true, value: void 0 });
|
|
3905
3928
|
logHttp("DEBUG", `Request [${requestId}] SSE stream ended`, {
|
|
3906
3929
|
totalBytes,
|
|
3907
3930
|
lineCount,
|
|
@@ -3909,14 +3932,15 @@ var NodeHttpClient = class {
|
|
|
3909
3932
|
});
|
|
3910
3933
|
});
|
|
3911
3934
|
res.on("error", (e) => {
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3935
|
+
failStream(e);
|
|
3936
|
+
});
|
|
3937
|
+
res.on("aborted", () => {
|
|
3938
|
+
failStream(new Error("SSE stream aborted"));
|
|
3939
|
+
});
|
|
3940
|
+
res.on("close", () => {
|
|
3941
|
+
if (!done || !res.complete) {
|
|
3942
|
+
failStream(new Error("SSE stream closed before end"));
|
|
3918
3943
|
}
|
|
3919
|
-
logHttp("ERROR", `Request [${requestId}] SSE stream error`, { error: e.message });
|
|
3920
3944
|
});
|
|
3921
3945
|
try {
|
|
3922
3946
|
while (true) {
|
|
@@ -3936,9 +3960,12 @@ var NodeHttpClient = class {
|
|
|
3936
3960
|
const waitResult = await new Promise((r) => {
|
|
3937
3961
|
waiting = r;
|
|
3938
3962
|
});
|
|
3939
|
-
|
|
3963
|
+
void waitResult;
|
|
3940
3964
|
}
|
|
3941
3965
|
} finally {
|
|
3966
|
+
if (signal && abortHandler) {
|
|
3967
|
+
signal.removeEventListener("abort", abortHandler);
|
|
3968
|
+
}
|
|
3942
3969
|
if (!done && !res.destroyed) {
|
|
3943
3970
|
res.destroy();
|
|
3944
3971
|
}
|
|
@@ -3965,6 +3992,7 @@ var NodeHttpClient = class {
|
|
|
3965
3992
|
logHttp("ERROR", `Request [${requestId}] timeout`);
|
|
3966
3993
|
req.destroy(new Error("Request timeout"));
|
|
3967
3994
|
});
|
|
3995
|
+
req.setTimeout(requestTimeoutMs);
|
|
3968
3996
|
if (options.signal) {
|
|
3969
3997
|
options.signal.addEventListener("abort", () => {
|
|
3970
3998
|
logHttp("DEBUG", `Request [${requestId}] aborted`);
|
|
@@ -4371,6 +4399,47 @@ var FileSystemGateway = class {
|
|
|
4371
4399
|
const fs = nodeRequire("fs");
|
|
4372
4400
|
fs.writeFileSync(path, content, encoding);
|
|
4373
4401
|
}
|
|
4402
|
+
/**
|
|
4403
|
+
* Copy a file.
|
|
4404
|
+
*/
|
|
4405
|
+
copyFile(source, destination) {
|
|
4406
|
+
if (!this.allowWrites) {
|
|
4407
|
+
throw new Error(`Writes not allowed: ${destination}`);
|
|
4408
|
+
}
|
|
4409
|
+
this.validatePath(source, "copy");
|
|
4410
|
+
this.validatePath(destination, "copy");
|
|
4411
|
+
const platform = detectPlatform();
|
|
4412
|
+
const dir = this.dirname(destination);
|
|
4413
|
+
this.mkdir(dir, { recursive: true });
|
|
4414
|
+
if (platform === "puerts" && typeof CS !== "undefined") {
|
|
4415
|
+
CS.System.IO.File.Copy(source, destination, true);
|
|
4416
|
+
return;
|
|
4417
|
+
}
|
|
4418
|
+
const fs = nodeRequire("fs");
|
|
4419
|
+
fs.copyFileSync(source, destination);
|
|
4420
|
+
}
|
|
4421
|
+
/**
|
|
4422
|
+
* Rename or move a file.
|
|
4423
|
+
*/
|
|
4424
|
+
renameFile(source, destination) {
|
|
4425
|
+
if (!this.allowWrites) {
|
|
4426
|
+
throw new Error(`Writes not allowed: ${destination}`);
|
|
4427
|
+
}
|
|
4428
|
+
this.validatePath(source, "rename");
|
|
4429
|
+
this.validatePath(destination, "rename");
|
|
4430
|
+
const platform = detectPlatform();
|
|
4431
|
+
const dir = this.dirname(destination);
|
|
4432
|
+
this.mkdir(dir, { recursive: true });
|
|
4433
|
+
if (platform === "puerts" && typeof CS !== "undefined") {
|
|
4434
|
+
if (CS.System.IO.File.Exists(destination)) {
|
|
4435
|
+
CS.System.IO.File.Delete(destination);
|
|
4436
|
+
}
|
|
4437
|
+
CS.System.IO.File.Move(source, destination);
|
|
4438
|
+
return;
|
|
4439
|
+
}
|
|
4440
|
+
const fs = nodeRequire("fs");
|
|
4441
|
+
fs.renameSync(source, destination);
|
|
4442
|
+
}
|
|
4374
4443
|
/**
|
|
4375
4444
|
* Delete file
|
|
4376
4445
|
*/
|
|
@@ -4937,6 +5006,52 @@ function mapOpenAIStopReason(reason) {
|
|
|
4937
5006
|
}
|
|
4938
5007
|
}
|
|
4939
5008
|
|
|
5009
|
+
// ../../packages/ai/src/providers/assistant-content-validation.ts
|
|
5010
|
+
var EMPTY_ASSISTANT_CONTENT_ERROR = "stream ended without assistant content";
|
|
5011
|
+
var EMPTY_ASSISTANT_CONTENT_ERROR_CODE = "empty_assistant_content";
|
|
5012
|
+
var EmptyAssistantContentError = class extends Error {
|
|
5013
|
+
code = EMPTY_ASSISTANT_CONTENT_ERROR_CODE;
|
|
5014
|
+
constructor(message = EMPTY_ASSISTANT_CONTENT_ERROR) {
|
|
5015
|
+
super(message);
|
|
5016
|
+
this.name = "EmptyAssistantContentError";
|
|
5017
|
+
}
|
|
5018
|
+
};
|
|
5019
|
+
function hasAssistantContent(message) {
|
|
5020
|
+
return message.content.some((block) => {
|
|
5021
|
+
if (block.type === "text") {
|
|
5022
|
+
return block.text.trim().length > 0;
|
|
5023
|
+
}
|
|
5024
|
+
if (block.type === "thinking") {
|
|
5025
|
+
return block.thinking.trim().length > 0;
|
|
5026
|
+
}
|
|
5027
|
+
if (block.type === "toolCall") {
|
|
5028
|
+
return block.name.trim().length > 0;
|
|
5029
|
+
}
|
|
5030
|
+
return false;
|
|
5031
|
+
});
|
|
5032
|
+
}
|
|
5033
|
+
function assertAssistantHasContent(message) {
|
|
5034
|
+
if (!hasAssistantContent(message)) {
|
|
5035
|
+
throw new EmptyAssistantContentError();
|
|
5036
|
+
}
|
|
5037
|
+
}
|
|
5038
|
+
function isEmptyAssistantContentError(error) {
|
|
5039
|
+
return error instanceof EmptyAssistantContentError || typeof error === "object" && error !== null && "code" in error && error.code === EMPTY_ASSISTANT_CONTENT_ERROR_CODE;
|
|
5040
|
+
}
|
|
5041
|
+
function logEmptyAssistantContentError(error, model, options) {
|
|
5042
|
+
if (!isEmptyAssistantContentError(error)) {
|
|
5043
|
+
return;
|
|
5044
|
+
}
|
|
5045
|
+
getLogger().child({ module: "ai.provider" }).warn(EMPTY_ASSISTANT_CONTENT_ERROR, {
|
|
5046
|
+
code: EMPTY_ASSISTANT_CONTENT_ERROR_CODE,
|
|
5047
|
+
provider: model.provider,
|
|
5048
|
+
model: model.id,
|
|
5049
|
+
api: model.api,
|
|
5050
|
+
sessionId: options?.sessionId,
|
|
5051
|
+
metadata: options?.metadata
|
|
5052
|
+
});
|
|
5053
|
+
}
|
|
5054
|
+
|
|
4940
5055
|
// ../../packages/ai/src/providers/openai-compat.ts
|
|
4941
5056
|
var streamOpenAICompletions = (model, context, options) => {
|
|
4942
5057
|
const stream = new AssistantMessageEventStream();
|
|
@@ -5172,9 +5287,11 @@ var streamOpenAICompletions = (model, context, options) => {
|
|
|
5172
5287
|
if (output.stopReason === "aborted" || output.stopReason === "error") {
|
|
5173
5288
|
throw new Error("An unknown error occurred");
|
|
5174
5289
|
}
|
|
5290
|
+
assertAssistantHasContent(output);
|
|
5175
5291
|
stream.push({ type: "done", reason: output.stopReason, message: output });
|
|
5176
5292
|
stream.end();
|
|
5177
5293
|
} catch (error) {
|
|
5294
|
+
logEmptyAssistantContentError(error, model, options);
|
|
5178
5295
|
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
|
|
5179
5296
|
output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
|
|
5180
5297
|
stream.push({ type: "error", reason: output.stopReason, error: output });
|
|
@@ -5553,9 +5670,11 @@ var streamAnthropic = (model, context, options) => {
|
|
|
5553
5670
|
if (options?.signal?.aborted) {
|
|
5554
5671
|
throw new Error("Request was aborted");
|
|
5555
5672
|
}
|
|
5673
|
+
assertAssistantHasContent(output);
|
|
5556
5674
|
stream.push({ type: "done", reason: output.stopReason, message: output });
|
|
5557
5675
|
stream.end();
|
|
5558
5676
|
} catch (error) {
|
|
5677
|
+
logEmptyAssistantContentError(error, model, options);
|
|
5559
5678
|
for (const block of output.content) delete block.index;
|
|
5560
5679
|
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
|
|
5561
5680
|
output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
getFileSystem,
|
|
9
9
|
getPlatformConfig,
|
|
10
10
|
streamSimple
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-D7NAXU7F.js";
|
|
12
12
|
import {
|
|
13
13
|
__require
|
|
14
14
|
} from "./chunk-TG2EQLX2.js";
|
|
@@ -374,6 +374,182 @@ function createCompactionSummaryMessage(summary, timestamp) {
|
|
|
374
374
|
};
|
|
375
375
|
}
|
|
376
376
|
|
|
377
|
+
// ../../packages/agent-framework/src/session/durable-file.ts
|
|
378
|
+
var DEFAULT_FILE_RETRY_DELAYS_MS = [0, 25, 75, 150];
|
|
379
|
+
function durableFilePaths(filePath) {
|
|
380
|
+
return {
|
|
381
|
+
main: filePath,
|
|
382
|
+
backup: `${filePath}.bak`,
|
|
383
|
+
previous: `${filePath}.prev`
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
function isTransientFileError(error) {
|
|
387
|
+
const code = typeof error === "object" && error && "code" in error ? String(error.code) : "";
|
|
388
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
389
|
+
return /^(EPERM|EACCES|EBUSY|ENOTEMPTY)$/.test(code) || /\b(EPERM|EACCES|EBUSY|locked|busy)\b/i.test(message);
|
|
390
|
+
}
|
|
391
|
+
function sleep(ms) {
|
|
392
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
393
|
+
}
|
|
394
|
+
async function retryFileOperation(operation, retryDelaysMs) {
|
|
395
|
+
let lastError;
|
|
396
|
+
for (const [index, delayMs] of retryDelaysMs.entries()) {
|
|
397
|
+
if (delayMs > 0) {
|
|
398
|
+
await sleep(delayMs);
|
|
399
|
+
}
|
|
400
|
+
try {
|
|
401
|
+
operation();
|
|
402
|
+
return;
|
|
403
|
+
} catch (error) {
|
|
404
|
+
lastError = error;
|
|
405
|
+
if (!isTransientFileError(error) || index === retryDelaysMs.length - 1) {
|
|
406
|
+
throw error;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
throw lastError;
|
|
411
|
+
}
|
|
412
|
+
function retryDelays(options) {
|
|
413
|
+
return options.retryDelaysMs ?? DEFAULT_FILE_RETRY_DELAYS_MS;
|
|
414
|
+
}
|
|
415
|
+
function tempPathFor(filePath, operation) {
|
|
416
|
+
return `${filePath}.${operation}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
417
|
+
}
|
|
418
|
+
async function replaceFile(gateway, filePath, content, retryDelaysMs) {
|
|
419
|
+
const tempPath = tempPathFor(filePath, "durable");
|
|
420
|
+
gateway.writeFile(tempPath, content, "utf-8");
|
|
421
|
+
try {
|
|
422
|
+
try {
|
|
423
|
+
await retryFileOperation(() => gateway.renameFile(tempPath, filePath), retryDelaysMs);
|
|
424
|
+
} catch {
|
|
425
|
+
await retryFileOperation(() => gateway.copyFile(tempPath, filePath), retryDelaysMs);
|
|
426
|
+
try {
|
|
427
|
+
gateway.deleteFile(tempPath);
|
|
428
|
+
} catch {
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
} catch (error) {
|
|
432
|
+
try {
|
|
433
|
+
gateway.deleteFile(tempPath);
|
|
434
|
+
} catch {
|
|
435
|
+
}
|
|
436
|
+
throw error;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
async function copyExistingFile(gateway, sourcePath, destinationPath, retryDelaysMs) {
|
|
440
|
+
if (!gateway.exists(sourcePath)) {
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
await retryFileOperation(() => gateway.copyFile(sourcePath, destinationPath), retryDelaysMs);
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
446
|
+
function readCandidate(options, role, path3) {
|
|
447
|
+
if (!options.gateway.exists(path3)) {
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
const rawContent = options.gateway.readFile(path3, "utf-8");
|
|
451
|
+
const parsed = options.parse(rawContent, path3);
|
|
452
|
+
const updatedAt = Number.isFinite(parsed.updatedAt) ? parsed.updatedAt : 0;
|
|
453
|
+
return {
|
|
454
|
+
...parsed,
|
|
455
|
+
updatedAt,
|
|
456
|
+
role,
|
|
457
|
+
path: path3,
|
|
458
|
+
rawContent
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
function candidatePriority(role) {
|
|
462
|
+
if (role === "main") return 3;
|
|
463
|
+
if (role === "backup") return 2;
|
|
464
|
+
return 1;
|
|
465
|
+
}
|
|
466
|
+
function chooseBestCandidate(candidates) {
|
|
467
|
+
return [...candidates].sort((a, b) => {
|
|
468
|
+
const updatedAtDiff = b.updatedAt - a.updatedAt;
|
|
469
|
+
if (updatedAtDiff !== 0) return updatedAtDiff;
|
|
470
|
+
return candidatePriority(b.role) - candidatePriority(a.role);
|
|
471
|
+
})[0];
|
|
472
|
+
}
|
|
473
|
+
async function writeDurableFile(options, content) {
|
|
474
|
+
const parsed = options.parse(content, options.filePath);
|
|
475
|
+
const durableContent = parsed.content;
|
|
476
|
+
const paths = durableFilePaths(options.filePath);
|
|
477
|
+
const delays = retryDelays(options);
|
|
478
|
+
if (options.gateway.exists(paths.backup)) {
|
|
479
|
+
await copyExistingFile(options.gateway, paths.backup, paths.previous, delays);
|
|
480
|
+
}
|
|
481
|
+
await replaceFile(options.gateway, paths.backup, durableContent, delays);
|
|
482
|
+
await replaceFile(options.gateway, paths.main, durableContent, delays);
|
|
483
|
+
}
|
|
484
|
+
async function loadDurableFile(options) {
|
|
485
|
+
const paths = durableFilePaths(options.filePath);
|
|
486
|
+
const roles = [
|
|
487
|
+
["main", paths.main],
|
|
488
|
+
["backup", paths.backup],
|
|
489
|
+
["previous", paths.previous]
|
|
490
|
+
];
|
|
491
|
+
const candidates = [];
|
|
492
|
+
for (const [role, path3] of roles) {
|
|
493
|
+
try {
|
|
494
|
+
const candidate = readCandidate(options, role, path3);
|
|
495
|
+
if (candidate) {
|
|
496
|
+
candidates.push(candidate);
|
|
497
|
+
}
|
|
498
|
+
} catch {
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
if (candidates.length === 0) {
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
504
|
+
const best = chooseBestCandidate(candidates);
|
|
505
|
+
const main = candidates.find((candidate) => candidate.role === "main");
|
|
506
|
+
const backup = candidates.find((candidate) => candidate.role === "backup");
|
|
507
|
+
const needsMainRestore = !main || main.rawContent !== best.content;
|
|
508
|
+
const needsBackupRefresh = !backup || backup.rawContent !== best.content;
|
|
509
|
+
let restoredMain = false;
|
|
510
|
+
let refreshedBackup = false;
|
|
511
|
+
let repairError;
|
|
512
|
+
const delays = retryDelays(options);
|
|
513
|
+
try {
|
|
514
|
+
if (needsBackupRefresh) {
|
|
515
|
+
if (backup && backup.rawContent !== best.content) {
|
|
516
|
+
await replaceFile(options.gateway, paths.previous, backup.content, delays);
|
|
517
|
+
}
|
|
518
|
+
await replaceFile(options.gateway, paths.backup, best.content, delays);
|
|
519
|
+
refreshedBackup = true;
|
|
520
|
+
}
|
|
521
|
+
if (needsMainRestore) {
|
|
522
|
+
await replaceFile(options.gateway, paths.main, best.content, delays);
|
|
523
|
+
restoredMain = true;
|
|
524
|
+
}
|
|
525
|
+
} catch (error) {
|
|
526
|
+
repairError = error;
|
|
527
|
+
}
|
|
528
|
+
return {
|
|
529
|
+
data: best.data,
|
|
530
|
+
content: best.content,
|
|
531
|
+
source: best.role,
|
|
532
|
+
restoredMain,
|
|
533
|
+
refreshedBackup,
|
|
534
|
+
repairError
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
function durableFileExists(gateway, filePath) {
|
|
538
|
+
const paths = durableFilePaths(filePath);
|
|
539
|
+
return gateway.exists(paths.main) || gateway.exists(paths.backup) || gateway.exists(paths.previous);
|
|
540
|
+
}
|
|
541
|
+
function deleteDurableFile(gateway, filePath) {
|
|
542
|
+
const paths = durableFilePaths(filePath);
|
|
543
|
+
let deleted = false;
|
|
544
|
+
for (const path3 of [paths.main, paths.backup, paths.previous]) {
|
|
545
|
+
if (gateway.exists(path3)) {
|
|
546
|
+
gateway.deleteFile(path3);
|
|
547
|
+
deleted = true;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return deleted;
|
|
551
|
+
}
|
|
552
|
+
|
|
377
553
|
// ../../packages/agent-framework/src/session/store.ts
|
|
378
554
|
var SESSION_VERSION = 2;
|
|
379
555
|
function isSessionEntry(value) {
|
|
@@ -434,28 +610,6 @@ function migrateV1ToV2(data) {
|
|
|
434
610
|
// Keep for backward compatibility
|
|
435
611
|
};
|
|
436
612
|
}
|
|
437
|
-
function writeFileAtomic(gateway, filePath, content) {
|
|
438
|
-
const tempPath = `${filePath}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
439
|
-
gateway.writeFile(tempPath, content, "utf-8");
|
|
440
|
-
try {
|
|
441
|
-
const req = globalThis.require;
|
|
442
|
-
if (typeof req === "function") {
|
|
443
|
-
req("fs").renameSync(tempPath, filePath);
|
|
444
|
-
} else {
|
|
445
|
-
gateway.writeFile(filePath, content, "utf-8");
|
|
446
|
-
try {
|
|
447
|
-
gateway.deleteFile(tempPath);
|
|
448
|
-
} catch {
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
} catch {
|
|
452
|
-
gateway.writeFile(filePath, content, "utf-8");
|
|
453
|
-
try {
|
|
454
|
-
gateway.deleteFile(tempPath);
|
|
455
|
-
} catch {
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
613
|
var FileSessionStore = class {
|
|
460
614
|
sessionsDir;
|
|
461
615
|
gateway;
|
|
@@ -485,6 +639,33 @@ var FileSessionStore = class {
|
|
|
485
639
|
const safeId = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
486
640
|
return this.gateway.join(this.sessionsDir, `${safeId}.json`);
|
|
487
641
|
}
|
|
642
|
+
normalizeLoadedData(data) {
|
|
643
|
+
if (data.version === LEGACY_VERSION || !data.version) {
|
|
644
|
+
return { data: migrateV1ToV2(data), shouldPersist: true };
|
|
645
|
+
}
|
|
646
|
+
if (data.version !== SESSION_VERSION) {
|
|
647
|
+
console.warn(
|
|
648
|
+
`[SessionStore] Session version mismatch: ${data.version} vs ${SESSION_VERSION}`
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
if (!data.entries) {
|
|
652
|
+
data.entries = [];
|
|
653
|
+
}
|
|
654
|
+
return { data, shouldPersist: false };
|
|
655
|
+
}
|
|
656
|
+
parseSessionContent(content, filePath) {
|
|
657
|
+
if (!content || content.trim().length === 0) {
|
|
658
|
+
throw new Error("empty session file");
|
|
659
|
+
}
|
|
660
|
+
const parsed = JSON.parse(content);
|
|
661
|
+
const normalized = this.normalizeLoadedData(parsed);
|
|
662
|
+
const persistedContent = normalized.shouldPersist ? JSON.stringify(normalized.data, null, 2) : content;
|
|
663
|
+
return {
|
|
664
|
+
data: normalized.data,
|
|
665
|
+
content: persistedContent,
|
|
666
|
+
updatedAt: normalized.data.metadata?.updatedAt ?? 0
|
|
667
|
+
};
|
|
668
|
+
}
|
|
488
669
|
/**
|
|
489
670
|
* Save a session to disk (v2 format)
|
|
490
671
|
*/
|
|
@@ -514,7 +695,11 @@ var FileSessionStore = class {
|
|
|
514
695
|
};
|
|
515
696
|
const json = JSON.stringify(sessionData, null, 2);
|
|
516
697
|
const filePath = this.getSessionPath(sessionId);
|
|
517
|
-
|
|
698
|
+
await writeDurableFile({
|
|
699
|
+
gateway: this.gateway,
|
|
700
|
+
filePath,
|
|
701
|
+
parse: (content, path3) => this.parseSessionContent(content, path3)
|
|
702
|
+
}, json);
|
|
518
703
|
}
|
|
519
704
|
/**
|
|
520
705
|
* Legacy save method for backward compatibility
|
|
@@ -542,32 +727,23 @@ var FileSessionStore = class {
|
|
|
542
727
|
*/
|
|
543
728
|
async load(sessionId) {
|
|
544
729
|
const filePath = this.getSessionPath(sessionId);
|
|
545
|
-
if (!this.gateway.exists(filePath)) {
|
|
546
|
-
return null;
|
|
547
|
-
}
|
|
548
730
|
try {
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
this.
|
|
731
|
+
const loaded = await loadDurableFile({
|
|
732
|
+
gateway: this.gateway,
|
|
733
|
+
filePath,
|
|
734
|
+
parse: (content, path3) => this.parseSessionContent(content, path3)
|
|
735
|
+
});
|
|
736
|
+
if (!loaded) {
|
|
553
737
|
return null;
|
|
554
738
|
}
|
|
555
|
-
|
|
556
|
-
if (data.version === LEGACY_VERSION || !data.version) {
|
|
557
|
-
const migrated = migrateV1ToV2(data);
|
|
558
|
-
const migratedJson = JSON.stringify(migrated, null, 2);
|
|
559
|
-
writeFileAtomic(this.gateway, filePath, migratedJson);
|
|
560
|
-
return migrated;
|
|
561
|
-
}
|
|
562
|
-
if (data.version !== SESSION_VERSION) {
|
|
739
|
+
if (loaded.restoredMain || loaded.refreshedBackup) {
|
|
563
740
|
console.warn(
|
|
564
|
-
`[SessionStore]
|
|
741
|
+
`[SessionStore] Repaired session ${sessionId} from ${loaded.source}` + (loaded.repairError ? ` with repair warning: ${loaded.repairError}` : "")
|
|
565
742
|
);
|
|
743
|
+
} else if (loaded.repairError) {
|
|
744
|
+
console.warn(`[SessionStore] Loaded session ${sessionId} but sidecar refresh failed: ${loaded.repairError}`);
|
|
566
745
|
}
|
|
567
|
-
|
|
568
|
-
data.entries = [];
|
|
569
|
-
}
|
|
570
|
-
return data;
|
|
746
|
+
return loaded.data;
|
|
571
747
|
} catch (e) {
|
|
572
748
|
console.error(`[SessionStore] Failed to load session: ${sessionId}`, e);
|
|
573
749
|
return null;
|
|
@@ -578,12 +754,8 @@ var FileSessionStore = class {
|
|
|
578
754
|
*/
|
|
579
755
|
async delete(sessionId) {
|
|
580
756
|
const filePath = this.getSessionPath(sessionId);
|
|
581
|
-
if (!this.gateway.exists(filePath)) {
|
|
582
|
-
return false;
|
|
583
|
-
}
|
|
584
757
|
try {
|
|
585
|
-
this.gateway
|
|
586
|
-
return true;
|
|
758
|
+
return deleteDurableFile(this.gateway, filePath);
|
|
587
759
|
} catch (e) {
|
|
588
760
|
console.error(`[SessionStore] Failed to delete session: ${sessionId}`, e);
|
|
589
761
|
return false;
|
|
@@ -594,7 +766,7 @@ var FileSessionStore = class {
|
|
|
594
766
|
*/
|
|
595
767
|
async exists(sessionId) {
|
|
596
768
|
const filePath = this.getSessionPath(sessionId);
|
|
597
|
-
return this.gateway
|
|
769
|
+
return durableFileExists(this.gateway, filePath);
|
|
598
770
|
}
|
|
599
771
|
/**
|
|
600
772
|
* List all session IDs
|
|
@@ -604,7 +776,20 @@ var FileSessionStore = class {
|
|
|
604
776
|
return [];
|
|
605
777
|
}
|
|
606
778
|
const files = this.gateway.readdir(this.sessionsDir);
|
|
607
|
-
|
|
779
|
+
const sessionIds = /* @__PURE__ */ new Set();
|
|
780
|
+
for (const file of files) {
|
|
781
|
+
if (file.endsWith("-files.json") || file.endsWith("-files.json.bak") || file.endsWith("-files.json.prev")) {
|
|
782
|
+
continue;
|
|
783
|
+
}
|
|
784
|
+
if (file.endsWith(".json")) {
|
|
785
|
+
sessionIds.add(file.replace(/\.json$/i, ""));
|
|
786
|
+
} else if (file.endsWith(".json.bak")) {
|
|
787
|
+
sessionIds.add(file.replace(/\.json\.bak$/i, ""));
|
|
788
|
+
} else if (file.endsWith(".json.prev")) {
|
|
789
|
+
sessionIds.add(file.replace(/\.json\.prev$/i, ""));
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
return [...sessionIds];
|
|
608
793
|
}
|
|
609
794
|
/**
|
|
610
795
|
* List all session metadata
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
createSharedWebSearchTool,
|
|
9
9
|
interpretShellExit,
|
|
10
10
|
requestInteraction
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-SW6G4XW2.js";
|
|
12
12
|
import {
|
|
13
13
|
Type
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-D7NAXU7F.js";
|
|
15
15
|
|
|
16
16
|
// src/config.ts
|
|
17
17
|
import { existsSync, mkdirSync, readFileSync, renameSync } from "fs";
|
package/dist/cli.js
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
getSettingsPath,
|
|
15
15
|
getThemesDir,
|
|
16
16
|
migrateConfigFromAgentDir
|
|
17
|
-
} from "./chunks/chunk-
|
|
17
|
+
} from "./chunks/chunk-YLOLJRLJ.js";
|
|
18
18
|
import {
|
|
19
19
|
AGENTS_CONTEXT_FILE_NAME,
|
|
20
20
|
AgentSessionController,
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
selectToolsForRuntimePolicy,
|
|
53
53
|
shouldPreserveExecutionStateForUserText,
|
|
54
54
|
supersedeExecutionState
|
|
55
|
-
} from "./chunks/chunk-
|
|
55
|
+
} from "./chunks/chunk-SW6G4XW2.js";
|
|
56
56
|
import {
|
|
57
57
|
Deref,
|
|
58
58
|
Errors,
|
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
setLogger,
|
|
87
87
|
sortToolModelCandidatesByCapability,
|
|
88
88
|
type_exports
|
|
89
|
-
} from "./chunks/chunk-
|
|
89
|
+
} from "./chunks/chunk-D7NAXU7F.js";
|
|
90
90
|
import {
|
|
91
91
|
resolveCliProjectRoot
|
|
92
92
|
} from "./chunks/chunk-NTYHFBUA.js";
|
|
@@ -65347,7 +65347,7 @@ var InteractiveMode = class {
|
|
|
65347
65347
|
if (savedLevel) {
|
|
65348
65348
|
this.thinkingLevel = savedLevel;
|
|
65349
65349
|
}
|
|
65350
|
-
const { Agent } = await import("./chunks/src-
|
|
65350
|
+
const { Agent } = await import("./chunks/src-LZC56DRG.js");
|
|
65351
65351
|
const activeSession = this.sessionManager.getActiveSession();
|
|
65352
65352
|
this.agent = new Agent({
|
|
65353
65353
|
initialState: {
|
|
@@ -67340,7 +67340,7 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
67340
67340
|
`);
|
|
67341
67341
|
console.log("Assistant: ");
|
|
67342
67342
|
}
|
|
67343
|
-
const { Agent } = await import("./chunks/src-
|
|
67343
|
+
const { Agent } = await import("./chunks/src-LZC56DRG.js");
|
|
67344
67344
|
let agent;
|
|
67345
67345
|
const printModeExtensions = await loadPrintModeExtensions({
|
|
67346
67346
|
cwd,
|