chatroom-cli 1.102.2 → 1.103.1
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/index.js +710 -380
- package/dist/index.js.map +39 -31
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -27788,6 +27788,110 @@ function createHarnessActivityEmitter() {
|
|
|
27788
27788
|
}
|
|
27789
27789
|
var init_harness_activity_emitter = () => {};
|
|
27790
27790
|
|
|
27791
|
+
// ../../services/backend/src/domain/entities/harness/model-variant.ts
|
|
27792
|
+
function parseParamList(encoded, paramsPart) {
|
|
27793
|
+
const params = {};
|
|
27794
|
+
for (const param of paramsPart.split(",")) {
|
|
27795
|
+
if (!PARAM_RE.test(param)) {
|
|
27796
|
+
throw new ModelVariantParseError(`malformed variant param "${param}" in "${encoded}" (expected key=value)`);
|
|
27797
|
+
}
|
|
27798
|
+
const eq = param.indexOf("=");
|
|
27799
|
+
const key = param.slice(0, eq);
|
|
27800
|
+
if (Object.prototype.hasOwnProperty.call(params, key)) {
|
|
27801
|
+
throw new ModelVariantParseError(`duplicate variant param "${key}" in "${encoded}"`);
|
|
27802
|
+
}
|
|
27803
|
+
params[key] = param.slice(eq + 1);
|
|
27804
|
+
}
|
|
27805
|
+
return params;
|
|
27806
|
+
}
|
|
27807
|
+
function decodeModelVariant(encoded) {
|
|
27808
|
+
if (encoded.length === 0) {
|
|
27809
|
+
throw new ModelVariantParseError("empty model variant");
|
|
27810
|
+
}
|
|
27811
|
+
const match17 = MODEL_VARIANT_RE.exec(encoded);
|
|
27812
|
+
if (!match17) {
|
|
27813
|
+
throw new ModelVariantParseError(`malformed model variant: "${encoded}"`);
|
|
27814
|
+
}
|
|
27815
|
+
const [, model, paramsPart] = match17;
|
|
27816
|
+
if (paramsPart === undefined) {
|
|
27817
|
+
return { model, params: {} };
|
|
27818
|
+
}
|
|
27819
|
+
return { model, params: parseParamList(encoded, paramsPart) };
|
|
27820
|
+
}
|
|
27821
|
+
function encodeModelVariant(model, params = {}) {
|
|
27822
|
+
const entries2 = Object.entries(params);
|
|
27823
|
+
if (entries2.length === 0)
|
|
27824
|
+
return model;
|
|
27825
|
+
const paramsPart = entries2.map(([key, value]) => `${key}=${value}`).join(",");
|
|
27826
|
+
return `${model}[${paramsPart}]`;
|
|
27827
|
+
}
|
|
27828
|
+
function expandModelVariantCatalog(baseModelIds, combinations) {
|
|
27829
|
+
return baseModelIds.flatMap((id3) => combinations.map((combo) => encodeModelVariant(id3, combo)));
|
|
27830
|
+
}
|
|
27831
|
+
function describeCombination(combo) {
|
|
27832
|
+
const entries2 = Object.entries(combo);
|
|
27833
|
+
return entries2.length === 0 ? "no params" : entries2.map(([k, v2]) => `${k}=${v2}`).join(",");
|
|
27834
|
+
}
|
|
27835
|
+
function validateModelVariantParams(variant, schema) {
|
|
27836
|
+
const supported = schema.find((combo) => Object.keys(combo).length === Object.keys(variant.params).length && Object.entries(combo).every(([key, value]) => variant.params[key] === value));
|
|
27837
|
+
if (!supported) {
|
|
27838
|
+
throw new ModelVariantValidationError(`unsupported variant params for model "${variant.model}": ` + `${describeCombination(variant.params)}; ` + `allowed: ${schema.map(describeCombination).join(" | ")}`);
|
|
27839
|
+
}
|
|
27840
|
+
return variant;
|
|
27841
|
+
}
|
|
27842
|
+
var ModelVariantParseError, ModelVariantValidationError, MODEL_VARIANT_RE, PARAM_RE;
|
|
27843
|
+
var init_model_variant = __esm(() => {
|
|
27844
|
+
ModelVariantParseError = class ModelVariantParseError extends Error {
|
|
27845
|
+
code = "MODEL_VARIANT_PARSE";
|
|
27846
|
+
constructor(message) {
|
|
27847
|
+
super(message);
|
|
27848
|
+
this.name = "ModelVariantParseError";
|
|
27849
|
+
}
|
|
27850
|
+
};
|
|
27851
|
+
ModelVariantValidationError = class ModelVariantValidationError extends Error {
|
|
27852
|
+
code = "MODEL_VARIANT_VALIDATION";
|
|
27853
|
+
constructor(message) {
|
|
27854
|
+
super(message);
|
|
27855
|
+
this.name = "ModelVariantValidationError";
|
|
27856
|
+
}
|
|
27857
|
+
};
|
|
27858
|
+
MODEL_VARIANT_RE = /^([^\[\]]+?)(?:\[([^\]]*)\])?$/;
|
|
27859
|
+
PARAM_RE = /^[A-Za-z0-9_-]+=[^,\[\]\=]+$/;
|
|
27860
|
+
});
|
|
27861
|
+
|
|
27862
|
+
// src/daemon/infrastructure/local/harness/services/opencode-sdk/pure.ts
|
|
27863
|
+
function parseModelId(model) {
|
|
27864
|
+
if (!model)
|
|
27865
|
+
return;
|
|
27866
|
+
const slashIdx = model.indexOf("/");
|
|
27867
|
+
if (slashIdx === -1)
|
|
27868
|
+
return;
|
|
27869
|
+
const providerID = model.substring(0, slashIdx);
|
|
27870
|
+
const modelID = model.substring(slashIdx + 1);
|
|
27871
|
+
if (!providerID || !modelID)
|
|
27872
|
+
return;
|
|
27873
|
+
return { providerID, modelID };
|
|
27874
|
+
}
|
|
27875
|
+
function parseOpencodeSpawnModel(model) {
|
|
27876
|
+
if (!model.includes("["))
|
|
27877
|
+
return { model };
|
|
27878
|
+
const decoded = decodeModelVariant(model);
|
|
27879
|
+
const variant = decoded.params.variant;
|
|
27880
|
+
let resolvedModel = decoded.model;
|
|
27881
|
+
if (!resolvedModel.includes("/")) {
|
|
27882
|
+
const slashIdx = model.indexOf("/");
|
|
27883
|
+
const bracketIdx = model.indexOf("[");
|
|
27884
|
+
if (slashIdx !== -1 && slashIdx < bracketIdx) {
|
|
27885
|
+
resolvedModel = `${model.slice(0, slashIdx)}/${resolvedModel}`;
|
|
27886
|
+
}
|
|
27887
|
+
}
|
|
27888
|
+
return { model: resolvedModel, ...variant ? { variant } : {} };
|
|
27889
|
+
}
|
|
27890
|
+
var isInfoLine = (line) => line.trimStart().startsWith("INFO ");
|
|
27891
|
+
var init_pure = __esm(() => {
|
|
27892
|
+
init_model_variant();
|
|
27893
|
+
});
|
|
27894
|
+
|
|
27791
27895
|
// src/daemon/infrastructure/local/harness/services/session-log-callbacks.ts
|
|
27792
27896
|
function createSessionLogCallbacks() {
|
|
27793
27897
|
let logCb;
|
|
@@ -27805,6 +27909,7 @@ var OPENCODE_COMMAND = "opencode", OpenCodeAgentService;
|
|
|
27805
27909
|
var init_opencode_agent_service = __esm(() => {
|
|
27806
27910
|
init_harness_activity_emitter();
|
|
27807
27911
|
init_base_cli_agent_service();
|
|
27912
|
+
init_pure();
|
|
27808
27913
|
OpenCodeAgentService = class OpenCodeAgentService extends BaseCLIAgentService {
|
|
27809
27914
|
id = "opencode";
|
|
27810
27915
|
displayName = "OpenCode";
|
|
@@ -27826,9 +27931,13 @@ var init_opencode_agent_service = __esm(() => {
|
|
|
27826
27931
|
`).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
27827
27932
|
}
|
|
27828
27933
|
async spawn(options) {
|
|
27934
|
+
const parsed = options.model ? parseOpencodeSpawnModel(options.model) : undefined;
|
|
27829
27935
|
const args2 = ["run"];
|
|
27830
|
-
if (
|
|
27831
|
-
args2.push("--model",
|
|
27936
|
+
if (parsed?.model) {
|
|
27937
|
+
args2.push("--model", parsed.model);
|
|
27938
|
+
}
|
|
27939
|
+
if (parsed?.variant) {
|
|
27940
|
+
args2.push("--variant", parsed.variant);
|
|
27832
27941
|
}
|
|
27833
27942
|
const fullPrompt = options.systemPrompt ? `${options.systemPrompt}
|
|
27834
27943
|
|
|
@@ -28025,6 +28134,36 @@ class PiRpcReader {
|
|
|
28025
28134
|
}
|
|
28026
28135
|
var init_pi_rpc_reader = () => {};
|
|
28027
28136
|
|
|
28137
|
+
// src/daemon/infrastructure/local/harness/services/pi/pure.ts
|
|
28138
|
+
function parsePiSpawnModel(model) {
|
|
28139
|
+
if (!model.includes("["))
|
|
28140
|
+
return { model };
|
|
28141
|
+
const decoded = decodeModelVariant(model);
|
|
28142
|
+
const thinking = decoded.params.thinking;
|
|
28143
|
+
let resolvedModel = decoded.model;
|
|
28144
|
+
if (!resolvedModel.includes("/")) {
|
|
28145
|
+
const slashIdx = model.indexOf("/");
|
|
28146
|
+
const bracketIdx = model.indexOf("[");
|
|
28147
|
+
if (slashIdx !== -1 && slashIdx < bracketIdx) {
|
|
28148
|
+
resolvedModel = `${model.slice(0, slashIdx)}/${resolvedModel}`;
|
|
28149
|
+
}
|
|
28150
|
+
}
|
|
28151
|
+
return { model: resolvedModel, ...thinking ? { thinking } : {} };
|
|
28152
|
+
}
|
|
28153
|
+
function resolvePiThinkingLevel(thinking) {
|
|
28154
|
+
if (!thinking)
|
|
28155
|
+
return;
|
|
28156
|
+
if (PI_THINKING_LEVELS.includes(thinking)) {
|
|
28157
|
+
return thinking;
|
|
28158
|
+
}
|
|
28159
|
+
return;
|
|
28160
|
+
}
|
|
28161
|
+
var PI_THINKING_LEVELS;
|
|
28162
|
+
var init_pure2 = __esm(() => {
|
|
28163
|
+
init_model_variant();
|
|
28164
|
+
PI_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"];
|
|
28165
|
+
});
|
|
28166
|
+
|
|
28028
28167
|
// src/daemon/infrastructure/local/harness/services/agent-log-format.ts
|
|
28029
28168
|
function buildAgentLogPrefix(agent, context5) {
|
|
28030
28169
|
const roleTag = context5.role ?? "unknown";
|
|
@@ -28128,9 +28267,10 @@ function isExplicitToolError(result) {
|
|
|
28128
28267
|
function getPiSessionDir(workingDir) {
|
|
28129
28268
|
return join6(workingDir, ".chatroom", "pi-sessions");
|
|
28130
28269
|
}
|
|
28131
|
-
var PI_COMMAND = "pi", GET_STATE_TIMEOUT_MS = 5000,
|
|
28270
|
+
var PI_COMMAND = "pi", GET_STATE_TIMEOUT_MS = 5000, PiAgentService;
|
|
28132
28271
|
var init_pi_agent_service = __esm(() => {
|
|
28133
28272
|
init_pi_rpc_reader();
|
|
28273
|
+
init_pure2();
|
|
28134
28274
|
init_spawn_env();
|
|
28135
28275
|
init_harness_activity_emitter();
|
|
28136
28276
|
init_base_cli_agent_service();
|
|
@@ -28170,13 +28310,15 @@ var init_pi_agent_service = __esm(() => {
|
|
|
28170
28310
|
}
|
|
28171
28311
|
async spawn(options) {
|
|
28172
28312
|
const { prompt, systemPrompt, model, context: context5, workingDir } = options;
|
|
28313
|
+
const parsed = model ? parsePiSpawnModel(model) : undefined;
|
|
28173
28314
|
const childProcess = this.spawnPiRpcProcess({
|
|
28174
28315
|
workingDir,
|
|
28175
28316
|
systemPrompt,
|
|
28176
|
-
model,
|
|
28317
|
+
model: parsed?.model,
|
|
28318
|
+
thinking: parsed?.thinking,
|
|
28177
28319
|
resolvedConvexUrl: options.resolvedConvexUrl
|
|
28178
28320
|
});
|
|
28179
|
-
await this.
|
|
28321
|
+
await this.assertChildProcessStarted(childProcess);
|
|
28180
28322
|
if (!childProcess.stdout) {
|
|
28181
28323
|
throw new Error("Pi RPC process has no stdout");
|
|
28182
28324
|
}
|
|
@@ -28198,6 +28340,9 @@ var init_pi_agent_service = __esm(() => {
|
|
|
28198
28340
|
if (args2.model) {
|
|
28199
28341
|
rpcArgs.push("--model", args2.model);
|
|
28200
28342
|
}
|
|
28343
|
+
if (args2.thinking) {
|
|
28344
|
+
rpcArgs.push("--thinking", args2.thinking);
|
|
28345
|
+
}
|
|
28201
28346
|
if (args2.systemPrompt) {
|
|
28202
28347
|
rpcArgs.push("--system-prompt", args2.systemPrompt);
|
|
28203
28348
|
}
|
|
@@ -28210,15 +28355,6 @@ var init_pi_agent_service = __esm(() => {
|
|
|
28210
28355
|
});
|
|
28211
28356
|
return childProcess;
|
|
28212
28357
|
}
|
|
28213
|
-
async waitForSpawnReady(childProcess) {
|
|
28214
|
-
await new Promise((resolve2) => setTimeout(resolve2, SPAWN_READY_DELAY_MS2));
|
|
28215
|
-
if (childProcess.killed || childProcess.exitCode !== null) {
|
|
28216
|
-
throw new Error(`Agent process exited immediately (exit code: ${childProcess.exitCode})`);
|
|
28217
|
-
}
|
|
28218
|
-
if (!childProcess.pid) {
|
|
28219
|
-
throw new Error("Agent process started but has no PID");
|
|
28220
|
-
}
|
|
28221
|
-
}
|
|
28222
28358
|
writePrompt(child, prompt) {
|
|
28223
28359
|
return new Promise((resolve2, reject) => {
|
|
28224
28360
|
if (!child.stdin) {
|
|
@@ -28512,13 +28648,27 @@ function cursorLegacySlugToVariant(flatSlug) {
|
|
|
28512
28648
|
}
|
|
28513
28649
|
const effort = base.match(/-(low|medium|high|xhigh|max)$/)?.[1];
|
|
28514
28650
|
if (effort) {
|
|
28515
|
-
params.effort = effort === "max" ? "xhigh" : effort;
|
|
28651
|
+
params.effort = effort === "max" && base.includes("opus") ? "xhigh" : effort;
|
|
28516
28652
|
base = base.slice(0, -(effort.length + 1));
|
|
28517
28653
|
}
|
|
28518
28654
|
if (Object.keys(params).length === 0)
|
|
28519
28655
|
return;
|
|
28520
28656
|
return { base, params };
|
|
28521
28657
|
}
|
|
28658
|
+
function normalizeCursorParamsForCliSlug(params) {
|
|
28659
|
+
const out = {};
|
|
28660
|
+
const effort = params.effort ?? (params.reasoning && params.reasoning !== "none" ? params.reasoning : undefined);
|
|
28661
|
+
if (effort && effort !== "none") {
|
|
28662
|
+
out.effort = effort;
|
|
28663
|
+
}
|
|
28664
|
+
if (params.fast === "enabled" || params.fast === "true") {
|
|
28665
|
+
out.fast = "enabled";
|
|
28666
|
+
}
|
|
28667
|
+
if (params.thinking === "enabled" || params.thinking === "true") {
|
|
28668
|
+
out.thinking = "enabled";
|
|
28669
|
+
}
|
|
28670
|
+
return out;
|
|
28671
|
+
}
|
|
28522
28672
|
function cursorVariantToCliSlug(base, params) {
|
|
28523
28673
|
const suffix = [];
|
|
28524
28674
|
if (params.effort && params.effort !== "none")
|
|
@@ -28530,77 +28680,6 @@ function cursorVariantToCliSlug(base, params) {
|
|
|
28530
28680
|
return suffix.length ? `${base}-${suffix.join("-")}` : base;
|
|
28531
28681
|
}
|
|
28532
28682
|
|
|
28533
|
-
// ../../services/backend/src/domain/entities/harness/model-variant.ts
|
|
28534
|
-
function parseParamList(encoded, paramsPart) {
|
|
28535
|
-
const params = {};
|
|
28536
|
-
for (const param of paramsPart.split(",")) {
|
|
28537
|
-
if (!PARAM_RE.test(param)) {
|
|
28538
|
-
throw new ModelVariantParseError(`malformed variant param "${param}" in "${encoded}" (expected key=value)`);
|
|
28539
|
-
}
|
|
28540
|
-
const eq = param.indexOf("=");
|
|
28541
|
-
const key = param.slice(0, eq);
|
|
28542
|
-
if (Object.prototype.hasOwnProperty.call(params, key)) {
|
|
28543
|
-
throw new ModelVariantParseError(`duplicate variant param "${key}" in "${encoded}"`);
|
|
28544
|
-
}
|
|
28545
|
-
params[key] = param.slice(eq + 1);
|
|
28546
|
-
}
|
|
28547
|
-
return params;
|
|
28548
|
-
}
|
|
28549
|
-
function decodeModelVariant(encoded) {
|
|
28550
|
-
if (encoded.length === 0) {
|
|
28551
|
-
throw new ModelVariantParseError("empty model variant");
|
|
28552
|
-
}
|
|
28553
|
-
const match17 = MODEL_VARIANT_RE.exec(encoded);
|
|
28554
|
-
if (!match17) {
|
|
28555
|
-
throw new ModelVariantParseError(`malformed model variant: "${encoded}"`);
|
|
28556
|
-
}
|
|
28557
|
-
const [, model, paramsPart] = match17;
|
|
28558
|
-
if (paramsPart === undefined) {
|
|
28559
|
-
return { model, params: {} };
|
|
28560
|
-
}
|
|
28561
|
-
return { model, params: parseParamList(encoded, paramsPart) };
|
|
28562
|
-
}
|
|
28563
|
-
function encodeModelVariant(model, params = {}) {
|
|
28564
|
-
const entries2 = Object.entries(params);
|
|
28565
|
-
if (entries2.length === 0)
|
|
28566
|
-
return model;
|
|
28567
|
-
const paramsPart = entries2.map(([key, value]) => `${key}=${value}`).join(",");
|
|
28568
|
-
return `${model}[${paramsPart}]`;
|
|
28569
|
-
}
|
|
28570
|
-
function expandModelVariantCatalog(baseModelIds, combinations) {
|
|
28571
|
-
return baseModelIds.flatMap((id3) => combinations.map((combo) => encodeModelVariant(id3, combo)));
|
|
28572
|
-
}
|
|
28573
|
-
function describeCombination(combo) {
|
|
28574
|
-
const entries2 = Object.entries(combo);
|
|
28575
|
-
return entries2.length === 0 ? "no params" : entries2.map(([k, v2]) => `${k}=${v2}`).join(",");
|
|
28576
|
-
}
|
|
28577
|
-
function validateModelVariantParams(variant, schema) {
|
|
28578
|
-
const supported = schema.find((combo) => Object.keys(combo).length === Object.keys(variant.params).length && Object.entries(combo).every(([key, value]) => variant.params[key] === value));
|
|
28579
|
-
if (!supported) {
|
|
28580
|
-
throw new ModelVariantValidationError(`unsupported variant params for model "${variant.model}": ` + `${describeCombination(variant.params)}; ` + `allowed: ${schema.map(describeCombination).join(" | ")}`);
|
|
28581
|
-
}
|
|
28582
|
-
return variant;
|
|
28583
|
-
}
|
|
28584
|
-
var ModelVariantParseError, ModelVariantValidationError, MODEL_VARIANT_RE, PARAM_RE;
|
|
28585
|
-
var init_model_variant = __esm(() => {
|
|
28586
|
-
ModelVariantParseError = class ModelVariantParseError extends Error {
|
|
28587
|
-
code = "MODEL_VARIANT_PARSE";
|
|
28588
|
-
constructor(message) {
|
|
28589
|
-
super(message);
|
|
28590
|
-
this.name = "ModelVariantParseError";
|
|
28591
|
-
}
|
|
28592
|
-
};
|
|
28593
|
-
ModelVariantValidationError = class ModelVariantValidationError extends Error {
|
|
28594
|
-
code = "MODEL_VARIANT_VALIDATION";
|
|
28595
|
-
constructor(message) {
|
|
28596
|
-
super(message);
|
|
28597
|
-
this.name = "ModelVariantValidationError";
|
|
28598
|
-
}
|
|
28599
|
-
};
|
|
28600
|
-
MODEL_VARIANT_RE = /^([^\[\]]+?)(?:\[([^\]]*)\])?$/;
|
|
28601
|
-
PARAM_RE = /^[A-Za-z0-9_-]+=[^,\[\]\=]+$/;
|
|
28602
|
-
});
|
|
28603
|
-
|
|
28604
28683
|
// ../../services/backend/src/domain/entities/harness/model-provider.ts
|
|
28605
28684
|
function prefixModelWithProvider(provider, modelId) {
|
|
28606
28685
|
const bracket = modelId.indexOf("[");
|
|
@@ -28809,7 +28888,7 @@ function decodeCursorVariant(encoded) {
|
|
|
28809
28888
|
try {
|
|
28810
28889
|
const decoded = decodeModelVariant(encoded);
|
|
28811
28890
|
return {
|
|
28812
|
-
cliSlug: cursorVariantToCliSlug(decoded.model, decoded.params),
|
|
28891
|
+
cliSlug: cursorVariantToCliSlug(decoded.model, normalizeCursorParamsForCliSlug(decoded.params)),
|
|
28813
28892
|
params: decoded.params
|
|
28814
28893
|
};
|
|
28815
28894
|
} catch {
|
|
@@ -28838,9 +28917,7 @@ function decodedVariantToModelSelection(decoded) {
|
|
|
28838
28917
|
...params.length > 0 ? { params } : {}
|
|
28839
28918
|
};
|
|
28840
28919
|
}
|
|
28841
|
-
function resolveCursorSdkSpawnModelSelection(model
|
|
28842
|
-
if (!model)
|
|
28843
|
-
return { id: defaultModel };
|
|
28920
|
+
function resolveCursorSdkSpawnModelSelection(model) {
|
|
28844
28921
|
const bare = resolveCursorSdkModel(model);
|
|
28845
28922
|
if (bare.includes("[")) {
|
|
28846
28923
|
const decoded = decodeModelVariant(bare);
|
|
@@ -29949,6 +30026,18 @@ var init_claude_sdk_stream_adapter = __esm(() => {
|
|
|
29949
30026
|
};
|
|
29950
30027
|
});
|
|
29951
30028
|
|
|
30029
|
+
// src/daemon/infrastructure/local/harness/services/require-harness-model.ts
|
|
30030
|
+
function requireHarnessModel(model, context5) {
|
|
30031
|
+
const trimmed = model?.trim();
|
|
30032
|
+
if (!trimmed) {
|
|
30033
|
+
throw new Error(`Harness model is required (${context5})`);
|
|
30034
|
+
}
|
|
30035
|
+
return trimmed;
|
|
30036
|
+
}
|
|
30037
|
+
function resolveHarnessResumeModel(spawnModel, storedModel, context5) {
|
|
30038
|
+
return requireHarnessModel(spawnModel ?? storedModel, context5);
|
|
30039
|
+
}
|
|
30040
|
+
|
|
29952
30041
|
// src/daemon/infrastructure/local/harness/services/wire-native-stream-adapter.ts
|
|
29953
30042
|
function wireNativeStreamAdapter(args2) {
|
|
29954
30043
|
args2.adapter.setAssistantTextCapture((text) => {
|
|
@@ -29985,7 +30074,7 @@ async function withTimeout(p, ms, label) {
|
|
|
29985
30074
|
// src/daemon/infrastructure/local/harness/services/claude-sdk/claude-sdk-agent-service.ts
|
|
29986
30075
|
import { randomUUID } from "node:crypto";
|
|
29987
30076
|
function decodeClaudeSdkModel(model) {
|
|
29988
|
-
const variant = decodeClaudeVariant(model);
|
|
30077
|
+
const variant = decodeClaudeVariant(requireHarnessModel(model, "claude-sdk"));
|
|
29989
30078
|
return { model: variant?.model, effort: variant?.effort };
|
|
29990
30079
|
}
|
|
29991
30080
|
async function loadSdk() {
|
|
@@ -30408,7 +30497,8 @@ var init_claude_sdk_agent_service = __esm(() => {
|
|
|
30408
30497
|
}
|
|
30409
30498
|
}
|
|
30410
30499
|
async spawn(options) {
|
|
30411
|
-
const
|
|
30500
|
+
const resolvedModel = requireHarnessModel(options.model, "claude-sdk spawn");
|
|
30501
|
+
const { model, effort } = decodeClaudeSdkModel(resolvedModel);
|
|
30412
30502
|
const deferInitialTurn = options.deferInitialTurn ?? false;
|
|
30413
30503
|
const keeper = this.spawnKeeper(options.workingDir);
|
|
30414
30504
|
const pid = keeper.pid;
|
|
@@ -30442,7 +30532,8 @@ var init_claude_sdk_agent_service = __esm(() => {
|
|
|
30442
30532
|
const pid = keeper.pid;
|
|
30443
30533
|
await loadSdk();
|
|
30444
30534
|
const executablePath = await resolvePathToClaudeCodeExecutable();
|
|
30445
|
-
const
|
|
30535
|
+
const resolvedModel = resolveHarnessResumeModel(options.model, stored.model, "claude-sdk resumeFromDaemonMemory");
|
|
30536
|
+
const { model, effort } = decodeClaudeSdkModel(resolvedModel);
|
|
30446
30537
|
return this.startRunningSession({
|
|
30447
30538
|
pid,
|
|
30448
30539
|
keeper,
|
|
@@ -30478,7 +30569,8 @@ var init_codex_sdk_model_variants = __esm(() => {
|
|
|
30478
30569
|
{ reasoning: "low" },
|
|
30479
30570
|
{ reasoning: "medium" },
|
|
30480
30571
|
{ reasoning: "high" },
|
|
30481
|
-
{ reasoning: "xhigh" }
|
|
30572
|
+
{ reasoning: "xhigh" },
|
|
30573
|
+
{ reasoning: "max" }
|
|
30482
30574
|
];
|
|
30483
30575
|
});
|
|
30484
30576
|
|
|
@@ -31511,7 +31603,8 @@ ${deferredResume}` : deferredResume;
|
|
|
31511
31603
|
}
|
|
31512
31604
|
}
|
|
31513
31605
|
async spawn(options) {
|
|
31514
|
-
const
|
|
31606
|
+
const model = requireHarnessModel(options.model, "codex-sdk spawn");
|
|
31607
|
+
const variant = decodeCodexVariant(model);
|
|
31515
31608
|
const deferInitialTurn = options.deferInitialTurn ?? false;
|
|
31516
31609
|
const keeper = this.spawnKeeper(options.workingDir);
|
|
31517
31610
|
const pid = keeper.pid;
|
|
@@ -31542,7 +31635,7 @@ ${options.prompt}`;
|
|
|
31542
31635
|
thread,
|
|
31543
31636
|
context: context5,
|
|
31544
31637
|
workingDir: options.workingDir,
|
|
31545
|
-
model
|
|
31638
|
+
model,
|
|
31546
31639
|
initialPrompt: fullPrompt,
|
|
31547
31640
|
deferInitialTurn,
|
|
31548
31641
|
storedSystemPrompt: options.systemPrompt
|
|
@@ -31552,7 +31645,8 @@ ${options.prompt}`;
|
|
|
31552
31645
|
try {
|
|
31553
31646
|
const keeper = this.spawnKeeper(stored.workingDir);
|
|
31554
31647
|
const pid = keeper.pid;
|
|
31555
|
-
const
|
|
31648
|
+
const model = resolveHarnessResumeModel(options.model, stored.model, "codex-sdk resumeFromDaemonMemory");
|
|
31649
|
+
const variant = decodeCodexVariant(model);
|
|
31556
31650
|
const { Codex } = await loadSdk2();
|
|
31557
31651
|
const codexPath = resolveCodexExecutablePath();
|
|
31558
31652
|
const codex = new Codex({
|
|
@@ -31567,7 +31661,7 @@ ${options.prompt}`;
|
|
|
31567
31661
|
thread,
|
|
31568
31662
|
context: options.context,
|
|
31569
31663
|
workingDir: stored.workingDir,
|
|
31570
|
-
model
|
|
31664
|
+
model,
|
|
31571
31665
|
initialPrompt: options.prompt,
|
|
31572
31666
|
storedSystemPrompt: options.systemPrompt,
|
|
31573
31667
|
resumedThreadId: stored.harnessSessionId
|
|
@@ -32225,7 +32319,8 @@ var init_cursor_sdk_agent_service = __esm(() => {
|
|
|
32225
32319
|
const context5 = options.context;
|
|
32226
32320
|
const logPrefix = buildAgentLogPrefix("cursor-sdk", context5);
|
|
32227
32321
|
const agentName = stored.agentName;
|
|
32228
|
-
const
|
|
32322
|
+
const model = resolveHarnessResumeModel(options.model, stored.model, "cursor-sdk resumeFromDaemonMemory");
|
|
32323
|
+
const modelSelection = resolveCursorSdkSpawnModelSelection(model);
|
|
32229
32324
|
const systemPrompt = options.systemPrompt ? `${NO_SUBAGENT_DIRECTIVE2}
|
|
32230
32325
|
|
|
32231
32326
|
${options.systemPrompt}` : NO_SUBAGENT_DIRECTIVE2;
|
|
@@ -32252,7 +32347,7 @@ ${options.prompt}`;
|
|
|
32252
32347
|
agent,
|
|
32253
32348
|
context: context5,
|
|
32254
32349
|
agentName,
|
|
32255
|
-
model
|
|
32350
|
+
model,
|
|
32256
32351
|
workingDir: stored.workingDir,
|
|
32257
32352
|
initialPrompt: fullPrompt,
|
|
32258
32353
|
forceFirstTurn: true
|
|
@@ -32512,7 +32607,8 @@ ${deferredResume}` : deferredResume;
|
|
|
32512
32607
|
const context5 = options.context;
|
|
32513
32608
|
const logPrefix = buildAgentLogPrefix("cursor-sdk", context5);
|
|
32514
32609
|
const agentName = buildAgentName2(context5);
|
|
32515
|
-
const
|
|
32610
|
+
const model = requireHarnessModel(options.model, "cursor-sdk spawn");
|
|
32611
|
+
const modelSelection = resolveCursorSdkSpawnModelSelection(model);
|
|
32516
32612
|
const systemPrompt = options.systemPrompt ? `${NO_SUBAGENT_DIRECTIVE2}
|
|
32517
32613
|
|
|
32518
32614
|
${options.systemPrompt}` : NO_SUBAGENT_DIRECTIVE2;
|
|
@@ -32540,7 +32636,7 @@ ${options.prompt}`;
|
|
|
32540
32636
|
agent,
|
|
32541
32637
|
context: context5,
|
|
32542
32638
|
agentName,
|
|
32543
|
-
model
|
|
32639
|
+
model,
|
|
32544
32640
|
workingDir: options.workingDir,
|
|
32545
32641
|
initialPrompt: fullPrompt,
|
|
32546
32642
|
forceFirstTurn: !deferInitialTurn,
|
|
@@ -34513,21 +34609,6 @@ var init_parse_listening_url = __esm(() => {
|
|
|
34513
34609
|
LISTENING_URL_RE = /opencode server listening on (https?:\/\/127\.0\.0\.1:\d+(?:\/[^\s]*)?)/;
|
|
34514
34610
|
});
|
|
34515
34611
|
|
|
34516
|
-
// src/daemon/infrastructure/local/harness/services/opencode-sdk/pure.ts
|
|
34517
|
-
function parseModelId(model) {
|
|
34518
|
-
if (!model)
|
|
34519
|
-
return;
|
|
34520
|
-
const slashIdx = model.indexOf("/");
|
|
34521
|
-
if (slashIdx === -1)
|
|
34522
|
-
return;
|
|
34523
|
-
const providerID = model.substring(0, slashIdx);
|
|
34524
|
-
const modelID = model.substring(slashIdx + 1);
|
|
34525
|
-
if (!providerID || !modelID)
|
|
34526
|
-
return;
|
|
34527
|
-
return { providerID, modelID };
|
|
34528
|
-
}
|
|
34529
|
-
var isInfoLine = (line) => line.trimStart().startsWith("INFO ");
|
|
34530
|
-
|
|
34531
34612
|
// src/daemon/infrastructure/local/harness/services/opencode-sdk/select-agent.ts
|
|
34532
34613
|
function selectAgent(agents) {
|
|
34533
34614
|
const primaries = agents.filter((a) => a.mode !== "subagent");
|
|
@@ -35018,12 +35099,15 @@ var init_binary_agent_service = __esm(() => {
|
|
|
35018
35099
|
|
|
35019
35100
|
// src/daemon/infrastructure/local/harness/services/opencode-sdk/opencode-sdk-agent-service.ts
|
|
35020
35101
|
function buildDisabledToolsPromptBody(args2) {
|
|
35021
|
-
const
|
|
35102
|
+
const model = requireHarnessModel(args2.model, "opencode-sdk prompt");
|
|
35103
|
+
const parsed = parseOpencodeSpawnModel(model);
|
|
35104
|
+
const modelParts = parseModelId(parsed.model);
|
|
35022
35105
|
return {
|
|
35023
35106
|
agent: args2.agentName,
|
|
35024
35107
|
...args2.composedSystem ? { system: args2.composedSystem } : {},
|
|
35025
35108
|
parts: [{ type: "text", text: args2.prompt }],
|
|
35026
35109
|
...modelParts ? { model: modelParts } : {},
|
|
35110
|
+
...parsed.variant ? { variant: parsed.variant } : {},
|
|
35027
35111
|
tools: {
|
|
35028
35112
|
task: false,
|
|
35029
35113
|
question: false,
|
|
@@ -35035,6 +35119,7 @@ var SERVE_STARTUP_TIMEOUT_MS = 1e4, SESSION_CREATE_TIMEOUT_MS = 30000, PROMPT_AS
|
|
|
35035
35119
|
var init_opencode_sdk_agent_service = __esm(() => {
|
|
35036
35120
|
init_dist();
|
|
35037
35121
|
init_parse_listening_url();
|
|
35122
|
+
init_pure();
|
|
35038
35123
|
init_session_event_forwarder();
|
|
35039
35124
|
init_session_metadata_store();
|
|
35040
35125
|
init_spawn_env();
|
|
@@ -35299,6 +35384,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
35299
35384
|
this.sessionStore.remove(args2.sessionId);
|
|
35300
35385
|
}
|
|
35301
35386
|
async startFreshSessionOnServe(args2) {
|
|
35387
|
+
const model = requireHarnessModel(args2.model, "opencode-sdk resume fallback");
|
|
35302
35388
|
const existingForwarder = this.forwarders.get(args2.pid);
|
|
35303
35389
|
existingForwarder?.stop();
|
|
35304
35390
|
this.forwarders.delete(args2.pid);
|
|
@@ -35354,14 +35440,14 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
35354
35440
|
await this.promptSessionAsync(client4, newSessionId2, buildDisabledToolsPromptBody({
|
|
35355
35441
|
agentName: args2.agentName,
|
|
35356
35442
|
prompt: args2.prompt,
|
|
35357
|
-
model
|
|
35443
|
+
model
|
|
35358
35444
|
}));
|
|
35359
35445
|
}
|
|
35360
35446
|
async resumeFromDaemonMemory(options, session2) {
|
|
35361
35447
|
const { prompt, systemPrompt, model, context: context5 } = options;
|
|
35362
35448
|
const sessionId = session2.harnessSessionId;
|
|
35363
35449
|
const agentName = session2.agentName;
|
|
35364
|
-
const modelForSession = model
|
|
35450
|
+
const modelForSession = resolveHarnessResumeModel(model, session2.model, "opencode-sdk resumeFromDaemonMemory");
|
|
35365
35451
|
const workingDir = session2.workingDir;
|
|
35366
35452
|
const { childProcess, pid, baseUrl, client: client4 } = await this.startServeAndClient(workingDir, options.resolvedConvexUrl);
|
|
35367
35453
|
let forwarder;
|
|
@@ -35408,7 +35494,8 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
35408
35494
|
});
|
|
35409
35495
|
}
|
|
35410
35496
|
async spawn(options) {
|
|
35411
|
-
const { prompt, systemPrompt,
|
|
35497
|
+
const { prompt, systemPrompt, context: context5 } = options;
|
|
35498
|
+
const model = requireHarnessModel(options.model, "opencode-sdk spawn");
|
|
35412
35499
|
const deferInitialTurn = options.deferInitialTurn ?? false;
|
|
35413
35500
|
const { childProcess, pid, baseUrl, client: client4 } = await this.startServeAndClient(options.workingDir, options.resolvedConvexUrl);
|
|
35414
35501
|
let sessionId;
|
|
@@ -35488,6 +35575,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
35488
35575
|
const activityEmitter = this.activityEmittersByPid.get(pid);
|
|
35489
35576
|
activityEmitter?.beginTurn();
|
|
35490
35577
|
const client4 = createOpencodeClient({ baseUrl: meta.baseUrl });
|
|
35578
|
+
const model = requireHarnessModel(meta.model, "opencode-sdk resumeTurn");
|
|
35491
35579
|
const deferredSystem = meta.deferredSystemPrompt;
|
|
35492
35580
|
const context5 = {
|
|
35493
35581
|
machineId: meta.machineId,
|
|
@@ -35499,7 +35587,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
35499
35587
|
agentName: meta.agentName,
|
|
35500
35588
|
prompt,
|
|
35501
35589
|
composedSystem: deferredSystem,
|
|
35502
|
-
model
|
|
35590
|
+
model
|
|
35503
35591
|
}));
|
|
35504
35592
|
if (deferredSystem) {
|
|
35505
35593
|
this.sessionStore.upsert({ ...meta, deferredSystemPrompt: undefined });
|
|
@@ -35511,7 +35599,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
35511
35599
|
baseUrl: meta.baseUrl,
|
|
35512
35600
|
context: context5,
|
|
35513
35601
|
agentName: meta.agentName,
|
|
35514
|
-
model
|
|
35602
|
+
model,
|
|
35515
35603
|
prompt,
|
|
35516
35604
|
oldSessionId: meta.sessionId
|
|
35517
35605
|
});
|
|
@@ -35775,17 +35863,13 @@ function waitForResumeOrAbort4(session2) {
|
|
|
35775
35863
|
})
|
|
35776
35864
|
]);
|
|
35777
35865
|
}
|
|
35778
|
-
function
|
|
35779
|
-
|
|
35780
|
-
|
|
35781
|
-
|
|
35782
|
-
|
|
35783
|
-
}
|
|
35784
|
-
const provider = model.slice(0, slash);
|
|
35785
|
-
const modelId = model.slice(slash + 1);
|
|
35786
|
-
return modelRegistry.find(provider, modelId);
|
|
35866
|
+
function resolveRequiredModel(modelRegistry, model) {
|
|
35867
|
+
const slash = model.indexOf("/");
|
|
35868
|
+
const resolved = slash === -1 ? modelRegistry.getAll().find((entry) => entry.id === model) : modelRegistry.find(model.slice(0, slash), model.slice(slash + 1));
|
|
35869
|
+
if (!resolved) {
|
|
35870
|
+
throw new Error(`Pi model not found: ${model}`);
|
|
35787
35871
|
}
|
|
35788
|
-
return
|
|
35872
|
+
return resolved;
|
|
35789
35873
|
}
|
|
35790
35874
|
function writeSpawnError4(logPrefix, err, emitLogLine) {
|
|
35791
35875
|
const line = formatAgentLogLine(logPrefix, "spawn-error", formatPiSdkLoadError(err));
|
|
@@ -35803,6 +35887,7 @@ var init_pi_sdk_agent_service = __esm(() => {
|
|
|
35803
35887
|
init_base_cli_agent_service();
|
|
35804
35888
|
init_detection_result();
|
|
35805
35889
|
init_pi_agent_service();
|
|
35890
|
+
init_pure2();
|
|
35806
35891
|
PiSdkAgentService = class PiSdkAgentService extends BaseCLIAgentService {
|
|
35807
35892
|
id = "pi-sdk";
|
|
35808
35893
|
displayName = "Pi (SDK)";
|
|
@@ -35848,6 +35933,78 @@ var init_pi_sdk_agent_service = __esm(() => {
|
|
|
35848
35933
|
return [];
|
|
35849
35934
|
}
|
|
35850
35935
|
}
|
|
35936
|
+
getHarnessReconnectContext(pid) {
|
|
35937
|
+
const session2 = this.sessions.get(pid);
|
|
35938
|
+
if (!session2) {
|
|
35939
|
+
return;
|
|
35940
|
+
}
|
|
35941
|
+
return {
|
|
35942
|
+
agentName: "builder",
|
|
35943
|
+
model: session2.model
|
|
35944
|
+
};
|
|
35945
|
+
}
|
|
35946
|
+
async resumeFromDaemonMemory(options, stored) {
|
|
35947
|
+
const model = resolveHarnessResumeModel(options.model, stored.model, "pi-sdk resumeFromDaemonMemory");
|
|
35948
|
+
const keeper = this.spawnKeeper(stored.workingDir);
|
|
35949
|
+
const pid = keeper.pid;
|
|
35950
|
+
try {
|
|
35951
|
+
const session2 = await this.openResumedSession({
|
|
35952
|
+
workingDir: stored.workingDir,
|
|
35953
|
+
systemPrompt: options.systemPrompt,
|
|
35954
|
+
harnessSessionId: stored.harnessSessionId
|
|
35955
|
+
});
|
|
35956
|
+
const fullPrompt = `${options.systemPrompt}
|
|
35957
|
+
|
|
35958
|
+
${options.prompt}`;
|
|
35959
|
+
return this.startRunningSession({
|
|
35960
|
+
pid,
|
|
35961
|
+
keeper,
|
|
35962
|
+
session: session2,
|
|
35963
|
+
context: options.context,
|
|
35964
|
+
workingDir: stored.workingDir,
|
|
35965
|
+
model,
|
|
35966
|
+
initialPrompt: fullPrompt,
|
|
35967
|
+
deferInitialTurn: false,
|
|
35968
|
+
storedSystemPrompt: options.systemPrompt
|
|
35969
|
+
});
|
|
35970
|
+
} catch (err) {
|
|
35971
|
+
writeSpawnError4(buildAgentLogPrefix("pi-sdk", options.context), err);
|
|
35972
|
+
keeper.kill();
|
|
35973
|
+
this.deleteProcess(pid);
|
|
35974
|
+
return this.spawn({ ...options, model });
|
|
35975
|
+
}
|
|
35976
|
+
}
|
|
35977
|
+
async openResumedSession(args2) {
|
|
35978
|
+
const {
|
|
35979
|
+
AuthStorage,
|
|
35980
|
+
createAgentSession,
|
|
35981
|
+
DefaultResourceLoader,
|
|
35982
|
+
getAgentDir,
|
|
35983
|
+
ModelRegistry,
|
|
35984
|
+
SessionManager
|
|
35985
|
+
} = await loadSdk4();
|
|
35986
|
+
const authStorage = AuthStorage.create();
|
|
35987
|
+
const modelRegistry = ModelRegistry.create(authStorage);
|
|
35988
|
+
const sessions = await SessionManager.list(args2.workingDir, getPiSessionDir(args2.workingDir));
|
|
35989
|
+
const match17 = sessions.find((s) => s.id === args2.harnessSessionId);
|
|
35990
|
+
if (!match17) {
|
|
35991
|
+
throw new Error(`Pi session ${args2.harnessSessionId} not found`);
|
|
35992
|
+
}
|
|
35993
|
+
const resourceLoader = new DefaultResourceLoader({
|
|
35994
|
+
cwd: args2.workingDir,
|
|
35995
|
+
agentDir: getAgentDir(),
|
|
35996
|
+
systemPromptOverride: () => args2.systemPrompt
|
|
35997
|
+
});
|
|
35998
|
+
await resourceLoader.reload();
|
|
35999
|
+
const { session: session2 } = await withTimeout(createAgentSession({
|
|
36000
|
+
cwd: args2.workingDir,
|
|
36001
|
+
sessionManager: SessionManager.open(match17.path, getPiSessionDir(args2.workingDir)),
|
|
36002
|
+
authStorage,
|
|
36003
|
+
modelRegistry,
|
|
36004
|
+
resourceLoader
|
|
36005
|
+
}), SESSION_CREATE_TIMEOUT_MS2, "createAgentSession");
|
|
36006
|
+
return session2;
|
|
36007
|
+
}
|
|
35851
36008
|
async resumeTurn(pid, prompt) {
|
|
35852
36009
|
const session2 = this.sessions.get(pid);
|
|
35853
36010
|
if (!session2) {
|
|
@@ -35907,10 +36064,10 @@ var init_pi_sdk_agent_service = __esm(() => {
|
|
|
35907
36064
|
} = await loadSdk4();
|
|
35908
36065
|
const authStorage = AuthStorage.create();
|
|
35909
36066
|
const modelRegistry = ModelRegistry.create(authStorage);
|
|
35910
|
-
const
|
|
35911
|
-
|
|
35912
|
-
|
|
35913
|
-
|
|
36067
|
+
const model = requireHarnessModel(args2.model, "pi-sdk spawn");
|
|
36068
|
+
const parsed = parsePiSpawnModel(model);
|
|
36069
|
+
const resolvedModel = resolveRequiredModel(modelRegistry, parsed.model ?? model);
|
|
36070
|
+
const thinkingLevel = resolvePiThinkingLevel(parsed?.thinking);
|
|
35914
36071
|
const agentDir = getAgentDir();
|
|
35915
36072
|
const resourceLoader = new DefaultResourceLoader({
|
|
35916
36073
|
cwd: args2.workingDir,
|
|
@@ -35921,6 +36078,7 @@ var init_pi_sdk_agent_service = __esm(() => {
|
|
|
35921
36078
|
const { session: session2 } = await withTimeout(createAgentSession({
|
|
35922
36079
|
cwd: args2.workingDir,
|
|
35923
36080
|
model: resolvedModel,
|
|
36081
|
+
...thinkingLevel ? { thinkingLevel } : {},
|
|
35924
36082
|
sessionManager: SessionManager.create(getPiSessionDir(args2.workingDir)),
|
|
35925
36083
|
authStorage,
|
|
35926
36084
|
modelRegistry,
|
|
@@ -35934,6 +36092,7 @@ var init_pi_sdk_agent_service = __esm(() => {
|
|
|
35934
36092
|
keeper,
|
|
35935
36093
|
session: session2,
|
|
35936
36094
|
context: context5,
|
|
36095
|
+
model,
|
|
35937
36096
|
initialPrompt,
|
|
35938
36097
|
deferInitialTurn = false,
|
|
35939
36098
|
storedSystemPrompt
|
|
@@ -35943,6 +36102,7 @@ var init_pi_sdk_agent_service = __esm(() => {
|
|
|
35943
36102
|
const logPrefix = buildAgentLogPrefix("pi-sdk", context5);
|
|
35944
36103
|
const sdkSession = {
|
|
35945
36104
|
session: session2,
|
|
36105
|
+
model,
|
|
35946
36106
|
keeper,
|
|
35947
36107
|
aborted: false,
|
|
35948
36108
|
storedSystemPrompt
|
|
@@ -36096,6 +36256,7 @@ ${deferredResume}` : deferredResume;
|
|
|
36096
36256
|
}
|
|
36097
36257
|
async spawn(options) {
|
|
36098
36258
|
const deferInitialTurn = options.deferInitialTurn ?? false;
|
|
36259
|
+
const model = requireHarnessModel(options.model, "pi-sdk spawn");
|
|
36099
36260
|
const keeper = this.spawnKeeper(options.workingDir);
|
|
36100
36261
|
const pid = keeper.pid;
|
|
36101
36262
|
const context5 = options.context;
|
|
@@ -36107,7 +36268,7 @@ ${options.prompt}`;
|
|
|
36107
36268
|
session2 = await this.createSession({
|
|
36108
36269
|
workingDir: options.workingDir,
|
|
36109
36270
|
systemPrompt: options.systemPrompt,
|
|
36110
|
-
model
|
|
36271
|
+
model
|
|
36111
36272
|
});
|
|
36112
36273
|
} catch (err) {
|
|
36113
36274
|
keeper.kill();
|
|
@@ -36120,7 +36281,7 @@ ${options.prompt}`;
|
|
|
36120
36281
|
session: session2,
|
|
36121
36282
|
context: context5,
|
|
36122
36283
|
workingDir: options.workingDir,
|
|
36123
|
-
model
|
|
36284
|
+
model,
|
|
36124
36285
|
initialPrompt: fullPrompt,
|
|
36125
36286
|
deferInitialTurn,
|
|
36126
36287
|
storedSystemPrompt: options.systemPrompt
|
|
@@ -79996,6 +80157,40 @@ var init_builder_to_planner = __esm(() => {
|
|
|
79996
80157
|
// ../../services/backend/src/domain/usecase/enhancer/enhancer-handoff-content.ts
|
|
79997
80158
|
var ENHANCER_USER_MESSAGE_PLACEHOLDER = "{{USER_MESSAGE}}";
|
|
79998
80159
|
|
|
80160
|
+
// ../../services/backend/prompts/utils/data-query-design.ts
|
|
80161
|
+
function getDataQueryDesignTemplateBlock() {
|
|
80162
|
+
return `## Persistent state and query pattern design
|
|
80163
|
+
|
|
80164
|
+
**Goal:** Small updates must not cause large cache invalidations. High-frequency writes use projections to smaller tables.
|
|
80165
|
+
|
|
80166
|
+
### 1. Sources of concern
|
|
80167
|
+
| Source | Write frequency | Read pattern | Risk |
|
|
80168
|
+
|--------|---------------|--------------|------|
|
|
80169
|
+
| \`<table/mutation>\` | \`<frequency>\` | \`<pattern>\` | \`<scan / hot partition>\` |
|
|
80170
|
+
|
|
80171
|
+
### 2. Schema design
|
|
80172
|
+
**Hot path:** \`<table>\` — fields, projection from \`<source>\`
|
|
80173
|
+
**Cold path:** \`<table>\` — …
|
|
80174
|
+
|
|
80175
|
+
\`\`\`typescript
|
|
80176
|
+
// target schema shape
|
|
80177
|
+
\`\`\`
|
|
80178
|
+
|
|
80179
|
+
### 3. Index design (within limits)
|
|
80180
|
+
| Table | Index | Serves query | Budget |
|
|
80181
|
+
|-------|-------|--------------|--------|
|
|
80182
|
+
|
|
80183
|
+
### 4. Query design (within limits)
|
|
80184
|
+
| Query | Index | Rows scanned | Timeout | Invalidation scope |
|
|
80185
|
+
|-------|-------|--------------|---------|-------------------|
|
|
80186
|
+
|
|
80187
|
+
\`\`\`typescript
|
|
80188
|
+
// target query signature
|
|
80189
|
+
\`\`\`
|
|
80190
|
+
|
|
80191
|
+
<!-- Write exactly "Not Applicable." for the entire section if no persistence changes -->`;
|
|
80192
|
+
}
|
|
80193
|
+
|
|
79999
80194
|
// ../../services/backend/prompts/utils/frontend-design-ux-checklist.ts
|
|
80000
80195
|
function getFrontendDesignUxPlanningPrinciplesBlock() {
|
|
80001
80196
|
return `<!-- Ground every flow in user history and repository patterns. Recommend one existing pattern when multiple exist; do not prescribe style choices the project has not adopted. -->`;
|
|
@@ -80073,36 +80268,7 @@ export function ComponentName({ ... }: Props) {
|
|
|
80073
80268
|
</handoff-frontend-design>
|
|
80074
80269
|
|
|
80075
80270
|
<handoff-data-design>
|
|
80076
|
-
|
|
80077
|
-
|
|
80078
|
-
**Goal:** Small updates must not cause large cache invalidations. High-frequency writes use projections to smaller tables.
|
|
80079
|
-
|
|
80080
|
-
### 1. Sources of concern
|
|
80081
|
-
| Source | Write frequency | Read pattern | Risk |
|
|
80082
|
-
|--------|---------------|--------------|------|
|
|
80083
|
-
| \`<table/mutation>\` | \`<frequency>\` | \`<pattern>\` | \`<scan / hot partition>\` |
|
|
80084
|
-
|
|
80085
|
-
### 2. Schema design
|
|
80086
|
-
**Hot path:** \`<table>\` — fields, projection from \`<source>\`
|
|
80087
|
-
**Cold path:** \`<table>\` — …
|
|
80088
|
-
|
|
80089
|
-
\`\`\`typescript
|
|
80090
|
-
// target schema shape
|
|
80091
|
-
\`\`\`
|
|
80092
|
-
|
|
80093
|
-
### 3. Index design (within limits)
|
|
80094
|
-
| Table | Index | Serves query | Budget |
|
|
80095
|
-
|-------|-------|--------------|--------|
|
|
80096
|
-
|
|
80097
|
-
### 4. Query design (within limits)
|
|
80098
|
-
| Query | Index | Rows scanned | Timeout | Invalidation scope |
|
|
80099
|
-
|-------|-------|--------------|---------|-------------------|
|
|
80100
|
-
|
|
80101
|
-
\`\`\`typescript
|
|
80102
|
-
// target query signature
|
|
80103
|
-
\`\`\`
|
|
80104
|
-
|
|
80105
|
-
<!-- Write exactly "Not Applicable." for the entire section if no persistence changes -->
|
|
80271
|
+
${getDataQueryDesignTemplateBlock()}
|
|
80106
80272
|
</handoff-data-design>
|
|
80107
80273
|
|
|
80108
80274
|
<handoff-notes>
|
|
@@ -80731,14 +80897,22 @@ var init_backlog = __esm(() => {
|
|
|
80731
80897
|
// ../../services/backend/src/domain/usecase/skills/modules/code-review/index.ts
|
|
80732
80898
|
var init_code_review = () => {};
|
|
80733
80899
|
|
|
80900
|
+
// ../../services/backend/src/domain/usecase/skills/modules/data-design/index.ts
|
|
80901
|
+
var init_data_design = () => {};
|
|
80902
|
+
|
|
80734
80903
|
// ../../services/backend/src/domain/usecase/skills/modules/defragmentation/index.ts
|
|
80735
80904
|
var init_defragmentation = () => {};
|
|
80736
80905
|
|
|
80906
|
+
// ../../services/backend/src/domain/usecase/skills/modules/user-centricity/index.ts
|
|
80907
|
+
var init_user_centricity = () => {};
|
|
80908
|
+
|
|
80737
80909
|
// ../../services/backend/src/domain/usecase/skills/registry.ts
|
|
80738
80910
|
var init_registry4 = __esm(() => {
|
|
80739
80911
|
init_backlog();
|
|
80740
80912
|
init_code_review();
|
|
80913
|
+
init_data_design();
|
|
80741
80914
|
init_defragmentation();
|
|
80915
|
+
init_user_centricity();
|
|
80742
80916
|
});
|
|
80743
80917
|
|
|
80744
80918
|
// ../../services/backend/prompts/sections/glossary.ts
|
|
@@ -80774,9 +80948,23 @@ var init_glossary = __esm(() => {
|
|
|
80774
80948
|
linkedSkillId: "code-review"
|
|
80775
80949
|
},
|
|
80776
80950
|
{
|
|
80777
|
-
term: "
|
|
80778
|
-
definition: "
|
|
80951
|
+
term: "defragmentation",
|
|
80952
|
+
definition: "Workflow for large or multi-surface revisions: study all relevant surfaces, establish a golden path, migrate every caller, then delete legacy implementations.",
|
|
80779
80953
|
linkedSkillId: "defragmentation"
|
|
80954
|
+
},
|
|
80955
|
+
{
|
|
80956
|
+
term: "user-centricity",
|
|
80957
|
+
definition: "Design guidance for UI changes: translate user intent into complete flows with explicit loading, empty, error, and success states, stable layout, project patterns, keyboard behavior, feedback, affordances, and destructive-action safeguards.",
|
|
80958
|
+
linkedSkillId: "user-centricity"
|
|
80959
|
+
},
|
|
80960
|
+
{
|
|
80961
|
+
term: "data-design",
|
|
80962
|
+
definition: "Persistence and query design guidance: make write/read risks, hot and cold paths, projections, indexes, scan limits, timeouts, and invalidation scope explicit.",
|
|
80963
|
+
linkedSkillId: "data-design"
|
|
80964
|
+
},
|
|
80965
|
+
{
|
|
80966
|
+
term: "structural-decisions",
|
|
80967
|
+
definition: "Meta-level architectural choices that persist in the codebase and influence consistency: " + "folder structure, file naming, interface definitions, and key abstraction names/locations " + "(e.g., Repository/Service layers)."
|
|
80780
80968
|
}
|
|
80781
80969
|
];
|
|
80782
80970
|
NATIVE_GLOSSARY_TERMS = [
|
|
@@ -81041,6 +81229,14 @@ var init_cursor_sdk_config = __esm(() => {
|
|
|
81041
81229
|
outputActivity: true,
|
|
81042
81230
|
processExited: true
|
|
81043
81231
|
},
|
|
81232
|
+
crashRecovery: {
|
|
81233
|
+
onSessionFailure: {
|
|
81234
|
+
maxAttempts: 6,
|
|
81235
|
+
intervalMs: 1e4,
|
|
81236
|
+
resumeFirstAttempts: 3,
|
|
81237
|
+
recoveryReason: "platform.cursor_sdk_session_reopen"
|
|
81238
|
+
}
|
|
81239
|
+
},
|
|
81044
81240
|
wireEvents: ["sdk.cursor.message", "sdk.cursor.run.completed", "wire.log.agent_end"]
|
|
81045
81241
|
};
|
|
81046
81242
|
});
|
|
@@ -102818,6 +103014,25 @@ function resolveResumableHarnessSessionId(snapshot) {
|
|
|
102818
103014
|
return snapshot.resumableHarnessSessionId ?? snapshot.harnessSessionId;
|
|
102819
103015
|
}
|
|
102820
103016
|
|
|
103017
|
+
// src/daemon/domain/entities/session-recovery-policy.ts
|
|
103018
|
+
function resolveSessionRecoveryPolicy(harness, classification2) {
|
|
103019
|
+
const caps = getHarnessCapabilities(harness);
|
|
103020
|
+
if (classification2.hadSessionFailure && caps.crashRecovery?.onSessionFailure) {
|
|
103021
|
+
return caps.crashRecovery.onSessionFailure;
|
|
103022
|
+
}
|
|
103023
|
+
return DEFAULT_CRASH_RECOVERY_POLICY;
|
|
103024
|
+
}
|
|
103025
|
+
var DEFAULT_CRASH_RECOVERY_POLICY;
|
|
103026
|
+
var init_session_recovery_policy = __esm(() => {
|
|
103027
|
+
init_types();
|
|
103028
|
+
DEFAULT_CRASH_RECOVERY_POLICY = {
|
|
103029
|
+
maxAttempts: 1,
|
|
103030
|
+
intervalMs: 0,
|
|
103031
|
+
resumeFirstAttempts: 0,
|
|
103032
|
+
recoveryReason: "platform.crash_recovery"
|
|
103033
|
+
};
|
|
103034
|
+
});
|
|
103035
|
+
|
|
102821
103036
|
// src/daemon/domain/usecase/classify-resume-storm-reason.ts
|
|
102822
103037
|
function classifyResumeStormReason(logLines) {
|
|
102823
103038
|
const blob = logLines.join(`
|
|
@@ -102926,18 +103141,6 @@ function appendRecentLogLine(slot, line) {
|
|
|
102926
103141
|
}
|
|
102927
103142
|
var RECENT_LOG_LINE_CAP2 = 100;
|
|
102928
103143
|
|
|
102929
|
-
// src/daemon/domain/usecase/cursor-sdk-session-reopen-retry.ts
|
|
102930
|
-
var CURSOR_SDK_SESSION_REOPEN_MAX_ATTEMPTS = 20, CURSOR_SDK_SESSION_REOPEN_INTERVAL_MS = 5000, CURSOR_SDK_SESSION_REOPEN_REASON = "platform.cursor_sdk_session_reopen", CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS = 3;
|
|
102931
|
-
|
|
102932
|
-
// src/daemon/domain/usecase/detect-cursor-sdk-run-error.ts
|
|
102933
|
-
function isCursorSdkRunErrorInLogs(logLines) {
|
|
102934
|
-
return logLines.some((line) => line.includes(" run-error]"));
|
|
102935
|
-
}
|
|
102936
|
-
function formatCursorSdkRunErrorMessage(logLines) {
|
|
102937
|
-
const line = [...logLines].reverse().find((l) => l.includes(" run-error]"));
|
|
102938
|
-
return line?.trim() ?? "Cursor SDK run failed";
|
|
102939
|
-
}
|
|
102940
|
-
|
|
102941
103144
|
// src/daemon/domain/usecase/handle-turn-completed.ts
|
|
102942
103145
|
async function handleTurnCompleted(deps, input, slot) {
|
|
102943
103146
|
if (await tryAbortResumeStorm(deps, input, slot)) {
|
|
@@ -103074,6 +103277,19 @@ var init_native_spawn_presence = __esm(() => {
|
|
|
103074
103277
|
init_execution_kind();
|
|
103075
103278
|
});
|
|
103076
103279
|
|
|
103280
|
+
// src/daemon/infrastructure/local/harness/session-monitors/no-op-session-monitor.ts
|
|
103281
|
+
var NO_FAILURE, noOpSessionMonitor;
|
|
103282
|
+
var init_no_op_session_monitor = __esm(() => {
|
|
103283
|
+
NO_FAILURE = {
|
|
103284
|
+
hadSessionFailure: false,
|
|
103285
|
+
failureKind: "none",
|
|
103286
|
+
recoverable: true
|
|
103287
|
+
};
|
|
103288
|
+
noOpSessionMonitor = {
|
|
103289
|
+
classifyExitFailure: () => NO_FAILURE
|
|
103290
|
+
};
|
|
103291
|
+
});
|
|
103292
|
+
|
|
103077
103293
|
// src/daemon/infrastructure/agent-process-manager/agent-process-manager.ts
|
|
103078
103294
|
function agentKey3(chatroomId, role) {
|
|
103079
103295
|
return `${chatroomId}:${role.toLowerCase()}`;
|
|
@@ -103083,7 +103299,7 @@ class AgentProcessManager {
|
|
|
103083
103299
|
deps;
|
|
103084
103300
|
slots = new Map;
|
|
103085
103301
|
lastHarnessSessions = new Map;
|
|
103086
|
-
|
|
103302
|
+
sessionRecoveryRetryInFlight = new Set;
|
|
103087
103303
|
exitRetryQueue = [];
|
|
103088
103304
|
exitRetryTimer = null;
|
|
103089
103305
|
turnEndQueue = new TurnEndQueue;
|
|
@@ -103501,12 +103717,12 @@ class AgentProcessManager {
|
|
|
103501
103717
|
});
|
|
103502
103718
|
}));
|
|
103503
103719
|
this.resetSlotAfterExit(slot);
|
|
103504
|
-
|
|
103720
|
+
const exitLifecyclePromise = this.emitExitEvent(slot, opts, ctx);
|
|
103505
103721
|
try {
|
|
103506
103722
|
await this.deps.persistence.clearAgentPid(this.deps.machineId, opts.chatroomId, opts.role);
|
|
103507
103723
|
} catch {}
|
|
103508
103724
|
this.untrackAllServices(opts.pid);
|
|
103509
|
-
lifecyclePromise.then(() => this.dispatchRestartAfterExit(opts, ctx, key)).catch(() => {});
|
|
103725
|
+
lifecyclePromise.then(() => this.dispatchRestartAfterExit(opts, ctx, key, exitLifecyclePromise)).catch(() => {});
|
|
103510
103726
|
}
|
|
103511
103727
|
captureExitContext(slot, opts, stopReason) {
|
|
103512
103728
|
return {
|
|
@@ -103554,7 +103770,7 @@ class AgentProcessManager {
|
|
|
103554
103770
|
slot.pendingOperation = undefined;
|
|
103555
103771
|
slot.nativeTurnPhase = undefined;
|
|
103556
103772
|
}
|
|
103557
|
-
|
|
103773
|
+
emitExitEvent(slot, opts, ctx) {
|
|
103558
103774
|
const stopReason = ctx.stopReason;
|
|
103559
103775
|
const exitArgs = {
|
|
103560
103776
|
sessionId: this.deps.sessionId,
|
|
@@ -103568,14 +103784,14 @@ class AgentProcessManager {
|
|
|
103568
103784
|
signal: opts.signal ?? undefined,
|
|
103569
103785
|
agentHarness: ctx.harness
|
|
103570
103786
|
};
|
|
103571
|
-
this.recordAgentExit(opts.role, exitArgs, "Failed to record agent exit event");
|
|
103787
|
+
return this.recordAgentExit(opts.role, exitArgs, "Failed to record agent exit event");
|
|
103572
103788
|
}
|
|
103573
103789
|
untrackAllServices(pid) {
|
|
103574
103790
|
for (const service3 of this.deps.agentServices.values()) {
|
|
103575
103791
|
service3.untrack(pid);
|
|
103576
103792
|
}
|
|
103577
103793
|
}
|
|
103578
|
-
dispatchRestartAfterExit(opts, ctx, _key) {
|
|
103794
|
+
dispatchRestartAfterExit(opts, ctx, _key, exitLifecyclePromise) {
|
|
103579
103795
|
if (this.isStopRequested(opts.chatroomId, opts.role)) {
|
|
103580
103796
|
return;
|
|
103581
103797
|
}
|
|
@@ -103586,14 +103802,123 @@ class AgentProcessManager {
|
|
|
103586
103802
|
}
|
|
103587
103803
|
return;
|
|
103588
103804
|
}
|
|
103589
|
-
this.maybeRestartAgent(opts, ctx);
|
|
103805
|
+
this.maybeRestartAgent(opts, ctx, exitLifecyclePromise);
|
|
103590
103806
|
}
|
|
103591
|
-
|
|
103592
|
-
|
|
103593
|
-
|
|
103807
|
+
maybeRestartAgent(opts, ctx, exitLifecyclePromise) {
|
|
103808
|
+
const { harness, recentLogLines } = ctx;
|
|
103809
|
+
const logs = recentLogLines ?? [];
|
|
103810
|
+
if (!harness || !ctx.workingDir) {
|
|
103811
|
+
console.log(`[AgentProcessManager] ⚠️ Cannot restart — missing harness or workingDir ` + `(role: ${opts.role}, harness: ${harness ?? "none"}, workingDir: ${ctx.workingDir ?? "none"})`);
|
|
103812
|
+
return;
|
|
103594
103813
|
}
|
|
103595
|
-
|
|
103596
|
-
|
|
103814
|
+
const monitor = this.deps.sessionMonitors.get(harness) ?? noOpSessionMonitor;
|
|
103815
|
+
const monitorCtx = {
|
|
103816
|
+
recentLogLines: logs,
|
|
103817
|
+
harness,
|
|
103818
|
+
wantResume: ctx.wantResume
|
|
103819
|
+
};
|
|
103820
|
+
const classification2 = monitor.classifyExitFailure(monitorCtx);
|
|
103821
|
+
this.retrySessionRecovery(opts, ctx, classification2, monitor, monitorCtx, exitLifecyclePromise);
|
|
103822
|
+
}
|
|
103823
|
+
async retrySessionRecovery(opts, ctx, classification2, monitor, monitorCtx, exitLifecyclePromise) {
|
|
103824
|
+
const harness = ctx.harness;
|
|
103825
|
+
const policy = resolveSessionRecoveryPolicy(harness, classification2);
|
|
103826
|
+
const key = agentKey3(opts.chatroomId, opts.role);
|
|
103827
|
+
const multiAttempt = policy.maxAttempts > 1;
|
|
103828
|
+
if (multiAttempt && this.sessionRecoveryRetryInFlight.has(key)) {
|
|
103829
|
+
return;
|
|
103830
|
+
}
|
|
103831
|
+
if (multiAttempt) {
|
|
103832
|
+
this.sessionRecoveryRetryInFlight.add(key);
|
|
103833
|
+
}
|
|
103834
|
+
try {
|
|
103835
|
+
await this.prepareSessionRecoveryBeforeRetry(opts, classification2, exitLifecyclePromise);
|
|
103836
|
+
const lastError = await this.runSessionRecoveryAttempts(opts, ctx, classification2, monitor, monitorCtx, policy, key, multiAttempt);
|
|
103837
|
+
if (lastError === null)
|
|
103838
|
+
return;
|
|
103839
|
+
if (multiAttempt) {
|
|
103840
|
+
const failureMessage = `${harness} session recovery failed after ${policy.maxAttempts} attempts: ${lastError}`;
|
|
103841
|
+
console.log(`[AgentProcessManager] ⛔ ${failureMessage}`);
|
|
103842
|
+
this.emitStartFailedEvent(opts.role, opts.chatroomId, failureMessage);
|
|
103843
|
+
} else {
|
|
103844
|
+
console.log(`[AgentProcessManager] ⚠️ Agent restart did not complete for ${opts.role}: ${lastError}`);
|
|
103845
|
+
}
|
|
103846
|
+
} catch (err) {
|
|
103847
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
103848
|
+
console.log(` ⚠️ Session recovery retry loop failed: ${message}`);
|
|
103849
|
+
this.emitStartFailedEvent(opts.role, opts.chatroomId, message);
|
|
103850
|
+
} finally {
|
|
103851
|
+
if (multiAttempt) {
|
|
103852
|
+
this.sessionRecoveryRetryInFlight.delete(key);
|
|
103853
|
+
}
|
|
103854
|
+
}
|
|
103855
|
+
}
|
|
103856
|
+
async prepareSessionRecoveryBeforeRetry(opts, classification2, exitLifecyclePromise) {
|
|
103857
|
+
if (!classification2.requiresTaskReleaseBeforeRecovery)
|
|
103858
|
+
return;
|
|
103859
|
+
this.clearLastInFlightTask(opts.chatroomId, opts.role);
|
|
103860
|
+
if (exitLifecyclePromise) {
|
|
103861
|
+
await exitLifecyclePromise;
|
|
103862
|
+
}
|
|
103863
|
+
}
|
|
103864
|
+
async runSessionRecoveryAttempts(opts, ctx, classification2, monitor, monitorCtx, policy, key, multiAttempt) {
|
|
103865
|
+
const generation = this.slots.get(key)?.stopGeneration;
|
|
103866
|
+
let lastError = "unknown";
|
|
103867
|
+
for (let attempt = 1;attempt <= policy.maxAttempts; attempt++) {
|
|
103868
|
+
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103869
|
+
return null;
|
|
103870
|
+
if (classification2.hadSessionFailure && policy.resumeFirstAttempts > 0 && attempt === policy.resumeFirstAttempts + 1) {
|
|
103871
|
+
this.clearHarnessSessionAfterResumePhaseFailure(key, opts);
|
|
103872
|
+
}
|
|
103873
|
+
const wantResume = monitor.resolveWantResume?.(attempt, classification2, monitorCtx) ?? (classification2.hadSessionFailure ? false : ctx.wantResume ?? true);
|
|
103874
|
+
if (multiAttempt) {
|
|
103875
|
+
const stored = this.lastHarnessSessions.get(key);
|
|
103876
|
+
const storedSessionId = stored ? resolveResumableHarnessSessionId(stored) : undefined;
|
|
103877
|
+
await this.emitSessionReopenRetry(opts.chatroomId, opts.role, attempt, policy.maxAttempts, attempt > 1 ? lastError : undefined, storedSessionId);
|
|
103878
|
+
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103879
|
+
return null;
|
|
103880
|
+
}
|
|
103881
|
+
const attemptResult = await this.executeSessionRecoveryAttempt(opts, ctx, policy, wantResume, multiAttempt, generation);
|
|
103882
|
+
if (attemptResult.kind === "success" || attemptResult.kind === "stopped")
|
|
103883
|
+
return null;
|
|
103884
|
+
if (attemptResult.kind === "crash_loop")
|
|
103885
|
+
return null;
|
|
103886
|
+
lastError = attemptResult.lastError;
|
|
103887
|
+
if (attempt < policy.maxAttempts && policy.intervalMs > 0) {
|
|
103888
|
+
await this.deps.clock.delay(policy.intervalMs);
|
|
103889
|
+
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103890
|
+
return null;
|
|
103891
|
+
}
|
|
103892
|
+
}
|
|
103893
|
+
return lastError;
|
|
103894
|
+
}
|
|
103895
|
+
async executeSessionRecoveryAttempt(opts, ctx, policy, wantResume, multiAttempt, generation) {
|
|
103896
|
+
const harness = ctx.harness;
|
|
103897
|
+
const ensureOpts = {
|
|
103898
|
+
chatroomId: opts.chatroomId,
|
|
103899
|
+
role: opts.role,
|
|
103900
|
+
agentHarness: harness,
|
|
103901
|
+
model: ctx.model,
|
|
103902
|
+
workingDir: ctx.workingDir,
|
|
103903
|
+
reason: policy.recoveryReason,
|
|
103904
|
+
wantResume
|
|
103905
|
+
};
|
|
103906
|
+
const result = await this.ensureRunning(ensureOpts);
|
|
103907
|
+
if (result.success)
|
|
103908
|
+
return { kind: "success" };
|
|
103909
|
+
if (this.isStopRequested(opts.chatroomId, opts.role, generation)) {
|
|
103910
|
+
return { kind: "stopped" };
|
|
103911
|
+
}
|
|
103912
|
+
const error51 = result.error ?? "unknown";
|
|
103913
|
+
if (!multiAttempt && result.error === "backoff") {
|
|
103914
|
+
await this.retryCrashRecoveryAfterBackoff(opts, ctx, ensureOpts, result.retryAfterMs);
|
|
103915
|
+
return { kind: "success" };
|
|
103916
|
+
}
|
|
103917
|
+
if (result.error === "crash_loop") {
|
|
103918
|
+
this.handleCrashLoopLimitReached(opts, ctx.recentLogLines);
|
|
103919
|
+
return { kind: "crash_loop" };
|
|
103920
|
+
}
|
|
103921
|
+
return { kind: "failed", lastError: error51 };
|
|
103597
103922
|
}
|
|
103598
103923
|
maybeEmitProviderUnavailable(chatroomId, role, slot) {
|
|
103599
103924
|
if (!slot || slot.harness !== "codex-sdk" || slot.providerUnavailableEmitted)
|
|
@@ -103625,48 +103950,6 @@ class AgentProcessManager {
|
|
|
103625
103950
|
recoverable: providerUnavailableRecoverable(classification2.reason)
|
|
103626
103951
|
}).catch(() => {});
|
|
103627
103952
|
}
|
|
103628
|
-
maybeRestartAgent(opts, ctx) {
|
|
103629
|
-
const { harness, model, workingDir, recentLogLines } = ctx;
|
|
103630
|
-
const logs = recentLogLines ?? [];
|
|
103631
|
-
if (!harness || !workingDir) {
|
|
103632
|
-
console.log(`[AgentProcessManager] ⚠️ Cannot restart — missing harness or workingDir ` + `(role: ${opts.role}, harness: ${harness ?? "none"}, workingDir: ${workingDir ?? "none"})`);
|
|
103633
|
-
return;
|
|
103634
|
-
}
|
|
103635
|
-
const hadRunError = this.hasCursorSdkRunErrorInContext(logs);
|
|
103636
|
-
if (harness === "cursor-sdk") {
|
|
103637
|
-
this.retryCursorSdkSessionReopen(opts, ctx, hadRunError);
|
|
103638
|
-
return;
|
|
103639
|
-
}
|
|
103640
|
-
this.attemptCrashRecoveryRestart(opts, ctx, {
|
|
103641
|
-
chatroomId: opts.chatroomId,
|
|
103642
|
-
role: opts.role,
|
|
103643
|
-
agentHarness: harness,
|
|
103644
|
-
model,
|
|
103645
|
-
workingDir,
|
|
103646
|
-
reason: "platform.crash_recovery",
|
|
103647
|
-
wantResume: hadRunError ? false : ctx.wantResume ?? true
|
|
103648
|
-
});
|
|
103649
|
-
}
|
|
103650
|
-
async attemptCrashRecoveryRestart(exitOpts, ctx, ensureOpts) {
|
|
103651
|
-
try {
|
|
103652
|
-
const result = await this.ensureRunning(ensureOpts);
|
|
103653
|
-
if (result.success)
|
|
103654
|
-
return;
|
|
103655
|
-
if (result.error === "backoff") {
|
|
103656
|
-
await this.retryCrashRecoveryAfterBackoff(exitOpts, ctx, ensureOpts, result.retryAfterMs);
|
|
103657
|
-
return;
|
|
103658
|
-
}
|
|
103659
|
-
if (result.error === "crash_loop") {
|
|
103660
|
-
this.handleCrashLoopLimitReached(exitOpts, ctx.recentLogLines);
|
|
103661
|
-
return;
|
|
103662
|
-
}
|
|
103663
|
-
console.log(`[AgentProcessManager] ⚠️ Agent restart did not complete for ${exitOpts.role}: ${result.error ?? "unknown"}`);
|
|
103664
|
-
} catch (err) {
|
|
103665
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
103666
|
-
console.log(` ⚠️ Failed to restart agent: ${message}`);
|
|
103667
|
-
this.emitStartFailedEvent(exitOpts.role, exitOpts.chatroomId, message);
|
|
103668
|
-
}
|
|
103669
|
-
}
|
|
103670
103953
|
async retryCrashRecoveryAfterBackoff(exitOpts, ctx, ensureOpts, retryAfterMs) {
|
|
103671
103954
|
if (retryAfterMs === undefined || retryAfterMs <= 0) {
|
|
103672
103955
|
return;
|
|
@@ -103704,71 +103987,6 @@ class AgentProcessManager {
|
|
|
103704
103987
|
});
|
|
103705
103988
|
}
|
|
103706
103989
|
}
|
|
103707
|
-
resolveCursorSdkReopenWantResume(hadRunError, attempt, ctx) {
|
|
103708
|
-
if (hadRunError && attempt <= CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS) {
|
|
103709
|
-
return true;
|
|
103710
|
-
}
|
|
103711
|
-
if (hadRunError) {
|
|
103712
|
-
return false;
|
|
103713
|
-
}
|
|
103714
|
-
return ctx.wantResume ?? true;
|
|
103715
|
-
}
|
|
103716
|
-
async retryCursorSdkSessionReopen(opts, ctx, hadRunError) {
|
|
103717
|
-
const key = agentKey3(opts.chatroomId, opts.role);
|
|
103718
|
-
if (this.sessionReopenRetryInFlight.has(key)) {
|
|
103719
|
-
return;
|
|
103720
|
-
}
|
|
103721
|
-
this.sessionReopenRetryInFlight.add(key);
|
|
103722
|
-
const generation = this.slots.get(key)?.stopGeneration;
|
|
103723
|
-
const harness = ctx.harness;
|
|
103724
|
-
const model = ctx.model;
|
|
103725
|
-
const workingDir = ctx.workingDir;
|
|
103726
|
-
let lastError = "unknown";
|
|
103727
|
-
try {
|
|
103728
|
-
for (let attempt = 1;attempt <= CURSOR_SDK_SESSION_REOPEN_MAX_ATTEMPTS; attempt++) {
|
|
103729
|
-
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103730
|
-
return;
|
|
103731
|
-
if (hadRunError && attempt === CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS + 1) {
|
|
103732
|
-
this.clearHarnessSessionAfterResumePhaseFailure(key, opts);
|
|
103733
|
-
}
|
|
103734
|
-
const wantResume = this.resolveCursorSdkReopenWantResume(hadRunError, attempt, ctx);
|
|
103735
|
-
const stored = this.lastHarnessSessions.get(key);
|
|
103736
|
-
const storedSessionId = stored ? resolveResumableHarnessSessionId(stored) : undefined;
|
|
103737
|
-
await this.emitSessionReopenRetry(opts.chatroomId, opts.role, attempt, attempt > 1 ? lastError : undefined, storedSessionId);
|
|
103738
|
-
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103739
|
-
return;
|
|
103740
|
-
const result = await this.ensureRunning({
|
|
103741
|
-
chatroomId: opts.chatroomId,
|
|
103742
|
-
role: opts.role,
|
|
103743
|
-
agentHarness: harness,
|
|
103744
|
-
model,
|
|
103745
|
-
workingDir,
|
|
103746
|
-
reason: CURSOR_SDK_SESSION_REOPEN_REASON,
|
|
103747
|
-
wantResume
|
|
103748
|
-
});
|
|
103749
|
-
if (result.success) {
|
|
103750
|
-
return;
|
|
103751
|
-
}
|
|
103752
|
-
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103753
|
-
return;
|
|
103754
|
-
lastError = result.error ?? "unknown";
|
|
103755
|
-
if (attempt < CURSOR_SDK_SESSION_REOPEN_MAX_ATTEMPTS) {
|
|
103756
|
-
await this.deps.clock.delay(CURSOR_SDK_SESSION_REOPEN_INTERVAL_MS);
|
|
103757
|
-
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103758
|
-
return;
|
|
103759
|
-
}
|
|
103760
|
-
}
|
|
103761
|
-
const failureMessage = `cursor-sdk session reopen failed after ${CURSOR_SDK_SESSION_REOPEN_MAX_ATTEMPTS} attempts: ${lastError}`;
|
|
103762
|
-
console.log(`[AgentProcessManager] ⛔ ${failureMessage}`);
|
|
103763
|
-
this.emitStartFailedEvent(opts.role, opts.chatroomId, failureMessage);
|
|
103764
|
-
} catch (err) {
|
|
103765
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
103766
|
-
console.log(` ⚠️ cursor-sdk session reopen retry loop failed: ${message}`);
|
|
103767
|
-
this.emitStartFailedEvent(opts.role, opts.chatroomId, message);
|
|
103768
|
-
} finally {
|
|
103769
|
-
this.sessionReopenRetryInFlight.delete(key);
|
|
103770
|
-
}
|
|
103771
|
-
}
|
|
103772
103990
|
emitStartFailedEvent(role, chatroomId, error51) {
|
|
103773
103991
|
logDaemonAuditEvent(this.deps.logEvent, {
|
|
103774
103992
|
type: "agent.startFailed",
|
|
@@ -103978,7 +104196,11 @@ class AgentProcessManager {
|
|
|
103978
104196
|
this.queueExitRetry({ role, args: exitArgs });
|
|
103979
104197
|
});
|
|
103980
104198
|
const emittedAt = this.deps.clock.now();
|
|
103981
|
-
this.deps.lifecycleOutbox.enqueue(buildExitedLifecycleFact(exitArgs, emittedAt)).
|
|
104199
|
+
return this.deps.lifecycleOutbox.enqueue(buildExitedLifecycleFact(exitArgs, emittedAt)).then(() => {
|
|
104200
|
+
return;
|
|
104201
|
+
}).catch((err) => {
|
|
104202
|
+
console.log(` ⚠️ Failed to enqueue agent exited lifecycle fact: ${err.message}`);
|
|
104203
|
+
});
|
|
103982
104204
|
}
|
|
103983
104205
|
async clearAgentPidQuietly(chatroomId, role) {
|
|
103984
104206
|
try {
|
|
@@ -104156,7 +104378,7 @@ class AgentProcessManager {
|
|
|
104156
104378
|
console.log(` ⚠️ Failed to emit sessionResumeFailed event: ${err.message}`);
|
|
104157
104379
|
}
|
|
104158
104380
|
}
|
|
104159
|
-
async emitSessionReopenRetry(chatroomId, role, attempt, error51, harnessSessionId) {
|
|
104381
|
+
async emitSessionReopenRetry(chatroomId, role, attempt, maxAttempts, error51, harnessSessionId) {
|
|
104160
104382
|
try {
|
|
104161
104383
|
await logDaemonAuditEvent(this.deps.logEvent, {
|
|
104162
104384
|
type: "agent.sessionReopenRetry",
|
|
@@ -104164,7 +104386,7 @@ class AgentProcessManager {
|
|
|
104164
104386
|
role,
|
|
104165
104387
|
machineId: this.deps.machineId,
|
|
104166
104388
|
attempt,
|
|
104167
|
-
maxAttempts
|
|
104389
|
+
maxAttempts,
|
|
104168
104390
|
...error51 ? { error: error51 } : {},
|
|
104169
104391
|
...harnessSessionId ? { harnessSessionId } : {}
|
|
104170
104392
|
});
|
|
@@ -104174,11 +104396,11 @@ class AgentProcessManager {
|
|
|
104174
104396
|
chatroomId,
|
|
104175
104397
|
role,
|
|
104176
104398
|
attempt,
|
|
104177
|
-
maxAttempts
|
|
104399
|
+
maxAttempts,
|
|
104178
104400
|
...error51 ? { error: error51 } : {},
|
|
104179
104401
|
...harnessSessionId ? { harnessSessionId } : {}
|
|
104180
104402
|
});
|
|
104181
|
-
console.log(`[AgentProcessManager] ✅ Emitted agent.sessionReopenRetry for ${role} (attempt ${attempt}/${
|
|
104403
|
+
console.log(`[AgentProcessManager] ✅ Emitted agent.sessionReopenRetry for ${role} (attempt ${attempt}/${maxAttempts})`);
|
|
104182
104404
|
} catch (err) {
|
|
104183
104405
|
console.log(` ⚠️ Failed to emit sessionReopenRetry event: ${err.message}`);
|
|
104184
104406
|
}
|
|
@@ -104757,6 +104979,7 @@ var init_agent_process_manager = __esm(() => {
|
|
|
104757
104979
|
init_agent_lifecycle_runtime();
|
|
104758
104980
|
init_agent_lifecycle_types();
|
|
104759
104981
|
init_agent_stop();
|
|
104982
|
+
init_session_recovery_policy();
|
|
104760
104983
|
init_spawn_policy();
|
|
104761
104984
|
init_abort_resume_storm();
|
|
104762
104985
|
init_classify_provider_error();
|
|
@@ -104768,6 +104991,99 @@ var init_agent_process_manager = __esm(() => {
|
|
|
104768
104991
|
init_native_task_delivery_coordinator();
|
|
104769
104992
|
init_native_turn_phase2();
|
|
104770
104993
|
init_native_spawn_presence();
|
|
104994
|
+
init_no_op_session_monitor();
|
|
104995
|
+
});
|
|
104996
|
+
|
|
104997
|
+
// src/daemon/domain/usecase/cursor-sdk-session-reopen-retry.ts
|
|
104998
|
+
var CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS = 3;
|
|
104999
|
+
|
|
105000
|
+
// src/daemon/domain/usecase/detect-cursor-sdk-run-error.ts
|
|
105001
|
+
function isCursorSdkRunErrorInLogs(logLines) {
|
|
105002
|
+
return logLines.some((line) => line.includes(" run-error]"));
|
|
105003
|
+
}
|
|
105004
|
+
function formatCursorSdkRunErrorMessage(logLines) {
|
|
105005
|
+
const line = [...logLines].reverse().find((l) => l.includes(" run-error]"));
|
|
105006
|
+
return line?.trim() ?? "Cursor SDK run failed";
|
|
105007
|
+
}
|
|
105008
|
+
function isCursorSdkAuthErrorInLogs(logLines) {
|
|
105009
|
+
if (classifyResumeStormReason(logLines) !== "auth_error")
|
|
105010
|
+
return false;
|
|
105011
|
+
return logLines.some((line) => line.includes("[cursor-sdk:"));
|
|
105012
|
+
}
|
|
105013
|
+
function hasCursorSdkSessionReopenTrigger(logLines) {
|
|
105014
|
+
return isCursorSdkRunErrorInLogs(logLines) || isCursorSdkAuthErrorInLogs(logLines);
|
|
105015
|
+
}
|
|
105016
|
+
var init_detect_cursor_sdk_run_error = __esm(() => {
|
|
105017
|
+
init_classify_resume_storm_reason();
|
|
105018
|
+
});
|
|
105019
|
+
|
|
105020
|
+
// src/daemon/infrastructure/local/harness/session-monitors/cursor-sdk-session-monitor.ts
|
|
105021
|
+
var cursorSdkSessionMonitor;
|
|
105022
|
+
var init_cursor_sdk_session_monitor = __esm(() => {
|
|
105023
|
+
init_detect_cursor_sdk_run_error();
|
|
105024
|
+
cursorSdkSessionMonitor = {
|
|
105025
|
+
classifyExitFailure(ctx) {
|
|
105026
|
+
const logs = ctx.recentLogLines;
|
|
105027
|
+
if (!hasCursorSdkSessionReopenTrigger(logs)) {
|
|
105028
|
+
return { hadSessionFailure: false, failureKind: "none", recoverable: true };
|
|
105029
|
+
}
|
|
105030
|
+
const auth = isCursorSdkAuthErrorInLogs(logs);
|
|
105031
|
+
console.log(`[CursorSdkSessionMonitor] session failure detected: ${formatCursorSdkRunErrorMessage(logs)}`);
|
|
105032
|
+
return {
|
|
105033
|
+
hadSessionFailure: true,
|
|
105034
|
+
failureKind: auth ? "auth_error" : "run_error",
|
|
105035
|
+
recoverable: true,
|
|
105036
|
+
requiresTaskReleaseBeforeRecovery: auth
|
|
105037
|
+
};
|
|
105038
|
+
},
|
|
105039
|
+
resolveWantResume(attempt, classification2, ctx) {
|
|
105040
|
+
if (classification2.hadSessionFailure && attempt <= CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS) {
|
|
105041
|
+
return true;
|
|
105042
|
+
}
|
|
105043
|
+
if (classification2.hadSessionFailure) {
|
|
105044
|
+
return false;
|
|
105045
|
+
}
|
|
105046
|
+
return ctx.wantResume ?? true;
|
|
105047
|
+
}
|
|
105048
|
+
};
|
|
105049
|
+
});
|
|
105050
|
+
|
|
105051
|
+
// src/daemon/infrastructure/local/harness/session-monitors/session-monitor-registry.ts
|
|
105052
|
+
function registerSessionMonitor(harnessId, monitor) {
|
|
105053
|
+
registry3.set(harnessId, monitor);
|
|
105054
|
+
}
|
|
105055
|
+
function getSessionMonitor(harnessId) {
|
|
105056
|
+
return registry3.get(harnessId);
|
|
105057
|
+
}
|
|
105058
|
+
function getAllSessionMonitors() {
|
|
105059
|
+
return new Map(registry3);
|
|
105060
|
+
}
|
|
105061
|
+
var registry3;
|
|
105062
|
+
var init_session_monitor_registry = __esm(() => {
|
|
105063
|
+
registry3 = new Map;
|
|
105064
|
+
});
|
|
105065
|
+
|
|
105066
|
+
// src/daemon/infrastructure/local/harness/session-monitors/init-session-monitors.ts
|
|
105067
|
+
function initSessionMonitorRegistry() {
|
|
105068
|
+
if (initialized2)
|
|
105069
|
+
return;
|
|
105070
|
+
for (const harness of AGENT_HARNESSES) {
|
|
105071
|
+
registerSessionMonitor(harness, harness === "cursor-sdk" ? cursorSdkSessionMonitor : noOpSessionMonitor);
|
|
105072
|
+
}
|
|
105073
|
+
for (const service3 of getAllHarnesses()) {
|
|
105074
|
+
if (!getSessionMonitor(service3.id)) {
|
|
105075
|
+
registerSessionMonitor(service3.id, noOpSessionMonitor);
|
|
105076
|
+
}
|
|
105077
|
+
}
|
|
105078
|
+
initialized2 = true;
|
|
105079
|
+
}
|
|
105080
|
+
var initialized2 = false;
|
|
105081
|
+
var init_init_session_monitors = __esm(() => {
|
|
105082
|
+
init_agent2();
|
|
105083
|
+
init_cursor_sdk_session_monitor();
|
|
105084
|
+
init_no_op_session_monitor();
|
|
105085
|
+
init_session_monitor_registry();
|
|
105086
|
+
init_registry2();
|
|
104771
105087
|
});
|
|
104772
105088
|
|
|
104773
105089
|
// src/daemon/entry/init-daemon.ts
|
|
@@ -104831,6 +105147,7 @@ function assembleDaemonSessionInit(args2) {
|
|
|
104831
105147
|
config: config4,
|
|
104832
105148
|
convexUrl,
|
|
104833
105149
|
agentServices,
|
|
105150
|
+
sessionMonitors,
|
|
104834
105151
|
cachedModels,
|
|
104835
105152
|
deps
|
|
104836
105153
|
} = args2;
|
|
@@ -104847,6 +105164,7 @@ function assembleDaemonSessionInit(args2) {
|
|
|
104847
105164
|
}),
|
|
104848
105165
|
logSink: activeLogSink,
|
|
104849
105166
|
agentServices,
|
|
105167
|
+
sessionMonitors,
|
|
104850
105168
|
backend: deps.backend,
|
|
104851
105169
|
sessionId: typedSessionId,
|
|
104852
105170
|
machineId,
|
|
@@ -105028,11 +105346,13 @@ Run: ${formatAuthLoginCommand(convexUrl)}`);
|
|
|
105028
105346
|
const config4 = yield* setupMachineEffect();
|
|
105029
105347
|
const { machineId } = config4;
|
|
105030
105348
|
initHarnessRegistry();
|
|
105349
|
+
initSessionMonitorRegistry();
|
|
105031
105350
|
const agentServices = new Map(getAllHarnesses().map((s) => [s.id, s]));
|
|
105351
|
+
const sessionMonitors = getAllSessionMonitors();
|
|
105032
105352
|
yield* registerMachineEffect(client4, typedSessionId, config4);
|
|
105033
105353
|
const cachedModels = yield* fetchCachedMachineModelsEffect(client4, typedSessionId, machineId);
|
|
105034
105354
|
yield* connectDaemonEffect(client4, typedSessionId, machineId);
|
|
105035
|
-
return { typedSessionId, config: config4, machineId, agentServices, cachedModels };
|
|
105355
|
+
return { typedSessionId, config: config4, machineId, agentServices, sessionMonitors, cachedModels };
|
|
105036
105356
|
}), activeLogSink, activeLogEvent, connectDaemonEffect = (client4, sessionId, machineId) => exports_Effect.tryPromise({
|
|
105037
105357
|
try: () => client4.mutation(api.machines.updateDaemonStatus, {
|
|
105038
105358
|
sessionId: asConvexSessionId(sessionId),
|
|
@@ -105120,6 +105440,8 @@ var init_init_daemon = __esm(() => {
|
|
|
105120
105440
|
init_agent_process_manager();
|
|
105121
105441
|
init_registry3();
|
|
105122
105442
|
init_services2();
|
|
105443
|
+
init_init_session_monitors();
|
|
105444
|
+
init_session_monitor_registry();
|
|
105123
105445
|
AUTH_WAIT_TIMEOUT_MS = 5 * 60 * 1000;
|
|
105124
105446
|
initDaemonEffect = exports_Effect.gen(function* () {
|
|
105125
105447
|
const lockAcquired = yield* exports_Effect.tryPromise({
|
|
@@ -105149,7 +105471,7 @@ var init_init_daemon = __esm(() => {
|
|
|
105149
105471
|
try: () => getConvexClient(),
|
|
105150
105472
|
catch: (e) => e
|
|
105151
105473
|
});
|
|
105152
|
-
const { typedSessionId, config: config4, machineId, agentServices, cachedModels } = yield* connectWithRetryEffect(client4, sessionId, convexUrl);
|
|
105474
|
+
const { typedSessionId, config: config4, machineId, agentServices, sessionMonitors, cachedModels } = yield* connectWithRetryEffect(client4, sessionId, convexUrl);
|
|
105153
105475
|
const init2 = assembleDaemonSessionInit({
|
|
105154
105476
|
client: client4,
|
|
105155
105477
|
typedSessionId,
|
|
@@ -105157,6 +105479,7 @@ var init_init_daemon = __esm(() => {
|
|
|
105157
105479
|
config: config4,
|
|
105158
105480
|
convexUrl,
|
|
105159
105481
|
agentServices,
|
|
105482
|
+
sessionMonitors,
|
|
105160
105483
|
cachedModels,
|
|
105161
105484
|
deps: createDefaultDeps22()
|
|
105162
105485
|
});
|
|
@@ -105455,7 +105778,8 @@ async function resumeSession(deps, input) {
|
|
|
105455
105778
|
const { harness, journalFactory, chunkExtractor, nowFn = Date.now } = deps;
|
|
105456
105779
|
const { harnessSessionId, opencodeSessionId } = input;
|
|
105457
105780
|
const session2 = await harness.resumeSession(opencodeSessionId, {
|
|
105458
|
-
harnessSessionId
|
|
105781
|
+
harnessSessionId,
|
|
105782
|
+
...input.model ? { model: input.model } : {}
|
|
105459
105783
|
});
|
|
105460
105784
|
const journal = journalFactory.create(harnessSessionId);
|
|
105461
105785
|
const unsubscribeEvents = session2.onEvent((event) => {
|
|
@@ -105781,6 +106105,7 @@ class ClaudeSdkHarness {
|
|
|
105781
106105
|
async newSession(config4) {
|
|
105782
106106
|
if (this.closed)
|
|
105783
106107
|
throw new Error("Harness is closed");
|
|
106108
|
+
const defaultModel = requireHarnessModel(config4.model, "claude-sdk newSession");
|
|
105784
106109
|
const opencodeSessionId = randomUUID6();
|
|
105785
106110
|
const session2 = new ClaudeSdkSession({
|
|
105786
106111
|
cwd: this.cwd,
|
|
@@ -105788,25 +106113,27 @@ class ClaudeSdkHarness {
|
|
|
105788
106113
|
query: this.query,
|
|
105789
106114
|
opencodeSessionId,
|
|
105790
106115
|
sessionTitle: config4.title ?? "",
|
|
105791
|
-
defaultModel
|
|
106116
|
+
defaultModel,
|
|
105792
106117
|
systemPrompt: config4.systemPrompt,
|
|
105793
106118
|
onClose: (id3) => this.sessions.delete(id3)
|
|
105794
106119
|
});
|
|
105795
106120
|
this.sessions.set(opencodeSessionId, session2);
|
|
105796
106121
|
return session2;
|
|
105797
106122
|
}
|
|
105798
|
-
async resumeSession(sessionId,
|
|
106123
|
+
async resumeSession(sessionId, options) {
|
|
105799
106124
|
if (this.closed)
|
|
105800
106125
|
throw new Error("Harness is closed");
|
|
105801
106126
|
const existing = this.sessions.get(sessionId);
|
|
105802
106127
|
if (existing)
|
|
105803
106128
|
return existing;
|
|
106129
|
+
const defaultModel = requireHarnessModel(options?.model, "claude-sdk resumeSession");
|
|
105804
106130
|
const session2 = new ClaudeSdkSession({
|
|
105805
106131
|
cwd: this.cwd,
|
|
105806
106132
|
executablePath: this.executablePath,
|
|
105807
106133
|
query: this.query,
|
|
105808
106134
|
opencodeSessionId: sessionId,
|
|
105809
106135
|
sessionTitle: "",
|
|
106136
|
+
defaultModel,
|
|
105810
106137
|
providerSessionId: sessionId,
|
|
105811
106138
|
resumeOnFirstQuery: true,
|
|
105812
106139
|
onClose: (id3) => this.sessions.delete(id3)
|
|
@@ -105829,7 +106156,7 @@ class ClaudeSdkHarness {
|
|
|
105829
106156
|
this.sessions.clear();
|
|
105830
106157
|
}
|
|
105831
106158
|
}
|
|
105832
|
-
var
|
|
106159
|
+
var _sdkCache5, _sdkLoadError5, _executablePathCache, startClaudeSdkHarness = async (config4) => {
|
|
105833
106160
|
try {
|
|
105834
106161
|
const sdk = await loadSdk5();
|
|
105835
106162
|
const executablePath = await loadExecutablePath();
|
|
@@ -106082,51 +106409,51 @@ class CursorSdkHarness {
|
|
|
106082
106409
|
}
|
|
106083
106410
|
];
|
|
106084
106411
|
}
|
|
106085
|
-
|
|
106086
|
-
if (this.closed)
|
|
106087
|
-
throw new Error("Harness is closed");
|
|
106412
|
+
requireApiKey() {
|
|
106088
106413
|
const apiKey = process.env.CURSOR_API_KEY?.trim();
|
|
106089
106414
|
if (!apiKey)
|
|
106090
106415
|
throw new Error("CURSOR_API_KEY is not set");
|
|
106091
|
-
|
|
106092
|
-
|
|
106093
|
-
|
|
106094
|
-
apiKey,
|
|
106095
|
-
model: modelSelection,
|
|
106096
|
-
local: { cwd: this.cwd, settingSources: [], enableAgentRetries: true }
|
|
106097
|
-
}), AGENT_CREATE_TIMEOUT_MS2, "Agent.create");
|
|
106416
|
+
return apiKey;
|
|
106417
|
+
}
|
|
106418
|
+
registerAgentSession(agent, sessionTitle) {
|
|
106098
106419
|
const session2 = new CursorSdkSession({
|
|
106099
106420
|
agent,
|
|
106100
106421
|
opencodeSessionId: agent.agentId,
|
|
106101
|
-
sessionTitle
|
|
106422
|
+
sessionTitle,
|
|
106102
106423
|
onClose: (id3) => this.sessions.delete(id3)
|
|
106103
106424
|
});
|
|
106104
106425
|
this.sessions.set(agent.agentId, session2);
|
|
106105
106426
|
return session2;
|
|
106106
106427
|
}
|
|
106107
|
-
async
|
|
106428
|
+
async newSession(config4) {
|
|
106429
|
+
if (this.closed)
|
|
106430
|
+
throw new Error("Harness is closed");
|
|
106431
|
+
const apiKey = this.requireApiKey();
|
|
106432
|
+
const model = requireHarnessModel(config4.model, "cursor-sdk newSession");
|
|
106433
|
+
const modelSelection = resolveCursorSdkSpawnModelSelection(model);
|
|
106434
|
+
const { Agent } = await loadSdk6();
|
|
106435
|
+
const agent = await withTimeout(Agent.create({
|
|
106436
|
+
apiKey,
|
|
106437
|
+
model: modelSelection,
|
|
106438
|
+
local: { cwd: this.cwd, settingSources: [], enableAgentRetries: true }
|
|
106439
|
+
}), AGENT_CREATE_TIMEOUT_MS2, "Agent.create");
|
|
106440
|
+
return this.registerAgentSession(agent, config4.title ?? "");
|
|
106441
|
+
}
|
|
106442
|
+
async resumeSession(sessionId, options) {
|
|
106108
106443
|
if (this.closed)
|
|
106109
106444
|
throw new Error("Harness is closed");
|
|
106110
106445
|
const existing = this.sessions.get(sessionId);
|
|
106111
106446
|
if (existing)
|
|
106112
106447
|
return existing;
|
|
106113
|
-
const
|
|
106114
|
-
|
|
106115
|
-
throw new Error("CURSOR_API_KEY is not set");
|
|
106448
|
+
const model = requireHarnessModel(options?.model, "cursor-sdk resumeSession");
|
|
106449
|
+
const apiKey = this.requireApiKey();
|
|
106116
106450
|
const { Agent } = await loadSdk6();
|
|
106117
106451
|
const agent = await withTimeout(Agent.resume(sessionId, {
|
|
106118
106452
|
apiKey,
|
|
106119
|
-
model: resolveCursorSdkSpawnModelSelection(
|
|
106453
|
+
model: resolveCursorSdkSpawnModelSelection(model),
|
|
106120
106454
|
local: { cwd: this.cwd, settingSources: [], enableAgentRetries: true }
|
|
106121
106455
|
}), AGENT_CREATE_TIMEOUT_MS2, "Agent.resume");
|
|
106122
|
-
|
|
106123
|
-
agent,
|
|
106124
|
-
opencodeSessionId: agent.agentId,
|
|
106125
|
-
sessionTitle: "",
|
|
106126
|
-
onClose: (id3) => this.sessions.delete(id3)
|
|
106127
|
-
});
|
|
106128
|
-
this.sessions.set(agent.agentId, session2);
|
|
106129
|
-
return session2;
|
|
106456
|
+
return this.registerAgentSession(agent, "");
|
|
106130
106457
|
}
|
|
106131
106458
|
async fetchSessionTitle(_opencodeSessionId) {
|
|
106132
106459
|
return;
|
|
@@ -106143,7 +106470,7 @@ class CursorSdkHarness {
|
|
|
106143
106470
|
this.sessions.clear();
|
|
106144
106471
|
}
|
|
106145
106472
|
}
|
|
106146
|
-
var
|
|
106473
|
+
var AGENT_CREATE_TIMEOUT_MS2 = 60000, _sdkCache6, _sdkLoadError6, startCursorSdkHarness = async (config4) => {
|
|
106147
106474
|
try {
|
|
106148
106475
|
await loadSdk6();
|
|
106149
106476
|
} catch (err) {
|
|
@@ -106470,6 +106797,7 @@ class OpencodeSdkHarness {
|
|
|
106470
106797
|
async newSession(config4) {
|
|
106471
106798
|
if (this.closed)
|
|
106472
106799
|
throw new Error("Harness is closed");
|
|
106800
|
+
requireHarnessModel(config4.model, "opencode-sdk newSession");
|
|
106473
106801
|
const created = await this.client.session.create({
|
|
106474
106802
|
body: {
|
|
106475
106803
|
...config4.title ? { title: config4.title } : {}
|
|
@@ -106805,17 +107133,13 @@ async function loadSdk7() {
|
|
|
106805
107133
|
throw err;
|
|
106806
107134
|
}
|
|
106807
107135
|
}
|
|
106808
|
-
function
|
|
106809
|
-
|
|
106810
|
-
|
|
106811
|
-
|
|
106812
|
-
|
|
106813
|
-
}
|
|
106814
|
-
const provider = model.slice(0, slash);
|
|
106815
|
-
const modelId = model.slice(slash + 1);
|
|
106816
|
-
return modelRegistry.find(provider, modelId);
|
|
107136
|
+
function resolveRequiredModel2(modelRegistry, model) {
|
|
107137
|
+
const slash = model.indexOf("/");
|
|
107138
|
+
const resolved = slash === -1 ? modelRegistry.getAll().find((entry) => entry.id === model) : modelRegistry.find(model.slice(0, slash), model.slice(slash + 1));
|
|
107139
|
+
if (!resolved) {
|
|
107140
|
+
throw new Error(`Pi model not found: ${model}`);
|
|
106817
107141
|
}
|
|
106818
|
-
return
|
|
107142
|
+
return resolved;
|
|
106819
107143
|
}
|
|
106820
107144
|
|
|
106821
107145
|
class PiSdkHarness {
|
|
@@ -106857,7 +107181,14 @@ class PiSdkHarness {
|
|
|
106857
107181
|
async newSession(config4) {
|
|
106858
107182
|
if (this.closed)
|
|
106859
107183
|
throw new Error("Harness is closed");
|
|
106860
|
-
const
|
|
107184
|
+
const model = requireHarnessModel(config4.model, "pi-sdk newSession");
|
|
107185
|
+
const { SessionManager } = await loadSdk7();
|
|
107186
|
+
const session2 = await this.openAgentSession({
|
|
107187
|
+
systemPrompt: config4.systemPrompt ?? "",
|
|
107188
|
+
model,
|
|
107189
|
+
sessionManager: SessionManager.create(getPiSessionDir(this.cwd)),
|
|
107190
|
+
requireModel: true
|
|
107191
|
+
});
|
|
106861
107192
|
const piSession = new PiSdkSession({
|
|
106862
107193
|
session: session2,
|
|
106863
107194
|
opencodeSessionId: session2.sessionId,
|
|
@@ -106867,36 +107198,24 @@ class PiSdkHarness {
|
|
|
106867
107198
|
this.sessions.set(session2.sessionId, piSession);
|
|
106868
107199
|
return piSession;
|
|
106869
107200
|
}
|
|
106870
|
-
async resumeSession(sessionId,
|
|
107201
|
+
async resumeSession(sessionId, options) {
|
|
106871
107202
|
if (this.closed)
|
|
106872
107203
|
throw new Error("Harness is closed");
|
|
106873
107204
|
const existing = this.sessions.get(sessionId);
|
|
106874
107205
|
if (existing)
|
|
106875
107206
|
return existing;
|
|
106876
|
-
const {
|
|
107207
|
+
const { SessionManager } = await loadSdk7();
|
|
106877
107208
|
const sessions = await SessionManager.list(this.cwd, getPiSessionDir(this.cwd));
|
|
106878
107209
|
const match17 = sessions.find((s) => s.id === sessionId);
|
|
106879
107210
|
if (!match17) {
|
|
106880
107211
|
throw new Error(`Session ${sessionId} not found on the harness`);
|
|
106881
107212
|
}
|
|
106882
|
-
const
|
|
106883
|
-
|
|
106884
|
-
|
|
106885
|
-
systemPromptOverride: () => ""
|
|
106886
|
-
});
|
|
106887
|
-
await resourceLoader.reload();
|
|
106888
|
-
const resolvedModel = resolveModel2(this.modelRegistry);
|
|
106889
|
-
if (!resolvedModel) {
|
|
106890
|
-
throw new Error("No Pi model available");
|
|
106891
|
-
}
|
|
106892
|
-
const { session: session2 } = await withTimeout(createAgentSession({
|
|
106893
|
-
cwd: this.cwd,
|
|
106894
|
-
model: resolvedModel,
|
|
107213
|
+
const session2 = await this.openAgentSession({
|
|
107214
|
+
systemPrompt: "",
|
|
107215
|
+
model: options?.model,
|
|
106895
107216
|
sessionManager: SessionManager.open(match17.path, getPiSessionDir(this.cwd)),
|
|
106896
|
-
|
|
106897
|
-
|
|
106898
|
-
resourceLoader
|
|
106899
|
-
}), SESSION_CREATE_TIMEOUT_MS3, "createAgentSession");
|
|
107217
|
+
requireModel: false
|
|
107218
|
+
});
|
|
106900
107219
|
const piSession = new PiSdkSession({
|
|
106901
107220
|
session: session2,
|
|
106902
107221
|
opencodeSessionId: session2.sessionId,
|
|
@@ -106920,30 +107239,34 @@ class PiSdkHarness {
|
|
|
106920
107239
|
await Promise.all(closing);
|
|
106921
107240
|
this.sessions.clear();
|
|
106922
107241
|
}
|
|
106923
|
-
async
|
|
106924
|
-
const { createAgentSession, DefaultResourceLoader, getAgentDir
|
|
106925
|
-
const
|
|
106926
|
-
|
|
107242
|
+
async openAgentSession(args2) {
|
|
107243
|
+
const { createAgentSession, DefaultResourceLoader, getAgentDir } = await loadSdk7();
|
|
107244
|
+
const parsed = args2.model ? parsePiSpawnModel(args2.model) : undefined;
|
|
107245
|
+
const modelSlug = parsed?.model ?? args2.model;
|
|
107246
|
+
const resolvedModel = args2.requireModel ? resolveRequiredModel2(this.modelRegistry, requireHarnessModel(modelSlug, "pi-sdk openAgentSession")) : modelSlug ? resolveRequiredModel2(this.modelRegistry, modelSlug) : undefined;
|
|
107247
|
+
const thinkingLevel = resolvePiThinkingLevel(parsed?.thinking);
|
|
107248
|
+
if (args2.requireModel && !resolvedModel) {
|
|
106927
107249
|
throw new Error("No Pi model available — configure provider credentials in ~/.pi/agent/auth.json");
|
|
106928
107250
|
}
|
|
106929
107251
|
const resourceLoader = new DefaultResourceLoader({
|
|
106930
107252
|
cwd: this.cwd,
|
|
106931
107253
|
agentDir: getAgentDir(),
|
|
106932
|
-
systemPromptOverride: () => systemPrompt
|
|
107254
|
+
systemPromptOverride: () => args2.systemPrompt
|
|
106933
107255
|
});
|
|
106934
107256
|
await resourceLoader.reload();
|
|
106935
107257
|
const { session: session2 } = await withTimeout(createAgentSession({
|
|
106936
107258
|
cwd: this.cwd,
|
|
106937
|
-
|
|
106938
|
-
sessionManager: SessionManager.create(getPiSessionDir(this.cwd)),
|
|
107259
|
+
sessionManager: args2.sessionManager,
|
|
106939
107260
|
authStorage: this.authStorage,
|
|
106940
107261
|
modelRegistry: this.modelRegistry,
|
|
106941
|
-
resourceLoader
|
|
107262
|
+
resourceLoader,
|
|
107263
|
+
...resolvedModel ? { model: resolvedModel } : {},
|
|
107264
|
+
...thinkingLevel ? { thinkingLevel } : {}
|
|
106942
107265
|
}), SESSION_CREATE_TIMEOUT_MS3, "createAgentSession");
|
|
106943
107266
|
return session2;
|
|
106944
107267
|
}
|
|
106945
107268
|
}
|
|
106946
|
-
var SESSION_CREATE_TIMEOUT_MS3 = 60000,
|
|
107269
|
+
var SESSION_CREATE_TIMEOUT_MS3 = 60000, _sdkCache7, _sdkLoadError7, startPiSdkHarness = async (config4) => {
|
|
106947
107270
|
try {
|
|
106948
107271
|
const { AuthStorage, ModelRegistry } = await loadSdk7();
|
|
106949
107272
|
const authStorage = AuthStorage.create();
|
|
@@ -106959,6 +107282,7 @@ var SESSION_CREATE_TIMEOUT_MS3 = 60000, DEFAULT_MODEL3 = "opencode/big-pickle",
|
|
|
106959
107282
|
var init_pi_harness = __esm(() => {
|
|
106960
107283
|
init_pi_session();
|
|
106961
107284
|
init_pi_agent_service();
|
|
107285
|
+
init_pure2();
|
|
106962
107286
|
init_pi_sdk_package();
|
|
106963
107287
|
});
|
|
106964
107288
|
|
|
@@ -107145,6 +107469,8 @@ async function resolveSessionHandle(daemonSession, deps, info) {
|
|
|
107145
107469
|
const harness = await ensureHarnessAlive(daemonSession, deps, info);
|
|
107146
107470
|
if (!harness)
|
|
107147
107471
|
return null;
|
|
107472
|
+
const modelConfig = info.lastUsedConfig.model;
|
|
107473
|
+
const model = modelConfig ? requireHarnessModel(`${modelConfig.providerID}/${modelConfig.modelID}`, "agentic-query resumeSession") : requireHarnessModel(undefined, "agentic-query resumeSession");
|
|
107148
107474
|
const resumed = await resumeSession({
|
|
107149
107475
|
harness,
|
|
107150
107476
|
journalFactory: deps.journalFactory,
|
|
@@ -107153,7 +107479,8 @@ async function resolveSessionHandle(daemonSession, deps, info) {
|
|
|
107153
107479
|
harnessSessionId: rowId,
|
|
107154
107480
|
opencodeSessionId: info.opencodeSessionId,
|
|
107155
107481
|
workspaceId: info.workspaceId,
|
|
107156
|
-
harnessName: info.harnessName
|
|
107482
|
+
harnessName: info.harnessName,
|
|
107483
|
+
model
|
|
107157
107484
|
});
|
|
107158
107485
|
deps.activeSessions.set(rowId, resumed);
|
|
107159
107486
|
wireResumedIdle(resumed, deps, info);
|
|
@@ -107265,7 +107592,10 @@ async function openPendingHarnessSession(daemonSession, deps, input, options) {
|
|
|
107265
107592
|
logPrefix
|
|
107266
107593
|
});
|
|
107267
107594
|
const modelConfig = lastUsedConfig.model;
|
|
107268
|
-
|
|
107595
|
+
if (!modelConfig) {
|
|
107596
|
+
throw new Error("Harness model is required (agentic-query open session)");
|
|
107597
|
+
}
|
|
107598
|
+
const model = requireHarnessModel(`${modelConfig.providerID}/${modelConfig.modelID}`, "agentic-query newSession");
|
|
107269
107599
|
const liveSession = await harness.newSession({
|
|
107270
107600
|
agent: lastUsedConfig.agent,
|
|
107271
107601
|
model,
|
|
@@ -134762,4 +135092,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
134762
135092
|
});
|
|
134763
135093
|
program2.parse();
|
|
134764
135094
|
|
|
134765
|
-
//# debugId=
|
|
135095
|
+
//# debugId=48E3BD8E7ACDCBFA64756E2164756E21
|