@iinm/plain-agent 1.10.13 → 1.10.15

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/README.md CHANGED
@@ -68,12 +68,12 @@ Create the configuration.
68
68
  "webSearch": {
69
69
  "provider": "gemini",
70
70
  "apiKey": "<GEMINI_API_KEY>",
71
- "model": "gemini-3-flash-preview"
71
+ "model": "gemini-3.5-flash"
72
72
 
73
73
  // Or use Vertex AI (Requires gcloud CLI to get authentication token)
74
74
  // "provider": "gemini-vertex-ai",
75
75
  // "baseURL": "https://aiplatform.googleapis.com/v1beta1/projects/<project_id>/locations/<location>",
76
- // "model": "gemini-3-flash-preview"
76
+ // "model": "gemini-3.5-flash"
77
77
 
78
78
  // Or use a custom command
79
79
  // "provider": "command",
@@ -84,7 +84,7 @@ Create the configuration.
84
84
  "webFetch": {
85
85
  "provider": "gemini",
86
86
  "apiKey": "<GEMINI_API_KEY>",
87
- "model": "gemini-3-flash-preview"
87
+ "model": "gemini-3.5-flash"
88
88
 
89
89
  // Or use Vertex AI (Requires gcloud CLI to get authentication token)
90
90
 
@@ -475,7 +475,7 @@
475
475
  },
476
476
 
477
477
  {
478
- "name": "gemini-3-flash-preview",
478
+ "name": "gemini-3.5-flash",
479
479
  "variant": "thinking-medium",
480
480
  "platform": {
481
481
  "name": "gemini",
@@ -485,7 +485,7 @@
485
485
  "model": {
486
486
  "format": "gemini",
487
487
  "config": {
488
- "model": "gemini-3-flash-preview",
488
+ "model": "gemini-3.5-flash",
489
489
  "config": {
490
490
  "requestConfig": {
491
491
  "generationConfig": {
@@ -503,14 +503,14 @@
503
503
  "currency": "USD",
504
504
  "unit": "1M",
505
505
  "costs": {
506
- "promptTokenCount": 0.5,
507
- "cachedContentTokenCount": -0.45,
508
- "candidatesTokenCount": 3
506
+ "promptTokenCount": 1.5,
507
+ "cachedContentTokenCount": -1.35,
508
+ "candidatesTokenCount": 9
509
509
  }
510
510
  }
511
511
  },
512
512
  {
513
- "name": "gemini-3-flash-preview",
513
+ "name": "gemini-3.5-flash",
514
514
  "variant": "thinking-high",
515
515
  "platform": {
516
516
  "name": "gemini",
@@ -520,7 +520,7 @@
520
520
  "model": {
521
521
  "format": "gemini",
522
522
  "config": {
523
- "model": "gemini-3-flash-preview",
523
+ "model": "gemini-3.5-flash",
524
524
  "config": {
525
525
  "requestConfig": {
526
526
  "generationConfig": {
@@ -538,9 +538,9 @@
538
538
  "currency": "USD",
539
539
  "unit": "1M",
540
540
  "costs": {
541
- "promptTokenCount": 0.5,
542
- "cachedContentTokenCount": -0.45,
543
- "candidatesTokenCount": 3
541
+ "promptTokenCount": 1.5,
542
+ "cachedContentTokenCount": -1.35,
543
+ "candidatesTokenCount": 9
544
544
  }
545
545
  }
546
546
  },
@@ -616,7 +616,7 @@
616
616
  },
617
617
 
618
618
  {
619
- "name": "gemini-3-flash-preview",
619
+ "name": "gemini-3.5-flash",
620
620
  "variant": "thinking-medium-vertex-ai",
621
621
  "platform": {
622
622
  "name": "vertex-ai",
@@ -625,7 +625,7 @@
625
625
  "model": {
626
626
  "format": "gemini",
627
627
  "config": {
628
- "model": "gemini-3-flash-preview",
628
+ "model": "gemini-3.5-flash",
629
629
  "config": {
630
630
  "requestConfig": {
631
631
  "generationConfig": {
@@ -643,14 +643,14 @@
643
643
  "currency": "USD",
644
644
  "unit": "1M",
645
645
  "costs": {
646
- "promptTokenCount": 0.5,
647
- "cachedContentTokenCount": -0.45,
648
- "candidatesTokenCount": 3
646
+ "promptTokenCount": 1.5,
647
+ "cachedContentTokenCount": -1.35,
648
+ "candidatesTokenCount": 9
649
649
  }
650
650
  }
651
651
  },
652
652
  {
653
- "name": "gemini-3-flash-preview",
653
+ "name": "gemini-3.5-flash",
654
654
  "variant": "thinking-high-vertex-ai",
655
655
  "platform": {
656
656
  "name": "vertex-ai",
@@ -659,7 +659,7 @@
659
659
  "model": {
660
660
  "format": "gemini",
661
661
  "config": {
662
- "model": "gemini-3-flash-preview",
662
+ "model": "gemini-3.5-flash",
663
663
  "config": {
664
664
  "requestConfig": {
665
665
  "generationConfig": {
@@ -677,9 +677,9 @@
677
677
  "currency": "USD",
678
678
  "unit": "1M",
679
679
  "costs": {
680
- "promptTokenCount": 0.5,
681
- "cachedContentTokenCount": -0.45,
682
- "candidatesTokenCount": 3
680
+ "promptTokenCount": 1.5,
681
+ "cachedContentTokenCount": -1.35,
682
+ "candidatesTokenCount": 9
683
683
  }
684
684
  }
685
685
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iinm/plain-agent",
3
- "version": "1.10.13",
3
+ "version": "1.10.15",
4
4
  "description": "A lightweight CLI-based coding agent",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/cli/args.mjs CHANGED
@@ -184,7 +184,7 @@ export function printHelp(exitCode = 0) {
184
184
  console.log(`
185
185
  Usage: plain [options]
186
186
  plain batch [options] <task>
187
- plain resume [<sessionId>] [--list] [-c <file>]
187
+ plain resume [<sessionId>] [--list]
188
188
  plain cost [--from YYYY-MM-DD] [--to YYYY-MM-DD]
189
189
  plain list-models
190
190
  plain install-claude-code-plugins
@@ -210,7 +210,7 @@ Subcommands:
210
210
  install-claude-code-plugins Install Claude Code plugins
211
211
 
212
212
  Examples:
213
- plain -m gpt-5.4+thinking-medium
213
+ plain -m claude-sonnet-4-6+thinking-high
214
214
  plain batch \\
215
215
  -c ~/.config/plain-agent/config.local.json \\
216
216
  -c .plain-agent/config.json \\
@@ -15,12 +15,12 @@ import { applyInlineMarkdown, formatMarkdownTable } from "./formatter.mjs";
15
15
  * correctly without special boundary-detection logic.
16
16
  *
17
17
  * @param {(lines: string[], maxWidth?: number) => string} [formatTable=formatMarkdownTable] - Table formatting function (injectable for testing)
18
- * @param {number} [maxWidth] - Maximum terminal display width (defaults to process.stdout.columns - 4 or 80)
18
+ * @param {() => number} [maxWidth] - Maximum terminal display width (defaults to process.stdout.columns - 4 or 100)
19
19
  * @returns {{ feed: (chunk: string) => StreamFormatterResult, forceFlush: () => StreamFormatterResult }}
20
20
  */
21
21
  export function createStreamFormatter(
22
22
  formatTable = formatMarkdownTable,
23
- maxWidth = process.stdout.columns ? process.stdout.columns - 4 : 80,
23
+ maxWidth = () => (process.stdout.columns ? process.stdout.columns - 4 : 100),
24
24
  ) {
25
25
  /** @type {string} - Accumulated incomplete line */
26
26
  let pendingLine = "";
@@ -168,7 +168,7 @@ export function createStreamFormatter(
168
168
  l.endsWith("\n") ? l.slice(0, -1) : l,
169
169
  );
170
170
  try {
171
- const formatted = formatTable(rawLines, maxWidth);
171
+ const formatted = formatTable(rawLines, maxWidth());
172
172
  output.push(`${formatted}\n`);
173
173
  } catch (err) {
174
174
  // Fallback: output raw lines if formatting fails
package/src/main.mjs CHANGED
@@ -241,23 +241,22 @@ export async function main(argv = process.argv) {
241
241
 
242
242
  if (resumedState) {
243
243
  // Switching models on resume is not supported. The model from the saved
244
- // session always wins. If config disagrees, fail loudly.
244
+ // session always wins. If config disagrees, warn and continue.
245
245
  if (
246
246
  modelNameWithVariant &&
247
247
  modelNameWithVariant !== resumedState.modelName
248
248
  ) {
249
249
  console.error(
250
250
  styleText(
251
- "red",
251
+ "yellow",
252
252
  [
253
- `Cannot resume session ${resumedState.sessionId}: model mismatch.`,
253
+ `⚠️ Model mismatch for session ${resumedState.sessionId}.`,
254
254
  ` saved model: ${resumedState.modelName}`,
255
255
  ` current model: ${modelNameWithVariant}`,
256
- "Resume must use the same model the session was started with.",
256
+ "Resuming with the saved model.",
257
257
  ].join("\n"),
258
258
  ),
259
259
  );
260
- process.exit(1);
261
260
  }
262
261
  modelNameWithVariant = resumedState.modelName;
263
262
  }
@@ -34,8 +34,8 @@ export function createCacheEnabledGeminiModelCaller(
34
34
 
35
35
  const props = {
36
36
  cacheTTL: 2 * 60, // seconds
37
- // https://ai.google.dev/gemini-api/docs/caching#considerations
38
- minCacheableTokenCount: 2048,
37
+ // https://ai.google.dev/gemini-api/docs/caching
38
+ minCacheableTokenCount: 4096,
39
39
  };
40
40
 
41
41
  /**
@@ -60,7 +60,7 @@ export function createCacheEnabledGeminiModelCaller(
60
60
  /** @type {GeminiToolConfig} */
61
61
  const toolConfig = {
62
62
  functionCallingConfig: {
63
- // Workaround to prevent MALFORMED_FUNCTION_CALL issues with gemini-3-flash
63
+ // Workaround to prevent MALFORMED_FUNCTION_CALL issues with gemini 3 flash
64
64
  mode: "VALIDATED",
65
65
  },
66
66
  };
@@ -132,7 +132,7 @@ export function createCacheEnabledGeminiModelCaller(
132
132
  ...baseRequest,
133
133
  system_instruction: systemInstruction,
134
134
  contents: contentsWithoutSystem,
135
- tools: tools.length ? tools : undefined,
135
+ tools: input.tools?.length ? tools : [],
136
136
  toolConfig,
137
137
  };
138
138
 
@@ -264,7 +264,7 @@ async function webFetchViaCommand(config, input) {
264
264
  * @returns {Promise<string | Error>}
265
265
  */
266
266
  async function webFetchViaGemini(config, input, retryCount) {
267
- const model = config.model ?? "gemini-3-flash-preview";
267
+ const model = config.model ?? "gemini-3.5-flash";
268
268
  const url =
269
269
  config.provider === "gemini-vertex-ai"
270
270
  ? `${config.baseURL}/publishers/google/models/${config.model}:generateContent`
@@ -330,7 +330,7 @@ async function webSearchViaCommand(config, input) {
330
330
  * @returns {Promise<string | Error>}
331
331
  */
332
332
  async function webSearchViaGemini(config, input, retryCount) {
333
- const model = config.model ?? "gemini-3-flash-preview";
333
+ const model = config.model ?? "gemini-3.5-flash";
334
334
  const url =
335
335
  config.provider === "gemini-vertex-ai"
336
336
  ? `${config.baseURL}/publishers/google/models/${config.model}:generateContent`