@polka-codes/core 0.8.23 → 0.8.25
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/_tsup-dts-rollup.d.ts +41 -17
- package/dist/index.d.ts +1 -0
- package/dist/index.js +212 -120
- package/package.json +1 -1
|
@@ -8,19 +8,20 @@ declare abstract class AgentBase {
|
|
|
8
8
|
protected readonly config: Readonly<AgentBaseConfig>;
|
|
9
9
|
protected readonly handlers: Record<string, FullToolInfo>;
|
|
10
10
|
constructor(name: string, ai: AiServiceBase, config: AgentBaseConfig);
|
|
11
|
+
abort(): void;
|
|
11
12
|
get parameters(): Readonly<any>;
|
|
12
13
|
get messages(): Readonly<MessageParam[]>;
|
|
13
14
|
setMessages(messages: Readonly<MessageParam[]>): void;
|
|
14
|
-
start(prompt:
|
|
15
|
-
step(prompt:
|
|
15
|
+
start(prompt: UserContent): Promise<ExitReason>;
|
|
16
|
+
step(prompt: UserContent): Promise<AssistantMessageContent[]>;
|
|
16
17
|
handleStepResponse(response: AssistantMessageContent[]): Promise<{
|
|
17
18
|
type: "reply";
|
|
18
|
-
message:
|
|
19
|
+
message: UserContent;
|
|
19
20
|
} | {
|
|
20
21
|
type: "exit";
|
|
21
22
|
reason: ExitReason;
|
|
22
23
|
}>;
|
|
23
|
-
continueTask(userMessage:
|
|
24
|
+
continueTask(userMessage: UserContent): Promise<ExitReason>;
|
|
24
25
|
protected abstract onBeforeInvokeTool(name: string, args: Record<string, string>): Promise<ToolResponse | undefined>;
|
|
25
26
|
get model(): {
|
|
26
27
|
provider: string;
|
|
@@ -93,6 +94,7 @@ export { agentsPrompt as agentsPrompt_alias_1 }
|
|
|
93
94
|
export { agentsPrompt as agentsPrompt_alias_2 }
|
|
94
95
|
|
|
95
96
|
declare abstract class AiServiceBase {
|
|
97
|
+
#private;
|
|
96
98
|
readonly usageMeter: UsageMeter;
|
|
97
99
|
readonly options: AiServiceOptions;
|
|
98
100
|
constructor(options: AiServiceOptions);
|
|
@@ -101,7 +103,8 @@ declare abstract class AiServiceBase {
|
|
|
101
103
|
id: string;
|
|
102
104
|
info: ModelInfo;
|
|
103
105
|
};
|
|
104
|
-
abstract sendImpl(systemPrompt: string, messages: MessageParam[]): ApiStream;
|
|
106
|
+
abstract sendImpl(systemPrompt: string, messages: MessageParam[], signal: AbortSignal): ApiStream;
|
|
107
|
+
abort(): void;
|
|
105
108
|
send(systemPrompt: string, messages: MessageParam[]): ApiStream;
|
|
106
109
|
request(systemPrompt: string, messages: MessageParam[]): Promise<{
|
|
107
110
|
response: string;
|
|
@@ -300,7 +303,7 @@ export declare class AnthropicService extends AiServiceBase {
|
|
|
300
303
|
info: ModelInfo;
|
|
301
304
|
};
|
|
302
305
|
constructor(options: AiServiceOptions);
|
|
303
|
-
sendImpl(systemPrompt: string, messages: MessageParam[]): ApiStream;
|
|
306
|
+
sendImpl(systemPrompt: string, messages: MessageParam[], signal: AbortSignal): ApiStream;
|
|
304
307
|
}
|
|
305
308
|
|
|
306
309
|
declare type ApiStream = AsyncGenerator<ApiStreamChunk>;
|
|
@@ -795,7 +798,7 @@ export declare class DeepSeekService extends AiServiceBase {
|
|
|
795
798
|
info: ModelInfo;
|
|
796
799
|
};
|
|
797
800
|
constructor(options: AiServiceOptions);
|
|
798
|
-
sendImpl(systemPrompt: string, messages: MessageParam[]): ApiStream;
|
|
801
|
+
sendImpl(systemPrompt: string, messages: MessageParam[], signal: AbortSignal): ApiStream;
|
|
799
802
|
}
|
|
800
803
|
|
|
801
804
|
declare const _default: {
|
|
@@ -1061,7 +1064,7 @@ export { _default_10 as updateKnowledge_alias_2 }
|
|
|
1061
1064
|
declare const _default_11: {
|
|
1062
1065
|
handler: ToolHandler<{
|
|
1063
1066
|
readonly name: "write_to_file";
|
|
1064
|
-
readonly description: "Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file. Ensure that the output content does not include incorrect escaped character patterns such as `<
|
|
1067
|
+
readonly description: "Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file. Ensure that the output content does not include incorrect escaped character patterns such as `<`, `>`, or `&`. Also ensure there is no unwanted CDATA tags in the content.";
|
|
1065
1068
|
readonly parameters: [{
|
|
1066
1069
|
readonly name: "path";
|
|
1067
1070
|
readonly description: "The path of the file to write to";
|
|
@@ -1087,7 +1090,7 @@ declare const _default_11: {
|
|
|
1087
1090
|
}, FilesystemProvider>;
|
|
1088
1091
|
isAvailable: (provider: FilesystemProvider) => boolean;
|
|
1089
1092
|
name: "write_to_file";
|
|
1090
|
-
description: "Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file. Ensure that the output content does not include incorrect escaped character patterns such as `<
|
|
1093
|
+
description: "Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file. Ensure that the output content does not include incorrect escaped character patterns such as `<`, `>`, or `&`. Also ensure there is no unwanted CDATA tags in the content.";
|
|
1091
1094
|
parameters: [{
|
|
1092
1095
|
readonly name: "path";
|
|
1093
1096
|
readonly description: "The path of the file to write to";
|
|
@@ -1945,6 +1948,8 @@ declare type ExitReason = {
|
|
|
1945
1948
|
type: 'UsageExceeded';
|
|
1946
1949
|
} | {
|
|
1947
1950
|
type: 'WaitForUserInput';
|
|
1951
|
+
} | {
|
|
1952
|
+
type: 'Aborted';
|
|
1948
1953
|
} | ToolResponseExit | ToolResponseInterrupted | ToolResponseHandOver | ToolResponseDelegate | {
|
|
1949
1954
|
type: 'Pause';
|
|
1950
1955
|
responses: ToolResponseOrToolPause[];
|
|
@@ -2111,6 +2116,8 @@ export declare const handler_alias_8: ToolHandler<typeof toolInfo_alias_8, Files
|
|
|
2111
2116
|
|
|
2112
2117
|
export declare const handler_alias_9: ToolHandler<typeof toolInfo_alias_9, FilesystemProvider>;
|
|
2113
2118
|
|
|
2119
|
+
export declare type ImageBlockParam = Anthropic.Messages.ImageBlockParam;
|
|
2120
|
+
|
|
2114
2121
|
declare type Input = {
|
|
2115
2122
|
commitMessages: string;
|
|
2116
2123
|
commitDiff: string;
|
|
@@ -2470,6 +2477,7 @@ declare class MultiAgent {
|
|
|
2470
2477
|
}): Promise<ExitReason>;
|
|
2471
2478
|
continueTask(userMessage: string): Promise<ExitReason>;
|
|
2472
2479
|
get hasActiveAgent(): boolean;
|
|
2480
|
+
abort(): void;
|
|
2473
2481
|
}
|
|
2474
2482
|
export { MultiAgent }
|
|
2475
2483
|
export { MultiAgent as MultiAgent_alias_1 }
|
|
@@ -2493,7 +2501,7 @@ export declare class OllamaService extends AiServiceBase {
|
|
|
2493
2501
|
info: ModelInfo;
|
|
2494
2502
|
};
|
|
2495
2503
|
constructor(options: AiServiceOptions);
|
|
2496
|
-
sendImpl(systemPrompt: string, messages: MessageParam[]): ApiStream;
|
|
2504
|
+
sendImpl(systemPrompt: string, messages: MessageParam[], signal: AbortSignal): ApiStream;
|
|
2497
2505
|
}
|
|
2498
2506
|
|
|
2499
2507
|
declare const openAiModelInfoSaneDefaults: {
|
|
@@ -2515,7 +2523,7 @@ export declare class OpenRouterService extends AiServiceBase {
|
|
|
2515
2523
|
info: ModelInfo;
|
|
2516
2524
|
};
|
|
2517
2525
|
constructor(options: AiServiceOptions);
|
|
2518
|
-
sendImpl(systemPrompt: string, messages: MessageParam[]): ApiStream;
|
|
2526
|
+
sendImpl(systemPrompt: string, messages: MessageParam[], signal: AbortSignal): ApiStream;
|
|
2519
2527
|
}
|
|
2520
2528
|
|
|
2521
2529
|
declare type Output = {
|
|
@@ -2605,15 +2613,24 @@ declare enum Policies {
|
|
|
2605
2613
|
export { Policies }
|
|
2606
2614
|
export { Policies as Policies_alias_1 }
|
|
2607
2615
|
|
|
2608
|
-
declare const replaceInFile_2: (fileContent: string, diff: string) =>
|
|
2616
|
+
declare const replaceInFile_2: (fileContent: string, diff: string) => ReplaceResult;
|
|
2609
2617
|
export { replaceInFile_2 as replaceInFileHelper }
|
|
2610
2618
|
export { replaceInFile_2 as replaceInFile_alias_3 }
|
|
2611
2619
|
export { replaceInFile_2 as replaceInFile_alias_4 }
|
|
2612
2620
|
|
|
2621
|
+
declare type ReplaceResult = {
|
|
2622
|
+
content: string;
|
|
2623
|
+
status: 'no_diff_applied' | 'some_diff_applied' | 'all_diff_applied';
|
|
2624
|
+
appliedCount: number;
|
|
2625
|
+
totalCount: number;
|
|
2626
|
+
};
|
|
2627
|
+
export { ReplaceResult }
|
|
2628
|
+
export { ReplaceResult as ReplaceResult_alias_1 }
|
|
2629
|
+
|
|
2613
2630
|
declare const responsePrompts: {
|
|
2614
2631
|
readonly errorInvokeTool: (tool: string, error: unknown) => string;
|
|
2615
2632
|
readonly requireUseTool: "Error: No tool use detected. You MUST use a tool before proceeding.\ne.g. <tool_tool_name>tool_name</tool_tool_name>\n\nEnsure the opening and closing tags are correctly nested and closed, and that you are using the correct tool name.\nAvoid unnecessary text or symbols before or after the tool use.\nAvoid unnecessary escape characters or special characters.\n";
|
|
2616
|
-
readonly toolResults: (tool: string, result:
|
|
2633
|
+
readonly toolResults: (tool: string, result: UserContent) => (TextBlockParam | ImageBlockParam)[];
|
|
2617
2634
|
readonly commandResult: (command: string, exitCode: number, stdout: string, stderr: string) => string;
|
|
2618
2635
|
};
|
|
2619
2636
|
export { responsePrompts }
|
|
@@ -2726,7 +2743,7 @@ export { TaskEventKind as TaskEventKind_alias_2 }
|
|
|
2726
2743
|
*/
|
|
2727
2744
|
declare interface TaskEventStartRequest extends TaskEventBase {
|
|
2728
2745
|
kind: TaskEventKind.StartRequest;
|
|
2729
|
-
userMessage:
|
|
2746
|
+
userMessage: UserContent;
|
|
2730
2747
|
}
|
|
2731
2748
|
export { TaskEventStartRequest }
|
|
2732
2749
|
export { TaskEventStartRequest as TaskEventStartRequest_alias_1 }
|
|
@@ -2809,6 +2826,8 @@ export { TaskEventUsageExceeded }
|
|
|
2809
2826
|
export { TaskEventUsageExceeded as TaskEventUsageExceeded_alias_1 }
|
|
2810
2827
|
export { TaskEventUsageExceeded as TaskEventUsageExceeded_alias_2 }
|
|
2811
2828
|
|
|
2829
|
+
export declare type TextBlockParam = Anthropic.Messages.TextBlockParam;
|
|
2830
|
+
|
|
2812
2831
|
declare interface TextContent {
|
|
2813
2832
|
type: 'text';
|
|
2814
2833
|
content: string;
|
|
@@ -3077,7 +3096,7 @@ export declare const toolInfo_alias_12: {
|
|
|
3077
3096
|
|
|
3078
3097
|
export declare const toolInfo_alias_13: {
|
|
3079
3098
|
readonly name: "write_to_file";
|
|
3080
|
-
readonly description: "Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file. Ensure that the output content does not include incorrect escaped character patterns such as `<
|
|
3099
|
+
readonly description: "Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file. Ensure that the output content does not include incorrect escaped character patterns such as `<`, `>`, or `&`. Also ensure there is no unwanted CDATA tags in the content.";
|
|
3081
3100
|
readonly parameters: [{
|
|
3082
3101
|
readonly name: "path";
|
|
3083
3102
|
readonly description: "The path of the file to write to";
|
|
@@ -3427,7 +3446,7 @@ export { ToolResponseInvalid as ToolResponseInvalid_alias_1 }
|
|
|
3427
3446
|
declare type ToolResponseOrToolPause = {
|
|
3428
3447
|
type: 'response';
|
|
3429
3448
|
tool: string;
|
|
3430
|
-
response:
|
|
3449
|
+
response: UserContent;
|
|
3431
3450
|
} | {
|
|
3432
3451
|
type: 'pause';
|
|
3433
3452
|
tool: string;
|
|
@@ -3446,7 +3465,7 @@ export { ToolResponsePause as ToolResponsePause_alias_1 }
|
|
|
3446
3465
|
|
|
3447
3466
|
declare type ToolResponseReply = {
|
|
3448
3467
|
type: ToolResponseType.Reply;
|
|
3449
|
-
message:
|
|
3468
|
+
message: UserContent;
|
|
3450
3469
|
};
|
|
3451
3470
|
export { ToolResponseReply }
|
|
3452
3471
|
export { ToolResponseReply as ToolResponseReply_alias_1 }
|
|
@@ -3530,6 +3549,11 @@ export { UsageMeter }
|
|
|
3530
3549
|
export { UsageMeter as UsageMeter_alias_1 }
|
|
3531
3550
|
export { UsageMeter as UsageMeter_alias_2 }
|
|
3532
3551
|
|
|
3552
|
+
declare type UserContent = string | (TextBlockParam | ImageBlockParam)[];
|
|
3553
|
+
export { UserContent }
|
|
3554
|
+
export { UserContent as UserContent_alias_1 }
|
|
3555
|
+
export { UserContent as UserContent_alias_2 }
|
|
3556
|
+
|
|
3533
3557
|
declare type WebProvider = {
|
|
3534
3558
|
fetchUrl?: (url: string) => Promise<string>;
|
|
3535
3559
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { defaultModels } from './_tsup-dts-rollup.js';
|
|
|
4
4
|
export { createService } from './_tsup-dts-rollup.js';
|
|
5
5
|
export { UsageMeter } from './_tsup-dts-rollup.js';
|
|
6
6
|
export { AiServiceBase } from './_tsup-dts-rollup.js';
|
|
7
|
+
export { UserContent } from './_tsup-dts-rollup.js';
|
|
7
8
|
export { MessageParam } from './_tsup-dts-rollup.js';
|
|
8
9
|
export { AiServiceOptions } from './_tsup-dts-rollup.js';
|
|
9
10
|
export { ModelInfo } from './_tsup-dts-rollup.js';
|
package/dist/index.js
CHANGED
|
@@ -8,14 +8,19 @@ var __export = (target, all) => {
|
|
|
8
8
|
var AiServiceBase = class {
|
|
9
9
|
usageMeter;
|
|
10
10
|
options;
|
|
11
|
+
#abortController;
|
|
11
12
|
constructor(options) {
|
|
12
13
|
this.options = options;
|
|
13
14
|
this.usageMeter = options.usageMeter;
|
|
14
15
|
}
|
|
16
|
+
abort() {
|
|
17
|
+
this.#abortController?.abort();
|
|
18
|
+
}
|
|
15
19
|
async *send(systemPrompt, messages) {
|
|
16
20
|
this.usageMeter.checkLimit();
|
|
17
21
|
this.usageMeter.incrementMessageCount();
|
|
18
|
-
|
|
22
|
+
this.#abortController = new AbortController();
|
|
23
|
+
const stream = this.sendImpl(systemPrompt, messages, this.#abortController.signal);
|
|
19
24
|
for await (const chunk of stream) {
|
|
20
25
|
switch (chunk.type) {
|
|
21
26
|
case "usage":
|
|
@@ -28,7 +33,8 @@ var AiServiceBase = class {
|
|
|
28
33
|
async request(systemPrompt, messages) {
|
|
29
34
|
this.usageMeter.checkLimit();
|
|
30
35
|
this.usageMeter.incrementMessageCount();
|
|
31
|
-
|
|
36
|
+
this.#abortController = new AbortController();
|
|
37
|
+
const stream = this.sendImpl(systemPrompt, messages, this.#abortController.signal);
|
|
32
38
|
const usage = {
|
|
33
39
|
inputTokens: 0,
|
|
34
40
|
outputTokens: 0,
|
|
@@ -208,7 +214,7 @@ var AnthropicService = class extends AiServiceBase {
|
|
|
208
214
|
info: anthropicModels[id] ?? anthropicModels[anthropicDefaultModelId]
|
|
209
215
|
};
|
|
210
216
|
}
|
|
211
|
-
async *sendImpl(systemPrompt, messages) {
|
|
217
|
+
async *sendImpl(systemPrompt, messages, signal) {
|
|
212
218
|
let stream;
|
|
213
219
|
const modelId = this.model.id;
|
|
214
220
|
const cacheControl = this.#options.enableCache ? { type: "ephemeral" } : void 0;
|
|
@@ -236,52 +242,58 @@ var AnthropicService = class extends AiServiceBase {
|
|
|
236
242
|
}, []);
|
|
237
243
|
const lastUserMsgIndex = userMsgIndices[userMsgIndices.length - 1] ?? -1;
|
|
238
244
|
const secondLastMsgUserIndex = userMsgIndices[userMsgIndices.length - 2] ?? -1;
|
|
239
|
-
stream = await this.#client.messages.create(
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
245
|
+
stream = await this.#client.messages.create(
|
|
246
|
+
{
|
|
247
|
+
model: modelId,
|
|
248
|
+
max_tokens: this.model.info.maxTokens || 8192,
|
|
249
|
+
thinking: thinkingBudgetTokens ? { type: "enabled", budget_tokens: thinkingBudgetTokens } : void 0,
|
|
250
|
+
temperature,
|
|
251
|
+
system: [
|
|
252
|
+
{
|
|
253
|
+
text: systemPrompt,
|
|
254
|
+
type: "text",
|
|
255
|
+
cache_control: cacheControl
|
|
256
|
+
}
|
|
257
|
+
],
|
|
258
|
+
// setting cache breakpoint for system prompt so new tasks can reuse it
|
|
259
|
+
messages: messages.map((message, index) => {
|
|
260
|
+
if (index === lastUserMsgIndex || index === secondLastMsgUserIndex) {
|
|
261
|
+
return {
|
|
262
|
+
...message,
|
|
263
|
+
content: typeof message.content === "string" ? [
|
|
264
|
+
{
|
|
265
|
+
type: "text",
|
|
266
|
+
text: message.content,
|
|
267
|
+
cache_control: cacheControl
|
|
268
|
+
}
|
|
269
|
+
] : message.content.map(
|
|
270
|
+
(content, contentIndex) => contentIndex === message.content.length - 1 ? {
|
|
271
|
+
...content,
|
|
272
|
+
cache_control: cacheControl
|
|
273
|
+
} : content
|
|
274
|
+
)
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
return message;
|
|
278
|
+
}),
|
|
279
|
+
stream: true
|
|
280
|
+
},
|
|
281
|
+
{ signal }
|
|
282
|
+
);
|
|
274
283
|
break;
|
|
275
284
|
}
|
|
276
285
|
default: {
|
|
277
|
-
stream = await this.#client.messages.create(
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
286
|
+
stream = await this.#client.messages.create(
|
|
287
|
+
{
|
|
288
|
+
model: modelId,
|
|
289
|
+
max_tokens: this.model.info.maxTokens || 8192,
|
|
290
|
+
temperature: 0,
|
|
291
|
+
system: [{ text: systemPrompt, type: "text" }],
|
|
292
|
+
messages,
|
|
293
|
+
stream: true
|
|
294
|
+
},
|
|
295
|
+
{ signal }
|
|
296
|
+
);
|
|
285
297
|
break;
|
|
286
298
|
}
|
|
287
299
|
}
|
|
@@ -487,19 +499,22 @@ var DeepSeekService = class extends AiServiceBase {
|
|
|
487
499
|
info: deepSeekModels[id] ?? deepSeekModels[deepSeekDefaultModelId]
|
|
488
500
|
};
|
|
489
501
|
}
|
|
490
|
-
async *sendImpl(systemPrompt, messages) {
|
|
502
|
+
async *sendImpl(systemPrompt, messages, signal) {
|
|
491
503
|
const openAiMessages = [
|
|
492
504
|
{ role: "system", content: systemPrompt },
|
|
493
505
|
...convertToOpenAiMessages(messages)
|
|
494
506
|
];
|
|
495
|
-
const stream = await this.#client.chat.completions.create(
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
507
|
+
const stream = await this.#client.chat.completions.create(
|
|
508
|
+
{
|
|
509
|
+
model: this.model.id,
|
|
510
|
+
max_completion_tokens: this.model.info.maxTokens,
|
|
511
|
+
messages: openAiMessages,
|
|
512
|
+
temperature: 0,
|
|
513
|
+
stream: true,
|
|
514
|
+
stream_options: { include_usage: true }
|
|
515
|
+
},
|
|
516
|
+
{ signal }
|
|
517
|
+
);
|
|
503
518
|
for await (const chunk of stream) {
|
|
504
519
|
const delta = chunk.choices[0]?.delta;
|
|
505
520
|
if (delta?.reasoning_content) {
|
|
@@ -549,17 +564,20 @@ var OllamaService = class extends AiServiceBase {
|
|
|
549
564
|
info: openAiModelInfoSaneDefaults
|
|
550
565
|
};
|
|
551
566
|
}
|
|
552
|
-
async *sendImpl(systemPrompt, messages) {
|
|
567
|
+
async *sendImpl(systemPrompt, messages, signal) {
|
|
553
568
|
const openAiMessages = [
|
|
554
569
|
{ role: "system", content: systemPrompt },
|
|
555
570
|
...convertToOpenAiMessages(messages)
|
|
556
571
|
];
|
|
557
|
-
const stream = await this.#client.chat.completions.create(
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
572
|
+
const stream = await this.#client.chat.completions.create(
|
|
573
|
+
{
|
|
574
|
+
model: this.model.id,
|
|
575
|
+
messages: openAiMessages,
|
|
576
|
+
temperature: 0,
|
|
577
|
+
stream: true
|
|
578
|
+
},
|
|
579
|
+
{ signal }
|
|
580
|
+
);
|
|
563
581
|
for await (const chunk of stream) {
|
|
564
582
|
const delta = chunk.choices[0]?.delta;
|
|
565
583
|
if (delta?.content) {
|
|
@@ -609,7 +627,7 @@ var OpenRouterService = class extends AiServiceBase {
|
|
|
609
627
|
this.#modelProviderInfo = data.data;
|
|
610
628
|
});
|
|
611
629
|
}
|
|
612
|
-
async *sendImpl(systemPrompt, messages) {
|
|
630
|
+
async *sendImpl(systemPrompt, messages, signal) {
|
|
613
631
|
const openAiMessages = [
|
|
614
632
|
{ role: "system", content: systemPrompt },
|
|
615
633
|
...convertToOpenAiMessages(messages)
|
|
@@ -662,15 +680,18 @@ var OpenRouterService = class extends AiServiceBase {
|
|
|
662
680
|
if (this.model.id === "deepseek/deepseek-chat") {
|
|
663
681
|
shouldApplyMiddleOutTransform = true;
|
|
664
682
|
}
|
|
665
|
-
const stream = await this.#client.chat.completions.create(
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
683
|
+
const stream = await this.#client.chat.completions.create(
|
|
684
|
+
{
|
|
685
|
+
model: this.model.id,
|
|
686
|
+
messages: openAiMessages,
|
|
687
|
+
temperature: 0,
|
|
688
|
+
stream: true,
|
|
689
|
+
transforms: shouldApplyMiddleOutTransform ? ["middle-out"] : void 0,
|
|
690
|
+
include_reasoning: true,
|
|
691
|
+
...reasoning
|
|
692
|
+
},
|
|
693
|
+
{ signal }
|
|
694
|
+
);
|
|
674
695
|
let genId;
|
|
675
696
|
for await (const chunk of stream) {
|
|
676
697
|
if ("error" in chunk) {
|
|
@@ -1008,7 +1029,7 @@ var getArray = (args, name, defaultValue) => {
|
|
|
1008
1029
|
};
|
|
1009
1030
|
|
|
1010
1031
|
// src/tools/utils/replaceInFile.ts
|
|
1011
|
-
var replaceInFile =
|
|
1032
|
+
var replaceInFile = (fileContent, diff) => {
|
|
1012
1033
|
const blockPattern = /<<<<<+ SEARCH>?\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+ REPLACE/g;
|
|
1013
1034
|
const blocks = [];
|
|
1014
1035
|
for (let match = blockPattern.exec(diff); match !== null; match = blockPattern.exec(diff)) {
|
|
@@ -1053,14 +1074,32 @@ var replaceInFile = async (fileContent, diff) => {
|
|
|
1053
1074
|
const startPos = endPos - strippedSearch.length;
|
|
1054
1075
|
return content.slice(0, startPos) + replace + content.slice(endPos);
|
|
1055
1076
|
}
|
|
1056
|
-
|
|
1057
|
-
${search}`);
|
|
1077
|
+
return null;
|
|
1058
1078
|
};
|
|
1059
1079
|
let updatedFile = fileContent;
|
|
1080
|
+
let appliedCount = 0;
|
|
1081
|
+
const totalCount = blocks.length;
|
|
1060
1082
|
for (const { search, replace } of blocks) {
|
|
1061
|
-
|
|
1083
|
+
const result = findAndReplace(updatedFile, search, replace);
|
|
1084
|
+
if (result !== null) {
|
|
1085
|
+
updatedFile = result;
|
|
1086
|
+
appliedCount++;
|
|
1087
|
+
}
|
|
1062
1088
|
}
|
|
1063
|
-
|
|
1089
|
+
let status;
|
|
1090
|
+
if (appliedCount === 0) {
|
|
1091
|
+
status = "no_diff_applied";
|
|
1092
|
+
} else if (appliedCount < totalCount) {
|
|
1093
|
+
status = "some_diff_applied";
|
|
1094
|
+
} else {
|
|
1095
|
+
status = "all_diff_applied";
|
|
1096
|
+
}
|
|
1097
|
+
return {
|
|
1098
|
+
content: updatedFile,
|
|
1099
|
+
status,
|
|
1100
|
+
appliedCount,
|
|
1101
|
+
totalCount
|
|
1102
|
+
};
|
|
1064
1103
|
};
|
|
1065
1104
|
|
|
1066
1105
|
// src/tools/askFollowupQuestion.ts
|
|
@@ -1759,14 +1798,26 @@ var handler8 = async (provider, args) => {
|
|
|
1759
1798
|
if (fileContent == null) {
|
|
1760
1799
|
return {
|
|
1761
1800
|
type: "Error" /* Error */,
|
|
1762
|
-
message: `<
|
|
1801
|
+
message: `<replace_in_file_result path="${path}" status="failed" message="File not found" />`
|
|
1802
|
+
};
|
|
1803
|
+
}
|
|
1804
|
+
const result = replaceInFile(fileContent, diff);
|
|
1805
|
+
if (result.status === "no_diff_applied") {
|
|
1806
|
+
return {
|
|
1807
|
+
type: "Error" /* Error */,
|
|
1808
|
+
message: `<replace_in_file_result path="${path}" status="failed" message="Unable to apply changes" />`
|
|
1809
|
+
};
|
|
1810
|
+
}
|
|
1811
|
+
await provider.writeFile(path, result.content);
|
|
1812
|
+
if (result.status === "some_diff_applied") {
|
|
1813
|
+
return {
|
|
1814
|
+
type: "Reply" /* Reply */,
|
|
1815
|
+
message: `<replace_in_file_result path="${path}" status="some_diff_applied" applied_count="${result.appliedCount}" total_count="${result.totalCount}" />`
|
|
1763
1816
|
};
|
|
1764
1817
|
}
|
|
1765
|
-
const result = await replaceInFile(fileContent, diff);
|
|
1766
|
-
await provider.writeFile(path, result);
|
|
1767
1818
|
return {
|
|
1768
1819
|
type: "Reply" /* Reply */,
|
|
1769
|
-
message: `<
|
|
1820
|
+
message: `<replace_in_file_result path="${path}" status="all_diff_applied" />`
|
|
1770
1821
|
};
|
|
1771
1822
|
};
|
|
1772
1823
|
var isAvailable8 = (provider) => {
|
|
@@ -2166,7 +2217,7 @@ var updateKnowledge_default = {
|
|
|
2166
2217
|
// src/tools/writeToFile.ts
|
|
2167
2218
|
var toolInfo11 = {
|
|
2168
2219
|
name: "write_to_file",
|
|
2169
|
-
description: "Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file. Ensure that the output content does not include incorrect escaped character patterns such as `<
|
|
2220
|
+
description: "Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file. Ensure that the output content does not include incorrect escaped character patterns such as `<`, `>`, or `&`. Also ensure there is no unwanted CDATA tags in the content.",
|
|
2170
2221
|
parameters: [
|
|
2171
2222
|
{
|
|
2172
2223
|
name: "path",
|
|
@@ -2217,7 +2268,9 @@ var handler11 = async (provider, args) => {
|
|
|
2217
2268
|
};
|
|
2218
2269
|
}
|
|
2219
2270
|
const path = getString(args, "path");
|
|
2220
|
-
|
|
2271
|
+
let content = getString(args, "content");
|
|
2272
|
+
const trimmedContent = content.trim();
|
|
2273
|
+
if (trimmedContent.startsWith("<![CDATA[") && content.endsWith("]]>")) content = trimmedContent.slice(9, -3);
|
|
2221
2274
|
await provider.writeFile(path, content);
|
|
2222
2275
|
return {
|
|
2223
2276
|
type: "Reply" /* Reply */,
|
|
@@ -2773,12 +2826,27 @@ Ensure the opening and closing tags are correctly nested and closed, and that yo
|
|
|
2773
2826
|
Avoid unnecessary text or symbols before or after the tool use.
|
|
2774
2827
|
Avoid unnecessary escape characters or special characters.
|
|
2775
2828
|
`,
|
|
2776
|
-
toolResults: (tool, result) =>
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
</tool_response
|
|
2829
|
+
toolResults: (tool, result) => {
|
|
2830
|
+
if (typeof result === "string") {
|
|
2831
|
+
return [
|
|
2832
|
+
{
|
|
2833
|
+
type: "text",
|
|
2834
|
+
text: `<tool_response name=${tool}>${result}</tool_response>`
|
|
2835
|
+
}
|
|
2836
|
+
];
|
|
2837
|
+
}
|
|
2838
|
+
return [
|
|
2839
|
+
{
|
|
2840
|
+
type: "text",
|
|
2841
|
+
text: `<tool_response name=${tool}>`
|
|
2842
|
+
},
|
|
2843
|
+
...result,
|
|
2844
|
+
{
|
|
2845
|
+
type: "text",
|
|
2846
|
+
text: "</tool_response>"
|
|
2847
|
+
}
|
|
2848
|
+
];
|
|
2849
|
+
},
|
|
2782
2850
|
commandResult: (command, exitCode, stdout, stderr) => `<command>${command}</command>
|
|
2783
2851
|
<command_exit_code>${exitCode}</command_exit_code>
|
|
2784
2852
|
<command_stdout>
|
|
@@ -2815,6 +2883,7 @@ var AgentBase = class {
|
|
|
2815
2883
|
handlers;
|
|
2816
2884
|
#messages = [];
|
|
2817
2885
|
#policies;
|
|
2886
|
+
#aborted = false;
|
|
2818
2887
|
constructor(name, ai, config) {
|
|
2819
2888
|
this.ai = ai;
|
|
2820
2889
|
if (config.agents && config.agents.length > 0) {
|
|
@@ -2846,6 +2915,10 @@ ${instance.prompt}`;
|
|
|
2846
2915
|
this.config = config;
|
|
2847
2916
|
this.#policies = policies;
|
|
2848
2917
|
}
|
|
2918
|
+
abort() {
|
|
2919
|
+
this.#aborted = true;
|
|
2920
|
+
this.ai.abort();
|
|
2921
|
+
}
|
|
2849
2922
|
get parameters() {
|
|
2850
2923
|
return this.ai.options.parameters;
|
|
2851
2924
|
}
|
|
@@ -2874,11 +2947,17 @@ ${instance.prompt}`;
|
|
|
2874
2947
|
async #processLoop(userMessage) {
|
|
2875
2948
|
let nextRequest = userMessage;
|
|
2876
2949
|
while (true) {
|
|
2950
|
+
if (this.#aborted) {
|
|
2951
|
+
return { type: "Aborted" };
|
|
2952
|
+
}
|
|
2877
2953
|
if (this.ai.usageMeter.isLimitExceeded().result) {
|
|
2878
2954
|
this.#callback({ kind: "UsageExceeded" /* UsageExceeded */, agent: this });
|
|
2879
2955
|
return { type: "UsageExceeded" };
|
|
2880
2956
|
}
|
|
2881
2957
|
const response = await this.#request(nextRequest);
|
|
2958
|
+
if (this.#aborted) {
|
|
2959
|
+
return { type: "Aborted" };
|
|
2960
|
+
}
|
|
2882
2961
|
const resp = await this.#handleResponse(response);
|
|
2883
2962
|
if (resp.type === "exit") {
|
|
2884
2963
|
this.#callback({ kind: "EndTask" /* EndTask */, agent: this, exitReason: resp.reason });
|
|
@@ -2925,14 +3004,23 @@ ${instance.prompt}`;
|
|
|
2925
3004
|
}
|
|
2926
3005
|
}
|
|
2927
3006
|
} catch (error) {
|
|
3007
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
3008
|
+
break;
|
|
3009
|
+
}
|
|
2928
3010
|
console.error("Error in stream:", error);
|
|
2929
3011
|
}
|
|
2930
3012
|
if (currentAssistantMessage) {
|
|
2931
3013
|
break;
|
|
2932
3014
|
}
|
|
3015
|
+
if (this.#aborted) {
|
|
3016
|
+
break;
|
|
3017
|
+
}
|
|
2933
3018
|
console.debug(`Retrying request ${i + 1} of ${retryCount}`);
|
|
2934
3019
|
}
|
|
2935
3020
|
if (!currentAssistantMessage) {
|
|
3021
|
+
if (this.#aborted) {
|
|
3022
|
+
return [];
|
|
3023
|
+
}
|
|
2936
3024
|
throw new Error("No assistant message received");
|
|
2937
3025
|
}
|
|
2938
3026
|
this.#messages.push({
|
|
@@ -2960,23 +3048,26 @@ ${instance.prompt}`;
|
|
|
2960
3048
|
await this.#callback({ kind: "ToolUse" /* ToolUse */, agent: this, tool: content.name });
|
|
2961
3049
|
const toolResp = await this.#invokeTool(content.name, content.params);
|
|
2962
3050
|
switch (toolResp.type) {
|
|
2963
|
-
case "Reply" /* Reply */:
|
|
3051
|
+
case "Reply" /* Reply */: {
|
|
2964
3052
|
await this.#callback({ kind: "ToolReply" /* ToolReply */, agent: this, tool: content.name });
|
|
2965
3053
|
toolResponses.push({ type: "response", tool: content.name, response: toolResp.message });
|
|
2966
3054
|
break;
|
|
3055
|
+
}
|
|
2967
3056
|
case "Exit" /* Exit */:
|
|
2968
3057
|
if (toolResponses.length > 0) {
|
|
2969
3058
|
break outer;
|
|
2970
3059
|
}
|
|
2971
3060
|
return { type: "exit", reason: toolResp };
|
|
2972
|
-
case "Invalid" /* Invalid */:
|
|
3061
|
+
case "Invalid" /* Invalid */: {
|
|
2973
3062
|
await this.#callback({ kind: "ToolInvalid" /* ToolInvalid */, agent: this, tool: content.name });
|
|
2974
3063
|
toolResponses.push({ type: "response", tool: content.name, response: toolResp.message });
|
|
2975
3064
|
break outer;
|
|
2976
|
-
|
|
3065
|
+
}
|
|
3066
|
+
case "Error" /* Error */: {
|
|
2977
3067
|
await this.#callback({ kind: "ToolError" /* ToolError */, agent: this, tool: content.name });
|
|
2978
3068
|
toolResponses.push({ type: "response", tool: content.name, response: toolResp.message });
|
|
2979
3069
|
break outer;
|
|
3070
|
+
}
|
|
2980
3071
|
case "Interrupted" /* Interrupted */:
|
|
2981
3072
|
await this.#callback({ kind: "ToolInterrupted" /* ToolInterrupted */, agent: this, tool: content.name });
|
|
2982
3073
|
return { type: "exit", reason: toolResp };
|
|
@@ -3026,7 +3117,7 @@ ${instance.prompt}`;
|
|
|
3026
3117
|
if (toolResponses.length === 0) {
|
|
3027
3118
|
return { type: "reply", message: responsePrompts.requireUseTool };
|
|
3028
3119
|
}
|
|
3029
|
-
const finalResp = toolResponses.filter((resp) => resp.type === "response").
|
|
3120
|
+
const finalResp = toolResponses.filter((resp) => resp.type === "response").flatMap(({ tool, response: response2 }) => responsePrompts.toolResults(tool, response2));
|
|
3030
3121
|
return { type: "reply", message: finalResp };
|
|
3031
3122
|
}
|
|
3032
3123
|
async #invokeTool(name, args) {
|
|
@@ -3643,6 +3734,7 @@ var MultiAgent = class {
|
|
|
3643
3734
|
case "Delegate" /* Delegate */:
|
|
3644
3735
|
console.warn("Unexpected exit reason", delegateResult);
|
|
3645
3736
|
break;
|
|
3737
|
+
case "Aborted":
|
|
3646
3738
|
case "Interrupted" /* Interrupted */:
|
|
3647
3739
|
return delegateResult;
|
|
3648
3740
|
case "Exit" /* Exit */:
|
|
@@ -3650,6 +3742,7 @@ var MultiAgent = class {
|
|
|
3650
3742
|
}
|
|
3651
3743
|
return delegateResult;
|
|
3652
3744
|
}
|
|
3745
|
+
case "Aborted":
|
|
3653
3746
|
case "Interrupted" /* Interrupted */:
|
|
3654
3747
|
case "Exit" /* Exit */:
|
|
3655
3748
|
this.#agents.pop();
|
|
@@ -3682,6 +3775,11 @@ var MultiAgent = class {
|
|
|
3682
3775
|
get hasActiveAgent() {
|
|
3683
3776
|
return this.#agents.length > 0;
|
|
3684
3777
|
}
|
|
3778
|
+
abort() {
|
|
3779
|
+
if (this.hasActiveAgent) {
|
|
3780
|
+
this.#agents[this.#agents.length - 1].abort();
|
|
3781
|
+
}
|
|
3782
|
+
}
|
|
3685
3783
|
};
|
|
3686
3784
|
|
|
3687
3785
|
// src/config.ts
|
|
@@ -3758,27 +3856,26 @@ var prompt = `
|
|
|
3758
3856
|
You are equipped with **Knowledge Management** capabilities:
|
|
3759
3857
|
|
|
3760
3858
|
1. **What to capture**
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
\u2022 Any other insight that a future contributor would find crucial.
|
|
3859
|
+
- Public API of each file (public classes, functions, methods, parameters, return types).
|
|
3860
|
+
- High-level description of each file's purpose.
|
|
3861
|
+
- Invariants and assumptions that must always hold.
|
|
3862
|
+
- Project or directory-specific coding patterns, styles, and architectural conventions.
|
|
3863
|
+
- Any other insight that a future contributor would find crucial.
|
|
3767
3864
|
|
|
3768
3865
|
2. **Where to store it**
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3866
|
+
- Save knowledge in a YAML file named \`knowledge.ai.yml\`.
|
|
3867
|
+
- **Create the file in the repository root if it does not yet exist.**
|
|
3868
|
+
- One file per directory.
|
|
3772
3869
|
- The repository root file records knowledge that applies project-wide (e.g., service responsibilities, global patterns).
|
|
3773
3870
|
- Each sub-directory keeps only the knowledge relevant to that directory or package.
|
|
3774
|
-
|
|
3871
|
+
- Use clear top-level keys such as \`description\`, \`files\`, \`rules\`.
|
|
3775
3872
|
|
|
3776
3873
|
3. **When to update**
|
|
3777
|
-
|
|
3874
|
+
- **Default behaviour:** only create / update knowledge for the files you actively read, create, or modify during the current task.
|
|
3778
3875
|
- Operate on other files **only if the user explicitly requests it**.
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3876
|
+
- **While working**: after reading, analysing, creating, or modifying code, immediately record any new or changed knowledge.
|
|
3877
|
+
- **On refactor / deletion**: locate and delete or amend obsolete entries so that knowledge never drifts from the codebase.
|
|
3878
|
+
- **Granularity**: update only the affected directory's \`knowledge.ai.yml\`, except when the change has global impact.
|
|
3782
3879
|
|
|
3783
3880
|
4. **How to format (illustrative)**
|
|
3784
3881
|
\`\`\`yaml
|
|
@@ -3788,19 +3885,14 @@ files:
|
|
|
3788
3885
|
description: "Numeric helpers for currency calculations"
|
|
3789
3886
|
api:
|
|
3790
3887
|
functions:
|
|
3791
|
-
1:
|
|
3792
|
-
name: "add"
|
|
3793
|
-
params:
|
|
3794
|
-
1: { name: "a", type: "number" }
|
|
3795
|
-
2: { name: "b", type: "number" }
|
|
3796
|
-
returns: "number"
|
|
3888
|
+
1: add(a: number, b: number): number
|
|
3797
3889
|
rules:
|
|
3798
3890
|
1: "rules that apply to all files in this directory"
|
|
3799
3891
|
\`\`\`
|
|
3800
3892
|
|
|
3801
3893
|
5. **Source of truth**
|
|
3802
|
-
|
|
3803
|
-
|
|
3894
|
+
- **Never invent knowledge.** Everything you record must be *directly derived* from existing code, comments, commit messages, or explicit user instructions.
|
|
3895
|
+
- If a section has no confirmed content, omit it rather than guessing.
|
|
3804
3896
|
|
|
3805
3897
|
6. **Automatic context**
|
|
3806
3898
|
When you are asked to read or modify a file, the orchestration layer will supply any existing knowledge for that path automatically. Use it, refine it, and keep it accurate.
|
|
@@ -3809,11 +3901,11 @@ rules:
|
|
|
3809
3901
|
You can use the \`updateKnowledge\` tool to efficiently update knowledge files with smart merging capabilities.
|
|
3810
3902
|
|
|
3811
3903
|
8. **Dictionary-First Format**
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3904
|
+
- **Always prefer dictionaries** for structured data.
|
|
3905
|
+
- The **\`files\` section must be a dictionary keyed by file path** (e.g., \`"math.ts": {...}\`).
|
|
3906
|
+
- For other lists (rules, functions, etc.), use numbered dictionaries.
|
|
3907
|
+
- Arrays are allowed only when strict ordering is essential and dictionaries cannot express it.
|
|
3908
|
+
- When removing items, refer to them by their numeric key or index; gaps are fine.
|
|
3817
3909
|
|
|
3818
3910
|
Your workflow **must**:
|
|
3819
3911
|
1. Detect knowledge deltas.
|