@nanopm/cli 0.1.1 → 0.1.2

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 +49 -25
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { Command } from "commander";
5
5
 
6
6
  // ../daemon/src/adapters/claude-code/index.ts
7
7
  import { execFile, spawn } from "child_process";
8
+ import { randomUUID } from "crypto";
8
9
  import { createInterface } from "readline";
9
10
  import { writeFile as writeFile2 } from "fs/promises";
10
11
  import { join as join3 } from "path";
@@ -3792,7 +3793,26 @@ var ClaudeCodeAdapter = class {
3792
3793
  else args.push("--session-id", spec.sessionId);
3793
3794
  return args;
3794
3795
  }
3796
+ /**
3797
+ * One session, and one more when the model asked for is newer than this Claude Code: a
3798
+ * skill names `claude-opus-5-5`, a Claude Code older than 2.1.280 refuses it, and the run
3799
+ * used to end there with no roadmap (activation row 36). The second session asks for the
3800
+ * family alias under a fresh id and says so, so the run works on the Opus the machine has.
3801
+ * Any other failure stays a failure.
3802
+ */
3795
3803
  async *run(spec) {
3804
+ for await (const event of this.runOnce(spec)) {
3805
+ const alias = event.type === "failed" ? olderAlias(spec.model, event.message) : null;
3806
+ if (!alias) {
3807
+ yield event;
3808
+ continue;
3809
+ }
3810
+ yield { type: "text", text: `This Claude Code does not know ${spec.model} yet; using ${alias}. \`claude update\` brings the newer model.` };
3811
+ yield* this.runOnce({ ...spec, model: alias, sessionId: randomUUID(), resumeSessionId: void 0 });
3812
+ return;
3813
+ }
3814
+ }
3815
+ async *runOnce(spec) {
3796
3816
  const mcpConfigPath = join3(spec.runDir, "mcp.json");
3797
3817
  const mcpServers = Object.fromEntries(
3798
3818
  spec.mcp.map((s) => [s.name, { command: s.command, args: s.args, env: s.env }])
@@ -3839,6 +3859,10 @@ var ClaudeCodeAdapter = class {
3839
3859
  }
3840
3860
  }
3841
3861
  };
3862
+ function olderAlias(model, message) {
3863
+ if (!model || !/does not support this model/i.test(message)) return null;
3864
+ return ["opus", "sonnet", "haiku"].find((family) => model.includes(family) && model !== family) ?? null;
3865
+ }
3842
3866
  function appendExit(message, code) {
3843
3867
  return code === null || code === 0 ? message : `${message} (exit ${code})`;
3844
3868
  }
@@ -5200,7 +5224,7 @@ async function clonelessSkills(skillsDir = findSkillsDir()) {
5200
5224
  }
5201
5225
 
5202
5226
  // ../daemon/src/problem-mapping-harness.ts
