mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-17 10:02:23 +00:00
Remove allowDuringStreaming flag - commands always run immediately
Hook commands now always execute immediately, even during streaming. If a command needs to interact with the LLM, it uses pi.sendMessage() which handles queueing automatically. This simplifies the API and eliminates the issue of queued slash commands being sent to the LLM instead of executing.
This commit is contained in:
parent
f8352bb7d7
commit
575c875475
5 changed files with 66 additions and 78 deletions
|
|
@ -29,14 +29,6 @@ export default function (pi: HookAPI) {
|
||||||
return box;
|
return box;
|
||||||
});
|
});
|
||||||
|
|
||||||
pi.registerCommand("no-stream", {
|
|
||||||
description: "Send a message without streaming",
|
|
||||||
handler: async (ctx) => {
|
|
||||||
ctx.ui.notify("Sending message after streaming is done...");
|
|
||||||
},
|
|
||||||
allowDuringStreaming: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Register /test-msg command
|
// Register /test-msg command
|
||||||
pi.registerCommand("test-msg", {
|
pi.registerCommand("test-msg", {
|
||||||
description: "Send a test custom message",
|
description: "Send a test custom message",
|
||||||
|
|
|
||||||
|
|
@ -6104,9 +6104,9 @@ export const MODELS = {
|
||||||
contextWindow: 32768,
|
contextWindow: 32768,
|
||||||
maxTokens: 4096,
|
maxTokens: 4096,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
"anthropic/claude-3.5-haiku": {
|
"anthropic/claude-3.5-haiku-20241022": {
|
||||||
id: "anthropic/claude-3.5-haiku",
|
id: "anthropic/claude-3.5-haiku-20241022",
|
||||||
name: "Anthropic: Claude 3.5 Haiku",
|
name: "Anthropic: Claude 3.5 Haiku (2024-10-22)",
|
||||||
api: "openai-completions",
|
api: "openai-completions",
|
||||||
provider: "openrouter",
|
provider: "openrouter",
|
||||||
baseUrl: "https://openrouter.ai/api/v1",
|
baseUrl: "https://openrouter.ai/api/v1",
|
||||||
|
|
@ -6121,9 +6121,9 @@ export const MODELS = {
|
||||||
contextWindow: 200000,
|
contextWindow: 200000,
|
||||||
maxTokens: 8192,
|
maxTokens: 8192,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
"anthropic/claude-3.5-haiku-20241022": {
|
"anthropic/claude-3.5-haiku": {
|
||||||
id: "anthropic/claude-3.5-haiku-20241022",
|
id: "anthropic/claude-3.5-haiku",
|
||||||
name: "Anthropic: Claude 3.5 Haiku (2024-10-22)",
|
name: "Anthropic: Claude 3.5 Haiku",
|
||||||
api: "openai-completions",
|
api: "openai-completions",
|
||||||
provider: "openrouter",
|
provider: "openrouter",
|
||||||
baseUrl: "https://openrouter.ai/api/v1",
|
baseUrl: "https://openrouter.ai/api/v1",
|
||||||
|
|
@ -6359,6 +6359,23 @@ export const MODELS = {
|
||||||
contextWindow: 128000,
|
contextWindow: 128000,
|
||||||
maxTokens: 16384,
|
maxTokens: 16384,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
|
"meta-llama/llama-3.1-8b-instruct": {
|
||||||
|
id: "meta-llama/llama-3.1-8b-instruct",
|
||||||
|
name: "Meta: Llama 3.1 8B Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "openrouter",
|
||||||
|
baseUrl: "https://openrouter.ai/api/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.02,
|
||||||
|
output: 0.03,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
"meta-llama/llama-3.1-405b-instruct": {
|
"meta-llama/llama-3.1-405b-instruct": {
|
||||||
id: "meta-llama/llama-3.1-405b-instruct",
|
id: "meta-llama/llama-3.1-405b-instruct",
|
||||||
name: "Meta: Llama 3.1 405B Instruct",
|
name: "Meta: Llama 3.1 405B Instruct",
|
||||||
|
|
@ -6393,23 +6410,6 @@ export const MODELS = {
|
||||||
contextWindow: 131072,
|
contextWindow: 131072,
|
||||||
maxTokens: 4096,
|
maxTokens: 4096,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
"meta-llama/llama-3.1-8b-instruct": {
|
|
||||||
id: "meta-llama/llama-3.1-8b-instruct",
|
|
||||||
name: "Meta: Llama 3.1 8B Instruct",
|
|
||||||
api: "openai-completions",
|
|
||||||
provider: "openrouter",
|
|
||||||
baseUrl: "https://openrouter.ai/api/v1",
|
|
||||||
reasoning: false,
|
|
||||||
input: ["text"],
|
|
||||||
cost: {
|
|
||||||
input: 0.02,
|
|
||||||
output: 0.03,
|
|
||||||
cacheRead: 0,
|
|
||||||
cacheWrite: 0,
|
|
||||||
},
|
|
||||||
contextWindow: 131072,
|
|
||||||
maxTokens: 16384,
|
|
||||||
} satisfies Model<"openai-completions">,
|
|
||||||
"mistralai/mistral-nemo": {
|
"mistralai/mistral-nemo": {
|
||||||
id: "mistralai/mistral-nemo",
|
id: "mistralai/mistral-nemo",
|
||||||
name: "Mistral: Mistral Nemo",
|
name: "Mistral: Mistral Nemo",
|
||||||
|
|
@ -6546,6 +6546,23 @@ export const MODELS = {
|
||||||
contextWindow: 128000,
|
contextWindow: 128000,
|
||||||
maxTokens: 4096,
|
maxTokens: 4096,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
|
"openai/gpt-4o-2024-05-13": {
|
||||||
|
id: "openai/gpt-4o-2024-05-13",
|
||||||
|
name: "OpenAI: GPT-4o (2024-05-13)",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "openrouter",
|
||||||
|
baseUrl: "https://openrouter.ai/api/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
"openai/gpt-4o": {
|
"openai/gpt-4o": {
|
||||||
id: "openai/gpt-4o",
|
id: "openai/gpt-4o",
|
||||||
name: "OpenAI: GPT-4o",
|
name: "OpenAI: GPT-4o",
|
||||||
|
|
@ -6580,23 +6597,6 @@ export const MODELS = {
|
||||||
contextWindow: 128000,
|
contextWindow: 128000,
|
||||||
maxTokens: 64000,
|
maxTokens: 64000,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
"openai/gpt-4o-2024-05-13": {
|
|
||||||
id: "openai/gpt-4o-2024-05-13",
|
|
||||||
name: "OpenAI: GPT-4o (2024-05-13)",
|
|
||||||
api: "openai-completions",
|
|
||||||
provider: "openrouter",
|
|
||||||
baseUrl: "https://openrouter.ai/api/v1",
|
|
||||||
reasoning: false,
|
|
||||||
input: ["text", "image"],
|
|
||||||
cost: {
|
|
||||||
input: 5,
|
|
||||||
output: 15,
|
|
||||||
cacheRead: 0,
|
|
||||||
cacheWrite: 0,
|
|
||||||
},
|
|
||||||
contextWindow: 128000,
|
|
||||||
maxTokens: 4096,
|
|
||||||
} satisfies Model<"openai-completions">,
|
|
||||||
"meta-llama/llama-3-70b-instruct": {
|
"meta-llama/llama-3-70b-instruct": {
|
||||||
id: "meta-llama/llama-3-70b-instruct",
|
id: "meta-llama/llama-3-70b-instruct",
|
||||||
name: "Meta: Llama 3 70B Instruct",
|
name: "Meta: Llama 3 70B Instruct",
|
||||||
|
|
@ -6835,23 +6835,6 @@ export const MODELS = {
|
||||||
contextWindow: 8191,
|
contextWindow: 8191,
|
||||||
maxTokens: 4096,
|
maxTokens: 4096,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
"openai/gpt-3.5-turbo": {
|
|
||||||
id: "openai/gpt-3.5-turbo",
|
|
||||||
name: "OpenAI: GPT-3.5 Turbo",
|
|
||||||
api: "openai-completions",
|
|
||||||
provider: "openrouter",
|
|
||||||
baseUrl: "https://openrouter.ai/api/v1",
|
|
||||||
reasoning: false,
|
|
||||||
input: ["text"],
|
|
||||||
cost: {
|
|
||||||
input: 0.5,
|
|
||||||
output: 1.5,
|
|
||||||
cacheRead: 0,
|
|
||||||
cacheWrite: 0,
|
|
||||||
},
|
|
||||||
contextWindow: 16385,
|
|
||||||
maxTokens: 4096,
|
|
||||||
} satisfies Model<"openai-completions">,
|
|
||||||
"openai/gpt-4": {
|
"openai/gpt-4": {
|
||||||
id: "openai/gpt-4",
|
id: "openai/gpt-4",
|
||||||
name: "OpenAI: GPT-4",
|
name: "OpenAI: GPT-4",
|
||||||
|
|
@ -6869,6 +6852,23 @@ export const MODELS = {
|
||||||
contextWindow: 8191,
|
contextWindow: 8191,
|
||||||
maxTokens: 4096,
|
maxTokens: 4096,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
|
"openai/gpt-3.5-turbo": {
|
||||||
|
id: "openai/gpt-3.5-turbo",
|
||||||
|
name: "OpenAI: GPT-3.5 Turbo",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "openrouter",
|
||||||
|
baseUrl: "https://openrouter.ai/api/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 1.5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 16385,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
"openrouter/auto": {
|
"openrouter/auto": {
|
||||||
id: "openrouter/auto",
|
id: "openrouter/auto",
|
||||||
name: "OpenRouter: Auto Router",
|
name: "OpenRouter: Auto Router",
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@ const SNAKE_SAVE_TYPE = "snake-save";
|
||||||
export default function (pi: HookAPI) {
|
export default function (pi: HookAPI) {
|
||||||
pi.registerCommand("snake", {
|
pi.registerCommand("snake", {
|
||||||
description: "Play Snake!",
|
description: "Play Snake!",
|
||||||
allowDuringStreaming: true, // Run even during streaming, not queued
|
|
||||||
handler: async (ctx) => {
|
handler: async (ctx) => {
|
||||||
if (!ctx.hasUI) {
|
if (!ctx.hasUI) {
|
||||||
ctx.ui.notify("Snake requires interactive mode", "error");
|
ctx.ui.notify("Snake requires interactive mode", "error");
|
||||||
|
|
|
||||||
|
|
@ -442,8 +442,7 @@ export interface HookCommandContext {
|
||||||
export interface RegisteredCommand {
|
export interface RegisteredCommand {
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
/** If true, command runs during streaming instead of being queued */
|
|
||||||
allowDuringStreaming?: boolean;
|
|
||||||
handler: (ctx: HookCommandContext) => Promise<void>;
|
handler: (ctx: HookCommandContext) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -456,9 +455,9 @@ export interface HookAPI {
|
||||||
on(event: "session", handler: HookHandler<SessionEvent, SessionEventResult | void>): void;
|
on(event: "session", handler: HookHandler<SessionEvent, SessionEventResult | void>): void;
|
||||||
// biome-ignore lint/suspicious/noConfusingVoidType: void allows handlers to not return anything
|
// biome-ignore lint/suspicious/noConfusingVoidType: void allows handlers to not return anything
|
||||||
on(event: "context", handler: HookHandler<ContextEvent, ContextEventResult | void>): void;
|
on(event: "context", handler: HookHandler<ContextEvent, ContextEventResult | void>): void;
|
||||||
// biome-ignore lint/suspicious/noConfusingVoidType: void allows handlers to not return anything
|
|
||||||
on(
|
on(
|
||||||
event: "before_agent_start",
|
event: "before_agent_start",
|
||||||
|
// biome-ignore lint/suspicious/noConfusingVoidType: void allows handlers to not return anything
|
||||||
handler: HookHandler<BeforeAgentStartEvent, BeforeAgentStartEventResult | void>,
|
handler: HookHandler<BeforeAgentStartEvent, BeforeAgentStartEventResult | void>,
|
||||||
): void;
|
): void;
|
||||||
on(event: "agent_start", handler: HookHandler<AgentStartEvent>): void;
|
on(event: "agent_start", handler: HookHandler<AgentStartEvent>): void;
|
||||||
|
|
@ -527,10 +526,7 @@ export interface HookAPI {
|
||||||
* Register a custom slash command.
|
* Register a custom slash command.
|
||||||
* Handler receives HookCommandContext.
|
* Handler receives HookCommandContext.
|
||||||
*/
|
*/
|
||||||
registerCommand(
|
registerCommand(name: string, options: { description?: string; handler: RegisteredCommand["handler"] }): void;
|
||||||
name: string,
|
|
||||||
options: { description?: string; allowDuringStreaming?: boolean; handler: RegisteredCommand["handler"] },
|
|
||||||
): void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a shell command and return stdout/stderr/code.
|
* Execute a shell command and return stdout/stderr/code.
|
||||||
|
|
|
||||||
|
|
@ -744,13 +744,13 @@ export class InteractiveMode {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this hook command can run during streaming (not queued)
|
// Hook commands always run immediately, even during streaming
|
||||||
if (text.startsWith("/") && this.session.hookRunner && this.session.isStreaming) {
|
// (if they need to interact with LLM, they use pi.sendMessage which handles queueing)
|
||||||
|
if (text.startsWith("/") && this.session.hookRunner) {
|
||||||
const spaceIndex = text.indexOf(" ");
|
const spaceIndex = text.indexOf(" ");
|
||||||
const commandName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);
|
const commandName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);
|
||||||
const command = this.session.hookRunner.getCommand(commandName);
|
const command = this.session.hookRunner.getCommand(commandName);
|
||||||
if (command?.allowDuringStreaming) {
|
if (command) {
|
||||||
// Execute hook command right away
|
|
||||||
this.editor.addToHistory(text);
|
this.editor.addToHistory(text);
|
||||||
this.editor.setText("");
|
this.editor.setText("");
|
||||||
await this.session.prompt(text);
|
await this.session.prompt(text);
|
||||||
|
|
@ -758,7 +758,7 @@ export class InteractiveMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Queue message if agent is streaming
|
// Queue regular messages if agent is streaming
|
||||||
if (this.session.isStreaming) {
|
if (this.session.isStreaming) {
|
||||||
await this.session.queueMessage(text);
|
await this.session.queueMessage(text);
|
||||||
this.updatePendingMessagesDisplay();
|
this.updatePendingMessagesDisplay();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue