@opendatalabs/connect 0.9.2 → 0.9.4
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/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +129 -58
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/update-check.d.ts +3 -3
- package/dist/cli/update-check.d.ts.map +1 -1
- package/dist/cli/update-check.js +43 -11
- package/dist/cli/update-check.js.map +1 -1
- package/dist/core/cli-types.d.ts +27 -0
- package/dist/core/cli-types.d.ts.map +1 -1
- package/dist/core/cli-types.js +6 -0
- package/dist/core/cli-types.js.map +1 -1
- package/dist/core/state-store.d.ts +3 -0
- package/dist/core/state-store.d.ts.map +1 -1
- package/dist/core/state-store.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/update-check-worker.d.ts +0 -2
- package/dist/cli/update-check-worker.d.ts.map +0 -1
- package/dist/cli/update-check-worker.js +0 -55
- package/dist/cli/update-check-worker.js.map +0 -1
package/dist/cli/index.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export declare function buildDataListNextSteps(datasetRecords: Array<{
|
|
|
40
40
|
authMode?: "automated" | "interactive" | "legacy";
|
|
41
41
|
}>): string[];
|
|
42
42
|
export declare function buildDataShowNextSteps(source: string, datasetCount: number, sourceLabels?: SourceLabelMap): string[];
|
|
43
|
+
/** Derive a human-readable message from a stored `connectionHealthReason`. */
|
|
44
|
+
export declare function formatHealthMessage(reason: string | undefined): string | null;
|
|
43
45
|
export declare function getCliVersion(): string;
|
|
44
46
|
export declare function getCliChannel(version?: string): "stable" | "canary";
|
|
45
47
|
export declare function getCliInstallMethod(execPath?: string): CliInstallMethod;
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAuCA,OAAO,EAQL,YAAY,EAIb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EACV,UAAU,EAEV,gBAAgB,EAEhB,SAAS,EACT,YAAY,EACb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAyCjE,UAAU,cAAc;IACtB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAED,UAAU,iBAAiB;IACzB,CAAC,MAAM,EAAE,MAAM,GAAG;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,WAAW,GAAG,aAAa,GAAG,QAAQ,CAAC;KACnD,CAAC;CACH;AA2BD,KAAK,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AAehF,wBAAsB,MAAM,CAAC,IAAI,WAAe,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
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
|
@@ -33,7 +33,7 @@ import { detectPersonalServerTarget, ingestResult, } from "../personal-server/in
|
|
|
33
33
|
import { findDataConnectorsDir, ManagedPlaywrightRuntime, } from "../runtime/index.js";
|
|
34
34
|
import { listAvailableSkills, installSkill, readInstalledSkills, } from "../skills/index.js";
|
|
35
35
|
import { queryStatus, querySources, queryDataList, queryDataShow, queryDoctor, } from "./queries.js";
|
|
36
|
-
import { readUpdateCheck, isNewerVersion,
|
|
36
|
+
import { checkForUpdate, readUpdateCheck, isNewerVersion, } from "./update-check.js";
|
|
37
37
|
function cleanDescription(desc) {
|
|
38
38
|
return desc
|
|
39
39
|
.replace(/ using Playwright browser automation\.?/i, ".")
|
|
@@ -51,6 +51,7 @@ export async function runCli(argv = process.argv) {
|
|
|
51
51
|
}
|
|
52
52
|
const parsedOptions = extractGlobalOptions(normalizedArgv);
|
|
53
53
|
const cliVersion = getCliVersion();
|
|
54
|
+
const installMethod = getCliInstallMethod();
|
|
54
55
|
// Non-blocking update check — compute suppression flags early
|
|
55
56
|
const shouldNotify = !parsedOptions.json &&
|
|
56
57
|
process.stdout.isTTY &&
|
|
@@ -58,23 +59,12 @@ export async function runCli(argv = process.argv) {
|
|
|
58
59
|
!process.env.CI &&
|
|
59
60
|
!process.env.AGENT &&
|
|
60
61
|
!process.env.VANA_DETACHED;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
updateNotice = `\nUpdate available: ${cliVersion} → ${cached.latestVersion}\nRun: ${lifecycle.upgrade}\n`;
|
|
68
|
-
}
|
|
69
|
-
else if (!cached) {
|
|
70
|
-
// Cache missing or expired — spawn background check
|
|
71
|
-
spawnUpdateCheck(cliVersion, getCliInstallMethod());
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
// Suppress all errors — update check is purely informational
|
|
76
|
-
}
|
|
77
|
-
}
|
|
62
|
+
// Fire update check concurrently — no await, runs in the background.
|
|
63
|
+
// If it finishes before the command completes, the cache is written and
|
|
64
|
+
// the SAME run can read it for the notification below.
|
|
65
|
+
const updateCheckPromise = shouldNotify
|
|
66
|
+
? checkForUpdate(cliVersion, installMethod).catch(() => { })
|
|
67
|
+
: undefined;
|
|
78
68
|
const program = new Command();
|
|
79
69
|
program
|
|
80
70
|
.name("vana")
|
|
@@ -415,29 +405,38 @@ Examples:
|
|
|
415
405
|
process.exitCode = await runScheduleRemove(parsedOptions);
|
|
416
406
|
});
|
|
417
407
|
try {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
if (error
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
error.code === "commander.version") {
|
|
426
|
-
process.exitCode = error.exitCode;
|
|
427
|
-
return Number(process.exitCode ?? 0);
|
|
428
|
-
}
|
|
429
|
-
// Commander already printed to stderr; just set exit code.
|
|
408
|
+
await program.parseAsync(normalizedArgv);
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
if (error instanceof CommanderError) {
|
|
412
|
+
if (error.code === "commander.help" ||
|
|
413
|
+
error.code === "commander.helpDisplayed" ||
|
|
414
|
+
error.code === "commander.version") {
|
|
430
415
|
process.exitCode = error.exitCode;
|
|
431
|
-
return Number(process.exitCode ??
|
|
416
|
+
return Number(process.exitCode ?? 0);
|
|
432
417
|
}
|
|
433
|
-
|
|
418
|
+
// Commander already printed to stderr; just set exit code.
|
|
419
|
+
process.exitCode = error.exitCode;
|
|
420
|
+
return Number(process.exitCode ?? 1);
|
|
434
421
|
}
|
|
435
|
-
|
|
422
|
+
throw error;
|
|
436
423
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
424
|
+
// Show update notification if a newer version is available.
|
|
425
|
+
// The concurrent check may have populated the cache during this run.
|
|
426
|
+
if (shouldNotify) {
|
|
427
|
+
try {
|
|
428
|
+
await updateCheckPromise;
|
|
429
|
+
const cache = await readUpdateCheck();
|
|
430
|
+
if (cache && isNewerVersion(cliVersion, cache.latestVersion)) {
|
|
431
|
+
const { upgrade } = getLifecycleCommands(installMethod, getCliChannel(cliVersion));
|
|
432
|
+
process.stderr.write(`\nUpdate available: ${cliVersion} → ${cache.latestVersion}\nRun: ${upgrade}\n`);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
// Never block exit for update notification failures
|
|
437
|
+
}
|
|
440
438
|
}
|
|
439
|
+
return Number(process.exitCode ?? 0);
|
|
441
440
|
}
|
|
442
441
|
async function runConnect(rawSource, options) {
|
|
443
442
|
const source = rawSource.toLowerCase();
|
|
@@ -450,7 +449,7 @@ async function runConnect(rawSource, options) {
|
|
|
450
449
|
let setupLogPath;
|
|
451
450
|
let fetchLogPath;
|
|
452
451
|
let runLogPath;
|
|
453
|
-
let
|
|
452
|
+
let pendingExitCode = null;
|
|
454
453
|
try {
|
|
455
454
|
// Title
|
|
456
455
|
renderer?.title(displayName);
|
|
@@ -688,7 +687,7 @@ async function runConnect(rawSource, options) {
|
|
|
688
687
|
if (event.logPath) {
|
|
689
688
|
runLogPath = event.logPath;
|
|
690
689
|
}
|
|
691
|
-
if (
|
|
690
|
+
if (pendingExitCode !== null && event.type !== "collection-complete") {
|
|
692
691
|
continue;
|
|
693
692
|
}
|
|
694
693
|
if (event.type === "needs-input") {
|
|
@@ -698,6 +697,9 @@ async function runConnect(rawSource, options) {
|
|
|
698
697
|
lastError: event.message ?? "Input required.",
|
|
699
698
|
lastLogPath: event.logPath,
|
|
700
699
|
connectionHealth: "needs_reauth",
|
|
700
|
+
connectionHealthChangedAt: new Date().toISOString(),
|
|
701
|
+
connectionHealthReason: `needs-input: ${event.message ?? "Input required."}`,
|
|
702
|
+
connectionHealthRetryable: false,
|
|
701
703
|
});
|
|
702
704
|
emit.event({
|
|
703
705
|
type: "outcome",
|
|
@@ -705,8 +707,7 @@ async function runConnect(rawSource, options) {
|
|
|
705
707
|
source: resolution.source,
|
|
706
708
|
});
|
|
707
709
|
renderer?.fail(`${displayName} needs credentials. Run without --no-input to authenticate.`);
|
|
708
|
-
|
|
709
|
-
continue;
|
|
710
|
+
pendingExitCode = 1;
|
|
710
711
|
}
|
|
711
712
|
if (event.type === "progress-update") {
|
|
712
713
|
// Drive the renderer with scope information from the event
|
|
@@ -735,6 +736,9 @@ async function runConnect(rawSource, options) {
|
|
|
735
736
|
lastError: event.message ?? "Connector run failed.",
|
|
736
737
|
lastLogPath: event.logPath,
|
|
737
738
|
connectionHealth: "error",
|
|
739
|
+
connectionHealthChangedAt: new Date().toISOString(),
|
|
740
|
+
connectionHealthReason: `runtime-error: ${event.message ?? "Connector run failed."}`,
|
|
741
|
+
connectionHealthRetryable: /timeout|ECONNREFUSED|ENOTFOUND|rate.?limit|50[234]|socket hang up/i.test(event.message ?? ""),
|
|
738
742
|
});
|
|
739
743
|
renderer?.fail(`Problem connecting ${displayName}.`);
|
|
740
744
|
renderer?.detail(event.message ?? "Connector run failed.");
|
|
@@ -744,7 +748,7 @@ async function runConnect(rawSource, options) {
|
|
|
744
748
|
status: CliOutcomeStatus.RUNTIME_ERROR,
|
|
745
749
|
source: resolution.source,
|
|
746
750
|
});
|
|
747
|
-
|
|
751
|
+
pendingExitCode = 1;
|
|
748
752
|
continue;
|
|
749
753
|
}
|
|
750
754
|
if (event.type === "headed-required") {
|
|
@@ -760,6 +764,9 @@ async function runConnect(rawSource, options) {
|
|
|
760
764
|
lastResultPath: null,
|
|
761
765
|
lastLogPath: event.logPath,
|
|
762
766
|
connectionHealth: "needs_reauth",
|
|
767
|
+
connectionHealthChangedAt: new Date().toISOString(),
|
|
768
|
+
connectionHealthReason: `legacy-auth: ${event.message ?? "Legacy authentication is required."}`,
|
|
769
|
+
connectionHealthRetryable: false,
|
|
763
770
|
});
|
|
764
771
|
renderer?.fail(`Manual step required for ${displayName}.`);
|
|
765
772
|
renderer?.detail(`Complete the browser step locally, then rerun vana connect ${source}.`);
|
|
@@ -768,8 +775,7 @@ async function runConnect(rawSource, options) {
|
|
|
768
775
|
status: CliOutcomeStatus.LEGACY_AUTH,
|
|
769
776
|
source: resolution.source,
|
|
770
777
|
});
|
|
771
|
-
|
|
772
|
-
continue;
|
|
778
|
+
pendingExitCode = 1;
|
|
773
779
|
}
|
|
774
780
|
if (event.type === "collection-complete" && event.resultPath) {
|
|
775
781
|
// Check if the result is actually an error object
|
|
@@ -781,13 +787,17 @@ async function runConnect(rawSource, options) {
|
|
|
781
787
|
"error" in parsed &&
|
|
782
788
|
Object.keys(parsed).length <= 2) {
|
|
783
789
|
// Connector returned an error, not real data
|
|
790
|
+
const errorMsg = typeof parsed.error === "string"
|
|
791
|
+
? parsed.error
|
|
792
|
+
: "Collection returned an error";
|
|
784
793
|
await updateSourceState(source, {
|
|
785
794
|
lastRunAt: new Date().toISOString(),
|
|
786
795
|
lastRunOutcome: CliOutcomeStatus.RUNTIME_ERROR,
|
|
787
796
|
connectionHealth: "error",
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
797
|
+
connectionHealthChangedAt: new Date().toISOString(),
|
|
798
|
+
connectionHealthReason: `error-result: ${errorMsg}`,
|
|
799
|
+
connectionHealthRetryable: false,
|
|
800
|
+
lastError: errorMsg,
|
|
791
801
|
lastLogPath: runLogPath ?? fetchLogPath,
|
|
792
802
|
});
|
|
793
803
|
renderer?.fail(`Problem connecting ${displayName}.`);
|
|
@@ -799,12 +809,15 @@ async function runConnect(rawSource, options) {
|
|
|
799
809
|
status: CliOutcomeStatus.RUNTIME_ERROR,
|
|
800
810
|
source,
|
|
801
811
|
});
|
|
802
|
-
|
|
812
|
+
pendingExitCode = 1;
|
|
803
813
|
continue;
|
|
804
814
|
}
|
|
805
815
|
}
|
|
806
|
-
catch {
|
|
807
|
-
|
|
816
|
+
catch (parseError) {
|
|
817
|
+
const msg = parseError instanceof Error ? parseError.message : "Unknown error";
|
|
818
|
+
await updateSourceState(source, {
|
|
819
|
+
lastError: `Failed to parse result file (${event.resultPath}): ${msg}`,
|
|
820
|
+
});
|
|
808
821
|
}
|
|
809
822
|
collectedResult = true;
|
|
810
823
|
resultPath = event.resultPath;
|
|
@@ -845,8 +858,8 @@ async function runConnect(rawSource, options) {
|
|
|
845
858
|
}));
|
|
846
859
|
}
|
|
847
860
|
}
|
|
848
|
-
if (
|
|
849
|
-
return
|
|
861
|
+
if (pendingExitCode !== null && !collectedResult) {
|
|
862
|
+
return pendingExitCode;
|
|
850
863
|
}
|
|
851
864
|
if (!collectedResult) {
|
|
852
865
|
await updateSourceState(resolution.source, {
|
|
@@ -881,7 +894,10 @@ async function runConnect(rawSource, options) {
|
|
|
881
894
|
lastError: ingestFailureMessage,
|
|
882
895
|
lastResultPath: resultPath,
|
|
883
896
|
lastLogPath: runLogPath ?? fetchLogPath ?? setupLogPath ?? null,
|
|
884
|
-
connectionHealth: "healthy",
|
|
897
|
+
connectionHealth: pendingExitCode !== null ? undefined : "healthy",
|
|
898
|
+
connectionHealthChangedAt: pendingExitCode !== null ? undefined : new Date().toISOString(),
|
|
899
|
+
connectionHealthReason: pendingExitCode !== null ? undefined : "collection-complete",
|
|
900
|
+
connectionHealthRetryable: undefined,
|
|
885
901
|
ingestScopes: ingestScopeResults,
|
|
886
902
|
});
|
|
887
903
|
// Build scope-aware success summary
|
|
@@ -904,6 +920,8 @@ async function runConnect(rawSource, options) {
|
|
|
904
920
|
else {
|
|
905
921
|
successSummary = `Collected your ${displayName} data and saved it locally.`;
|
|
906
922
|
}
|
|
923
|
+
// Auto-schedule collection if no schedule exists (non-blocking)
|
|
924
|
+
await maybeAutoSchedule(emit, options).catch(() => { });
|
|
907
925
|
// --- Phase 7: Success summary ---
|
|
908
926
|
renderer?.success(`Connected ${displayName}.`);
|
|
909
927
|
renderer?.detail(successSummary);
|
|
@@ -941,9 +959,9 @@ async function runConnect(rawSource, options) {
|
|
|
941
959
|
source: resolution.source,
|
|
942
960
|
resultPath,
|
|
943
961
|
});
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
962
|
+
if (pendingExitCode !== null) {
|
|
963
|
+
return pendingExitCode;
|
|
964
|
+
}
|
|
947
965
|
return 0;
|
|
948
966
|
}
|
|
949
967
|
catch (error) {
|
|
@@ -1120,7 +1138,12 @@ async function runStatus(options) {
|
|
|
1120
1138
|
if (stored) {
|
|
1121
1139
|
sourceHealthMap[sourceId] = {
|
|
1122
1140
|
connectionHealth: stored.connectionHealth,
|
|
1141
|
+
connectionHealthChangedAt: stored.connectionHealthChangedAt,
|
|
1142
|
+
connectionHealthReason: stored.connectionHealthReason,
|
|
1143
|
+
connectionHealthRetryable: stored.connectionHealthRetryable,
|
|
1123
1144
|
lastCollectedAt: stored.lastCollectedAt,
|
|
1145
|
+
lastLogPath: stored.lastLogPath,
|
|
1146
|
+
lastError: stored.lastError,
|
|
1124
1147
|
};
|
|
1125
1148
|
}
|
|
1126
1149
|
}
|
|
@@ -1187,6 +1210,16 @@ async function runStatus(options) {
|
|
|
1187
1210
|
? `collected ${formatRelativeTime(stored.lastCollectedAt)}`
|
|
1188
1211
|
: "";
|
|
1189
1212
|
emit.keyValue(` ${displayName}`, `${healthLabel}${staleTag} ${collectedAgo}`, healthTone);
|
|
1213
|
+
if ((health === "needs_reauth" || health === "error") &&
|
|
1214
|
+
stored?.connectionHealthReason) {
|
|
1215
|
+
const msg = formatHealthMessage(stored.connectionHealthReason);
|
|
1216
|
+
const ago = stored.connectionHealthChangedAt
|
|
1217
|
+
? ` (${formatRelativeTime(stored.connectionHealthChangedAt)})`
|
|
1218
|
+
: "";
|
|
1219
|
+
if (msg) {
|
|
1220
|
+
emit.detail(` \u21b3 ${msg}${ago} Run \`vana connect ${sourceId}\``);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1190
1223
|
if (health === "needs_reauth" && !needsReauthSource) {
|
|
1191
1224
|
needsReauthSource = sourceId;
|
|
1192
1225
|
}
|
|
@@ -2038,14 +2071,16 @@ async function runServerData(scope, options) {
|
|
|
2038
2071
|
}
|
|
2039
2072
|
// If PS is available, try to list remote scopes via client
|
|
2040
2073
|
let remoteScopes = [];
|
|
2074
|
+
let remoteScopeFallbackReason;
|
|
2041
2075
|
if (target.state === "available" && target.url) {
|
|
2042
2076
|
try {
|
|
2043
2077
|
const { createPersonalServerClient: createClient } = await import("../personal-server/client.js");
|
|
2044
2078
|
const client = createClient({ url: target.url });
|
|
2045
2079
|
remoteScopes = await client.listScopes(scope);
|
|
2046
2080
|
}
|
|
2047
|
-
catch {
|
|
2048
|
-
|
|
2081
|
+
catch (err) {
|
|
2082
|
+
remoteScopeFallbackReason =
|
|
2083
|
+
err instanceof Error ? err.message : "unknown error";
|
|
2049
2084
|
}
|
|
2050
2085
|
}
|
|
2051
2086
|
// Use remote scopes if available, otherwise fall back to local
|
|
@@ -2063,6 +2098,7 @@ async function runServerData(scope, options) {
|
|
|
2063
2098
|
count: scopeList.length,
|
|
2064
2099
|
scopes: scopeList,
|
|
2065
2100
|
source: remoteScopes.length > 0 ? "remote" : "local",
|
|
2101
|
+
...(remoteScopeFallbackReason ? { remoteScopeFallbackReason } : {}),
|
|
2066
2102
|
})}\n`);
|
|
2067
2103
|
return 0;
|
|
2068
2104
|
}
|
|
@@ -2321,6 +2357,10 @@ export async function gatherSourceStatuses(storedSources, metadata = {}) {
|
|
|
2321
2357
|
connectorVersion: stored.connectorVersion,
|
|
2322
2358
|
exportFrequency: stored.exportFrequency,
|
|
2323
2359
|
lastCollectedAt: stored.lastCollectedAt,
|
|
2360
|
+
connectionHealth: stored.connectionHealth,
|
|
2361
|
+
connectionHealthChangedAt: stored.connectionHealthChangedAt,
|
|
2362
|
+
connectionHealthReason: stored.connectionHealthReason,
|
|
2363
|
+
connectionHealthRetryable: stored.connectionHealthRetryable,
|
|
2324
2364
|
installed,
|
|
2325
2365
|
sessionPresent: stored.sessionPresent ?? false,
|
|
2326
2366
|
lastRunAt: stored.lastRunAt ?? null,
|
|
@@ -2472,6 +2512,14 @@ function formatSourceStatusDetails(source) {
|
|
|
2472
2512
|
tone: "muted",
|
|
2473
2513
|
});
|
|
2474
2514
|
}
|
|
2515
|
+
if (source.connectionHealthReason && source.connectionHealth !== "healthy") {
|
|
2516
|
+
details.push({
|
|
2517
|
+
kind: "row",
|
|
2518
|
+
label: "Cause",
|
|
2519
|
+
value: source.connectionHealthReason,
|
|
2520
|
+
tone: "muted",
|
|
2521
|
+
});
|
|
2522
|
+
}
|
|
2475
2523
|
if (source.lastRunAt) {
|
|
2476
2524
|
details.push({
|
|
2477
2525
|
kind: "row",
|
|
@@ -2632,6 +2680,28 @@ function buildLogsNextSteps(records) {
|
|
|
2632
2680
|
"Check overall status with `vana status`.",
|
|
2633
2681
|
];
|
|
2634
2682
|
}
|
|
2683
|
+
/** Derive a human-readable message from a stored `connectionHealthReason`. */
|
|
2684
|
+
export function formatHealthMessage(reason) {
|
|
2685
|
+
if (!reason)
|
|
2686
|
+
return null;
|
|
2687
|
+
const colonIndex = reason.indexOf(": ");
|
|
2688
|
+
const prefix = colonIndex > 0 ? reason.slice(0, colonIndex) : reason;
|
|
2689
|
+
const detail = colonIndex > 0 ? reason.slice(colonIndex + 2) : "";
|
|
2690
|
+
switch (prefix) {
|
|
2691
|
+
case "needs-input":
|
|
2692
|
+
return `Requires interactive login${detail ? `: ${detail}` : ""}.`;
|
|
2693
|
+
case "legacy-auth":
|
|
2694
|
+
return `Needed a browser window${detail ? `: ${detail}` : ""}. Reconnect interactively.`;
|
|
2695
|
+
case "runtime-error":
|
|
2696
|
+
return `Collection failed${detail ? ` — ${detail}` : ""}.`;
|
|
2697
|
+
case "error-result":
|
|
2698
|
+
return `Connector returned an error${detail ? `: ${detail}` : ""}.`;
|
|
2699
|
+
case "collection-complete":
|
|
2700
|
+
return null; // No message needed for healthy state
|
|
2701
|
+
default:
|
|
2702
|
+
return reason; // Graceful fallback for unknown prefixes
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2635
2705
|
/** Extract a `vana ...` command from a next-step sentence wrapped in backticks. */
|
|
2636
2706
|
function extractCommand(sentence) {
|
|
2637
2707
|
const match = sentence.match(/`(vana\s[^`]+)`/);
|
|
@@ -3280,7 +3350,7 @@ async function getExistingScheduleInterval() {
|
|
|
3280
3350
|
}
|
|
3281
3351
|
return null;
|
|
3282
3352
|
}
|
|
3283
|
-
async function maybeAutoSchedule(options) {
|
|
3353
|
+
async function maybeAutoSchedule(emit, options) {
|
|
3284
3354
|
// Skip if --no-input (detached/agent context shouldn't create schedules)
|
|
3285
3355
|
if (options.noInput)
|
|
3286
3356
|
return;
|
|
@@ -3291,6 +3361,7 @@ async function maybeAutoSchedule(options) {
|
|
|
3291
3361
|
if (existing !== null)
|
|
3292
3362
|
return; // Schedule already exists
|
|
3293
3363
|
await runScheduleAdd("daily", { json: false, quiet: true });
|
|
3364
|
+
emit.detail("Auto-scheduled daily collection.");
|
|
3294
3365
|
}
|
|
3295
3366
|
function generateLaunchdPlist(vanaBinary, intervalSeconds) {
|
|
3296
3367
|
const logsPath = path.join(getLogsDir(), "schedule.log");
|