5203
- import { randomUUID } from "crypto";
5227
+ import { randomUUID as randomUUID2 } from "crypto";
5204
5228
  function mappingHarnessRunner(options) {
5205
5229
  return async (input) => {
5206
5230
  const skill = await loadSkill(`problem-${input.role}`);
@@ -5209,7 +5233,7 @@ function mappingHarnessRunner(options) {
5209
5233
  for await (const event of options.adapter.run({
5210
5234
  cwd: options.runDir,
5211
5235
  runDir: options.runDir,
5212
- sessionId: randomUUID(),
5236
+ sessionId: randomUUID2(),
5213
5237
  systemPrompt: `${skill.body}
5214
5238
 
5215
5239
  Output schema:
@@ -5500,7 +5524,7 @@ function mappingUsage(checkpoints) {
5500
5524
  }
5501
5525
 
5502
5526
  // ../daemon/src/persona-job.ts
5503
- import { randomUUID as randomUUID2 } from "crypto";
5527
+ import { randomUUID as randomUUID3 } from "crypto";
5504
5528
 
5505
5529
  // ../daemon/src/crew-retry.ts
5506
5530
  async function askAgainIfUnanswered(attempt7, say, role7) {
@@ -5813,7 +5837,7 @@ async function attempt({
5813
5837
  await onEvent({ type: "text", text: say });
5814
5838
  for await (const event of adapter.run({
5815
5839
  ...spec,
5816
- sessionId: randomUUID2(),
5840
+ sessionId: randomUUID3(),
5817
5841
  resumeSessionId: void 0,
5818
5842
  capabilities: [],
5819
5843
  mcp: [],
@@ -6034,7 +6058,7 @@ async function collect2(client, projectId, cwd, replace) {
6034
6058
  }
6035
6059
 
6036
6060
  // ../daemon/src/direction-job.ts
6037
- import { randomUUID as randomUUID3 } from "crypto";
6061
+ import { randomUUID as randomUUID4 } from "crypto";
6038
6062
 
6039
6063
  // ../daemon/src/crew-no-downgrade.ts
6040
6064
  function keepsTheLine(job, live, confidence) {
@@ -6229,7 +6253,7 @@ ${renderTests()}` : skill.body;
6229
6253
  await onEvent({ type: "text", text: say });
6230
6254
  for await (const event of adapter.run({
6231
6255
  ...spec,
6232
- sessionId: randomUUID3(),
6256
+ sessionId: randomUUID4(),
6233
6257
  resumeSessionId: void 0,
6234
6258
  capabilities: [],
6235
6259
  mcp: [],
@@ -6358,7 +6382,7 @@ async function collect3(client, projectId) {
6358
6382
  }
6359
6383
 
6360
6384
  // ../daemon/src/pitch-job.ts
6361
- import { randomUUID as randomUUID4 } from "crypto";
6385
+ import { randomUUID as randomUUID5 } from "crypto";
6362
6386
  async function runPitchJob({ client, job, adapter, spec, onEvent }) {
6363
6387
  if (!job.project_id) throw new Error("A pitch needs a project.");
6364
6388
  const projectId = job.project_id;
@@ -6463,7 +6487,7 @@ async function attempt3({
6463
6487
  await onEvent({ type: "text", text: say });
6464
6488
  for await (const event of adapter.run({
6465
6489
  ...spec,
6466
- sessionId: randomUUID4(),
6490
+ sessionId: randomUUID5(),
6467
6491
  resumeSessionId: void 0,
6468
6492
  capabilities: [],
6469
6493
  mcp: [],
@@ -6575,7 +6599,7 @@ async function collect4(client, projectId) {
6575
6599
  }
6576
6600
 
6577
6601
  // ../daemon/src/market-job.ts
6578
- import { randomUUID as randomUUID5 } from "crypto";
6602
+ import { randomUUID as randomUUID6 } from "crypto";
6579
6603
 
6580
6604
  // ../daemon/src/web-journal.ts
6581
6605
  var HARNESS_WEB_TOOLS = ["WebSearch", "WebFetch"];
@@ -6816,7 +6840,7 @@ async function attempt4({ adapter, spec, onEvent, role: which, prompt, say }) {
6816
6840
  await onEvent({ type: "text", text: say });
6817
6841
  for await (const event of adapter.run({
6818
6842
  ...spec,
6819
- sessionId: randomUUID5(),
6843
+ sessionId: randomUUID6(),
6820
6844
  resumeSessionId: void 0,
6821
6845
  capabilities,
6822
6846
  mcp: which === "scout" ? spec.mcp : [],
@@ -6899,7 +6923,7 @@ async function collect5(client, projectId, ask6) {
6899
6923
  }
6900
6924
 
6901
6925
  // ../daemon/src/needs-job.ts
6902
- import { randomUUID as randomUUID6 } from "crypto";
6926
+ import { randomUUID as randomUUID7 } from "crypto";
6903
6927
  var SIGNALS_MAX = 40;
6904
6928
  var SIGNAL_CHARS = 3e3;
6905
6929
  async function runNeedsJob({ client, job, adapter, spec, onEvent }) {
@@ -7478,7 +7502,7 @@ async function attempt5({ adapter, spec, onEvent, role: which, schema: shape2, t
7478
7502
  await onEvent({ type: "text", text: say });
7479
7503
  for await (const event of adapter.run({
7480
7504
  ...spec,
7481
- sessionId: randomUUID6(),
7505
+ sessionId: randomUUID7(),
7482
7506
  resumeSessionId: void 0,
7483
7507
  capabilities: granted,
7484
7508
  mcp: granted.length ? spec.mcp : [],
@@ -7700,7 +7724,7 @@ function opportunitiesOutputSchema(which) {
7700
7724
  }
7701
7725
 
7702
7726
  // ../daemon/src/crew.ts
7703
- import { randomUUID as randomUUID7 } from "crypto";
7727
+ import { randomUUID as randomUUID8 } from "crypto";
7704
7728
  import { mkdir as mkdir2 } from "fs/promises";
7705
7729
  import { join as join7 } from "path";
7706
7730
  var READ_ONLY = {
@@ -7727,7 +7751,7 @@ async function attempt6({ adapter, spec, onEvent, skill: skillName, name, schema
7727
7751
  // A role that may not read the code does not stand in it (docs/nanopm-71-deep-dive-lenses.md).
7728
7752
  cwd: grant.includes("read_repo") ? spec.cwd : runDir,
7729
7753
  runDir,
7730
- sessionId: randomUUID7(),
7754
+ sessionId: randomUUID8(),
7731
7755
  resumeSessionId: void 0,
7732
7756
  capabilities: [...grant],
7733
7757
  mcp: grant.includes("read_data") ? spec.mcp : [],
@@ -9229,7 +9253,7 @@ async function readRoadmap(client, projectId) {
9229
9253
  }
9230
9254
 
9231
9255
  // ../daemon/src/reword-job.ts
9232
- import { randomUUID as randomUUID8 } from "crypto";
9256
+ import { randomUUID as randomUUID9 } from "crypto";
9233
9257
  async function runRewordJob({ client, job, adapter, spec, onEvent }) {
9234
9258
  if (!job.project_id) throw new Error("A rewrite needs a project.");
9235
9259
  const asked = RewordParams.safeParse(job.params);
@@ -9291,7 +9315,7 @@ async function session({ adapter, spec, onEvent, prompt }) {
9291
9315
  let usage;
9292
9316
  for await (const event of adapter.run({
9293
9317
  ...spec,
9294
- sessionId: randomUUID8(),
9318
+ sessionId: randomUUID9(),
9295
9319
  resumeSessionId: void 0,
9296
9320
  capabilities: [],
9297
9321
  mcp: [],
@@ -9326,7 +9350,7 @@ ${body}
9326
9350
  }
9327
9351
 
9328
9352
  // ../daemon/src/talk-job.ts
9329
- import { randomUUID as randomUUID9 } from "crypto";
9353
+ import { randomUUID as randomUUID10 } from "crypto";
9330
9354
  var ALLOWED = /* @__PURE__ */ new Set([...TALK_TOOLS.map((t) => `mcp__nanopm__${t}`), "StructuredOutput"]);
9331
9355
  async function runTalkJob({ client, job, adapter, spec, onEvent }) {
9332
9356
  if (!job.project_id) throw new Error("A conversation needs a project.");
@@ -9358,7 +9382,7 @@ async function runTalkJob({ client, job, adapter, spec, onEvent }) {
9358
9382
  let usage;
9359
9383
  for await (const event of adapter.run({
9360
9384
  ...spec,
9361
- sessionId: randomUUID9(),
9385
+ sessionId: randomUUID10(),
9362
9386
  resumeSessionId: void 0,
9363
9387
  capabilities: skill.manifest.capabilities,
9364
9388
  harnessWeb: false,
@@ -9395,7 +9419,7 @@ var told = (r) => ({
9395
9419
 
9396
9420
  // ../daemon/src/objective-definitions.ts
9397
9421
  import { execFile as execFile4 } from "child_process";
9398
- import { randomUUID as randomUUID10 } from "crypto";
9422
+ import { randomUUID as randomUUID11 } from "crypto";
9399
9423
  import { existsSync as existsSync2 } from "fs";
9400
9424
  import { mkdir as mkdir3, readFile as readFile5 } from "fs/promises";
9401
9425
  import { join as join8 } from "path";
@@ -9571,7 +9595,7 @@ async function readDefinitions({ adapter, spec, publish: publish5, journal, hasR
9571
9595
  for await (const event of adapter.run({
9572
9596
  ...spec,
9573
9597
  runDir,
9574
- sessionId: randomUUID10(),
9598
+ sessionId: randomUUID11(),
9575
9599
  resumeSessionId: void 0,
9576
9600
  capabilities: ["read_repo"],
9577
9601
  // No Glob: it read the folder at 15 s a search (Guillaume's suggestions took 75 s,
@@ -9895,7 +9919,7 @@ function localDate(timezone, at) {
9895
9919
  }
9896
9920
 
9897
9921
  // ../daemon/src/run-job.ts
9898
- import { randomUUID as randomUUID11 } from "crypto";
9922
+ import { randomUUID as randomUUID12 } from "crypto";
9899
9923
  import { existsSync as existsSync3 } from "fs";
9900
9924
  import { mkdir as mkdir4, readFile as readFile6, rm as rm2 } from "fs/promises";
9901
9925
  import { homedir as homedir2, tmpdir } from "os";
@@ -10340,7 +10364,7 @@ async function execute(job, skill, ctx, events) {
10340
10364
  const runDir = join9(nanopmHome(), "run", job.id);
10341
10365
  await mkdir4(runDir, { recursive: true, mode: 448 });
10342
10366
  const resumeSessionId = job.resume_of ? await sessionOf(ctx.client, job.resume_of) : void 0;
10343
- const sessionId = resumeSessionId ?? randomUUID11();
10367
+ const sessionId = resumeSessionId ?? randomUUID12();
10344
10368
  await ctx.client.from("jobs").update({ harness_session_id: sessionId }).eq("id", job.id);
10345
10369
  const adapter = ctx.adapter ?? new ClaudeCodeAdapter();
10346
10370
  const [project, searchProvider] = job.project_id ? await Promise.all([loadProject(ctx.client, job.project_id), loadSearchProvider(ctx.client, job.project_id)]) : [null, null];
@@ -11247,7 +11271,7 @@ function contextFromEnv(env = process.env) {
11247
11271
 
11248
11272
  // ../memory-mcp/src/server.ts
11249
11273
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
11250
- import { randomUUID as randomUUID12 } from "crypto";
11274
+ import { randomUUID as randomUUID13 } from "crypto";
11251
11275
  import { setTimeout as sleep2 } from "timers/promises";
11252
11276
  import { z as z20 } from "zod";
11253
11277
 
@@ -13090,7 +13114,7 @@ async function talkAct(ctx, roundOf, proposed, asked, why) {
13090
13114
  const [round2, world] = await Promise.all([roundOf, talkWorld(ctx.client, ctx.projectId)]);
13091
13115
  const ref = change.kind === "add" ? change.parent : change.kind === "add_solution" ? change.leaf : change.ref;
13092
13116
  const target = ref ? currentRow(world, ref)?.ref ?? currentSolution(world, ref)?.ref ?? ref : void 0;
13093
- const base = { id: randomUUID12(), change, ...movesDown(change, world) ? { down: true } : {}, ...change.kind === "brainstorm" ? { cost: runCost(change.depth) } : {} };
13117
+ const base = { id: randomUUID13(), change, ...movesDown(change, world) ? { down: true } : {}, ...change.kind === "brainstorm" ? { cost: runCost(change.depth) } : {} };
13094
13118
  let action;
13095
13119
  if (!askedIn(asked, round2.words)) {
13096
13120
  action = { ...base, state: "suggested", line: talkLine(change, world, false), ...target ? { target } : {} };
@@ -13885,7 +13909,7 @@ import { promisify as promisify7 } from "util";
13885
13909
  // package.json
13886
13910
  var package_default = {
13887
13911
  name: "@nanopm/cli",
13888
- version: "0.1.1",
13912
+ version: "0.1.2",
13889
13913
  description: "An autonomous product manager for builders who run several small products. Runs on your machine, drives your own coding harness.",
13890
13914
  type: "module",
13891
13915
  license: "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanopm/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "An autonomous product manager for builders who run several small products. Runs on your machine, drives your own coding harness.",
5
5
  "type": "module",
6
6
  "license": "MIT",