@ctliz/agent-intercom-codex 0.11.0-connect.2 → 0.12.0-connect.1

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/codex/runtime.ts CHANGED
@@ -95,13 +95,28 @@ function shortHash(value: string): string {
95
95
  return createHash("sha256").update(value).digest("hex").slice(0, 8);
96
96
  }
97
97
 
98
+ const GENERIC_SESSION_ID_REGEX = /^[A-Za-z0-9_-]{1,128}$/;
99
+
98
100
  export function buildCodexRuntimeIdentity(env: NodeJS.ProcessEnv = process.env, cwd = env.PWD || processCwd(), pid = process.pid): CodexRuntimeIdentity {
99
- const sessionId = env.CODEX_INTERCOM_SESSION_ID?.trim()
100
- || env.CODEX_PEER_ID?.trim()
101
- || `codex-${pid}-${shortHash(cwd)}`;
101
+ let sessionId = env.CODEX_INTERCOM_SESSION_ID?.trim()
102
+ || env.CODEX_PEER_ID?.trim();
103
+ if (!sessionId && env.AGENT_INTERCOM_SESSION_ID !== undefined) {
104
+ const raw = env.AGENT_INTERCOM_SESSION_ID.trim();
105
+ if (raw) {
106
+ if (!GENERIC_SESSION_ID_REGEX.test(raw)) {
107
+ throw new Error("Invalid AGENT_INTERCOM_SESSION_ID: must match ^[A-Za-z0-9_-]{1,128}$");
108
+ }
109
+ sessionId = raw;
110
+ }
111
+ }
112
+ if (!sessionId) {
113
+ sessionId = `codex-${pid}-${shortHash(cwd)}`;
114
+ }
115
+
102
116
  const cwdName = basename(cwd) || "workspace";
103
117
  const name = env.CODEX_INTERCOM_NAME?.trim()
104
118
  || env.CODEX_PEER_NAME?.trim()
119
+ || (env.AGENT_INTERCOM_SESSION_NAME !== undefined && env.AGENT_INTERCOM_SESSION_NAME.trim() ? env.AGENT_INTERCOM_SESSION_NAME.trim() : undefined)
105
120
  || `codex-${cwdName}-${pid}`;
106
121
  return {
107
122
  sessionId,
package/codex/team.ts CHANGED
@@ -8,10 +8,15 @@ import {
8
8
  workerIdentityFromEnvironment,
9
9
  type WorkerIdentityV2,
10
10
  } from "@ctliz/agent-intercom-core/boss";
11
+ import { readTeamManifestAsync, TeamManifestError } from "@ctliz/agent-intercom-core/team-manifest";
12
+
13
+ export type TeamSource = "orchestrator" | "boss" | "manifest" | "live" | "standalone";
11
14
 
12
15
  export interface TeamSession {
13
16
  id: string;
14
17
  name?: string;
18
+ model?: string;
19
+ origin?: "local" | "remote";
15
20
  boss?: {
16
21
  binding?: {
17
22
  bossRunId?: unknown;
@@ -43,8 +48,22 @@ interface StoredWorker {
43
48
  canonicalIdentity?: WorkerIdentityV2;
44
49
  }
45
50
 
46
- export interface TeamMember { id: string; target: string; harness?: string; role?: string; state?: string; connected: boolean; }
47
- export interface IntercomTeam { teamId?: string; self: { id: string; workerId?: string; isManager: boolean }; manager?: { target: string; connected: boolean }; coworkers: TeamMember[]; }
51
+ export interface TeamMember {
52
+ id: string;
53
+ target: string;
54
+ harness?: string;
55
+ role?: string;
56
+ state?: string;
57
+ connected: boolean;
58
+ }
59
+
60
+ export interface IntercomTeam {
61
+ teamId?: string;
62
+ self: { id: string; workerId?: string; isManager: boolean };
63
+ manager?: { target: string; connected: boolean };
64
+ coworkers: TeamMember[];
65
+ source: TeamSource;
66
+ }
48
67
 
49
68
  const LEGACY_LIVE_STATES = new Set(["provisioning", "running", "idle", "needs_attention", "stopping"]);
50
69
  const CANONICAL_LIVE_STATES = new Set(["provisioning", "registering", "ready", "working", "waiting", "paused", "stalled", "blocked", "unreachable"]);
@@ -54,12 +73,26 @@ const connectedTo = (sessions: TeamSession[], target: string): boolean => {
54
73
  return sessions.some((session) => session.id === target || session.name?.toLowerCase() === normalized);
55
74
  };
56
75
 
76
+ function hasBossEnvironmentKeys(env: NodeJS.ProcessEnv): boolean {
77
+ const bossKeys = [
78
+ "AGENT_INTERCOM_BOSS_RUN_ID",
79
+ "AGENT_INTERCOM_PARTICIPANT_ID",
80
+ "AGENT_INTERCOM_BINDING_EPOCH",
81
+ "AGENT_INTERCOM_WORKER_INCARNATION_ID",
82
+ "AGENT_INTERCOM_WORKER_GENERATION",
83
+ ] as const;
84
+ return bossKeys.some((key) => env[key] !== undefined);
85
+ }
86
+
57
87
  function bossIdentityFromEnvironment(env: NodeJS.ProcessEnv): WorkerIdentityV2 | undefined {
58
- const bossKeys = ["AGENT_INTERCOM_BOSS_RUN_ID", "AGENT_INTERCOM_PARTICIPANT_ID", "AGENT_INTERCOM_BINDING_EPOCH"] as const;
59
- if (!bossKeys.some((key) => env[key] !== undefined)) return undefined;
60
- const identity = workerIdentityFromEnvironment(env);
61
- if (!("bossRunId" in identity)) throw new Error("Incomplete Boss worker identity cannot discover a team");
62
- return identity;
88
+ if (!hasBossEnvironmentKeys(env)) return undefined;
89
+ try {
90
+ const identity = workerIdentityFromEnvironment(env);
91
+ if (!("bossRunId" in identity)) return undefined;
92
+ return identity;
93
+ } catch {
94
+ return undefined;
95
+ }
63
96
  }
64
97
 
65
98
  function canonicalWorker(value: unknown): StoredWorker {
@@ -133,17 +166,123 @@ async function readWorkers(agentDir: string): Promise<{ version: 1 | 2; workers:
133
166
  }
134
167
  }
135
168
 
169
+ async function resolveNonAuthoritativeTeam(
170
+ input: { selfId: string; sessions: TeamSession[] },
171
+ env: NodeJS.ProcessEnv,
172
+ ): Promise<IntercomTeam> {
173
+ if (env.AGENT_INTERCOM_TEAM_MANIFEST !== undefined) {
174
+ const rawPath = env.AGENT_INTERCOM_TEAM_MANIFEST.trim();
175
+ if (!rawPath) {
176
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
177
+ }
178
+ const manifest = await readTeamManifestAsync(rawPath);
179
+ if (!manifest) {
180
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
181
+ }
182
+ const selfMember = manifest.members.find((m) => m.sessionId === input.selfId);
183
+ if (!selfMember) {
184
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
185
+ }
186
+
187
+ const isManager = input.selfId === manifest.leadId;
188
+ const managerTarget = manifest.leadId;
189
+ const managerConnected = connectedTo(input.sessions, managerTarget);
190
+
191
+ const coworkers: TeamMember[] = manifest.members
192
+ .filter((m) => m.sessionId !== input.selfId)
193
+ .filter((m) => isManager || m.sessionId !== managerTarget)
194
+ .map((m) => {
195
+ const live = input.sessions.find((s) => s.id === m.sessionId || s.name === m.sessionId);
196
+ return {
197
+ id: m.sessionId,
198
+ target: m.sessionId,
199
+ role: m.role,
200
+ connected: Boolean(live),
201
+ };
202
+ });
203
+
204
+ return {
205
+ teamId: manifest.runId,
206
+ self: { id: input.selfId, isManager },
207
+ manager: { target: managerTarget, connected: managerConnected },
208
+ coworkers,
209
+ source: "manifest",
210
+ };
211
+ }
212
+
213
+ if (stringValue(env.AGENT_INTERCOM_SCOPE_ID)) {
214
+ const managerTarget = stringValue(env.AGENT_INTERCOM_MANAGER_TARGET)
215
+ ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
216
+ const role = stringValue(env.AGENT_INTERCOM_ROLE)?.toLowerCase();
217
+
218
+ const isManager = role === "manager"
219
+ || (managerTarget !== undefined && managerTarget === input.selfId)
220
+ || (managerTarget === undefined && role !== "worker");
221
+
222
+ const effectiveManagerTarget = isManager ? input.selfId : managerTarget;
223
+
224
+ const coworkers: TeamMember[] = input.sessions
225
+ .filter((session) => session.id !== input.selfId)
226
+ .filter((session) => session.model !== "human")
227
+ .filter((session) => session.id !== effectiveManagerTarget)
228
+ .map((session): TeamMember => ({
229
+ id: session.id,
230
+ target: session.id,
231
+ ...(session.model ? { harness: session.model } : {}),
232
+ connected: true,
233
+ }));
234
+
235
+ const manager = effectiveManagerTarget
236
+ ? {
237
+ target: effectiveManagerTarget,
238
+ connected: isManager ? true : connectedTo(input.sessions, effectiveManagerTarget),
239
+ }
240
+ : undefined;
241
+
242
+ return {
243
+ teamId: effectiveManagerTarget ?? input.selfId,
244
+ self: { id: input.selfId, isManager },
245
+ ...(manager ? { manager } : {}),
246
+ coworkers,
247
+ source: "live",
248
+ };
249
+ }
250
+
251
+ const managerTarget = stringValue(env.AGENT_INTERCOM_MANAGER_TARGET)
252
+ ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
253
+ return {
254
+ teamId: managerTarget ?? input.selfId,
255
+ self: { id: input.selfId, isManager: !managerTarget },
256
+ manager: managerTarget
257
+ ? { target: managerTarget, connected: connectedTo(input.sessions, managerTarget) }
258
+ : { target: input.selfId, connected: true },
259
+ coworkers: [],
260
+ source: "standalone",
261
+ };
262
+ }
263
+
136
264
  export async function resolveIntercomTeam(input: { selfId: string; sessions: TeamSession[]; env?: NodeJS.ProcessEnv; agentDir?: string }): Promise<IntercomTeam> {
137
265
  const env = input.env ?? process.env;
138
266
  const snapshot = await readWorkers(input.agentDir ?? getAgentDirPath());
139
267
  const workers = snapshot.workers;
140
268
  const workerId = stringValue(env.AGENT_INTERCOM_WORKER_ID);
269
+ const selfSession = input.sessions.find((session) => session.id === input.selfId);
270
+ const isBossContext = selfSession?.boss !== undefined || hasBossEnvironmentKeys(env);
141
271
  const bossIdentity = bossIdentityFromEnvironment(env);
142
272
  const runId = stringValue(env.AGENT_INTERCOM_RUN_ID);
273
+
274
+ if (isBossContext && bossIdentity === undefined) {
275
+ return {
276
+ self: { id: input.selfId, ...(workerId ? { workerId } : {}), isManager: false },
277
+ coworkers: [],
278
+ source: "boss",
279
+ };
280
+ }
281
+
143
282
  const currentMatches = workerId ? workers.filter((worker) => (
144
283
  stringValue(worker.id) === workerId
145
284
  && (bossIdentity === undefined
146
- ? (!runId || stringValue(worker.runId) === runId)
285
+ ? (snapshot.version === 1 && (!runId || stringValue(worker.runId) === runId))
147
286
  : snapshot.version === 2
148
287
  && worker.canonicalIdentity?.workerId === bossIdentity.workerId
149
288
  && worker.canonicalIdentity.workerIncarnationId === bossIdentity.workerIncarnationId
@@ -166,13 +305,69 @@ export async function resolveIntercomTeam(input: { selfId: string; sessions: Tea
166
305
  // projection. A substituted self ID, ambiguous ID/target, or stale binding
167
306
  // never unlocks a roster assembled from ambient same-run records.
168
307
  if (bossIdentity !== undefined && !exactCurrentProjection) {
169
- return { self: { id: input.selfId, ...(workerId ? { workerId } : {}), isManager: false }, coworkers: [] };
308
+ return { self: { id: input.selfId, ...(workerId ? { workerId } : {}), isManager: false }, coworkers: [], source: "boss" };
309
+ }
310
+
311
+ if (bossIdentity === undefined && !current) {
312
+ if (workerId === undefined && snapshot.version === 1) {
313
+ const ownedCoworkers = workers
314
+ .filter((worker) => worker.owned === true)
315
+ .filter((worker) => {
316
+ const mgr = stringValue(worker.managerSessionId);
317
+ return mgr !== undefined && mgr === input.selfId;
318
+ })
319
+ .filter((worker) => LEGACY_LIVE_STATES.has(stringValue(worker.state) ?? ""))
320
+ .filter((worker) => stringValue(worker.id) !== input.selfId)
321
+ .map((worker): TeamMember | undefined => {
322
+ const id = stringValue(worker.id);
323
+ if (!id) return undefined;
324
+ const target = stringValue(worker.intercomTarget) ?? id;
325
+ return {
326
+ id,
327
+ target,
328
+ ...(stringValue(worker.harness) ? { harness: stringValue(worker.harness) } : {}),
329
+ ...(stringValue(worker.role) ? { role: stringValue(worker.role) } : {}),
330
+ ...(stringValue(worker.state) ? { state: stringValue(worker.state) } : {}),
331
+ connected: connectedTo(input.sessions, target),
332
+ };
333
+ })
334
+ .filter((member): member is TeamMember => Boolean(member));
335
+
336
+ if (ownedCoworkers.length > 0) {
337
+ return {
338
+ teamId: input.selfId,
339
+ self: { id: input.selfId, isManager: true },
340
+ manager: { target: input.selfId, connected: true },
341
+ coworkers: ownedCoworkers,
342
+ source: "orchestrator",
343
+ };
344
+ }
345
+ }
346
+
347
+ return resolveNonAuthoritativeTeam(input, env);
170
348
  }
171
349
 
172
- const managerTarget = stringValue(current?.managerSessionId)
173
- ?? (bossIdentity === undefined ? stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID) : undefined);
174
- const teamId = managerTarget ?? input.selfId;
175
350
  const currentRole = stringValue(current?.role);
351
+ const selfIsManager = bossIdentity !== undefined
352
+ ? currentRole === "manager"
353
+ : undefined;
354
+
355
+ const managerTarget = bossIdentity !== undefined
356
+ ? (selfIsManager ? input.selfId : stringValue(current?.managerSessionId))
357
+ : stringValue(current?.managerSessionId) ?? stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
358
+
359
+ if (bossIdentity === undefined && !managerTarget) {
360
+ return {
361
+ self: { id: input.selfId, ...(workerId ? { workerId } : {}), isManager: false },
362
+ coworkers: [],
363
+ source: "orchestrator",
364
+ };
365
+ }
366
+
367
+ const teamId = bossIdentity !== undefined
368
+ ? ("bossRunId" in bossIdentity ? bossIdentity.bossRunId : managerTarget ?? input.selfId)
369
+ : (managerTarget ?? input.selfId);
370
+
176
371
  const canDiscoverOwnedRoster = bossIdentity === undefined || currentRole === "manager" || currentRole === "controller";
177
372
  const coworkers = (canDiscoverOwnedRoster ? workers : []).filter((worker) => worker.owned === true)
178
373
  .filter((worker) => bossIdentity === undefined || (
@@ -182,10 +377,10 @@ export async function resolveIntercomTeam(input: { selfId: string; sessions: Tea
182
377
  && "bossRunId" in bossIdentity
183
378
  && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId
184
379
  ))
185
- .filter((worker) => stringValue(worker.managerSessionId) === teamId)
380
+ .filter((worker) => stringValue(worker.managerSessionId) === (bossIdentity !== undefined ? managerTarget : teamId))
186
381
  .filter((worker) => stringValue(worker.intercomTarget) !== managerTarget)
187
382
  .filter((worker) => (snapshot.version === 2 ? CANONICAL_LIVE_STATES : LEGACY_LIVE_STATES).has(stringValue(worker.state) ?? ""))
188
- .filter((worker) => stringValue(worker.id) !== workerId)
383
+ .filter((worker) => stringValue(worker.id) !== workerId && stringValue(worker.id) !== input.selfId)
189
384
  .map((worker): TeamMember | undefined => {
190
385
  const id = stringValue(worker.id);
191
386
  if (!id) return undefined;
@@ -222,16 +417,48 @@ export async function resolveIntercomTeam(input: { selfId: string; sessions: Tea
222
417
  : bossIdentity === undefined
223
418
  ? connectedTo(input.sessions, managerTarget)
224
419
  : managerWorker !== undefined && exactBossRosterSession(input.sessions, managerWorker) !== undefined;
420
+
421
+ const isManager = bossIdentity !== undefined
422
+ ? selfIsManager!
423
+ : false;
424
+
225
425
  return {
226
426
  teamId,
227
- self: { id: input.selfId, ...(workerId ? { workerId } : {}), isManager: bossIdentity === undefined && !managerTarget },
427
+ self: { id: input.selfId, ...(workerId ? { workerId } : {}), isManager },
228
428
  ...(managerTarget
229
- ? { manager: { target: managerTarget, connected: managerConnected } }
230
- : bossIdentity === undefined ? { manager: { target: input.selfId, connected: true } } : {}),
429
+ ? { manager: { target: managerTarget, connected: isManager ? true : managerConnected } }
430
+ : {}),
231
431
  coworkers,
432
+ source: bossIdentity !== undefined ? "boss" : "orchestrator",
232
433
  };
233
434
  }
234
435
 
436
+ /** Authorizes a read-only local inbox lookup using exact orchestrator ownership. */
437
+ export function resolveManagedInboxSession(input: {
438
+ team: IntercomTeam;
439
+ sessions: TeamSession[];
440
+ requestedSession: string;
441
+ }): TeamSession {
442
+ if (input.team.source !== "orchestrator" && input.team.source !== "boss") {
443
+ throw new Error("Pending-ask inbox access denied: cross-session inbox inspection is only permitted for Orchestrator/Boss-managed teams");
444
+ }
445
+ if (!input.team.self.isManager) {
446
+ throw new Error("Only a manager may inspect another session's pending-ask inbox");
447
+ }
448
+ const member = input.team.coworkers.find((entry) => entry.target === input.requestedSession);
449
+ if (!member) {
450
+ throw new Error(`Pending-ask inbox access denied for "${input.requestedSession}"; select an owned coworker target returned by intercom_team`);
451
+ }
452
+ const liveSession = input.sessions.find((session) => session.id === input.requestedSession);
453
+ if (!liveSession) {
454
+ throw new Error(`Pending-ask inbox access denied for "${input.requestedSession}"; the owned coworker target must equal an exact connected stable session ID`);
455
+ }
456
+ if (liveSession.origin === "remote") {
457
+ throw new Error(`Pending-ask inbox "${input.requestedSession}" is remote and cannot be read from this host`);
458
+ }
459
+ return liveSession;
460
+ }
461
+
235
462
  export function formatIntercomTeam(team: IntercomTeam): string {
236
463
  const lines = [
237
464
  `Manager: ${team.manager ? `${team.manager.target} [${team.manager.connected ? "connected" : "not connected"}]` : "unknown"}`,
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- process.stderr.write("[agent-intercom-build] package=@ctliz/agent-intercom-codex version=0.11.0-connect.2 target=bridge-daemon sourceSha256=3f81ffd19c83ad2f4db13939ce8dba9eae17d8c4b0c419e405941e0352f9c102\n");
2
+ process.stderr.write("[agent-intercom-build] package=@ctliz/agent-intercom-codex version=0.12.0-connect.1 target=bridge-daemon sourceSha256=f5d619a0fa1debe9fa5b5850ec8d372a474488d0fb4bde6540cd7656f6bb2c51\n");
3
3
 
4
4
  // codex/bridge-daemon.ts
5
5
  import { once } from "node:events";
@@ -2808,6 +2808,7 @@ import {
2808
2808
  parseWorkerIdentityV2 as parseWorkerIdentityV22,
2809
2809
  workerIdentityFromEnvironment
2810
2810
  } from "@ctliz/agent-intercom-core/boss";
2811
+ import { readTeamManifestAsync, TeamManifestError } from "@ctliz/agent-intercom-core/team-manifest";
2811
2812
  var LEGACY_LIVE_STATES = /* @__PURE__ */ new Set(["provisioning", "running", "idle", "needs_attention", "stopping"]);
2812
2813
  var CANONICAL_LIVE_STATES = /* @__PURE__ */ new Set(["provisioning", "registering", "ready", "working", "waiting", "paused", "stalled", "blocked", "unreachable"]);
2813
2814
  var stringValue = (value) => typeof value === "string" && value.trim() ? value.trim() : void 0;
@@ -2815,12 +2816,25 @@ var connectedTo = (sessions, target) => {
2815
2816
  const normalized = target.toLowerCase();
2816
2817
  return sessions.some((session) => session.id === target || session.name?.toLowerCase() === normalized);
2817
2818
  };
2819
+ function hasBossEnvironmentKeys(env) {
2820
+ const bossKeys = [
2821
+ "AGENT_INTERCOM_BOSS_RUN_ID",
2822
+ "AGENT_INTERCOM_PARTICIPANT_ID",
2823
+ "AGENT_INTERCOM_BINDING_EPOCH",
2824
+ "AGENT_INTERCOM_WORKER_INCARNATION_ID",
2825
+ "AGENT_INTERCOM_WORKER_GENERATION"
2826
+ ];
2827
+ return bossKeys.some((key) => env[key] !== void 0);
2828
+ }
2818
2829
  function bossIdentityFromEnvironment(env) {
2819
- const bossKeys = ["AGENT_INTERCOM_BOSS_RUN_ID", "AGENT_INTERCOM_PARTICIPANT_ID", "AGENT_INTERCOM_BINDING_EPOCH"];
2820
- if (!bossKeys.some((key) => env[key] !== void 0)) return void 0;
2821
- const identity = workerIdentityFromEnvironment(env);
2822
- if (!("bossRunId" in identity)) throw new Error("Incomplete Boss worker identity cannot discover a team");
2823
- return identity;
2830
+ if (!hasBossEnvironmentKeys(env)) return void 0;
2831
+ try {
2832
+ const identity = workerIdentityFromEnvironment(env);
2833
+ if (!("bossRunId" in identity)) return void 0;
2834
+ return identity;
2835
+ } catch {
2836
+ return void 0;
2837
+ }
2824
2838
  }
2825
2839
  function canonicalWorker(value) {
2826
2840
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("worker must be an object");
@@ -2874,25 +2888,138 @@ async function readWorkers(agentDir) {
2874
2888
  return { version: 1, workers: [] };
2875
2889
  }
2876
2890
  }
2891
+ async function resolveNonAuthoritativeTeam(input, env) {
2892
+ if (env.AGENT_INTERCOM_TEAM_MANIFEST !== void 0) {
2893
+ const rawPath = env.AGENT_INTERCOM_TEAM_MANIFEST.trim();
2894
+ if (!rawPath) {
2895
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
2896
+ }
2897
+ const manifest = await readTeamManifestAsync(rawPath);
2898
+ if (!manifest) {
2899
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
2900
+ }
2901
+ const selfMember = manifest.members.find((m) => m.sessionId === input.selfId);
2902
+ if (!selfMember) {
2903
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
2904
+ }
2905
+ const isManager = input.selfId === manifest.leadId;
2906
+ const managerTarget2 = manifest.leadId;
2907
+ const managerConnected = connectedTo(input.sessions, managerTarget2);
2908
+ const coworkers = manifest.members.filter((m) => m.sessionId !== input.selfId).filter((m) => isManager || m.sessionId !== managerTarget2).map((m) => {
2909
+ const live = input.sessions.find((s) => s.id === m.sessionId || s.name === m.sessionId);
2910
+ return {
2911
+ id: m.sessionId,
2912
+ target: m.sessionId,
2913
+ role: m.role,
2914
+ connected: Boolean(live)
2915
+ };
2916
+ });
2917
+ return {
2918
+ teamId: manifest.runId,
2919
+ self: { id: input.selfId, isManager },
2920
+ manager: { target: managerTarget2, connected: managerConnected },
2921
+ coworkers,
2922
+ source: "manifest"
2923
+ };
2924
+ }
2925
+ if (stringValue(env.AGENT_INTERCOM_SCOPE_ID)) {
2926
+ const managerTarget2 = stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
2927
+ const role = stringValue(env.AGENT_INTERCOM_ROLE)?.toLowerCase();
2928
+ const isManager = role === "manager" || managerTarget2 !== void 0 && managerTarget2 === input.selfId || managerTarget2 === void 0 && role !== "worker";
2929
+ const effectiveManagerTarget = isManager ? input.selfId : managerTarget2;
2930
+ const coworkers = input.sessions.filter((session) => session.id !== input.selfId).filter((session) => session.model !== "human").filter((session) => session.id !== effectiveManagerTarget).map((session) => ({
2931
+ id: session.id,
2932
+ target: session.id,
2933
+ ...session.model ? { harness: session.model } : {},
2934
+ connected: true
2935
+ }));
2936
+ const manager = effectiveManagerTarget ? {
2937
+ target: effectiveManagerTarget,
2938
+ connected: isManager ? true : connectedTo(input.sessions, effectiveManagerTarget)
2939
+ } : void 0;
2940
+ return {
2941
+ teamId: effectiveManagerTarget ?? input.selfId,
2942
+ self: { id: input.selfId, isManager },
2943
+ ...manager ? { manager } : {},
2944
+ coworkers,
2945
+ source: "live"
2946
+ };
2947
+ }
2948
+ const managerTarget = stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
2949
+ return {
2950
+ teamId: managerTarget ?? input.selfId,
2951
+ self: { id: input.selfId, isManager: !managerTarget },
2952
+ manager: managerTarget ? { target: managerTarget, connected: connectedTo(input.sessions, managerTarget) } : { target: input.selfId, connected: true },
2953
+ coworkers: [],
2954
+ source: "standalone"
2955
+ };
2956
+ }
2877
2957
  async function resolveIntercomTeam(input) {
2878
2958
  const env = input.env ?? process.env;
2879
2959
  const snapshot = await readWorkers(input.agentDir ?? getAgentDirPath());
2880
2960
  const workers = snapshot.workers;
2881
2961
  const workerId = stringValue(env.AGENT_INTERCOM_WORKER_ID);
2962
+ const selfSession = input.sessions.find((session) => session.id === input.selfId);
2963
+ const isBossContext = selfSession?.boss !== void 0 || hasBossEnvironmentKeys(env);
2882
2964
  const bossIdentity = bossIdentityFromEnvironment(env);
2883
2965
  const runId = stringValue(env.AGENT_INTERCOM_RUN_ID);
2884
- const currentMatches = workerId ? workers.filter((worker) => stringValue(worker.id) === workerId && (bossIdentity === void 0 ? !runId || stringValue(worker.runId) === runId : snapshot.version === 2 && worker.canonicalIdentity?.workerId === bossIdentity.workerId && worker.canonicalIdentity.workerIncarnationId === bossIdentity.workerIncarnationId && worker.canonicalIdentity.workerGeneration === bossIdentity.workerGeneration && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId && worker.canonicalIdentity.participantId === bossIdentity.participantId && worker.canonicalIdentity.bindingEpoch === bossIdentity.bindingEpoch)) : [];
2966
+ if (isBossContext && bossIdentity === void 0) {
2967
+ return {
2968
+ self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false },
2969
+ coworkers: [],
2970
+ source: "boss"
2971
+ };
2972
+ }
2973
+ const currentMatches = workerId ? workers.filter((worker) => stringValue(worker.id) === workerId && (bossIdentity === void 0 ? snapshot.version === 1 && (!runId || stringValue(worker.runId) === runId) : snapshot.version === 2 && worker.canonicalIdentity?.workerId === bossIdentity.workerId && worker.canonicalIdentity.workerIncarnationId === bossIdentity.workerIncarnationId && worker.canonicalIdentity.workerGeneration === bossIdentity.workerGeneration && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId && worker.canonicalIdentity.participantId === bossIdentity.participantId && worker.canonicalIdentity.bindingEpoch === bossIdentity.bindingEpoch)) : [];
2885
2974
  const current = bossIdentity === void 0 ? currentMatches[0] : currentMatches.length === 1 ? currentMatches[0] : void 0;
2886
2975
  const currentTarget = stringValue(current?.intercomTarget);
2887
2976
  const exactCurrentProjection = current !== void 0 && currentTarget === input.selfId && workers.filter((worker) => stringValue(worker.id) === workerId).length === 1 && workers.filter((worker) => stringValue(worker.intercomTarget) === currentTarget).length === 1 && exactBossRosterSession(input.sessions, current) !== void 0;
2888
2977
  if (bossIdentity !== void 0 && !exactCurrentProjection) {
2889
- return { self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false }, coworkers: [] };
2978
+ return { self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false }, coworkers: [], source: "boss" };
2979
+ }
2980
+ if (bossIdentity === void 0 && !current) {
2981
+ if (workerId === void 0 && snapshot.version === 1) {
2982
+ const ownedCoworkers = workers.filter((worker) => worker.owned === true).filter((worker) => {
2983
+ const mgr = stringValue(worker.managerSessionId);
2984
+ return mgr !== void 0 && mgr === input.selfId;
2985
+ }).filter((worker) => LEGACY_LIVE_STATES.has(stringValue(worker.state) ?? "")).filter((worker) => stringValue(worker.id) !== input.selfId).map((worker) => {
2986
+ const id = stringValue(worker.id);
2987
+ if (!id) return void 0;
2988
+ const target = stringValue(worker.intercomTarget) ?? id;
2989
+ return {
2990
+ id,
2991
+ target,
2992
+ ...stringValue(worker.harness) ? { harness: stringValue(worker.harness) } : {},
2993
+ ...stringValue(worker.role) ? { role: stringValue(worker.role) } : {},
2994
+ ...stringValue(worker.state) ? { state: stringValue(worker.state) } : {},
2995
+ connected: connectedTo(input.sessions, target)
2996
+ };
2997
+ }).filter((member) => Boolean(member));
2998
+ if (ownedCoworkers.length > 0) {
2999
+ return {
3000
+ teamId: input.selfId,
3001
+ self: { id: input.selfId, isManager: true },
3002
+ manager: { target: input.selfId, connected: true },
3003
+ coworkers: ownedCoworkers,
3004
+ source: "orchestrator"
3005
+ };
3006
+ }
3007
+ }
3008
+ return resolveNonAuthoritativeTeam(input, env);
2890
3009
  }
2891
- const managerTarget = stringValue(current?.managerSessionId) ?? (bossIdentity === void 0 ? stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID) : void 0);
2892
- const teamId = managerTarget ?? input.selfId;
2893
3010
  const currentRole = stringValue(current?.role);
3011
+ const selfIsManager = bossIdentity !== void 0 ? currentRole === "manager" : void 0;
3012
+ const managerTarget = bossIdentity !== void 0 ? selfIsManager ? input.selfId : stringValue(current?.managerSessionId) : stringValue(current?.managerSessionId) ?? stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
3013
+ if (bossIdentity === void 0 && !managerTarget) {
3014
+ return {
3015
+ self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false },
3016
+ coworkers: [],
3017
+ source: "orchestrator"
3018
+ };
3019
+ }
3020
+ const teamId = bossIdentity !== void 0 ? "bossRunId" in bossIdentity ? bossIdentity.bossRunId : managerTarget ?? input.selfId : managerTarget ?? input.selfId;
2894
3021
  const canDiscoverOwnedRoster = bossIdentity === void 0 || currentRole === "manager" || currentRole === "controller";
2895
- const coworkers = (canDiscoverOwnedRoster ? workers : []).filter((worker) => worker.owned === true).filter((worker) => bossIdentity === void 0 || snapshot.version === 2 && worker.canonicalIdentity !== void 0 && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId).filter((worker) => stringValue(worker.managerSessionId) === teamId).filter((worker) => stringValue(worker.intercomTarget) !== managerTarget).filter((worker) => (snapshot.version === 2 ? CANONICAL_LIVE_STATES : LEGACY_LIVE_STATES).has(stringValue(worker.state) ?? "")).filter((worker) => stringValue(worker.id) !== workerId).map((worker) => {
3022
+ const coworkers = (canDiscoverOwnedRoster ? workers : []).filter((worker) => worker.owned === true).filter((worker) => bossIdentity === void 0 || snapshot.version === 2 && worker.canonicalIdentity !== void 0 && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId).filter((worker) => stringValue(worker.managerSessionId) === (bossIdentity !== void 0 ? managerTarget : teamId)).filter((worker) => stringValue(worker.intercomTarget) !== managerTarget).filter((worker) => (snapshot.version === 2 ? CANONICAL_LIVE_STATES : LEGACY_LIVE_STATES).has(stringValue(worker.state) ?? "")).filter((worker) => stringValue(worker.id) !== workerId && stringValue(worker.id) !== input.selfId).map((worker) => {
2896
3023
  const id = stringValue(worker.id);
2897
3024
  if (!id) return void 0;
2898
3025
  const target = stringValue(worker.intercomTarget) ?? id;
@@ -2909,11 +3036,13 @@ async function resolveIntercomTeam(input) {
2909
3036
  }).filter((member) => Boolean(member));
2910
3037
  const managerWorker = managerTarget === void 0 ? void 0 : workers.find((worker) => stringValue(worker.intercomTarget) === managerTarget && (bossIdentity === void 0 || snapshot.version === 2 && stringValue(worker.role) === "manager" && worker.canonicalIdentity !== void 0 && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId));
2911
3038
  const managerConnected = managerTarget === void 0 ? true : bossIdentity === void 0 ? connectedTo(input.sessions, managerTarget) : managerWorker !== void 0 && exactBossRosterSession(input.sessions, managerWorker) !== void 0;
3039
+ const isManager = bossIdentity !== void 0 ? selfIsManager : false;
2912
3040
  return {
2913
3041
  teamId,
2914
- self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: bossIdentity === void 0 && !managerTarget },
2915
- ...managerTarget ? { manager: { target: managerTarget, connected: managerConnected } } : bossIdentity === void 0 ? { manager: { target: input.selfId, connected: true } } : {},
2916
- coworkers
3042
+ self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager },
3043
+ ...managerTarget ? { manager: { target: managerTarget, connected: isManager ? true : managerConnected } } : {},
3044
+ coworkers,
3045
+ source: bossIdentity !== void 0 ? "boss" : "orchestrator"
2917
3046
  };
2918
3047
  }
2919
3048
  function formatIntercomTeam(team) {
package/dist/broker.mjs CHANGED
@@ -1,4 +1,4 @@
1
- process.stderr.write("[agent-intercom-build] package=@ctliz/agent-intercom-codex version=0.11.0-connect.2 target=broker sourceSha256=3f81ffd19c83ad2f4db13939ce8dba9eae17d8c4b0c419e405941e0352f9c102\n");
1
+ process.stderr.write("[agent-intercom-build] package=@ctliz/agent-intercom-codex version=0.12.0-connect.1 target=broker sourceSha256=f5d619a0fa1debe9fa5b5850ec8d372a474488d0fb4bde6540cd7656f6bb2c51\n");
2
2
 
3
3
  // broker/broker.ts
4
4
  import net from "net";
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@ctliz/agent-intercom-codex",
4
- "version": "0.11.0-connect.2",
5
- "sourceSha256": "3f81ffd19c83ad2f4db13939ce8dba9eae17d8c4b0c419e405941e0352f9c102",
4
+ "version": "0.12.0-connect.1",
5
+ "sourceSha256": "f5d619a0fa1debe9fa5b5850ec8d372a474488d0fb4bde6540cd7656f6bb2c51",
6
6
  "targets": [
7
7
  "codex-server",
8
8
  "broker",
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- process.stderr.write("[agent-intercom-build] package=@ctliz/agent-intercom-codex version=0.11.0-connect.2 target=codex-server sourceSha256=3f81ffd19c83ad2f4db13939ce8dba9eae17d8c4b0c419e405941e0352f9c102\n");
2
+ process.stderr.write("[agent-intercom-build] package=@ctliz/agent-intercom-codex version=0.12.0-connect.1 target=codex-server sourceSha256=f5d619a0fa1debe9fa5b5850ec8d372a474488d0fb4bde6540cd7656f6bb2c51\n");
3
3
 
4
4
  // codex/server.ts
5
5
  import readline from "node:readline";
@@ -2089,6 +2089,7 @@ import {
2089
2089
  parseWorkerIdentityV2 as parseWorkerIdentityV22,
2090
2090
  workerIdentityFromEnvironment
2091
2091
  } from "@ctliz/agent-intercom-core/boss";
2092
+ import { readTeamManifestAsync, TeamManifestError } from "@ctliz/agent-intercom-core/team-manifest";
2092
2093
  var LEGACY_LIVE_STATES = /* @__PURE__ */ new Set(["provisioning", "running", "idle", "needs_attention", "stopping"]);
2093
2094
  var CANONICAL_LIVE_STATES = /* @__PURE__ */ new Set(["provisioning", "registering", "ready", "working", "waiting", "paused", "stalled", "blocked", "unreachable"]);
2094
2095
  var stringValue = (value) => typeof value === "string" && value.trim() ? value.trim() : void 0;
@@ -2096,12 +2097,25 @@ var connectedTo = (sessions, target) => {
2096
2097
  const normalized = target.toLowerCase();
2097
2098
  return sessions.some((session) => session.id === target || session.name?.toLowerCase() === normalized);
2098
2099
  };
2100
+ function hasBossEnvironmentKeys(env) {
2101
+ const bossKeys = [
2102
+ "AGENT_INTERCOM_BOSS_RUN_ID",
2103
+ "AGENT_INTERCOM_PARTICIPANT_ID",
2104
+ "AGENT_INTERCOM_BINDING_EPOCH",
2105
+ "AGENT_INTERCOM_WORKER_INCARNATION_ID",
2106
+ "AGENT_INTERCOM_WORKER_GENERATION"
2107
+ ];
2108
+ return bossKeys.some((key) => env[key] !== void 0);
2109
+ }
2099
2110
  function bossIdentityFromEnvironment(env) {
2100
- const bossKeys = ["AGENT_INTERCOM_BOSS_RUN_ID", "AGENT_INTERCOM_PARTICIPANT_ID", "AGENT_INTERCOM_BINDING_EPOCH"];
2101
- if (!bossKeys.some((key) => env[key] !== void 0)) return void 0;
2102
- const identity = workerIdentityFromEnvironment(env);
2103
- if (!("bossRunId" in identity)) throw new Error("Incomplete Boss worker identity cannot discover a team");
2104
- return identity;
2111
+ if (!hasBossEnvironmentKeys(env)) return void 0;
2112
+ try {
2113
+ const identity = workerIdentityFromEnvironment(env);
2114
+ if (!("bossRunId" in identity)) return void 0;
2115
+ return identity;
2116
+ } catch {
2117
+ return void 0;
2118
+ }
2105
2119
  }
2106
2120
  function canonicalWorker(value) {
2107
2121
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("worker must be an object");
@@ -2155,25 +2169,138 @@ async function readWorkers(agentDir) {
2155
2169
  return { version: 1, workers: [] };
2156
2170
  }
2157
2171
  }
2172
+ async function resolveNonAuthoritativeTeam(input, env) {
2173
+ if (env.AGENT_INTERCOM_TEAM_MANIFEST !== void 0) {
2174
+ const rawPath = env.AGENT_INTERCOM_TEAM_MANIFEST.trim();
2175
+ if (!rawPath) {
2176
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
2177
+ }
2178
+ const manifest = await readTeamManifestAsync(rawPath);
2179
+ if (!manifest) {
2180
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
2181
+ }
2182
+ const selfMember = manifest.members.find((m) => m.sessionId === input.selfId);
2183
+ if (!selfMember) {
2184
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
2185
+ }
2186
+ const isManager = input.selfId === manifest.leadId;
2187
+ const managerTarget2 = manifest.leadId;
2188
+ const managerConnected = connectedTo(input.sessions, managerTarget2);
2189
+ const coworkers = manifest.members.filter((m) => m.sessionId !== input.selfId).filter((m) => isManager || m.sessionId !== managerTarget2).map((m) => {
2190
+ const live = input.sessions.find((s) => s.id === m.sessionId || s.name === m.sessionId);
2191
+ return {
2192
+ id: m.sessionId,
2193
+ target: m.sessionId,
2194
+ role: m.role,
2195
+ connected: Boolean(live)
2196
+ };
2197
+ });
2198
+ return {
2199
+ teamId: manifest.runId,
2200
+ self: { id: input.selfId, isManager },
2201
+ manager: { target: managerTarget2, connected: managerConnected },
2202
+ coworkers,
2203
+ source: "manifest"
2204
+ };
2205
+ }
2206
+ if (stringValue(env.AGENT_INTERCOM_SCOPE_ID)) {
2207
+ const managerTarget2 = stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
2208
+ const role = stringValue(env.AGENT_INTERCOM_ROLE)?.toLowerCase();
2209
+ const isManager = role === "manager" || managerTarget2 !== void 0 && managerTarget2 === input.selfId || managerTarget2 === void 0 && role !== "worker";
2210
+ const effectiveManagerTarget = isManager ? input.selfId : managerTarget2;
2211
+ const coworkers = input.sessions.filter((session) => session.id !== input.selfId).filter((session) => session.model !== "human").filter((session) => session.id !== effectiveManagerTarget).map((session) => ({
2212
+ id: session.id,
2213
+ target: session.id,
2214
+ ...session.model ? { harness: session.model } : {},
2215
+ connected: true
2216
+ }));
2217
+ const manager = effectiveManagerTarget ? {
2218
+ target: effectiveManagerTarget,
2219
+ connected: isManager ? true : connectedTo(input.sessions, effectiveManagerTarget)
2220
+ } : void 0;
2221
+ return {
2222
+ teamId: effectiveManagerTarget ?? input.selfId,
2223
+ self: { id: input.selfId, isManager },
2224
+ ...manager ? { manager } : {},
2225
+ coworkers,
2226
+ source: "live"
2227
+ };
2228
+ }
2229
+ const managerTarget = stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
2230
+ return {
2231
+ teamId: managerTarget ?? input.selfId,
2232
+ self: { id: input.selfId, isManager: !managerTarget },
2233
+ manager: managerTarget ? { target: managerTarget, connected: connectedTo(input.sessions, managerTarget) } : { target: input.selfId, connected: true },
2234
+ coworkers: [],
2235
+ source: "standalone"
2236
+ };
2237
+ }
2158
2238
  async function resolveIntercomTeam(input) {
2159
2239
  const env = input.env ?? process.env;
2160
2240
  const snapshot = await readWorkers(input.agentDir ?? getAgentDirPath());
2161
2241
  const workers = snapshot.workers;
2162
2242
  const workerId = stringValue(env.AGENT_INTERCOM_WORKER_ID);
2243
+ const selfSession = input.sessions.find((session) => session.id === input.selfId);
2244
+ const isBossContext = selfSession?.boss !== void 0 || hasBossEnvironmentKeys(env);
2163
2245
  const bossIdentity = bossIdentityFromEnvironment(env);
2164
2246
  const runId = stringValue(env.AGENT_INTERCOM_RUN_ID);
2165
- const currentMatches = workerId ? workers.filter((worker) => stringValue(worker.id) === workerId && (bossIdentity === void 0 ? !runId || stringValue(worker.runId) === runId : snapshot.version === 2 && worker.canonicalIdentity?.workerId === bossIdentity.workerId && worker.canonicalIdentity.workerIncarnationId === bossIdentity.workerIncarnationId && worker.canonicalIdentity.workerGeneration === bossIdentity.workerGeneration && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId && worker.canonicalIdentity.participantId === bossIdentity.participantId && worker.canonicalIdentity.bindingEpoch === bossIdentity.bindingEpoch)) : [];
2247
+ if (isBossContext && bossIdentity === void 0) {
2248
+ return {
2249
+ self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false },
2250
+ coworkers: [],
2251
+ source: "boss"
2252
+ };
2253
+ }
2254
+ const currentMatches = workerId ? workers.filter((worker) => stringValue(worker.id) === workerId && (bossIdentity === void 0 ? snapshot.version === 1 && (!runId || stringValue(worker.runId) === runId) : snapshot.version === 2 && worker.canonicalIdentity?.workerId === bossIdentity.workerId && worker.canonicalIdentity.workerIncarnationId === bossIdentity.workerIncarnationId && worker.canonicalIdentity.workerGeneration === bossIdentity.workerGeneration && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId && worker.canonicalIdentity.participantId === bossIdentity.participantId && worker.canonicalIdentity.bindingEpoch === bossIdentity.bindingEpoch)) : [];
2166
2255
  const current = bossIdentity === void 0 ? currentMatches[0] : currentMatches.length === 1 ? currentMatches[0] : void 0;
2167
2256
  const currentTarget = stringValue(current?.intercomTarget);
2168
2257
  const exactCurrentProjection = current !== void 0 && currentTarget === input.selfId && workers.filter((worker) => stringValue(worker.id) === workerId).length === 1 && workers.filter((worker) => stringValue(worker.intercomTarget) === currentTarget).length === 1 && exactBossRosterSession(input.sessions, current) !== void 0;
2169
2258
  if (bossIdentity !== void 0 && !exactCurrentProjection) {
2170
- return { self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false }, coworkers: [] };
2259
+ return { self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false }, coworkers: [], source: "boss" };
2260
+ }
2261
+ if (bossIdentity === void 0 && !current) {
2262
+ if (workerId === void 0 && snapshot.version === 1) {
2263
+ const ownedCoworkers = workers.filter((worker) => worker.owned === true).filter((worker) => {
2264
+ const mgr = stringValue(worker.managerSessionId);
2265
+ return mgr !== void 0 && mgr === input.selfId;
2266
+ }).filter((worker) => LEGACY_LIVE_STATES.has(stringValue(worker.state) ?? "")).filter((worker) => stringValue(worker.id) !== input.selfId).map((worker) => {
2267
+ const id = stringValue(worker.id);
2268
+ if (!id) return void 0;
2269
+ const target = stringValue(worker.intercomTarget) ?? id;
2270
+ return {
2271
+ id,
2272
+ target,
2273
+ ...stringValue(worker.harness) ? { harness: stringValue(worker.harness) } : {},
2274
+ ...stringValue(worker.role) ? { role: stringValue(worker.role) } : {},
2275
+ ...stringValue(worker.state) ? { state: stringValue(worker.state) } : {},
2276
+ connected: connectedTo(input.sessions, target)
2277
+ };
2278
+ }).filter((member) => Boolean(member));
2279
+ if (ownedCoworkers.length > 0) {
2280
+ return {
2281
+ teamId: input.selfId,
2282
+ self: { id: input.selfId, isManager: true },
2283
+ manager: { target: input.selfId, connected: true },
2284
+ coworkers: ownedCoworkers,
2285
+ source: "orchestrator"
2286
+ };
2287
+ }
2288
+ }
2289
+ return resolveNonAuthoritativeTeam(input, env);
2171
2290
  }
2172
- const managerTarget = stringValue(current?.managerSessionId) ?? (bossIdentity === void 0 ? stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID) : void 0);
2173
- const teamId = managerTarget ?? input.selfId;
2174
2291
  const currentRole = stringValue(current?.role);
2292
+ const selfIsManager = bossIdentity !== void 0 ? currentRole === "manager" : void 0;
2293
+ const managerTarget = bossIdentity !== void 0 ? selfIsManager ? input.selfId : stringValue(current?.managerSessionId) : stringValue(current?.managerSessionId) ?? stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
2294
+ if (bossIdentity === void 0 && !managerTarget) {
2295
+ return {
2296
+ self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false },
2297
+ coworkers: [],
2298
+ source: "orchestrator"
2299
+ };
2300
+ }
2301
+ const teamId = bossIdentity !== void 0 ? "bossRunId" in bossIdentity ? bossIdentity.bossRunId : managerTarget ?? input.selfId : managerTarget ?? input.selfId;
2175
2302
  const canDiscoverOwnedRoster = bossIdentity === void 0 || currentRole === "manager" || currentRole === "controller";
2176
- const coworkers = (canDiscoverOwnedRoster ? workers : []).filter((worker) => worker.owned === true).filter((worker) => bossIdentity === void 0 || snapshot.version === 2 && worker.canonicalIdentity !== void 0 && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId).filter((worker) => stringValue(worker.managerSessionId) === teamId).filter((worker) => stringValue(worker.intercomTarget) !== managerTarget).filter((worker) => (snapshot.version === 2 ? CANONICAL_LIVE_STATES : LEGACY_LIVE_STATES).has(stringValue(worker.state) ?? "")).filter((worker) => stringValue(worker.id) !== workerId).map((worker) => {
2303
+ const coworkers = (canDiscoverOwnedRoster ? workers : []).filter((worker) => worker.owned === true).filter((worker) => bossIdentity === void 0 || snapshot.version === 2 && worker.canonicalIdentity !== void 0 && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId).filter((worker) => stringValue(worker.managerSessionId) === (bossIdentity !== void 0 ? managerTarget : teamId)).filter((worker) => stringValue(worker.intercomTarget) !== managerTarget).filter((worker) => (snapshot.version === 2 ? CANONICAL_LIVE_STATES : LEGACY_LIVE_STATES).has(stringValue(worker.state) ?? "")).filter((worker) => stringValue(worker.id) !== workerId && stringValue(worker.id) !== input.selfId).map((worker) => {
2177
2304
  const id = stringValue(worker.id);
2178
2305
  if (!id) return void 0;
2179
2306
  const target = stringValue(worker.intercomTarget) ?? id;
@@ -2190,11 +2317,13 @@ async function resolveIntercomTeam(input) {
2190
2317
  }).filter((member) => Boolean(member));
2191
2318
  const managerWorker = managerTarget === void 0 ? void 0 : workers.find((worker) => stringValue(worker.intercomTarget) === managerTarget && (bossIdentity === void 0 || snapshot.version === 2 && stringValue(worker.role) === "manager" && worker.canonicalIdentity !== void 0 && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId));
2192
2319
  const managerConnected = managerTarget === void 0 ? true : bossIdentity === void 0 ? connectedTo(input.sessions, managerTarget) : managerWorker !== void 0 && exactBossRosterSession(input.sessions, managerWorker) !== void 0;
2320
+ const isManager = bossIdentity !== void 0 ? selfIsManager : false;
2193
2321
  return {
2194
2322
  teamId,
2195
- self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: bossIdentity === void 0 && !managerTarget },
2196
- ...managerTarget ? { manager: { target: managerTarget, connected: managerConnected } } : bossIdentity === void 0 ? { manager: { target: input.selfId, connected: true } } : {},
2197
- coworkers
2323
+ self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager },
2324
+ ...managerTarget ? { manager: { target: managerTarget, connected: isManager ? true : managerConnected } } : {},
2325
+ coworkers,
2326
+ source: bossIdentity !== void 0 ? "boss" : "orchestrator"
2198
2327
  };
2199
2328
  }
2200
2329
  function formatIntercomTeam(team) {
@@ -2261,10 +2390,23 @@ function publicPendingEntry(entry, selector) {
2261
2390
  function shortHash(value) {
2262
2391
  return createHash3("sha256").update(value).digest("hex").slice(0, 8);
2263
2392
  }
2393
+ var GENERIC_SESSION_ID_REGEX = /^[A-Za-z0-9_-]{1,128}$/;
2264
2394
  function buildCodexRuntimeIdentity(env = process.env, cwd = env.PWD || processCwd(), pid = process.pid) {
2265
- const sessionId = env.CODEX_INTERCOM_SESSION_ID?.trim() || env.CODEX_PEER_ID?.trim() || `codex-${pid}-${shortHash(cwd)}`;
2395
+ let sessionId = env.CODEX_INTERCOM_SESSION_ID?.trim() || env.CODEX_PEER_ID?.trim();
2396
+ if (!sessionId && env.AGENT_INTERCOM_SESSION_ID !== void 0) {
2397
+ const raw = env.AGENT_INTERCOM_SESSION_ID.trim();
2398
+ if (raw) {
2399
+ if (!GENERIC_SESSION_ID_REGEX.test(raw)) {
2400
+ throw new Error("Invalid AGENT_INTERCOM_SESSION_ID: must match ^[A-Za-z0-9_-]{1,128}$");
2401
+ }
2402
+ sessionId = raw;
2403
+ }
2404
+ }
2405
+ if (!sessionId) {
2406
+ sessionId = `codex-${pid}-${shortHash(cwd)}`;
2407
+ }
2266
2408
  const cwdName = basename(cwd) || "workspace";
2267
- const name = env.CODEX_INTERCOM_NAME?.trim() || env.CODEX_PEER_NAME?.trim() || `codex-${cwdName}-${pid}`;
2409
+ const name = env.CODEX_INTERCOM_NAME?.trim() || env.CODEX_PEER_NAME?.trim() || (env.AGENT_INTERCOM_SESSION_NAME !== void 0 && env.AGENT_INTERCOM_SESSION_NAME.trim() ? env.AGENT_INTERCOM_SESSION_NAME.trim() : void 0) || `codex-${cwdName}-${pid}`;
2268
2410
  return {
2269
2411
  sessionId,
2270
2412
  name,
package/dist/coi.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- process.stderr.write("[agent-intercom-build] package=@ctliz/agent-intercom-codex version=0.11.0-connect.2 target=coi sourceSha256=3f81ffd19c83ad2f4db13939ce8dba9eae17d8c4b0c419e405941e0352f9c102\n");
2
+ process.stderr.write("[agent-intercom-build] package=@ctliz/agent-intercom-codex version=0.12.0-connect.1 target=coi sourceSha256=f5d619a0fa1debe9fa5b5850ec8d372a474488d0fb4bde6540cd7656f6bb2c51\n");
3
3
 
4
4
  // codex/coi.ts
5
5
  import { once as once2 } from "node:events";
@@ -2823,6 +2823,7 @@ import {
2823
2823
  parseWorkerIdentityV2 as parseWorkerIdentityV22,
2824
2824
  workerIdentityFromEnvironment
2825
2825
  } from "@ctliz/agent-intercom-core/boss";
2826
+ import { readTeamManifestAsync, TeamManifestError } from "@ctliz/agent-intercom-core/team-manifest";
2826
2827
  var LEGACY_LIVE_STATES = /* @__PURE__ */ new Set(["provisioning", "running", "idle", "needs_attention", "stopping"]);
2827
2828
  var CANONICAL_LIVE_STATES = /* @__PURE__ */ new Set(["provisioning", "registering", "ready", "working", "waiting", "paused", "stalled", "blocked", "unreachable"]);
2828
2829
  var stringValue = (value) => typeof value === "string" && value.trim() ? value.trim() : void 0;
@@ -2830,12 +2831,25 @@ var connectedTo = (sessions, target) => {
2830
2831
  const normalized = target.toLowerCase();
2831
2832
  return sessions.some((session) => session.id === target || session.name?.toLowerCase() === normalized);
2832
2833
  };
2834
+ function hasBossEnvironmentKeys(env) {
2835
+ const bossKeys = [
2836
+ "AGENT_INTERCOM_BOSS_RUN_ID",
2837
+ "AGENT_INTERCOM_PARTICIPANT_ID",
2838
+ "AGENT_INTERCOM_BINDING_EPOCH",
2839
+ "AGENT_INTERCOM_WORKER_INCARNATION_ID",
2840
+ "AGENT_INTERCOM_WORKER_GENERATION"
2841
+ ];
2842
+ return bossKeys.some((key) => env[key] !== void 0);
2843
+ }
2833
2844
  function bossIdentityFromEnvironment(env) {
2834
- const bossKeys = ["AGENT_INTERCOM_BOSS_RUN_ID", "AGENT_INTERCOM_PARTICIPANT_ID", "AGENT_INTERCOM_BINDING_EPOCH"];
2835
- if (!bossKeys.some((key) => env[key] !== void 0)) return void 0;
2836
- const identity = workerIdentityFromEnvironment(env);
2837
- if (!("bossRunId" in identity)) throw new Error("Incomplete Boss worker identity cannot discover a team");
2838
- return identity;
2845
+ if (!hasBossEnvironmentKeys(env)) return void 0;
2846
+ try {
2847
+ const identity = workerIdentityFromEnvironment(env);
2848
+ if (!("bossRunId" in identity)) return void 0;
2849
+ return identity;
2850
+ } catch {
2851
+ return void 0;
2852
+ }
2839
2853
  }
2840
2854
  function canonicalWorker(value) {
2841
2855
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("worker must be an object");
@@ -2889,25 +2903,138 @@ async function readWorkers(agentDir) {
2889
2903
  return { version: 1, workers: [] };
2890
2904
  }
2891
2905
  }
2906
+ async function resolveNonAuthoritativeTeam(input, env) {
2907
+ if (env.AGENT_INTERCOM_TEAM_MANIFEST !== void 0) {
2908
+ const rawPath = env.AGENT_INTERCOM_TEAM_MANIFEST.trim();
2909
+ if (!rawPath) {
2910
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
2911
+ }
2912
+ const manifest = await readTeamManifestAsync(rawPath);
2913
+ if (!manifest) {
2914
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
2915
+ }
2916
+ const selfMember = manifest.members.find((m) => m.sessionId === input.selfId);
2917
+ if (!selfMember) {
2918
+ throw new TeamManifestError("ERR_TEAM_MANIFEST_INVALID");
2919
+ }
2920
+ const isManager = input.selfId === manifest.leadId;
2921
+ const managerTarget2 = manifest.leadId;
2922
+ const managerConnected = connectedTo(input.sessions, managerTarget2);
2923
+ const coworkers = manifest.members.filter((m) => m.sessionId !== input.selfId).filter((m) => isManager || m.sessionId !== managerTarget2).map((m) => {
2924
+ const live = input.sessions.find((s) => s.id === m.sessionId || s.name === m.sessionId);
2925
+ return {
2926
+ id: m.sessionId,
2927
+ target: m.sessionId,
2928
+ role: m.role,
2929
+ connected: Boolean(live)
2930
+ };
2931
+ });
2932
+ return {
2933
+ teamId: manifest.runId,
2934
+ self: { id: input.selfId, isManager },
2935
+ manager: { target: managerTarget2, connected: managerConnected },
2936
+ coworkers,
2937
+ source: "manifest"
2938
+ };
2939
+ }
2940
+ if (stringValue(env.AGENT_INTERCOM_SCOPE_ID)) {
2941
+ const managerTarget2 = stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
2942
+ const role = stringValue(env.AGENT_INTERCOM_ROLE)?.toLowerCase();
2943
+ const isManager = role === "manager" || managerTarget2 !== void 0 && managerTarget2 === input.selfId || managerTarget2 === void 0 && role !== "worker";
2944
+ const effectiveManagerTarget = isManager ? input.selfId : managerTarget2;
2945
+ const coworkers = input.sessions.filter((session) => session.id !== input.selfId).filter((session) => session.model !== "human").filter((session) => session.id !== effectiveManagerTarget).map((session) => ({
2946
+ id: session.id,
2947
+ target: session.id,
2948
+ ...session.model ? { harness: session.model } : {},
2949
+ connected: true
2950
+ }));
2951
+ const manager = effectiveManagerTarget ? {
2952
+ target: effectiveManagerTarget,
2953
+ connected: isManager ? true : connectedTo(input.sessions, effectiveManagerTarget)
2954
+ } : void 0;
2955
+ return {
2956
+ teamId: effectiveManagerTarget ?? input.selfId,
2957
+ self: { id: input.selfId, isManager },
2958
+ ...manager ? { manager } : {},
2959
+ coworkers,
2960
+ source: "live"
2961
+ };
2962
+ }
2963
+ const managerTarget = stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
2964
+ return {
2965
+ teamId: managerTarget ?? input.selfId,
2966
+ self: { id: input.selfId, isManager: !managerTarget },
2967
+ manager: managerTarget ? { target: managerTarget, connected: connectedTo(input.sessions, managerTarget) } : { target: input.selfId, connected: true },
2968
+ coworkers: [],
2969
+ source: "standalone"
2970
+ };
2971
+ }
2892
2972
  async function resolveIntercomTeam(input) {
2893
2973
  const env = input.env ?? process.env;
2894
2974
  const snapshot = await readWorkers(input.agentDir ?? getAgentDirPath());
2895
2975
  const workers = snapshot.workers;
2896
2976
  const workerId = stringValue(env.AGENT_INTERCOM_WORKER_ID);
2977
+ const selfSession = input.sessions.find((session) => session.id === input.selfId);
2978
+ const isBossContext = selfSession?.boss !== void 0 || hasBossEnvironmentKeys(env);
2897
2979
  const bossIdentity = bossIdentityFromEnvironment(env);
2898
2980
  const runId = stringValue(env.AGENT_INTERCOM_RUN_ID);
2899
- const currentMatches = workerId ? workers.filter((worker) => stringValue(worker.id) === workerId && (bossIdentity === void 0 ? !runId || stringValue(worker.runId) === runId : snapshot.version === 2 && worker.canonicalIdentity?.workerId === bossIdentity.workerId && worker.canonicalIdentity.workerIncarnationId === bossIdentity.workerIncarnationId && worker.canonicalIdentity.workerGeneration === bossIdentity.workerGeneration && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId && worker.canonicalIdentity.participantId === bossIdentity.participantId && worker.canonicalIdentity.bindingEpoch === bossIdentity.bindingEpoch)) : [];
2981
+ if (isBossContext && bossIdentity === void 0) {
2982
+ return {
2983
+ self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false },
2984
+ coworkers: [],
2985
+ source: "boss"
2986
+ };
2987
+ }
2988
+ const currentMatches = workerId ? workers.filter((worker) => stringValue(worker.id) === workerId && (bossIdentity === void 0 ? snapshot.version === 1 && (!runId || stringValue(worker.runId) === runId) : snapshot.version === 2 && worker.canonicalIdentity?.workerId === bossIdentity.workerId && worker.canonicalIdentity.workerIncarnationId === bossIdentity.workerIncarnationId && worker.canonicalIdentity.workerGeneration === bossIdentity.workerGeneration && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId && worker.canonicalIdentity.participantId === bossIdentity.participantId && worker.canonicalIdentity.bindingEpoch === bossIdentity.bindingEpoch)) : [];
2900
2989
  const current = bossIdentity === void 0 ? currentMatches[0] : currentMatches.length === 1 ? currentMatches[0] : void 0;
2901
2990
  const currentTarget = stringValue(current?.intercomTarget);
2902
2991
  const exactCurrentProjection = current !== void 0 && currentTarget === input.selfId && workers.filter((worker) => stringValue(worker.id) === workerId).length === 1 && workers.filter((worker) => stringValue(worker.intercomTarget) === currentTarget).length === 1 && exactBossRosterSession(input.sessions, current) !== void 0;
2903
2992
  if (bossIdentity !== void 0 && !exactCurrentProjection) {
2904
- return { self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false }, coworkers: [] };
2993
+ return { self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false }, coworkers: [], source: "boss" };
2994
+ }
2995
+ if (bossIdentity === void 0 && !current) {
2996
+ if (workerId === void 0 && snapshot.version === 1) {
2997
+ const ownedCoworkers = workers.filter((worker) => worker.owned === true).filter((worker) => {
2998
+ const mgr = stringValue(worker.managerSessionId);
2999
+ return mgr !== void 0 && mgr === input.selfId;
3000
+ }).filter((worker) => LEGACY_LIVE_STATES.has(stringValue(worker.state) ?? "")).filter((worker) => stringValue(worker.id) !== input.selfId).map((worker) => {
3001
+ const id = stringValue(worker.id);
3002
+ if (!id) return void 0;
3003
+ const target = stringValue(worker.intercomTarget) ?? id;
3004
+ return {
3005
+ id,
3006
+ target,
3007
+ ...stringValue(worker.harness) ? { harness: stringValue(worker.harness) } : {},
3008
+ ...stringValue(worker.role) ? { role: stringValue(worker.role) } : {},
3009
+ ...stringValue(worker.state) ? { state: stringValue(worker.state) } : {},
3010
+ connected: connectedTo(input.sessions, target)
3011
+ };
3012
+ }).filter((member) => Boolean(member));
3013
+ if (ownedCoworkers.length > 0) {
3014
+ return {
3015
+ teamId: input.selfId,
3016
+ self: { id: input.selfId, isManager: true },
3017
+ manager: { target: input.selfId, connected: true },
3018
+ coworkers: ownedCoworkers,
3019
+ source: "orchestrator"
3020
+ };
3021
+ }
3022
+ }
3023
+ return resolveNonAuthoritativeTeam(input, env);
2905
3024
  }
2906
- const managerTarget = stringValue(current?.managerSessionId) ?? (bossIdentity === void 0 ? stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID) : void 0);
2907
- const teamId = managerTarget ?? input.selfId;
2908
3025
  const currentRole = stringValue(current?.role);
3026
+ const selfIsManager = bossIdentity !== void 0 ? currentRole === "manager" : void 0;
3027
+ const managerTarget = bossIdentity !== void 0 ? selfIsManager ? input.selfId : stringValue(current?.managerSessionId) : stringValue(current?.managerSessionId) ?? stringValue(env.AGENT_INTERCOM_MANAGER_TARGET) ?? stringValue(env.AGENT_INTERCOM_MANAGER_SESSION_ID);
3028
+ if (bossIdentity === void 0 && !managerTarget) {
3029
+ return {
3030
+ self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: false },
3031
+ coworkers: [],
3032
+ source: "orchestrator"
3033
+ };
3034
+ }
3035
+ const teamId = bossIdentity !== void 0 ? "bossRunId" in bossIdentity ? bossIdentity.bossRunId : managerTarget ?? input.selfId : managerTarget ?? input.selfId;
2909
3036
  const canDiscoverOwnedRoster = bossIdentity === void 0 || currentRole === "manager" || currentRole === "controller";
2910
- const coworkers = (canDiscoverOwnedRoster ? workers : []).filter((worker) => worker.owned === true).filter((worker) => bossIdentity === void 0 || snapshot.version === 2 && worker.canonicalIdentity !== void 0 && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId).filter((worker) => stringValue(worker.managerSessionId) === teamId).filter((worker) => stringValue(worker.intercomTarget) !== managerTarget).filter((worker) => (snapshot.version === 2 ? CANONICAL_LIVE_STATES : LEGACY_LIVE_STATES).has(stringValue(worker.state) ?? "")).filter((worker) => stringValue(worker.id) !== workerId).map((worker) => {
3037
+ const coworkers = (canDiscoverOwnedRoster ? workers : []).filter((worker) => worker.owned === true).filter((worker) => bossIdentity === void 0 || snapshot.version === 2 && worker.canonicalIdentity !== void 0 && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId).filter((worker) => stringValue(worker.managerSessionId) === (bossIdentity !== void 0 ? managerTarget : teamId)).filter((worker) => stringValue(worker.intercomTarget) !== managerTarget).filter((worker) => (snapshot.version === 2 ? CANONICAL_LIVE_STATES : LEGACY_LIVE_STATES).has(stringValue(worker.state) ?? "")).filter((worker) => stringValue(worker.id) !== workerId && stringValue(worker.id) !== input.selfId).map((worker) => {
2911
3038
  const id = stringValue(worker.id);
2912
3039
  if (!id) return void 0;
2913
3040
  const target = stringValue(worker.intercomTarget) ?? id;
@@ -2924,11 +3051,13 @@ async function resolveIntercomTeam(input) {
2924
3051
  }).filter((member) => Boolean(member));
2925
3052
  const managerWorker = managerTarget === void 0 ? void 0 : workers.find((worker) => stringValue(worker.intercomTarget) === managerTarget && (bossIdentity === void 0 || snapshot.version === 2 && stringValue(worker.role) === "manager" && worker.canonicalIdentity !== void 0 && "bossRunId" in worker.canonicalIdentity && "bossRunId" in bossIdentity && worker.canonicalIdentity.bossRunId === bossIdentity.bossRunId));
2926
3053
  const managerConnected = managerTarget === void 0 ? true : bossIdentity === void 0 ? connectedTo(input.sessions, managerTarget) : managerWorker !== void 0 && exactBossRosterSession(input.sessions, managerWorker) !== void 0;
3054
+ const isManager = bossIdentity !== void 0 ? selfIsManager : false;
2927
3055
  return {
2928
3056
  teamId,
2929
- self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager: bossIdentity === void 0 && !managerTarget },
2930
- ...managerTarget ? { manager: { target: managerTarget, connected: managerConnected } } : bossIdentity === void 0 ? { manager: { target: input.selfId, connected: true } } : {},
2931
- coworkers
3057
+ self: { id: input.selfId, ...workerId ? { workerId } : {}, isManager },
3058
+ ...managerTarget ? { manager: { target: managerTarget, connected: isManager ? true : managerConnected } } : {},
3059
+ coworkers,
3060
+ source: bossIdentity !== void 0 ? "boss" : "orchestrator"
2932
3061
  };
2933
3062
  }
2934
3063
  function formatIntercomTeam(team) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctliz/agent-intercom-codex",
3
- "version": "0.11.0-connect.2",
3
+ "version": "0.12.0-connect.1",
4
4
  "description": "Codex MCP plugin for direct local messaging with Pi and Codex coding-agent sessions.",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "type": "module",
@@ -63,13 +63,13 @@
63
63
  "pi"
64
64
  ],
65
65
  "peerDependencies": {
66
- "@ctliz/agent-intercom-core": "0.1.0"
66
+ "@ctliz/agent-intercom-core": "0.2.0"
67
67
  },
68
68
  "optionalDependencies": {
69
69
  "node-pty": "^1.1.0"
70
70
  },
71
71
  "devDependencies": {
72
- "@ctliz/agent-intercom-core": "git+https://github.com/ctliz/agent-intercom-core.git#37e074970e2a9de32a16fc325607c3b476b0bd45",
72
+ "@ctliz/agent-intercom-core": "0.2.0",
73
73
  "@types/node": "^24.0.0",
74
74
  "esbuild": "^0.28.1",
75
75
  "tsx": "^4.20.0",