@cryer/star-cli 0.3.5 → 0.3.7
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/README.md +97 -38
- package/README.zh-CN.md +95 -39
- package/dist/chunk-4X25DNTF.js +1441 -0
- package/dist/chunk-4X25DNTF.js.map +1 -0
- package/dist/{chunk-OIDB2E5J.js → chunk-OOOW7FC4.js} +1574 -200
- package/dist/chunk-OOOW7FC4.js.map +1 -0
- package/dist/{loop-H5RYTO2O.js → loop-DVVPIOS7.js} +2 -3
- package/dist/main.js +126 -5975
- package/dist/main.js.map +1 -1
- package/dist/repl-RT6HBM5B.js +5464 -0
- package/dist/repl-RT6HBM5B.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-B6P4VUBE.js +0 -122
- package/dist/chunk-B6P4VUBE.js.map +0 -1
- package/dist/chunk-OIDB2E5J.js.map +0 -1
- package/dist/stream-H4BYBVAZ.js +0 -184
- package/dist/stream-H4BYBVAZ.js.map +0 -1
- /package/dist/{loop-H5RYTO2O.js.map → loop-DVVPIOS7.js.map} +0 -0
package/dist/stream-H4BYBVAZ.js
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
starHome,
|
|
4
|
-
summarizeStreamError
|
|
5
|
-
} from "./chunk-B6P4VUBE.js";
|
|
6
|
-
|
|
7
|
-
// src/llm/stream.ts
|
|
8
|
-
import { streamText } from "ai";
|
|
9
|
-
|
|
10
|
-
// src/llm/debug.ts
|
|
11
|
-
import { appendFileSync } from "fs";
|
|
12
|
-
import path from "path";
|
|
13
|
-
function debugStreamLog(event, data) {
|
|
14
|
-
if (!process.env.STAR_DEBUG) return;
|
|
15
|
-
try {
|
|
16
|
-
const line = `${JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), event, ...data })}
|
|
17
|
-
`;
|
|
18
|
-
appendFileSync(path.join(starHome(), "debug.log"), line);
|
|
19
|
-
} catch {
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// src/llm/stream.ts
|
|
24
|
-
var DEFAULT_IDLE_TIMEOUT_MS = 2e4;
|
|
25
|
-
var DEFAULT_FIRST_PART_TIMEOUT_MS = 12e4;
|
|
26
|
-
var CACHE_READ_KEYS = ["cacheReadInputTokens", "cache_read_input_tokens"];
|
|
27
|
-
var CACHED_PROMPT_KEYS = ["cachedPromptTokens", "cached_prompt_tokens", "cachedTokens"];
|
|
28
|
-
function extractCacheUsage(providerMetadata) {
|
|
29
|
-
if (!providerMetadata || typeof providerMetadata !== "object") return {};
|
|
30
|
-
for (const value of Object.values(providerMetadata)) {
|
|
31
|
-
if (!value || typeof value !== "object") continue;
|
|
32
|
-
const record = value;
|
|
33
|
-
for (const key of CACHE_READ_KEYS) {
|
|
34
|
-
const n = record[key];
|
|
35
|
-
if (typeof n === "number" && Number.isFinite(n)) return { cacheReadInputTokens: n };
|
|
36
|
-
}
|
|
37
|
-
for (const key of CACHED_PROMPT_KEYS) {
|
|
38
|
-
const n = record[key];
|
|
39
|
-
if (typeof n === "number" && Number.isFinite(n)) return { cachedPromptTokens: n };
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return {};
|
|
43
|
-
}
|
|
44
|
-
async function* streamChat(opts) {
|
|
45
|
-
const controller = new AbortController();
|
|
46
|
-
const onAbort = () => controller.abort();
|
|
47
|
-
opts.abortSignal?.addEventListener("abort", onAbort);
|
|
48
|
-
if (opts.abortSignal?.aborted) controller.abort();
|
|
49
|
-
const result = streamText({
|
|
50
|
-
model: opts.model,
|
|
51
|
-
messages: opts.messages,
|
|
52
|
-
tools: opts.tools,
|
|
53
|
-
abortSignal: controller.signal,
|
|
54
|
-
maxTokens: opts.maxTokens,
|
|
55
|
-
// Disable the SDK's own retries (ai@4 defaults to 2 internal attempts with
|
|
56
|
-
// fixed backoff that ignores Retry-After and the abort signal, and
|
|
57
|
-
// exhaustion throws an AI_RetryError stripped of status/headers/body) —
|
|
58
|
-
// the retry policy in agent/loop.ts + llm/retry.ts owns the full budget
|
|
59
|
-
// and needs the raw error to classify.
|
|
60
|
-
maxRetries: 0,
|
|
61
|
-
experimental_providerMetadata: {
|
|
62
|
-
// Only the openai provider (our responses-protocol path) reads these;
|
|
63
|
-
// other providers ignore unknown metadata. The SDK's responses provider
|
|
64
|
-
// sends every tool with strict:true by default (strictSchemas), and
|
|
65
|
-
// strict mode requires every schema property to be required — our
|
|
66
|
-
// classic function-calling schemas use optional properties, which
|
|
67
|
-
// relays then reject. store:false matches how codex and opencode talk
|
|
68
|
-
// to relays (no server-side response storage).
|
|
69
|
-
openai: { strictSchemas: false, store: false }
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
const idleTimeoutMs = opts.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
73
|
-
const firstPartTimeoutMs = opts.firstPartTimeoutMs ?? DEFAULT_FIRST_PART_TIMEOUT_MS;
|
|
74
|
-
const iterator = result.fullStream[Symbol.asyncIterator]();
|
|
75
|
-
let seenPart = false;
|
|
76
|
-
let deltas = 0;
|
|
77
|
-
let hasContent = false;
|
|
78
|
-
debugStreamLog("request", {
|
|
79
|
-
messages: opts.messages.length,
|
|
80
|
-
idleTimeoutMs,
|
|
81
|
-
firstPartTimeoutMs
|
|
82
|
-
});
|
|
83
|
-
try {
|
|
84
|
-
for (; ; ) {
|
|
85
|
-
let timer;
|
|
86
|
-
const idle = new Promise((resolve) => {
|
|
87
|
-
timer = setTimeout(() => resolve(null), seenPart ? idleTimeoutMs : firstPartTimeoutMs);
|
|
88
|
-
});
|
|
89
|
-
let next;
|
|
90
|
-
try {
|
|
91
|
-
next = await Promise.race([iterator.next(), idle]);
|
|
92
|
-
} catch (error) {
|
|
93
|
-
debugStreamLog("stream-throw", {
|
|
94
|
-
seenPart,
|
|
95
|
-
deltas,
|
|
96
|
-
error: error instanceof Error ? summarizeStreamError(error) : String(error)
|
|
97
|
-
});
|
|
98
|
-
throw error;
|
|
99
|
-
} finally {
|
|
100
|
-
if (timer) clearTimeout(timer);
|
|
101
|
-
}
|
|
102
|
-
if (next === null) {
|
|
103
|
-
debugStreamLog("idle-timeout", {
|
|
104
|
-
seenPart,
|
|
105
|
-
deltas,
|
|
106
|
-
waitedMs: seenPart ? idleTimeoutMs : firstPartTimeoutMs
|
|
107
|
-
});
|
|
108
|
-
yield {
|
|
109
|
-
type: "finish",
|
|
110
|
-
finishReason: "idle-timeout",
|
|
111
|
-
usage: void 0,
|
|
112
|
-
// Content already streamed means the reply may be cut off
|
|
113
|
-
// mid-thought; the loop surfaces a notice for that.
|
|
114
|
-
...hasContent ? { truncated: true } : {}
|
|
115
|
-
};
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
if (next.done) {
|
|
119
|
-
debugStreamLog("end", { seenPart, deltas });
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
seenPart = true;
|
|
123
|
-
const part = next.value;
|
|
124
|
-
switch (part.type) {
|
|
125
|
-
case "text-delta":
|
|
126
|
-
deltas++;
|
|
127
|
-
hasContent = true;
|
|
128
|
-
yield { type: "text-delta", text: part.textDelta };
|
|
129
|
-
break;
|
|
130
|
-
case "reasoning":
|
|
131
|
-
deltas++;
|
|
132
|
-
hasContent = true;
|
|
133
|
-
yield { type: "reasoning", text: part.textDelta };
|
|
134
|
-
break;
|
|
135
|
-
case "tool-call":
|
|
136
|
-
hasContent = true;
|
|
137
|
-
yield {
|
|
138
|
-
type: "tool-call",
|
|
139
|
-
id: part.toolCallId,
|
|
140
|
-
name: part.toolName,
|
|
141
|
-
args: part.args
|
|
142
|
-
};
|
|
143
|
-
break;
|
|
144
|
-
case "finish": {
|
|
145
|
-
const finite = (n) => Number.isFinite(n) ? n : 0;
|
|
146
|
-
const cache = extractCacheUsage(
|
|
147
|
-
part.providerMetadata ?? part.experimental_providerMetadata
|
|
148
|
-
);
|
|
149
|
-
debugStreamLog("finish", {
|
|
150
|
-
finishReason: part.finishReason,
|
|
151
|
-
usage: part.usage,
|
|
152
|
-
deltas
|
|
153
|
-
});
|
|
154
|
-
yield {
|
|
155
|
-
type: "finish",
|
|
156
|
-
finishReason: part.finishReason,
|
|
157
|
-
usage: part.usage ? {
|
|
158
|
-
promptTokens: finite(part.usage.promptTokens),
|
|
159
|
-
completionTokens: finite(part.usage.completionTokens),
|
|
160
|
-
totalTokens: finite(part.usage.totalTokens),
|
|
161
|
-
...cache
|
|
162
|
-
} : void 0
|
|
163
|
-
};
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
case "error": {
|
|
167
|
-
if (opts.abortSignal?.aborted) return;
|
|
168
|
-
const error = part.error instanceof Error ? part.error : new Error(String(part.error));
|
|
169
|
-
debugStreamLog("error-part", { seenPart, deltas, error: summarizeStreamError(error) });
|
|
170
|
-
yield { type: "error", error };
|
|
171
|
-
break;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
} finally {
|
|
176
|
-
opts.abortSignal?.removeEventListener("abort", onAbort);
|
|
177
|
-
controller.abort();
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
export {
|
|
181
|
-
extractCacheUsage,
|
|
182
|
-
streamChat
|
|
183
|
-
};
|
|
184
|
-
//# sourceMappingURL=stream-H4BYBVAZ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/llm/stream.ts","../src/llm/debug.ts"],"sourcesContent":["import { type LanguageModel, type ToolSet, streamText } from \"ai\";\nimport type { StreamEvent, TokenUsage } from \"../core/events\";\nimport type { CoreMessage } from \"../core/messages\";\nimport { debugStreamLog } from \"./debug\";\nimport { summarizeStreamError } from \"./retry\";\n\nexport interface StreamChatOptions {\n model: LanguageModel;\n messages: CoreMessage[];\n tools?: Record<string, unknown>;\n abortSignal?: AbortSignal;\n maxTokens?: number;\n // Idle watchdog: some relays deliver the final content but never send the\n // terminal chunks (or never close the socket). If no stream part arrives\n // within this window once streaming has started, the stream is ended\n // gracefully with what we have.\n idleTimeoutMs?: number;\n // Separate, longer allowance for the very first part: thinking models and\n // slow relays can take a while before producing anything, and a false\n // timeout here would kill a healthy request.\n firstPartTimeoutMs?: number;\n}\n\nconst DEFAULT_IDLE_TIMEOUT_MS = 20_000;\nconst DEFAULT_FIRST_PART_TIMEOUT_MS = 120_000;\n\nconst CACHE_READ_KEYS = [\"cacheReadInputTokens\", \"cache_read_input_tokens\"];\nconst CACHED_PROMPT_KEYS = [\"cachedPromptTokens\", \"cached_prompt_tokens\", \"cachedTokens\"];\n\n// Pulls prompt-cache token counts out of a finish part's providerMetadata.\n// Anthropic-style fields (cacheReadInputTokens) report cache reads on top of\n// promptTokens; OpenAI-style fields (cachedPromptTokens) are a subset of it.\n// Only finite numbers are accepted; anything else means \"not provided\".\nexport function extractCacheUsage(\n providerMetadata: unknown,\n): Pick<TokenUsage, \"cachedPromptTokens\" | \"cacheReadInputTokens\"> {\n if (!providerMetadata || typeof providerMetadata !== \"object\") return {};\n for (const value of Object.values(providerMetadata)) {\n if (!value || typeof value !== \"object\") continue;\n const record = value as Record<string, unknown>;\n for (const key of CACHE_READ_KEYS) {\n const n = record[key];\n if (typeof n === \"number\" && Number.isFinite(n)) return { cacheReadInputTokens: n };\n }\n for (const key of CACHED_PROMPT_KEYS) {\n const n = record[key];\n if (typeof n === \"number\" && Number.isFinite(n)) return { cachedPromptTokens: n };\n }\n }\n return {};\n}\n\nexport async function* streamChat(opts: StreamChatOptions): AsyncGenerator<StreamEvent> {\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n opts.abortSignal?.addEventListener(\"abort\", onAbort);\n // Abort listeners only fire on future aborts: mirror an abort that already\n // happened before this listener was registered (Esc landing while the loop\n // was still preparing the request), or the request would run on until the\n // idle watchdog despite having been cancelled.\n if (opts.abortSignal?.aborted) controller.abort();\n const result = streamText({\n model: opts.model,\n messages: opts.messages,\n tools: opts.tools as ToolSet | undefined,\n abortSignal: controller.signal,\n maxTokens: opts.maxTokens,\n // Disable the SDK's own retries (ai@4 defaults to 2 internal attempts with\n // fixed backoff that ignores Retry-After and the abort signal, and\n // exhaustion throws an AI_RetryError stripped of status/headers/body) —\n // the retry policy in agent/loop.ts + llm/retry.ts owns the full budget\n // and needs the raw error to classify.\n maxRetries: 0,\n experimental_providerMetadata: {\n // Only the openai provider (our responses-protocol path) reads these;\n // other providers ignore unknown metadata. The SDK's responses provider\n // sends every tool with strict:true by default (strictSchemas), and\n // strict mode requires every schema property to be required — our\n // classic function-calling schemas use optional properties, which\n // relays then reject. store:false matches how codex and opencode talk\n // to relays (no server-side response storage).\n openai: { strictSchemas: false, store: false },\n },\n });\n const idleTimeoutMs = opts.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;\n const firstPartTimeoutMs = opts.firstPartTimeoutMs ?? DEFAULT_FIRST_PART_TIMEOUT_MS;\n const iterator = result.fullStream[Symbol.asyncIterator]();\n let seenPart = false;\n let deltas = 0;\n // Any visible content streamed (text, reasoning, or a tool call) — decides\n // whether an idle-watchdog cutoff marks the finish event as truncated.\n let hasContent = false;\n debugStreamLog(\"request\", {\n messages: opts.messages.length,\n idleTimeoutMs,\n firstPartTimeoutMs,\n });\n try {\n for (;;) {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const idle = new Promise<null>((resolve) => {\n timer = setTimeout(() => resolve(null), seenPart ? idleTimeoutMs : firstPartTimeoutMs);\n });\n let next: Awaited<ReturnType<typeof iterator.next>> | null;\n try {\n next = await Promise.race([iterator.next(), idle]);\n } catch (error) {\n debugStreamLog(\"stream-throw\", {\n seenPart,\n deltas,\n error: error instanceof Error ? summarizeStreamError(error) : String(error),\n });\n throw error;\n } finally {\n // Clear in finally: when iterator.next() rejects, skipping this would\n // leave the watchdog timer pending for up to the full first-part\n // allowance.\n if (timer) clearTimeout(timer);\n }\n if (next === null) {\n // Note: the AI SDK holds the model's finish part until the source\n // stream closes, so a relay that stops sending without closing can\n // only be detected by this watchdog.\n debugStreamLog(\"idle-timeout\", {\n seenPart,\n deltas,\n waitedMs: seenPart ? idleTimeoutMs : firstPartTimeoutMs,\n });\n yield {\n type: \"finish\",\n finishReason: \"idle-timeout\",\n usage: undefined,\n // Content already streamed means the reply may be cut off\n // mid-thought; the loop surfaces a notice for that.\n ...(hasContent ? { truncated: true } : {}),\n };\n return;\n }\n if (next.done) {\n debugStreamLog(\"end\", { seenPart, deltas });\n return;\n }\n seenPart = true;\n const part = next.value;\n switch (part.type) {\n case \"text-delta\":\n deltas++;\n hasContent = true;\n yield { type: \"text-delta\", text: part.textDelta };\n break;\n case \"reasoning\":\n deltas++;\n hasContent = true;\n yield { type: \"reasoning\", text: part.textDelta };\n break;\n case \"tool-call\":\n hasContent = true;\n yield {\n type: \"tool-call\",\n id: part.toolCallId,\n name: part.toolName,\n args: part.args,\n };\n break;\n case \"finish\": {\n const finite = (n: number) => (Number.isFinite(n) ? n : 0);\n const cache = extractCacheUsage(\n part.providerMetadata ?? part.experimental_providerMetadata,\n );\n debugStreamLog(\"finish\", {\n finishReason: part.finishReason,\n usage: part.usage,\n deltas,\n });\n yield {\n type: \"finish\",\n finishReason: part.finishReason,\n usage: part.usage\n ? {\n promptTokens: finite(part.usage.promptTokens),\n completionTokens: finite(part.usage.completionTokens),\n totalTokens: finite(part.usage.totalTokens),\n ...cache,\n }\n : undefined,\n };\n return;\n }\n case \"error\": {\n // A user-initiated abort surfacing as a stream error is not a failure.\n if (opts.abortSignal?.aborted) return;\n const error = part.error instanceof Error ? part.error : new Error(String(part.error));\n debugStreamLog(\"error-part\", { seenPart, deltas, error: summarizeStreamError(error) });\n yield { type: \"error\", error };\n break;\n }\n }\n }\n } finally {\n opts.abortSignal?.removeEventListener(\"abort\", onAbort);\n // Cancels the upstream request if it is still open (e.g. a relay that\n // sent its last byte but kept the connection alive).\n controller.abort();\n }\n}\n","import { appendFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { starHome } from \"../config/paths\";\n\n// STAR_DEBUG-gated JSONL log of stream internals (~/.star-cli/debug.log):\n// what the provider actually sent — finish reasons, usage, error details —\n// so a misbehaving relay can be diagnosed from the client side. All write\n// failures are silent; logging must never break a turn.\nexport function debugStreamLog(event: string, data?: Record<string, unknown>): void {\n if (!process.env.STAR_DEBUG) return;\n try {\n const line = `${JSON.stringify({ ts: new Date().toISOString(), event, ...data })}\\n`;\n appendFileSync(path.join(starHome(), \"debug.log\"), line);\n } catch {\n // best-effort only\n }\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|