pi-crew 0.1.25 → 0.1.27

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": "pi-crew",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "Pi extension for coordinated AI teams, workflows, worktrees, and async task orchestration",
5
5
  "author": "baphuongna",
6
6
  "license": "MIT",
@@ -71,6 +71,7 @@
71
71
  "dependencies": {
72
72
  "cli-highlight": "^2.1.11",
73
73
  "diff": "^5.2.0",
74
+ "jiti": "^2.6.1",
74
75
  "typebox": "^1.1.24"
75
76
  },
76
77
  "devDependencies": {
@@ -1,13 +1,15 @@
1
1
  import { spawn, type SpawnOptions } from "node:child_process";
2
2
  import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
- import { fileURLToPath } from "node:url";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
5
  import type { TeamRunManifest } from "../state/types.ts";
6
6
 
7
- export function getBackgroundRunnerCommand(runnerPath: string, cwd: string, runId: string): { args: string[]; loader: "strip-types" } {
7
+ export function getBackgroundRunnerCommand(runnerPath: string, cwd: string, runId: string): { args: string[]; loader: "jiti" } {
8
+ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
9
+ const jitiRegisterPath = path.join(packageRoot, "node_modules", "jiti", "lib", "jiti-register.mjs");
8
10
  return {
9
- args: ["--experimental-strip-types", runnerPath, "--cwd", cwd, "--run-id", runId],
10
- loader: "strip-types",
11
+ args: ["--import", pathToFileURL(jitiRegisterPath).href, runnerPath, "--cwd", cwd, "--run-id", runId],
12
+ loader: "jiti",
11
13
  };
12
14
  }
13
15
 
@@ -43,8 +43,13 @@ function hasDurableActiveAgentEvidence(agent: CrewAgentRecord): boolean {
43
43
  return Boolean(agent.statusPath || agent.eventsPath || agent.outputPath || agent.progress || agent.toolUses || agent.jsonEvents);
44
44
  }
45
45
 
46
+ export function hasStaleAsyncProcess(run: TeamRunManifest): boolean {
47
+ if (!isActiveRunStatus(run.status) || !run.async) return false;
48
+ return !checkProcessLiveness(run.async.pid).alive;
49
+ }
50
+
46
51
  export function isDisplayActiveRun(run: TeamRunManifest, agents: CrewAgentRecord[] = [], now = Date.now()): boolean {
47
- if (!isActiveRunStatus(run.status) || isLikelyOrphanedActiveRun(run, agents, now)) return false;
52
+ if (!isActiveRunStatus(run.status) || hasStaleAsyncProcess(run) || isLikelyOrphanedActiveRun(run, agents, now)) return false;
48
53
  if (agents.length === 0) return true;
49
54
  return agents.some(hasDurableActiveAgentEvidence);
50
55
  }
@@ -51,26 +51,34 @@ function safeNoopTheme(): CrewTheme {
51
51
  };
52
52
  }
53
53
 
54
- function asStringFn(value: unknown): ((color: CrewThemeColor | CrewThemeBg, text: string) => string) | undefined {
54
+ function asStringFn(value: unknown, owner?: object): ((color: CrewThemeColor | CrewThemeBg, text: string) => string) | undefined {
55
55
  if (typeof value !== "function") return undefined;
56
56
  return (color: CrewThemeColor | CrewThemeBg, text: string) => {
57
- const fn = value as (color: CrewThemeColor | CrewThemeBg, text: string) => unknown;
58
- const result = fn(color, text);
59
- return typeof result === "string" ? result : text;
57
+ try {
58
+ const fn = value as (this: object | undefined, color: CrewThemeColor | CrewThemeBg, text: string) => unknown;
59
+ const result = fn.call(owner, color, text);
60
+ return typeof result === "string" ? result : text;
61
+ } catch {
62
+ return text;
63
+ }
60
64
  };
61
65
  }
62
66
 
63
- function asUnaryFn(value: unknown): ((text: string) => string) | undefined {
67
+ function asUnaryFn(value: unknown, owner?: object): ((text: string) => string) | undefined {
64
68
  if (typeof value !== "function") return undefined;
65
69
  return (text: string) => {
66
- const fn = value as (text: string) => unknown;
67
- const result = fn(text);
68
- return typeof result === "string" ? result : text;
70
+ try {
71
+ const fn = value as (this: object | undefined, text: string) => unknown;
72
+ const result = fn.call(owner, text);
73
+ return typeof result === "string" ? result : text;
74
+ } catch {
75
+ return text;
76
+ }
69
77
  };
70
78
  }
71
79
 
72
- function asInverse(value: unknown): (text: string) => string {
73
- return asUnaryFn(value) ?? inverseAnsi;
80
+ function asInverse(value: unknown, owner?: object): (text: string) => string {
81
+ return asUnaryFn(value, owner) ?? inverseAnsi;
74
82
  }
75
83
 
76
84
  function asRecord(value: unknown): Record<string, unknown> | undefined {
@@ -168,15 +176,15 @@ export function asCrewTheme(raw: unknown): CrewTheme {
168
176
  const fallback = safeNoopTheme();
169
177
  if (!raw || typeof raw !== "object") return fallback;
170
178
  const record = raw as Record<string, unknown>;
171
- const fg = asStringFn(record.fg);
172
- const bold = asUnaryFn(record.bold);
179
+ const fg = asStringFn(record.fg, raw);
180
+ const bold = asUnaryFn(record.bold, raw);
173
181
  if (!fg || !bold) return fallback;
174
182
  return {
175
183
  fg,
176
- bg: asStringFn(record.bg),
184
+ bg: asStringFn(record.bg, raw),
177
185
  bold,
178
- italic: asUnaryFn(record.italic),
179
- underline: asUnaryFn(record.underline),
180
- inverse: asInverse(record.inverse),
186
+ italic: asUnaryFn(record.italic, raw),
187
+ underline: asUnaryFn(record.underline, raw),
188
+ inverse: asInverse(record.inverse, raw),
181
189
  };
182
190
  }