@dinoxx/dinox-cli 2.14.0 → 2.15.0

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 (76) hide show
  1. package/dist/ai/ragxClient.d.ts +15 -0
  2. package/dist/ai/ragxClient.js +71 -0
  3. package/dist/cli.js +27 -3
  4. package/dist/commands/batch.d.ts +35 -0
  5. package/dist/commands/batch.js +202 -0
  6. package/dist/commands/boxes/index.js +21 -21
  7. package/dist/commands/mcp.d.ts +6 -0
  8. package/dist/commands/mcp.js +47 -0
  9. package/dist/commands/notes/actions.js +18 -2
  10. package/dist/commands/notes/descriptors.js +111 -5
  11. package/dist/commands/notes/detailContent.d.ts +19 -0
  12. package/dist/commands/notes/detailContent.js +62 -0
  13. package/dist/commands/notes/export.js +4 -0
  14. package/dist/commands/notes/repo/search.d.ts +2 -1
  15. package/dist/commands/notes/repo/search.js +1 -1
  16. package/dist/commands/notes/repo/semantic.d.ts +14 -0
  17. package/dist/commands/notes/repo/semantic.js +31 -0
  18. package/dist/commands/notes/searchResponse.d.ts +3 -0
  19. package/dist/commands/notes/searchResponse.js +1 -0
  20. package/dist/commands/notes/semantic.d.ts +116 -0
  21. package/dist/commands/notes/semantic.js +332 -0
  22. package/dist/commands/prompt/index.js +7 -5
  23. package/dist/commands/savedViews/index.js +12 -3
  24. package/dist/commands/schema/globalOptions.d.ts +6 -0
  25. package/dist/commands/schema/globalOptions.js +6 -0
  26. package/dist/commands/schema/renderSkills.js +5 -2
  27. package/dist/commands/schema/spec.js +18 -7
  28. package/dist/commands/storage/index.js +7 -5
  29. package/dist/commands/sync.js +3 -3
  30. package/dist/commands/tags/index.js +21 -21
  31. package/dist/commands/todo/index.js +22 -2
  32. package/dist/commands/todo/repo.d.ts +5 -0
  33. package/dist/commands/todo/repo.js +7 -2
  34. package/dist/commands/writeReceipt.d.ts +13 -0
  35. package/dist/commands/writeReceipt.js +12 -0
  36. package/dist/config/serviceEndpoints.d.ts +2 -0
  37. package/dist/config/serviceEndpoints.js +2 -0
  38. package/dist/daemon/client.d.ts +2 -0
  39. package/dist/daemon/client.js +22 -2
  40. package/dist/daemon/forward.d.ts +4 -1
  41. package/dist/daemon/forward.js +13 -4
  42. package/dist/daemon/server.d.ts +1 -1
  43. package/dist/daemon/server.js +17 -1
  44. package/dist/daemon/types.d.ts +6 -0
  45. package/dist/dinox.js +12 -10
  46. package/dist/gateway/deviceHost.js +2 -1
  47. package/dist/gateway/mcpCommandTools.d.ts +15 -5
  48. package/dist/gateway/mcpCommandTools.js +30 -19
  49. package/dist/gateway/mcpEnv.d.ts +2 -0
  50. package/dist/gateway/mcpEnv.js +2 -0
  51. package/dist/gateway/mcpGroups.d.ts +3 -0
  52. package/dist/gateway/mcpGroups.js +4 -0
  53. package/dist/gateway/mcpServer.d.ts +10 -1
  54. package/dist/gateway/mcpServer.js +25 -5
  55. package/dist/powersync/syncPass.js +13 -1
  56. package/dist/powersync/tokenIndex.d.ts +2 -0
  57. package/dist/powersync/tokenIndex.js +1 -0
  58. package/dist/requests/execute.d.ts +11 -0
  59. package/dist/requests/execute.js +26 -0
  60. package/dist/skills/commandRefs.js +2 -10
  61. package/dist/utils/cursor.d.ts +9 -0
  62. package/dist/utils/cursor.js +61 -0
  63. package/dist/utils/defaultFormat.d.ts +8 -0
  64. package/dist/utils/defaultFormat.js +38 -0
  65. package/dist/utils/errorCodes.d.ts +4 -0
  66. package/dist/utils/errorCodes.js +1 -0
  67. package/dist/utils/output.d.ts +2 -0
  68. package/dist/utils/output.js +41 -3
  69. package/dist/utils/progress.d.ts +25 -0
  70. package/dist/utils/progress.js +59 -0
  71. package/dist/utils/requestContext.d.ts +8 -0
  72. package/dist/utils/select.d.ts +20 -0
  73. package/dist/utils/select.js +92 -0
  74. package/dist/utils/usageError.d.ts +37 -0
  75. package/dist/utils/usageError.js +127 -0
  76. package/package.json +1 -1
