@llamaventures/cli 1.18.1 → 1.20.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/AGENT_BRIEFING.md +4 -2
- package/CHANGELOG.md +36 -0
- package/README.md +12 -4
- package/README.zh-CN.md +9 -2
- package/bin/llama-mcp.mjs +100 -124
- package/bin/llama.mjs +116 -168
- package/contracts/core-api.json +9 -0
- package/contracts/required-operations.json +342 -0
- package/lib/build-info.mjs +34 -0
- package/lib/build-manifest.json +15 -0
- package/lib/client.mjs +6 -1
- package/lib/oauth-flow.mjs +1 -0
- package/lib/version-check.mjs +1 -0
- package/package.json +8 -3
package/bin/llama.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { createRequire } from "module";
|
|
4
4
|
import { randomUUID } from "crypto";
|
|
5
|
+
import { readFile } from "fs/promises";
|
|
5
6
|
import readline from "readline";
|
|
6
7
|
import {
|
|
7
8
|
DEFAULT_BASE_URL,
|
|
@@ -11,7 +12,6 @@ import {
|
|
|
11
12
|
TOKEN_FILE,
|
|
12
13
|
getAuthHeaders,
|
|
13
14
|
getBaseUrl,
|
|
14
|
-
getLastAgentEvent,
|
|
15
15
|
getToken,
|
|
16
16
|
print,
|
|
17
17
|
readBriefing,
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
import { LLAMA_CLI_CLIENT_ID, pkceLoopbackFlow, revokeToken as revokeOAuthToken } from "../lib/oauth-flow.mjs";
|
|
36
36
|
import { deleteBundle, detectBackend, readBundle, writeBundle } from "../lib/oauth-storage.mjs";
|
|
37
37
|
import { maybeNudgeUpdate, getUpdateNudge } from "../lib/version-check.mjs";
|
|
38
|
+
import { getBuildInfo } from "../lib/build-info.mjs";
|
|
38
39
|
|
|
39
40
|
const requireFromHere = createRequire(import.meta.url);
|
|
40
41
|
const { version: PKG_VERSION } = requireFromHere("../package.json");
|
|
@@ -174,45 +175,6 @@ function slugifyTitle(title) {
|
|
|
174
175
|
return slug;
|
|
175
176
|
}
|
|
176
177
|
|
|
177
|
-
function parseExpectedIds(raw) {
|
|
178
|
-
const text = typeof raw === "string" ? raw : "";
|
|
179
|
-
const expected = { dealIds: [], wikiSlugs: [], raw: [] };
|
|
180
|
-
for (const item of text.split(",").map((s) => s.trim()).filter(Boolean)) {
|
|
181
|
-
const [kind, ...rest] = item.split(":");
|
|
182
|
-
const value = rest.join(":").trim();
|
|
183
|
-
if (kind === "deal" && value) expected.dealIds.push(value);
|
|
184
|
-
else if ((kind === "wiki" || kind === "slug") && value) expected.wikiSlugs.push(value);
|
|
185
|
-
else expected.raw.push(item);
|
|
186
|
-
}
|
|
187
|
-
return expected;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
async function submitEvalFeedback(action, flags, queryText = "") {
|
|
191
|
-
const useLast = flags.last !== false;
|
|
192
|
-
const last = useLast ? getLastAgentEvent() : null;
|
|
193
|
-
const eventId =
|
|
194
|
-
flags.event && flags.event !== true
|
|
195
|
-
? Number(flags.event)
|
|
196
|
-
: last?.lastEventId ?? null;
|
|
197
|
-
if ((action === "good" || action === "bad") && !eventId && !queryText) {
|
|
198
|
-
throw new Error(`Usage: llama eval ${action} [--last] [--reason "..."]`);
|
|
199
|
-
}
|
|
200
|
-
const body = {
|
|
201
|
-
action,
|
|
202
|
-
eventId: Number.isFinite(eventId) ? eventId : undefined,
|
|
203
|
-
query: queryText || undefined,
|
|
204
|
-
surface: flags.surface && flags.surface !== true ? String(flags.surface) : last?.lastSurface ?? undefined,
|
|
205
|
-
expected:
|
|
206
|
-
flags.expect && flags.expect !== true
|
|
207
|
-
? parseExpectedIds(String(flags.expect))
|
|
208
|
-
: {},
|
|
209
|
-
reason: flags.reason && flags.reason !== true ? String(flags.reason) : undefined,
|
|
210
|
-
privacyLevel:
|
|
211
|
-
flags.privacy && flags.privacy !== true ? String(flags.privacy) : "internal",
|
|
212
|
-
};
|
|
213
|
-
return request("POST", "/api/agent/eval-feedback", body);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
178
|
// Client-side fuzzy match — used as a fallback when the server hasn't yet
|
|
217
179
|
// shipped the search/filter API (Fix B, 2026-04-25). Once the server
|
|
218
180
|
// returns the `{deals,total,limit,offset}` envelope, this path is never
|
|
@@ -402,8 +364,8 @@ Agent onboarding (run once on first install):
|
|
|
402
364
|
llama activity new-deals --since 24h # recent deal creations for agents
|
|
403
365
|
llama activity updated-deals --since 7d # meaningful deal updates, grouped
|
|
404
366
|
llama explain <url-or-object> # explain Command URL/object status + lifecycle
|
|
405
|
-
llama
|
|
406
|
-
llama
|
|
367
|
+
llama pref list [--status proposed] # standing agent preferences (injected every turn)
|
|
368
|
+
llama pref add reply-style "Lead with the conclusion." [--team]
|
|
407
369
|
|
|
408
370
|
External pitch — talk to Llama Ventures' intake agent (no token required):
|
|
409
371
|
llama pitch start --name "Jane Doe" --email "jane@acme.ai"
|
|
@@ -425,6 +387,7 @@ Manually-set \`llc_\` tokens are used as a fallback.
|
|
|
425
387
|
|
|
426
388
|
Deals:
|
|
427
389
|
llama deal create "Company" --source <name> --deal-owner <name|email|userId> --source-direction Inbound|Outbound --description "..." --status Interested|Outreached|Sourced --website https://...
|
|
390
|
+
llama deal founders set <dealId> --json '[{"name":"Ada","email":"ada@example.com","linkedin_url":"https://linkedin.com/in/ada"}]'
|
|
428
391
|
llama deal show <dealId>
|
|
429
392
|
llama deal feed <dealId> # every contribution (facts + notes), human-typed or assistant-drafted, newest first
|
|
430
393
|
llama deal update <dealId> <field> <value>
|
|
@@ -512,7 +475,7 @@ Brief blocks:
|
|
|
512
475
|
|
|
513
476
|
Common flags on every add-*:
|
|
514
477
|
--source-section <key> Target a structured section (team, highlights, recommendation,
|
|
515
|
-
|
|
478
|
+
landscape_map, competitors). Without this, blocks land in "_other"
|
|
516
479
|
at the bottom of the TOC. AI writers want this.
|
|
517
480
|
--reply-to <blockId> Make the block a reply to <blockId>. Snapshots parent's heading
|
|
518
481
|
+ 200-char excerpt into meta so the back-link survives parent
|
|
@@ -521,10 +484,9 @@ Brief blocks:
|
|
|
521
484
|
2026-05-03). Use bottom for batched writes that need to
|
|
522
485
|
preserve insertion order.
|
|
523
486
|
|
|
524
|
-
Brief
|
|
487
|
+
Brief refresh + agent-run revert:
|
|
525
488
|
llama deal refresh-brief <dealId> [--force] # re-eval stale sections
|
|
526
489
|
# --force = every unlocked watcher-managed section
|
|
527
|
-
llama deal refresh-persona <dealId> <persona-key> # server validates persona key
|
|
528
490
|
llama deal revert-run <dealId> <runId> --section <key> # legacy 4-section model only
|
|
529
491
|
# section: company|team|highlights|recommendation
|
|
530
492
|
|
|
@@ -534,17 +496,13 @@ Deal soft-delete / restore / trash list:
|
|
|
534
496
|
llama deal trash # list deleted deals
|
|
535
497
|
|
|
536
498
|
Deal facts (AI-extracted or human-asserted, with verification):
|
|
499
|
+
llama deal ingest <dealId> --file <packet.json> [--idempotency-key <key>] # atomic facts + optional Feed note
|
|
500
|
+
packet: {"source":{"kind":"meeting_note","title":"Office visit"},"facts":[{"category":"team","claim":"..."}],"note":"..."}
|
|
501
|
+
categories: company_basics | team | product | market | financials | fundraise | risk | milestone | meta
|
|
537
502
|
llama deal fact list <dealId>
|
|
538
503
|
llama deal fact add <dealId> --category <cat> --claim "<text>" [--source "..."] [--source-url <url>] [--confidence high|medium|low] [--attested]
|
|
539
504
|
llama deal fact verify <dealId> <factId> --status confirmed|disputed [--corrected-value "..."]
|
|
540
505
|
|
|
541
|
-
Skill corrections (persona-owner pushback — read by persona-watcher):
|
|
542
|
-
llama skill-correction list <skill-slug> [--include-deleted]
|
|
543
|
-
llama skill-correction add <skill-slug> "<correction text>" [--deal <uuid>] [--block <blockId>]
|
|
544
|
-
llama skill-correction delete <id>
|
|
545
|
-
Server enforces persona owner OR system admin on POST/DELETE; GET is open.
|
|
546
|
-
External personas (owner_email=null) are admin-only for write.
|
|
547
|
-
|
|
548
506
|
Mentions / Inbox:
|
|
549
507
|
llama mentions # default: my unresolved cues
|
|
550
508
|
llama mentions list [--everyone] [--all] # --everyone = team-wide; --all = include resolved
|
|
@@ -661,7 +619,6 @@ Common:
|
|
|
661
619
|
llama agent bootstrap live Llama OS skill manifest from Command
|
|
662
620
|
llama skills search "<query>" discover which skill to read
|
|
663
621
|
llama explain <url-or-object> explain Command URLs, 404s, deleted objects
|
|
664
|
-
llama eval bad --last mark latest CLI/MCP result as an eval candidate
|
|
665
622
|
|
|
666
623
|
Command groups — run \`llama help <group>\` for that group's commands:
|
|
667
624
|
deal create · show · feed · update · enrich · search · collaborators · links · delete
|
|
@@ -670,7 +627,7 @@ Command groups — run \`llama help <group>\` for that group's commands:
|
|
|
670
627
|
facts deal facts + skill corrections (the sourced, trust-rated layer)
|
|
671
628
|
timeline timeline · posts · mentions
|
|
672
629
|
wiki cross-deal knowledge entries (markdown or HTML)
|
|
673
|
-
|
|
630
|
+
pref standing agent preferences: list · add · retire · approve
|
|
674
631
|
memo long-form HTML investment memo
|
|
675
632
|
html deal-specific HTML artifacts (/deals/<id>/browse/<slug>)
|
|
676
633
|
pitch external founder intake (no token needed)
|
|
@@ -689,7 +646,7 @@ the CLI auto-detects it — no token needed (\`llc_\` tokens are a fallback).`;
|
|
|
689
646
|
const HELP_AREA_MATCH = {
|
|
690
647
|
deal: [/^Deals/, /^Collaborators/, /^Soft-delete/, /^Deal links/, /^Deal soft-delete/],
|
|
691
648
|
activity: [/^Agent activity/],
|
|
692
|
-
brief: [/^Brief blocks
|
|
649
|
+
brief: [/^Brief blocks/],
|
|
693
650
|
facts: [/^Deal facts/, /^Skill corrections/],
|
|
694
651
|
timeline: [/^Timeline/, /^Mentions/],
|
|
695
652
|
wiki: [/^Wiki/, /^Where does this HTML/],
|
|
@@ -1005,6 +962,10 @@ async function runPitchRepl() {
|
|
|
1005
962
|
async function main() {
|
|
1006
963
|
const [area, action, ...rest] = process.argv.slice(2);
|
|
1007
964
|
if (area === "--version" || area === "-v" || area === "version") {
|
|
965
|
+
if (action === "--json" || action === "json") {
|
|
966
|
+
print(getBuildInfo());
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
1008
969
|
// `llama version --check` — explicitly check npm for a newer release and
|
|
1009
970
|
// print the upgrade line (or "up to date"). Lets an agent surface the
|
|
1010
971
|
// nudge on demand, separate from the throttled, TTY-gated auto-nudge.
|
|
@@ -1158,6 +1119,49 @@ async function main() {
|
|
|
1158
1119
|
throw new Error(`Unknown skills subcommand "${sub}". Use: list / search / show.`);
|
|
1159
1120
|
}
|
|
1160
1121
|
|
|
1122
|
+
// `llama pref ...` — standing agent preferences (learning-domain v1).
|
|
1123
|
+
// Own user scope activates immediately; team scope needs a system admin.
|
|
1124
|
+
if (area === "pref" || area === "prefs" || area === "preferences") {
|
|
1125
|
+
const sub = action;
|
|
1126
|
+
if (!sub || sub === "list") {
|
|
1127
|
+
const { flags } = parseFlags(rest, ["json", "status"]);
|
|
1128
|
+
const params = new URLSearchParams();
|
|
1129
|
+
if (flags.status && flags.status !== true) params.set("status", String(flags.status));
|
|
1130
|
+
const result = await request("GET", `/api/agent/preferences${params.toString() ? `?${params}` : ""}`);
|
|
1131
|
+
print(result);
|
|
1132
|
+
return;
|
|
1133
|
+
}
|
|
1134
|
+
if (sub === "add") {
|
|
1135
|
+
const { flags, positional } = parseFlags(rest, ["team", "evidence", "json"]);
|
|
1136
|
+
const key = positional[0];
|
|
1137
|
+
const content = positional.slice(1).join(" ").trim();
|
|
1138
|
+
if (!key || !content) {
|
|
1139
|
+
throw new Error('Usage: llama pref add <key> "<content, max 280 chars>" [--team] [--evidence "..."]');
|
|
1140
|
+
}
|
|
1141
|
+
const result = await request("POST", "/api/agent/preferences", {
|
|
1142
|
+
scope: flags.team ? "team" : "user",
|
|
1143
|
+
key,
|
|
1144
|
+
content,
|
|
1145
|
+
evidence: flags.evidence && flags.evidence !== true ? String(flags.evidence) : undefined,
|
|
1146
|
+
});
|
|
1147
|
+
print(result);
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
if (sub === "retire" || sub === "approve") {
|
|
1151
|
+
const { positional } = parseFlags(rest, ["json"]);
|
|
1152
|
+
const id = Number(positional[0]);
|
|
1153
|
+
if (!Number.isInteger(id) || id <= 0) {
|
|
1154
|
+
throw new Error(`Usage: llama pref ${sub} <id>`);
|
|
1155
|
+
}
|
|
1156
|
+
const result = await request("PATCH", `/api/agent/preferences/${id}`, {
|
|
1157
|
+
status: sub === "approve" ? "active" : "retired",
|
|
1158
|
+
});
|
|
1159
|
+
print(result);
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
throw new Error(`Unknown pref subcommand "${sub}". Use: list / add / retire / approve.`);
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1161
1165
|
if (area === "explain" || (area === "agent" && action === "explain")) {
|
|
1162
1166
|
const args = area === "explain" ? [action, ...rest].filter(Boolean) : rest;
|
|
1163
1167
|
const { flags, positional } = parseFlags(args, ["json", "type", "id", "lang"]);
|
|
@@ -1195,43 +1199,6 @@ async function main() {
|
|
|
1195
1199
|
return;
|
|
1196
1200
|
}
|
|
1197
1201
|
|
|
1198
|
-
if (area === "eval") {
|
|
1199
|
-
const sub = action;
|
|
1200
|
-
if (sub === "good" || sub === "bad") {
|
|
1201
|
-
const { flags, positional } = parseFlags(rest, [
|
|
1202
|
-
"last",
|
|
1203
|
-
"event",
|
|
1204
|
-
"reason",
|
|
1205
|
-
"expect",
|
|
1206
|
-
"surface",
|
|
1207
|
-
"privacy",
|
|
1208
|
-
]);
|
|
1209
|
-
const q = positional.join(" ").trim();
|
|
1210
|
-
print(await submitEvalFeedback(sub, flags, q));
|
|
1211
|
-
return;
|
|
1212
|
-
}
|
|
1213
|
-
if (sub === "add") {
|
|
1214
|
-
const { flags, positional } = parseFlags(rest, [
|
|
1215
|
-
"event",
|
|
1216
|
-
"expect",
|
|
1217
|
-
"reason",
|
|
1218
|
-
"surface",
|
|
1219
|
-
"privacy",
|
|
1220
|
-
]);
|
|
1221
|
-
const q = positional.join(" ").trim();
|
|
1222
|
-
if (!q && !flags.event) {
|
|
1223
|
-
throw new Error(
|
|
1224
|
-
`Usage: llama eval add "<query>" --surface deal|wiki --expect wiki:<slug>|deal:<uuid>`,
|
|
1225
|
-
);
|
|
1226
|
-
}
|
|
1227
|
-
print(await submitEvalFeedback("add", flags, q));
|
|
1228
|
-
return;
|
|
1229
|
-
}
|
|
1230
|
-
throw new Error(
|
|
1231
|
-
"Usage: llama eval good|bad [--last] [--reason ...] OR llama eval add \"<query>\" --expect wiki:<slug>|deal:<uuid>",
|
|
1232
|
-
);
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
1202
|
// `llama pitch ...` — external founder-pitch family. No Llama token
|
|
1236
1203
|
// required; bootstraps a session against /api/external/* via PoW + cookie.
|
|
1237
1204
|
// See lib/external.mjs and AGENT_BRIEFING.md for the full surface.
|
|
@@ -1484,6 +1451,26 @@ async function main() {
|
|
|
1484
1451
|
return;
|
|
1485
1452
|
}
|
|
1486
1453
|
|
|
1454
|
+
if (area === "deal" && action === "founders") {
|
|
1455
|
+
const sub = rest[0];
|
|
1456
|
+
const dealId = rest[1];
|
|
1457
|
+
const { flags } = parseFlags(rest.slice(2), ["json"]);
|
|
1458
|
+
if (sub !== "set" || !dealId || typeof flags.json !== "string") {
|
|
1459
|
+
throw new Error(
|
|
1460
|
+
"Usage: llama deal founders set <dealId> --json '[{\"name\":\"Ada\",\"email\":\"ada@example.com\"}]'"
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1463
|
+
let founders;
|
|
1464
|
+
try {
|
|
1465
|
+
founders = JSON.parse(flags.json);
|
|
1466
|
+
} catch {
|
|
1467
|
+
throw new Error("--json must be a valid JSON array");
|
|
1468
|
+
}
|
|
1469
|
+
if (!Array.isArray(founders)) throw new Error("--json must be a JSON array");
|
|
1470
|
+
print(await request("PUT", `/api/deals/${encodeURIComponent(dealId)}/founders`, { founders }));
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1487
1474
|
// ----- deals.extra JSONB patches (system-admin only, server-gated) -----
|
|
1488
1475
|
// Same endpoint as `deal update`, but `extraKey` instead of `field`.
|
|
1489
1476
|
// Server patches one top-level key via jsonb_set and audits the change
|
|
@@ -1700,6 +1687,8 @@ async function main() {
|
|
|
1700
1687
|
const linkId = rest[2];
|
|
1701
1688
|
if (!linkId) throw new Error(`Usage: llama deal link ${sub} <dealId> <linkId>`);
|
|
1702
1689
|
const path = `/api/deals/${encodeURIComponent(dealId)}/links/${encodeURIComponent(linkId)}`;
|
|
1690
|
+
// @core-api-operation DELETE /api/deals/{dealId}/links/{linkId}
|
|
1691
|
+
// @core-api-operation POST /api/deals/{dealId}/links/{linkId}/restore
|
|
1703
1692
|
print(await request(
|
|
1704
1693
|
sub === "delete" ? "DELETE" : "POST",
|
|
1705
1694
|
sub === "delete" ? path : `${path}/restore`
|
|
@@ -1735,6 +1724,36 @@ async function main() {
|
|
|
1735
1724
|
return;
|
|
1736
1725
|
}
|
|
1737
1726
|
|
|
1727
|
+
// ----- Canonical source-packet ingest (atomic facts + optional Feed note) -----
|
|
1728
|
+
if (area === "deal" && action === "ingest") {
|
|
1729
|
+
const dealId = rest[0];
|
|
1730
|
+
const { flags } = parseFlags(rest.slice(1), ["file", "idempotency-key"]);
|
|
1731
|
+
if (!dealId || !flags.file || flags.file === true) {
|
|
1732
|
+
throw new Error(
|
|
1733
|
+
"Usage: llama deal ingest <dealId> --file <packet.json> [--idempotency-key <key>]\n" +
|
|
1734
|
+
'Packet: {"source":{"kind":"meeting_note","title":"Office visit"},' +
|
|
1735
|
+
'"facts":[{"category":"team","claim":"..."}],"note":"..."}'
|
|
1736
|
+
);
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
let packet;
|
|
1740
|
+
try {
|
|
1741
|
+
packet = JSON.parse(await readFile(String(flags.file), "utf8"));
|
|
1742
|
+
} catch (error) {
|
|
1743
|
+
throw new Error(`Cannot read ingest packet ${flags.file}: ${error?.message ?? String(error)}`);
|
|
1744
|
+
}
|
|
1745
|
+
if (!packet || Array.isArray(packet) || typeof packet !== "object") {
|
|
1746
|
+
throw new Error("Ingest packet must be a JSON object");
|
|
1747
|
+
}
|
|
1748
|
+
if (flags["idempotency-key"] !== undefined && flags["idempotency-key"] !== true) {
|
|
1749
|
+
packet.idempotencyKey = String(flags["idempotency-key"]);
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
// @core-api-operation POST /api/deals/{dealId}/ingest
|
|
1753
|
+
print(await request("POST", `/api/deals/${encodeURIComponent(dealId)}/ingest`, packet));
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1738
1757
|
// ----- Deal facts (AI-extracted or human-asserted, with verification) -----
|
|
1739
1758
|
if (area === "deal" && action === "fact") {
|
|
1740
1759
|
const sub = rest[0];
|
|
@@ -1811,24 +1830,6 @@ async function main() {
|
|
|
1811
1830
|
return;
|
|
1812
1831
|
}
|
|
1813
1832
|
|
|
1814
|
-
// ----- Persona refresh: re-run a single persona-watcher -----
|
|
1815
|
-
// Persona keys are validated server-side. Returns runId or null
|
|
1816
|
-
// (debounced / deal inactive). Used by /admin and the per-block
|
|
1817
|
-
// "重新生成" flow.
|
|
1818
|
-
if (area === "deal" && action === "refresh-persona") {
|
|
1819
|
-
const dealId = rest[0];
|
|
1820
|
-
const persona = rest[1];
|
|
1821
|
-
if (!dealId || !persona) {
|
|
1822
|
-
throw new Error(`Usage: llama deal refresh-persona <dealId> <persona-key>`);
|
|
1823
|
-
}
|
|
1824
|
-
print(await request(
|
|
1825
|
-
"POST",
|
|
1826
|
-
`/api/deals/${encodeURIComponent(dealId)}/refresh-persona`,
|
|
1827
|
-
{ persona }
|
|
1828
|
-
));
|
|
1829
|
-
return;
|
|
1830
|
-
}
|
|
1831
|
-
|
|
1832
1833
|
// ----- Agent-run revert (legacy 4-section brief model) -----
|
|
1833
1834
|
// Reverts a single section to the `before` value snapshotted by the
|
|
1834
1835
|
// watcher run. Does NOT re-fire the watcher (intentional: human action).
|
|
@@ -1967,6 +1968,7 @@ async function main() {
|
|
|
1967
1968
|
if (!slug) throw new Error("Usage: llama wiki read <slug> [--lang en|zh]");
|
|
1968
1969
|
const lang = flags.lang === "zh" ? "zh" : "en";
|
|
1969
1970
|
const path = `/api/wiki/${encodeURIComponent(slug)}?lang=${lang}`;
|
|
1971
|
+
// @core-api-operation GET /api/wiki/{slug}
|
|
1970
1972
|
print(await request("GET", path));
|
|
1971
1973
|
return;
|
|
1972
1974
|
}
|
|
@@ -2106,7 +2108,7 @@ Routing — is this the right command?
|
|
|
2106
2108
|
const meta = { updated_at: new Date().toISOString(), updated_by: "cli", by_agent: false };
|
|
2107
2109
|
|
|
2108
2110
|
// --source-section <key>: target a structured section (e.g. team /
|
|
2109
|
-
// highlights /
|
|
2111
|
+
// highlights / competitors). Without this, blocks land in the
|
|
2110
2112
|
// "_other" group at the bottom of the TOC. AI writers want this
|
|
2111
2113
|
// virtually always — without it they cannot contribute to existing
|
|
2112
2114
|
// structured sections.
|
|
@@ -2298,6 +2300,9 @@ Routing — is this the right command?
|
|
|
2298
2300
|
if (flags["errors-only"]) params.set("errors_only", "1");
|
|
2299
2301
|
}
|
|
2300
2302
|
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
2303
|
+
// @core-api-operation GET /api/admin/auth-events
|
|
2304
|
+
// @core-api-operation GET /api/admin/deal-events
|
|
2305
|
+
// @core-api-operation GET /api/admin/agent-events
|
|
2301
2306
|
print(await request("GET", `/api/admin/${sub}${qs}`));
|
|
2302
2307
|
return;
|
|
2303
2308
|
}
|
|
@@ -2347,63 +2352,6 @@ Routing — is this the right command?
|
|
|
2347
2352
|
throw new Error(`Unknown mentions subcommand "${sub}". Use: list / show / resolve / unread.`);
|
|
2348
2353
|
}
|
|
2349
2354
|
|
|
2350
|
-
// ----- Skill corrections (persona-owner pushback workflow) -----
|
|
2351
|
-
// Persona owners (or system admins) record long-term rules each
|
|
2352
|
-
// persona-DD skill must obey. Read by the persona-watcher and prepended
|
|
2353
|
-
// to the system prompt at run time. Soft-delete is non-cascading —
|
|
2354
|
-
// deleting a row does NOT auto-fire watcher; the next natural run
|
|
2355
|
-
// (manual / stale_re_eval) just stops including the deleted rule.
|
|
2356
|
-
//
|
|
2357
|
-
// Permissions enforced server-side: only the persona owner (per
|
|
2358
|
-
// PERSONA_SKILLS in src/lib/persona-skills.ts) or a system admin can
|
|
2359
|
-
// POST or DELETE. Anyone can GET. External personas (owner_email=null)
|
|
2360
|
-
// are admin-only for write.
|
|
2361
|
-
if (area === "skill-correction") {
|
|
2362
|
-
const sub = action;
|
|
2363
|
-
|
|
2364
|
-
if (sub === "list") {
|
|
2365
|
-
const skillSlug = rest[0];
|
|
2366
|
-
if (!skillSlug) {
|
|
2367
|
-
throw new Error("Usage: llama skill-correction list <skill-slug> [--include-deleted]");
|
|
2368
|
-
}
|
|
2369
|
-
const { flags } = parseFlags(rest.slice(1));
|
|
2370
|
-
const params = new URLSearchParams({ skill: skillSlug });
|
|
2371
|
-
if (flags["include-deleted"]) params.set("include_deleted", "1");
|
|
2372
|
-
print(await request("GET", `/api/skill-corrections?${params.toString()}`));
|
|
2373
|
-
return;
|
|
2374
|
-
}
|
|
2375
|
-
|
|
2376
|
-
if (sub === "add") {
|
|
2377
|
-
const { flags, positional } = parseFlags(rest);
|
|
2378
|
-
const skillSlug = positional[0];
|
|
2379
|
-
const correctionText = positional.slice(1).join(" ").trim();
|
|
2380
|
-
if (!skillSlug || !correctionText) {
|
|
2381
|
-
throw new Error(
|
|
2382
|
-
`Usage: llama skill-correction add <skill-slug> "<correction text>" ` +
|
|
2383
|
-
`[--deal <uuid>] [--block <blockId>]`
|
|
2384
|
-
);
|
|
2385
|
-
}
|
|
2386
|
-
print(await request("POST", "/api/skill-corrections", {
|
|
2387
|
-
skill_slug: skillSlug,
|
|
2388
|
-
correction_text: correctionText,
|
|
2389
|
-
triggered_in_deal_uuid: flags.deal ? String(flags.deal) : null,
|
|
2390
|
-
triggered_in_block_id: flags.block ? String(flags.block) : null,
|
|
2391
|
-
}));
|
|
2392
|
-
return;
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
|
-
if (sub === "delete") {
|
|
2396
|
-
const id = rest[0];
|
|
2397
|
-
if (!id) throw new Error("Usage: llama skill-correction delete <id>");
|
|
2398
|
-
print(await request("DELETE", `/api/skill-corrections/${encodeURIComponent(id)}`));
|
|
2399
|
-
return;
|
|
2400
|
-
}
|
|
2401
|
-
|
|
2402
|
-
throw new Error(
|
|
2403
|
-
`Unknown skill-correction subcommand "${sub || ""}". Use: list / add / delete.`
|
|
2404
|
-
);
|
|
2405
|
-
}
|
|
2406
|
-
|
|
2407
2355
|
// ----- Memo (long-form HTML investment memo) -----
|
|
2408
2356
|
// The Memo tab in the deal page renders HTML stored in deal_memos.
|
|
2409
2357
|
// Two sources of memo content:
|