@g3un/pi-orchestra 0.2.1 → 0.9.2

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.
@@ -1,6 +1,6 @@
1
1
  import { defineTool, type ExtensionContext } from "@earendil-works/pi-coding-agent";
2
2
  import { Type } from "typebox";
3
- import type { AgentProfile, AgentResultStatus, AgentRun, AgentRunResult } from "../core/subagent.ts";
3
+ import type { AgentResultStatus, AgentRun, AgentRunResult } from "../core/subagent.ts";
4
4
  import type { Bus } from "../core/bus.ts";
5
5
  import type { OrchestraApi } from "../core/orchestra.ts";
6
6
  import type { AgentStore } from "../core/store.ts";
@@ -9,7 +9,8 @@ import {
9
9
  closeAgentRuns,
10
10
  formatError,
11
11
  formatNamedEntityLabel,
12
- isTerminalAgentState,
12
+ isAgentRunActive,
13
+ isAgentRunFinished,
13
14
  normalizeEntityName,
14
15
  slugify,
15
16
  toAgentRunResult,
@@ -18,6 +19,8 @@ import {
18
19
  AgentProfileParams,
19
20
  spawnSubagent,
20
21
  SubagentRunNameParam,
22
+ toAgentProfile,
23
+ type RawAgentProfileParams,
21
24
  type SubagentSpawnInput,
22
25
  withDefaultProfileModel,
23
26
  } from "./subagent.ts";
@@ -44,7 +47,7 @@ export interface WorkgroupSettlement {
44
47
  workerResults: AgentRunResult[];
45
48
  /** Every terminal result observed while settling this workgroup. */
46
49
  completedResults: AgentRunResult[];
47
- winner?: AgentRunResult;
50
+ winner: AgentRunResult | undefined;
48
51
  pendingRunIds: string[];
49
52
  }
50
53
 
@@ -69,9 +72,9 @@ export interface WorkgroupLaunchFailedEvent extends WorkgroupLaunchEvent {
69
72
 
70
73
  export interface WorkgroupToolDeps {
71
74
  orchestra: OrchestraApi;
72
- onWorkgroupLaunching?: (event: WorkgroupLaunchEvent) => void;
73
- onWorkgroupLaunched?: (event: WorkgroupLaunchedEvent) => void;
74
- onWorkgroupLaunchFailed?: (event: WorkgroupLaunchFailedEvent) => void;
75
+ onWorkgroupLaunching: ((event: WorkgroupLaunchEvent) => void) | undefined;
76
+ onWorkgroupLaunched: ((event: WorkgroupLaunchedEvent) => void) | undefined;
77
+ onWorkgroupLaunchFailed: ((event: WorkgroupLaunchFailedEvent) => void) | undefined;
75
78
  }
76
79
 
77
80
  export const WorkgroupMemberParams = Type.Object(
@@ -144,7 +147,7 @@ export function createWorkgroupTool({
144
147
  try {
145
148
  const preparedInput: PreparedWorkgroupInput = {
146
149
  ...input,
147
- members: prepareMembers(input.members, orchestra.listRuns()),
150
+ members: prepareMembers(input.members, orchestra.listRuns({ busId: undefined })),
148
151
  };
149
152
  const spawnResults = await Promise.allSettled(
150
153
  preparedInput.members.map(async (member): Promise<SpawnSuccess> => {
@@ -157,7 +160,7 @@ export function createWorkgroupTool({
157
160
  const failures = collectSpawnFailures(preparedInput.members, spawnResults);
158
161
  if (failures.length > 0) {
159
162
  const cleanupResults = await Promise.allSettled(
160
- successes.map((success) => orchestra.closeAgent(success.run.id)),
163
+ successes.map((success) => orchestra.closeAgent(success.run.id, { busId: undefined })),
161
164
  );
162
165
  throw new Error(formatLaunchFailure(failures, successes, cleanupResults));
163
166
  }
@@ -275,12 +278,13 @@ class WorkgroupSettlementCollector {
275
278
  status: resolveWorkgroupStatus(this.completedResults),
276
279
  workerResults: this.completedResults,
277
280
  completedResults: this.completedResults,
281
+ winner: undefined,
278
282
  pendingRunIds: this.getPendingRunIds(),
279
283
  });
280
284
  };
281
285
 
282
286
  const observeRun = (run: AgentRun) => {
283
- if (settled || !this.runIds.has(run.id) || !isTerminalAgentState(run.state)) return;
287
+ if (settled || !this.runIds.has(run.id) || !isAgentRunFinished(run)) return;
284
288
  this.recordTerminalRun(run);
285
289
  finishFromCurrentState();
286
290
  };
@@ -294,6 +298,7 @@ class WorkgroupSettlementCollector {
294
298
  status: "failed",
295
299
  workerResults: [],
296
300
  completedResults: [],
301
+ winner: undefined,
297
302
  pendingRunIds: [],
298
303
  });
299
304
  }
@@ -308,7 +313,7 @@ class WorkgroupSettlementCollector {
308
313
  }
309
314
 
310
315
  private recordTerminalRun(run: AgentRun): void {
311
- if (!isTerminalAgentState(run.state) || this.completedRunIds.has(run.id)) return;
316
+ if (!isAgentRunFinished(run) || this.completedRunIds.has(run.id)) return;
312
317
 
313
318
  this.completedRunIds.add(run.id);
314
319
  this.completedResults.push(toAgentRunResult(run));
@@ -317,12 +322,15 @@ class WorkgroupSettlementCollector {
317
322
  private isSettled(): boolean {
318
323
  return [...this.runIds].every((runId) => {
319
324
  const run = this.store.getRun(runId);
320
- return run !== undefined && isTerminalAgentState(run.state);
325
+ return run !== undefined && isAgentRunFinished(run);
321
326
  });
322
327
  }
323
328
 
324
329
  private getPendingRunIds(): string[] {
325
- return [...this.runIds].filter((runId) => this.store.getRun(runId)?.state === "idle");
330
+ return [...this.runIds].filter((runId) => {
331
+ const run = this.store.getRun(runId);
332
+ return run !== undefined && isAgentRunActive(run);
333
+ });
326
334
  }
327
335
  }
328
336
 
@@ -353,7 +361,7 @@ function toWorkgroupInput(params: RawWorkgroupParams): WorkgroupInput {
353
361
 
354
362
  export function toWorkgroupMember(member: RawWorkgroupMemberParams, label: string): WorkgroupMember {
355
363
  if (!member.profile) throw new Error(`${label} requires profile.`);
356
- return { profile: member.profile, name: member.name, assignment: member.assignment };
364
+ return { profile: toAgentProfile(member.profile), name: member.name, assignment: member.assignment };
357
365
  }
358
366
 
359
367
  function withDefaultModelsForWorkgroup(input: WorkgroupInput, ctx: ExtensionContext): WorkgroupInput {
@@ -531,7 +539,7 @@ type RawWorkgroupParams = {
531
539
  };
532
540
 
533
541
  export type RawWorkgroupMemberParams = {
534
- profile?: AgentProfile;
542
+ profile?: RawAgentProfileParams;
535
543
  name?: string;
536
544
  assignment?: string;
537
545
  };
package/src/utils.ts CHANGED
@@ -61,7 +61,15 @@ export function requireWorkflow(store: AgentStore, id: string): WorkflowRun {
61
61
  }
62
62
 
63
63
  export function isTerminalAgentState(state: AgentState): boolean {
64
- return state !== "idle";
64
+ return state === "success" || state === "blocked" || state === "failed" || state === "closed";
65
+ }
66
+
67
+ export function isAgentRunActive(run: AgentRun): boolean {
68
+ return run.state === "running" && run.result === undefined;
69
+ }
70
+
71
+ export function isAgentRunFinished(run: AgentRun): boolean {
72
+ return isTerminalAgentState(run.state) || run.result !== undefined;
65
73
  }
66
74
 
67
75
  export function indent(text: string, prefix = " "): string {
@@ -87,5 +95,7 @@ export function toAgentRunResult(run: AgentRun): AgentRunResult {
87
95
  }
88
96
 
89
97
  export async function closeAgentRuns(orchestra: OrchestraApi, runIds: string[]): Promise<void> {
90
- await Promise.allSettled([...new Set(runIds)].map(async (runId) => await orchestra.closeAgent(runId)));
98
+ await Promise.allSettled(
99
+ [...new Set(runIds)].map(async (runId) => await orchestra.closeAgent(runId, { busId: undefined })),
100
+ );
91
101
  }
@@ -1,20 +0,0 @@
1
- import type { AgentProfile } from "../core/subagent.ts";
2
-
3
- export interface StageLeaderProfileOptions {
4
- name?: string;
5
- model?: string;
6
- }
7
-
8
- export function createStageLeaderProfile(options: StageLeaderProfileOptions = {}): AgentProfile {
9
- return {
10
- name: options.name ?? "stage-leader",
11
- systemPrompt: [
12
- "You are a workflow stage leader: produce concise canonical output for the next stage.",
13
- "Use only supplied context (workflow/stage goals, previous outputs, worker results, bus context); do not research, inspect files, run commands, or request external info.",
14
- "Deduplicate and reconcile findings; note conflicts/gaps; prefer finish results over bus context.",
15
- "Prefer status=success if useful output exists; use blocked if context is insufficient, failed if synthesis fails.",
16
- ].join("\n"),
17
- tools: [],
18
- model: options.model,
19
- };
20
- }