CODING AGENT HARNESS · SOURCE AUDITREPORT 05 / 18
05

Little Coder

用小而硬的约束增强 Pi,特别适合本地小模型;安全仍主要是规则而非隔离。

TypeScript · Local-model Pi ExtensionApache-2.0main
SOURCE
VERIFIED
Repository
itayinbarr/little-coder
Commit
e758baa38f6f28adefadd567077b05f68a05d6fa
Commit date
2026-07-25T22:48:12+03:00
Findings
20
Citations
63
Tracked files
194
EXECUTIVE READING

先给结论,再进入源码

核心机制

Pi 内核 + 动态知识尾部注入 + 80% watchdog

上下文

大 Read 压到 30 行;知识按失败/近期工具/意图排序

安全边界

宿主 bash;shell 分段白名单与重定向检测

适用建设

llama.cpp/Ollama、小模型、本地受控编码

值得借鉴

  • 为小模型补充确定性不变量
  • 知识注入兼顾 KV cache
  • 多 Agent 工作流轻巧

需要警惕

  • 无 OS 沙箱
  • checkpoint 非事务且有路径兼容缺口
  • 文本 tool call 只能纠偏

直接带走

  • Read-before-Edit
  • 禁止整文件覆写
  • 失败驱动知识排序
00 · METHOD

研究口径:先锁提交,再沿运行链读代码

README POLICY

README 仅用于定位产品意图;核心结论来自 launcher、pi ExtensionAPI 事件处理、工具实现、测试与 benchmark pipeline。

FACT POLICY

严格区分 little-coder 自己实现的扩展能力与 @earendil-works/pi-coding-agent 提供的内核能力;安全结论同时审计工具旁路与真实子进程实现。

INFERENCE POLICY

优劣势和建设建议由多处源码综合,并以 inference/limitation 标注,不把注释中的设计目标自动当作已兑现事实。

L1运行实现
L2接口契约
L3测试证明
L4文档佐证
L5明确推断

本页引用 24 个不同源码/测试文件;证据角色分布:契约 19 · 实现 41 · Prompt 1 · 测试 2。代码块是固定提交中的原文截取,长区间仅在中部折叠,首尾行号保持真实。

01 · TECHNICAL MAPS

架构总图与单轮执行链路

两张图均由本页证据账本生成,并通过 Archify showcase 9 项校验(0 error / 0 warning)。图可单独打开、搜索、缩放和追踪关系。

FIGURE 01Little Coder Harness 架构图全屏打开 ↗
FIGURE 02用户输入到工具回写的技术链路全屏打开 ↗
02 · COVERAGE MAP

审计维度与证据等级

入口、会话与主循环 verified L1 / L2

确认其是 pi launcher + ExtensionAPI 增强层,不自带独立 Agent 内核。

Provider、流式与重试 partial L1 / L2 / L3

已审计本地 provider 注册与 context probe;流式协议主体继承 pi。

上下文、压缩与记忆 verified L1 / L2 / L3

已审计中途 watchdog、读结果裁剪、尾部注入、证据跨压缩保留。

工具分发与结果治理 verified L1 / L2 / L3

已审计事件层 write/edit/shell guard、allowlist 和 malformed tool-call 修复。

执行环境与沙箱 verified L1 / L2

ShellSession 直接 execSync;项目没有 OS/容器沙箱,主要依赖策略门。

权限与安全 verified L1 / L2 / L3

已审计 auto/manual/accept-all、shell 分段与写旁路检测、子 Agent 工具收窄。

指令与 Prompt verified L1 / L2 / L3

已审计固定 AGENTS、技能/知识选择、KV-cache 友好尾部注入与 dedupe。

工具、连接器与插件 verified L1 / L2

已审计 bundled/env/user/pi-ecosystem 四类扩展来源和 browser/evidence/shell 工具。

子 Agent 与协作 verified L1 / L2 / L3

已审计独立子进程、工具约束、结果截断、并发、超时与 plan/deep-research 编排。

持久化与观测 partial L1 / L2 / L3

有 UI intervention、子 Agent usage、session evidence 与文件 checkpoint;无统一 trace backend。

测试、评测与成熟度 verified L2 / L3

关键守卫有 Vitest,deep-research 生产 pipeline 与 batch eval 共用实现。

01
DIMENSION · ENTRY-SESSION-LOOP

入口、会话与主循环

本章共 1 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

01
L1事实little-architecture-001

它是 pi 的 Harness 增强层,而不是另一套 Agent 内核

源码事实

launcher 解析依赖中的 pi CLI,显式加载 bundled/env/user 扩展,以固定 AGENTS.md 启动 pi;package.json 直接依赖 @earendil-works/pi-coding-agent。

白话解释

可以把它理解成给 pi 装了一套“小模型护栏与外挂”,对话循环、会话和基础工具仍由 pi 驱动。

对自研 Harness 的含义

分析和选型时必须把 little-coder 的差异能力与 pi 基座分开计分。

关键源码 · 契约
package.json · L33–L43
   33    "scripts": {
   34      "pi": "pi",
   35      "test": "vitest run",
   36      "test:py": "python3 -m pytest benchmarks/test_rpc_client.py -q",
   37      "typecheck": "tsc --noEmit"
   38    },
   39    "dependencies": {
   40      "@earendil-works/pi-coding-agent": "^0.79.4",
   41      "@sinclair/typebox": "^0.34.49",
   42      "playwright": "^1.59.1"
   43    },
查看全部 4 处证据
  • 契约 package.json:33–43 运行、测试脚本及 pi 依赖。
  • 实现 bin/little-coder.mjs:84–139 从依赖布局解析 pi CLI 入口。
  • 实现 bin/little-coder.mjs:285–354 用固定指令、显式扩展和用户参数组成 pi argv。
  • 实现 bin/little-coder.mjs:481–513 以当前 Node 进程真正启动 pi。
02
DIMENSION · TOOLS-CONNECTORS-PLUGINS

工具、连接器与插件

本章共 1 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

02
L1事实little-extensions-001

扩展来源分层,默认固定集合,pi 生态桥显式 opt-in

源码事实

launcher 按 bundled、LITTLE_CODER_EXTRA_EXTENSIONS、用户扩展目录的顺序加载,后者可覆盖前者;默认传 --no-extensions 禁止 pi 自动发现,只有 --with-pi-extensions 才开启且由 pi 对项目扩展做 trust prompt。

白话解释

默认追求可预测:装哪些插件是确定的;想接入 pi 大生态可以开开关,但会牺牲冷启动上下文和固定能力面。

对自研 Harness 的含义

这是“小模型少即是多”的插件治理取舍。

