@llamaventures/cli 1.25.0 → 1.26.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 +8 -0
- package/CHANGELOG.md +19 -0
- package/bin/llama-mcp.mjs +96 -93
- package/bin/llama.mjs +72 -169
- package/contracts/core-api.json +4 -4
- package/contracts/required-operations.json +12 -20
- package/lib/build-manifest.json +4 -4
- package/package.json +3 -3
package/AGENT_BRIEFING.md
CHANGED
|
@@ -150,6 +150,7 @@ The table below details the exact CLI for each destination.
|
|
|
150
150
|
| HTML artifact, external — founder-facing share link | Netlify | Only when the user explicitly says "share link", "give it to the founder", "publish publicly". Use the `netlify-access-guard` workflow (server-side password + edge 401 verification). |
|
|
151
151
|
| Insights, decisions, framework improvements | Wiki (markdown) | `llama wiki save <slug> --content "..."` (with attribution — see below) |
|
|
152
152
|
| **HTML wiki entry — standalone HTML page hosted at `/wiki/<slug>`** (sector landscape, market map, dashboard, hand-styled thesis page) | **Wiki (HTML)** | `llama wiki save <slug> --title "..." --file <path.html> --sources "..."`. Auto-detects content_type=html from extension. Public page is full-viewport sandboxed iframe takeover (no wiki chrome). Sources/status/title still required; appears in `wiki search` + backlinks. Use when the user says "deploy this HTML to wiki", "wiki 词条", "make this page a wiki entry". HTML must be self-contained (inline CSS/JS, image data URIs or external URLs) — asset bundles aren't supported on wiki yet. **Native comments + working in-page (#) anchor links are injected automatically** — readers discuss inline and the table of contents scrolls; you don't wire anything up (pages that already embed the comment widget are left as-is). |
|
|
153
|
+
| **Document wiki entry — a PDF / DOCX / XLSX read at `/wiki/<slug>`** (deck, market model, memo you were handed) | **Wiki (document)** | `llama wiki save <slug> --title "..." --file <path.{pdf,docx,xlsx}> --sources "..."`. The document itself is what readers open: a PDF in the browser's own viewer with page navigation, a DOCX or XLSX converted for reading with the original still downloadable. Use when someone hands you a file and wants it ON the wiki. Do NOT transcribe it into markdown, and do NOT write an article describing a file nobody can open. |
|
|
153
154
|
| Large files (deck / PDF / transcript) | Drive deal folder | the deal's `folder_url` (from `llama deal show`) → upload via your filesystem / Drive tool |
|
|
154
155
|
| Cross-team cues | Inbox + email | `llama post <dealId> "@<teammate> ..." --cue` — use `--cue` only after the user explicitly authorized that recipient |
|
|
155
156
|
|
|
@@ -288,6 +289,13 @@ llama wiki save <slug> --title "..." --file path.html --sources "..." [--content
|
|
|
288
289
|
# --content-type html (or markdown) overrides the inference.
|
|
289
290
|
# Refuses to switch content_type on an existing slug; delete + re-create
|
|
290
291
|
# if you really mean to change format.
|
|
292
|
+
|
|
293
|
+
# Document entry — the file IS the entry, readable at /wiki/<slug>:
|
|
294
|
+
llama wiki save <slug> --title "..." --file path.{pdf,docx,xlsx} --sources "..." [--doc-kind ...]
|
|
295
|
+
# PDF opens in the browser's viewer; DOCX and XLSX are converted for reading
|
|
296
|
+
# (a spreadsheet keeps one tab per sheet). The original stays downloadable.
|
|
297
|
+
# Upload the document you have — do NOT transcribe it into markdown first,
|
|
298
|
+
# and do NOT write an article describing a file nobody can open.
|
|
291
299
|
# Delete / restore (soft, reversible — CONSTITUTION §8):
|
|
292
300
|
llama wiki delete <slug> [--lang en|zh]
|
|
293
301
|
llama wiki restore <slug> [--lang en|zh]
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,25 @@ this project adheres to [Semantic Versioning](https://semver.org).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.26.0] - 2026-08-11
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- `llama wiki save <slug> --file <path>.{pdf,docx,xlsx}` uploads the document
|
|
13
|
+
itself as the wiki entry, so readers open it at `/wiki/<slug>` instead of an
|
|
14
|
+
article describing it. A PDF opens in the browser's own viewer; DOCX and XLSX
|
|
15
|
+
are converted for reading with the original still downloadable.
|
|
16
|
+
- `wiki_save_file` MCP tool — the same publish from a local file path, for
|
|
17
|
+
MCP-native agents, mirroring `html_upload_file`.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- Pin the Core API consumer contract to 3.33.0. The wiki document upload calls
|
|
21
|
+
an operation that does not exist on older Llama Command.
|
|
22
|
+
|
|
23
|
+
### Removed
|
|
24
|
+
- Retire every CLI/MCP Memo mutation path. `llama memo` and MCP now expose the
|
|
25
|
+
current Memo read-only; generation runs only from Llama Command's durable
|
|
26
|
+
Memo Agent. Deal enrichment no longer accepts `--memo` / `generateMemo`.
|
|
27
|
+
|
|
9
28
|
## [1.25.0] - 2026-08-05
|
|
10
29
|
|
|
11
30
|
### Added
|
package/bin/llama-mcp.mjs
CHANGED
|
@@ -116,9 +116,6 @@ function buildEnrichmentAgentMessage(args = {}) {
|
|
|
116
116
|
"monid",
|
|
117
117
|
];
|
|
118
118
|
const budget = args.budgetCents ?? "50";
|
|
119
|
-
const memo = args.generateMemo
|
|
120
|
-
? "Generate memo only after enrichment because the caller explicitly requested it."
|
|
121
|
-
: "Do not generate memo.";
|
|
122
119
|
return [
|
|
123
120
|
"Run server-side deal enrichment for this deal.",
|
|
124
121
|
`Use sources: ${sources.join(", ")}.`,
|
|
@@ -127,7 +124,7 @@ function buildEnrichmentAgentMessage(args = {}) {
|
|
|
127
124
|
"Write canonical evidence links, sourced deal facts, stable deal fields, and typed factual values where supported.",
|
|
128
125
|
"For typed factual values, call read_typed_factual_layer first and use upsert_typed_fact for queryable fields.",
|
|
129
126
|
"Search snippets alone are not high-confidence evidence; fetch direct sources where possible.",
|
|
130
|
-
|
|
127
|
+
"Do not generate Memo; the durable Memo Agent in Llama Command owns that separate workflow.",
|
|
131
128
|
"End with what was written, what was skipped, and open questions.",
|
|
132
129
|
].join(" ");
|
|
133
130
|
}
|
|
@@ -1046,6 +1043,95 @@ server.registerTool(
|
|
|
1046
1043
|
})
|
|
1047
1044
|
);
|
|
1048
1045
|
|
|
1046
|
+
server.registerTool(
|
|
1047
|
+
"wiki_save_file",
|
|
1048
|
+
{
|
|
1049
|
+
description:
|
|
1050
|
+
"Publish a PDF / DOCX / XLSX from a LOCAL FILE PATH as the wiki entry " +
|
|
1051
|
+
"itself. Readers open the document at /wiki/<slug>: a PDF in the " +
|
|
1052
|
+
"browser's own viewer with page navigation, a DOCX or XLSX converted " +
|
|
1053
|
+
"for reading (a spreadsheet keeps one tab per sheet), and the original " +
|
|
1054
|
+
"always downloadable. Use this whenever someone hands you a document " +
|
|
1055
|
+
"and wants it ON the wiki — do NOT transcribe it into markdown for " +
|
|
1056
|
+
"wiki_save, and do NOT write an article describing a file nobody can " +
|
|
1057
|
+
"open. Reads filePath on the machine running this MCP server, so the " +
|
|
1058
|
+
"bytes never pass through tool-call context. Deal-specific documents " +
|
|
1059
|
+
"belong on the deal page instead (html_upload_file).",
|
|
1060
|
+
inputSchema: {
|
|
1061
|
+
slug: z.string().describe("kebab-case slug"),
|
|
1062
|
+
title: z.string(),
|
|
1063
|
+
filePath: z
|
|
1064
|
+
.string()
|
|
1065
|
+
.describe("absolute or relative local path to a .pdf / .docx / .xlsx"),
|
|
1066
|
+
sources: z
|
|
1067
|
+
.array(z.string())
|
|
1068
|
+
.min(1)
|
|
1069
|
+
.describe(
|
|
1070
|
+
"citation list — URLs, doc names, or meeting references. At least one required."
|
|
1071
|
+
),
|
|
1072
|
+
type: z.string().optional().describe("optional category tag, e.g. 'company'"),
|
|
1073
|
+
doc_kind: z
|
|
1074
|
+
.string()
|
|
1075
|
+
.optional()
|
|
1076
|
+
.describe("optional — how the wiki home browses and search filters"),
|
|
1077
|
+
lang: z.enum(["en", "zh"]).optional().describe("default: en"),
|
|
1078
|
+
},
|
|
1079
|
+
},
|
|
1080
|
+
async ({ slug, title, filePath, sources, type, doc_kind, lang }) => {
|
|
1081
|
+
const { readFileSync } = await import("node:fs");
|
|
1082
|
+
const { basename } = await import("node:path");
|
|
1083
|
+
const ext = String(filePath).toLowerCase().match(/\.(pdf|docx|xlsx)$/)?.[1];
|
|
1084
|
+
if (!ext) {
|
|
1085
|
+
return textResult(
|
|
1086
|
+
`Error: wiki_save_file takes a .pdf, .docx, or .xlsx. For markdown or a ` +
|
|
1087
|
+
`standalone HTML page, use wiki_save.`,
|
|
1088
|
+
true,
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
let buf;
|
|
1092
|
+
try {
|
|
1093
|
+
buf = readFileSync(String(filePath));
|
|
1094
|
+
} catch (err) {
|
|
1095
|
+
return textResult(`Error reading ${filePath}: ${err?.message ?? String(err)}`, true);
|
|
1096
|
+
}
|
|
1097
|
+
const MAX = 50 * 1024 * 1024;
|
|
1098
|
+
if (buf.length > MAX) {
|
|
1099
|
+
return textResult(
|
|
1100
|
+
`Error: ${basename(String(filePath))} is ${(buf.length / 1024 / 1024).toFixed(1)} MB; ` +
|
|
1101
|
+
`the wiki caps files at 50 MB. Link to the Drive copy instead.`,
|
|
1102
|
+
true,
|
|
1103
|
+
);
|
|
1104
|
+
}
|
|
1105
|
+
const mime = {
|
|
1106
|
+
pdf: "application/pdf",
|
|
1107
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
1108
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
1109
|
+
}[ext];
|
|
1110
|
+
const form = new FormData();
|
|
1111
|
+
form.append("file", new Blob([buf], { type: mime }), basename(String(filePath)));
|
|
1112
|
+
form.append("title", String(title));
|
|
1113
|
+
form.append("sources", sources.join(";"));
|
|
1114
|
+
form.append("lang", lang === "zh" ? "zh" : "en");
|
|
1115
|
+
if (type) form.append("type", String(type));
|
|
1116
|
+
if (doc_kind) form.append("doc_kind", String(doc_kind));
|
|
1117
|
+
|
|
1118
|
+
const headers = await getAuthHeaders();
|
|
1119
|
+
// @core-api-operation POST /api/wiki/{slug}/file
|
|
1120
|
+
const res = await fetch(
|
|
1121
|
+
`${getBaseUrl()}/api/wiki/${encodeURIComponent(slug)}/file`,
|
|
1122
|
+
{ method: "POST", headers, body: form }, // let fetch set the multipart boundary
|
|
1123
|
+
);
|
|
1124
|
+
const body = await res.json().catch(() => ({}));
|
|
1125
|
+
if (!res.ok) {
|
|
1126
|
+
return textResult(
|
|
1127
|
+
`HTTP ${res.status}: ${body?.error || JSON.stringify(body).slice(0, 300)}`,
|
|
1128
|
+
true,
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
return textResult(JSON.stringify(body, null, 2));
|
|
1132
|
+
},
|
|
1133
|
+
);
|
|
1134
|
+
|
|
1049
1135
|
server.registerTool(
|
|
1050
1136
|
"wiki_delete",
|
|
1051
1137
|
{
|
|
@@ -1212,9 +1298,8 @@ server.registerTool(
|
|
|
1212
1298
|
"status, and planned writes without changing facts/links/memo. With " +
|
|
1213
1299
|
"apply=true and executor=server_agent, this starts the server-side Deal " +
|
|
1214
1300
|
"Agent unless harnessOnly=true. Set apply=true only when the user " +
|
|
1215
|
-
"explicitly wants the enrichment run recorded/applied. " +
|
|
1216
|
-
"
|
|
1217
|
-
"for Memo generation after enrichment.",
|
|
1301
|
+
"explicitly wants the enrichment run recorded/applied. Memo generation is " +
|
|
1302
|
+
"not part of enrichment and is available only in Llama Command's Memo Agent.",
|
|
1218
1303
|
inputSchema: {
|
|
1219
1304
|
dealId: z.string().describe("deal uuid"),
|
|
1220
1305
|
dryRun: z.boolean().optional().describe("default true unless apply=true"),
|
|
@@ -1234,10 +1319,6 @@ server.registerTool(
|
|
|
1234
1319
|
.max(500)
|
|
1235
1320
|
.optional()
|
|
1236
1321
|
.describe("Monid spend cap for this run, in cents; default is 50 when Monid is requested"),
|
|
1237
|
-
generateMemo: z
|
|
1238
|
-
.boolean()
|
|
1239
|
-
.optional()
|
|
1240
|
-
.describe("explicitly request memo regeneration after enrichment; default false"),
|
|
1241
1322
|
harnessOnly: z
|
|
1242
1323
|
.boolean()
|
|
1243
1324
|
.optional()
|
|
@@ -1248,13 +1329,13 @@ server.registerTool(
|
|
|
1248
1329
|
.describe("optional override instruction for the server-side Deal Agent"),
|
|
1249
1330
|
},
|
|
1250
1331
|
},
|
|
1251
|
-
async ({ dealId, dryRun, apply, executor, sources, budgetCents,
|
|
1332
|
+
async ({ dealId, dryRun, apply, executor, sources, budgetCents, harnessOnly, message }) => {
|
|
1252
1333
|
const effectiveExecutor = executor ?? "server_agent";
|
|
1253
1334
|
if (apply === true && effectiveExecutor === "server_agent" && harnessOnly !== true) {
|
|
1254
1335
|
return runDealAgentTool({
|
|
1255
1336
|
dealId,
|
|
1256
1337
|
title: "MCP enrichment",
|
|
1257
|
-
message: buildEnrichmentAgentMessage({ sources, budgetCents,
|
|
1338
|
+
message: buildEnrichmentAgentMessage({ sources, budgetCents, message }),
|
|
1258
1339
|
});
|
|
1259
1340
|
}
|
|
1260
1341
|
return callApi("POST", `/api/deals/${encodeURIComponent(dealId)}/enrich`, {
|
|
@@ -1263,7 +1344,6 @@ server.registerTool(
|
|
|
1263
1344
|
executor: effectiveExecutor,
|
|
1264
1345
|
sources,
|
|
1265
1346
|
budgetCents,
|
|
1266
|
-
generateMemo,
|
|
1267
1347
|
});
|
|
1268
1348
|
}
|
|
1269
1349
|
);
|
|
@@ -1432,7 +1512,7 @@ server.registerTool(
|
|
|
1432
1512
|
);
|
|
1433
1513
|
|
|
1434
1514
|
// ============================================================
|
|
1435
|
-
// Memo —
|
|
1515
|
+
// Memo — read-only. Generation runs only from the durable Memo Agent in the UI.
|
|
1436
1516
|
// ============================================================
|
|
1437
1517
|
|
|
1438
1518
|
server.registerTool(
|
|
@@ -1440,9 +1520,7 @@ server.registerTool(
|
|
|
1440
1520
|
{
|
|
1441
1521
|
description:
|
|
1442
1522
|
"Fetch the current memo for a deal. Returns the envelope: memo " +
|
|
1443
|
-
"(html, version, source, updated_by, updated_at)
|
|
1444
|
-
"('composed' = server-generated, 'override' = hand-written), and " +
|
|
1445
|
-
"inflight (if a server-side regeneration is in progress). html " +
|
|
1523
|
+
"(html, version, source, updated_by, updated_at) and mode. html " +
|
|
1446
1524
|
"can be 50-100KB — be deliberate about including it in your reply.",
|
|
1447
1525
|
inputSchema: {
|
|
1448
1526
|
dealId: z.string().describe("deal uuid"),
|
|
@@ -1452,81 +1530,6 @@ server.registerTool(
|
|
|
1452
1530
|
callApi("GET", `/api/deals/${encodeURIComponent(dealId)}/memo`)
|
|
1453
1531
|
);
|
|
1454
1532
|
|
|
1455
|
-
server.registerTool(
|
|
1456
|
-
"memo_regenerate",
|
|
1457
|
-
{
|
|
1458
|
-
description:
|
|
1459
|
-
"Trigger server-side regeneration of the deal memo. Synchronous: " +
|
|
1460
|
-
"returns the final result (version, model, duration_ms, degraded) " +
|
|
1461
|
-
"once the composer finishes. Typical duration 2-3 minutes. Use " +
|
|
1462
|
-
"tier='opus' for high-stakes deals (higher cost, deeper analysis). " +
|
|
1463
|
-
"Pass `instructions` to steer THIS regeneration (e.g. 'focus on team " +
|
|
1464
|
-
"risk', 'frame as a follow-on') — applied across all panels, never " +
|
|
1465
|
-
"overrides the facts or the verdict.",
|
|
1466
|
-
inputSchema: {
|
|
1467
|
-
dealId: z.string().describe("deal uuid"),
|
|
1468
|
-
tier: z
|
|
1469
|
-
.enum(["sonnet", "opus"])
|
|
1470
|
-
.optional()
|
|
1471
|
-
.describe("LLM tier (default: sonnet)"),
|
|
1472
|
-
instructions: z
|
|
1473
|
-
.string()
|
|
1474
|
-
.optional()
|
|
1475
|
-
.describe(
|
|
1476
|
-
"Free-text steering for this regeneration only, e.g. 'focus on team risk'. Applied to all panels; never overrides verified facts or the verdict anchor."
|
|
1477
|
-
),
|
|
1478
|
-
},
|
|
1479
|
-
},
|
|
1480
|
-
async ({ dealId, tier, instructions }) =>
|
|
1481
|
-
callApi("POST", `/api/deals/${encodeURIComponent(dealId)}/memo`, {
|
|
1482
|
-
action: "regenerate",
|
|
1483
|
-
stream: false,
|
|
1484
|
-
model: tier ?? "sonnet",
|
|
1485
|
-
instructions: instructions || undefined,
|
|
1486
|
-
})
|
|
1487
|
-
);
|
|
1488
|
-
|
|
1489
|
-
server.registerTool(
|
|
1490
|
-
"memo_save",
|
|
1491
|
-
{
|
|
1492
|
-
description:
|
|
1493
|
-
"Save hand-written HTML as a manual override for a deal's memo. " +
|
|
1494
|
-
"Manual overrides take precedence over auto-composed memos on " +
|
|
1495
|
-
"read. Pass the full HTML document including <!DOCTYPE html>, " +
|
|
1496
|
-
"<style>, and <body> — it's rendered as-is in a sandboxed iframe.",
|
|
1497
|
-
inputSchema: {
|
|
1498
|
-
dealId: z.string().describe("deal uuid"),
|
|
1499
|
-
html: z
|
|
1500
|
-
.string()
|
|
1501
|
-
.describe("full HTML document"),
|
|
1502
|
-
},
|
|
1503
|
-
},
|
|
1504
|
-
async ({ dealId, html }) =>
|
|
1505
|
-
callApi("PUT", `/api/deals/${encodeURIComponent(dealId)}/memo`, { html })
|
|
1506
|
-
);
|
|
1507
|
-
|
|
1508
|
-
server.registerTool(
|
|
1509
|
-
"memo_reset",
|
|
1510
|
-
{
|
|
1511
|
-
description:
|
|
1512
|
-
"Reset memo state. Default drops only the manual override row " +
|
|
1513
|
-
"(next read falls back to the auto-composed version, if any). " +
|
|
1514
|
-
"Pass scope='all' to drop every version for the deal — destructive, " +
|
|
1515
|
-
"use sparingly.",
|
|
1516
|
-
inputSchema: {
|
|
1517
|
-
dealId: z.string().describe("deal uuid"),
|
|
1518
|
-
scope: z
|
|
1519
|
-
.enum(["override_only", "all"])
|
|
1520
|
-
.optional()
|
|
1521
|
-
.describe("default: override_only"),
|
|
1522
|
-
},
|
|
1523
|
-
},
|
|
1524
|
-
async ({ dealId, scope }) =>
|
|
1525
|
-
callApi("DELETE", `/api/deals/${encodeURIComponent(dealId)}/memo`, {
|
|
1526
|
-
scope: scope ?? "override_only",
|
|
1527
|
-
})
|
|
1528
|
-
);
|
|
1529
|
-
|
|
1530
1533
|
// ============================================================
|
|
1531
1534
|
// Deal page HTML — hand-authored sandboxed page per deal
|
|
1532
1535
|
// ============================================================
|
package/bin/llama.mjs
CHANGED
|
@@ -314,9 +314,6 @@ function buildEnrichmentAgentMessage(flags) {
|
|
|
314
314
|
"monid",
|
|
315
315
|
];
|
|
316
316
|
const budget = flags["budget-cents"] || flags.budgetCents || "50";
|
|
317
|
-
const memo = boolFlag(flags, "memo", "generate-memo", "generateMemo")
|
|
318
|
-
? "Generate memo only after enrichment because the caller explicitly requested it."
|
|
319
|
-
: "Do not generate memo.";
|
|
320
317
|
return [
|
|
321
318
|
"Run server-side deal enrichment for this deal.",
|
|
322
319
|
`Use sources: ${sources.join(", ")}.`,
|
|
@@ -325,7 +322,7 @@ function buildEnrichmentAgentMessage(flags) {
|
|
|
325
322
|
"Write canonical evidence links, sourced deal facts, stable deal fields, and typed factual values where supported.",
|
|
326
323
|
"For typed factual values, call read_typed_factual_layer first and use upsert_typed_fact for queryable fields.",
|
|
327
324
|
"Search snippets alone are not high-confidence evidence; fetch direct sources where possible.",
|
|
328
|
-
|
|
325
|
+
"Do not generate Memo; the durable Memo Agent in Llama Command owns that separate workflow.",
|
|
329
326
|
"End with what was written, what was skipped, and open questions.",
|
|
330
327
|
].join(" ");
|
|
331
328
|
}
|
|
@@ -409,7 +406,7 @@ Deals:
|
|
|
409
406
|
llama deal update <dealId> leadInvestor "Acme Capital"
|
|
410
407
|
llama deal enrich <dealId> [--dry-run] [--apply] [--executor server_agent|external_agent|planner]
|
|
411
408
|
[--sources website,github,linkedin,yc,monid] [--budget-cents 50]
|
|
412
|
-
[--
|
|
409
|
+
[--prompt] [--harness-only]
|
|
413
410
|
dry-run returns the harness; --apply --executor server_agent runs the server Deal Agent.
|
|
414
411
|
llama deal agent run <dealId> --message "collect founder evidence and update typed facts"
|
|
415
412
|
llama deal extra set <dealId> <key> <value> # system-admin only
|
|
@@ -539,6 +536,8 @@ Where does this HTML / thesis / artifact go?
|
|
|
539
536
|
(renders at /deals/<id>/browse/<slug>; see "Deal page HTML" below)
|
|
540
537
|
Cross-deal / institutional? ..... llama wiki save <slug> --title "..." --file <path>.html --sources "..."
|
|
541
538
|
(renders at /wiki/<slug>; see "Wiki" below)
|
|
539
|
+
A document, not a page? ......... llama wiki save <slug> --title "..." --file <path>.{pdf,docx,xlsx} --sources "..."
|
|
540
|
+
(the file itself becomes the entry; see "Wiki" below)
|
|
542
541
|
Founder-facing public share? .... Netlify (with netlify-access-guard skill), only when user explicitly
|
|
543
542
|
says "share publicly". Llama Command outranks Netlify for everything
|
|
544
543
|
internal — don't reach for Netlify by default.
|
|
@@ -552,17 +551,19 @@ Wiki:
|
|
|
552
551
|
llama wiki save <slug> --title "..." --file path.html --sources "..." [--content-type html]
|
|
553
552
|
(.html / .htm extension auto-implies content_type=html)
|
|
554
553
|
Native comments + working in-page (#) links are added automatically — just upload self-contained HTML.
|
|
554
|
+
Document entry — the file itself is the entry, readable at /wiki/<slug>:
|
|
555
|
+
llama wiki save <slug> --title "..." --file path.{pdf,docx,xlsx} --sources "..." [--doc-kind ...]
|
|
556
|
+
PDF opens in the browser's viewer (pages, search, zoom); DOCX and XLSX are converted for reading,
|
|
557
|
+
a spreadsheet keeping one tab per sheet. The original stays downloadable from the page either way.
|
|
558
|
+
Upload the document you have — don't transcribe it into markdown first.
|
|
555
559
|
➜ Use Wiki when the artifact is NOT tied to one specific deal — sector landscape, market map,
|
|
556
560
|
thesis, framework, methodology. For deal-specific HTML use "llama html publish <deal>" instead.
|
|
557
561
|
Delete / restore (soft — reversible):
|
|
558
562
|
llama wiki delete <slug> [--lang en|zh]
|
|
559
563
|
llama wiki restore <slug> [--lang en|zh]
|
|
560
564
|
|
|
561
|
-
Memo (
|
|
565
|
+
Memo (read-only; generation runs only from the Memo Agent in Llama Command):
|
|
562
566
|
llama memo show <dealId> [--out <path>] [--json] # default: html → stdout (pipeable to file / browser)
|
|
563
|
-
llama memo regenerate <dealId> [--opus] [--instructions "..."] # --instructions steers THIS run (e.g. "focus on team risk"); progress → stderr
|
|
564
|
-
llama memo save <dealId> --file <path> # paste a hand-written HTML as manual override
|
|
565
|
-
llama memo reset <dealId> [--all] # default drops manual override; --all drops every version
|
|
566
567
|
|
|
567
568
|
Deal page HTML (hand-authored sandboxed pages on /deals/<id>/browse/<slug>):
|
|
568
569
|
➜ Use this for DEAL-SPECIFIC artifacts: IC memo for X, dashboard for X, 2×2 for X.
|
|
@@ -1647,7 +1648,7 @@ async function main() {
|
|
|
1647
1648
|
throw new Error(
|
|
1648
1649
|
"Usage: llama deal enrich <dealId> [--dry-run] [--apply] " +
|
|
1649
1650
|
"[--executor server_agent|external_agent|planner] " +
|
|
1650
|
-
"[--sources website,github,linkedin,yc,monid] [--budget-cents 50] [--
|
|
1651
|
+
"[--sources website,github,linkedin,yc,monid] [--budget-cents 50] [--prompt]"
|
|
1651
1652
|
);
|
|
1652
1653
|
}
|
|
1653
1654
|
const { flags } = parseFlags(rest.slice(1), [
|
|
@@ -1656,9 +1657,6 @@ async function main() {
|
|
|
1656
1657
|
"executor",
|
|
1657
1658
|
"sources",
|
|
1658
1659
|
"budget-cents",
|
|
1659
|
-
"memo",
|
|
1660
|
-
"generate-memo",
|
|
1661
|
-
"generateMemo",
|
|
1662
1660
|
"prompt",
|
|
1663
1661
|
"handoff",
|
|
1664
1662
|
"harness-only",
|
|
@@ -1686,7 +1684,6 @@ async function main() {
|
|
|
1686
1684
|
executor,
|
|
1687
1685
|
sources,
|
|
1688
1686
|
budgetCents,
|
|
1689
|
-
generateMemo: boolFlag(flags, "memo", "generate-memo", "generateMemo"),
|
|
1690
1687
|
}
|
|
1691
1688
|
);
|
|
1692
1689
|
if (flags.prompt === true || flags.handoff === true) {
|
|
@@ -2123,9 +2120,13 @@ async function main() {
|
|
|
2123
2120
|
llama wiki save <slug> --title "..." --content "..." --sources "url1;url2" [--type company] [--related "A;B"] [--lang en|zh] [--content-type markdown|html]
|
|
2124
2121
|
or
|
|
2125
2122
|
llama wiki save <slug> --title "..." --file path/to/article.{md,html} --sources "url1;url2" [--type company] [--related "A;B"] [--lang en|zh] [--content-type markdown|html]
|
|
2123
|
+
or, to put a document itself on the wiki:
|
|
2124
|
+
llama wiki save <slug> --title "..." --file path/to/deck.{pdf,docx,xlsx} --sources "..." [--doc-kind ...]
|
|
2126
2125
|
|
|
2127
2126
|
Pass either --content (inline) or --file (read from disk). With --file, content_type auto-detects from extension (.html/.htm → html, else markdown). Use --content-type to override.
|
|
2128
2127
|
|
|
2128
|
+
A .pdf / .docx / .xlsx uploads as the entry itself: readers open the document at /wiki/<slug> — a PDF in the browser's viewer, a spreadsheet with one tab per sheet — and the original stays downloadable. --content-type does not apply there.
|
|
2129
|
+
|
|
2129
2130
|
Routing — is this the right command?
|
|
2130
2131
|
✓ Cross-deal / institutional knowledge (sector landscape, market map, thesis, framework, methodology)
|
|
2131
2132
|
→ YES, you're in the right place.
|
|
@@ -2139,6 +2140,58 @@ Routing — is this the right command?
|
|
|
2139
2140
|
if (inlineContent && filePath) {
|
|
2140
2141
|
throw new Error("Pass either --content OR --file, not both.");
|
|
2141
2142
|
}
|
|
2143
|
+
const splitCsvFlag = (v) => String(v).split(/[;|]/).map((s) => s.trim()).filter(Boolean);
|
|
2144
|
+
|
|
2145
|
+
// A document goes up as bytes, not as text. The server converts DOCX and
|
|
2146
|
+
// XLSX for the reader and keeps the original for download; a PDF opens in
|
|
2147
|
+
// the browser's own viewer. Everything else here stays the JSON path.
|
|
2148
|
+
const docExt = filePath
|
|
2149
|
+
? String(filePath).toLowerCase().match(/\.(pdf|docx|xlsx)$/)?.[1]
|
|
2150
|
+
: null;
|
|
2151
|
+
if (docExt) {
|
|
2152
|
+
if (flags["content-type"]) {
|
|
2153
|
+
throw new Error(
|
|
2154
|
+
`--content-type does not apply to a .${docExt}: the server decides how to render it from the file itself.`,
|
|
2155
|
+
);
|
|
2156
|
+
}
|
|
2157
|
+
const { readFileSync } = await import("fs");
|
|
2158
|
+
const { basename } = await import("path");
|
|
2159
|
+
const buf = readFileSync(String(filePath));
|
|
2160
|
+
const MAX = 50 * 1024 * 1024;
|
|
2161
|
+
if (buf.length > MAX) {
|
|
2162
|
+
throw new Error(
|
|
2163
|
+
`${basename(String(filePath))} is ${buf.length} bytes; the wiki caps files at ${MAX} (50MB). Link to the Drive copy instead.`,
|
|
2164
|
+
);
|
|
2165
|
+
}
|
|
2166
|
+
const mime = {
|
|
2167
|
+
pdf: "application/pdf",
|
|
2168
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
2169
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
2170
|
+
}[docExt];
|
|
2171
|
+
const form = new FormData();
|
|
2172
|
+
form.append("file", new Blob([buf], { type: mime }), basename(String(filePath)));
|
|
2173
|
+
form.append("lang", flags.lang === "zh" ? "zh" : "en");
|
|
2174
|
+
form.append("title", String(title));
|
|
2175
|
+
form.append("sources", splitCsvFlag(sourcesRaw).join(";"));
|
|
2176
|
+
if (flags.type) form.append("type", String(flags.type));
|
|
2177
|
+
if (flags["doc-kind"]) form.append("doc_kind", String(flags["doc-kind"]));
|
|
2178
|
+
|
|
2179
|
+
const headers = await getAuthHeaders();
|
|
2180
|
+
// @core-api-operation POST /api/wiki/{slug}/file
|
|
2181
|
+
const res = await fetch(
|
|
2182
|
+
`${getBaseUrl()}/api/wiki/${encodeURIComponent(slug)}/file`,
|
|
2183
|
+
{ method: "POST", headers, body: form },
|
|
2184
|
+
);
|
|
2185
|
+
const out = await res.json().catch(() => ({}));
|
|
2186
|
+
if (!res.ok) {
|
|
2187
|
+
throw new Error(
|
|
2188
|
+
`HTTP ${res.status}: ${out?.error || JSON.stringify(out).slice(0, 300)}`,
|
|
2189
|
+
);
|
|
2190
|
+
}
|
|
2191
|
+
print(out);
|
|
2192
|
+
return;
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2142
2195
|
// Read body — either inline or from file.
|
|
2143
2196
|
let body;
|
|
2144
2197
|
let inferredType = "markdown";
|
|
@@ -2512,13 +2565,9 @@ Routing — is this the right command?
|
|
|
2512
2565
|
throw new Error(`Unknown mentions subcommand "${sub}". Use: list / show / resolve / unread.`);
|
|
2513
2566
|
}
|
|
2514
2567
|
|
|
2515
|
-
// ----- Memo (
|
|
2516
|
-
//
|
|
2517
|
-
//
|
|
2518
|
-
// - composed: generated by the server-side memo composer on demand
|
|
2519
|
-
// - manual: a hand-written HTML you paste in
|
|
2520
|
-
// Manual always beats composed on read; reset to drop the manual row
|
|
2521
|
-
// and fall back to the composed one.
|
|
2568
|
+
// ----- Memo (read-only) -----
|
|
2569
|
+
// Generation is intentionally absent from CLI. The durable Memo Agent in
|
|
2570
|
+
// Llama Command owns the only generation path.
|
|
2522
2571
|
if (area === "memo") {
|
|
2523
2572
|
const sub = action;
|
|
2524
2573
|
|
|
@@ -2542,9 +2591,7 @@ Routing — is this the right command?
|
|
|
2542
2591
|
const html = data?.memo?.html;
|
|
2543
2592
|
if (!html) {
|
|
2544
2593
|
if (data?.requires_compose) {
|
|
2545
|
-
throw new Error(
|
|
2546
|
-
"No memo for this deal yet — run `llama memo regenerate <dealId>` to compose one."
|
|
2547
|
-
);
|
|
2594
|
+
throw new Error("No memo for this deal yet — generate it with the Memo Agent in Llama Command.");
|
|
2548
2595
|
}
|
|
2549
2596
|
throw new Error("Memo response missing html field.");
|
|
2550
2597
|
}
|
|
@@ -2560,152 +2607,8 @@ Routing — is this the right command?
|
|
|
2560
2607
|
return;
|
|
2561
2608
|
}
|
|
2562
2609
|
|
|
2563
|
-
// regenerate — kick off the server-side composer. Streams panel
|
|
2564
|
-
// progress events to stderr so you can see live status; prints
|
|
2565
|
-
// final summary JSON (version, model, duration) to stdout.
|
|
2566
|
-
if (sub === "regenerate") {
|
|
2567
|
-
const dealId = rest[0];
|
|
2568
|
-
if (!dealId) {
|
|
2569
|
-
throw new Error(
|
|
2570
|
-
'Usage: llama memo regenerate <dealId> [--opus] [--instructions "..."]'
|
|
2571
|
-
);
|
|
2572
|
-
}
|
|
2573
|
-
const { flags } = parseFlags(rest.slice(1));
|
|
2574
|
-
const tier = flags.opus ? "opus" : "sonnet";
|
|
2575
|
-
const authHeaders = await getAuthHeaders();
|
|
2576
|
-
if (Object.keys(authHeaders).length === 0) {
|
|
2577
|
-
throw new Error(
|
|
2578
|
-
"Not authenticated. Run `gcloud auth login` or `llama token set <llc_...>` first."
|
|
2579
|
-
);
|
|
2580
|
-
}
|
|
2581
|
-
const res = await fetch(
|
|
2582
|
-
`${getBaseUrl()}/api/deals/${encodeURIComponent(dealId)}/memo`,
|
|
2583
|
-
{
|
|
2584
|
-
method: "POST",
|
|
2585
|
-
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
2586
|
-
body: JSON.stringify({
|
|
2587
|
-
action: "regenerate",
|
|
2588
|
-
stream: true,
|
|
2589
|
-
model: tier,
|
|
2590
|
-
instructions: flags.instructions
|
|
2591
|
-
? String(flags.instructions)
|
|
2592
|
-
: undefined,
|
|
2593
|
-
}),
|
|
2594
|
-
}
|
|
2595
|
-
);
|
|
2596
|
-
if (!res.ok || !res.body) {
|
|
2597
|
-
const text = await res.text().catch(() => "");
|
|
2598
|
-
throw new Error(`HTTP ${res.status}: ${text.slice(0, 300)}`);
|
|
2599
|
-
}
|
|
2600
|
-
|
|
2601
|
-
const reader = res.body.getReader();
|
|
2602
|
-
const decoder = new TextDecoder();
|
|
2603
|
-
let buffer = "";
|
|
2604
|
-
let doneEvent = null;
|
|
2605
|
-
const startedAt = Date.now();
|
|
2606
|
-
const progress = { done: 0, total: 12, placeholders: 0, retries: 0 };
|
|
2607
|
-
|
|
2608
|
-
while (true) {
|
|
2609
|
-
const { value, done: streamDone } = await reader.read();
|
|
2610
|
-
if (streamDone) break;
|
|
2611
|
-
buffer += decoder.decode(value, { stream: true });
|
|
2612
|
-
let idx;
|
|
2613
|
-
while ((idx = buffer.indexOf("\n\n")) !== -1) {
|
|
2614
|
-
const frame = buffer.slice(0, idx);
|
|
2615
|
-
buffer = buffer.slice(idx + 2);
|
|
2616
|
-
const dataLine = frame.split("\n").find((l) => l.startsWith("data:"));
|
|
2617
|
-
if (!dataLine) continue;
|
|
2618
|
-
let event;
|
|
2619
|
-
try {
|
|
2620
|
-
event = JSON.parse(dataLine.replace(/^data:\s?/, ""));
|
|
2621
|
-
} catch {
|
|
2622
|
-
continue;
|
|
2623
|
-
}
|
|
2624
|
-
const elapsed = ((Date.now() - startedAt) / 1000).toFixed(1);
|
|
2625
|
-
const phase = event.phase || "?";
|
|
2626
|
-
if (phase === "panel_done") {
|
|
2627
|
-
progress.done = event.panels_completed ?? progress.done + 1;
|
|
2628
|
-
progress.total = event.panels_total ?? progress.total;
|
|
2629
|
-
if (event.status === "placeholder") progress.placeholders += 1;
|
|
2630
|
-
if (event.status === "retry-recovered") progress.retries += 1;
|
|
2631
|
-
const mark =
|
|
2632
|
-
event.status === "ok"
|
|
2633
|
-
? "✓"
|
|
2634
|
-
: event.status === "retry-recovered"
|
|
2635
|
-
? "↻"
|
|
2636
|
-
: "⚠";
|
|
2637
|
-
console.error(
|
|
2638
|
-
`${elapsed}s ${mark} ${event.panel} [${progress.done}/${progress.total}]`
|
|
2639
|
-
);
|
|
2640
|
-
} else if (phase === "anchor_done") {
|
|
2641
|
-
console.error(
|
|
2642
|
-
`${elapsed}s anchor → ${event.verdict_label || event.verdict}`
|
|
2643
|
-
);
|
|
2644
|
-
} else if (phase === "assembling") {
|
|
2645
|
-
console.error(`${elapsed}s assembling…`);
|
|
2646
|
-
} else if (phase === "done") {
|
|
2647
|
-
doneEvent = event;
|
|
2648
|
-
} else if (phase === "error") {
|
|
2649
|
-
throw new Error(`Memo composer error: ${event.error}`);
|
|
2650
|
-
}
|
|
2651
|
-
}
|
|
2652
|
-
}
|
|
2653
|
-
|
|
2654
|
-
if (!doneEvent) {
|
|
2655
|
-
throw new Error("Stream ended without 'done' event.");
|
|
2656
|
-
}
|
|
2657
|
-
print({
|
|
2658
|
-
ok: true,
|
|
2659
|
-
version: doneEvent.version,
|
|
2660
|
-
degraded: doneEvent.degraded,
|
|
2661
|
-
model: doneEvent.model,
|
|
2662
|
-
duration_ms: doneEvent.duration_ms,
|
|
2663
|
-
placeholders: progress.placeholders,
|
|
2664
|
-
retries: progress.retries,
|
|
2665
|
-
});
|
|
2666
|
-
return;
|
|
2667
|
-
}
|
|
2668
|
-
|
|
2669
|
-
// save — upload hand-written HTML as a manual override.
|
|
2670
|
-
if (sub === "save") {
|
|
2671
|
-
const { flags } = parseFlags(rest);
|
|
2672
|
-
const dealId = rest[0];
|
|
2673
|
-
if (!dealId || !flags.file) {
|
|
2674
|
-
throw new Error("Usage: llama memo save <dealId> --file <path>");
|
|
2675
|
-
}
|
|
2676
|
-
const { readFileSync } = await import("fs");
|
|
2677
|
-
const html = readFileSync(String(flags.file), "utf-8");
|
|
2678
|
-
if (!html.trim()) throw new Error(`File ${flags.file} is empty.`);
|
|
2679
|
-
print(
|
|
2680
|
-
await request(
|
|
2681
|
-
"PUT",
|
|
2682
|
-
`/api/deals/${encodeURIComponent(dealId)}/memo`,
|
|
2683
|
-
{ html }
|
|
2684
|
-
)
|
|
2685
|
-
);
|
|
2686
|
-
return;
|
|
2687
|
-
}
|
|
2688
|
-
|
|
2689
|
-
// reset — default drops only the manual override (next read returns
|
|
2690
|
-
// the composed row, if any); --all drops every version for this deal.
|
|
2691
|
-
if (sub === "reset") {
|
|
2692
|
-
const dealId = rest[0];
|
|
2693
|
-
if (!dealId) {
|
|
2694
|
-
throw new Error("Usage: llama memo reset <dealId> [--all]");
|
|
2695
|
-
}
|
|
2696
|
-
const { flags } = parseFlags(rest.slice(1));
|
|
2697
|
-
print(
|
|
2698
|
-
await request(
|
|
2699
|
-
"DELETE",
|
|
2700
|
-
`/api/deals/${encodeURIComponent(dealId)}/memo`,
|
|
2701
|
-
{ scope: flags.all ? "all" : "override_only" }
|
|
2702
|
-
)
|
|
2703
|
-
);
|
|
2704
|
-
return;
|
|
2705
|
-
}
|
|
2706
|
-
|
|
2707
2610
|
throw new Error(
|
|
2708
|
-
`Unknown memo subcommand "${sub || ""}". Use: show
|
|
2611
|
+
`Unknown memo subcommand "${sub || ""}". Use: show. Memo generation is available only in Llama Command.`
|
|
2709
2612
|
);
|
|
2710
2613
|
}
|
|
2711
2614
|
|
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": "3.
|
|
4
|
+
"apiVersion": "3.33.0",
|
|
5
5
|
"openapiVersion": "3.0.3",
|
|
6
|
-
"sha256": "
|
|
7
|
-
"pathCount":
|
|
8
|
-
"operationCount":
|
|
6
|
+
"sha256": "d673c2f38f63be2cd92415d9c384b40d115165ca4ba11bfb93ddaf4036226eed",
|
|
7
|
+
"pathCount": 238,
|
|
8
|
+
"operationCount": 312
|
|
9
9
|
}
|
|
@@ -86,14 +86,6 @@
|
|
|
86
86
|
"method": "GET",
|
|
87
87
|
"path": "/api/deals/{dealId}"
|
|
88
88
|
},
|
|
89
|
-
{
|
|
90
|
-
"method": "GET",
|
|
91
|
-
"path": "/api/deals/{dealId}/workflow"
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
"method": "POST",
|
|
95
|
-
"path": "/api/deals/{dealId}/workflow"
|
|
96
|
-
},
|
|
97
89
|
{
|
|
98
90
|
"method": "POST",
|
|
99
91
|
"path": "/api/deals/{dealId}/agent-runs/{runId}/revert"
|
|
@@ -234,22 +226,10 @@
|
|
|
234
226
|
"method": "POST",
|
|
235
227
|
"path": "/api/deals/{dealId}/links/{linkId}/restore"
|
|
236
228
|
},
|
|
237
|
-
{
|
|
238
|
-
"method": "DELETE",
|
|
239
|
-
"path": "/api/deals/{dealId}/memo"
|
|
240
|
-
},
|
|
241
229
|
{
|
|
242
230
|
"method": "GET",
|
|
243
231
|
"path": "/api/deals/{dealId}/memo"
|
|
244
232
|
},
|
|
245
|
-
{
|
|
246
|
-
"method": "POST",
|
|
247
|
-
"path": "/api/deals/{dealId}/memo"
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
"method": "PUT",
|
|
251
|
-
"path": "/api/deals/{dealId}/memo"
|
|
252
|
-
},
|
|
253
233
|
{
|
|
254
234
|
"method": "POST",
|
|
255
235
|
"path": "/api/deals/{dealId}/posts"
|
|
@@ -278,6 +258,14 @@
|
|
|
278
258
|
"method": "GET",
|
|
279
259
|
"path": "/api/deals/{dealId}/timeline"
|
|
280
260
|
},
|
|
261
|
+
{
|
|
262
|
+
"method": "GET",
|
|
263
|
+
"path": "/api/deals/{dealId}/workflow"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"method": "POST",
|
|
267
|
+
"path": "/api/deals/{dealId}/workflow"
|
|
268
|
+
},
|
|
281
269
|
{
|
|
282
270
|
"method": "POST",
|
|
283
271
|
"path": "/api/external/chat"
|
|
@@ -354,6 +342,10 @@
|
|
|
354
342
|
"method": "GET",
|
|
355
343
|
"path": "/api/wiki/{slug}"
|
|
356
344
|
},
|
|
345
|
+
{
|
|
346
|
+
"method": "POST",
|
|
347
|
+
"path": "/api/wiki/{slug}/file"
|
|
348
|
+
},
|
|
357
349
|
{
|
|
358
350
|
"method": "POST",
|
|
359
351
|
"path": "/api/wiki/{slug}/restore"
|
package/lib/build-manifest.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"format": "llama.cli-build.v1",
|
|
3
3
|
"packageName": "@llamaventures/cli",
|
|
4
|
-
"packageVersion": "1.
|
|
5
|
-
"sourceSha": "
|
|
4
|
+
"packageVersion": "1.26.0",
|
|
5
|
+
"sourceSha": "c330b8222f075478e50a96e160b647b09f535e3d",
|
|
6
6
|
"sourceKind": "github",
|
|
7
7
|
"sourceDirty": false,
|
|
8
8
|
"coreApiContract": {
|
|
9
9
|
"format": "llama.core-api-contract.v1",
|
|
10
10
|
"name": "llama-core-api",
|
|
11
|
-
"apiVersion": "3.
|
|
11
|
+
"apiVersion": "3.33.0",
|
|
12
12
|
"openapiVersion": "3.0.3",
|
|
13
|
-
"sha256": "
|
|
13
|
+
"sha256": "d673c2f38f63be2cd92415d9c384b40d115165ca4ba11bfb93ddaf4036226eed"
|
|
14
14
|
}
|
|
15
15
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llamaventures/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.0",
|
|
4
4
|
"description": "CLI + MCP server for the Llama Ventures investment workbench (command.llamaventures.vc).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "npm run test:agent-routing && npm run test:contract",
|
|
8
8
|
"test:agent-routing": "node scripts/verify-agent-routing.mjs",
|
|
9
|
-
"test:contract": "node --test scripts/build-manifest.test.mjs scripts/core-api-call-sites.test.mjs scripts/investment-workflow-contract.test.mjs scripts/server-compatibility.test.mjs scripts/verify-core-api-contract.test.mjs scripts/workflow-audit.test.mjs scripts/workflow-remediation.test.mjs && node scripts/verify-core-api-contract.mjs",
|
|
9
|
+
"test:contract": "node --test scripts/build-manifest.test.mjs scripts/core-api-call-sites.test.mjs scripts/investment-workflow-contract.test.mjs scripts/memo-retirement.test.mjs scripts/server-compatibility.test.mjs scripts/verify-core-api-contract.test.mjs scripts/workflow-audit.test.mjs scripts/workflow-remediation.test.mjs && node scripts/verify-core-api-contract.mjs",
|
|
10
10
|
"verify:artifact": "node scripts/verify-release-artifact.mjs",
|
|
11
11
|
"verify:release": "npm test && npm run verify:artifact && node scripts/verify-tarball-clean.mjs",
|
|
12
12
|
"prepack": "node scripts/prepare-build-manifest.mjs",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@modelcontextprotocol/sdk": "1.
|
|
59
|
+
"@modelcontextprotocol/sdk": "1.30.0",
|
|
60
60
|
"@napi-rs/keyring": "^1.3.0",
|
|
61
61
|
"zod": "^4.4.3"
|
|
62
62
|
}
|