@songsid/agend 2.1.0-beta.44 → 2.1.0-beta.46
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/dist/fleet-context.d.ts
CHANGED
|
@@ -75,4 +75,10 @@ export interface FleetContext {
|
|
|
75
75
|
lastError?: string;
|
|
76
76
|
}>;
|
|
77
77
|
getInstanceExecutionState?(name: string): "idle" | "working" | "stuck" | "paused" | null;
|
|
78
|
+
/**
|
|
79
|
+
* Show a model-selection inline keyboard for the given instance in a TG topic.
|
|
80
|
+
* Returns a fallback text message if no model list is available (caller should send it).
|
|
81
|
+
* Returns null if the menu was shown successfully.
|
|
82
|
+
*/
|
|
83
|
+
promptModelMenu?(instanceName: string, userId: string, channelId: string, adapter: import("./channel/types.js").ChannelAdapter, chatId: string, threadId?: string): Promise<string | null>;
|
|
78
84
|
}
|
package/dist/fleet-manager.d.ts
CHANGED
|
@@ -379,6 +379,12 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
379
379
|
private getModelOptions;
|
|
380
380
|
/** `/model` slash handler (admin only). No arg → DC menu; `/model <name>` → apply directly. */
|
|
381
381
|
private handleModelSlash;
|
|
382
|
+
/**
|
|
383
|
+
* Show a TG inline-keyboard model-selection menu. Reuses the same
|
|
384
|
+
* pendingModelSelects coordinator as the DC Select Menu path.
|
|
385
|
+
* Returns null on success (menu shown), or a fallback string to send.
|
|
386
|
+
*/
|
|
387
|
+
promptModelMenu(instanceName: string, userId: string, channelId: string, adapter: ChannelAdapter, chatId: string, threadId?: string): Promise<string | null>;
|
|
382
388
|
/** Consume a `/model` selection callback. Returns true for all model-select ids (incl. stale). */
|
|
383
389
|
private handleModelSelection;
|
|
384
390
|
/** Apply a model to an instance: runtime paste (claude-code) or persist + restart (others). */
|
package/dist/fleet-manager.js
CHANGED
|
@@ -4317,6 +4317,45 @@ When users create specialized instances, suggest these configurations:
|
|
|
4317
4317
|
await data.respond("Usage: /model <name> — e.g. /model sonnet");
|
|
4318
4318
|
}
|
|
4319
4319
|
}
|
|
4320
|
+
/**
|
|
4321
|
+
* Show a TG inline-keyboard model-selection menu. Reuses the same
|
|
4322
|
+
* pendingModelSelects coordinator as the DC Select Menu path.
|
|
4323
|
+
* Returns null on success (menu shown), or a fallback string to send.
|
|
4324
|
+
*/
|
|
4325
|
+
async promptModelMenu(instanceName, userId, channelId, adapter, chatId, threadId) {
|
|
4326
|
+
const options = await this.getModelOptions(instanceName);
|
|
4327
|
+
if (options.length === 0) {
|
|
4328
|
+
return `No model list available for ${instanceName}. Use \`/model <name>\` to set one directly.`;
|
|
4329
|
+
}
|
|
4330
|
+
const nonce = randomBytes(6).toString("hex");
|
|
4331
|
+
const choices = options.slice(0, 25).map(o => ({
|
|
4332
|
+
id: `${MODEL_SELECT_CALLBACK_PREFIX}${nonce}:${o.id}`,
|
|
4333
|
+
label: o.description ? `${o.label} — ${o.description}` : o.label,
|
|
4334
|
+
}));
|
|
4335
|
+
const respond = async (text) => {
|
|
4336
|
+
await adapter.sendText(chatId, text, { threadId });
|
|
4337
|
+
return undefined;
|
|
4338
|
+
};
|
|
4339
|
+
const timer = setTimeout(() => {
|
|
4340
|
+
const p = this.pendingModelSelects.get(nonce);
|
|
4341
|
+
if (p) {
|
|
4342
|
+
this.pendingModelSelects.delete(nonce);
|
|
4343
|
+
p.respond("⏰ Model selection expired.").catch(() => { });
|
|
4344
|
+
}
|
|
4345
|
+
}, CLASSIC_BACKEND_SELECTION_TIMEOUT_MS);
|
|
4346
|
+
timer.unref?.();
|
|
4347
|
+
this.pendingModelSelects.set(nonce, { instanceName, model: "", userId, channelId, timer, respond, adapter, adapterChatId: chatId, adapterThreadId: threadId });
|
|
4348
|
+
try {
|
|
4349
|
+
await adapter.promptUser(chatId, `Choose a model for ${instanceName}:`, choices, { threadId });
|
|
4350
|
+
return null; // menu shown
|
|
4351
|
+
}
|
|
4352
|
+
catch (err) {
|
|
4353
|
+
this.pendingModelSelects.delete(nonce);
|
|
4354
|
+
clearTimeout(timer);
|
|
4355
|
+
this.logger.warn({ err, instanceName }, "TG model menu failed");
|
|
4356
|
+
return `Usage: /model <name> — e.g. /model sonnet`;
|
|
4357
|
+
}
|
|
4358
|
+
}
|
|
4320
4359
|
/** Consume a `/model` selection callback. Returns true for all model-select ids (incl. stale). */
|
|
4321
4360
|
async handleModelSelection(data) {
|
|
4322
4361
|
if (!data.callbackData.startsWith(MODEL_SELECT_CALLBACK_PREFIX))
|
|
@@ -4335,8 +4374,39 @@ When users create specialized instances, suggest these configurations:
|
|
|
4335
4374
|
return true;
|
|
4336
4375
|
this.pendingModelSelects.delete(match[1]);
|
|
4337
4376
|
clearTimeout(pending.timer);
|
|
4338
|
-
const
|
|
4339
|
-
|
|
4377
|
+
const model = match[2];
|
|
4378
|
+
// Send immediate "⏳ Switching..." feedback, then apply in background.
|
|
4379
|
+
const progressText = `⏳ Switching ${pending.instanceName} to \`${model}\`…`;
|
|
4380
|
+
let progressMsgId;
|
|
4381
|
+
if (pending.adapter && pending.adapterChatId) {
|
|
4382
|
+
// TG path: send a new message and capture messageId for later edit
|
|
4383
|
+
try {
|
|
4384
|
+
const sent = await pending.adapter.sendText(pending.adapterChatId, progressText, { threadId: pending.adapterThreadId });
|
|
4385
|
+
progressMsgId = sent.messageId;
|
|
4386
|
+
}
|
|
4387
|
+
catch { /* non-fatal */ }
|
|
4388
|
+
}
|
|
4389
|
+
else {
|
|
4390
|
+
// DC path: respond immediately with progress text
|
|
4391
|
+
await pending.respond(progressText).catch(() => { });
|
|
4392
|
+
}
|
|
4393
|
+
// Apply model in background — don't await here (keeps callback handler fast)
|
|
4394
|
+
void (async () => {
|
|
4395
|
+
const result = await this.applyModel(pending.instanceName, model);
|
|
4396
|
+
if (pending.adapter && pending.adapterChatId) {
|
|
4397
|
+
if (progressMsgId) {
|
|
4398
|
+
pending.adapter.editMessage(pending.adapterChatId, progressMsgId, result, pending.adapterThreadId).catch(() => {
|
|
4399
|
+
pending.adapter.sendText(pending.adapterChatId, result, { threadId: pending.adapterThreadId }).catch(() => { });
|
|
4400
|
+
});
|
|
4401
|
+
}
|
|
4402
|
+
else {
|
|
4403
|
+
pending.adapter.sendText(pending.adapterChatId, result, { threadId: pending.adapterThreadId }).catch(() => { });
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4406
|
+
else {
|
|
4407
|
+
await pending.respond(result).catch(() => { });
|
|
4408
|
+
}
|
|
4409
|
+
})();
|
|
4340
4410
|
return true;
|
|
4341
4411
|
}
|
|
4342
4412
|
/** Apply a model to an instance: runtime paste (claude-code) or persist + restart (others). */
|