shipr-agent 0.1.4 → 0.1.5

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 +143 -57
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -101309,70 +101309,156 @@ async function handleSimulate(args, state2) {
101309
101309
  process.stdout.write(PROMPT);
101310
101310
  });
101311
101311
  }
101312
- function handleModel(args, state2) {
101312
+ function interactivePick(title, items) {
101313
+ return new Promise((resolve) => {
101314
+ let cursor = items.findIndex((i2) => i2.active) ?? 0;
101315
+ if (cursor < 0)
101316
+ cursor = 0;
101317
+ const stdin = process.stdin;
101318
+ const wasRaw = stdin.isRaw;
101319
+ function render2() {
101320
+ const totalLines = items.length + 4;
101321
+ process.stdout.write(`\x1B[${totalLines}A\x1B[0J`);
101322
+ draw();
101323
+ }
101324
+ function draw() {
101325
+ console.log("");
101326
+ console.log(` ${BRAND_BOLD(title)} ${DIM2("↑↓ navigate Enter select q back")}`);
101327
+ console.log("");
101328
+ let lastGroup = "";
101329
+ for (let i2 = 0;i2 < items.length; i2++) {
101330
+ const item = items[i2];
101331
+ if (item.group && item.group !== lastGroup) {
101332
+ if (lastGroup)
101333
+ console.log("");
101334
+ lastGroup = item.group;
101335
+ }
101336
+ const selected = i2 === cursor;
101337
+ const pointer = selected ? BRAND8("❯ ") : " ";
101338
+ const label = selected ? source_default.bold(item.label) : item.label;
101339
+ const hint = item.hint ? ` ${DIM2(item.hint)}` : "";
101340
+ const activeTag = item.active ? source_default.green(" ◀") : "";
101341
+ console.log(` ${pointer}${label}${hint}${activeTag}`);
101342
+ }
101343
+ console.log("");
101344
+ }
101345
+ function cleanup() {
101346
+ stdin.removeListener("data", onKey);
101347
+ stdin.setRawMode(wasRaw ?? false);
101348
+ if (!stdin.isRaw) {
101349
+ stdin.resume();
101350
+ }
101351
+ }
101352
+ function onKey(data) {
101353
+ const key = data.toString();
101354
+ if (key === "q" || key === "\x1B" || key === "\x03") {
101355
+ cleanup();
101356
+ console.log(DIM2(" Cancelled."));
101357
+ resolve(null);
101358
+ return;
101359
+ }
101360
+ if (key === "\r" || key === `
101361
+ `) {
101362
+ cleanup();
101363
+ const selected = items[cursor];
101364
+ console.log(source_default.green(" ✓"), `Selected: ${source_default.bold(selected.label)}`);
101365
+ resolve(selected.value);
101366
+ return;
101367
+ }
101368
+ if (key === "\x1B[A" || key === "k") {
101369
+ cursor = cursor > 0 ? cursor - 1 : items.length - 1;
101370
+ render2();
101371
+ return;
101372
+ }
101373
+ if (key === "\x1B[B" || key === "j") {
101374
+ cursor = cursor < items.length - 1 ? cursor + 1 : 0;
101375
+ render2();
101376
+ return;
101377
+ }
101378
+ }
101379
+ stdin.setRawMode(true);
101380
+ stdin.resume();
101381
+ stdin.on("data", onKey);
101382
+ draw();
101383
+ });
101384
+ }
101385
+ async function handleModel(args, state2, rl) {
101313
101386
  const parts = args.trim().split(/\s+/).filter(Boolean);
101314
- if (parts.length === 0) {
101315
- console.log("");
101316
- console.log(` ${BRAND8("Provider:")} ${source_default.bold(state2.activeProvider)}`);
101317
- console.log(` ${BRAND8("Model:")} ${source_default.bold(state2.activeModel)}`);
101318
- console.log("");
101319
- console.log(DIM2(" Usage:"));
101320
- console.log(DIM2(" /model <provider> Switch provider (uses default model)"));
101321
- console.log(DIM2(" /model <provider> <model> Switch provider and model"));
101322
- console.log("");
101323
- console.log(DIM2(" Available:"));
101324
- const providers = listProviders();
101325
- for (const name of providers) {
101326
- const factory = PROVIDER_MAP[name];
101327
- if (!factory)
101328
- continue;
101329
- const p = factory();
101330
- const models = p.getModels();
101331
- const active = name === state2.activeProvider ? BRAND8(" ◀ active") : "";
101332
- console.log(` ${source_default.bold(name)}${active}`);
101333
- for (const m of models) {
101334
- const isActive = name === state2.activeProvider && m.id === state2.activeModel;
101335
- const marker = isActive ? source_default.green(" ● ") : " ";
101336
- const ctx = `${(m.contextWindow / 1000).toFixed(0)}k`;
101337
- console.log(`${marker}${m.id} ${DIM2(ctx)}`);
101387
+ if (parts.length >= 1) {
101388
+ const providerName = parts[0];
101389
+ const allProviders = listProviders();
101390
+ const match = allProviders.find((p) => p === providerName) ?? allProviders.find((p) => p.startsWith(providerName));
101391
+ if (!match) {
101392
+ console.log(source_default.red(" "), `Unknown provider: ${providerName}`);
101393
+ console.log(DIM2(` Available: ${allProviders.join(", ")}`));
101394
+ return;
101395
+ }
101396
+ state2.activeProvider = match;
101397
+ if (parts.length >= 2) {
101398
+ const modelId = parts[1];
101399
+ const available = getAllModelsForProvider(match);
101400
+ const exactMatch = available.find((m) => m === modelId);
101401
+ const fuzzyMatch = available.find((m) => m.includes(modelId));
101402
+ state2.activeModel = exactMatch ?? fuzzyMatch ?? getDefaultModel(match);
101403
+ if (!exactMatch && !fuzzyMatch) {
101404
+ console.log(source_default.yellow(""), `Model "${modelId}" not found. Using default.`);
101338
101405
  }
101406
+ } else {
101407
+ state2.activeModel = getDefaultModel(match);
101339
101408
  }
101340
- console.log("");
101409
+ console.log(source_default.green(""), `Provider: ${source_default.bold(state2.activeProvider)} Model: ${source_default.bold(state2.activeModel)}`);
101341
101410
  return;
101342
101411
  }
101343
- const providerName = parts[0];
101344
- const allProviders = listProviders();
101345
- if (!allProviders.includes(providerName)) {
101346
- const match = allProviders.find((p) => p.startsWith(providerName));
101347
- if (match) {
101348
- state2.activeProvider = match;
101349
- state2.activeModel = getDefaultModel(match);
101350
- console.log(source_default.green(" ✓"), `Provider: ${source_default.bold(match)} Model: ${source_default.bold(state2.activeModel)}`);
101351
- return;
101352
- }
101353
- console.log(source_default.red(" ✗"), `Unknown provider: ${providerName}`);
101354
- console.log(DIM2(` Available: ${allProviders.join(", ")}`));
101412
+ rl.pause();
101413
+ const providers = listProviders();
101414
+ const providerItems = providers.map((name) => {
101415
+ const factory2 = PROVIDER_MAP[name];
101416
+ const models2 = factory2 ? factory2().getModels() : [];
101417
+ return {
101418
+ label: name,
101419
+ value: name,
101420
+ hint: `${models2.length} model${models2.length !== 1 ? "s" : ""}`,
101421
+ active: name === state2.activeProvider
101422
+ };
101423
+ });
101424
+ const chosenProvider = await interactivePick("Select Provider", providerItems);
101425
+ if (!chosenProvider) {
101426
+ rl.resume();
101355
101427
  return;
101356
101428
  }
101357
- state2.activeProvider = providerName;
101358
- if (parts.length >= 2) {
101359
- const modelId = parts[1];
101360
- const available = getAllModelsForProvider(providerName);
101361
- const exactMatch = available.find((m) => m === modelId);
101362
- const fuzzyMatch = available.find((m) => m.includes(modelId));
101363
- if (exactMatch) {
101364
- state2.activeModel = exactMatch;
101365
- } else if (fuzzyMatch) {
101366
- state2.activeModel = fuzzyMatch;
101367
- } else {
101368
- console.log(source_default.yellow(" ⚠"), `Model "${modelId}" not found for ${providerName}. Using default.`);
101369
- console.log(DIM2(` Available: ${available.join(", ")}`));
101370
- state2.activeModel = getDefaultModel(providerName);
101371
- }
101372
- } else {
101373
- state2.activeModel = getDefaultModel(providerName);
101429
+ state2.activeProvider = chosenProvider;
101430
+ const models = getAllModelsForProvider(chosenProvider);
101431
+ const defaultModel = getDefaultModel(chosenProvider);
101432
+ if (models.length <= 1) {
101433
+ state2.activeModel = models[0] ?? defaultModel;
101434
+ console.log(source_default.green(" ✓"), `Provider: ${source_default.bold(state2.activeProvider)} Model: ${source_default.bold(state2.activeModel)}`);
101435
+ rl.resume();
101436
+ return;
101437
+ }
101438
+ const factory = PROVIDER_MAP[chosenProvider];
101439
+ const providerInstance = factory ? factory() : null;
101440
+ const modelDefs = providerInstance ? providerInstance.getModels() : [];
101441
+ const modelItems = models.map((id) => {
101442
+ const def = modelDefs.find((m) => m.id === id);
101443
+ const ctx = def ? `${(def.contextWindow / 1000).toFixed(0)}k` : "";
101444
+ const price = def && def.inputPricePer1M > 0 ? `$${def.inputPricePer1M.toFixed(2)}/$${def.outputPricePer1M.toFixed(2)}` : def ? "free" : "";
101445
+ return {
101446
+ label: id,
101447
+ value: id,
101448
+ hint: [ctx, price].filter(Boolean).join(" "),
101449
+ active: id === state2.activeModel && chosenProvider === state2.activeProvider
101450
+ };
101451
+ });
101452
+ const chosenModel = await interactivePick("Select Model", modelItems);
101453
+ if (!chosenModel) {
101454
+ state2.activeModel = defaultModel;
101455
+ console.log(source_default.green(" ✓"), `Provider: ${source_default.bold(state2.activeProvider)} Model: ${source_default.bold(state2.activeModel)}`);
101456
+ rl.resume();
101457
+ return;
101374
101458
  }
101459
+ state2.activeModel = chosenModel;
101375
101460
  console.log(source_default.green(" ✓"), `Provider: ${source_default.bold(state2.activeProvider)} Model: ${source_default.bold(state2.activeModel)}`);
101461
+ rl.resume();
101376
101462
  }
101377
101463
  async function handleStatus() {
101378
101464
  const { readdir: readdir8, readFile: readFile21 } = await import("node:fs/promises");
@@ -101753,7 +101839,7 @@ async function startRepl() {
101753
101839
  await handleCost();
101754
101840
  break;
101755
101841
  case "/model":
101756
- handleModel(args, state2);
101842
+ await handleModel(args, state2, rl);
101757
101843
  break;
101758
101844
  case "/auth":
101759
101845
  await handleAuth(args);
@@ -103287,7 +103373,7 @@ function getVersion() {
103287
103373
  const pkg = require2("../package.json");
103288
103374
  return pkg.version;
103289
103375
  } catch {
103290
- return "0.1.4";
103376
+ return "0.1.5";
103291
103377
  }
103292
103378
  }
103293
103379
  var hasArgs = process.argv.length > 2;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shipr-agent",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Fully autonomous terminal-based coding agent",
5
5
  "type": "module",
6
6
  "bin": {