pi-firecode 0.8.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/LICENSE +21 -0
- package/README.md +40 -0
- package/config.example.jsonc +100 -0
- package/config.ts +474 -0
- package/deliver.ts +32 -0
- package/flame-frames.ts +460 -0
- package/format.ts +80 -0
- package/header.ts +92 -0
- package/herdr-client.ts +60 -0
- package/index.ts +62 -0
- package/jsonc.ts +34 -0
- package/master/event-card.ts +106 -0
- package/master/event-format.ts +52 -0
- package/master/index.ts +1200 -0
- package/master/prompt.ts +26 -0
- package/master/prompts/master.zh.md +17 -0
- package/master/prompts/worker.zh.md +1 -0
- package/master/role.ts +13 -0
- package/master/spawn.ts +193 -0
- package/master/state.ts +201 -0
- package/package.json +59 -0
- package/provider/claude-sub.ts +129 -0
- package/provider/openai-native/index.ts +8 -0
- package/provider/openai-native/src/compact-client.ts +362 -0
- package/provider/openai-native/src/config.ts +297 -0
- package/provider/openai-native/src/extension.ts +93 -0
- package/provider/openai-native/src/native-compaction.ts +151 -0
- package/provider/openai-native/src/native-details.ts +157 -0
- package/provider/openai-native/src/native-replay.ts +253 -0
- package/provider/openai-native/src/native-runtime.ts +144 -0
- package/provider/openai-native/src/options.ts +85 -0
- package/provider/openai-native/src/request-pipeline.ts +21 -0
- package/provider/openai-native/src/responses-input.ts +433 -0
- package/review/advisor.ts +112 -0
- package/review/card.ts +385 -0
- package/review/checkpoint.ts +384 -0
- package/review/evidence.ts +232 -0
- package/review/index.ts +1246 -0
- package/review/outcome.ts +74 -0
- package/review/progress.ts +324 -0
- package/review/prompt.ts +210 -0
- package/review/prompts/advisor.en.md +41 -0
- package/review/prompts/advisor.zh.md +42 -0
- package/review/prompts/review.en.md +75 -0
- package/review/prompts/review.zh.md +75 -0
- package/review/reviewer.ts +356 -0
- package/review/session.ts +129 -0
- package/review/state.ts +905 -0
- package/review/ui.ts +528 -0
- package/session/bark.ts +157 -0
- package/session/herdr-display.ts +87 -0
- package/session/presets.ts +257 -0
- package/session/rename.ts +46 -0
- package/session/stats.ts +310 -0
- package/session/working-flame.ts +116 -0
- package/statusbar/index.ts +118 -0
- package/statusbar/quota-cache.ts +60 -0
- package/statusbar/quota-parse.ts +85 -0
- package/statusbar/quota.ts +203 -0
- package/statusbar/render.ts +181 -0
- package/statusbar/tps.ts +87 -0
- package/theme.ts +84 -0
- package/tools/grouping.ts +233 -0
- package/tools/index.ts +183 -0
- package/tools/line.ts +194 -0
- package/tools/parts.ts +143 -0
- package/tools/timing.ts +22 -0
- package/watcher/card.ts +85 -0
- package/watcher/index.ts +204 -0
- package/watcher/observer.ts +75 -0
- package/watcher/prompts/watch.zh.md +46 -0
- package/watcher/transcript.ts +64 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { Model } from "@earendil-works/pi-ai";
|
|
2
|
+
import type { AgentSessionEvent } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import type { ThinkingLevelValue } from "../config.js";
|
|
4
|
+
import type { InProcessSessionPool } from "../master/spawn.js";
|
|
5
|
+
import type { PromptLayers } from "./prompt.js";
|
|
6
|
+
|
|
7
|
+
export type ReviewSessionResult =
|
|
8
|
+
| { kind: "output"; text: string }
|
|
9
|
+
| { kind: "empty" }
|
|
10
|
+
| { kind: "timeout" }
|
|
11
|
+
| { kind: "aborted" }
|
|
12
|
+
| { kind: "error"; message: string };
|
|
13
|
+
|
|
14
|
+
export interface ReviewSessionOptions {
|
|
15
|
+
pool: InProcessSessionPool;
|
|
16
|
+
resolveModel(id: string): Promise<Model<any>>;
|
|
17
|
+
role: "reviewer" | "advisor";
|
|
18
|
+
model: string;
|
|
19
|
+
thinking: ThinkingLevelValue;
|
|
20
|
+
tools: string[];
|
|
21
|
+
prompt: PromptLayers;
|
|
22
|
+
cwd: string;
|
|
23
|
+
timeoutMs: number;
|
|
24
|
+
signal?: AbortSignal;
|
|
25
|
+
onEvent?: (event: AgentSessionEvent) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type ReviewSessionRunner = (
|
|
29
|
+
options: Omit<ReviewSessionOptions, "pool" | "resolveModel">,
|
|
30
|
+
) => Promise<ReviewSessionResult>;
|
|
31
|
+
|
|
32
|
+
export function createReviewSessionRunner(
|
|
33
|
+
pool: InProcessSessionPool,
|
|
34
|
+
resolveModel: ReviewSessionOptions["resolveModel"],
|
|
35
|
+
): ReviewSessionRunner {
|
|
36
|
+
return (options) => runReviewSession({ ...options, pool, resolveModel });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function runReviewSession(options: ReviewSessionOptions): Promise<ReviewSessionResult> {
|
|
40
|
+
if (options.signal?.aborted) return { kind: "aborted" };
|
|
41
|
+
let spawned: Awaited<ReturnType<InProcessSessionPool["spawn"]>>;
|
|
42
|
+
try {
|
|
43
|
+
spawned = await options.pool.spawn({
|
|
44
|
+
cwd: options.cwd,
|
|
45
|
+
role: options.role,
|
|
46
|
+
model: await options.resolveModel(options.model),
|
|
47
|
+
thinking: options.thinking,
|
|
48
|
+
tools: [...new Set(options.tools)].filter((tool) => tool !== "write" && tool !== "edit"),
|
|
49
|
+
systemPrompt: { mode: "replace", text: clean(options.prompt.system) },
|
|
50
|
+
contextFiles: false,
|
|
51
|
+
persistence: { type: "memory" },
|
|
52
|
+
isolated: true,
|
|
53
|
+
});
|
|
54
|
+
} catch (error) {
|
|
55
|
+
return options.signal?.aborted
|
|
56
|
+
? { kind: "aborted" }
|
|
57
|
+
: { kind: "error", message: errorText(error) };
|
|
58
|
+
}
|
|
59
|
+
if (options.signal?.aborted) {
|
|
60
|
+
spawned.dispose();
|
|
61
|
+
return { kind: "aborted" };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let finalText: string | undefined;
|
|
65
|
+
let finalError: string | undefined;
|
|
66
|
+
const unsubscribe = spawned.session.subscribe((event) => {
|
|
67
|
+
const assistant = assistantMessage(event);
|
|
68
|
+
if (assistant) {
|
|
69
|
+
finalText = messageText(assistant.content);
|
|
70
|
+
finalError = assistant.stopReason === "error"
|
|
71
|
+
? assistant.errorMessage || "model error"
|
|
72
|
+
: undefined;
|
|
73
|
+
}
|
|
74
|
+
options.onEvent?.(event);
|
|
75
|
+
});
|
|
76
|
+
let interrupted: "aborted" | "timeout" | undefined;
|
|
77
|
+
let wake!: () => void;
|
|
78
|
+
const interruption = new Promise<void>((resolve) => { wake = resolve; });
|
|
79
|
+
const onAbort = () => { interrupted = "aborted"; wake(); };
|
|
80
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
81
|
+
const timeout = setTimeout(() => { interrupted = "timeout"; wake(); }, options.timeoutMs);
|
|
82
|
+
try {
|
|
83
|
+
const run = spawned.prompt(clean(options.prompt.user)).catch((error) => {
|
|
84
|
+
finalError = errorText(error);
|
|
85
|
+
});
|
|
86
|
+
await Promise.race([run, interruption]);
|
|
87
|
+
if (interrupted) {
|
|
88
|
+
await spawned.session.abort();
|
|
89
|
+
return { kind: interrupted };
|
|
90
|
+
}
|
|
91
|
+
if (finalError) return { kind: "error", message: finalError };
|
|
92
|
+
return finalText?.trim() ? { kind: "output", text: finalText } : { kind: "empty" };
|
|
93
|
+
} finally {
|
|
94
|
+
clearTimeout(timeout);
|
|
95
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
96
|
+
unsubscribe();
|
|
97
|
+
spawned.dispose();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function assistantMessage(event: AgentSessionEvent): {
|
|
102
|
+
role?: string;
|
|
103
|
+
content?: unknown;
|
|
104
|
+
stopReason?: string;
|
|
105
|
+
errorMessage?: string;
|
|
106
|
+
} | undefined {
|
|
107
|
+
if (event.type === "message_end") return event.message.role === "assistant" ? event.message : undefined;
|
|
108
|
+
if (event.type !== "agent_end") return undefined;
|
|
109
|
+
return [...event.messages].reverse().find((message) => message.role === "assistant");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function messageText(content: unknown): string {
|
|
113
|
+
if (typeof content === "string") return content;
|
|
114
|
+
if (!Array.isArray(content)) return "";
|
|
115
|
+
return content
|
|
116
|
+
.filter((part): part is { type: "text"; text: string } =>
|
|
117
|
+
typeof part === "object" && part !== null && (part as { type?: unknown }).type === "text"
|
|
118
|
+
&& typeof (part as { text?: unknown }).text === "string")
|
|
119
|
+
.map((part) => part.text)
|
|
120
|
+
.join("\n");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function clean(text: string): string {
|
|
124
|
+
return text.replaceAll("\0", "");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function errorText(error: unknown): string {
|
|
128
|
+
return error instanceof Error ? error.message : String(error);
|
|
129
|
+
}
|