@llamaventures/cli 1.15.0 → 1.16.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Llama Ventures Agent Briefing
2
2
 
3
- You've been onboarded as a teammate of [Llama Ventures](https://llamaventures.vc) via the `@llamaventures/cli` package. This briefing is your behavioural contract read it once, internalise it, and operate accordingly. The user shouldn't have to explain any of this to you again.
3
+ You've been onboarded as a teammate of [Llama Ventures](https://llamaventures.vc) via the `@llamaventures/cli` package. This bundled briefing is a fallback copy of the behavioural contract. When authenticated, prefer the server-owned contract from `llama agent-onboard`, `llama agent bootstrap`, or MCP `agent_briefing`; read it once, internalise it, and operate accordingly. The user shouldn't have to explain any of this to you again.
4
4
 
5
5
  You are not just an AI assistant. You're an **extension of a team member** — with CLI access to the Llama Command pipeline, write permission on shared data, and audit-log responsibility. Treat the status seriously.
6
6
 
@@ -25,6 +25,7 @@ Most teammates don't know everything this CLI can do. Part of your job is to sur
25
25
  This npm package is public, but Llama OS skills are private. Do not assume the skill text is bundled locally. For team-token sessions, discover the live runtime library through Llama Command:
26
26
 
27
27
  - Start with `llama agent bootstrap` or MCP `agent_bootstrap` when you need the current Command + Llama OS contract.
28
+ - Use `llama agent-onboard` or MCP `agent_briefing` for the server-owned Agent Runtime Contract. The npm-bundled text is fallback only.
28
29
  - Use `llama skills search "<task>"` or MCP `skills_search` before choosing a Llama workflow.
29
30
  - Use `llama skills show <slug>` or MCP `skills_read` only for the relevant skill.
30
31
  - Use `llama explain <command-url-or-object>` or MCP `object_inspect` for 404s, deleted wiki pages, notifier links, deal URLs, and unknown Command objects before telling the user "the system is broken."
@@ -38,6 +39,9 @@ Any time the user mentions a company name or founder name:
38
39
  1. **Run `llama deal search "<name>"` BEFORE web search.** Always. No exceptions.
39
40
  2. If pipeline has it → pull the data, integrate into your reply silently.
40
41
  3. If pipeline doesn't have it → ask once: "New name. Add to pipeline? (Y/n)". On yes, `llama deal create`.
42
+ - Use `--status Outreached` when we only contacted/logged the company and have no response or effective relationship yet.
43
+ - Use `--status Sourced` only once there is a response, intro, meeting, or another real relationship signal.
44
+ - Also set `--source-direction Inbound` if the deal came into the firm; set `--source-direction Outbound` if Llama found/listed/reached out first.
41
45
  4. If user gives you new facts (status / valuation / founder note) → `llama deal update` immediately, tell the user **one line** afterward.
42
46
 
43
47
  Don't:
@@ -201,12 +205,20 @@ llama deal show <dealId>
201
205
  llama deal list [--owner ...] [--status ...]
202
206
 
203
207
  # Pipeline — write
204
- llama deal create "Company" --description "..."
208
+ llama deal create "Company" --description "..." --source-direction Outbound --status Outreached
209
+ llama deal create "Company" --description "..." --source-direction Inbound --status Sourced
205
210
  llama deal update <dealId> <field> <value>
206
- # writable: status theirStage stage notes dealOwner source description website
211
+ # writable: status theirStage stage notes dealOwner source sourceDirection description website
207
212
  # location founders proposedAmount roundSize valuation sector subsector
208
213
  # foundedYear leadInvestor investors (each write logs a deal_events row)
209
214
 
215
+ # Our Stage vocabulary starts with:
216
+ # Outreached → Sourced → First Meeting → Diligence → Partner Meeting → Term Sheet → Invested
217
+ # `Outreached` is relationship memory only. Do not inflate it to `Sourced`
218
+ # unless a real relationship signal exists.
219
+ # `sourceDirection` is separate: Inbound = came into the firm; Outbound =
220
+ # we found/listed/reached out first.
221
+
210
222
  # Brief blocks
211
223
  llama brief blocks <dealId>
212
224
  llama brief add-text <dealId> --heading "..." --body "..."
@@ -326,9 +338,9 @@ the intake agent; relay the conversation, then surface the verdict.
326
338
 
327
339
  ## Where this content lives
328
340
 
