@iinm/plain-agent 1.14.1 → 1.14.3

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
@@ -1,7 +1,7 @@
1
1
  # Plain Agent
2
2
 
3
3
  [![CodeQL](https://github.com/iinm/plain-agent/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/iinm/plain-agent/actions/workflows/github-code-scanning/codeql)
4
- [![Socket Badge](https://badge.socket.dev/npm/package/@iinm/plain-agent/1.14.1)](https://socket.dev/npm/package/@iinm/plain-agent)
4
+ [![Socket Badge](https://badge.socket.dev/npm/package/@iinm/plain-agent/1.14.3)](https://socket.dev/npm/package/@iinm/plain-agent)
5
5
  [![install size](https://packagephobia.com/badge?p=@iinm/plain-agent)](https://packagephobia.com/result?p=@iinm/plain-agent)
6
6
 
7
7
  A lightweight terminal-based coding agent focused on safety and low token cost
@@ -455,6 +455,14 @@ Create a configuration file.
455
455
  "cache_read_input_tokens": 0.11,
456
456
  "cache_creation_input_tokens": 1.375
457
457
  }
458
+ },
459
+ // Required for soft limit (auto-compact) to work
460
+ "autoCompact": {
461
+ "inputTokensKeys": [
462
+ "input_tokens",
463
+ "cache_read_input_tokens",
464
+ "cache_creation_input_tokens"
465
+ ]
458
466
  }
459
467
  },
460
468
  {
@@ -482,6 +490,14 @@ Create a configuration file.
482
490
  "cache_read_input_tokens": 0.33,
483
491
  "cache_creation_input_tokens": 4.125
484
492
  }
493
+ },
494
+ // Required for soft limit (auto-compact) to work
495
+ "autoCompact": {
496
+ "inputTokensKeys": [
497
+ "input_tokens",
498
+ "cache_read_input_tokens",
499
+ "cache_creation_input_tokens"
500
+ ]
485
501
  }
486
502
  }
487
503
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iinm/plain-agent",
3
- "version": "1.14.1",
3
+ "version": "1.14.3",
4
4
  "description": "A lightweight terminal-based coding agent focused on safety and low token cost",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/agentLoop.mjs CHANGED
@@ -109,6 +109,7 @@ export function createAgentLoop({
109
109
  let thinkingLoops = 0;
110
110
  const maxThinkingLoops = 5;
111
111
  let turnsAfterCompactPrompt = -1;
112
+ let turnsSinceSubagentReminder = 0;
112
113
  while (true) {
113
114
  // Check if auto-approve was paused by Ctrl-C during tool execution
114
115
  if (pauseSignal.isPaused()) {
@@ -262,6 +263,9 @@ export function createAgentLoop({
262
263
  stateManager.appendMessages([{ role: "user", content: toolResults }]);
263
264
  }
264
265
 
266
+ // Subagent reminder: every 5 turns, remind the model of its subagent role
267
+ let autoCompactFired = false;
268
+
265
269
  // Auto-compact: insert prompt if context exceeds soft limit
266
270
  if (contextSoftLimit && inputTokensKeys && providerTokenUsage) {
267
271
  const inputTokens = extractInputTokenCount(
@@ -286,6 +290,7 @@ export function createAgentLoop({
286
290
  },
287
291
  ]);
288
292
  turnsAfterCompactPrompt = 0;
293
+ autoCompactFired = true;
289
294
  console.error(
290
295
  styleText(
291
296
  "yellow",
@@ -295,6 +300,27 @@ export function createAgentLoop({
295
300
  }
296
301
  }
297
302
  }
303
+
304
+ if (!subagentManager.isSubagentActive()) {
305
+ turnsSinceSubagentReminder = 0;
306
+ } else if (!autoCompactFired) {
307
+ turnsSinceSubagentReminder += 1;
308
+ // Inject reminder every 5 turns (fires when counter reaches 5, 10, 15, ...)
309
+ if (turnsSinceSubagentReminder % 5 === 0) {
310
+ const activeSubagent = subagentManager.getActiveSubagent();
311
+ stateManager.appendMessages([
312
+ {
313
+ role: "user",
314
+ content: [
315
+ {
316
+ type: "text",
317
+ text: `System: You are subagent "${activeSubagent?.name}". Call "switch_to_main_agent" when your goal is done.`,
318
+ },
319
+ ],
320
+ },
321
+ ]);
322
+ }
323
+ }
298
324
  }
299
325
  }
300
326
 
package/src/config.mjs CHANGED
@@ -234,6 +234,20 @@ async function trustConfigHash(hash) {
234
234
  await fs.writeFile(path.join(TRUSTED_CONFIG_HASHES_DIR, hash), "");
235
235
  }
236
236
 
237
+ /**
238
+ * Check whether auto-compact is effectively disabled because the model
239
+ * definition lacks `autoCompact.inputTokensKeys`.
240
+ *
241
+ * @param {number | undefined} contextSoftLimit
242
+ * @param {string[] | undefined} inputTokensKeys
243
+ * @returns {boolean}
244
+ */
245
+ export function isAutoCompactMisconfigured(contextSoftLimit, inputTokensKeys) {
246
+ return Boolean(
247
+ contextSoftLimit && (!inputTokensKeys || inputTokensKeys.length === 0),
248
+ );
249
+ }
250
+
237
251
  /**
238
252
  * Resolve the effective context soft limit for the given model.
239
253
  *
package/src/main.mjs CHANGED
@@ -16,7 +16,11 @@ import { startBatchSession } from "./cli/batch.mjs";
16
16
  import { runCostCommand } from "./cli/cost.mjs";
17
17
  import { startInteractiveSession } from "./cli/interactive.mjs";
18
18
  import { runTestApprovalCommand } from "./cli/testApproval.mjs";
19
- import { loadAppConfig, resolveContextSoftLimit } from "./config.mjs";
19
+ import {
20
+ isAutoCompactMisconfigured,
21
+ loadAppConfig,
22
+ resolveContextSoftLimit,
23
+ } from "./config.mjs";
20
24
  import { loadAgentRoles } from "./context/loadAgentRoles.mjs";
21
25
  import { loadPrompts } from "./context/loadPrompts.mjs";
22
26
  import { AGENT_PROJECT_METADATA_DIR, USER_NAME } from "./env.mjs";
@@ -434,6 +438,16 @@ export async function main(argv = process.argv) {
434
438
  modelNameWithVariant,
435
439
  );
436
440
 
441
+ const inputTokensKeys = modelDef.autoCompact?.inputTokensKeys;
442
+ if (isAutoCompactMisconfigured(contextSoftLimit, inputTokensKeys)) {
443
+ console.error(
444
+ styleText(
445
+ "yellow",
446
+ `⚠️ autoCompact.softLimit is set but model "${modelNameWithVariant}" has no autoCompact.inputTokensKeys.`,
447
+ ),
448
+ );
449
+ }
450
+
437
451
  const { userEventEmitter, agentEventEmitter, agentCommands } = createAgent({
438
452
  callModel: agentCallModel,
439
453
  prompt,
@@ -449,7 +463,7 @@ export async function main(argv = process.argv) {
449
463
  },
450
464
  initialState: resumedState,
451
465
  contextSoftLimit,
452
- inputTokensKeys: modelDef.autoCompact?.inputTokensKeys,
466
+ inputTokensKeys,
453
467
  });
454
468
 
455
469
  const sessionOptions = {