@automagik/omni 2.260504.2 → 2.260505.2
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/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/update.d.ts +162 -7
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/index.js +407 -58
- package/dist/legacy-cleanup.d.ts +82 -0
- package/dist/legacy-cleanup.d.ts.map +1 -0
- package/dist/server/index.js +1 -1
- package/dist/update-diagnostics.d.ts +136 -0
- package/dist/update-diagnostics.d.ts.map +1 -0
- package/package.json +10 -10
|
@@ -61,6 +61,14 @@ export interface DoctorOptions {
|
|
|
61
61
|
fix?: boolean;
|
|
62
62
|
json?: boolean;
|
|
63
63
|
verbose?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Force read-only mode. When true, any `fix: true` is suppressed and
|
|
66
|
+
* `runDoctor` only collects the check report. Used by `omni update`'s
|
|
67
|
+
* post-update maintenance hook (`runPostUpdateMaintenance`) so the
|
|
68
|
+
* probe stays read-only — `omni doctor --fix` remains the explicit
|
|
69
|
+
* operator action for repair.
|
|
70
|
+
*/
|
|
71
|
+
dryRun?: boolean;
|
|
64
72
|
}
|
|
65
73
|
/**
|
|
66
74
|
* Narrow shape of a pm2 process entry from `pm2 jlist`. We only care about
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,KAAK,MAAM,EACX,KAAK,YAAY,EAKlB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,KAAK,kBAAkB,EAKxB,MAAM,6BAA6B,CAAC;AAarC,8CAA8C;AAC9C,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhD,kDAAkD;AAClD,MAAM,MAAM,OAAO,GACf,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,gBAAgB,GAChB,oBAAoB,GACpB,eAAe,GACf,YAAY,GACZ,kBAAkB,GAClB,yBAAyB,GACzB,sCAAsC,GACtC,mBAAmB,CAAC;AAExB,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { Command } from 'commander';
|
|
24
24
|
import { type Config } from '../config.js';
|
|
25
|
+
import { type ParallelInstallReport } from '../update-diagnostics.js';
|
|
26
|
+
import { type DoctorReport, runDoctor } from './doctor.js';
|
|
25
27
|
export type UpdateChannel = 'latest' | 'next';
|
|
26
28
|
/**
|
|
27
29
|
* Resolve the npm dist-tag to install. Priority:
|
|
@@ -44,11 +46,26 @@ export interface HealthBody {
|
|
|
44
46
|
* trigger a spurious mismatch.
|
|
45
47
|
*/
|
|
46
48
|
export declare function normalizeVersion(version: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Reasons the verify step can be skipped without a server probe. Aligned
|
|
51
|
+
* byte-for-byte with the genie-side `VerifyResult.skipped.reason` shape so
|
|
52
|
+
* cross-CLI diagnostics tooling can read either repo's output uniformly
|
|
53
|
+
* (see `.genie/wishes/update-unify-stages/SHARED-DESIGN.md`).
|
|
54
|
+
*
|
|
55
|
+
* - `no-restart`: operator passed `--no-restart`, so no service was touched.
|
|
56
|
+
* - `no-verify-flag`: operator passed `--no-verify`, restart ran but probe was suppressed.
|
|
57
|
+
* - `no-running-services`: no tracked PM2 services were online before the install.
|
|
58
|
+
*/
|
|
59
|
+
export type VerifySkipReason = 'no-restart' | 'no-verify-flag' | 'no-running-services';
|
|
47
60
|
/**
|
|
48
61
|
* Result of the pure 3-step update verification. Exported so tests can
|
|
49
62
|
* exercise the logic without mocking pm2 / fetch / process.exit.
|
|
63
|
+
*
|
|
64
|
+
* Public-shape parity with the genie wish — each variant's keys match
|
|
65
|
+
* `automagik-dev/genie` exactly so a shared diagnostics consumer can decode
|
|
66
|
+
* either CLI's output without per-repo branching.
|
|
50
67
|
*/
|
|
51
|
-
export type
|
|
68
|
+
export type VerifyResult = {
|
|
52
69
|
kind: 'ok';
|
|
53
70
|
cliVersion: string;
|
|
54
71
|
serverVersion: string;
|
|
@@ -61,22 +78,155 @@ export type UpdateVerifyResult = {
|
|
|
61
78
|
serverVersion: string | null;
|
|
62
79
|
} | {
|
|
63
80
|
kind: 'auth-invalid';
|
|
81
|
+
} | {
|
|
82
|
+
kind: 'skipped';
|
|
83
|
+
reason: VerifySkipReason;
|
|
64
84
|
};
|
|
65
85
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
|
|
69
|
-
|
|
86
|
+
* @deprecated Use {@link VerifyResult}. Retained for backward compatibility
|
|
87
|
+
* with any external consumer that imported the original name.
|
|
88
|
+
*/
|
|
89
|
+
export type UpdateVerifyResult = VerifyResult;
|
|
90
|
+
/**
|
|
91
|
+
* Args accepted by {@link decideVerify}. Either `skipReason` is set (the
|
|
92
|
+
* verify step short-circuits to `{ kind: 'skipped' }`) or all of `latest` /
|
|
93
|
+
* `apiPort` / `healthBody` / `keyValid` are provided for the full decision.
|
|
70
94
|
*/
|
|
71
|
-
export
|
|
95
|
+
export type DecideVerifyArgs = {
|
|
72
96
|
latest: string;
|
|
73
97
|
apiPort: number;
|
|
74
98
|
healthBody: HealthBody | null;
|
|
75
99
|
keyValid: boolean;
|
|
76
|
-
|
|
100
|
+
skipReason?: undefined;
|
|
101
|
+
} | {
|
|
102
|
+
skipReason: VerifySkipReason;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Pure decision function for update verification. Given the raw inputs
|
|
106
|
+
* (health body + key-valid flag + CLI version + port), return a tagged
|
|
107
|
+
* union describing the outcome. The caller decides how to render and
|
|
108
|
+
* whether to exit non-zero.
|
|
109
|
+
*
|
|
110
|
+
* When `skipReason` is provided, the function short-circuits to
|
|
111
|
+
* `{ kind: 'skipped', reason }` without inspecting the other fields. This
|
|
112
|
+
* is the path used by `--no-restart`, `--no-verify`, and the
|
|
113
|
+
* no-running-services case.
|
|
114
|
+
*/
|
|
115
|
+
export declare function decideVerify(args: DecideVerifyArgs): VerifyResult;
|
|
116
|
+
/**
|
|
117
|
+
* @deprecated Use {@link decideVerify}. Pointer-equal alias retained for
|
|
118
|
+
* backward compatibility with any external consumer that imported the
|
|
119
|
+
* original name.
|
|
120
|
+
*/
|
|
121
|
+
export declare const decideUpdateVerify: typeof decideVerify;
|
|
77
122
|
/** Error message strings — exported for tests and documentation. */
|
|
78
123
|
export declare function updateErrorVersionMismatch(cli: string, server: string | null): string;
|
|
79
124
|
export declare const UPDATE_ERROR_AUTH_INVALID = "Auth key invalid after restart. Run: omni doctor --fix";
|
|
125
|
+
/**
|
|
126
|
+
* Detect a parallel npm-global install of `@automagik/omni`. Omni doesn't
|
|
127
|
+
* support npm-global server (we install via `bun add -g`), but a parallel
|
|
128
|
+
* install hides stale binaries on PATH and confuses `which omni`. When
|
|
129
|
+
* detected, the operator gets a one-line warning naming the offending path
|
|
130
|
+
* with the recommended remediation: `npm uninstall -g @automagik/omni`.
|
|
131
|
+
*
|
|
132
|
+
* Pure-ish: probes `npm root -g`, then checks if `<root>/@automagik/omni`
|
|
133
|
+
* exists. Never throws — when `npm` is absent the probe simply reports
|
|
134
|
+
* `skipped: 'npm-not-on-path'` and the warning never fires.
|
|
135
|
+
*
|
|
136
|
+
* Exported for tests so we can exercise both paths without spawning npm.
|
|
137
|
+
*/
|
|
138
|
+
export declare function detectParallelNpmGlobalInstall(deps?: {
|
|
139
|
+
npmRoot?: () => string | null;
|
|
140
|
+
exists?: (p: string) => boolean;
|
|
141
|
+
}): ParallelInstallReport;
|
|
142
|
+
/**
|
|
143
|
+
* Reasons the post-update maintenance hook can be skipped.
|
|
144
|
+
*
|
|
145
|
+
* - `cli-flag`: operator passed `--skip-maintenance`.
|
|
146
|
+
* - `env`: `OMNI_UPDATE_SKIP_MAINTENANCE` was set in the environment.
|
|
147
|
+
* - `verify-failed`: upstream `decideVerify` outcome was not `ok`, so probing
|
|
148
|
+
* further is pointless (the operator already has a
|
|
149
|
+
* `Run: omni doctor` pointer from the verify step).
|
|
150
|
+
*/
|
|
151
|
+
export type MaintenanceSkipReason = 'cli-flag' | 'env' | 'verify-failed';
|
|
152
|
+
/**
|
|
153
|
+
* Outcome of a single post-update maintenance run. Public-shape parity with
|
|
154
|
+
* the genie wish — the same field names land in diagnostics so a shared
|
|
155
|
+
* consumer can read either CLI's output uniformly.
|
|
156
|
+
*
|
|
157
|
+
* - `completed`: `runDoctor` returned a report (regardless of WARN/FAIL counts).
|
|
158
|
+
* - `failed`: `runDoctor` threw; the call was non-blocking, exit code stays 0.
|
|
159
|
+
* - `skipped`: maintenance was opted out (flag/env) or upstream verify wasn't OK.
|
|
160
|
+
*/
|
|
161
|
+
export type MaintenanceOutcome = 'completed' | 'failed' | 'skipped';
|
|
162
|
+
/**
|
|
163
|
+
* Captured shape of the post-update maintenance hook. Always populated, even
|
|
164
|
+
* when skipped — diagnostics (Group 4) consumes the same struct on every
|
|
165
|
+
* code path so the JSON file shape is invariant.
|
|
166
|
+
*/
|
|
167
|
+
export interface MaintenanceReport {
|
|
168
|
+
outcome: MaintenanceOutcome;
|
|
169
|
+
/** Wall time spent inside `runDoctor` (or 0 when skipped). */
|
|
170
|
+
durationMs: number;
|
|
171
|
+
/** Present only when `outcome === 'completed'`. */
|
|
172
|
+
doctorReport?: DoctorReport;
|
|
173
|
+
/** Present only when `outcome === 'skipped'`. */
|
|
174
|
+
skipReason?: MaintenanceSkipReason;
|
|
175
|
+
/** Present only when `outcome === 'failed'` — the thrown error message. */
|
|
176
|
+
error?: string;
|
|
177
|
+
}
|
|
178
|
+
/** Env-var name that opts out of the post-update maintenance hook. */
|
|
179
|
+
export declare const OMNI_UPDATE_SKIP_MAINTENANCE_ENV = "OMNI_UPDATE_SKIP_MAINTENANCE";
|
|
180
|
+
/**
|
|
181
|
+
* Resolve the effective skip reason for the post-update maintenance hook.
|
|
182
|
+
* Returns `null` when maintenance should run. Pure — exported for tests so
|
|
183
|
+
* we can exercise the precedence logic without spinning up `runDoctor`.
|
|
184
|
+
*
|
|
185
|
+
* Precedence (first match wins):
|
|
186
|
+
* 1. `verify-failed` — upstream verify wasn't `ok`; nothing to probe.
|
|
187
|
+
* 2. `cli-flag` — operator passed `--skip-maintenance`.
|
|
188
|
+
* 3. `env` — `OMNI_UPDATE_SKIP_MAINTENANCE` is set to a truthy value.
|
|
189
|
+
*
|
|
190
|
+
* The truthy check for the env var matches the same loose semantics as
|
|
191
|
+
* `--yes`/CI flags elsewhere: any non-empty value other than `0`/`false`
|
|
192
|
+
* counts as opt-out.
|
|
193
|
+
*/
|
|
194
|
+
export declare function resolveMaintenanceSkipReason(args: {
|
|
195
|
+
verifyOk: boolean;
|
|
196
|
+
skipMaintenance: boolean | undefined;
|
|
197
|
+
env: Record<string, string | undefined>;
|
|
198
|
+
}): MaintenanceSkipReason | null;
|
|
199
|
+
/**
|
|
200
|
+
* Format the one-line summary printed after a completed maintenance run.
|
|
201
|
+
* Pure — exported so tests can lock the exact shape and so diagnostics
|
|
202
|
+
* (Group 4) can reuse it without re-deriving the format.
|
|
203
|
+
*
|
|
204
|
+
* Shape: `Maintenance: <ok> ok, <warn> warn, <fail> fail`.
|
|
205
|
+
*/
|
|
206
|
+
export declare function formatMaintenanceSummary(report: DoctorReport): string;
|
|
207
|
+
/**
|
|
208
|
+
* Run the post-update maintenance hook — a read-only `omni doctor` sweep
|
|
209
|
+
* that captures a `DoctorReport` for diagnostics.
|
|
210
|
+
*
|
|
211
|
+
* The call is non-blocking by contract: any thrown error is captured into
|
|
212
|
+
* the returned `MaintenanceReport` (`outcome: 'failed'`) and the caller
|
|
213
|
+
* proceeds with exit code 0. This matches the shared exit-code contract
|
|
214
|
+
* (see `SHARED-DESIGN.md` §4.5: "Maintenance failed (non-blocking) → 0,
|
|
215
|
+
* with banner warning").
|
|
216
|
+
*
|
|
217
|
+
* `runDoctor({ json: true, dryRun: true })` is the canonical call shape:
|
|
218
|
+
* `dryRun: true` defeats any accidental `fix: true` injection so the probe
|
|
219
|
+
* never mutates pm2 / config / DB state. `omni doctor --fix` remains the
|
|
220
|
+
* explicit operator action for repair (decision #4).
|
|
221
|
+
*
|
|
222
|
+
* `runDoctorImpl` is injected for tests so we can stub the doctor surface
|
|
223
|
+
* without monkey-patching the module — module-level mocks leak across
|
|
224
|
+
* test files in bun and would pollute `doctor.test.ts`.
|
|
225
|
+
*/
|
|
226
|
+
export declare function runPostUpdateMaintenance(args: {
|
|
227
|
+
skipReason: MaintenanceSkipReason | null;
|
|
228
|
+
runDoctorImpl?: typeof runDoctor;
|
|
229
|
+
}): Promise<MaintenanceReport>;
|
|
80
230
|
/**
|
|
81
231
|
* Halt updates that would cross the phase-2 default-flip cutoff on hosts
|
|
82
232
|
* still running legacy embedded pgserve without the canonical binary
|
|
@@ -90,5 +240,10 @@ export declare function checkCanonicalPgservePreflight(args: {
|
|
|
90
240
|
useCanonicalPgserve: boolean | undefined;
|
|
91
241
|
pgserveOnPath: boolean;
|
|
92
242
|
}): string | null;
|
|
243
|
+
/**
|
|
244
|
+
* Parse the `--skip-cleanup=name1,name2` value into a Set. Empty / undefined
|
|
245
|
+
* yields an empty set. Whitespace and empty entries are tolerated.
|
|
246
|
+
*/
|
|
247
|
+
export declare function parseSkipCleanupList(value: string | undefined): Set<string>;
|
|
93
248
|
export declare function createUpdateCommand(): Command;
|
|
94
249
|
//# sourceMappingURL=update.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -78229,7 +78229,7 @@ var require_path = __commonJS((exports) => {
|
|
|
78229
78229
|
function isAbsolute(path) {
|
|
78230
78230
|
return path.charAt(0) === "/";
|
|
78231
78231
|
}
|
|
78232
|
-
function
|
|
78232
|
+
function join18(...args) {
|
|
78233
78233
|
return normalizePath(args.join("/"));
|
|
78234
78234
|
}
|
|
78235
78235
|
function dirname6(path) {
|
|
@@ -78254,7 +78254,7 @@ var require_path = __commonJS((exports) => {
|
|
|
78254
78254
|
exports.basename = basename6;
|
|
78255
78255
|
exports.dirname = dirname6;
|
|
78256
78256
|
exports.isAbsolute = isAbsolute;
|
|
78257
|
-
exports.join =
|
|
78257
|
+
exports.join = join18;
|
|
78258
78258
|
exports.normalizePath = normalizePath;
|
|
78259
78259
|
exports.relative = relative;
|
|
78260
78260
|
exports.resolve = resolve4;
|
|
@@ -100994,12 +100994,12 @@ var require_instrumentation9 = __commonJS((exports) => {
|
|
|
100994
100994
|
pendingMetrics.forEach((m2) => m2());
|
|
100995
100995
|
return result;
|
|
100996
100996
|
}).catch((reason) => {
|
|
100997
|
-
let
|
|
100997
|
+
let errorMessage2;
|
|
100998
100998
|
let errorType = semantic_conventions_1.ERROR_TYPE_VALUE_OTHER;
|
|
100999
100999
|
if (typeof reason === "string" || reason === undefined) {
|
|
101000
|
-
|
|
101000
|
+
errorMessage2 = reason;
|
|
101001
101001
|
} else if (typeof reason === "object" && Object.prototype.hasOwnProperty.call(reason, "message")) {
|
|
101002
|
-
|
|
101002
|
+
errorMessage2 = reason.message;
|
|
101003
101003
|
errorType = reason.constructor.name;
|
|
101004
101004
|
}
|
|
101005
101005
|
pendingMetrics.forEach((m2) => m2(errorType));
|
|
@@ -101007,7 +101007,7 @@ var require_instrumentation9 = __commonJS((exports) => {
|
|
|
101007
101007
|
span.setAttribute(semantic_conventions_1.ATTR_ERROR_TYPE, errorType);
|
|
101008
101008
|
span.setStatus({
|
|
101009
101009
|
code: api_1.SpanStatusCode.ERROR,
|
|
101010
|
-
message:
|
|
101010
|
+
message: errorMessage2
|
|
101011
101011
|
});
|
|
101012
101012
|
});
|
|
101013
101013
|
throw reason;
|
|
@@ -114211,7 +114211,7 @@ import { fileURLToPath } from "url";
|
|
|
114211
114211
|
// package.json
|
|
114212
114212
|
var package_default = {
|
|
114213
114213
|
name: "@automagik/omni",
|
|
114214
|
-
version: "2.
|
|
114214
|
+
version: "2.260505.2",
|
|
114215
114215
|
description: "LLM-optimized CLI for Omni",
|
|
114216
114216
|
type: "module",
|
|
114217
114217
|
bin: {
|
|
@@ -119684,7 +119684,7 @@ async function runDoctor(options, depsOverride) {
|
|
|
119684
119684
|
const deps = depsOverride ?? productionDeps();
|
|
119685
119685
|
let checks = await runAllChecks(deps);
|
|
119686
119686
|
const fixesApplied = [];
|
|
119687
|
-
if (options.fix) {
|
|
119687
|
+
if (options.fix && options.dryRun !== true) {
|
|
119688
119688
|
const phase1 = await runPhase1MigrationFix(deps, checks, fixesApplied);
|
|
119689
119689
|
checks = phase1.checks;
|
|
119690
119690
|
await runPhase2Fixes(deps, checks, phase1.canonicalFailed, fixesApplied);
|
|
@@ -125829,10 +125829,11 @@ function createTurnsCommand() {
|
|
|
125829
125829
|
}
|
|
125830
125830
|
|
|
125831
125831
|
// src/commands/update.ts
|
|
125832
|
+
import { existsSync as existsSync17 } from "fs";
|
|
125833
|
+
import { join as join16 } from "path";
|
|
125832
125834
|
import { createInterface as createInterface3 } from "readline";
|
|
125833
125835
|
init_source();
|
|
125834
125836
|
init_config();
|
|
125835
|
-
init_output();
|
|
125836
125837
|
|
|
125837
125838
|
// src/sidecar-cleanup.ts
|
|
125838
125839
|
var SIDECAR_BASENAME = "nats-reply-sidecar.mjs";
|
|
@@ -126009,8 +126010,185 @@ function formatCleanupSummary(result) {
|
|
|
126009
126010
|
return lines.join(`
|
|
126010
126011
|
`);
|
|
126011
126012
|
}
|
|
126012
|
-
|
|
126013
|
-
|
|
126013
|
+
|
|
126014
|
+
// src/legacy-cleanup.ts
|
|
126015
|
+
function createNatsReplySidecarArtifact() {
|
|
126016
|
+
let lastResult = null;
|
|
126017
|
+
return {
|
|
126018
|
+
name: "nats-reply-sidecar",
|
|
126019
|
+
async detect() {
|
|
126020
|
+
return true;
|
|
126021
|
+
},
|
|
126022
|
+
async cleanup() {
|
|
126023
|
+
const result = await cleanupSidecars();
|
|
126024
|
+
lastResult = result;
|
|
126025
|
+
const removed = [];
|
|
126026
|
+
const warnings = [];
|
|
126027
|
+
for (const m2 of result.pm2Stopped) {
|
|
126028
|
+
removed.push(`pm2:${m2.name.length > 0 ? m2.name : `pm_id=${m2.pmId}`}`);
|
|
126029
|
+
}
|
|
126030
|
+
for (const m2 of result.rawKilled) {
|
|
126031
|
+
removed.push(`pid:${m2.pid}`);
|
|
126032
|
+
}
|
|
126033
|
+
for (const m2 of result.pm2Failed) {
|
|
126034
|
+
warnings.push(`pm2-failed:${m2.name.length > 0 ? m2.name : `pm_id=${m2.pmId}`}`);
|
|
126035
|
+
}
|
|
126036
|
+
for (const m2 of result.rawFailed) {
|
|
126037
|
+
warnings.push(`raw-failed:pid=${m2.pid}`);
|
|
126038
|
+
}
|
|
126039
|
+
return { removed, warnings };
|
|
126040
|
+
},
|
|
126041
|
+
summary() {
|
|
126042
|
+
return lastResult === null ? "" : formatCleanupSummary(lastResult);
|
|
126043
|
+
}
|
|
126044
|
+
};
|
|
126045
|
+
}
|
|
126046
|
+
var REGISTRY = [createNatsReplySidecarArtifact()];
|
|
126047
|
+
function errorMessage(error2) {
|
|
126048
|
+
return error2 instanceof Error ? error2.message : String(error2);
|
|
126049
|
+
}
|
|
126050
|
+
function erroredOutcome(name, phase, error2) {
|
|
126051
|
+
const message2 = errorMessage(error2);
|
|
126052
|
+
return {
|
|
126053
|
+
name,
|
|
126054
|
+
state: "errored",
|
|
126055
|
+
removed: [],
|
|
126056
|
+
warnings: [`${phase}-threw:${message2}`],
|
|
126057
|
+
summary: "",
|
|
126058
|
+
error: message2
|
|
126059
|
+
};
|
|
126060
|
+
}
|
|
126061
|
+
async function runArtifact(artifact) {
|
|
126062
|
+
let detected;
|
|
126063
|
+
try {
|
|
126064
|
+
detected = await artifact.detect();
|
|
126065
|
+
} catch (error2) {
|
|
126066
|
+
return erroredOutcome(artifact.name, "detect", error2);
|
|
126067
|
+
}
|
|
126068
|
+
if (!detected) {
|
|
126069
|
+
return {
|
|
126070
|
+
name: artifact.name,
|
|
126071
|
+
state: "not-detected",
|
|
126072
|
+
removed: [],
|
|
126073
|
+
warnings: [],
|
|
126074
|
+
summary: ""
|
|
126075
|
+
};
|
|
126076
|
+
}
|
|
126077
|
+
try {
|
|
126078
|
+
const { removed, warnings } = await artifact.cleanup();
|
|
126079
|
+
return {
|
|
126080
|
+
name: artifact.name,
|
|
126081
|
+
state: "ran",
|
|
126082
|
+
removed,
|
|
126083
|
+
warnings,
|
|
126084
|
+
summary: artifact.summary()
|
|
126085
|
+
};
|
|
126086
|
+
} catch (error2) {
|
|
126087
|
+
return erroredOutcome(artifact.name, "cleanup", error2);
|
|
126088
|
+
}
|
|
126089
|
+
}
|
|
126090
|
+
async function cleanupLegacyArtifacts(skipList) {
|
|
126091
|
+
const outcomes = [];
|
|
126092
|
+
const skipped = [];
|
|
126093
|
+
for (const artifact of REGISTRY) {
|
|
126094
|
+
if (skipList.has(artifact.name)) {
|
|
126095
|
+
skipped.push(artifact.name);
|
|
126096
|
+
outcomes.push({
|
|
126097
|
+
name: artifact.name,
|
|
126098
|
+
state: "skipped",
|
|
126099
|
+
removed: [],
|
|
126100
|
+
warnings: [],
|
|
126101
|
+
summary: ""
|
|
126102
|
+
});
|
|
126103
|
+
continue;
|
|
126104
|
+
}
|
|
126105
|
+
outcomes.push(await runArtifact(artifact));
|
|
126106
|
+
}
|
|
126107
|
+
const succeeded = outcomes.every((o2) => o2.state !== "errored" && (o2.state !== "ran" || o2.warnings.length === 0));
|
|
126108
|
+
return { outcomes, succeeded, skipped };
|
|
126109
|
+
}
|
|
126110
|
+
|
|
126111
|
+
// src/commands/update.ts
|
|
126112
|
+
init_output();
|
|
126113
|
+
|
|
126114
|
+
// src/update-diagnostics.ts
|
|
126115
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
126116
|
+
import { homedir as homedir11 } from "os";
|
|
126117
|
+
import { join as join15 } from "path";
|
|
126118
|
+
var UPDATE_DIAGNOSTICS_SCHEMA_VERSION = 1;
|
|
126119
|
+
function createDiagnostics(args) {
|
|
126120
|
+
const startedAt = new Date().toISOString();
|
|
126121
|
+
return {
|
|
126122
|
+
schemaVersion: UPDATE_DIAGNOSTICS_SCHEMA_VERSION,
|
|
126123
|
+
startedAt,
|
|
126124
|
+
finishedAt: startedAt,
|
|
126125
|
+
cli: { runningVersion: args.runningVersion, channel: args.channel },
|
|
126126
|
+
registry: { latestVersion: null },
|
|
126127
|
+
preflight: { ran: false, blocked: false },
|
|
126128
|
+
install: { attempted: false, succeeded: null, targetVersion: null },
|
|
126129
|
+
restart: { attempted: false, succeeded: null, services: [] },
|
|
126130
|
+
verify: null,
|
|
126131
|
+
cleanups: null,
|
|
126132
|
+
maintenance: null,
|
|
126133
|
+
parallelNpmGlobal: null,
|
|
126134
|
+
recentLogSignals: [],
|
|
126135
|
+
exitCode: 0
|
|
126136
|
+
};
|
|
126137
|
+
}
|
|
126138
|
+
function getDiagnosticsDir() {
|
|
126139
|
+
const base = process.env.OMNI_CONFIG_DIR ?? join15(homedir11(), ".omni");
|
|
126140
|
+
return join15(base, "logs");
|
|
126141
|
+
}
|
|
126142
|
+
function getDiagnosticsPath(startedAt) {
|
|
126143
|
+
const safe = startedAt.replace(/:/g, "-");
|
|
126144
|
+
return join15(getDiagnosticsDir(), `update-diagnostics-${safe}.json`);
|
|
126145
|
+
}
|
|
126146
|
+
function tailFileLines(path, maxLines) {
|
|
126147
|
+
if (!existsSync16(path))
|
|
126148
|
+
return [];
|
|
126149
|
+
try {
|
|
126150
|
+
const raw2 = readFileSync11(path, "utf8");
|
|
126151
|
+
const lines = raw2.split(/\r?\n/);
|
|
126152
|
+
if (lines.length > 0 && lines[lines.length - 1] === "")
|
|
126153
|
+
lines.pop();
|
|
126154
|
+
return lines.slice(-maxLines);
|
|
126155
|
+
} catch {
|
|
126156
|
+
return [];
|
|
126157
|
+
}
|
|
126158
|
+
}
|
|
126159
|
+
function collectRecentLogSignals(maxLinesPerStream = 30, logPathsFor = getPm2LogPaths) {
|
|
126160
|
+
const signals2 = [];
|
|
126161
|
+
for (const name of Object.values(PM2_PROCESSES)) {
|
|
126162
|
+
const { out, error: error2 } = logPathsFor(name);
|
|
126163
|
+
const outLines = tailFileLines(out, maxLinesPerStream);
|
|
126164
|
+
if (outLines.length > 0) {
|
|
126165
|
+
signals2.push({ source: name, stream: "out", lines: outLines });
|
|
126166
|
+
}
|
|
126167
|
+
const errLines = tailFileLines(error2, maxLinesPerStream);
|
|
126168
|
+
if (errLines.length > 0) {
|
|
126169
|
+
signals2.push({ source: name, stream: "error", lines: errLines });
|
|
126170
|
+
}
|
|
126171
|
+
}
|
|
126172
|
+
return signals2;
|
|
126173
|
+
}
|
|
126174
|
+
function writeDiagnostics(state, exitCode) {
|
|
126175
|
+
state.exitCode = exitCode;
|
|
126176
|
+
state.finishedAt = new Date().toISOString();
|
|
126177
|
+
if (state.recentLogSignals.length === 0) {
|
|
126178
|
+
state.recentLogSignals = collectRecentLogSignals();
|
|
126179
|
+
}
|
|
126180
|
+
const dir = getDiagnosticsDir();
|
|
126181
|
+
const path = getDiagnosticsPath(state.startedAt);
|
|
126182
|
+
try {
|
|
126183
|
+
if (!existsSync16(dir)) {
|
|
126184
|
+
mkdirSync10(dir, { recursive: true, mode: 448 });
|
|
126185
|
+
}
|
|
126186
|
+
writeFileSync9(path, `${JSON.stringify(state, null, 2)}
|
|
126187
|
+
`, { mode: 384 });
|
|
126188
|
+
return path;
|
|
126189
|
+
} catch {
|
|
126190
|
+
return null;
|
|
126191
|
+
}
|
|
126014
126192
|
}
|
|
126015
126193
|
|
|
126016
126194
|
// src/commands/update.ts
|
|
@@ -126111,7 +126289,10 @@ async function restartPm2Services(processNames) {
|
|
|
126111
126289
|
function normalizeVersion(version2) {
|
|
126112
126290
|
return version2.split("+")[0] ?? version2;
|
|
126113
126291
|
}
|
|
126114
|
-
function
|
|
126292
|
+
function decideVerify(args) {
|
|
126293
|
+
if (args.skipReason !== undefined) {
|
|
126294
|
+
return { kind: "skipped", reason: args.skipReason };
|
|
126295
|
+
}
|
|
126115
126296
|
const cliVersion = normalizeVersion(args.latest);
|
|
126116
126297
|
if (args.healthBody === null) {
|
|
126117
126298
|
return { kind: "health-unreachable", apiPort: args.apiPort };
|
|
@@ -126166,52 +126347,158 @@ function printVerifyBanner(latest) {
|
|
|
126166
126347
|
console.log(`${source_default.green("\u2713")} Server: v${latest} (healthy)`);
|
|
126167
126348
|
console.log(`${source_default.green("\u2713")} Auth: key valid`);
|
|
126168
126349
|
}
|
|
126169
|
-
|
|
126170
|
-
|
|
126171
|
-
|
|
126350
|
+
function printVerifySkippedBanner(latest) {
|
|
126351
|
+
console.log(`${source_default.green("\u2713")} CLI: v${latest}`);
|
|
126352
|
+
console.log(`${source_default.yellow("-")} Server: v${latest} (skipped)`);
|
|
126353
|
+
console.log(`${source_default.yellow("-")} Auth: skipped`);
|
|
126354
|
+
}
|
|
126355
|
+
function detectParallelNpmGlobalInstall(deps) {
|
|
126356
|
+
const npmRootFn = deps?.npmRoot ?? defaultNpmRoot;
|
|
126357
|
+
const existsFn = deps?.exists ?? existsSync17;
|
|
126358
|
+
let root;
|
|
126359
|
+
try {
|
|
126360
|
+
root = npmRootFn();
|
|
126361
|
+
} catch {
|
|
126362
|
+
return { detected: false, skipped: "npm-root-failed" };
|
|
126363
|
+
}
|
|
126364
|
+
if (root === null || root.length === 0) {
|
|
126365
|
+
return { detected: false, skipped: "npm-not-on-path" };
|
|
126366
|
+
}
|
|
126367
|
+
const candidate = join16(root, "@automagik", "omni");
|
|
126368
|
+
if (existsFn(candidate)) {
|
|
126369
|
+
return { detected: true, path: candidate };
|
|
126370
|
+
}
|
|
126371
|
+
return { detected: false };
|
|
126372
|
+
}
|
|
126373
|
+
function defaultNpmRoot() {
|
|
126374
|
+
try {
|
|
126375
|
+
const result = Bun.spawnSync({
|
|
126376
|
+
cmd: ["npm", "root", "-g"],
|
|
126377
|
+
stdout: "pipe",
|
|
126378
|
+
stderr: "pipe",
|
|
126379
|
+
timeout: 5000
|
|
126380
|
+
});
|
|
126381
|
+
if (result.exitCode !== 0)
|
|
126382
|
+
return null;
|
|
126383
|
+
const text3 = new TextDecoder().decode(result.stdout).trim();
|
|
126384
|
+
return text3.length > 0 ? text3 : null;
|
|
126385
|
+
} catch {
|
|
126386
|
+
return null;
|
|
126387
|
+
}
|
|
126388
|
+
}
|
|
126389
|
+
async function runLegacyCleanup(skipList) {
|
|
126390
|
+
const cleanupSpinner = ora("Checking for legacy artifacts to clean up...").start();
|
|
126391
|
+
const report = await cleanupLegacyArtifacts(skipList);
|
|
126172
126392
|
cleanupSpinner.stop();
|
|
126173
|
-
const
|
|
126174
|
-
|
|
126175
|
-
|
|
126393
|
+
for (const outcome of report.outcomes) {
|
|
126394
|
+
if (outcome.state === "ran" && outcome.summary.length > 0) {
|
|
126395
|
+
console.log(outcome.summary);
|
|
126396
|
+
}
|
|
126176
126397
|
}
|
|
126177
|
-
return
|
|
126398
|
+
return report;
|
|
126178
126399
|
}
|
|
126179
|
-
|
|
126400
|
+
var OMNI_UPDATE_SKIP_MAINTENANCE_ENV = "OMNI_UPDATE_SKIP_MAINTENANCE";
|
|
126401
|
+
function resolveMaintenanceSkipReason(args) {
|
|
126402
|
+
if (!args.verifyOk)
|
|
126403
|
+
return "verify-failed";
|
|
126404
|
+
if (args.skipMaintenance === true)
|
|
126405
|
+
return "cli-flag";
|
|
126406
|
+
const raw2 = args.env[OMNI_UPDATE_SKIP_MAINTENANCE_ENV];
|
|
126407
|
+
if (raw2 !== undefined && raw2 !== "" && raw2 !== "0" && raw2.toLowerCase() !== "false") {
|
|
126408
|
+
return "env";
|
|
126409
|
+
}
|
|
126410
|
+
return null;
|
|
126411
|
+
}
|
|
126412
|
+
function formatMaintenanceSummary(report) {
|
|
126413
|
+
const { ok: ok2, warn: warn2, fail } = report.summary;
|
|
126414
|
+
return `Maintenance: ${ok2} ok, ${warn2} warn, ${fail} fail`;
|
|
126415
|
+
}
|
|
126416
|
+
async function runPostUpdateMaintenance(args) {
|
|
126417
|
+
if (args.skipReason !== null) {
|
|
126418
|
+
return { outcome: "skipped", durationMs: 0, skipReason: args.skipReason };
|
|
126419
|
+
}
|
|
126420
|
+
const impl = args.runDoctorImpl ?? runDoctor;
|
|
126421
|
+
const startedAt = Date.now();
|
|
126422
|
+
try {
|
|
126423
|
+
const doctorReport = await impl({ json: true, dryRun: true });
|
|
126424
|
+
return {
|
|
126425
|
+
outcome: "completed",
|
|
126426
|
+
durationMs: Date.now() - startedAt,
|
|
126427
|
+
doctorReport
|
|
126428
|
+
};
|
|
126429
|
+
} catch (err2) {
|
|
126430
|
+
return {
|
|
126431
|
+
outcome: "failed",
|
|
126432
|
+
durationMs: Date.now() - startedAt,
|
|
126433
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
126434
|
+
};
|
|
126435
|
+
}
|
|
126436
|
+
}
|
|
126437
|
+
async function restartServicesAndVerify(servicesToRestart, latest, options3, diagnostics, finalize) {
|
|
126180
126438
|
const apiPort = loadServerConfig().port;
|
|
126439
|
+
diagnostics.restart.attempted = true;
|
|
126440
|
+
diagnostics.restart.services = [...servicesToRestart];
|
|
126181
126441
|
const restartSpinner = ora("Restarting services...").start();
|
|
126182
126442
|
const restartSucceeded = await restartPm2Services(servicesToRestart);
|
|
126183
126443
|
restartSpinner.stop();
|
|
126444
|
+
diagnostics.restart.succeeded = restartSucceeded;
|
|
126184
126445
|
if (!restartSucceeded) {
|
|
126185
126446
|
warn(`omni CLI updated to v${latest}, but one or more service restarts failed. Run \`omni status\`.`);
|
|
126186
|
-
|
|
126187
|
-
}
|
|
126188
|
-
let
|
|
126189
|
-
if (options3.
|
|
126190
|
-
|
|
126447
|
+
finalize(1);
|
|
126448
|
+
}
|
|
126449
|
+
let cleanupReport = null;
|
|
126450
|
+
if (options3.legacyCleanup) {
|
|
126451
|
+
cleanupReport = await runLegacyCleanup(options3.skipList);
|
|
126452
|
+
diagnostics.cleanups = cleanupReport;
|
|
126453
|
+
}
|
|
126454
|
+
if (options3.skipVerify) {
|
|
126455
|
+
const result2 = decideVerify({ skipReason: "no-verify-flag" });
|
|
126456
|
+
diagnostics.verify = result2;
|
|
126457
|
+
printVerifySkippedBanner(latest);
|
|
126458
|
+
if (cleanupReport !== null && !cleanupReport.succeeded) {
|
|
126459
|
+
warn("One or more legacy artifacts could not be cleaned up automatically. " + "See messages above and docs/migration/nats-genie-sidecar-decommission.md.");
|
|
126460
|
+
}
|
|
126461
|
+
const maintenance = await runPostUpdateMaintenance({ skipReason: "verify-failed" });
|
|
126462
|
+
diagnostics.maintenance = maintenance;
|
|
126463
|
+
return;
|
|
126191
126464
|
}
|
|
126192
126465
|
const verifySpinner = ora("Verifying server version...").start();
|
|
126193
126466
|
const healthBody = await fetchHealthBody(apiPort, UPDATE_HEALTH_TIMEOUT_MS);
|
|
126194
126467
|
verifySpinner.stop();
|
|
126195
126468
|
const keyValid = healthBody !== null ? await validateStoredKey(apiPort) : false;
|
|
126196
|
-
const result =
|
|
126469
|
+
const result = decideVerify({ latest, apiPort, healthBody, keyValid });
|
|
126470
|
+
diagnostics.verify = result;
|
|
126197
126471
|
switch (result.kind) {
|
|
126198
|
-
case "ok":
|
|
126472
|
+
case "ok": {
|
|
126199
126473
|
printVerifyBanner(result.cliVersion);
|
|
126200
|
-
if (
|
|
126201
|
-
warn("One or more legacy
|
|
126474
|
+
if (cleanupReport !== null && !cleanupReport.succeeded) {
|
|
126475
|
+
warn("One or more legacy artifacts could not be cleaned up automatically. " + "See messages above and docs/migration/nats-genie-sidecar-decommission.md.");
|
|
126476
|
+
}
|
|
126477
|
+
const skipReason = resolveMaintenanceSkipReason({
|
|
126478
|
+
verifyOk: true,
|
|
126479
|
+
skipMaintenance: options3.skipMaintenance,
|
|
126480
|
+
env: process.env
|
|
126481
|
+
});
|
|
126482
|
+
const maintenance = await runPostUpdateMaintenance({ skipReason });
|
|
126483
|
+
diagnostics.maintenance = maintenance;
|
|
126484
|
+
if (maintenance.outcome === "completed" && maintenance.doctorReport) {
|
|
126485
|
+
info(formatMaintenanceSummary(maintenance.doctorReport));
|
|
126486
|
+
} else if (maintenance.outcome === "failed") {
|
|
126487
|
+
warn(`Maintenance: skipped (runDoctor failed: ${maintenance.error ?? "unknown error"})`);
|
|
126202
126488
|
}
|
|
126203
126489
|
return;
|
|
126490
|
+
}
|
|
126204
126491
|
case "health-unreachable":
|
|
126205
126492
|
warn(`omni CLI updated to v${latest}, but health check failed on port ${result.apiPort}. Run \`omni status\`.`);
|
|
126206
|
-
|
|
126493
|
+
finalize(1);
|
|
126207
126494
|
break;
|
|
126208
126495
|
case "version-mismatch":
|
|
126209
126496
|
console.error(`${source_default.red("\u2717")} ${updateErrorVersionMismatch(result.cliVersion, result.serverVersion)}`);
|
|
126210
|
-
|
|
126497
|
+
finalize(1);
|
|
126211
126498
|
break;
|
|
126212
126499
|
case "auth-invalid":
|
|
126213
126500
|
console.error(`${source_default.red("\u2717")} ${UPDATE_ERROR_AUTH_INVALID}`);
|
|
126214
|
-
|
|
126501
|
+
finalize(1);
|
|
126215
126502
|
break;
|
|
126216
126503
|
}
|
|
126217
126504
|
}
|
|
@@ -126288,20 +126575,35 @@ async function runUpdate(options3) {
|
|
|
126288
126575
|
if (options3.next || options3.stable) {
|
|
126289
126576
|
persistChannel(channel2);
|
|
126290
126577
|
}
|
|
126578
|
+
const currentClean = VERSION.split("+")[0];
|
|
126579
|
+
const diagnostics = createDiagnostics({ runningVersion: currentClean, channel: channel2 });
|
|
126580
|
+
const finalize = (exitCode) => {
|
|
126581
|
+
const path = writeDiagnostics(diagnostics, exitCode);
|
|
126582
|
+
if (path !== null && process.env.OMNI_UPDATE_DIAGNOSTICS_VERBOSE === "1") {
|
|
126583
|
+
info(`Diagnostics written: ${path}`);
|
|
126584
|
+
}
|
|
126585
|
+
process.exit(exitCode);
|
|
126586
|
+
};
|
|
126587
|
+
const parallelInstall = detectParallelNpmGlobalInstall();
|
|
126588
|
+
diagnostics.parallelNpmGlobal = parallelInstall;
|
|
126589
|
+
if (parallelInstall.detected && parallelInstall.path) {
|
|
126590
|
+
warn(`Parallel npm-global install of ${PACKAGE_NAME} detected at ${parallelInstall.path}. This may shadow the bun-installed binary on PATH. Recommended: npm uninstall -g ${PACKAGE_NAME}`);
|
|
126591
|
+
}
|
|
126291
126592
|
info(`Channel: ${channel2}${channel2 === "next" ? " (dev builds)" : " (stable)"}`);
|
|
126292
126593
|
const versionSpinner = ora(`Checking ${channel2} version of ${PACKAGE_NAME}...`).start();
|
|
126293
126594
|
const latest = await fetchLatestVersion(channel2);
|
|
126294
126595
|
versionSpinner.stop();
|
|
126596
|
+
diagnostics.registry.latestVersion = latest;
|
|
126295
126597
|
if (latest === null) {
|
|
126296
126598
|
warn("Could not reach npm registry. Check your network connection and try again.");
|
|
126297
|
-
|
|
126599
|
+
return finalize(1);
|
|
126298
126600
|
}
|
|
126299
|
-
const currentClean = VERSION.split("+")[0];
|
|
126300
126601
|
if (currentClean === latest) {
|
|
126301
126602
|
success(`Already up to date (v${latest}, channel: ${channel2})`);
|
|
126302
|
-
|
|
126603
|
+
return finalize(0);
|
|
126303
126604
|
}
|
|
126304
126605
|
if (!options3.skipCanonicalPreflight) {
|
|
126606
|
+
diagnostics.preflight.ran = true;
|
|
126305
126607
|
const serverConfig = loadServerConfig();
|
|
126306
126608
|
const preflightError = checkCanonicalPgservePreflight({
|
|
126307
126609
|
currentVersion: currentClean,
|
|
@@ -126310,8 +126612,11 @@ async function runUpdate(options3) {
|
|
|
126310
126612
|
pgserveOnPath: isPgserveOnPath()
|
|
126311
126613
|
});
|
|
126312
126614
|
if (preflightError !== null) {
|
|
126615
|
+
diagnostics.preflight.blocked = true;
|
|
126616
|
+
diagnostics.preflight.reason = preflightError.split(`
|
|
126617
|
+
`)[0];
|
|
126313
126618
|
warn(preflightError);
|
|
126314
|
-
|
|
126619
|
+
return finalize(1);
|
|
126315
126620
|
}
|
|
126316
126621
|
}
|
|
126317
126622
|
info(`Update available: v${currentClean} \u2192 v${latest} (${channel2})`);
|
|
@@ -126319,27 +126624,47 @@ async function runUpdate(options3) {
|
|
|
126319
126624
|
const confirmed = await promptConfirm(`Update from v${currentClean} to v${latest}? [Y/n] `);
|
|
126320
126625
|
if (!confirmed) {
|
|
126321
126626
|
info("Update cancelled.");
|
|
126322
|
-
|
|
126627
|
+
return finalize(0);
|
|
126323
126628
|
}
|
|
126324
126629
|
}
|
|
126325
126630
|
const servicesToRestart = options3.restart !== false ? getRunningPm2Services() : [];
|
|
126326
126631
|
const installSpinner = ora(`Updating ${PACKAGE_NAME}@${channel2}...`).start();
|
|
126632
|
+
diagnostics.install.attempted = true;
|
|
126633
|
+
diagnostics.install.targetVersion = latest;
|
|
126327
126634
|
const installed = await installLatest(channel2);
|
|
126328
126635
|
installSpinner.stop();
|
|
126636
|
+
diagnostics.install.succeeded = installed;
|
|
126329
126637
|
if (!installed) {
|
|
126330
126638
|
warn(`Installation failed. Your current version (v${currentClean}) is still intact.`);
|
|
126331
|
-
|
|
126639
|
+
return finalize(1);
|
|
126640
|
+
}
|
|
126641
|
+
const sidecarCleanupExplicit = options3.sidecarCleanup === false;
|
|
126642
|
+
if (sidecarCleanupExplicit) {
|
|
126643
|
+
info("--no-sidecar-cleanup (deprecated alias for --no-legacy-cleanup)");
|
|
126332
126644
|
}
|
|
126645
|
+
const legacyCleanupEnabled = options3.legacyCleanup !== false && options3.sidecarCleanup !== false;
|
|
126646
|
+
const skipList = parseSkipCleanupList(options3.skipCleanup);
|
|
126333
126647
|
if (servicesToRestart.length > 0) {
|
|
126334
126648
|
await restartServicesAndVerify(servicesToRestart, latest, {
|
|
126335
|
-
|
|
126336
|
-
|
|
126337
|
-
|
|
126338
|
-
|
|
126649
|
+
legacyCleanup: legacyCleanupEnabled,
|
|
126650
|
+
skipList,
|
|
126651
|
+
skipMaintenance: options3.skipMaintenance === true,
|
|
126652
|
+
skipVerify: options3.verify === false
|
|
126653
|
+
}, diagnostics, finalize);
|
|
126654
|
+
return finalize(0);
|
|
126655
|
+
}
|
|
126656
|
+
diagnostics.verify = decideVerify({ skipReason: "no-restart" });
|
|
126339
126657
|
success(`omni updated to v${latest}`);
|
|
126658
|
+
return finalize(0);
|
|
126659
|
+
}
|
|
126660
|
+
function parseSkipCleanupList(value) {
|
|
126661
|
+
if (!value)
|
|
126662
|
+
return new Set;
|
|
126663
|
+
const names = value.split(",").map((s2) => s2.trim()).filter((s2) => s2.length > 0);
|
|
126664
|
+
return new Set(names);
|
|
126340
126665
|
}
|
|
126341
126666
|
function createUpdateCommand() {
|
|
126342
|
-
return new Command("update").description(`Update ${PACKAGE_NAME} to the latest version (restart only services already running)`).option("-y, --yes", "Skip confirmation prompts (non-interactive)").option("--no-restart", "Update CLI only; skip service restarts and verification").option("--no-
|
|
126667
|
+
return new Command("update").description(`Update ${PACKAGE_NAME} to the latest version (restart only services already running)`).option("-y, --yes", "Skip confirmation prompts (non-interactive)").option("--no-restart", "Update CLI only; skip service restarts and verification").option("--no-verify", "Restart services but skip the post-restart probe (use when a release ships a broken /api/v2/health and operators need to roll forward)").option("--no-legacy-cleanup", "Skip every registered legacy-artifact cleanup (e.g. nats-reply-sidecar)").option("--no-sidecar-cleanup", "Deprecated alias for --no-legacy-cleanup").option("--skip-cleanup <names>", 'Comma-separated list of legacy-cleanup registry entries to skip (e.g. "nats-reply-sidecar")').option("--next", "Switch to dev builds (npm @next tag) and persist as default").option("--stable", "Switch to stable releases (npm @latest tag) and persist as default").option("--skip-canonical-preflight", "Bypass the canonical-pgserve phase-2 pre-flight (NOT recommended; for operators who pre-installed pgserve via a path the auto-detector misses)").option("--skip-maintenance", `Skip the post-update maintenance hook (read-only \`omni doctor\` sweep). Also honored via the ${OMNI_UPDATE_SKIP_MAINTENANCE_ENV} env var.`).addHelpText("after", `
|
|
126343
126668
|
Channels:
|
|
126344
126669
|
- stable (default) \u2014 tracks the npm @latest tag, bumped from main branch releases.
|
|
126345
126670
|
- next (dev builds) \u2014 tracks the npm @next tag, bumped on every CI-green dev merge.
|
|
@@ -126365,14 +126690,38 @@ Behavior:
|
|
|
126365
126690
|
"Server version mismatch: cli=v<X> server=v<Y>. Run: omni doctor"
|
|
126366
126691
|
- On auth failure, exits non-zero with:
|
|
126367
126692
|
"Auth key invalid after restart. Run: omni doctor --fix"
|
|
126368
|
-
- After a successful restart,
|
|
126369
|
-
|
|
126370
|
-
|
|
126371
|
-
|
|
126372
|
-
|
|
126693
|
+
- After a successful restart, runs every registered legacy-artifact cleanup.
|
|
126694
|
+
The day-one entry is nats-reply-sidecar: it scans for any legacy
|
|
126695
|
+
nats-reply-sidecar.mjs process (PM2-managed or raw) and stops it. The
|
|
126696
|
+
sidecar was an external workaround for bugs that were fixed in #362;
|
|
126697
|
+
leaving it running causes every agent reply to be delivered twice.
|
|
126698
|
+
Skip every cleanup with --no-legacy-cleanup, or skip a single registry
|
|
126699
|
+
entry with --skip-cleanup=<name1,name2>. The deprecated alias
|
|
126700
|
+
--no-sidecar-cleanup still works and behaves identically. Manual runbook:
|
|
126373
126701
|
docs/migration/nats-genie-sidecar-decommission.md
|
|
126374
126702
|
- Use --no-restart to skip restart + verification entirely. --no-restart
|
|
126375
|
-
also skips
|
|
126703
|
+
also skips legacy-artifact cleanup; manage those services manually.
|
|
126704
|
+
- Use --no-verify to restart services but skip the post-restart probe.
|
|
126705
|
+
The banner shows the new CLI version on both lines but tags Server /
|
|
126706
|
+
Auth as "(skipped)"; maintenance is auto-skipped because verify never
|
|
126707
|
+
confirmed health.
|
|
126708
|
+
- Detects parallel npm-global installs of ${PACKAGE_NAME} (omni installs
|
|
126709
|
+
via bun-global; an npm-global install hides stale binaries on PATH and
|
|
126710
|
+
confuses 'which omni'). When found, prints a one-line warning naming
|
|
126711
|
+
the offending path; recommended remediation: npm uninstall -g ${PACKAGE_NAME}.
|
|
126712
|
+
- Every invocation writes a diagnostics record to
|
|
126713
|
+
~/.omni/logs/update-diagnostics-<iso>.json (schemaVersion: 1). Captures
|
|
126714
|
+
install attempt, registry probe, restart outcome, verify result, cleanup
|
|
126715
|
+
registry result, maintenance hook, and a tail of pm2 log signals. Set
|
|
126716
|
+
OMNI_UPDATE_DIAGNOSTICS_VERBOSE=1 to print the path on completion. A
|
|
126717
|
+
failed write never changes the update exit code.
|
|
126718
|
+
- On a successful restart + verify, runs a post-update maintenance hook:
|
|
126719
|
+
a read-only \`omni doctor\` sweep that prints a one-line summary
|
|
126720
|
+
("Maintenance: <ok> ok, <warn> warn, <fail> fail"). The probe never
|
|
126721
|
+
mutates pm2 / config / DB state (\`omni doctor --fix\` remains the
|
|
126722
|
+
explicit operator action for repair). A failing maintenance call is
|
|
126723
|
+
non-fatal \u2014 exit code stays 0 with a banner warning. Skip with
|
|
126724
|
+
--skip-maintenance or ${OMNI_UPDATE_SKIP_MAINTENANCE_ENV}=1.
|
|
126376
126725
|
- Verify runtime health after update with: omni status
|
|
126377
126726
|
`).action(runUpdate);
|
|
126378
126727
|
}
|
|
@@ -126484,9 +126833,9 @@ function createVoiceCommand() {
|
|
|
126484
126833
|
const startTime = Date.now();
|
|
126485
126834
|
let saveDir = "";
|
|
126486
126835
|
if (opts.save) {
|
|
126487
|
-
const { mkdirSync:
|
|
126836
|
+
const { mkdirSync: mkdirSync11 } = await import("fs");
|
|
126488
126837
|
saveDir = opts.save;
|
|
126489
|
-
|
|
126838
|
+
mkdirSync11(saveDir, { recursive: true });
|
|
126490
126839
|
info(`Saving audio to: ${saveDir}`);
|
|
126491
126840
|
}
|
|
126492
126841
|
ws.onopen = () => {
|
|
@@ -126710,17 +127059,17 @@ init_config();
|
|
|
126710
127059
|
init_output();
|
|
126711
127060
|
|
|
126712
127061
|
// src/manifest-pin.ts
|
|
126713
|
-
import { existsSync as
|
|
126714
|
-
import { homedir as
|
|
126715
|
-
import { join as
|
|
127062
|
+
import { existsSync as existsSync18, readFileSync as readFileSync12, renameSync as renameSync3, writeFileSync as writeFileSync10 } from "fs";
|
|
127063
|
+
import { homedir as homedir12 } from "os";
|
|
127064
|
+
import { join as join17 } from "path";
|
|
126716
127065
|
var PACKAGE_NAME2 = "@automagik/omni";
|
|
126717
|
-
var BUN_GLOBAL_MANIFEST =
|
|
127066
|
+
var BUN_GLOBAL_MANIFEST = join17(homedir12(), ".bun", "install", "global", "package.json");
|
|
126718
127067
|
function pinManifestEntry(manifestPath, exactVersion) {
|
|
126719
|
-
if (!
|
|
127068
|
+
if (!existsSync18(manifestPath))
|
|
126720
127069
|
return false;
|
|
126721
127070
|
let manifest;
|
|
126722
127071
|
try {
|
|
126723
|
-
manifest = JSON.parse(
|
|
127072
|
+
manifest = JSON.parse(readFileSync12(manifestPath, "utf-8"));
|
|
126724
127073
|
} catch {
|
|
126725
127074
|
return false;
|
|
126726
127075
|
}
|
|
@@ -126746,7 +127095,7 @@ function pinManifestEntry(manifestPath, exactVersion) {
|
|
|
126746
127095
|
return false;
|
|
126747
127096
|
const tmp = `${manifestPath}.tmp.${process.pid}`;
|
|
126748
127097
|
try {
|
|
126749
|
-
|
|
127098
|
+
writeFileSync10(tmp, `${JSON.stringify(manifest, null, 2)}
|
|
126750
127099
|
`, { mode: 420 });
|
|
126751
127100
|
renameSync3(tmp, manifestPath);
|
|
126752
127101
|
} catch {
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy artifact cleanup registry.
|
|
3
|
+
*
|
|
4
|
+
* Generalizes the bespoke `cleanupSidecars()` step in `omni update` into a
|
|
5
|
+
* registry of `LegacyArtifact` entries so future deprecation cleanups (e.g.
|
|
6
|
+
* obsolete WhatsApp baileys session formats, dead pm2 process names, stale
|
|
7
|
+
* config files) drop in without code changes to the update orchestration.
|
|
8
|
+
*
|
|
9
|
+
* The day-one entry is `nats-reply-sidecar`, which wraps the existing
|
|
10
|
+
* `cleanupSidecars()` / `cleanupSucceeded()` / `formatCleanupSummary()`
|
|
11
|
+
* helpers in `sidecar-cleanup.ts`. Operator-facing output is byte-identical
|
|
12
|
+
* to the pre-registry behavior — the registry only changes the dispatch.
|
|
13
|
+
*
|
|
14
|
+
* Public shape mirrors the genie wish (independent code, identical signature
|
|
15
|
+
* per SHARED-DESIGN.md decision #3).
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* One legacy artifact eligible for cleanup. Implementations are stateful:
|
|
19
|
+
* `cleanup()` may stash the raw result so `summary()` can render it.
|
|
20
|
+
*/
|
|
21
|
+
export interface LegacyArtifact {
|
|
22
|
+
readonly name: string;
|
|
23
|
+
/**
|
|
24
|
+
* Best-effort fast probe — return true if cleanup() should be run. Returning
|
|
25
|
+
* false is reserved for hard short-circuits (e.g. the artifact's namespace
|
|
26
|
+
* doesn't exist on this OS). If detection itself is cheap relative to
|
|
27
|
+
* cleanup, implementations may simply return true and let the empty-case
|
|
28
|
+
* path in cleanup() produce an empty summary.
|
|
29
|
+
*/
|
|
30
|
+
detect(): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Run the cleanup. Returns the user-visible artifacts (`removed`) and any
|
|
33
|
+
* non-fatal problems (`warnings`). Implementations should never throw —
|
|
34
|
+
* the registry treats a thrown error as "warning, succeeded=false".
|
|
35
|
+
*/
|
|
36
|
+
cleanup(): Promise<{
|
|
37
|
+
removed: string[];
|
|
38
|
+
warnings: string[];
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Human-readable multi-line summary of the most recent cleanup() call.
|
|
42
|
+
* Empty string when nothing happened (so the caller can suppress the block).
|
|
43
|
+
*/
|
|
44
|
+
summary(): string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Per-artifact outcome captured in the report.
|
|
48
|
+
*/
|
|
49
|
+
export interface ArtifactOutcome {
|
|
50
|
+
readonly name: string;
|
|
51
|
+
readonly state: 'ran' | 'skipped' | 'not-detected' | 'errored';
|
|
52
|
+
readonly removed: string[];
|
|
53
|
+
readonly warnings: string[];
|
|
54
|
+
readonly summary: string;
|
|
55
|
+
readonly error?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Aggregate cleanup outcome across the registry. Consumed by diagnostics
|
|
59
|
+
* (Group 4) and by the update banner ("warn loudly when a cleanup partially
|
|
60
|
+
* failed").
|
|
61
|
+
*/
|
|
62
|
+
export interface CleanupReport {
|
|
63
|
+
readonly outcomes: ArtifactOutcome[];
|
|
64
|
+
/** True iff every ran artifact reported zero warnings AND nothing errored. */
|
|
65
|
+
readonly succeeded: boolean;
|
|
66
|
+
/** Names that were skipped via `skipList`. */
|
|
67
|
+
readonly skipped: string[];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The live registry. Order matters — artifacts run sequentially so an earlier
|
|
71
|
+
* cleanup's side effects are visible to a later one (e.g. stopping a process
|
|
72
|
+
* before deleting its config file).
|
|
73
|
+
*
|
|
74
|
+
* To add a new artifact:
|
|
75
|
+
* 1. Implement `LegacyArtifact` (idempotent, never-throws).
|
|
76
|
+
* 2. Append a factory call below.
|
|
77
|
+
* 3. Add a unit test that runs the registry round-trip.
|
|
78
|
+
* 4. Document the deprecation in `docs/migration/`.
|
|
79
|
+
*/
|
|
80
|
+
export declare const REGISTRY: LegacyArtifact[];
|
|
81
|
+
export declare function cleanupLegacyArtifacts(skipList: Set<string>): Promise<CleanupReport>;
|
|
82
|
+
//# sourceMappingURL=legacy-cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-cleanup.d.ts","sourceRoot":"","sources":["../src/legacy-cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC9D;;;OAGG;IACH,OAAO,IAAI,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,cAAc,GAAG,SAAS,CAAC;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAC;IACrC,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;CAC5B;AA+CD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,EAAE,cAAc,EAAuC,CAAC;AA2D7E,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAuB1F"}
|
package/dist/server/index.js
CHANGED
|
@@ -224688,7 +224688,7 @@ var init_sentry_scrub = __esm(() => {
|
|
|
224688
224688
|
var require_package8 = __commonJS((exports, module) => {
|
|
224689
224689
|
module.exports = {
|
|
224690
224690
|
name: "@omni/api",
|
|
224691
|
-
version: "2.
|
|
224691
|
+
version: "2.260505.2",
|
|
224692
224692
|
type: "module",
|
|
224693
224693
|
exports: {
|
|
224694
224694
|
".": {
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update diagnostics capture.
|
|
3
|
+
*
|
|
4
|
+
* Every `omni update` invocation writes a structured JSON report to
|
|
5
|
+
* `~/.omni/logs/update-diagnostics-<iso>.json` capturing the install attempt,
|
|
6
|
+
* registry probe, restart, verify outcome, cleanup registry result,
|
|
7
|
+
* maintenance hook, and a tail of recent pm2 log signals. The file is the
|
|
8
|
+
* canonical post-mortem artifact: operators paste it into bug reports; the
|
|
9
|
+
* shape mirrors the genie wish (independent code, parity per
|
|
10
|
+
* `SHARED-DESIGN.md` decision #3) so a shared diagnostics consumer can read
|
|
11
|
+
* either CLI's output uniformly. omni starts at `schemaVersion: 1` (decision
|
|
12
|
+
* #4 in the wish: per-repo schema versions are intentionally asymmetric).
|
|
13
|
+
*
|
|
14
|
+
* The writer is best-effort: any failure (no perms, disk full, etc.) is
|
|
15
|
+
* swallowed so update never exits non-zero because diagnostics couldn't be
|
|
16
|
+
* persisted.
|
|
17
|
+
*/
|
|
18
|
+
import type { MaintenanceReport, UpdateChannel, VerifyResult } from './commands/update.js';
|
|
19
|
+
import type { CleanupReport } from './legacy-cleanup.js';
|
|
20
|
+
/** Stable schema version for omni-side update diagnostics. */
|
|
21
|
+
export declare const UPDATE_DIAGNOSTICS_SCHEMA_VERSION: 1;
|
|
22
|
+
/** Captured tail of one pm2 log file (best-effort). */
|
|
23
|
+
export interface LogSignal {
|
|
24
|
+
/** Tracked pm2 process name (e.g. `omni-v2-api`). */
|
|
25
|
+
source: string;
|
|
26
|
+
/** Which file (`out` or `error`). */
|
|
27
|
+
stream: 'out' | 'error';
|
|
28
|
+
/** Up to N most recent lines, oldest first. Empty when the file does not exist. */
|
|
29
|
+
lines: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Outcome of the parallel npm-global install probe (Group 5a). Omni doesn't
|
|
33
|
+
* support npm-global server, but a parallel install hides stale binaries on
|
|
34
|
+
* PATH and confuses `which omni`. Captured here so a future bug report
|
|
35
|
+
* includes the smoking-gun path.
|
|
36
|
+
*/
|
|
37
|
+
export interface ParallelInstallReport {
|
|
38
|
+
detected: boolean;
|
|
39
|
+
/** Filesystem path to the parallel install (when detected). */
|
|
40
|
+
path?: string;
|
|
41
|
+
/** Reason detection couldn't run, e.g. `npm` not on PATH. */
|
|
42
|
+
skipped?: string;
|
|
43
|
+
}
|
|
44
|
+
/** Top-level diagnostics record. */
|
|
45
|
+
export interface UpdateDiagnostics {
|
|
46
|
+
readonly schemaVersion: typeof UPDATE_DIAGNOSTICS_SCHEMA_VERSION;
|
|
47
|
+
/** ISO-8601 timestamp the run started at (filename derives from this). */
|
|
48
|
+
startedAt: string;
|
|
49
|
+
/** ISO-8601 timestamp diagnostics was finalized (= just before write). */
|
|
50
|
+
finishedAt: string;
|
|
51
|
+
cli: {
|
|
52
|
+
/** CLI version executing this update (the previous one — install hasn't restarted us). */
|
|
53
|
+
runningVersion: string;
|
|
54
|
+
channel: UpdateChannel;
|
|
55
|
+
};
|
|
56
|
+
registry: {
|
|
57
|
+
latestVersion: string | null;
|
|
58
|
+
};
|
|
59
|
+
preflight: {
|
|
60
|
+
/** Did the canonical-pgserve phase-2 check run? False when `--skip-canonical-preflight`. */
|
|
61
|
+
ran: boolean;
|
|
62
|
+
/** Did the check return a blocking error? When true, the run aborted. */
|
|
63
|
+
blocked: boolean;
|
|
64
|
+
/** First line of the rendered error message, when blocked. */
|
|
65
|
+
reason?: string;
|
|
66
|
+
};
|
|
67
|
+
install: {
|
|
68
|
+
attempted: boolean;
|
|
69
|
+
succeeded: boolean | null;
|
|
70
|
+
targetVersion: string | null;
|
|
71
|
+
};
|
|
72
|
+
restart: {
|
|
73
|
+
attempted: boolean;
|
|
74
|
+
succeeded: boolean | null;
|
|
75
|
+
services: string[];
|
|
76
|
+
};
|
|
77
|
+
verify: VerifyResult | null;
|
|
78
|
+
cleanups: CleanupReport | null;
|
|
79
|
+
maintenance: MaintenanceReport | null;
|
|
80
|
+
parallelNpmGlobal: ParallelInstallReport | null;
|
|
81
|
+
recentLogSignals: LogSignal[];
|
|
82
|
+
/** Final exit code — populated by the writer; useful for bug-report triage. */
|
|
83
|
+
exitCode: number;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Build a fresh diagnostics state with the invariant fields populated.
|
|
87
|
+
* Mutated in-place by `runUpdate` as it advances through the pipeline.
|
|
88
|
+
*/
|
|
89
|
+
export declare function createDiagnostics(args: {
|
|
90
|
+
runningVersion: string;
|
|
91
|
+
channel: UpdateChannel;
|
|
92
|
+
}): UpdateDiagnostics;
|
|
93
|
+
/** Get the directory diagnostics are written to. Honors `OMNI_CONFIG_DIR`. */
|
|
94
|
+
export declare function getDiagnosticsDir(): string;
|
|
95
|
+
/**
|
|
96
|
+
* Compute the canonical filename for a diagnostics record. The ISO timestamp
|
|
97
|
+
* is sanitized to be filename-safe (`:` → `-`).
|
|
98
|
+
*/
|
|
99
|
+
export declare function getDiagnosticsPath(startedAt: string): string;
|
|
100
|
+
/**
|
|
101
|
+
* Read the last `maxLines` lines of a UTF-8 text file. Best-effort: returns
|
|
102
|
+
* an empty array on any error (missing file, perms, decoding issue).
|
|
103
|
+
*
|
|
104
|
+
* Implementation notes:
|
|
105
|
+
* - We slurp the whole file (pm2 log files are small in steady state and
|
|
106
|
+
* log-rotated by pm2-logrotate; reading the whole thing is simpler than
|
|
107
|
+
* a reverse-byte tail and avoids edge cases on multi-byte UTF-8).
|
|
108
|
+
* - Trailing empty line from a trailing newline is dropped.
|
|
109
|
+
*/
|
|
110
|
+
export declare function tailFileLines(path: string, maxLines: number): string[];
|
|
111
|
+
/**
|
|
112
|
+
* Collect the most recent log lines from each tracked pm2 process. Skips
|
|
113
|
+
* processes whose log files don't exist (i.e. that have never run on this
|
|
114
|
+
* host). Limited to `maxLinesPerStream` per file to keep diagnostics small.
|
|
115
|
+
*
|
|
116
|
+
* `logPathsFor` is injectable so tests can point at a tmp dir without
|
|
117
|
+
* touching the developer's real `~/.omni/logs` (pm2 log paths don't honor
|
|
118
|
+
* `OMNI_CONFIG_DIR` and we'd rather not change that surface here).
|
|
119
|
+
*
|
|
120
|
+
* This is best-effort and called from the diagnostics writer; never throws.
|
|
121
|
+
*/
|
|
122
|
+
export declare function collectRecentLogSignals(maxLinesPerStream?: number, logPathsFor?: (name: string) => {
|
|
123
|
+
out: string;
|
|
124
|
+
error: string;
|
|
125
|
+
}): LogSignal[];
|
|
126
|
+
/**
|
|
127
|
+
* Persist the diagnostics record to `~/.omni/logs/update-diagnostics-*.json`.
|
|
128
|
+
* Returns the path that was written (or null on failure). Never throws —
|
|
129
|
+
* diagnostics is observability, not load-bearing for the update outcome.
|
|
130
|
+
*
|
|
131
|
+
* The exit code is captured into `state.exitCode` and the timestamp into
|
|
132
|
+
* `state.finishedAt` before serialization so the JSON file is a complete
|
|
133
|
+
* snapshot at write time.
|
|
134
|
+
*/
|
|
135
|
+
export declare function writeDiagnostics(state: UpdateDiagnostics, exitCode: number): string | null;
|
|
136
|
+
//# sourceMappingURL=update-diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-diagnostics.d.ts","sourceRoot":"","sources":["../src/update-diagnostics.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automagik/omni",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.260505.2",
|
|
4
4
|
"description": "LLM-optimized CLI for Omni",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -51,15 +51,15 @@
|
|
|
51
51
|
"qrcode-terminal": "^0.12.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@omni/api": "2.
|
|
55
|
-
"@omni/channel-discord": "2.
|
|
56
|
-
"@omni/channel-gupshup": "2.
|
|
57
|
-
"@omni/channel-sdk": "2.
|
|
58
|
-
"@omni/channel-slack": "2.
|
|
59
|
-
"@omni/channel-telegram": "2.
|
|
60
|
-
"@omni/channel-whatsapp": "2.
|
|
61
|
-
"@omni/core": "2.
|
|
62
|
-
"@omni/sdk": "2.
|
|
54
|
+
"@omni/api": "2.260505.1",
|
|
55
|
+
"@omni/channel-discord": "2.260505.1",
|
|
56
|
+
"@omni/channel-gupshup": "2.260505.1",
|
|
57
|
+
"@omni/channel-sdk": "2.260505.1",
|
|
58
|
+
"@omni/channel-slack": "2.260505.1",
|
|
59
|
+
"@omni/channel-telegram": "2.260505.1",
|
|
60
|
+
"@omni/channel-whatsapp": "2.260505.1",
|
|
61
|
+
"@omni/core": "2.260505.1",
|
|
62
|
+
"@omni/sdk": "2.260505.1",
|
|
63
63
|
"@types/node": "^22.10.3",
|
|
64
64
|
"@types/qrcode-terminal": "^0.12.2",
|
|
65
65
|
"typescript": "^5.7.3"
|