@quatcode/agent 0.2.0 → 0.2.1

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/store.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
package/dist/tui.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { ImagePart } from "@quatcode/core";
1
2
  export type TuiOptions = {
2
3
  dir: string;
3
4
  model?: string;
@@ -13,4 +14,9 @@ export type TuiOptions = {
13
14
  };
14
15
  };
15
16
  export declare function runTui(options: TuiOptions): Promise<number>;
17
+ export declare function nextImageIndex(text: string): number;
18
+ export declare function extractInputImages(text: string, images: ReadonlyMap<number, ImagePart>): {
19
+ text: string;
20
+ images: ImagePart[];
21
+ };
16
22
  //# sourceMappingURL=tui.d.ts.map
package/dist/tui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"AAkGA,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,EAAE,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,WAAW,CAAA;KAAE,CAAC;CAC/D,CAAC;AAuCF,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAWjE"}
1
+ {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAEV,SAAS,EAMV,MAAM,gBAAgB,CAAC;AAoFxB,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,EAAE,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,WAAW,CAAA;KAAE,CAAC;CAC/D,CAAC;AAwCF,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAWjE;AAmlFD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASnD;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,GACrC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,EAAE,CAAA;CAAE,CAavC"}
package/dist/tui.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import path from "node:path";
2
2
  import { homedir } from "node:os";
3
- import { Session, ToolRegistry, addUsage, createProviderFromEnv, emptyUsage, estimateCost, runAgent, } from "@quatcode/core";
3
+ import { readFile, stat } from "node:fs/promises";
4
+ import { Session, ToolRegistry, addUsage, emptyUsage, estimateCost, runAgent, } from "@quatcode/core";
4
5
  import { analyzeCommand, createProjectTools, McpManager } from "@quatcode/tools";
5
6
  import { buildProjectContext, createBrainTools, scanProject } from "@quatcode/brain";
6
7
  import { Keyboard } from "./keyboard.js";
@@ -10,7 +11,7 @@ import { Screen } from "./screen.js";
10
11
  import { TurnController, fmtCost, fmtDuration, fmtTokens } from "./turn.js";
11
12
  import { renderBanner } from "./logo.js";
12
13
  import { renderMarkdown } from "./markdown.js";
13
- import { CUSTOM_MODEL, PROVIDERS, buildProvider, defaultModelFor, effortsForModel, fetchProviderModels, hasKey, keyEnvFor, resolveProviderForModel, } from "./models.js";
14
+ import { ADD_PROVIDER, allProviders, buildProvider, defaultModelFor, effortsForModel, hasKey, keyEnvFor, probeProviderModels, providerEnvKey, providerMeta, providerSlug, registerCustomProvider, removeCustomProvider, resolveProviderForModel, } from "./models.js";
14
15
  import { activeThemeId, bg, bold, buildColorRemap, clipAnsi, fg, getThemes, glyphs, padEndTo, palette, remapColors, setTheme, stringWidth, stripAnsi, tone, } from "./theme.js";
15
16
  import { listSessionsForDir, loadConfig, makeSessionId, saveConfig, saveSession, deleteSession } from "./store.js";
16
17
  import { configFile, conversationKey, deleteConversation, displayTitle, latestPerConversation, messagesForStorage, sortConversations, updateConversation, } from "./store.js";
@@ -22,6 +23,7 @@ const COMMAND_INFO = [
22
23
  { name: "/help", desc: "show this help" },
23
24
  { name: "/new", desc: "new conversation (clears the screen)" },
24
25
  { name: "/model", args: "[id]", desc: "pick or set the model" },
26
+ { name: "/provider", args: "[add|list|remove]", desc: "connect a provider by API key" },
25
27
  { name: "/effort", args: "[level]", desc: "reasoning effort (minimal…high)" },
26
28
  { name: "/key", desc: "enter the API key for the current provider" },
27
29
  { name: "/dir", args: "[path]", desc: "change the project directory" },
@@ -123,7 +125,7 @@ class TuiApp {
123
125
  lastTurn = null;
124
126
  turnUndo = null;
125
127
  pendingInitial = null;
126
- pendingImages = [];
128
+ pendingImages = new Map();
127
129
  userMarkers = [];
128
130
  messageCursor = -1;
129
131
  selection = null;
@@ -164,6 +166,17 @@ class TuiApp {
164
166
  if (value && process.env[name] === undefined)
165
167
  process.env[name] = value;
166
168
  }
169
+ for (const [id, custom] of Object.entries(this.config.customProviders ?? {})) {
170
+ registerCustomProvider({
171
+ id,
172
+ label: custom.label,
173
+ envKey: custom.envKey,
174
+ kind: "openai",
175
+ baseUrl: custom.baseUrl,
176
+ defaultModel: custom.models[0]?.id ?? "",
177
+ models: custom.models,
178
+ });
179
+ }
167
180
  this.effort = this.opts.effort ?? this.config.effort ?? null;
168
181
  setTheme(this.config.theme ?? "quatcode");
169
182
  this.screen.applyBackground();
@@ -216,10 +229,12 @@ class TuiApp {
216
229
  this.append([` ${tone.mist("// cancelled")}`]);
217
230
  continue;
218
231
  }
219
- const input = result.text;
220
- this.buffer.addHistory(input);
221
- const images = this.pendingImages;
222
- this.pendingImages = [];
232
+ const extracted = extractInputImages(result.text, this.pendingImages);
233
+ this.pendingImages = new Map();
234
+ const input = extracted.text;
235
+ const images = extracted.images;
236
+ if (input)
237
+ this.buffer.addHistory(input);
223
238
  const isCommand = input.startsWith("/");
224
239
  if (!isCommand)
225
240
  this.clearSplash();
@@ -305,7 +320,11 @@ class TuiApp {
305
320
  onKeys = (keys) => {
306
321
  for (const key of keys) {
307
322
  if (key.type === "resize") {
323
+ this.screen.applyBackground();
308
324
  this.scheduleRender();
325
+ const settle = setTimeout(() => this.scheduleRender(), 150);
326
+ if (typeof settle.unref === "function")
327
+ settle.unref();
309
328
  continue;
310
329
  }
311
330
  if (key.type === "mouse") {
@@ -458,7 +477,8 @@ class TuiApp {
458
477
  this.buffer.killToEnd();
459
478
  break;
460
479
  case "w":
461
- this.buffer.deleteWordBefore();
480
+ if (!this.deleteImageTokenBefore())
481
+ this.buffer.deleteWordBefore();
462
482
  break;
463
483
  case "p":
464
484
  this.buffer.historyPrev();
@@ -478,8 +498,14 @@ class TuiApp {
478
498
  this.buffer.moveWord(-1);
479
499
  else if (key.ch === "f" || key.ch === "F")
480
500
  this.buffer.moveWord(1);
481
- else if (key.ch === "d" || key.ch === "D")
482
- this.buffer.deleteWordAfter();
501
+ else if (key.ch === "d" || key.ch === "D") {
502
+ if (!this.deleteImageTokenAfter())
503
+ this.buffer.deleteWordAfter();
504
+ }
505
+ else if (key.ch === "v" || key.ch === "V") {
506
+ void this.pasteFromClipboard();
507
+ return;
508
+ }
483
509
  break;
484
510
  case "nav":
485
511
  if ((key.dir === "up" || key.dir === "down") &&
@@ -555,10 +581,12 @@ class TuiApp {
555
581
  this.toggleMode();
556
582
  break;
557
583
  case "backspace":
558
- this.buffer.backspace();
584
+ if (!this.deleteImageTokenBefore())
585
+ this.buffer.backspace();
559
586
  break;
560
587
  case "delete":
561
- this.buffer.deleteForward();
588
+ if (!this.deleteImageTokenAfter())
589
+ this.buffer.deleteForward();
562
590
  break;
563
591
  case "escape":
564
592
  this.finishLine({ kind: "cancel" });
@@ -745,21 +773,44 @@ class TuiApp {
745
773
  async pasteFromClipboard() {
746
774
  const image = readClipboardImage();
747
775
  if (image) {
748
- this.pendingImages.push(image);
749
- const kb = Math.max(1, Math.round((image.data.length * 3) / 4 / 1024));
750
- this.append([
751
- ` ${tone.accent(glyphs.diamond)} ${tone.mist(`// image attached (${image.mediaType} · ${kb} KB) · it will be sent with the next message`)}`,
752
- ]);
776
+ this.attachImageMarker(image);
753
777
  return;
754
778
  }
755
779
  const text = readClipboardText();
756
780
  if (text && text.length > 0) {
781
+ const fromPath = await imageFromPath(text);
782
+ if (fromPath) {
783
+ this.attachImageMarker(fromPath);
784
+ return;
785
+ }
757
786
  this.buffer.insert(text.replace(/\r\n?/g, "\n"));
758
787
  this.scheduleRender();
759
788
  return;
760
789
  }
761
790
  this.append([` ${tone.mist("// clipboard is empty or unavailable")}`]);
762
791
  }
792
+ deleteImageTokenBefore() {
793
+ const length = imageTokenBefore(this.buffer.cursorLineBefore());
794
+ if (length <= 0)
795
+ return false;
796
+ this.buffer.deleteBefore(length);
797
+ return true;
798
+ }
799
+ deleteImageTokenAfter() {
800
+ const length = imageTokenAfter(this.buffer.cursorLineAfter());
801
+ if (length <= 0)
802
+ return false;
803
+ this.buffer.deleteAfter(length);
804
+ return true;
805
+ }
806
+ attachImageMarker(image) {
807
+ const index = nextImageIndex(this.buffer.text());
808
+ this.pendingImages.set(index, image);
809
+ const current = this.buffer.text();
810
+ const needsSpace = current.length > 0 && !/\s$/.test(current);
811
+ this.buffer.insert(`${needsSpace ? " " : ""}[Image ${index}] `);
812
+ this.scheduleRender();
813
+ }
763
814
  copySelection() {
764
815
  const text = this.selectionText();
765
816
  this.selection = null;
@@ -976,6 +1027,7 @@ class TuiApp {
976
1027
  prompt: this.inputPrompt,
977
1028
  placeholder: this.inputPlaceholder,
978
1029
  mask: this.inputMask,
1030
+ style: styleInputLine,
979
1031
  });
980
1032
  this.lastInputRender = rendered;
981
1033
  const suggestions = this.suggestions();
@@ -1104,40 +1156,33 @@ class TuiApp {
1104
1156
  return `${tone.silver(`${this.providerId} · ${this.model}`)}${keyState}`;
1105
1157
  }
1106
1158
  detectProvider() {
1107
- if (process.env.ANTHROPIC_API_KEY)
1108
- return "anthropic";
1109
- if (process.env.OPENAI_API_KEY)
1110
- return "openai";
1111
- if (process.env.GEMINI_API_KEY)
1112
- return "gemini";
1159
+ for (const provider of allProviders()) {
1160
+ if (process.env[provider.envKey])
1161
+ return provider.id;
1162
+ }
1113
1163
  return null;
1114
1164
  }
1115
1165
  detectEnvSetup() {
1166
+ const envModelFor = (id) => {
1167
+ const meta = providerMeta(id);
1168
+ if (!meta)
1169
+ return undefined;
1170
+ return process.env[`${meta.envKey.replace(/_API_KEY$/, "")}_MODEL`];
1171
+ };
1172
+ const pick = (id) => ({
1173
+ id,
1174
+ model: envModelFor(id) ?? defaultModelFor(id),
1175
+ });
1116
1176
  const override = process.env.QUATCODE_PROVIDER?.toLowerCase();
1117
- if (override === "anthropic" || override === "openai" || override === "gemini") {
1118
- const envModel = {
1119
- anthropic: process.env.ANTHROPIC_MODEL,
1120
- openai: process.env.OPENAI_MODEL,
1121
- gemini: process.env.GEMINI_MODEL,
1122
- }[override];
1123
- return { id: override, model: envModel ?? defaultModelFor(override) };
1124
- }
1125
- if (process.env.ANTHROPIC_MODEL)
1126
- return { id: "anthropic", model: process.env.ANTHROPIC_MODEL };
1127
- if (process.env.OPENAI_MODEL)
1128
- return { id: "openai", model: process.env.OPENAI_MODEL };
1129
- if (process.env.GEMINI_MODEL)
1130
- return { id: "gemini", model: process.env.GEMINI_MODEL };
1131
- try {
1132
- const provider = createProviderFromEnv();
1133
- const id = provider.id;
1134
- if (provider.defaultModel &&
1135
- (id === "anthropic" || id === "openai" || id === "gemini")) {
1136
- return { id, model: provider.defaultModel };
1137
- }
1177
+ if (override && providerMeta(override))
1178
+ return pick(override);
1179
+ for (const provider of allProviders()) {
1180
+ if (envModelFor(provider.id))
1181
+ return pick(provider.id);
1138
1182
  }
1139
- catch {
1140
- return null;
1183
+ for (const provider of allProviders()) {
1184
+ if (process.env[provider.envKey])
1185
+ return pick(provider.id);
1141
1186
  }
1142
1187
  return null;
1143
1188
  }
@@ -1227,65 +1272,195 @@ class TuiApp {
1227
1272
  return null;
1228
1273
  }
1229
1274
  }
1230
- async collectModelEntries() {
1231
- const result = [];
1232
- for (const provider of PROVIDERS) {
1233
- let models = provider.models;
1234
- if (hasKey(provider.id)) {
1235
- this.setStatus({ label: `LOADING ${provider.label.toUpperCase()} MODELS` });
1236
- const live = await fetchProviderModels(provider.id);
1237
- if (live.length > 0)
1238
- models = live;
1275
+ async changeModel() {
1276
+ for (;;) {
1277
+ const pickerEntries = [
1278
+ { kind: "header", label: "setup" },
1279
+ {
1280
+ kind: "item",
1281
+ value: ADD_PROVIDER,
1282
+ label: "add a provider…",
1283
+ hint: "connect by API key",
1284
+ },
1285
+ ];
1286
+ for (const provider of allProviders()) {
1287
+ if (provider.models.length === 0)
1288
+ continue;
1289
+ pickerEntries.push({
1290
+ kind: "header",
1291
+ label: `${provider.label} · ${hasKey(provider.id) ? "key set" : "no key"}${provider.custom ? " · added" : ""}`,
1292
+ });
1293
+ for (const model of provider.models) {
1294
+ pickerEntries.push({
1295
+ kind: "item",
1296
+ value: `${provider.id}:${model.id}`,
1297
+ label: model.id,
1298
+ hint: model.label,
1299
+ });
1300
+ }
1239
1301
  }
1240
- for (const model of models) {
1241
- result.push({ providerId: provider.id, id: model.id, label: model.label });
1302
+ const chosen = await this.openPicker(new Picker({ title: "select a model", entries: pickerEntries, filterable: true }));
1303
+ if (!chosen)
1304
+ return false;
1305
+ if (chosen === ADD_PROVIDER) {
1306
+ const added = await this.addProviderFlow();
1307
+ if (added) {
1308
+ this.renderNow();
1309
+ await this.pause(650);
1310
+ }
1311
+ continue;
1242
1312
  }
1313
+ const separator = chosen.indexOf(":");
1314
+ const model = chosen.slice(separator + 1);
1315
+ this.applyModel(chosen.slice(0, separator), model);
1316
+ await this.chooseEffortForModel(model);
1317
+ return true;
1243
1318
  }
1244
- this.setStatus(null);
1245
- return result;
1246
1319
  }
1247
- async changeModel() {
1248
- this.setStatus({ label: "LOADING MODELS" });
1249
- const entries = await this.collectModelEntries();
1250
- this.setStatus(null);
1251
- const pickerEntries = [];
1252
- for (const provider of PROVIDERS) {
1253
- const models = entries.filter((entry) => entry.providerId === provider.id);
1254
- if (models.length === 0)
1255
- continue;
1256
- pickerEntries.push({
1257
- kind: "header",
1258
- label: `${provider.label} · ${hasKey(provider.id) ? "key set" : "no key"}`,
1259
- });
1260
- for (const model of models) {
1261
- pickerEntries.push({
1262
- kind: "item",
1263
- value: `${provider.id}:${model.id}`,
1264
- label: model.id,
1265
- hint: model.label,
1266
- });
1320
+ async providerCommand(arg) {
1321
+ const parts = arg.split(/\s+/).filter(Boolean);
1322
+ const sub = (parts[0] ?? "").toLowerCase();
1323
+ const rest = parts.slice(1).join(" ").trim();
1324
+ if (!sub || sub === "add" || sub === "connect") {
1325
+ await this.addProviderFlow();
1326
+ return;
1327
+ }
1328
+ if (sub === "list" || sub === "ls") {
1329
+ const lines = [` ${tone.mist("// PROVIDERS")}`];
1330
+ for (const provider of allProviders()) {
1331
+ const state = hasKey(provider.id) ? tone.accent("key set") : tone.mist("no key");
1332
+ lines.push(` ${padEndTo(tone.bone(provider.label), 18)}${tone.silver(`${provider.models.length} models`)} ${state}${provider.custom ? tone.mist(" · added") : ""}`);
1333
+ lines.push(` ${tone.mist(`${provider.envKey}${provider.baseUrl ? ` · ${provider.baseUrl}` : ""}`)}`);
1267
1334
  }
1335
+ lines.push("");
1336
+ lines.push(` ${tone.mist("// add: /provider add (or /model → add a provider…) · remove: /provider remove <name>")}`);
1337
+ this.append(lines);
1338
+ return;
1268
1339
  }
1269
- pickerEntries.push({ kind: "item", value: CUSTOM_MODEL, label: "custom model id…" });
1270
- const chosen = await this.openPicker(new Picker({ title: "select a model", entries: pickerEntries, filterable: true }));
1271
- if (!chosen)
1340
+ if (sub === "remove" || sub === "rm") {
1341
+ if (!rest) {
1342
+ this.append([` ${tone.mist("// usage: /provider remove <name>")}`]);
1343
+ return;
1344
+ }
1345
+ const meta = providerMeta(rest);
1346
+ if (!meta) {
1347
+ this.append([` ${tone.red(`// no provider named ${rest}`)}`]);
1348
+ return;
1349
+ }
1350
+ if (!meta.custom) {
1351
+ this.append([` ${tone.red(`// ${rest} is a built-in provider and cannot be removed`)}`]);
1352
+ return;
1353
+ }
1354
+ const confirmed = await this.confirm(`remove provider "${rest}"?`);
1355
+ if (!confirmed) {
1356
+ this.append([` ${tone.mist("// cancelled")}`]);
1357
+ return;
1358
+ }
1359
+ removeCustomProvider(rest);
1360
+ if (meta.envKey) {
1361
+ const keys = { ...(this.config.keys ?? {}) };
1362
+ if (keys[meta.envKey]) {
1363
+ delete keys[meta.envKey];
1364
+ this.config.keys = keys;
1365
+ }
1366
+ delete process.env[meta.envKey];
1367
+ }
1368
+ if (this.config.customProviders?.[rest]) {
1369
+ const next = { ...this.config.customProviders };
1370
+ delete next[rest];
1371
+ this.config.customProviders = next;
1372
+ }
1373
+ if (this.providerId === rest) {
1374
+ this.applyModel("anthropic", defaultModelFor("anthropic"));
1375
+ this.append([` ${tone.mist(`// MODEL → ${this.providerId} · ${this.model}`)}`]);
1376
+ }
1377
+ await saveConfig({ ...this.config }).catch(() => undefined);
1378
+ this.append([
1379
+ ` ${tone.accent(glyphs.diamond)} ${tone.mist(`// PROVIDER REMOVED → ${rest}`)}`,
1380
+ ]);
1381
+ return;
1382
+ }
1383
+ this.append([` ${tone.mist("// usage: /provider [add|list|remove <name>]")}`]);
1384
+ }
1385
+ async addProviderFlow() {
1386
+ const nameResult = await this.readLine({
1387
+ prompt: ` ${tone.bone("PROVIDER NAME")} ${tone.mist(glyphs.prompt)} `,
1388
+ placeholder: "e.g. together, fireworks, cerebras",
1389
+ });
1390
+ if (nameResult.kind !== "submit" || !nameResult.text.trim()) {
1391
+ this.append([` ${tone.mist("// cancelled")}`]);
1272
1392
  return false;
1273
- if (chosen === CUSTOM_MODEL) {
1274
- const result = await this.readLine({
1275
- prompt: ` ${tone.bone("MODEL ID")} ${tone.mist(glyphs.prompt)} `,
1276
- placeholder: "e.g. claude-sonnet-5-5",
1277
- });
1278
- if (result.kind !== "submit" || !result.text.trim())
1279
- return false;
1280
- const id = result.text.trim();
1281
- this.applyModel(resolveProviderForModel(id) ?? this.providerId, id);
1282
- await this.chooseEffortForModel(id);
1283
- return true;
1284
1393
  }
1285
- const separator = chosen.indexOf(":");
1286
- const model = chosen.slice(separator + 1);
1287
- this.applyModel(chosen.slice(0, separator), model);
1288
- await this.chooseEffortForModel(model);
1394
+ const id = providerSlug(nameResult.text);
1395
+ const existing = providerMeta(id);
1396
+ if (existing && !existing.custom) {
1397
+ this.append([` ${tone.red(`// ${id} is already a built-in provider — pick it from the list`)}`]);
1398
+ return false;
1399
+ }
1400
+ const urlResult = await this.readLine({
1401
+ prompt: ` ${tone.bone("BASE URL")} ${tone.mist(glyphs.prompt)} `,
1402
+ placeholder: "https://api.example.com/v1",
1403
+ });
1404
+ if (urlResult.kind !== "submit" || !urlResult.text.trim()) {
1405
+ this.append([` ${tone.mist("// cancelled")}`]);
1406
+ return false;
1407
+ }
1408
+ const baseUrl = urlResult.text.trim().replace(/\/+$/, "");
1409
+ if (!/^https?:\/\//i.test(baseUrl)) {
1410
+ this.append([` ${tone.red("// base url must start with http:// or https://")}`]);
1411
+ return false;
1412
+ }
1413
+ const keyResult = await this.readLine({
1414
+ prompt: ` ${tone.bone("API KEY")} ${tone.mist(glyphs.prompt)} `,
1415
+ mask: true,
1416
+ placeholder: "",
1417
+ });
1418
+ if (keyResult.kind !== "submit" || !keyResult.text.trim()) {
1419
+ this.append([` ${tone.mist("// cancelled")}`]);
1420
+ return false;
1421
+ }
1422
+ const apiKey = keyResult.text.trim();
1423
+ this.setStatus({ label: `CHECKING ${id.toUpperCase()}` });
1424
+ let models = [];
1425
+ try {
1426
+ models = await probeProviderModels(baseUrl, apiKey);
1427
+ }
1428
+ catch (err) {
1429
+ this.setStatus(null);
1430
+ this.append([
1431
+ ` ${tone.red(`// ${errorMessage(err)}`)}`,
1432
+ ` ${tone.mist("// the provider must expose an OpenAI-compatible GET /models")}`,
1433
+ ]);
1434
+ return false;
1435
+ }
1436
+ this.setStatus(null);
1437
+ if (models.length === 0) {
1438
+ this.append([` ${tone.red("// no chat models found at this endpoint")}`]);
1439
+ return false;
1440
+ }
1441
+ const envKey = providerEnvKey(id);
1442
+ registerCustomProvider({
1443
+ id,
1444
+ label: id,
1445
+ envKey,
1446
+ kind: "openai",
1447
+ baseUrl,
1448
+ defaultModel: models[0]?.id ?? "",
1449
+ models,
1450
+ custom: true,
1451
+ });
1452
+ process.env[envKey] = apiKey;
1453
+ this.config.keys = { ...(this.config.keys ?? {}), [envKey]: apiKey };
1454
+ this.config.customProviders = {
1455
+ ...(this.config.customProviders ?? {}),
1456
+ [id]: { label: id, baseUrl, envKey, models },
1457
+ };
1458
+ await saveConfig({ ...this.config }).catch(() => undefined);
1459
+ this.append([
1460
+ ` ${tone.accent(glyphs.diamond)} ${tone.mist(`// PROVIDER ADDED → ${id} · ${models.length} model${models.length === 1 ? "" : "s"}`)}`,
1461
+ ` ${tone.silver(baseUrl)}`,
1462
+ ` ${tone.mist(clipAnsi(models.slice(0, 6).map((model) => model.id).join(" · "), Math.max(20, this.contentWidth() - 6)))}`,
1463
+ ]);
1289
1464
  return true;
1290
1465
  }
1291
1466
  effortEntries(efforts, current) {
@@ -1622,6 +1797,7 @@ class TuiApp {
1622
1797
  this.session = new Session(this.system);
1623
1798
  this.conversationId = makeSessionId();
1624
1799
  this.lastTurn = null;
1800
+ this.pendingImages = new Map();
1625
1801
  this.transcript = [];
1626
1802
  this.userMarkers = [];
1627
1803
  this.messageCursor = -1;
@@ -1643,6 +1819,9 @@ class TuiApp {
1643
1819
  }
1644
1820
  }
1645
1821
  return false;
1822
+ case "provider":
1823
+ await this.providerCommand(arg);
1824
+ return false;
1646
1825
  case "effort":
1647
1826
  await this.effortCommand(arg);
1648
1827
  return false;
@@ -2328,7 +2507,7 @@ class TuiApp {
2328
2507
  const keys = [
2329
2508
  ["enter", "send"],
2330
2509
  ["ctrl+enter", "newline (shift+enter, ctrl+space, ctrl+j, \\ + enter too)"],
2331
- ["ctrl+v", "paste text or an image"],
2510
+ ["ctrl+v / alt+v", "paste text or an image — alt+v works even if the terminal eats ctrl+v"],
2332
2511
  ["mouse drag", "select text · ctrl+c copies"],
2333
2512
  ["permission card", "← → select · enter confirm · mouse click"],
2334
2513
  ["sessions picker", "ctrl+r rename · ctrl+p pin · ctrl+d delete"],
@@ -2437,6 +2616,80 @@ function shortenHome(dir) {
2437
2616
  const home = homedir();
2438
2617
  return dir.startsWith(home) ? `~${dir.slice(home.length)}` : dir;
2439
2618
  }
2619
+ const IMAGE_EXTENSIONS = {
2620
+ ".png": "image/png",
2621
+ ".jpg": "image/jpeg",
2622
+ ".jpeg": "image/jpeg",
2623
+ ".webp": "image/webp",
2624
+ ".gif": "image/gif",
2625
+ ".bmp": "image/bmp",
2626
+ };
2627
+ const IMAGE_MARKER_RE = /\[Image (\d+)\]/g;
2628
+ export function nextImageIndex(text) {
2629
+ const used = new Set();
2630
+ for (const match of text.matchAll(IMAGE_MARKER_RE)) {
2631
+ const index = Number(match[1]);
2632
+ if (Number.isInteger(index) && index > 0)
2633
+ used.add(index);
2634
+ }
2635
+ let index = 1;
2636
+ while (used.has(index))
2637
+ index += 1;
2638
+ return index;
2639
+ }
2640
+ export function extractInputImages(text, images) {
2641
+ const used = [];
2642
+ const cleaned = text
2643
+ .replace(IMAGE_MARKER_RE, (match, raw) => {
2644
+ const image = images.get(Number(raw));
2645
+ if (!image)
2646
+ return match;
2647
+ used.push(image);
2648
+ return "";
2649
+ })
2650
+ .replace(/[ \t]{2,}/g, " ")
2651
+ .replace(/[ \t]+\n/g, "\n")
2652
+ .trim();
2653
+ return { text: cleaned, images: used };
2654
+ }
2655
+ function imageTokenBefore(before) {
2656
+ const match = /(?:\[Image \d+\][ \t]*)+$/.exec(before);
2657
+ return match ? match[0].length : 0;
2658
+ }
2659
+ function imageTokenAfter(after) {
2660
+ const match = /^(?:\[Image \d+\][ \t]*)+/.exec(after);
2661
+ return match ? match[0].length : 0;
2662
+ }
2663
+ function styleInputLine(text) {
2664
+ const parts = text.split(/(\[Image \d+\])/);
2665
+ if (parts.length === 1)
2666
+ return tone.bone(text);
2667
+ return parts
2668
+ .map((part) => /^\[Image \d+\]$/.test(part) ? tone.onBone(part) : tone.bone(part))
2669
+ .join("");
2670
+ }
2671
+ async function imageFromPath(raw) {
2672
+ const lines = raw
2673
+ .split(/\r?\n/)
2674
+ .map((line) => line.trim().replace(/^["']|["']$/g, "").trim())
2675
+ .filter(Boolean);
2676
+ if (lines.length !== 1)
2677
+ return null;
2678
+ const file = lines[0];
2679
+ const mediaType = IMAGE_EXTENSIONS[path.extname(file).toLowerCase()];
2680
+ if (!mediaType)
2681
+ return null;
2682
+ try {
2683
+ const info = await stat(file);
2684
+ if (!info.isFile() || info.size === 0 || info.size > 12 * 1024 * 1024)
2685
+ return null;
2686
+ const data = await readFile(file);
2687
+ return { type: "image", mediaType, data: data.toString("base64") };
2688
+ }
2689
+ catch {
2690
+ return null;
2691
+ }
2692
+ }
2440
2693
  function errorMessage(err) {
2441
2694
  return err instanceof Error ? err.message : String(err);
2442
2695
  }