@sns-myagent/cli 0.3.7 → 0.3.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +63 -24
  3. package/bin/snsagent.js +3 -41
  4. package/dist/cli.js +3267 -3288
  5. package/package.json +3 -3
  6. package/src/adapters/telegram/handler.ts +1 -1
  7. package/src/agents/ensemble.ts +3 -4
  8. package/src/agents/executor.ts +129 -0
  9. package/src/async/notifier.ts +1 -1
  10. package/src/cli/config-cli.ts +1 -1
  11. package/src/cli/entry.ts +2 -2
  12. package/src/cli/gallery-fixtures/misc.ts +3 -3
  13. package/src/cli/grep-cli.ts +3 -3
  14. package/src/cli/grievances-cli.ts +2 -2
  15. package/src/cli/index.ts +243 -24
  16. package/src/cli/plugin-cli.ts +5 -5
  17. package/src/cli/setup-cli.ts +3 -3
  18. package/src/cli/setup-model-picker.ts +1 -1
  19. package/src/cli/shell-cli.ts +1 -1
  20. package/src/cli/ssh-cli.ts +1 -1
  21. package/src/cli/stats-cli.ts +1 -1
  22. package/src/cli/tiny-models-cli.ts +3 -3
  23. package/src/cli/ttsr-cli.ts +2 -2
  24. package/src/cli/update-cli.ts +3 -3
  25. package/src/cli/usage-cli.ts +1 -1
  26. package/src/cli-commands.ts +6 -6
  27. package/src/commands/acp.ts +2 -2
  28. package/src/commands/chat.ts +3 -3
  29. package/src/commands/install.ts +5 -5
  30. package/src/commands/say.ts +4 -4
  31. package/src/commands/setup.ts +1 -1
  32. package/src/config/defaults.ts +5 -3
  33. package/src/config/schema.ts +8 -0
  34. package/src/config/settings-schema.ts +1 -1
  35. package/src/config/sns-config.ts +1 -1
  36. package/src/extensibility/plugins/loader.ts +1 -1
  37. package/src/extensibility/plugins/manager.ts +2 -2
  38. package/src/hindsight/client.ts +1 -1
  39. package/src/internal-urls/docs-index.generated.txt +2 -0
  40. package/src/main.ts +4 -0
  41. package/src/modes/acp/acp-agent.ts +3 -3
  42. package/src/modes/components/plugin-settings.ts +2 -2
  43. package/src/modes/components/welcome.ts +66 -160
  44. package/src/modes/interactive-mode.ts +2 -2
  45. package/src/modes/print-mode.ts +2 -2
  46. package/src/modes/setup-version.ts +1 -1
  47. package/src/modes/setup-wizard/scenes/byok-setup.ts +354 -0
  48. package/src/modes/setup-wizard/scenes/outro.ts +2 -2
  49. package/src/modes/setup-wizard/scenes/providers.ts +6 -5
  50. package/src/modes/setup-wizard/scenes/splash.ts +3 -3
  51. package/src/modes/setup-wizard/wizard-overlay.ts +2 -2
  52. package/src/modes/theme/dark.json +21 -20
  53. package/src/modes/theme/light.json +30 -29
  54. package/src/modes/utils/ui-helpers.ts +1 -1
  55. package/src/slash-commands/builtin-registry.ts +6 -3
  56. package/src/stt/recorder.ts +3 -3
  57. package/src/tts/player.ts +1 -1
  58. package/src/tts/tts-client.ts +1 -1
  59. package/src/tui/chat-blocks.ts +4 -4
  60. package/src/tui/chat-ui.ts +3 -3
  61. package/src/tui/code-cell.ts +3 -3
  62. package/src/tui/command-palette.ts +3 -3
  63. package/src/tui/splash.ts +12 -18
  64. package/src/ui/banner.ts +51 -66
  65. package/src/ui/chat-prompt.ts +2 -2
  66. package/src/ui/colors.ts +17 -14
  67. package/src/ui/error-display.ts +2 -2
  68. package/src/ui/gradient.ts +3 -3
  69. package/src/ui/memory-toast.ts +5 -5
  70. package/src/ui/status-bar.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Plugin CLI command handlers.
