mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 09:01:14 +00:00
Release v0.27.8 - OAuth takes priority over settings.json API keys
This commit is contained in:
parent
60768b90f3
commit
a965b6f160
14 changed files with 426 additions and 102 deletions
40
package-lock.json
generated
40
package-lock.json
generated
|
|
@ -6447,11 +6447,11 @@
|
|||
},
|
||||
"packages/agent": {
|
||||
"name": "@mariozechner/pi-agent-core",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mariozechner/pi-ai": "^0.27.7",
|
||||
"@mariozechner/pi-tui": "^0.27.7"
|
||||
"@mariozechner/pi-ai": "^0.27.8",
|
||||
"@mariozechner/pi-tui": "^0.27.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.3.0",
|
||||
|
|
@ -6481,7 +6481,7 @@
|
|||
},
|
||||
"packages/ai": {
|
||||
"name": "@mariozechner/pi-ai",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "0.71.2",
|
||||
|
|
@ -6523,12 +6523,12 @@
|
|||
},
|
||||
"packages/coding-agent": {
|
||||
"name": "@mariozechner/pi-coding-agent",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mariozechner/pi-agent-core": "^0.27.7",
|
||||
"@mariozechner/pi-ai": "^0.27.7",
|
||||
"@mariozechner/pi-tui": "^0.27.7",
|
||||
"@mariozechner/pi-agent-core": "^0.27.8",
|
||||
"@mariozechner/pi-ai": "^0.27.8",
|
||||
"@mariozechner/pi-tui": "^0.27.8",
|
||||
"chalk": "^5.5.0",
|
||||
"cli-highlight": "^2.1.11",
|
||||
"diff": "^8.0.2",
|
||||
|
|
@ -6569,13 +6569,13 @@
|
|||
},
|
||||
"packages/mom": {
|
||||
"name": "@mariozechner/pi-mom",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sandbox-runtime": "^0.0.16",
|
||||
"@mariozechner/pi-agent-core": "^0.27.7",
|
||||
"@mariozechner/pi-ai": "^0.27.7",
|
||||
"@mariozechner/pi-coding-agent": "^0.27.7",
|
||||
"@mariozechner/pi-agent-core": "^0.27.8",
|
||||
"@mariozechner/pi-ai": "^0.27.8",
|
||||
"@mariozechner/pi-coding-agent": "^0.27.8",
|
||||
"@sinclair/typebox": "^0.34.0",
|
||||
"@slack/socket-mode": "^2.0.0",
|
||||
"@slack/web-api": "^7.0.0",
|
||||
|
|
@ -6614,10 +6614,10 @@
|
|||
},
|
||||
"packages/pods": {
|
||||
"name": "@mariozechner/pi",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mariozechner/pi-agent-core": "^0.27.7",
|
||||
"@mariozechner/pi-agent-core": "^0.27.8",
|
||||
"chalk": "^5.5.0"
|
||||
},
|
||||
"bin": {
|
||||
|
|
@ -6630,7 +6630,7 @@
|
|||
},
|
||||
"packages/proxy": {
|
||||
"name": "@mariozechner/pi-proxy",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.14.0",
|
||||
"hono": "^4.6.16"
|
||||
|
|
@ -6646,7 +6646,7 @@
|
|||
},
|
||||
"packages/tui": {
|
||||
"name": "@mariozechner/pi-tui",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/mime-types": "^2.1.4",
|
||||
|
|
@ -6690,12 +6690,12 @@
|
|||
},
|
||||
"packages/web-ui": {
|
||||
"name": "@mariozechner/pi-web-ui",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lmstudio/sdk": "^1.5.0",
|
||||
"@mariozechner/pi-ai": "^0.27.7",
|
||||
"@mariozechner/pi-tui": "^0.27.7",
|
||||
"@mariozechner/pi-ai": "^0.27.8",
|
||||
"@mariozechner/pi-tui": "^0.27.8",
|
||||
"docx-preview": "^0.3.7",
|
||||
"jszip": "^3.10.1",
|
||||
"lucide": "^0.544.0",
|
||||
|
|
@ -6716,7 +6716,7 @@
|
|||
},
|
||||
"packages/web-ui/example": {
|
||||
"name": "pi-web-ui-example",
|
||||
"version": "1.15.7",
|
||||
"version": "1.15.8",
|
||||
"dependencies": {
|
||||
"@mariozechner/mini-lit": "^0.2.0",
|
||||
"@mariozechner/pi-ai": "file:../../ai",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@mariozechner/pi-agent-core",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
"prepublishOnly": "npm run clean && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mariozechner/pi-ai": "^0.27.7",
|
||||
"@mariozechner/pi-tui": "^0.27.7"
|
||||
"@mariozechner/pi-ai": "^0.27.8",
|
||||
"@mariozechner/pi-tui": "^0.27.8"
|
||||
},
|
||||
"keywords": [
|
||||
"ai",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@mariozechner/pi-ai",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
|
|
|
|||
|
|
@ -2919,8 +2919,8 @@ export const MODELS = {
|
|||
cost: {
|
||||
input: 0.3,
|
||||
output: 1.2,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
cacheRead: 0.03,
|
||||
cacheWrite: 0.375,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
|
|
@ -6359,23 +6359,6 @@ export const MODELS = {
|
|||
contextWindow: 128000,
|
||||
maxTokens: 16384,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"meta-llama/llama-3.1-70b-instruct": {
|
||||
id: "meta-llama/llama-3.1-70b-instruct",
|
||||
name: "Meta: Llama 3.1 70B Instruct",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.39999999999999997,
|
||||
output: 0.39999999999999997,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 131072,
|
||||
maxTokens: 4096,
|
||||
} 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",
|
||||
|
|
@ -6410,6 +6393,23 @@ export const MODELS = {
|
|||
contextWindow: 10000,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"meta-llama/llama-3.1-70b-instruct": {
|
||||
id: "meta-llama/llama-3.1-70b-instruct",
|
||||
name: "Meta: Llama 3.1 70B Instruct",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.39999999999999997,
|
||||
output: 0.39999999999999997,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 131072,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"mistralai/mistral-nemo": {
|
||||
id: "mistralai/mistral-nemo",
|
||||
name: "Mistral: Mistral Nemo",
|
||||
|
|
@ -6546,6 +6546,23 @@ export const MODELS = {
|
|||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
} 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": {
|
||||
id: "openai/gpt-4o",
|
||||
name: "OpenAI: GPT-4o",
|
||||
|
|
@ -6580,23 +6597,6 @@ export const MODELS = {
|
|||
contextWindow: 128000,
|
||||
maxTokens: 64000,
|
||||
} 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": {
|
||||
id: "meta-llama/llama-3-70b-instruct",
|
||||
name: "Meta: Llama 3 70B Instruct",
|
||||
|
|
@ -6716,23 +6716,6 @@ export const MODELS = {
|
|||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-4-turbo-preview": {
|
||||
id: "openai/gpt-4-turbo-preview",
|
||||
name: "OpenAI: GPT-4 Turbo Preview",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 10,
|
||||
output: 30,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-3.5-turbo-0613": {
|
||||
id: "openai/gpt-3.5-turbo-0613",
|
||||
name: "OpenAI: GPT-3.5 Turbo (older v0613)",
|
||||
|
|
@ -6750,6 +6733,23 @@ export const MODELS = {
|
|||
contextWindow: 4095,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"openai/gpt-4-turbo-preview": {
|
||||
id: "openai/gpt-4-turbo-preview",
|
||||
name: "OpenAI: GPT-4 Turbo Preview",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 10,
|
||||
output: 30,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"mistralai/mistral-tiny": {
|
||||
id: "mistralai/mistral-tiny",
|
||||
name: "Mistral Tiny",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.27.8] - 2025-12-24
|
||||
|
||||
### Fixed
|
||||
|
||||
- **API key priority**: OAuth tokens now take priority over settings.json API keys. Previously, an API key in settings.json would trump OAuth, causing users logged in with a plan (unlimited tokens) to be billed via PAYG instead.
|
||||
|
||||
## [0.27.7] - 2025-12-24
|
||||
|
||||
### Fixed
|
||||
|
|
|
|||
314
packages/coding-agent/docs/hooks-v2.md
Normal file
314
packages/coding-agent/docs/hooks-v2.md
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
# Hooks v2: Commands + Context Control
|
||||
|
||||
Extends hooks with slash commands and context manipulation primitives.
|
||||
|
||||
## Goals
|
||||
|
||||
1. Hooks can register slash commands (`/pop`, `/pr`, `/test`)
|
||||
2. Hooks can save custom session entries
|
||||
3. Hooks can transform context before it goes to LLM
|
||||
4. All handlers get unified baseline access to state
|
||||
|
||||
Benchmark: `/pop` (session stacking) implementable entirely as a hook.
|
||||
|
||||
## API Extensions
|
||||
|
||||
### Commands
|
||||
|
||||
```typescript
|
||||
pi.command("pop", {
|
||||
description: "Pop to previous turn",
|
||||
handler: async (ctx) => {
|
||||
// ctx has full access (see Unified Context below)
|
||||
const selected = await ctx.ui.select("Pop to:", options);
|
||||
// ...
|
||||
return { status: "Done" }; // show status
|
||||
return "prompt text"; // send to agent
|
||||
return; // do nothing
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Custom Entries
|
||||
|
||||
```typescript
|
||||
// Save arbitrary entry to session
|
||||
await ctx.saveEntry({
|
||||
type: "stack_pop", // custom type, ignored by core
|
||||
backToIndex: 5,
|
||||
summary: "...",
|
||||
timestamp: Date.now()
|
||||
});
|
||||
```
|
||||
|
||||
### Context Transform
|
||||
|
||||
```typescript
|
||||
// Fires when building context for LLM
|
||||
pi.on("context", (event, ctx) => {
|
||||
// event.entries: all session entries (including custom types)
|
||||
// event.messages: core-computed messages (after compaction)
|
||||
|
||||
// Return modified messages, or undefined to keep default
|
||||
return { messages: transformed };
|
||||
});
|
||||
```
|
||||
|
||||
Multiple `context` handlers chain: each receives previous handler's output.
|
||||
|
||||
### Rebuild Trigger
|
||||
|
||||
```typescript
|
||||
// Force context rebuild (after saving entries)
|
||||
await ctx.rebuildContext();
|
||||
```
|
||||
|
||||
## Unified Context
|
||||
|
||||
All handlers receive:
|
||||
|
||||
```typescript
|
||||
interface HookEventContext {
|
||||
// Existing
|
||||
exec(cmd: string, args: string[], opts?): Promise<ExecResult>;
|
||||
ui: { select, confirm, input, notify };
|
||||
hasUI: boolean;
|
||||
cwd: string;
|
||||
sessionFile: string | null;
|
||||
|
||||
// New: State (read-only)
|
||||
model: Model<any> | null;
|
||||
thinkingLevel: ThinkingLevel;
|
||||
entries: readonly SessionEntry[];
|
||||
messages: readonly AppMessage[];
|
||||
|
||||
// New: Utilities
|
||||
findModel(provider: string, id: string): Model<any> | null;
|
||||
availableModels(): Promise<Model<any>[]>;
|
||||
resolveApiKey(model: Model<any>): Promise<string | undefined>;
|
||||
|
||||
// New: Mutation (commands only? or all?)
|
||||
saveEntry(entry: { type: string; [k: string]: unknown }): Promise<void>;
|
||||
rebuildContext(): Promise<void>;
|
||||
}
|
||||
```
|
||||
|
||||
Commands additionally get:
|
||||
- `args: string[]`, `argsRaw: string`
|
||||
- `setModel()`, `setThinkingLevel()` (state mutation)
|
||||
|
||||
## Benchmark: Stacking as Hook
|
||||
|
||||
```typescript
|
||||
export default function(pi: HookAPI) {
|
||||
// Command: /pop
|
||||
pi.command("pop", {
|
||||
description: "Pop to previous turn, summarizing substack",
|
||||
handler: async (ctx) => {
|
||||
// 1. Build turn list from entries
|
||||
const turns = ctx.entries
|
||||
.map((e, i) => ({ e, i }))
|
||||
.filter(({ e }) => e.type === "message" && e.message.role === "user")
|
||||
.map(({ e, i }) => ({ index: i, text: e.message.content.slice(0, 50) }));
|
||||
|
||||
if (!turns.length) return { status: "No turns to pop" };
|
||||
|
||||
// 2. User selects
|
||||
const selected = await ctx.ui.select("Pop to:", turns.map(t => t.text));
|
||||
if (!selected) return;
|
||||
const backTo = turns.find(t => t.text === selected)!.index;
|
||||
|
||||
// 3. Summarize entries from backTo to now
|
||||
const toSummarize = ctx.entries.slice(backTo)
|
||||
.filter(e => e.type === "message")
|
||||
.map(e => e.message);
|
||||
const summary = await generateSummary(toSummarize, ctx);
|
||||
|
||||
// 4. Save custom entry
|
||||
await ctx.saveEntry({
|
||||
type: "stack_pop",
|
||||
backToIndex: backTo,
|
||||
summary,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
// 5. Rebuild
|
||||
await ctx.rebuildContext();
|
||||
return { status: "Popped stack" };
|
||||
}
|
||||
});
|
||||
|
||||
// Context transform: apply stack pops
|
||||
pi.on("context", (event, ctx) => {
|
||||
const pops = event.entries.filter(e => e.type === "stack_pop");
|
||||
if (!pops.length) return; // use default
|
||||
|
||||
// Build exclusion set
|
||||
const excluded = new Set<number>();
|
||||
const summaryAt = new Map<number, string>();
|
||||
|
||||
for (const pop of pops) {
|
||||
const popIdx = event.entries.indexOf(pop);
|
||||
for (let i = pop.backToIndex; i <= popIdx; i++) excluded.add(i);
|
||||
summaryAt.set(pop.backToIndex, pop.summary);
|
||||
}
|
||||
|
||||
// Build filtered messages
|
||||
const messages: AppMessage[] = [];
|
||||
for (let i = 0; i < event.entries.length; i++) {
|
||||
if (excluded.has(i)) continue;
|
||||
|
||||
if (summaryAt.has(i)) {
|
||||
messages.push({
|
||||
role: "user",
|
||||
content: `[Subtask completed]\n\n${summaryAt.get(i)}`,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
}
|
||||
|
||||
const e = event.entries[i];
|
||||
if (e.type === "message") messages.push(e.message);
|
||||
}
|
||||
|
||||
return { messages };
|
||||
});
|
||||
}
|
||||
|
||||
async function generateSummary(messages, ctx) {
|
||||
const apiKey = await ctx.resolveApiKey(ctx.model);
|
||||
// Call LLM for summary...
|
||||
}
|
||||
```
|
||||
|
||||
## Core Changes Required
|
||||
|
||||
### session-manager.ts
|
||||
|
||||
```typescript
|
||||
// Allow saving arbitrary entries
|
||||
saveEntry(entry: { type: string; [k: string]: unknown }): void {
|
||||
if (!entry.type) throw new Error("Entry must have type");
|
||||
this.inMemoryEntries.push(entry);
|
||||
this._persist(entry);
|
||||
}
|
||||
|
||||
// buildSessionContext ignores unknown types (existing behavior works)
|
||||
```
|
||||
|
||||
### hooks/types.ts
|
||||
|
||||
```typescript
|
||||
// New event
|
||||
interface ContextEvent {
|
||||
type: "context";
|
||||
entries: readonly SessionEntry[];
|
||||
messages: AppMessage[];
|
||||
}
|
||||
|
||||
// Extended base context (see Unified Context above)
|
||||
|
||||
// Command types
|
||||
interface CommandOptions {
|
||||
description?: string;
|
||||
handler: (ctx: CommandContext) => Promise<CommandResult | void>;
|
||||
}
|
||||
|
||||
type CommandResult =
|
||||
| string
|
||||
| { prompt: string; attachments?: Attachment[] }
|
||||
| { status: string };
|
||||
```
|
||||
|
||||
### hooks/loader.ts
|
||||
|
||||
```typescript
|
||||
// Track registered commands
|
||||
interface LoadedHook {
|
||||
path: string;
|
||||
handlers: Map<string, Handler[]>;
|
||||
commands: Map<string, CommandOptions>; // NEW
|
||||
}
|
||||
|
||||
// createHookAPI adds command() method
|
||||
```
|
||||
|
||||
### hooks/runner.ts
|
||||
|
||||
```typescript
|
||||
class HookRunner {
|
||||
// State callbacks (set by AgentSession)
|
||||
setStateCallbacks(cb: StateCallbacks): void;
|
||||
|
||||
// Command invocation
|
||||
getCommands(): Map<string, CommandOptions>;
|
||||
invokeCommand(name: string, argsRaw: string): Promise<CommandResult | void>;
|
||||
|
||||
// Context event with chaining
|
||||
async emitContext(entries, messages): Promise<AppMessage[]> {
|
||||
let result = messages;
|
||||
for (const hook of this.hooks) {
|
||||
const handlers = hook.handlers.get("context");
|
||||
for (const h of handlers ?? []) {
|
||||
const out = await h({ entries, messages: result }, this.createContext());
|
||||
if (out?.messages) result = out.messages;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### agent-session.ts
|
||||
|
||||
```typescript
|
||||
// Expose saveEntry
|
||||
async saveEntry(entry): Promise<void> {
|
||||
this.sessionManager.saveEntry(entry);
|
||||
}
|
||||
|
||||
// Rebuild context
|
||||
async rebuildContext(): Promise<void> {
|
||||
const base = this.sessionManager.buildSessionContext();
|
||||
const entries = this.sessionManager.getEntries();
|
||||
const messages = await this._hookRunner.emitContext(entries, base.messages);
|
||||
this.agent.replaceMessages(messages);
|
||||
}
|
||||
|
||||
// Fire context event during normal context building too
|
||||
```
|
||||
|
||||
### interactive-mode.ts
|
||||
|
||||
```typescript
|
||||
// In setupEditorSubmitHandler, check hook commands
|
||||
const commands = this.session.hookRunner?.getCommands();
|
||||
if (commands?.has(commandName)) {
|
||||
const result = await this.session.invokeCommand(commandName, argsRaw);
|
||||
// Handle result...
|
||||
return;
|
||||
}
|
||||
|
||||
// Add hook commands to autocomplete
|
||||
```
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. **Mutation in all handlers or commands only?**
|
||||
- `saveEntry`/`rebuildContext` in all handlers = more power, more footguns
|
||||
- Commands only = safer, but limits hook creativity
|
||||
- Recommendation: start with commands only
|
||||
|
||||
2. **Context event timing**
|
||||
- Fire on every prompt? Or only when explicitly rebuilt?
|
||||
- Need to fire on session load too
|
||||
- Recommendation: fire whenever agent.replaceMessages is called
|
||||
|
||||
3. **Compaction interaction**
|
||||
- Core compaction runs first, then `context` event
|
||||
- Hooks can post-process compacted output
|
||||
- Future: compaction itself could become a replaceable hook
|
||||
|
||||
4. **Multiple context handlers**
|
||||
- Chain in load order (global → project)
|
||||
- Each sees previous output
|
||||
- No explicit priority system (KISS)
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@mariozechner/pi-coding-agent",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
||||
"type": "module",
|
||||
"piConfig": {
|
||||
|
|
@ -39,9 +39,9 @@
|
|||
"prepublishOnly": "npm run clean && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mariozechner/pi-agent-core": "^0.27.7",
|
||||
"@mariozechner/pi-ai": "^0.27.7",
|
||||
"@mariozechner/pi-tui": "^0.27.7",
|
||||
"@mariozechner/pi-agent-core": "^0.27.8",
|
||||
"@mariozechner/pi-ai": "^0.27.8",
|
||||
"@mariozechner/pi-tui": "^0.27.8",
|
||||
"chalk": "^5.5.0",
|
||||
"cli-highlight": "^2.1.11",
|
||||
"diff": "^8.0.2",
|
||||
|
|
|
|||
|
|
@ -328,21 +328,25 @@ export function discoverSlashCommands(cwd?: string, agentDir?: string): FileSlas
|
|||
|
||||
/**
|
||||
* Create the default API key resolver.
|
||||
* Priority: settings.json apiKeys > custom providers (models.json) > OAuth > environment variables.
|
||||
* Priority: OAuth > custom providers (models.json) > environment variables > settings.json apiKeys.
|
||||
*
|
||||
* OAuth takes priority so users logged in with a plan (e.g. unlimited tokens) aren't
|
||||
* accidentally billed via a PAYG API key sitting in settings.json.
|
||||
*/
|
||||
export function defaultGetApiKey(
|
||||
settingsManager?: SettingsManager,
|
||||
): (model: Model<any>) => Promise<string | undefined> {
|
||||
return async (model: Model<any>) => {
|
||||
// Check settings.json apiKeys first
|
||||
if (settingsManager) {
|
||||
const settingsKey = settingsManager.getApiKey(model.provider);
|
||||
if (settingsKey) {
|
||||
return settingsKey;
|
||||
}
|
||||
// Check OAuth, custom providers, env vars first
|
||||
const resolvedKey = await getApiKeyForModel(model);
|
||||
if (resolvedKey) {
|
||||
return resolvedKey;
|
||||
}
|
||||
// Fall back to existing resolution (custom providers, OAuth, env vars)
|
||||
return getApiKeyForModel(model);
|
||||
// Fall back to settings.json apiKeys
|
||||
if (settingsManager) {
|
||||
return settingsManager.getApiKey(model.provider);
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@mariozechner/pi-mom",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"description": "Slack bot that delegates messages to the pi coding agent",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
|
@ -21,9 +21,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sandbox-runtime": "^0.0.16",
|
||||
"@mariozechner/pi-agent-core": "^0.27.7",
|
||||
"@mariozechner/pi-ai": "^0.27.7",
|
||||
"@mariozechner/pi-coding-agent": "^0.27.7",
|
||||
"@mariozechner/pi-agent-core": "^0.27.8",
|
||||
"@mariozechner/pi-ai": "^0.27.8",
|
||||
"@mariozechner/pi-coding-agent": "^0.27.8",
|
||||
"@sinclair/typebox": "^0.34.0",
|
||||
"@slack/socket-mode": "^2.0.0",
|
||||
"@slack/web-api": "^7.0.0",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@mariozechner/pi",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"description": "CLI tool for managing vLLM deployments on GPU pods",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
"node": ">=20.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mariozechner/pi-agent-core": "^0.27.7",
|
||||
"@mariozechner/pi-agent-core": "^0.27.8",
|
||||
"chalk": "^5.5.0"
|
||||
},
|
||||
"devDependencies": {}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@mariozechner/pi-proxy",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"type": "module",
|
||||
"description": "CORS and authentication proxy for pi-ai",
|
||||
"main": "dist/index.js",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@mariozechner/pi-tui",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "pi-web-ui-example",
|
||||
"version": "1.15.7",
|
||||
"version": "1.15.8",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@mariozechner/pi-web-ui",
|
||||
"version": "0.27.7",
|
||||
"version": "0.27.8",
|
||||
"description": "Reusable web UI components for AI chat interfaces powered by @mariozechner/pi-ai",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@lmstudio/sdk": "^1.5.0",
|
||||
"@mariozechner/pi-ai": "^0.27.7",
|
||||
"@mariozechner/pi-tui": "^0.27.7",
|
||||
"@mariozechner/pi-ai": "^0.27.8",
|
||||
"@mariozechner/pi-tui": "^0.27.8",
|
||||
"docx-preview": "^0.3.7",
|
||||
"jszip": "^3.10.1",
|
||||
"lucide": "^0.544.0",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue