shipr-agent 0.1.5 → 0.1.6

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 +207 -72
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -101234,17 +101234,135 @@ function getAllModelsForProvider(providerName) {
101234
101234
  const p = factory();
101235
101235
  return p.getModels().map((m) => m.id);
101236
101236
  }
101237
- function showCommandHints(partial2) {
101238
- const query = partial2.toLowerCase();
101239
- const matches = COMMANDS.filter((c) => c.name.startsWith(query));
101240
- if (matches.length === 0)
101241
- return;
101242
- console.log("");
101243
- for (const cmd of matches) {
101244
- const args = cmd.args ? ` ${DIM2(cmd.args)}` : "";
101245
- console.log(` ${BRAND8(cmd.name)}${args} ${DIM2("—")} ${DIM2(cmd.description)}`);
101246
- }
101247
- console.log("");
101237
+ function commandPicker(initial) {
101238
+ return new Promise((resolve) => {
101239
+ let query = initial;
101240
+ let selectedIdx = 0;
101241
+ let scrollTop = 0;
101242
+ let drawnLines = 0;
101243
+ const stdin = process.stdin;
101244
+ const wasRaw = stdin.isRaw;
101245
+ function filtered() {
101246
+ const q = query.slice(1).toLowerCase();
101247
+ if (!q)
101248
+ return COMMANDS;
101249
+ return COMMANDS.filter((c) => c.name.slice(1).startsWith(q) || c.name.slice(1).includes(q));
101250
+ }
101251
+ function clamp() {
101252
+ const matches = filtered();
101253
+ if (selectedIdx >= matches.length)
101254
+ selectedIdx = Math.max(0, matches.length - 1);
101255
+ if (selectedIdx < scrollTop)
101256
+ scrollTop = selectedIdx;
101257
+ if (selectedIdx >= scrollTop + PICKER_VISIBLE)
101258
+ scrollTop = selectedIdx - PICKER_VISIBLE + 1;
101259
+ }
101260
+ function draw() {
101261
+ const matches = filtered();
101262
+ const visible = matches.slice(scrollTop, scrollTop + PICKER_VISIBLE);
101263
+ const total = matches.length;
101264
+ const lines = [];
101265
+ lines.push(` ${DIM2(">")} ${source_default.bold(query)}`);
101266
+ lines.push("");
101267
+ if (visible.length === 0) {
101268
+ lines.push(DIM2(" No matching commands."));
101269
+ } else {
101270
+ for (let i2 = 0;i2 < visible.length; i2++) {
101271
+ const item = visible[i2];
101272
+ const gi = scrollTop + i2;
101273
+ const sel = gi === selectedIdx;
101274
+ const pointer = sel ? BRAND8("❯ ") : " ";
101275
+ const name = sel ? BRAND_BOLD(item.name.padEnd(14)) : BRAND8(item.name.padEnd(14));
101276
+ const desc = sel ? item.description : DIM2(item.description);
101277
+ lines.push(` ${pointer}${name} ${desc}`);
101278
+ }
101279
+ }
101280
+ lines.push("");
101281
+ const from = total === 0 ? 0 : scrollTop + 1;
101282
+ const to = Math.min(scrollTop + PICKER_VISIBLE, total);
101283
+ lines.push(DIM2(` Use ↑↓ to navigate, Tab/Enter to select, Esc to cancel • Showing ${from}–${to} of ${total}`));
101284
+ if (drawnLines > 0) {
101285
+ process.stdout.write(`\x1B[${drawnLines}A\x1B[0J`);
101286
+ }
101287
+ for (const line of lines) {
101288
+ process.stdout.write(line + `
101289
+ `);
101290
+ }
101291
+ drawnLines = lines.length;
101292
+ }
101293
+ function cleanup() {
101294
+ stdin.removeListener("data", onKey);
101295
+ if (wasRaw !== undefined)
101296
+ stdin.setRawMode(wasRaw);
101297
+ if (!stdin.isRaw)
101298
+ stdin.resume();
101299
+ }
101300
+ function cancel() {
101301
+ cleanup();
101302
+ if (drawnLines > 0)
101303
+ process.stdout.write(`\x1B[${drawnLines}A\x1B[0J`);
101304
+ resolve(null);
101305
+ }
101306
+ function select() {
101307
+ const matches = filtered();
101308
+ const chosen = matches[selectedIdx]?.name ?? null;
101309
+ cleanup();
101310
+ if (drawnLines > 0)
101311
+ process.stdout.write(`\x1B[${drawnLines}A\x1B[0J`);
101312
+ resolve(chosen);
101313
+ }
101314
+ function onKey(data) {
101315
+ const key = data.toString();
101316
+ if (key === "\x1B" || key === "\x03") {
101317
+ cancel();
101318
+ return;
101319
+ }
101320
+ if (key === "\r" || key === `
101321
+ ` || key === "\t") {
101322
+ select();
101323
+ return;
101324
+ }
101325
+ if (key === "" || key === "\b") {
101326
+ if (query.length > 1) {
101327
+ query = query.slice(0, -1);
101328
+ selectedIdx = 0;
101329
+ scrollTop = 0;
101330
+ draw();
101331
+ } else {
101332
+ cancel();
101333
+ }
101334
+ return;
101335
+ }
101336
+ if (key === "\x1B[A") {
101337
+ if (selectedIdx > 0) {
101338
+ selectedIdx--;
101339
+ clamp();
101340
+ draw();
101341
+ }
101342
+ return;
101343
+ }
101344
+ if (key === "\x1B[B") {
101345
+ if (selectedIdx < filtered().length - 1) {
101346
+ selectedIdx++;
101347
+ clamp();
101348
+ draw();
101349
+ }
101350
+ return;
101351
+ }
101352
+ if (key.length === 1 && key >= " ") {
101353
+ query += key;
101354
+ selectedIdx = 0;
101355
+ scrollTop = 0;
101356
+ draw();
101357
+ return;
101358
+ }
101359
+ }
101360
+ stdin.setRawMode(true);
101361
+ stdin.resume();
101362
+ stdin.on("data", onKey);
101363
+ drawnLines = 0;
101364
+ draw();
101365
+ });
101248
101366
  }
101249
101367
  async function handleRun(args, state2) {
101250
101368
  if (!args.trim()) {
@@ -101776,7 +101894,7 @@ async function startRepl() {
101776
101894
  }
101777
101895
  console.log("");
101778
101896
  console.log(DIM2(" Type /help for commands, /run <mission> to start."));
101779
- console.log(DIM2(` Press Tab to autocomplete commands.
101897
+ console.log(DIM2(` Type / to browse all commands interactively.
101780
101898
  `));
101781
101899
  const state2 = {
101782
101900
  activeProvider,
@@ -101794,17 +101912,62 @@ async function startRepl() {
101794
101912
  historySize: 200
101795
101913
  });
101796
101914
  rl.prompt();
101915
+ const NO_ARG_COMMANDS = new Set(["/resume", "/status", "/cost", "/providers", "/missions", "/help", "/exit", "/quit", "/q", "/model"]);
101916
+ async function dispatchCommand(cmd, args) {
101917
+ switch (cmd) {
101918
+ case "/run":
101919
+ await handleRun(args, state2);
101920
+ break;
101921
+ case "/simulate":
101922
+ await handleSimulate(args, state2);
101923
+ break;
101924
+ case "/resume":
101925
+ await handleResume(state2);
101926
+ break;
101927
+ case "/status":
101928
+ await handleStatus();
101929
+ break;
101930
+ case "/steer":
101931
+ await handleSteer(args);
101932
+ break;
101933
+ case "/cost":
101934
+ await handleCost();
101935
+ break;
101936
+ case "/model":
101937
+ await handleModel(args, state2, rl);
101938
+ break;
101939
+ case "/auth":
101940
+ await handleAuth(args);
101941
+ break;
101942
+ case "/providers":
101943
+ handleProviders();
101944
+ break;
101945
+ case "/missions":
101946
+ await handleMissions();
101947
+ break;
101948
+ case "/help":
101949
+ handleHelp();
101950
+ break;
101951
+ case "/exit":
101952
+ case "/quit":
101953
+ case "/q":
101954
+ if (state2.missionRunning) {
101955
+ console.log(source_default.yellow(" ⚠"), "A mission is still running. It will be interrupted.");
101956
+ }
101957
+ console.log(DIM2(" Goodbye."));
101958
+ rl.close();
101959
+ process.exit(0);
101960
+ break;
101961
+ default:
101962
+ console.log(DIM2(` Unknown command: ${cmd}. Type ${BRAND8("/")} to see all commands.`));
101963
+ }
101964
+ }
101797
101965
  rl.on("line", (line) => {
101798
101966
  const trimmed2 = line.trim();
101799
101967
  if (!trimmed2) {
101800
101968
  rl.prompt();
101801
101969
  return;
101802
101970
  }
101803
- if (trimmed2 === "/") {
101804
- showCommandHints("/");
101805
- rl.prompt();
101806
- return;
101807
- }
101808
101971
  if (!trimmed2.startsWith("/")) {
101809
101972
  console.log(DIM2(` hint: use ${BRAND8("/run")} <your mission> to start. Type ${BRAND8("/")} to see all commands.`));
101810
101973
  rl.prompt();
@@ -101813,61 +101976,33 @@ async function startRepl() {
101813
101976
  const spaceIdx = trimmed2.indexOf(" ");
101814
101977
  const cmd = spaceIdx === -1 ? trimmed2 : trimmed2.slice(0, spaceIdx);
101815
101978
  const args = spaceIdx === -1 ? "" : trimmed2.slice(spaceIdx + 1);
101816
- if (spaceIdx === -1 && !COMMAND_NAMES.includes(cmd)) {
101817
- showCommandHints(cmd);
101818
- rl.prompt();
101979
+ if (trimmed2 === "/" || spaceIdx === -1 && !COMMAND_NAMES.includes(cmd)) {
101980
+ rl.pause();
101981
+ let skipFinalPrompt = false;
101982
+ commandPicker(trimmed2).then(async (chosen) => {
101983
+ if (chosen) {
101984
+ if (NO_ARG_COMMANDS.has(chosen)) {
101985
+ await dispatchCommand(chosen, "");
101986
+ rl.resume();
101987
+ } else {
101988
+ skipFinalPrompt = true;
101989
+ rl.resume();
101990
+ rl.prompt();
101991
+ rl.write(chosen + " ");
101992
+ }
101993
+ } else {
101994
+ rl.resume();
101995
+ }
101996
+ }).catch((err) => {
101997
+ rl.resume();
101998
+ console.log(source_default.red(" ✗"), err.message);
101999
+ }).finally(() => {
102000
+ if (!skipFinalPrompt)
102001
+ rl.prompt();
102002
+ });
101819
102003
  return;
101820
102004
  }
101821
- const dispatch = async () => {
101822
- switch (cmd) {
101823
- case "/run":
101824
- await handleRun(args, state2);
101825
- break;
101826
- case "/simulate":
101827
- await handleSimulate(args, state2);
101828
- break;
101829
- case "/resume":
101830
- await handleResume(state2);
101831
- break;
101832
- case "/status":
101833
- await handleStatus();
101834
- break;
101835
- case "/steer":
101836
- await handleSteer(args);
101837
- break;
101838
- case "/cost":
101839
- await handleCost();
101840
- break;
101841
- case "/model":
101842
- await handleModel(args, state2, rl);
101843
- break;
101844
- case "/auth":
101845
- await handleAuth(args);
101846
- break;
101847
- case "/providers":
101848
- handleProviders();
101849
- break;
101850
- case "/missions":
101851
- await handleMissions();
101852
- break;
101853
- case "/help":
101854
- handleHelp();
101855
- break;
101856
- case "/exit":
101857
- case "/quit":
101858
- case "/q":
101859
- if (state2.missionRunning) {
101860
- console.log(source_default.yellow(" ⚠"), "A mission is still running. It will be interrupted.");
101861
- }
101862
- console.log(DIM2(" Goodbye."));
101863
- rl.close();
101864
- process.exit(0);
101865
- break;
101866
- default:
101867
- console.log(DIM2(` Unknown command: ${cmd}. Type ${BRAND8("/")} to see all commands.`));
101868
- }
101869
- };
101870
- dispatch().catch((err) => {
102005
+ dispatchCommand(cmd, args).catch((err) => {
101871
102006
  console.log(source_default.red(" ✗"), err.message);
101872
102007
  }).finally(() => {
101873
102008
  rl.prompt();
@@ -101879,7 +102014,7 @@ async function startRepl() {
101879
102014
  process.exit(0);
101880
102015
  });
101881
102016
  }
101882
- var BRAND8, BRAND_BOLD, DIM2, PROMPT, COMMANDS, COMMAND_NAMES, BANNER;
102017
+ var BRAND8, BRAND_BOLD, DIM2, PROMPT, COMMANDS, COMMAND_NAMES, BANNER, PICKER_VISIBLE = 6;
101883
102018
  var init_repl = __esm(async () => {
101884
102019
  init_source();
101885
102020
  init_keychain();
@@ -103373,7 +103508,7 @@ function getVersion() {
103373
103508
  const pkg = require2("../package.json");
103374
103509
  return pkg.version;
103375
103510
  } catch {
103376
- return "0.1.5";
103511
+ return "0.1.6";
103377
103512
  }
103378
103513
  }
103379
103514
  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.5",
3
+ "version": "0.1.6",
4
4
  "description": "Fully autonomous terminal-based coding agent",
5
5
  "type": "module",
6
6
  "bin": {