@@ -0,0 +1,92 @@
1
+ import { DinoxError } from './errors.js';
2
+ const FIELD_PATH = /^[A-Za-z0-9_$-]+(\.[A-Za-z0-9_$-]+)*$/;
3
+ /**
4
+ * Parses `--select notes.id,notes.title,count` into a selection tree. A path
5
+ * that names a parent also keeps everything below it (`notes,notes.id` keeps
6
+ * whole notes).
7
+ */
8
+ export function parseFieldSelection(value) {
9
+ const raw = Array.isArray(value) ? value.join(',') : String(value ?? '');
10
+ const paths = raw.split(',').map((path) => path.trim()).filter(Boolean);
11
+ if (paths.length === 0) {
12
+ throw new DinoxError('--select needs at least one field path, e.g. --select notes.id,notes.title', {
13
+ code: 'INVALID_ARGUMENT',
14
+ recoverable: true,
15
+ });
16
+ }
17
+ const selection = {};
18
+ for (const path of paths) {
19
+ if (!FIELD_PATH.test(path)) {
20
+ throw new DinoxError(`Invalid --select field path: ${path}`, {
21
+ code: 'INVALID_ARGUMENT',
22
+ recoverable: true,
23
+ suggestion: 'Use dot-separated output field names from `dino schema <command> --format json`.',
24
+ });
25
+ }
26
+ let node = selection;
27
+ const segments = path.split('.');
28
+ segments.forEach((segment, index) => {
29
+ if (node[segment] === true)
30
+ return;
31
+ if (index === segments.length - 1) {
32
+ node[segment] = true;
33
+ return;
34
+ }
35
+ node[segment] ??= {};
36
+ node = node[segment];
37
+ });
38
+ }
39
+ return selection;
40
+ }
41
+ /**
42
+ * Keeps only the selected fields. Arrays are projected item by item, so
43
+ * `notes.id` selects the id of every note. Returns the projected value and the
44
+ * paths that matched nothing anywhere, so a typo is reported instead of
45
+ * silently producing empty output.
46
+ */
47
+ export function projectFields(value, selection) {
48
+ const matched = new Set();
49
+ // Paths below an empty list or a null value cannot be checked; never report them.
50
+ const assumeMatched = (node, prefix) => {
51
+ for (const [key, child] of Object.entries(node)) {
52
+ const path = prefix ? `${prefix}.${key}` : key;
53
+ matched.add(path);
54
+ if (child !== true)
55
+ assumeMatched(child, path);
56
+ }
57
+ };
58
+ const project = (current, node, prefix) => {
59
+ if (Array.isArray(current)) {
60
+ if (current.length === 0)
61
+ assumeMatched(node, prefix);
62
+ return current.map((item) => project(item, node, prefix));
63
+ }
64
+ if (!current || typeof current !== 'object') {
65
+ assumeMatched(node, prefix);
66
+ return current;
67
+ }
68
+ const record = current;
69
+ const result = {};
70
+ for (const [key, child] of Object.entries(node)) {
71
+ if (!Object.prototype.hasOwnProperty.call(record, key))
72
+ continue;
73
+ const path = prefix ? `${prefix}.${key}` : key;
74
+ matched.add(path);
75
+ result[key] = child === true ? record[key] : project(record[key], child, path);
76
+ }
77
+ return result;
78
+ };
79
+ const projected = project(value, selection, '');
80
+ const missing = [];
81
+ const collect = (node, prefix) => {
82
+ for (const [key, child] of Object.entries(node)) {
83
+ const path = prefix ? `${prefix}.${key}` : key;
84
+ if (!matched.has(path))
85
+ missing.push(path);
86
+ else if (child !== true)
87
+ collect(child, path);
88
+ }
89
+ };
90
+ collect(selection, '');
91
+ return { value: projected, missing };
92
+ }
@@ -0,0 +1,37 @@
1
+ import type { Command } from 'commander';
2
+ import type { SuggestedAction } from './errors.js';
3
+ export type UsageErrorKind = 'unknown_option' | 'unknown_command' | 'missing_argument' | 'missing_option_value' | 'missing_required_option' | 'invalid_option_value' | 'too_many_arguments' | 'usage';
4
+ /** Machine-readable form of a Commander usage error, carried in the error's `details`. */
5
+ export type UsageErrorDetails = {
6
+ kind: UsageErrorKind;
7
+ /** The offending option, command, or argument name, when Commander names one. */
8
+ token: string | null;
9
+ /** Commander's spelling suggestions, closest first. */
10
+ did_you_mean: string[];
11
+ /** Dot path of the deepest command that was recognized, e.g. `note.search`. */
12
+ command: string | null;
13
+ };
14
+ export type ParsedUsageError = {
15
+ message: string;
16
+ details: UsageErrorDetails;
17
+ suggestion?: string;
18
+ suggestedAction?: SuggestedAction;
19
+ };
20
+ type ResolvedCommand = {
21
+ /** Names of the recognized commands, outermost first. */
22
+ path: string[];
23
+ command: Command;
24
+ /** The first word that did not name a subcommand of `command`. */
25
+ unmatched: string | null;
26
+ };
27
+ /** Walks argv through the command tree as far as it names commands. */
28
+ export declare function resolveCommand(program: Command, argv: string[]): ResolvedCommand;
29
+ /** Closest candidates, using the same thresholds as Commander's own suggestions. */
30
+ export declare function suggestSimilar(word: string, candidates: string[]): string[];
31
+ /**
32
+ * Turns Commander's error text ("error: unknown option '--limt'\n(Did you mean
33
+ * --limit?)") into a message, structured details and, when there is exactly
34
+ * one suggestion, the corrected command line an agent can run.
35
+ */
36
+ export declare function parseCommanderUsageError(text: string, argv: string[], program: Command): ParsedUsageError;
37
+ export {};
@@ -0,0 +1,127 @@
1
+ import { GLOBAL_VALUE_OPTIONS } from '../commands/schema/globalOptions.js';
2
+ const PATTERNS = [
3
+ ['unknown_option', /^unknown option '([^']+)'/],
4
+ ['unknown_command', /^unknown command '([^']+)'/],
5
+ ['missing_argument', /^missing required argument '([^']+)'/],
6
+ ['missing_option_value', /^option '([^']+)' argument missing/],
7
+ ['missing_required_option', /^required option '([^']+)' not specified/],
8
+ ['invalid_option_value', /^option '([^']+)' argument '.*' is invalid/s],
9
+ ['too_many_arguments', /^too many arguments/],
10
+ ];
11
+ /** Walks argv through the command tree as far as it names commands. */
12
+ export function resolveCommand(program, argv) {
13
+ const path = [];
14
+ let current = program;
15
+ for (let i = 0; i < argv.length; i++) {
16
+ const arg = argv[i];
17
+ if (arg === '--')
18
+ break;
19
+ if (GLOBAL_VALUE_OPTIONS.includes(arg)) {
20
+ i++;
21
+ continue;
22
+ }
23
+ if (arg.startsWith('-'))
24
+ continue;
25
+ const next = current.commands.find((command) => command.name() === arg || command.aliases().includes(arg));
26
+ if (!next)
27
+ return { path, command: current, unmatched: arg };
28
+ path.push(next.name());
29
+ current = next;
30
+ }
31
+ return { path, command: current, unmatched: null };
32
+ }
33
+ /** Optimal string alignment distance (Damerau-Levenshtein with adjacent transpositions). */
34
+ function editDistance(a, b) {
35
+ const d = Array.from({ length: a.length + 1 }, (_, i) => [i, ...Array(b.length).fill(0)]);
36
+ for (let j = 0; j <= b.length; j++)
37
+ d[0][j] = j;
38
+ for (let i = 1; i <= a.length; i++) {
39
+ for (let j = 1; j <= b.length; j++) {
40
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
41
+ d[i][j] = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
42
+ if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
43
+ d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1);
44
+ }
45
+ }
46
+ }
47
+ return d[a.length][b.length];
48
+ }
49
+ /** Closest candidates, using the same thresholds as Commander's own suggestions. */
50
+ export function suggestSimilar(word, candidates) {
51
+ let best = 3;
52
+ let similar = [];
53
+ for (const candidate of new Set(candidates)) {
54
+ if (candidate.length <= 1)
55
+ continue;
56
+ const distance = editDistance(word, candidate);
57
+ const length = Math.max(word.length, candidate.length);
58
+ if ((length - distance) / length <= 0.4)
59
+ continue;
60
+ if (distance < best) {
61
+ best = distance;
62
+ similar = [candidate];
63
+ }
64
+ else if (distance === best) {
65
+ similar.push(candidate);
66
+ }
67
+ }
68
+ return similar.sort((a, b) => a.localeCompare(b));
69
+ }
70
+ function shellQuote(arg) {
71
+ return /^[A-Za-z0-9_@%+=:,./-]+$/.test(arg) ? arg : `'${arg.replace(/'/g, `'\\''`)}'`;
72
+ }
73
+ /**
74
+ * Turns Commander's error text ("error: unknown option '--limt'\n(Did you mean
75
+ * --limit?)") into a message, structured details and, when there is exactly
76
+ * one suggestion, the corrected command line an agent can run.
77
+ */
78
+ export function parseCommanderUsageError(text, argv, program) {
79
+ const body = text.trim().replace(/^error:\s*/i, '');
80
+ const suggestionMatch = /\n?\(Did you mean (?:one of )?(.+)\?\)\s*$/.exec(body);
81
+ let message = (suggestionMatch ? body.slice(0, suggestionMatch.index) : body).trim();
82
+ let didYouMean = suggestionMatch ? suggestionMatch[1].split(',').map((item) => item.trim()).filter(Boolean) : [];
83
+ const resolved = resolveCommand(program, argv);
84
+ let kind = 'usage';
85
+ let token = null;
86
+ for (const [candidate, pattern] of PATTERNS) {
87
+ const match = pattern.exec(message);
88
+ if (match) {
89
+ kind = candidate;
90
+ token = match[1] ?? null;
91
+ break;
92
+ }
93
+ }
94
+ // A command group with its own action reports a mistyped subcommand as an
95
+ // extra argument; report it as the unknown command it is.
96
+ if (resolved.command.commands.length > 0 && resolved.unmatched && (kind === 'too_many_arguments' || kind === 'unknown_command')) {
97
+ kind = 'unknown_command';
98
+ token = resolved.unmatched;
99
+ message = `unknown command '${token}'${resolved.path.length > 0 ? ` for 'dino ${resolved.path.join(' ')}'` : ''}`;
100
+ }
101
+ if (kind === 'unknown_command' && token) {
102
+ didYouMean = suggestSimilar(token, resolved.command.commands.flatMap((command) => [command.name(), ...command.aliases()]));
103
+ }
104
+ const command = resolved.path.length > 0 ? resolved.path.join('.') : null;
105
+ const details = { kind, token, did_you_mean: didYouMean, command };
106
+ // Only leaf commands have a schema of their own; the bare form lists them all.
107
+ const schemaHint = command && resolved.command.commands.length === 0
108
+ ? `dino schema ${command} --format json`
109
+ : 'dino schema --format json';
110
+ const parsed = {
111
+ message,
112
+ details,
113
+ suggestion: didYouMean.length > 0
114
+ ? `Did you mean ${didYouMean.join(' or ')}? Run \`${schemaHint}\` to list valid ${kind === 'unknown_command' ? 'commands' : 'options'}.`
115
+ : `Run \`${schemaHint}\` for the valid arguments and options.`,
116
+ };
117
+ const index = token ? argv.indexOf(token) : -1;
118
+ if (didYouMean.length === 1 && index !== -1 && (kind === 'unknown_option' || kind === 'unknown_command')) {
119
+ const corrected = [...argv];
120
+ corrected[index] = didYouMean[0];
121
+ parsed.suggestedAction = {
122
+ command: `dino ${corrected.map(shellQuote).join(' ')}`,
123
+ reason: `${token} is not a valid ${kind === 'unknown_option' ? 'option' : 'command'}; ${didYouMean[0]} is the closest match.`,
124
+ };
125
+ }
126
+ return parsed;
127
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dinoxx/dinox-cli",
3
- "version": "2.14.0",
3
+ "version": "2.15.0",
4
4
  "description": "Dinox CLI",
5
5
  "main": "dist/dinox.js",
6
6
  "scripts": {