@llamaventures/cli 1.19.0 → 1.22.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 +11 -6
- package/CHANGELOG.md +49 -1
- package/README.md +12 -4
- package/README.zh-CN.md +9 -2
- package/bin/llama-mcp.mjs +133 -138
- package/bin/llama.mjs +102 -179
- package/contracts/core-api.json +4 -4
- package/contracts/required-operations.json +336 -85
- package/lib/build-manifest.json +4 -4
- package/lib/client.mjs +48 -3
- package/lib/server-compatibility.mjs +96 -0
- package/package.json +2 -2
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,
|
|
@@ -175,45 +175,6 @@ function slugifyTitle(title) {
|
|
|
175
175
|
return slug;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
function parseExpectedIds(raw) {
|
|
179
|
-
const text = typeof raw === "string" ? raw : "";
|
|
180
|
-
const expected = { dealIds: [], wikiSlugs: [], raw: [] };
|
|
181
|
-
for (const item of text.split(",").map((s) => s.trim()).filter(Boolean)) {
|
|
182
|
-
const [kind, ...rest] = item.split(":");
|
|
183
|
-
const value = rest.join(":").trim();
|
|
184
|
-
if (kind === "deal" && value) expected.dealIds.push(value);
|
|
185
|
-
else if ((kind === "wiki" || kind === "slug") && value) expected.wikiSlugs.push(value);
|
|
186
|
-
else expected.raw.push(item);
|
|
187
|
-
}
|
|
188
|
-
return expected;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
async function submitEvalFeedback(action, flags, queryText = "") {
|
|
192
|
-
const useLast = flags.last !== false;
|
|
193
|
-
const last = useLast ? getLastAgentEvent() : null;
|
|
194
|
-
const eventId =
|
|
195
|
-
flags.event && flags.event !== true
|
|
196
|
-
? Number(flags.event)
|
|
197
|
-
: last?.lastEventId ?? null;
|
|
198
|
-
if ((action === "good" || action === "bad") && !eventId && !queryText) {
|
|
199
|
-
throw new Error(`Usage: llama eval ${action} [--last] [--reason "..."]`);
|
|
200
|
-
}
|
|
201
|
-
const body = {
|
|
202
|
-
action,
|
|
203
|
-
eventId: Number.isFinite(eventId) ? eventId : undefined,
|
|
204
|
-
query: queryText || undefined,
|
|
205
|
-
surface: flags.surface && flags.surface !== true ? String(flags.surface) : last?.lastSurface ?? undefined,
|
|
206
|
-
expected:
|
|
207
|
-
flags.expect && flags.expect !== true
|
|
208
|
-
? parseExpectedIds(String(flags.expect))
|
|
209
|
-
: {},
|
|
210
|
-
reason: flags.reason && flags.reason !== true ? String(flags.reason) : undefined,
|
|
211
|
-
privacyLevel:
|
|
212
|
-
flags.privacy && flags.privacy !== true ? String(flags.privacy) : "internal",
|
|
213
|
-
};
|
|
214
|
-
return request("POST", "/api/agent/eval-feedback", body);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
178
|
// Client-side fuzzy match — used as a fallback when the server hasn't yet
|
|
218
179
|
// shipped the search/filter API (Fix B, 2026-04-25). Once the server
|
|
219
180
|
// returns the `{deals,total,limit,offset}` envelope, this path is never
|
|
@@ -403,8 +364,8 @@ Agent onboarding (run once on first install):
|
|
|
403
364
|
llama activity new-deals --since 24h # recent deal creations for agents
|
|
404
365
|
llama activity updated-deals --since 7d # meaningful deal updates, grouped
|
|
405
366
|
llama explain <url-or-object> # explain Command URL/object status + lifecycle
|
|
406
|
-
llama
|
|
407
|
-
llama
|
|
367
|
+
llama pref list [--status proposed] # standing agent preferences (injected every turn)
|
|
368
|
+
llama pref add reply-style "Lead with the conclusion." [--team]
|
|
408
369
|
|
|
409
370
|
External pitch — talk to Llama Ventures' intake agent (no token required):
|
|
410
371
|
llama pitch start --name "Jane Doe" --email "jane@acme.ai"
|
|
@@ -496,16 +457,17 @@ Approvals (partner queue — self-claim approvals):
|
|
|
496
457
|
|
|
497
458
|
Timeline / Posts:
|
|
498
459
|
llama timeline <dealId> # full unified feed
|
|
499
|
-
llama post <dealId> "message body" [--link url] [--link-name "name"]
|
|
460
|
+
llama post <dealId> "message body" [--link url] [--link-name "name"] [--cue]
|
|
461
|
+
# --cue only after explicit user approval
|
|
500
462
|
|
|
501
463
|
Brief blocks:
|
|
502
464
|
llama brief blocks <dealId> # list current block array
|
|
503
465
|
llama brief block <dealId> <blockId> # fetch one block's body (manifest in 'llama deal show')
|
|
504
|
-
llama brief add-text <dealId> --heading "..." --body "..."
|
|
505
|
-
llama brief add-link <dealId> --url "..." --label "..." [--description "..."]
|
|
506
|
-
llama brief add-embed <dealId> --url "..." [--label "..."]
|
|
507
|
-
llama brief add-callout <dealId> --tone insight|info|warning|success --heading "..." --body "..."
|
|
508
|
-
llama brief edit <dealId> <blockId> [--heading ...] [--body ...] [--url ...] [--label ...] [--tone ...]
|
|
466
|
+
llama brief add-text <dealId> --heading "..." --body "..." [--cue]
|
|
467
|
+
llama brief add-link <dealId> --url "..." --label "..." [--description "..."] [--cue]
|
|
468
|
+
llama brief add-embed <dealId> --url "..." [--label "..."] [--cue]
|
|
469
|
+
llama brief add-callout <dealId> --tone insight|info|warning|success --heading "..." --body "..." [--cue]
|
|
470
|
+
llama brief edit <dealId> <blockId> [--heading ...] [--body ...] [--url ...] [--label ...] [--tone ...] [--cue]
|
|
509
471
|
[--source-section <key>] [--lock|--unlock] [--hide|--unhide]
|
|
510
472
|
llama brief delete <dealId> <blockId>
|
|
511
473
|
llama brief history <dealId> <blockId> [--limit 50] # prior versions of this block (newest first)
|
|
@@ -514,7 +476,7 @@ Brief blocks:
|
|
|
514
476
|
|
|
515
477
|
Common flags on every add-*:
|
|
516
478
|
--source-section <key> Target a structured section (team, highlights, recommendation,
|
|
517
|
-
|
|
479
|
+
landscape_map, competitors). Without this, blocks land in "_other"
|
|
518
480
|
at the bottom of the TOC. AI writers want this.
|
|
519
481
|
--reply-to <blockId> Make the block a reply to <blockId>. Snapshots parent's heading
|
|
520
482
|
+ 200-char excerpt into meta so the back-link survives parent
|
|
@@ -523,10 +485,9 @@ Brief blocks:
|
|
|
523
485
|
2026-05-03). Use bottom for batched writes that need to
|
|
524
486
|
preserve insertion order.
|
|
525
487
|
|
|
526
|
-
Brief
|
|
488
|
+
Brief refresh + agent-run revert:
|
|
527
489
|
llama deal refresh-brief <dealId> [--force] # re-eval stale sections
|
|
528
490
|
# --force = every unlocked watcher-managed section
|
|
529
|
-
llama deal refresh-persona <dealId> <persona-key> # server validates persona key
|
|
530
491
|
llama deal revert-run <dealId> <runId> --section <key> # legacy 4-section model only
|
|
531
492
|
# section: company|team|highlights|recommendation
|
|
532
493
|
|
|
@@ -536,17 +497,13 @@ Deal soft-delete / restore / trash list:
|
|
|
536
497
|
llama deal trash # list deleted deals
|
|
537
498
|
|
|
538
499
|
Deal facts (AI-extracted or human-asserted, with verification):
|
|
500
|
+
llama deal ingest <dealId> --file <packet.json> [--idempotency-key <key>] # atomic facts + optional Feed note
|
|
501
|
+
packet: {"source":{"kind":"meeting_note","title":"Office visit"},"facts":[{"category":"team","claim":"..."}],"note":"..."}
|
|
502
|
+
categories: company_basics | team | product | market | financials | fundraise | risk | milestone | meta
|
|
539
503
|
llama deal fact list <dealId>
|
|
540
504
|
llama deal fact add <dealId> --category <cat> --claim "<text>" [--source "..."] [--source-url <url>] [--confidence high|medium|low] [--attested]
|
|
541
505
|
llama deal fact verify <dealId> <factId> --status confirmed|disputed [--corrected-value "..."]
|
|
542
506
|
|
|
543
|
-
Skill corrections (persona-owner pushback — read by persona-watcher):
|
|
544
|
-
llama skill-correction list <skill-slug> [--include-deleted]
|
|
545
|
-
llama skill-correction add <skill-slug> "<correction text>" [--deal <uuid>] [--block <blockId>]
|
|
546
|
-
llama skill-correction delete <id>
|
|
547
|
-
Server enforces persona owner OR system admin on POST/DELETE; GET is open.
|
|
548
|
-
External personas (owner_email=null) are admin-only for write.
|
|
549
|
-
|
|
550
507
|
Mentions / Inbox:
|
|
551
508
|
llama mentions # default: my unresolved cues
|
|
552
509
|
llama mentions list [--everyone] [--all] # --everyone = team-wide; --all = include resolved
|
|
@@ -663,7 +620,6 @@ Common:
|
|
|
663
620
|
llama agent bootstrap live Llama OS skill manifest from Command
|
|
664
621
|
llama skills search "<query>" discover which skill to read
|
|
665
622
|
llama explain <url-or-object> explain Command URLs, 404s, deleted objects
|
|
666
|
-
llama eval bad --last mark latest CLI/MCP result as an eval candidate
|
|
667
623
|
|
|
668
624
|
Command groups — run \`llama help <group>\` for that group's commands:
|
|
669
625
|
deal create · show · feed · update · enrich · search · collaborators · links · delete
|
|
@@ -672,7 +628,7 @@ Command groups — run \`llama help <group>\` for that group's commands:
|
|
|
672
628
|
facts deal facts + skill corrections (the sourced, trust-rated layer)
|
|
673
629
|
timeline timeline · posts · mentions
|
|
674
630
|
wiki cross-deal knowledge entries (markdown or HTML)
|
|
675
|
-
|
|
631
|
+
pref standing agent preferences: list · add · retire · approve
|
|
676
632
|
memo long-form HTML investment memo
|
|
677
633
|
html deal-specific HTML artifacts (/deals/<id>/browse/<slug>)
|
|
678
634
|
pitch external founder intake (no token needed)
|
|
@@ -691,7 +647,7 @@ the CLI auto-detects it — no token needed (\`llc_\` tokens are a fallback).`;
|
|
|
691
647
|
const HELP_AREA_MATCH = {
|
|
692
648
|
deal: [/^Deals/, /^Collaborators/, /^Soft-delete/, /^Deal links/, /^Deal soft-delete/],
|
|
693
649
|
activity: [/^Agent activity/],
|
|
694
|
-
brief: [/^Brief blocks
|
|
650
|
+
brief: [/^Brief blocks/],
|
|
695
651
|
facts: [/^Deal facts/, /^Skill corrections/],
|
|
696
652
|
timeline: [/^Timeline/, /^Mentions/],
|
|
697
653
|
wiki: [/^Wiki/, /^Where does this HTML/],
|
|
@@ -1164,6 +1120,49 @@ async function main() {
|
|
|
1164
1120
|
throw new Error(`Unknown skills subcommand "${sub}". Use: list / search / show.`);
|
|
1165
1121
|
}
|
|
1166
1122
|
|
|
1123
|
+
// `llama pref ...` — standing agent preferences (learning-domain v1).
|
|
1124
|
+
// Own user scope activates immediately; team scope needs a system admin.
|
|
1125
|
+
if (area === "pref" || area === "prefs" || area === "preferences") {
|
|
1126
|
+
const sub = action;
|
|
1127
|
+
if (!sub || sub === "list") {
|
|
1128
|
+
const { flags } = parseFlags(rest, ["json", "status"]);
|
|
1129
|
+
const params = new URLSearchParams();
|
|
1130
|
+
if (flags.status && flags.status !== true) params.set("status", String(flags.status));
|
|
1131
|
+
const result = await request("GET", `/api/agent/preferences${params.toString() ? `?${params}` : ""}`);
|
|
1132
|
+
print(result);
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
if (sub === "add") {
|
|
1136
|
+
const { flags, positional } = parseFlags(rest, ["team", "evidence", "json"]);
|
|
1137
|
+
const key = positional[0];
|
|
1138
|
+
const content = positional.slice(1).join(" ").trim();
|
|
1139
|
+
if (!key || !content) {
|
|
1140
|
+
throw new Error('Usage: llama pref add <key> "<content, max 280 chars>" [--team] [--evidence "..."]');
|
|
1141
|
+
}
|
|
1142
|
+
const result = await request("POST", "/api/agent/preferences", {
|
|
1143
|
+
scope: flags.team ? "team" : "user",
|
|
1144
|
+
key,
|
|
1145
|
+
content,
|
|
1146
|
+
evidence: flags.evidence && flags.evidence !== true ? String(flags.evidence) : undefined,
|
|
1147
|
+
});
|
|
1148
|
+
print(result);
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
if (sub === "retire" || sub === "approve") {
|
|
1152
|
+
const { positional } = parseFlags(rest, ["json"]);
|
|
1153
|
+
const id = Number(positional[0]);
|
|
1154
|
+
if (!Number.isInteger(id) || id <= 0) {
|
|
1155
|
+
throw new Error(`Usage: llama pref ${sub} <id>`);
|
|
1156
|
+
}
|
|
1157
|
+
const result = await request("PATCH", `/api/agent/preferences/${id}`, {
|
|
1158
|
+
status: sub === "approve" ? "active" : "retired",
|
|
1159
|
+
});
|
|
1160
|
+
print(result);
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
throw new Error(`Unknown pref subcommand "${sub}". Use: list / add / retire / approve.`);
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1167
1166
|
if (area === "explain" || (area === "agent" && action === "explain")) {
|
|
1168
1167
|
const args = area === "explain" ? [action, ...rest].filter(Boolean) : rest;
|
|
1169
1168
|
const { flags, positional } = parseFlags(args, ["json", "type", "id", "lang"]);
|
|
@@ -1201,43 +1200,6 @@ async function main() {
|
|
|
1201
1200
|
return;
|
|
1202
1201
|
}
|
|
1203
1202
|
|
|
1204
|
-
if (area === "eval") {
|
|
1205
|
-
const sub = action;
|
|
1206
|
-
if (sub === "good" || sub === "bad") {
|
|
1207
|
-
const { flags, positional } = parseFlags(rest, [
|
|
1208
|
-
"last",
|
|
1209
|
-
"event",
|
|
1210
|
-
"reason",
|
|
1211
|
-
"expect",
|
|
1212
|
-
"surface",
|
|
1213
|
-
"privacy",
|
|
1214
|
-
]);
|
|
1215
|
-
const q = positional.join(" ").trim();
|
|
1216
|
-
print(await submitEvalFeedback(sub, flags, q));
|
|
1217
|
-
return;
|
|
1218
|
-
}
|
|
1219
|
-
if (sub === "add") {
|
|
1220
|
-
const { flags, positional } = parseFlags(rest, [
|
|
1221
|
-
"event",
|
|
1222
|
-
"expect",
|
|
1223
|
-
"reason",
|
|
1224
|
-
"surface",
|
|
1225
|
-
"privacy",
|
|
1226
|
-
]);
|
|
1227
|
-
const q = positional.join(" ").trim();
|
|
1228
|
-
if (!q && !flags.event) {
|
|
1229
|
-
throw new Error(
|
|
1230
|
-
`Usage: llama eval add "<query>" --surface deal|wiki --expect wiki:<slug>|deal:<uuid>`,
|
|
1231
|
-
);
|
|
1232
|
-
}
|
|
1233
|
-
print(await submitEvalFeedback("add", flags, q));
|
|
1234
|
-
return;
|
|
1235
|
-
}
|
|
1236
|
-
throw new Error(
|
|
1237
|
-
"Usage: llama eval good|bad [--last] [--reason ...] OR llama eval add \"<query>\" --expect wiki:<slug>|deal:<uuid>",
|
|
1238
|
-
);
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
1203
|
// `llama pitch ...` — external founder-pitch family. No Llama token
|
|
1242
1204
|
// required; bootstraps a session against /api/external/* via PoW + cookie.
|
|
1243
1205
|
// See lib/external.mjs and AGENT_BRIEFING.md for the full surface.
|
|
@@ -1763,6 +1725,36 @@ async function main() {
|
|
|
1763
1725
|
return;
|
|
1764
1726
|
}
|
|
1765
1727
|
|
|
1728
|
+
// ----- Canonical source-packet ingest (atomic facts + optional Feed note) -----
|
|
1729
|
+
if (area === "deal" && action === "ingest") {
|
|
1730
|
+
const dealId = rest[0];
|
|
1731
|
+
const { flags } = parseFlags(rest.slice(1), ["file", "idempotency-key"]);
|
|
1732
|
+
if (!dealId || !flags.file || flags.file === true) {
|
|
1733
|
+
throw new Error(
|
|
1734
|
+
"Usage: llama deal ingest <dealId> --file <packet.json> [--idempotency-key <key>]\n" +
|
|
1735
|
+
'Packet: {"source":{"kind":"meeting_note","title":"Office visit"},' +
|
|
1736
|
+
'"facts":[{"category":"team","claim":"..."}],"note":"..."}'
|
|
1737
|
+
);
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
let packet;
|
|
1741
|
+
try {
|
|
1742
|
+
packet = JSON.parse(await readFile(String(flags.file), "utf8"));
|
|
1743
|
+
} catch (error) {
|
|
1744
|
+
throw new Error(`Cannot read ingest packet ${flags.file}: ${error?.message ?? String(error)}`);
|
|
1745
|
+
}
|
|
1746
|
+
if (!packet || Array.isArray(packet) || typeof packet !== "object") {
|
|
1747
|
+
throw new Error("Ingest packet must be a JSON object");
|
|
1748
|
+
}
|
|
1749
|
+
if (flags["idempotency-key"] !== undefined && flags["idempotency-key"] !== true) {
|
|
1750
|
+
packet.idempotencyKey = String(flags["idempotency-key"]);
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
// @core-api-operation POST /api/deals/{dealId}/ingest
|
|
1754
|
+
print(await request("POST", `/api/deals/${encodeURIComponent(dealId)}/ingest`, packet));
|
|
1755
|
+
return;
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1766
1758
|
// ----- Deal facts (AI-extracted or human-asserted, with verification) -----
|
|
1767
1759
|
if (area === "deal" && action === "fact") {
|
|
1768
1760
|
const sub = rest[0];
|
|
@@ -1839,24 +1831,6 @@ async function main() {
|
|
|
1839
1831
|
return;
|
|
1840
1832
|
}
|
|
1841
1833
|
|
|
1842
|
-
// ----- Persona refresh: re-run a single persona-watcher -----
|
|
1843
|
-
// Persona keys are validated server-side. Returns runId or null
|
|
1844
|
-
// (debounced / deal inactive). Used by /admin and the per-block
|
|
1845
|
-
// "重新生成" flow.
|
|
1846
|
-
if (area === "deal" && action === "refresh-persona") {
|
|
1847
|
-
const dealId = rest[0];
|
|
1848
|
-
const persona = rest[1];
|
|
1849
|
-
if (!dealId || !persona) {
|
|
1850
|
-
throw new Error(`Usage: llama deal refresh-persona <dealId> <persona-key>`);
|
|
1851
|
-
}
|
|
1852
|
-
print(await request(
|
|
1853
|
-
"POST",
|
|
1854
|
-
`/api/deals/${encodeURIComponent(dealId)}/refresh-persona`,
|
|
1855
|
-
{ persona }
|
|
1856
|
-
));
|
|
1857
|
-
return;
|
|
1858
|
-
}
|
|
1859
|
-
|
|
1860
1834
|
// ----- Agent-run revert (legacy 4-section brief model) -----
|
|
1861
1835
|
// Reverts a single section to the `before` value snapshotted by the
|
|
1862
1836
|
// watcher run. Does NOT re-fire the watcher (intentional: human action).
|
|
@@ -1961,7 +1935,7 @@ async function main() {
|
|
|
1961
1935
|
const { flags, positional } = parseFlags(rest);
|
|
1962
1936
|
const body = positional[0];
|
|
1963
1937
|
if (!dealId || !body) {
|
|
1964
|
-
throw new Error(`Usage: llama post <dealId> "message body" [--link url] [--link-name "name"]`);
|
|
1938
|
+
throw new Error(`Usage: llama post <dealId> "message body" [--link url] [--link-name "name"] [--cue]`);
|
|
1965
1939
|
}
|
|
1966
1940
|
const attachments = flags.link
|
|
1967
1941
|
? [{ url: String(flags.link), name: flags["link-name"] ? String(flags["link-name"]) : String(flags.link) }]
|
|
@@ -1969,7 +1943,7 @@ async function main() {
|
|
|
1969
1943
|
print(await request(
|
|
1970
1944
|
"POST",
|
|
1971
1945
|
`/api/deals/${encodeURIComponent(dealId)}/posts`,
|
|
1972
|
-
{ body, attachments }
|
|
1946
|
+
{ body, attachments, cue_authorized: flags.cue === true }
|
|
1973
1947
|
));
|
|
1974
1948
|
return;
|
|
1975
1949
|
}
|
|
@@ -2135,7 +2109,7 @@ Routing — is this the right command?
|
|
|
2135
2109
|
const meta = { updated_at: new Date().toISOString(), updated_by: "cli", by_agent: false };
|
|
2136
2110
|
|
|
2137
2111
|
// --source-section <key>: target a structured section (e.g. team /
|
|
2138
|
-
// highlights /
|
|
2112
|
+
// highlights / competitors). Without this, blocks land in the
|
|
2139
2113
|
// "_other" group at the bottom of the TOC. AI writers want this
|
|
2140
2114
|
// virtually always — without it they cannot contribute to existing
|
|
2141
2115
|
// structured sections.
|
|
@@ -2195,7 +2169,10 @@ Routing — is this the right command?
|
|
|
2195
2169
|
if (!cur) cur = await request("GET", `/api/deals/${encodeURIComponent(dealId)}/blocks`);
|
|
2196
2170
|
const existing = cur.blocks ?? [];
|
|
2197
2171
|
const next = position === "top" ? [block, ...existing] : [...existing, block];
|
|
2198
|
-
print(await request("PUT", `/api/deals/${encodeURIComponent(dealId)}/blocks`, {
|
|
2172
|
+
print(await request("PUT", `/api/deals/${encodeURIComponent(dealId)}/blocks`, {
|
|
2173
|
+
blocks: next,
|
|
2174
|
+
cue_authorized: flags.cue === true,
|
|
2175
|
+
}));
|
|
2199
2176
|
console.log(`Created block ${id}`);
|
|
2200
2177
|
return;
|
|
2201
2178
|
}
|
|
@@ -2205,7 +2182,7 @@ Routing — is this the right command?
|
|
|
2205
2182
|
const dealId = rest[0];
|
|
2206
2183
|
const blockId = rest[1];
|
|
2207
2184
|
if (!dealId || !blockId) {
|
|
2208
|
-
throw new Error("Usage: llama brief edit <dealId> <blockId> [--heading ...] [--body ...] [--url ...] [--label ...] [--description ...] [--tone ...] [--source-section ...] [--lock|--unlock] [--hide|--unhide]");
|
|
2185
|
+
throw new Error("Usage: llama brief edit <dealId> <blockId> [--heading ...] [--body ...] [--url ...] [--label ...] [--description ...] [--tone ...] [--source-section ...] [--lock|--unlock] [--hide|--unhide] [--cue]");
|
|
2209
2186
|
}
|
|
2210
2187
|
const patch = {};
|
|
2211
2188
|
for (const k of ["heading", "body", "url", "label", "description", "tone"]) {
|
|
@@ -2225,8 +2202,11 @@ Routing — is this the right command?
|
|
|
2225
2202
|
metaPatch.sourceSection = String(flags["source-section"]);
|
|
2226
2203
|
}
|
|
2227
2204
|
if (Object.keys(metaPatch).length > 0) patch.meta = metaPatch;
|
|
2205
|
+
if (flags.cue === true) patch.cue_authorized = true;
|
|
2228
2206
|
|
|
2229
|
-
if (Object.keys(patch).length === 0
|
|
2207
|
+
if (Object.keys(patch).length === 0 || (Object.keys(patch).length === 1 && patch.cue_authorized === true)) {
|
|
2208
|
+
throw new Error("at least one field flag required");
|
|
2209
|
+
}
|
|
2230
2210
|
print(await request("PATCH", `/api/deals/${encodeURIComponent(dealId)}/blocks/${encodeURIComponent(blockId)}`, patch));
|
|
2231
2211
|
return;
|
|
2232
2212
|
}
|
|
@@ -2379,63 +2359,6 @@ Routing — is this the right command?
|
|
|
2379
2359
|
throw new Error(`Unknown mentions subcommand "${sub}". Use: list / show / resolve / unread.`);
|
|
2380
2360
|
}
|
|
2381
2361
|
|
|
2382
|
-
// ----- Skill corrections (persona-owner pushback workflow) -----
|
|
2383
|
-
// Persona owners (or system admins) record long-term rules each
|
|
2384
|
-
// persona-DD skill must obey. Read by the persona-watcher and prepended
|
|
2385
|
-
// to the system prompt at run time. Soft-delete is non-cascading —
|
|
2386
|
-
// deleting a row does NOT auto-fire watcher; the next natural run
|
|
2387
|
-
// (manual / stale_re_eval) just stops including the deleted rule.
|
|
2388
|
-
//
|
|
2389
|
-
// Permissions enforced server-side: only the persona owner (per
|
|
2390
|
-
// PERSONA_SKILLS in src/lib/persona-skills.ts) or a system admin can
|
|
2391
|
-
// POST or DELETE. Anyone can GET. External personas (owner_email=null)
|
|
2392
|
-
// are admin-only for write.
|
|
2393
|
-
if (area === "skill-correction") {
|
|
2394
|
-
const sub = action;
|
|
2395
|
-
|
|
2396
|
-
if (sub === "list") {
|
|
2397
|
-
const skillSlug = rest[0];
|
|
2398
|
-
if (!skillSlug) {
|
|
2399
|
-
throw new Error("Usage: llama skill-correction list <skill-slug> [--include-deleted]");
|
|
2400
|
-
}
|
|
2401
|
-
const { flags } = parseFlags(rest.slice(1));
|
|
2402
|
-
const params = new URLSearchParams({ skill: skillSlug });
|
|
2403
|
-
if (flags["include-deleted"]) params.set("include_deleted", "1");
|
|
2404
|
-
print(await request("GET", `/api/skill-corrections?${params.toString()}`));
|
|
2405
|
-
return;
|
|
2406
|
-
}
|
|
2407
|
-
|
|
2408
|
-
if (sub === "add") {
|
|
2409
|
-
const { flags, positional } = parseFlags(rest);
|
|
2410
|
-
const skillSlug = positional[0];
|
|
2411
|
-
const correctionText = positional.slice(1).join(" ").trim();
|
|
2412
|
-
if (!skillSlug || !correctionText) {
|
|
2413
|
-
throw new Error(
|
|
2414
|
-
`Usage: llama skill-correction add <skill-slug> "<correction text>" ` +
|
|
2415
|
-
`[--deal <uuid>] [--block <blockId>]`
|
|
2416
|
-
);
|
|
2417
|
-
}
|
|
2418
|
-
print(await request("POST", "/api/skill-corrections", {
|
|
2419
|
-
skill_slug: skillSlug,
|
|
2420
|
-
correction_text: correctionText,
|
|
2421
|
-
triggered_in_deal_uuid: flags.deal ? String(flags.deal) : null,
|
|
2422
|
-
triggered_in_block_id: flags.block ? String(flags.block) : null,
|
|
2423
|
-
}));
|
|
2424
|
-
return;
|
|
2425
|
-
}
|
|
2426
|
-
|
|
2427
|
-
if (sub === "delete") {
|
|
2428
|
-
const id = rest[0];
|
|
2429
|
-
if (!id) throw new Error("Usage: llama skill-correction delete <id>");
|
|
2430
|
-
print(await request("DELETE", `/api/skill-corrections/${encodeURIComponent(id)}`));
|
|
2431
|
-
return;
|
|
2432
|
-
}
|
|
2433
|
-
|
|
2434
|
-
throw new Error(
|
|
2435
|
-
`Unknown skill-correction subcommand "${sub || ""}". Use: list / add / delete.`
|
|
2436
|
-
);
|
|
2437
|
-
}
|
|
2438
|
-
|
|
2439
2362
|
// ----- Memo (long-form HTML investment memo) -----
|
|
2440
2363
|
// The Memo tab in the deal page renders HTML stored in deal_memos.
|
|
2441
2364
|
// Two sources of memo content:
|
package/contracts/core-api.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"format": "llama.core-api-contract.v1",
|
|
3
3
|
"name": "llama-core-api",
|
|
4
|
-
"apiVersion": "
|
|
4
|
+
"apiVersion": "3.5.0",
|
|
5
5
|
"openapiVersion": "3.0.3",
|
|
6
|
-
"sha256": "
|
|
7
|
-
"pathCount":
|
|
8
|
-
"operationCount":
|
|
6
|
+
"sha256": "31c7d23ee06bd4282aa2451698604cc30df4792d4a0e9674593a809b4eb55767",
|
|
7
|
+
"pathCount": 216,
|
|
8
|
+
"operationCount": 281
|
|
9
9
|
}
|