@percher/core 0.2.6 → 0.3.0

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 (206) hide show
  1. package/dist/ai-files-manifest.d.ts +28 -0
  2. package/dist/ai-files-manifest.d.ts.map +1 -0
  3. package/dist/ai-files-manifest.js +96 -0
  4. package/dist/ai-files-manifest.js.map +1 -0
  5. package/dist/commands/account.d.ts +51 -0
  6. package/dist/commands/account.d.ts.map +1 -0
  7. package/dist/commands/account.js +88 -0
  8. package/dist/commands/account.js.map +1 -0
  9. package/dist/commands/ai-files.d.ts +73 -0
  10. package/dist/commands/ai-files.d.ts.map +1 -0
  11. package/dist/commands/ai-files.js +179 -0
  12. package/dist/commands/ai-files.js.map +1 -0
  13. package/dist/commands/billing.d.ts +1 -1
  14. package/dist/commands/billing.d.ts.map +1 -1
  15. package/dist/commands/billing.js +1 -1
  16. package/dist/commands/billing.js.map +1 -1
  17. package/dist/commands/continue.d.ts +48 -0
  18. package/dist/commands/continue.d.ts.map +1 -0
  19. package/dist/commands/continue.js +121 -0
  20. package/dist/commands/continue.js.map +1 -0
  21. package/dist/commands/create.d.ts +1 -1
  22. package/dist/commands/create.d.ts.map +1 -1
  23. package/dist/commands/create.js +1 -1
  24. package/dist/commands/create.js.map +1 -1
  25. package/dist/commands/dashboard.d.ts +15 -0
  26. package/dist/commands/dashboard.d.ts.map +1 -0
  27. package/dist/commands/dashboard.js +33 -0
  28. package/dist/commands/dashboard.js.map +1 -0
  29. package/dist/commands/data-export.d.ts +21 -0
  30. package/dist/commands/data-export.d.ts.map +1 -0
  31. package/dist/commands/data-export.js +36 -0
  32. package/dist/commands/data-export.js.map +1 -0
  33. package/dist/commands/data.d.ts +1 -1
  34. package/dist/commands/data.d.ts.map +1 -1
  35. package/dist/commands/data.js +1 -1
  36. package/dist/commands/data.js.map +1 -1
  37. package/dist/commands/delete.d.ts +1 -1
  38. package/dist/commands/delete.d.ts.map +1 -1
  39. package/dist/commands/delete.js +1 -1
  40. package/dist/commands/delete.js.map +1 -1
  41. package/dist/commands/deploys.d.ts +2 -2
  42. package/dist/commands/deploys.d.ts.map +1 -1
  43. package/dist/commands/deploys.js +21 -5
  44. package/dist/commands/deploys.js.map +1 -1
  45. package/dist/commands/dev.d.ts +1 -9
  46. package/dist/commands/dev.d.ts.map +1 -1
  47. package/dist/commands/dev.js +77 -23
  48. package/dist/commands/dev.js.map +1 -1
  49. package/dist/commands/diagnose.d.ts +1 -1
  50. package/dist/commands/diagnose.d.ts.map +1 -1
  51. package/dist/commands/diagnose.js +1 -1
  52. package/dist/commands/diagnose.js.map +1 -1
  53. package/dist/commands/doctor.d.ts +63 -1
  54. package/dist/commands/doctor.d.ts.map +1 -1
  55. package/dist/commands/doctor.js +792 -10
  56. package/dist/commands/doctor.js.map +1 -1
  57. package/dist/commands/domains.d.ts +1 -1
  58. package/dist/commands/domains.d.ts.map +1 -1
  59. package/dist/commands/domains.js +1 -1
  60. package/dist/commands/domains.js.map +1 -1
  61. package/dist/commands/env-scan.d.ts +2 -0
  62. package/dist/commands/env-scan.d.ts.map +1 -0
  63. package/dist/commands/env-scan.js +92 -0
  64. package/dist/commands/env-scan.js.map +1 -0
  65. package/dist/commands/env.d.ts +1 -1
  66. package/dist/commands/env.d.ts.map +1 -1
  67. package/dist/commands/env.js +1 -1
  68. package/dist/commands/env.js.map +1 -1
  69. package/dist/commands/export.d.ts +1 -1
  70. package/dist/commands/export.js +1 -1
  71. package/dist/commands/generate.d.ts +1 -1
  72. package/dist/commands/generate.d.ts.map +1 -1
  73. package/dist/commands/generate.js +14 -9
  74. package/dist/commands/generate.js.map +1 -1
  75. package/dist/commands/github.d.ts +60 -0
  76. package/dist/commands/github.d.ts.map +1 -0
  77. package/dist/commands/github.js +112 -0
  78. package/dist/commands/github.js.map +1 -0
  79. package/dist/commands/import-project.d.ts +1 -1
  80. package/dist/commands/import-project.d.ts.map +1 -1
  81. package/dist/commands/import-project.js +1 -1
  82. package/dist/commands/import-project.js.map +1 -1
  83. package/dist/commands/init.d.ts +1 -1
  84. package/dist/commands/init.d.ts.map +1 -1
  85. package/dist/commands/init.js +1 -1
  86. package/dist/commands/init.js.map +1 -1
  87. package/dist/commands/insights.d.ts +1 -1
  88. package/dist/commands/insights.d.ts.map +1 -1
  89. package/dist/commands/insights.js +1 -1
  90. package/dist/commands/insights.js.map +1 -1
  91. package/dist/commands/login.d.ts +1 -1
  92. package/dist/commands/login.d.ts.map +1 -1
  93. package/dist/commands/login.js +1 -1
  94. package/dist/commands/login.js.map +1 -1
  95. package/dist/commands/logs.d.ts +1 -1
  96. package/dist/commands/logs.d.ts.map +1 -1
  97. package/dist/commands/logs.js +1 -1
  98. package/dist/commands/logs.js.map +1 -1
  99. package/dist/commands/mcp.d.ts +1 -1
  100. package/dist/commands/mcp.d.ts.map +1 -1
  101. package/dist/commands/mcp.js +1 -1
  102. package/dist/commands/mcp.js.map +1 -1
  103. package/dist/commands/open.d.ts +1 -1
  104. package/dist/commands/open.d.ts.map +1 -1
  105. package/dist/commands/open.js +1 -1
  106. package/dist/commands/open.js.map +1 -1
  107. package/dist/commands/publish-failure.d.ts +31 -0
  108. package/dist/commands/publish-failure.d.ts.map +1 -0
  109. package/dist/commands/publish-failure.js +142 -0
  110. package/dist/commands/publish-failure.js.map +1 -0
  111. package/dist/commands/publish-node.d.ts +13 -0
  112. package/dist/commands/publish-node.d.ts.map +1 -0
  113. package/dist/commands/publish-node.js +38 -0
  114. package/dist/commands/publish-node.js.map +1 -0
  115. package/dist/commands/publish.d.ts +87 -3
  116. package/dist/commands/publish.d.ts.map +1 -1
  117. package/dist/commands/publish.js +589 -156
  118. package/dist/commands/publish.js.map +1 -1
  119. package/dist/commands/push.d.ts +45 -8
  120. package/dist/commands/push.d.ts.map +1 -1
  121. package/dist/commands/push.js +215 -22
  122. package/dist/commands/push.js.map +1 -1
  123. package/dist/commands/redeploy.d.ts +28 -0
  124. package/dist/commands/redeploy.d.ts.map +1 -0
  125. package/dist/commands/redeploy.js +417 -0
  126. package/dist/commands/redeploy.js.map +1 -0
  127. package/dist/commands/rename.d.ts +1 -1
  128. package/dist/commands/rename.d.ts.map +1 -1
  129. package/dist/commands/rename.js +1 -1
  130. package/dist/commands/rename.js.map +1 -1
  131. package/dist/commands/reproduce.d.ts +64 -0
  132. package/dist/commands/reproduce.d.ts.map +1 -0
  133. package/dist/commands/reproduce.js +211 -0
  134. package/dist/commands/reproduce.js.map +1 -0
  135. package/dist/commands/reset-superuser.d.ts +1 -1
  136. package/dist/commands/reset-superuser.d.ts.map +1 -1
  137. package/dist/commands/reset-superuser.js +1 -1
  138. package/dist/commands/reset-superuser.js.map +1 -1
  139. package/dist/commands/restore.d.ts +79 -0
  140. package/dist/commands/restore.d.ts.map +1 -0
  141. package/dist/commands/restore.js +164 -0
  142. package/dist/commands/restore.js.map +1 -0
  143. package/dist/commands/resume.d.ts +1 -1
  144. package/dist/commands/resume.d.ts.map +1 -1
  145. package/dist/commands/resume.js +1 -1
  146. package/dist/commands/resume.js.map +1 -1
  147. package/dist/commands/rollback.d.ts +20 -8
  148. package/dist/commands/rollback.d.ts.map +1 -1
  149. package/dist/commands/rollback.js +11 -6
  150. package/dist/commands/rollback.js.map +1 -1
  151. package/dist/commands/unsuspend.d.ts +35 -0
  152. package/dist/commands/unsuspend.d.ts.map +1 -0
  153. package/dist/commands/unsuspend.js +27 -0
  154. package/dist/commands/unsuspend.js.map +1 -0
  155. package/dist/commands/versions.d.ts +1 -1
  156. package/dist/commands/versions.d.ts.map +1 -1
  157. package/dist/commands/versions.js +1 -1
  158. package/dist/commands/versions.js.map +1 -1
  159. package/dist/commands/wait-deploy.d.ts +92 -0
  160. package/dist/commands/wait-deploy.d.ts.map +1 -0
  161. package/dist/commands/wait-deploy.js +225 -0
  162. package/dist/commands/wait-deploy.js.map +1 -0
  163. package/dist/env-scan-source.d.ts +39 -0
  164. package/dist/env-scan-source.d.ts.map +1 -0
  165. package/dist/env-scan-source.js +332 -0
  166. package/dist/env-scan-source.js.map +1 -0
  167. package/dist/error-classifier.d.ts.map +1 -1
  168. package/dist/error-classifier.js +67 -4
  169. package/dist/error-classifier.js.map +1 -1
  170. package/dist/errors.d.ts +8 -1
  171. package/dist/errors.d.ts.map +1 -1
  172. package/dist/errors.js +2 -0
  173. package/dist/errors.js.map +1 -1
  174. package/dist/index.d.ts +14 -1
  175. package/dist/index.d.ts.map +1 -1
  176. package/dist/index.js +13 -0
  177. package/dist/index.js.map +1 -1
  178. package/dist/plans.d.ts +11 -0
  179. package/dist/plans.d.ts.map +1 -1
  180. package/dist/plans.js +10 -0
  181. package/dist/plans.js.map +1 -1
  182. package/dist/poll-deployment.d.ts +47 -0
  183. package/dist/poll-deployment.d.ts.map +1 -0
  184. package/dist/poll-deployment.js +57 -0
  185. package/dist/poll-deployment.js.map +1 -0
  186. package/dist/recovery.d.ts +356 -0
  187. package/dist/recovery.d.ts.map +1 -0
  188. package/dist/recovery.js +299 -0
  189. package/dist/recovery.js.map +1 -0
  190. package/dist/stream-utils.d.ts +21 -0
  191. package/dist/stream-utils.d.ts.map +1 -0
  192. package/dist/stream-utils.js +41 -0
  193. package/dist/stream-utils.js.map +1 -0
  194. package/dist/templates/ai-files/claude-md.d.ts +7 -0
  195. package/dist/templates/ai-files/claude-md.d.ts.map +1 -0
  196. package/dist/templates/ai-files/claude-md.js +78 -0
  197. package/dist/templates/ai-files/claude-md.js.map +1 -0
  198. package/dist/templates/ai-files/cursor-percher-mdc.d.ts +7 -0
  199. package/dist/templates/ai-files/cursor-percher-mdc.d.ts.map +1 -0
  200. package/dist/templates/ai-files/cursor-percher-mdc.js +111 -0
  201. package/dist/templates/ai-files/cursor-percher-mdc.js.map +1 -0
  202. package/dist/templates/ai-files/index.d.ts +8 -0
  203. package/dist/templates/ai-files/index.d.ts.map +1 -0
  204. package/dist/templates/ai-files/index.js +4 -0
  205. package/dist/templates/ai-files/index.js.map +1 -0
  206. package/package.json +5 -5