关键源码 · 实现
bin/little-coder.mjs · L157–L217
  157  // ---- 4. Auto-discover bundled extensions ----
  158  // Load order matters: bundled first, then the env var, then the user
  159  // directory. pi applies later `--extension` flags after earlier ones, so a
  160  // user extension can override bundled behavior rather than being shadowed by
  161  // it. The three sources are recorded in LITTLE_CODER_EXTENSION_MANIFEST below
  162  // so the `/extensions` command can tell the user where each one came from.
  163  const extDir = join(pkgRoot, ".pi", "extensions");
  164  const extArgs = [];
  165  const loadedBundled = [];
  166  if (existsSync(extDir)) {
  167    for (const name of readdirSync(extDir).sort()) {
  168      const subdir = join(extDir, name);
  169      const idx = join(subdir, "index.ts");
  170      try {
  171        if (statSync(subdir).isDirectory() && existsSync(idx)) {
  172          extArgs.push("--extension", idx);
  173          loadedBundled.push(idx);
  174        }
  175      } catch {
  176        // skip unreadable entries
  177      }
  178    }
  179  }
  180  
      … 27 lines omitted; exact range 157–217 …
  208  {
  209    const discovered = discoverUserExtensions(process.env);
  210    userExtensionsDir = discovered.dir;
  211    userExtensionWarnings = discovered.warnings;
  212    for (const w of discovered.warnings) console.error(w);
  213    for (const entry of discovered.entries) {
  214      extArgs.push("--extension", entry);
  215      loadedFromUserDir.push(entry);
  216    }
  217  }
查看全部 3 处证据
  • 实现 bin/little-coder.mjs:157–217 三类显式扩展的发现和覆盖顺序。
  • 契约 bin/little-coder.mjs:219–227 pi 生态发现默认关闭,项目扩展仍走上游信任提示。
  • 实现 bin/little-coder.mjs:338–367 启动参数和扩展 provenance manifest。
03
DIMENSION · CONTEXT-COMPACTION-MEMORY

上下文、压缩与记忆

本章共 2 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

03
L1事实little-context-001

80% 中途压缩 watchdog 补上 pi 的长自主运行缺口

源码事实

每个 turn_start 读取 live context usage,默认 80% 触发 ctx.compact;完成后自动发送继续消息。它用 in-flight guard、5% 滞回与效果测量防止重复压缩陷入 Nothing to compact。

白话解释

模型若连续几十轮调用工具、不把控制权还给用户,原生 pi 可能迟迟不压缩;这个扩展在每一小轮都看油表,快满了就主动整理上下文再接着做。

对自研 Harness 的含义

长自治任务的上下文治理不能只挂在用户轮边界。

关键源码 · 契约
.pi/extensions/context-watchdog/index.ts · L3–L29
    3  // Mid-run context watchdog (issue #59).
    4  //
    5  // pi only evaluates auto-compaction at a *user-turn boundary* — its
    6  // `_checkCompaction` runs inside `_handlePostAgentRun`, which fires only after
    7  // `agent.prompt()` has fully returned (i.e. once the model stops requesting
    8  // tools and goes idle). During one long autonomous run this boundary is never
    9  // reached: little-coder's small models routinely chain dozens of tool-call
   10  // turns before yielding, so context grows unchecked and can blow straight past
   11  // the window — pi then only reacts to the *overflow error* after the fact.
   12  // charly1r reproduced exactly this: context climbing 34k → 40k → … → 64k across
   13  // many `slot release` turns with no compaction until the request overflowed.
   14  //
   15  // pi does expose the levers to fix this from an extension: `ctx.getContextUsage()`
   16  // reports live token usage against the active model's window, and `ctx.compact()`
   17  // triggers pi's own compaction without awaiting it. This extension watches usage
   18  // at every turn boundary and, once it crosses a threshold, proactively kicks off
   19  // compaction — so a long single run compacts *before* it overflows, at roughly
   20  // the same point pi would have if the model had yielded.
   21  //
   22  // Tuning / opt-out:
   23  //   LITTLE_CODER_COMPACT_AT_PERCENT   trigger threshold, percent of the context
   24  //                                     window (default 80). <=0 or >=100 disables.
   25  //   LITTLE_CODER_NO_COMPACT_WATCHDOG=1  hard off.
   26  //
   27  // This is complementary to pi's end-of-run compaction, not a replacement — the
   28  // `compacting` guard below keeps us from re-firing while a compaction is already
   29  // in flight, and pi's own threshold/overflow paths still run at run boundaries.
查看全部 3 处证据
  • 契约 .pi/extensions/context-watchdog/index.ts:3–29 上游边界缺口、live usage 与中途 compact 机制。
  • 实现 .pi/extensions/context-watchdog/index.ts:59–107 默认阈值、5% progress band 与触发判断。
  • 实现 .pi/extensions/context-watchdog/index.ts:153–223 效果测量、暂停/重启、compact 回调和自动续跑。
04
L1事实little-context-002

超大 Read 结果在进入 LLM 前缩成 30 行

源码事实

read 的成功 tool_result 会用 3.5 chars/token 估算;已知 usage 时按剩余窗口判断,未知时单文件不得超过窗口一半。超限则替换为头 30 行和 grep/定向 read 指令,图片保持原样。

白话解释

文件虽然已经从磁盘读了,但在送给模型前会截流,避免一份两千行源码把小模型的记忆一次塞爆。

对自研 Harness 的含义

工具输出也是上下文预算的一等公民,不能只压聊天历史。

关键源码 · 契约
.pi/extensions/read-guard/index.ts · L4–L27
    4  // Harness intervention: trim a `read` result that would overflow the context window.
    5  //
    6  // little-coder drives SMALL local models with small context windows (the
    7  // model's registered contextWindow, read live below via getContextUsage()).
    8  // pi's built-in `read` returns up to ~2000 lines in a single tool result
    9  // — for a small model that one result can blow past the remaining budget, evict
   10  // earlier conversation, and wreck the run. That's exactly the class of failure
   11  // the harness-intervention layer exists to catch (cf. thinking-budget cap,
   12  // write-guard redirect, turn-cap).
   13  //
   14  // When a read result would push context usage past the window, we replace it
   15  // with only the file's first HEAD_LINES lines plus a message telling the model
   16  // why it was trimmed and to use those lines to understand the structure, then
   17  // locate what it needs with grep/find or a targeted read (offset/limit) — rather
   18  // than re-reading the whole file. The user sees one uniform "harness
   19  // intervention: …" line, like every other intervention.
   20  //
   21  // Why `tool_result`, not `tool_call`: a `tool_call` handler can only `block`
   22  // with a `reason` string (no file content) or mutate `input.limit` (lines but no
   23  // message). Delivering BOTH the first 30 lines AND an explanation in one result
   24  // requires `tool_result`, whose return value replaces the content the model sees
   25  // (ToolResultEventResult.content). The full file is still read from disk (pi
   26  // already caps that at ~2000 lines) but the oversized text never reaches the LLM
   27  // context because we swap it out before it lands.
