@opendatalabs/connect 0.8.1-canary.e3412ff → 0.8.1-canary.f421ec8

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 (142) hide show
  1. package/README.md +42 -0
  2. package/dist/cli/bin.d.ts +3 -0
  3. package/dist/cli/bin.d.ts.map +1 -0
  4. package/dist/cli/bin.js +7 -0
  5. package/dist/cli/bin.js.map +1 -0
  6. package/dist/cli/index.d.ts +2 -0
  7. package/dist/cli/index.d.ts.map +1 -0
  8. package/dist/cli/index.js +612 -0
  9. package/dist/cli/index.js.map +1 -0
  10. package/dist/cli/main.d.ts +2 -0
  11. package/dist/cli/main.d.ts.map +1 -0
  12. package/dist/cli/main.js +2 -0
  13. package/dist/cli/main.js.map +1 -0
  14. package/dist/connectors/index.d.ts +2 -0
  15. package/dist/connectors/index.d.ts.map +1 -0
  16. package/dist/connectors/index.js +2 -0
  17. package/dist/connectors/index.js.map +1 -0
  18. package/dist/connectors/registry.d.ts +30 -0
  19. package/dist/connectors/registry.d.ts.map +1 -0
  20. package/dist/connectors/registry.js +166 -0
  21. package/dist/connectors/registry.js.map +1 -0
  22. package/dist/core/cli-types.d.ts +121 -0
  23. package/dist/core/cli-types.d.ts.map +1 -0
  24. package/dist/core/cli-types.js +63 -0
  25. package/dist/core/cli-types.js.map +1 -0
  26. package/dist/core/constants.d.ts +33 -0
  27. package/dist/core/constants.d.ts.map +1 -0
  28. package/dist/core/constants.js +25 -0
  29. package/dist/core/constants.js.map +1 -0
  30. package/dist/core/errors.d.ts +47 -0
  31. package/dist/core/errors.d.ts.map +1 -0
  32. package/dist/core/errors.js +50 -0
  33. package/dist/core/errors.js.map +1 -0
  34. package/dist/core/grants.d.ts +19 -0
  35. package/dist/core/grants.d.ts.map +1 -0
  36. package/dist/core/grants.js +31 -0
  37. package/dist/core/grants.js.map +1 -0
  38. package/dist/core/index.d.ts +8 -0
  39. package/dist/core/index.d.ts.map +1 -0
  40. package/dist/core/index.js +7 -0
  41. package/dist/core/index.js.map +1 -0
  42. package/dist/core/paths.d.ts +8 -0
  43. package/dist/core/paths.d.ts.map +1 -0
  44. package/dist/core/paths.js +25 -0
  45. package/dist/core/paths.js.map +1 -0
  46. package/dist/core/state-store.d.ts +16 -0
  47. package/dist/core/state-store.d.ts.map +1 -0
  48. package/dist/core/state-store.js +23 -0
  49. package/dist/core/state-store.js.map +1 -0
  50. package/dist/core/types.d.ts +135 -0
  51. package/dist/core/types.d.ts.map +1 -0
  52. package/dist/core/types.js +2 -0
  53. package/dist/core/types.js.map +1 -0
  54. package/dist/index.d.ts +2 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +2 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/personal-server/index.d.ts +8 -0
  59. package/dist/personal-server/index.d.ts.map +1 -0
  60. package/dist/personal-server/index.js +76 -0
  61. package/dist/personal-server/index.js.map +1 -0
  62. package/dist/react/ConnectButton.d.ts +27 -0
  63. package/dist/react/ConnectButton.d.ts.map +1 -0
  64. package/dist/react/ConnectButton.js +39 -0
  65. package/dist/react/ConnectButton.js.map +1 -0
  66. package/dist/react/index.d.ts +4 -0
  67. package/dist/react/index.d.ts.map +1 -0
  68. package/dist/react/index.js +4 -0
  69. package/dist/react/index.js.map +1 -0
  70. package/dist/react/useVanaConnect.d.ts +50 -0
  71. package/dist/react/useVanaConnect.d.ts.map +1 -0
  72. package/dist/react/useVanaConnect.js +114 -0
  73. package/dist/react/useVanaConnect.js.map +1 -0
  74. package/dist/react/useVanaData.d.ts +69 -0
  75. package/dist/react/useVanaData.d.ts.map +1 -0
  76. package/dist/react/useVanaData.js +144 -0
  77. package/dist/react/useVanaData.js.map +1 -0
  78. package/dist/runtime/core/contracts.d.ts +69 -0
  79. package/dist/runtime/core/contracts.d.ts.map +1 -0
  80. package/dist/runtime/core/contracts.js +2 -0
  81. package/dist/runtime/core/contracts.js.map +1 -0
  82. package/dist/runtime/core/index.d.ts +2 -0
  83. package/dist/runtime/core/index.d.ts.map +1 -0
  84. package/dist/runtime/core/index.js +2 -0
  85. package/dist/runtime/core/index.js.map +1 -0
  86. package/dist/runtime/index.d.ts +4 -0
  87. package/dist/runtime/index.d.ts.map +1 -0
  88. package/dist/runtime/index.js +3 -0
  89. package/dist/runtime/index.js.map +1 -0
  90. package/dist/runtime/managed-playwright.d.ts +33 -0
  91. package/dist/runtime/managed-playwright.d.ts.map +1 -0
  92. package/dist/runtime/managed-playwright.js +113 -0
  93. package/dist/runtime/managed-playwright.js.map +1 -0
  94. package/dist/runtime/playwright/browser.d.ts +11 -0
  95. package/dist/runtime/playwright/browser.d.ts.map +1 -0
  96. package/dist/runtime/playwright/browser.js +208 -0
  97. package/dist/runtime/playwright/browser.js.map +1 -0
  98. package/dist/runtime/playwright/in-process-run.d.ts +6 -0
  99. package/dist/runtime/playwright/in-process-run.d.ts.map +1 -0
  100. package/dist/runtime/playwright/in-process-run.js +519 -0
  101. package/dist/runtime/playwright/in-process-run.js.map +1 -0
  102. package/dist/runtime/playwright/index.d.ts +3 -0
  103. package/dist/runtime/playwright/index.d.ts.map +1 -0
  104. package/dist/runtime/playwright/index.js +3 -0
  105. package/dist/runtime/playwright/index.js.map +1 -0
  106. package/dist/runtime/repo-paths.d.ts +2 -0
  107. package/dist/runtime/repo-paths.d.ts.map +1 -0
  108. package/dist/runtime/repo-paths.js +36 -0
  109. package/dist/runtime/repo-paths.js.map +1 -0
  110. package/dist/server/config.d.ts +38 -0
  111. package/dist/server/config.d.ts.map +1 -0
  112. package/dist/server/config.js +45 -0
  113. package/dist/server/config.js.map +1 -0
  114. package/dist/server/connect.d.ts +43 -0
  115. package/dist/server/connect.d.ts.map +1 -0
  116. package/dist/server/connect.js +105 -0
  117. package/dist/server/connect.js.map +1 -0
  118. package/dist/server/data-client.d.ts +31 -0
  119. package/dist/server/data-client.d.ts.map +1 -0
  120. package/dist/server/data-client.js +92 -0
  121. package/dist/server/data-client.js.map +1 -0
  122. package/dist/server/index.d.ts +8 -0
  123. package/dist/server/index.d.ts.map +1 -0
  124. package/dist/server/index.js +8 -0
  125. package/dist/server/index.js.map +1 -0
  126. package/dist/server/manifest-signer.d.ts +25 -0
  127. package/dist/server/manifest-signer.d.ts.map +1 -0
  128. package/dist/server/manifest-signer.js +51 -0
  129. package/dist/server/manifest-signer.js.map +1 -0
  130. package/dist/server/request-signer.d.ts +31 -0
  131. package/dist/server/request-signer.d.ts.map +1 -0
  132. package/dist/server/request-signer.js +69 -0
  133. package/dist/server/request-signer.js.map +1 -0
  134. package/dist/server/session-relay.d.ts +39 -0
  135. package/dist/server/session-relay.d.ts.map +1 -0
  136. package/dist/server/session-relay.js +74 -0
  137. package/dist/server/session-relay.js.map +1 -0
  138. package/dist/server/webhook.d.ts +11 -0
  139. package/dist/server/webhook.d.ts.map +1 -0
  140. package/dist/server/webhook.js +18 -0
  141. package/dist/server/webhook.js.map +1 -0
  142. package/package.json +6 -1