@@ -0,0 +1,35 @@
1
+ import { z } from "zod/v3";
2
+ import type { Context } from "../context";
3
+ export declare const unsuspendInputSchema: z.ZodObject<{
4
+ app: z.ZodString;
5
+ }, "strip", z.ZodTypeAny, {
6
+ app: string;
7
+ }, {
8
+ app: string;
9
+ }>;
10
+ export type UnsuspendInput = z.infer<typeof unsuspendInputSchema>;
11
+ export interface UnsuspendResult {
12
+ ok: true;
13
+ app: {
14
+ id: string;
15
+ name: string;
16
+ status: string;
17
+ };
18
+ /** True if this call flipped the app from suspended to active.
19
+ * False if the app was already active (idempotent). */
20
+ flipped: boolean;
21
+ summary: string;
22
+ }
23
+ /**
24
+ * Unsuspend an app. Used from CLI ("Lock removed") and from the
25
+ * agent surface (`percher_unsuspend` MCP tool) when an auto-suspend
26
+ * is the recovery action the agent should take after the user has
27
+ * fixed the underlying failure.
28
+ *
29
+ * Server-side this triggers the cooldown threshold in
30
+ * FailureLoopGuard: if the app fails N=3 more times within an hour,
31
+ * it auto-suspends again (faster than the standard N=8) — discourages
32
+ * the "unsuspend → resume the loop → re-burn the budget" antipattern.
33
+ */
34
+ export declare function unsuspend(ctx: Context, input: UnsuspendInput): Promise<UnsuspendResult>;
35
+ //# sourceMappingURL=unsuspend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unsuspend.d.ts","sourceRoot":"","sources":["../../src/commands/unsuspend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,eAAO,MAAM,oBAAoB;;;;;;EAE/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,IAAI,CAAC;IACT,GAAG,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD;4DACwD;IACxD,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAU7F"}
@@ -0,0 +1,27 @@
1
+ import { z } from "zod/v3";
2
+ export const unsuspendInputSchema = z.object({
3
+ app: z.string().min(1).describe("App name or id to unsuspend"),
4
+ });
5
+ /**
6
+ * Unsuspend an app. Used from CLI ("Lock removed") and from the
7
+ * agent surface (`percher_unsuspend` MCP tool) when an auto-suspend
8
+ * is the recovery action the agent should take after the user has
9
+ * fixed the underlying failure.
10
+ *
11
+ * Server-side this triggers the cooldown threshold in
12
+ * FailureLoopGuard: if the app fails N=3 more times within an hour,
13
+ * it auto-suspends again (faster than the standard N=8) — discourages
14
+ * the "unsuspend → resume the loop → re-burn the budget" antipattern.
15
+ */
16
+ export async function unsuspend(ctx, input) {
17
+ const result = await ctx.client.apps.unsuspend(input.app);
18
+ return {
19
+ ok: true,
20
+ app: result.app,
21
+ flipped: result.flipped,
22
+ summary: result.flipped
23
+ ? `Unsuspended ${result.app.name}. If it fails 3 more times in the next hour, the cooldown threshold will auto-suspend it again — fix the cause before retrying.`
24
+ : `${result.app.name} was already active (no change).`,
25
+ };
26
+ }
27
+ //# sourceMappingURL=unsuspend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unsuspend.js","sourceRoot":"","sources":["../../src/commands/unsuspend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAG3B,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,6BAA6B,CAAC;CAC/D,CAAC,CAAC;AAYH;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAY,EAAE,KAAqB;IACjE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1D,OAAO;QACL,EAAE,EAAE,IAAI;QACR,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,OAAO,EAAE,MAAM,CAAC,OAAO;YACrB,CAAC,CAAC,eAAe,MAAM,CAAC,GAAG,CAAC,IAAI,iIAAiI;YACjK,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,kCAAkC;KACzD,CAAC;AACJ,CAAC"}
@@ -1,4 +1,4 @@
1
- import { z } from "zod";
1
+ import { z } from "zod/v3";
2
2
  import type { Context } from "../context";