查看全部 3 处证据
  • 契约 .pi/extensions/read-guard/index.ts:4–27 在 tool_result 替换超大文本的原因。
  • 实现 .pi/extensions/read-guard/index.ts:29–82 30 行、窗口一半 fallback 和 token 判断。
  • 实现 .pi/extensions/read-guard/index.ts:108–153 文本限定、usage 检查与替换结果。
04
DIMENSION · INSTRUCTIONS-PROMPTS

指令与 Prompt

本章共 3 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

05
L1事实little-prompt-001

动态知识放在对话尾部,保护 KV cache

源码事实

技能、知识、计划与研究 brief 默认作为隐藏 custom message 放在用户消息后,而不是改 system prompt;字节相同的块不重复注入。可用环境变量切回旧 system 模式。

白话解释

固定的历史前缀不动,只在最末尾塞这轮真正需要的小纸条,本地模型就不用每轮重算十几万 token 的缓存。

对自研 Harness 的含义

对本地推理,prompt 稳定性本身就是性能架构。

关键源码 · 契约
.pi/extensions/_shared/inject.ts · L1–L27
    1  // Where little-coder's per-turn context augmentation lands (issue #73).
    2  //
    3  // Four extensions add a block of guidance to a turn: skill-inject (tool skill
    4  // cards + the research directive), knowledge-inject (algorithm reference
    5  // entries), plan-mode (planning instructions + research), and deep-research
    6  // (the report brief). All four used to append to the SYSTEM PROMPT.
    7  //
    8  // That destroyed the KV cache. The system prompt is the first thing in the
    9  // request, so changing it invalidates the entire cached prefix — and these
   10  // blocks are recomputed per turn from the user's prompt, so they changed
   11  // almost every turn. manueloverride caught it with `cache-hunter`: llama.cpp
   12  // re-churning 120k of message history "for no reason" mid-conversation.
   13  //
   14  // pi already has the right hook. `before_agent_start` may return a `message`
   15  // instead of a `systemPrompt` (core/extensions/types.d.ts::
   16  // BeforeAgentStartEventResult); pi appends it AFTER the user's message
   17  // (core/agent-session.js) and converts `role: "custom"` to a `user` message on
   18  // the way to the provider (core/messages.js::convertToLlm). So the block lands
   19  // at the TAIL of the conversation with every preceding byte untouched — the
   20  // prefix stays cached and only the new tokens are processed.
   21  //
   22  // The recency argument that put these blocks last in the system prompt gets
   23  // stronger, not weaker: small models weight the end of the context most, and
   24  // the conversation tail is as late as it gets.
   25  //
   26  // `LITTLE_CODER_INJECT_MODE=system` restores the old system-prompt behavior,
   27  // which is what the whitepaper scaffold reproduction was measured against.
查看全部 3 处证据
  • 契约 .pi/extensions/_shared/inject.ts:1–27 system prompt 动态变化导致 KV cache 失效的根因。
  • 实现 .pi/extensions/_shared/inject.ts:29–65 隐藏尾消息与 system 兼容模式。
  • 实现 .pi/extensions/_shared/inject.ts:67–86 对持久尾消息做字节级去重。
06
L1事实little-skills-001

技能选择按失败恢复、近期工具、当前意图排序

源码事实

