claudish 9.1.0 → 9.2.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.
Files changed (2) hide show
  1. package/dist/index.js +79 -52
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -715,7 +715,7 @@ var init_onepassword_config = __esm(() => {
715
715
  });
716
716
 
717
717
  // src/version.ts
718
- var VERSION = "9.1.0";
718
+ var VERSION = "9.2.1";
719
719
 
720
720
  // src/logger.ts
721
721
  import { appendFile, existsSync as existsSync2, mkdirSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
@@ -33599,6 +33599,26 @@ data: ${JSON.stringify(data)}
33599
33599
  }
33600
33600
  openToolBlocks.clear();
33601
33601
  };
33602
+ const endTurnWithText = (text) => {
33603
+ const idx = curIdx++;
33604
+ send("content_block_start", {
33605
+ type: "content_block_start",
33606
+ index: idx,
33607
+ content_block: { type: "text", text: "" }
33608
+ });
33609
+ send("content_block_delta", {
33610
+ type: "content_block_delta",
33611
+ index: idx,
33612
+ delta: { type: "text_delta", text }
33613
+ });
33614
+ send("content_block_stop", { type: "content_block_stop", index: idx });
33615
+ send("message_delta", {
33616
+ type: "message_delta",
33617
+ delta: { stop_reason: "end_turn", stop_sequence: null },
33618
+ usage: { input_tokens: inputTokens, output_tokens: outputTokens }
33619
+ });
33620
+ send("message_stop", { type: "message_stop" });
33621
+ };
33602
33622
  send("message_start", {
33603
33623
  type: "message_start",
33604
33624
  message: {
@@ -33809,24 +33829,7 @@ data: ${JSON.stringify(data)}
33809
33829
 
33810
33830
  [Context limit reached] This model's backend enforces a smaller context window${cap} than its API spec. ` + "Run /clear to start fresh (/compact will also fail \u2014 it re-sends the full conversation), " + `or route the model via \`oai@${opts.modelName}\` to use the full-size window.`;
33811
33831
  }
33812
- const errorIdx = curIdx++;
33813
- send("content_block_start", {
33814
- type: "content_block_start",
33815
- index: errorIdx,
33816
- content_block: { type: "text", text: "" }
33817
- });
33818
- send("content_block_delta", {
33819
- type: "content_block_delta",
33820
- index: errorIdx,
33821
- delta: { type: "text_delta", text: errorText }
33822
- });
33823
- send("content_block_stop", { type: "content_block_stop", index: errorIdx });
33824
- send("message_delta", {
33825
- type: "message_delta",
33826
- delta: { stop_reason: "end_turn", stop_sequence: null },
33827
- usage: { input_tokens: inputTokens, output_tokens: outputTokens }
33828
- });
33829
- send("message_stop", { type: "message_stop" });
33832
+ endTurnWithText(errorText);
33830
33833
  isClosed = true;
33831
33834
  if (pingInterval) {
33832
33835
  clearInterval(pingInterval);
@@ -33877,27 +33880,19 @@ data: ${JSON.stringify(data)}
33877
33880
  try {
33878
33881
  closeReasoning();
33879
33882
  closeText();
33883
+ const toolCallCutOff = openToolBlocks.size > 0;
33880
33884
  closeTools();
33881
- const errorIdx = curIdx++;
33882
- send("content_block_start", {
33883
- type: "content_block_start",
33884
- index: errorIdx,
33885
- content_block: { type: "text", text: "" }
33886
- });
33887
- send("content_block_delta", {
33888
- type: "content_block_delta",
33889
- index: errorIdx,
33890
- delta: { type: "text_delta", text: `
33885
+ if (toolCallCutOff) {
33886
+ log("[ResponsesSSE] tool arguments cut off mid-stream \u2192 error event");
33887
+ send("error", {
33888
+ type: "error",
33889
+ error: { type: "api_error", message: `Stream error: ${error}` }
33890
+ });
33891
+ } else {
33892
+ endTurnWithText(`
33891
33893
 
33892
- [Stream error: ${error}]` }
33893
- });
33894
- send("content_block_stop", { type: "content_block_stop", index: errorIdx });
33895
- send("message_delta", {
33896
- type: "message_delta",
33897
- delta: { stop_reason: "end_turn", stop_sequence: null },
33898
- usage: { input_tokens: inputTokens, output_tokens: outputTokens }
33899
- });
33900
- send("message_stop", { type: "message_stop" });
33894
+ [Stream error: ${error}]`);
33895
+ }
33901
33896
  } catch {}
33902
33897
  isClosed = true;
33903
33898
  if (opts.onTokenUpdate)
@@ -40410,6 +40405,18 @@ function teamSlotActivity(teamSessionId) {
40410
40405
  }
40411
40406
  return out;
40412
40407
  }
40408
+ function teamSlotLiveBytes(teamSessionId) {
40409
+ const run = liveTeamRuns.get(teamSessionId);
40410
+ if (!run)
40411
+ return null;
40412
+ const out = {};
40413
+ for (const slotId of run.processes.keys()) {
40414
+ const bytes = run.liveBytesFor(slotId);
40415
+ if (bytes !== null)
40416
+ out[slotId] = bytes;
40417
+ }
40418
+ return out;
40419
+ }
40413
40420
  async function cancelTeamRun(teamSessionId, slotId) {
40414
40421
  const run = liveTeamRuns.get(teamSessionId);
40415
40422
  if (!run)
@@ -40862,6 +40869,7 @@ async function startModels(sessionPath, opts = {}) {
40862
40869
  processes,
40863
40870
  idleMsFor: (slotId) => runtimes.get(slotId)?.getIdleMs() ?? null,
40864
40871
  activityFor: (slotId) => runtimes.get(slotId)?.getActivity() ?? null,
40872
+ liveBytesFor: (slotId) => runtimes.get(slotId)?.getByteCount() ?? null,
40865
40873
  cancelledSlots
40866
40874
  });
40867
40875
  const done = (async () => {
@@ -47107,6 +47115,28 @@ function buildChildClaudeFlags(agent, claudeFlags) {
47107
47115
  const flags = [...named ? ["--agent", named] : [], ...cleaned];
47108
47116
  return flags.length > 0 ? flags : undefined;
47109
47117
  }
47118
+ function teamStatusNote(opts) {
47119
+ if (!opts.anyRunning)
47120
+ return;
47121
+ const trap = "outputSize is the size of the FINAL answer and is written once, when a slot " + "finishes. Every RUNNING slot therefore reports 0 however much work it has done: " + "it is NOT a progress signal, and 0 there does not mean the slot produced nothing.";
47122
+ if (!opts.live) {
47123
+ return `${trap} This run is not live in this process \u2014 it was started elsewhere, or this ` + "server restarted \u2014 so there are no liveness fields for it and the states above are " + "whatever was last written to status.json.";
47124
+ }
47125
+ return `${trap} Judge a running slot on three fields read TOGETHER: ` + "live_output_bytes_by_slot (answer bytes so far, the number outputSize will become), " + "idle_seconds_by_slot (seconds of silence) and activity_by_slot (what it is doing). " + "Silence in tool_executing is a build or test suite running, and is not a failure " + 'signal. Nothing cancels on your behalf \u2014 use mode:"cancel" if you decide to.';
47126
+ }
47127
+ function buildTeamStatusPayload(opts) {
47128
+ const { status, sessionPath, idle, activity, liveBytes } = opts;
47129
+ const anyRunning = Object.values(status.models).some((m) => m.state === "RUNNING");
47130
+ const note = teamStatusNote({ anyRunning, live: idle !== null });
47131
+ return {
47132
+ ...status,
47133
+ live_output_bytes_by_slot: liveBytes,
47134
+ idle_seconds_by_slot: idle,
47135
+ activity_by_slot: activity,
47136
+ ...note ? { note } : {},
47137
+ ...anyRunning ? {} : { summary: formatTeamResult(status, sessionPath) }
47138
+ };
47139
+ }
47110
47140
  function formatTeamResult(status, sessionPath) {
47111
47141
  const entries = Object.entries(status.models).sort(([a], [b]) => a.localeCompare(b));
47112
47142
  const failed = entries.filter(([, m]) => m.state === "FAILED" || m.state === "TIMEOUT" || m.state === "EMPTY");
@@ -47592,14 +47622,14 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
47592
47622
  });
47593
47623
  tools.push({
47594
47624
  name: "team",
47595
- description: "Run AI models on a task with anonymized outputs and optional blind judging. " + "Modes: 'run' (START the models and return a slot map immediately \u2014 it does NOT " + "wait), 'status' (per-slot state, plus how long each slot has been silent), " + "'cancel' (stop one slot or the whole run), 'judge' (blind-vote on existing " + "outputs), 'run-and-judge' (the blocking pipeline). " + "NO SLOT IS EVER KILLED ON A TIMER. A team slot is a full Claude Code session and " + "may work for a long time; a slot inside a build or test suite emits nothing for " + "minutes and is working, not stuck. Poll 'status', judge the silence against the " + "task you set, and use 'cancel' if you decide a slot is wedged.",
47625
+ description: "Run AI models on a task with anonymized outputs and optional blind judging. " + "Modes: 'run' (START the models and return a slot map immediately \u2014 it does NOT " + "wait), 'status' (per-slot state, plus live answer bytes, seconds of silence and " + "current activity per slot), " + "'cancel' (stop one slot or the whole run), 'judge' (blind-vote on existing " + "outputs), 'run-and-judge' (the blocking pipeline). " + "NO SLOT IS EVER KILLED ON A TIMER. A team slot is a full Claude Code session and " + "may work for a long time; a slot inside a build or test suite emits nothing for " + "minutes and is working, not stuck. Poll 'status', judge the silence against the " + "task you set, and use 'cancel' if you decide a slot is wedged. " + "JUDGING A RUNNING SLOT: read live_output_bytes_by_slot, idle_seconds_by_slot and " + "activity_by_slot. Do NOT use 'outputSize' \u2014 it is the size of the final answer, " + "written only when a slot finishes, so it is 0 for every running slot no matter how " + "much that slot has produced.",
47596
47626
  inputSchema: {
47597
47627
  type: "object",
47598
47628
  properties: {
47599
47629
  mode: {
47600
47630
  type: "string",
47601
47631
  enum: ["run", "judge", "run-and-judge", "status", "cancel"],
47602
- description: "Operation mode. 'run' STARTS the models and returns immediately with a " + "slot map \u2014 it does not wait. Poll 'status' for progress, then 'judge' once " + "the slots have finished. 'run-and-judge' is the blocking pipeline and holds " + "the call open for the whole run. 'cancel' stops one slot or the whole run."
47632
+ description: "Operation mode. 'run' STARTS the models and returns immediately with a " + "slot map \u2014 it does not wait. Poll 'status' for progress (read it from " + "live_output_bytes_by_slot and activity_by_slot, never from outputSize, " + "which stays 0 until a slot finishes), then 'judge' once the slots have " + "finished. 'run-and-judge' is the blocking pipeline and holds the call open " + "for the whole run. 'cancel' stops one slot or the whole run."
47603
47633
  },
47604
47634
  slot: {
47605
47635
  type: "string",
@@ -47750,21 +47780,17 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
47750
47780
  case "status": {
47751
47781
  const status = getStatus(resolved);
47752
47782
  const teamSessionId = resolved.split("/").filter(Boolean).pop() ?? "team";
47753
- const idle = teamSlotIdleSeconds(teamSessionId);
47754
- const settled = !Object.values(status.models).some((m) => m.state === "RUNNING");
47755
47783
  return {
47756
47784
  content: [
47757
47785
  {
47758
47786
  type: "text",
47759
- text: JSON.stringify({
47760
- ...status,
47761
- idle_seconds_by_slot: idle,
47762
- activity_by_slot: teamSlotActivity(teamSessionId),
47763
- ...idle ? {
47764
- note: "idle_seconds_by_slot is how long each slot has been silent; " + "read it against activity_by_slot. Silence in tool_executing " + "is a build or test suite running, and is not a failure " + 'signal. Nothing cancels on your behalf \u2014 use mode:"cancel" ' + "if you decide to."
47765
- } : {},
47766
- ...settled ? { summary: formatTeamResult(status, resolved) } : {}
47767
- }, null, 2)
47787
+ text: JSON.stringify(buildTeamStatusPayload({
47788
+ status,
47789
+ sessionPath: resolved,
47790
+ idle: teamSlotIdleSeconds(teamSessionId),
47791
+ activity: teamSlotActivity(teamSessionId),
47792
+ liveBytes: teamSlotLiveBytes(teamSessionId)
47793
+ }), null, 2)
47768
47794
  }
47769
47795
  ]
47770
47796
  };
@@ -69386,7 +69412,8 @@ Team Status`);
69386
69412
  }
69387
69413
  const rawArgs = process.argv.slice(2);
69388
69414
  const explicitNoAutoApprove = rawArgs.includes("--no-auto-approve");
69389
- if (cliConfig.autoApprove && !explicitNoAutoApprove && !cliConfig.stdin && cliConfig.interactive) {
69415
+ const explicitAutoApprove = rawArgs.includes("-y") || rawArgs.includes("--auto-approve");
69416
+ if (cliConfig.autoApprove && !explicitNoAutoApprove && !explicitAutoApprove && !cliConfig.stdin && cliConfig.interactive) {
69390
69417
  await Promise.resolve().then(() => init_profile_config());
69391
69418
  try {
69392
69419
  const cfg = loadConfig();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "9.1.0",
3
+ "version": "9.2.1",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,10 +60,10 @@
60
60
  "ai"
61
61
  ],
62
62
  "optionalDependencies": {
63
- "@claudish/magmux-darwin-arm64": "9.1.0",
64
- "@claudish/magmux-darwin-x64": "9.1.0",
65
- "@claudish/magmux-linux-arm64": "9.1.0",
66
- "@claudish/magmux-linux-x64": "9.1.0"
63
+ "@claudish/magmux-darwin-arm64": "9.2.1",
64
+ "@claudish/magmux-darwin-x64": "9.2.1",
65
+ "@claudish/magmux-linux-arm64": "9.2.1",
66
+ "@claudish/magmux-linux-x64": "9.2.1"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",