@devkitvault/recall 1.2.3 → 1.2.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/README.md CHANGED
@@ -39,7 +39,7 @@ recall playbook run deploy --dry-run
39
39
 
40
40
  `recall playbook run` executes steps. Ask never does.
41
41
 
42
- Ask prints a suggestion (`source` is `vault`, `cache`, or `llm`). Copy or save it yourself.
42
+ Ask prints a suggestion (`source` is `vault`, `cache`, or `recall agent` for a generated answer). Copy or save it yourself.
43
43
 
44
44
  ```sh
45
45
  recall save "docker compose up -d" --name docker --tags docker
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.askCommand = void 0;
7
7
  exports.printSuggestion = printSuggestion;
8
8
  exports.printAskError = printAskError;
9
+ exports.promptSaveMeta = promptSaveMeta;
9
10
  exports.saveSuggestion = saveSuggestion;
10
11
  exports.resolveAsk = resolveAsk;
11
12
  exports.runAsk = runAsk;
@@ -17,7 +18,9 @@ const auth_1 = require("../lib/auth");
17
18
  const events_1 = require("../lib/events");
18
19
  const project_1 = require("../lib/project");
19
20
  const runtime_1 = require("../lib/runtime");
21
+ const source_label_1 = require("../lib/source-label");
20
22
  const spinner_1 = require("../lib/spinner");
23
+ const tags_1 = require("../lib/tags");
21
24
  function riskColor(risk) {
22
25
  if (risk === 'DANGEROUS')
23
26
  return chalk_1.default.red(risk);
@@ -34,7 +37,7 @@ function printSuggestion(result) {
34
37
  console.log(` ${chalk_1.default.dim(result.explanation)}`);
35
38
  }
36
39
  console.log();
37
- console.log(` ${chalk_1.default.dim('shell:')} ${result.shell} ${chalk_1.default.dim('risk:')} ${riskColor(result.risk)} ${chalk_1.default.dim('source:')} ${result.source}`);
40
+ console.log(` ${chalk_1.default.dim('shell:')} ${result.shell} ${chalk_1.default.dim('risk:')} ${riskColor(result.risk)} ${chalk_1.default.dim('source:')} ${(0, source_label_1.sourceLabel)(result.source)}`);
38
41
  if (result.source === 'vault') {
39
42
  const playbook = result.explanation?.includes('playbooks');
40
43
  console.log(chalk_1.default.dim(playbook ? ' from your playbooks' : ' from your vault'));
@@ -67,12 +70,25 @@ function printAskError(err) {
67
70
  }
68
71
  console.error(chalk_1.default.red('\n Failed to resolve that request.\n'));
69
72
  }
70
- function parseTags(raw) {
71
- const tags = (raw ?? '')
72
- .split(',')
73
- .map((t) => t.trim())
74
- .filter(Boolean);
75
- return tags.length ? tags : undefined;
73
+ async function promptSaveMeta(existingName) {
74
+ const questions = [];
75
+ if (!existingName?.trim()) {
76
+ questions.push({
77
+ type: 'input',
78
+ name: 'name',
79
+ message: 'Name (optional):',
80
+ });
81
+ }
82
+ questions.push({
83
+ type: 'input',
84
+ name: 'tags',
85
+ message: 'Tags (optional):',
86
+ });
87
+ const answers = await inquirer_1.default.prompt(questions);
88
+ return {
89
+ name: existingName?.trim() || answers.name,
90
+ tags: (0, tags_1.parseTags)(answers.tags),
91
+ };
76
92
  }
77
93
  async function saveSuggestion(token, command, name, source, risk, tags) {
78
94
  await api_1.ApiClient.post('/commands', {
@@ -81,7 +97,7 @@ async function saveSuggestion(token, command, name, source, risk, tags) {
81
97
  tags,
82
98
  }, token);
83
99
  await (0, events_1.track)('ai_accepted', { source, risk, saved: true });
84
- console.log(chalk_1.default.green('\n Saved.\n'));
100
+ console.log(chalk_1.default.green(`\n ${(0, tags_1.formatSavedMessage)(name, tags)}\n`));
85
101
  }
86
102
  async function resolveAsk(opts) {
87
103
  const runtime = (0, runtime_1.detectRuntime)();
@@ -124,27 +140,16 @@ async function runAsk(query) {
124
140
  }]);
125
141
  if (!save)
126
142
  return;
127
- const { name, tags } = await inquirer_1.default.prompt([
128
- {
129
- type: 'input',
130
- name: 'name',
131
- message: 'Name (optional):',
132
- },
133
- {
134
- type: 'input',
135
- name: 'tags',
136
- message: 'Tags (optional):',
137
- },
138
- ]);
143
+ const { name, tags } = await promptSaveMeta();
139
144
  try {
140
- await saveSuggestion(token, result.command, name, result.source, result.risk, parseTags(tags));
145
+ await saveSuggestion(token, result.command, name, result.source, result.risk, tags);
141
146
  }
142
147
  catch (err) {
143
148
  printAskError(err);
144
149
  }
145
150
  }
146
151
  exports.askCommand = new commander_1.Command('ask')
147
- .description('Suggest a command from natural language (does not run it)')
152
+ .description('Suggest a terminal command. Ask is for terminal commands only and does not run them.')
148
153
  .argument('<query...>', 'What you want to do')
149
154
  .action(async (parts) => {
150
155
  await runAsk(parts.join(' '));
@@ -11,8 +11,8 @@ const events_1 = require("../lib/events");
11
11
  const turns_1 = require("../lib/turns");
12
12
  const ask_1 = require("./ask");
13
13
  function printReplHelp() {
14
- console.log(chalk_1.default.dim(' Ask prints a command. It does not run it.'));
15
- console.log(chalk_1.default.dim(' /save [name] save the last suggestion'));
14
+ console.log(chalk_1.default.dim(' Ask is for terminal commands only. It prints a command and does not run it.'));
15
+ console.log(chalk_1.default.dim(' /save [name] save the last suggestion (asks for tags)'));
16
16
  console.log(chalk_1.default.dim(' /clear forget this session'));
17
17
  console.log(chalk_1.default.dim(' /exit leave'));
18
18
  }
@@ -29,7 +29,7 @@ async function runRepl() {
29
29
  let turnIndex = 0;
30
30
  let busy = false;
31
31
  let open = true;
32
- console.log(chalk_1.default.dim(' Ask session. Prints only. /help for commands.'));
32
+ console.log(chalk_1.default.dim(' Ask is for terminal commands only. Prints only. /help for commands.'));
33
33
  rl.prompt();
34
34
  async function handleLine(raw) {
35
35
  const line = raw.trim();
@@ -54,9 +54,10 @@ async function runRepl() {
54
54
  console.log(chalk_1.default.dim(' nothing to save'));
55
55
  return;
56
56
  }
57
- const name = line === '/save' ? undefined : line.slice(6).trim();
57
+ const named = line === '/save' ? undefined : line.slice(6).trim();
58
58
  try {
59
- await (0, ask_1.saveSuggestion)(token, last.command, name, last.source, last.risk);
59
+ const { name, tags } = await (0, ask_1.promptSaveMeta)(named);
60
+ await (0, ask_1.saveSuggestion)(token, last.command, name, last.source, last.risk, tags);
60
61
  }
61
62
  catch {
62
63
  console.error(chalk_1.default.red('\n Failed to save.\n'));
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sourceLabel = sourceLabel;
4
+ /** Printed Ask source. API/DB still use `llm` for generated answers. */
5
+ function sourceLabel(source) {
6
+ return source === 'llm' ? 'recall agent' : source;
7
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTags = parseTags;
4
+ exports.formatSavedMessage = formatSavedMessage;
5
+ function parseTags(raw) {
6
+ const tags = (raw ?? '')
7
+ .split(',')
8
+ .map((t) => t.trim())
9
+ .filter(Boolean);
10
+ return tags.length ? tags : undefined;
11
+ }
12
+ function formatSavedMessage(name, tags) {
13
+ const label = name?.trim() || undefined;
14
+ const tagPart = tags?.length ? ` [${tags.join(', ')}]` : '';
15
+ if (label)
16
+ return `Saved as "${label}"${tagPart}.`;
17
+ if (tagPart)
18
+ return `Saved${tagPart}.`;
19
+ return 'Saved.';
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devkitvault/recall",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "recall CLI — AI terminal copilot with a personal command vault",
5
5
  "keywords": [
6
6
  "cli",