@arizeai/phoenix-cli 1.8.1 → 1.9.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 (242) hide show
  1. package/README.md +34 -0
  2. package/build/cli.d.ts.map +1 -1
  3. package/build/cli.js +2 -1
  4. package/build/cli.js.map +1 -1
  5. package/build/client.d.ts +5 -1
  6. package/build/client.d.ts.map +1 -1
  7. package/build/client.js +2 -1
  8. package/build/client.js.map +1 -1
  9. package/build/commands/annotationConfig.d.ts.map +1 -1
  10. package/build/commands/annotationConfig.js.map +1 -1
  11. package/build/commands/{annotationMutationUtils.d.ts → annotationMutations.d.ts} +1 -1
  12. package/build/commands/annotationMutations.d.ts.map +1 -0
  13. package/build/commands/{annotationMutationUtils.js → annotationMutations.js} +1 -1
  14. package/build/commands/annotationMutations.js.map +1 -0
  15. package/build/commands/api.d.ts.map +1 -1
  16. package/build/commands/api.js.map +1 -1
  17. package/build/commands/auth.d.ts +1 -1
  18. package/build/commands/auth.d.ts.map +1 -1
  19. package/build/commands/auth.js +6 -12
  20. package/build/commands/auth.js.map +1 -1
  21. package/build/commands/dataset.d.ts.map +1 -1
  22. package/build/commands/dataset.js.map +1 -1
  23. package/build/commands/docs.d.ts +51 -0
  24. package/build/commands/docs.d.ts.map +1 -1
  25. package/build/commands/docs.js +86 -37
  26. package/build/commands/docs.js.map +1 -1
  27. package/build/commands/experiment.d.ts.map +1 -1
  28. package/build/commands/experiment.js.map +1 -1
  29. package/build/commands/fetchSpanAnnotations.d.ts +14 -0
  30. package/build/commands/fetchSpanAnnotations.d.ts.map +1 -0
  31. package/build/commands/fetchSpanAnnotations.js +57 -0
  32. package/build/commands/fetchSpanAnnotations.js.map +1 -0
  33. package/build/commands/fetchTraceAnnotations.d.ts +14 -0
  34. package/build/commands/fetchTraceAnnotations.d.ts.map +1 -0
  35. package/build/commands/fetchTraceAnnotations.js +57 -0
  36. package/build/commands/fetchTraceAnnotations.js.map +1 -0
  37. package/build/commands/formatAnnotationMutation.d.ts +1 -1
  38. package/build/commands/formatAnnotationMutation.d.ts.map +1 -1
  39. package/build/commands/formatNoteMutation.d.ts +1 -1
  40. package/build/commands/formatNoteMutation.d.ts.map +1 -1
  41. package/build/commands/formatSetup.d.ts +50 -0
  42. package/build/commands/formatSetup.d.ts.map +1 -0
  43. package/build/commands/formatSetup.js +64 -0
  44. package/build/commands/formatSetup.js.map +1 -0
  45. package/build/commands/index.d.ts +4 -3
  46. package/build/commands/index.d.ts.map +1 -1
  47. package/build/commands/index.js +4 -3
  48. package/build/commands/index.js.map +1 -1
  49. package/build/commands/{noteMutationUtils.d.ts → noteMutations.d.ts} +1 -1
  50. package/build/commands/noteMutations.d.ts.map +1 -0
  51. package/build/commands/{noteMutationUtils.js → noteMutations.js} +1 -1
  52. package/build/commands/noteMutations.js.map +1 -0
  53. package/build/commands/options.d.ts +248 -0
  54. package/build/commands/options.d.ts.map +1 -0
  55. package/build/commands/options.js +16 -0
  56. package/build/commands/options.js.map +1 -0
  57. package/build/commands/profile.d.ts.map +1 -1
  58. package/build/commands/profile.js +3 -11
  59. package/build/commands/profile.js.map +1 -1
  60. package/build/commands/project.d.ts.map +1 -1
  61. package/build/commands/project.js +0 -1
  62. package/build/commands/project.js.map +1 -1
  63. package/build/commands/prompt.d.ts.map +1 -1
  64. package/build/commands/prompt.js.map +1 -1
  65. package/build/commands/self.d.ts.map +1 -1
  66. package/build/commands/self.js.map +1 -1
  67. package/build/commands/session.d.ts.map +1 -1
  68. package/build/commands/session.js +4 -4
  69. package/build/commands/session.js.map +1 -1
  70. package/build/commands/{sessionAnnotationsCommand.d.ts → sessionAnnotations.d.ts} +1 -1
  71. package/build/commands/sessionAnnotations.d.ts.map +1 -0
  72. package/build/commands/{sessionAnnotationsCommand.js → sessionAnnotations.js} +1 -1
  73. package/build/commands/sessionAnnotations.js.map +1 -0
  74. package/build/commands/setup.d.ts +19 -0
  75. package/build/commands/setup.d.ts.map +1 -0
  76. package/build/commands/setup.js +245 -0
  77. package/build/commands/setup.js.map +1 -0
  78. package/build/commands/span.d.ts.map +1 -1
  79. package/build/commands/span.js +5 -5
  80. package/build/commands/span.js.map +1 -1
  81. package/build/commands/spanAnnotations.d.ts +6 -13
  82. package/build/commands/spanAnnotations.d.ts.map +1 -1
  83. package/build/commands/spanAnnotations.js +154 -47
  84. package/build/commands/spanAnnotations.js.map +1 -1
  85. package/build/commands/trace.d.ts.map +1 -1
  86. package/build/commands/trace.js +6 -6
  87. package/build/commands/trace.js.map +1 -1
  88. package/build/commands/traceAnnotations.d.ts +6 -13
  89. package/build/commands/traceAnnotations.d.ts.map +1 -1
  90. package/build/commands/traceAnnotations.js +157 -47
  91. package/build/commands/traceAnnotations.js.map +1 -1
  92. package/build/curl.d.ts +17 -0
  93. package/build/curl.d.ts.map +1 -1
  94. package/build/curl.js.map +1 -1
  95. package/build/optionParsers.d.ts +12 -0
  96. package/build/optionParsers.d.ts.map +1 -1
  97. package/build/optionParsers.js +15 -0
  98. package/build/optionParsers.js.map +1 -1
  99. package/build/pxi/App.d.ts.map +1 -1
  100. package/build/pxi/App.js +4 -0
  101. package/build/pxi/App.js.map +1 -1
  102. package/build/pxi/options.d.ts +98 -0
  103. package/build/pxi/options.d.ts.map +1 -1
  104. package/build/pxi/options.js.map +1 -1
  105. package/build/settings.d.ts.map +1 -1
  106. package/build/settings.js +4 -0
  107. package/build/settings.js.map +1 -1
  108. package/build/setup/agents/registry.d.ts +78 -0
  109. package/build/setup/agents/registry.d.ts.map +1 -0
  110. package/build/setup/agents/registry.js +129 -0
  111. package/build/setup/agents/registry.js.map +1 -0
  112. package/build/setup/copy.d.ts +167 -0
  113. package/build/setup/copy.d.ts.map +1 -0
  114. package/build/setup/copy.js +290 -0
  115. package/build/setup/copy.js.map +1 -0
  116. package/build/setup/deps/buildDefaultDeps.d.ts +13 -0
  117. package/build/setup/deps/buildDefaultDeps.d.ts.map +1 -0
  118. package/build/setup/deps/buildDefaultDeps.js +29 -0
  119. package/build/setup/deps/buildDefaultDeps.js.map +1 -0
  120. package/build/setup/deps/clipboard.d.ts +12 -0
  121. package/build/setup/deps/clipboard.d.ts.map +1 -0
  122. package/build/setup/deps/clipboard.js +30 -0
  123. package/build/setup/deps/clipboard.js.map +1 -0
  124. package/build/setup/deps/clock.d.ts +10 -0
  125. package/build/setup/deps/clock.d.ts.map +1 -0
  126. package/build/setup/deps/clock.js +11 -0
  127. package/build/setup/deps/clock.js.map +1 -0
  128. package/build/setup/deps/context.d.ts +28 -0
  129. package/build/setup/deps/context.d.ts.map +1 -0
  130. package/build/setup/deps/context.js +24 -0
  131. package/build/setup/deps/context.js.map +1 -0
  132. package/build/setup/deps/docs.d.ts +41 -0
  133. package/build/setup/deps/docs.d.ts.map +1 -0
  134. package/build/setup/deps/docs.js +33 -0
  135. package/build/setup/deps/docs.js.map +1 -0
  136. package/build/setup/deps/index.d.ts +42 -0
  137. package/build/setup/deps/index.d.ts.map +1 -0
  138. package/build/setup/deps/index.js +16 -0
  139. package/build/setup/deps/index.js.map +1 -0
  140. package/build/setup/deps/phoenixClient.d.ts +22 -0
  141. package/build/setup/deps/phoenixClient.d.ts.map +1 -0
  142. package/build/setup/deps/phoenixClient.js +17 -0
  143. package/build/setup/deps/phoenixClient.js.map +1 -0
  144. package/build/setup/deps/processes.d.ts +28 -0
  145. package/build/setup/deps/processes.d.ts.map +1 -0
  146. package/build/setup/deps/processes.js +58 -0
  147. package/build/setup/deps/processes.js.map +1 -0
  148. package/build/setup/deps/prompter.d.ts +42 -0
  149. package/build/setup/deps/prompter.d.ts.map +1 -0
  150. package/build/setup/deps/prompter.js +10 -0
  151. package/build/setup/deps/prompter.js.map +1 -0
  152. package/build/setup/errors.d.ts +27 -0
  153. package/build/setup/errors.d.ts.map +1 -0
  154. package/build/setup/errors.js +36 -0
  155. package/build/setup/errors.js.map +1 -0
  156. package/build/setup/options.d.ts +113 -0
  157. package/build/setup/options.d.ts.map +1 -0
  158. package/build/setup/options.js +63 -0
  159. package/build/setup/options.js.map +1 -0
  160. package/build/setup/prompts/instrumentationPrompt.d.ts +42 -0
  161. package/build/setup/prompts/instrumentationPrompt.d.ts.map +1 -0
  162. package/build/setup/prompts/instrumentationPrompt.js +64 -0
  163. package/build/setup/prompts/instrumentationPrompt.js.map +1 -0
  164. package/build/setup/runSetup.d.ts +45 -0
  165. package/build/setup/runSetup.d.ts.map +1 -0
  166. package/build/setup/runSetup.js +212 -0
  167. package/build/setup/runSetup.js.map +1 -0
  168. package/build/setup/steps/chooseEndpoint.d.ts +36 -0
  169. package/build/setup/steps/chooseEndpoint.d.ts.map +1 -0
  170. package/build/setup/steps/chooseEndpoint.js +125 -0
  171. package/build/setup/steps/chooseEndpoint.js.map +1 -0
  172. package/build/setup/steps/confirmGitSafety.d.ts +17 -0
  173. package/build/setup/steps/confirmGitSafety.d.ts.map +1 -0
  174. package/build/setup/steps/confirmGitSafety.js +73 -0
  175. package/build/setup/steps/confirmGitSafety.js.map +1 -0
  176. package/build/setup/steps/establishConnection.d.ts +29 -0
  177. package/build/setup/steps/establishConnection.d.ts.map +1 -0
  178. package/build/setup/steps/establishConnection.js +143 -0
  179. package/build/setup/steps/establishConnection.js.map +1 -0
  180. package/build/setup/steps/installTooling.d.ts +28 -0
  181. package/build/setup/steps/installTooling.d.ts.map +1 -0
  182. package/build/setup/steps/installTooling.js +79 -0
  183. package/build/setup/steps/installTooling.js.map +1 -0
  184. package/build/setup/steps/instrumentApp.d.ts +41 -0
  185. package/build/setup/steps/instrumentApp.d.ts.map +1 -0
  186. package/build/setup/steps/instrumentApp.js +131 -0
  187. package/build/setup/steps/instrumentApp.js.map +1 -0
  188. package/build/setup/steps/offerPxProfile.d.ts +20 -0
  189. package/build/setup/steps/offerPxProfile.d.ts.map +1 -0
  190. package/build/setup/steps/offerPxProfile.js +95 -0
  191. package/build/setup/steps/offerPxProfile.js.map +1 -0
  192. package/build/setup/steps/prefetchDocs.d.ts +24 -0
  193. package/build/setup/steps/prefetchDocs.d.ts.map +1 -0
  194. package/build/setup/steps/prefetchDocs.js +49 -0
  195. package/build/setup/steps/prefetchDocs.js.map +1 -0
  196. package/build/setup/steps/verifyTraces.d.ts +44 -0
  197. package/build/setup/steps/verifyTraces.d.ts.map +1 -0
  198. package/build/setup/steps/verifyTraces.js +119 -0
  199. package/build/setup/steps/verifyTraces.js.map +1 -0
  200. package/build/setup/steps/writeEnvFile.d.ts +19 -0
  201. package/build/setup/steps/writeEnvFile.d.ts.map +1 -0
  202. package/build/setup/steps/writeEnvFile.js +50 -0
  203. package/build/setup/steps/writeEnvFile.js.map +1 -0
  204. package/build/setup/ui/clackPrompter.d.ts +11 -0
  205. package/build/setup/ui/clackPrompter.d.ts.map +1 -0
  206. package/build/setup/ui/clackPrompter.js +107 -0
  207. package/build/setup/ui/clackPrompter.js.map +1 -0
  208. package/build/setup/ui/selectBoolean.d.ts +18 -0
  209. package/build/setup/ui/selectBoolean.d.ts.map +1 -0
  210. package/build/setup/ui/selectBoolean.js +14 -0
  211. package/build/setup/ui/selectBoolean.js.map +1 -0
  212. package/build/setup/util/gitignoreCoverage.d.ts +24 -0
  213. package/build/setup/util/gitignoreCoverage.d.ts.map +1 -0
  214. package/build/setup/util/gitignoreCoverage.js +43 -0
  215. package/build/setup/util/gitignoreCoverage.js.map +1 -0
  216. package/build/setup/util/paths.d.ts +6 -0
  217. package/build/setup/util/paths.d.ts.map +1 -0
  218. package/build/setup/util/paths.js +23 -0
  219. package/build/setup/util/paths.js.map +1 -0
  220. package/build/setup/util/redact.d.ts +12 -0
  221. package/build/setup/util/redact.d.ts.map +1 -0
  222. package/build/setup/util/redact.js +31 -0
  223. package/build/setup/util/redact.js.map +1 -0
  224. package/build/validation/endpoint.d.ts +19 -0
  225. package/build/validation/endpoint.d.ts.map +1 -0
  226. package/build/validation/endpoint.js +39 -0
  227. package/build/validation/endpoint.js.map +1 -0
  228. package/package.json +15 -12
  229. package/build/commands/annotationMutationUtils.d.ts.map +0 -1
  230. package/build/commands/annotationMutationUtils.js.map +0 -1
  231. package/build/commands/noteMutationUtils.d.ts.map +0 -1
  232. package/build/commands/noteMutationUtils.js.map +0 -1
  233. package/build/commands/sessionAnnotationsCommand.d.ts.map +0 -1
  234. package/build/commands/sessionAnnotationsCommand.js.map +0 -1
  235. package/build/commands/spanAnnotationsCommand.d.ts +0 -7
  236. package/build/commands/spanAnnotationsCommand.d.ts.map +0 -1
  237. package/build/commands/spanAnnotationsCommand.js +0 -164
  238. package/build/commands/spanAnnotationsCommand.js.map +0 -1
  239. package/build/commands/traceAnnotationsCommand.d.ts +0 -7
  240. package/build/commands/traceAnnotationsCommand.d.ts.map +0 -1
  241. package/build/commands/traceAnnotationsCommand.js +0 -167
  242. package/build/commands/traceAnnotationsCommand.js.map +0 -1
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Instrumentation hand-off.
3
+ *
4
+ * Lanes, in order of preference: launch a detected coding agent directly
5
+ * (prompt pre-loaded, credentials injected via env), copy the prompt for an
6
+ * agent the user runs themselves, or manual via the quickstart docs. All
7
+ * lanes converge on the trace-verification step — setup's definition of
8
+ * done is API-verified data flow, not agent self-report.
9
+ *
10
+ * `--agent` pre-answers the lane, which is what makes an unattended run
11
+ * possible: with no TTY there is no prompt to pick a lane from, and the agent
12
+ * runs in background mode (no TUI to hand the terminal to).
13
+ */
14
+ import { buildLaunchSpec, getCodingAgent, probeBinary, } from "../agents/registry.js";
15
+ import * as COPY from "../copy.js";
16
+ import { SetupFatalError } from "../errors.js";
17
+ import { buildInstrumentationPrompt } from "../prompts/instrumentationPrompt.js";
18
+ import { tracesUrl } from "./verifyTraces.js";
19
+ const DEFAULT_LOCAL_ENDPOINT = "http://localhost:6006";
20
+ export async function instrumentApp(deps, connection, args) {
21
+ const { authEnabled, agentDetection, languages, mode } = args;
22
+ const prompt = buildInstrumentationPrompt({
23
+ projectName: connection.projectName,
24
+ endpoint: connection.endpoint,
25
+ isDefaultEndpoint: connection.endpoint === DEFAULT_LOCAL_ENDPOINT,
26
+ docs: {
27
+ quickstartPython: COPY.DOCS.quickstartPython,
28
+ quickstartTypeScript: COPY.DOCS.quickstartTypeScript,
29
+ phoenixOtelSetup: COPY.DOCS.phoenixOtelSetup,
30
+ integrationsIndex: COPY.DOCS.integrationsIndex,
31
+ },
32
+ tracesUrl: tracesUrl(connection),
33
+ authEnabled,
34
+ languages,
35
+ // Only advertise the local docs dir when it holds pages — an empty one
36
+ // (docs site down, over-narrow workflow filter) would send the agent to
37
+ // read a directory with nothing in it instead of the web.
38
+ ...(args.docs?.hasPagesOnDisk ? { localDocsDir: args.docs.outputDir } : {}),
39
+ });
40
+ // `--agent` short-circuits the lane prompt. The binary is probed rather
41
+ // than taken from the detection sweep so a named-but-missing agent fails
42
+ // with "not on your PATH" instead of silently dropping to another lane.
43
+ if (args.agent) {
44
+ const agent = getCodingAgent(args.agent);
45
+ if (!agent) {
46
+ throw new SetupFatalError(COPY.INSTRUMENTATION.unknownAgent(args.agent));
47
+ }
48
+ if (!(await probeBinary(deps, agent.binary))) {
49
+ throw new SetupFatalError(COPY.INSTRUMENTATION.agentNotFound(agent.label, agent.binary));
50
+ }
51
+ return launchAgent(deps, connection, { agent, prompt, mode });
52
+ }
53
+ const detectedAgents = await agentDetection;
54
+ const options = [
55
+ ...detectedAgents.map((agent) => ({
56
+ value: `agent:${agent.id}`,
57
+ label: COPY.INSTRUMENTATION.launchLabel(agent.label),
58
+ hint: COPY.INSTRUMENTATION.launchHint,
59
+ })),
60
+ {
61
+ value: "clipboard",
62
+ label: COPY.INSTRUMENTATION.clipboardLabel,
63
+ hint: COPY.INSTRUMENTATION.clipboardHint,
64
+ },
65
+ {
66
+ value: "manual",
67
+ label: COPY.INSTRUMENTATION.manualLabel,
68
+ hint: COPY.INSTRUMENTATION.manualHint,
69
+ },
70
+ ];
71
+ const choice = await deps.prompter.select({
72
+ message: COPY.INSTRUMENTATION.modeMessage,
73
+ options,
74
+ });
75
+ const chosenAgent = detectedAgents.find((agent) => choice === `agent:${agent.id}`);
76
+ if (chosenAgent) {
77
+ return launchAgent(deps, connection, { agent: chosenAgent, prompt, mode });
78
+ }
79
+ if (choice === "clipboard") {
80
+ const copied = await deps.writeClipboard(prompt);
81
+ if (copied) {
82
+ deps.prompter.line(COPY.INSTRUMENTATION.promptCopied);
83
+ }
84
+ else {
85
+ deps.prompter.line(COPY.INSTRUMENTATION.promptCopyFailed);
86
+ deps.prompter.note(prompt);
87
+ }
88
+ await deps.prompter.select({
89
+ message: COPY.INSTRUMENTATION.clipboardDoneMessage,
90
+ options: [
91
+ { value: true, label: COPY.INSTRUMENTATION.clipboardDoneLabel },
92
+ ],
93
+ });
94
+ return { kind: "clipboard" };
95
+ }
96
+ deps.prompter.line(COPY.INSTRUMENTATION.manualDocs(COPY.DOCS.instrumentationIndex));
97
+ await deps.prompter.select({
98
+ message: COPY.INSTRUMENTATION.manualDoneMessage,
99
+ options: [{ value: true, label: COPY.INSTRUMENTATION.manualDoneLabel }],
100
+ });
101
+ return { kind: "manual" };
102
+ }
103
+ /**
104
+ * Run the agent with the prompt pre-loaded. A non-zero exit is a warning, not
105
+ * a failure: the agent may have instrumented the app and then exited badly,
106
+ * and trace verification — not the agent's exit code — decides whether setup
107
+ * succeeded.
108
+ */
109
+ async function launchAgent(deps, connection, { agent, prompt, mode, }) {
110
+ // Without its TUI *and* without permission bypass, an agent stalls on the
111
+ // first approval it wants, with no terminal to approve it on — the run then
112
+ // dies at the verification timeout with nothing to show. Say so up front.
113
+ if (mode.background && !mode.bypassPermissions) {
114
+ deps.prompter.line(COPY.INSTRUMENTATION.backgroundNeedsYolo(agent.label));
115
+ }
116
+ deps.prompter.line(mode.background
117
+ ? COPY.INSTRUMENTATION.launchingBackground(agent.label)
118
+ : COPY.INSTRUMENTATION.launching(agent.label));
119
+ const spec = buildLaunchSpec(agent, {
120
+ prompt,
121
+ cwd: deps.context.cwd,
122
+ connection,
123
+ mode,
124
+ });
125
+ const { exitCode } = await deps.processes.spawnInteractive(spec);
126
+ if (exitCode !== 0) {
127
+ deps.prompter.line(COPY.INSTRUMENTATION.agentExitWarning(agent.label));
128
+ }
129
+ return { kind: "agent", agent: agent.id, exitCode };
130
+ }
131
+ //# sourceMappingURL=instrumentApp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumentApp.js","sourceRoot":"","sources":["../../../src/setup/steps/instrumentApp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Offer to point `px` at the project setup just connected.
3
+ *
4
+ * Because setup *is* px, everything here is in-process — the profile
5
+ * (including the API key, when auth is on) is written through px's own
6
+ * settings module (`~/.px/settings.json`, dir 0700, file 0600). No argv or
7
+ * subprocess ever carries the secret. Any failure is a non-fatal warning;
8
+ * setup proceeds regardless.
9
+ */
10
+ import type { SetupDeps } from "../deps/index.js";
11
+ import type { Connection } from "./establishConnection.js";
12
+ /** `local` for localhost, else the host with dots and colons → dashes. */
13
+ export declare function profileNameForEndpoint(endpoint: string): string;
14
+ export interface PxProfileArgs {
15
+ connection: Connection;
16
+ /** Override the settings file path (tests). */
17
+ settingsPath?: string;
18
+ }
19
+ export declare function offerPxProfile(deps: Pick<SetupDeps, "prompter">, { connection, settingsPath }: PxProfileArgs): Promise<void>;
20
+ //# sourceMappingURL=offerPxProfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offerPxProfile.d.ts","sourceRoot":"","sources":["../../../src/setup/steps/offerPxProfile.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAYH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,0EAA0E;AAC1E,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO/D;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,UAAU,CAAC;IACvB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EACjC,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,aAAa,GAC1C,OAAO,CAAC,IAAI,CAAC,CAoFf"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Offer to point `px` at the project setup just connected.
3
+ *
4
+ * Because setup *is* px, everything here is in-process — the profile
5
+ * (including the API key, when auth is on) is written through px's own
6
+ * settings module (`~/.px/settings.json`, dir 0700, file 0600). No argv or
7
+ * subprocess ever carries the secret. Any failure is a non-fatal warning;
8
+ * setup proceeds regardless.
9
+ */
10
+ import { getSettingsPath, getStoredActiveProfile, loadSettings, saveSettings, SettingsFileError, } from "../../settings.js";
11
+ import * as COPY from "../copy.js";
12
+ import { SetupCancelledError } from "../errors.js";
13
+ import { redactForDisplay } from "../util/redact.js";
14
+ /** `local` for localhost, else the host with dots and colons → dashes. */
15
+ export function profileNameForEndpoint(endpoint) {
16
+ // URL.hostname keeps the brackets on IPv6 literals (e.g. "[::1]").
17
+ const host = new URL(endpoint).hostname;
18
+ if (host === "localhost" || host === "127.0.0.1" || host === "[::1]") {
19
+ return "local";
20
+ }
21
+ return host.replace(/^\[|\]$/g, "").replace(/[.:]/g, "-");
22
+ }
23
+ export async function offerPxProfile(deps, { connection, settingsPath }) {
24
+ // Strict, and on its own: a settings file whose contents don't parse must not
25
+ // degrade to the empty profiles record a lenient load returns, which the save
26
+ // below would then write over whatever the user had. A file that is simply
27
+ // absent is not an error — the load returns fresh settings for it.
28
+ let settings;
29
+ try {
30
+ settings = loadSettings({ settingsPath, strict: true });
31
+ }
32
+ catch (error) {
33
+ // Only a file we can't parse gets sent here. `px profile create`, the
34
+ // remedy the generic failure suggests, loads the same file the same strict
35
+ // way — so for this one failure it is no remedy at all, and the file itself
36
+ // is what has to be dealt with.
37
+ if (error instanceof SettingsFileError) {
38
+ deps.prompter.line(COPY.PX_PROFILE.unreadableSettings(settingsPath ?? getSettingsPath(), redactForDisplay(error.message)));
39
+ return;
40
+ }
41
+ deps.prompter.line(COPY.PX_PROFILE.failed(redactForDisplay(String(error))));
42
+ return;
43
+ }
44
+ try {
45
+ const active = getStoredActiveProfile(settings);
46
+ // A fully-configured active profile pointing elsewhere is a conflict —
47
+ // ask before switching, never clobber silently. A partially configured
48
+ // profile (missing endpoint or project) is non-conflicting.
49
+ const conflicting = active !== undefined &&
50
+ Boolean(active.entry.endpoint) &&
51
+ Boolean(active.entry.project) &&
52
+ (active.entry.endpoint !== connection.endpoint ||
53
+ active.entry.project !== connection.projectName);
54
+ const optedIn = await deps.prompter.select(conflicting && active
55
+ ? {
56
+ message: COPY.PX_PROFILE.conflictMessage(active.name, active.entry.endpoint ?? ""),
57
+ options: [
58
+ { value: false, label: COPY.PX_PROFILE.conflictNo },
59
+ { value: true, label: COPY.PX_PROFILE.conflictYes },
60
+ ],
61
+ }
62
+ : {
63
+ message: COPY.PX_PROFILE.optInMessage,
64
+ options: [
65
+ { value: true, label: COPY.PX_PROFILE.optInYes },
66
+ { value: false, label: COPY.PX_PROFILE.optInNo },
67
+ ],
68
+ });
69
+ if (!optedIn) {
70
+ return;
71
+ }
72
+ const profileName = profileNameForEndpoint(connection.endpoint);
73
+ const entry = {
74
+ endpoint: connection.endpoint,
75
+ project: connection.projectName,
76
+ };
77
+ if (connection.apiKey) {
78
+ entry.apiKey = connection.apiKey;
79
+ }
80
+ settings.profiles[profileName] = {
81
+ ...settings.profiles[profileName],
82
+ ...entry,
83
+ };
84
+ settings.activeProfile = profileName;
85
+ saveSettings(settings, { settingsPath });
86
+ deps.prompter.line(COPY.PX_PROFILE.created(profileName));
87
+ }
88
+ catch (error) {
89
+ if (error instanceof SetupCancelledError) {
90
+ throw error;
91
+ }
92
+ deps.prompter.line(COPY.PX_PROFILE.failed(redactForDisplay(String(error))));
93
+ }
94
+ }
95
+ //# sourceMappingURL=offerPxProfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offerPxProfile.js","sourceRoot":"","sources":["../../../src/setup/steps/offerPxProfile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Prefetch the Phoenix docs into the repo, so the instrumentation agent reads
3
+ * package names and APIs from disk instead of fetching URLs mid-run.
4
+ *
5
+ * Runs only when instrumentation runs — the docs exist to serve the agent, so
6
+ * a registration-only run has no reason to write them. Never fatal: a docs
7
+ * site that is slow or down degrades to the agent fetching pages itself, which
8
+ * is what it did before this step existed.
9
+ *
10
+ * Must run after the git-safety gate: the download writes untracked files
11
+ * under `.px/`, which a fast headless run could otherwise mistake for
12
+ * pre-existing user changes.
13
+ */
14
+ import { type DocsPrefetchOptions, type DocsPrefetchResult, type SetupDeps } from "../deps/index.js";
15
+ /**
16
+ * Download the docs and gitignore what they wrote. A failure is reported and
17
+ * dropped: the connection and hand-off files are real work worth keeping, and
18
+ * the agent can still read the docs from the web.
19
+ */
20
+ export declare function prefetchDocs(deps: Pick<SetupDeps, "fetchDocs" | "prompter" | "context">, { docs, isGitRepository, }: {
21
+ docs: DocsPrefetchOptions;
22
+ isGitRepository: boolean;
23
+ }): Promise<DocsPrefetchResult | undefined>;
24
+ //# sourceMappingURL=prefetchDocs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefetchDocs.d.ts","sourceRoot":"","sources":["../../../src/setup/steps/prefetchDocs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACf,MAAM,SAAS,CAAC;AAMjB;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC,EAC3D,EACE,IAAI,EACJ,eAAe,GAChB,EAAE;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,GACzD,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CA6BzC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Prefetch the Phoenix docs into the repo, so the instrumentation agent reads
3
+ * package names and APIs from disk instead of fetching URLs mid-run.
4
+ *
5
+ * Runs only when instrumentation runs — the docs exist to serve the agent, so
6
+ * a registration-only run has no reason to write them. Never fatal: a docs
7
+ * site that is slow or down degrades to the agent fetching pages itself, which
8
+ * is what it did before this step existed.
9
+ *
10
+ * Must run after the git-safety gate: the download writes untracked files
11
+ * under `.px/`, which a fast headless run could otherwise mistake for
12
+ * pre-existing user changes.
13
+ */
14
+ import * as COPY from "../copy.js";
15
+ import { unknownWorkflowWarning, } from "../deps/index.js";
16
+ import { ensureGitignored } from "../util/gitignoreCoverage.js";
17
+ /** The docs land under `.px/`, so that is what gets gitignored. */
18
+ const DOCS_GITIGNORE_ENTRY = ".px/";
19
+ /**
20
+ * Download the docs and gitignore what they wrote. A failure is reported and
21
+ * dropped: the connection and hand-off files are real work worth keeping, and
22
+ * the agent can still read the docs from the web.
23
+ */
24
+ export async function prefetchDocs(deps, { docs, isGitRepository, }) {
25
+ if (!docs.enabled) {
26
+ return undefined;
27
+ }
28
+ deps.prompter.line(COPY.DOCS_PREFETCH.fetching);
29
+ try {
30
+ const result = await deps.fetchDocs(docs);
31
+ // A typo'd --workflow filters silently, so name it — otherwise the run
32
+ // reports "0 pages" with no hint the workflow value was the problem.
33
+ for (const workflow of result.unknownWorkflows ?? []) {
34
+ deps.prompter.line(unknownWorkflowWarning(workflow));
35
+ }
36
+ const { appended } = ensureGitignored({
37
+ directory: deps.context.cwd,
38
+ filenames: [DOCS_GITIGNORE_ENTRY],
39
+ isGitRepository,
40
+ });
41
+ deps.prompter.line(COPY.DOCS_PREFETCH.wrote(result.written, result.outputDir));
42
+ return { ...result, gitignoreAppended: appended };
43
+ }
44
+ catch (error) {
45
+ deps.prompter.line(COPY.DOCS_PREFETCH.failed(error instanceof Error ? error.message : String(error)));
46
+ return undefined;
47
+ }
48
+ }
49
+ //# sourceMappingURL=prefetchDocs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefetchDocs.js","sourceRoot":"","sources":["../../../src/setup/steps/prefetchDocs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,EACL,sBAAsB,GAIvB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,mEAAmE;AACnE,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAEpC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAA2D,EAC3D,EACE,IAAI,EACJ,eAAe,GACyC;IAE1D,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC1C,uEAAuE;QACvE,qEAAqE;QACrE,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,gBAAgB,IAAI,EAAE,EAAE,CAAC;YACrD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC;YACpC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG;YAC3B,SAAS,EAAE,CAAC,oBAAoB,CAAC;YACjC,eAAe;SAChB,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,IAAI,CAChB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,CAC3D,CAAC;QACF,OAAO,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,QAAQ,CAAC,IAAI,CAChB,IAAI,CAAC,aAAa,CAAC,MAAM,CACvB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACvD,CACF,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Wait for the first trace to land.
3
+ *
4
+ * Setup verifies data flow itself: it polls the Phoenix span-search API
5
+ * for a span newer than the start of this run until one arrives. The human is
6
+ * only consulted at the timeout escape hatch ("keep watching / finish
7
+ * anyway") — never asked to eyeball the UI as the definition of done.
8
+ */
9
+ import type { SetupDeps } from "../deps/index.js";
10
+ import type { Connection } from "./establishConnection.js";
11
+ /**
12
+ * The project may not exist until the first trace lands, so link by name via
13
+ * the redirect route rather than by an id we no longer have.
14
+ */
15
+ export declare function tracesUrl(connection: Connection): string;
16
+ /**
17
+ * True when the project already has spans inside the clock-skew window at
18
+ * `sinceMs`. Checked before instrumentation begins: any span visible at that
19
+ * point predates this run, so verification must not credit the skew window.
20
+ */
21
+ export declare function hasSpansInSkewWindow(deps: Pick<SetupDeps, "createClient">, connection: Connection, { sinceMs }: {
22
+ sinceMs: number;
23
+ }): Promise<boolean>;
24
+ /**
25
+ * Watch for the first trace since `sinceMs`. Resolves true when a span is
26
+ * observed via the API, false when the wait ends without one — the user gave
27
+ * up at the timeout prompt, or, in a headless run, the first window elapsed.
28
+ *
29
+ * The "keep watching?" prompt is the only thing that can extend the wait, so a
30
+ * headless run gets exactly one window: there is no terminal to ask on, and
31
+ * looping forever would hang an unattended caller.
32
+ *
33
+ * @param args.sinceMs - instrumentation start; only spans after it count.
34
+ * @param args.allowClockSkew - widen the window by the skew tolerance. Pass
35
+ * false when the project had spans before instrumentation began (see
36
+ * `hasSpansInSkewWindow`), so stale spans cannot satisfy verification.
37
+ * @param args.headless - no prompting; give up after one window.
38
+ */
39
+ export declare function waitForFirstTrace(deps: Pick<SetupDeps, "clock" | "createClient" | "prompter">, connection: Connection, { sinceMs, allowClockSkew, headless, }: {
40
+ sinceMs: number;
41
+ allowClockSkew?: boolean;
42
+ headless?: boolean;
43
+ }): Promise<boolean>;
44
+ //# sourceMappingURL=verifyTraces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyTraces.d.ts","sourceRoot":"","sources":["../../../src/setup/steps/verifyTraces.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAQxD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAIxD;AAOD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,EACrC,UAAU,EAAE,UAAU,EACtB,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAC/B,OAAO,CAAC,OAAO,CAAC,CAMlB;AA0DD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,cAAc,GAAG,UAAU,CAAC,EAC5D,UAAU,EAAE,UAAU,EACtB,EACE,OAAO,EACP,cAAqB,EACrB,QAAgB,GACjB,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACnE,OAAO,CAAC,OAAO,CAAC,CAoClB"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Wait for the first trace to land.
3
+ *
4
+ * Setup verifies data flow itself: it polls the Phoenix span-search API
5
+ * for a span newer than the start of this run until one arrives. The human is
6
+ * only consulted at the timeout escape hatch ("keep watching / finish
7
+ * anyway") — never asked to eyeball the UI as the definition of done.
8
+ */
9
+ import * as COPY from "../copy.js";
10
+ const POLL_INTERVAL_MS = 2_000;
11
+ const POLL_WINDOW_MS = 60_000;
12
+ const POLL_REQUEST_TIMEOUT_MS = 5_000;
13
+ /** Tolerance for clock skew between this machine and the span producer. */
14
+ const START_TIME_SKEW_MS = 60_000;
15
+ /**
16
+ * The project may not exist until the first trace lands, so link by name via
17
+ * the redirect route rather than by an id we no longer have.
18
+ */
19
+ export function tracesUrl(connection) {
20
+ return `${connection.endpoint}/redirects/projects/${encodeURIComponent(connection.projectName)}`;
21
+ }
22
+ /** Inclusive lower bound of the span search, as the API's ISO timestamp. */
23
+ function searchStartTime(sinceMs, skewMs) {
24
+ return new Date(sinceMs - skewMs).toISOString();
25
+ }
26
+ /**
27
+ * True when the project already has spans inside the clock-skew window at
28
+ * `sinceMs`. Checked before instrumentation begins: any span visible at that
29
+ * point predates this run, so verification must not credit the skew window.
30
+ */
31
+ export async function hasSpansInSkewWindow(deps, connection, { sinceMs }) {
32
+ return hasNewSpans(spanSearchClient(deps, connection), connection.projectName, searchStartTime(sinceMs, START_TIME_SKEW_MS));
33
+ }
34
+ function spanSearchClient(deps, connection) {
35
+ return deps.createClient({
36
+ endpoint: connection.endpoint,
37
+ apiKey: connection.apiKey,
38
+ });
39
+ }
40
+ /**
41
+ * One span-search request. Any failure is a "not yet": a 404 means the project
42
+ * has no spans to have created it, and a network hiccup mid-poll should keep
43
+ * setup watching rather than abort it.
44
+ */
45
+ async function hasNewSpans(client, projectName, startTime) {
46
+ try {
47
+ const { data } = await client.GET("/v1/projects/{project_identifier}/spans", {
48
+ params: {
49
+ path: { project_identifier: projectName },
50
+ query: { limit: 1, start_time: startTime },
51
+ },
52
+ signal: AbortSignal.timeout(POLL_REQUEST_TIMEOUT_MS),
53
+ });
54
+ return (data?.data.length ?? 0) > 0;
55
+ }
56
+ catch {
57
+ return false;
58
+ }
59
+ }
60
+ /** Poll until a span arrives or the window elapses. */
61
+ async function pollWindow(deps, client, connection, startTime) {
62
+ const deadline = deps.clock.now() + POLL_WINDOW_MS;
63
+ for (;;) {
64
+ if (await hasNewSpans(client, connection.projectName, startTime)) {
65
+ return true;
66
+ }
67
+ if (deps.clock.now() >= deadline) {
68
+ return false;
69
+ }
70
+ await deps.clock.sleep(POLL_INTERVAL_MS);
71
+ }
72
+ }
73
+ /**
74
+ * Watch for the first trace since `sinceMs`. Resolves true when a span is
75
+ * observed via the API, false when the wait ends without one — the user gave
76
+ * up at the timeout prompt, or, in a headless run, the first window elapsed.
77
+ *
78
+ * The "keep watching?" prompt is the only thing that can extend the wait, so a
79
+ * headless run gets exactly one window: there is no terminal to ask on, and
80
+ * looping forever would hang an unattended caller.
81
+ *
82
+ * @param args.sinceMs - instrumentation start; only spans after it count.
83
+ * @param args.allowClockSkew - widen the window by the skew tolerance. Pass
84
+ * false when the project had spans before instrumentation began (see
85
+ * `hasSpansInSkewWindow`), so stale spans cannot satisfy verification.
86
+ * @param args.headless - no prompting; give up after one window.
87
+ */
88
+ export async function waitForFirstTrace(deps, connection, { sinceMs, allowClockSkew = true, headless = false, }) {
89
+ const url = tracesUrl(connection);
90
+ const startTime = searchStartTime(sinceMs, allowClockSkew ? START_TIME_SKEW_MS : 0);
91
+ const client = spanSearchClient(deps, connection);
92
+ deps.prompter.note(COPY.VERIFY.waitingBody(url), COPY.VERIFY.title);
93
+ for (;;) {
94
+ if (await pollWindow(deps, client, connection, startTime)) {
95
+ deps.prompter.line(COPY.VERIFY.received(url));
96
+ return true;
97
+ }
98
+ if (headless) {
99
+ deps.prompter.line(COPY.VERIFY.notVerifiedHeadless(url));
100
+ return false;
101
+ }
102
+ const keepWatching = await deps.prompter.select({
103
+ message: COPY.VERIFY.timeoutMessage,
104
+ options: [
105
+ { value: true, label: COPY.VERIFY.keepWatchingLabel },
106
+ {
107
+ value: false,
108
+ label: COPY.VERIFY.finishLabel,
109
+ hint: COPY.VERIFY.finishHint,
110
+ },
111
+ ],
112
+ });
113
+ if (!keepWatching) {
114
+ deps.prompter.note(COPY.VERIFY.notVerifiedBody(url), COPY.VERIFY.notVerifiedTitle);
115
+ return false;
116
+ }
117
+ }
118
+ }
119
+ //# sourceMappingURL=verifyTraces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyTraces.js","sourceRoot":"","sources":["../../../src/setup/steps/verifyTraces.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Write the hand-off file.
3
+ *
4
+ * Writes `.env.phoenix` into cwd (deliberately not the repo root — bounded
5
+ * blast radius in monorepos), mode 0600, then ensures it is gitignored. The
6
+ * file emits the SDK env var names — it configures the user's app, not px.
7
+ */
8
+ import type { SetupDeps } from "../deps/index.js";
9
+ import type { Connection } from "./establishConnection.js";
10
+ export declare const ENV_FILE_NAME = ".env.phoenix";
11
+ export declare function renderEnvFile(connection: Connection, isoDate: string): string;
12
+ export interface WriteEnvFileResult {
13
+ envFilePath: string;
14
+ gitignoreAppended: string[];
15
+ }
16
+ export declare function writeEnvFile(deps: Pick<SetupDeps, "clock" | "context">, connection: Connection, { isGitRepository }: {
17
+ isGitRepository: boolean;
18
+ }): WriteEnvFileResult;
19
+ //# sourceMappingURL=writeEnvFile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writeEnvFile.d.ts","sourceRoot":"","sources":["../../../src/setup/steps/writeEnvFile.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,eAAO,MAAM,aAAa,iBAAiB,CAAC;AAY5C,wBAAgB,aAAa,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAU7E;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC,EAC1C,UAAU,EAAE,UAAU,EACtB,EAAE,eAAe,EAAE,EAAE;IAAE,eAAe,EAAE,OAAO,CAAA;CAAE,GAChD,kBAAkB,CAmBpB"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Write the hand-off file.
3
+ *
4
+ * Writes `.env.phoenix` into cwd (deliberately not the repo root — bounded
5
+ * blast radius in monorepos), mode 0600, then ensures it is gitignored. The
6
+ * file emits the SDK env var names — it configures the user's app, not px.
7
+ */
8
+ import * as fs from "node:fs";
9
+ import * as path from "node:path";
10
+ import * as COPY from "../copy.js";
11
+ import { ensureGitignored } from "../util/gitignoreCoverage.js";
12
+ export const ENV_FILE_NAME = ".env.phoenix";
13
+ /**
14
+ * Double-quote a value for a `source`-able env file, escaping the characters
15
+ * the shell still interprets inside double quotes. Project names may contain
16
+ * spaces (the default is the cwd basename), and dotenv-style loaders strip
17
+ * the same quotes.
18
+ */
19
+ function quoteEnvValue(value) {
20
+ return `"${value.replace(/[\\"$`]/g, (char) => `\\${char}`)}"`;
21
+ }
22
+ export function renderEnvFile(connection, isoDate) {
23
+ const lines = [
24
+ COPY.ENV_FILE.fileHeaderEnv(isoDate),
25
+ `PHOENIX_COLLECTOR_ENDPOINT=${quoteEnvValue(connection.endpoint)}`,
26
+ `PHOENIX_PROJECT_NAME=${quoteEnvValue(connection.projectName)}`,
27
+ ];
28
+ if (connection.apiKey) {
29
+ lines.push(`PHOENIX_API_KEY=${quoteEnvValue(connection.apiKey)}`);
30
+ }
31
+ return `${lines.join("\n")}\n`;
32
+ }
33
+ export function writeEnvFile(deps, connection, { isGitRepository }) {
34
+ const isoDate = new Date(deps.clock.now()).toISOString();
35
+ const envFilePath = path.join(deps.context.cwd, ENV_FILE_NAME);
36
+ fs.writeFileSync(envFilePath, renderEnvFile(connection, isoDate), {
37
+ encoding: "utf-8",
38
+ mode: 0o600,
39
+ });
40
+ // Rewrites of an existing file keep its old mode — enforce 0600 anyway.
41
+ fs.chmodSync(envFilePath, 0o600);
42
+ // Applied in the auth-off case too: the file may later gain a key.
43
+ const { appended } = ensureGitignored({
44
+ directory: deps.context.cwd,
45
+ filenames: [ENV_FILE_NAME],
46
+ isGitRepository,
47
+ });
48
+ return { envFilePath, gitignoreAppended: appended };
49
+ }
50
+ //# sourceMappingURL=writeEnvFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writeEnvFile.js","sourceRoot":"","sources":["../../../src/setup/steps/writeEnvFile.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAEhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAG7D,MAAM,CAAC,MAAM,aAAa,GAAG,cAAc,CAAC;AAE5C;;;;;GAKG;AACH,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,UAAsB,EAAE,OAAe;IACnE,MAAM,KAAK,GAAG;QACZ,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;QACpC,8BAA8B,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;QAClE,wBAAwB,aAAa,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE;KAChE,CAAC;IACF,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,mBAAmB,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC;AAOD,MAAM,UAAU,YAAY,CAC1B,IAA0C,EAC1C,UAAsB,EACtB,EAAE,eAAe,EAAgC;IAEjD,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACzD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAE/D,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE;QAChE,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;IACH,wEAAwE;IACxE,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAEjC,mEAAmE;IACnE,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC;QACpC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG;QAC3B,SAAS,EAAE,CAAC,aAAa,CAAC;QAC1B,eAAe;KAChB,CAAC,CAAC;IAEH,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC;AACtD,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Clack-backed implementation of setup's `Prompter` seam.
3
+ *
4
+ * House rules: setup has no confirm primitive — every
5
+ * choice, including booleans, is a select. Cancellation (Ctrl-C / Escape)
6
+ * maps to `SetupCancelledError`, unwinding to the single catch site in the
7
+ * command handler.
8
+ */
9
+ import type { Prompter } from "../deps/index.js";
10
+ export declare function createClackPrompter(): Prompter;
11
+ //# sourceMappingURL=clackPrompter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clackPrompter.d.ts","sourceRoot":"","sources":["../../../src/setup/ui/clackPrompter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,SAAS,CAAC;AAWtD,wBAAgB,mBAAmB,IAAI,QAAQ,CAyG9C"}