sparkecoder 0.1.71 → 0.1.73
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/dist/agent/index.d.ts +3 -3
- package/dist/agent/index.js +212 -51
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +214 -53
- package/dist/cli.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/{index-CYNqPa6Z.d.ts → index-dbWF1hyW.d.ts} +57 -49
- package/dist/index.d.ts +5 -5
- package/dist/index.js +214 -53
- package/dist/index.js.map +1 -1
- package/dist/{schema-C7Mm4Ykn.d.ts → schema-XcP0dedO.d.ts} +3 -3
- package/dist/{search-CVVfuBPZ.d.ts → search-CCffrVJE.d.ts} +4 -4
- package/dist/server/index.js +214 -53
- package/dist/server/index.js.map +1 -1
- package/dist/skills/default/qa.md +53 -14
- package/dist/tools/index.d.ts +3 -3
- package/dist/tools/index.js.map +1 -1
- package/package.json +1 -1
- package/src/skills/default/qa.md +53 -14
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/web/.next/server/app/index.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
- /package/web/.next/standalone/web/.next/static/{CvXz-9ALpAXX-GsCxrOdt → 2xYE9FvjZmf0tU0NF5Jvj}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{CvXz-9ALpAXX-GsCxrOdt → 2xYE9FvjZmf0tU0NF5Jvj}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{CvXz-9ALpAXX-GsCxrOdt → 2xYE9FvjZmf0tU0NF5Jvj}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{CvXz-9ALpAXX-GsCxrOdt → 2xYE9FvjZmf0tU0NF5Jvj}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{CvXz-9ALpAXX-GsCxrOdt → 2xYE9FvjZmf0tU0NF5Jvj}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{CvXz-9ALpAXX-GsCxrOdt → 2xYE9FvjZmf0tU0NF5Jvj}/_ssgManifest.js +0 -0
- /package/web/.next/static/{CvXz-9ALpAXX-GsCxrOdt → 2xYE9FvjZmf0tU0NF5Jvj}/_buildManifest.js +0 -0
- /package/web/.next/static/{CvXz-9ALpAXX-GsCxrOdt → 2xYE9FvjZmf0tU0NF5Jvj}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{CvXz-9ALpAXX-GsCxrOdt → 2xYE9FvjZmf0tU0NF5Jvj}/_ssgManifest.js +0 -0
package/dist/db/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as Checkpoint, F as FileBackup, M as ModelMessage, a as Message, S as Session, L as LoadedSkill, T as TodoItem, b as ToolExecution, A as ActiveStream, I as IndexStatusRecord, c as IndexedChunk, d as SubagentExecution, e as SubagentStep, f as Terminal } from '../schema-
|
|
2
|
-
export { N as NewActiveStream, g as NewCheckpoint, h as NewFileBackup, i as NewIndexStatusRecord, j as NewIndexedChunk, k as NewMessage, l as NewSession, m as NewSubagentExecution, n as NewTerminal, o as NewTodoItem, p as NewToolExecution, q as SessionConfig, r as TaskConfig, U as UserContentPart, s as UserFilePart, t as UserImagePart, u as UserModelMessage, v as UserTextPart } from '../schema-
|
|
1
|
+
import { C as Checkpoint, F as FileBackup, M as ModelMessage, a as Message, S as Session, L as LoadedSkill, T as TodoItem, b as ToolExecution, A as ActiveStream, I as IndexStatusRecord, c as IndexedChunk, d as SubagentExecution, e as SubagentStep, f as Terminal } from '../schema-XcP0dedO.js';
|
|
2
|
+
export { N as NewActiveStream, g as NewCheckpoint, h as NewFileBackup, i as NewIndexStatusRecord, j as NewIndexedChunk, k as NewMessage, l as NewSession, m as NewSubagentExecution, n as NewTerminal, o as NewTodoItem, p as NewToolExecution, q as SessionConfig, r as TaskConfig, U as UserContentPart, s as UserFilePart, t as UserImagePart, u as UserModelMessage, v as UserTextPart } from '../schema-XcP0dedO.js';
|
|
3
3
|
import 'drizzle-orm/sqlite-core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ModelMessage, streamText } from 'ai';
|
|
2
|
-
import { S as Session, b as ToolExecution, r as TaskConfig } from './schema-
|
|
2
|
+
import { S as Session, b as ToolExecution, r as TaskConfig } from './schema-XcP0dedO.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { B as BashToolProgress, W as WriteFileProgress, S as SearchToolProgress } from './search-
|
|
4
|
+
import { B as BashToolProgress, W as WriteFileProgress, S as SearchToolProgress } from './search-CCffrVJE.js';
|
|
5
5
|
|
|
6
6
|
declare const ToolApprovalConfigSchema: z.ZodObject<{
|
|
7
7
|
bash: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -37,54 +37,54 @@ declare const SessionConfigSchema: z.ZodObject<{
|
|
|
37
37
|
error: z.ZodOptional<z.ZodString>;
|
|
38
38
|
iterations: z.ZodOptional<z.ZodNumber>;
|
|
39
39
|
}, "strip", z.ZodTypeAny, {
|
|
40
|
-
status: "
|
|
41
|
-
enabled: boolean;
|
|
40
|
+
status: "completed" | "failed" | "running";
|
|
42
41
|
outputSchema: Record<string, unknown>;
|
|
43
|
-
|
|
42
|
+
enabled: boolean;
|
|
43
|
+
error?: string | undefined;
|
|
44
44
|
maxIterations?: number | undefined;
|
|
45
|
+
webhookUrl?: string | undefined;
|
|
45
46
|
result?: unknown;
|
|
46
|
-
error?: string | undefined;
|
|
47
47
|
iterations?: number | undefined;
|
|
48
48
|
}, {
|
|
49
|
-
status: "
|
|
50
|
-
enabled: boolean;
|
|
49
|
+
status: "completed" | "failed" | "running";
|
|
51
50
|
outputSchema: Record<string, unknown>;
|
|
52
|
-
|
|
51
|
+
enabled: boolean;
|
|
52
|
+
error?: string | undefined;
|
|
53
53
|
maxIterations?: number | undefined;
|
|
54
|
+
webhookUrl?: string | undefined;
|
|
54
55
|
result?: unknown;
|
|
55
|
-
error?: string | undefined;
|
|
56
56
|
iterations?: number | undefined;
|
|
57
57
|
}>>;
|
|
58
58
|
}, "strip", z.ZodTypeAny, {
|
|
59
59
|
maxContextChars: number;
|
|
60
60
|
toolApprovals?: Record<string, boolean> | undefined;
|
|
61
61
|
approvalWebhook?: string | undefined;
|
|
62
|
-
skillsDirectory?: string | undefined;
|
|
63
62
|
task?: {
|
|
64
|
-
status: "
|
|
65
|
-
enabled: boolean;
|
|
63
|
+
status: "completed" | "failed" | "running";
|
|
66
64
|
outputSchema: Record<string, unknown>;
|
|
67
|
-
|
|
65
|
+
enabled: boolean;
|
|
66
|
+
error?: string | undefined;
|
|
68
67
|
maxIterations?: number | undefined;
|
|
68
|
+
webhookUrl?: string | undefined;
|
|
69
69
|
result?: unknown;
|
|
70
|
-
error?: string | undefined;
|
|
71
70
|
iterations?: number | undefined;
|
|
72
71
|
} | undefined;
|
|
72
|
+
skillsDirectory?: string | undefined;
|
|
73
73
|
}, {
|
|
74
74
|
toolApprovals?: Record<string, boolean> | undefined;
|
|
75
75
|
approvalWebhook?: string | undefined;
|
|
76
|
-
skillsDirectory?: string | undefined;
|
|
77
|
-
maxContextChars?: number | undefined;
|
|
78
76
|
task?: {
|
|
79
|
-
status: "
|
|
80
|
-
enabled: boolean;
|
|
77
|
+
status: "completed" | "failed" | "running";
|
|
81
78
|
outputSchema: Record<string, unknown>;
|
|
82
|
-
|
|
79
|
+
enabled: boolean;
|
|
80
|
+
error?: string | undefined;
|
|
83
81
|
maxIterations?: number | undefined;
|
|
82
|
+
webhookUrl?: string | undefined;
|
|
84
83
|
result?: unknown;
|
|
85
|
-
error?: string | undefined;
|
|
86
84
|
iterations?: number | undefined;
|
|
87
85
|
} | undefined;
|
|
86
|
+
skillsDirectory?: string | undefined;
|
|
87
|
+
maxContextChars?: number | undefined;
|
|
88
88
|
}>;
|
|
89
89
|
declare const SparkcoderConfigSchema: z.ZodObject<{
|
|
90
90
|
defaultModel: z.ZodDefault<z.ZodString>;
|
|
@@ -179,6 +179,7 @@ declare const SparkcoderConfigSchema: z.ZodObject<{
|
|
|
179
179
|
exclude?: string[] | undefined;
|
|
180
180
|
}>>;
|
|
181
181
|
}, "strip", z.ZodTypeAny, {
|
|
182
|
+
defaultModel: string;
|
|
182
183
|
toolApprovals: {
|
|
183
184
|
bash: boolean;
|
|
184
185
|
write_file: boolean;
|
|
@@ -186,7 +187,6 @@ declare const SparkcoderConfigSchema: z.ZodObject<{
|
|
|
186
187
|
load_skill: boolean;
|
|
187
188
|
todo: boolean;
|
|
188
189
|
};
|
|
189
|
-
defaultModel: string;
|
|
190
190
|
skills: {
|
|
191
191
|
directory: string;
|
|
192
192
|
additionalDirectories: string[];
|
|
@@ -202,8 +202,8 @@ declare const SparkcoderConfigSchema: z.ZodObject<{
|
|
|
202
202
|
publicUrl?: string | undefined;
|
|
203
203
|
};
|
|
204
204
|
databasePath: string;
|
|
205
|
-
approvalWebhook?: string | undefined;
|
|
206
205
|
workingDirectory?: string | undefined;
|
|
206
|
+
approvalWebhook?: string | undefined;
|
|
207
207
|
remoteServer?: {
|
|
208
208
|
url?: string | undefined;
|
|
209
209
|
authKey?: string | undefined;
|
|
@@ -217,6 +217,8 @@ declare const SparkcoderConfigSchema: z.ZodObject<{
|
|
|
217
217
|
namespace?: string | undefined;
|
|
218
218
|
} | undefined;
|
|
219
219
|
}, {
|
|
220
|
+
defaultModel?: string | undefined;
|
|
221
|
+
workingDirectory?: string | undefined;
|
|
220
222
|
toolApprovals?: {
|
|
221
223
|
bash?: boolean | undefined;
|
|
222
224
|
write_file?: boolean | undefined;
|
|
@@ -225,8 +227,6 @@ declare const SparkcoderConfigSchema: z.ZodObject<{
|
|
|
225
227
|
todo?: boolean | undefined;
|
|
226
228
|
} | undefined;
|
|
227
229
|
approvalWebhook?: string | undefined;
|
|
228
|
-
workingDirectory?: string | undefined;
|
|
229
|
-
defaultModel?: string | undefined;
|
|
230
230
|
skills?: {
|
|
231
231
|
directory?: string | undefined;
|
|
232
232
|
additionalDirectories?: string[] | undefined;
|
|
@@ -299,40 +299,54 @@ interface ResolvedConfig extends Omit<SparkcoderConfig, 'server'> {
|
|
|
299
299
|
|
|
300
300
|
interface ContextManagerOptions {
|
|
301
301
|
sessionId: string;
|
|
302
|
+
modelId: string;
|
|
302
303
|
maxContextChars: number;
|
|
303
304
|
keepRecentMessages: number;
|
|
304
305
|
autoSummarize: boolean;
|
|
305
306
|
}
|
|
306
307
|
/**
|
|
307
|
-
* Manages conversation context
|
|
308
|
+
* Manages conversation context with a three-phase rolling window:
|
|
308
309
|
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
310
|
+
* Phase 1 – Compact: strip todo tool calls, trim large tool outputs,
|
|
311
|
+
* and remove thinking blocks from older messages (no LLM cost).
|
|
312
|
+
* Phase 2 – Chunk-summarize: when compacted context still exceeds the
|
|
313
|
+
* model's rolling target, summarize the oldest ~30 K-token chunk
|
|
314
|
+
* via a cheap/fast model (gemini-3-flash-preview).
|
|
315
|
+
* Phase 3 – Roll summaries: when accumulated summaries exceed their budget
|
|
316
|
+
* (~15 % of rolling target), re-summarize them into one.
|
|
311
317
|
*/
|
|
312
318
|
declare class ContextManager {
|
|
313
319
|
private sessionId;
|
|
320
|
+
private modelId;
|
|
314
321
|
private maxContextChars;
|
|
315
322
|
private keepRecentMessages;
|
|
316
323
|
private autoSummarize;
|
|
317
|
-
private
|
|
324
|
+
private summaries;
|
|
318
325
|
constructor(options: ContextManagerOptions);
|
|
319
326
|
/**
|
|
320
|
-
* Get messages for the current context
|
|
321
|
-
* Returns ModelMessage[] that can be passed directly to streamText/generateText
|
|
322
|
-
*
|
|
323
|
-
* Includes self-repair: if messages from the database have been corrupted
|
|
324
|
-
* (e.g., Date objects in tool outputs from parseDates), they are automatically
|
|
325
|
-
* sanitized to conform to the AI SDK's ModelMessage schema.
|
|
327
|
+
* Get messages for the current context, applying the three-phase pipeline.
|
|
326
328
|
*/
|
|
327
329
|
getMessages(): Promise<ModelMessage[]>;
|
|
328
330
|
/**
|
|
329
|
-
*
|
|
331
|
+
* Strip non-essential content from messages older than the most recent
|
|
332
|
+
* `recentCount`. Operates in-memory only — does not touch the DB.
|
|
330
333
|
*/
|
|
331
|
-
|
|
334
|
+
compactOlderMessages(messages: ModelMessage[], recentCount: number): ModelMessage[];
|
|
335
|
+
private compactMessage;
|
|
336
|
+
private trimToolResult;
|
|
332
337
|
/**
|
|
333
|
-
*
|
|
334
|
-
*
|
|
338
|
+
* While estimated tokens exceed `rollingTarget`, peel off the oldest
|
|
339
|
+
* ~SUMMARY_CHUNK_TOKENS worth of messages, summarize them via the cheap
|
|
340
|
+
* model, and prepend the summary.
|
|
335
341
|
*/
|
|
342
|
+
private chunkSummarize;
|
|
343
|
+
private summarizeChunk;
|
|
344
|
+
/**
|
|
345
|
+
* If accumulated summaries exceed `budget` tokens, re-summarize them
|
|
346
|
+
* into a single condensed summary.
|
|
347
|
+
*/
|
|
348
|
+
private rollSummaries;
|
|
349
|
+
private messageTokens;
|
|
336
350
|
addUserMessage(content: string | Array<{
|
|
337
351
|
type: string;
|
|
338
352
|
text?: string;
|
|
@@ -340,22 +354,14 @@ declare class ContextManager {
|
|
|
340
354
|
data?: string;
|
|
341
355
|
mediaType?: string;
|
|
342
356
|
}>): Promise<void>;
|
|
343
|
-
/**
|
|
344
|
-
* Add response messages from AI SDK directly
|
|
345
|
-
* This is the preferred method - use result.response.messages from streamText/generateText
|
|
346
|
-
*/
|
|
347
357
|
addResponseMessages(messages: ModelMessage[]): Promise<void>;
|
|
348
|
-
/**
|
|
349
|
-
* Get current context statistics
|
|
350
|
-
*/
|
|
351
358
|
getStats(): Promise<{
|
|
352
359
|
messageCount: number;
|
|
353
360
|
contextChars: number;
|
|
361
|
+
estimatedTokens: number;
|
|
354
362
|
hasSummary: boolean;
|
|
363
|
+
summaryCount: number;
|
|
355
364
|
}>;
|
|
356
|
-
/**
|
|
357
|
-
* Clear all messages in the context
|
|
358
|
-
*/
|
|
359
365
|
clear(): Promise<void>;
|
|
360
366
|
}
|
|
361
367
|
|
|
@@ -540,7 +546,9 @@ declare class Agent {
|
|
|
540
546
|
getContextStats(): Promise<{
|
|
541
547
|
messageCount: number;
|
|
542
548
|
contextChars: number;
|
|
549
|
+
estimatedTokens: number;
|
|
543
550
|
hasSummary: boolean;
|
|
551
|
+
summaryCount: number;
|
|
544
552
|
}>;
|
|
545
553
|
/**
|
|
546
554
|
* Clear conversation context (start fresh)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { R as ResolvedConfig } from './index-
|
|
2
|
-
export { A as Agent, a as AgentOptions, b as AgentRunOptions, c as AgentStreamResult, S as SparkcoderConfig, T as ToolApprovalConfig } from './index-
|
|
1
|
+
import { R as ResolvedConfig } from './index-dbWF1hyW.js';
|
|
2
|
+
export { A as Agent, a as AgentOptions, b as AgentRunOptions, c as AgentStreamResult, S as SparkcoderConfig, T as ToolApprovalConfig } from './index-dbWF1hyW.js';
|
|
3
3
|
export { ServerOptions, createApp, startServer, stopServer } from './server/index.js';
|
|
4
4
|
export { checkpointQueries, closeDatabase, fileBackupQueries, getDb, initDatabase, messageQueries, sessionQueries, skillQueries, todoQueries, toolExecutionQueries } from './db/index.js';
|
|
5
|
-
import { F as FileBackup, C as Checkpoint } from './schema-
|
|
6
|
-
export { a as Message, M as ModelMessage, S as Session, q as SessionConfig, f as Terminal, T as TodoItem, b as ToolExecution } from './schema-
|
|
5
|
+
import { F as FileBackup, C as Checkpoint } from './schema-XcP0dedO.js';
|
|
6
|
+
export { a as Message, M as ModelMessage, S as Session, q as SessionConfig, f as Terminal, T as TodoItem, b as ToolExecution } from './schema-XcP0dedO.js';
|
|
7
7
|
export { createLoadSkillTool, createReadFileTool, createTodoTool, createTools } from './tools/index.js';
|
|
8
|
-
export { c as createBashTool, a as createWriteFileTool } from './search-
|
|
8
|
+
export { c as createBashTool, a as createWriteFileTool } from './search-CCffrVJE.js';
|
|
9
9
|
import 'ai';
|
|
10
10
|
import 'zod';
|
|
11
11
|
import 'hono/types';
|
package/dist/index.js
CHANGED
|
@@ -2280,6 +2280,19 @@ import { z as z2 } from "zod";
|
|
|
2280
2280
|
import { exec as exec2 } from "child_process";
|
|
2281
2281
|
import { promisify as promisify2 } from "util";
|
|
2282
2282
|
|
|
2283
|
+
// src/utils/tokens.ts
|
|
2284
|
+
var CHARS_PER_TOKEN = 4;
|
|
2285
|
+
var MESSAGE_OVERHEAD_TOKENS = 4;
|
|
2286
|
+
function estimateTokens(text) {
|
|
2287
|
+
return Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
2288
|
+
}
|
|
2289
|
+
function estimateMessageTokens(messages) {
|
|
2290
|
+
return messages.reduce((total, msg) => {
|
|
2291
|
+
const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
|
|
2292
|
+
return total + estimateTokens(content) + MESSAGE_OVERHEAD_TOKENS;
|
|
2293
|
+
}, 0);
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2283
2296
|
// src/utils/truncate.ts
|
|
2284
2297
|
var MAX_OUTPUT_CHARS = 1e4;
|
|
2285
2298
|
function truncateOutput(output, maxChars = MAX_OUTPUT_CHARS) {
|
|
@@ -6267,9 +6280,6 @@ ${conversationHistory}
|
|
|
6267
6280
|
Summary:`;
|
|
6268
6281
|
}
|
|
6269
6282
|
|
|
6270
|
-
// src/agent/context.ts
|
|
6271
|
-
init_config();
|
|
6272
|
-
|
|
6273
6283
|
// src/utils/sanitize-messages.ts
|
|
6274
6284
|
import { modelMessageSchema } from "ai";
|
|
6275
6285
|
function convertDatesToStrings(value) {
|
|
@@ -6406,79 +6416,237 @@ function sanitizeModelMessages(messages) {
|
|
|
6406
6416
|
return result;
|
|
6407
6417
|
}
|
|
6408
6418
|
|
|
6419
|
+
// src/agent/model-limits.ts
|
|
6420
|
+
var MODEL_LIMITS = {
|
|
6421
|
+
"anthropic/claude-opus-4-6": { contextWindow: 2e5, rollingTarget: 15e4 },
|
|
6422
|
+
"anthropic/claude-sonnet-4": { contextWindow: 2e5, rollingTarget: 15e4 },
|
|
6423
|
+
"anthropic/claude-3.5-sonnet": { contextWindow: 2e5, rollingTarget: 15e4 },
|
|
6424
|
+
"anthropic/claude-3-haiku": { contextWindow: 2e5, rollingTarget: 15e4 },
|
|
6425
|
+
"google/gemini-3-flash-preview": { contextWindow: 1e6, rollingTarget: 15e4 },
|
|
6426
|
+
"google/gemini-2.5-pro": { contextWindow: 1e6, rollingTarget: 15e4 },
|
|
6427
|
+
"google/gemini-2.5-flash": { contextWindow: 1e6, rollingTarget: 15e4 },
|
|
6428
|
+
"openai/gpt-4o": { contextWindow: 128e3, rollingTarget: 78e3 },
|
|
6429
|
+
"openai/gpt-4.1": { contextWindow: 1e6, rollingTarget: 15e4 },
|
|
6430
|
+
"openai/o3": { contextWindow: 2e5, rollingTarget: 15e4 },
|
|
6431
|
+
"xai/grok-3": { contextWindow: 131072, rollingTarget: 8e4 }
|
|
6432
|
+
};
|
|
6433
|
+
var DEFAULT_LIMITS = { contextWindow: 2e5, rollingTarget: 15e4 };
|
|
6434
|
+
var PREFIX_DEFAULTS = {
|
|
6435
|
+
"anthropic/": { contextWindow: 2e5, rollingTarget: 15e4 },
|
|
6436
|
+
"google/": { contextWindow: 1e6, rollingTarget: 15e4 },
|
|
6437
|
+
"openai/": { contextWindow: 128e3, rollingTarget: 78e3 },
|
|
6438
|
+
"xai/": { contextWindow: 131072, rollingTarget: 8e4 }
|
|
6439
|
+
};
|
|
6440
|
+
function getModelLimits(modelId) {
|
|
6441
|
+
const normalized = modelId.trim().toLowerCase();
|
|
6442
|
+
const exact = MODEL_LIMITS[normalized];
|
|
6443
|
+
if (exact) return exact;
|
|
6444
|
+
for (const [prefix, limits] of Object.entries(PREFIX_DEFAULTS)) {
|
|
6445
|
+
if (normalized.startsWith(prefix)) return limits;
|
|
6446
|
+
}
|
|
6447
|
+
return DEFAULT_LIMITS;
|
|
6448
|
+
}
|
|
6449
|
+
var SUMMARIZATION_MODEL = "google/gemini-3-flash-preview";
|
|
6450
|
+
var SUMMARY_CHUNK_TOKENS = 3e4;
|
|
6451
|
+
var SUMMARY_BUDGET_RATIO = 0.15;
|
|
6452
|
+
|
|
6409
6453
|
// src/agent/context.ts
|
|
6454
|
+
var TOOL_OUTPUT_TRIM_CHARS = 400;
|
|
6455
|
+
var COMPACTABLE_TOOLS = /* @__PURE__ */ new Set([
|
|
6456
|
+
"read_file",
|
|
6457
|
+
"bash",
|
|
6458
|
+
"explore_agent",
|
|
6459
|
+
"code_graph"
|
|
6460
|
+
]);
|
|
6410
6461
|
var ContextManager = class {
|
|
6411
6462
|
sessionId;
|
|
6463
|
+
modelId;
|
|
6412
6464
|
maxContextChars;
|
|
6413
6465
|
keepRecentMessages;
|
|
6414
6466
|
autoSummarize;
|
|
6415
|
-
|
|
6467
|
+
summaries = [];
|
|
6416
6468
|
constructor(options) {
|
|
6417
6469
|
this.sessionId = options.sessionId;
|
|
6470
|
+
this.modelId = options.modelId;
|
|
6418
6471
|
this.maxContextChars = options.maxContextChars;
|
|
6419
6472
|
this.keepRecentMessages = options.keepRecentMessages;
|
|
6420
6473
|
this.autoSummarize = options.autoSummarize;
|
|
6421
6474
|
}
|
|
6422
6475
|
/**
|
|
6423
|
-
* Get messages for the current context
|
|
6424
|
-
* Returns ModelMessage[] that can be passed directly to streamText/generateText
|
|
6425
|
-
*
|
|
6426
|
-
* Includes self-repair: if messages from the database have been corrupted
|
|
6427
|
-
* (e.g., Date objects in tool outputs from parseDates), they are automatically
|
|
6428
|
-
* sanitized to conform to the AI SDK's ModelMessage schema.
|
|
6476
|
+
* Get messages for the current context, applying the three-phase pipeline.
|
|
6429
6477
|
*/
|
|
6430
6478
|
async getMessages() {
|
|
6431
|
-
let
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
if (this.autoSummarize
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6479
|
+
let messages = await messageQueries.getModelMessages(this.sessionId);
|
|
6480
|
+
messages = sanitizeModelMessages(messages);
|
|
6481
|
+
messages = this.compactOlderMessages(messages, this.keepRecentMessages);
|
|
6482
|
+
if (this.autoSummarize) {
|
|
6483
|
+
const { rollingTarget } = getModelLimits(this.modelId);
|
|
6484
|
+
const summaryBudget = Math.floor(rollingTarget * SUMMARY_BUDGET_RATIO);
|
|
6485
|
+
messages = await this.chunkSummarize(messages, rollingTarget);
|
|
6486
|
+
await this.rollSummaries(summaryBudget);
|
|
6487
|
+
}
|
|
6488
|
+
if (this.summaries.length > 0) {
|
|
6489
|
+
const summaryContent = this.summaries.join("\n\n---\n\n");
|
|
6490
|
+
messages = [
|
|
6439
6491
|
{
|
|
6440
6492
|
role: "system",
|
|
6441
6493
|
content: `[Previous conversation summary]
|
|
6442
|
-
${
|
|
6494
|
+
${summaryContent}`
|
|
6443
6495
|
},
|
|
6444
|
-
...
|
|
6496
|
+
...messages
|
|
6445
6497
|
];
|
|
6446
6498
|
}
|
|
6447
|
-
return
|
|
6499
|
+
return messages;
|
|
6448
6500
|
}
|
|
6501
|
+
// ---------------------------------------------------------------------------
|
|
6502
|
+
// Phase 1 – Compact
|
|
6503
|
+
// ---------------------------------------------------------------------------
|
|
6449
6504
|
/**
|
|
6450
|
-
*
|
|
6505
|
+
* Strip non-essential content from messages older than the most recent
|
|
6506
|
+
* `recentCount`. Operates in-memory only — does not touch the DB.
|
|
6451
6507
|
*/
|
|
6452
|
-
|
|
6453
|
-
if (messages.length <=
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
const
|
|
6457
|
-
const
|
|
6458
|
-
const
|
|
6459
|
-
|
|
6508
|
+
compactOlderMessages(messages, recentCount) {
|
|
6509
|
+
if (messages.length <= recentCount) return messages;
|
|
6510
|
+
const boundary = messages.length - recentCount;
|
|
6511
|
+
const olderMessages = messages.slice(0, boundary);
|
|
6512
|
+
const recentMessages = messages.slice(boundary);
|
|
6513
|
+
const compacted = [];
|
|
6514
|
+
for (const msg of olderMessages) {
|
|
6515
|
+
const processed = this.compactMessage(msg);
|
|
6516
|
+
if (processed) compacted.push(processed);
|
|
6517
|
+
}
|
|
6518
|
+
return [...compacted, ...recentMessages];
|
|
6519
|
+
}
|
|
6520
|
+
compactMessage(msg) {
|
|
6521
|
+
if (!Array.isArray(msg.content)) return msg;
|
|
6522
|
+
const parts = [];
|
|
6523
|
+
for (const part of msg.content) {
|
|
6524
|
+
if (part.type === "tool-call" && part.toolName === "todo") continue;
|
|
6525
|
+
if (part.type === "tool-result" && part.toolName === "todo") continue;
|
|
6526
|
+
if (part.type === "reasoning" || part.type === "thinking") continue;
|
|
6527
|
+
if (part.type === "tool-result" && COMPACTABLE_TOOLS.has(part.toolName)) {
|
|
6528
|
+
parts.push(this.trimToolResult(part));
|
|
6529
|
+
continue;
|
|
6530
|
+
}
|
|
6531
|
+
parts.push(part);
|
|
6532
|
+
}
|
|
6533
|
+
if (parts.length === 0) return null;
|
|
6534
|
+
return { ...msg, content: parts };
|
|
6535
|
+
}
|
|
6536
|
+
trimToolResult(part) {
|
|
6537
|
+
const results = Array.isArray(part.result) ? part.result : [part.result];
|
|
6538
|
+
const trimmedResults = results.map((r) => {
|
|
6539
|
+
if (typeof r === "string" && r.length > TOOL_OUTPUT_TRIM_CHARS) {
|
|
6540
|
+
const half = Math.floor(TOOL_OUTPUT_TRIM_CHARS / 2);
|
|
6541
|
+
return r.slice(0, half) + `
|
|
6542
|
+
...[trimmed ${r.length - TOOL_OUTPUT_TRIM_CHARS} chars]...
|
|
6543
|
+
` + r.slice(-half);
|
|
6544
|
+
}
|
|
6545
|
+
if (r && typeof r === "object" && typeof r.text === "string" && r.text.length > TOOL_OUTPUT_TRIM_CHARS) {
|
|
6546
|
+
const half = Math.floor(TOOL_OUTPUT_TRIM_CHARS / 2);
|
|
6547
|
+
return {
|
|
6548
|
+
...r,
|
|
6549
|
+
text: r.text.slice(0, half) + `
|
|
6550
|
+
...[trimmed ${r.text.length - TOOL_OUTPUT_TRIM_CHARS} chars]...
|
|
6551
|
+
` + r.text.slice(-half)
|
|
6552
|
+
};
|
|
6553
|
+
}
|
|
6554
|
+
return r;
|
|
6555
|
+
});
|
|
6556
|
+
return {
|
|
6557
|
+
...part,
|
|
6558
|
+
result: Array.isArray(part.result) ? trimmedResults : trimmedResults[0]
|
|
6559
|
+
};
|
|
6560
|
+
}
|
|
6561
|
+
// ---------------------------------------------------------------------------
|
|
6562
|
+
// Phase 2 – Chunk-summarize
|
|
6563
|
+
// ---------------------------------------------------------------------------
|
|
6564
|
+
/**
|
|
6565
|
+
* While estimated tokens exceed `rollingTarget`, peel off the oldest
|
|
6566
|
+
* ~SUMMARY_CHUNK_TOKENS worth of messages, summarize them via the cheap
|
|
6567
|
+
* model, and prepend the summary.
|
|
6568
|
+
*/
|
|
6569
|
+
async chunkSummarize(messages, rollingTarget) {
|
|
6570
|
+
let totalTokens = estimateMessageTokens(messages);
|
|
6571
|
+
while (totalTokens > rollingTarget && messages.length > this.keepRecentMessages) {
|
|
6572
|
+
let chunkTokens = 0;
|
|
6573
|
+
let chunkEnd = 0;
|
|
6574
|
+
const maxChunkable = messages.length - this.keepRecentMessages;
|
|
6575
|
+
for (let i = 0; i < maxChunkable; i++) {
|
|
6576
|
+
const msgTokens = this.messageTokens(messages[i]);
|
|
6577
|
+
chunkTokens += msgTokens;
|
|
6578
|
+
chunkEnd = i + 1;
|
|
6579
|
+
if (chunkTokens >= SUMMARY_CHUNK_TOKENS) break;
|
|
6580
|
+
}
|
|
6581
|
+
if (chunkEnd === 0) break;
|
|
6582
|
+
const chunk = messages.slice(0, chunkEnd);
|
|
6583
|
+
const remaining = messages.slice(chunkEnd);
|
|
6584
|
+
const summary = await this.summarizeChunk(chunk);
|
|
6585
|
+
if (summary) {
|
|
6586
|
+
this.summaries.push(summary);
|
|
6587
|
+
console.log(
|
|
6588
|
+
`[Context] Summarized ${chunk.length} messages (~${chunkTokens} tokens) into ${estimateTokens(summary)} tokens`
|
|
6589
|
+
);
|
|
6590
|
+
}
|
|
6591
|
+
messages = remaining;
|
|
6592
|
+
totalTokens = estimateMessageTokens(messages);
|
|
6593
|
+
}
|
|
6594
|
+
return messages;
|
|
6595
|
+
}
|
|
6596
|
+
async summarizeChunk(chunk) {
|
|
6597
|
+
const historyText = chunk.map((msg) => {
|
|
6460
6598
|
const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
|
|
6461
6599
|
return `[${msg.role}]: ${content}`;
|
|
6462
6600
|
}).join("\n\n");
|
|
6463
6601
|
try {
|
|
6464
|
-
const config = getConfig();
|
|
6465
|
-
const summaryPrompt = createSummaryPrompt(historyText);
|
|
6466
6602
|
const result = await generateText2({
|
|
6467
|
-
model: resolveModel(
|
|
6468
|
-
prompt:
|
|
6603
|
+
model: resolveModel(SUMMARIZATION_MODEL),
|
|
6604
|
+
prompt: createSummaryPrompt(historyText)
|
|
6469
6605
|
});
|
|
6470
|
-
|
|
6471
|
-
console.log(`[Context] Summarized ${oldMessages.length} messages into ${this.summary.length} chars`);
|
|
6472
|
-
return recentMessages;
|
|
6606
|
+
return result.text;
|
|
6473
6607
|
} catch (error) {
|
|
6474
|
-
console.error("[Context]
|
|
6475
|
-
return
|
|
6608
|
+
console.error("[Context] Chunk summarization failed:", error);
|
|
6609
|
+
return null;
|
|
6476
6610
|
}
|
|
6477
6611
|
}
|
|
6612
|
+
// ---------------------------------------------------------------------------
|
|
6613
|
+
// Phase 3 – Roll summaries
|
|
6614
|
+
// ---------------------------------------------------------------------------
|
|
6478
6615
|
/**
|
|
6479
|
-
*
|
|
6480
|
-
*
|
|
6616
|
+
* If accumulated summaries exceed `budget` tokens, re-summarize them
|
|
6617
|
+
* into a single condensed summary.
|
|
6481
6618
|
*/
|
|
6619
|
+
async rollSummaries(budget) {
|
|
6620
|
+
if (this.summaries.length <= 1) return;
|
|
6621
|
+
const totalSummaryTokens = this.summaries.reduce(
|
|
6622
|
+
(t, s) => t + estimateTokens(s),
|
|
6623
|
+
0
|
|
6624
|
+
);
|
|
6625
|
+
if (totalSummaryTokens <= budget) return;
|
|
6626
|
+
const combined = this.summaries.join("\n\n---\n\n");
|
|
6627
|
+
try {
|
|
6628
|
+
const result = await generateText2({
|
|
6629
|
+
model: resolveModel(SUMMARIZATION_MODEL),
|
|
6630
|
+
prompt: createSummaryPrompt(combined)
|
|
6631
|
+
});
|
|
6632
|
+
console.log(
|
|
6633
|
+
`[Context] Rolled ${this.summaries.length} summaries (${totalSummaryTokens} tokens) into ${estimateTokens(result.text)} tokens`
|
|
6634
|
+
);
|
|
6635
|
+
this.summaries = [result.text];
|
|
6636
|
+
} catch (error) {
|
|
6637
|
+
console.error("[Context] Summary rolling failed:", error);
|
|
6638
|
+
}
|
|
6639
|
+
}
|
|
6640
|
+
// ---------------------------------------------------------------------------
|
|
6641
|
+
// Helpers
|
|
6642
|
+
// ---------------------------------------------------------------------------
|
|
6643
|
+
messageTokens(msg) {
|
|
6644
|
+
const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
|
|
6645
|
+
return estimateTokens(content) + 4;
|
|
6646
|
+
}
|
|
6647
|
+
// ---------------------------------------------------------------------------
|
|
6648
|
+
// Public API (unchanged)
|
|
6649
|
+
// ---------------------------------------------------------------------------
|
|
6482
6650
|
async addUserMessage(content) {
|
|
6483
6651
|
const userMessage = {
|
|
6484
6652
|
role: "user",
|
|
@@ -6486,30 +6654,22 @@ ${this.summary}`
|
|
|
6486
6654
|
};
|
|
6487
6655
|
await messageQueries.create(this.sessionId, userMessage);
|
|
6488
6656
|
}
|
|
6489
|
-
/**
|
|
6490
|
-
* Add response messages from AI SDK directly
|
|
6491
|
-
* This is the preferred method - use result.response.messages from streamText/generateText
|
|
6492
|
-
*/
|
|
6493
6657
|
async addResponseMessages(messages) {
|
|
6494
6658
|
await messageQueries.addMany(this.sessionId, messages);
|
|
6495
6659
|
}
|
|
6496
|
-
/**
|
|
6497
|
-
* Get current context statistics
|
|
6498
|
-
*/
|
|
6499
6660
|
async getStats() {
|
|
6500
6661
|
const messages = await messageQueries.getModelMessages(this.sessionId);
|
|
6501
6662
|
return {
|
|
6502
6663
|
messageCount: messages.length,
|
|
6503
6664
|
contextChars: calculateContextSize(messages),
|
|
6504
|
-
|
|
6665
|
+
estimatedTokens: estimateMessageTokens(messages),
|
|
6666
|
+
hasSummary: this.summaries.length > 0,
|
|
6667
|
+
summaryCount: this.summaries.length
|
|
6505
6668
|
};
|
|
6506
6669
|
}
|
|
6507
|
-
/**
|
|
6508
|
-
* Clear all messages in the context
|
|
6509
|
-
*/
|
|
6510
6670
|
async clear() {
|
|
6511
6671
|
await messageQueries.deleteBySession(this.sessionId);
|
|
6512
|
-
this.
|
|
6672
|
+
this.summaries = [];
|
|
6513
6673
|
}
|
|
6514
6674
|
};
|
|
6515
6675
|
|
|
@@ -6577,6 +6737,7 @@ var Agent = class _Agent {
|
|
|
6577
6737
|
}
|
|
6578
6738
|
const context = new ContextManager({
|
|
6579
6739
|
sessionId: session.id,
|
|
6740
|
+
modelId: session.model || config.defaultModel,
|
|
6580
6741
|
maxContextChars: config.context?.maxChars || 2e5,
|
|
6581
6742
|
keepRecentMessages: config.context?.keepRecentMessages || 10,
|
|
6582
6743
|
autoSummarize: config.context?.autoSummarize ?? true
|