@iinm/plain-agent 1.10.6 → 1.10.7

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
@@ -381,7 +381,7 @@ Files are loaded in the following order. Settings in later files override earlie
381
381
  "args": ["ci"]
382
382
  },
383
383
  "mode": "sandbox",
384
- "extraArgs": ["--allow-net", "0.0.0.0/0"]
384
+ "additionalArgs": ["--allow-net", "0.0.0.0/0"]
385
385
  }
386
386
  ]
387
387
  }
package/bin/plain CHANGED
@@ -1,3 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import("../src/main.mjs");
3
+ import { main } from "../src/main.mjs";
4
+
5
+ main().catch((err) => {
6
+ console.error(err);
7
+ process.exit(1);
8
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iinm/plain-agent",
3
- "version": "1.10.6",
3
+ "version": "1.10.7",
4
4
  "description": "A lightweight CLI-based coding agent",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -31,6 +31,7 @@
31
31
  "scripts": {
32
32
  "check": "npm run lint && tsc && npm run test",
33
33
  "test": "node --test",
34
+ "coverage": "node --experimental-test-coverage --test",
34
35
  "lint": "npx @biomejs/biome check",
35
36
  "fix": "npx @biomejs/biome check --fix"
36
37
  },
package/src/main.mjs CHANGED
@@ -34,64 +34,70 @@ import { createWebSearchTool } from "./tools/webSearch.mjs";
34
34
  import { writeFileTool } from "./tools/writeFile.mjs";
35
35
  import { createToolUseApprover } from "./toolUseApprover.mjs";
36
36
 
37
- const cliArgs = parseCliArgs(process.argv);
38
- if (cliArgs.subcommand.type === "help") {
39
- printHelp();
40
- }
41
-
42
- if (cliArgs.subcommand.type === "list-models") {
43
- const { appConfig } = await loadAppConfig({ skipTrustCheck: true });
44
- if (!appConfig.models || appConfig.models.length === 0) {
45
- console.error("No models found in configuration.");
46
- process.exit(1);
47
- }
48
- for (const model of appConfig.models) {
49
- const platform = model.platform;
50
- console.log(
51
- `${model.name}+${model.variant} (platform: ${platform.name}+${platform.variant})`,
52
- );
37
+ /**
38
+ * CLI entry point. Separated from top-level so that importing this module
39
+ * does not start the application — required for code-coverage smoke tests.
40
+ *
41
+ * @param {string[]} argv - Typically `process.argv`.
42
+ */
43
+ export async function main(argv = process.argv) {
44
+ const cliArgs = parseCliArgs(argv);
45
+ if (cliArgs.subcommand.type === "help") {
46
+ printHelp();
53
47
  }
54
- process.exit(0);
55
- }
56
48
 
57
- if (cliArgs.subcommand.type === "install-claude-code-plugins") {
58
- await installClaudeCodePlugins();
59
- process.exit(0);
60
- }
61
-
62
- if (cliArgs.subcommand.type === "cost") {
63
- try {
64
- const exitCode = await runCostCommand({
65
- from: cliArgs.subcommand.from,
66
- to: cliArgs.subcommand.to,
67
- });
68
- process.exit(exitCode);
69
- } catch (err) {
70
- const message = err instanceof Error ? err.message : String(err);
71
- console.error(message);
72
- process.exit(1);
49
+ if (cliArgs.subcommand.type === "list-models") {
50
+ const { appConfig } = await loadAppConfig({ skipTrustCheck: true });
51
+ if (!appConfig.models || appConfig.models.length === 0) {
52
+ console.error("No models found in configuration.");
53
+ process.exit(1);
54
+ }
55
+ for (const model of appConfig.models) {
56
+ const platform = model.platform;
57
+ console.log(
58
+ `${model.name}+${model.variant} (platform: ${platform.name}+${platform.variant})`,
59
+ );
60
+ }
61
+ process.exit(0);
73
62
  }
74
- }
75
63
 
76
- if (cliArgs.subcommand.type === "resume" && cliArgs.subcommand.list) {
77
- const sessions = await listSessions();
78
- if (sessions.length === 0) {
79
- console.log("No resumable sessions in .plain-agent/sessions/.");
64
+ if (cliArgs.subcommand.type === "install-claude-code-plugins") {
65
+ await installClaudeCodePlugins();
80
66
  process.exit(0);
81
67
  }
82
- console.log("Resumable sessions (most recently updated first):\n");
83
- for (const s of sessions) {
84
- console.log(
85
- ` ${s.sessionId} ${s.modelName} (updated ${formatLocalDateTime(s.lastUpdatedAt)}, ${s.messageCount} messages)`,
86
- );
87
- if (s.workingDir !== process.cwd()) {
88
- console.log(` workingDir: ${s.workingDir}`);
68
+
69
+ if (cliArgs.subcommand.type === "cost") {
70
+ try {
71
+ const exitCode = await runCostCommand({
72
+ from: cliArgs.subcommand.from,
73
+ to: cliArgs.subcommand.to,
74
+ });
75
+ process.exit(exitCode);
76
+ } catch (err) {
77
+ const message = err instanceof Error ? err.message : String(err);
78
+ console.error(message);
79
+ process.exit(1);
89
80
  }
90
81
  }
91
- process.exit(0);
92
- }
93
82
 
94
- (async () => {
83
+ if (cliArgs.subcommand.type === "resume" && cliArgs.subcommand.list) {
84
+ const sessions = await listSessions();
85
+ if (sessions.length === 0) {
86
+ console.log("No resumable sessions in .plain-agent/sessions/.");
87
+ process.exit(0);
88
+ }
89
+ console.log("Resumable sessions (most recently updated first):\n");
90
+ for (const s of sessions) {
91
+ console.log(
92
+ ` ${s.sessionId} ${s.modelName} (updated ${formatLocalDateTime(s.lastUpdatedAt)}, ${s.messageCount} messages)`,
93
+ );
94
+ if (s.workingDir !== process.cwd()) {
95
+ console.log(` workingDir: ${s.workingDir}`);
96
+ }
97
+ }
98
+ process.exit(0);
99
+ }
100
+
95
101
  /** @type {SessionState | null} */
96
102
  let resumedState = null;
97
103
 
@@ -430,10 +436,7 @@ if (cliArgs.subcommand.type === "resume" && cliArgs.subcommand.list) {
430
436
  voiceInput: appConfig.voiceInput,
431
437
  });
432
438
  }
433
- })().catch((err) => {
434
- console.error(err);
435
- process.exit(1);
436
- });
439
+ }
437
440
 
438
441
  /**
439
442
  * Generate a session id of the form `YYYY-MM-DD-HHMM-<3 random base36 chars>`.
package/src/prompt.mjs CHANGED
@@ -70,6 +70,10 @@ Memory files should include:
70
70
 
71
71
  Call multiple tools at once when they don't depend on each other's results.
72
72
 
73
+ ## patch_file
74
+
75
+ Always read the target lines with \`read_file\` first to verify line numbers and their 2-char hashes before calling \`patch_file\`.
76
+
73
77
  ## exec_command
74
78
 
75
79
  - Use relative paths.