@friendlyrobot/discord-pi-agent 0.5.8 → 0.5.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.
@@ -24,6 +24,9 @@ export declare class AgentService {
24
24
  private requireSession;
25
25
  private applyConfiguredThinkingLevel;
26
26
  private applyConfiguredThinkingLevelForSession;
27
+ listModels(): Promise<string>;
28
+ switchModel(provider: string, modelId: string): Promise<string>;
29
+ getCurrentModelDisplay(): string;
27
30
  getThinkingLevel(): {
28
31
  current: ThinkingLevel;
29
32
  available: ThinkingLevel[];
package/dist/index.js CHANGED
@@ -361,6 +361,51 @@ class AgentService {
361
361
  }
362
362
  }
363
363
  }
364
+ async listModels() {
365
+ const availableModels = await this.modelRegistry.getAvailable();
366
+ const session = this.session;
367
+ const currentDisplay = session?.model ? `${session.model.provider}/${session.model.id}` : null;
368
+ const lines = availableModels.map((model) => {
369
+ const display = `${model.provider}/${model.id}`;
370
+ const marker = currentDisplay === display ? " (current)" : "";
371
+ return ` ${display}${marker}`;
372
+ });
373
+ return [
374
+ `Available models (${availableModels.length}):`,
375
+ ...lines,
376
+ `
377
+ Usage: !model <provider/modelId> to switch.`
378
+ ].join(`
379
+ `);
380
+ }
381
+ async switchModel(provider, modelId) {
382
+ const session = this.requireSession();
383
+ const model = this.modelRegistry.find(provider, modelId);
384
+ if (!model) {
385
+ const availableModels = await this.modelRegistry.getAvailable();
386
+ const matches = availableModels.filter((m) => {
387
+ return m.provider === provider;
388
+ }).map((m) => `${m.provider}/${m.id}`);
389
+ const hint = matches.length > 0 ? `
390
+ Models from "${provider}": ${matches.join(", ")}` : `
391
+ Use !model to see all available models.`;
392
+ return `Model not found: ${provider}/${modelId}.${hint}`;
393
+ }
394
+ if (isSameModel(session.model, model)) {
395
+ return `Already using ${provider}/${modelId}.`;
396
+ }
397
+ await session.setModel(model);
398
+ await this.applyConfiguredThinkingLevelForSession(session);
399
+ const thinkingInfo = session.supportsThinking() ? ` (thinking: ${session.thinkingLevel})` : "";
400
+ return `Switched to ${provider}/${modelId}${thinkingInfo}.`;
401
+ }
402
+ getCurrentModelDisplay() {
403
+ const session = this.session;
404
+ if (!session?.model) {
405
+ return "(no model selected)";
406
+ }
407
+ return `${session.model.provider}/${session.model.id}`;
408
+ }
364
409
  getThinkingLevel() {
365
410
  const session = this.requireSession();
366
411
  if (!session.supportsThinking()) {
@@ -558,6 +603,7 @@ async function handleCommand(input, ctx) {
558
603
  "!help - show this message",
559
604
  "!status - show current session status",
560
605
  "!thinking - show or set thinking/reasoning level",
606
+ "!model - list available models or switch to one",
561
607
  "!compact - compact the persistent session",
562
608
  "!reset-session - start a fresh persistent session",
563
609
  "!reload - reload resources (AGENTS.md, extensions, skills, etc.)",
@@ -640,6 +686,42 @@ async function handleCommand(input, ctx) {
640
686
  response: `Thinking level set to "${requestedLevel}".`
641
687
  };
642
688
  }
689
+ if (trimmed === "!model" || trimmed.startsWith("!model ")) {
690
+ const effectiveSession = session ?? agentService.getSession();
691
+ if (!effectiveSession) {
692
+ return {
693
+ handled: true,
694
+ response: "No active session."
695
+ };
696
+ }
697
+ const parts = trimmed.split(" ");
698
+ if (parts.length === 1) {
699
+ const current = agentService.getCurrentModelDisplay();
700
+ const modelList = await agentService.listModels();
701
+ return {
702
+ handled: true,
703
+ response: `Current model: ${current}
704
+
705
+ ${modelList}`
706
+ };
707
+ }
708
+ const arg = parts.slice(1).join(" ");
709
+ const slashIndex = arg.indexOf("/");
710
+ if (slashIndex === -1) {
711
+ return {
712
+ handled: true,
713
+ response: `Usage: !model <provider/modelId>
714
+ Example: !model openrouter/anthropic/claude-sonnet-4
715
+ Use !model without args to see available models.`
716
+ };
717
+ }
718
+ const provider = arg.substring(0, slashIndex);
719
+ const modelId = arg.substring(slashIndex + 1);
720
+ return {
721
+ handled: true,
722
+ response: await agentService.switchModel(provider, modelId)
723
+ };
724
+ }
643
725
  if (trimmed === "!compact") {
644
726
  const effectiveSession = session ?? agentService.getSession();
645
727
  if (!effectiveSession) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@friendlyrobot/discord-pi-agent",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "Reusable Discord gateway bridge for persistent pi agent sessions",
5
5
  "license": "MIT",
6
6
  "type": "module",