pi-firecode 1.0.0 → 1.0.1

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.
Files changed (93) hide show
  1. package/README.md +55 -41
  2. package/README.zh-CN.md +74 -0
  3. package/config.example.jsonc +21 -22
  4. package/dist/config.example.jsonc +90 -0
  5. package/dist/index.js +11464 -0
  6. package/dist/master/prompts/master.en.md +22 -0
  7. package/{master → dist/master}/prompts/master.zh.md +3 -3
  8. package/dist/master/prompts/worker.en.md +1 -0
  9. package/dist/watcher/prompts/watch.en.md +43 -0
  10. package/package.json +10 -27
  11. package/activity.ts +0 -92
  12. package/busy.ts +0 -188
  13. package/config.ts +0 -500
  14. package/deliver.ts +0 -119
  15. package/flame.ts +0 -149
  16. package/format.ts +0 -133
  17. package/header.ts +0 -218
  18. package/herdr-client.ts +0 -60
  19. package/index.ts +0 -68
  20. package/jsonc.ts +0 -34
  21. package/master/actions.ts +0 -293
  22. package/master/activity-list.ts +0 -281
  23. package/master/event-card.ts +0 -87
  24. package/master/event-format.ts +0 -83
  25. package/master/guard.ts +0 -46
  26. package/master/index.ts +0 -252
  27. package/master/list-view.ts +0 -129
  28. package/master/outbox.ts +0 -188
  29. package/master/prompt.ts +0 -26
  30. package/master/role.ts +0 -18
  31. package/master/run.ts +0 -315
  32. package/master/runtime.ts +0 -259
  33. package/master/spawn.ts +0 -234
  34. package/master/state.ts +0 -225
  35. package/master/worker-view.ts +0 -517
  36. package/provider/claude-sub.ts +0 -151
  37. package/provider/openai-native/index.ts +0 -8
  38. package/provider/openai-native/src/compact-client.ts +0 -350
  39. package/provider/openai-native/src/config.ts +0 -297
  40. package/provider/openai-native/src/extension.ts +0 -93
  41. package/provider/openai-native/src/native-compaction.ts +0 -151
  42. package/provider/openai-native/src/native-details.ts +0 -157
  43. package/provider/openai-native/src/native-replay.ts +0 -253
  44. package/provider/openai-native/src/native-runtime.ts +0 -144
  45. package/provider/openai-native/src/options.ts +0 -87
  46. package/provider/openai-native/src/request-pipeline.ts +0 -21
  47. package/provider/openai-native/src/responses-input.ts +0 -433
  48. package/review/advisor.ts +0 -110
  49. package/review/card.ts +0 -398
  50. package/review/checkpoint.ts +0 -378
  51. package/review/evidence.ts +0 -230
  52. package/review/index.ts +0 -992
  53. package/review/occupancy.ts +0 -25
  54. package/review/outcome.ts +0 -98
  55. package/review/prompt.ts +0 -209
  56. package/review/reviewer.ts +0 -353
  57. package/review/session.ts +0 -110
  58. package/review/state.ts +0 -877
  59. package/review/ui.ts +0 -89
  60. package/round-recorder.ts +0 -18
  61. package/session/herdr-display.ts +0 -87
  62. package/session/presets.ts +0 -300
  63. package/session/quota.ts +0 -123
  64. package/session/rename.ts +0 -46
  65. package/session/stats.ts +0 -313
  66. package/statusbar/index.ts +0 -256
  67. package/statusbar/render.ts +0 -113
  68. package/theme.ts +0 -45
  69. package/tools/actions.ts +0 -53
  70. package/tools/assistant-view.ts +0 -64
  71. package/tools/click-anchor.ts +0 -56
  72. package/tools/group-view.ts +0 -420
  73. package/tools/grouping.ts +0 -158
  74. package/tools/host.ts +0 -369
  75. package/tools/index.ts +0 -186
  76. package/tools/line.ts +0 -231
  77. package/tools/machine.ts +0 -78
  78. package/tools/parts.ts +0 -143
  79. package/tools/round.ts +0 -95
  80. package/tools/timing.ts +0 -22
  81. package/tools/turn-clock.ts +0 -41
  82. package/tools/turn-summary.ts +0 -109
  83. package/truncated-write.ts +0 -18
  84. package/watcher/card.ts +0 -91
  85. package/watcher/index.ts +0 -176
  86. package/watcher/observer.ts +0 -75
  87. package/watcher/transcript.ts +0 -56
  88. /package/{master → dist/master}/prompts/worker.zh.md +0 -0
  89. /package/{review → dist/review}/prompts/advisor.en.md +0 -0
  90. /package/{review → dist/review}/prompts/advisor.zh.md +0 -0
  91. /package/{review → dist/review}/prompts/review.en.md +0 -0
  92. /package/{review → dist/review}/prompts/review.zh.md +0 -0
  93. /package/{watcher → dist/watcher}/prompts/watch.zh.md +0 -0
