@fickydev/pigent 0.1.8 → 0.1.9
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/CHANGELOG.md +1 -0
- package/PLAN.md +2 -2
- package/TODO.md +2 -1
- package/package.json +1 -1
- package/pigent.yaml +2 -1
- package/src/agents/BotCommandHandler.ts +18 -8
- package/src/pi/PiAvailableModels.ts +23 -0
package/CHANGELOG.md
CHANGED
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
- Added session-scoped model and thinking level overrides with `/model` and `/thinking` Telegram commands.
|
|
46
46
|
- Planned Telegram inline-button model and thinking level pickers backed by configured model choices.
|
|
47
47
|
- Added Telegram inline-button pickers for `/model` and `/thinking`, callback handling, and bot command menu registration.
|
|
48
|
+
- Changed `/model` picker to use Pi's currently available models automatically when explicit `modelChoices` are not configured.
|
|
48
49
|
- Kept daemon process alive after startup so CLI runs do not exit after `pigent ready`.
|
|
49
50
|
|
|
50
51
|
### Changed
|
package/PLAN.md
CHANGED
|
@@ -214,7 +214,7 @@ Telegram should also provide inline-button pickers so non-technical users can ch
|
|
|
214
214
|
- after selection, bot should answer the callback and update or send a confirmation message
|
|
215
215
|
- daemon startup should register Telegram bot commands through `setMyCommands` so users see Pigent commands in the Telegram command menu
|
|
216
216
|
|
|
217
|
-
Model choices
|
|
217
|
+
Model choices default to Pi's currently available models from `ModelRegistry.getAvailable()`. Operators may optionally configure explicit choices to curate or rename the button list:
|
|
218
218
|
|
|
219
219
|
```yaml
|
|
220
220
|
modelChoices:
|
|
@@ -226,7 +226,7 @@ modelChoices:
|
|
|
226
226
|
label: GPT-4.1
|
|
227
227
|
```
|
|
228
228
|
|
|
229
|
-
The command and callback handlers should validate agent access and model availability through a Pi model resolver. They must not reveal API keys, auth values, raw environment variables, or provider secrets.
|
|
229
|
+
The command and callback handlers should validate agent access and model availability through a Pi model resolver. They must not reveal API keys, auth values, raw environment variables, or provider secrets. The available-model fallback should use Pi auth presence checks only and never print secret values.
|
|
230
230
|
|
|
231
231
|
## Prompt Composition
|
|
232
232
|
|
package/TODO.md
CHANGED
|
@@ -184,9 +184,10 @@
|
|
|
184
184
|
- [x] `/thinking` show thinking level for default chat agent session
|
|
185
185
|
- [x] `/thinking <level>` set thinking level for default chat agent session
|
|
186
186
|
- [x] `/thinking default` clear thinking level for default chat agent session
|
|
187
|
-
- [x] `/model` inline button picker for
|
|
187
|
+
- [x] `/model` inline button picker for currently available Pi models
|
|
188
188
|
- [x] `/thinking` inline button picker
|
|
189
189
|
- [x] Handle model picker callback and persist selected session model
|
|
190
|
+
- [x] Fallback to Pi `ModelRegistry.getAvailable()` when `modelChoices` is empty
|
|
190
191
|
- [x] Handle thinking picker callback and persist selected session thinking level
|
|
191
192
|
- [x] Add `Use default` model/thinking buttons
|
|
192
193
|
- [ ] `/model <agentId> <provider/modelId>` set model for an explicit agent session
|
package/package.json
CHANGED
package/pigent.yaml
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
telegramChats: []
|
|
2
2
|
modelChoices: []
|
|
3
3
|
|
|
4
|
-
#
|
|
4
|
+
# Optional. If empty, /model uses Pi's currently available models automatically.
|
|
5
|
+
# Add choices to curate or rename buttons for /model.
|
|
5
6
|
#
|
|
6
7
|
# modelChoices:
|
|
7
8
|
# - id: anthropic/claude-sonnet-4-5
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { InboundMessage, InlineKeyboardButton } from "../channels/types";
|
|
2
2
|
import type { ModelChoiceConfig } from "../config/schemas";
|
|
3
3
|
import type { Repositories } from "../db/repositories";
|
|
4
|
+
import { getAvailableModelChoices } from "../pi/PiAvailableModels";
|
|
4
5
|
import { isValidModelRef } from "../pi/PiModelResolver";
|
|
5
6
|
import type { AgentRegistry } from "./AgentRegistry";
|
|
6
7
|
|
|
@@ -96,16 +97,18 @@ export class BotCommandHandler {
|
|
|
96
97
|
const value = args.join(" ").trim();
|
|
97
98
|
|
|
98
99
|
if (!value) {
|
|
100
|
+
const choices = await this.loadModelChoices();
|
|
101
|
+
|
|
99
102
|
return {
|
|
100
103
|
handled: true,
|
|
101
104
|
text: [
|
|
102
105
|
`Agent: ${sessionResult.agentId}`,
|
|
103
106
|
`Session model: ${sessionResult.session.model ?? "default"}`,
|
|
104
|
-
|
|
107
|
+
choices.length > 0
|
|
105
108
|
? "Choose a model:"
|
|
106
|
-
: "No
|
|
109
|
+
: "No available Pi models found. Configure provider auth or use /model <provider/modelId> manually.",
|
|
107
110
|
].join("\n"),
|
|
108
|
-
inlineKeyboard:
|
|
111
|
+
inlineKeyboard: choices.length > 0 ? this.modelKeyboard(choices) : undefined,
|
|
109
112
|
};
|
|
110
113
|
}
|
|
111
114
|
|
|
@@ -156,12 +159,13 @@ export class BotCommandHandler {
|
|
|
156
159
|
const sessionResult = await this.getDefaultSession(message);
|
|
157
160
|
if (!sessionResult.ok) return sessionResult.message;
|
|
158
161
|
|
|
162
|
+
const choices = await this.loadModelChoices();
|
|
159
163
|
const choiceIndex = Number(message.text.slice("/model:set:".length));
|
|
160
|
-
if (!Number.isSafeInteger(choiceIndex) || choiceIndex < 0 || choiceIndex >=
|
|
164
|
+
if (!Number.isSafeInteger(choiceIndex) || choiceIndex < 0 || choiceIndex >= choices.length) {
|
|
161
165
|
return "Unknown model choice.";
|
|
162
166
|
}
|
|
163
167
|
|
|
164
|
-
const choice =
|
|
168
|
+
const choice = choices[choiceIndex];
|
|
165
169
|
const session = await this.repositories.sessions.updateModel(sessionResult.session.id, choice.id);
|
|
166
170
|
return `Session model for ${session.agentId} set to ${choice.label} (${session.model}).`;
|
|
167
171
|
}
|
|
@@ -195,13 +199,19 @@ export class BotCommandHandler {
|
|
|
195
199
|
return `Session thinking level cleared for ${session.agentId}. Current: ${session.thinkingLevel ?? "default"}`;
|
|
196
200
|
}
|
|
197
201
|
|
|
198
|
-
private
|
|
202
|
+
private async loadModelChoices(): Promise<ModelChoiceConfig[]> {
|
|
203
|
+
if (this.modelChoices.length > 0) return this.modelChoices;
|
|
204
|
+
|
|
205
|
+
return getAvailableModelChoices();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private modelKeyboard(choices: ModelChoiceConfig[]): InlineKeyboardButton[][] {
|
|
199
209
|
const rows = chunk(
|
|
200
|
-
|
|
210
|
+
choices.map((choice, index) => ({
|
|
201
211
|
text: choice.label,
|
|
202
212
|
callbackData: `model:set:${index}`,
|
|
203
213
|
})),
|
|
204
|
-
|
|
214
|
+
1,
|
|
205
215
|
);
|
|
206
216
|
|
|
207
217
|
rows.push([{ text: "Use default", callbackData: "model:default" }]);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { Model } from "@earendil-works/pi-ai";
|
|
3
|
+
|
|
4
|
+
export type AvailableModelChoice = {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export async function getAvailableModelChoices(): Promise<AvailableModelChoice[]> {
|
|
10
|
+
const authStorage = AuthStorage.create();
|
|
11
|
+
const modelRegistry = ModelRegistry.create(authStorage);
|
|
12
|
+
const models = await modelRegistry.getAvailable();
|
|
13
|
+
|
|
14
|
+
return models.map(toChoice).sort((a, b) => a.label.localeCompare(b.label));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function toChoice(model: Model<any>): AvailableModelChoice {
|
|
18
|
+
const modelWithName = model as Model<any> & { name?: string };
|
|
19
|
+
const id = `${model.provider}/${model.id}`;
|
|
20
|
+
const label = modelWithName.name ? `${modelWithName.name} (${id})` : id;
|
|
21
|
+
|
|
22
|
+
return { id, label };
|
|
23
|
+
}
|