3
3
  export declare const versionsInputSchema: z.ZodObject<{
4
4
  app: z.ZodOptional<z.ZodString>;
@@ -1 +1 @@
1
- {"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../../src/commands/versions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,eAAO,MAAM,mBAAmB;;;;;;EAA2C,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,aAAkB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAS7F"}
1
+ {"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../../src/commands/versions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,eAAO,MAAM,mBAAmB;;;;;;EAA2C,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,aAAkB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAS7F"}
@@ -1,4 +1,4 @@
1
- import { z } from "zod";
1
+ import { z } from "zod/v3";
2
2
  import { readPercherTomlAppName } from "../app-name";
3
3
  import { PercherCoreError } from "../errors";
4
4
  export const versionsInputSchema = z.object({ app: z.string().optional() });
@@ -1 +1 @@
1
- {"version":3,"file":"versions.js","sourceRoot":"","sources":["../../src/commands/versions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAS5E,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAY,EAAE,QAAuB,EAAE;IACpE,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,IAAI,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,gBAAgB,CAAC,4CAA4C,EAAE;YACvE,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,6DAA6D;SACpE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"versions.js","sourceRoot":"","sources":["../../src/commands/versions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAS5E,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAY,EAAE,QAAuB,EAAE;IACpE,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,IAAI,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,gBAAgB,CAAC,4CAA4C,EAAE;YACvE,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,6DAA6D;SACpE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,92 @@
1
+ import type { App, Deployment } from "@percher/client";
2
+ import { z } from "zod/v3";
3
+ import type { Context } from "../context";
4
+ import { type PublishRecovery } from "../recovery";
5
+ import type { PublishError } from "./publish";
6
+ export declare const waitForDeployInputSchema: z.ZodObject<{
7
+ app: z.ZodString;
8
+ deployId: z.ZodString;
9
+ timeoutSeconds: z.ZodOptional<z.ZodNumber>;
10
+ pollIntervalSeconds: z.ZodOptional<z.ZodNumber>;
11
+ }, "strip", z.ZodTypeAny, {
12
+ app: string;
13
+ deployId: string;
14
+ timeoutSeconds?: number | undefined;
15
+ pollIntervalSeconds?: number | undefined;
16
+ }, {
17
+ app: string;
18
+ deployId: string;
19
+ timeoutSeconds?: number | undefined;
20
+ pollIntervalSeconds?: number | undefined;
21
+ }>;
22
+ export type WaitForDeployInput = z.infer<typeof waitForDeployInputSchema>;
23
+ export interface WaitForDeployResult {
24
+ /**
25
+ * - `live` — deployment reached terminal success.
26
+ * - `failed` — deployment reached terminal failure (`error` populated).
27
+ * - `replaced` — deployment was superseded. Resolver looks at the
28
+ * latest deploy on the app and routes accordingly:
29
+ * • newer live exists → `nextAction: "none"`, `url` is the
30
+ * current live URL, `summary` includes the resolved deployId.
31
+ * • newer deploy still in flight → `nextAction: "wait_deploy"`
32
+ * pointing at the newer deployId.
33
+ * • no newer / latest also failed → `nextAction: "ask_user"`.
34
+ * Never `retry` — replaced isn't a transient failure of this row.
35
+ * - `still_running` — timeout hit before terminal status; agent should
36
+ * call this tool again with the same deployId.
37
+ */
38
+ status: "live" | "failed" | "replaced" | "still_running";
39
+ app: {
40
+ id: string;
41
+ name: string;
42
+ url: string;
43
+ };
44
+ deployment: Deployment;
45
+ /** Live or preview URL on success. */
46
+ url?: string;
47
+ /** Wall-clock seconds spent in this single wait call. */
48
+ elapsedSeconds: number;
49
+ /**
50
+ * Total seconds since the deployment was first created (server-side
51
+ * `createdAt`). Helps the agent answer "is this stuck?" — combined
52
+ * with status, an `elapsedSeconds`-since-create > 600 in `building`
53
+ * is a strong signal of a real stall, not just a slow build.
54
+ */
55
+ totalElapsedSeconds: number;
56
+ error?: PublishError;
57
+ recovery: PublishRecovery;
58
+ summary: string;
59
+ }
60
+ /**
61
+ * FUTURE11 Phase 2 — short-poll a specific deploy without starting a new
62
+ * one. Returns terminal results when the deploy reaches live/failed
63
+ * within the timeout, otherwise returns `still_running` with a
64
+ * `wait_deploy` recovery so the agent loops without growing the call
65
+ * stack. Never starts a new deploy.
66
+ */
67
+ export declare function waitForDeploy(ctx: Context, input: WaitForDeployInput): Promise<WaitForDeployResult>;
68
+ /**
69
+ * FUTURE11 review round 5 — resolve what `replaced` actually means by
70
+ * looking at the latest deploy. Two API code-paths produce `replaced`:
71
+ *
72
+ * 1. `markPreviousLiveAsReplaced` — a NEWER live deploy succeeded
73
+ * and pushed this row aside. App is live; route to nextAction='none'.
74
+ * 2. `markLiveDeployReplaced` — reconcile saw the container is gone
75
+ * (CONTAINER_NOT_FOUND). No newer live exists; app is effectively
76
+ * down. Route to ask_user.
77
+ *
78
+ * Resolver also handles the in-flight case where the newer deploy is
79
+ * still building — point at it via wait_deploy. Matches FUTURE12 Phase
80
+ * 4's locked behavior for `replaced_by_newer`.
81
+ */
82
+ export declare function resolveReplaced(opts: {
83
+ ctx: Context;
84
+ app: App;
85
+ replacedDeployment: Deployment;
86
+ }): Promise<{
87
+ recovery: PublishRecovery;
88
+ url?: string;
89
+ summary: string;
90
+ resolvedDeployment?: Deployment;
91
+ }>;
92
+ //# sourceMappingURL=wait-deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait-deploy.d.ts","sourceRoot":"","sources":["../../src/commands/wait-deploy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,KAAK,eAAe,EAKrB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;EAmBnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;;OAaG;IACH,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,eAAe,CAAC;IACzD,GAAG,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,UAAU,EAAE,UAAU,CAAC;IACvB,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,eAAe,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAoE9B;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,GAAG,CAAC;IACT,kBAAkB,EAAE,UAAU,CAAC;CAChC,GAAG,OAAO,CAAC;IACV,QAAQ,EAAE,eAAe,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,UAAU,CAAC;CACjC,CAAC,CA4ED"}
@@ -0,0 +1,225 @@
1
+ import { z } from "zod/v3";
2
+ import { RECOVERY_NONE, recoveryAsk, recoveryNone, recoveryWait, } from "../recovery";
3
+ import { classifyDeploymentFailure } from "./publish-failure";
4
+ export const waitForDeployInputSchema = z.object({
5
+ app: z.string().describe("App name (the value of [app].name in percher.toml)"),
6
+ deployId: z.string().describe("Deploy id returned by percher_publish (e.g. dep_abc123)"),
7
+ timeoutSeconds: z
8
+ .number()
9
+ .int()
10
+ .min(1)
11
+ .max(120)
12
+ .optional()
13
+ .describe("Maximum wall-clock seconds to wait before returning still_running (default 30, max 120). Keeping this short is the point — the agent can resume in another short call without holding a long-lived connection."),
14
+ pollIntervalSeconds: z
15
+ .number()
16
+ .int()
17
+ .min(1)
18
+ .max(30)
19
+ .optional()
20
+ .describe("Seconds between polls (default 2)."),
21
+ });
22
+ /**
23
+ * FUTURE11 Phase 2 — short-poll a specific deploy without starting a new
24
+ * one. Returns terminal results when the deploy reaches live/failed
25
+ * within the timeout, otherwise returns `still_running` with a
26
+ * `wait_deploy` recovery so the agent loops without growing the call
27
+ * stack. Never starts a new deploy.
28
+ */
29
+ export async function waitForDeploy(ctx, input) {
30
+ const timeoutSeconds = input.timeoutSeconds ?? 30;
31
+ const pollIntervalSeconds = input.pollIntervalSeconds ?? 2;
32
+ // Fetch app + initial deployment in parallel; the app row is needed for
33
+ // the URL on success and for failure-classification context.
34
+ const [app, initial] = await Promise.all([
35
+ ctx.client.apps.get(input.app),
36
+ ctx.client.apps.getDeployment(input.app, input.deployId),
37
+ ]);
38
+ const startedAt = Date.now();
39
+ const deadlineMs = startedAt + timeoutSeconds * 1000;
40
+ let deployment = initial;
41
+ while (!isTerminal(deployment.status)) {
42
+ if (Date.now() >= deadlineMs) {
43
+ return buildStillRunningResult(app, deployment, startedAt);
44
+ }
45
+ await new Promise((r) => setTimeout(r, pollIntervalSeconds * 1000));
46
+ try {
47
+ deployment = await ctx.client.apps.getDeployment(input.app, input.deployId);
48
+ }
49
+ catch (err) {
50
+ // Transient fetch errors during a short wait don't justify
51
+ // throwing — return still_running so the agent retries. The
52
+ // deploy may already be live server-side; the agent's next call
53
+ // will pick that up.
54
+ const msg = err.message ?? String(err);
55
+ if (msg.startsWith("network error:")) {
56
+ return buildStillRunningResult(app, deployment, startedAt, msg);
57
+ }
58
+ throw err;
59
+ }
60
+ }
61
+ if (deployment.status === "failed") {
62
+ const { error, recovery, summary } = await classifyDeploymentFailure({
63
+ ctx,
64
+ app,
65
+ deployment,
66
+ });
67
+ return {
68
+ status: "failed",
69
+ app: { id: app.id, name: app.name, url: app.url },
70
+ deployment,
71
+ elapsedSeconds: Math.round((Date.now() - startedAt) / 1000),
72
+ totalElapsedSeconds: secondsSinceCreated(deployment),
73
+ error,
74
+ recovery,
75
+ summary,
76
+ };
77
+ }
78
+ if (deployment.status === "replaced") {
79
+ return await buildReplacedResult({ ctx, app, deployment, startedAt });
80
+ }
81
+ const url = deployment.previewUrl ?? deployment.url ?? app.url;
82
+ return {
83
+ status: "live",
84
+ app: { id: app.id, name: app.name, url: app.url },
85
+ deployment,
86
+ url,
87
+ elapsedSeconds: Math.round((Date.now() - startedAt) / 1000),
88
+ totalElapsedSeconds: secondsSinceCreated(deployment),
89
+ recovery: RECOVERY_NONE,
90
+ summary: `${app.name} deploy ${deployment.id} is live → ${url}`,
91
+ };
92
+ }
93
+ function isTerminal(status) {
94
+ return status === "live" || status === "failed" || status === "replaced";
95
+ }
96
+ /**
97
+ * FUTURE11 review round 5 — resolve what `replaced` actually means by
98
+ * looking at the latest deploy. Two API code-paths produce `replaced`:
99
+ *
100
+ * 1. `markPreviousLiveAsReplaced` — a NEWER live deploy succeeded
101
+ * and pushed this row aside. App is live; route to nextAction='none'.
102
+ * 2. `markLiveDeployReplaced` — reconcile saw the container is gone
103
+ * (CONTAINER_NOT_FOUND). No newer live exists; app is effectively
104
+ * down. Route to ask_user.
105
+ *
106
+ * Resolver also handles the in-flight case where the newer deploy is
107
+ * still building — point at it via wait_deploy. Matches FUTURE12 Phase
108
+ * 4's locked behavior for `replaced_by_newer`.
109
+ */
110
+ export async function resolveReplaced(opts) {
111
+ const { ctx, app, replacedDeployment } = opts;
112
+ // Filter the lookup to the same deploy kind. A `replaced` row is
113
+ // always a live deploy in the API (both markPreviousLiveAsReplaced
114
+ // and markLiveDeployReplaced enforce eq(deployments.type, "live")),
115
+ // so without `type` filtering a newer preview deploy could hijack
116
+ // recovery — the resolver might wait on the preview, surface a
117
+ // preview URL as if it were the canonical live, or fall back to
118
+ // ask_user when previews push the real successor past the limit.
119
+ // Default to "live" when the row's type is missing for any reason.
120
+ const deployType = replacedDeployment.type ?? "live";
121
+ let latest;
122
+ try {
123
+ const deploys = await ctx.client.apps.listDeploys(app.name, {
124
+ limit: 5,
125
+ type: deployType,
126
+ });
127
+ // Skip the row we already know is replaced; pick the most recent
128
+ // deploy that's not this one. The list is ordered desc by createdAt.
129
+ latest = deploys.find((d) => d.id !== replacedDeployment.id);
130
+ }
131
+ catch {
132
+ return {
133
+ recovery: recoveryAsk({
134
+ prompt: `${app.name} deploy ${replacedDeployment.id} was replaced, but listing recent deploys failed. Check the dashboard or run \`percher doctor --app ${app.name}\` to inspect current state.`,
135
+ reasonCode: "replaced_by_newer",
136
+ }),
137
+ summary: `${app.name} deploy ${replacedDeployment.id} was replaced, but listing recent deploys failed. Surface to user — they can check the dashboard.`,
138
+ };
139
+ }
140
+ if (!latest) {
141
+ return {
142
+ recovery: recoveryAsk({
143
+ prompt: `${app.name} deploy ${replacedDeployment.id} was replaced and there are no other deploys to resolve to. Surface this to the user — they may need to redeploy.`,
144
+ reasonCode: "replaced_by_newer",
145
+ }),
146
+ summary: `${app.name} deploy ${replacedDeployment.id} was replaced and there are no other deploys to resolve to. Surface to user.`,
147
+ };
148
+ }
149
+ if (latest.status === "live") {
150
+ const url = latest.previewUrl ?? latest.url ?? app.url;
151
+ return {
152
+ recovery: recoveryNone({ reasonCode: "replaced_by_newer", url }),
153
+ url,
154
+ resolvedDeployment: latest,
155
+ summary: `${app.name} deploy ${replacedDeployment.id} was replaced — the app is live at ${url} via deploy ${latest.id}.`,
156
+ };
157
+ }
158
+ if (latest.status === "queued" || latest.status === "building" || latest.status === "deploying") {
159
+ const reasonCode = latest.status === "queued"
160
+ ? "deploy_queued"
161
+ : latest.status === "building"
162
+ ? "deploy_building"
163
+ : "deploy_deploying";
164
+ return {
165
+ recovery: recoveryWait({ app: app.name, deployId: latest.id, reasonCode }),
166
+ resolvedDeployment: latest,
167
+ summary: `${app.name} deploy ${replacedDeployment.id} was replaced; the newer deploy ${latest.id} is ${latest.status} — call percher_wait_for_deploy.`,
168
+ };
169
+ }
170
+ // latest is failed or another replaced — there's no clear current
171
+ // live state. Surface to user; FUTURE12's expanded doctor will own
172
+ // deeper diagnostics.
173
+ return {
174
+ recovery: recoveryAsk({
175
+ prompt: `${app.name} deploy ${replacedDeployment.id} was replaced, and the latest deploy ${latest.id} is also ${latest.status}. Run \`percher doctor --app ${app.name}\` to diagnose, or surface this to the user.`,
176
+ reasonCode: "replaced_by_newer",
177
+ }),
178
+ resolvedDeployment: latest,
179
+ summary: `${app.name} deploy ${replacedDeployment.id} was replaced; the latest deploy ${latest.id} is ${latest.status}. Surface to user.`,
180
+ };
181
+ }
182
+ async function buildReplacedResult(opts) {
183
+ const { ctx, app, deployment, startedAt } = opts;
184
+ const resolved = await resolveReplaced({ ctx, app, replacedDeployment: deployment });
185
+ return {
186
+ status: "replaced",
187
+ app: { id: app.id, name: app.name, url: app.url },
188
+ deployment,
189
+ url: resolved.url,
190
+ elapsedSeconds: Math.round((Date.now() - startedAt) / 1000),
191
+ totalElapsedSeconds: secondsSinceCreated(deployment),
192
+ recovery: resolved.recovery,
193
+ summary: resolved.summary,
194
+ };
195
+ }
196
+ function buildStillRunningResult(app, deployment, startedAt, networkHint) {
197
+ return {
198
+ status: "still_running",
199
+ app: { id: app.id, name: app.name, url: app.url },
200
+ deployment,
201
+ elapsedSeconds: Math.round((Date.now() - startedAt) / 1000),
202
+ totalElapsedSeconds: secondsSinceCreated(deployment),
203
+ recovery: recoveryWait({
204
+ app: app.name,
205
+ deployId: deployment.id,
206
+ reasonCode: deployment.status === "queued"
207
+ ? "deploy_queued"
208
+ : deployment.status === "building"
209
+ ? "deploy_building"
210
+ : deployment.status === "deploying"
211
+ ? "deploy_deploying"
212
+ : "deploy_timeout",
213
+ }),
214
+ summary: networkHint
215
+ ? `${app.name} deploy ${deployment.id} still ${deployment.status} (transient: ${networkHint}) — call percher_wait_for_deploy again.`
216
+ : `${app.name} deploy ${deployment.id} still ${deployment.status} — call percher_wait_for_deploy again.`,
217
+ };
218
+ }
219
+ function secondsSinceCreated(deployment) {
220
+ const t = Date.parse(deployment.createdAt);
221
+ if (Number.isNaN(t))
222
+ return 0;
223
+ return Math.max(0, Math.round((Date.now() - t) / 1000));
224
+ }
225
+ //# sourceMappingURL=wait-deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait-deploy.js","sourceRoot":"","sources":["../../src/commands/wait-deploy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,OAAO,EAEL,aAAa,EACb,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oDAAoD,CAAC;IAC9E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yDAAyD,CAAC;IACxF,cAAc,EAAE,CAAC;SACd,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,gNAAgN,CACjN;IACH,mBAAmB,EAAE,CAAC;SACnB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,QAAQ,EAAE;SACV,QAAQ,CAAC,oCAAoC,CAAC;CAClD,CAAC,CAAC;AAqCH;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAY,EACZ,KAAyB;IAEzB,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC;IAClD,MAAM,mBAAmB,GAAG,KAAK,CAAC,mBAAmB,IAAI,CAAC,CAAC;IAE3D,wEAAwE;IACxE,6DAA6D;IAC7D,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACvC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;QAC9B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC;KACzD,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAG,SAAS,GAAG,cAAc,GAAG,IAAI,CAAC;IACrD,IAAI,UAAU,GAAG,OAAO,CAAC;IAEzB,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,UAAU,EAAE,CAAC;YAC7B,OAAO,uBAAuB,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC,CAAC,CAAC;QACpE,IAAI,CAAC;YACH,UAAU,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC9E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,2DAA2D;YAC3D,4DAA4D;YAC5D,gEAAgE;YAChE,qBAAqB;YACrB,MAAM,GAAG,GAAI,GAAa,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;YAClD,IAAI,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACrC,OAAO,uBAAuB,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;YAClE,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,yBAAyB,CAAC;YACnE,GAAG;YACH,GAAG;YACH,UAAU;SACX,CAAC,CAAC;QACH,OAAO;YACL,MAAM,EAAE,QAAQ;YAChB,GAAG,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE;YACjD,UAAU;YACV,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;YAC3D,mBAAmB,EAAE,mBAAmB,CAAC,UAAU,CAAC;YACpD,KAAK;YACL,QAAQ;YACR,OAAO;SACR,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACrC,OAAO,MAAM,mBAAmB,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,CAAC,UAAU,IAAI,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC;IAC/D,OAAO;QACL,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE;QACjD,UAAU;QACV,GAAG;QACH,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;QAC3D,mBAAmB,EAAE,mBAAmB,CAAC,UAAU,CAAC;QACpD,QAAQ,EAAE,aAAa;QACvB,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,WAAW,UAAU,CAAC,EAAE,cAAc,GAAG,EAAE;KAChE,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,MAA4B;IAC9C,OAAO,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,UAAU,CAAC;AAC3E,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAIrC;IAMC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAC;IAE9C,iEAAiE;IACjE,mEAAmE;IACnE,oEAAoE;IACpE,kEAAkE;IAClE,+DAA+D;IAC/D,gEAAgE;IAChE,iEAAiE;IACjE,mEAAmE;IACnE,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,IAAI,MAAM,CAAC;IACrD,IAAI,MAA8B,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE;YAC1D,KAAK,EAAE,CAAC;YACR,IAAI,EAAE,UAAU;SACjB,CAAC,CAAC;QACH,iEAAiE;QACjE,qEAAqE;QACrE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,kBAAkB,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,QAAQ,EAAE,WAAW,CAAC;gBACpB,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,WAAW,kBAAkB,CAAC,EAAE,uGAAuG,GAAG,CAAC,IAAI,8BAA8B;gBAChM,UAAU,EAAE,mBAAmB;aAChC,CAAC;YACF,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,WAAW,kBAAkB,CAAC,EAAE,mGAAmG;SACxJ,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,QAAQ,EAAE,WAAW,CAAC;gBACpB,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,WAAW,kBAAkB,CAAC,EAAE,mHAAmH;gBACtK,UAAU,EAAE,mBAAmB;aAChC,CAAC;YACF,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,WAAW,kBAAkB,CAAC,EAAE,8EAA8E;SACnI,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC;QACvD,OAAO;YACL,QAAQ,EAAE,YAAY,CAAC,EAAE,UAAU,EAAE,mBAAmB,EAAE,GAAG,EAAE,CAAC;YAChE,GAAG;YACH,kBAAkB,EAAE,MAAM;YAC1B,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,WAAW,kBAAkB,CAAC,EAAE,sCAAsC,GAAG,eAAe,MAAM,CAAC,EAAE,GAAG;SACzH,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAChG,MAAM,UAAU,GACd,MAAM,CAAC,MAAM,KAAK,QAAQ;YACxB,CAAC,CAAC,eAAe;YACjB,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU;gBAC5B,CAAC,CAAC,iBAAiB;gBACnB,CAAC,CAAC,kBAAkB,CAAC;QAC3B,OAAO;YACL,QAAQ,EAAE,YAAY,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,UAAU,EAAE,CAAC;YAC1E,kBAAkB,EAAE,MAAM;YAC1B,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,WAAW,kBAAkB,CAAC,EAAE,mCAAmC,MAAM,CAAC,EAAE,OAAO,MAAM,CAAC,MAAM,kCAAkC;SACvJ,CAAC;IACJ,CAAC;IAED,kEAAkE;IAClE,mEAAmE;IACnE,sBAAsB;IACtB,OAAO;QACL,QAAQ,EAAE,WAAW,CAAC;YACpB,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,WAAW,kBAAkB,CAAC,EAAE,wCAAwC,MAAM,CAAC,EAAE,YAAY,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,IAAI,8CAA8C;YACnN,UAAU,EAAE,mBAAmB;SAChC,CAAC;QACF,kBAAkB,EAAE,MAAM;QAC1B,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,WAAW,kBAAkB,CAAC,EAAE,oCAAoC,MAAM,CAAC,EAAE,OAAO,MAAM,CAAC,MAAM,oBAAoB;KAC1I,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,IAKlC;IACC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,kBAAkB,EAAE,UAAU,EAAE,CAAC,CAAC;IACrF,OAAO;QACL,MAAM,EAAE,UAAU;QAClB,GAAG,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE;QACjD,UAAU;QACV,GAAG,EAAE,QAAQ,CAAC,GAAG;QACjB,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;QAC3D,mBAAmB,EAAE,mBAAmB,CAAC,UAAU,CAAC;QACpD,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,OAAO,EAAE,QAAQ,CAAC,OAAO;KAC1B,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAC9B,GAAQ,EACR,UAAsB,EACtB,SAAiB,EACjB,WAAoB;IAEpB,OAAO;QACL,MAAM,EAAE,eAAe;QACvB,GAAG,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE;QACjD,UAAU;QACV,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;QAC3D,mBAAmB,EAAE,mBAAmB,CAAC,UAAU,CAAC;QACpD,QAAQ,EAAE,YAAY,CAAC;YACrB,GAAG,EAAE,GAAG,CAAC,IAAI;YACb,QAAQ,EAAE,UAAU,CAAC,EAAE;YACvB,UAAU,EACR,UAAU,CAAC,MAAM,KAAK,QAAQ;gBAC5B,CAAC,CAAC,eAAe;gBACjB,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,UAAU;oBAChC,CAAC,CAAC,iBAAiB;oBACnB,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,WAAW;wBACjC,CAAC,CAAC,kBAAkB;wBACpB,CAAC,CAAC,gBAAgB;SAC3B,CAAC;QACF,OAAO,EAAE,WAAW;YAClB,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,WAAW,UAAU,CAAC,EAAE,UAAU,UAAU,CAAC,MAAM,gBAAgB,WAAW,yCAAyC;YACpI,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,WAAW,UAAU,CAAC,EAAE,UAAU,UAAU,CAAC,MAAM,wCAAwC;KAC3G,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,UAAsB;IACjD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC3C,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * A single env reference discovered by the source scanner.
3
+ *
4
+ * The scanner inspects an extracted upload tarball before queueing a deploy.
5
+ * Phase 6c uses these references to enforce the `[env]` contract in
6
+ * `percher.toml`: any static key not declared in `required`, `optional`, or
7
+ * `ignore` blocks the deploy with a `fix_config` problem.
8
+ */
9
+ export interface EnvReference {
10
+ /** The env key referenced. Empty string when `shape` is `"dynamic"`. */
11
+ key: string;
12
+ /** File path relative to the source root (forward slashes). */
13
+ file: string;
14
+ /** 1-based line number where the reference appears. */
15
+ line: number;
16
+ /** Verbatim source line (trimmed) for diagnostics. */
17
+ context: string;
18
+ /** Static (literal key) vs dynamic (e.g. `process.env[varName]`). */
19
+ shape: "static" | "dynamic";
20
+ }
21
+ export interface ScanOptions {
22
+ /** Optional list of relative paths to skip on top of the built-in defaults. */
23
+ exclude?: string[];
24
+ /**
25
+ * Files larger than this in bytes are skipped silently (default 1 MiB).
26
+ * Prevents pathological inputs (minified bundles, huge JSON blobs) from
27
+ * dominating scan time.
28
+ */
29
+ maxFileBytes?: number;
30
+ }
31
+ /**
32
+ * Recursively scans `rootDir` for env references in supported source files.
33
+ *
34
+ * Read-only: never modifies the source tree. Tolerant of unreadable files and
35
+ * directories — they are skipped silently. Files exceeding `maxFileBytes` are
36
+ * skipped to bound runtime on pathological inputs (minified bundles, etc.).
37
+ */
38
+ export declare function scanSourceForEnvRefs(rootDir: string, opts?: ScanOptions): Promise<EnvReference[]>;
39
+ //# sourceMappingURL=env-scan-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-scan-source.d.ts","sourceRoot":"","sources":["../src/env-scan-source.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA6QD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CA+CzB"}