@heyditto/cli 1.5.0 → 1.7.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.
- package/README.md +73 -16
- package/dist/cli.js +459 -412
- package/dist/cli.js.map +1 -1
- package/package.json +6 -3
package/dist/cli.js
CHANGED
|
@@ -2,14 +2,26 @@
|
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
import { createInterface } from "node:readline/promises";
|
|
5
|
-
import { parseArgs } from "node:util";
|
|
6
5
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
7
6
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
7
|
+
import { Command, Option } from "commander";
|
|
8
8
|
import { agentSignupURL, apiBaseURL, authFilePath, mcpServerURL, newKeyURL, packageName, packageVersion, resolveApiKey, } from "./config.js";
|
|
9
9
|
import { clearStoredKey, readStoredAuth, writeStoredAuth, writeStoredKey } from "./store.js";
|
|
10
10
|
const OUTPUT_FORMATS = ["json", "text", "markdown", "raw"];
|
|
11
|
-
const outputOption = { type: "string" };
|
|
12
11
|
const MEMORY_FORMATS = ["full", "outline", "blocks"];
|
|
12
|
+
function outputOption() {
|
|
13
|
+
return new Option("--output <format>", "output format")
|
|
14
|
+
.choices([...OUTPUT_FORMATS])
|
|
15
|
+
.default("text");
|
|
16
|
+
}
|
|
17
|
+
function hiddenOutputOption() {
|
|
18
|
+
return outputOption().hideHelp();
|
|
19
|
+
}
|
|
20
|
+
function memoryFormatOption() {
|
|
21
|
+
return new Option("--memory-format <format>", "memory body format")
|
|
22
|
+
.choices([...MEMORY_FORMATS])
|
|
23
|
+
.default("full");
|
|
24
|
+
}
|
|
13
25
|
function parseOutputFormat(value) {
|
|
14
26
|
if (!value)
|
|
15
27
|
return "text";
|
|
@@ -32,6 +44,14 @@ function parseIntegerOption(value, name) {
|
|
|
32
44
|
throw new Error(`${name} must be an integer`);
|
|
33
45
|
return n;
|
|
34
46
|
}
|
|
47
|
+
function parseNumberOption(value, name) {
|
|
48
|
+
if (!value)
|
|
49
|
+
return undefined;
|
|
50
|
+
const n = Number.parseFloat(value);
|
|
51
|
+
if (!Number.isFinite(n))
|
|
52
|
+
throw new Error(`${name} must be a number`);
|
|
53
|
+
return n;
|
|
54
|
+
}
|
|
35
55
|
function parseJSONOption(value, name) {
|
|
36
56
|
try {
|
|
37
57
|
return JSON.parse(value);
|
|
@@ -72,68 +92,14 @@ function formatToolResult(result, format) {
|
|
|
72
92
|
return JSON.stringify({ text }, null, 2);
|
|
73
93
|
}
|
|
74
94
|
}
|
|
75
|
-
// text / markdown
|
|
95
|
+
// text / markdown: pass the text block through; fall back to raw envelope.
|
|
76
96
|
return text ?? JSON.stringify(result, null, 2);
|
|
77
97
|
}
|
|
78
|
-
function usage() {
|
|
79
|
-
return `${packageName} ${packageVersion}
|
|
80
|
-
|
|
81
|
-
Usage:
|
|
82
|
-
heyditto save <content> [--source <s>] [--source-context <c>]
|
|
83
|
-
heyditto search <query>... [--include-public] [--filter-username <u>]
|
|
84
|
-
heyditto fetch <id>... [--memory-format full|outline|blocks]
|
|
85
|
-
heyditto list [--username <u>] [--limit <n>] [--offset <n>] [--source <s>]
|
|
86
|
-
heyditto update <id> [--content <text>|--content-file <path>] [--title <t>]
|
|
87
|
-
[--source-context <c>] [--edits-json <json>|--edits-file <path>]
|
|
88
|
-
[--base-revision <n>]
|
|
89
|
-
heyditto publish <id> [--title <t>] [--privacy-mode scan_and_block|scan_and_warn|scan_and_redact]
|
|
90
|
-
heyditto unpublish (--memory-id <id>|--share-id <id>|<id>)
|
|
91
|
-
heyditto subjects <query> [--top-k <n>]
|
|
92
|
-
heyditto memories <subject-id>... [--query <q>]
|
|
93
|
-
heyditto network <pair-id> [--limit <n>]
|
|
94
|
-
heyditto graphs create <name> Create a dedicated graph you own
|
|
95
|
-
heyditto graphs list Public graphs you're subscribed to
|
|
96
|
-
heyditto graphs add <@username> Subscribe to a public graph
|
|
97
|
-
heyditto graphs remove <@username> Unsubscribe from a public graph
|
|
98
|
-
heyditto graphs subscribers Who is subscribed to your graph
|
|
99
|
-
heyditto init --agent [--agent-caller <name>] [--subscribe <@graph>] [<@graph>...] [--json]
|
|
100
|
-
|
|
101
|
-
All data commands (and 'status') accept --output <format>, where <format>
|
|
102
|
-
is one of: json, text, markdown, raw. Default is 'text' (passthrough of
|
|
103
|
-
the server's text block, which is JSON for data commands). Use --output json
|
|
104
|
-
to guarantee structured JSON output suitable for piping into 'jq'.
|
|
105
|
-
|
|
106
|
-
Auth:
|
|
107
|
-
heyditto init --agent [--json] Create a free, claimable agent account
|
|
108
|
-
heyditto init --agent --subscribe @minos ...pre-subscribed to public graph(s)
|
|
109
|
-
heyditto init --agent @minos @a,@b (positional form; repeatable /
|
|
110
|
-
comma-separated; '@' optional)
|
|
111
|
-
heyditto login [<key>] [--paste] [--stdin] Save an API key to ${authFilePath()}
|
|
112
|
-
heyditto logout Delete the saved key
|
|
113
|
-
heyditto status [--output <format>] Show endpoint, key source, live tools
|
|
114
|
-
heyditto config Print MCP client config snippet
|
|
115
|
-
|
|
116
|
-
Other:
|
|
117
|
-
heyditto help Show this message
|
|
118
|
-
|
|
119
|
-
Note: on macOS, Apple ships /usr/bin/ditto (a file-copy utility). If 'ditto'
|
|
120
|
-
runs the wrong tool, install with 'npm i -g @heyditto/cli' and invoke as
|
|
121
|
-
'heyditto' (alias bin), or check 'type -a ditto' to disambiguate.
|
|
122
|
-
|
|
123
|
-
Environment:
|
|
124
|
-
DITTO_API_KEY Optional override (takes precedence over the saved key).
|
|
125
|
-
Run 'heyditto init --agent --json' for no-human setup, or get
|
|
126
|
-
a human-owned key at ${newKeyURL()}.
|
|
127
|
-
DITTO_API_BASE Optional. Defaults to https://api.heyditto.ai.
|
|
128
|
-
DITTO_CONFIG_DIR Optional. Defaults to $XDG_CONFIG_HOME/heyditto/cli or
|
|
129
|
-
~/.config/heyditto/cli.
|
|
130
|
-
`;
|
|
131
|
-
}
|
|
132
98
|
async function getClient() {
|
|
133
99
|
const { key, source } = await resolveApiKey();
|
|
134
100
|
if (!key) {
|
|
135
101
|
process.stderr.write(`error: no Ditto API key configured.\n\n` +
|
|
136
|
-
` Run: heyditto init --
|
|
102
|
+
` Run: heyditto init --json\n` +
|
|
137
103
|
` Or save an existing key with: heyditto login <key>\n` +
|
|
138
104
|
` Human-owned keys are available at ${newKeyURL()}.\n`);
|
|
139
105
|
process.exit(1);
|
|
@@ -164,11 +130,6 @@ async function callAndPrint(name, args, format) {
|
|
|
164
130
|
await client.close();
|
|
165
131
|
}
|
|
166
132
|
}
|
|
167
|
-
function requirePositionals(positionals, minimum, label) {
|
|
168
|
-
if (positionals.length < minimum) {
|
|
169
|
-
throw new Error(`${label}: expected at least ${minimum} argument(s), got ${positionals.length}`);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
133
|
async function readKeyFromStdin() {
|
|
173
134
|
return new Promise((resolve, reject) => {
|
|
174
135
|
let buf = "";
|
|
@@ -192,28 +153,19 @@ function openInBrowser(url) {
|
|
|
192
153
|
const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
193
154
|
const child = spawn(cmd, args, { stdio: "ignore", detached: true });
|
|
194
155
|
child.on("error", () => {
|
|
195
|
-
/* swallow
|
|
156
|
+
/* swallow: best-effort */
|
|
196
157
|
});
|
|
197
158
|
child.unref();
|
|
198
159
|
}
|
|
199
|
-
async function cmdLogin(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
paste: { type: "boolean", default: false },
|
|
204
|
-
stdin: { type: "boolean", default: false },
|
|
205
|
-
output: outputOption,
|
|
206
|
-
},
|
|
207
|
-
allowPositionals: true,
|
|
208
|
-
});
|
|
209
|
-
parseOutputFormat(values.output); // validate but ignored — login is interactive
|
|
210
|
-
let key = positionals[0]?.trim();
|
|
211
|
-
if (!key && values.stdin) {
|
|
160
|
+
async function cmdLogin(keyArg, options) {
|
|
161
|
+
parseOutputFormat(options.output); // validate but ignored: login is interactive
|
|
162
|
+
let key = keyArg?.trim();
|
|
163
|
+
if (!key && options.stdin) {
|
|
212
164
|
key = (await readKeyFromStdin()).trim();
|
|
213
165
|
}
|
|
214
166
|
else if (!key) {
|
|
215
|
-
if (
|
|
216
|
-
process.stderr.write(`Opening ${newKeyURL()} in your browser
|
|
167
|
+
if (options.paste) {
|
|
168
|
+
process.stderr.write(`Opening ${newKeyURL()} in your browser...\n`);
|
|
217
169
|
openInBrowser(newKeyURL());
|
|
218
170
|
}
|
|
219
171
|
if (!process.stdin.isTTY) {
|
|
@@ -224,7 +176,7 @@ async function cmdLogin(rest) {
|
|
|
224
176
|
if (!key)
|
|
225
177
|
throw new Error("no key provided");
|
|
226
178
|
if (!key.startsWith("ditto_mcp_")) {
|
|
227
|
-
process.stderr.write(`warning: key does not start with "ditto_mcp_"
|
|
179
|
+
process.stderr.write(`warning: key does not start with "ditto_mcp_" - proceeding anyway\n`);
|
|
228
180
|
}
|
|
229
181
|
await writeStoredKey(key);
|
|
230
182
|
process.stdout.write(`Saved key to ${authFilePath()}\n`);
|
|
@@ -236,27 +188,17 @@ async function cmdLogin(rest) {
|
|
|
236
188
|
function defaultAgentCaller() {
|
|
237
189
|
return process.env.DITTO_AGENT_CALLER?.trim() || process.env.CURSOR_AGENT?.trim() || "agent";
|
|
238
190
|
}
|
|
239
|
-
async function cmdInit(
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
"agent-caller": { type: "string" },
|
|
245
|
-
subscribe: { type: "string", multiple: true },
|
|
246
|
-
json: { type: "boolean", default: false },
|
|
247
|
-
output: outputOption,
|
|
248
|
-
},
|
|
249
|
-
allowPositionals: true,
|
|
250
|
-
});
|
|
251
|
-
const output = values.json ? "json" : parseOutputFormat(values.output);
|
|
252
|
-
if (!values.agent) {
|
|
253
|
-
throw new Error("init currently supports only --agent");
|
|
191
|
+
async function cmdInit(graphs, options) {
|
|
192
|
+
const output = options.json ? "json" : parseOutputFormat(options.output);
|
|
193
|
+
// --agent is accepted for backward compatibility. Agent init is the default.
|
|
194
|
+
if (options.agentCaller && options.name && options.agentCaller !== options.name) {
|
|
195
|
+
throw new Error("init: use either --name or --agent-caller, not both");
|
|
254
196
|
}
|
|
255
197
|
// --subscribe pre-subscribes the new agent to public foundation knowledge
|
|
256
198
|
// graphs (e.g. the @minos mentor KG). Accepts repeats and comma-separated
|
|
257
199
|
// lists, plus bare positional graph names: --subscribe @minos @a,@b.
|
|
258
200
|
// De-duped; '@' optional.
|
|
259
|
-
const subscribeGraphs = Array.from(new Set([...(
|
|
201
|
+
const subscribeGraphs = Array.from(new Set([...(options.subscribe ?? []), ...graphs]
|
|
260
202
|
.flatMap((v) => v.split(","))
|
|
261
203
|
.map((g) => g.trim().replace(/^@/, ""))
|
|
262
204
|
.filter((g) => g.length > 0)));
|
|
@@ -285,7 +227,7 @@ async function cmdInit(rest) {
|
|
|
285
227
|
if (stored?.apiKey) {
|
|
286
228
|
throw new Error(`a Ditto API key is already saved at ${authFilePath()}; run 'heyditto logout' before creating an agent account`);
|
|
287
229
|
}
|
|
288
|
-
const agentCaller =
|
|
230
|
+
const agentCaller = options.name?.trim() || options.agentCaller?.trim() || defaultAgentCaller();
|
|
289
231
|
const response = await fetch(agentSignupURL(), {
|
|
290
232
|
method: "POST",
|
|
291
233
|
headers: {
|
|
@@ -364,13 +306,8 @@ async function cmdInit(rest) {
|
|
|
364
306
|
}
|
|
365
307
|
process.stdout.write(`Claim later: ${signup.claimURL}\n`);
|
|
366
308
|
}
|
|
367
|
-
async function cmdLogout(
|
|
368
|
-
|
|
369
|
-
args: rest,
|
|
370
|
-
options: { output: outputOption },
|
|
371
|
-
allowPositionals: true,
|
|
372
|
-
});
|
|
373
|
-
parseOutputFormat(values.output);
|
|
309
|
+
async function cmdLogout(options) {
|
|
310
|
+
parseOutputFormat(options.output);
|
|
374
311
|
const removed = await clearStoredKey();
|
|
375
312
|
if (removed) {
|
|
376
313
|
process.stdout.write(`Removed ${authFilePath()}\n`);
|
|
@@ -382,225 +319,183 @@ async function cmdLogout(rest) {
|
|
|
382
319
|
process.stderr.write(`note: DITTO_API_KEY is still set in your environment and will continue to be used.\n`);
|
|
383
320
|
}
|
|
384
321
|
}
|
|
385
|
-
async function cmdSave(
|
|
386
|
-
const
|
|
387
|
-
args: rest,
|
|
388
|
-
options: {
|
|
389
|
-
source: { type: "string", default: "cli" },
|
|
390
|
-
"source-context": { type: "string" },
|
|
391
|
-
output: outputOption,
|
|
392
|
-
},
|
|
393
|
-
allowPositionals: true,
|
|
394
|
-
});
|
|
395
|
-
const format = parseOutputFormat(values.output);
|
|
396
|
-
requirePositionals(positionals, 1, "save");
|
|
322
|
+
async function cmdSave(content, options) {
|
|
323
|
+
const format = parseOutputFormat(options.output);
|
|
397
324
|
await callAndPrint("save_memory", {
|
|
398
|
-
content:
|
|
399
|
-
source:
|
|
400
|
-
sourceContext:
|
|
325
|
+
content: content.join(" "),
|
|
326
|
+
source: options.source ?? "cli",
|
|
327
|
+
sourceContext: options.sourceContext,
|
|
401
328
|
}, format);
|
|
402
329
|
}
|
|
403
|
-
async function cmdSearch(
|
|
404
|
-
const
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
"include-public": { type: "boolean", default: false },
|
|
408
|
-
"filter-username": { type: "string" },
|
|
409
|
-
output: outputOption,
|
|
410
|
-
},
|
|
411
|
-
allowPositionals: true,
|
|
412
|
-
});
|
|
413
|
-
const format = parseOutputFormat(values.output);
|
|
414
|
-
requirePositionals(positionals, 1, "search");
|
|
415
|
-
const args = { queries: positionals };
|
|
416
|
-
if (values["include-public"])
|
|
330
|
+
async function cmdSearch(queries, options) {
|
|
331
|
+
const format = parseOutputFormat(options.output);
|
|
332
|
+
const args = { queries };
|
|
333
|
+
if (options.includePublic)
|
|
417
334
|
args.includePublic = true;
|
|
418
|
-
if (
|
|
419
|
-
args.filterUsername =
|
|
335
|
+
if (options.filterUsername)
|
|
336
|
+
args.filterUsername = options.filterUsername;
|
|
420
337
|
await callAndPrint("search_memories", args, format);
|
|
421
338
|
}
|
|
422
|
-
async function cmdFetch(
|
|
423
|
-
const
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const format = parseOutputFormat(
|
|
429
|
-
const memoryFormat = parseMemoryFormat(values["memory-format"]);
|
|
430
|
-
requirePositionals(positionals, 1, "fetch");
|
|
431
|
-
await callAndPrint("fetch_memories", { ids: positionals, format: memoryFormat }, format);
|
|
432
|
-
}
|
|
433
|
-
async function cmdList(rest) {
|
|
434
|
-
const { values } = parseArgs({
|
|
435
|
-
args: rest,
|
|
436
|
-
options: {
|
|
437
|
-
username: { type: "string" },
|
|
438
|
-
limit: { type: "string" },
|
|
439
|
-
offset: { type: "string" },
|
|
440
|
-
source: { type: "string" },
|
|
441
|
-
output: outputOption,
|
|
442
|
-
},
|
|
443
|
-
allowPositionals: true,
|
|
444
|
-
});
|
|
445
|
-
const format = parseOutputFormat(values.output);
|
|
339
|
+
async function cmdFetch(ids, options) {
|
|
340
|
+
const format = parseOutputFormat(options.output);
|
|
341
|
+
const memoryFormat = parseMemoryFormat(options.memoryFormat);
|
|
342
|
+
await callAndPrint("fetch_memories", { ids, format: memoryFormat }, format);
|
|
343
|
+
}
|
|
344
|
+
async function cmdList(options) {
|
|
345
|
+
const format = parseOutputFormat(options.output);
|
|
446
346
|
const args = {};
|
|
447
|
-
if (
|
|
448
|
-
args.username =
|
|
449
|
-
const limit = parseIntegerOption(
|
|
347
|
+
if (options.username)
|
|
348
|
+
args.username = options.username;
|
|
349
|
+
const limit = parseIntegerOption(options.limit, "--limit");
|
|
450
350
|
if (limit !== undefined)
|
|
451
351
|
args.limit = limit;
|
|
452
|
-
const offset = parseIntegerOption(
|
|
352
|
+
const offset = parseIntegerOption(options.offset, "--offset");
|
|
453
353
|
if (offset !== undefined)
|
|
454
354
|
args.offset = offset;
|
|
455
|
-
if (
|
|
456
|
-
args.source =
|
|
355
|
+
if (options.source)
|
|
356
|
+
args.source = options.source;
|
|
457
357
|
await callAndPrint("list_memories", args, format);
|
|
458
358
|
}
|
|
459
|
-
async function cmdUpdate(
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
options: {
|
|
463
|
-
content: { type: "string" },
|
|
464
|
-
"content-file": { type: "string" },
|
|
465
|
-
title: { type: "string" },
|
|
466
|
-
"source-context": { type: "string" },
|
|
467
|
-
"edits-json": { type: "string" },
|
|
468
|
-
"edits-file": { type: "string" },
|
|
469
|
-
"base-revision": { type: "string" },
|
|
470
|
-
output: outputOption,
|
|
471
|
-
},
|
|
472
|
-
allowPositionals: true,
|
|
473
|
-
});
|
|
474
|
-
const format = parseOutputFormat(values.output);
|
|
475
|
-
requirePositionals(positionals, 1, "update");
|
|
476
|
-
if (values.content && values["content-file"]) {
|
|
359
|
+
async function cmdUpdate(id, options) {
|
|
360
|
+
const format = parseOutputFormat(options.output);
|
|
361
|
+
if (options.content && options.contentFile) {
|
|
477
362
|
throw new Error("update: use either --content or --content-file, not both");
|
|
478
363
|
}
|
|
479
|
-
if (
|
|
364
|
+
if (options.editsJson && options.editsFile) {
|
|
480
365
|
throw new Error("update: use either --edits-json or --edits-file, not both");
|
|
481
366
|
}
|
|
482
|
-
if ((
|
|
367
|
+
if ((options.content || options.contentFile) && (options.editsJson || options.editsFile)) {
|
|
483
368
|
throw new Error("update: content replacement and block edits are mutually exclusive");
|
|
484
369
|
}
|
|
485
|
-
const args = { memoryId:
|
|
486
|
-
if (
|
|
487
|
-
args.content =
|
|
488
|
-
if (
|
|
489
|
-
args.content = await readTextFile(
|
|
490
|
-
if (
|
|
491
|
-
args.title =
|
|
492
|
-
if (
|
|
493
|
-
args.sourceContext =
|
|
494
|
-
if (
|
|
495
|
-
const raw =
|
|
496
|
-
args.edits = parseJSONOption(raw,
|
|
497
|
-
const baseRevision = parseIntegerOption(
|
|
370
|
+
const args = { memoryId: id };
|
|
371
|
+
if (options.content)
|
|
372
|
+
args.content = options.content;
|
|
373
|
+
if (options.contentFile)
|
|
374
|
+
args.content = await readTextFile(options.contentFile, "--content-file");
|
|
375
|
+
if (options.title !== undefined)
|
|
376
|
+
args.title = options.title;
|
|
377
|
+
if (options.sourceContext !== undefined)
|
|
378
|
+
args.sourceContext = options.sourceContext;
|
|
379
|
+
if (options.editsJson || options.editsFile) {
|
|
380
|
+
const raw = options.editsJson ?? (await readTextFile(options.editsFile, "--edits-file"));
|
|
381
|
+
args.edits = parseJSONOption(raw, options.editsJson ? "--edits-json" : "--edits-file");
|
|
382
|
+
const baseRevision = parseIntegerOption(options.baseRevision, "--base-revision");
|
|
498
383
|
if (baseRevision === undefined) {
|
|
499
384
|
throw new Error("update: --base-revision is required with block edits");
|
|
500
385
|
}
|
|
501
386
|
args.baseRevision = baseRevision;
|
|
502
387
|
}
|
|
503
388
|
else {
|
|
504
|
-
const baseRevision = parseIntegerOption(
|
|
389
|
+
const baseRevision = parseIntegerOption(options.baseRevision, "--base-revision");
|
|
505
390
|
if (baseRevision !== undefined)
|
|
506
391
|
args.baseRevision = baseRevision;
|
|
507
392
|
}
|
|
508
393
|
await callAndPrint("update_memory", args, format);
|
|
509
394
|
}
|
|
510
|
-
async function cmdPublish(
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
},
|
|
518
|
-
allowPositionals: true,
|
|
519
|
-
});
|
|
520
|
-
const format = parseOutputFormat(values.output);
|
|
521
|
-
requirePositionals(positionals, 1, "publish");
|
|
522
|
-
const args = { memoryId: positionals[0] };
|
|
523
|
-
if (values.title !== undefined)
|
|
524
|
-
args.title = values.title;
|
|
525
|
-
if (values["privacy-mode"] !== undefined)
|
|
526
|
-
args.privacyMode = values["privacy-mode"];
|
|
395
|
+
async function cmdPublish(id, options) {
|
|
396
|
+
const format = parseOutputFormat(options.output);
|
|
397
|
+
const args = { memoryId: id };
|
|
398
|
+
if (options.title !== undefined)
|
|
399
|
+
args.title = options.title;
|
|
400
|
+
if (options.privacyMode !== undefined)
|
|
401
|
+
args.privacyMode = options.privacyMode;
|
|
527
402
|
await callAndPrint("publish_memory", args, format);
|
|
528
403
|
}
|
|
529
|
-
async function cmdUnpublish(
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
options: {
|
|
533
|
-
"memory-id": { type: "string" },
|
|
534
|
-
"share-id": { type: "string" },
|
|
535
|
-
output: outputOption,
|
|
536
|
-
},
|
|
537
|
-
allowPositionals: true,
|
|
538
|
-
});
|
|
539
|
-
const format = parseOutputFormat(values.output);
|
|
540
|
-
const provided = [values["memory-id"], values["share-id"], positionals[0]].filter(Boolean);
|
|
404
|
+
async function cmdUnpublish(id, options) {
|
|
405
|
+
const format = parseOutputFormat(options.output);
|
|
406
|
+
const provided = [options.memoryId, options.shareId, id].filter(Boolean);
|
|
541
407
|
if (provided.length !== 1) {
|
|
542
408
|
throw new Error("unpublish: provide exactly one of --memory-id, --share-id, or positional id");
|
|
543
409
|
}
|
|
544
410
|
const args = {};
|
|
545
|
-
if (
|
|
546
|
-
args.memoryId =
|
|
411
|
+
if (options.memoryId) {
|
|
412
|
+
args.memoryId = options.memoryId;
|
|
547
413
|
}
|
|
548
|
-
else if (
|
|
549
|
-
args.shareId =
|
|
414
|
+
else if (options.shareId) {
|
|
415
|
+
args.shareId = options.shareId;
|
|
550
416
|
}
|
|
551
417
|
else {
|
|
552
|
-
args.memoryId =
|
|
418
|
+
args.memoryId = id;
|
|
553
419
|
}
|
|
554
420
|
await callAndPrint("unpublish_memory", args, format);
|
|
555
421
|
}
|
|
556
|
-
async function cmdSubjects(
|
|
557
|
-
const
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
allowPositionals: true,
|
|
561
|
-
});
|
|
562
|
-
const format = parseOutputFormat(values.output);
|
|
563
|
-
requirePositionals(positionals, 1, "subjects");
|
|
564
|
-
const args = { query: positionals.join(" ") };
|
|
565
|
-
const topK = parseIntegerOption(values["top-k"], "--top-k");
|
|
422
|
+
async function cmdSubjects(query, options) {
|
|
423
|
+
const format = parseOutputFormat(options.output);
|
|
424
|
+
const args = { query: query.join(" ") };
|
|
425
|
+
const topK = parseIntegerOption(options.topK, "--top-k");
|
|
566
426
|
if (topK !== undefined)
|
|
567
427
|
args.topK = topK;
|
|
568
428
|
await callAndPrint("search_subjects", args, format);
|
|
569
429
|
}
|
|
570
|
-
async function cmdMemories(
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
});
|
|
576
|
-
const format = parseOutputFormat(values.output);
|
|
577
|
-
requirePositionals(positionals, 1, "memories");
|
|
578
|
-
const args = { subjectIds: positionals };
|
|
579
|
-
if (values.query)
|
|
580
|
-
args.query = values.query;
|
|
430
|
+
async function cmdMemories(subjectIds, options) {
|
|
431
|
+
const format = parseOutputFormat(options.output);
|
|
432
|
+
const args = { subjectIds };
|
|
433
|
+
if (options.query)
|
|
434
|
+
args.query = options.query;
|
|
581
435
|
await callAndPrint("search_memories_in_subjects", args, format);
|
|
582
436
|
}
|
|
583
|
-
async function cmdNetwork(
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
allowPositionals: true,
|
|
588
|
-
});
|
|
589
|
-
const format = parseOutputFormat(values.output);
|
|
590
|
-
requirePositionals(positionals, 1, "network");
|
|
591
|
-
const args = { pairId: positionals[0] };
|
|
592
|
-
const limit = parseIntegerOption(values.limit, "--limit");
|
|
437
|
+
async function cmdNetwork(pairId, options) {
|
|
438
|
+
const format = parseOutputFormat(options.output);
|
|
439
|
+
const args = { pairId };
|
|
440
|
+
const limit = parseIntegerOption(options.limit, "--limit");
|
|
593
441
|
if (limit !== undefined)
|
|
594
442
|
args.limit = limit;
|
|
595
443
|
await callAndPrint("get_memory_network", args, format);
|
|
596
444
|
}
|
|
597
|
-
async function
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
445
|
+
async function cmdFriends(options) {
|
|
446
|
+
await callAndPrint("list_friends", {}, parseOutputFormat(options.output));
|
|
447
|
+
}
|
|
448
|
+
async function cmdKnowledgeGraphs(options) {
|
|
449
|
+
await callAndPrint("list_knowledge_graphs", {}, parseOutputFormat(options.output));
|
|
450
|
+
}
|
|
451
|
+
async function cmdMyMemories(options) {
|
|
452
|
+
const args = {};
|
|
453
|
+
const limit = parseIntegerOption(options.limit, "--limit");
|
|
454
|
+
if (limit !== undefined)
|
|
455
|
+
args.limit = limit;
|
|
456
|
+
const offset = parseIntegerOption(options.offset, "--offset");
|
|
457
|
+
if (offset !== undefined)
|
|
458
|
+
args.offset = offset;
|
|
459
|
+
if (options.source)
|
|
460
|
+
args.source = options.source;
|
|
461
|
+
await callAndPrint("list_my_memories", args, parseOutputFormat(options.output));
|
|
462
|
+
}
|
|
463
|
+
async function cmdSubjectEdges(subjectId, options) {
|
|
464
|
+
const args = { subjectId };
|
|
465
|
+
if (options.kg)
|
|
466
|
+
args.kg = options.kg;
|
|
467
|
+
const limit = parseIntegerOption(options.limit, "--limit");
|
|
468
|
+
if (limit !== undefined)
|
|
469
|
+
args.limit = limit;
|
|
470
|
+
const minWeight = parseNumberOption(options.minWeight, "--min-weight");
|
|
471
|
+
if (minWeight !== undefined)
|
|
472
|
+
args.minWeight = minWeight;
|
|
473
|
+
await callAndPrint("get_subject_edges", args, parseOutputFormat(options.output));
|
|
474
|
+
}
|
|
475
|
+
async function cmdGraphSharing(options) {
|
|
476
|
+
if (!!options.enable === !!options.disable) {
|
|
477
|
+
throw new Error("sharing: provide exactly one of --enable or --disable");
|
|
478
|
+
}
|
|
479
|
+
const args = {
|
|
480
|
+
publicSubscriptionsEnabled: !!options.enable,
|
|
481
|
+
};
|
|
482
|
+
if (options.title !== undefined)
|
|
483
|
+
args.title = options.title;
|
|
484
|
+
if (options.description !== undefined)
|
|
485
|
+
args.description = options.description;
|
|
486
|
+
await callAndPrint("set_knowledge_graph_sharing", args, parseOutputFormat(options.output));
|
|
487
|
+
}
|
|
488
|
+
async function cmdDelete(memoryId, options) {
|
|
489
|
+
if (!options.confirm) {
|
|
490
|
+
throw new Error("delete: pass --confirm to permanently delete this memory");
|
|
491
|
+
}
|
|
492
|
+
const args = { memoryId, confirm: true };
|
|
493
|
+
if (options.kg)
|
|
494
|
+
args.kg = options.kg;
|
|
495
|
+
await callAndPrint("delete_memory", args, parseOutputFormat(options.output));
|
|
496
|
+
}
|
|
497
|
+
async function cmdStatus(options) {
|
|
498
|
+
const format = parseOutputFormat(options.output);
|
|
604
499
|
const [{ key, source }, stored] = await Promise.all([resolveApiKey(), readStoredAuth()]);
|
|
605
500
|
const report = {
|
|
606
501
|
package: packageName,
|
|
@@ -655,7 +550,7 @@ async function cmdStatus(rest) {
|
|
|
655
550
|
`api key: ${report.apiKey.present ? "set" : "MISSING"} (source: ${report.apiKey.source})`,
|
|
656
551
|
];
|
|
657
552
|
if (!report.apiKey.present) {
|
|
658
|
-
lines.push(``, `Run 'heyditto init --
|
|
553
|
+
lines.push(``, `Run 'heyditto init --json' for no-human setup, or get a key at ${newKeyURL()} and run 'heyditto login <key>'.`);
|
|
659
554
|
}
|
|
660
555
|
else if (report.tools) {
|
|
661
556
|
lines.push(`tools: ${report.tools.join(", ")}`);
|
|
@@ -664,20 +559,15 @@ async function cmdStatus(rest) {
|
|
|
664
559
|
lines.push(`connect: ok`, `tools: unavailable (tools/list failed: ${report.toolsError})`);
|
|
665
560
|
}
|
|
666
561
|
else if (report.connect && !report.connect.ok) {
|
|
667
|
-
lines.push(`connect: FAILED
|
|
562
|
+
lines.push(`connect: FAILED - ${report.connect.error}`);
|
|
668
563
|
}
|
|
669
564
|
if (report.agent?.claimURL) {
|
|
670
565
|
lines.push(`agent: unclaimed (${report.agent.caller || "agent"})`, `claim: ${report.agent.claimURL}`);
|
|
671
566
|
}
|
|
672
567
|
process.stdout.write(`${lines.join("\n")}\n`);
|
|
673
568
|
}
|
|
674
|
-
function cmdConfig(
|
|
675
|
-
|
|
676
|
-
args: rest,
|
|
677
|
-
options: { output: outputOption },
|
|
678
|
-
allowPositionals: true,
|
|
679
|
-
});
|
|
680
|
-
parseOutputFormat(values.output); // accepted; output is always JSON
|
|
569
|
+
function cmdConfig(options) {
|
|
570
|
+
parseOutputFormat(options.output); // accepted; output is always JSON
|
|
681
571
|
const config = {
|
|
682
572
|
mcpServers: {
|
|
683
573
|
ditto: {
|
|
@@ -689,141 +579,298 @@ function cmdConfig(rest) {
|
|
|
689
579
|
};
|
|
690
580
|
process.stdout.write(`${JSON.stringify(config, null, 2)}\n`);
|
|
691
581
|
}
|
|
692
|
-
//
|
|
693
|
-
//
|
|
694
|
-
//
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
582
|
+
// These commands mirror the MCP subscription tools. Subscriptions only ever
|
|
583
|
+
// cover other users' public graphs by @username; this cannot touch the account's
|
|
584
|
+
// own graph or app graph, since those are not subscriptions.
|
|
585
|
+
async function cmdGraphsCreate(nameParts, options) {
|
|
586
|
+
await callAndPrint("create_dedicated_graph", { name: nameParts.join(" ") }, parseOutputFormat(options.output));
|
|
587
|
+
}
|
|
588
|
+
async function cmdGraphsList(options) {
|
|
589
|
+
await callAndPrint("list_knowledge_graph_subscriptions", {}, parseOutputFormat(options.output));
|
|
590
|
+
}
|
|
591
|
+
async function cmdGraphsSubscribers(options) {
|
|
592
|
+
await callAndPrint("list_knowledge_graph_subscribers", {}, parseOutputFormat(options.output));
|
|
593
|
+
}
|
|
594
|
+
async function cmdGraphsAdd(username, options) {
|
|
595
|
+
await callAndPrint("subscribe_knowledge_graph", { username }, parseOutputFormat(options.output));
|
|
596
|
+
}
|
|
597
|
+
async function cmdGraphsRemove(username, options) {
|
|
598
|
+
await callAndPrint("unsubscribe_knowledge_graph", { username }, parseOutputFormat(options.output));
|
|
599
|
+
}
|
|
600
|
+
function addExamples(command, examples) {
|
|
601
|
+
return command.addHelpText("after", `\nExamples:\n${examples}`);
|
|
602
|
+
}
|
|
603
|
+
function buildProgram() {
|
|
604
|
+
const program = new Command();
|
|
605
|
+
program
|
|
606
|
+
.name("heyditto")
|
|
607
|
+
.description("Save, search, fetch, and traverse Ditto memories from the shell.")
|
|
608
|
+
.version(packageVersion, "-v, --version", "print the CLI version")
|
|
609
|
+
.helpCommand("help [command]", "show help for a command")
|
|
610
|
+
.showHelpAfterError()
|
|
611
|
+
.addHelpText("after", `
|
|
612
|
+
Notes:
|
|
613
|
+
On macOS, Apple ships /usr/bin/ditto (a file-copy utility). If 'ditto'
|
|
614
|
+
runs the wrong tool, install with 'npm i -g @heyditto/cli' and invoke as
|
|
615
|
+
'heyditto' (alias bin), or check 'type -a ditto' to disambiguate.
|
|
616
|
+
|
|
617
|
+
Environment:
|
|
618
|
+
DITTO_API_KEY Optional override, taking precedence over the saved key.
|
|
619
|
+
DITTO_API_BASE Optional API base URL. Defaults to https://api.heyditto.ai.
|
|
620
|
+
DITTO_CONFIG_DIR Optional config directory. Defaults to $XDG_CONFIG_HOME/heyditto/cli
|
|
621
|
+
or ~/.config/heyditto/cli.
|
|
622
|
+
`);
|
|
623
|
+
addExamples(program
|
|
624
|
+
.command("save")
|
|
625
|
+
.description("save a memory")
|
|
626
|
+
.summary("save a memory")
|
|
627
|
+
.argument("<content...>", "memory content")
|
|
628
|
+
.option("--source <source>", "memory source", "cli")
|
|
629
|
+
.option("--source-context <context>", "source context, such as a filename")
|
|
630
|
+
.addOption(outputOption())
|
|
631
|
+
.action(cmdSave), ` heyditto save "Project X uses Bun + SolidJS"
|
|
632
|
+
heyditto save "$(cat note.md)" --source document --source-context note.md`);
|
|
633
|
+
addExamples(program
|
|
634
|
+
.command("search")
|
|
635
|
+
.description("search private memories, optionally public graphs")
|
|
636
|
+
.summary("search private memories, optionally public graphs")
|
|
637
|
+
.argument("<query...>", "one or more search queries")
|
|
638
|
+
.option("--include-public", "include public DittoHub memories")
|
|
639
|
+
.option("--filter-username <username>", "scope public results to a username")
|
|
640
|
+
.addOption(outputOption())
|
|
641
|
+
.action(cmdSearch), ` heyditto search "typescript preferences"
|
|
642
|
+
heyditto search "launch notes" --include-public --filter-username peyton`);
|
|
643
|
+
program
|
|
644
|
+
.command("fetch")
|
|
645
|
+
.description("fetch memories by id")
|
|
646
|
+
.summary("fetch memories by id")
|
|
647
|
+
.argument("<id...>", "memory ids or public share ids")
|
|
648
|
+
.addOption(memoryFormatOption())
|
|
649
|
+
.addOption(outputOption())
|
|
650
|
+
.action(cmdFetch);
|
|
651
|
+
program
|
|
652
|
+
.command("list")
|
|
653
|
+
.description("list memories or public publishes")
|
|
654
|
+
.summary("list memories or public publishes")
|
|
655
|
+
.option("--username <username>", "list public DittoHub publishes for a username")
|
|
656
|
+
.option("--limit <number>", "maximum number of results")
|
|
657
|
+
.option("--offset <number>", "result offset")
|
|
658
|
+
.option("--source <source>", "filter by memory source")
|
|
659
|
+
.addOption(outputOption())
|
|
660
|
+
.action(cmdList);
|
|
661
|
+
program
|
|
662
|
+
.command("my-memories")
|
|
663
|
+
.alias("list_my_memories")
|
|
664
|
+
.description("list only your saved memories")
|
|
665
|
+
.summary("list only your saved memories")
|
|
666
|
+
.option("--limit <number>", "maximum number of results")
|
|
667
|
+
.option("--offset <number>", "result offset")
|
|
668
|
+
.option("--source <source>", "filter by memory source")
|
|
669
|
+
.addOption(outputOption())
|
|
670
|
+
.action(cmdMyMemories);
|
|
671
|
+
program
|
|
672
|
+
.command("update")
|
|
673
|
+
.description("update a saved memory")
|
|
674
|
+
.summary("update a saved memory")
|
|
675
|
+
.argument("<id>", "memory id")
|
|
676
|
+
.option("--content <text>", "replacement memory content")
|
|
677
|
+
.option("--content-file <path>", "path to replacement memory content")
|
|
678
|
+
.option("--title <title>", "memory title")
|
|
679
|
+
.option("--source-context <context>", "source context")
|
|
680
|
+
.option("--edits-json <json>", "structured block edits as JSON")
|
|
681
|
+
.option("--edits-file <path>", "path to structured block edits JSON")
|
|
682
|
+
.option("--base-revision <number>", "base memory revision")
|
|
683
|
+
.addOption(outputOption())
|
|
684
|
+
.addHelpText("after", `
|
|
685
|
+
Examples:
|
|
686
|
+
heyditto update <memory-id> --content-file revised.md --output json
|
|
687
|
+
heyditto update <memory-id> --edits-file edits.json --base-revision 3 --output json`)
|
|
688
|
+
.action(cmdUpdate);
|
|
689
|
+
program
|
|
690
|
+
.command("publish")
|
|
691
|
+
.description("publish a memory to DittoHub")
|
|
692
|
+
.summary("publish a memory to DittoHub")
|
|
693
|
+
.argument("<id>", "memory id")
|
|
694
|
+
.option("--title <title>", "public title")
|
|
695
|
+
.option("--privacy-mode <mode>", "privacy mode: scan_and_block, scan_and_warn, or scan_and_redact")
|
|
696
|
+
.addOption(outputOption())
|
|
697
|
+
.action(cmdPublish);
|
|
698
|
+
program
|
|
699
|
+
.command("unpublish")
|
|
700
|
+
.description("remove an existing public share")
|
|
701
|
+
.summary("remove an existing public share")
|
|
702
|
+
.argument("[id]", "memory id")
|
|
703
|
+
.option("--memory-id <id>", "memory id")
|
|
704
|
+
.option("--share-id <id>", "share id")
|
|
705
|
+
.addOption(outputOption())
|
|
706
|
+
.action(cmdUnpublish);
|
|
707
|
+
program
|
|
708
|
+
.command("delete")
|
|
709
|
+
.alias("delete_memory")
|
|
710
|
+
.description("permanently delete a saved memory")
|
|
711
|
+
.summary("permanently delete a saved memory")
|
|
712
|
+
.argument("<memory-id>", "memory id")
|
|
713
|
+
.requiredOption("--confirm", "confirm permanent deletion")
|
|
714
|
+
.option("--kg <alias>", "knowledge graph alias")
|
|
715
|
+
.addOption(outputOption())
|
|
716
|
+
.action(cmdDelete);
|
|
717
|
+
program
|
|
718
|
+
.command("subjects")
|
|
719
|
+
.description("search the subject graph")
|
|
720
|
+
.summary("search the subject graph")
|
|
721
|
+
.argument("<query...>", "subject search query")
|
|
722
|
+
.option("--top-k <number>", "maximum number of subjects")
|
|
723
|
+
.addOption(outputOption())
|
|
724
|
+
.action(cmdSubjects);
|
|
725
|
+
program
|
|
726
|
+
.command("subject-edges")
|
|
727
|
+
.alias("get_subject_edges")
|
|
728
|
+
.description("list related subjects for a subject")
|
|
729
|
+
.summary("list related subjects for a subject")
|
|
730
|
+
.argument("<subject-id>", "subject id")
|
|
731
|
+
.option("--kg <alias>", "knowledge graph alias")
|
|
732
|
+
.option("--limit <number>", "maximum number of related subjects")
|
|
733
|
+
.option("--min-weight <number>", "minimum edge weight from 0 to 1")
|
|
734
|
+
.addOption(outputOption())
|
|
735
|
+
.action(cmdSubjectEdges);
|
|
736
|
+
program
|
|
737
|
+
.command("memories")
|
|
738
|
+
.description("fetch memory previews for subjects")
|
|
739
|
+
.summary("fetch memory previews for subjects")
|
|
740
|
+
.argument("<subject-id...>", "subject ids")
|
|
741
|
+
.option("--query <query>", "optional search query")
|
|
742
|
+
.addOption(outputOption())
|
|
743
|
+
.action(cmdMemories);
|
|
744
|
+
program
|
|
745
|
+
.command("network")
|
|
746
|
+
.description("traverse related memories")
|
|
747
|
+
.summary("traverse related memories")
|
|
748
|
+
.argument("<pair-id>", "memory pair id")
|
|
749
|
+
.option("--limit <number>", "maximum number of related memories")
|
|
750
|
+
.addOption(outputOption())
|
|
751
|
+
.action(cmdNetwork);
|
|
752
|
+
program
|
|
753
|
+
.command("friends")
|
|
754
|
+
.alias("list_friends")
|
|
755
|
+
.description("list Ditto friends")
|
|
756
|
+
.summary("list Ditto friends")
|
|
757
|
+
.addOption(outputOption())
|
|
758
|
+
.action(cmdFriends);
|
|
759
|
+
program
|
|
760
|
+
.command("knowledge-graphs")
|
|
761
|
+
.alias("list_knowledge_graphs")
|
|
762
|
+
.description("list readable knowledge graphs")
|
|
763
|
+
.summary("list readable knowledge graphs")
|
|
764
|
+
.addOption(outputOption())
|
|
765
|
+
.action(cmdKnowledgeGraphs);
|
|
766
|
+
program
|
|
767
|
+
.command("graph-sharing")
|
|
768
|
+
.alias("set_knowledge_graph_sharing")
|
|
769
|
+
.description("configure whether others can subscribe to your graph")
|
|
770
|
+
.summary("configure graph sharing")
|
|
771
|
+
.option("--enable", "allow public subscriptions to your graph")
|
|
772
|
+
.option("--disable", "disable public subscriptions to your graph")
|
|
773
|
+
.option("--title <title>", "subscribable graph title")
|
|
774
|
+
.option("--description <description>", "subscribable graph description")
|
|
775
|
+
.addOption(outputOption())
|
|
776
|
+
.action(cmdGraphSharing);
|
|
777
|
+
const graphs = program
|
|
778
|
+
.command("graphs")
|
|
779
|
+
.description("manage knowledge graph subscriptions")
|
|
780
|
+
.summary("manage knowledge graph subscriptions")
|
|
781
|
+
.showHelpAfterError()
|
|
782
|
+
.addHelpText("after", `
|
|
783
|
+
Subscriptions cover other users' public graphs by @username. They do not modify
|
|
784
|
+
your own graph or an app graph.`);
|
|
785
|
+
graphs
|
|
786
|
+
.command("create")
|
|
787
|
+
.description("create a dedicated graph you own")
|
|
788
|
+
.argument("<name...>", "graph name")
|
|
789
|
+
.addOption(outputOption())
|
|
790
|
+
.action(cmdGraphsCreate);
|
|
791
|
+
graphs
|
|
792
|
+
.command("list")
|
|
793
|
+
.description("list public graphs you're subscribed to")
|
|
794
|
+
.addOption(outputOption())
|
|
795
|
+
.action(cmdGraphsList);
|
|
796
|
+
graphs
|
|
797
|
+
.command("available")
|
|
798
|
+
.alias("list_knowledge_graphs")
|
|
799
|
+
.description("list readable knowledge graphs")
|
|
800
|
+
.addOption(outputOption())
|
|
801
|
+
.action(cmdKnowledgeGraphs);
|
|
802
|
+
graphs
|
|
803
|
+
.command("add")
|
|
804
|
+
.description("subscribe to a public graph")
|
|
805
|
+
.argument("<username>", "public graph username, with or without @")
|
|
806
|
+
.addOption(outputOption())
|
|
807
|
+
.action(cmdGraphsAdd);
|
|
808
|
+
graphs
|
|
809
|
+
.command("remove")
|
|
810
|
+
.description("unsubscribe from a public graph")
|
|
811
|
+
.argument("<username>", "public graph username, with or without @")
|
|
812
|
+
.addOption(outputOption())
|
|
813
|
+
.action(cmdGraphsRemove);
|
|
814
|
+
graphs
|
|
815
|
+
.command("subscribers")
|
|
816
|
+
.description("list who is subscribed to your graph")
|
|
817
|
+
.addOption(outputOption())
|
|
818
|
+
.action(cmdGraphsSubscribers);
|
|
819
|
+
graphs
|
|
820
|
+
.command("sharing")
|
|
821
|
+
.alias("set_knowledge_graph_sharing")
|
|
822
|
+
.description("configure whether others can subscribe to your graph")
|
|
823
|
+
.option("--enable", "allow public subscriptions to your graph")
|
|
824
|
+
.option("--disable", "disable public subscriptions to your graph")
|
|
825
|
+
.option("--title <title>", "subscribable graph title")
|
|
826
|
+
.option("--description <description>", "subscribable graph description")
|
|
827
|
+
.addOption(outputOption())
|
|
828
|
+
.action(cmdGraphSharing);
|
|
829
|
+
program
|
|
830
|
+
.command("init")
|
|
831
|
+
.description("initialize a claimable agent account")
|
|
832
|
+
.argument("[graph...]", "public graphs to subscribe to")
|
|
833
|
+
.addOption(new Option("--agent", "create a free, claimable agent account").hideHelp())
|
|
834
|
+
.option("--name <name>", "agent name")
|
|
835
|
+
.option("--agent-caller <name>", "agent name")
|
|
836
|
+
.addOption(new Option("--subscribe <graph>", "public graphs to subscribe to")
|
|
837
|
+
.argParser((value, previous) => [...(previous ?? []), value]))
|
|
838
|
+
.option("--json", "print machine-readable output")
|
|
839
|
+
.addOption(hiddenOutputOption())
|
|
840
|
+
.action(cmdInit);
|
|
841
|
+
program
|
|
842
|
+
.command("login")
|
|
843
|
+
.description("save an API key")
|
|
844
|
+
.argument("[key]", "Ditto API key")
|
|
845
|
+
.option("--paste", "open the key creation page before prompting")
|
|
846
|
+
.option("--stdin", "read the API key from stdin")
|
|
847
|
+
.addOption(hiddenOutputOption())
|
|
848
|
+
.action(cmdLogin);
|
|
849
|
+
program
|
|
850
|
+
.command("logout")
|
|
851
|
+
.description("delete the saved API key")
|
|
852
|
+
.addOption(hiddenOutputOption())
|
|
853
|
+
.action(cmdLogout);
|
|
854
|
+
program
|
|
855
|
+
.command("status")
|
|
856
|
+
.description("show CLI auth and endpoint status")
|
|
857
|
+
.addOption(outputOption())
|
|
858
|
+
.action(cmdStatus);
|
|
859
|
+
program
|
|
860
|
+
.command("config")
|
|
861
|
+
.description("print MCP client configuration")
|
|
862
|
+
.addOption(hiddenOutputOption())
|
|
863
|
+
.action(cmdConfig);
|
|
864
|
+
return program;
|
|
759
865
|
}
|
|
760
866
|
async function main() {
|
|
761
|
-
const argv = process.argv
|
|
762
|
-
const
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
await cmdInit(rest);
|
|
767
|
-
return;
|
|
768
|
-
case "save":
|
|
769
|
-
await cmdSave(rest);
|
|
770
|
-
return;
|
|
771
|
-
case "search":
|
|
772
|
-
await cmdSearch(rest);
|
|
773
|
-
return;
|
|
774
|
-
case "fetch":
|
|
775
|
-
await cmdFetch(rest);
|
|
776
|
-
return;
|
|
777
|
-
case "list":
|
|
778
|
-
await cmdList(rest);
|
|
779
|
-
return;
|
|
780
|
-
case "update":
|
|
781
|
-
await cmdUpdate(rest);
|
|
782
|
-
return;
|
|
783
|
-
case "publish":
|
|
784
|
-
await cmdPublish(rest);
|
|
785
|
-
return;
|
|
786
|
-
case "unpublish":
|
|
787
|
-
await cmdUnpublish(rest);
|
|
788
|
-
return;
|
|
789
|
-
case "subjects":
|
|
790
|
-
await cmdSubjects(rest);
|
|
791
|
-
return;
|
|
792
|
-
case "memories":
|
|
793
|
-
await cmdMemories(rest);
|
|
794
|
-
return;
|
|
795
|
-
case "network":
|
|
796
|
-
await cmdNetwork(rest);
|
|
797
|
-
return;
|
|
798
|
-
case "graphs":
|
|
799
|
-
await cmdGraphs(rest);
|
|
800
|
-
return;
|
|
801
|
-
case "login":
|
|
802
|
-
await cmdLogin(rest);
|
|
803
|
-
return;
|
|
804
|
-
case "logout":
|
|
805
|
-
await cmdLogout(rest);
|
|
806
|
-
return;
|
|
807
|
-
case "status":
|
|
808
|
-
await cmdStatus(rest);
|
|
809
|
-
return;
|
|
810
|
-
case "config":
|
|
811
|
-
cmdConfig(rest);
|
|
812
|
-
return;
|
|
813
|
-
case undefined:
|
|
814
|
-
case "help":
|
|
815
|
-
case "--help":
|
|
816
|
-
case "-h":
|
|
817
|
-
process.stdout.write(usage());
|
|
818
|
-
return;
|
|
819
|
-
case "--version":
|
|
820
|
-
case "-v":
|
|
821
|
-
process.stdout.write(`${packageVersion}\n`);
|
|
822
|
-
return;
|
|
823
|
-
default:
|
|
824
|
-
process.stderr.write(`Unknown command: ${command}\n\n${usage()}`);
|
|
825
|
-
process.exitCode = 2;
|
|
867
|
+
const argv = [...process.argv];
|
|
868
|
+
const args = argv.slice(2);
|
|
869
|
+
if (args[0] === "graphs" &&
|
|
870
|
+
(args.length === 1 || (args[1].startsWith("-") && args[1] !== "-h" && args[1] !== "--help"))) {
|
|
871
|
+
argv.splice(3, 0, "list");
|
|
826
872
|
}
|
|
873
|
+
await buildProgram().parseAsync(argv);
|
|
827
874
|
}
|
|
828
875
|
main().catch((error) => {
|
|
829
876
|
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|