claudish 9.1.0 → 9.2.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.
Files changed (2) hide show
  1. package/dist/index.js +45 -14
  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.0";
719
719
 
720
720
  // src/logger.ts
721
721
  import { appendFile, existsSync as existsSync2, mkdirSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
@@ -40410,6 +40410,18 @@ function teamSlotActivity(teamSessionId) {
40410
40410
  }
40411
40411
  return out;
40412
40412
  }
40413
+ function teamSlotLiveBytes(teamSessionId) {
40414
+ const run = liveTeamRuns.get(teamSessionId);
40415
+ if (!run)
40416
+ return null;
40417
+ const out = {};
40418
+ for (const slotId of run.processes.keys()) {
40419
+ const bytes = run.liveBytesFor(slotId);
40420
+ if (bytes !== null)
40421
+ out[slotId] = bytes;
40422
+ }
40423
+ return out;
40424
+ }
40413
40425
  async function cancelTeamRun(teamSessionId, slotId) {
40414
40426
  const run = liveTeamRuns.get(teamSessionId);
40415
40427
  if (!run)
@@ -40862,6 +40874,7 @@ async function startModels(sessionPath, opts = {}) {
40862
40874
  processes,
40863
40875
  idleMsFor: (slotId) => runtimes.get(slotId)?.getIdleMs() ?? null,
40864
40876
  activityFor: (slotId) => runtimes.get(slotId)?.getActivity() ?? null,
40877
+ liveBytesFor: (slotId) => runtimes.get(slotId)?.getByteCount() ?? null,
40865
40878
  cancelledSlots
40866
40879
  });
40867
40880
  const done = (async () => {
@@ -47107,6 +47120,28 @@ function buildChildClaudeFlags(agent, claudeFlags) {
47107
47120
  const flags = [...named ? ["--agent", named] : [], ...cleaned];
47108
47121
  return flags.length > 0 ? flags : undefined;
47109
47122
  }
47123
+ function teamStatusNote(opts) {
47124
+ if (!opts.anyRunning)
47125
+ return;
47126
+ 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.";
47127
+ if (!opts.live) {
47128
+ 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.";
47129
+ }
47130
+ 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.';
47131
+ }
47132
+ function buildTeamStatusPayload(opts) {
47133
+ const { status, sessionPath, idle, activity, liveBytes } = opts;
47134
+ const anyRunning = Object.values(status.models).some((m) => m.state === "RUNNING");
47135
+ const note = teamStatusNote({ anyRunning, live: idle !== null });
47136
+ return {
47137
+ ...status,
47138
+ live_output_bytes_by_slot: liveBytes,
47139
+ idle_seconds_by_slot: idle,
47140
+ activity_by_slot: activity,
47141
+ ...note ? { note } : {},
47142
+ ...anyRunning ? {} : { summary: formatTeamResult(status, sessionPath) }
47143
+ };
47144
+ }
47110
47145
  function formatTeamResult(status, sessionPath) {
47111
47146
  const entries = Object.entries(status.models).sort(([a], [b]) => a.localeCompare(b));
47112
47147
  const failed = entries.filter(([, m]) => m.state === "FAILED" || m.state === "TIMEOUT" || m.state === "EMPTY");
@@ -47592,14 +47627,14 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
47592
47627
  });
47593
47628
  tools.push({
47594
47629
  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.",
47630
+ 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
47631
  inputSchema: {
47597
47632
  type: "object",
47598
47633
  properties: {
47599
47634
  mode: {
47600
47635
  type: "string",
47601
47636
  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."
47637
+ 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
47638
  },
47604
47639
  slot: {
47605
47640
  type: "string",
@@ -47750,21 +47785,17 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
47750
47785
  case "status": {
47751
47786
  const status = getStatus(resolved);
47752
47787
  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
47788
  return {
47756
47789
  content: [
47757
47790
  {
47758
47791
  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)
47792
+ text: JSON.stringify(buildTeamStatusPayload({
47793
+ status,
47794
+ sessionPath: resolved,
47795
+ idle: teamSlotIdleSeconds(teamSessionId),
47796
+ activity: teamSlotActivity(teamSessionId),
47797
+ liveBytes: teamSlotLiveBytes(teamSessionId)
47798
+ }), null, 2)
47768
47799
  }
47769
47800
  ]
47770
47801
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "9.1.0",
3
+ "version": "9.2.0",
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.0",
64
+ "@claudish/magmux-darwin-x64": "9.2.0",
65
+ "@claudish/magmux-linux-arm64": "9.2.0",
66
+ "@claudish/magmux-linux-x64": "9.2.0"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",