@danypops/pi-packed 0.27.12 → 0.27.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/adoption/check.d.ts +54 -0
  2. package/dist/adoption/check.d.ts.map +1 -0
  3. package/dist/adoption/duplicate-dependency-doctor.d.ts +17 -0
  4. package/dist/adoption/duplicate-dependency-doctor.d.ts.map +1 -0
  5. package/dist/adoption/install-validation.d.ts +63 -0
  6. package/dist/adoption/install-validation.d.ts.map +1 -0
  7. package/dist/adoption/module-freshness.d.ts +39 -0
  8. package/dist/adoption/module-freshness.d.ts.map +1 -0
  9. package/dist/adoption/service-doctor.d.ts +21 -0
  10. package/dist/adoption/service-doctor.d.ts.map +1 -0
  11. package/dist/adoption/smoke.d.ts +39 -0
  12. package/dist/adoption/smoke.d.ts.map +1 -0
  13. package/dist/daemon/daemon-service.d.ts +281 -0
  14. package/dist/daemon/daemon-service.d.ts.map +1 -0
  15. package/dist/doctor-format.js +16 -0
  16. package/dist/packages/installed.d.ts +32 -0
  17. package/dist/packages/installed.d.ts.map +1 -0
  18. package/dist/packages/package.d.ts +272 -0
  19. package/dist/packages/package.d.ts.map +1 -0
  20. package/dist/public/client.d.ts.map +1 -0
  21. package/dist/public/doctor-format.d.ts +57 -0
  22. package/dist/public/doctor-format.d.ts.map +1 -0
  23. package/dist/public/protocol.d.ts.map +1 -0
  24. package/dist/publish/publish.d.ts +120 -0
  25. package/dist/publish/publish.d.ts.map +1 -0
  26. package/dist/shared/constants.d.ts +51 -0
  27. package/dist/shared/constants.d.ts.map +1 -0
  28. package/extension/src/doctor-render.ts +32 -0
  29. package/extension/src/vehicle-tools.ts +16 -0
  30. package/package.json +8 -4
  31. package/service/src/adoption/doctor.ts +12 -77
  32. package/service/src/public/doctor-format.ts +89 -0
  33. package/service/test/public-boundary.test.ts +5 -1
  34. package/service/tsconfig.public.json +11 -2
  35. package/dist/client.d.ts.map +0 -1
  36. package/dist/protocol.d.ts.map +0 -1
  37. /package/dist/{client.d.ts → public/client.d.ts} +0 -0
  38. /package/dist/{protocol.d.ts → public/protocol.d.ts} +0 -0
