vana-cli 0.23.9 → 0.23.11

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.
package/README.md CHANGED
@@ -304,7 +304,7 @@ Make sure your HTML includes `<link rel="manifest" href="/manifest.json">`.
304
304
  ## Connectors
305
305
 
306
306
  Available data connectors and their scopes (schema definitions):
307
- [`vana-com/data-connectors/schemas`](https://github.com/vana-com/data-connectors/tree/main/schemas)
307
+ [`PDP-Connect/data-connectors/schemas`](https://github.com/PDP-Connect/data-connectors/tree/main/schemas)
308
308
 
309
309
  ## API Reference
310
310
 
@@ -1,3 +1,4 @@
1
+ import type { ConnectRenderer } from "./render/connect-renderer.js";
1
2
  import { readCliState } from "../core/index.js";
2
3
  import type { CliChannel, CliInstallMethod, CliStatus, SourceStatus } from "../core/cli-types.js";
3
4
  import type { AvailableSource } from "../connectors/registry.js";
@@ -14,6 +15,7 @@ interface SourceMetadataMap {
14
15
  }
15
16
  type RenderTone = "accent" | "success" | "warning" | "error" | "muted" | "info";
16
17
  export declare function runCli(argv?: string[]): Promise<number>;
18
+ export declare function withPhaseProgress<T>(renderer: ConnectRenderer | null, label: string, work: () => Promise<T>, delayMs?: number): Promise<T>;
17
19
  export declare function formatUptime(seconds: number): string;
18
20
  export declare function displaySource(source: string, labels?: SourceLabelMap): string;
19
21
  export declare function humanizeIssue(message: string): string;
@@ -88,5 +90,19 @@ export declare function compareDatasetOrder(left: {
88
90
  source: string;
89
91
  }): number;
90
92
  export declare function hasCollectedData(dataState: SourceStatus["dataState"] | null | undefined): boolean;
93
+ export declare class ScheduleTargetUnstableError extends Error {
94
+ }
95
+ /**
96
+ * The argv a scheduler should run, every element an absolute path.
97
+ *
98
+ * launchd, cron and Task Scheduler inherit none of the shell's PATH, so the
99
+ * `vana` on `$PATH` is the wrong answer twice over: under npm it is a shim
100
+ * whose `#!/usr/bin/env node` shebang cannot find a version-managed node,
101
+ * and the scheduler only reports it as `env: node: No such file or
102
+ * directory`. Naming the interpreter and the script outright removes the
103
+ * lookup entirely.
104
+ */
105
+ export declare function resolveScheduledCommand(installMethod?: CliInstallMethod, execPath?: string, entryScript?: string): string[];
106
+ export declare function generateLaunchdPlist(vanaCommand: string[], intervalSeconds: number): string;
91
107
  export {};
92
108
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -753,6 +753,54 @@ async function runTelemetryDisable(options) {
753
753
  emit.success("Telemetry disabled.");
754
754
  return 0;
755
755
  }
756
+ /**
757
+ * How long a phase may stay silent before it gets a spinner.
758
+ *
759
+ * Connect is deliberately quiet when everything is warm, so a line appears
760
+ * only once a phase outlives this. Past it the terminal would otherwise sit
761
+ * blank while the CLI waits on the network, on Chromium, or on a page load.
762
+ */
763
+ const PHASE_PROGRESS_DELAY_MS = 400;
764
+ function startPhaseProgress(renderer, label, delayMs = PHASE_PROGRESS_DELAY_MS) {
765
+ if (!renderer) {
766
+ return { settle() { }, abandon() { } };
767
+ }
768
+ let drawn = false;
769
+ let finished = false;
770
+ const timer = setTimeout(() => {
771
+ drawn = true;
772
+ renderer.scopeActive(label);
773
+ }, delayMs);
774
+ timer.unref?.();
775
+ return {
776
+ settle() {
777
+ if (finished)
778
+ return;
779
+ finished = true;
780
+ clearTimeout(timer);
781
+ if (drawn)
782
+ renderer.scopeDone(label);
783
+ },
784
+ abandon() {
785
+ if (finished)
786
+ return;
787
+ finished = true;
788
+ clearTimeout(timer);
789
+ },
790
+ };
791
+ }
792
+ export async function withPhaseProgress(renderer, label, work, delayMs = PHASE_PROGRESS_DELAY_MS) {
793
+ const progress = startPhaseProgress(renderer, label, delayMs);
794
+ try {
795
+ const result = await work();
796
+ progress.settle();
797
+ return result;
798
+ }
799
+ catch (error) {
800
+ progress.abandon();
801
+ throw error;
802
+ }
803
+ }
756
804
  async function runConnect(rawSource, options) {
757
805
  const source = rawSource.toLowerCase();
758
806
  const runtime = new ManagedPlaywrightRuntime();
@@ -768,7 +816,7 @@ async function runConnect(rawSource, options) {
768
816
  try {
769
817
  // Title
770
818
  renderer?.title(displayName);
771
- const target = await detectPersonalServerTarget();
819
+ const target = await withPhaseProgress(renderer, "Finding your Personal Server", () => detectPersonalServerTarget());
772
820
  // --- Phase 1: Runtime check (silent if installed) ---
773
821
  if (runtime.state !== "installed") {
774
822
  if (options.noInput) {
@@ -809,7 +857,7 @@ async function runConnect(rawSource, options) {
809
857
  trackActiveTelemetryEvent("runtime_install_started", { source });
810
858
  let installResult;
811
859
  try {
812
- installResult = await runtime.ensureInstalled(Boolean(options.yes));
860
+ installResult = await withPhaseProgress(renderer, "Installing browser engine (one time, ~150MB)", () => runtime.ensureInstalled(Boolean(options.yes)));
813
861
  }
814
862
  catch (error) {
815
863
  trackActiveTelemetryEvent("runtime_install_failed", {
@@ -824,7 +872,6 @@ async function runConnect(rawSource, options) {
824
872
  runtime: installResult.runtime,
825
873
  logPath: installResult.logPath,
826
874
  });
827
- renderer?.scopeDone("Runtime ready");
828
875
  }
829
876
  else {
830
877
  emit.event({
@@ -837,7 +884,7 @@ async function runConnect(rawSource, options) {
837
884
  const currentVersion = preState.sources[source]?.connectorVersion;
838
885
  let fetched;
839
886
  try {
840
- fetched = await runtime.fetchConnector(source, currentVersion);
887
+ fetched = await withPhaseProgress(renderer, `Getting the ${displayName} connector`, () => runtime.fetchConnector(source, currentVersion));
841
888
  }
842
889
  catch (firstError) {
843
890
  const firstMessage = firstError instanceof Error ? firstError.message : "";
@@ -850,7 +897,7 @@ async function runConnect(rawSource, options) {
850
897
  const cacheDir = getConnectorCacheDir();
851
898
  const sourceCacheDir = path.join(cacheDir, source);
852
899
  await fsp.rm(sourceCacheDir, { recursive: true, force: true });
853
- const resolution = await fetchConnectorToCache(source, cacheDir, undefined);
900
+ const resolution = await withPhaseProgress(renderer, "Cached connector looks stale, downloading a fresh one", () => fetchConnectorToCache(source, cacheDir, undefined));
854
901
  fetched = {
855
902
  connectorPath: resolution.connectorPath,
856
903
  logPath: "",
@@ -870,7 +917,8 @@ async function runConnect(rawSource, options) {
870
917
  lastLogPath: getErrorLogPath(retryError),
871
918
  });
872
919
  renderer?.fail(`${displayName} connector could not be verified.`);
873
- renderer?.detail(`Try again later, or report: https://github.com/vana-com/data-connectors/issues`);
920
+ renderer?.detail(message);
921
+ renderer?.detail(`Try again later, or report: https://github.com/PDP-Connect/data-connectors/issues`);
874
922
  emit.event({
875
923
  type: "outcome",
876
924
  status: CliOutcomeStatus.CONNECTOR_UNAVAILABLE,
@@ -967,12 +1015,17 @@ async function runConnect(rawSource, options) {
967
1015
  let collectedResult = false;
968
1016
  let blockedByRequiredInput = false;
969
1017
  let ingestScopeResults;
1018
+ // Chromium start-up and the first page load happen before a connector
1019
+ // reports anything, which is the longest silent stretch of a warm run.
1020
+ const launchProgress = startPhaseProgress(renderer, `Opening ${displayName} in a browser`);
970
1021
  // In IPC mode (--ipc), don’t provide an interactive callback.
971
1022
  // The runtime will write a pending-input file and poll for the
972
1023
  // response, letting an external agent handle credential collection.
973
1024
  const interactiveCallback = options.ipc
974
1025
  ? undefined
975
1026
  : async (needInput) => {
1027
+ // Settle first: a spinner repaint would overwrite the prompt.
1028
+ launchProgress.settle();
976
1029
  renderer?.pauseForPrompt();
977
1030
  // Show connector’s prompt message
978
1031
  if (renderer) {
@@ -1019,6 +1072,10 @@ async function runConnect(rawSource, options) {
1019
1072
  if (event.logPath) {
1020
1073
  runLogPath = event.logPath;
1021
1074
  }
1075
+ // status-update draws nothing, so it is not proof the browser is up.
1076
+ if (event.type !== "status-update") {
1077
+ launchProgress.settle();
1078
+ }
1022
1079
  if (pendingExitCode !== null && event.type !== "collection-complete") {
1023
1080
  continue;
1024
1081
  }
@@ -1157,7 +1214,7 @@ async function runConnect(rawSource, options) {
1157
1214
  }
1158
1215
  collectedResult = true;
1159
1216
  resultPath = event.resultPath;
1160
- const ingestEvents = await ingestResult(resolution.source, resultPath, target);
1217
+ const ingestEvents = await withPhaseProgress(renderer, "Saving to your Personal Server", () => ingestResult(resolution.source, resultPath, target));
1161
1218
  for (const ingestEvent of ingestEvents) {
1162
1219
  emit.event(ingestEvent);
1163
1220
  }
@@ -1200,6 +1257,7 @@ async function runConnect(rawSource, options) {
1200
1257
  }));
1201
1258
  }
1202
1259
  }
1260
+ launchProgress.settle();
1203
1261
  if (pendingExitCode !== null && !collectedResult) {
1204
1262
  return pendingExitCode;
1205
1263
  }
@@ -1266,8 +1324,7 @@ async function runConnect(rawSource, options) {
1266
1324
  else {
1267
1325
  successSummary = `Collected your ${displayName} data and saved it locally.`;
1268
1326
  }
1269
- // Auto-schedule collection if no schedule exists (non-blocking)
1270
- await maybeAutoSchedule(emit, options).catch(() => { });
1327
+ const hasSchedule = (await getExistingScheduleInterval().catch(() => null)) !== null;
1271
1328
  // --- Phase 7: Success summary ---
1272
1329
  renderer?.success(`Connected ${displayName}.`);
1273
1330
  renderer?.detail(successSummary);
@@ -1297,6 +1354,9 @@ async function runConnect(rawSource, options) {
1297
1354
  else {
1298
1355
  renderer?.next(`vana data show ${source}`);
1299
1356
  }
1357
+ if (!hasSchedule) {
1358
+ renderer?.detail("Keep this fresh automatically — run `vana schedule add` to collect on a schedule.");
1359
+ }
1300
1360
  // Suggest skills if not yet installed
1301
1361
  const installedSkills = await readInstalledSkills();
1302
1362
  if (installedSkills.length === 0) {
@@ -4087,6 +4147,15 @@ const LAUNCHD_LABEL = "com.vana.collect";
4087
4147
  const LAUNCHD_PLIST_PATH = path.join(os.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
4088
4148
  const CRONTAB_MARKER = "# vana-scheduled-collection";
4089
4149
  const WINDOWS_TASK_NAME = "VanaScheduledCollection";
4150
+ function escapeXml(value) {
4151
+ return value
4152
+ .replace(/&/g, "&amp;")
4153
+ .replace(/</g, "&lt;")
4154
+ .replace(/>/g, "&gt;");
4155
+ }
4156
+ function quoteForShell(value) {
4157
+ return `'${value.replace(/'/g, `'\\''`)}'`;
4158
+ }
4090
4159
  function parseIntervalSeconds(interval) {
4091
4160
  const lower = interval.toLowerCase().trim();
4092
4161
  const match = /^(\d+)\s*(h|d|m|w)$/i.exec(lower);
@@ -4116,23 +4185,32 @@ function formatIntervalHuman(seconds) {
4116
4185
  return `${Math.round(seconds / 3600)}h`;
4117
4186
  return `${Math.round(seconds / 86400)}d`;
4118
4187
  }
4119
- function resolveVanaBinaryPath() {
4120
- // For SEA binaries, process.execPath is the binary itself
4121
- const installMethod = getCliInstallMethod();
4188
+ export class ScheduleTargetUnstableError extends Error {
4189
+ }
4190
+ /**
4191
+ * The argv a scheduler should run, every element an absolute path.
4192
+ *
4193
+ * launchd, cron and Task Scheduler inherit none of the shell's PATH, so the
4194
+ * `vana` on `$PATH` is the wrong answer twice over: under npm it is a shim
4195
+ * whose `#!/usr/bin/env node` shebang cannot find a version-managed node,
4196
+ * and the scheduler only reports it as `env: node: No such file or
4197
+ * directory`. Naming the interpreter and the script outright removes the
4198
+ * lookup entirely.
4199
+ */
4200
+ export function resolveScheduledCommand(installMethod = getCliInstallMethod(), execPath = process.execPath, entryScript = process.argv[1]) {
4201
+ // A SEA binary is its own interpreter; there is no script to pass.
4122
4202
  if (installMethod === "homebrew" || installMethod === "installer") {
4123
- return process.execPath;
4203
+ return [execPath];
4124
4204
  }
4125
- // For development, try to find the vana binary via which/where
4126
- try {
4127
- const cmd = process.platform === "win32" ? "where vana" : "which vana";
4128
- const result = execSync(cmd, { encoding: "utf8" }).trim();
4129
- // `where` on Windows may return multiple lines; take the first
4130
- return result.split("\n")[0].trim();
4205
+ if (!entryScript || !path.isAbsolute(entryScript)) {
4206
+ throw new ScheduleTargetUnstableError("Could not work out which file to schedule.");
4131
4207
  }
4132
- catch {
4133
- // Fall back to process.execPath + argv[1]
4134
- return `${process.execPath} ${process.argv[1]}`;
4208
+ // npx unpacks into a cache npm is free to evict, so a schedule pointing
4209
+ // there works until it silently does not.
4210
+ if (normalizePathForMatch(entryScript).includes("/_npx/")) {
4211
+ throw new ScheduleTargetUnstableError("This CLI is running from an npx cache, which npm may delete at any time.");
4135
4212
  }
4213
+ return [execPath, entryScript];
4136
4214
  }
4137
4215
  async function getExistingScheduleInterval() {
4138
4216
  if (process.platform === "darwin") {
@@ -4179,28 +4257,11 @@ async function getExistingScheduleInterval() {
4179
4257
  }
4180
4258
  return null;
4181
4259
  }
4182
- async function maybeAutoSchedule(emit, options) {
4183
- // Skip if --no-input (detached/agent context shouldn't create schedules)
4184
- if (options.noInput)
4185
- return;
4186
- // Skip unsupported platforms
4187
- if (!["darwin", "linux", "win32"].includes(process.platform))
4188
- return;
4189
- const existing = await getExistingScheduleInterval();
4190
- if (existing !== null)
4191
- return; // Schedule already exists
4192
- await runScheduleAdd("daily", { json: false, quiet: true });
4193
- emit.detail("Auto-scheduled daily collection.");
4194
- }
4195
- function generateLaunchdPlist(vanaBinary, intervalSeconds) {
4260
+ export function generateLaunchdPlist(vanaCommand, intervalSeconds) {
4196
4261
  const logsPath = path.join(getLogsDir(), "schedule.log");
4197
- // Handle the case where vanaBinary might contain a space (node + script)
4198
- const programArgs = vanaBinary.includes(" ")
4199
- ? vanaBinary
4200
- .split(" ")
4201
- .map((arg) => ` <string>${arg}</string>`)
4202
- .join("\n")
4203
- : ` <string>${vanaBinary}</string>`;
4262
+ const programArgs = vanaCommand
4263
+ .map((arg) => ` <string>${escapeXml(arg)}</string>`)
4264
+ .join("\n");
4204
4265
  return `<?xml version="1.0" encoding="UTF-8"?>
4205
4266
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4206
4267
  <plist version="1.0">
@@ -4218,31 +4279,43 @@ ${programArgs}
4218
4279
  <key>StartInterval</key>
4219
4280
  <integer>${intervalSeconds}</integer>
4220
4281
  <key>StandardOutPath</key>
4221
- <string>${logsPath}</string>
4282
+ <string>${escapeXml(logsPath)}</string>
4222
4283
  <key>StandardErrorPath</key>
4223
- <string>${logsPath}</string>
4284
+ <string>${escapeXml(logsPath)}</string>
4224
4285
  <key>RunAtLoad</key>
4225
4286
  <true/>
4226
4287
  </dict>
4227
4288
  </plist>
4228
4289
  `;
4229
4290
  }
4230
- function generateCrontabEntry(vanaBinary, intervalHours) {
4291
+ function generateCrontabEntry(vanaCommand, intervalHours) {
4231
4292
  const logsPath = path.join(getLogsDir(), "schedule.log");
4232
4293
  const hourExpr = intervalHours >= 24 ? "0" : `0`;
4233
4294
  const dayExpr = "*";
4234
4295
  const hourInterval = intervalHours >= 24 ? "0" : intervalHours >= 1 ? `*/${intervalHours}` : "*";
4235
- return `${hourExpr} ${hourInterval} ${dayExpr} * * ${vanaBinary} collect --all --quiet --no-input >> ${logsPath} 2>&1 ${CRONTAB_MARKER}`;
4296
+ const program = vanaCommand.map((arg) => quoteForShell(arg)).join(" ");
4297
+ return `${hourExpr} ${hourInterval} ${dayExpr} * * ${program} collect --all --quiet --no-input >> ${quoteForShell(logsPath)} 2>&1 ${CRONTAB_MARKER}`;
4236
4298
  }
4237
4299
  async function runScheduleAdd(interval, options) {
4238
4300
  const emit = createEmitter(options);
4239
4301
  const intervalSeconds = parseIntervalSeconds(interval);
4240
4302
  const intervalLabel = formatIntervalHuman(intervalSeconds);
4241
- const vanaBinary = resolveVanaBinaryPath();
4303
+ let vanaCommand;
4304
+ try {
4305
+ vanaCommand = resolveScheduledCommand();
4306
+ }
4307
+ catch (error) {
4308
+ if (!(error instanceof ScheduleTargetUnstableError)) {
4309
+ throw error;
4310
+ }
4311
+ emit.info(`Cannot schedule collection. ${error.message}`);
4312
+ emit.detail("Install the CLI first (`npm install -g vana-cli`), then run `vana schedule add` from that install.");
4313
+ return 1;
4314
+ }
4242
4315
  await fsp.mkdir(getLogsDir(), { recursive: true });
4243
4316
  if (process.platform === "darwin") {
4244
4317
  // macOS: launchd
4245
- const plist = generateLaunchdPlist(vanaBinary, intervalSeconds);
4318
+ const plist = generateLaunchdPlist(vanaCommand, intervalSeconds);
4246
4319
  const plistDir = path.dirname(LAUNCHD_PLIST_PATH);
4247
4320
  await fsp.mkdir(plistDir, { recursive: true });
4248
4321
  // Unload existing if present
@@ -4279,7 +4352,7 @@ async function runScheduleAdd(interval, options) {
4279
4352
  // Linux: cron doesn't defer missed jobs (unlike launchd), so we run
4280
4353
  // hourly and let isCollectionDue() filter per-source. This way a
4281
4354
  // missed 2am tick self-heals at 3am instead of waiting 24h.
4282
- const entry = generateCrontabEntry(vanaBinary, 1);
4355
+ const entry = generateCrontabEntry(vanaCommand, 1);
4283
4356
  try {
4284
4357
  // Read existing crontab, filter out old vana entries, add new one
4285
4358
  let existing = "";
@@ -4321,7 +4394,7 @@ async function runScheduleAdd(interval, options) {
4321
4394
  if (process.platform === "win32") {
4322
4395
  // Windows: Task Scheduler
4323
4396
  const intervalMinutes = Math.max(1, Math.round(intervalSeconds / 60));
4324
- const trCmd = `\\"${vanaBinary}\\" collect --all --quiet --no-input`;
4397
+ const trCmd = `${vanaCommand.map((arg) => `\\"${arg}\\"`).join(" ")} collect --all --quiet --no-input`;
4325
4398
  try {
4326
4399
  try {
4327
4400
  execSync(`schtasks /Delete /TN "${WINDOWS_TASK_NAME}" /F 2>nul`, {