@agfpd/iapeer 0.4.119 → 0.4.120

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agfpd/iapeer",
3
- "version": "0.4.119",
3
+ "version": "0.4.120",
4
4
  "description": "Run Claude Code and Codex CLI as local background agents that message each other, wake on demand, and share one memory.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "agfpd",
@@ -1080,12 +1080,31 @@ export interface ControlResult {
1080
1080
  * "specify runtime"). The clean-slash control namespace (interrupt/compact/…) is the
1081
1081
  * caller's; /alias_* expansions are message, not control (docs/Control §namespace).
1082
1082
  */
1083
+ /**
1084
+ * Which session an operator control (interrupt / compact / …) WITHOUT a runtime acts on. An operator
1085
+ * commands the DIALOGUE they see, not a session they must name: the dialogue a runtime-less send
1086
+ * reaches is the peer's default_runtime (config-anchored, resolvePeerDeliveryTarget), so a LIVE
1087
+ * default wins even when other runtimes are live too (incident 18.10: /stop on a peer with claude AND
1088
+ * opencode live answered «specify runtime» while the opencode turn ran on). A dead default with
1089
+ * exactly one live endpoint → that one (the only running session). Only a dead default with SEVERAL
1090
+ * live endpoints stays ambiguous → explicit refusal. An explicit runtime is exact.
1091
+ */
1092
+ export function resolveControlTarget(personality: string, runtime: string | undefined, env: NodeJS.ProcessEnv = process.env): Result<DeliveryTarget> {
1093
+ if (runtime) return resolveDeliveryTarget({ personality, runtime, env })
1094
+ const peer = findPeer(readPeersIndex({ env }), personality)
1095
+ if (peer) {
1096
+ const anchored = resolveDeliveryTarget({ personality, runtime: peer.runtime, env })
1097
+ if (anchored.ok) return anchored
1098
+ }
1099
+ return resolveDeliveryTarget({ personality, env })
1100
+ }
1101
+
1083
1102
  export async function routeControl(personality: string, runtime: string | undefined, command: ControlCommand): Promise<Result<ControlResult>> {
1084
1103
  if (!isValidName(personality)) {
1085
1104
  return err(`invalid personality "${personality}" — must match /^[a-z][a-z0-9-]{0,31}$/`)
1086
1105
  }
1087
1106
  if (runtime && !isRuntime(runtime)) return err(`invalid runtime "${runtime}"`)
1088
- const target = resolveDeliveryTarget({ personality, runtime })
1107
+ const target = resolveControlTarget(personality, runtime)
1089
1108
  if (!target.ok) return err(`cannot control "${personality}": ${target.error.message}`)
1090
1109
  const done = await executeControlOnTarget(target.value, command)
1091
1110
  if (!done.ok) return done