@@ -0,0 +1,54 @@
1
+ import { type ExtensionSmokeResult } from "./smoke.ts";
2
+ export type DiagnosticSeverity = "error" | "warning" | "info";
3
+ export interface Diagnostic {
4
+ code: string;
5
+ severity: DiagnosticSeverity;
6
+ path: string;
7
+ message: string;
8
+ fix?: string;
9
+ }
10
+ export interface CheckReport {
11
+ root: string;
12
+ ok: boolean;
13
+ diagnostics: Diagnostic[];
14
+ summary: {
15
+ errors: number;
16
+ warnings: number;
17
+ info: number;
18
+ };
19
+ checkedFiles: number;
20
+ truncated: boolean;
21
+ smoke?: {
22
+ extensions: ExtensionSmokeResult[];
23
+ };
24
+ }
25
+ export interface CheckOptions {
26
+ generic?: boolean;
27
+ smoke?: boolean;
28
+ maxDiagnostics?: number;
29
+ maxFiles?: number;
30
+ }
31
+ export interface PackageChecker {
32
+ check(packagePath: string, options?: CheckOptions): Promise<CheckReport>;
33
+ }
34
+ export declare class StaticPackageChecker implements PackageChecker {
35
+ check(packagePath: string, options?: CheckOptions): Promise<CheckReport>;
36
+ }
37
+ declare const RESOURCE_FIELDS: readonly ["extensions", "skills", "prompts", "themes"];
38
+ export declare function walk(root: string, maxFiles: number, bundledRoots: string[]): {
39
+ files: string[];
40
+ truncated: boolean;
41
+ };
42
+ export declare function matchesPattern(file: string, pattern: string): boolean;
43
+ export declare function isContainedFile(root: string, file: string): boolean;
44
+ export type ResourceField = (typeof RESOURCE_FIELDS)[number];
45
+ /** Pure discovery: which shipped files a package's own manifest (or
46
+ * conventional-directory fallback) declares as extensions/skills/prompts/
47
+ * themes, after the same extension-type and containment filtering
48
+ * resourcesCheck diagnoses -- without the diagnostics. Used by the
49
+ * package-resource overlay to know what there is to enable or disable. */
50
+ export declare function discoverPackageResources(root: string, pkg: Record<string, unknown>, files: string[]): Record<ResourceField, string[]>;
51
+ export declare function checkPackage(packagePath: string, options?: CheckOptions): Promise<CheckReport>;
52
+ export declare function formatCheckReport(report: CheckReport, json: boolean): string;
53
+ export {};
54
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../service/src/adoption/check.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,oBAAoB,EAAqB,MAAM,YAAY,CAAC;AAE1E,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE;QAAE,UAAU,EAAE,oBAAoB,EAAE,CAAA;KAAE,CAAC;CAC/C;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC9B,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACzE;AAED,qBAAa,oBAAqB,YAAW,cAAc;IAC1D,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;CAGxE;AAyBD,QAAA,MAAM,eAAe,wDAAyD,CAAC;AA0B/E,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAoCpH;AAsCD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAIrE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOnE;AA4FD,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D;;;;0EAI0E;AAC1E,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC,CAYrI;AAueD,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CA6GxG;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAwB5E"}
@@ -0,0 +1,17 @@
1
+ export interface DuplicateDependencyLocation {
2
+ readonly path: string;
3
+ readonly version: string;
4
+ }
5
+ export interface DuplicateDependencyDiagnostic {
6
+ readonly name: string;
7
+ readonly locations: readonly DuplicateDependencyLocation[];
8
+ }
9
+ /**
10
+ * Every @danypops/<name> resolved to more than one distinct version
11
+ * anywhere under piHome/npm/node_modules -- sorted by name for stable
12
+ * output. Two locations at the SAME version are never reported (npm simply
13
+ * didn't need to hoist further, not a real split); only an actual version
14
+ * disagreement is.
15
+ */
16
+ export declare function findDuplicateDependencyVersions(piHome: string): DuplicateDependencyDiagnostic[];
17
+ //# sourceMappingURL=duplicate-dependency-doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicate-dependency-doctor.d.ts","sourceRoot":"","sources":["../../service/src/adoption/duplicate-dependency-doctor.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,6BAA6B;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,SAAS,2BAA2B,EAAE,CAAC;CAC3D;AAqDD;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,MAAM,GAAG,6BAA6B,EAAE,CAgB/F"}
@@ -0,0 +1,63 @@
1
+ export interface ExtensionLoadResult {
2
+ path: string;
3
+ ok: boolean;
4
+ message?: string;
5
+ /** Non-gating: @danypops/vehicle-client-pi's pi-load-harness checks two
6
+ * further Pi extension load paths (native ESM, jiti tryNative:false)
7
+ * beyond the one path above (jiti tryNative:true) already gates install.
8
+ * Surfaced as observational evidence only, for two independent reasons:
9
+ * (1) native-esm can legitimately fail for a perfectly loadable extension
10
+ * on an older Node without TS type-stripping support, with no real-world
11
+ * signal yet on how often that's a false alarm; (2) this check only
12
+ * verifies the module *imports* cleanly -- unlike the gating check above,
13
+ * it never calls the extension's exported factory, so it cannot catch a
14
+ * factory that throws once actually registered (confirmed directly: the
15
+ * BROKEN test fixture, whose factory always throws, reports ok:true on
16
+ * every one of these paths). Complementary evidence for an import-time
17
+ * failure class, not a broader replacement for the gating check. */
18
+ additionalLoadPaths?: PiLoadPathResult[];
19
+ }
20
+ export interface PiLoadPathResult {
21
+ path: "native-esm" | "jiti-try-native-false" | "jiti-try-native-true";
22
+ ok: boolean;
23
+ error?: string;
24
+ }
25
+ export interface InstallValidationResult {
26
+ ok: boolean;
27
+ source: string;
28
+ extensions: ExtensionLoadResult[];
29
+ message?: string;
30
+ }
31
+ export interface InstallValidator {
32
+ validate(source: string): Promise<InstallValidationResult>;
33
+ }
34
+ /**
35
+ * Shared with ExecInstaller.install() (the single ad hoc path, which validates then commits
36
+ * itself) and SetupManager.apply() (the batch path, which validates every package change
37
+ * concurrently via Installer.validate() before ever calling installOnly() on any of them) --
38
+ * one formatting rule for "why was this install refused", not two copies that could drift.
39
+ */
40
+ export declare function assertInstallValidationOk(validation: InstallValidationResult): void;
41
+ /** Strips packed's own "npm:" scheme -- what npm pack itself expects is a
42
+ * bare registry spec (name, name@version) or a local path. Returns
43
+ * undefined for git:/https:/local sources: nothing here to stage from an
44
+ * npm tarball, so headless validation is out of scope for them. */
45
+ export declare function bareNpmSpec(source: string): string | undefined;
46
+ /** Runs pi-extension-harness's mock-pi-cli against one extension entry
47
+ * point, in its own load-only mode (--tool omitted): a real, isolated
48
+ * subprocess exercising Pi's own production jiti load path. */
49
+ export declare function validateExtensionLoadsHeadless(entryPath: string, timeoutMs?: number): Promise<ExtensionLoadResult>;
50
+ /** Stages the real npm tarball in isolation and headlessly load-checks
51
+ * every pi.extensions entry it declares. A non-npm source has nothing to
52
+ * stage and passes through as ok. A package with no pi.extensions passes
53
+ * only if it declares some other pi manifest resource (skills/prompts/
54
+ * themes) or has a matching pi convention directory on disk -- otherwise
55
+ * it isn't a Pi package at all (a plain npm dependency like is-number or
56
+ * is-buffer) and is refused rather than silently admitted as a dead
57
+ * `packages` entry pi itself would never load anything from. */
58
+ export declare class HeadlessInstallValidator implements InstallValidator {
59
+ private readonly timeoutMs?;
60
+ constructor(timeoutMs?: number | undefined);
61
+ validate(source: string): Promise<InstallValidationResult>;
62
+ }
63
+ //# sourceMappingURL=install-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-validation.d.ts","sourceRoot":"","sources":["../../service/src/adoption/install-validation.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;wEAYoE;IACpE,mBAAmB,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,YAAY,GAAG,uBAAuB,GAAG,sBAAsB,CAAC;IACtE,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACvC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAC3D;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,uBAAuB,GAAG,IAAI,CAOnF;AAkFD;;;mEAGmE;AACnE,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE9D;AAkED;;+DAE+D;AAC/D,wBAAsB,8BAA8B,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAmCxH;AAwBD;;;;;;;gEAOgE;AAChE,qBAAa,wBAAyB,YAAW,gBAAgB;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAV,SAAS,CAAC,EAAE,MAAM,YAAA;IAEzC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAgEhE"}
@@ -0,0 +1,39 @@
1
+ export interface LoadedModuleSnapshot {
2
+ readonly name: string;
3
+ readonly packageJsonPath: string;
4
+ readonly version?: string;
5
+ readonly mtimeMs?: number;
6
+ }
7
+ export interface ModuleFreshnessDiagnostic {
8
+ readonly name: string;
9
+ readonly loadedVersion?: string;
10
+ readonly currentVersion?: string;
11
+ /** True only when both mtimes are known and genuinely differ -- never a
12
+ * guess from version alone (a version string can stay identical across
13
+ * a same-version reinstall that still replaced the file, and not every
14
+ * package bumps a version for a local/dev iteration). */
15
+ readonly stale: boolean;
16
+ }
17
+ /**
18
+ * Resolves `name`'s real installed package.json via Node's own module
19
+ * resolution (see smoke.ts's resolveDependencyModulesDir -- correct for
20
+ * both a nested and a hoisted layout, never executes anything) starting
21
+ * from `fromDir`, then records its version/mtime. undefined when `name`
22
+ * isn't resolvable from here at all -- never thrown, so one unresolvable
23
+ * watched name never prevents capturing the rest.
24
+ */
25
+ export declare function captureLoadedModule(fromDir: string, name: string): LoadedModuleSnapshot | undefined;
26
+ /** Bulk capture, skipping (not failing on) any name that isn't resolvable. */
27
+ export declare function captureLoadedModules(fromDir: string, names: readonly string[]): LoadedModuleSnapshot[];
28
+ export declare function checkModuleFreshness(snapshot: LoadedModuleSnapshot): ModuleFreshnessDiagnostic;
29
+ export declare function checkModuleFreshnessAll(snapshots: readonly LoadedModuleSnapshot[]): ModuleFreshnessDiagnostic[];
30
+ /** The exact set of names worth watching for a long-running process: its
31
+ * own direct runtime dependencies (package.json's "dependencies" field) --
32
+ * the ones a static top-level import actually loads once at process start.
33
+ * devDependencies/peerDependencies are never loaded by the running process
34
+ * itself, so watching them would only ever report false staleness. Bounded
35
+ * the same way readPackageDeclarations elsewhere in this codebase bounds
36
+ * an untrusted-shape read -- never throws on a malformed package.json,
37
+ * just reports nothing to watch. */
38
+ export declare function ownRuntimeDependencyNames(packageJsonPath: string, maxNames?: number): string[];
39
+ //# sourceMappingURL=module-freshness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-freshness.d.ts","sourceRoot":"","sources":["../../service/src/adoption/module-freshness.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;6DAGyD;IACzD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACxB;AAYD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAKnG;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,oBAAoB,EAAE,CAOtG;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,yBAAyB,CAI9F;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,SAAS,oBAAoB,EAAE,GAAG,yBAAyB,EAAE,CAE/G;AAED;;;;;;;oCAOoC;AACpC,wBAAgB,yBAAyB,CAAC,eAAe,EAAE,MAAM,EAAE,QAAQ,SAAM,GAAG,MAAM,EAAE,CAQ3F"}
@@ -0,0 +1,21 @@
1
+ import type { ServiceInstallDeps } from "@danypops/vehicle-server/service";
2
+ export interface ServiceUnitDiagnostic {
3
+ code: "SERVICE_EXEC_PATH_MISSING" | "SERVICE_NOT_RUNNING" | "SERVICE_STATUS_UNAVAILABLE" | "SERVICE_STALE_CODE";
4
+ severity: "error" | "warning";
5
+ package: string;
6
+ unitName: string;
7
+ message: string;
8
+ }
9
+ export interface ServiceDoctorReport {
10
+ ok: boolean;
11
+ diagnostics: ServiceUnitDiagnostic[];
12
+ checked: number;
13
+ }
14
+ export interface ServiceDoctorDeps extends ServiceInstallDeps {
15
+ fileExists(path: string): boolean;
16
+ /** Undefined (never throws) when the path doesn't exist or can't be stat'd. */
17
+ getMtimeMs(path: string): number | undefined;
18
+ }
19
+ export declare function checkServiceUnitPaths(piHome: string, projectRoot: string | undefined, deps: ServiceDoctorDeps): ServiceDoctorReport;
20
+ export declare function formatServiceDoctorReport(report: ServiceDoctorReport, json: boolean): string;
21
+ //# sourceMappingURL=service-doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-doctor.d.ts","sourceRoot":"","sources":["../../service/src/adoption/service-doctor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAI3E,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,2BAA2B,GAAG,qBAAqB,GAAG,4BAA4B,GAAG,oBAAoB,CAAC;IAChH,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,qBAAqB,EAAE,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC5D,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,+EAA+E;IAC/E,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC7C;AAiBD,wBAAgB,qBAAqB,CACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,IAAI,EAAE,iBAAiB,GACrB,mBAAmB,CAqFrB;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,mBAAmB,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAO5F"}
@@ -0,0 +1,39 @@
1
+ export type SmokeStatus = "ok" | "timeout" | "crash" | "capability-denied" | "output-limit" | "sandbox-unavailable";
2
+ export interface SmokeRegistrations {
3
+ tools: string[];
4
+ commands: string[];
5
+ shortcuts: string[];
6
+ flags: string[];
7
+ providers: string[];
8
+ events: string[];
9
+ renderers: string[];
10
+ }
11
+ export interface ExtensionSmokeResult {
12
+ path: string;
13
+ status: SmokeStatus;
14
+ durationMs: number;
15
+ registrations: SmokeRegistrations;
16
+ message?: string;
17
+ }
18
+ export interface SmokeOptions {
19
+ timeoutMs?: number;
20
+ maxOutputBytes?: number;
21
+ maxProcesses?: number;
22
+ }
23
+ /**
24
+ * Resolves an installed dependency's real on-disk package directory via
25
+ * Node's own module-resolution algorithm (require.resolve against its
26
+ * package.json), starting from `fromDir` -- correct regardless of whether
27
+ * the package manager nested it under fromDir's own node_modules or
28
+ * hoisted it to a shared ancestor node_modules (npm's own hoisting
29
+ * decision, driven by what else in the tree also depends on it).
30
+ * Confirmed live: `packed doctor --json` crashed hard reconstructing a
31
+ * fixed nested-only path (`<packageDirectory>/node_modules/jiti`) that
32
+ * doesn't exist once jiti is hoisted to Pi's own npm prefix instead of
33
+ * pi-packed's own node_modules. Never executes the resolved module --
34
+ * require.resolve only locates a path, it never runs anything. undefined
35
+ * (not a throw) when genuinely unresolvable from here.
36
+ */
37
+ export declare function resolveDependencyModulesDir(fromDir: string, name: string): string | undefined;
38
+ export declare function runExtensionSmoke(packagePath: string, extensionFile: string, options?: SmokeOptions): Promise<ExtensionSmokeResult>;
39
+ //# sourceMappingURL=smoke.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke.d.ts","sourceRoot":"","sources":["../../service/src/adoption/smoke.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,GAAG,mBAAmB,GAAG,cAAc,GAAG,qBAAqB,CAAC;AAEpH,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,kBAAkB,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AA2BD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO7F;AA4ID,wBAAsB,iBAAiB,CACtC,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,YAAiB,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAoF/B"}
@@ -0,0 +1,281 @@
1
+ import { type VehicleRegistrar, type VehicleRegistrationOutcome, type VehicleSpec } from "@danypops/armada";
2
+ import { type ServiceInstallResult, type ServiceSpec } from "@danypops/vehicle-server/service";
3
+ import type { InstalledPkg } from "../packages/package.ts";
4
+ export interface DaemonServiceManifest {
5
+ /** Relative to the installed package's own root directory. */
6
+ binPath: string;
7
+ args?: string[];
8
+ /** Defaults to the bare npm package name (scope stripped). */
9
+ name?: string;
10
+ displayName?: string;
11
+ /** Runtime handle filename inside the Vehicle's XDG runtime directory. */
12
+ handleFilename?: string;
13
+ workingDirectory?: string;
14
+ restartOnFailure?: boolean;
15
+ restartSec?: number;
16
+ }
17
+ export type ResolveDaemonServiceResult = {
18
+ ok: true;
19
+ spec: ServiceSpec;
20
+ }
21
+ /** notADaemon: this package (and nothing one level into its own dependencies) is Vehicle-shaped at all -- the overwhelmingly common case for a non-daemon Pi package, distinct from a real failure (systemctl unavailable, spec resolved but install itself failed). A caller composing install + install-service (see cli.ts's `install` command) uses this to stay silent instead of surfacing a false alarm on every ordinary package install. */
22
+ | {
23
+ ok: false;
24
+ reason: string;
25
+ notADaemon?: boolean;
26
+ };
27
+ /** A resolved daemon entrypoint, already an absolute binPath -- the common shape both an explicit manifest and detection converge to before a ServiceSpec is built. */
28
+ interface ResolvedDaemonEntrypoint {
29
+ binPath: string;
30
+ args?: string[];
31
+ name: string;
32
+ displayName?: string;
33
+ handleFilename?: string;
34
+ workingDirectory?: string;
35
+ restartOnFailure?: boolean;
36
+ restartSec?: number;
37
+ version: string;
38
+ }
39
+ export declare function detectVehicleDaemonService(packageDir: string, fallbackName: string, hoistedNodeModulesDir?: string): ResolvedDaemonEntrypoint | undefined;
40
+ /**
41
+ * Resolves the installed package's daemon entrypoint -- an explicit
42
+ * `packed.daemonService` manifest first, then detectVehicleDaemonService()
43
+ * -- and builds the exact ServiceSpec its own `service install` command
44
+ * would build. npm sources only for now; git:/local sources resolve to a
45
+ * different on-disk layout not yet supported here.
46
+ */
47
+ export declare function resolveDaemonServiceSpec(piHome: string, source: string): ResolveDaemonServiceResult;
48
+ export interface DaemonDependencyPkg {
49
+ name: string;
50
+ version: string;
51
+ /** The Armada vehicle name resolveDaemonServiceSpec built for this package -- may differ
52
+ * from `name`'s own bare unscoped form when a packed.daemonService manifest overrides it. */
53
+ vehicleName: string;
54
+ }
55
+ /**
56
+ * Every top-level npm package physically installed under piHome/npm/node_modules
57
+ * that resolveDaemonServiceSpec() itself already recognizes as a real Vehicle-
58
+ * shaped daemon (an explicit packed.daemonService manifest, or
59
+ * detectVehicleDaemonService()'s own-bin-plus-real-vehicle-dependency
60
+ * convention), but that is NOT itself a pi:-configured extension
61
+ * (readPackageDeclarations() has no entry for it) -- e.g. @danypops/lector,
62
+ * added directly to piHome/npm/package.json as an independent pin so it can
63
+ * run ahead of whatever version its own pi-lector wrapper's dependency tree
64
+ * would otherwise resolve. These are real, running Armada vehicles that a
65
+ * pi:-manifest-only "installed packages" notion makes permanently invisible
66
+ * to `packed installed`/`packed update` -- see
67
+ * packed-package-update-restart-service-cant-manage.
68
+ *
69
+ * Deliberately does NOT walk one level into each configured extension's own
70
+ * dependencies the way resolveDaemonServiceSpec's own detection does for
71
+ * install-service/restart-service/doctor (service-doctor.ts's
72
+ * checkServiceUnitPaths already reaches that same dependency through its
73
+ * wrapper extension's own row) -- duplicating that walk here would
74
+ * double-report the same Vehicle under two different package names. This
75
+ * only reports a dependency independently resolvable BY ITS OWN NAME at
76
+ * piHome/npm's own top level -- exactly the shape a caller can actually run
77
+ * `packed update npm:<name>` against directly.
78
+ */
79
+ export declare function listUnconfiguredDaemonDependencies(piHome: string): DaemonDependencyPkg[];
80
+ /**
81
+ * True when `packageName` (a bare npm name) is a pi:-configured extension --
82
+ * present in readPackageDeclarations()'s own packages[] list, regardless of
83
+ * whether it's pinned. The other half of the classification
84
+ * classifyUpdateSource() needs: a name that resolves ok via
85
+ * resolveDaemonServiceSpec() but returns false here is a "daemon-dependency"
86
+ * class source, not an "extension" one.
87
+ */
88
+ export declare function isConfiguredExtension(piHome: string, packageName: string): boolean;
89
+ export type UpdateSourceKind = "extension" | "daemon-dependency";
90
+ /**
91
+ * Classifies an npm: source for package.update's own two-path mutation:
92
+ * "extension" (pi:-configured, settings.json's packages[] -- `pi update
93
+ * --extension` already handles this correctly, unchanged) vs.
94
+ * "daemon-dependency" (NOT pi:-configured, but resolveDaemonServiceSpec()
95
+ * resolves it directly BY ITS OWN NAME -- pi-core can never see this one;
96
+ * confirmed via this house's own failing-test repro, service/test/
97
+ * install.test.ts, of pi's real "No matching package found"). Needs the
98
+ * alternate npm-level mutation path (Installer.updateDaemonDependency())
99
+ * instead of shelling to `pi update --extension` at all.
100
+ *
101
+ * undefined for a non-npm: source, or an npm: source that is neither
102
+ * (never installed, or installed but not Vehicle-shaped) -- package.update's
103
+ * existing catch-all path (calling `pi update --extension` and surfacing
104
+ * whatever it reports) still applies unchanged to either of those, exactly
105
+ * as it did before this classification existed.
106
+ */
107
+ export declare function classifyUpdateSource(piHome: string, source: string): UpdateSourceKind | undefined;
108
+ /**
109
+ * `packed installed`'s real, whole-fleet listing: every pi:-configured
110
+ * extension (`kind: "extension"`, exactly today's
111
+ * readInstalledPackagesAcrossScopes() output, unchanged) PLUS every
112
+ * top-level daemon-only dependency listUnconfiguredDaemonDependencies() can
113
+ * independently resolve (`kind: "daemon-dependency"`) -- so a real, running
114
+ * Armada vehicle like @danypops/lector shows up under its own name instead
115
+ * of staying invisibly nested inside its pi-lector wrapper's own row. See
116
+ * packed-package-update-restart-service-cant-manage.
117
+ *
118
+ * projectRoot only ever widens the extension half (matching
119
+ * readInstalledPackagesAcrossScopes' own scope) -- daemon-dependency
120
+ * detection is global-only for now, since the reported gap itself (an
121
+ * independently-pinned piHome/npm/package.json dependency) is a global-scope
122
+ * shape; a project-scoped .pi/npm equivalent is real future work, not
123
+ * something this fixes today.
124
+ */
125
+ export declare function listManagedPackages(piHome: string, projectRoot?: string): InstalledPkg[];
126
+ export interface ReconcileAllResult {
127
+ /** `versionChanged` is true only when this pass's newly-resolved version genuinely differs
128
+ * from what Armada had registered before this sweep started -- `installed: true` alone means
129
+ * only "the register call itself succeeded", which is true on every healthy pass whether or
130
+ * not anything actually changed underneath (register()/reconcile() is a safe no-op against
131
+ * unchanged desired state). A caller wanting to know whether this pass genuinely restarted
132
+ * something (vs. just re-confirmed a healthy, unchanged fleet) must check this, not `installed`. */
133
+ reconciled: Array<{
134
+ packageName: string;
135
+ vehicleName: string;
136
+ installed: boolean;
137
+ versionChanged: boolean;
138
+ reason?: string;
139
+ }>;
140
+ skipped: number;
141
+ failed: Array<{
142
+ packageName: string;
143
+ reason: string;
144
+ }>;
145
+ /** Every Vehicle unregistered because this sweep no longer discovers it at all -- see pruneStaleVehicles. */
146
+ pruned: Array<{
147
+ vehicleName: string;
148
+ executable: string;
149
+ }>;
150
+ pruneFailed: Array<{
151
+ vehicleName: string;
152
+ reason: string;
153
+ }>;
154
+ }
155
+ /** Packed's own stable cross-daemon identity -- both its real Armada vehicle name (this file's own
156
+ * self-registration guards below) and, since it's the same daemon, the name it registers under in
157
+ * the shared Vehicle Handle Directory for Vehicle Shell broker mode (see daemon.ts's own
158
+ * daemonOptions() -- vehicleName: PACKED_VEHICLE_NAME). One canonical name, not two. */
159
+ export declare const PACKED_VEHICLE_NAME = "pi-packed";
160
+ /**
161
+ * Builds the command to launch armada's own `restart pi-packed` out-of-process. Plain
162
+ * `spawn(..., { detached: true }).unref()` is NOT enough on Linux: systemd's default
163
+ * KillMode=control-group kills every process in a unit's cgroup on `stop`, including a
164
+ * detached+unref'd child -- setsid() escapes a Unix process group, not a cgroup. Confirmed
165
+ * live: a bare detached spawn was killed mid-restart the instant the child's own `armada
166
+ * restart`'s `stop` step fired, because the child was still inside armada-pi-packed's own
167
+ * cgroup. `systemd-run --user --collect --unit=<name>` launches it as an independent
168
+ * transient unit with its own cgroup instead, immune to this unit's stop (confirmed live:
169
+ * a probe unit's child outlived its own service being stopped). launchd/Windows don't tear
170
+ * down a detached child's process tree the same way, so they use a plain spawn.
171
+ */
172
+ export declare function selfRestartCommand(platform: NodeJS.Platform, execPath: string, cliPath: string, unitName: string): {
173
+ readonly command: string;
174
+ readonly arguments: readonly string[];
175
+ };
176
+ /** Fire-and-forget: schedule Packed's own Vehicle to restart from OUTSIDE this process (see
177
+ * selfRestartCommand for why a plain detached spawn alone doesn't survive on Linux). Runs a
178
+ * beat later so the response reporting "scheduled" has time to flush first. Swallows a
179
+ * resolution/spawn failure silently: worst case is the pre-existing behavior (a human restarts
180
+ * the service by hand), never a crash. */
181
+ export type SelfRestartScheduler = (spec: ServiceSpec) => void;
182
+ export declare const scheduleSelfRestart: SelfRestartScheduler;
183
+ /**
184
+ * Sweeps every installed Packed package (global scope, plus a project's own
185
+ * pins when projectRoot is given), resolves each to a Vehicle-shaped daemon
186
+ * exactly as install()/restart() already do per-package, and upserts +
187
+ * reconciles it through Armada. This is what makes Armada authoritative for
188
+ * every Vehicle Packed knows about, not just the one source a single
189
+ * install/update call happened to touch -- it also self-heals a Vehicle
190
+ * whose daemon package version bumped as someone else's transitive
191
+ * dependency, and a Vehicle a prior Packed version never registered at all.
192
+ * Idempotent and safe to call unconditionally: a non-daemon package costs
193
+ * one or two file reads (see resolveDaemonServiceSpec) and never reaches
194
+ * Armada. Two packages that resolve to the same Vehicle (a Pi extension and
195
+ * its own daemon dependency, both separately Packed-tracked) reconcile it
196
+ * once, not twice.
197
+ */
198
+ export declare function reconcileAllDaemonServices(piHome: string, projectRoot: string | undefined, installer: Pick<DaemonServiceInstaller, "install" | "listRegisteredVehicles" | "unregisterVehicleByName">): Promise<ReconcileAllResult>;
199
+ export interface DaemonServiceInstaller {
200
+ install(piHome: string, source: string): Promise<{
201
+ ok: true;
202
+ result: ServiceInstallResult;
203
+ spec: ServiceSpec;
204
+ } | {
205
+ ok: false;
206
+ reason: string;
207
+ notADaemon?: boolean;
208
+ }>;
209
+ remove(piHome: string, source: string): Promise<{
210
+ ok: true;
211
+ result: ServiceInstallResult;
212
+ spec: ServiceSpec;
213
+ } | {
214
+ ok: false;
215
+ reason: string;
216
+ notADaemon?: boolean;
217
+ }>;
218
+ restart(piHome: string, source: string): Promise<{
219
+ ok: true;
220
+ restarted: boolean;
221
+ reason?: string;
222
+ spec: ServiceSpec;
223
+ } | {
224
+ ok: false;
225
+ reason: string;
226
+ notADaemon?: boolean;
227
+ }>;
228
+ /** Every Vehicle Armada currently declares -- see pruneStaleVehicles' own doc comment for why this exists. */
229
+ listRegisteredVehicles(): Promise<readonly VehicleSpec[]>;
230
+ /**
231
+ * Unregisters by Armada vehicle NAME directly, distinct from remove()'s
232
+ * own by-npm-source resolution -- pruning has no installed package left to
233
+ * resolve a source from; the whole point is the vehicle survived past
234
+ * whatever used to produce it.
235
+ */
236
+ unregisterVehicleByName(name: string): Promise<VehicleRegistrationOutcome>;
237
+ }
238
+ /**
239
+ * Calls Armada's own VehicleRegistrar directly (in-process), rather than
240
+ * shelling out to its CLI as a subprocess -- the same registration logic
241
+ * `@danypops/armada` exposes to any other library consumer, not a Packed-
242
+ * specific reimplementation. One registrar per instance so its manifest
243
+ * path/native controller are resolved once, not on every call.
244
+ */
245
+ export declare class RealDaemonServiceInstaller implements DaemonServiceInstaller {
246
+ private readonly registrar;
247
+ private readonly selfRestart;
248
+ constructor(registrar?: VehicleRegistrar, selfRestart?: SelfRestartScheduler);
249
+ listRegisteredVehicles(): Promise<readonly VehicleSpec[]>;
250
+ unregisterVehicleByName(name: string): Promise<VehicleRegistrationOutcome>;
251
+ install(piHome: string, source: string): Promise<{
252
+ ok: true;
253
+ result: ServiceInstallResult;
254
+ spec: ServiceSpec;
255
+ } | {
256
+ ok: false;
257
+ reason: string;
258
+ notADaemon?: boolean;
259
+ }>;
260
+ remove(piHome: string, source: string): Promise<{
261
+ ok: true;
262
+ result: ServiceInstallResult;
263
+ spec: ServiceSpec;
264
+ } | {
265
+ ok: false;
266
+ reason: string;
267
+ notADaemon?: boolean;
268
+ }>;
269
+ restart(piHome: string, source: string): Promise<{
270
+ ok: true;
271
+ restarted: boolean;
272
+ reason?: string;
273
+ spec: ServiceSpec;
274
+ } | {
275
+ ok: false;
276
+ reason: string;
277
+ notADaemon?: boolean;
278
+ }>;
279
+ }
280
+ export {};
281
+ //# sourceMappingURL=daemon-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-service.d.ts","sourceRoot":"","sources":["../../service/src/daemon/daemon-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ function F(z){return`${z.name} (${z.source}) [${z.scope}] ${z.extension}`}function J(z,G){if(G)return`${JSON.stringify(z)}
2
+ `;let A=`${z.ok?"PASS":"FAIL"} — ${z.scanned} extension(s) scanned, ${z.conflicts.length} conflict(s)
3
+ `;for(let q of z.conflicts){A+=`
4
+ CONFLICT ${q.kind} "${q.name}" claimed by:
5
+ `;for(let B of q.claimants)A+=` - ${F(B)}
6
+ `}for(let q of z.extensions){if(q.status==="ok")continue;A+=`
7
+ ${q.status.toUpperCase()} ${F({name:q.name,source:q.source,scope:q.scope,extension:q.extension})}${q.message?`: ${q.message}`:""}
8
+ `}for(let q of z.serviceUnits)A+=`
9
+ ${q.severity.toUpperCase()} ${q.code} ${q.package} (${q.unitName}.service): ${q.message}
10
+ `;for(let q of z.duplicateDependencies){let B=q.locations.map((E)=>`${E.version} (${E.path})`).join(", ");A+=`
11
+ DUPLICATE_DEPENDENCY_VERSION ${q.name}: ${B}
12
+ `}for(let q of z.moduleFreshness??[]){if(!q.stale)continue;A+=`
13
+ STALE_MODULE_CACHE ${q.name}: the daemon loaded ${q.loadedVersion??"an unknown version"} at startup, but ${q.currentVersion??"a different version"} is now on disk -- restart the daemon (systemctl --user restart pi-packed.service) to pick it up.
14
+ `}if(z.truncated)A+=`
15
+ Output truncated: more enabled extensions exist than this run's bound.
16
+ `;return A}export{J as formatDoctorReport};
@@ -0,0 +1,32 @@
1
+ import type { InstalledPkg } from "./package.ts";
2
+ export declare function splitNpmSource(spec: string): [name: string, version: string];
3
+ /**
4
+ * True when a configured npm: source pins an exact version, e.g.
5
+ * "npm:@scope/pkg@1.2.3" vs. the floating "npm:@scope/pkg". `pi update`
6
+ * intentionally leaves pinned sources unchanged (see readInstalledPackages)
7
+ * but still exits 0 and prints "Updated <source>" either way -- callers
8
+ * must not treat that text as proof anything changed.
9
+ */
10
+ export declare function isPinnedNpmSource(source: string): boolean;
11
+ /** The bare npm package name for a configured npm: source, pinned or not.
12
+ * undefined for git:/https: sources -- there is no npm-registry name to read. */
13
+ export declare function npmPackageName(source: string): string | undefined;
14
+ /** Reads a single npm package's real on-disk resolved version, regardless of
15
+ * whether its configured source is pinned -- ground truth for detecting
16
+ * whether an update actually changed anything. undefined for non-npm
17
+ * sources or when node_modules has no matching package.json to read. */
18
+ export declare function readResolvedVersion(piHome: string, source: string): string | undefined;
19
+ export declare function readResolvedIntegrity(piHome: string, source: string): string | undefined;
20
+ export declare function readPackageDeclarations(piHome: string): string[];
21
+ export declare function readInstalledPackages(piHome: string): InstalledPkg[];
22
+ /**
23
+ * Global scope alone is invisible to a project's own .pi/settings.json pin --
24
+ * confirmed live: a project pinned a stale major version of a since-split
25
+ * package, and nothing in packed's own drift detection ever saw it. Merges
26
+ * global and (when given) project-scoped declarations, tagging each so a
27
+ * name pinned differently in each scope is reported twice, not silently
28
+ * deduped into one.
29
+ */
30
+ export declare function readInstalledPackagesAcrossScopes(piHome: string, projectRoot?: string): InstalledPkg[];
31
+ export declare function defaultPiHome(): string;
32
+ //# sourceMappingURL=installed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installed.d.ts","sourceRoot":"","sources":["../../service/src/packages/installed.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAI5E;AAoBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAIzD;AAED;iFACiF;AACjF,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIjE;AAED;;;wEAGwE;AACxE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGtF;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAYxF;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAWhE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAYpE;AAED;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CAKtG;AAED,wBAAgB,aAAa,IAAI,MAAM,CAItC"}