329
- - This file: `AGENT_BRIEFING.md` in the `@llamaventures/cli` npm package
330
- - Re-printable any time: `llama agent-onboard`
331
- - MCP prompt: `agent_briefing` from the `llama-mcp` server
341
+ - Canonical when authenticated: `GET /api/agent/briefing` via `llama agent-onboard` or MCP `agent_briefing`
342
+ - Runtime home screen: `GET /api/agent/manifest` via `llama agent bootstrap` or MCP `agent_bootstrap`
343
+ - Fallback copy: `AGENT_BRIEFING.md` in the `@llamaventures/cli` npm package
332
344
  - Public source: <https://github.com/Llama-Ventures/llama-cli/blob/main/AGENT_BRIEFING.md>
333
345
 
334
346
  You're now a Llama Ventures teammate (or an external agent helping a
package/CHANGELOG.md CHANGED
@@ -6,6 +6,38 @@ this project adheres to [Semantic Versioning](https://semver.org).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.16.0] - 2026-06-22
10
+
11
+ ### Added
12
+ - CLI and MCP requests now send bounded local-agent telemetry metadata to
13
+ Llama Command: client kind/version, detected agent client, session id,
14
+ normalized command, latency, status, sanitized args, result ids, and bounded
15
+ result summaries.
16
+ - `llama eval good|bad --last` and `llama eval add "<query>" --expect ...`
17
+ let agents and humans turn real search usage into Golden Query Eval
18
+ feedback.
19
+ - MCP tool `record_eval_feedback` mirrors the CLI eval feedback path for
20
+ MCP-native agents.
21
+
22
+ ### Changed
23
+ - `llama agent-onboard` and MCP `agent_briefing` now prefer the authenticated
24
+ Llama Command `/api/agent/briefing` runtime contract, with bundled
25
+ `AGENT_BRIEFING.md` retained as fallback only.
26
+ - `llama agent bootstrap` and MCP `agent_bootstrap` now pass the local CLI
27
+ version to Command so the server can return stale/ok CLI guidance as part of
28
+ the agent contract.
29
+
30
+ ## [1.15.1] — 2026-06-16
31
+
32
+ ### Changed
33
+ - Documented the new `Outreached` Our Stage across CLI, MCP, and agent
34
+ briefing surfaces. Agents should use `Outreached` for logged outreach
35
+ without a response/effective relationship, and reserve `Sourced` for real
36
+ relationship signals.
37
+ - Added `sourceDirection` / `--source-direction` guidance across CLI, MCP, and
38
+ agent briefing surfaces. Use `Inbound` for deals that came into the firm and
39
+ `Outbound` for companies Llama found/listed/reached out to first.
40
+
9
41
  ## [1.15.0] — 2026-06-15
10
42
 
11
43
  ### Added
package/README.md CHANGED
@@ -180,11 +180,14 @@ llama token show
180
180
 
181
181
  # Pipeline — read
182
182
  llama deal search "acme ai"
183
+ llama deal list --owner alex --status Outreached
184
+ llama deal list --source-direction Outbound --status Outreached
183
185
  llama deal list --owner alex --status Diligence
184
186
  llama deal show <dealId>
185
187
 
186
188
  # Pipeline — write
187
- llama deal create "Acme AI" --description "..." --source Gavin
189
+ llama deal create "Acme AI" --description "..." --source Gavin --source-direction Outbound --status Outreached
190
+ llama deal create "Acme AI" --description "..." --source Gavin --source-direction Inbound --status Sourced
188
191
  llama deal update <dealId> status Diligence
189
192
  llama deal enrich <dealId> --dry-run
190
193
  llama deal enrich <dealId> --apply --executor server_agent
@@ -193,6 +196,13 @@ llama deal agent run <dealId> --message "collect founder evidence and update typ
193
196
  llama deal delete <dealId> # soft (audit-logged)
194
197
  llama deal restore <dealId>
195
198
 
199
+ # Status semantics
200
+ # Outreached = contact/logged, but no response or effective relationship yet.
201
+ # Sourced = response, intro, meeting, or another real relationship signal exists.
202
+ # sourceDirection is separate:
203
+ # Inbound = came into the firm.
204
+ # Outbound = we found/listed/reached out first.
205
+
196
206
  # Deal Brief — ordered, typed blocks (text · link · embed · callout)
197
207
  llama brief blocks <dealId>
198
208
  llama brief add-text <dealId> --heading "..." --body "..."
@@ -216,6 +226,8 @@ llama agent bootstrap
216
226
  llama skills search "wiki delete tombstone"
217
227
  llama skills show llama-command
218
228
  llama explain https://command.llamaventures.vc/wiki/some-page
229
+ llama eval bad --last --reason "missed the llamaos weekly note"
230
+ llama eval add "last week llama dev weekly" --expect wiki:llamaos-weekly-2026-06-17
219
231
 
220
232
  # Wiki
221
233
  llama wiki search "<query>"
@@ -252,10 +264,31 @@ agents can pattern-match without parsing prose.
252
264
 
253
265
  ---
254
266
 
267
+ ### Golden Query Eval feedback
268
+
269
+ The CLI and MCP server send lightweight client telemetry to Command for each
270
+ authenticated request: client kind/version, detected agent client, local session
271
+ id, normalized command, sanitized args, canonical result ids, status, latency,
272
+ and bounded summaries. It records what Llama Command was asked to do, not the
273
+ user's private Claude Code/Codex/Cursor conversation or local files.
274
+
275
+ Search commands automatically become eval candidates. Agents can mark the latest
276
+ result explicitly:
277
+
278
+ ```bash
279
+ llama eval good --last
280
+ llama eval bad --last --reason "wrong top wiki"
281
+ llama eval add "AI陪伴" --surface deal --expect deal:<uuid>
282
+ ```
283
+
284
+ MCP-native agents use `record_eval_feedback` for the same flow.
285
+
286
+ ---
287
+
255
288
  ## MCP server
256
289
 
257
290
  The bundled `llama-mcp` is a **stdio Model Context Protocol** server exposing
258
- **56 typed tools** that mirror the most-used CLI surface. Every tool is named
291
+ typed tools that mirror the most-used CLI surface. Every tool is named
259
292
  and scoped — there is no generic API passthrough, by design (a public-package
260
293
  escape hatch reachable from a prompt-injectable agent context is exactly the
261
294
  shape we want to avoid).
@@ -280,9 +313,11 @@ printf '%s\n' \
280
313
  ```
281
314
 
282
315
  Auth is identical to the CLI's chain (gcloud → `$LLAMA_TOKEN` → `~/.llama/token`).
283
- The `agent_briefing` MCP **prompt** also returns
284
- [`AGENT_BRIEFING.md`](AGENT_BRIEFING.md) verbatim, so any new agent loading the
285
- server can self-onboard without leaving the protocol.
316
+ The `agent_briefing` MCP **prompt** returns the server-owned Agent Runtime
317
+ Contract when authenticated, so any new agent loading the server can
318
+ self-onboard without leaving the protocol. The bundled
319
+ [`AGENT_BRIEFING.md`](AGENT_BRIEFING.md) is only a fallback if the server
320
+ briefing route is temporarily unavailable.
286
321
 
287
322
  For current Llama OS skills, use the runtime tools instead of looking for a
288
323
  local private repo: `agent_bootstrap`, `skills_search`, `skills_read`, and
@@ -342,8 +377,8 @@ extensions, no transport flags.
342
377
 
343
378
  > If you're new and want the agent to onboard itself, run
344
379
  > `llama agent-onboard` from the CLI or fetch the `agent_briefing` prompt from
345
- > the MCP server. It's the workflow contract — autonomy levels, attribution
346
- > grammar, error recovery, anti-pollution rules.
380
+ > the MCP server. It pulls the Command-owned workflow contract — current CLI
381
+ > guidance, attribution grammar, error recovery, and anti-pollution rules.
347
382
 
348
383
  ---
349
384
 
package/README.zh-CN.md CHANGED
@@ -201,11 +201,14 @@ llama token show
201
201
 
202
202
  # Pipeline——读
203
203
  llama deal search "acme ai"
204
+ llama deal list --owner alex --status Outreached
205
+ llama deal list --source-direction Outbound --status Outreached
204
206
  llama deal list --owner alex --status Diligence
205
207
  llama deal show <dealId>
206
208
 
207
209
  # Pipeline——写
208
- llama deal create "Acme AI" --description "..." --source Gavin
210
+ llama deal create "Acme AI" --description "..." --source Gavin --source-direction Outbound --status Outreached
211
+ llama deal create "Acme AI" --description "..." --source Gavin --source-direction Inbound --status Sourced
209
212
  llama deal update <dealId> status Diligence
210
213
  llama deal enrich <dealId> --dry-run
211
214
  llama deal enrich <dealId> --apply --executor server_agent
@@ -214,6 +217,13 @@ llama deal agent run <dealId> --message "collect founder evidence and update typ
214
217
  llama deal delete <dealId> # 软删除(审计日志记录)
215
218
  llama deal restore <dealId>
216
219
 
220
+ # Status 语义
221
+ # Outreached = 只是联系/记录了,还没有回复或有效关系。
222
+ # Sourced = 已有回复、intro、会议,或其它真实关系信号。
223
+ # sourceDirection 是单独维度:
224
+ # Inbound = 自然流入公司。
225
+ # Outbound = 我们主动发现/建名单/触达。
226
+
217
227
  # Deal Brief——有序的、有类型的 block(text · link · embed · callout)
218
228
  llama brief blocks <dealId>
219
229
  llama brief add-text <dealId> --heading "..." --body "..."
@@ -289,9 +299,10 @@ printf '%s\n' \
289
299
  ```
290
300
 
291
301
  认证链跟 CLI 完全一样(gcloud → `$LLAMA_TOKEN` → `~/.llama/token`)。
292
- `agent_briefing` 这个 MCP **prompt** 还会原样吐出
293
- [`AGENT_BRIEFING.md`](AGENT_BRIEFING.md)——刚装上 server 的 agent
294
- 不用离开协议就能给自己 onboard。
302
+ `agent_briefing` 这个 MCP **prompt** 会在认证后拉取 Command 服务端的
303
+ Agent Runtime Contract——刚装上 server 的 agent 不用离开协议就能给自己
304
+ onboard。包内 [`AGENT_BRIEFING.md`](AGENT_BRIEFING.md) 只是服务端 briefing
305
+ 临时不可用时的 fallback。
295
306
 
296
307
  要读当前 Llama OS skills,用 runtime tools:`agent_bootstrap`、
297
308
  `skills_search`、`skills_read`、`object_inspect`。公开 npm 包不打包私有
@@ -348,7 +359,7 @@ claude mcp add llama -- llama-mcp
348
359
  </details>
349
360
 
350
361
  > 想让 agent 自己 onboard?跑 `llama agent-onboard`,或者从 MCP server
351
- > 拉 `agent_briefing` prompt——那是 AI agent 的工作合约(autonomy 等级、
362
+ > 拉 `agent_briefing` prompt——它会拿 Command 服务端的工作合约(CLI 状态、
352
363
  > attribution 语法、错误恢复、anti-pollution 规则)。
353
364
 
354
365
  ---
package/bin/llama-mcp.mjs CHANGED
@@ -11,7 +11,14 @@ import { createRequire } from "module";
11
11
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
12
12
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
13
13
  import { z } from "zod";
14
- import { getAuthHeaders, readBriefing, request, requestSse } from "../lib/client.mjs";
14
+ import {
15
+ getAuthHeaders,
16
+ getLastAgentEvent,
17
+ readBriefing,
18
+ request,
19
+ requestSse,
20
+ setClientRuntime,
21
+ } from "../lib/client.mjs";
15
22
 
16
23
  const requireFromHere = createRequire(import.meta.url);
17
24
  const { version: PKG_VERSION } = requireFromHere("../package.json");
@@ -23,6 +30,8 @@ import {
23
30
  uploadExternalFile,
24
31
  } from "../lib/external.mjs";
25
32
 
33
+ setClientRuntime({ client: "mcp" });
34
+
26
35
  // Wrap a request() call into the MCP CallToolResult shape. Catches errors
27
36
  // (NO_AUTH / 401 / 5xx / network) and surfaces them as `isError: true`
28
37
  // content so the calling agent sees a clean error string instead of the
@@ -56,6 +65,20 @@ function splitSources(value) {
56
65
  .filter(Boolean);
57
66
  }
58
67
 
68
+ function expectedIds(value) {
69
+ const expected = { dealIds: [], wikiSlugs: [], raw: [] };
70
+ if (!value) return expected;
71
+ const items = Array.isArray(value) ? value : String(value).split(",");
72
+ for (const item of items.map((s) => String(s).trim()).filter(Boolean)) {
73
+ const [kind, ...rest] = item.split(":");
74
+ const id = rest.join(":").trim();
75
+ if (kind === "deal" && id) expected.dealIds.push(id);
76
+ else if ((kind === "wiki" || kind === "slug") && id) expected.wikiSlugs.push(id);
77
+ else expected.raw.push(item);
78
+ }
79
+ return expected;
80
+ }
81
+
59
82
  function buildEnrichmentAgentMessage(args = {}) {
60
83
  if (args.message) return String(args.message);
61
84
  const sources = splitSources(args.sources) ?? [
@@ -209,11 +232,47 @@ server.registerTool(
209
232
  },
210
233
  async ({ limit } = {}) => {
211
234
  const params = new URLSearchParams();
235
+ params.set("clientVersion", PKG_VERSION);
212
236
  if (limit) params.set("limit", String(limit));
213
237
  return callApi("GET", `/api/agent/manifest${params.toString() ? `?${params}` : ""}`);
214
238
  }
215
239
  );
216
240
 
241
+ server.registerTool(
242
+ "record_eval_feedback",
243
+ {
244
+ description:
245
+ "Mark the latest llama CLI/MCP result as good/bad or add a real query " +
246
+ "to the Golden Query Eval candidate pool. Use when the user says a " +
247
+ "Llama Command search/result was right, wrong, missing a source, or should be regression-tested.",
248
+ inputSchema: {
249
+ action: z.enum(["good", "bad", "add"]).describe("feedback action"),
250
+ eventId: z.number().optional().describe("agent_client_events id; defaults to latest local event"),
251
+ query: z.string().optional().describe("required for manual add when no source event is available"),
252
+ surface: z.string().optional().describe("deal, wiki, activity, people, or manual"),
253
+ expect: z
254
+ .union([z.string(), z.array(z.string())])
255
+ .optional()
256
+ .describe("expected ids like wiki:llamaos-weekly-2026-06-17 or deal:<uuid>"),
257
+ reason: z.string().optional().describe("why this was good/bad or should be tracked"),
258
+ privacyLevel: z.string().optional().describe("default internal"),
259
+ },
260
+ },
261
+ async ({ action, eventId, query, surface, expect, reason, privacyLevel }) => {
262
+ const last = getLastAgentEvent();
263
+ const body = {
264
+ action,
265
+ eventId: eventId ?? last?.lastEventId,
266
+ query,
267
+ surface: surface ?? last?.lastSurface,
268
+ expected: expectedIds(expect),
269
+ reason,
270
+ privacyLevel: privacyLevel ?? "internal",
271
+ };
272
+ return callApi("POST", "/api/agent/eval-feedback", body);
273
+ }
274
+ );
275
+
217
276
  server.registerTool(
218
277
  "skills_search",
219
278
  {
@@ -280,7 +339,7 @@ server.registerTool(
280
339
  {
281
340
  description:
282
341
  "Search the Llama Ventures deal pipeline. Fuzzy match on company name, " +
283
- "founders, description, founder info, notes, deal owner, source, and location. " +
342
+ "founders, description, founder info, notes, deal owner, source, source direction, and location. " +
284
343
  "Returns up to `limit` deals (default 200, cap 1000).",
285
344
  inputSchema: {
286
345
  q: z.string().optional().describe("fuzzy search query across all text fields"),
@@ -291,7 +350,7 @@ server.registerTool(
291
350
  .string()
292
351
  .optional()
293
352
  .describe(
294
- "exact match on 'Our Stage' (Sourced, First Meeting, Diligence, Partner Meeting, Term Sheet, Invested, Passed, Stalled, Future, Unknown)"
353
+ "exact match on 'Our Stage' (Outreached, Sourced, First Meeting, Diligence, Partner Meeting, Term Sheet, Invested, Passed, Stalled, Future, Unknown). Outreached means contact was logged but no effective relationship/response exists yet."
295
354
  ),
296
355
  theirStage: z.string().optional().describe("exact match on 'Their Stage'"),
297
356
  stage: z
@@ -300,6 +359,10 @@ server.registerTool(
300
359
  .describe(
301
360
  "exact match on Round (Pre-Seed, Seed, Series A, Series B, Series C+, Stealth)"
302
361
  ),
362
+ sourceDirection: z
363
+ .string()
364
+ .optional()
365
+ .describe("exact match on source direction: Inbound, Outbound, or Unknown"),
303
366
  limit: z.number().optional().describe("max results (default 200, cap 1000)"),
304
367
  offset: z.number().optional(),
305
368
  },
@@ -318,7 +381,7 @@ server.registerTool(
318
381
  {
319
382
  description:
320
383
  "Get the full canonical record for one deal by uuid. Includes status, " +
321
- "stage, founders, owner, source, valuation, all whitelisted writable fields, " +
384
+ "stage, founders, owner, source, sourceDirection, valuation, all whitelisted writable fields, " +
322
385
  "and the `extra` JSONB blob.",
323
386
  inputSchema: {
324
387
  dealId: z.string().describe("deal uuid"),
@@ -348,8 +411,17 @@ server.registerTool(
348
411
  .string()
349
412
  .optional()
350
413
  .describe("Pre-Seed | Seed | Series A | Series B | Series C+ | Stealth"),
351
- status: z.string().optional().describe("Our Stage workflow position"),
414
+ status: z
415
+ .string()
416
+ .optional()
417
+ .describe(
418
+ "Our Stage workflow position. Use Outreached when we only contacted/logged them and have no response/effective relationship; use Sourced only once there is a response, intro, meeting, or other real relationship signal."
419
+ ),
352
420
  source: z.string().optional().describe("free-form sourced-by; recommend nominating a user"),
421
+ sourceDirection: z
422
+ .string()
423
+ .optional()
424
+ .describe("Separate direction tag: Inbound if the deal came into the firm; Outbound if Llama found/listed/reached out first; Unknown if unclear."),
353
425
  notes: z.string().optional(),
354
426
  location: z.string().optional(),
355
427
  },
@@ -362,7 +434,7 @@ server.registerTool(
362
434
  {
363
435
  description:
364
436
  "Update a single whitelisted field on a deal. Writable fields: status, theirStage, " +
365
- "notes, stage, dealOwner, source, description, website, location, founders, " +
437
+ "notes, stage, dealOwner, source, sourceDirection, description, website, location, founders, " +
366
438
  "proposedAmount, roundSize, valuation, sector, subsector, foundedYear, leadInvestor, " +
367
439
  "investors. Logs a field_change event in deal_events.",
368
440
  inputSchema: {
@@ -1582,11 +1654,12 @@ server.registerPrompt(
1582
1654
  "skills_search, and skills_read.",
1583
1655
  },
1584
1656
  async () => {
1585
- // Gate the briefing behind a /api/me check so unauthenticated MCP
1586
- // clients can't harvest internal workflow / command surface just by
1587
- // requesting the prompt. Mirrors the CLI gate in bin/llama.mjs.
1657
+ // Gate the briefing behind authenticated Command runtime. The server-owned
1658
+ // /api/agent/briefing contract is canonical; bundled AGENT_BRIEFING.md is
1659
+ // only a rollout/offline fallback for authenticated users.
1588
1660
  const headers = await getAuthHeaders();
1589
1661
  let stub = null;
1662
+ let briefing = null;
1590
1663
  if (Object.keys(headers).length === 0) {
1591
1664
  stub =
1592
1665
  "Llama Ventures team onboarding requires credentials.\n\n" +
@@ -1597,19 +1670,28 @@ server.registerPrompt(
1597
1670
  "Founder / external visitor: use the `pitch_*` tools — no token required.";
1598
1671
  } else {
1599
1672
  try {
1600
- await request("GET", "/api/me");
1673
+ const params = new URLSearchParams({ clientVersion: PKG_VERSION });
1674
+ const body = await request("GET", `/api/agent/briefing?${params}`);
1675
+ briefing = body?.briefing || null;
1601
1676
  } catch (err) {
1602
- stub =
1603
- "Llama Ventures team onboarding requires valid credentials. " +
1604
- "Server rejected the credentials we sent. Re-mint at " +
1605
- "https://command.llamaventures.vc/settings/tokens.";
1677
+ const msg = err?.message || "";
1678
+ if (msg.includes("Error[UNAUTHORIZED]") || msg.includes("Error[NO_AUTH]")) {
1679
+ stub =
1680
+ "Llama Ventures team onboarding requires valid credentials. " +
1681
+ "Server rejected the credentials we sent. Re-mint at " +
1682
+ "https://command.llamaventures.vc/settings/tokens.";
1683
+ } else {
1684
+ briefing =
1685
+ "Warning: server agent briefing unavailable; using bundled fallback.\n\n" +
1686
+ readBriefing();
1687
+ }
1606
1688
  }
1607
1689
  }
1608
1690
  return {
1609
1691
  messages: [
1610
1692
  {
1611
1693
  role: "user",
1612
- content: { type: "text", text: stub ?? readBriefing() },
1694
+ content: { type: "text", text: stub ?? briefing ?? readBriefing() },
1613
1695
  },
1614
1696
  ],
1615
1697
  };