@tyvm/knowhow 0.0.129 → 0.0.131
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 +4 -4
- package/src/agents/base/base.ts +40 -5
- package/src/agents/configurable/ConfigAgent.ts +0 -1
- package/src/agents/tools/index.ts +1 -0
- package/src/agents/tools/list.ts +2 -0
- package/src/agents/tools/skills.ts +79 -0
- package/src/agents/tools/startAgentTask.ts +17 -13
- package/src/ai.ts +55 -24
- package/src/chat/CliChatService.ts +7 -1
- package/src/chat/modules/AgentModule.ts +156 -15
- package/src/chat/renderer/PlainRenderer.ts +218 -0
- package/src/chat/renderer/index.ts +1 -0
- package/src/chat/renderer/loadRenderer.ts +2 -0
- package/src/chat.ts +2 -2
- package/src/cli.ts +10 -0
- package/src/clients/anthropic.ts +68 -2
- package/src/clients/fireworks.ts +10 -1
- package/src/clients/index.ts +5 -3
- package/src/clients/meta.ts +9 -0
- package/src/clients/openai.ts +28 -5
- package/src/clients/pricing/anthropic.ts +11 -0
- package/src/clients/pricing/fireworks.ts +12 -0
- package/src/clients/pricing/openai.ts +3 -0
- package/src/clients/types.ts +27 -4
- package/src/clients/xai.ts +2 -2
- package/src/commands/agent.ts +70 -18
- package/src/commands/agents.ts +556 -0
- package/src/commands/behaviors.ts +47 -0
- package/src/commands/hash.ts +124 -0
- package/src/commands/misc.ts +157 -3
- package/src/commands/services.ts +6 -2
- package/src/commands/skills.ts +107 -0
- package/src/config.ts +51 -1
- package/src/generate.ts +507 -0
- package/src/index.ts +34 -216
- package/src/plugins/PluginBase.ts +0 -2
- package/src/plugins/SkillsPlugin.ts +11 -124
- package/src/plugins/language.ts +0 -1
- package/src/plugins/plugins.ts +24 -13
- package/src/plugins/types.ts +8 -2
- package/src/services/BehaviorsService.ts +464 -0
- package/src/services/KnowhowClient.ts +61 -0
- package/src/services/SkillsService.ts +820 -0
- package/src/services/Tools.ts +2 -0
- package/src/services/index.ts +8 -2
- package/src/services/modules/types.ts +2 -0
- package/src/types.ts +36 -4
- package/ts_build/package.json +4 -4
- package/ts_build/src/agents/base/base.d.ts +9 -1
- package/ts_build/src/agents/base/base.js +29 -4
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/configurable/ConfigAgent.js.map +1 -1
- package/ts_build/src/agents/tools/index.d.ts +1 -0
- package/ts_build/src/agents/tools/index.js +1 -0
- package/ts_build/src/agents/tools/index.js.map +1 -1
- package/ts_build/src/agents/tools/list.js +2 -0
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/agents/tools/skills.d.ts +33 -0
- package/ts_build/src/agents/tools/skills.js +62 -0
- package/ts_build/src/agents/tools/skills.js.map +1 -0
- package/ts_build/src/agents/tools/startAgentTask.d.ts +2 -2
- package/ts_build/src/agents/tools/startAgentTask.js +13 -12
- package/ts_build/src/agents/tools/startAgentTask.js.map +1 -1
- package/ts_build/src/ai.d.ts +10 -4
- package/ts_build/src/ai.js +27 -25
- package/ts_build/src/ai.js.map +1 -1
- package/ts_build/src/chat/CliChatService.d.ts +1 -1
- package/ts_build/src/chat/CliChatService.js +4 -1
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.d.ts +2 -0
- package/ts_build/src/chat/modules/AgentModule.js +130 -4
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/modules/CustomCommandsModule.d.ts +1 -1
- package/ts_build/src/chat/renderer/PlainRenderer.d.ts +28 -0
- package/ts_build/src/chat/renderer/PlainRenderer.js +169 -0
- package/ts_build/src/chat/renderer/PlainRenderer.js.map +1 -0
- package/ts_build/src/chat/renderer/index.d.ts +1 -0
- package/ts_build/src/chat/renderer/index.js +3 -1
- package/ts_build/src/chat/renderer/index.js.map +1 -1
- package/ts_build/src/chat/renderer/loadRenderer.js +2 -0
- package/ts_build/src/chat/renderer/loadRenderer.js.map +1 -1
- package/ts_build/src/chat.d.ts +1 -1
- package/ts_build/src/chat.js +2 -2
- package/ts_build/src/chat.js.map +1 -1
- package/ts_build/src/cli.js +9 -0
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/clients/anthropic.d.ts +2 -0
- package/ts_build/src/clients/anthropic.js +39 -1
- package/ts_build/src/clients/anthropic.js.map +1 -1
- package/ts_build/src/clients/fireworks.js +7 -0
- package/ts_build/src/clients/fireworks.js.map +1 -1
- package/ts_build/src/clients/index.js +3 -1
- package/ts_build/src/clients/index.js.map +1 -1
- package/ts_build/src/clients/meta.d.ts +2 -0
- package/ts_build/src/clients/meta.js +5 -0
- package/ts_build/src/clients/meta.js.map +1 -1
- package/ts_build/src/clients/openai.d.ts +1 -0
- package/ts_build/src/clients/openai.js +25 -5
- package/ts_build/src/clients/openai.js.map +1 -1
- package/ts_build/src/clients/pricing/anthropic.d.ts +3 -0
- package/ts_build/src/clients/pricing/anthropic.js +6 -0
- package/ts_build/src/clients/pricing/anthropic.js.map +1 -1
- package/ts_build/src/clients/pricing/fireworks.d.ts +1 -0
- package/ts_build/src/clients/pricing/fireworks.js +5 -1
- package/ts_build/src/clients/pricing/fireworks.js.map +1 -1
- package/ts_build/src/clients/pricing/openai.js +3 -0
- package/ts_build/src/clients/pricing/openai.js.map +1 -1
- package/ts_build/src/clients/types.d.ts +6 -1
- package/ts_build/src/clients/xai.js +1 -1
- package/ts_build/src/clients/xai.js.map +1 -1
- package/ts_build/src/commands/agent.js +58 -15
- package/ts_build/src/commands/agent.js.map +1 -1
- package/ts_build/src/commands/agents.d.ts +2 -0
- package/ts_build/src/commands/agents.js +460 -0
- package/ts_build/src/commands/agents.js.map +1 -0
- package/ts_build/src/commands/behaviors.d.ts +2 -0
- package/ts_build/src/commands/behaviors.js +43 -0
- package/ts_build/src/commands/behaviors.js.map +1 -0
- package/ts_build/src/commands/hash.d.ts +2 -0
- package/ts_build/src/commands/hash.js +117 -0
- package/ts_build/src/commands/hash.js.map +1 -0
- package/ts_build/src/commands/misc.js +108 -2
- package/ts_build/src/commands/misc.js.map +1 -1
- package/ts_build/src/commands/services.js +4 -2
- package/ts_build/src/commands/services.js.map +1 -1
- package/ts_build/src/commands/skills.d.ts +2 -0
- package/ts_build/src/commands/skills.js +85 -0
- package/ts_build/src/commands/skills.js.map +1 -0
- package/ts_build/src/config.js +34 -0
- package/ts_build/src/config.js.map +1 -1
- package/ts_build/src/generate.d.ts +16 -0
- package/ts_build/src/generate.js +304 -0
- package/ts_build/src/generate.js.map +1 -0
- package/ts_build/src/index.d.ts +3 -3
- package/ts_build/src/index.js +13 -118
- package/ts_build/src/index.js.map +1 -1
- package/ts_build/src/plugins/PluginBase.d.ts +0 -2
- package/ts_build/src/plugins/PluginBase.js.map +1 -1
- package/ts_build/src/plugins/SkillsPlugin.d.ts +1 -6
- package/ts_build/src/plugins/SkillsPlugin.js +6 -135
- package/ts_build/src/plugins/SkillsPlugin.js.map +1 -1
- package/ts_build/src/plugins/language.js.map +1 -1
- package/ts_build/src/plugins/plugins.d.ts +4 -1
- package/ts_build/src/plugins/plugins.js +17 -11
- package/ts_build/src/plugins/plugins.js.map +1 -1
- package/ts_build/src/plugins/types.d.ts +3 -2
- package/ts_build/src/services/BehaviorsService.d.ts +48 -0
- package/ts_build/src/services/BehaviorsService.js +382 -0
- package/ts_build/src/services/BehaviorsService.js.map +1 -0
- package/ts_build/src/services/KnowhowClient.d.ts +8 -0
- package/ts_build/src/services/KnowhowClient.js +20 -0
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/SkillsService.d.ts +60 -0
- package/ts_build/src/services/SkillsService.js +641 -0
- package/ts_build/src/services/SkillsService.js.map +1 -0
- package/ts_build/src/services/Tools.d.ts +2 -0
- package/ts_build/src/services/Tools.js.map +1 -1
- package/ts_build/src/services/index.d.ts +3 -0
- package/ts_build/src/services/index.js +8 -2
- package/ts_build/src/services/index.js.map +1 -1
- package/ts_build/src/services/modules/index.d.ts +4 -2
- package/ts_build/src/services/modules/types.d.ts +2 -0
- package/ts_build/src/types.d.ts +14 -4
- package/ts_build/src/types.js.map +1 -1
package/src/clients/openai.ts
CHANGED
|
@@ -107,7 +107,11 @@ export class GenericOpenAiClient implements GenericClient {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
resolveReasoningEffort(options: CompletionOptions): "low" | "medium" | "high" {
|
|
110
|
-
|
|
110
|
+
const effort = options.reasoning_effort ?? this.detectReasoningEffort(options.messages);
|
|
111
|
+
// "none" is not a valid SDK ReasoningEffort — callers that need "none" should
|
|
112
|
+
// check isReasoningDisabled() separately and skip the reasoning params.
|
|
113
|
+
if (effort === "none") return "low";
|
|
114
|
+
return effort;
|
|
111
115
|
}
|
|
112
116
|
|
|
113
117
|
/**
|
|
@@ -116,7 +120,8 @@ export class GenericOpenAiClient implements GenericClient {
|
|
|
116
120
|
* If the requested level is not supported, picks the lowest supported level.
|
|
117
121
|
*/
|
|
118
122
|
resolveReasoningEffortForModel(options: CompletionOptions): string {
|
|
119
|
-
const
|
|
123
|
+
const raw = options.reasoning_effort ?? this.detectReasoningEffort(options.messages);
|
|
124
|
+
const requested = raw === "none" ? "none" : raw;
|
|
120
125
|
const pricing = OpenAiTextPricing[options.model];
|
|
121
126
|
const supportedLevels = pricing?.reasoningLevels;
|
|
122
127
|
if (!supportedLevels || supportedLevels.length === 0) {
|
|
@@ -130,6 +135,11 @@ export class GenericOpenAiClient implements GenericClient {
|
|
|
130
135
|
return supportedLevels[0];
|
|
131
136
|
}
|
|
132
137
|
|
|
138
|
+
/** Returns true when the caller explicitly requested thinking/reasoning to be disabled. */
|
|
139
|
+
isReasoningDisabled(options: CompletionOptions): boolean {
|
|
140
|
+
return options.reasoning_effort === "none";
|
|
141
|
+
}
|
|
142
|
+
|
|
133
143
|
async createChatCompletion(
|
|
134
144
|
options: CompletionOptions
|
|
135
145
|
): Promise<CompletionResponse> {
|
|
@@ -154,7 +164,7 @@ export class GenericOpenAiClient implements GenericClient {
|
|
|
154
164
|
model: options.model,
|
|
155
165
|
messages: openaiMessages,
|
|
156
166
|
max_tokens: options.max_tokens,
|
|
157
|
-
...(OpenAiReasoningModels.includes(options.model) && {
|
|
167
|
+
...(OpenAiReasoningModels.includes(options.model) && !this.isReasoningDisabled(options) && {
|
|
158
168
|
max_tokens: undefined,
|
|
159
169
|
max_completion_tokens: Math.max(options.max_tokens ?? 0, 16_000),
|
|
160
170
|
reasoning_effort: this.resolveReasoningEffort(options),
|
|
@@ -186,6 +196,11 @@ export class GenericOpenAiClient implements GenericClient {
|
|
|
186
196
|
prompt_tokens_details: {
|
|
187
197
|
cached_tokens: response.usage.prompt_tokens_details?.cached_tokens ?? 0,
|
|
188
198
|
},
|
|
199
|
+
...(response.usage.completion_tokens_details?.reasoning_tokens != null && {
|
|
200
|
+
output_tokens_details: {
|
|
201
|
+
reasoning_tokens: response.usage.completion_tokens_details.reasoning_tokens,
|
|
202
|
+
},
|
|
203
|
+
}),
|
|
189
204
|
} : undefined,
|
|
190
205
|
usd_cost: usdCost,
|
|
191
206
|
};
|
|
@@ -350,9 +365,12 @@ export class GenericOpenAiClient implements GenericClient {
|
|
|
350
365
|
input,
|
|
351
366
|
...(instructions && { instructions }),
|
|
352
367
|
// Don't limit max_output_tokens for Responses API - codex truncates tool call arguments when limited
|
|
353
|
-
...(OpenAiReasoningModels.includes(options.model) && {
|
|
368
|
+
...(OpenAiReasoningModels.includes(options.model) && !this.isReasoningDisabled(options) && {
|
|
354
369
|
max_output_tokens: Math.max(options.max_tokens || 0, 16000),
|
|
355
|
-
reasoning: {
|
|
370
|
+
reasoning: {
|
|
371
|
+
effort: this.resolveReasoningEffortForModel(options),
|
|
372
|
+
...(options.reasoning_summary && { summary: "auto" }),
|
|
373
|
+
},
|
|
356
374
|
}),
|
|
357
375
|
...(tools?.length && {
|
|
358
376
|
tools,
|
|
@@ -372,6 +390,11 @@ export class GenericOpenAiClient implements GenericClient {
|
|
|
372
390
|
cached_tokens:
|
|
373
391
|
response.usage.input_tokens_details?.cached_tokens ?? 0,
|
|
374
392
|
},
|
|
393
|
+
...((response.usage as any).output_tokens_details?.reasoning_tokens != null && {
|
|
394
|
+
output_tokens_details: {
|
|
395
|
+
reasoning_tokens: (response.usage as any).output_tokens_details.reasoning_tokens,
|
|
396
|
+
},
|
|
397
|
+
}),
|
|
375
398
|
}
|
|
376
399
|
: undefined;
|
|
377
400
|
|
|
@@ -10,6 +10,13 @@ import { completions, ModelCatalogEntry, ModelPricing } from "./types";
|
|
|
10
10
|
export const AnthropicModels = {
|
|
11
11
|
// Active models
|
|
12
12
|
Fable5: "claude-fable-5",
|
|
13
|
+
// Short aliases (without date suffix) — Anthropic resolves these to the latest
|
|
14
|
+
// dated version. Pricing entries for the short aliases are added to the pricing
|
|
15
|
+
// table below so cost tracking works regardless of whether the user specifies
|
|
16
|
+
// the full dated name or the short alias.
|
|
17
|
+
Sonnet4_5Short: "claude-sonnet-4-5",
|
|
18
|
+
Haiku4_5Short: "claude-haiku-4-5",
|
|
19
|
+
Opus4_5Short: "claude-opus-4-5",
|
|
13
20
|
Sonnet5: "claude-sonnet-5",
|
|
14
21
|
Mythos5: "claude-mythos-5",
|
|
15
22
|
MythosPreview: "claude-mythos-preview",
|
|
@@ -101,6 +108,10 @@ export const AnthropicTextPricing: Record<string, ModelPricing> = {
|
|
|
101
108
|
[AnthropicModels.Opus4_1]: { input: 15.0, cache_write: 18.75, cache_hit: 1.5, output: 75.0 },
|
|
102
109
|
[AnthropicModels.Sonnet4_5]: { input: 3.0, input_gt_200k: 6.0, cache_write: 3.75, cache_hit: 0.3, output: 15.0, output_gt_200k: 22.5 },
|
|
103
110
|
[AnthropicModels.Haiku4_5]: { input: 1.0, cache_write: 1.25, cache_hit: 0.1, output: 5.0 },
|
|
111
|
+
// Short aliases — same pricing as their dated counterparts
|
|
112
|
+
[AnthropicModels.Sonnet4_5Short]: { input: 3.0, input_gt_200k: 6.0, cache_write: 3.75, cache_hit: 0.3, output: 15.0, output_gt_200k: 22.5 },
|
|
113
|
+
[AnthropicModels.Haiku4_5Short]: { input: 1.0, cache_write: 1.25, cache_hit: 0.1, output: 5.0 },
|
|
114
|
+
[AnthropicModels.Opus4_5Short]: { input: 5.0, cache_write: 6.25, cache_hit: 0.5, output: 25.0 },
|
|
104
115
|
// Deprecated — pricing retained for cost tracking
|
|
105
116
|
[AnthropicModels.Opus4]: { input: 15.0, cache_write: 18.75, cache_hit: 1.5, output: 75.0, deprecated: true, deprecationDate: "2026-06-15" },
|
|
106
117
|
[AnthropicModels.Sonnet4]: { input: 3.0, input_gt_200k: 6.0, cache_write: 3.75, cache_hit: 0.3, output: 15.0, output_gt_200k: 22.5, deprecated: true, deprecationDate: "2026-06-15" },
|
|
@@ -40,3 +40,15 @@ export const FireworksTextPricing: Record<string, ModelPricing> = {
|
|
|
40
40
|
// OpenAI OSS
|
|
41
41
|
"accounts/fireworks/models/gpt-oss-120b": { input: 0.15, cache_hit: 0.01, output: 0.60 },
|
|
42
42
|
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Fireworks AI embedding/reranker model pricing (USD per 1M tokens)
|
|
46
|
+
* Source: https://fireworks.ai/pricing
|
|
47
|
+
*/
|
|
48
|
+
export const FireworksEmbeddingPricing: Record<string, ModelPricing> = {
|
|
49
|
+
// Qwen3 Embedding 8B — $0.10/M tokens, context 40k
|
|
50
|
+
"accounts/fireworks/models/qwen3-embedding-8b": { input: 0.10, output: 0.10 },
|
|
51
|
+
|
|
52
|
+
// Qwen3 Reranker 8B — $0.20/M tokens, context 40k
|
|
53
|
+
"accounts/fireworks/models/qwen3-reranker-8b": { input: 0.20, output: 0.20 },
|
|
54
|
+
};
|
|
@@ -167,6 +167,9 @@ export const OpenAiResponsesOnlyModels: string[] = [
|
|
|
167
167
|
OpenAiModels.GPT_55_Pro,
|
|
168
168
|
OpenAiModels.GPT_55,
|
|
169
169
|
OpenAiModels.GPT_5_Pro,
|
|
170
|
+
OpenAiModels.GPT_56_Sol,
|
|
171
|
+
OpenAiModels.GPT_56_Terra,
|
|
172
|
+
OpenAiModels.GPT_56_Luna,
|
|
170
173
|
OpenAiModels.o1,
|
|
171
174
|
OpenAiModels.o1_Pro,
|
|
172
175
|
];
|
package/src/clients/types.ts
CHANGED
|
@@ -86,10 +86,26 @@ export interface CompletionOptions extends RetryOptions {
|
|
|
86
86
|
tools?: Tool[];
|
|
87
87
|
tool_choice?: "auto" | "none";
|
|
88
88
|
max_tokens?: number;
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Reasoning effort level for models that support it.
|
|
91
|
+
* Maps to: OpenAI reasoning_effort/reasoning.effort, xAI reasoning.effort,
|
|
92
|
+
* Gemini thinkingLevel/thinkingBudget, Anthropic thinking mode.
|
|
93
|
+
*
|
|
94
|
+
* "none" = disable thinking entirely (Anthropic: thinking.type="disabled",
|
|
95
|
+
* OpenAI: reasoning.effort="none"). Only supported by models that
|
|
96
|
+
* allow disabling thinking (e.g. claude-sonnet-5).
|
|
97
|
+
* "low" = minimal thinking
|
|
98
|
+
* "medium" = balanced (default for most models)
|
|
99
|
+
* "high" = maximum reasoning
|
|
100
|
+
*/
|
|
101
|
+
reasoning_effort?: "none" | "low" | "medium" | "high";
|
|
102
|
+
/**
|
|
103
|
+
* When true, request a summarized view of the model's thinking process.
|
|
104
|
+
* - Anthropic: thinking.display = "summarized"
|
|
105
|
+
* - OpenAI: reasoning.summary = "auto"
|
|
106
|
+
* Defaults to false (no summary displayed).
|
|
107
|
+
*/
|
|
108
|
+
reasoning_summary?: boolean;
|
|
93
109
|
/**
|
|
94
110
|
* When true, hints to the client that this task is long-running and it should
|
|
95
111
|
* use a long-TTL cache where available.
|
|
@@ -115,6 +131,13 @@ export interface TokenUsage {
|
|
|
115
131
|
output_tokens?: number;
|
|
116
132
|
/** Convenience total (prompt + completion) */
|
|
117
133
|
total_tokens?: number;
|
|
134
|
+
/** Breakdown of output tokens — thinking/reasoning tokens are billed as output
|
|
135
|
+
* but should NOT be counted toward the visible-content heuristics. */
|
|
136
|
+
output_tokens_details?: {
|
|
137
|
+
/** Anthropic: thinking_tokens, OpenAI: reasoning_tokens */
|
|
138
|
+
thinking_tokens?: number;
|
|
139
|
+
reasoning_tokens?: number;
|
|
140
|
+
};
|
|
118
141
|
/** Cache details */
|
|
119
142
|
prompt_tokens_details?: {
|
|
120
143
|
/** Tokens served from the prompt cache (reduces cost) */
|
package/src/clients/xai.ts
CHANGED
|
@@ -76,9 +76,9 @@ export class GenericXAIClient implements GenericClient {
|
|
|
76
76
|
model: options.model,
|
|
77
77
|
messages: xaiMessages,
|
|
78
78
|
max_tokens: options.max_tokens,
|
|
79
|
-
...(XaiReasoningModels.includes(options.model) && options.reasoning_effort && {
|
|
79
|
+
...(XaiReasoningModels.includes(options.model) && options.reasoning_effort && options.reasoning_effort !== "none" && {
|
|
80
80
|
// grok-3-mini models support reasoning_effort: "low" | "medium" | "high"
|
|
81
|
-
reasoning_effort: options.reasoning_effort,
|
|
81
|
+
reasoning_effort: options.reasoning_effort as "low" | "medium" | "high",
|
|
82
82
|
}),
|
|
83
83
|
...(options.tools && {
|
|
84
84
|
tools: options.tools,
|
package/src/commands/agent.ts
CHANGED
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { readPromptFile } from "../ai";
|
|
3
|
+
import { BehaviorsService } from "../services/BehaviorsService";
|
|
3
4
|
import { AgentModule } from "../chat/modules/AgentModule";
|
|
4
5
|
import { AskModule } from "../chat/modules/AskModule";
|
|
5
6
|
import { SearchModule } from "../chat/modules/SearchModule";
|
|
6
7
|
import { SessionsModule } from "../chat/modules/SessionsModule";
|
|
7
8
|
import { SetupModule } from "../chat/modules/SetupModule";
|
|
9
|
+
import { PlainRenderer } from "../chat/renderer/PlainRenderer";
|
|
8
10
|
import { loadRenderer } from "../chat/renderer/loadRenderer";
|
|
9
11
|
import { getConfig } from "../config";
|
|
10
12
|
|
|
13
|
+
async function setupRenderer(chatService: any, rendererSpecifier: string): Promise<void> {
|
|
14
|
+
const resolved =
|
|
15
|
+
rendererSpecifier === "basic" && !process.stdout.isTTY ? "plain" : rendererSpecifier;
|
|
16
|
+
try {
|
|
17
|
+
const renderer = await loadRenderer(resolved);
|
|
18
|
+
chatService.setContext({ renderer });
|
|
19
|
+
} catch (err: any) {
|
|
20
|
+
console.warn(`⚠ Could not load renderer "${resolved}": ${err.message}`);
|
|
21
|
+
console.warn(" Falling back to basic renderer.");
|
|
22
|
+
try {
|
|
23
|
+
const fallback = !process.stdout.isTTY ? new PlainRenderer() : await loadRenderer("basic");
|
|
24
|
+
chatService.setContext({ renderer: fallback });
|
|
25
|
+
} catch (_) {}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
11
29
|
async function readStdin(): Promise<string> {
|
|
12
30
|
return new Promise((resolve) => {
|
|
13
31
|
let data = "";
|
|
@@ -27,24 +45,6 @@ async function readStdin(): Promise<string> {
|
|
|
27
45
|
});
|
|
28
46
|
}
|
|
29
47
|
|
|
30
|
-
/**
|
|
31
|
-
* Set up the renderer on the chat service context.
|
|
32
|
-
* Priority: CLI --renderer flag > config.chat.renderer > "basic" (ConsoleRenderer)
|
|
33
|
-
*/
|
|
34
|
-
async function setupRenderer(chatService: any, rendererSpecifier: string): Promise<void> {
|
|
35
|
-
try {
|
|
36
|
-
const renderer = await loadRenderer(rendererSpecifier);
|
|
37
|
-
chatService.setContext({ renderer });
|
|
38
|
-
} catch (err: any) {
|
|
39
|
-
console.warn(`⚠ Could not load renderer "${rendererSpecifier}": ${err.message}`);
|
|
40
|
-
console.warn(" Falling back to basic renderer.");
|
|
41
|
-
try {
|
|
42
|
-
const fallback = await loadRenderer("basic");
|
|
43
|
-
chatService.setContext({ renderer: fallback });
|
|
44
|
-
} catch (_) {}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
48
|
export function addAgentCommand(program: Command, getChatService: () => any): void {
|
|
49
49
|
program
|
|
50
50
|
.command("agent")
|
|
@@ -67,6 +67,14 @@ export function addAgentCommand(program: Command, getChatService: () => any): vo
|
|
|
67
67
|
)
|
|
68
68
|
.option("--message-id <messageId>", "Knowhow message ID for task tracking")
|
|
69
69
|
.option("--sync-fs", "Enable filesystem-based synchronization")
|
|
70
|
+
.option(
|
|
71
|
+
"--behavior-id <id>",
|
|
72
|
+
"Force a specific behavior by its ID (skips trigger matching)"
|
|
73
|
+
)
|
|
74
|
+
.option(
|
|
75
|
+
"--behavior-file <path>",
|
|
76
|
+
"Force a specific behavior by its file path (skips trigger matching)"
|
|
77
|
+
)
|
|
70
78
|
.option(
|
|
71
79
|
"--task-id <taskId>",
|
|
72
80
|
"Pre-generated task ID (used with --sync-fs for predictable agent directory path)"
|
|
@@ -92,6 +100,7 @@ export function addAgentCommand(program: Command, getChatService: () => any): vo
|
|
|
92
100
|
try { config = await getConfig(); } catch (_) {}
|
|
93
101
|
const rendererSpecifier = options.renderer ?? config.chat?.renderer ?? "basic";
|
|
94
102
|
await setupRenderer(chatService, rendererSpecifier);
|
|
103
|
+
|
|
95
104
|
const agentModule = new AgentModule();
|
|
96
105
|
|
|
97
106
|
if (options.resume) {
|
|
@@ -131,11 +140,54 @@ export function addAgentCommand(program: Command, getChatService: () => any): vo
|
|
|
131
140
|
}
|
|
132
141
|
|
|
133
142
|
await agentModule.initialize(chatService);
|
|
143
|
+
|
|
144
|
+
// Match a behavior from local disk (.knowhow/behaviors/)
|
|
145
|
+
let behaviorSystemPrompt: string | undefined;
|
|
146
|
+
let behaviorModel: string | undefined;
|
|
147
|
+
const behaviorsSvc = new BehaviorsService();
|
|
148
|
+
|
|
149
|
+
let matchedBehavior = null;
|
|
150
|
+
|
|
151
|
+
if (options.behaviorFile) {
|
|
152
|
+
// Load behavior directly from a file path
|
|
153
|
+
matchedBehavior = behaviorsSvc.loadBehaviorFromFile(options.behaviorFile);
|
|
154
|
+
if (matchedBehavior) {
|
|
155
|
+
console.log(`🎯 Using behavior from file: ${options.behaviorFile}`);
|
|
156
|
+
} else {
|
|
157
|
+
console.error(`❌ Could not load behavior from file: ${options.behaviorFile}`);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
} else if (options.behaviorId) {
|
|
161
|
+
// Load behavior by ID (searches local disk behaviors)
|
|
162
|
+
matchedBehavior = behaviorsSvc.findBehaviorById(options.behaviorId);
|
|
163
|
+
if (matchedBehavior) {
|
|
164
|
+
console.log(`🎯 Using behavior by ID: ${options.behaviorId} (${matchedBehavior.name})`);
|
|
165
|
+
} else {
|
|
166
|
+
console.error(`❌ No behavior found with ID: ${options.behaviorId}`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
// Default: match by trigger text
|
|
171
|
+
matchedBehavior = behaviorsSvc.matchBehaviorLocal(input);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (matchedBehavior) {
|
|
175
|
+
console.log(`🎯 Matched behavior: ${matchedBehavior.name}`);
|
|
176
|
+
if (matchedBehavior.instructions) {
|
|
177
|
+
behaviorSystemPrompt = matchedBehavior.instructions;
|
|
178
|
+
}
|
|
179
|
+
if (matchedBehavior.model) {
|
|
180
|
+
behaviorModel = matchedBehavior.model;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
134
184
|
const { taskCompleted } = await agentModule.setupAgent({
|
|
135
185
|
...options,
|
|
136
186
|
input,
|
|
137
187
|
maxTimeLimit: parseInt(options.maxTimeLimit, 10),
|
|
138
188
|
maxSpendLimit: parseFloat(options.maxSpendLimit),
|
|
189
|
+
...(behaviorSystemPrompt ? { systemPrompt: behaviorSystemPrompt } : {}),
|
|
190
|
+
...(behaviorModel ? { model: behaviorModel } : {}),
|
|
139
191
|
run: true,
|
|
140
192
|
});
|
|
141
193
|
await taskCompleted;
|