external-subagent 0.6.5 → 0.6.6

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
@@ -159,11 +159,16 @@ from the available set.
159
159
  | `permission_mode` | `build`, `edit`, `plan`, or `yolo`; defaults to `build` when unset |
160
160
  | `developer_instructions` | Free-form instructions, delivered as described below |
161
161
 
162
- `--profile` cannot be combined with `--subagent`, `--model`, `--effort`, or
163
- `--permission_mode`; put those in the profile JSON or omit `profile`. Fields
162
+ `--profile` cannot be combined with `--subagent`, `--model`, `--effort`,
163
+ `--developer-instructions`, or `--permission-mode`; put those in the profile
164
+ JSON or omit `profile`. Fields
164
165
  left out of the profile fall back to the same defaults as an unprofiled
165
- spawn. `developer_instructions` rides the codex runtime's native
166
- `developerInstructions` channel when the effective subagent is `codex`; every
166
+ spawn. `developer_instructions` is also accepted as a per-spawn parameter
167
+ (`--developer-instructions` on the CLI, `developer_instructions` in the MCP
168
+ and daemon RPC spawn inputs) with identical delivery semantics; the codex
169
+ runtime's native
170
+ `developerInstructions` channel carries it when the effective subagent is
171
+ `codex`; every
167
172
  other subagent receives it silently concatenated in front of the prompt:
168
173
 