package/README.md CHANGED
@@ -78,6 +78,15 @@ If you prefer to integrate the SDK into an existing project, follow the steps be
78
78
 
79
79
  ### Install
80
80
 
81
+ If you are evaluating this branch before it lands on `main`, use the prerelease path in the next section. The stable install commands below are the intended post-merge install path.
82
+
83
+ macOS with Homebrew:
84
+
85
+ ```bash
86
+ brew tap vana-com/vana
87
+ brew install vana
88
+ ```
89
+
81
90
  macOS and Linux:
82
91
 
83
92
  ```bash
@@ -92,6 +101,39 @@ iwr https://raw.githubusercontent.com/vana-com/vana-connect/main/install/install
92
101
 
93
102
  Both installers fetch the latest GitHub release asset for your platform, verify its checksum, and install `vana` without requiring Node or npm.
94
103
 
104
+ ### Canary / prerelease testing
105
+
106
+ If you are testing an unreleased branch build, install from the branch installer and pass the prerelease tag explicitly.
107
+
108
+ macOS with Homebrew:
109
+
110
+ ```bash
111
+ brew tap vana-com/vana
112
+ brew install vana
113
+ ```
114
+
115
+ The current Homebrew tap is following the latest `vana-connect` canary while this CLI is still rolling out.
116
+
117
+ macOS and Linux:
118
+
119
+ ```bash
120
+ curl -fsSL https://raw.githubusercontent.com/vana-com/vana-connect/feat/connect-cli-v1/install/install.sh | sh -s -- --version canary-feat-connect-cli-v1
121
+ ```
122
+
123
+ Windows PowerShell:
124
+
125
+ ```powershell
126
+ & ([scriptblock]::Create((iwr https://raw.githubusercontent.com/vana-com/vana-connect/feat/connect-cli-v1/install/install.ps1 -useb).Content)) --version canary-feat-connect-cli-v1
127
+ ```
128
+
129
+ The current hosted prerelease is:
130
+
131
+ `canary-feat-connect-cli-v1`
132
+
133
+ Release page:
134
+
135
+ `https://github.com/vana-com/vana-connect/releases/tag/canary-feat-connect-cli-v1`
136
+
95
137
  If you want the npm package path as a fallback:
96
138
 
97
139
  ```bash
@@ -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/cli/bin.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from "./index.js";
3
+ const exitCode = await runCli(process.argv);
4
+ if (typeof exitCode === "number") {
5
+ process.exitCode = exitCode;
6
+ }
7
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../../src/cli/bin.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC5C,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;IACjC,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runCli(argv?: string[]): Promise<number>;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAmDA,wBAAsB,MAAM,CAAC,IAAI,WAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA2CjE"}
@@ -0,0 +1,612 @@
1
+ import fs from "node:fs";
2
+ import fsp from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { confirm, input, password } from "@inquirer/prompts";
5
+ import { Command } from "commander";
6
+ import { CliOutcomeStatus, getBrowserProfilesDir, getConnectorCacheDir, getLastResultPath, readCliState, updateSourceState, } from "../core/index.js";
7
+ import { listAvailableSources } from "../connectors/registry.js";
8
+ import { detectPersonalServerTarget, ingestResult, } from "../personal-server/index.js";
9
+ import { findDataConnectorsDir, ManagedPlaywrightRuntime, } from "../runtime/index.js";
10
+ export async function runCli(argv = process.argv) {
11
+ const normalizedArgv = normalizeArgv(argv);
12
+ const parsedOptions = extractGlobalOptions(normalizedArgv);
13
+ const program = new Command();
14
+ program.name("vana").description("Vana Connect CLI");
15
+ program
16
+ .command("connect <source>")
17
+ .option("--json", "Output machine-readable JSON")
18
+ .option("--no-input", "Fail instead of prompting for input")
19
+ .option("--yes", "Approve safe setup prompts automatically")
20
+ .option("--quiet", "Reduce non-essential output")
21
+ .action(async (source) => {
22
+ process.exitCode = await runConnect(source, parsedOptions);
23
+ });
24
+ program
25
+ .command("sources")
26
+ .description("List supported sources")
27
+ .option("--json", "Output machine-readable JSON")
28
+ .action(async () => {
29
+ process.exitCode = await runList(parsedOptions);
30
+ });
31
+ program
32
+ .command("status")
33
+ .description("Show runtime and Personal Server status")
34
+ .option("--json", "Output machine-readable JSON")
35
+ .action(async () => {
36
+ process.exitCode = await runStatus(parsedOptions);
37
+ });
38
+ program
39
+ .command("setup")
40
+ .description("Install or repair the local runtime")
41
+ .option("--json", "Output machine-readable JSON")
42
+ .option("--yes", "Approve safe setup prompts automatically")
43
+ .action(async () => {
44
+ process.exitCode = await runSetup(parsedOptions);
45
+ });
46
+ await program.parseAsync(normalizedArgv);
47
+ return Number(process.exitCode ?? 0);
48
+ }
49
+ async function runConnect(source, options) {
50
+ const runtime = new ManagedPlaywrightRuntime();
51
+ const emit = createEmitter(options);
52
+ const registrySources = await loadRegistrySources();
53
+ const sourceLabels = createSourceLabelMap(registrySources);
54
+ let setupLogPath;
55
+ let fetchLogPath;
56
+ let runLogPath;
57
+ try {
58
+ emit.info(`Finding a connector for ${displaySource(source, sourceLabels)}...`);
59
+ const target = await detectPersonalServerTarget();
60
+ if (runtime.state !== "installed") {
61
+ emit.info(`Vana Connect needs a local browser runtime before it can connect ${displaySource(source, sourceLabels)}.`);
62
+ emit.info("");
63
+ emit.info("This will install:");
64
+ emit.info("- the local browser runtime");
65
+ emit.info("- a Chromium browser engine");
66
+ emit.info("- local runtime files under ~/.dataconnect/");
67
+ emit.info("");
68
+ emit.info("Your credentials stay on this machine. Nothing is sent anywhere except the platform you’re connecting to.");
69
+ if (!options.yes) {
70
+ if (options.noInput) {
71
+ emit.event({
72
+ type: "outcome",
73
+ status: CliOutcomeStatus.SETUP_REQUIRED,
74
+ source,
75
+ });
76
+ return 1;
77
+ }
78
+ const shouldContinue = await confirm({
79
+ message: "Continue?",
80
+ default: true,
81
+ });
82
+ if (!shouldContinue) {
83
+ emit.event({
84
+ type: "outcome",
85
+ status: CliOutcomeStatus.SETUP_REQUIRED,
86
+ source,
87
+ reason: "setup_declined",
88
+ });
89
+ return 1;
90
+ }
91
+ }
92
+ const installResult = await runtime.ensureInstalled(Boolean(options.yes));
93
+ setupLogPath = installResult.logPath;
94
+ emit.event({
95
+ type: "setup-complete",
96
+ runtime: installResult.runtime,
97
+ logPath: installResult.logPath,
98
+ });
99
+ emit.info("Runtime ready.");
100
+ if (installResult.logPath) {
101
+ emit.info(`Setup log: ${installResult.logPath}`);
102
+ }
103
+ }
104
+ else {
105
+ emit.event({
106
+ type: "setup-check",
107
+ runtime: runtime.state,
108
+ });
109
+ }
110
+ const fetched = await runtime.fetchConnector(source);
111
+ fetchLogPath = fetched.logPath;
112
+ const sourceDetails = registrySources.find((item) => item.id === source);
113
+ const resolution = {
114
+ source,
115
+ connectorPath: fetched.connectorPath,
116
+ };
117
+ emit.event({
118
+ type: "connector-resolved",
119
+ source: resolution.source,
120
+ connectorPath: resolution.connectorPath,
121
+ logPath: fetched.logPath,
122
+ });
123
+ emit.info("Connector ready.");
124
+ if (sourceDetails?.description) {
125
+ emit.info(sourceDetails.description);
126
+ }
127
+ const profilePath = path.join(getBrowserProfilesDir(), `${path.basename(resolution.connectorPath, path.extname(resolution.connectorPath))}`);
128
+ if (fs.existsSync(profilePath)) {
129
+ emit.info(`Found an existing ${displaySource(source, sourceLabels)} session. Trying that first...`);
130
+ }
131
+ await updateSourceState(resolution.source, {
132
+ connectorInstalled: true,
133
+ sessionPresent: fs.existsSync(profilePath),
134
+ lastError: null,
135
+ });
136
+ emit.info(`Connecting to ${displaySource(source, sourceLabels)}...`);
137
+ emit.info("Collecting your data...");
138
+ let finalStatus = CliOutcomeStatus.UNEXPECTED_INTERNAL_ERROR;
139
+ let resultPath = getLastResultPath();
140
+ let collectedResult = false;
141
+ for await (const event of runtime.runConnector({
142
+ connectorPath: resolution.connectorPath,
143
+ source: resolution.source,
144
+ noInput: options.noInput,
145
+ onNeedInput: async (needInput) => {
146
+ emit.info("");
147
+ emit.info(`To connect ${displaySource(source, sourceLabels)}, Vana Connect will open a local browser session on this machine.`);
148
+ emit.info("Your credentials stay local.");
149
+ emit.info("");
150
+ emit.info(needInput.message ??
151
+ `${displaySource(source, sourceLabels)} needs additional details to continue.`);
152
+ const values = {};
153
+ for (const field of needInput.fields) {
154
+ if (field.toLowerCase().includes("password")) {
155
+ values[field] = await password({ message: humanizeField(field) });
156
+ }
157
+ else {
158
+ values[field] = await input({ message: humanizeField(field) });
159
+ }
160
+ }
161
+ return values;
162
+ },
163
+ })) {
164
+ emit.event(event);
165
+ if (event.logPath) {
166
+ runLogPath = event.logPath;
167
+ }
168
+ if (event.type === "needs-input") {
169
+ await updateSourceState(resolution.source, {
170
+ lastRunAt: new Date().toISOString(),
171
+ lastRunOutcome: CliOutcomeStatus.NEEDS_INPUT,
172
+ lastError: event.message ?? "Input required.",
173
+ });
174
+ emit.event({
175
+ type: "outcome",
176
+ status: CliOutcomeStatus.NEEDS_INPUT,
177
+ source: resolution.source,
178
+ });
179
+ if (!options.json) {
180
+ emit.info(`${displaySource(source, sourceLabels)} needs additional input before it can connect.`);
181
+ emit.info(`Next: run \`vana connect ${source}\` without \`--no-input\`.`);
182
+ }
183
+ return 1;
184
+ }
185
+ if (event.type === "runtime-error") {
186
+ await updateSourceState(resolution.source, {
187
+ lastRunAt: new Date().toISOString(),
188
+ lastRunOutcome: CliOutcomeStatus.RUNTIME_ERROR,
189
+ lastError: event.message ?? "Connector run failed.",
190
+ });
191
+ emit.info(event.message ?? "Connector run failed.");
192
+ emit.event({
193
+ type: "outcome",
194
+ status: CliOutcomeStatus.RUNTIME_ERROR,
195
+ source: resolution.source,
196
+ });
197
+ if (event.logPath) {
198
+ emit.info(`Run log: ${event.logPath}`);
199
+ }
200
+ return 1;
201
+ }
202
+ if (event.type === "headed-required") {
203
+ if (event.message) {
204
+ emit.info(event.message);
205
+ }
206
+ if (event.url) {
207
+ emit.info(`Opening ${displaySource(source, sourceLabels)} in a local browser session...`);
208
+ }
209
+ continue;
210
+ }
211
+ if (event.type === "legacy-auth") {
212
+ await updateSourceState(resolution.source, {
213
+ lastRunAt: new Date().toISOString(),
214
+ lastRunOutcome: CliOutcomeStatus.LEGACY_AUTH,
215
+ lastError: event.message ?? "Legacy authentication is required.",
216
+ dataState: "none",
217
+ });
218
+ emit.info(event.message ??
219
+ "This connector needs a manual browser step that is not available in non-interactive mode.");
220
+ emit.info(`Next: run \`vana connect ${source}\` without \`--no-input\`.`);
221
+ if (event.logPath) {
222
+ emit.info(`Run log: ${event.logPath}`);
223
+ }
224
+ emit.event({
225
+ type: "outcome",
226
+ status: CliOutcomeStatus.LEGACY_AUTH,
227
+ source: resolution.source,
228
+ });
229
+ return 1;
230
+ }
231
+ if (event.type === "collection-complete" && event.resultPath) {
232
+ collectedResult = true;
233
+ resultPath = event.resultPath;
234
+ const ingestEvents = await ingestResult(resolution.source, resultPath, target);
235
+ for (const ingestEvent of ingestEvents) {
236
+ emit.event(ingestEvent);
237
+ }
238
+ const ingestCompleted = ingestEvents.some((ingestEvent) => ingestEvent.type === "ingest-complete");
239
+ finalStatus = ingestCompleted
240
+ ? CliOutcomeStatus.CONNECTED_AND_INGESTED
241
+ : CliOutcomeStatus.CONNECTED_LOCAL_ONLY;
242
+ }
243
+ }
244
+ if (!collectedResult) {
245
+ await updateSourceState(resolution.source, {
246
+ connectorInstalled: true,
247
+ sessionPresent: fs.existsSync(profilePath),
248
+ lastRunAt: new Date().toISOString(),
249
+ lastRunOutcome: CliOutcomeStatus.UNEXPECTED_INTERNAL_ERROR,
250
+ dataState: "none",
251
+ lastError: "Connector run ended without a result.",
252
+ });
253
+ emit.event({
254
+ type: "outcome",
255
+ status: CliOutcomeStatus.UNEXPECTED_INTERNAL_ERROR,
256
+ source: resolution.source,
257
+ reason: "Connector run ended without a result.",
258
+ });
259
+ if (runLogPath) {
260
+ emit.info(`Run log: ${runLogPath}`);
261
+ }
262
+ return 1;
263
+ }
264
+ const dataState = finalStatus === CliOutcomeStatus.CONNECTED_AND_INGESTED
265
+ ? "ingested_personal_server"
266
+ : "collected_local";
267
+ await updateSourceState(resolution.source, {
268
+ connectorInstalled: true,
269
+ sessionPresent: true,
270
+ lastRunAt: new Date().toISOString(),
271
+ lastRunOutcome: finalStatus,
272
+ dataState,
273
+ lastError: null,
274
+ });
275
+ if (finalStatus === CliOutcomeStatus.CONNECTED_AND_INGESTED) {
276
+ emit.info(`Connected ${displaySource(source, sourceLabels)}.`);
277
+ emit.info(`Collected your ${displaySource(source, sourceLabels)} data and synced it to your Personal Server.`);
278
+ }
279
+ else {
280
+ if (target.state !== "available") {
281
+ emit.info(`No Personal Server is available right now, so your ${displaySource(source, sourceLabels)} data was saved locally.`);
282
+ }
283
+ emit.info(`Connected ${displaySource(source, sourceLabels)}.`);
284
+ emit.info(`Collected your ${displaySource(source, sourceLabels)} data and saved it locally.`);
285
+ emit.info(`Local result: ${resultPath}`);
286
+ }
287
+ if (runLogPath) {
288
+ emit.info(`Run log: ${runLogPath}`);
289
+ }
290
+ else if (fetchLogPath) {
291
+ emit.info(`Fetch log: ${fetchLogPath}`);
292
+ }
293
+ else if (setupLogPath) {
294
+ emit.info(`Setup log: ${setupLogPath}`);
295
+ }
296
+ emit.info("Next: run `vana status` to inspect your current connection state.");
297
+ emit.event({
298
+ type: "outcome",
299
+ status: finalStatus,
300
+ source: resolution.source,
301
+ resultPath,
302
+ });
303
+ return 0;
304
+ }
305
+ catch (error) {
306
+ const message = error instanceof Error ? error.message : "Unexpected error.";
307
+ emit.info(message);
308
+ emit.event({
309
+ type: "outcome",
310
+ status: CliOutcomeStatus.UNEXPECTED_INTERNAL_ERROR,
311
+ source,
312
+ reason: message,
313
+ });
314
+ if (runLogPath) {
315
+ emit.info(`Run log: ${runLogPath}`);
316
+ }
317
+ else if (fetchLogPath) {
318
+ emit.info(`Fetch log: ${fetchLogPath}`);
319
+ }
320
+ else if (setupLogPath) {
321
+ emit.info(`Setup log: ${setupLogPath}`);
322
+ }
323
+ return 1;
324
+ }
325
+ }
326
+ async function runList(options) {
327
+ const sources = await loadRegistrySources();
328
+ const installedSourceIds = new Set((await listInstalledConnectorFiles()).map((source) => source.source));
329
+ const enrichedSources = sources.map((source) => ({
330
+ ...source,
331
+ installed: installedSourceIds.has(source.id),
332
+ }));
333
+ if (options.json) {
334
+ process.stdout.write(`${JSON.stringify({ sources: enrichedSources })}\n`);
335
+ return 0;
336
+ }
337
+ const emit = createEmitter(options);
338
+ for (const source of enrichedSources) {
339
+ const description = source.description ? ` - ${source.description}` : "";
340
+ const installed = source.installed ? " [installed]" : "";
341
+ const authMode = formatAuthModeBadge(source.authMode);
342
+ emit.info(`${source.name}${installed}${authMode}${description}`);
343
+ }
344
+ return 0;
345
+ }
346
+ async function runStatus(options) {
347
+ const emit = createEmitter(options);
348
+ const runtime = new ManagedPlaywrightRuntime();
349
+ const personalServer = await detectPersonalServerTarget();
350
+ const state = await readCliState();
351
+ const registrySources = await loadRegistrySources();
352
+ const sourceLabels = createSourceLabelMap(registrySources);
353
+ const sourceMetadata = createSourceMetadataMap(registrySources);
354
+ const sources = await gatherSourceStatuses(state.sources, sourceMetadata);
355
+ const status = {
356
+ runtime: runtime.state,
357
+ runtimePath: runtime.runtimePath,
358
+ personalServer: personalServer.state,
359
+ personalServerUrl: personalServer.url,
360
+ sources,
361
+ };
362
+ if (options.json) {
363
+ process.stdout.write(`${JSON.stringify(status)}\n`);
364
+ return 0;
365
+ }
366
+ emit.info("Vana Connect status");
367
+ emit.info("");
368
+ emit.info(`Runtime: ${status.runtime}`);
369
+ emit.info(`Personal Server: ${status.personalServer}`);
370
+ emit.info("");
371
+ for (const source of status.sources) {
372
+ emit.info(formatSourceStatus(source, sourceLabels));
373
+ const details = formatSourceStatusDetail(source);
374
+ if (details) {
375
+ emit.info(` ${details}`);
376
+ }
377
+ }
378
+ return 0;
379
+ }
380
+ async function runSetup(options) {
381
+ const emit = createEmitter(options);
382
+ const runtime = new ManagedPlaywrightRuntime();
383
+ if (runtime.state === "installed") {
384
+ emit.info("Vana Connect runtime is already installed.");
385
+ emit.event({ type: "setup-check", runtime: runtime.state });
386
+ return 0;
387
+ }
388
+ try {
389
+ const result = await runtime.ensureInstalled(Boolean(options.yes));
390
+ emit.info("Runtime ready.");
391
+ if (result.logPath) {
392
+ emit.info(`Setup log: ${result.logPath}`);
393
+ }
394
+ emit.event({
395
+ type: "setup-complete",
396
+ runtime: result.runtime,
397
+ logPath: result.logPath,
398
+ });
399
+ return 0;
400
+ }
401
+ catch (error) {
402
+ const message = error instanceof Error
403
+ ? error.message
404
+ : "Vana Connect could not finish installing the local runtime.";
405
+ emit.info(message);
406
+ emit.event({
407
+ type: "outcome",
408
+ status: CliOutcomeStatus.RUNTIME_ERROR,
409
+ reason: message,
410
+ });
411
+ return 1;
412
+ }
413
+ }
414
+ function createEmitter(options) {
415
+ return {
416
+ event(event) {
417
+ if (options.json) {
418
+ process.stdout.write(`${JSON.stringify(event)}\n`);
419
+ }
420
+ },
421
+ info(message) {
422
+ if (options.json || options.quiet) {
423
+ return;
424
+ }
425
+ process.stdout.write(`${message}\n`);
426
+ },
427
+ };
428
+ }
429
+ function displaySource(source, labels = {}) {
430
+ return labels[source] ?? source.charAt(0).toUpperCase() + source.slice(1);
431
+ }
432
+ function humanizeField(value) {
433
+ return value
434
+ .replace(/([a-z])([A-Z])/g, "$1 $2")
435
+ .replace(/[_-]/g, " ")
436
+ .replace(/^\w/, (match) => match.toUpperCase());
437
+ }
438
+ async function gatherSourceStatuses(storedSources, metadata = {}) {
439
+ const installedFiles = await listInstalledConnectorFiles();
440
+ const sourceNames = new Set([
441
+ ...Object.keys(storedSources),
442
+ ...installedFiles.map((file) => file.source),
443
+ ]);
444
+ return [...sourceNames]
445
+ .sort((left, right) => left.localeCompare(right))
446
+ .map((source) => {
447
+ const stored = storedSources[source] ?? {};
448
+ const installed = installedFiles.some((file) => file.source === source);
449
+ const details = metadata[source];
450
+ return {
451
+ source,
452
+ name: details?.name,
453
+ company: details?.company,
454
+ description: details?.description,
455
+ authMode: details?.authMode ?? inferInstalledAuthMode(installedFiles, source),
456
+ installed,
457
+ sessionPresent: stored.sessionPresent ?? false,
458
+ lastRunAt: stored.lastRunAt ?? null,
459
+ lastRunOutcome: stored.lastRunOutcome ?? null,
460
+ dataState: stored.dataState === "ingested_personal_server"
461
+ ? "ingested_personal_server"
462
+ : stored.dataState === "collected_local"
463
+ ? "collected_local"
464
+ : "none",
465
+ lastError: stored.lastError ?? null,
466
+ };
467
+ });
468
+ }
469
+ async function listInstalledConnectorFiles() {
470
+ const connectorsDir = getConnectorCacheDir();
471
+ try {
472
+ const results = [];
473
+ const entries = await fsp.readdir(connectorsDir, { withFileTypes: true });
474
+ for (const entry of entries) {
475
+ if (!entry.isDirectory()) {
476
+ continue;
477
+ }
478
+ const companyDir = path.join(connectorsDir, entry.name);
479
+ const files = await fsp.readdir(companyDir);
480
+ for (const file of files) {
481
+ if (!file.endsWith("-playwright.js")) {
482
+ continue;
483
+ }
484
+ results.push({
485
+ source: file.replace(/-playwright\.js$/, ""),
486
+ path: path.join(companyDir, file),
487
+ });
488
+ }
489
+ }
490
+ return results;
491
+ }
492
+ catch {
493
+ return [];
494
+ }
495
+ }
496
+ function formatSourceStatus(source, labels = {}) {
497
+ const authModeSuffix = source.authMode === "legacy"
498
+ ? " [legacy]"
499
+ : source.authMode === "interactive"
500
+ ? " [interactive]"
501
+ : "";
502
+ if (!source.installed) {
503
+ return `${displaySource(source.source, labels)}${authModeSuffix}: not connected`;
504
+ }
505
+ if (!source.lastRunOutcome) {
506
+ return `${displaySource(source.source, labels)}${authModeSuffix}: installed`;
507
+ }
508
+ if (source.lastRunOutcome === CliOutcomeStatus.NEEDS_INPUT) {
509
+ return `${displaySource(source.source, labels)}${authModeSuffix}: needs input`;
510
+ }
511
+ if (source.lastRunOutcome === CliOutcomeStatus.RUNTIME_ERROR) {
512
+ return `${displaySource(source.source, labels)}${authModeSuffix}: error`;
513
+ }
514
+ if (source.lastRunOutcome === CliOutcomeStatus.LEGACY_AUTH) {
515
+ return `${displaySource(source.source, labels)}${authModeSuffix}: manual browser step required`;
516
+ }
517
+ if (source.dataState === "ingested_personal_server") {
518
+ return `${displaySource(source.source, labels)}${authModeSuffix}: connected, synced`;
519
+ }
520
+ if (source.dataState === "collected_local") {
521
+ return `${displaySource(source.source, labels)}${authModeSuffix}: connected, local only`;
522
+ }
523
+ return `${displaySource(source.source, labels)}${authModeSuffix}: connected`;
524
+ }
525
+ function formatSourceStatusDetail(source) {
526
+ if (source.lastRunOutcome === CliOutcomeStatus.NEEDS_INPUT) {
527
+ return source.lastError
528
+ ? `${source.lastError}. Run \`vana connect ${source.source}\` interactively.`
529
+ : `Run \`vana connect ${source.source}\` interactively.`;
530
+ }
531
+ if (source.lastRunOutcome === CliOutcomeStatus.LEGACY_AUTH) {
532
+ return `Run \`vana connect ${source.source}\` without \`--no-input\` to complete the manual browser step.`;
533
+ }
534
+ if (source.lastRunOutcome === CliOutcomeStatus.RUNTIME_ERROR) {
535
+ return source.lastError ?? "The last connector run failed.";
536
+ }
537
+ if (!source.lastRunOutcome && source.installed) {
538
+ return `Run \`vana connect ${source.source}\` to collect data.`;
539
+ }
540
+ return null;
541
+ }
542
+ function normalizeArgv(argv) {
543
+ if (argv[2] === "connect" &&
544
+ ["list", "status", "setup"].includes(argv[3] ?? "")) {
545
+ const mapping = {
546
+ list: "sources",
547
+ status: "status",
548
+ setup: "setup",
549
+ };
550
+ return [argv[0], argv[1], mapping[argv[3]], ...argv.slice(4)];
551
+ }
552
+ return argv;
553
+ }
554
+ function extractGlobalOptions(argv) {
555
+ return {
556
+ json: argv.includes("--json"),
557
+ noInput: argv.includes("--no-input"),
558
+ yes: argv.includes("--yes"),
559
+ quiet: argv.includes("--quiet"),
560
+ };
561
+ }
562
+ function createSourceLabelMap(sources) {
563
+ return Object.fromEntries(sources.map((source) => [source.id, source.name]));
564
+ }
565
+ function createSourceMetadataMap(sources) {
566
+ return Object.fromEntries(sources.map((source) => [
567
+ source.id,
568
+ {
569
+ name: source.name,
570
+ company: source.company,
571
+ description: source.description,
572
+ authMode: source.authMode,
573
+ },
574
+ ]));
575
+ }
576
+ function formatAuthModeBadge(authMode) {
577
+ if (authMode === "legacy") {
578
+ return " [legacy]";
579
+ }
580
+ if (authMode === "interactive") {
581
+ return " [interactive]";
582
+ }
583
+ return "";
584
+ }
585
+ function inferInstalledAuthMode(installedFiles, source) {
586
+ const match = installedFiles.find((file) => file.source === source);
587
+ if (!match) {
588
+ return undefined;
589
+ }
590
+ try {
591
+ const script = fs.readFileSync(match.path, "utf8");
592
+ if (/page\.requestInput\(/.test(script)) {
593
+ return "interactive";
594
+ }
595
+ if (/page\.(showBrowser|promptUser)\(/.test(script)) {
596
+ return "legacy";
597
+ }
598
+ return "automated";
599
+ }
600
+ catch {
601
+ return undefined;
602
+ }
603
+ }
604
+ async function loadRegistrySources() {
605
+ try {
606
+ return ((await listAvailableSources(findDataConnectorsDir() ?? undefined)) ?? []);
607
+ }
608
+ catch {
609
+ return [];
610
+ }
611
+ }
612
+ //# sourceMappingURL=index.js.map