@pi-harness/pi-harness 0.1.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.
Files changed (185) hide show
  1. package/README.md +161 -0
  2. package/apps/web/dist/assets/index-C4tLweAB.js +20 -0
  3. package/apps/web/dist/assets/index-DPgRbQ4_.css +1 -0
  4. package/apps/web/dist/index.html +14 -0
  5. package/apps/web/index.html +13 -0
  6. package/apps/web/package.json +24 -0
  7. package/apps/web/profile/cordis.yml +44 -0
  8. package/apps/web/server-dist/bin.d.ts +3 -0
  9. package/apps/web/server-dist/bin.d.ts.map +1 -0
  10. package/apps/web/server-dist/bin.js +67 -0
  11. package/apps/web/server-dist/bin.js.map +1 -0
  12. package/apps/web/src/command-palette.ts +84 -0
  13. package/apps/web/src/file-diff.ts +42 -0
  14. package/apps/web/src/main.ts +12 -0
  15. package/apps/web/src/runtime.css +4 -0
  16. package/apps/web/src/server/bin.ts +64 -0
  17. package/apps/web/src/style.css +7 -0
  18. package/apps/web/tsconfig.build.json +1 -0
  19. package/apps/web/tsconfig.json +1 -0
  20. package/package.json +48 -0
  21. package/packages/api-gateway/dist/index.d.ts +8 -0
  22. package/packages/api-gateway/dist/index.d.ts.map +1 -0
  23. package/packages/api-gateway/dist/index.js +582 -0
  24. package/packages/api-gateway/dist/index.js.map +1 -0
  25. package/packages/api-gateway/package.json +29 -0
  26. package/packages/api-gateway/src/index.ts +577 -0
  27. package/packages/api-gateway/test/index.test.ts +327 -0
  28. package/packages/api-gateway/tsconfig.build.json +1 -0
  29. package/packages/api-gateway/tsconfig.json +1 -0
  30. package/packages/bundle-web-app/cordis.patch.yml +12 -0
  31. package/packages/bundle-web-app/dist/index.d.ts +12 -0
  32. package/packages/bundle-web-app/dist/index.d.ts.map +1 -0
  33. package/packages/bundle-web-app/dist/index.js +63 -0
  34. package/packages/bundle-web-app/dist/index.js.map +1 -0
  35. package/packages/bundle-web-app/package.json +30 -0
  36. package/packages/bundle-web-app/src/index.ts +69 -0
  37. package/packages/bundle-web-app/test/index.test.ts +29 -0
  38. package/packages/bundle-web-app/tsconfig.build.json +1 -0
  39. package/packages/bundle-web-app/tsconfig.json +1 -0
  40. package/packages/cli/dist/args.d.ts +16 -0
  41. package/packages/cli/dist/args.d.ts.map +1 -0
  42. package/packages/cli/dist/args.js +53 -0
  43. package/packages/cli/dist/args.js.map +1 -0
  44. package/packages/cli/dist/bin.d.ts +3 -0
  45. package/packages/cli/dist/bin.d.ts.map +1 -0
  46. package/packages/cli/dist/bin.js +40 -0
  47. package/packages/cli/dist/bin.js.map +1 -0
  48. package/packages/cli/dist/main.d.ts +14 -0
  49. package/packages/cli/dist/main.d.ts.map +1 -0
  50. package/packages/cli/dist/main.js +148 -0
  51. package/packages/cli/dist/main.js.map +1 -0
  52. package/packages/cli/dist/node-stdio.d.ts +10 -0
  53. package/packages/cli/dist/node-stdio.d.ts.map +1 -0
  54. package/packages/cli/dist/node-stdio.js +34 -0
  55. package/packages/cli/dist/node-stdio.js.map +1 -0
  56. package/packages/cli/dist/relaunch.d.ts +5 -0
  57. package/packages/cli/dist/relaunch.d.ts.map +1 -0
  58. package/packages/cli/dist/relaunch.js +52 -0
  59. package/packages/cli/dist/relaunch.js.map +1 -0
  60. package/packages/cli/package.json +25 -0
  61. package/packages/cli/src/args.ts +50 -0
  62. package/packages/cli/src/bin.ts +41 -0
  63. package/packages/cli/src/main.ts +155 -0
  64. package/packages/cli/src/node-stdio.ts +40 -0
  65. package/packages/cli/src/relaunch.ts +48 -0
  66. package/packages/cli/test/args.test.ts +28 -0
  67. package/packages/cli/test/cli.test.ts +153 -0
  68. package/packages/cli/test/relaunch.test.ts +29 -0
  69. package/packages/cli/tsconfig.build.json +11 -0
  70. package/packages/cli/tsconfig.json +10 -0
  71. package/packages/client-web/dist/control-room.d.ts +102 -0
  72. package/packages/client-web/dist/control-room.d.ts.map +1 -0
  73. package/packages/client-web/dist/control-room.js +12 -0
  74. package/packages/client-web/dist/control-room.js.map +1 -0
  75. package/packages/client-web/dist/design-contract.d.ts +85 -0
  76. package/packages/client-web/dist/design-contract.d.ts.map +1 -0
  77. package/packages/client-web/dist/design-contract.js +99 -0
  78. package/packages/client-web/dist/design-contract.js.map +1 -0
  79. package/packages/client-web/dist/index.d.ts +17 -0
  80. package/packages/client-web/dist/index.d.ts.map +1 -0
  81. package/packages/client-web/dist/index.js +19 -0
  82. package/packages/client-web/dist/index.js.map +1 -0
  83. package/packages/client-web/dist/react-room.d.ts +6 -0
  84. package/packages/client-web/dist/react-room.d.ts.map +1 -0
  85. package/packages/client-web/dist/react-room.js +103 -0
  86. package/packages/client-web/dist/react-room.js.map +1 -0
  87. package/packages/client-web/package.json +29 -0
  88. package/packages/client-web/src/control-room.ts +10 -0
  89. package/packages/client-web/src/design-contract.ts +112 -0
  90. package/packages/client-web/src/index.ts +21 -0
  91. package/packages/client-web/src/react-room.tsx +78 -0
  92. package/packages/client-web/test/design-contract.test.ts +24 -0
  93. package/packages/client-web/tsconfig.build.json +1 -0
  94. package/packages/client-web/tsconfig.json +1 -0
  95. package/packages/core/dist/boot.d.ts +13 -0
  96. package/packages/core/dist/boot.d.ts.map +1 -0
  97. package/packages/core/dist/boot.js +96 -0
  98. package/packages/core/dist/boot.js.map +1 -0
  99. package/packages/core/dist/context.d.ts +3 -0
  100. package/packages/core/dist/context.d.ts.map +1 -0
  101. package/packages/core/dist/context.js +2 -0
  102. package/packages/core/dist/context.js.map +1 -0
  103. package/packages/core/dist/index.d.ts +7 -0
  104. package/packages/core/dist/index.d.ts.map +1 -0
  105. package/packages/core/dist/index.js +6 -0
  106. package/packages/core/dist/index.js.map +1 -0
  107. package/packages/core/dist/plugins/model.d.ts +8 -0
  108. package/packages/core/dist/plugins/model.d.ts.map +1 -0
  109. package/packages/core/dist/plugins/model.js +12 -0
  110. package/packages/core/dist/plugins/model.js.map +1 -0
  111. package/packages/core/dist/plugins/models.d.ts +16 -0
  112. package/packages/core/dist/plugins/models.d.ts.map +1 -0
  113. package/packages/core/dist/plugins/models.js +24 -0
  114. package/packages/core/dist/plugins/models.js.map +1 -0
  115. package/packages/core/dist/plugins/resources.d.ts +18 -0
  116. package/packages/core/dist/plugins/resources.d.ts.map +1 -0
  117. package/packages/core/dist/plugins/resources.js +48 -0
  118. package/packages/core/dist/plugins/resources.js.map +1 -0
  119. package/packages/core/dist/plugins/runtime.d.ts +14 -0
  120. package/packages/core/dist/plugins/runtime.d.ts.map +1 -0
  121. package/packages/core/dist/plugins/runtime.js +68 -0
  122. package/packages/core/dist/plugins/runtime.js.map +1 -0
  123. package/packages/core/dist/plugins/session.d.ts +15 -0
  124. package/packages/core/dist/plugins/session.d.ts.map +1 -0
  125. package/packages/core/dist/plugins/session.js +20 -0
  126. package/packages/core/dist/plugins/session.js.map +1 -0
  127. package/packages/core/dist/plugins/stdio.d.ts +8 -0
  128. package/packages/core/dist/plugins/stdio.d.ts.map +1 -0
  129. package/packages/core/dist/plugins/stdio.js +20 -0
  130. package/packages/core/dist/plugins/stdio.js.map +1 -0
  131. package/packages/core/dist/plugins/tools.d.ts +13 -0
  132. package/packages/core/dist/plugins/tools.d.ts.map +1 -0
  133. package/packages/core/dist/plugins/tools.js +17 -0
  134. package/packages/core/dist/plugins/tools.js.map +1 -0
  135. package/packages/core/dist/profile.d.ts +8 -0
  136. package/packages/core/dist/profile.d.ts.map +1 -0
  137. package/packages/core/dist/profile.js +28 -0
  138. package/packages/core/dist/profile.js.map +1 -0
  139. package/packages/core/dist/runtime.d.ts +16 -0
  140. package/packages/core/dist/runtime.d.ts.map +1 -0
  141. package/packages/core/dist/runtime.js +33 -0
  142. package/packages/core/dist/runtime.js.map +1 -0
  143. package/packages/core/dist/services.d.ts +63 -0
  144. package/packages/core/dist/services.d.ts.map +1 -0
  145. package/packages/core/dist/services.js +39 -0
  146. package/packages/core/dist/services.js.map +1 -0
  147. package/packages/core/dist/stdio.d.ts +25 -0
  148. package/packages/core/dist/stdio.d.ts.map +1 -0
  149. package/packages/core/dist/stdio.js +74 -0
  150. package/packages/core/dist/stdio.js.map +1 -0
  151. package/packages/core/package.json +44 -0
  152. package/packages/core/profiles/default/cordis.yml +35 -0
  153. package/packages/core/profiles/development/cordis.yml +47 -0
  154. package/packages/core/src/boot.ts +103 -0
  155. package/packages/core/src/context.ts +3 -0
  156. package/packages/core/src/index.ts +6 -0
  157. package/packages/core/src/plugins/model.ts +12 -0
  158. package/packages/core/src/plugins/models.ts +32 -0
  159. package/packages/core/src/plugins/resources.ts +57 -0
  160. package/packages/core/src/plugins/runtime.ts +73 -0
  161. package/packages/core/src/plugins/session.ts +27 -0
  162. package/packages/core/src/plugins/stdio.ts +20 -0
  163. package/packages/core/src/plugins/tools.ts +23 -0
  164. package/packages/core/src/profile.ts +31 -0
  165. package/packages/core/src/runtime.ts +39 -0
  166. package/packages/core/src/services.ts +105 -0
  167. package/packages/core/src/stdio.ts +88 -0
  168. package/packages/core/test/boot.test.ts +86 -0
  169. package/packages/core/test/profile.test.ts +39 -0
  170. package/packages/core/test/profiles.integration.test.ts +93 -0
  171. package/packages/core/test/runtime-fixture.ts +31 -0
  172. package/packages/core/test/runtime.test.ts +54 -0
  173. package/packages/core/test/services.test.ts +131 -0
  174. package/packages/core/test/stdio.test.ts +87 -0
  175. package/packages/core/tsconfig.build.json +10 -0
  176. package/packages/core/tsconfig.json +10 -0
  177. package/packages/host-webserver/dist/index.d.ts +29 -0
  178. package/packages/host-webserver/dist/index.d.ts.map +1 -0
  179. package/packages/host-webserver/dist/index.js +73 -0
  180. package/packages/host-webserver/dist/index.js.map +1 -0
  181. package/packages/host-webserver/package.json +27 -0
  182. package/packages/host-webserver/src/index.ts +97 -0
  183. package/packages/host-webserver/test/index.test.ts +43 -0
  184. package/packages/host-webserver/tsconfig.build.json +1 -0
  185. package/packages/host-webserver/tsconfig.json +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,aAAc,SAAQ,KAAK;IACpB,IAAI,GAAG,eAAe,CAAC;CAC1C;AAID,SAAS,WAAW,CAAC,IAAuB,EAAE,KAAa,EAAE,MAAc;IACzE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAC9B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,MAAM,IAAI,aAAa,CAAC,GAAG,MAAM,mBAAmB,CAAC,CAAC;IACjG,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAuB;IACvD,IAAI,OAAO,GAAG,SAAS,CAAC;IACxB,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,UAA8B,CAAC;IACnC,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,eAAe,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;YAC/C,MAAM;QACR,CAAC;QACD,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC9D,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACpE,IAAI,GAAG,KAAK,eAAe,EAAE,CAAC;YAC5B,UAAU,GAAG,IAAI,CAAC;YAClB,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACxB,IAAI,eAAe;gBAAE,MAAM,IAAI,aAAa,CAAC,sCAAsC,CAAC,CAAC;YACrF,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;YAChD,eAAe,GAAG,IAAI,CAAC;YACvB,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACvB,IAAI,UAAU,KAAK,SAAS;gBAAE,MAAM,IAAI,aAAa,CAAC,qCAAqC,CAAC,CAAC;YAC7F,UAAU,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;YAClD,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,eAAe,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,eAAe,IAAI,UAAU,KAAK,SAAS;QAAE,MAAM,IAAI,aAAa,CAAC,gDAAgD,CAAC,CAAC;IAC3H,OAAO,UAAU,KAAK,SAAS;QAC7B,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE;QAC7D,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AACrE,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { runCli } from "./main.js";
