@pi-orca/core 0.0.2-dev.20260413162335

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.
Files changed (87) hide show
  1. package/README.md +228 -0
  2. package/defaults/config.yaml +28 -0
  3. package/dist/index.d.ts +8 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +8 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/types/agent.d.ts +72 -0
  8. package/dist/types/agent.d.ts.map +1 -0
  9. package/dist/types/agent.js +6 -0
  10. package/dist/types/agent.js.map +1 -0
  11. package/dist/types/archivable.d.ts +23 -0
  12. package/dist/types/archivable.d.ts.map +1 -0
  13. package/dist/types/archivable.js +47 -0
  14. package/dist/types/archivable.js.map +1 -0
  15. package/dist/types/config.d.ts +42 -0
  16. package/dist/types/config.d.ts.map +1 -0
  17. package/dist/types/config.js +42 -0
  18. package/dist/types/config.js.map +1 -0
  19. package/dist/types/index.d.ts +12 -0
  20. package/dist/types/index.d.ts.map +1 -0
  21. package/dist/types/index.js +12 -0
  22. package/dist/types/index.js.map +1 -0
  23. package/dist/types/labels.d.ts +28 -0
  24. package/dist/types/labels.d.ts.map +1 -0
  25. package/dist/types/labels.js +45 -0
  26. package/dist/types/labels.js.map +1 -0
  27. package/dist/types/lock.d.ts +16 -0
  28. package/dist/types/lock.d.ts.map +1 -0
  29. package/dist/types/lock.js +6 -0
  30. package/dist/types/lock.js.map +1 -0
  31. package/dist/types/message.d.ts +29 -0
  32. package/dist/types/message.d.ts.map +1 -0
  33. package/dist/types/message.js +6 -0
  34. package/dist/types/message.js.map +1 -0
  35. package/dist/types/task.d.ts +45 -0
  36. package/dist/types/task.d.ts.map +1 -0
  37. package/dist/types/task.js +27 -0
  38. package/dist/types/task.js.map +1 -0
  39. package/dist/types/team.d.ts +38 -0
  40. package/dist/types/team.d.ts.map +1 -0
  41. package/dist/types/team.js +6 -0
  42. package/dist/types/team.js.map +1 -0
  43. package/dist/utils/autocomplete.d.ts +42 -0
  44. package/dist/utils/autocomplete.d.ts.map +1 -0
  45. package/dist/utils/autocomplete.js +111 -0
  46. package/dist/utils/autocomplete.js.map +1 -0
  47. package/dist/utils/config-loader.d.ts +17 -0
  48. package/dist/utils/config-loader.d.ts.map +1 -0
  49. package/dist/utils/config-loader.js +81 -0
  50. package/dist/utils/config-loader.js.map +1 -0
  51. package/dist/utils/dag.d.ts +34 -0
  52. package/dist/utils/dag.d.ts.map +1 -0
  53. package/dist/utils/dag.js +96 -0
  54. package/dist/utils/dag.js.map +1 -0
  55. package/dist/utils/duration.d.ts +21 -0
  56. package/dist/utils/duration.d.ts.map +1 -0
  57. package/dist/utils/duration.js +47 -0
  58. package/dist/utils/duration.js.map +1 -0
  59. package/dist/utils/filesystem.d.ts +53 -0
  60. package/dist/utils/filesystem.d.ts.map +1 -0
  61. package/dist/utils/filesystem.js +99 -0
  62. package/dist/utils/filesystem.js.map +1 -0
  63. package/dist/utils/heartbeat.d.ts +23 -0
  64. package/dist/utils/heartbeat.d.ts.map +1 -0
  65. package/dist/utils/heartbeat.js +53 -0
  66. package/dist/utils/heartbeat.js.map +1 -0
  67. package/dist/utils/index.d.ts +14 -0
  68. package/dist/utils/index.d.ts.map +1 -0
  69. package/dist/utils/index.js +14 -0
  70. package/dist/utils/index.js.map +1 -0
  71. package/dist/utils/lock.d.ts +43 -0
  72. package/dist/utils/lock.d.ts.map +1 -0
  73. package/dist/utils/lock.js +89 -0
  74. package/dist/utils/lock.js.map +1 -0
  75. package/dist/utils/path.d.ts +88 -0
  76. package/dist/utils/path.d.ts.map +1 -0
  77. package/dist/utils/path.js +128 -0
  78. package/dist/utils/path.js.map +1 -0
  79. package/dist/utils/process.d.ts +20 -0
  80. package/dist/utils/process.d.ts.map +1 -0
  81. package/dist/utils/process.js +40 -0
  82. package/dist/utils/process.js.map +1 -0
  83. package/dist/utils/yaml.d.ts +30 -0
  84. package/dist/utils/yaml.d.ts.map +1 -0
  85. package/dist/utils/yaml.js +58 -0
  86. package/dist/utils/yaml.js.map +1 -0
  87. package/package.json +47 -0
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Duration parsing utilities.
3
+ * Spec: §3.7 — Duration Parsing
4
+ */
5
+ /**
6
+ * Parse a duration string to milliseconds.
7
+ * Supports: 30s, 5m, 2h, 7d, 14d
8
+ *
9
+ * @param input - Duration string
10
+ * @returns Milliseconds
11
+ * @throws Error if format is invalid
12
+ */
13
+ export function parseDuration(input) {
14
+ const match = input.match(/^(\d+)([smhd])$/);
15
+ if (!match) {
16
+ throw new Error(`Invalid duration format: ${input}. Expected format: <number><unit> (e.g., 30s, 5m, 2h, 7d)`);
17
+ }
18
+ const value = parseInt(match[1], 10);
19
+ const unit = match[2];
20
+ const multipliers = {
21
+ s: 1000,
22
+ m: 60 * 1000,
23
+ h: 60 * 60 * 1000,
24
+ d: 24 * 60 * 60 * 1000,
25
+ };
26
+ return value * multipliers[unit];
27
+ }
28
+ /**
29
+ * Format milliseconds to a human-readable duration string.
30
+ *
31
+ * @param ms - Milliseconds
32
+ * @returns Human-readable duration (e.g., "5m", "2h", "7d")
33
+ */
34
+ export function formatDuration(ms) {
35
+ const seconds = Math.floor(ms / 1000);
36
+ const minutes = Math.floor(seconds / 60);
37
+ const hours = Math.floor(minutes / 60);
38
+ const days = Math.floor(hours / 24);
39
+ if (days > 0)
40
+ return `${days}d`;
41
+ if (hours > 0)
42
+ return `${hours}h`;
43
+ if (minutes > 0)
44
+ return `${minutes}m`;
45
+ return `${seconds}s`;
46
+ }
47
+ //# sourceMappingURL=duration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duration.js","sourceRoot":"","sources":["../../src/utils/duration.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,2DAA2D,CAAC,CAAC;IAChH,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAEtB,MAAM,WAAW,GAA2B;QAC1C,CAAC,EAAE,IAAI;QACP,CAAC,EAAE,EAAE,GAAG,IAAI;QACZ,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;QACjB,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;KACvB,CAAC;IAEF,OAAO,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IAEpC,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,GAAG,IAAI,GAAG,CAAC;IAChC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,GAAG,KAAK,GAAG,CAAC;IAClC,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,GAAG,OAAO,GAAG,CAAC;IACtC,OAAO,GAAG,OAAO,GAAG,CAAC;AACvB,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Filesystem utilities.
3
+ * Spec: §3.2 — Filesystem Helpers
4
+ */
5
+ /**
6
+ * Atomic file write using write-to-tmp-then-rename pattern.
7
+ * Spec: §10 mentions write-to-tmp-then-rename
8
+ *
9
+ * @param filePath - Target file path
10
+ * @param content - Content to write
11
+ */
12
+ export declare function atomicWrite(filePath: string, content: string): Promise<void>;
13
+ /**
14
+ * Ensure directory exists (recursive mkdir).
15
+ *
16
+ * @param dirPath - Directory path
17
+ */
18
+ export declare function ensureDir(dirPath: string): Promise<void>;
19
+ /**
20
+ * Ensure directory exists (synchronous).
21
+ *
22
+ * @param dirPath - Directory path
23
+ */
24
+ export declare function ensureDirSync(dirPath: string): void;
25
+ /**
26
+ * Bootstrap a file with default content if it doesn't exist.
27
+ * Spec: §2.1 "Bootstrap on first access"
28
+ *
29
+ * @param filePath - File path
30
+ * @param defaultContent - Default content (string or object for YAML)
31
+ * @param options - Bootstrap options
32
+ * @returns Created flag and content
33
+ */
34
+ export declare function bootstrapFile<T>(filePath: string, defaultContent: T | string, options?: {
35
+ notify?: boolean;
36
+ }): Promise<{
37
+ created: boolean;
38
+ content: T;
39
+ }>;
40
+ /**
41
+ * Safe file read that returns null if file doesn't exist.
42
+ *
43
+ * @param filePath - File path
44
+ * @returns File content or null
45
+ */
46
+ export declare function readFileIfExists(filePath: string): Promise<string | null>;
47
+ /**
48
+ * Safe file delete (no error if doesn't exist).
49
+ *
50
+ * @param filePath - File path
51
+ */
52
+ export declare function deleteFileIfExists(filePath: string): Promise<void>;
53
+ //# sourceMappingURL=filesystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/utils/filesystem.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYlF;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAKnD;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,CAAC,GAAG,MAAM,EAC1B,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC,CA8B3C;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAK/E;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxE"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Filesystem utilities.
3
+ * Spec: §3.2 — Filesystem Helpers
4
+ */
5
+ import { mkdir, writeFile, rename, readFile, unlink } from "fs/promises";
6
+ import { dirname } from "path";
7
+ import { existsSync } from "fs";
8
+ /**
9
+ * Atomic file write using write-to-tmp-then-rename pattern.
10
+ * Spec: §10 mentions write-to-tmp-then-rename
11
+ *
12
+ * @param filePath - Target file path
13
+ * @param content - Content to write
14
+ */
15
+ export async function atomicWrite(filePath, content) {
16
+ const tmpPath = `${filePath}.tmp`;
17
+ const dir = dirname(filePath);
18
+ // Ensure parent directory exists
19
+ await ensureDir(dir);
20
+ // Write to temp file
21
+ await writeFile(tmpPath, content, "utf-8");
22
+ // Atomic rename
23
+ await rename(tmpPath, filePath);
24
+ }
25
+ /**
26
+ * Ensure directory exists (recursive mkdir).
27
+ *
28
+ * @param dirPath - Directory path
29
+ */
30
+ export async function ensureDir(dirPath) {
31
+ await mkdir(dirPath, { recursive: true });
32
+ }
33
+ /**
34
+ * Ensure directory exists (synchronous).
35
+ *
36
+ * @param dirPath - Directory path
37
+ */
38
+ export function ensureDirSync(dirPath) {
39
+ if (!existsSync(dirPath)) {
40
+ // Note: Using fs.mkdirSync would be better, but keeping async pattern
41
+ throw new Error(`ensureDirSync not implemented - use ensureDir instead`);
42
+ }
43
+ }
44
+ /**
45
+ * Bootstrap a file with default content if it doesn't exist.
46
+ * Spec: §2.1 "Bootstrap on first access"
47
+ *
48
+ * @param filePath - File path
49
+ * @param defaultContent - Default content (string or object for YAML)
50
+ * @param options - Bootstrap options
51
+ * @returns Created flag and content
52
+ */
53
+ export async function bootstrapFile(filePath, defaultContent, options) {
54
+ // If file exists, read and return it
55
+ if (existsSync(filePath)) {
56
+ const existing = await readFile(filePath, "utf-8");
57
+ // If defaultContent is an object, parse as YAML
58
+ if (typeof defaultContent !== "string") {
59
+ const YAML = await import("yaml");
60
+ const parsed = YAML.parse(existing);
61
+ return { created: false, content: parsed };
62
+ }
63
+ return { created: false, content: existing };
64
+ }
65
+ // Create with defaults
66
+ const dir = dirname(filePath);
67
+ await ensureDir(dir);
68
+ const contentStr = typeof defaultContent === "string"
69
+ ? defaultContent
70
+ : await import("yaml").then(YAML => YAML.stringify(defaultContent));
71
+ await atomicWrite(filePath, contentStr);
72
+ if (options?.notify) {
73
+ console.log(`Created default config at ${filePath}`);
74
+ }
75
+ return { created: true, content: defaultContent };
76
+ }
77
+ /**
78
+ * Safe file read that returns null if file doesn't exist.
79
+ *
80
+ * @param filePath - File path
81
+ * @returns File content or null
82
+ */
83
+ export async function readFileIfExists(filePath) {
84
+ if (!existsSync(filePath)) {
85
+ return null;
86
+ }
87
+ return readFile(filePath, "utf-8");
88
+ }
89
+ /**
90
+ * Safe file delete (no error if doesn't exist).
91
+ *
92
+ * @param filePath - File path
93
+ */
94
+ export async function deleteFileIfExists(filePath) {
95
+ if (existsSync(filePath)) {
96
+ await unlink(filePath);
97
+ }
98
+ }
99
+ //# sourceMappingURL=filesystem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../../src/utils/filesystem.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Heartbeat utilities.
3
+ * Spec: §5.6 — Heartbeat and Cost Tracking
4
+ */
5
+ export interface HeartbeatOptions {
6
+ filePath: string;
7
+ intervalMs: number;
8
+ updateFn: (data: any) => any;
9
+ }
10
+ export interface Heartbeat {
11
+ start(): void;
12
+ stop(): void;
13
+ update(patch: Partial<any>): void;
14
+ }
15
+ /**
16
+ * Create a heartbeat timer that periodically writes status to a file.
17
+ * Spec: §5.6 — Heartbeat and Cost Tracking
18
+ *
19
+ * @param options - Heartbeat configuration
20
+ * @returns Heartbeat controller
21
+ */
22
+ export declare function createHeartbeat(options: HeartbeatOptions): Heartbeat;
23
+ //# sourceMappingURL=heartbeat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../../src/utils/heartbeat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC;CAC9B;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;IACb,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;CACnC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CA0CpE"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Heartbeat utilities.
3
+ * Spec: §5.6 — Heartbeat and Cost Tracking
4
+ */
5
+ import { atomicWrite } from "./filesystem.js";
6
+ import YAML from "yaml";
7
+ /**
8
+ * Create a heartbeat timer that periodically writes status to a file.
9
+ * Spec: §5.6 — Heartbeat and Cost Tracking
10
+ *
11
+ * @param options - Heartbeat configuration
12
+ * @returns Heartbeat controller
13
+ */
14
+ export function createHeartbeat(options) {
15
+ const { filePath, intervalMs, updateFn } = options;
16
+ let timer = null;
17
+ let data = {};
18
+ const writeStatus = async () => {
19
+ try {
20
+ const updated = updateFn(data);
21
+ updated.lastHeartbeat = new Date().toISOString();
22
+ const content = YAML.stringify(updated);
23
+ await atomicWrite(filePath, content);
24
+ }
25
+ catch (error) {
26
+ console.error("Heartbeat write failed:", error);
27
+ }
28
+ };
29
+ return {
30
+ start() {
31
+ if (timer)
32
+ return;
33
+ // Initial write
34
+ writeStatus();
35
+ // Set up interval
36
+ timer = setInterval(() => {
37
+ writeStatus();
38
+ }, intervalMs);
39
+ },
40
+ stop() {
41
+ if (timer) {
42
+ clearInterval(timer);
43
+ timer = null;
44
+ }
45
+ // Final flush
46
+ writeStatus();
47
+ },
48
+ update(patch) {
49
+ data = { ...data, ...patch };
50
+ },
51
+ };
52
+ }
53
+ //# sourceMappingURL=heartbeat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../src/utils/heartbeat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,IAAI,MAAM,MAAM,CAAC;AAcxB;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,OAAyB;IACvD,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IACnD,IAAI,KAAK,GAA0B,IAAI,CAAC;IACxC,IAAI,IAAI,GAAQ,EAAE,CAAC;IAEnB,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC/B,OAAO,CAAC,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACjD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACxC,MAAM,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,KAAK;YACH,IAAI,KAAK;gBAAE,OAAO;YAElB,gBAAgB;YAChB,WAAW,EAAE,CAAC;YAEd,kBAAkB;YAClB,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;gBACvB,WAAW,EAAE,CAAC;YAChB,CAAC,EAAE,UAAU,CAAC,CAAC;QACjB,CAAC;QAED,IAAI;YACF,IAAI,KAAK,EAAE,CAAC;gBACV,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;YACD,cAAc;YACd,WAAW,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,CAAC,KAAmB;YACxB,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC;QAC/B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Pi Orca Core Utilities
3
+ */
4
+ export * from "./duration.js";
5
+ export * from "./path.js";
6
+ export * from "./yaml.js";
7
+ export * from "./filesystem.js";
8
+ export * from "./lock.js";
9
+ export * from "./process.js";
10
+ export * from "./dag.js";
11
+ export * from "./heartbeat.js";
12
+ export * from "./config-loader.js";
13
+ export * from "./autocomplete.js";
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Pi Orca Core Utilities
3
+ */
4
+ export * from "./duration.js";
5
+ export * from "./path.js";
6
+ export * from "./yaml.js";
7
+ export * from "./filesystem.js";
8
+ export * from "./lock.js";
9
+ export * from "./process.js";
10
+ export * from "./dag.js";
11
+ export * from "./heartbeat.js";
12
+ export * from "./config-loader.js";
13
+ export * from "./autocomplete.js";
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Lock file utilities.
3
+ * Spec: §3.4 — Lock File Schema
4
+ */
5
+ import { LockInfo } from "../types/lock.js";
6
+ /**
7
+ * Acquire a lock file.
8
+ * Fails if lock exists and PID is alive.
9
+ * Succeeds if lock doesn't exist or PID is dead (stale lock).
10
+ * Spec: §3.4 — Lock File Management
11
+ *
12
+ * @param lockPath - Path to lock file
13
+ * @param sessionInfo - Session information for the lock
14
+ * @returns true if lock acquired, false if already held by another session
15
+ */
16
+ export declare function acquireLock(lockPath: string, sessionInfo: LockInfo): Promise<boolean>;
17
+ /**
18
+ * Release a lock file.
19
+ * Only releases if current session holds the lock.
20
+ * Spec: §3.4 — Lock File Management
21
+ *
22
+ * @param lockPath - Path to lock file
23
+ * @param sessionId - Session ID attempting to release
24
+ * @returns true if lock released, false if not held by this session
25
+ */
26
+ export declare function releaseLock(lockPath: string, sessionId: string): Promise<boolean>;
27
+ /**
28
+ * Read a lock file.
29
+ * Spec: §3.4 — Lock File Management
30
+ *
31
+ * @param lockPath - Path to lock file
32
+ * @returns Lock info or null if doesn't exist
33
+ */
34
+ export declare function readLock(lockPath: string): Promise<LockInfo | null>;
35
+ /**
36
+ * Check if a lock file is stale (PID is dead).
37
+ * Spec: §3.4 — Lock File Management
38
+ *
39
+ * @param lockPath - Path to lock file
40
+ * @returns true if lock is stale
41
+ */
42
+ export declare function isLockStale(lockPath: string): Promise<boolean>;
43
+ //# sourceMappingURL=lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/utils/lock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAI5C;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAgB3F;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYvF;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAWzE;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOpE"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Lock file utilities.
3
+ * Spec: §3.4 — Lock File Schema
4
+ */
5
+ import { existsSync } from "fs";
6
+ import { readFile } from "fs/promises";
7
+ import YAML from "yaml";
8
+ import { atomicWrite, deleteFileIfExists } from "./filesystem.js";
9
+ import { isPidAlive } from "./process.js";
10
+ /**
11
+ * Acquire a lock file.
12
+ * Fails if lock exists and PID is alive.
13
+ * Succeeds if lock doesn't exist or PID is dead (stale lock).
14
+ * Spec: §3.4 — Lock File Management
15
+ *
16
+ * @param lockPath - Path to lock file
17
+ * @param sessionInfo - Session information for the lock
18
+ * @returns true if lock acquired, false if already held by another session
19
+ */
20
+ export async function acquireLock(lockPath, sessionInfo) {
21
+ // Check if lock exists
22
+ if (existsSync(lockPath)) {
23
+ // Check if lock is stale
24
+ const isStale = await isLockStale(lockPath);
25
+ if (!isStale) {
26
+ return false; // Lock held by live process
27
+ }
28
+ // Remove stale lock
29
+ await deleteFileIfExists(lockPath);
30
+ }
31
+ // Create lock
32
+ const lockContent = YAML.stringify(sessionInfo);
33
+ await atomicWrite(lockPath, lockContent);
34
+ return true;
35
+ }
36
+ /**
37
+ * Release a lock file.
38
+ * Only releases if current session holds the lock.
39
+ * Spec: §3.4 — Lock File Management
40
+ *
41
+ * @param lockPath - Path to lock file
42
+ * @param sessionId - Session ID attempting to release
43
+ * @returns true if lock released, false if not held by this session
44
+ */
45
+ export async function releaseLock(lockPath, sessionId) {
46
+ if (!existsSync(lockPath)) {
47
+ return false;
48
+ }
49
+ const lockInfo = await readLock(lockPath);
50
+ if (!lockInfo || lockInfo.sessionId !== sessionId) {
51
+ return false; // Not our lock
52
+ }
53
+ await deleteFileIfExists(lockPath);
54
+ return true;
55
+ }
56
+ /**
57
+ * Read a lock file.
58
+ * Spec: §3.4 — Lock File Management
59
+ *
60
+ * @param lockPath - Path to lock file
61
+ * @returns Lock info or null if doesn't exist
62
+ */
63
+ export async function readLock(lockPath) {
64
+ if (!existsSync(lockPath)) {
65
+ return null;
66
+ }
67
+ try {
68
+ const content = await readFile(lockPath, "utf-8");
69
+ return YAML.parse(content);
70
+ }
71
+ catch {
72
+ return null;
73
+ }
74
+ }
75
+ /**
76
+ * Check if a lock file is stale (PID is dead).
77
+ * Spec: §3.4 — Lock File Management
78
+ *
79
+ * @param lockPath - Path to lock file
80
+ * @returns true if lock is stale
81
+ */
82
+ export async function isLockStale(lockPath) {
83
+ const lockInfo = await readLock(lockPath);
84
+ if (!lockInfo) {
85
+ return true; // No lock = stale
86
+ }
87
+ return !isPidAlive(lockInfo.pid);
88
+ }
89
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/utils/lock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,WAAqB;IACvE,uBAAuB;IACvB,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,yBAAyB;QACzB,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,KAAK,CAAC,CAAC,4BAA4B;QAC5C,CAAC;QACD,oBAAoB;QACpB,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,cAAc;IACd,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,SAAiB;IACnE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC,CAAC,eAAe;IAC/B,CAAC;IAED,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACnC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAgB;IAC7C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAa,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB;IAChD,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,CAAC,kBAAkB;IACjC,CAAC;IAED,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Path resolution utilities.
3
+ * Spec: §3.2 — Filesystem Helpers
4
+ */
5
+ /**
6
+ * Get current project slug.
7
+ * For now, returns the current directory basename.
8
+ * TODO: Integrate with Pi's project slug detection.
9
+ *
10
+ * @returns Project slug
11
+ */
12
+ export declare function getProjectSlug(): string;
13
+ /**
14
+ * Get Orca runtime directory for a project.
15
+ * ~/.pi/agent/sessions/<project-slug>/orca/
16
+ *
17
+ * Override the base directory with PI_ORCA_BASE_DIR env var (used by tests).
18
+ *
19
+ * @param projectSlug - Project slug (defaults to current)
20
+ * @returns Absolute path to runtime directory
21
+ */
22
+ export declare function getOrcaRuntimeDir(projectSlug?: string): string;
23
+ /**
24
+ * Get Orca tasks directory.
25
+ * ~/.pi/agent/sessions/<project-slug>/orca/tasks/
26
+ *
27
+ * @param projectSlug - Project slug (defaults to current)
28
+ * @returns Absolute path to tasks directory
29
+ */
30
+ export declare function getOrcaTasksDir(projectSlug?: string): string;
31
+ /**
32
+ * Get Orca messages store directory.
33
+ * ~/.pi/agent/sessions/<project-slug>/orca/messages/store/
34
+ *
35
+ * @param projectSlug - Project slug (defaults to current)
36
+ * @returns Absolute path to messages store
37
+ */
38
+ export declare function getOrcaMessagesStoreDir(projectSlug?: string): string;
39
+ /**
40
+ * Get Orca messages inbox directory for a session.
41
+ * ~/.pi/agent/sessions/<project-slug>/orca/messages/inbox/<session-id>/
42
+ *
43
+ * @param sessionId - Session ID
44
+ * @param projectSlug - Project slug (defaults to current)
45
+ * @returns Absolute path to inbox directory
46
+ */
47
+ export declare function getOrcaMessagesInboxDir(sessionId: string, projectSlug?: string): string;
48
+ /**
49
+ * Get sibling .orca directory for a session JSONL file.
50
+ * Replaces .jsonl extension with .orca
51
+ *
52
+ * @param sessionPath - Path to session JSONL file (relative or absolute)
53
+ * @returns Absolute path to sibling .orca directory
54
+ */
55
+ export declare function getOrcaSiblingDir(sessionPath: string): string;
56
+ /**
57
+ * Get user-level Orca directory.
58
+ * ~/.pi/agent/orca/
59
+ *
60
+ * Override the base directory with PI_ORCA_USER_DIR env var (used by tests).
61
+ *
62
+ * @returns Absolute path to user Orca directory
63
+ */
64
+ export declare function getUserOrcaDir(): string;
65
+ /**
66
+ * Get project-level Orca directory.
67
+ * <project>/.pi/orca/
68
+ *
69
+ * @param projectRoot - Project root directory (defaults to cwd)
70
+ * @returns Absolute path to project Orca directory
71
+ */
72
+ export declare function getProjectOrcaDir(projectRoot?: string): string;
73
+ /**
74
+ * Resolve session path to absolute.
75
+ * If path is relative, resolves against ~/.pi/agent/sessions/
76
+ *
77
+ * @param sessionPath - Session path (relative or absolute)
78
+ * @returns Absolute path
79
+ */
80
+ export declare function resolveSessionPath(sessionPath: string): string;
81
+ /**
82
+ * Make session path relative to ~/.pi/agent/sessions/
83
+ *
84
+ * @param absolutePath - Absolute session path
85
+ * @returns Relative path
86
+ */
87
+ export declare function makeSessionPathRelative(absolutePath: string): string;
88
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;;;;;GAMG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAM9D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAU7D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAMpE"}