@tyvm/knowhow 0.0.84 → 0.0.86
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/package.json +1 -1
- package/src/agents/base/base.ts +99 -37
- package/src/agents/researcher/researcher.ts +1 -2
- package/src/agents/tools/aiClient.ts +48 -0
- package/src/agents/tools/list.ts +57 -0
- package/src/chat/CliChatService.ts +3 -1
- package/src/chat/modules/AgentModule.ts +20 -31
- package/src/chat/types.ts +1 -0
- package/src/cli.ts +19 -10
- package/src/clients/anthropic.ts +11 -0
- package/src/clients/contextLimits.ts +106 -0
- package/src/clients/gemini.ts +11 -0
- package/src/clients/index.ts +112 -0
- package/src/clients/openai.ts +11 -0
- package/src/clients/pricing/anthropic.ts +0 -4
- package/src/clients/pricing/google.ts +81 -2
- package/src/clients/pricing/openai.ts +68 -0
- package/src/clients/types.ts +8 -0
- package/src/clients/xai.ts +11 -0
- package/src/types.ts +79 -7
- package/tests/clients/pricing.test.ts +144 -0
- package/ts_build/package.json +1 -1
- package/ts_build/src/agents/base/base.d.ts +4 -0
- package/ts_build/src/agents/base/base.js +53 -28
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/researcher/researcher.js +1 -1
- package/ts_build/src/agents/researcher/researcher.js.map +1 -1
- package/ts_build/src/agents/tools/aiClient.d.ts +3 -0
- package/ts_build/src/agents/tools/aiClient.js +31 -1
- package/ts_build/src/agents/tools/aiClient.js.map +1 -1
- package/ts_build/src/agents/tools/list.js +48 -0
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.d.ts +1 -4
- package/ts_build/src/chat/modules/AgentModule.js +12 -15
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/types.d.ts +1 -0
- package/ts_build/src/cli.js +3 -2
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/clients/anthropic.d.ts +8 -4
- package/ts_build/src/clients/anthropic.js +9 -0
- package/ts_build/src/clients/anthropic.js.map +1 -1
- package/ts_build/src/clients/contextLimits.d.ts +3 -0
- package/ts_build/src/clients/contextLimits.js +88 -0
- package/ts_build/src/clients/contextLimits.js.map +1 -0
- package/ts_build/src/clients/gemini.d.ts +14 -10
- package/ts_build/src/clients/gemini.js +9 -0
- package/ts_build/src/clients/gemini.js.map +1 -1
- package/ts_build/src/clients/index.d.ts +15 -0
- package/ts_build/src/clients/index.js +70 -0
- package/ts_build/src/clients/index.js.map +1 -1
- package/ts_build/src/clients/openai.d.ts +4 -0
- package/ts_build/src/clients/openai.js +9 -0
- package/ts_build/src/clients/openai.js.map +1 -1
- package/ts_build/src/clients/pricing/anthropic.d.ts +4 -4
- package/ts_build/src/clients/pricing/anthropic.js +0 -4
- package/ts_build/src/clients/pricing/anthropic.js.map +1 -1
- package/ts_build/src/clients/pricing/google.d.ts +10 -10
- package/ts_build/src/clients/pricing/google.js +74 -2
- package/ts_build/src/clients/pricing/google.js.map +1 -1
- package/ts_build/src/clients/pricing/openai.js +65 -0
- package/ts_build/src/clients/pricing/openai.js.map +1 -1
- package/ts_build/src/clients/types.d.ts +4 -0
- package/ts_build/src/clients/xai.d.ts +4 -0
- package/ts_build/src/clients/xai.js +9 -0
- package/ts_build/src/clients/xai.js.map +1 -1
- package/ts_build/src/types.d.ts +33 -4
- package/ts_build/src/types.js +73 -5
- package/ts_build/src/types.js.map +1 -1
- package/ts_build/tests/clients/pricing.test.d.ts +1 -0
- package/ts_build/tests/clients/pricing.test.js +90 -0
- package/ts_build/tests/clients/pricing.test.js.map +1 -0
package/package.json
CHANGED
package/src/agents/base/base.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventEmitter } from "events";
|
|
1
|
+
import { EventEmitter } from "events"; // kept for reference; agentEvents now uses EventService
|
|
2
2
|
import {
|
|
3
3
|
GenericClient,
|
|
4
4
|
Message,
|
|
@@ -18,6 +18,7 @@ import { EventService } from "../../services/EventService";
|
|
|
18
18
|
import { AIClient, Clients } from "../../clients";
|
|
19
19
|
import { Models } from "../../ai";
|
|
20
20
|
import { MessageProcessor } from "../../services/MessageProcessor";
|
|
21
|
+
import { DEFAULT_CONTEXT_LIMIT } from "../../clients/contextLimits";
|
|
21
22
|
import { Marked } from "../../utils";
|
|
22
23
|
|
|
23
24
|
export { Message, Tool, ToolCall };
|
|
@@ -58,6 +59,10 @@ export abstract class BaseAgent implements IAgent {
|
|
|
58
59
|
protected turnCount = 0;
|
|
59
60
|
protected totalCostUsd = 0;
|
|
60
61
|
protected currentThread = 0;
|
|
62
|
+
|
|
63
|
+
protected compressThreshold = 30000;
|
|
64
|
+
protected compressMinMessages = 30;
|
|
65
|
+
|
|
61
66
|
protected threads = [] as Message[][];
|
|
62
67
|
protected pendingUserMessages = [] as Message[];
|
|
63
68
|
protected taskBreakdown = "";
|
|
@@ -109,21 +114,30 @@ export abstract class BaseAgent implements IAgent {
|
|
|
109
114
|
|
|
110
115
|
// Subscribe to "agent:msg" events for dynamic context loading
|
|
111
116
|
// Use setListener with a key so re-creating the agent doesn't double-subscribe
|
|
112
|
-
this.events.setListener(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
this.events.setListener(
|
|
118
|
+
{
|
|
119
|
+
key: `agent:msg:${this.constructor.name}`,
|
|
120
|
+
event: this.eventTypes.agentMsg,
|
|
121
|
+
},
|
|
122
|
+
(eventData: any) => {
|
|
123
|
+
if (
|
|
124
|
+
this.status === this.eventTypes.inProgress ||
|
|
125
|
+
this.status === this.eventTypes.pause
|
|
126
|
+
) {
|
|
127
|
+
const message = {
|
|
128
|
+
role: "user",
|
|
129
|
+
content: JSON.stringify(eventData),
|
|
130
|
+
} as Message;
|
|
131
|
+
this.addPendingMessage(message);
|
|
132
|
+
}
|
|
122
133
|
}
|
|
123
|
-
|
|
134
|
+
);
|
|
124
135
|
}
|
|
125
136
|
|
|
126
|
-
protected log(
|
|
137
|
+
protected log(
|
|
138
|
+
message: string,
|
|
139
|
+
level: "info" | "warn" | "error" = "info"
|
|
140
|
+
): void {
|
|
127
141
|
this.agentEvents.emit(this.eventTypes.agentLog, {
|
|
128
142
|
agentName: this.name,
|
|
129
143
|
message,
|
|
@@ -133,6 +147,29 @@ export abstract class BaseAgent implements IAgent {
|
|
|
133
147
|
});
|
|
134
148
|
}
|
|
135
149
|
|
|
150
|
+
setCompressThreshold(threshold: number) {
|
|
151
|
+
this.compressThreshold = threshold;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Returns the effective compress threshold for the current model.
|
|
156
|
+
* If the user has manually set a custom threshold (different from the default 30k),
|
|
157
|
+
* that value is used as-is. Otherwise, the threshold is dynamically computed as
|
|
158
|
+
* 85% of the model's context window limit, falling back to DEFAULT_CONTEXT_LIMIT.
|
|
159
|
+
*/
|
|
160
|
+
getCompressThreshold(): number {
|
|
161
|
+
if (this.compressThreshold !== DEFAULT_CONTEXT_LIMIT) {
|
|
162
|
+
return this.compressThreshold;
|
|
163
|
+
}
|
|
164
|
+
const result = this.clientService.getContextLimit(
|
|
165
|
+
this.getProvider() as string,
|
|
166
|
+
this.getModel()
|
|
167
|
+
);
|
|
168
|
+
const contextLimit = result?.contextLimit ?? DEFAULT_CONTEXT_LIMIT;
|
|
169
|
+
const threshold = result?.threshold ?? contextLimit;
|
|
170
|
+
return Math.floor(threshold * 0.85);
|
|
171
|
+
}
|
|
172
|
+
|
|
136
173
|
setMaxTurns(maxTurns: number | null) {
|
|
137
174
|
this.maxTurns = maxTurns;
|
|
138
175
|
}
|
|
@@ -259,7 +296,10 @@ export abstract class BaseAgent implements IAgent {
|
|
|
259
296
|
private checkLimits(): boolean {
|
|
260
297
|
// Check turn limit
|
|
261
298
|
if (this.maxTurns !== null && this.turnCount >= this.maxTurns) {
|
|
262
|
-
this.log(
|
|
299
|
+
this.log(
|
|
300
|
+
`Turn limit reached: ${this.turnCount}/${this.maxTurns}`,
|
|
301
|
+
"warn"
|
|
302
|
+
);
|
|
263
303
|
return true;
|
|
264
304
|
}
|
|
265
305
|
|
|
@@ -268,8 +308,9 @@ export abstract class BaseAgent implements IAgent {
|
|
|
268
308
|
this.log(
|
|
269
309
|
`Spend limit reached: $${this.totalCostUsd.toFixed(
|
|
270
310
|
4
|
|
271
|
-
)}/$${this.maxSpend.toFixed(4)}
|
|
272
|
-
|
|
311
|
+
)}/$${this.maxSpend.toFixed(4)}`,
|
|
312
|
+
"warn"
|
|
313
|
+
);
|
|
273
314
|
return true;
|
|
274
315
|
}
|
|
275
316
|
|
|
@@ -333,7 +374,9 @@ export abstract class BaseAgent implements IAgent {
|
|
|
333
374
|
return this.summaries;
|
|
334
375
|
}
|
|
335
376
|
|
|
336
|
-
abstract getInitialMessages(
|
|
377
|
+
abstract getInitialMessages(
|
|
378
|
+
userInput: string | MessageContent[]
|
|
379
|
+
): Promise<Message[]>;
|
|
337
380
|
|
|
338
381
|
async processToolMessages(toolCall: ToolCall) {
|
|
339
382
|
this.agentEvents.emit(this.eventTypes.toolCall, { toolCall });
|
|
@@ -431,7 +474,11 @@ export abstract class BaseAgent implements IAgent {
|
|
|
431
474
|
}
|
|
432
475
|
|
|
433
476
|
this.log(
|
|
434
|
-
`Required tool: [${
|
|
477
|
+
`Required tool: [${
|
|
478
|
+
this.requiredToolNames
|
|
479
|
+
}] not available, checking for finalAnswer. Enabled: ${this.getEnabledToolNames().join(
|
|
480
|
+
", "
|
|
481
|
+
)}`
|
|
435
482
|
);
|
|
436
483
|
|
|
437
484
|
// Otherwise we're missing the required tool, lets use finalAnswer if we have it
|
|
@@ -442,8 +489,9 @@ export abstract class BaseAgent implements IAgent {
|
|
|
442
489
|
// We have the final answer tool, but it wasn't required
|
|
443
490
|
if (hasFinalAnswer && !requiredFinalAnswer) {
|
|
444
491
|
this.log(
|
|
445
|
-
"Required tool not available, setting finalAnswer as required tool"
|
|
446
|
-
|
|
492
|
+
"Required tool not available, setting finalAnswer as required tool",
|
|
493
|
+
"warn"
|
|
494
|
+
);
|
|
447
495
|
this.requiredToolNames.push("finalAnswer");
|
|
448
496
|
return false;
|
|
449
497
|
}
|
|
@@ -491,7 +539,11 @@ export abstract class BaseAgent implements IAgent {
|
|
|
491
539
|
} as Message);
|
|
492
540
|
}
|
|
493
541
|
|
|
494
|
-
async call(
|
|
542
|
+
async call(
|
|
543
|
+
userInput: string | MessageContent[],
|
|
544
|
+
_messages?: Message[],
|
|
545
|
+
retryCount = 0
|
|
546
|
+
) {
|
|
495
547
|
if (this.status === this.eventTypes.notStarted) {
|
|
496
548
|
this.status = this.eventTypes.inProgress;
|
|
497
549
|
}
|
|
@@ -551,7 +603,6 @@ export abstract class BaseAgent implements IAgent {
|
|
|
551
603
|
messages,
|
|
552
604
|
"pre_call"
|
|
553
605
|
);
|
|
554
|
-
const compressThreshold = 30000;
|
|
555
606
|
|
|
556
607
|
const response = await this.getClient().createChatCompletion({
|
|
557
608
|
model,
|
|
@@ -575,6 +626,7 @@ export abstract class BaseAgent implements IAgent {
|
|
|
575
626
|
}
|
|
576
627
|
|
|
577
628
|
this.adjustTotalCostUsd(response?.usd_cost);
|
|
629
|
+
this.log("agent response cost: " + response?.usd_cost);
|
|
578
630
|
|
|
579
631
|
// Typically, there's only one choice in the array, but you could have many
|
|
580
632
|
// If you set `n` to more than 1, you will get multiple choices
|
|
@@ -679,12 +731,14 @@ export abstract class BaseAgent implements IAgent {
|
|
|
679
731
|
}
|
|
680
732
|
|
|
681
733
|
if (
|
|
682
|
-
this.getMessagesLength(messages) >
|
|
683
|
-
messages.length >
|
|
734
|
+
this.getMessagesLength(messages) > this.getCompressThreshold() &&
|
|
735
|
+
messages.length > this.compressMinMessages
|
|
684
736
|
) {
|
|
685
737
|
const taskBreakdown = await this.getTaskBreakdown(messages);
|
|
686
738
|
this.log(
|
|
687
|
-
`Compressing messages: ${this.getMessagesLength(
|
|
739
|
+
`Compressing messages: ${this.getMessagesLength(
|
|
740
|
+
messages
|
|
741
|
+
)} exceeds ${this.getCompressThreshold()}`
|
|
688
742
|
);
|
|
689
743
|
messages = await this.compressMessages(messages, startIndex, endIndex);
|
|
690
744
|
this.startNewThread(messages);
|
|
@@ -713,6 +767,7 @@ export abstract class BaseAgent implements IAgent {
|
|
|
713
767
|
if (e.toString().includes("429")) {
|
|
714
768
|
this.setNotHealthy();
|
|
715
769
|
return this.call(userInput, _messages, retryCount);
|
|
770
|
+
}
|
|
716
771
|
const errorStr = e.toString();
|
|
717
772
|
const isNonRetriable =
|
|
718
773
|
errorStr.includes("401") ||
|
|
@@ -731,15 +786,15 @@ export abstract class BaseAgent implements IAgent {
|
|
|
731
786
|
if (isRetriable && retryCount < 3) {
|
|
732
787
|
const delay = 1000 * Math.pow(2, retryCount);
|
|
733
788
|
this.log(
|
|
734
|
-
`Agent request failed (attempt ${
|
|
789
|
+
`Agent request failed (attempt ${
|
|
790
|
+
retryCount + 1
|
|
791
|
+
}/3), retrying in ${delay}ms: ${e.message}`,
|
|
735
792
|
"warn"
|
|
736
793
|
);
|
|
737
794
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
738
795
|
return this.call(userInput, _messages, retryCount + 1);
|
|
739
796
|
}
|
|
740
797
|
|
|
741
|
-
}
|
|
742
|
-
|
|
743
798
|
this.log(`Agent failed: ${e}`, "error");
|
|
744
799
|
|
|
745
800
|
if ("response" in e && "data" in e.response) {
|
|
@@ -798,11 +853,16 @@ export abstract class BaseAgent implements IAgent {
|
|
|
798
853
|
details: {
|
|
799
854
|
totalCostUsd: this.getTotalCostUsd(),
|
|
800
855
|
elapsedMs: this.runTime(),
|
|
801
|
-
remainingTimeMs:
|
|
802
|
-
|
|
856
|
+
remainingTimeMs:
|
|
857
|
+
this.maxRunTimeMs && this.startTimeMs
|
|
858
|
+
? this.maxRunTimeMs - (Date.now() - this.startTimeMs)
|
|
859
|
+
: undefined,
|
|
860
|
+
remainingTurns: this.maxTurns
|
|
861
|
+
? this.maxTurns - this.turnCount
|
|
862
|
+
: undefined,
|
|
863
|
+
remainingBudget: this.maxSpend
|
|
864
|
+
? this.maxSpend - this.totalCostUsd
|
|
803
865
|
: undefined,
|
|
804
|
-
remainingTurns: this.maxTurns ? this.maxTurns - this.turnCount : undefined,
|
|
805
|
-
remainingBudget: this.maxSpend ? this.maxSpend - this.totalCostUsd : undefined,
|
|
806
866
|
},
|
|
807
867
|
timestamp: Date.now(),
|
|
808
868
|
});
|
|
@@ -836,19 +896,21 @@ export abstract class BaseAgent implements IAgent {
|
|
|
836
896
|
}
|
|
837
897
|
|
|
838
898
|
const taskPrompt = `
|
|
899
|
+
Analyze all previous messages.
|
|
900
|
+
|
|
839
901
|
Generate a detailed task breakdown for this conversation, include a section for the following:
|
|
840
902
|
1. Task List
|
|
841
903
|
2. Completion Criteria - when the agent should stop
|
|
842
904
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
\n\n<ToAnalyze>${JSON.stringify(messages)}</ToAnalyze>`;
|
|
905
|
+
Your output will be used to guide the work of the agent, and determine when we've accomplished the goal
|
|
906
|
+
`;
|
|
846
907
|
|
|
847
908
|
const model = this.getModel();
|
|
848
909
|
|
|
849
910
|
const response = await this.getClient().createChatCompletion({
|
|
850
911
|
model,
|
|
851
912
|
messages: [
|
|
913
|
+
...messages,
|
|
852
914
|
{
|
|
853
915
|
role: "user",
|
|
854
916
|
content: taskPrompt,
|
|
@@ -859,9 +921,8 @@ export abstract class BaseAgent implements IAgent {
|
|
|
859
921
|
|
|
860
922
|
this.adjustTotalCostUsd(response.usd_cost);
|
|
861
923
|
|
|
862
|
-
this.log(String(response));
|
|
863
|
-
|
|
864
924
|
this.taskBreakdown = response.choices[0].message.content;
|
|
925
|
+
this.log(`task breakdown cost: ${response.usd_cost}`);
|
|
865
926
|
return this.taskBreakdown;
|
|
866
927
|
}
|
|
867
928
|
|
|
@@ -936,6 +997,7 @@ export abstract class BaseAgent implements IAgent {
|
|
|
936
997
|
100
|
|
937
998
|
).toFixed(2);
|
|
938
999
|
|
|
1000
|
+
this.log(`compression cost: ${response.usd_cost}`);
|
|
939
1001
|
this.log(
|
|
940
1002
|
`Compressed messages from ${oldLength} to ${newLength}, ${compressionRatio}% reduction in size`
|
|
941
1003
|
);
|
|
@@ -8,7 +8,7 @@ export class ResearcherAgent extends BaseAgent {
|
|
|
8
8
|
|
|
9
9
|
constructor(context: AgentContext) {
|
|
10
10
|
super(context);
|
|
11
|
-
this.setModel(Models.google.
|
|
11
|
+
this.setModel(Models.google.Gemini_3_Flash_Preview);
|
|
12
12
|
this.setProvider("google");
|
|
13
13
|
this.disableTool("patchFile");
|
|
14
14
|
this.disableTool("writeFile");
|
|
@@ -106,4 +106,3 @@ export class ResearcherAgent extends BaseAgent {
|
|
|
106
106
|
] as Message[];
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
-
|
|
@@ -128,3 +128,51 @@ export async function listAllEmbeddingModels(): Promise<Record<string, string[]>
|
|
|
128
128
|
|
|
129
129
|
return contextClients.listAllEmbeddingModels();
|
|
130
130
|
}
|
|
131
|
+
|
|
132
|
+
export async function listAllImageModels(): Promise<Record<string, string[]>> {
|
|
133
|
+
// Get context from bound ToolsService
|
|
134
|
+
const toolService = (
|
|
135
|
+
this instanceof ToolsService ? this : services().Tools
|
|
136
|
+
) as ToolsService;
|
|
137
|
+
|
|
138
|
+
const toolContext = toolService.getContext();
|
|
139
|
+
const { Clients: contextClients } = toolContext;
|
|
140
|
+
|
|
141
|
+
if (!contextClients) {
|
|
142
|
+
throw new Error("Clients not available in tool context");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return contextClients.listAllImageModels();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export async function listAllAudioModels(): Promise<Record<string, string[]>> {
|
|
149
|
+
// Get context from bound ToolsService
|
|
150
|
+
const toolService = (
|
|
151
|
+
this instanceof ToolsService ? this : services().Tools
|
|
152
|
+
) as ToolsService;
|
|
153
|
+
|
|
154
|
+
const toolContext = toolService.getContext();
|
|
155
|
+
const { Clients: contextClients } = toolContext;
|
|
156
|
+
|
|
157
|
+
if (!contextClients) {
|
|
158
|
+
throw new Error("Clients not available in tool context");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return contextClients.listAllAudioModels();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export async function listAllVideoModels(): Promise<Record<string, string[]>> {
|
|
165
|
+
// Get context from bound ToolsService
|
|
166
|
+
const toolService = (
|
|
167
|
+
this instanceof ToolsService ? this : services().Tools
|
|
168
|
+
) as ToolsService;
|
|
169
|
+
|
|
170
|
+
const toolContext = toolService.getContext();
|
|
171
|
+
const { Clients: contextClients } = toolContext;
|
|
172
|
+
|
|
173
|
+
if (!contextClients) {
|
|
174
|
+
throw new Error("Clients not available in tool context");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return contextClients.listAllVideoModels();
|
|
178
|
+
}
|
package/src/agents/tools/list.ts
CHANGED
|
@@ -506,6 +506,63 @@ export const includedTools = [
|
|
|
506
506
|
},
|
|
507
507
|
},
|
|
508
508
|
|
|
509
|
+
{
|
|
510
|
+
type: "function",
|
|
511
|
+
function: {
|
|
512
|
+
name: "listAllImageModels",
|
|
513
|
+
description:
|
|
514
|
+
"List all available image generation models using the knowhow ai client. Use this to discover which providers and models support image generation.",
|
|
515
|
+
parameters: {
|
|
516
|
+
type: "object",
|
|
517
|
+
properties: {},
|
|
518
|
+
required: [],
|
|
519
|
+
},
|
|
520
|
+
returns: {
|
|
521
|
+
type: "object",
|
|
522
|
+
description:
|
|
523
|
+
"A dictionary of all available image generation models for each provider",
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
|
|
528
|
+
{
|
|
529
|
+
type: "function",
|
|
530
|
+
function: {
|
|
531
|
+
name: "listAllAudioModels",
|
|
532
|
+
description:
|
|
533
|
+
"List all available audio generation models (TTS/transcription) using the knowhow ai client. Use this to discover which providers and models support audio generation.",
|
|
534
|
+
parameters: {
|
|
535
|
+
type: "object",
|
|
536
|
+
properties: {},
|
|
537
|
+
required: [],
|
|
538
|
+
},
|
|
539
|
+
returns: {
|
|
540
|
+
type: "object",
|
|
541
|
+
description:
|
|
542
|
+
"A dictionary of all available audio generation models for each provider",
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
|
|
547
|
+
{
|
|
548
|
+
type: "function",
|
|
549
|
+
function: {
|
|
550
|
+
name: "listAllVideoModels",
|
|
551
|
+
description:
|
|
552
|
+
"List all available video generation models using the knowhow ai client. Use this to discover which providers and models support video generation.",
|
|
553
|
+
parameters: {
|
|
554
|
+
type: "object",
|
|
555
|
+
properties: {},
|
|
556
|
+
required: [],
|
|
557
|
+
},
|
|
558
|
+
returns: {
|
|
559
|
+
type: "object",
|
|
560
|
+
description:
|
|
561
|
+
"A dictionary of all available video generation models for each provider",
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
},
|
|
565
|
+
|
|
509
566
|
{
|
|
510
567
|
type: "function",
|
|
511
568
|
function: {
|
|
@@ -318,7 +318,9 @@ export class CliChatService implements ChatService {
|
|
|
318
318
|
|
|
319
319
|
while (true) {
|
|
320
320
|
// Recompute available commands each iteration so mode changes are reflected in autocomplete
|
|
321
|
-
const currentCommandNames = this.getCommandsForActiveModes().map(
|
|
321
|
+
const currentCommandNames = this.getCommandsForActiveModes().map(
|
|
322
|
+
(cmd) => `/${cmd.name}`
|
|
323
|
+
);
|
|
322
324
|
|
|
323
325
|
// Check active modes for a promptText first, then fall back to context.promptText, then default
|
|
324
326
|
const activeModeWithPrompt = this.modes
|
|
@@ -556,28 +556,21 @@ Please continue from where you left off and complete the original request.
|
|
|
556
556
|
return true;
|
|
557
557
|
}
|
|
558
558
|
|
|
559
|
-
|
|
560
|
-
// Create initial interaction for the chatHistory
|
|
561
|
-
const initialInteraction: ChatInteraction = {
|
|
562
|
-
input,
|
|
563
|
-
output: "", // Will be filled after agent completion
|
|
564
|
-
summaries: [],
|
|
565
|
-
lastThread: [],
|
|
566
|
-
};
|
|
559
|
+
context.chatHistory = context.chatHistory || [];
|
|
567
560
|
|
|
568
|
-
const {
|
|
561
|
+
const { taskId } = await this.startAgent(
|
|
569
562
|
context.selectedAgent,
|
|
570
563
|
input,
|
|
571
|
-
context.chatHistory
|
|
564
|
+
context.chatHistory
|
|
572
565
|
);
|
|
573
566
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
}
|
|
567
|
+
context.chatHistory.push({
|
|
568
|
+
input,
|
|
569
|
+
output: "", // Output will be filled in when the agent responds and the session is updated
|
|
570
|
+
taskId,
|
|
571
|
+
});
|
|
579
572
|
|
|
580
|
-
return
|
|
573
|
+
return true;
|
|
581
574
|
}
|
|
582
575
|
return false;
|
|
583
576
|
}
|
|
@@ -1005,7 +998,7 @@ Please continue from where you left off and complete the original request.
|
|
|
1005
998
|
selectedAgent: BaseAgent,
|
|
1006
999
|
initialInput: string,
|
|
1007
1000
|
chatHistory: ChatInteraction[] = []
|
|
1008
|
-
)
|
|
1001
|
+
) {
|
|
1009
1002
|
try {
|
|
1010
1003
|
const { agent, taskId, formattedPrompt } = await this.setupAgent({
|
|
1011
1004
|
agentName: selectedAgent.name,
|
|
@@ -1013,15 +1006,12 @@ Please continue from where you left off and complete the original request.
|
|
|
1013
1006
|
chatHistory,
|
|
1014
1007
|
run: false, // Don't run yet, we need to set up event listeners first
|
|
1015
1008
|
});
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
);
|
|
1021
|
-
return result;
|
|
1009
|
+
|
|
1010
|
+
await this.attachedAgentChatLoop(taskId, agent, formattedPrompt);
|
|
1011
|
+
|
|
1012
|
+
return { taskId };
|
|
1022
1013
|
} catch (error) {
|
|
1023
1014
|
console.error("Error starting agent:", error);
|
|
1024
|
-
return { result: false, finalOutput: "Error starting agent" };
|
|
1025
1015
|
}
|
|
1026
1016
|
}
|
|
1027
1017
|
|
|
@@ -1029,7 +1019,7 @@ Please continue from where you left off and complete the original request.
|
|
|
1029
1019
|
taskId: string,
|
|
1030
1020
|
agent: AttachableAgent,
|
|
1031
1021
|
initialInput?: string
|
|
1032
|
-
): Promise<
|
|
1022
|
+
): Promise<void> {
|
|
1033
1023
|
try {
|
|
1034
1024
|
let agentFinalOutput: string | undefined;
|
|
1035
1025
|
|
|
@@ -1068,6 +1058,11 @@ Please continue from where you left off and complete the original request.
|
|
|
1068
1058
|
}
|
|
1069
1059
|
}
|
|
1070
1060
|
|
|
1061
|
+
if (context.chatHistory) {
|
|
1062
|
+
const found = context.chatHistory.find((h) => h.taskId === taskId);
|
|
1063
|
+
found.output = agentFinalOutput;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1071
1066
|
resolve("done");
|
|
1072
1067
|
// Exit agent:attached mode so the prompt resets back to the default
|
|
1073
1068
|
this.detachFromAgent();
|
|
@@ -1081,14 +1076,8 @@ Please continue from where you left off and complete the original request.
|
|
|
1081
1076
|
taskInfo?.formattedPrompt || taskInfo?.initialInput || initialInput
|
|
1082
1077
|
);
|
|
1083
1078
|
}
|
|
1084
|
-
|
|
1085
|
-
// Return immediately — the main startChatLoop on CliChatService
|
|
1086
|
-
// now handles all user input via the registered agent:attached commands.
|
|
1087
|
-
// Any non-command input is forwarded to the agent via handleInput below.
|
|
1088
|
-
return { result: true, finalOutput: agentFinalOutput };
|
|
1089
1079
|
} catch (error) {
|
|
1090
1080
|
console.error("Agent execution failed:", error);
|
|
1091
|
-
return { result: false, finalOutput: "Error during agent execution" };
|
|
1092
1081
|
}
|
|
1093
1082
|
}
|
|
1094
1083
|
}
|
package/src/chat/types.ts
CHANGED
package/src/cli.ts
CHANGED
|
@@ -242,14 +242,15 @@ async function main() {
|
|
|
242
242
|
options.input || "Please continue from where you left off.";
|
|
243
243
|
|
|
244
244
|
await agentModule.initialize(chatService);
|
|
245
|
-
const { taskCompleted } =
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
245
|
+
const { taskCompleted: resumed } =
|
|
246
|
+
await agentModule.resumeFromMessages({
|
|
247
|
+
agentName: options.agentName || "Patcher",
|
|
248
|
+
input: resumeInput,
|
|
249
|
+
threads,
|
|
250
|
+
messageId: options.messageId,
|
|
251
|
+
taskId: options.taskId,
|
|
252
|
+
});
|
|
253
|
+
await resumed;
|
|
253
254
|
return;
|
|
254
255
|
}
|
|
255
256
|
|
|
@@ -320,6 +321,7 @@ async function main() {
|
|
|
320
321
|
plugins: config.plugins.enabled,
|
|
321
322
|
currentModel: options.model,
|
|
322
323
|
currentProvider: options.provider,
|
|
324
|
+
chatHistory: [],
|
|
323
325
|
});
|
|
324
326
|
} catch (error) {
|
|
325
327
|
console.error("Error asking AI:", error);
|
|
@@ -380,7 +382,10 @@ async function main() {
|
|
|
380
382
|
program
|
|
381
383
|
.command("sessions")
|
|
382
384
|
.description("Manage agent sessions from CLI")
|
|
383
|
-
.option(
|
|
385
|
+
.option(
|
|
386
|
+
"--all",
|
|
387
|
+
"Show all historical sessions (default: current process only)"
|
|
388
|
+
)
|
|
384
389
|
.option("--csv", "Output sessions as CSV")
|
|
385
390
|
.action(async (options) => {
|
|
386
391
|
try {
|
|
@@ -388,7 +393,11 @@ async function main() {
|
|
|
388
393
|
await agentModule.initialize(chatService);
|
|
389
394
|
const sessionsModule = new SessionsModule(agentModule);
|
|
390
395
|
await sessionsModule.initialize(chatService);
|
|
391
|
-
await sessionsModule.logSessionTable(
|
|
396
|
+
await sessionsModule.logSessionTable(
|
|
397
|
+
options.all || false,
|
|
398
|
+
options.csv || false,
|
|
399
|
+
true
|
|
400
|
+
);
|
|
392
401
|
} catch (error) {
|
|
393
402
|
console.error("Error listing sessions:", error);
|
|
394
403
|
process.exit(1);
|
package/src/clients/anthropic.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Anthropic from "@anthropic-ai/sdk";
|
|
2
2
|
import { wait } from "../utils";
|
|
3
3
|
import { AnthropicTextPricing } from "./pricing";
|
|
4
|
+
import { ContextLimits } from "./contextLimits";
|
|
4
5
|
import { Models } from "../types";
|
|
5
6
|
import {
|
|
6
7
|
GenericClient,
|
|
@@ -483,6 +484,16 @@ export class GenericAnthropicClient implements GenericClient {
|
|
|
483
484
|
throw new Error("Anthropic does not support audio transcription");
|
|
484
485
|
}
|
|
485
486
|
|
|
487
|
+
getContextLimit(model: string): { contextLimit: number; threshold: number } | undefined {
|
|
488
|
+
const contextLimit = ContextLimits[model];
|
|
489
|
+
if (contextLimit === undefined) return undefined;
|
|
490
|
+
const pricing = AnthropicTextPricing[model];
|
|
491
|
+
// If the model has tiered pricing above 200k tokens, use 200k as the threshold
|
|
492
|
+
const threshold =
|
|
493
|
+
pricing && "input_gt_200k" in pricing ? 200_000 : contextLimit;
|
|
494
|
+
return { contextLimit, threshold };
|
|
495
|
+
}
|
|
496
|
+
|
|
486
497
|
async createAudioGeneration(
|
|
487
498
|
options: AudioGenerationOptions
|
|
488
499
|
): Promise<AudioGenerationResponse> {
|