@@ -1,25 +0,0 @@
1
- /**
2
- * 审查占用频道:review 是唯一发布者,herdr 集成、输入框外壳与观察员订阅;频道名与 payload 只在这里定义。
3
- * 消费者按 active 的 true/false 做计数配对,所以进度变化不能靠重发 true:持有时带活的 progress 访问器,
4
- * 外壳每次绘制调用它。progress 是进程内求值函数,频道不可序列化转发。
5
- */
6
- export const OCCUPANCY_CHANNEL = "herdr:blocked";
7
- /** 持有时的展示标签:herdr 侧边栏与 Master 的 state_labels 判定都读它。 */
8
- export const OCCUPANCY_LABEL = "对抗审查进行中";
9
-
10
- /** 审查此刻在哪一步:排队等回合结束、审查者在审、顾问介入、执行模型修复、总结回合。 */
11
- export type ReviewStage = "queued" | "reviewing" | "advisor" | "fixing" | "summarizing";
12
-
13
- export interface ReviewProgress {
14
- stage: ReviewStage;
15
- /** 当前轮次;排队时为 0。 */
16
- round: number;
17
- /** 本轮通过 / 阻断 / 审查者总数;只有 reviewing 有意义。 */
18
- passed: number;
19
- blocked: number;
20
- total: number;
21
- }
22
-
23
- export type OccupancyPayload =
24
- | { active: true; label: string; progress: () => ReviewProgress | undefined }
25
- | { active: false };
package/review/outcome.ts DELETED
@@ -1,98 +0,0 @@
1
- import { readFileSync } from "node:fs";
2
- import { CHECKPOINT_TYPE, isValidCheckpoint } from "./checkpoint.js";
3
- import type { ReviewState } from "./state.js";
4
-
5
- export type ReviewOutcome =
6
- | { status: "passed"; runId: string; rounds: number }
7
- | { status: "stopped"; runId: string; rounds: number; advisorAdvice?: string }
8
- | { status: "failed"; runId: string; rounds: number; reason: string }
9
- | { status: "in_progress"; runId: string }
10
- | { status: "none"; runId?: string }
11
- | { status: "error"; message: string };
12
-
13
- /** 只读 Worker session,解析最近一条 fire-review checkpoint 的判定;会话结束时的一次性兜底读取用它。 */
14
- export function readReviewOutcome(sessionPath: string): ReviewOutcome {
15
- let content: string;
16
- try {
17
- content = readFileSync(sessionPath, "utf8");
18
- } catch (error) {
19
- if (isMissingFile(error)) return { status: "none" };
20
- return { status: "error", message: `无法读取 session 文件:${errorMessage(error)}` };
21
- }
22
-
23
- let latest: ReviewState | undefined;
24
- let damage: string | undefined;
25
- // session 尾行可能正写到一半;跳过损坏行并保留最近一条可验证记录,
26
- // 不能让截断尾行抹掉已有结果。
27
- for (const [index, line] of content.split(/\r?\n/u).entries()) {
28
- if (!line.trim()) continue;
29
- let entry: unknown;
30
- try {
31
- entry = JSON.parse(line);
32
- } catch {
33
- damage ??= `session 第 ${index + 1} 行不是有效 JSON`;
34
- continue;
35
- }
36
- if (!isCheckpointEntry(entry)) continue;
37
- if (isValidCheckpoint(entry.data)) latest = entry.data as ReviewState;
38
- else damage ??= "fire-review checkpoint 格式无效";
39
- }
40
- if (!latest) return damage ? { status: "error", message: damage } : { status: "none" };
41
- return outcomeOf(latest);
42
- }
43
-
44
- /** 会话事件里刚追加的一条记录若是有效 checkpoint,给出它的判定;订阅方据此增量跟进,不重读整份 JSONL。 */
45
- export function outcomeOfEntry(entry: unknown): ReviewOutcome | undefined {
46
- const state = checkpointOf(entry);
47
- return state && outcomeOf(state);
48
- }
49
-
50
- /** 审查进行中的轮次与审查者进度;不是审查相的 checkpoint 或不是 checkpoint 都给 undefined。 */
51
- export interface ReviewProgress {
52
- round: number;
53
- settled: number;
54
- total: number;
55
- }
56
-
57
- export function reviewProgressOf(entry: unknown): ReviewProgress | undefined {
58
- const active = checkpointOf(entry)?.active;
59
- return active ? { round: active.round, settled: active.settledCount, total: active.reviewers.length } : undefined;
60
- }
61
-
62
- function checkpointOf(entry: unknown): ReviewState | undefined {
63
- return isCheckpointEntry(entry) && isValidCheckpoint(entry.data) ? entry.data as ReviewState : undefined;
64
- }
65
-
66
- function outcomeOf(latest: ReviewState): ReviewOutcome {
67
- if (latest.phase === "idle") return { status: "none", runId: latest.runId };
68
- if (latest.phase !== "settled") return { status: "in_progress", runId: latest.runId };
69
- const rounds = latest.history.length;
70
- const last = latest.history.at(-1);
71
- const result = last?.result;
72
- if (result === "passed") return { status: "passed", runId: latest.runId, rounds };
73
- // stopped(顾问叫停)与 failed(maxRounds 用尽)都是质量裁决终止;
74
- // error / cancelled / timed_out 是基础设施故障或人为中断,不弱化成“停止”。
75
- if (result === "stopped" || result === "failed") {
76
- // 顾问叫停时把裁决带给读取方:Master 拿到停止原因才能调整方向。
77
- const advice = last?.advisor?.advice;
78
- return { status: "stopped", runId: latest.runId, rounds, ...(advice ? { advisorAdvice: advice } : {}) };
79
- }
80
- // 轮记录的 details 已写明故障形态(超时/供应商报错);枚举名只是它缺失时的兜底。
81
- return { status: "failed", runId: latest.runId, rounds, reason: last?.details?.trim() || result || "unknown" };
82
- }
83
-
84
- function isCheckpointEntry(value: unknown): value is { data: unknown } {
85
- return typeof value === "object" && value !== null
86
- && (value as Record<string, unknown>).type === "custom"
87
- && (value as Record<string, unknown>).customType === CHECKPOINT_TYPE
88
- && "data" in value;
89
- }
90
-
91
- function isMissingFile(error: unknown): boolean {
92
- return typeof error === "object" && error !== null
93
- && (error as { code?: unknown }).code === "ENOENT";
94
- }
95
-
96
- function errorMessage(error: unknown): string {
97
- return error instanceof Error ? error.message : String(error);
98
- }
package/review/prompt.ts DELETED
@@ -1,209 +0,0 @@
1
- /**
2
- * Prompt 组装:纯函数拼装审查 / 顾问 / 修复反馈文本。
3
- * 模板文件读取是唯一 IO(readPrompt),拼装本身零副作用可单测。
4
- */
5
- import { readFileSync } from "node:fs";
6
- import { dirname, join } from "node:path";
7
- import { fileURLToPath } from "node:url";
8
- import type { Language } from "../config.js";
9
- import { wrapEnvelope } from "../deliver.js";
10
- import type { AdvisorResult, ReviewState, SummaryKind } from "./state.js";
11
-
12
- const PROMPTS_DIR = join(dirname(fileURLToPath(import.meta.url)), "prompts");
13
-
14
- export type PromptKind = "review" | "advisor";
15
-
16
- export function readPrompt(kind: PromptKind, language: Language): string {
17
- return readFileSync(join(PROMPTS_DIR, `${kind}.${language}.md`), "utf8");
18
- }
19
-
20
- export interface ReviewPromptInput {
21
- language: Language;
22
- scope: string;
23
- focus: string;
24
- evidence: string;
25
- history: ReviewState["history"];
26
- round: number;
27
- }
28
-
29
- export interface PromptLayers {
30
- system: string;
31
- user: string;
32
- }
33
-
34
- /** 审查政策走 system 层;需求与历史留在 user 层,不能反向改写审查契约。 */
35
- export function buildReviewPrompt(template: string, input: ReviewPromptInput): PromptLayers {
36
- const sep = input.language === "en" ? ":" : ":";
37
- const evidence = input.evidence.replaceAll("</session_evidence>", "&lt;/session_evidence&gt;");
38
- const parts = [
39
- `${input.language === "en" ? "Review target" : "审查对象"}${sep}\n${input.scope}`,
40
- ];
41
- if (input.focus)
42
- parts.push(`${input.language === "en" ? "Focus" : "关注点"}${sep}\n${input.focus}`);
43
- const prior = priorRoundsSection(input.history, input.round, input.language);
44
- if (prior) parts.push(prior);
45
- parts.push(
46
- `${input.language === "en" ? "Session record" : "会话记录"}${sep}\n<session_evidence>\n${evidence}\n</session_evidence>`,
47
- reviewReminder(input.language),
48
- );
49
- return promptLayers(
50
- template,
51
- parts.filter((part) => part !== "").join("\n\n"),
52
- input.language,
53
- );
54
- }
55
-
56
- function promptLayers(system: string, user: string, language: Language): PromptLayers {
57
- if (!system.trim())
58
- throw new Error(
59
- language === "en" ? "FireReview system prompt is empty" : "FireReview system prompt 为空",
60
- );
61
- return { system, user };
62
- }
63
-
64
- function reviewReminder(language: Language) {
65
- return language === "en"
66
- ? "Now complete the review under the system prompt and strictly follow its output contract."
67
- : "现在按 system prompt 的审查规则完成审查,并严格遵守其输出契约。";
68
- }
69
-
70
- /** 往轮 FAIL 发现清单(两相收敛的闭环输入):第 2 轮起注入。 */
71
- function priorRoundsSection(
72
- history: ReviewState["history"],
73
- round: number,
74
- language: Language,
75
- ): string | undefined {
76
- const prior = history.filter((entry) => entry.round < round && entry.result === "failed");
77
- if (round <= 1 || prior.length === 0) return undefined;
78
- const header =
79
- language === "en"
80
- ? "Prior round findings (newest first)"
81
- : "往轮发现清单(由新到旧):";
82
- const body = prior
83
- .map((entry) => {
84
- const label =
85
- language === "en" ? `## Round ${entry.round} · failed` : `## 第 ${entry.round} 轮 · 未通过`;
86
- // 顾问裁决必须随轮注入:否则被顾问排除的发现会在后续轮被审查者原样重提,循环无法收敛。
87
- const advisor = entry.advisor
88
- ? `\n\n### ${language === "en" ? "Advisor ruling" : "顾问裁决"}(${entry.advisor.verdict})\n${entry.advisor.advice}`
89
- : "";
90
- return `${label}\n${entry.details}${advisor}`;
91
- })
92
- .join("\n\n");
93
- return `${header}\n${body}`;
94
- }
95
-
96
- export interface AdvisorPromptInput {
97
- language: Language;
98
- focus: string;
99
- details: string;
100
- history: ReviewState["history"];
101
- round: number;
102
- }
103
-
104
- export function buildAdvisorPrompt(template: string, input: AdvisorPromptInput): PromptLayers {
105
- const sep = input.language === "en" ? ":" : ":";
106
- const parts: string[] = [];
107
- if (input.focus)
108
- parts.push(`${input.language === "en" ? "Review focus" : "审查关注点"}${sep}\n${input.focus}`);
109
- parts.push(
110
- `${input.language === "en" ? "This round FAIL findings" : "本轮 FAIL 发现"}${sep}\n${input.details}`,
111
- );
112
- const prior = priorRoundsSection(input.history, input.round, input.language);
113
- if (prior) parts.push(`${input.language === "en" ? "Prior FAIL history" : "往轮 FAIL 历史"}${sep}\n${prior}`);
114
- parts.push(
115
- input.language === "en"
116
- ? "Now arbitrate under the system prompt and strictly follow its output contract."
117
- : "现在按 system prompt 的规则完成仲裁,并严格遵守其输出契约。",
118
- );
119
- return promptLayers(template, parts.join("\n\n"), input.language);
120
- }
121
-
122
- export interface FixFeedbackInput {
123
- language: Language;
124
- details: string;
125
- advisor: AdvisorResult | null;
126
- }
127
-
128
- /** 投递给执行模型的修复反馈:把审查发现当假设核实,修根因不压表象。 */
129
- export function buildFixFeedback(input: FixFeedbackInput): string {
130
- // narrow 与 continue 必须产生可区分的行为:narrow 不再要求逐条修全部发现,
131
- // 而是把顾问给的范围当约束,只修真正阻塞当前需求的那部分。
132
- const narrowed = input.advisor?.verdict === "narrow";
133
- const parts = [narrowInstruction(input.language, narrowed), "", input.details];
134
- if (input.advisor?.advice) {
135
- const label =
136
- input.language === "en"
137
- ? narrowed
138
- ? "Advisor scope (authoritative)"
139
- : "Advisor note"
140
- : narrowed
141
- ? "顾问收窄后的范围(以此为准)"
142
- : "顾问建议";
143
- parts.push("", `${label}${input.language === "en" ? ":" : ":"}`, input.advisor.advice);
144
- }
145
- return wrapEnvelope("firecode_review", parts.join("\n"));
146
- }
147
-
148
-
149
- function narrowInstruction(language: Language, narrowed: boolean) {
150
- if (!narrowed) return language === "en" ? FIX_INSTRUCTION_EN : FIX_INSTRUCTION_ZH;
151
- return language === "en" ? NARROW_INSTRUCTION_EN : NARROW_INSTRUCTION_ZH;
152
- }
153
-
154
- const FIX_INSTRUCTION_ZH =
155
- "本轮审查未通过,请修复以下发现。将审查反馈视为待核实假设,而非事实:先基于当前文件、测试/检查输出和会话约束核实。反馈属实时,逐条修复全部属实发现,修根因而非表象,同一根因的其他出现点一并修复,修完端到端验证问题已彻底解决后直接结束(本回合结束后会自动进入下一轮复审);避免无关重构、抽象、依赖或风格改动。反馈不成立时,不应用该反馈,并说明依据(文件、命令输出或约束)。";
156
-
157
- const NARROW_INSTRUCTION_ZH =
158
- "本轮审查未通过,但顾问判定发现清单范围过宽。下方是完整发现,仅供参考:只修顾问收窄后的范围内、真正阻塞当前需求的那部分,其余发现不要处理。先根据当前文件与命令输出核实再修,修根因不压表象,修复验证后直接结束(本回合结束后会自动进入下一轮复审);避免无关重构、抽象、依赖或风格改动。若认为收窄范围内的发现也不成立,说明依据并停下。";
159
-
160
- const NARROW_INSTRUCTION_EN =
161
- "This round's review failed, but the advisor judged the finding list too broad. The full findings below are context only: fix only the part inside the advisor's narrowed scope that actually blocks the current requirement, and leave the rest alone. Verify against current files and command output before fixing, fix root causes not symptoms, and finish directly after verification (the next review round will start automatically); avoid unrelated refactors, abstractions, dependency or style changes. If even the narrowed findings do not hold, explain why and stop.";
162
-
163
- /** 总结提示携带的终态材料上限:模型已经历过修复轮,材料只补它没见过的终态结论。 */
164
- const SUMMARY_MATERIAL_LIMIT = 4_000;
165
-
166
- export interface SummaryPromptInput {
167
- language: Language;
168
- kind: SummaryKind;
169
- rounds: number;
170
- /** 终态材料:通过=末轮审查结论;max_rounds=末轮发现;advisor_stop=顾问裁决。 */
171
- material: string;
172
- }
173
-
174
- /** 质量裁决终态后投给执行模型的总结回合提示:人话收尾,带反循环禁令。 */
175
- export function buildSummaryPrompt(input: SummaryPromptInput): string {
176
- const omitted = input.material.length - SUMMARY_MATERIAL_LIMIT;
177
- const material = omitted > 0
178
- ? `${input.material.slice(0, SUMMARY_MATERIAL_LIMIT)}\n${input.language === "en" ? `[material truncated: ${omitted} characters omitted]` : `[材料截断:省略 ${omitted} 字]`}`
179
- : input.material;
180
- const body = summaryInstruction(input.language, input.kind, input.rounds);
181
- const content = material.trim()
182
- ? `${body}\n\n${summaryMaterialLabel(input.language, input.kind)}\n${material}`
183
- : body;
184
- return wrapEnvelope("firecode_review", content);
185
- }
186
-
187
- function summaryMaterialLabel(language: Language, kind: SummaryKind): string {
188
- if (kind === "advisor_stop") return language === "en" ? "Advisor ruling:" : "顾问裁决:";
189
- if (kind === "max_rounds") return language === "en" ? "Final round findings:" : "末轮未通过的发现:";
190
- return language === "en" ? "Final review verdict:" : "末轮审查结论:";
191
- }
192
-
193
- function summaryInstruction(language: Language, kind: SummaryKind, rounds: number): string {
194
- if (language === "en") {
195
- if (kind === "passed")
196
- return `The adversarial review passed after ${rounds} round(s). Give the user a concise plain-language wrap-up: 1) what the review rounds found and what you fixed; 2) how it finally passed (key fixes and verification evidence); 3) non-blocking suggestions raised during review — list each and say whether you recommend addressing it and why. Summary only: do not change code or run tools; end this turn with the final reply.`;
197
- if (kind === "max_rounds")
198
- return `The adversarial review did not pass within ${rounds} round(s) and stopped at the limit. Summarize honestly for the user in plain language: 1) what each round got stuck on and what fixes you attempted; 2) your root-cause read on why it would not converge; 3) the real current state of the code and remaining risks; 4) what you recommend the user do next. Summary only: do not keep changing code or run tools; end this turn with the final reply.`;
199
- return `The adversarial review was stopped by the advisor (round ${rounds}). Using the advisor ruling below, summarize for the user: 1) how far the review loop got and what was fixed; 2) why the advisor called it off; 3) the current state and your recommended next step. Summary only: do not change code or run tools; end this turn with the final reply.`;
200
- }
201
- if (kind === "passed")
202
- return `对抗审查已通过(共 ${rounds} 轮)。请给用户一个简洁的人话收尾总结:1) 各轮审查发现了什么、你修了什么;2) 最终靠什么通过(关键修复与验证证据);3) 审查中提到但未阻塞通过的建议——逐条列出,并给出你建议处理还是不处理及理由。只做总结:不要修改代码、不要运行工具,直接以最终回复结束本回合。`;
203
- if (kind === "max_rounds")
204
- return `对抗审查在 ${rounds} 轮内未能通过,已按上限终止。请如实向用户总结(人话):1) 各轮分别卡在什么发现上、你做了哪些修复尝试;2) 你认为无法收敛的根因;3) 当前代码的真实状态与剩余风险;4) 建议用户下一步怎么办。只做总结:不要再继续修改代码或运行工具,直接以最终回复结束本回合。`;
205
- return `对抗审查被顾问裁定终止(第 ${rounds} 轮)。请结合下方顾问裁决向用户总结:1) 审查循环走到了哪一步、修了什么;2) 顾问为什么叫停;3) 当前状态与你建议的下一步。只做总结:不要再修改代码或运行工具,直接以最终回复结束本回合。`;
206
- }
207
-
208
- const FIX_INSTRUCTION_EN =
209
- "This round's review failed. Fix the findings below. Treat the review feedback as hypotheses to verify, not facts: verify against current files, test/check output and session constraints. When feedback is valid, fix every valid finding, fixing root causes not symptoms and other occurrences of the same root cause, and verify end-to-end that issues are truly resolved then finish directly (the next review round will start automatically); avoid unrelated refactors, abstractions, dependency or style changes. When feedback is not valid, do not apply it and explain why (files, command output, or constraints).";