@llamaventures/cli 1.18.0 → 1.19.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 +5 -4
- package/CHANGELOG.md +22 -1
- package/README.md +8 -1
- package/README.zh-CN.md +7 -1
- package/bin/llama-mcp.mjs +12 -5
- package/bin/llama.mjs +43 -11
- package/contracts/core-api.json +9 -0
- package/contracts/required-operations.json +91 -0
- package/lib/build-info.mjs +34 -0
- package/lib/build-manifest.json +15 -0
- package/lib/client.mjs +5 -0
- package/lib/oauth-flow.mjs +1 -0
- package/lib/version-check.mjs +1 -0
- package/package.json +8 -3
package/AGENT_BRIEFING.md
CHANGED
|
@@ -45,6 +45,7 @@ Any time the user mentions a company name or founder name:
|
|
|
45
45
|
- Use `--status Outreached` when we only contacted/logged the company and have no response or effective relationship yet.
|
|
46
46
|
- Use `--status Sourced` only once there is a response, intro, meeting, or another real relationship signal.
|
|
47
47
|
- Also set `--source-direction Inbound` if the deal came into the firm; set `--source-direction Outbound` if Llama found/listed/reached out first.
|
|
48
|
+
- If assigning an owner at create time, use `--deal-owner` with an exact `/api/field-options` value, email, or user id. Do not guess from a first name.
|
|
48
49
|
4. If user gives you new facts (status / valuation / founder note) → `llama deal update` immediately, tell the user **one line** afterward.
|
|
49
50
|
|
|
50
51
|
Don't:
|
|
@@ -62,7 +63,7 @@ A teammate says "I just met them and heard…" or pastes a chunk of notes. Your
|
|
|
62
63
|
|
|
63
64
|
1. **Find the deal** — `llama deal search "<name>"` (Pipeline First). New name → offer to create it.
|
|
64
65
|
2. **Split what they gave you into two kinds** — this is the whole data model:
|
|
65
|
-
- **Verifiable claims → facts.** `llama deal fact add <dealId> --category <cat> --claim "…" --source "<where it came from>"
|
|
66
|
+
- **Verifiable claims → facts.** `llama deal fact add <dealId> --category <cat> --claim "…" --source "<where it came from>" --source-url <url>`. A claim someone *relayed* ("their ARR is $3M", "raised from a16z") is a fact at **unverified** trust — it's hearsay until checked. Pass `--attested` ONLY if you actually verified it against a source yourself. In raw API terms, the fact text field is `claim` (`value` is only a compatibility alias), `source` is the human-readable provenance label, and `sourceUrl` is the canonical URL.
|
|
66
67
|
- **Their judgment / impression → a note.** `llama post <dealId> "…"`. "Founder seemed evasive", "I'd lean pass", "worth a second meeting" — opinion, not fact. Attributed, never "verified".
|
|
67
68
|
- A pasted blob → pull the verifiable claims out as facts, capture their take as a note.
|
|
68
69
|
3. **Read it back before you claim it's saved.** A tool call returning `{ok:true}` is NOT proof the content is where the user will look for it. After filing, run `llama deal feed <dealId>` and confirm your fact/note actually appears, THEN tell the user in plain language what you recorded and where. Never say "记好了 / saved" from the return value alone — the #1 failure is an agent writing to the wrong surface (e.g. the brief, which is the Memo and does NOT appear in the feed) and reporting success anyway. If it's not in the feed, you routed it wrong — fix it.
|
|
@@ -129,7 +130,7 @@ These three look similar but land in different surfaces. Don't infer from the co
|
|
|
129
130
|
|
|
130
131
|
| You want to… | Command | Lands in |
|
|
131
132
|
|---|---|---|
|
|
132
|
-
| Record a **sourced, verifiable fact** | `llama deal fact add <dealId> --category <cat> --claim "…" --source <url>` | Facts → deal **Feed** (FACT card) + citable in the **Memo** |
|
|
133
|
+
| Record a **sourced, verifiable fact** | `llama deal fact add <dealId> --category <cat> --claim "…" --source "deck p3" --source-url <url>` | Facts → deal **Feed** (FACT card) + citable in the **Memo** |
|
|
133
134
|
| Leave a **comment / opinion / question / reaction** for the team | `llama post <dealId> "…"` (`@name` to notify) | Posts → deal **Feed** (POST card); `@mention` fires email + UI badge |
|
|
134
135
|
| Write **narrative that belongs in the IC memo** | `llama brief add-text <dealId> --heading "…" --body "…"` | Brief blocks → **Memo tab only — NOT in the Feed** |
|
|
135
136
|
|
|
@@ -209,8 +210,8 @@ llama deal list [--owner ...] [--status ...]
|
|
|
209
210
|
|
|
210
211
|
# Pipeline — write
|
|
211
212
|
llama deal create "Company" --description "..." --source-direction Outbound --status Interested
|
|
212
|
-
llama deal create "Company" --description "..." --source-direction Outbound --status Outreached
|
|
213
|
-
llama deal create "Company" --description "..." --source-direction Inbound --status Sourced
|
|
213
|
+
llama deal create "Company" --description "..." --source-direction Outbound --status Outreached --deal-owner "owner@llamaventures.vc"
|
|
214
|
+
llama deal create "Company" --description "..." --source-direction Inbound --status Sourced --deal-owner "Exact Name"
|
|
214
215
|
llama deal update <dealId> <field> <value>
|
|
215
216
|
# writable: status theirStage stage notes dealOwner source sourceDirection description website
|
|
216
217
|
# location founders proposedAmount roundSize valuation sector subsector
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,26 @@ this project adheres to [Semantic Versioning](https://semver.org).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.19.0] - 2026-07-16
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- Pin each CLI artifact to the exact versioned Llama Core OpenAPI contract,
|
|
13
|
+
source commit, and complete source-derived operation inventory.
|
|
14
|
+
- Verify the contract identity and required Core operations during tests,
|
|
15
|
+
packaging, clean tarball installation, and release-gate validation.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Treat Core HTTP as the CLI's only backend boundary and expose contract/build
|
|
19
|
+
provenance through `llama version --json` for independent rollback audits.
|
|
20
|
+
|
|
21
|
+
## [1.18.1] - 2026-07-09
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- Clarified the Command facts write contract across CLI, MCP, and agent docs:
|
|
25
|
+
`claim` is canonical, `value` remains a compatibility alias, `sourceUrl`
|
|
26
|
+
round-trips as provenance, and categories are free text. `deal create` now
|
|
27
|
+
forwards `--deal-owner` using name, email, or user id.
|
|
28
|
+
|
|
9
29
|
## [1.18.0] - 2026-07-06
|
|
10
30
|
|
|
11
31
|
### Added
|
|
@@ -500,7 +520,8 @@ assistant-drafted (🤖) and enforces the AI trust ceiling.
|
|
|
500
520
|
|
|
501
521
|
---
|
|
502
522
|
|
|
503
|
-
[Unreleased]: https://github.com/Llama-Ventures/llama-cli/compare/v1.18.
|
|
523
|
+
[Unreleased]: https://github.com/Llama-Ventures/llama-cli/compare/v1.18.1...HEAD
|
|
524
|
+
[1.18.1]: https://github.com/Llama-Ventures/llama-cli/compare/v1.18.0...v1.18.1
|
|
504
525
|
[1.18.0]: https://github.com/Llama-Ventures/llama-cli/compare/v1.17.3...v1.18.0
|
|
505
526
|
[1.17.3]: https://github.com/Llama-Ventures/llama-cli/compare/v1.17.2...v1.17.3
|
|
506
527
|
[1.17.2]: https://github.com/Llama-Ventures/llama-cli/compare/v1.17.1...v1.17.2
|
package/README.md
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
```bash
|
|
43
43
|
npm i -g @llamaventures/cli # Node 18+; also puts `llama-mcp` on your PATH
|
|
44
44
|
llama --version
|
|
45
|
+
llama version --json # package, source commit, and pinned Core API contract
|
|
45
46
|
llama auth status # round-trips against /api/me
|
|
46
47
|
```
|
|
47
48
|
|
|
@@ -96,7 +97,8 @@ llama deal show <dealId>
|
|
|
96
97
|
llama deal feed <dealId> # every contribution, newest first
|
|
97
98
|
llama activity new-deals --since 24h # recent deal creations
|
|
98
99
|
llama activity updated-deals --since 7d # meaningful updates grouped by deal
|
|
99
|
-
llama deal create "Acme AI" --source alex --source-direction Outbound --status Interested
|
|
100
|
+
llama deal create "Acme AI" --source alex --deal-owner owner@llamaventures.vc --source-direction Outbound --status Interested
|
|
101
|
+
llama deal fact add <dealId> --category funding --claim "Raised a seed round" --source "deck p3" --source-url https://...
|
|
100
102
|
llama deal update <dealId> status Diligence
|
|
101
103
|
llama post <dealId> "note body"
|
|
102
104
|
llama brief add-text <dealId> --heading "..." --body "..."
|
|
@@ -111,6 +113,11 @@ Status vocabulary — `Interested`: tracked before any contact ·
|
|
|
111
113
|
signal exists. `sourceDirection` is separate: `Inbound` came to the firm,
|
|
112
114
|
`Outbound` we reached out first.
|
|
113
115
|
|
|
116
|
+
Facts use `claim` for the fact text. `source` is a readable provenance label
|
|
117
|
+
and `sourceUrl` is the canonical evidence URL; both round-trip from the API.
|
|
118
|
+
For deal owners, use an exact `/api/field-options` `dealOwner` value, a user
|
|
119
|
+
email, or a numeric user id.
|
|
120
|
+
|
|
114
121
|
Run `llama --help` for the group index, `llama help all` for the full
|
|
115
122
|
reference (100+ commands). Deletes are soft and audit-logged everywhere.
|
|
116
123
|
|
package/README.zh-CN.md
CHANGED
|
@@ -67,6 +67,7 @@ Pitch 完成后档案自动进我们团队的 inbox,我们会主动联系你
|
|
|
67
67
|
```bash
|
|
68
68
|
npm i -g @llamaventures/cli # Node 18+;llama-mcp 也会一起装上 PATH
|
|
69
69
|
llama --version
|
|
70
|
+
llama version --json # 包版本、源码 commit 与固定的 Core API 契约
|
|
70
71
|
llama auth status # 会跑一次 /api/me 验证
|
|
71
72
|
```
|
|
72
73
|
|
|
@@ -118,7 +119,8 @@ llama deal show <dealId>
|
|
|
118
119
|
llama deal feed <dealId> # 该 deal 的全部贡献,最新在前
|
|
119
120
|
llama activity new-deals --since 24h # 最近新建的 deal
|
|
120
121
|
llama activity updated-deals --since 7d # 按 deal 聚合的实质更新
|
|
121
|
-
llama deal create "Acme AI" --source alex --source-direction Outbound --status Interested
|
|
122
|
+
llama deal create "Acme AI" --source alex --deal-owner owner@llamaventures.vc --source-direction Outbound --status Interested
|
|
123
|
+
llama deal fact add <dealId> --category funding --claim "Raised a seed round" --source "deck p3" --source-url https://...
|
|
122
124
|
llama deal update <dealId> status Diligence
|
|
123
125
|
llama post <dealId> "备注内容"
|
|
124
126
|
llama brief add-text <dealId> --heading "..." --body "..."
|
|
@@ -132,6 +134,10 @@ Status 语义——`Interested`:接触前先记录关注 · `Outreached`:已
|
|
|
132
134
|
尚无回应 · `Sourced`:已有真实关系信号。`sourceDirection` 是独立维度:
|
|
133
135
|
`Inbound` 流入,`Outbound` 我们主动。
|
|
134
136
|
|
|
137
|
+
Facts 的正文用 `claim`。`source` 是人可读来源标签,`sourceUrl` 是 canonical
|
|
138
|
+
证据 URL;两者都会从 API 回显。`dealOwner` 请用 `/api/field-options`
|
|
139
|
+
里的精确 `dealOwner` 值、用户邮箱,或数字 user id。
|
|
140
|
+
|
|
135
141
|
`llama --help` 看分组索引,`llama help all` 看全部 100+ 命令。
|
|
136
142
|
所有删除默认软删除、有审计记录。
|
|
137
143
|
|
package/bin/llama-mcp.mjs
CHANGED
|
@@ -471,7 +471,11 @@ server.registerTool(
|
|
|
471
471
|
.describe(
|
|
472
472
|
"Our Stage workflow position. Use Interested when we want to record/track before contact; use Outreached when we contacted/logged them and have no response/effective relationship; use Sourced only once there is a response, intro, meeting, or other real relationship signal."
|
|
473
473
|
),
|
|
474
|
-
source: z.string().optional().describe("free-form sourced-by;
|
|
474
|
+
source: z.string().optional().describe("free-form sourced-by; exact team-member names also attach source_user_id"),
|
|
475
|
+
dealOwner: z
|
|
476
|
+
.string()
|
|
477
|
+
.optional()
|
|
478
|
+
.describe("owner override. Use an exact /api/field-options dealOwner value, a user email, or numeric user id."),
|
|
475
479
|
sourceDirection: z
|
|
476
480
|
.string()
|
|
477
481
|
.optional()
|
|
@@ -510,7 +514,7 @@ server.registerTool(
|
|
|
510
514
|
{
|
|
511
515
|
description:
|
|
512
516
|
"List a deal's recorded facts (the research substrate). Each fact carries a " +
|
|
513
|
-
"category, a claim, a source, a confidence, and a trust rung (unverified → " +
|
|
517
|
+
"category, a claim, a source/sourceUrl, a confidence, and a trust rung (unverified → " +
|
|
514
518
|
"agent-verified → human-vouched → endorsed) plus who/what recorded it.",
|
|
515
519
|
inputSchema: {
|
|
516
520
|
dealId: z.string(),
|
|
@@ -530,13 +534,15 @@ server.registerTool(
|
|
|
530
534
|
"something unconfirmed (stored 'unverified', which is the honest default). You CANNOT " +
|
|
531
535
|
"mark a fact as human-confirmed — only a person can raise it to 'human-vouched'. " +
|
|
532
536
|
"`confidence` is how certain the claim is; `attested` is whether YOU take responsibility " +
|
|
533
|
-
"for having checked it.
|
|
534
|
-
"
|
|
537
|
+
"for having checked it. `source` is a human-readable provenance label; `sourceUrl` is a " +
|
|
538
|
+
"canonical URL that round-trips as sourceUrl/source_url. Category is free text; common " +
|
|
539
|
+
"values include founders | financials | product | market | team | company_basics | risk | fundraise | milestone | meta.",
|
|
535
540
|
inputSchema: {
|
|
536
541
|
dealId: z.string(),
|
|
537
542
|
category: z.string(),
|
|
538
543
|
claim: z.string(),
|
|
539
544
|
source: z.string().optional().describe("where you found this (URL, 'deck p3', 'LinkedIn')"),
|
|
545
|
+
sourceUrl: z.string().optional().describe("canonical URL for the evidence, if separate from source"),
|
|
540
546
|
confidence: z.enum(["high", "medium", "low"]).optional(),
|
|
541
547
|
attested: z
|
|
542
548
|
.boolean()
|
|
@@ -544,11 +550,12 @@ server.registerTool(
|
|
|
544
550
|
.describe("true → stored 'agent-verified'; false/omitted → 'unverified'. Answer honestly."),
|
|
545
551
|
},
|
|
546
552
|
},
|
|
547
|
-
async ({ dealId, category, claim, source, confidence, attested }) =>
|
|
553
|
+
async ({ dealId, category, claim, source, sourceUrl, confidence, attested }) =>
|
|
548
554
|
callApi("POST", `/api/deals/${encodeURIComponent(dealId)}/facts`, {
|
|
549
555
|
category,
|
|
550
556
|
claim,
|
|
551
557
|
source: source ?? "",
|
|
558
|
+
...(sourceUrl ? { sourceUrl } : {}),
|
|
552
559
|
confidence: confidence ?? "medium",
|
|
553
560
|
attested: attested === true,
|
|
554
561
|
})
|
package/bin/llama.mjs
CHANGED
|
@@ -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");
|
|
@@ -424,7 +425,8 @@ auto-detects \`gcloud auth print-identity-token\` and uses Bearer auth.
|
|
|
424
425
|
Manually-set \`llc_\` tokens are used as a fallback.
|
|
425
426
|
|
|
426
427
|
Deals:
|
|
427
|
-
llama deal create "Company" --source <name> --source-direction Inbound|Outbound --description "..." --status Interested|Outreached|Sourced --website https://...
|
|
428
|
+
llama deal create "Company" --source <name> --deal-owner <name|email|userId> --source-direction Inbound|Outbound --description "..." --status Interested|Outreached|Sourced --website https://...
|
|
429
|
+
llama deal founders set <dealId> --json '[{"name":"Ada","email":"ada@example.com","linkedin_url":"https://linkedin.com/in/ada"}]'
|
|
428
430
|
llama deal show <dealId>
|
|
429
431
|
llama deal feed <dealId> # every contribution (facts + notes), human-typed or assistant-drafted, newest first
|
|
430
432
|
llama deal update <dealId> <field> <value>
|
|
@@ -534,8 +536,8 @@ Deal soft-delete / restore / trash list:
|
|
|
534
536
|
llama deal trash # list deleted deals
|
|
535
537
|
|
|
536
538
|
Deal facts (AI-extracted or human-asserted, with verification):
|
|
537
|
-
llama deal fact list <dealId>
|
|
538
|
-
llama deal fact add <dealId> --category <cat> --claim "<text>" [--source <url>] [--confidence high|medium|low] [--attested]
|
|
539
|
+
llama deal fact list <dealId>
|
|
540
|
+
llama deal fact add <dealId> --category <cat> --claim "<text>" [--source "..."] [--source-url <url>] [--confidence high|medium|low] [--attested]
|
|
539
541
|
llama deal fact verify <dealId> <factId> --status confirmed|disputed [--corrected-value "..."]
|
|
540
542
|
|
|
541
543
|
Skill corrections (persona-owner pushback — read by persona-watcher):
|
|
@@ -1005,6 +1007,10 @@ async function runPitchRepl() {
|
|
|
1005
1007
|
async function main() {
|
|
1006
1008
|
const [area, action, ...rest] = process.argv.slice(2);
|
|
1007
1009
|
if (area === "--version" || area === "-v" || area === "version") {
|
|
1010
|
+
if (action === "--json" || action === "json") {
|
|
1011
|
+
print(getBuildInfo());
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1008
1014
|
// `llama version --check` — explicitly check npm for a newer release and
|
|
1009
1015
|
// print the upgrade line (or "up to date"). Lets an agent surface the
|
|
1010
1016
|
// nudge on demand, separate from the throttled, TTY-gated auto-nudge.
|
|
@@ -1440,10 +1446,11 @@ async function main() {
|
|
|
1440
1446
|
if (area === "deal" && action === "create") {
|
|
1441
1447
|
const { flags, positional } = parseFlags(rest);
|
|
1442
1448
|
const companyName = positional.join(" ").trim();
|
|
1443
|
-
if (!companyName) throw new Error("Usage: llama deal create \"Company\" [--source Name]");
|
|
1449
|
+
if (!companyName) throw new Error("Usage: llama deal create \"Company\" [--source Name] [--deal-owner name|email|userId]");
|
|
1444
1450
|
const body = {
|
|
1445
1451
|
companyName,
|
|
1446
1452
|
source: flags.source,
|
|
1453
|
+
dealOwner: flags.dealOwner || flags["deal-owner"],
|
|
1447
1454
|
sourceDirection: flags.sourceDirection || flags["source-direction"],
|
|
1448
1455
|
description: flags.description,
|
|
1449
1456
|
website: flags.website,
|
|
@@ -1483,6 +1490,26 @@ async function main() {
|
|
|
1483
1490
|
return;
|
|
1484
1491
|
}
|
|
1485
1492
|
|
|
1493
|
+
if (area === "deal" && action === "founders") {
|
|
1494
|
+
const sub = rest[0];
|
|
1495
|
+
const dealId = rest[1];
|
|
1496
|
+
const { flags } = parseFlags(rest.slice(2), ["json"]);
|
|
1497
|
+
if (sub !== "set" || !dealId || typeof flags.json !== "string") {
|
|
1498
|
+
throw new Error(
|
|
1499
|
+
"Usage: llama deal founders set <dealId> --json '[{\"name\":\"Ada\",\"email\":\"ada@example.com\"}]'"
|
|
1500
|
+
);
|
|
1501
|
+
}
|
|
1502
|
+
let founders;
|
|
1503
|
+
try {
|
|
1504
|
+
founders = JSON.parse(flags.json);
|
|
1505
|
+
} catch {
|
|
1506
|
+
throw new Error("--json must be a valid JSON array");
|
|
1507
|
+
}
|
|
1508
|
+
if (!Array.isArray(founders)) throw new Error("--json must be a JSON array");
|
|
1509
|
+
print(await request("PUT", `/api/deals/${encodeURIComponent(dealId)}/founders`, { founders }));
|
|
1510
|
+
return;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1486
1513
|
// ----- deals.extra JSONB patches (system-admin only, server-gated) -----
|
|
1487
1514
|
// Same endpoint as `deal update`, but `extraKey` instead of `field`.
|
|
1488
1515
|
// Server patches one top-level key via jsonb_set and audits the change
|
|
@@ -1699,6 +1726,8 @@ async function main() {
|
|
|
1699
1726
|
const linkId = rest[2];
|
|
1700
1727
|
if (!linkId) throw new Error(`Usage: llama deal link ${sub} <dealId> <linkId>`);
|
|
1701
1728
|
const path = `/api/deals/${encodeURIComponent(dealId)}/links/${encodeURIComponent(linkId)}`;
|
|
1729
|
+
// @core-api-operation DELETE /api/deals/{dealId}/links/{linkId}
|
|
1730
|
+
// @core-api-operation POST /api/deals/{dealId}/links/{linkId}/restore
|
|
1702
1731
|
print(await request(
|
|
1703
1732
|
sub === "delete" ? "DELETE" : "POST",
|
|
1704
1733
|
sub === "delete" ? path : `${path}/restore`
|
|
@@ -1735,10 +1764,6 @@ async function main() {
|
|
|
1735
1764
|
}
|
|
1736
1765
|
|
|
1737
1766
|
// ----- Deal facts (AI-extracted or human-asserted, with verification) -----
|
|
1738
|
-
// NOTE: server routes currently use session-only auth() — token-only
|
|
1739
|
-
// callers will get 401 until /api/deals/:id/facts and
|
|
1740
|
-
// /api/deals/:id/facts/:factId switch to authenticate(). CLI surface
|
|
1741
|
-
// is forward-compatible.
|
|
1742
1767
|
if (area === "deal" && action === "fact") {
|
|
1743
1768
|
const sub = rest[0];
|
|
1744
1769
|
const dealId = rest[1];
|
|
@@ -1754,10 +1779,12 @@ async function main() {
|
|
|
1754
1779
|
}
|
|
1755
1780
|
|
|
1756
1781
|
if (sub === "add") {
|
|
1757
|
-
|
|
1782
|
+
const claim = flags.claim ?? flags.value;
|
|
1783
|
+
const sourceUrl = flags["source-url"] ?? flags.sourceUrl;
|
|
1784
|
+
if (!flags.category || !claim) {
|
|
1758
1785
|
throw new Error(
|
|
1759
1786
|
`Usage: llama deal fact add <dealId> --category <cat> --claim "<text>" ` +
|
|
1760
|
-
`[--source <url>] [--confidence high|medium|low] [--attested]`
|
|
1787
|
+
`[--source "..."] [--source-url <url>] [--confidence high|medium|low] [--attested]`
|
|
1761
1788
|
);
|
|
1762
1789
|
}
|
|
1763
1790
|
// --attested: the caller takes responsibility that this is accurate
|
|
@@ -1765,8 +1792,9 @@ async function main() {
|
|
|
1765
1792
|
// vouched; without it, it stays unverified. Declare honestly.
|
|
1766
1793
|
print(await request("POST", `/api/deals/${encodeURIComponent(dealId)}/facts`, {
|
|
1767
1794
|
category: String(flags.category),
|
|
1768
|
-
claim: String(
|
|
1795
|
+
claim: String(claim),
|
|
1769
1796
|
source: flags.source ? String(flags.source) : "",
|
|
1797
|
+
...(sourceUrl ? { sourceUrl: String(sourceUrl) } : {}),
|
|
1770
1798
|
confidence: flags.confidence ? String(flags.confidence) : "medium",
|
|
1771
1799
|
attested: flags.attested === true,
|
|
1772
1800
|
}));
|
|
@@ -1967,6 +1995,7 @@ async function main() {
|
|
|
1967
1995
|
if (!slug) throw new Error("Usage: llama wiki read <slug> [--lang en|zh]");
|
|
1968
1996
|
const lang = flags.lang === "zh" ? "zh" : "en";
|
|
1969
1997
|
const path = `/api/wiki/${encodeURIComponent(slug)}?lang=${lang}`;
|
|
1998
|
+
// @core-api-operation GET /api/wiki/{slug}
|
|
1970
1999
|
print(await request("GET", path));
|
|
1971
2000
|
return;
|
|
1972
2001
|
}
|
|
@@ -2298,6 +2327,9 @@ Routing — is this the right command?
|
|
|
2298
2327
|
if (flags["errors-only"]) params.set("errors_only", "1");
|
|
2299
2328
|
}
|
|
2300
2329
|
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
2330
|
+
// @core-api-operation GET /api/admin/auth-events
|
|
2331
|
+
// @core-api-operation GET /api/admin/deal-events
|
|
2332
|
+
// @core-api-operation GET /api/admin/agent-events
|
|
2301
2333
|
print(await request("GET", `/api/admin/${sub}${qs}`));
|
|
2302
2334
|
return;
|
|
2303
2335
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "llama.cli-core-api-operations.v1",
|
|
3
|
+
"coreApiContract": "contracts/core-api.json",
|
|
4
|
+
"requiredOperations": [
|
|
5
|
+
{ "method": "DELETE", "path": "/api/deals/{dealId}" },
|
|
6
|
+
{ "method": "DELETE", "path": "/api/deals/{dealId}/blocks/{blockId}" },
|
|
7
|
+
{ "method": "DELETE", "path": "/api/deals/{dealId}/collaborators/{userId}" },
|
|
8
|
+
{ "method": "DELETE", "path": "/api/deals/{dealId}/documents/{slug}" },
|
|
9
|
+
{ "method": "DELETE", "path": "/api/deals/{dealId}/documents/{slug}/html" },
|
|
10
|
+
{ "method": "DELETE", "path": "/api/deals/{dealId}/links/{linkId}" },
|
|
11
|
+
{ "method": "DELETE", "path": "/api/deals/{dealId}/memo" },
|
|
12
|
+
{ "method": "DELETE", "path": "/api/skill-corrections/{id}" },
|
|
13
|
+
{ "method": "DELETE", "path": "/api/wiki/{slug}" },
|
|
14
|
+
{ "method": "GET", "path": "/api/admin/agent-events" },
|
|
15
|
+
{ "method": "GET", "path": "/api/admin/auth-events" },
|
|
16
|
+
{ "method": "GET", "path": "/api/admin/deal-events" },
|
|
17
|
+
{ "method": "GET", "path": "/api/agent/activity" },
|
|
18
|
+
{ "method": "GET", "path": "/api/agent/briefing" },
|
|
19
|
+
{ "method": "GET", "path": "/api/agent/explain" },
|
|
20
|
+
{ "method": "GET", "path": "/api/agent/manifest" },
|
|
21
|
+
{ "method": "GET", "path": "/api/agent/skills" },
|
|
22
|
+
{ "method": "GET", "path": "/api/agent/skills/{slug}" },
|
|
23
|
+
{ "method": "GET", "path": "/api/deals" },
|
|
24
|
+
{ "method": "GET", "path": "/api/deals/{dealId}" },
|
|
25
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/blocks" },
|
|
26
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/blocks/{blockId}" },
|
|
27
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/blocks/{blockId}/history" },
|
|
28
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/collaborators" },
|
|
29
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/command-center" },
|
|
30
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/documents" },
|
|
31
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/documents/{slug}/html" },
|
|
32
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/documents/{slug}/html/history" },
|
|
33
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/facts" },
|
|
34
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/feed" },
|
|
35
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/links" },
|
|
36
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/memo" },
|
|
37
|
+
{ "method": "GET", "path": "/api/deals/{dealId}/timeline" },
|
|
38
|
+
{ "method": "GET", "path": "/api/deals/deleted" },
|
|
39
|
+
{ "method": "GET", "path": "/api/me" },
|
|
40
|
+
{ "method": "GET", "path": "/api/me/nominations" },
|
|
41
|
+
{ "method": "GET", "path": "/api/mentions" },
|
|
42
|
+
{ "method": "GET", "path": "/api/mentions/unread-count" },
|
|
43
|
+
{ "method": "GET", "path": "/api/oauth/authorize" },
|
|
44
|
+
{ "method": "GET", "path": "/api/partner/approvals" },
|
|
45
|
+
{ "method": "GET", "path": "/api/skill-corrections" },
|
|
46
|
+
{ "method": "GET", "path": "/api/users" },
|
|
47
|
+
{ "method": "GET", "path": "/api/wiki/{slug}" },
|
|
48
|
+
{ "method": "GET", "path": "/api/wiki/search" },
|
|
49
|
+
{ "method": "PATCH", "path": "/api/deals/{dealId}/blocks/{blockId}" },
|
|
50
|
+
{ "method": "PATCH", "path": "/api/deals/{dealId}/documents/{slug}" },
|
|
51
|
+
{ "method": "PATCH", "path": "/api/deals/{dealId}/facts/{factId}" },
|
|
52
|
+
{ "method": "POST", "path": "/api/agent/client-events" },
|
|
53
|
+
{ "method": "POST", "path": "/api/agent/eval-feedback" },
|
|
54
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/agent-runs/{runId}/revert" },
|
|
55
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/blocks/{blockId}/history" },
|
|
56
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/blocks/{blockId}/restore" },
|
|
57
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/collaborators" },
|
|
58
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/collaborators/{userId}/restore" },
|
|
59
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/documents" },
|
|
60
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/documents/{slug}/html/restore/{version}" },
|
|
61
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/enrich" },
|
|
62
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/facts" },
|
|
63
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/links" },
|
|
64
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/links/{linkId}/restore" },
|
|
65
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/memo" },
|
|
66
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/posts" },
|
|
67
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/propose-owner" },
|
|
68
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/refresh-brief" },
|
|
69
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/refresh-persona" },
|
|
70
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/restore" },
|
|
71
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/threads" },
|
|
72
|
+
{ "method": "POST", "path": "/api/deals/{dealId}/threads/{threadId}" },
|
|
73
|
+
{ "method": "POST", "path": "/api/deals/create" },
|
|
74
|
+
{ "method": "POST", "path": "/api/deals/update" },
|
|
75
|
+
{ "method": "POST", "path": "/api/external/chat" },
|
|
76
|
+
{ "method": "POST", "path": "/api/external/start-session" },
|
|
77
|
+
{ "method": "POST", "path": "/api/external/upload" },
|
|
78
|
+
{ "method": "POST", "path": "/api/mentions/{id}/resolve" },
|
|
79
|
+
{ "method": "POST", "path": "/api/nominations/{approvalId}" },
|
|
80
|
+
{ "method": "POST", "path": "/api/oauth/revoke" },
|
|
81
|
+
{ "method": "POST", "path": "/api/oauth/token" },
|
|
82
|
+
{ "method": "POST", "path": "/api/partner/approvals" },
|
|
83
|
+
{ "method": "POST", "path": "/api/skill-corrections" },
|
|
84
|
+
{ "method": "POST", "path": "/api/wiki/{slug}/restore" },
|
|
85
|
+
{ "method": "POST", "path": "/api/wiki/save" },
|
|
86
|
+
{ "method": "PUT", "path": "/api/deals/{dealId}/blocks" },
|
|
87
|
+
{ "method": "PUT", "path": "/api/deals/{dealId}/documents/{slug}/html" },
|
|
88
|
+
{ "method": "PUT", "path": "/api/deals/{dealId}/founders" },
|
|
89
|
+
{ "method": "PUT", "path": "/api/deals/{dealId}/memo" }
|
|
90
|
+
]
|
|
91
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
4
|
+
|
|
5
|
+
function readJson(relativePath) {
|
|
6
|
+
try {
|
|
7
|
+
return requireFromHere(relativePath);
|
|
8
|
+
} catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function getBuildInfo() {
|
|
14
|
+
const built = readJson("./build-manifest.json");
|
|
15
|
+
if (built) return built;
|
|
16
|
+
|
|
17
|
+
const packageJson = readJson("../package.json") || {};
|
|
18
|
+
const contract = readJson("../contracts/core-api.json") || {};
|
|
19
|
+
return {
|
|
20
|
+
format: "llama.cli-build.v1",
|
|
21
|
+
packageName: packageJson.name || "@llamaventures/cli",
|
|
22
|
+
packageVersion: packageJson.version || "unknown",
|
|
23
|
+
sourceSha: "local/unknown",
|
|
24
|
+
sourceKind: "local",
|
|
25
|
+
sourceDirty: null,
|
|
26
|
+
coreApiContract: {
|
|
27
|
+
format: contract.format || "unknown",
|
|
28
|
+
name: contract.name || "llama-core-api",
|
|
29
|
+
apiVersion: contract.apiVersion || "unknown",
|
|
30
|
+
openapiVersion: contract.openapiVersion || "unknown",
|
|
31
|
+
sha256: contract.sha256 || "unknown",
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "llama.cli-build.v1",
|
|
3
|
+
"packageName": "@llamaventures/cli",
|
|
4
|
+
"packageVersion": "1.19.0",
|
|
5
|
+
"sourceSha": "5f615ca16d607fc0da09887952afdf42301a43f8",
|
|
6
|
+
"sourceKind": "github",
|
|
7
|
+
"sourceDirty": false,
|
|
8
|
+
"coreApiContract": {
|
|
9
|
+
"format": "llama.core-api-contract.v1",
|
|
10
|
+
"name": "llama-core-api",
|
|
11
|
+
"apiVersion": "1.0.1",
|
|
12
|
+
"openapiVersion": "3.0.3",
|
|
13
|
+
"sha256": "95ce3639aeee15b0fed09830116838f2a11fd2e40e4f35bf80d785664ecf8d96"
|
|
14
|
+
}
|
|
15
|
+
}
|
package/lib/client.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import { fileURLToPath } from "url";
|
|
|
14
14
|
import { execFile as _execFile } from "child_process";
|
|
15
15
|
import { promisify } from "util";
|
|
16
16
|
import { createHash, randomUUID } from "crypto";
|
|
17
|
+
import { getBuildInfo } from "./build-info.mjs";
|
|
17
18
|
|
|
18
19
|
const execFile = promisify(_execFile);
|
|
19
20
|
|
|
@@ -207,9 +208,13 @@ function rememberAgentEvent(event) {
|
|
|
207
208
|
}
|
|
208
209
|
|
|
209
210
|
function agentClientHeaders(command) {
|
|
211
|
+
const build = getBuildInfo();
|
|
210
212
|
return {
|
|
211
213
|
"X-Llama-Client": runtimeClient,
|
|
212
214
|
"X-Llama-Client-Version": getPackageVersion(),
|
|
215
|
+
"X-Llama-Client-Source-Sha": build.sourceSha,
|
|
216
|
+
"X-Llama-API-Contract-Version": build.coreApiContract.apiVersion,
|
|
217
|
+
"X-Llama-API-Contract-Digest": build.coreApiContract.sha256,
|
|
213
218
|
"X-Llama-Agent-Client": detectAgentClient(),
|
|
214
219
|
"X-Llama-Agent-Session": currentAgentSessionId(),
|
|
215
220
|
"X-Llama-Command": command || "unknown",
|
package/lib/oauth-flow.mjs
CHANGED
|
@@ -173,6 +173,7 @@ export async function pkceLoopbackFlow({ baseUrl, scope, resource }) {
|
|
|
173
173
|
});
|
|
174
174
|
|
|
175
175
|
// Build authorize URL and open browser.
|
|
176
|
+
// @core-api-operation GET /api/oauth/authorize
|
|
176
177
|
const authorizeUrl = new URL(`${baseUrl}/api/oauth/authorize`);
|
|
177
178
|
authorizeUrl.searchParams.set("response_type", "code");
|
|
178
179
|
authorizeUrl.searchParams.set("client_id", CLIENT_ID);
|
package/lib/version-check.mjs
CHANGED
|
@@ -73,6 +73,7 @@ async function fetchLatest() {
|
|
|
73
73
|
// The /latest convenience endpoint returns full JSON under the default
|
|
74
74
|
// Accept. (The abbreviated "vnd.npm.install-v1+json" metadata type is only
|
|
75
75
|
// valid on the full packument endpoint — it 406s here.)
|
|
76
|
+
// @core-api-ignore external npm registry version check
|
|
76
77
|
const res = await fetch(REGISTRY_URL, { signal: controller.signal });
|
|
77
78
|
if (!res.ok) return null;
|
|
78
79
|
const data = await res.json();
|
package/package.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llamaventures/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "CLI + MCP server for the Llama Ventures investment workbench (command.llamaventures.vc).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "npm run test:agent-routing",
|
|
7
|
+
"test": "npm run test:agent-routing && npm run test:contract",
|
|
8
8
|
"test:agent-routing": "node scripts/verify-agent-routing.mjs",
|
|
9
|
-
"
|
|
9
|
+
"test:contract": "node --test scripts/build-manifest.test.mjs scripts/core-api-call-sites.test.mjs scripts/verify-core-api-contract.test.mjs && node scripts/verify-core-api-contract.mjs",
|
|
10
|
+
"verify:artifact": "node scripts/verify-release-artifact.mjs",
|
|
11
|
+
"verify:release": "npm test && npm run verify:artifact && node scripts/verify-tarball-clean.mjs",
|
|
12
|
+
"prepack": "node scripts/prepare-build-manifest.mjs",
|
|
13
|
+
"postpack": "node scripts/cleanup-build-manifest.mjs"
|
|
10
14
|
},
|
|
11
15
|
"bin": {
|
|
12
16
|
"llama": "bin/llama.mjs",
|
|
@@ -14,6 +18,7 @@
|
|
|
14
18
|
},
|
|
15
19
|
"files": [
|
|
16
20
|
"bin/",
|
|
21
|
+
"contracts/",
|
|
17
22
|
"lib/",
|
|
18
23
|
"AGENT_BRIEFING.md",
|
|
19
24
|
"CHANGELOG.md",
|