chatroom-cli 1.102.2 → 1.103.0

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 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 (options.model) {
27831
- args2.push("--model", options.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, SPAWN_READY_DELAY_MS2 = 500, PiAgentService;
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.waitForSpawnReady(childProcess);
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, defaultModel = "composer-2.5") {
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 { model, effort } = decodeClaudeSdkModel(options.model);
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 { model, effort } = decodeClaudeSdkModel(options.model ?? stored.model);
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 variant = decodeCodexVariant(options.model);
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: options.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 variant = decodeCodexVariant(options.model ?? stored.model);
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: options.model ?? stored.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 modelSelection = resolveCursorSdkSpawnModelSelection(options.model ?? stored.model);
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: options.model ?? stored.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 modelSelection = resolveCursorSdkSpawnModelSelection(options.model);
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: options.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 modelParts = args2.model ? parseModelId(args2.model) : undefined;
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: args2.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 ?? session2.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, model, context: context5 } = options;
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: meta.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: meta.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 resolveModel(modelRegistry, model) {
35779
- if (model) {
35780
- const slash = model.indexOf("/");
35781
- if (slash === -1) {
35782
- return modelRegistry.getAll().find((entry) => entry.id === model);
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 modelRegistry.getAvailable()[0];
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 resolvedModel = resolveModel(modelRegistry, args2.model);
35911
- if (!resolvedModel) {
35912
- throw new Error("No Pi model available — configure provider credentials in ~/.pi/agent/auth.json");
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: options.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: options.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
- ## Persistent state and query pattern design
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: "structural-decisions",
80778
- 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).",
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 = [
@@ -105455,7 +105643,8 @@ async function resumeSession(deps, input) {
105455
105643
  const { harness, journalFactory, chunkExtractor, nowFn = Date.now } = deps;
105456
105644
  const { harnessSessionId, opencodeSessionId } = input;
105457
105645
  const session2 = await harness.resumeSession(opencodeSessionId, {
105458
- harnessSessionId
105646
+ harnessSessionId,
105647
+ ...input.model ? { model: input.model } : {}
105459
105648
  });
105460
105649
  const journal = journalFactory.create(harnessSessionId);
105461
105650
  const unsubscribeEvents = session2.onEvent((event) => {
@@ -105781,6 +105970,7 @@ class ClaudeSdkHarness {
105781
105970
  async newSession(config4) {
105782
105971
  if (this.closed)
105783
105972
  throw new Error("Harness is closed");
105973
+ const defaultModel = requireHarnessModel(config4.model, "claude-sdk newSession");
105784
105974
  const opencodeSessionId = randomUUID6();
105785
105975
  const session2 = new ClaudeSdkSession({
105786
105976
  cwd: this.cwd,
@@ -105788,25 +105978,27 @@ class ClaudeSdkHarness {
105788
105978
  query: this.query,
105789
105979
  opencodeSessionId,
105790
105980
  sessionTitle: config4.title ?? "",
105791
- defaultModel: config4.model ?? DEFAULT_MODEL,
105981
+ defaultModel,
105792
105982
  systemPrompt: config4.systemPrompt,
105793
105983
  onClose: (id3) => this.sessions.delete(id3)
105794
105984
  });
105795
105985
  this.sessions.set(opencodeSessionId, session2);
105796
105986
  return session2;
105797
105987
  }
105798
- async resumeSession(sessionId, _options) {
105988
+ async resumeSession(sessionId, options) {
105799
105989
  if (this.closed)
105800
105990
  throw new Error("Harness is closed");
105801
105991
  const existing = this.sessions.get(sessionId);
105802
105992
  if (existing)
105803
105993
  return existing;
105994
+ const defaultModel = requireHarnessModel(options?.model, "claude-sdk resumeSession");
105804
105995
  const session2 = new ClaudeSdkSession({
105805
105996
  cwd: this.cwd,
105806
105997
  executablePath: this.executablePath,
105807
105998
  query: this.query,
105808
105999
  opencodeSessionId: sessionId,
105809
106000
  sessionTitle: "",
106001
+ defaultModel,
105810
106002
  providerSessionId: sessionId,
105811
106003
  resumeOnFirstQuery: true,
105812
106004
  onClose: (id3) => this.sessions.delete(id3)
@@ -105829,7 +106021,7 @@ class ClaudeSdkHarness {
105829
106021
  this.sessions.clear();
105830
106022
  }
105831
106023
  }
105832
- var DEFAULT_MODEL = "anthropic/sonnet", _sdkCache5, _sdkLoadError5, _executablePathCache, startClaudeSdkHarness = async (config4) => {
106024
+ var _sdkCache5, _sdkLoadError5, _executablePathCache, startClaudeSdkHarness = async (config4) => {
105833
106025
  try {
105834
106026
  const sdk = await loadSdk5();
105835
106027
  const executablePath = await loadExecutablePath();
@@ -106082,51 +106274,51 @@ class CursorSdkHarness {
106082
106274
  }
106083
106275
  ];
106084
106276
  }
106085
- async newSession(config4) {
106086
- if (this.closed)
106087
- throw new Error("Harness is closed");
106277
+ requireApiKey() {
106088
106278
  const apiKey = process.env.CURSOR_API_KEY?.trim();
106089
106279
  if (!apiKey)
106090
106280
  throw new Error("CURSOR_API_KEY is not set");
106091
- const modelSelection = resolveCursorSdkSpawnModelSelection(config4.model ?? DEFAULT_MODEL2);
106092
- const { Agent } = await loadSdk6();
106093
- const agent = await withTimeout(Agent.create({
106094
- apiKey,
106095
- model: modelSelection,
106096
- local: { cwd: this.cwd, settingSources: [], enableAgentRetries: true }
106097
- }), AGENT_CREATE_TIMEOUT_MS2, "Agent.create");
106281
+ return apiKey;
106282
+ }
106283
+ registerAgentSession(agent, sessionTitle) {
106098
106284
  const session2 = new CursorSdkSession({
106099
106285
  agent,
106100
106286
  opencodeSessionId: agent.agentId,
106101
- sessionTitle: config4.title ?? "",
106287
+ sessionTitle,
106102
106288
  onClose: (id3) => this.sessions.delete(id3)
106103
106289
  });
106104
106290
  this.sessions.set(agent.agentId, session2);
106105
106291
  return session2;
106106
106292
  }
106107
- async resumeSession(sessionId, _options) {
106293
+ async newSession(config4) {
106294
+ if (this.closed)
106295
+ throw new Error("Harness is closed");
106296
+ const apiKey = this.requireApiKey();
106297
+ const model = requireHarnessModel(config4.model, "cursor-sdk newSession");
106298
+ const modelSelection = resolveCursorSdkSpawnModelSelection(model);
106299
+ const { Agent } = await loadSdk6();
106300
+ const agent = await withTimeout(Agent.create({
106301
+ apiKey,
106302
+ model: modelSelection,
106303
+ local: { cwd: this.cwd, settingSources: [], enableAgentRetries: true }
106304
+ }), AGENT_CREATE_TIMEOUT_MS2, "Agent.create");
106305
+ return this.registerAgentSession(agent, config4.title ?? "");
106306
+ }
106307
+ async resumeSession(sessionId, options) {
106108
106308
  if (this.closed)
106109
106309
  throw new Error("Harness is closed");
106110
106310
  const existing = this.sessions.get(sessionId);
106111
106311
  if (existing)
106112
106312
  return existing;
106113
- const apiKey = process.env.CURSOR_API_KEY?.trim();
106114
- if (!apiKey)
106115
- throw new Error("CURSOR_API_KEY is not set");
106313
+ const model = requireHarnessModel(options?.model, "cursor-sdk resumeSession");
106314
+ const apiKey = this.requireApiKey();
106116
106315
  const { Agent } = await loadSdk6();
106117
106316
  const agent = await withTimeout(Agent.resume(sessionId, {
106118
106317
  apiKey,
106119
- model: resolveCursorSdkSpawnModelSelection(DEFAULT_MODEL2),
106318
+ model: resolveCursorSdkSpawnModelSelection(model),
106120
106319
  local: { cwd: this.cwd, settingSources: [], enableAgentRetries: true }
106121
106320
  }), AGENT_CREATE_TIMEOUT_MS2, "Agent.resume");
106122
- const session2 = new CursorSdkSession({
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;
106321
+ return this.registerAgentSession(agent, "");
106130
106322
  }
106131
106323
  async fetchSessionTitle(_opencodeSessionId) {
106132
106324
  return;
@@ -106143,7 +106335,7 @@ class CursorSdkHarness {
106143
106335
  this.sessions.clear();
106144
106336
  }
106145
106337
  }
106146
- var DEFAULT_MODEL2 = "composer-2.5", AGENT_CREATE_TIMEOUT_MS2 = 60000, _sdkCache6, _sdkLoadError6, startCursorSdkHarness = async (config4) => {
106338
+ var AGENT_CREATE_TIMEOUT_MS2 = 60000, _sdkCache6, _sdkLoadError6, startCursorSdkHarness = async (config4) => {
106147
106339
  try {
106148
106340
  await loadSdk6();
106149
106341
  } catch (err) {
@@ -106470,6 +106662,7 @@ class OpencodeSdkHarness {
106470
106662
  async newSession(config4) {
106471
106663
  if (this.closed)
106472
106664
  throw new Error("Harness is closed");
106665
+ requireHarnessModel(config4.model, "opencode-sdk newSession");
106473
106666
  const created = await this.client.session.create({
106474
106667
  body: {
106475
106668
  ...config4.title ? { title: config4.title } : {}
@@ -106805,17 +106998,13 @@ async function loadSdk7() {
106805
106998
  throw err;
106806
106999
  }
106807
107000
  }
106808
- function resolveModel2(modelRegistry, model) {
106809
- if (model) {
106810
- const slash = model.indexOf("/");
106811
- if (slash === -1) {
106812
- return modelRegistry.getAll().find((entry) => entry.id === model);
106813
- }
106814
- const provider = model.slice(0, slash);
106815
- const modelId = model.slice(slash + 1);
106816
- return modelRegistry.find(provider, modelId);
107001
+ function resolveRequiredModel2(modelRegistry, model) {
107002
+ const slash = model.indexOf("/");
107003
+ const resolved = slash === -1 ? modelRegistry.getAll().find((entry) => entry.id === model) : modelRegistry.find(model.slice(0, slash), model.slice(slash + 1));
107004
+ if (!resolved) {
107005
+ throw new Error(`Pi model not found: ${model}`);
106817
107006
  }
106818
- return modelRegistry.getAvailable()[0];
107007
+ return resolved;
106819
107008
  }
106820
107009
 
106821
107010
  class PiSdkHarness {
@@ -106857,7 +107046,14 @@ class PiSdkHarness {
106857
107046
  async newSession(config4) {
106858
107047
  if (this.closed)
106859
107048
  throw new Error("Harness is closed");
106860
- const session2 = await this.createAgentSession(config4.systemPrompt ?? "", config4.model);
107049
+ const model = requireHarnessModel(config4.model, "pi-sdk newSession");
107050
+ const { SessionManager } = await loadSdk7();
107051
+ const session2 = await this.openAgentSession({
107052
+ systemPrompt: config4.systemPrompt ?? "",
107053
+ model,
107054
+ sessionManager: SessionManager.create(getPiSessionDir(this.cwd)),
107055
+ requireModel: true
107056
+ });
106861
107057
  const piSession = new PiSdkSession({
106862
107058
  session: session2,
106863
107059
  opencodeSessionId: session2.sessionId,
@@ -106867,36 +107063,24 @@ class PiSdkHarness {
106867
107063
  this.sessions.set(session2.sessionId, piSession);
106868
107064
  return piSession;
106869
107065
  }
106870
- async resumeSession(sessionId, _options) {
107066
+ async resumeSession(sessionId, options) {
106871
107067
  if (this.closed)
106872
107068
  throw new Error("Harness is closed");
106873
107069
  const existing = this.sessions.get(sessionId);
106874
107070
  if (existing)
106875
107071
  return existing;
106876
- const { createAgentSession, DefaultResourceLoader, getAgentDir, SessionManager } = await loadSdk7();
107072
+ const { SessionManager } = await loadSdk7();
106877
107073
  const sessions = await SessionManager.list(this.cwd, getPiSessionDir(this.cwd));
106878
107074
  const match17 = sessions.find((s) => s.id === sessionId);
106879
107075
  if (!match17) {
106880
107076
  throw new Error(`Session ${sessionId} not found on the harness`);
106881
107077
  }
106882
- const resourceLoader = new DefaultResourceLoader({
106883
- cwd: this.cwd,
106884
- agentDir: getAgentDir(),
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,
107078
+ const session2 = await this.openAgentSession({
107079
+ systemPrompt: "",
107080
+ model: options?.model,
106895
107081
  sessionManager: SessionManager.open(match17.path, getPiSessionDir(this.cwd)),
106896
- authStorage: this.authStorage,
106897
- modelRegistry: this.modelRegistry,
106898
- resourceLoader
106899
- }), SESSION_CREATE_TIMEOUT_MS3, "createAgentSession");
107082
+ requireModel: false
107083
+ });
106900
107084
  const piSession = new PiSdkSession({
106901
107085
  session: session2,
106902
107086
  opencodeSessionId: session2.sessionId,
@@ -106920,30 +107104,34 @@ class PiSdkHarness {
106920
107104
  await Promise.all(closing);
106921
107105
  this.sessions.clear();
106922
107106
  }
106923
- async createAgentSession(systemPrompt, model) {
106924
- const { createAgentSession, DefaultResourceLoader, getAgentDir, SessionManager } = await loadSdk7();
106925
- const resolvedModel = resolveModel2(this.modelRegistry, model ?? DEFAULT_MODEL3);
106926
- if (!resolvedModel) {
107107
+ async openAgentSession(args2) {
107108
+ const { createAgentSession, DefaultResourceLoader, getAgentDir } = await loadSdk7();
107109
+ const parsed = args2.model ? parsePiSpawnModel(args2.model) : undefined;
107110
+ const modelSlug = parsed?.model ?? args2.model;
107111
+ const resolvedModel = args2.requireModel ? resolveRequiredModel2(this.modelRegistry, requireHarnessModel(modelSlug, "pi-sdk openAgentSession")) : modelSlug ? resolveRequiredModel2(this.modelRegistry, modelSlug) : undefined;
107112
+ const thinkingLevel = resolvePiThinkingLevel(parsed?.thinking);
107113
+ if (args2.requireModel && !resolvedModel) {
106927
107114
  throw new Error("No Pi model available — configure provider credentials in ~/.pi/agent/auth.json");
106928
107115
  }
106929
107116
  const resourceLoader = new DefaultResourceLoader({
106930
107117
  cwd: this.cwd,
106931
107118
  agentDir: getAgentDir(),
106932
- systemPromptOverride: () => systemPrompt
107119
+ systemPromptOverride: () => args2.systemPrompt
106933
107120
  });
106934
107121
  await resourceLoader.reload();
106935
107122
  const { session: session2 } = await withTimeout(createAgentSession({
106936
107123
  cwd: this.cwd,
106937
- model: resolvedModel,
106938
- sessionManager: SessionManager.create(getPiSessionDir(this.cwd)),
107124
+ sessionManager: args2.sessionManager,
106939
107125
  authStorage: this.authStorage,
106940
107126
  modelRegistry: this.modelRegistry,
106941
- resourceLoader
107127
+ resourceLoader,
107128
+ ...resolvedModel ? { model: resolvedModel } : {},
107129
+ ...thinkingLevel ? { thinkingLevel } : {}
106942
107130
  }), SESSION_CREATE_TIMEOUT_MS3, "createAgentSession");
106943
107131
  return session2;
106944
107132
  }
106945
107133
  }
106946
- var SESSION_CREATE_TIMEOUT_MS3 = 60000, DEFAULT_MODEL3 = "opencode/big-pickle", _sdkCache7, _sdkLoadError7, startPiSdkHarness = async (config4) => {
107134
+ var SESSION_CREATE_TIMEOUT_MS3 = 60000, _sdkCache7, _sdkLoadError7, startPiSdkHarness = async (config4) => {
106947
107135
  try {
106948
107136
  const { AuthStorage, ModelRegistry } = await loadSdk7();
106949
107137
  const authStorage = AuthStorage.create();
@@ -106959,6 +107147,7 @@ var SESSION_CREATE_TIMEOUT_MS3 = 60000, DEFAULT_MODEL3 = "opencode/big-pickle",
106959
107147
  var init_pi_harness = __esm(() => {
106960
107148
  init_pi_session();
106961
107149
  init_pi_agent_service();
107150
+ init_pure2();
106962
107151
  init_pi_sdk_package();
106963
107152
  });
106964
107153
 
@@ -107145,6 +107334,8 @@ async function resolveSessionHandle(daemonSession, deps, info) {
107145
107334
  const harness = await ensureHarnessAlive(daemonSession, deps, info);
107146
107335
  if (!harness)
107147
107336
  return null;
107337
+ const modelConfig = info.lastUsedConfig.model;
107338
+ const model = modelConfig ? requireHarnessModel(`${modelConfig.providerID}/${modelConfig.modelID}`, "agentic-query resumeSession") : requireHarnessModel(undefined, "agentic-query resumeSession");
107148
107339
  const resumed = await resumeSession({
107149
107340
  harness,
107150
107341
  journalFactory: deps.journalFactory,
@@ -107153,7 +107344,8 @@ async function resolveSessionHandle(daemonSession, deps, info) {
107153
107344
  harnessSessionId: rowId,
107154
107345
  opencodeSessionId: info.opencodeSessionId,
107155
107346
  workspaceId: info.workspaceId,
107156
- harnessName: info.harnessName
107347
+ harnessName: info.harnessName,
107348
+ model
107157
107349
  });
107158
107350
  deps.activeSessions.set(rowId, resumed);
107159
107351
  wireResumedIdle(resumed, deps, info);
@@ -107265,7 +107457,10 @@ async function openPendingHarnessSession(daemonSession, deps, input, options) {
107265
107457
  logPrefix
107266
107458
  });
107267
107459
  const modelConfig = lastUsedConfig.model;
107268
- const model = modelConfig ? `${modelConfig.providerID}/${modelConfig.modelID}` : undefined;
107460
+ if (!modelConfig) {
107461
+ throw new Error("Harness model is required (agentic-query open session)");
107462
+ }
107463
+ const model = requireHarnessModel(`${modelConfig.providerID}/${modelConfig.modelID}`, "agentic-query newSession");
107269
107464
  const liveSession = await harness.newSession({
107270
107465
  agent: lastUsedConfig.agent,
107271
107466
  model,
@@ -134762,4 +134957,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
134762
134957
  });
134763
134958
  program2.parse();
134764
134959
 
134765
- //# debugId=B34E804643624D4B64756E2164756E21
134960
+ //# debugId=1C27BCC36565FE7A64756E2164756E21