shipr-agent 0.1.3 → 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.
- package/dist/index.js +155 -57
- package/package.json +2 -2
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
|
|
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
|
|
101315
|
-
|
|
101316
|
-
|
|
101317
|
-
|
|
101318
|
-
|
|
101319
|
-
|
|
101320
|
-
|
|
101321
|
-
|
|
101322
|
-
|
|
101323
|
-
|
|
101324
|
-
|
|
101325
|
-
|
|
101326
|
-
const
|
|
101327
|
-
|
|
101328
|
-
|
|
101329
|
-
|
|
101330
|
-
|
|
101331
|
-
|
|
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
|
-
|
|
101344
|
-
const
|
|
101345
|
-
|
|
101346
|
-
const
|
|
101347
|
-
|
|
101348
|
-
|
|
101349
|
-
|
|
101350
|
-
|
|
101351
|
-
|
|
101352
|
-
|
|
101353
|
-
|
|
101354
|
-
|
|
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 =
|
|
101358
|
-
|
|
101359
|
-
|
|
101360
|
-
|
|
101361
|
-
|
|
101362
|
-
|
|
101363
|
-
|
|
101364
|
-
|
|
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;
|
|
101374
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;
|
|
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);
|
|
@@ -101829,6 +101915,9 @@ ${BRAND_BOLD(" ╚══════╝╚═╝ ╚═╝╚═╝╚═╝
|
|
|
101829
101915
|
`;
|
|
101830
101916
|
});
|
|
101831
101917
|
|
|
101918
|
+
// src/index.ts
|
|
101919
|
+
import { createRequire as createRequire2 } from "module";
|
|
101920
|
+
|
|
101832
101921
|
// node_modules/commander/esm.mjs
|
|
101833
101922
|
var import__ = __toESM(require_commander(), 1);
|
|
101834
101923
|
var {
|
|
@@ -103278,13 +103367,22 @@ async function findActiveMission(cwd2) {
|
|
|
103278
103367
|
}
|
|
103279
103368
|
|
|
103280
103369
|
// src/index.ts
|
|
103370
|
+
function getVersion() {
|
|
103371
|
+
try {
|
|
103372
|
+
const require2 = createRequire2(import.meta.url);
|
|
103373
|
+
const pkg = require2("../package.json");
|
|
103374
|
+
return pkg.version;
|
|
103375
|
+
} catch {
|
|
103376
|
+
return "0.1.5";
|
|
103377
|
+
}
|
|
103378
|
+
}
|
|
103281
103379
|
var hasArgs = process.argv.length > 2;
|
|
103282
103380
|
if (!hasArgs) {
|
|
103283
103381
|
const { startRepl: startRepl2 } = await init_repl().then(() => exports_repl);
|
|
103284
103382
|
await startRepl2();
|
|
103285
103383
|
} else {
|
|
103286
103384
|
const program2 = new Command;
|
|
103287
|
-
program2.name("shipr").version(
|
|
103385
|
+
program2.name("shipr").version(getVersion()).description("Fully autonomous terminal-based coding agent");
|
|
103288
103386
|
registerRunCommand(program2);
|
|
103289
103387
|
registerNewCommand(program2);
|
|
103290
103388
|
registerResumeCommand(program2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shipr-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Fully autonomous terminal-based coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
],
|
|
15
15
|
"scripts": {
|
|
16
16
|
"dev": "bun src/index.ts",
|
|
17
|
-
"build": "bun build src/index.ts --outdir dist --target node --format esm && node -e \"const fs=require('fs');const f='dist/index.js';let c=fs.readFileSync(f,'utf8');c=c.replace('#!/usr/bin/env bun','#!/usr/bin/env node');fs.writeFileSync(f,c)\"",
|
|
17
|
+
"build": "bun build src/index.ts --outdir dist --target node --format esm && node -e \"const fs=require('fs');const f='dist/index.js';const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));let c=fs.readFileSync(f,'utf8');c=c.replace('#!/usr/bin/env bun','#!/usr/bin/env node');c=c.replace('__SHIPR_VERSION__',pkg.version);fs.writeFileSync(f,c)\"",
|
|
18
18
|
"build:bin": "bun build src/index.ts --compile --outfile shipr",
|
|
19
19
|
"typecheck": "bunx tsc --noEmit",
|
|
20
20
|
"lint": "bunx biome check src/",
|