3
3
  *
4
- * Handles `omp plugin <command>` subcommands for plugin lifecycle management.
4
+ * Handles `snsagent plugin <command>` subcommands for plugin lifecycle management.
5
5
  */
6
6
 
7
7
  import { APP_NAME, getProjectDir } from "@oh-my-pi/pi-utils";
@@ -270,7 +270,7 @@ async function handleMarketplace(args: string[], _flags: PluginCommandArgs["flag
270
270
  }
271
271
  console.log(chalk.bold("Configured Marketplaces:\n"));
272
272
  for (const mp of marketplaces) {
273
- console.log(` ${chalk.cyan(mp.name)} ${chalk.dim(mp.sourceUri)}`);
273
+ console.log(` ${chalk.hex("#F97316")(mp.name)} ${chalk.dim(mp.sourceUri)}`);
274
274
  }
275
275
  } catch (err) {
276
276
  console.error(chalk.red(`${theme.status.error} Failed to list marketplaces: ${err}`));
@@ -294,7 +294,7 @@ async function handleDiscover(args: string[], _flags: PluginCommandArgs["flags"]
294
294
 
295
295
  console.log(chalk.bold(`Available Plugins${marketplace ? ` (${marketplace})` : ""}:\n`));
296
296
  for (const plugin of plugins) {
297
- console.log(` ${chalk.cyan(plugin.name)}${plugin.version ? `@${plugin.version}` : ""}`);
297
+ console.log(` ${chalk.hex("#F97316")(plugin.name)}${plugin.version ? `@${plugin.version}` : ""}`);
298
298
  if (plugin.description) {
299
299
  console.log(chalk.dim(` ${plugin.description}`));
300
300
  }
@@ -323,7 +323,7 @@ async function handleUpgrade(args: string[], flags: PluginCommandArgs["flags"]):
323
323
  if (flags.scope) {
324
324
  console.error(
325
325
  chalk.yellow(
326
- `Warning: --scope is ignored when upgrading all plugins. Use 'omp plugin upgrade <id> --scope ${flags.scope}' to target a specific plugin and scope.`,
326
+ `Warning: --scope is ignored when upgrading all plugins. Use 'snsagent plugin upgrade <id> --scope ${flags.scope}' to target a specific plugin and scope.`,
327
327
  ),
328
328
  );
329
329
  }
@@ -386,7 +386,7 @@ async function handleInstall(
386
386
  if (target.type === "local") {
387
387
  // Local paths route to link(): symlink the directory into the plugins
388
388
  // node_modules tree so source edits show up without a reinstall. Matches
389
- // `omp plugin link <path>` so users can use either verb interchangeably.
389
+ // `snsagent plugin link <path>` so users can use either verb interchangeably.
390
390
  if (flags.scope) {
391
391
  console.error(
392
392
  chalk.yellow(
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Setup CLI command handler.
3
3
  *
4
- * Handles `omp setup` for onboarding and `omp setup <component>` for optional dependencies.
4
+ * Handles `snsagent setup` for onboarding and `snsagent setup <component>` for optional dependencies.
5
5
  */
6
6
  import * as path from "node:path";
7
7
  import { $which, APP_NAME, getProjectDir, getPythonEnvDir } from "@oh-my-pi/pi-utils";
@@ -108,7 +108,7 @@ async function checkPythonSetup(): Promise<PythonCheckResult> {
108
108
  * Install Python packages using uv (preferred) or pip.
109
109
  */
110
110
  // Python installation helper removed: the subprocess runner has no Python
111
- // package dependencies beyond a working interpreter. `omp setup python --check`
111
+ // package dependencies beyond a working interpreter. `snsagent setup python --check`
112
112
  // remains as a probe; users install optional libs (pandas, matplotlib, ...)
113
113
  // directly via pip or the in-process `%pip` magic.
114
114
 
@@ -237,7 +237,7 @@ function buildSpeechComponents(): SpeechComponent[] {
237
237
  }
238
238
 
239
239
  /**
240
- * Unified `omp setup speech` flow. Drives every {@link SpeechComponent} through
240
+ * Unified `snsagent setup speech` flow. Drives every {@link SpeechComponent} through
241
241
  * one path: report (`--json`/`--check`) or install (interactive pick + ensure
242
242
  * with single-line progress; non-TTY skips pickers and installs configured
243
243
  * values).
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Standalone TUI model picker used by `omp setup speech`.
2
+ * Standalone TUI model picker used by `snsagent setup speech`.
3
3
  *
4
4
  * Mirrors {@link ./session-picker.ts} for the standalone-TUI lifecycle: spin up
5
5
  * a one-shot {@link TUI} over a {@link SelectList}, resolve on select/cancel, and
@@ -59,7 +59,7 @@ export async function runShellCommand(cmd: ShellCommandArgs): Promise<void> {
59
59
  let lastChar: string | null = null;
60
60
 
61
61
  const rl = createInterface({ input: process.stdin, output: process.stdout, terminal: true });
62
- const prompt = chalk.cyan(`${APP_NAME} shell> `);
62
+ const prompt = chalk.hex("#F97316")(`${APP_NAME} shell> `);
63
63
 
64
64
  const printHelp = () => {
65
65
  process.stdout.write(
@@ -169,7 +169,7 @@ async function handleList(cmd: SSHCommandArgs): Promise<void> {
169
169
 
170
170
  function printHosts(hosts: Record<string, SSHHostConfig>): void {
171
171
  for (const [name, config] of Object.entries(hosts)) {
172
- const parts = [chalk.cyan(name), config.host];
172
+ const parts = [chalk.hex("#F97316")(name), config.host];
173
173
  if (config.username) parts.push(chalk.dim(config.username));
174
174
  if (config.port && config.port !== 22) parts.push(chalk.dim(`port:${config.port}`));
175
175
  if (config.keyPath) parts.push(chalk.dim(config.keyPath));
@@ -30,7 +30,7 @@ function createSyncProgressReporter(): {
30
30
  lastRender = now;
31
31
  const label = chalk.dim(shortenSessionFile(event.sessionFile));
32
32
  const pct = ((event.current / event.total) * 100).toFixed(0).padStart(3, " ");
33
- const counter = chalk.cyan(`[${event.current}/${event.total}]`);
33
+ const counter = chalk.hex("#F97316")(`[${event.current}/${event.total}]`);
34
34
  const line = `${counter} ${pct}% ${label}`;
35
35
  const columns = stream.columns ?? 120;
36
36
  const trimmed = truncateToWidth(line, columns - 1);
@@ -56,8 +56,8 @@ function listModels(json: boolean | undefined): void {
56
56
  }
57
57
  writeLine(chalk.bold("Tiny local models"));
58
58
  for (const spec of TINY_LOCAL_MODELS) {
59
- const defaultMark = spec.key === DEFAULT_TINY_TITLE_LOCAL_MODEL_KEY ? chalk.cyan(" default") : "";
60
- writeLine(`${chalk.cyan(spec.key)}${defaultMark}`);
59
+ const defaultMark = spec.key === DEFAULT_TINY_TITLE_LOCAL_MODEL_KEY ? chalk.hex("#F97316")(" default") : "";
60
+ writeLine(`${chalk.hex("#F97316")(spec.key)}${defaultMark}`);
61
61
  writeLine(` ${spec.label} — ${spec.description}`);
62
62
  }
63
63
  }
@@ -81,7 +81,7 @@ function makeProgressReporter(modelKey: TinyLocalModelKey, json: boolean | undef
81
81
  const bytes = event.loaded && event.total ? ` ${formatBytes(event.loaded)}/${formatBytes(event.total)}` : "";
82
82
  const file = event.file ? ` ${event.file.split("/").at(-1) ?? event.file}` : "";
83
83
  const statusLabel = event.status === "ready" ? "Ready" : "Downloading";
84
- const line = `${chalk.cyan(statusLabel)} ${label} [${bar}] ${pct}${bytes}${file}`;
84
+ const line = `${chalk.hex("#F97316")(statusLabel)} ${label} [${bar}] ${pct}${bytes}${file}`;
85
85
  process.stdout.write(`\r${line.padEnd(lastWidth)}`);
86
86
  lastWidth = line.length;
87
87
  };
@@ -387,7 +387,7 @@ function renderTestReport(report: TestReport, verbose: boolean, isolated: boolea
387
387
  const ctxLabel = report.source === "tool" ? `tool:${report.tool ?? "?"}` : report.source;
388
388
  const pathLabel = report.filePath ? ` path=${report.filePath}` : "";
389
389
  process.stdout.write(
390
- `${chalk.bold("TTSR test")} — source=${chalk.cyan(ctxLabel)}${pathLabel} snippet=${chalk.dim(`${report.snippetBytes}b`)}\n`,
390
+ `${chalk.bold("TTSR test")} — source=${chalk.hex("#F97316")(ctxLabel)}${pathLabel} snippet=${chalk.dim(`${report.snippetBytes}b`)}\n`,
391
391
  );
392
392
  process.stdout.write(`${chalk.dim(` "${report.snippetPreview}"`)}\n\n`);
393
393
 
@@ -935,7 +935,7 @@ async function runScan(args: TtsrScanArgs, json: boolean, cwd: string): Promise<
935
935
  );
936
936
  } else {
937
937
  process.stdout.write(
938
- `${chalk.bold("TTSR scan")} — directory=${chalk.cyan(scanDir)} files=${chalk.dim(files.length)} scanned=${chalk.dim(scannedFiles)} rules=${chalk.dim(scanRulePlans.length)} gitignore=${chalk.dim(gitignore ? "on" : "off")} max-bytes=${chalk.dim(maxBytes === 0 ? "off" : String(maxBytes))}\n`,
938
+ `${chalk.bold("TTSR scan")} — directory=${chalk.hex("#F97316")(scanDir)} files=${chalk.dim(files.length)} scanned=${chalk.dim(scannedFiles)} rules=${chalk.dim(scanRulePlans.length)} gitignore=${chalk.dim(gitignore ? "on" : "off")} max-bytes=${chalk.dim(maxBytes === 0 ? "off" : String(maxBytes))}\n`,
939
939
  );
940
940
  if (countSkipped(skipped) > 0) {
941
941
  process.stdout.write(
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Update CLI command handler.
3
3
  *
4
- * Handles `omp update` to check for and install updates.
4
+ * Handles `snsagent update` to check for and install updates.
5
5
  * Uses the installer that owns the active omp executable when it can be detected.
6
6
  */
7
7
  import * as fs from "node:fs";
@@ -468,7 +468,7 @@ export async function replaceBinaryForUpdate(options: BinaryReplacementOptions):
468
468
  * - `--no-cache` tells bun to ignore its on-disk manifest snapshot so it
469
469
  * re-fetches metadata from that registry on every invocation.
470
470
  *
471
- * Together these two flags make `omp update` produce exactly the registry
471
+ * Together these two flags make `snsagent update` produce exactly the registry
472
472
  * lookup the version check just performed. See #1686.
473
473
  *
474
474
  * Also pins {@link NATIVES_PACKAGE} and the platform-specific
@@ -622,7 +622,7 @@ export async function runUpdateCommand(opts: { force: boolean; check: boolean })
622
622
  }
623
623
 
624
624
  if (comparison > 0) {
625
- console.log(chalk.cyan(`New version available: ${release.version}`));
625
+ console.log(chalk.hex("#F97316")(`New version available: ${release.version}`));
626
626
  } else {
627
627
  console.log(chalk.yellow(`Forcing reinstall of ${release.version}`));
628
628
  }
@@ -326,7 +326,7 @@ function formatAccountHeader(
326
326
  const planType = report.metadata?.planType;
327
327
  if (typeof planType === "string" && planType) header += chalk.dim(` · plan: ${planType}`);
328
328
  const savedResets = report.resetCredits?.availableCount ?? 0;
329
- if (savedResets > 0) header += chalk.cyan(` · ✦ ${savedResets} saved reset${savedResets === 1 ? "" : "s"}`);
329
+ if (savedResets > 0) header += chalk.hex("#F97316")(` · ✦ ${savedResets} saved reset${savedResets === 1 ? "" : "s"}`);
330
330
  if (report.fetchedAt && nowMs - report.fetchedAt > 90_000) {
331
331
  header += chalk.dim(` · fetched ${formatDuration(nowMs - report.fetchedAt)} ago`);
332
332
  }
@@ -47,24 +47,24 @@ export const commands: CommandEntry[] = [
47
47
  ];
48
48
 
49
49
  // Documented-looking plugin-management verbs that are NOT registered top-level
50
- // commands. Without a guard `resolveCliArgv` rewrites e.g. `omp list` to
51
- // `omp launch list`, silently forwarding the bare verb to the model as a prompt
50
+ // commands. Without a guard `resolveCliArgv` rewrites e.g. `snsagent list` to
51
+ // `snsagent launch list`, silently forwarding the bare verb to the model as a prompt
52
52
  // instead of managing plugins (#2935; same class as the `install` leak fixed in
53
53
  // #1496/#1498). A bare (single-arg) use gets a hint pointing at the real
54
- // `omp plugin <action>` command; multi-word invocations still fall through to
54
+ // `snsagent plugin <action>` command; multi-word invocations still fall through to
55
55
  // `launch`, so genuine prompts that merely begin with one of these words work.
56
56
  const RESERVED_TOP_LEVEL_WORDS = new Map<string, string>([
57
57
  [
58
58
  "extensions",
59
- '`omp extensions` is not a management command. Use `omp plugin list` / `omp plugin install`, or run `omp launch extensions` if you meant to send "extensions" as a prompt.',
59
+ '`snsagent extensions` is not a management command. Use `snsagent plugin list` / `snsagent plugin install`, or run `snsagent launch extensions` if you meant to send "extensions" as a prompt.',
60
60
  ],
61
61
  [
62
62
  "list",
63
- '`omp list` is not a top-level command. Use `omp plugin list` to list installed plugins, or run `omp launch list` if you meant to send "list" as a prompt.',
63
+ '`snsagent list` is not a top-level command. Use `snsagent plugin list` to list installed plugins, or run `snsagent launch list` if you meant to send "list" as a prompt.',
64
64
  ],
65
65
  [
66
66
  "remove",
67
- '`omp remove` is not a top-level command. Use `omp plugin uninstall <name>` to remove a plugin, or run `omp launch remove` if you meant to send "remove" as a prompt.',
67
+ '`snsagent remove` is not a top-level command. Use `snsagent plugin uninstall <name>` to remove a plugin, or run `snsagent launch remove` if you meant to send "remove" as a prompt.',
68
68
  ],
69
69
  ]);
70
70
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Run Oh My Pi as an ACP (Agent Client Protocol) server over stdio.
2
+ * Run snsagent as an ACP (Agent Client Protocol) server over stdio.
3
3
  *
4
4
  * Thin wrapper around the launch flow that forces `mode: "acp"` unless the
5
5
  * ACP terminal-auth flag asks the same command to open the interactive TUI.
@@ -10,7 +10,7 @@ import { runRootCommand } from "../main";
10
10
  import { prepareAcpTerminalAuthArgs } from "../modes/acp/terminal-auth";
11
11
 
12
12
  export default class Acp extends Command {
13
- static description = "Run Oh My Pi as an ACP (Agent Client Protocol) server over stdio";
13
+ static description = "Run snsagent as an ACP (Agent Client Protocol) server over stdio";
14
14
  static strict = false;
15
15
 
16
16
  async run(): Promise<void> {
@@ -1,7 +1,7 @@
1
1
  /**
2
- * `snscoder chat` — interactive chat subcommand.
2
+ * `snsagent chat` — interactive chat subcommand.
3
3
  *
4
- * Shows the snscoder banner, then delegates to the existing launch/agent
4
+ * Shows the snsagent banner, then delegates to the existing launch/agent
5
5
  * infrastructure for the actual LLM interaction loop.
6
6
  */
7
7
 
@@ -12,7 +12,7 @@ import { parseArgs } from "../cli/args.js";
12
12
  import { runRootCommand } from "../main.js";
13
13
 
14
14
  export default class Chat extends Command {
15
- static description = "Interactive chat with the snscoder agent";
15
+ static description = "Interactive chat with the snsagent agent";
16
16
  static strict = false;
17
17
 
18
18
  async run(): Promise<void> {
@@ -1,10 +1,10 @@
1
1
  /**
2
- * `omp install <target>` — top-level convenience over `omp plugin install` /
3
- * `omp plugin link`.
2
+ * `snsagent install <target>` — top-level convenience over `snsagent plugin install` /
3
+ * `snsagent plugin link`.
4
4
  *
5
5
  * The docs (omp.sh/docs/extension-authoring) advertise
6
6
  *
7
- * omp install ./my-extension
7
+ * snsagent install ./my-extension
8
8
  *
9
9
  * as a third loading mechanism that "symlinks the directory into the plugin
10
10
  * set and watches it for changes". Before this command existed, `install` was
@@ -25,7 +25,7 @@ import { type PluginAction, type PluginCommandArgs, runPluginCommand } from "../
25
25
  import { initTheme } from "../modes/theme/theme";
26
26
 
27
27
  /**
28
- * Heuristic used to decide whether `omp install <target>` should `link` a
28
+ * Heuristic used to decide whether `snsagent install <target>` should `link` a
29
29
  * local directory or `install` a remote spec. Exported for tests.
30
30
  */
31
31
  export function looksLikeLocalPath(target: string, cwd?: string): boolean {
@@ -66,7 +66,7 @@ export default class Install extends Command {
66
66
  const targets = Array.isArray(args.targets) ? args.targets : args.targets ? [args.targets] : [];
67
67
 
68
68
  if (targets.length === 0) {
69
- process.stderr.write("Usage: omp install <path | npm-spec | name@marketplace> [...]\n");
69
+ process.stderr.write("Usage: snsagent install <path | npm-spec | name@marketplace> [...]\n");
70
70
  process.exit(1);
71
71
  }
72
72
 
@@ -29,9 +29,9 @@ export default class Say extends Command {
29
29
  };
30
30
 
31
31
  static examples = [
32
- 'omp say "hello world"',
33
- 'omp say "hello world" --out /tmp/hello.wav',
34
- 'omp say "bonjour" --voice af_heart --model kokoro',
32
+ 'snsagent say "hello world"',
33
+ 'snsagent say "hello world" --out /tmp/hello.wav',
34
+ 'snsagent say "bonjour" --voice af_heart --model kokoro',
35
35
  ];
36
36
 
37
37
  async run(): Promise<void> {
@@ -60,7 +60,7 @@ export default class Say extends Command {
60
60
  process.stderr.write(
61
61
  chalk.red(
62
62
  `error: could not synthesize with local TTS model "${model}". ` +
63
- "Run `omp setup speech` to install it.\n",
63
+ "Run `snsagent setup speech` to install it.\n",
64
64
  ),
65
65
  );
66
66
  exitCode = 1;
@@ -21,7 +21,7 @@ export async function runOnboardingSetup(deps: OnboardingSetupDependencies = {})
21
21
  const stdinIsTTY = deps.stdinIsTTY ?? process.stdin.isTTY;
22
22
  const stdoutIsTTY = deps.stdoutIsTTY ?? process.stdout.isTTY;
23
23
  if (!stdinIsTTY || !stdoutIsTTY) {
24
- (deps.writeStderr ?? (text => process.stderr.write(text)))("omp setup requires an interactive TTY.\n");
24
+ (deps.writeStderr ?? (text => process.stderr.write(text)))("snsagent setup requires an interactive TTY.\n");
25
25
  (deps.exit ?? process.exit)(1);
26
26
  return;
27
27
  }
@@ -26,6 +26,7 @@ export const defaultConfig: Config = {
26
26
  path: "memory.jsonl",
27
27
  maxEntries: 1000,
28
28
  autoSummarize: true,
29
+ backend: "mnemopi",
29
30
  },
30
31
  };
31
32
 
@@ -44,9 +45,10 @@ export const DEFAULT_CONFIG_YAML =
44
45
  ` allowedChatIds: []\n` +
45
46
  ` pollIntervalMs: ${defaultConfig.telegram.pollIntervalMs}\n` +
46
47
  `memory:\n` +
47
- ` path: ${defaultConfig.memory.path}\n` +
48
- ` maxEntries: ${defaultConfig.memory.maxEntries}\n` +
49
- ` autoSummarize: ${defaultConfig.memory.autoSummarize}\n`;
48
+ ` path: ${defaultConfig.memory.path}\n` +
49
+ ` maxEntries: ${defaultConfig.memory.maxEntries}\n` +
50
+ ` autoSummarize: ${defaultConfig.memory.autoSummarize}\n` +
51
+ ` backend: ${defaultConfig.memory.backend}\n`;
50
52
 
51
53
  /** Default LLM provider id. */
52
54
  export const DEFAULT_PROVIDER = defaultConfig.model.provider;
@@ -32,6 +32,8 @@ export interface MemoryConfig {
32
32
  maxEntries: number;
33
33
  /** Auto-summarize old entries when count exceeds threshold. */
34
34
  autoSummarize: boolean;
35
+ /** Memory backend to use. */
36
+ backend: "mnemopi" | "hindsight" | "mnemosyne" | "mem0" | "lcm" | "local" | "off";
35
37
  }
36
38
 
37
39
  export interface Config {
@@ -109,6 +111,11 @@ export function validateConfig(raw: unknown): Config {
109
111
  if (typeof mem.autoSummarize !== "boolean") {
110
112
  throw new Error("config.memory.autoSummarize must be boolean");
111
113
  }
114
+ // Optional backend field with default
115
+ const backend = mem.backend;
116
+ if (backend !== undefined && !isNonEmptyString(backend)) {
117
+ throw new Error("config.memory.backend must be a string if present");
118
+ }
112
119
 
113
120
  const extra = r.extra;
114
121
  if (extra !== undefined && (typeof extra !== "object" || extra === null || Array.isArray(extra))) {
@@ -133,6 +140,7 @@ export function validateConfig(raw: unknown): Config {
133
140
  path: mem.path as string,
134
141
  maxEntries: mem.maxEntries as number,
135
142
  autoSummarize: mem.autoSummarize as boolean,
143
+ backend: (mem.backend ?? "mnemopi") as "mnemopi" | "hindsight" | "mnemosyne" | "mem0" | "lcm" | "local" | "off",
136
144
  },
137
145
  extra: extra as Record<string, unknown> | undefined,
138
146
  };
@@ -1426,7 +1426,7 @@ export const SETTINGS_SCHEMA = {
1426
1426
  tab: "interaction",
1427
1427
  group: "Startup & Updates",
1428
1428
  label: "Check for Updates",
1429
- description: "Check for omp updates on startup",
1429
+ description: "Check for snsagent updates on startup",
1430
1430
  },
1431
1431
  },
1432
1432
 
@@ -15,7 +15,7 @@ import * as os from "node:os";
15
15
 
16
16
  export const SNS_CONFIG_DIR_NAME = ".sns-myagent";
17
17
  export const SNS_CONFIG_FILE = "config.yaml";
18
- export const SNS_APP_NAME = "snscoder";
18
+ export const SNS_APP_NAME = "snsagent";
19
19
 
20
20
  export interface SnsConfig {
21
21
  apiKey?: string;
@@ -107,7 +107,7 @@ export async function getEnabledPlugins(cwd: string, opts: { home?: string } = {
107
107
 
108
108
  const manifest: PluginManifest | undefined = pluginPkg.omp || pluginPkg.pi;
109
109
  if (!manifest) {
110
- // Not an omp plugin, skip
110
+ // Not a snsagent plugin, skip
111
111
  continue;
112
112
  }
113
113
  manifest.version = pluginPkg.version;
@@ -430,7 +430,7 @@ export class PluginManager {
430
430
  // Step 2: refresh the git lockfile pin when re-installing an existing
431
431
  // git plugin. `bun install <spec>` is a no-op when the spec matches the
432
432
  // lockfile entry — it never re-resolves the remote ref — so re-running
433
- // `omp plugin install github:owner/repo` would silently keep the user on
433
+ // `snsagent plugin install github:owner/repo` would silently keep the user on
434
434
  // the original resolved commit even after upstream moved (#3063).
435
435
  // `bun update <name>` re-resolves the ref against the remote and
436
436
  // rewrites the pin; SHA-pinned refs stay put because the commit can't
@@ -866,7 +866,7 @@ export class PluginManager {
866
866
  status: hasManifest ? "ok" : "warning",
867
867
  message: hasManifest
868
868
  ? `v${pluginPkg.version}${pluginPkg.description ? ` - ${pluginPkg.description}` : ""}`
869
- : `v${pluginPkg.version} - No omp/pi manifest (not an omp plugin)`,
869
+ : `v${pluginPkg.version} - No omp/pi manifest (not an snsagent plugin)`,
870
870
  });
871
871
 
872
872
  // Check tools path exists if specified
@@ -10,7 +10,7 @@
10
10
 
11
11
  import type { HindsightConfig } from "./config";
12
12
 
13
- const USER_AGENT = "snscoder";
13
+ const USER_AGENT = "snsagent";
14
14
  const DEFAULT_USER_AGENT = USER_AGENT;
15
15
 
16
16
  export type Budget = "low" | "mid" | "high" | string;
@@ -0,0 +1,2 @@
1
+ ["configuration.md","faq.md","installation.md","memory.md","tbm.md","terminal-ui.md","termux.md","troubleshooting.md"]
2
+ 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
package/src/main.ts CHANGED
@@ -392,6 +392,7 @@ async function runInteractiveMode(
392
392
  resuming: boolean,
393
393
  forceSetupWizard: boolean,
394
394
  showStartupSplash: boolean,
395
+ modelRegistry: ModelRegistry,
395
396
  eventBus?: EventBus,
396
397
  initialMessage?: string,
397
398
  initialImages?: ImageContent[],
@@ -440,6 +441,8 @@ async function runInteractiveMode(
440
441
 
441
442
  if (setupWizard && setupScenes.length > 0) {
442
443
  await setupWizard.runSetupWizard(mode, setupScenes);
444
+ // Reload models.yml after wizard — BYOK tab may have written new provider config
445
+ await modelRegistry.refresh();
443
446
  }
444
447
 
445
448
  versionCheckPromise
@@ -1396,6 +1399,7 @@ export async function runRootCommand(
1396
1399
  Boolean(parsedArgs.continue || parsedArgs.resume || parsedArgs.fork),
1397
1400
  deps.forceSetupWizard === true,
1398
1401
  showStartupSplash,
1402
+ modelRegistry,
1399
1403
  eventBus,
1400
1404
  initialMessage,
1401
1405
  initialImages,
@@ -463,15 +463,15 @@ export class AcpAgent implements Agent {
463
463
  {
464
464
  id: "agent",
465
465
  name: "Use existing local credentials",
466
- description: "Authenticate via the provider keys/OAuth state already configured under ~/.omp.",
466
+ description: "Authenticate via the provider keys/OAuth state already configured.",
467
467
  },
468
468
  ];
469
469
  if (params.clientCapabilities?.auth?.terminal === true) {
470
470
  authMethods.push({
471
471
  type: "terminal",
472
472
  id: "terminal",
473
- name: "Set up Oh My Pi in terminal",
474
- description: "Launch the omp TUI to add provider keys and select models.",
473
+ name: "Set up snsagent in terminal",
474
+ description: "Launch the TUI to add provider keys and select models.",
475
475
  args: [ACP_TERMINAL_AUTH_FLAG],
476
476
  });
477
477
  }
@@ -112,9 +112,9 @@ export class PluginListComponent extends Container {
112
112
  if (entries.length === 0) {
113
113
  this.addChild(new Text(theme.fg("muted", " No plugins installed"), 0, 0));
114
114
  this.addChild(new Spacer(1));
115
- this.addChild(new Text(theme.fg("dim", " Install npm plugins: omp plugin install <package>"), 0, 0));
115
+ this.addChild(new Text(theme.fg("dim", " Install npm plugins: snsagent plugin install <package>"), 0, 0));
116
116
  this.addChild(
117
- new Text(theme.fg("dim", " Install marketplace plugins: omp plugin install <name>@<marketplace>"), 0, 0),
117
+ new Text(theme.fg("dim", " Install marketplace plugins: snsagent plugin install <name>@<marketplace>"), 0, 0),
118
118
  );
119
119
  this.addChild(new Spacer(1));
120
120
  this.addChild(new DynamicBorder());