7
+ import { shouldRelaunchForDevelopmentProfile, superviseDevelopmentProcess } from "./relaunch.js";
8
+ const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
9
+ const environment = {
10
+ cwd: process.cwd(),
11
+ agentDir: process.env.PI_AGENT_DIR ?? join(homedir(), ".pi", "agent"),
12
+ version: packageJson.version,
13
+ stdin: process.stdin,
14
+ stdout: process.stdout,
15
+ stderr: process.stderr,
16
+ shutdownTimeoutMs: 5_000,
17
+ forceExit(code) {
18
+ process.exit(code);
19
+ },
20
+ onSignal(listener) {
21
+ const signals = process.platform === "win32" ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
22
+ const handlers = signals.map((signal) => {
23
+ const handler = () => listener(signal);
24
+ process.on(signal, handler);
25
+ return { signal, handler };
26
+ });
27
+ return () => {
28
+ for (const { signal, handler } of handlers)
29
+ process.off(signal, handler);
30
+ };
31
+ },
32
+ };
33
+ const args = process.argv.slice(2);
34
+ if (shouldRelaunchForDevelopmentProfile(args, process.execArgv)) {
35
+ process.exitCode = await superviseDevelopmentProcess(process.execPath, ["--expose-internals", ...process.execArgv, fileURLToPath(import.meta.url), ...args], { stdio: "inherit" });
36
+ }
37
+ else {
38
+ process.exitCode = await runCli(args, environment);
39
+ }
40
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,MAAM,EAAuB,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,mCAAmC,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAEjG,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAwB,CAAC;AAEzH,MAAM,WAAW,GAAmB;IAClC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;IAClB,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC;IACrE,OAAO,EAAE,WAAW,CAAC,OAAO;IAC5B,KAAK,EAAE,OAAO,CAAC,KAAK;IACpB,MAAM,EAAE,OAAO,CAAC,MAAM;IACtB,MAAM,EAAE,OAAO,CAAC,MAAM;IACtB,iBAAiB,EAAE,KAAK;IACxB,SAAS,CAAC,IAAI;QACZ,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IACD,QAAQ,CAAC,QAAQ;QACf,MAAM,OAAO,GAAqB,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QACzH,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACtC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACvC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC5B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACV,KAAK,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,QAAQ;gBAAE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC3E,CAAC,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,IAAI,mCAAmC,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;IAChE,OAAO,CAAC,QAAQ,GAAG,MAAM,2BAA2B,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,oBAAoB,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AACrL,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { Readable, Writable } from "node:stream";
2
+ export interface CliEnvironment {
3
+ readonly cwd: string;
4
+ readonly agentDir: string;
5
+ readonly version: string;
6
+ readonly stdin: Readable;
7
+ readonly stdout: Writable;
8
+ readonly stderr: Writable;
9
+ readonly shutdownTimeoutMs: number;
10
+ forceExit(code: number): void;
11
+ onSignal(listener: (signal: NodeJS.Signals) => void): () => void;
12
+ }
13
+ export declare function runCli(_args: readonly string[], _environment: CliEnvironment): Promise<number>;
14
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAMtD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAClE;AAkBD,wBAAsB,MAAM,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,YAAY,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuHpG"}
@@ -0,0 +1,148 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { bootHarness, provideLaunchContext, provideStdioContext, resolveProfileConfig } from "@pi-harness/core";
3
+ import { CliUsageError, parseLauncherArgs } from "./args.js";
4
+ import { NodeStdio } from "./node-stdio.js";
5
+ import { PI_HARNESS_RESTART_EXIT_CODE } from "./relaunch.js";
6
+ async function settleWithin(promise, timeoutMs) {
7
+ let timer;
8
+ const timeout = new Promise((resolve) => {
9
+ timer = setTimeout(() => resolve({ settled: false }), timeoutMs);
10
+ });
11
+ const result = await Promise.race([promise.then((value) => ({ settled: true, value })), timeout]);
12
+ if (timer !== undefined)
13
+ clearTimeout(timer);
14
+ return result;
15
+ }
16
+ function signalExitCode(signal) {
17
+ return signal === "SIGINT" ? 130 : signal === "SIGHUP" ? 129 : 143;
18
+ }
19
+ export async function runCli(_args, _environment) {
20
+ const args = _args;
21
+ const environment = _environment;
22
+ let invocation;
23
+ try {
24
+ invocation = parseLauncherArgs(args);
25
+ }
26
+ catch (error) {
27
+ environment.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
28
+ return error instanceof CliUsageError ? 2 : 1;
29
+ }
30
+ if (invocation.mode === "help") {
31
+ environment.stdout.write("Usage: pih [--profile <name> | --config <path>] [--dump-config] [--] [--prompt <text> | <prompt>]\n");
32
+ return 0;
33
+ }
34
+ if (invocation.mode === "version") {
35
+ environment.stdout.write(`${environment.version}\n`);
36
+ return 0;
37
+ }
38
+ let configPath;
39
+ try {
40
+ configPath = await resolveProfileConfig({
41
+ ...(invocation.configPath === undefined ? { profile: invocation.profile ?? "default" } : { configPath: invocation.configPath }),
42
+ cwd: environment.cwd,
43
+ });
44
+ if (invocation.dumpConfig) {
45
+ environment.stdout.write(await readFile(configPath, "utf8"));
46
+ return 0;
47
+ }
48
+ }
49
+ catch (error) {
50
+ environment.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
51
+ return 2;
52
+ }
53
+ let harness;
54
+ let resultCode;
55
+ let forcedExit = false;
56
+ const forceExit = (code) => {
57
+ if (forcedExit)
58
+ return;
59
+ forcedExit = true;
60
+ environment.forceExit(code);
61
+ };
62
+ let requestedExit;
63
+ const requestedExitPromise = new Promise((resolve) => {
64
+ requestedExit = resolve;
65
+ });
66
+ let signalledExit;
67
+ const signalPromise = new Promise((resolve) => {
68
+ signalledExit = resolve;
69
+ });
70
+ const startupAbort = new AbortController();
71
+ const removeSignals = environment.onSignal((signal) => {
72
+ const code = signalExitCode(signal);
73
+ signalledExit?.(code);
74
+ startupAbort.abort(new Error(`Received ${signal}`));
75
+ });
76
+ try {
77
+ const stdio = new NodeStdio(environment.stdin, environment.stdout, environment.stderr);
78
+ const bootOutcome = bootHarness({
79
+ configPath,
80
+ signal: startupAbort.signal,
81
+ onFullReload() {
82
+ requestedExit?.(PI_HARNESS_RESTART_EXIT_CODE);
83
+ },
84
+ prepare(context) {
85
+ provideLaunchContext(context, {
86
+ cwd: environment.cwd,
87
+ agentDir: environment.agentDir,
88
+ args: invocation.args,
89
+ requestExit(code) {
90
+ requestedExit?.(code);
91
+ },
92
+ });
93
+ provideStdioContext(context, stdio);
94
+ },
95
+ }).then((booted) => ({ kind: "ready", harness: booted }), (error) => ({ kind: "error", error }));
96
+ const startup = await Promise.race([bootOutcome, signalPromise.then((code) => ({ kind: "signal", code }))]);
97
+ if (startup.kind === "signal") {
98
+ resultCode = startup.code;
99
+ const settled = await settleWithin(bootOutcome, environment.shutdownTimeoutMs);
100
+ if (!settled.settled) {
101
+ forceExit(startup.code);
102
+ return startup.code;
103
+ }
104
+ if (settled.value.kind === "ready")
105
+ harness = settled.value.harness;
106
+ return startup.code;
107
+ }
108
+ if (startup.kind === "error")
109
+ throw startup.error;
110
+ harness = startup.harness;
111
+ const application = harness.context.get("piApplication");
112
+ if (application === undefined)
113
+ throw new Error("Cordis profile did not provide a piApplication service");
114
+ const result = await Promise.race([
115
+ application.run().then((code) => ({ source: "application", code })),
116
+ requestedExitPromise.then((code) => ({ source: "request", code })),
117
+ signalPromise.then((code) => ({ source: "signal", code })),
118
+ ]);
119
+ resultCode = result.code;
120
+ if (result.source !== "application") {
121
+ const runtime = harness.context.get("piRuntime");
122
+ if (runtime !== undefined) {
123
+ const aborted = await settleWithin(runtime.abort().then(() => undefined, (error) => {
124
+ environment.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
125
+ }), environment.shutdownTimeoutMs);
126
+ if (!aborted.settled)
127
+ forceExit(result.code);
128
+ }
129
+ }
130
+ return result.code;
131
+ }
132
+ catch (error) {
133
+ environment.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
134
+ resultCode = 1;
135
+ return 1;
136
+ }
137
+ finally {
138
+ removeSignals();
139
+ if (harness !== undefined) {
140
+ const disposed = await settleWithin(harness.dispose().then(() => undefined, (error) => {
141
+ environment.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
142
+ }), environment.shutdownTimeoutMs);
143
+ if (!disposed.settled)
144
+ forceExit(resultCode ?? 1);
145
+ }
146
+ }
147
+ }
148
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Readable, Writable } from "node:stream";
2
+ import type { PiHarnessStdio } from "@pi-harness/core";
3
+ export declare class NodeStdio implements PiHarnessStdio {
4
+ #private;
5
+ constructor(input: Readable, output: Writable, error: Writable);
6
+ readPrompt(): Promise<string>;
7
+ writeOutput(text: string): void;
8
+ writeError(text: string): void;
9
+ }
10
+ //# sourceMappingURL=node-stdio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-stdio.d.ts","sourceRoot":"","sources":["../src/node-stdio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIvD,qBAAa,SAAU,YAAW,cAAc;;gBAKlC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ;IAMxD,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAenC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI/B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAG/B"}
@@ -0,0 +1,34 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ export class NodeStdio {
3
+ #input;
4
+ #output;
5
+ #error;
6
+ constructor(input, output, error) {
7
+ this.#input = input;
8
+ this.#output = output;
9
+ this.#error = error;
10
+ }
11
+ async readPrompt() {
12
+ if (this.#input.isTTY === true) {
13
+ const readline = createInterface({ input: this.#input, output: this.#output });
14
+ try {
15
+ return await readline.question("> ");
16
+ }
17
+ finally {
18
+ readline.close();
19
+ }
20
+ }
21
+ this.#input.setEncoding("utf8");
22
+ let content = "";
23
+ for await (const chunk of this.#input)
24
+ content += String(chunk);
25
+ return content.trimEnd();
26
+ }
27
+ writeOutput(text) {
28
+ this.#output.write(text);
29
+ }
30
+ writeError(text) {
31
+ this.#error.write(text);
32
+ }
33
+ }
34
+ //# sourceMappingURL=node-stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-stdio.js","sourceRoot":"","sources":["../src/node-stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAMzD,MAAM,OAAO,SAAS;IACX,MAAM,CAAmB;IACzB,OAAO,CAAW;IAClB,MAAM,CAAW;IAE1B,YAAY,KAAe,EAAE,MAAgB,EAAE,KAAe;QAC5D,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC/E,IAAI,CAAC;gBACH,OAAO,MAAM,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACvC,CAAC;oBAAS,CAAC;gBACT,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;QAChE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ import { type SpawnOptions } from "node:child_process";
2
+ export declare const PI_HARNESS_RESTART_EXIT_CODE = 75;
3
+ export declare function superviseDevelopmentProcess(command: string, args: readonly string[], options?: SpawnOptions): Promise<number>;
4
+ export declare function shouldRelaunchForDevelopmentProfile(args: readonly string[], execArgv: readonly string[]): boolean;
5
+ //# sourceMappingURL=relaunch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relaunch.d.ts","sourceRoot":"","sources":["../src/relaunch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG9D,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAS/C,wBAAsB,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBvI;AAED,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAQjH"}
@@ -0,0 +1,52 @@
1
+ import { spawn } from "node:child_process";
2
+ import { parseLauncherArgs } from "./args.js";
3
+ export const PI_HARNESS_RESTART_EXIT_CODE = 75;
4
+ function signalExitCode(signal) {
5
+ if (signal === "SIGINT")
6
+ return 130;
7
+ if (signal === "SIGHUP")
8
+ return 129;
9
+ if (signal === "SIGTERM")
10
+ return 143;
11
+ return 1;
12
+ }
13
+ export async function superviseDevelopmentProcess(command, args, options = {}) {
14
+ while (true) {
15
+ const result = await new Promise((resolve, reject) => {
16
+ const child = spawn(command, [...args], options);
17
+ const signals = process.platform === "win32" ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
18
+ const handlers = signals.map((signal) => {
19
+ const handler = () => child.kill(signal);
20
+ process.on(signal, handler);
21
+ return { signal, handler };
22
+ });
23
+ const cleanup = () => {
24
+ for (const { signal, handler } of handlers)
25
+ process.off(signal, handler);
26
+ };
27
+ child.once("error", (error) => {
28
+ cleanup();
29
+ reject(error);
30
+ });
31
+ child.once("exit", (code, signal) => {
32
+ cleanup();
33
+ resolve({ code, signal });
34
+ });
35
+ });
36
+ if (result.code === PI_HARNESS_RESTART_EXIT_CODE)
37
+ continue;
38
+ return result.code ?? signalExitCode(result.signal);
39
+ }
40
+ }
41
+ export function shouldRelaunchForDevelopmentProfile(args, execArgv) {
42
+ if (execArgv.includes("--expose-internals"))
43
+ return false;
44
+ try {
45
+ const invocation = parseLauncherArgs(args);
46
+ return invocation.mode === "run" && invocation.configPath === undefined && invocation.profile === "development" && !invocation.dumpConfig;
47
+ }
48
+ catch {
49
+ return false;
50
+ }
51
+ }
52
+ //# sourceMappingURL=relaunch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relaunch.js","sourceRoot":"","sources":["../src/relaunch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAE/C,SAAS,cAAc,CAAC,MAA6B;IACnD,IAAI,MAAM,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACpC,IAAI,MAAM,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACpC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IACrC,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,OAAe,EAAE,IAAuB,EAAE,UAAwB,EAAE;IACpH,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAyD,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3G,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;YACjD,MAAM,OAAO,GAAqB,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;YACzH,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;gBACtC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACzC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC5B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;YAC7B,CAAC,CAAC,CAAC;YACH,MAAM,OAAO,GAAG,GAAG,EAAE;gBACnB,KAAK,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,QAAQ;oBAAE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC3E,CAAC,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC5B,OAAO,EAAE,CAAC;gBACV,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;gBAClC,OAAO,EAAE,CAAC;gBACV,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAC5B,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,IAAI,KAAK,4BAA4B;YAAE,SAAS;QAC3D,OAAO,MAAM,CAAC,IAAI,IAAI,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mCAAmC,CAAC,IAAuB,EAAE,QAA2B;IACtG,IAAI,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1D,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC3C,OAAO,UAAU,CAAC,IAAI,KAAK,KAAK,IAAI,UAAU,CAAC,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,OAAO,KAAK,aAAa,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;IAC5I,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@pi-harness/cli",
3
+ "version": "0.1.1",
4
+ "description": "Plugin-first Pi Harness CLI",
5
+ "type": "module",
6
+ "bin": {
7
+ "pih": "./dist/bin.js"
8
+ },
9
+ "main": "./dist/main.js",
10
+ "types": "./dist/main.d.ts",
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "engines": {
15
+ "node": ">=22.19.0"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc -p tsconfig.build.json",
19
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
20
+ "typecheck": "tsc -p tsconfig.json"
21
+ },
22
+ "dependencies": {
23
+ "@pi-harness/core": "0.1.1"
24
+ }
25
+ }
@@ -0,0 +1,50 @@
1
+ export class CliUsageError extends Error {
2
+ override readonly name = "CliUsageError";
3
+ }
4
+
5
+ export type LauncherInvocation = { mode: "help" } | { mode: "version" } | { mode: "run"; profile?: string; configPath?: string; dumpConfig: boolean; args: string[] };
6
+
7
+ function optionValue(args: readonly string[], index: number, option: string): string {
8
+ const value = args[index + 1];
9
+ if (value === undefined || value === "--") throw new CliUsageError(`${option} requires a value`);
10
+ return value;
11
+ }
12
+
13
+ export function parseLauncherArgs(args: readonly string[]): LauncherInvocation {
14
+ let profile = "default";
15
+ let profileExplicit = false;
16
+ let configPath: string | undefined;
17
+ let dumpConfig = false;
18
+ const applicationArgs: string[] = [];
19
+ for (let index = 0; index < args.length; index += 1) {
20
+ const arg = args[index];
21
+ if (arg === "--") {
22
+ applicationArgs.push(...args.slice(index + 1));
23
+ break;
24
+ }
25
+ if (arg === "--help" || arg === "-h") return { mode: "help" };
26
+ if (arg === "--version" || arg === "-v") return { mode: "version" };
27
+ if (arg === "--dump-config") {
28
+ dumpConfig = true;
29
+ continue;
30
+ }
31
+ if (arg === "--profile") {
32
+ if (profileExplicit) throw new CliUsageError("--profile may only be specified once");
33
+ profile = optionValue(args, index, "--profile");
34
+ profileExplicit = true;
35
+ index += 1;
36
+ continue;
37
+ }
38
+ if (arg === "--config") {
39
+ if (configPath !== undefined) throw new CliUsageError("--config may only be specified once");
40
+ configPath = optionValue(args, index, "--config");
41
+ index += 1;
42
+ continue;
43
+ }
44
+ applicationArgs.push(arg ?? "");
45
+ }
46
+ if (profileExplicit && configPath !== undefined) throw new CliUsageError("--profile and --config cannot be used together");
47
+ return configPath === undefined
48
+ ? { mode: "run", profile, dumpConfig, args: applicationArgs }
49
+ : { mode: "run", configPath, dumpConfig, args: applicationArgs };
50
+ }
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFileSync } from "node:fs";
4
+ import { homedir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ import { runCli, type CliEnvironment } from "./main.js";
8
+ import { shouldRelaunchForDevelopmentProfile, superviseDevelopmentProcess } from "./relaunch.js";
9
+
10
+ const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")) as { version: string };
11
+
12
+ const environment: CliEnvironment = {
13
+ cwd: process.cwd(),
14
+ agentDir: process.env.PI_AGENT_DIR ?? join(homedir(), ".pi", "agent"),
15
+ version: packageJson.version,
16
+ stdin: process.stdin,
17
+ stdout: process.stdout,
18
+ stderr: process.stderr,
19
+ shutdownTimeoutMs: 5_000,
20
+ forceExit(code) {
21
+ process.exit(code);
22
+ },
23
+ onSignal(listener) {
24
+ const signals: NodeJS.Signals[] = process.platform === "win32" ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
25
+ const handlers = signals.map((signal) => {
26
+ const handler = () => listener(signal);
27
+ process.on(signal, handler);
28
+ return { signal, handler };
29
+ });
30
+ return () => {
31
+ for (const { signal, handler } of handlers) process.off(signal, handler);
32
+ };
33
+ },
34
+ };
35
+
36
+ const args = process.argv.slice(2);
37
+ if (shouldRelaunchForDevelopmentProfile(args, process.execArgv)) {
38
+ process.exitCode = await superviseDevelopmentProcess(process.execPath, ["--expose-internals", ...process.execArgv, fileURLToPath(import.meta.url), ...args], { stdio: "inherit" });
39
+ } else {
40
+ process.exitCode = await runCli(args, environment);
41
+ }
@@ -0,0 +1,155 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import type { Readable, Writable } from "node:stream";
3
+ import { bootHarness, provideLaunchContext, provideStdioContext, resolveProfileConfig, type BootedHarness } from "@pi-harness/core";
4
+ import { CliUsageError, parseLauncherArgs } from "./args.js";
5
+ import { NodeStdio } from "./node-stdio.js";
6
+ import { PI_HARNESS_RESTART_EXIT_CODE } from "./relaunch.js";
7
+
8
+ export interface CliEnvironment {
9
+ readonly cwd: string;
10
+ readonly agentDir: string;
11
+ readonly version: string;
12
+ readonly stdin: Readable;
13
+ readonly stdout: Writable;
14
+ readonly stderr: Writable;
15
+ readonly shutdownTimeoutMs: number;
16
+ forceExit(code: number): void;
17
+ onSignal(listener: (signal: NodeJS.Signals) => void): () => void;
18
+ }
19
+
20
+ type BootOutcome = { kind: "ready"; harness: BootedHarness } | { kind: "error"; error: unknown };
21
+
22
+ async function settleWithin<T>(promise: Promise<T>, timeoutMs: number): Promise<{ settled: true; value: T } | { settled: false }> {
23
+ let timer: NodeJS.Timeout | undefined;
24
+ const timeout = new Promise<{ settled: false }>((resolve) => {
25
+ timer = setTimeout(() => resolve({ settled: false }), timeoutMs);
26
+ });
27
+ const result = await Promise.race([promise.then((value) => ({ settled: true as const, value })), timeout]);
28
+ if (timer !== undefined) clearTimeout(timer);
29
+ return result;
30
+ }
31
+
32
+ function signalExitCode(signal: NodeJS.Signals): number {
33
+ return signal === "SIGINT" ? 130 : signal === "SIGHUP" ? 129 : 143;
34
+ }
35
+
36
+ export async function runCli(_args: readonly string[], _environment: CliEnvironment): Promise<number> {
37
+ const args = _args;
38
+ const environment = _environment;
39
+ let invocation: ReturnType<typeof parseLauncherArgs>;
40
+ try {
41
+ invocation = parseLauncherArgs(args);
42
+ } catch (error) {
43
+ environment.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
44
+ return error instanceof CliUsageError ? 2 : 1;
45
+ }
46
+ if (invocation.mode === "help") {
47
+ environment.stdout.write("Usage: pih [--profile <name> | --config <path>] [--dump-config] [--] [--prompt <text> | <prompt>]\n");
48
+ return 0;
49
+ }
50
+ if (invocation.mode === "version") {
51
+ environment.stdout.write(`${environment.version}\n`);
52
+ return 0;
53
+ }
54
+ let configPath: string;
55
+ try {
56
+ configPath = await resolveProfileConfig({
57
+ ...(invocation.configPath === undefined ? { profile: invocation.profile ?? "default" } : { configPath: invocation.configPath }),
58
+ cwd: environment.cwd,
59
+ });
60
+ if (invocation.dumpConfig) {
61
+ environment.stdout.write(await readFile(configPath, "utf8"));
62
+ return 0;
63
+ }
64
+ } catch (error) {
65
+ environment.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
66
+ return 2;
67
+ }
68
+
69
+ let harness: BootedHarness | undefined;
70
+ let resultCode: number | undefined;
71
+ let forcedExit = false;
72
+ const forceExit = (code: number) => {
73
+ if (forcedExit) return;
74
+ forcedExit = true;
75
+ environment.forceExit(code);
76
+ };
77
+ let requestedExit: ((code: number) => void) | undefined;
78
+ const requestedExitPromise = new Promise<number>((resolve) => {
79
+ requestedExit = resolve;
80
+ });
81
+ let signalledExit: ((code: number) => void) | undefined;
82
+ const signalPromise = new Promise<number>((resolve) => {
83
+ signalledExit = resolve;
84
+ });
85
+ const startupAbort = new AbortController();
86
+ const removeSignals = environment.onSignal((signal) => {
87
+ const code = signalExitCode(signal);
88
+ signalledExit?.(code);
89
+ startupAbort.abort(new Error(`Received ${signal}`));
90
+ });
91
+ try {
92
+ const stdio = new NodeStdio(environment.stdin, environment.stdout, environment.stderr);
93
+ const bootOutcome: Promise<BootOutcome> = bootHarness({
94
+ configPath,
95
+ signal: startupAbort.signal,
96
+ onFullReload() {
97
+ requestedExit?.(PI_HARNESS_RESTART_EXIT_CODE);
98
+ },
99
+ prepare(context) {
100
+ provideLaunchContext(context, {
101
+ cwd: environment.cwd,
102
+ agentDir: environment.agentDir,
103
+ args: invocation.args,
104
+ requestExit(code) {
105
+ requestedExit?.(code);
106
+ },
107
+ });
108
+ provideStdioContext(context, stdio);
109
+ },
110
+ }).then((booted): BootOutcome => ({ kind: "ready", harness: booted }), (error: unknown): BootOutcome => ({ kind: "error", error }));
111
+ const startup = await Promise.race([bootOutcome, signalPromise.then((code) => ({ kind: "signal" as const, code }))]);
112
+ if (startup.kind === "signal") {
113
+ resultCode = startup.code;
114
+ const settled = await settleWithin(bootOutcome, environment.shutdownTimeoutMs);
115
+ if (!settled.settled) {
116
+ forceExit(startup.code);
117
+ return startup.code;
118
+ }
119
+ if (settled.value.kind === "ready") harness = settled.value.harness;
120
+ return startup.code;
121
+ }
122
+ if (startup.kind === "error") throw startup.error;
123
+ harness = startup.harness;
124
+ const application = harness.context.get("piApplication");
125
+ if (application === undefined) throw new Error("Cordis profile did not provide a piApplication service");
126
+ const result = await Promise.race([
127
+ application.run().then((code) => ({ source: "application" as const, code })),
128
+ requestedExitPromise.then((code) => ({ source: "request" as const, code })),
129
+ signalPromise.then((code) => ({ source: "signal" as const, code })),
130
+ ]);
131
+ resultCode = result.code;
132
+ if (result.source !== "application") {
133
+ const runtime = harness.context.get("piRuntime");
134
+ if (runtime !== undefined) {
135
+ const aborted = await settleWithin(runtime.abort().then(() => undefined, (error: unknown) => {
136
+ environment.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
137
+ }), environment.shutdownTimeoutMs);
138
+ if (!aborted.settled) forceExit(result.code);
139
+ }
140
+ }
141
+ return result.code;
142
+ } catch (error) {
143
+ environment.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
144
+ resultCode = 1;
145
+ return 1;
146
+ } finally {
147
+ removeSignals();
148
+ if (harness !== undefined) {
149
+ const disposed = await settleWithin(harness.dispose().then(() => undefined, (error: unknown) => {
150
+ environment.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
151
+ }), environment.shutdownTimeoutMs);
152
+ if (!disposed.settled) forceExit(resultCode ?? 1);
153
+ }
154
+ }
155
+ }