@letterstory/cli 0.25.4 → 0.25.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/lib/cli.mjs +9 -2
- package/lib/commands/seers.mjs +188 -64
- package/package.json +1 -1
package/lib/cli.mjs
CHANGED
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
} from "./commands.mjs";
|
|
45
45
|
|
|
46
46
|
// Keep in sync with cli/package.json.
|
|
47
|
-
export const VERSION = "0.25.
|
|
47
|
+
export const VERSION = "0.25.5";
|
|
48
48
|
|
|
49
49
|
// Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
|
|
50
50
|
// can't accidentally swallow the id as --json's value.
|
|
@@ -460,7 +460,14 @@ Seers (event-driven signals -> drafts):
|
|
|
460
460
|
seers update <seer-id> [--name] [--collection] [--mode] [--enabled true|false]
|
|
461
461
|
[--interval <min>] [--config '<json>'|--config-file <path>]
|
|
462
462
|
seers delete <seer-id> --yes
|
|
463
|
-
seers run <seer-id>
|
|
463
|
+
seers run <seer-id> [--dry-run] [--no-produce] [--async]
|
|
464
|
+
Run now — THE DOOR (one seer run from the balance).
|
|
465
|
+
--dry-run: scan + judge, persist nothing, print signals
|
|
466
|
+
--no-produce: detect + record events only
|
|
467
|
+
--async: queue for the heartbeat, print a run id
|
|
468
|
+
seers run-status <run-id> One run: status, counts, constraints, verification
|
|
469
|
+
seers runs [--seer <seer-id>] [--limit <n>] Recent runs (origin, caller, verification)
|
|
470
|
+
seers balance Seer runs granted / used / available
|
|
464
471
|
seers events <seer-id> [--limit <n>] [--offset <n>] Detected signals w/ dedup + relevance
|
|
465
472
|
seers dismiss <seer-id> <event-id> Dismiss a signal (feeds the relevance judge)
|
|
466
473
|
seers headlines [--collection <uuid>] Seer-sourced suggestion feed
|
package/lib/commands/seers.mjs
CHANGED
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
// Connections are both headless: `seers connect github --token` (a PAT) and
|
|
8
8
|
// `seers connect notion --token` (a Notion internal-integration secret; run
|
|
9
9
|
// `seers connect notion` with no token for how to mint one and which pages to share).
|
|
10
|
-
//
|
|
11
|
-
// web scans can take minutes
|
|
10
|
+
// `seers run` is THE DOOR (lib/seers/run.ts): a direct, metered run (`seers balance`).
|
|
11
|
+
// Synchronous by default — news/regulation web scans can take minutes; pass --async to
|
|
12
|
+
// queue it and poll with `seers run-status`, --dry-run to see what it would record
|
|
13
|
+
// without recording anything, --no-produce to detect and record events only.
|
|
12
14
|
|
|
13
15
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
14
16
|
import { CliError } from "../client.mjs";
|
|
15
|
-
import { flagStr,
|
|
17
|
+
import { flagStr, flagBool, requirePositional, printResult, ok, argsFromFlags } from "./shared.mjs";
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* How the ratcheted commands in this file source their tool inputs — see `argsFromFlags` in
|
|
@@ -20,11 +22,89 @@ import { flagStr, flagNum, flagBool, requirePositional, printResult, compact, ok
|
|
|
20
22
|
* ratchet and stays in UNMAPPED_TOOLS; that list only shrinks.
|
|
21
23
|
*/
|
|
22
24
|
export const ARGS = {
|
|
25
|
+
// THE DOOR. `seers run <id>` — a direct, metered run. `--dry-run` scans + judges and
|
|
26
|
+
// persists nothing (returns the signals it would have recorded, with verdicts);
|
|
27
|
+
// `--no-produce` detects and records events only; `--async` queues it and prints a
|
|
28
|
+
// run id to poll with `seers run-status`.
|
|
23
29
|
run_seer: {
|
|
24
30
|
seer_id: { positional: 0, label: "seer-id", required: true },
|
|
31
|
+
dry_run: { flag: "dry-run", type: "bool" },
|
|
32
|
+
produce: { value: (flags) => (flags["no-produce"] === true ? false : undefined) },
|
|
33
|
+
async: { flag: "async", type: "bool" },
|
|
34
|
+
},
|
|
35
|
+
get_seer_run: {
|
|
36
|
+
run_id: { positional: 0, label: "run-id", required: true },
|
|
37
|
+
},
|
|
38
|
+
list_seer_runs: {
|
|
39
|
+
seer_id: { flag: "seer" },
|
|
40
|
+
limit: { flag: "limit", type: "num" },
|
|
41
|
+
},
|
|
42
|
+
get_seer_run_balance: {},
|
|
43
|
+
list_seers: {},
|
|
44
|
+
get_seer: {
|
|
45
|
+
seer_id: { positional: 0, label: "seer-id", required: true },
|
|
46
|
+
},
|
|
47
|
+
create_seer: {
|
|
48
|
+
name: { flag: "name", required: true },
|
|
49
|
+
collection_id: { flag: "collection", required: true },
|
|
50
|
+
provider: { flag: "provider", required: true },
|
|
51
|
+
mode: { flag: "mode", enum: ["suggest", "auto"] },
|
|
52
|
+
poll_interval_minutes: { flag: "interval", type: "num" },
|
|
53
|
+
// The whole config document — provider source params plus the behavior keys
|
|
54
|
+
// (auto_draft_scope, template_key, mention_degree, kernel_family, relevance{…}).
|
|
55
|
+
config: { value: (flags) => readJsonObjectFlag(flags, "config") ?? {} },
|
|
56
|
+
},
|
|
57
|
+
update_seer: {
|
|
58
|
+
seer_id: { positional: 0, label: "seer-id", required: true },
|
|
59
|
+
name: { flag: "name" },
|
|
60
|
+
collection_id: { flag: "collection" },
|
|
61
|
+
mode: { flag: "mode", enum: ["suggest", "auto"] },
|
|
62
|
+
enabled: { value: (flags) => readEnabledFlag(flags) },
|
|
63
|
+
poll_interval_minutes: { flag: "interval", type: "num" },
|
|
64
|
+
config: { value: (flags) => readJsonObjectFlag(flags, "config") },
|
|
65
|
+
},
|
|
66
|
+
delete_seer: {
|
|
67
|
+
seer_id: { positional: 0, label: "seer-id", required: true },
|
|
68
|
+
},
|
|
69
|
+
list_seer_events: {
|
|
70
|
+
seer_id: { positional: 0, label: "seer-id", required: true },
|
|
71
|
+
limit: { flag: "limit", type: "num" },
|
|
72
|
+
offset: { flag: "offset", type: "num" },
|
|
73
|
+
},
|
|
74
|
+
dismiss_seer_event: {
|
|
75
|
+
seer_id: { positional: 0, label: "seer-id", required: true },
|
|
76
|
+
event_id: { positional: 1, label: "event-id", required: true },
|
|
77
|
+
},
|
|
78
|
+
list_seer_headlines: {
|
|
79
|
+
collection_id: { flag: "collection" },
|
|
80
|
+
limit: { flag: "limit", type: "num" },
|
|
81
|
+
offset: { flag: "offset", type: "num" },
|
|
82
|
+
},
|
|
83
|
+
list_held_drafts: {
|
|
84
|
+
collection_id: { flag: "collection" },
|
|
85
|
+
},
|
|
86
|
+
resolve_held_draft: {
|
|
87
|
+
article_id: { positional: 0, label: "article-id", required: true },
|
|
88
|
+
// `seers release <id>` / `seers discard <id>` — the subcommand IS the action.
|
|
89
|
+
action: { value: (_flags, _positionals, extra) => extra.action },
|
|
90
|
+
},
|
|
91
|
+
list_seer_providers: {},
|
|
92
|
+
get_seer_connections: {},
|
|
93
|
+
set_github_connection: {
|
|
94
|
+
access_token: { flag: "token", required: true },
|
|
95
|
+
},
|
|
96
|
+
set_notion_connection: {
|
|
97
|
+
access_token: { flag: "token", required: true },
|
|
25
98
|
},
|
|
26
99
|
};
|
|
27
100
|
|
|
101
|
+
function readEnabledFlag(flags) {
|
|
102
|
+
const enabledRaw = flagStr(flags.enabled);
|
|
103
|
+
if (enabledRaw === undefined) return undefined;
|
|
104
|
+
if (enabledRaw !== "true" && enabledRaw !== "false") throw new CliError('--enabled must be "true" or "false"');
|
|
105
|
+
return enabledRaw === "true";
|
|
106
|
+
}
|
|
107
|
+
|
|
28
108
|
export async function cmdSeers(ctx) {
|
|
29
109
|
const sub = ctx.positionals[0];
|
|
30
110
|
const rest = { ...ctx, positionals: ctx.positionals.slice(1) };
|
|
@@ -45,6 +125,13 @@ export async function cmdSeers(ctx) {
|
|
|
45
125
|
return seersDelete(rest);
|
|
46
126
|
case "run":
|
|
47
127
|
return seersRun(rest);
|
|
128
|
+
case "run-status":
|
|
129
|
+
case "run-get":
|
|
130
|
+
return seersRunStatus(rest);
|
|
131
|
+
case "runs":
|
|
132
|
+
return seersRuns(rest);
|
|
133
|
+
case "balance":
|
|
134
|
+
return seersBalance(rest);
|
|
48
135
|
case "events":
|
|
49
136
|
return seersEvents(rest);
|
|
50
137
|
case "dismiss":
|
|
@@ -69,7 +156,7 @@ export async function cmdSeers(ctx) {
|
|
|
69
156
|
return seersApply(rest);
|
|
70
157
|
default:
|
|
71
158
|
throw new CliError(
|
|
72
|
-
`Unknown seers subcommand: ${sub ?? "(none)"}. Try: list, get, create, update, delete, run, events, dismiss, headlines, held, release, discard, providers, connections, connect, export, apply`
|
|
159
|
+
`Unknown seers subcommand: ${sub ?? "(none)"}. Try: list, get, create, update, delete, run, run-status, runs, balance, events, dismiss, headlines, held, release, discard, providers, connections, connect, export, apply`
|
|
73
160
|
);
|
|
74
161
|
}
|
|
75
162
|
}
|
|
@@ -113,7 +200,7 @@ function formatSeerLine(s) {
|
|
|
113
200
|
|
|
114
201
|
async function seersList(ctx) {
|
|
115
202
|
const { client, flags, io } = ctx;
|
|
116
|
-
const result = await client.callTool("list_seers",
|
|
203
|
+
const result = await client.callTool("list_seers", argsFromFlags(ARGS.list_seers, flags));
|
|
117
204
|
printResult(io, flags, result, (r) => {
|
|
118
205
|
const lines = (r.seers ?? []).map(formatSeerLine);
|
|
119
206
|
if (!lines.length) lines.push("No seers yet. Create one with `seers create` (see `seers providers`).");
|
|
@@ -128,36 +215,15 @@ async function seersList(ctx) {
|
|
|
128
215
|
|
|
129
216
|
async function seersGet(ctx) {
|
|
130
217
|
const { client, positionals, flags, io } = ctx;
|
|
131
|
-
const
|
|
132
|
-
const result = await client.callTool("get_seer", { seer_id: seerId });
|
|
218
|
+
const result = await client.callTool("get_seer", argsFromFlags(ARGS.get_seer, flags, positionals));
|
|
133
219
|
printResult(io, flags, result);
|
|
134
220
|
return 0;
|
|
135
221
|
}
|
|
136
222
|
|
|
137
|
-
function seerWriteArgsFromFlags(flags) {
|
|
138
|
-
const enabledRaw = flagStr(flags.enabled);
|
|
139
|
-
if (enabledRaw !== undefined && enabledRaw !== "true" && enabledRaw !== "false") {
|
|
140
|
-
throw new CliError('--enabled must be "true" or "false"');
|
|
141
|
-
}
|
|
142
|
-
return compact({
|
|
143
|
-
name: flagStr(flags.name),
|
|
144
|
-
collection_id: flagStr(flags.collection),
|
|
145
|
-
mode: flagStr(flags.mode),
|
|
146
|
-
poll_interval_minutes: flagNum(flags.interval),
|
|
147
|
-
enabled: enabledRaw === undefined ? undefined : enabledRaw === "true",
|
|
148
|
-
config: readJsonObjectFlag(flags, "config"),
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
|
|
152
223
|
async function seersCreate(ctx) {
|
|
153
224
|
const { client, flags, io } = ctx;
|
|
154
|
-
const args =
|
|
155
|
-
|
|
156
|
-
if (!args.collection_id) throw new CliError("Missing required --collection <uuid>");
|
|
157
|
-
const provider = flagStr(flags.provider);
|
|
158
|
-
if (!provider) throw new CliError("Missing required --provider (run `seers providers` for the catalog)");
|
|
159
|
-
delete args.enabled; // create has no enabled field; new seers start enabled
|
|
160
|
-
const result = await client.callTool("create_seer", { ...args, provider, config: args.config ?? {} });
|
|
225
|
+
const args = argsFromFlags(ARGS.create_seer, flags);
|
|
226
|
+
const result = await client.callTool("create_seer", args);
|
|
161
227
|
ok(ctx, "Seer created.");
|
|
162
228
|
printResult(io, flags, result, (r) => formatSeerLine(r.seer));
|
|
163
229
|
return 0;
|
|
@@ -165,12 +231,11 @@ async function seersCreate(ctx) {
|
|
|
165
231
|
|
|
166
232
|
async function seersUpdate(ctx) {
|
|
167
233
|
const { client, positionals, flags, io } = ctx;
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
if (Object.keys(args).length === 0) {
|
|
234
|
+
const args = argsFromFlags(ARGS.update_seer, flags, positionals);
|
|
235
|
+
if (Object.keys(args).length <= 1) {
|
|
171
236
|
throw new CliError("Nothing to update — pass --name/--collection/--mode/--enabled/--interval/--config");
|
|
172
237
|
}
|
|
173
|
-
const result = await client.callTool("update_seer",
|
|
238
|
+
const result = await client.callTool("update_seer", args);
|
|
174
239
|
ok(ctx, "Seer updated.");
|
|
175
240
|
printResult(io, flags, result, (r) => formatSeerLine(r.seer));
|
|
176
241
|
return 0;
|
|
@@ -178,26 +243,84 @@ async function seersUpdate(ctx) {
|
|
|
178
243
|
|
|
179
244
|
async function seersDelete(ctx) {
|
|
180
245
|
const { client, positionals, flags, io } = ctx;
|
|
181
|
-
const seerId = requirePositional(positionals, 0, "seer-id");
|
|
182
246
|
if (!flagBool(flags.yes)) throw new CliError("Deleting a seer removes its detected events. Re-run with --yes.");
|
|
183
|
-
const result = await client.callTool("delete_seer",
|
|
247
|
+
const result = await client.callTool("delete_seer", argsFromFlags(ARGS.delete_seer, flags, positionals));
|
|
184
248
|
ok(ctx, "Seer deleted.");
|
|
185
249
|
printResult(io, flags, result);
|
|
186
250
|
return 0;
|
|
187
251
|
}
|
|
188
252
|
|
|
253
|
+
function describeRun(r) {
|
|
254
|
+
const run = r.run ?? r;
|
|
255
|
+
const counts = `Detected ${r.detected ?? run.detected ?? 0}, produced ${r.produced ?? run.produced ?? 0} (auto-drafted ${
|
|
256
|
+
r.auto_drafted ?? run.auto_drafted ?? 0
|
|
257
|
+
}, suggested-only ${r.suggested_only ?? run.suggested_only ?? 0}, dismissed ${r.dismissed ?? run.dismissed ?? 0}).`;
|
|
258
|
+
const lines = [counts];
|
|
259
|
+
if (run.run_id)
|
|
260
|
+
lines.push(
|
|
261
|
+
`Run ${run.run_id} [${run.status}] origin=${run.origin} dry_run=${run.dry_run} produce=${run.produce}`
|
|
262
|
+
);
|
|
263
|
+
if (run.verification?.checks?.length) {
|
|
264
|
+
lines.push(
|
|
265
|
+
"Verification: " +
|
|
266
|
+
run.verification.checks.map((c) => `${c.id}=${c.verdict}${c.detail ? ` (${c.detail})` : ""}`).join("; ")
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
if (Array.isArray(run.signals) && run.signals.length) {
|
|
270
|
+
lines.push("", "Signals (dry run — nothing recorded):");
|
|
271
|
+
for (const sig of run.signals) {
|
|
272
|
+
lines.push(
|
|
273
|
+
` [${sig.relevance?.decision ?? "?"} ${
|
|
274
|
+
typeof sig.relevance?.score === "number" ? sig.relevance.score.toFixed(2) : "-"
|
|
275
|
+
}] ${sig.title}${sig.url ? ` ${sig.url}` : ""}`
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return lines.join("\n");
|
|
280
|
+
}
|
|
281
|
+
|
|
189
282
|
async function seersRun(ctx) {
|
|
190
283
|
const { client, positionals, flags, io } = ctx;
|
|
191
284
|
const args = argsFromFlags(ARGS.run_seer, flags, positionals);
|
|
192
|
-
|
|
285
|
+
if (!args.async)
|
|
286
|
+
ok(ctx, `${args.dry_run ? "Dry run" : "Polling now"} — web-scan providers can take a few minutes…`);
|
|
193
287
|
const result = await client.callTool("run_seer", args);
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
flags,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
288
|
+
if (result?.status === "queued" && result?.run_id) {
|
|
289
|
+
ok(ctx, `Run queued as ${result.run_id}. Poll it with: ${ctx.bin} seers run-status ${result.run_id}`);
|
|
290
|
+
printResult(io, flags, result);
|
|
291
|
+
return 0;
|
|
292
|
+
}
|
|
293
|
+
printResult(io, flags, result, describeRun);
|
|
294
|
+
return 0;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async function seersRunStatus(ctx) {
|
|
298
|
+
const { client, positionals, flags, io } = ctx;
|
|
299
|
+
const result = await client.callTool("get_seer_run", argsFromFlags(ARGS.get_seer_run, flags, positionals));
|
|
300
|
+
printResult(io, flags, result, describeRun);
|
|
301
|
+
return 0;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
async function seersRuns(ctx) {
|
|
305
|
+
const { client, flags, io } = ctx;
|
|
306
|
+
const result = await client.callTool("list_seer_runs", argsFromFlags(ARGS.list_seer_runs, flags));
|
|
307
|
+
printResult(io, flags, result, (r) => {
|
|
308
|
+
const lines = (r.runs ?? []).map(
|
|
309
|
+
(run) =>
|
|
310
|
+
`${run.run_id} [${run.status}] ${run.created_at} ${run.seer_name ?? run.seer_id ?? "?"} origin=${run.origin}${
|
|
311
|
+
run.dry_run ? " dry" : ""
|
|
312
|
+
} detected=${run.detected ?? "-"} produced=${run.produced ?? "-"}`
|
|
313
|
+
);
|
|
314
|
+
if (!lines.length) lines.push("No seer runs yet.");
|
|
315
|
+
return lines.join("\n");
|
|
316
|
+
});
|
|
317
|
+
return 0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
async function seersBalance(ctx) {
|
|
321
|
+
const { client, flags, io } = ctx;
|
|
322
|
+
const result = await client.callTool("get_seer_run_balance", argsFromFlags(ARGS.get_seer_run_balance, flags));
|
|
323
|
+
printResult(io, flags, result, (r) => `Seer runs: ${r.available} available (${r.used} of ${r.granted} used).`);
|
|
201
324
|
return 0;
|
|
202
325
|
}
|
|
203
326
|
|
|
@@ -205,8 +328,7 @@ async function seersRun(ctx) {
|
|
|
205
328
|
|
|
206
329
|
async function seersEvents(ctx) {
|
|
207
330
|
const { client, positionals, flags, io } = ctx;
|
|
208
|
-
const
|
|
209
|
-
const args = compact({ seer_id: seerId, limit: flagNum(flags.limit), offset: flagNum(flags.offset) });
|
|
331
|
+
const args = argsFromFlags(ARGS.list_seer_events, flags, positionals);
|
|
210
332
|
const result = await client.callTool("list_seer_events", args);
|
|
211
333
|
printResult(io, flags, result, (r) => {
|
|
212
334
|
const lines = (r.events ?? []).map((e) => {
|
|
@@ -223,9 +345,10 @@ async function seersEvents(ctx) {
|
|
|
223
345
|
|
|
224
346
|
async function seersDismiss(ctx) {
|
|
225
347
|
const { client, positionals, flags, io } = ctx;
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
348
|
+
const result = await client.callTool(
|
|
349
|
+
"dismiss_seer_event",
|
|
350
|
+
argsFromFlags(ARGS.dismiss_seer_event, flags, positionals)
|
|
351
|
+
);
|
|
229
352
|
ok(ctx, "Event dismissed.");
|
|
230
353
|
printResult(io, flags, result);
|
|
231
354
|
return 0;
|
|
@@ -233,12 +356,7 @@ async function seersDismiss(ctx) {
|
|
|
233
356
|
|
|
234
357
|
async function seersHeadlines(ctx) {
|
|
235
358
|
const { client, flags, io } = ctx;
|
|
236
|
-
const
|
|
237
|
-
collection_id: flagStr(flags.collection),
|
|
238
|
-
limit: flagNum(flags.limit),
|
|
239
|
-
offset: flagNum(flags.offset),
|
|
240
|
-
});
|
|
241
|
-
const result = await client.callTool("list_seer_headlines", args);
|
|
359
|
+
const result = await client.callTool("list_seer_headlines", argsFromFlags(ARGS.list_seer_headlines, flags));
|
|
242
360
|
printResult(io, flags, result, (r) => {
|
|
243
361
|
const lines = (r.headlines ?? []).map(
|
|
244
362
|
(h) => `${h.id} [${h.status}] ${h.title ?? h.headline ?? "(untitled)"}`
|
|
@@ -251,8 +369,7 @@ async function seersHeadlines(ctx) {
|
|
|
251
369
|
|
|
252
370
|
async function seersHeld(ctx) {
|
|
253
371
|
const { client, flags, io } = ctx;
|
|
254
|
-
const
|
|
255
|
-
const result = await client.callTool("list_held_drafts", args);
|
|
372
|
+
const result = await client.callTool("list_held_drafts", argsFromFlags(ARGS.list_held_drafts, flags));
|
|
256
373
|
printResult(io, flags, result, (r) => {
|
|
257
374
|
const lines = (r.drafts ?? []).map(
|
|
258
375
|
(d) => `${d.articleId} [${d.kind}] ${d.title} — ${d.reason} (dropped ${d.dropped}, unsure ${d.unsure})`
|
|
@@ -266,8 +383,10 @@ async function seersHeld(ctx) {
|
|
|
266
383
|
|
|
267
384
|
async function seersResolveHeld(ctx, action) {
|
|
268
385
|
const { client, positionals, flags, io } = ctx;
|
|
269
|
-
const
|
|
270
|
-
|
|
386
|
+
const result = await client.callTool(
|
|
387
|
+
"resolve_held_draft",
|
|
388
|
+
argsFromFlags(ARGS.resolve_held_draft, flags, positionals, { action })
|
|
389
|
+
);
|
|
271
390
|
ok(ctx, action === "release" ? "Draft released — it can publish through the normal path." : "Draft discarded.");
|
|
272
391
|
printResult(io, flags, result);
|
|
273
392
|
return 0;
|
|
@@ -277,7 +396,7 @@ async function seersResolveHeld(ctx, action) {
|
|
|
277
396
|
|
|
278
397
|
async function seersProviders(ctx) {
|
|
279
398
|
const { client, flags, io } = ctx;
|
|
280
|
-
const result = await client.callTool("list_seer_providers",
|
|
399
|
+
const result = await client.callTool("list_seer_providers", argsFromFlags(ARGS.list_seer_providers, flags));
|
|
281
400
|
printResult(io, flags, result, (r) => {
|
|
282
401
|
const blocks = (r.providers ?? []).map((p) => {
|
|
283
402
|
const fields = p.fields
|
|
@@ -296,7 +415,7 @@ async function seersProviders(ctx) {
|
|
|
296
415
|
|
|
297
416
|
async function seersConnections(ctx) {
|
|
298
417
|
const { client, flags, io } = ctx;
|
|
299
|
-
const result = await client.callTool("get_seer_connections",
|
|
418
|
+
const result = await client.callTool("get_seer_connections", argsFromFlags(ARGS.get_seer_connections, flags));
|
|
300
419
|
printResult(io, flags, result, (r) => {
|
|
301
420
|
const gh = r.github.connected
|
|
302
421
|
? `GitHub: connected as ${r.github.account_login} (${r.github.connected_at})`
|
|
@@ -313,9 +432,11 @@ async function seersConnect(ctx) {
|
|
|
313
432
|
const which = ctx.positionals[0];
|
|
314
433
|
const rest = { ...ctx, positionals: ctx.positionals.slice(1) };
|
|
315
434
|
if (which === "github") {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
435
|
+
if (!flagStr(rest.flags.token)) throw new CliError("Missing required --token <github-pat> (repo read access)");
|
|
436
|
+
const result = await rest.client.callTool(
|
|
437
|
+
"set_github_connection",
|
|
438
|
+
argsFromFlags(ARGS.set_github_connection, rest.flags)
|
|
439
|
+
);
|
|
319
440
|
ok(rest, "GitHub connected.");
|
|
320
441
|
printResult(rest.io, rest.flags, result);
|
|
321
442
|
return 0;
|
|
@@ -340,7 +461,10 @@ async function seersConnect(ctx) {
|
|
|
340
461
|
);
|
|
341
462
|
return 0;
|
|
342
463
|
}
|
|
343
|
-
const result = await rest.client.callTool(
|
|
464
|
+
const result = await rest.client.callTool(
|
|
465
|
+
"set_notion_connection",
|
|
466
|
+
argsFromFlags(ARGS.set_notion_connection, rest.flags)
|
|
467
|
+
);
|
|
344
468
|
ok(rest, `Notion connected${result.workspace_name ? ` to ${result.workspace_name}` : ""}.`);
|
|
345
469
|
ok(rest, "Reminder: the integration only watches pages you've shared with it in Notion.");
|
|
346
470
|
printResult(rest.io, rest.flags, result);
|