169
174
  ```
@@ -2,7 +2,7 @@ import fs from 'node:fs';
2
2
  import { CliError } from '../errors.mjs';
3
3
  import { profilesDir } from '../paths.mjs';
4
4
 
5
- const SPAWN_FIELDS = new Set(['profile', 'subagent', 'repository', 'permission_mode', 'prompt', 'model', 'effort', 'write_manifest']);
5
+ const SPAWN_FIELDS = new Set(['profile', 'subagent', 'repository', 'permission_mode', 'prompt', 'model', 'effort', 'developer_instructions', 'write_manifest']);
6
6
  const FLAG_FIELDS = new Map([
7
7
  ['--profile', 'profile'],
8
8
  ['--subagent', 'subagent'],
@@ -11,9 +11,10 @@ const FLAG_FIELDS = new Map([
11
11
  ['--permission-mode', 'permission_mode'],
12
12
  ['--model', 'model'],
13
13
  ['--effort', 'effort'],
14
+ ['--developer-instructions', 'developer_instructions'],
14
15
  ]);
15
16
 
16
- const PROFILE_MUTEX_ERROR = 'profile cannot be combined with subagent, permission_mode, model, or effort; specify these in the profile JSON or omit profile';
17
+ const PROFILE_MUTEX_ERROR = 'profile cannot be combined with subagent, permission_mode, model, effort, or developer_instructions; specify these in the profile JSON or omit profile';
17
18
 
18
19
  function flagValue(args, option) {
19
20
  const value = args.shift();
@@ -38,7 +39,7 @@ export function parseSpawnArgs(args) {
38
39
  input[field] = flagValue(remaining, option);
39
40
  }
40
41
  if (Object.hasOwn(input, 'profile')) {
41
- if (Object.hasOwn(input, 'subagent') || Object.hasOwn(input, 'permission_mode') || Object.hasOwn(input, 'model') || Object.hasOwn(input, 'effort')) {
42
+ if (Object.hasOwn(input, 'subagent') || Object.hasOwn(input, 'permission_mode') || Object.hasOwn(input, 'model') || Object.hasOwn(input, 'effort') || Object.hasOwn(input, 'developer_instructions')) {
42
43
  throw new CliError('INVALID_ARGUMENT', PROFILE_MUTEX_ERROR, 2);
43
44
  }
44
45
  }
@@ -59,7 +60,7 @@ export function prepareSpawnInput(input) {
59
60
  throw new CliError('INVALID_ARGUMENT', 'profile must be a non-empty string', 2);
60
61
  }
61
62
  if (input.profile !== undefined) {
62
- if (input.subagent !== undefined || input.permission_mode !== undefined || input.model !== undefined || input.effort !== undefined) {
63
+ if (input.subagent !== undefined || input.permission_mode !== undefined || input.model !== undefined || input.effort !== undefined || input.developer_instructions !== undefined) {
63
64
  throw new CliError('INVALID_ARGUMENT', PROFILE_MUTEX_ERROR, 2);
64
65
  }
65
66
  }
@@ -81,6 +82,15 @@ export function prepareSpawnInput(input) {
81
82
  if (input.effort !== undefined && (typeof input.effort !== 'string' || input.effort.length === 0)) {
82
83
  throw new CliError('INVALID_ARGUMENT', 'effort must be a non-empty string', 2);
83
84
  }
85
+ // Mirrors the daemon's spawn-parameter normalization: null is rejected on
86
+ // the wire, an empty/whitespace-only string stays accepted here (the daemon
87
+ // treats it as "not provided").
88
+ if (Object.prototype.hasOwnProperty.call(input, 'developer_instructions') && input.developer_instructions === null) {
89
+ throw new CliError('INVALID_ARGUMENT', 'developer_instructions must be omitted or a non-null string', 2);
90
+ }
91
+ if (input.developer_instructions !== undefined && typeof input.developer_instructions !== 'string') {
92
+ throw new CliError('INVALID_ARGUMENT', 'developer_instructions must be a string', 2);
93
+ }
84
94
  return { ...input };
85
95
  }
86
96
 
package/cli/constants.mjs CHANGED
@@ -12,7 +12,7 @@ const IS_DEBUG_VARIANT = process.env.EXTERNAL_SUBAGENT_VARIANT === 'debug';
12
12
 
13
13
  export const PRODUCT_NAME = IS_DEBUG_VARIANT ? 'external-subagent-debug' : 'external-subagent';
14
14
  export const PRODUCT_ID = IS_DEBUG_VARIANT ? 'external_subagent_debug' : 'external_subagent';
15
- export const VERSION = '0.6.5';
15
+ export const VERSION = '0.6.6';
16
16
  export const LAUNCH_AGENT_LABEL = IS_DEBUG_VARIANT ? 'com.external-subagent-debug.daemon' : 'com.external-subagent.daemon';
17
17
  export const DAEMON_BIN_NAME = IS_DEBUG_VARIANT ? 'external-subagent-debugd' : 'external-subagentd';
18
18
  export const MCP_BIN_NAME = IS_DEBUG_VARIANT ? 'external-subagent-debug-mcp' : 'external-subagent-mcp';
package/cli/rpc.mjs CHANGED
@@ -66,7 +66,7 @@ function readJsonInput(args) {
66
66
  function requestId() { return `cli-${process.pid}-${crypto.randomUUID()}`; }
67
67
 
68
68
  function manifest(input) {
69
- const allowed = new Set(['profile', 'subagent', 'repository', 'permission_mode', 'prompt', 'model', 'effort', 'write_manifest']);
69
+ const allowed = new Set(['profile', 'subagent', 'repository', 'permission_mode', 'prompt', 'model', 'effort', 'developer_instructions', 'write_manifest']);
70
70
  for (const key of Object.keys(input)) {
71
71
  if (!allowed.has(key)) throw new CliError('INVALID_ARGUMENT', `spawn contains unsupported field: ${key}`, 2);
72
72
  }
@@ -74,6 +74,7 @@ function manifest(input) {
74
74
  if (input.subagent !== undefined && (typeof input.subagent !== 'string' || input.subagent.length === 0)) throw new CliError('INVALID_ARGUMENT', 'subagent must be a non-empty string', 2);
75
75
  if (input.model !== undefined && (typeof input.model !== 'string' || input.model.length === 0)) throw new CliError('INVALID_ARGUMENT', 'model must be a non-empty string', 2);
76
76
  if (input.effort !== undefined && (typeof input.effort !== 'string' || input.effort.length === 0)) throw new CliError('INVALID_ARGUMENT', 'effort must be a non-empty string', 2);
77
+ if (input.developer_instructions !== undefined && (typeof input.developer_instructions !== 'string')) throw new CliError('INVALID_ARGUMENT', 'developer_instructions must be a string', 2);
77
78
  if (typeof input.repository !== 'string' || input.repository.length === 0 || typeof input.prompt !== 'string' || input.prompt.length === 0) throw new CliError('INVALID_ARGUMENT', 'create requires non-empty repository and prompt strings', 2);
78
79
  if (input.permission_mode !== undefined && (typeof input.permission_mode !== 'string' || input.permission_mode.length === 0)) throw new CliError('INVALID_ARGUMENT', 'permission_mode must be a non-empty string', 2);
79
80
  if (input.write_manifest !== undefined && (!Array.isArray(input.write_manifest) || input.write_manifest.some((value) => typeof value !== 'string' || value.length === 0))) throw new CliError('INVALID_ARGUMENT', 'write_manifest must contain non-empty strings', 2);
@@ -117,6 +118,7 @@ function methodFor(command, input) {
117
118
  ...(input.subagent !== undefined ? { subagent: input.subagent } : {}),
118
119
  ...(input.model !== undefined ? { model: input.model } : {}),
119
120
  ...(input.effort !== undefined ? { effort: input.effort } : {}),
121
+ ...(input.developer_instructions !== undefined ? { developer_instructions: input.developer_instructions } : {}),
120
122
  manifest: manifest(input),
121
123
  },
122
124
  };
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "product": "external-subagent",
4
- "version": "0.6.5",
4
+ "version": "0.6.6",
5
5
  "platform": "darwin-arm64",
6
6
  "files": [
7
7
  {
8
8
  "name": "external-subagentd",
9
- "bytes": 10503712,
9
+ "bytes": 10499872,
10
10
  "mode": "755",
11
- "sha256": "1a9516144d5eeda7d88383278f3a60ac8cedc8f374e5829d46462426a2fb4854"
11
+ "sha256": "0e0818026b3e67b4fc4f70c3afb5c04c876cc49cc0cf90727ad6e37ec897e916"
12
12
  },
13
13
  {
14
14
  "name": "external-subagent-mcp",
15
15
  "bytes": 935776,
16
16
  "mode": "755",
17
- "sha256": "23ffb90714a6574f313cd9fc79d8e25aa5b35c6f5020e53992229320168cdf78"
17
+ "sha256": "2162051fd153973fcdbada5dfbcc64f2faf46fc1b68043354fec86eb5b8c2050"
18
18
  }
19
19
  ]
20
20
  }
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "product": "external-subagent",
4
- "version": "0.6.5",
4
+ "version": "0.6.6",
5
5
  "platform": "linux-x64",
6
6
  "files": [
7
7
  {
8
8
  "name": "external-subagentd",
9
- "bytes": 12083304,
9
+ "bytes": 12082480,
10
10
  "mode": "755",
11
- "sha256": "68212a7873f8428d1cbe18137e689655b0402a92b9fc5f0710e5712766d24e4c"
11
+ "sha256": "4f7dd7d42b910990cd48424da9bfbcbbbdfa694ee1deca24ac00634cbe8895e6"
12
12
  },
13
13
  {
14
14
  "name": "external-subagent-mcp",
15
- "bytes": 1025456,
15
+ "bytes": 1025544,
16
16
  "mode": "755",
17
- "sha256": "7a95f5dea50ed52dc2167c1885ca887edae5ecfc188c4535e2d223d835374268"
17
+ "sha256": "f27f18ed61abe278bdb878f5b7f9a4b5d66be4995c9f147a66ea4cf5c086bd39"
18
18
  }
19
19
  ]
20
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "external-subagent",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "Manage bounded ZCode, DeepSeek Harness (DSH), Codex, and Google Antigravity (agy) subagent tasks through a local MCP service for any local host (Codex, ZCode, or a custom MCP client)",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -198,7 +198,7 @@
198
198
  "profile": {
199
199
  "type": "string",
200
200
  "minLength": 1,
201
- "description": "Profile name referencing a JSON preset in profiles/*.json. Mutually exclusive with subagent, permission_mode, model, and effort."
201
+ "description": "Profile name referencing a JSON preset in profiles/*.json. Mutually exclusive with subagent, permission_mode, model, effort, and developer_instructions."
202
202
  },
203
203
  "subagent": {
204
204
  "type": "string",
@@ -229,6 +229,11 @@
229
229
  "pattern": "^[a-z0-9_]+$",
230
230
  "description": "Reasoning-effort token: 1..24 bytes of [a-z0-9_]. codex admits only low, medium, high or xhigh; agy admits only low, medium, high or max; zcode and dsh pass the bounded token through. Omission keeps the runtime default."
231
231
  },
232
+ "developer_instructions": {
233
+ "type": "string",
234
+ "maxLength": 1048576,
235
+ "description": "Per-task developer instructions (at most 1 MiB). codex routes them through the native developerInstructions channel on thread/start (prompt stays verbatim); every other subagent splices them as a 'Developer Instructions:' prefix block ahead of the prompt. A trimmed-empty string means not provided (no admission effect). Mutually exclusive with profile: profiles carry their own developer_instructions. The spliced prompt stays under the shared 256 KiB prompt bound, which rejects the spawn before task creation; oversized developer_instructions are themselves rejected with validation before any task."
236
+ },
232
237
  "write_manifest": {
233
238
  "type": "array",
234
239
  "items": {
@@ -614,6 +619,7 @@
614
619
  "prompt",
615
620
  "model",
616
621
  "effort",
622
+ "developer_instructions",
617
623
  "write_manifest"
618
624
  ],
619
625
  "output": [