@greppleai/grip 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 (34) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +1 -1
  3. package/dist/core/auth-storage.d.ts.map +1 -1
  4. package/dist/core/auth-storage.js +3 -1
  5. package/dist/core/auth-storage.js.map +1 -1
  6. package/dist/core/grip-agent.d.ts.map +1 -1
  7. package/dist/core/grip-agent.js +4 -2
  8. package/dist/core/grip-agent.js.map +1 -1
  9. package/dist/core/sandbox/lima.d.ts.map +1 -1
  10. package/dist/core/sandbox/lima.js +6 -6
  11. package/dist/core/sandbox/lima.js.map +1 -1
  12. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  13. package/dist/modes/interactive/components/assistant-message.js +18 -7
  14. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  15. package/dist/modes/interactive/components/model-selector.d.ts +26 -18
  16. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  17. package/dist/modes/interactive/components/model-selector.js +220 -192
  18. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  19. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  20. package/dist/modes/interactive/interactive-mode.js +68 -6
  21. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  22. package/dist/utils/grip-user-agent.d.ts.map +1 -1
  23. package/dist/utils/grip-user-agent.js +1 -1
  24. package/dist/utils/grip-user-agent.js.map +1 -1
  25. package/docs/keybindings.md +3 -1
  26. package/docs/providers.md +3 -1
  27. package/docs/sandbox.md +1 -1
  28. package/docs/usage.md +37 -1
  29. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  30. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  31. package/examples/extensions/sandbox/package.json +1 -1
  32. package/examples/extensions/with-deps/package.json +1 -1
  33. package/npm-shrinkwrap.json +12 -12
  34. package/package.json +4 -4
@@ -428,16 +428,78 @@ export class InteractiveMode {
428
428
  }));
429
429
  }
430
430
  createBaseAutocompleteProvider() {
431
- // Define commands for autocomplete
431
+ // Commands without arguments remain selectable after a trailing space (e.g. /new ).
432
+ const noArgumentCommands = new Set([
433
+ "settings",
434
+ "scoped-models",
435
+ "share",
436
+ "copy",
437
+ "session",
438
+ "changelog",
439
+ "hotkeys",
440
+ "fork",
441
+ "clone",
442
+ "tree",
443
+ "login",
444
+ "logout",
445
+ "new",
446
+ "reload",
447
+ "resume",
448
+ "quit",
449
+ ]);
432
450
  const slashCommands = BUILTIN_SLASH_COMMANDS.map((command) => ({
433
451
  name: command.name,
434
452
  description: command.description,
453
+ showWithoutArguments: noArgumentCommands.has(command.name),
435
454
  }));
436
455
  const cdCommand = slashCommands.find((command) => command.name === "cd");
437
456
  if (cdCommand) {
438
457
  cdCommand.argumentHint = "<directory>";
439
458
  cdCommand.getArgumentCompletions = (prefix) => this.session.supportsDirectoryChange() ? getDirectoryCompletions(prefix, this.activeSession.getCwd()) : [];
440
459
  }
460
+ const choiceCompletions = (choices) => (prefix) => {
461
+ if (prefix.includes(" "))
462
+ return null;
463
+ return fuzzyFilter([...choices], prefix, (choice) => choice).map((choice) => ({
464
+ value: choice,
465
+ label: choice,
466
+ }));
467
+ };
468
+ const commandsByName = new Map();
469
+ for (const command of slashCommands) {
470
+ if (!commandsByName.has(command.name))
471
+ commandsByName.set(command.name, command);
472
+ }
473
+ for (const [name, hint, choices] of [
474
+ ["hooks", "<enable|disable>", ["enable", "disable"]],
475
+ ["context-compression", "[on|off]", ["on", "off"]],
476
+ ["compress-detection", "[on|off]", ["on", "off"]],
477
+ ]) {
478
+ const command = commandsByName.get(name);
479
+ if (command) {
480
+ command.argumentHint = hint;
481
+ command.getArgumentCompletions = choiceCompletions(choices);
482
+ }
483
+ }
484
+ const sandboxCommand = slashCommands.find((command) => command.name === "sandbox");
485
+ if (sandboxCommand) {
486
+ sandboxCommand.argumentHint = "<status|clear|--attach|start|list|stop>";
487
+ sandboxCommand.getArgumentCompletions = (prefix) => {
488
+ if (!prefix.includes(" ")) {
489
+ return fuzzyFilter(["status", "clear", "--attach", "start", "list", "stop"], prefix, (item) => item).map((item) => ({
490
+ value: item === "start" || item === "stop" || item === "--attach" ? `${item} ` : item,
491
+ label: item,
492
+ }));
493
+ }
494
+ const startMatch = prefix.match(/^start\s+(--[^\s]*)$/);
495
+ if (!startMatch)
496
+ return null;
497
+ return fuzzyFilter(["--name", "--template", "--update"], startMatch[1], (item) => item).map((item) => ({
498
+ value: `start ${item}${item === "--update" ? "" : " "}`,
499
+ label: item,
500
+ }));
501
+ };
502
+ }
441
503
  const modelCommand = slashCommands.find((command) => command.name === "model");
442
504
  if (modelCommand) {
443
505
  modelCommand.getArgumentCompletions = (prefix) => {
@@ -526,7 +588,7 @@ export class InteractiveMode {
526
588
  getSuggestions: async (lines, cursorLine, cursorCol, options) => {
527
589
  const beforeCursor = (lines[cursorLine] ?? "").slice(0, cursorCol);
528
590
  const nameMatch = beforeCursor.match(/^\/sandbox[ \t]+(start[ \t]+--name(?:[ \t]+([^\s]*))?)$/);
529
- if (!options.force || !nameMatch)
591
+ if (!nameMatch)
530
592
  return base.getSuggestions(lines, cursorLine, cursorCol, options);
531
593
  if (options.signal.aborted)
532
594
  return null;
@@ -4599,12 +4661,12 @@ export class InteractiveMode {
4599
4661
  return options.sort((a, b) => a.name.localeCompare(b.name));
4600
4662
  }
4601
4663
  showLoginAuthTypeSelector() {
4602
- const subscriptionLabel = "Use a subscription";
4664
+ const browserLabel = "Sign in (subscriptions or OpenRouter credits)";
4603
4665
  const apiKeyLabel = "Use an API key";
4604
4666
  this.showSelector((done) => {
4605
- const selector = new ExtensionSelectorComponent("Select authentication method:", [subscriptionLabel, apiKeyLabel], (option) => {
4667
+ const selector = new ExtensionSelectorComponent("Select authentication method:", [browserLabel, apiKeyLabel], (option) => {
4606
4668
  done();
4607
- const authType = option === subscriptionLabel ? "oauth" : "api_key";
4669
+ const authType = option === browserLabel ? "oauth" : "api_key";
4608
4670
  this.showLoginProviderSelector(authType);
4609
4671
  }, () => {
4610
4672
  done();
@@ -4616,7 +4678,7 @@ export class InteractiveMode {
4616
4678
  showLoginProviderSelector(authType) {
4617
4679
  const providerOptions = this.getLoginProviderOptions(authType);
4618
4680
  if (providerOptions.length === 0) {
4619
- this.showStatus(authType === "oauth" ? "No subscription providers available." : "No API key providers available.");
4681
+ this.showStatus(authType === "oauth" ? "No browser sign-in providers available." : "No API key providers available.");
4620
4682
  return;
4621
4683
  }
4622
4684
  this.showSelector((done) => {