skills/tools/*.md 带 target_tool 和 token_cost;每轮在默认 300 token 内先放上次失败工具,再放近期工具,最后按用户关键词预测,并过滤当前 allowed-tools。研究任务额外注入 browse→EvidenceAdd→再写的指令。

白话解释

它不会把整本工具手册都塞给小模型,只给最可能马上用到的几张卡;刚失败过的工具优先补课。

对自研 Harness 的含义

技能是按预算路由的运行时知识,而非全量静态 prompt。

关键源码 · 契约
.pi/extensions/skill-inject/index.ts · L8–L31
    8  // ── Tool-skill registry ─────────────────────────────────────────────────
    9  // Port of local/skill_augment.py. Loads skills/tools/*.md once, hooks
   10  // `before_agent_start` to add a `## Tool Usage Guidance` block to the turn.
   11  // Per-user-prompt selection using the whitepaper's 3-priority algorithm
   12  // (error recovery > recency > intent). Budget-guarded, cached.
   13  //
   14  // The block is delivered as a tail message rather than appended to the system
   15  // prompt — see _shared/inject.ts for why (issue #73: it was invalidating the
   16  // KV cache on every turn).
   17  
   18  interface ToolSkill {
   19    targetTool: string;
   20    body: string;
   21    tokenCost: number;
   22  }
   23  
   24  const skills = new Map<string, ToolSkill>();
   25  const selectionCache = new Map<string, string>();
   26  let loaded = false;
   27  
   28  // State tracked across the session so we have error-recovery + recency
   29  // signals by the time the next `before_agent_start` fires.
   30  const recentToolCalls: string[] = []; // most-recent-first, capped at 8
   31  let lastFailedTool: string | null = null;
查看全部 4 处证据
  • 契约 .pi/extensions/skill-inject/index.ts:8–31 三优先级、缓存和会话信号。
  • 实现 .pi/extensions/skill-inject/index.ts:75–132 加载 frontmatter、预算和三阶段选择。
  • Prompt .pi/extensions/skill-inject/index.ts:169–178 research-first 明确顺序。
  • 实现 .pi/extensions/skill-inject/index.ts:198–270 allowed tools、required tools、去重与尾部注入。
07
L1事实little-knowledge-001

算法知识以关键词打分并反向声明所需工具

源码事实

skills/knowledge 与 skills/protocols 条目按单词 1 分、短语 2 分打分,低于 2 不选,单条最多 150 token、总预算默认 200;当系统 prompt 已超过窗口 40% 或为 subtask 时不注入,并将 requires_tools 发布给 skill injector。

白话解释

题目像动态规划才临时塞动态规划小抄;而且小抄若要求某工具,会顺带保证那张工具说明也进来。

对自研 Harness 的含义

知识选择与工具可用性形成联动,但关键词法的召回精度有限。

关键源码 · 契约
.pi/extensions/knowledge-inject/index.ts · L8–L35
    8  // ── Knowledge-entry registry ────────────────────────────────────────────
    9  // Port of local/knowledge_augment.py. Loads skills/knowledge/*.md plus the
   10  // three root-level protocol skills (skills/protocols/*.md). Scores entries
   11  // against the user's prompt, selects top within budget, publishes
   12  // `requires_tools` on systemPromptOptions so skill-inject can include them.
   13  //
   14  // Like skill-inject, the selected entries ride in as a tail message rather
   15  // than a system-prompt append (issue #73 — see _shared/inject.ts).
   16  
   17  interface KnowledgeEntry {
   18    topic: string;
   19    body: string;
   20    tokenCost: number;
   21    keywords: string[];
   22    requiresTools: string[];
   23  }
   24  
   25  const entries = new Map<string, KnowledgeEntry>();
   26  const cache = new Map<string, string>();
   27  let loaded = false;
   28  
   29  const MIN_SCORE_THRESHOLD = 2.0;
   30  const PER_ENTRY_CAP = 150;
   31  
   32  function dirs(): string[] {
   33    const here = dirname(fileURLToPath(import.meta.url));
   34    const repo = join(here, "..", "..", "..");
   35    return [join(repo, "skills", "knowledge"), join(repo, "skills", "protocols")];
查看全部 3 处证据
  • 契约 .pi/extensions/knowledge-inject/index.ts:8–35 知识目录、预算和 required tools 设计。
  • 实现 .pi/extensions/knowledge-inject/index.ts:38–77 加载、成本上限与词/短语评分。
  • 实现 .pi/extensions/knowledge-inject/index.ts:93–156 上下文门禁、top selection 与工具联动。
05
DIMENSION · TOOL-DISPATCH

工具分发与结果治理

本章共 3 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

08
L1事实little-edit-001

禁止整文件覆写是跨 Write 与 shell 的不变量

源码事实

write tool_call 被原地规范路径;已有文件或 Windows 保留设备名会被拒并给出 Edit recipe。shell 的 >、heredoc、tee 等写目标也用同一 verdict 检查,append 例外。

白话解释

小模型想偷懒把整个文件重写,换成 `cat > file` 也绕不过去;它被迫做小块精确修改。

对自研 Harness 的含义

安全/质量不变量应按“副作用”覆盖所有等价工具,而不是只拦一个工具名。

关键源码 · 实现
.pi/extensions/write-guard/index.ts · L35–L75
   35   * Resolve a write `path` argument to a concrete on-disk path.
   36   *
   37   * Two deterministic rewrites:
   38   *
   39   * 1. `"/<single-segment>"` (e.g. `/foo.md`) → `<cwd>/<single-segment>`.
   40   *    Background: the model has been seen to anchor at filesystem root when
   41   *    given an "Absolute file path" schema and no obvious directory context.
   42   *    Genuine system-path writes always include at least one intermediate
   43   *    directory (`/etc/X`, `/tmp/Y/Z`), so a root + bare filename is almost
   44   *    always a mistake. Rewriting to cwd matches user intent and avoids
   45   *    accidentally writing to `/`.
   46   *
   47   * 2. Bare filename / relative path (no leading slash) → resolved against cwd.
   48   *
   49   * Anything else (absolute path with at least one intermediate directory) is
   50   * left untouched.
   51   */
   52  export function normalizeWritePath(
   53    filePath: string,
   54    cwd: string = process.cwd(),
   55  ): { path: string; rewrittenFrom?: string } {
   56    if (/^\/[^/]+$/.test(filePath)) {
   57      return { path: join(cwd, filePath.slice(1)), rewrittenFrom: filePath };
   58    }
      … 7 lines omitted; exact range 35–75 …
   66  // `path`; older little-coder builds and some prompts use `file_path`. We accept
   67  // both so the guard is independent of which write implementation is in play.
   68  function pathKey(input: Record<string, unknown>): "path" | "file_path" | undefined {
   69    if (typeof input.path === "string") return "path";
   70    if (typeof input.file_path === "string") return "file_path";
   71    return undefined;
   72  }
   73  
   74  // Tools that hand a string to a shell, and so can reach the filesystem without
   75  // going anywhere near the `write` tool (issue #70).
查看全部 4 处证据
  • 实现 .pi/extensions/write-guard/index.ts:35–75 相对路径、根目录裸文件与绝对路径规范化。
  • 实现 .pi/extensions/write-guard/index.ts:119–168 保留设备名、新文件、append 和已有文件 verdict。
  • 实现 .pi/extensions/write-guard/index.ts:158–205 事件层 Write 与 shell 写旁路拦截。
  • 测试 .pi/extensions/write-guard/write-guard.test.ts:197–279 heredoc、redirect、tee、append 与只读命令测试。
09
L1事实little-edit-002

Edit 强制先 Read,成功 Write/Edit 也更新已知文件集

源码事实

每会话维护 canonicalized readFiles;只有成功的 read/edit/write tool_result 才加入,未读文件的 edit 在执行前阻断,新会话清空。

白话解释

模型不能凭印象猜 oldText;先亲眼看过文件,才有资格改。

对自研 Harness 的含义

把编辑前置条件做成运行时门禁,比仅写进提示词可靠。

关键源码 · 契约
.pi/extensions/read-guard-edit/index.ts · L4–L29
    4  
    5  // Read-before-edit guard.
    6  //
    7  // Small models routinely fire `edit` with an `oldText` they never actually saw
    8  // — guessing at the current file contents — which either fails the exact-match
    9  // requirement (wasting a turn) or, worse, matches the wrong span. Editors the
   10  // user is used to (Claude Code et al.) enforce a simple invariant: a file must
   11  // be Read before it can be Edited. We reproduce that here.
   12  //
   13  // Mechanism mirrors write-guard: we don't own pi's built-in `read`/`edit`
   14  // tools, so we enforce at the event layer. We remember every file that was
   15  // successfully `read` this session (`tool_result`, !isError), and block any
   16  // `edit` whose target hasn't been read, redirecting the model to Read first.
   17  //
   18  // Why a separate extension from `read-guard`: read-guard trims an oversized
   19  // read so it can't overflow a small context window — a different concern from
   20  // the read-before-edit invariant. Keeping them apart keeps each single-purpose.
   21  //
   22  // A successful `edit` or `write` also marks the path as known: an edit only
   23  // succeeds when the file was already read (we'd have blocked it otherwise), and
   24  // a write means the model authored the file's contents, so a follow-up edit to
   25  // either is legitimate without a re-read.
   26  
   27  // Files read (or authored) in the current session. Module-scoped: one pi
   28  // process drives one session at a time, and we clear on session_start.
   29  export const readFiles = new Set<string>();
查看全部 3 处证据
  • 契约 .pi/extensions/read-guard-edit/index.ts:4–29 先读后改不变量及成功写入也算已知。
  • 实现 .pi/extensions/read-guard-edit/index.ts:59–89 session reset、成功结果登记和 edit 阻断。
  • 测试 .pi/extensions/read-guard-edit/read-guard-edit.test.ts:34–99 未读、失败读、写后改和路径拼写等测试。
10
L1限制little-output-001

文本化 tool call 只能纠偏,不能由扩展代执行

源码事实

turn_end 检测 fenced/XML/bare JSON 调用后发送 follow-up,Liquid Pythonic 格式只提示服务端启用匹配 --jinja;源码明确指出 pi ExtensionAPI 无法执行解析出的调用并合成 tool_result。

白话解释

它能看出模型把工具调用写成了普通文字,但没法替模型按下执行键,只能让模型重发,或要求修服务器模板。

对自研 Harness 的含义

对弱模型的协议容错受上游 ExtensionAPI 能力上限约束。

关键源码 · 契约
.pi/extensions/output-parser/index.ts · L5–L20
    5  // Detects malformed/fenced tool calls in assistant text and nudges the model
    6  // back onto native tool-calling. Active-repair (executing extracted calls
    7  // and synthesizing tool_result messages) is intentionally not attempted on
    8  // the headline Qwen3.6-35B-A3B path, which uses native tool calling. When
    9  // extracted calls ARE detected, we log them via ctx.ui.notify and queue a
   10  // follow-up nudge for the next turn.
   11  //
   12  // One format is handled differently: LFM2/Liquid "Pythonic" tool calls
   13  // (`<|tool_call_start|>[Read(path='…')]<|tool_call_end|>`, issue #42). Pythonic
   14  // IS that model's native channel, so a "use native tool calls" nudge can't move
   15  // it to another format — it would just re-emit the same text every turn and
   16  // loop. little-coder also can't execute the calls itself (pi exposes no
   17  // extension API to run a tool + synthesize its result). So for that format we
   18  // surface a single, accurate diagnostic pointing at the real fix — serving
   19  // llama.cpp with `--jinja` and the model's chat template, which parses the
   20  // calls into native tool_calls upstream — instead of looping a futile nudge.
查看全部 2 处证据
  • 契约 .pi/extensions/output-parser/index.ts:5–20 不做 active repair 的边界和 Liquid 特例。
  • 实现 .pi/extensions/output-parser/index.ts:38–85 native 检查、一次性诊断与 follow-up 重发。
06
DIMENSION · PERMISSIONS-SECURITY

权限与安全

本章共 1 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

11
L1事实little-permission-001

shell 权限是分段白名单,并显式检测写重定向

源码事实

auto 模式把命令按 &&、||、;、| 拆段,所有段都必须命中 safe prefix;在此前先检测写目标,阻止 cat/tee/redirection 绕过。manual 阻止未预批准命令,accept-all 放行供 benchmark 使用。

白话解释

不是看到开头是 `ls` 就放行 `ls && rm -rf /`,整条链每一段都要安全。

对自研 Harness 的含义

字符串白名单比简单前缀更稳,但仍不是操作系统沙箱。

关键源码 · 实现
.pi/extensions/permission-gate/index.ts · L11–L58
   11  //   LITTLE_CODER_PERMISSION_MODE=auto|accept-all|manual
   12  //   LITTLE_CODER_BASH_ALLOW="cmd1,cmd2 sub,..."  extra allow-prefixes,
   13  //                                                merged with the built-in list.
   14  //
   15  // Issue #70: the gate used to match only `bash`/`Bash`, so a model that hit a
   16  // refusal could re-run the same thing through the `ShellSession` tool and land
   17  // in an execSync with no gate at all. Every shell-executing tool is listed in
   18  // SHELL_TOOLS now, and they all go through the same whitelist.
   19  
   20  const BUILTIN_SAFE_PREFIXES: readonly string[] = [
   21    "ls", "cat", "head", "tail", "wc", "pwd", "echo", "printf", "date",
   22    "which", "type", "env", "printenv", "uname", "whoami", "id",
   23    "git log", "git status", "git diff", "git show", "git branch",
   24    "git remote", "git stash list", "git tag",
   25    "find ", "grep ", "rg ", "ag ", "fd ", "sed ",
   26    "python ", "python3 ", "node ", "ruby ", "perl ",
   27    "pip show", "pip list", "npm list", "cargo metadata",
   28    "df ", "du ", "free ", "top -bn", "ps ",
   29    "curl -I", "curl --head",
   30    // Routine filesystem scaffolding. Trailing space = word boundary, so
   31    // "cp " matches "cp a b" but not "cpufetch". rm stays off the list by
   32    // design; use LITTLE_CODER_BASH_ALLOW=rm if a deployment needs it.
   33    "cp ", "mv ", "mkdir ", "touch ",
   34  ];
      … 14 lines omitted; exact range 11–58 …
   49    return [...BUILTIN_SAFE_PREFIXES, ...parseExtraPrefixes(process.env.LITTLE_CODER_BASH_ALLOW)];
   50  }
   51  
   52  /**
   53   * True when EVERY command in `command` is whitelisted and none of them writes.
   54   *
   55   * Two hardenings over the original `startsWith` check, both from issue #70:
   56   *
   57   * 1. **Judge every segment.** The check ran on the raw string, so only the
   58   *    first command was ever inspected — `ls && rm -rf /` was "safe" because it
查看全部 2 处证据
  • 实现 .pi/extensions/permission-gate/index.ts:11–58 模式、safe prefix、命令链拆分和 isSafeBash。
  • 实现 .pi/extensions/permission-gate/index.ts:60–121 Write/Edit 旁路检测与三种模式。
07
DIMENSION · EXECUTION-SANDBOX

执行环境与沙箱

本章共 1 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

12
L1限制little-sandbox-001

默认执行是宿主 bash,不是容器或内核沙箱

源码事实

ShellSession 的本地后端直接 execSync(command, shell=/bin/bash),共享 process.cwd,最大 buffer 10MB;TB 模式仅代理给外部 tmux adapter。源码未施加 namespace、seccomp、Seatbelt 或容器隔离。

白话解释

一旦命令通过权限门,它就在你的真实机器上跑;白名单是保安问话,不是墙。

对自研 Harness 的含义

高风险仓库或全自动模式应由外层容器/VM 提供强隔离。

关键源码 · 契约
.pi/extensions/shell-session/index.ts · L6–L16
    6  // Port of local/tools/shell_session.py. Two backends implemented:
    7  //   1. tmux-proxy — when LITTLE_CODER_TB_MODE=1, route every command to the
    8  //      parent TB adapter over the extension_ui_request channel. The parent
    9  //      drives the actual TmuxSession so commands appear in TB's trajectory.
   10  //   2. subprocess — child_process.execSync for local use (GAIA doesn't use
   11  //      ShellSession; this is for local REPL + debugging of TB adapter).
   12  //
   13  // The sentinel-prompt pexpect backend from the Python version (persistent
   14  // bash process with state between calls) is deliberately skipped because
   15  // neither Terminal-Bench nor GAIA requires it; TB uses tmux, GAIA uses Bash.
   16  
查看全部 3 处证据
  • 契约 .pi/extensions/shell-session/index.ts:6–16 tmux proxy 与 subprocess 两后端。
  • 实现 .pi/extensions/shell-session/index.ts:24–38 宿主 /bin/bash execSync。
  • 实现 .pi/extensions/shell-session/index.ts:65–96 工具参数、timeout 与后端选择。
08
DIMENSION · SUBAGENTS-COLLABORATION

子 Agent 与协作

本章共 4 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

13
L1事实little-subagent-001

子 Agent 是独立 little-coder 进程,父上下文只收短报告

源码事实

dispatch 最多接收 4 个任务;每个 child 以 launcher 的 headless JSON 模式、独立上下文、同模型启动。全 transcript 只放 UI details,父模型只收到 ≤2000 chars 报告。

白话解释

子任务的搜索过程不会把父模型记忆塞满,父亲只看一页简报。

对自研 Harness 的含义

这是上下文隔离型协作,不是共享黑板式多 Agent。

关键源码 · 契约
.pi/extensions/subagent/index.ts · L12–L20
   12  // The `dispatch` tool: the main little-coder spawns isolated child little-coder
   13  // sessions ("sub-coders") to research a focused question — they read the repo
   14  // and browse online, then return a CONCISE report. The full child transcript
   15  // lives in the tool's `details` (UI-only); only the short report enters the
   16  // parent model's context. A live panel above the input tracks them while they
   17  // run. See spawn.ts for the engine and the read-only constraints.
   18  
   19  const MAX_PARALLEL = 4;
   20  
查看全部 4 处证据
  • 契约 .pi/extensions/subagent/index.ts:12–20 隔离 session、短报告与并行上限。
  • 契约 .pi/extensions/subagent/index.ts:49–73 dispatch schema 与只读能力说明。
  • 契约 .pi/extensions/subagent/spawn.ts:46–77 报告后缀、2000 字符上限、full transcript UI-only。
  • 实现 .pi/extensions/subagent/spawn.ts:251–320 headless child 启动、JSON event 解析和 usage 累积。
14
L1事实little-subagent-002

子 Agent 工具能力收窄且禁止递归 dispatch

源码事实

child 环境设置 allowed-tools 为 read/search/browser/bash,不含 edit/write/dispatch,并把 permission mode 设为 auto;tool-gating 对任何不在集合的 tool_call 返回 block。默认并发 1,可配置,支持 watchdog、SIGTERM→SIGKILL 和超时重试一次。

白话解释

孩子能查资料但不能改仓库,也不能再生孙子;本地单 GPU 默认串行,避免所谓并行反而拖慢。

对自研 Harness 的含义

能力交集和递归上限应在执行面强制,而不只写在子 Agent prompt 里。

关键源码 · 契约
.pi/extensions/subagent/spawn.ts · L25–L44
   25  // Tools a sub-coder may use: read + search + browse online + read-only bash.
   26  // Enforced by the tool-gating extension in the child. Deliberately omits
   27  // edit/write (children never mutate the tree) and `dispatch` (no fan-out bombs).
   28  export const SUBCODER_ALLOWED_TOOLS = [
   29    "read",
   30    "grep",
   31    "glob",
   32    "find",
   33    "ls",
   34    "bash",
   35    "webfetch",
   36    "websearch",
   37    "BrowserNavigate",
   38    "BrowserClick",
   39    "BrowserType",
   40    "BrowserScroll",
   41    "BrowserExtract",
   42    "BrowserBack",
   43    "BrowserHistory",
   44  ].join(",");
查看全部 4 处证据
  • 契约 .pi/extensions/subagent/spawn.ts:25–44 子 Agent 工具集合明确排除写和 dispatch。
  • 实现 .pi/extensions/subagent/spawn.ts:91–121 child env、auto 权限和默认串行。
  • 实现 .pi/extensions/tool-gating/index.ts:8–37 allowlist 同时进入 prompt options 与执行前 block。
  • 实现 .pi/extensions/subagent/spawn.ts:333–375 abort、两阶段 kill 与 watchdog。
15
L1事实little-plan-001

Plan Mode 本身就是一条多 Agent 工作流

源码事实

计划模式先用 reasoning child 拆出 1–4 个探索任务,再跑只读 explorer,生成 1–3 个澄清问题让用户选择,最后把 digest 和答案隐藏注入主 Agent 写计划;合成阶段启用 edit/write guard。

白话解释

它不是让一个模型说一句“我先计划”,而是先派侦察、再问人、最后写方案。

对自研 Harness 的含义

阶段式 Harness 能把计划质量从 prompt 风格提升为可执行工作流。

关键源码 · 契约
.pi/extensions/plan-mode/index.ts · L15–L35
   15  // Plan Mode — a Claude-Code-style "research, ask, then plan" flow.
   16  //
   17  // ctrl+q toggles plan mode (an indicator appears below the input). While it is
   18  // on, submitting a prompt does NOT run a normal coding turn; instead the
   19  // extension orchestrates:
   20  //   1. decompose the request into 1-4 exploration tasks (a reasoning sub-coder),
   21  //   2. dispatch those as read-only explorer sub-coders (isolated context; only
   22  //      their concise reports survive — their transcripts never enter this window),
   23  //   3. generate 1-3 clarifying questions with suggested answers (a sub-coder),
   24  //   4. ask them via the UI (with a free-text "Other" option),
   25  //   5. synthesize the reports + answers into a written plan in the main window,
   26  //   6. exit plan mode.
   27  //
   28  // An extension can't call inference directly, so every reasoning step is a
   29  // child little-coder (spawned via ../subagent/spawn.ts), and the final plan is
   30  // injected as a normal turn via pi.sendUserMessage so it lands in the chat.
   31  //
   32  // ctrl+q is unbound by pi AND by the emacs-style editor (which claims nearly
   33  // every other ctrl+<letter> — ctrl+y is its yank/paste, ctrl+a/e line motion,
   34  // etc.), so the extension can claim it cleanly without a conflict warning or
   35  // shadowing a built-in (shift+tab stays pi's thinking-level cycle — issue #47).
查看全部 3 处证据
  • 契约 .pi/extensions/plan-mode/index.ts:15–35 六阶段 research→ask→plan 流。
  • 实现 .pi/extensions/plan-mode/index.ts:95–147 目标拆解与澄清问题生成。
  • 实现 .pi/extensions/plan-mode/index.ts:186–278 探索、问答、隐藏合成与退出计划模式。
16
L1事实little-research-001

Deep Research 用生产同一 pipeline 做多波次研究

源码事实

pipeline 顺序是澄清→brief→lead 分解→wave 1→gap 分析→可选 wave 2;研究 child 禁 bash、要求实际 URL 与不猜测,推理 child 只拿本地只读工具;每 child 有超时,失败不阻断兄弟与后续阶段,meta 记录耗时、失败和 JSON fallback。

白话解释

它像一个小型研究团队:先定题、分工、第一轮搜集,再专门找遗漏补第二轮;评测调用的也是同一套生产函数。

对自研 Harness 的含义

工作流可测性较好,但多子进程对本地推理延迟很敏感。

关键源码 · 契约
.pi/extensions/deep-research/pipeline.ts · L1–L11
    1  // UI-agnostic research phase engine — the single source of truth for the
    2  // Scope → Research pipeline (phases 1-4). Both the interactive flow
    3  // (index.ts orchestrate()) and the headless batch eval drive THIS function, so
    4  // the eval measures the same code production runs. The WRITE phase (step 5) is
    5  // intentionally NOT here: the interactive flow hands it to the main agent, and
    6  // the eval writes via a dedicated sub-coder — both take {brief, digest} from the
    7  // result below.
    8  //
    9  // Every reasoning step is a child little-coder (an extension can't call
   10  // inference directly); research waves fan out read-only research sub-coders.
   11  // UI is injected via hooks so this module has no ctx/widget dependency.
查看全部 4 处证据
  • 契约 .pi/extensions/deep-research/pipeline.ts:1–11 生产与 batch eval 共用单一 pipeline。
  • 契约 .pi/extensions/deep-research/pipeline.ts:30–61 研究/推理工具隔离、超时与 URL 证据要求。
  • 实现 .pi/extensions/deep-research/pipeline.ts:160–220 澄清、brief 与单 Agent 分支。
  • 实现 .pi/extensions/deep-research/pipeline.ts:223–290 lead、wave1、gap 和 wave2。
09
DIMENSION · OBSERVABILITY-PERSISTENCE

持久化与观测

本章共 3 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

17
L1事实little-evidence-001

证据是 session-scoped 结构化对象,并显式跨压缩

源码事实

EvidenceAdd/Get/List 保存 source、note、≤1KB snippet 到进程内 session map;消息 compaction 不会删除该 extension state,session_compact 后发送 bridge 提醒模型仍可查询。

白话解释

引用依据不只躺在长聊天里,而是放到一个小抽屉;聊天被总结后,抽屉还在。

对自研 Harness 的含义

可寻址的结构化证据比让模型从摘要里回忆来源可靠,但进程退出后不持久。

关键源码 · 实现
.pi/extensions/evidence/index.ts · L5–L42
    5  // Port of local/tools/evidence.py. Per-session in-memory store of evidence
    6  // entries. GAIA requires cite-before-answer, and these entries survive
    7  // compaction (Phase 10's evidence-compact extension preserves them).
    8  
    9  const SNIPPET_CAP = 1024;
   10  
   11  interface EvidenceEntry {
   12    id: string;
   13    source: string;
   14    note: string;
   15    snippet: string;
   16  }
   17  
   18  // Map<sessionId, entries[]>
   19  const stores = new Map<string, EvidenceEntry[]>();
   20  
   21  function sessionKey(): string {
   22    return process.env.LITTLE_CODER_SESSION_ID || "default";
   23  }
   24  
   25  function bucket(): EvidenceEntry[] {
   26    const key = sessionKey();
   27    let b = stores.get(key);
   28    if (!b) {
      … 4 lines omitted; exact range 5–42 …
   33  }
   34  
   35  // Exported so tests and the evidence-compact extension can reach in.
   36  export function resetSessionStore(sessionId?: string): void {
   37    stores.delete(sessionId ?? sessionKey());
   38  }
   39  
   40  export function getSessionStore(sessionId?: string): EvidenceEntry[] {
   41    return stores.get(sessionId ?? sessionKey()) ?? [];
   42  }
查看全部 3 处证据
  • 实现 .pi/extensions/evidence/index.ts:5–42 session map、entry shape 和重置接口。
  • 实现 .pi/extensions/evidence/index.ts:49–118 EvidenceAdd/Get/List 工具和 snippet cap。
  • 实现 .pi/extensions/evidence-compact/index.ts:4–31 扩展状态跨压缩和 bridge follow-up。
18
L1事实little-quality-001

质量监控会 steer 自纠,但最多连续两次

源码事实

turn_end 基于回答文本、当前与上一轮工具调用及观察到的 known-tools 评估失败模式;非 aborted 失败会立即 steer correction,连续超过 2 次则停止纠正并发出 intervention。

白话解释

模型答歪时 Harness 会马上插一句纠偏,但不会无限唠叨把自己困进循环。

对自研 Harness 的含义

自动修复必须带 backoff 和中断语义。

关键源码 · 契约
.pi/extensions/quality-monitor/index.ts · L5–L18
    5  // Port of local/quality.py. Hooks turn_end, inspects the assistant message
    6  // + previous turn's tool calls, and — if we detect a failure mode — sends
    7  // a correction user message with deliverAs:"steer" so the model gets it
    8  // immediately on its next turn rather than waiting for the next user input.
    9  
   10  // Session-scoped state. Pi reuses extensions across turns within a session;
   11  // a fresh extension instance is loaded per session via the session lifecycle.
   12  let previousToolCalls: ToolCall[] = [];
   13  let consecutiveFailures = 0;
   14  const MAX_CONSECUTIVE_CORRECTIONS = 2; // stop nudging after 2 failed corrections
   15  
   16  export default function (pi: ExtensionAPI) {
   17    // Populate the known-tools set lazily by observing tool_execution events.
   18    // This avoids needing to read pi's tool registry directly.
查看全部 2 处证据
  • 契约 .pi/extensions/quality-monitor/index.ts:5–18 steer 修正和连续上限。
  • 实现 .pi/extensions/quality-monitor/index.ts:30–79 aborted 排除、质量判定、backoff 与 steer。
19
L1限制little-checkpoint-001

checkpoint 是 best-effort 文件快照,且存在 path 键兼容缺口

源码事实

首次 Write/Edit 前把原文件或 absent sentinel 写到 ~/.little-coder/checkpoints/<session>;异常全部吞掉。当前 tool_call handler 只读取 input.file_path,而同仓库的现代 pi 守卫已同时兼容 path/file_path,因此 path 形态的内置工具调用可能不备份。

白话解释

它有安全网,但不是保证能回滚的事务;而且某些正常工具参数形态可能连网都没张开。

对自研 Harness 的含义

不能把该 checkpoint 当成 Git 事务或灾难恢复承诺,建设自有 Agent 时应统一 canonical ToolIntent 后再做副作用审计。

关键源码 · 实现
.pi/extensions/checkpoint/index.ts · L6–L45
    6  // Port of checkpoint/hooks.py. Snapshots a file's contents before a Write
    7  // or Edit tool modifies it. First-write-wins per session (don't re-backup
    8  // a file already tracked this session). Backups land in
    9  // ~/.little-coder/checkpoints/<session>/.
   10  
   11  const tracked = new Map<string, Set<string>>(); // sessionId -> absolute paths
   12  
   13  function checkpointDir(sessionId: string): string {
   14    const dir = join(homedir(), ".little-coder", "checkpoints", sessionId);
   15    if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
   16    return dir;
   17  }
   18  
   19  function safeName(filePath: string): string {
   20    return filePath.replace(/[^A-Za-z0-9._-]/g, "_").slice(-200);
   21  }
   22  
   23  function backupIfNeeded(sessionId: string, filePath: string): void {
   24    if (!sessionId || !filePath) return;
   25    let session = tracked.get(sessionId);
   26    if (!session) {
   27      session = new Set();
   28      tracked.set(sessionId, session);
   29    }
      … 6 lines omitted; exact range 6–45 …
   36      } else {
   37        // Sentinel: file didn't exist before modification
   38        writeFileSync(
   39          join(checkpointDir(sessionId), safeName(filePath) + ".absent"),
   40          "",
   41        );
   42      }
   43    } catch {
   44      // Silent — checkpointing is best-effort
   45    }
查看全部 3 处证据
  • 实现 .pi/extensions/checkpoint/index.ts:6–45 首写快照、absent sentinel 与吞错语义。
  • 实现 .pi/extensions/checkpoint/index.ts:48–65 事件处理只读取 file_path。
  • 实现 .pi/extensions/read-guard-edit/index.ts:32–53 同项目其他现代守卫明确兼容 path/file_path。
10
DIMENSION · PROVIDER-STREAMING

Provider、流式与重试

本章共 1 个可定位结论;结论按“实现事实 → 白话解释 → 工程影响 → 源码摘录”展开。

20
L1事实little-provider-001

面向 llama.cpp/Ollama 的 provider 注册会探测真实上下文窗

源码事实

provider 由 shipped models、用户 override 和 URL env 合并;llama.cpp 启动时调用 /props 探测 live n_ctx,模型切换后重新探测并重新注册,使 read-guard 和预算使用真实窗口;失败静默回退声明值。

白话解释

服务端若实际开了 128K,它不会死信配置里的 32K;换模型后也会重新量尺。

对自研 Harness 的含义

上下文治理依赖 provider 元数据准确,动态模型路由后应重新校准。

关键源码 · 契约
.pi/extensions/llama-cpp-provider/index.ts · L13–L21
   13  // Data-driven provider registration. Reads:
   14  //   1. <pkgRoot>/models.json                       (shipped default)
   15  //   2. $LITTLE_CODER_MODELS_FILE (if set), else
   16  //      $XDG_CONFIG_HOME/little-coder/models.json, else
   17  //      $HOME/.config/little-coder/models.json     (user override; per-provider replace)
   18  //   3. LLAMACPP_BASE_URL / OLLAMA_BASE_URL env    (per-provider baseUrl override)
   19  //
   20  // Issue #13: previously the model list was hardcoded here and models.json was
   21  // only documentation, which made any user edit a no-op until they forked.
查看全部 3 处证据
  • 契约 .pi/extensions/llama-cpp-provider/index.ts:13–21 三层 provider 配置来源。
  • 实现 .pi/extensions/llama-cpp-provider/index.ts:43–86 启动探测与 provider 注册。
  • 实现 .pi/extensions/llama-cpp-provider/index.ts:89–121 模型切换重新探测并更新窗口。
APPENDIX · SOURCE INDEX

本报告引用过的实现文件

这是一份代码阅读索引,不是仓库文件总表。机器候选扫描覆盖整个仓库;进入结论的文件必须经人工沿调用链复核。

  1. 01package.jsonL33–43
  2. 02bin/little-coder.mjsL84–139, 285–354, 481–513, 157–217, 219–227, 338–367
  3. 03.pi/extensions/context-watchdog/index.tsL3–29, 59–107, 153–223
  4. 04.pi/extensions/read-guard/index.tsL4–27, 29–82, 108–153
  5. 05.pi/extensions/_shared/inject.tsL1–27, 29–65, 67–86
  6. 06.pi/extensions/skill-inject/index.tsL8–31, 75–132, 169–178, 198–270
  7. 07.pi/extensions/knowledge-inject/index.tsL8–35, 38–77, 93–156
  8. 08.pi/extensions/write-guard/index.tsL35–75, 119–168, 158–205
  9. 09.pi/extensions/write-guard/write-guard.test.tsL197–279
  10. 10.pi/extensions/read-guard-edit/index.tsL4–29, 59–89, 32–53
  11. 11.pi/extensions/read-guard-edit/read-guard-edit.test.tsL34–99
  12. 12.pi/extensions/permission-gate/index.tsL11–58, 60–121
  13. 13.pi/extensions/shell-session/index.tsL6–16, 24–38, 65–96
  14. 14.pi/extensions/subagent/index.tsL12–20, 49–73
  15. 15.pi/extensions/subagent/spawn.tsL46–77, 251–320, 25–44, 91–121, 333–375
  16. 16.pi/extensions/tool-gating/index.tsL8–37
  17. 17.pi/extensions/plan-mode/index.tsL15–35, 95–147, 186–278
  18. 18.pi/extensions/deep-research/pipeline.tsL1–11, 30–61, 160–220, 223–290
  19. 19.pi/extensions/evidence/index.tsL5–42, 49–118
  20. 20.pi/extensions/evidence-compact/index.tsL4–31
  21. 21.pi/extensions/quality-monitor/index.tsL5–18, 30–79
  22. 22.pi/extensions/llama-cpp-provider/index.tsL13–21, 43–86, 89–121
  23. 23.pi/extensions/checkpoint/index.tsL6–45, 48–65
  24. 24.pi/extensions/output-parser/index.tsL5–20, 38–85