@dbx-tools/appkit-lakebox 0.0.0-stage → 0.9.132

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 (55) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +197 -2
  3. package/index.ts +32 -0
  4. package/lib/index.d.ts +28 -0
  5. package/lib/index.js +26 -0
  6. package/lib/src/_package.d.ts +2 -0
  7. package/lib/src/_package.js +11 -0
  8. package/lib/src/_resource-registry.d.ts +41 -0
  9. package/lib/src/_resource-registry.js +128 -0
  10. package/lib/src/_service-snapshots.d.ts +55 -0
  11. package/lib/src/_service-snapshots.js +65 -0
  12. package/lib/src/config.d.ts +40 -0
  13. package/lib/src/config.js +86 -0
  14. package/lib/src/desktop.d.ts +6 -0
  15. package/lib/src/desktop.js +88 -0
  16. package/lib/src/metrics.d.ts +59 -0
  17. package/lib/src/metrics.js +151 -0
  18. package/lib/src/plugin.d.ts +259 -0
  19. package/lib/src/plugin.js +329 -0
  20. package/lib/src/routes.d.ts +75 -0
  21. package/lib/src/routes.js +441 -0
  22. package/lib/src/runtime.d.ts +154 -0
  23. package/lib/src/runtime.js +760 -0
  24. package/lib/src/services.d.ts +101 -0
  25. package/lib/src/services.js +188 -0
  26. package/lib/src/skills.d.ts +5 -0
  27. package/lib/src/skills.js +21 -0
  28. package/lib/src/user.d.ts +46 -0
  29. package/lib/src/user.js +76 -0
  30. package/lib/src/workspace.d.ts +43 -0
  31. package/lib/src/workspace.js +138 -0
  32. package/lib/tsconfig.tsbuildinfo +1 -0
  33. package/package.json +167 -4
  34. package/scripts/desktop-prerequisites.sh +66 -0
  35. package/scripts/desktop-session.sh +307 -0
  36. package/scripts/lakebox-admin.sh +234 -0
  37. package/scripts/lakebox-service.py +449 -0
  38. package/skills/html-page/SKILL.md +40 -0
  39. package/skills/jupyter-lab/SKILL.md +32 -0
  40. package/skills/lakebox-showcase/SKILL.md +66 -0
  41. package/skills/network-speed-test/SKILL.md +29 -0
  42. package/skills/realtime-whiteboard/SKILL.md +28 -0
  43. package/src/_package.ts +11 -0
  44. package/src/_resource-registry.ts +160 -0
  45. package/src/_service-snapshots.ts +84 -0
  46. package/src/config.ts +128 -0
  47. package/src/desktop.ts +97 -0
  48. package/src/metrics.ts +178 -0
  49. package/src/plugin.ts +446 -0
  50. package/src/routes.ts +524 -0
  51. package/src/runtime.ts +952 -0
  52. package/src/services.ts +239 -0
  53. package/src/skills.ts +23 -0
  54. package/src/user.ts +88 -0
  55. package/src/workspace.ts +185 -0
@@ -0,0 +1,128 @@
1
+ import { CacheManager } from "@databricks/appkit";
2
+ import { LakeboxApiError } from "@dbx-tools/lakebox/rest";
3
+ import { withAdvisoryLock } from "@dbx-tools/postgres";
4
+ import { log } from "@dbx-tools/shared-core";
5
+ import { z } from "zod";
6
+ const CACHE_NAMESPACE = "appkit-lakebox:resource";
7
+ const RESOURCE_TTL_SECONDS = 365 * 24 * 60 * 60;
8
+ const LEGACY_PREFIX = "dbx-lakebox-";
9
+ const logger = log.logger("appkit-lakebox:resource");
10
+ const LakeboxResourceReferenceSchema = z
11
+ .object({ sandboxId: z.string().min(1).describe("Databricks Lakebox identifier.") })
12
+ .strict()
13
+ .describe("Persistent pointer to the Databricks-assigned app Lakebox.");
14
+ /**
15
+ * Persists the Databricks-assigned Lakebox ID and serializes first creation
16
+ * across app replicas with the Lakebase service-principal pool.
17
+ */
18
+ export class LakeboxResourceRegistry {
19
+ application;
20
+ pool;
21
+ cache;
22
+ pending = new Map();
23
+ legacyChecked = new Set();
24
+ constructor(application, pool, cache = () => CacheManager.getInstanceSync()) {
25
+ this.application = application;
26
+ this.pool = pool;
27
+ this.cache = cache;
28
+ }
29
+ /** Resolves the current app Lakebox without creating one. */
30
+ async read(client, signal) {
31
+ const scope = await client.workspaceScope();
32
+ return this.resolve(client, scope, signal);
33
+ }
34
+ /** Returns the current app Lakebox or creates one with a Databricks-assigned name. */
35
+ async getOrCreate(client, signal) {
36
+ const scope = await client.workspaceScope();
37
+ const current = this.pending.get(scope);
38
+ if (current)
39
+ return current;
40
+ const pending = this.withLock(scope, async () => {
41
+ const existing = await this.resolve(client, scope, signal);
42
+ if (existing)
43
+ return existing;
44
+ const created = await client.create(signal);
45
+ try {
46
+ await this.write(scope, created.sandboxId);
47
+ }
48
+ catch (error) {
49
+ await client.delete(created.sandboxId, signal).catch(() => undefined);
50
+ throw error;
51
+ }
52
+ logger.info("created app Lakebox", { id: created.sandboxId });
53
+ return created;
54
+ }).finally(() => this.pending.delete(scope));
55
+ this.pending.set(scope, pending);
56
+ return pending;
57
+ }
58
+ /** Clears the persisted pointer after the managed Lakebox is deleted. */
59
+ async clear(client) {
60
+ const scope = await client.workspaceScope();
61
+ await this.cache().delete(this.key(scope));
62
+ this.legacyChecked.add(scope);
63
+ }
64
+ async resolve(client, scope, signal) {
65
+ const key = this.key(scope);
66
+ const value = await this.cache().get(key);
67
+ const parsed = LakeboxResourceReferenceSchema.safeParse(value);
68
+ if (value !== null && !parsed.success) {
69
+ logger.warn("discarded invalid cached Lakebox resource reference", {
70
+ application: this.application,
71
+ });
72
+ await this.cache().delete(key);
73
+ }
74
+ if (parsed.success) {
75
+ try {
76
+ return await client.get(parsed.data.sandboxId, signal);
77
+ }
78
+ catch (error) {
79
+ if (!(error instanceof LakeboxApiError) || error.status !== 404)
80
+ throw error;
81
+ await this.cache().delete(key);
82
+ this.legacyChecked.add(scope);
83
+ return undefined;
84
+ }
85
+ }
86
+ if (this.legacyChecked.has(scope))
87
+ return undefined;
88
+ this.legacyChecked.add(scope);
89
+ const legacy = selectLegacyLakebox(await client.list(signal), legacyLakeboxName(this.application));
90
+ if (!legacy)
91
+ return undefined;
92
+ await this.write(scope, legacy.sandboxId);
93
+ logger.info("adopted legacy named app Lakebox", { id: legacy.sandboxId });
94
+ return legacy;
95
+ }
96
+ async write(scope, sandboxId) {
97
+ await this.cache().set(this.key(scope), LakeboxResourceReferenceSchema.parse({ sandboxId }), {
98
+ ttl: RESOURCE_TTL_SECONDS,
99
+ });
100
+ }
101
+ key(scope) {
102
+ return this.cache().generateKey([CACHE_NAMESPACE, this.application], scope);
103
+ }
104
+ withLock(scope, fn) {
105
+ if (!this.pool)
106
+ return fn();
107
+ return withAdvisoryLock(this.pool, [CACHE_NAMESPACE, this.application, scope], fn);
108
+ }
109
+ }
110
+ function legacyLakeboxName(application) {
111
+ const slug = application
112
+ .trim()
113
+ .toLowerCase()
114
+ .replace(/[^a-z0-9]+/g, "-")
115
+ .replace(/^-|-$/g, "")
116
+ .slice(0, 200);
117
+ if (!slug)
118
+ throw new Error("A managed Lakebox requires a non-empty application key");
119
+ return `${LEGACY_PREFIX}${slug}`;
120
+ }
121
+ function selectLegacyLakebox(entries, name) {
122
+ return entries
123
+ .filter((entry) => entry.name === name)
124
+ .sort((left, right) => (Date.parse(left.createTime ?? "") || Number.MAX_SAFE_INTEGER) -
125
+ (Date.parse(right.createTime ?? "") || Number.MAX_SAFE_INTEGER) ||
126
+ left.sandboxId.localeCompare(right.sandboxId))[0];
127
+ }
128
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX3Jlc291cmNlLXJlZ2lzdHJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL19yZXNvdXJjZS1yZWdpc3RyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbEQsT0FBTyxFQUFFLGVBQWUsRUFBcUIsTUFBTSx5QkFBeUIsQ0FBQztBQUM3RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQW1CLE1BQU0scUJBQXFCLENBQUM7QUFDeEUsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzdDLE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFFeEIsTUFBTSxlQUFlLEdBQUcseUJBQXlCLENBQUM7QUFDbEQsTUFBTSxvQkFBb0IsR0FBRyxHQUFHLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFDaEQsTUFBTSxhQUFhLEdBQUcsY0FBYyxDQUFDO0FBQ3JDLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMseUJBQXlCLENBQUMsQ0FBQztBQUVyRCxNQUFNLDhCQUE4QixHQUFHLENBQUM7S0FDckMsTUFBTSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLGdDQUFnQyxDQUFDLEVBQUUsQ0FBQztLQUNuRixNQUFNLEVBQUU7S0FDUixRQUFRLENBQUMsNERBQTRELENBQUMsQ0FBQztBQWtCMUU7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLHVCQUF1QjtJQUtmO0lBQ0E7SUFDQTtJQU5GLE9BQU8sR0FBRyxJQUFJLEdBQUcsRUFBaUMsQ0FBQztJQUNuRCxhQUFhLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUVuRCxZQUNtQixXQUFtQixFQUNuQixJQUFpQixFQUNqQixRQUFRLEdBQWtCLEVBQUUsQ0FBQyxZ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S0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNqQixJQUFJLENBQUMsSUFBSTtRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsd0RBQXdELENBQUMsQ0FBQztJQUNyRixPQUFPLEdBQUcsYUFBYSxHQUFHLElBQUksRUFBRSxDQUFDO0FBQ25DLENBQUM7QUFFRCxTQUFTLG1CQUFtQixDQUMxQixPQUFnQyxFQUNoQyxJQUFZO0lBRVosT0FBTyxPQUFPO1NBQ1gsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQztTQUN0QyxJQUFJLENBQ0gsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FDZCxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUMsSUFBSSxNQUFNLENBQUMsZ0JBQWdCLENBQUM7UUFDNUQsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDLElBQUksTUFBTSxDQUFDLGdCQUFnQixDQUFDO1FBQ2pFLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FDaEQsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNULENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDYWNoZU1hbmFnZXIgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBMYWtlYm94QXBpRXJyb3IsIHR5cGUgTGFrZWJveEVudHJ5IH0gZnJvbSBcIkBkYngtdG9vbHMvbGFrZWJveC9yZXN0XCI7XG5pbXBvcnQgeyB3aXRoQWR2aXNvcnlMb2NrLCB0eXBlIFBnUG9vbExpa2UgfSBmcm9tIFwiQGRieC10b29scy9wb3N0Z3Jlc1wiO1xuaW1wb3J0IHsgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbmNvbnN0IENBQ0hFX05BTUVTUEFDRSA9IFwiYXBwa2l0LWxha2Vib3g6cmVzb3VyY2VcIjtcbmNvbnN0IFJFU09VUkNFX1RUTF9TRUNPTkRTID0gMzY1ICogMjQgKiA2MCAqIDYwO1xuY29uc3QgTEVHQUNZX1BSRUZJWCA9IFwiZGJ4LWxha2Vib3gtXCI7XG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiYXBwa2l0LWxha2Vib3g6cmVzb3VyY2VcIik7XG5cbmNvbnN0IExha2Vib3hSZXNvdXJjZVJlZmVyZW5jZVNjaGVtYSA9IHpcbiAgLm9iamVjdCh7IHNhbmRib3hJZDogei5zdHJpbmcoKS5taW4oMSkuZGVzY3JpYmUoXCJEYXRhYnJpY2tzIExha2Vib3ggaWRlbnRpZmllci5cIikgfSlcbiAgLnN0cmljdCgpXG4gIC5kZXNjcmliZShcIlBlcnNpc3RlbnQgcG9pbnRlciB0byB0aGUgRGF0YWJyaWNrcy1hc3NpZ25lZCBhcHAgTGFrZWJveC5cIik7XG5cbmludGVyZmFjZSBSZXNvdXJjZUNhY2hlIHtcbiAgZ2VuZXJhdGVLZXkocGFydHM6IChzdHJpbmcgfCBudW1iZXIgfCBvYmplY3QpW10sIHVzZXJLZXk6IHN0cmluZyk6IHN0cmluZztcbiAgZ2V0PFQ+KGtleTogc3RyaW5nKTogUHJvbWlzZTxUIHwgbnVsbD47XG4gIHNldDxUPihrZXk6IHN0cmluZywgdmFsdWU6IFQsIG9wdGlvbnM/OiB7IHR0bD86IG51bWJlciB9KTogUHJvbWlzZTx2b2lkPjtcbiAgZGVsZXRlKGtleTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbn1cblxuLyoqIExha2Vib3ggY2xpZW50IGNhcGFiaWxpdGllcyByZXF1aXJlZCBieSB0aGUgcGVyc2lzdGVudCByZXNvdXJjZSByZWdpc3RyeS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTGFrZWJveFJlc291cmNlQ2xpZW50IHtcbiAgd29ya3NwYWNlU2NvcGUoKTogUHJvbWlzZTxzdHJpbmc+O1xuICBsaXN0KHNpZ25hbD86IEFib3J0U2lnbmFsKTogUHJvbWlzZTxMYWtlYm94RW50cnlbXT47XG4gIGdldChpZDogc3RyaW5nLCBzaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8TGFrZWJveEVudHJ5PjtcbiAgY3JlYXRlKHNpZ25hbD86IEFib3J0U2lnbmFsKTogUHJvbWlzZTxMYWtlYm94RW50cnk+O1xuICBkZWxldGUoaWQ6IHN0cmluZywgc2lnbmFsPzogQWJvcnRTaWduYWwpOiBQcm9taXNlPHZvaWQ+O1xufVxuXG4vKipcbiAqIFBlcnNpc3RzIHRoZSBEYXRhYnJpY2tzLWFzc2lnbmVkIExha2Vib3ggSUQgYW5kIHNlcmlhbGl6ZXMgZmlyc3QgY3JlYXRpb25cbiAqIGFjcm9zcyBhcHAgcmVwbGljYXMgd2l0aCB0aGUgTGFrZWJhc2Ugc2VydmljZS1wcmluY2lwYWwgcG9vbC5cbiAqL1xuZXhwb3J0IGNsYXNzIExha2Vib3hSZXNvdXJjZVJlZ2lzdHJ5IHtcbiAgcHJpdmF0ZSByZWFkb25seSBwZW5kaW5nID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8TGFrZWJveEVudHJ5Pj4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBsZWdhY3lDaGVja2VkID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBhcHBsaWNhdGlvbjogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcG9vbD86IFBnUG9vbExpa2UsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjYWNoZSA9ICgpOiBSZXNvdXJjZUNhY2hlID0+IENhY2hlTWFuYWdlci5nZXRJbnN0YW5jZVN5bmMoKSxcbiAgKSB7fVxuXG4gIC8qKiBSZXNvbHZlcyB0aGUgY3VycmVudCBhcHAgTGFrZWJveCB3aXRob3V0IGNyZWF0aW5nIG9uZS4gKi9cbiAgYXN5bmMgcmVhZChcbiAgICBjbGllbnQ6IExha2Vib3hSZXNvdXJjZUNsaWVudCxcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogUHJvbWlzZTxMYWtlYm94RW50cnkgfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCBzY29wZSA9IGF3YWl0IGNsaWVudC53b3Jrc3BhY2VTY29wZSgpO1xuICAgIHJldHVybiB0aGlzLnJlc29sdmUoY2xpZW50LCBzY29wZSwgc2lnbmFsKTtcbiAgfVxuXG4gIC8qKiBSZXR1cm5zIHRoZSBjdXJyZW50IGFwcCBMYWtlYm94IG9yIGNyZWF0ZXMgb25lIHdpdGggYSBEYXRhYnJpY2tzLWFzc2lnbmVkIG5hbWUuICovXG4gIGFzeW5jIGdldE9yQ3JlYXRlKGNsaWVudDogTGFrZWJveFJlc291cmNlQ2xpZW50LCBzaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8TGFrZWJveEVudHJ5PiB7XG4gICAgY29uc3Qgc2NvcGUgPSBhd2FpdCBjbGllbnQud29ya3NwYWNlU2NvcGUoKTtcbiAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5wZW5kaW5nLmdldChzY29wZSk7XG4gICAgaWYgKGN1cnJlbnQpIHJldHVybiBjdXJyZW50O1xuICAgIGNvbnN0IHBlbmRpbmcgPSB0aGlzLndpdGhMb2NrKHNjb3BlLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHRoaXMucmVzb2x2ZShjbGllbnQsIHNjb3BlLCBzaWduYWwpO1xuICAgICAgaWYgKGV4aXN0aW5nKSByZXR1cm4gZXhpc3Rpbmc7XG4gICAgICBjb25zdCBjcmVhdGVkID0gYXdhaXQgY2xpZW50LmNyZWF0ZShzaWduYWwpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy53cml0ZShzY29wZSwgY3JlYXRlZC5zYW5kYm94SWQpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgYXdhaXQgY2xpZW50LmRlbGV0ZShjcmVhdGVkLnNhbmRib3hJZCwgc2lnbmFsKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICAgIGxvZ2dlci5pbmZvKFwiY3JlYXRlZCBhcHAgTGFrZWJveFwiLCB7IGlkOiBjcmVhdGVkLnNhbmRib3hJZCB9KTtcbiAgICAgIHJldHVybiBjcmVhdGVkO1xuICAgIH0pLmZpbmFsbHkoKCkgPT4gdGhpcy5wZW5kaW5nLmRlbGV0ZShzY29wZSkpO1xuICAgIHRoaXMucGVuZGluZy5zZXQoc2NvcGUsIHBlbmRpbmcpO1xuICAgIHJldHVybiBwZW5kaW5nO1xuICB9XG5cbiAgLyoqIENsZWFycyB0aGUgcGVyc2lzdGVkIHBvaW50ZXIgYWZ0ZXIgdGhlIG1hbmFnZWQgTGFrZWJveCBpcyBkZWxldGVkLiAqL1xuICBhc3luYyBjbGVhcihjbGllbnQ6IExha2Vib3hSZXNvdXJjZUNsaWVudCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHNjb3BlID0gYXdhaXQgY2xpZW50LndvcmtzcGFjZVNjb3BlKCk7XG4gICAgYXdhaXQgdGhpcy5jYWNoZSgpLmRlbGV0ZSh0aGlzLmtleShzY29wZSkpO1xuICAgIHRoaXMubGVnYWN5Q2hlY2tlZC5hZGQoc2NvcGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZXNvbHZlKFxuICAgIGNsaWVudDogTGFrZWJveFJlc291cmNlQ2xpZW50LFxuICAgIHNjb3BlOiBzdHJpbmcsXG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4gICk6IFByb21pc2U8TGFrZWJveEVudHJ5IHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3Qga2V5ID0gdGhpcy5rZXkoc2NvcGUpO1xuICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgdGhpcy5jYWNoZSgpLmdldDx1bmtub3duPihrZXkpO1xuICAgIGNvbnN0IHBhcnNlZCA9IExha2Vib3hSZXNvdXJjZVJlZmVyZW5jZVNjaGVtYS5zYWZlUGFyc2UodmFsdWUpO1xuICAgIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiAhcGFyc2VkLnN1Y2Nlc3MpIHtcbiAgICAgIGxvZ2dlci53YXJuKFwiZGlzY2FyZGVkIGludmFsaWQgY2FjaGVkIExha2Vib3ggcmVzb3VyY2UgcmVmZXJlbmNlXCIsIHtcbiAgICAgICAgYXBwbGljYXRpb246IHRoaXMuYXBwbGljYXRpb24sXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHRoaXMuY2FjaGUoKS5kZWxldGUoa2V5KTtcbiAgICB9XG4gICAgaWYgKHBhcnNlZC5zdWNjZXNzKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgY2xpZW50LmdldChwYXJzZWQuZGF0YS5zYW5kYm94SWQsIHNpZ25hbCk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBpZiAoIShlcnJvciBpbnN0YW5jZW9mIExha2Vib3hBcGlFcnJvcikgfHwgZXJyb3Iuc3RhdHVzICE9PSA0MDQpIHRocm93IGVycm9yO1xuICAgICAgICBhd2FpdCB0aGlzLmNhY2hlKCkuZGVsZXRlKGtleSk7XG4gICAgICAgIHRoaXMubGVnYWN5Q2hlY2tlZC5hZGQoc2NvcGUpO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAodGhpcy5sZWdhY3lDaGVja2VkLmhhcyhzY29wZSkpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgdGhpcy5sZWdhY3lDaGVja2VkLmFkZChzY29wZSk7XG4gICAgY29uc3QgbGVnYWN5ID0gc2VsZWN0TGVnYWN5TGFrZWJveChcbiAgICAgIGF3YWl0IGNsaWVudC5saXN0KHNpZ25hbCksXG4gICAgICBsZWdhY3lMYWtlYm94TmFtZSh0aGlzLmFwcGxpY2F0aW9uKSxcbiAgICApO1xuICAgIGlmICghbGVnYWN5KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGF3YWl0IHRoaXMud3JpdGUoc2NvcGUsIGxlZ2FjeS5zYW5kYm94SWQpO1xuICAgIGxvZ2dlci5pbmZvKFwiYWRvcHRlZCBsZWdhY3kgbmFtZWQgYXBwIExha2Vib3hcIiwgeyBpZDogbGVnYWN5LnNhbmRib3hJZCB9KTtcbiAgICByZXR1cm4gbGVnYWN5O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB3cml0ZShzY29wZTogc3RyaW5nLCBzYW5kYm94SWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuY2FjaGUoKS5zZXQodGhpcy5rZXkoc2NvcGUpLCBMYWtlYm94UmVzb3VyY2VSZWZlcmVuY2VTY2hlbWEucGFyc2UoeyBzYW5kYm94SWQgfSksIHtcbiAgICAgIHR0bDogUkVTT1VSQ0VfVFRMX1NFQ09ORFMsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGtleShzY29wZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5jYWNoZSgpLmdlbmVyYXRlS2V5KFtDQUNIRV9OQU1FU1BBQ0UsIHRoaXMuYXBwbGljYXRpb25dLCBzY29wZSk7XG4gIH1cblxuICBwcml2YXRlIHdpdGhMb2NrPFQ+KHNjb3BlOiBzdHJpbmcsIGZuOiAoKSA9PiBQcm9taXNlPFQ+KTogUHJvbWlzZTxUPiB7XG4gICAgaWYgKCF0aGlzLnBvb2wpIHJldHVybiBmbigpO1xuICAgIHJldHVybiB3aXRoQWR2aXNvcnlMb2NrKHRoaXMucG9vbCwgW0NBQ0hFX05BTUVTUEFDRSwgdGhpcy5hcHBsaWNhdGlvbiwgc2NvcGVdLCBmbik7XG4gIH1cbn1cblxuZnVuY3Rpb24gbGVnYWN5TGFrZWJveE5hbWUoYXBwbGljYXRpb246IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHNsdWcgPSBhcHBsaWNhdGlvblxuICAgIC50cmltKClcbiAgICAudG9Mb3dlckNhc2UoKVxuICAgIC5yZXBsYWNlKC9bXmEtejAtOV0rL2csIFwiLVwiKVxuICAgIC5yZXBsYWNlKC9eLXwtJC9nLCBcIlwiKVxuICAgIC5zbGljZSgwLCAyMDApO1xuICBpZiAoIXNsdWcpIHRocm93IG5ldyBFcnJvcihcIkEgbWFuYWdlZCBMYWtlYm94IHJlcXVpcmVzIGEgbm9uLWVtcHR5IGFwcGxpY2F0aW9uIGtleVwiKTtcbiAgcmV0dXJuIGAke0xFR0FDWV9QUkVGSVh9JHtzbHVnfWA7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdExlZ2FjeUxha2Vib3goXG4gIGVudHJpZXM6IHJlYWRvbmx5IExha2Vib3hFbnRyeVtdLFxuICBuYW1lOiBzdHJpbmcsXG4pOiBMYWtlYm94RW50cnkgfCB1bmRlZmluZWQge1xuICByZXR1cm4gZW50cmllc1xuICAgIC5maWx0ZXIoKGVudHJ5KSA9PiBlbnRyeS5uYW1lID09PSBuYW1lKVxuICAgIC5zb3J0KFxuICAgICAgKGxlZnQsIHJpZ2h0KSA9PlxuICAgICAgICAoRGF0ZS5wYXJzZShsZWZ0LmNyZWF0ZVRpbWUgPz8gXCJcIikgfHwgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpIC1cbiAgICAgICAgICAoRGF0ZS5wYXJzZShyaWdodC5jcmVhdGVUaW1lID8/IFwiXCIpIHx8IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSKSB8fFxuICAgICAgICBsZWZ0LnNhbmRib3hJZC5sb2NhbGVDb21wYXJlKHJpZ2h0LnNhbmRib3hJZCksXG4gICAgKVswXTtcbn1cbiJdfQ==
@@ -0,0 +1,55 @@
1
+ import { z } from "zod";
2
+ import { type LakeboxControllerService } from "./services.ts";
3
+ export declare const LakeboxServiceSnapshotSchema: z.ZodObject<{
4
+ observedAt: z.ZodString;
5
+ definitions: z.ZodArray<z.ZodObject<{
6
+ name: z.ZodString;
7
+ kind: z.ZodEnum<{
8
+ terminal: "terminal";
9
+ desktop: "desktop";
10
+ image: "image";
11
+ }>;
12
+ image: z.ZodOptional<z.ZodString>;
13
+ pull: z.ZodDefault<z.ZodEnum<{
14
+ missing: "missing";
15
+ always: "always";
16
+ }>>;
17
+ command: z.ZodOptional<z.ZodArray<z.ZodString>>;
18
+ env: z.ZodRecord<z.ZodString, z.ZodString>;
19
+ workingDirectory: z.ZodOptional<z.ZodString>;
20
+ mounts: z.ZodArray<z.ZodObject<{
21
+ source: z.ZodString;
22
+ target: z.ZodString;
23
+ readOnly: z.ZodBoolean;
24
+ }, z.core.$strict>>;
25
+ port: z.ZodNumber;
26
+ readiness: z.ZodEnum<{
27
+ tcp: "tcp";
28
+ none: "none";
29
+ }>;
30
+ readySeconds: z.ZodNumber;
31
+ autostart: z.ZodBoolean;
32
+ route: z.ZodBoolean;
33
+ stripPrefix: z.ZodBoolean;
34
+ openPath: z.ZodOptional<z.ZodString>;
35
+ }, z.core.$strict>>;
36
+ }, z.core.$strict>;
37
+ export type LakeboxServiceSnapshot = z.infer<typeof LakeboxServiceSnapshotSchema>;
38
+ /** Projects saved definitions into explicitly non-live stopped service records. */
39
+ export declare function stoppedSnapshotServices(snapshot: LakeboxServiceSnapshot): Map<string, LakeboxControllerService>;
40
+ interface SnapshotCache {
41
+ generateKey(parts: (string | number | object)[], userKey: string): string;
42
+ get<T>(key: string): Promise<T | null>;
43
+ set<T>(key: string, value: T, options?: {
44
+ ttl?: number;
45
+ }): Promise<void>;
46
+ }
47
+ /** Best-effort persistent snapshots backed by AppKit's configured cache. */
48
+ export declare class LakeboxServiceSnapshots {
49
+ private readonly cache;
50
+ constructor(cache?: () => SnapshotCache);
51
+ read(lakeboxId: string, userHash: string): Promise<LakeboxServiceSnapshot | undefined>;
52
+ write(lakeboxId: string, userHash: string, snapshot: LakeboxServiceSnapshot): Promise<void>;
53
+ private key;
54
+ }
55
+ export {};
@@ -0,0 +1,65 @@
1
+ import { CacheManager } from "@databricks/appkit";
2
+ import { errorUtils, log } from "@dbx-tools/shared-core";
3
+ import { z } from "zod";
4
+ import { LakeboxControllerDefinitionSchema } from "./services.js";
5
+ const CACHE_NAMESPACE = "appkit-lakebox:service-snapshot";
6
+ const SNAPSHOT_TTL_SECONDS = 365 * 24 * 60 * 60;
7
+ const logger = log.logger("appkit-lakebox:service-snapshot");
8
+ export const LakeboxServiceSnapshotSchema = z
9
+ .object({
10
+ observedAt: z.string().datetime().describe("Time the controller last returned this list."),
11
+ definitions: z
12
+ .array(LakeboxControllerDefinitionSchema)
13
+ .describe("Last observed saved service definitions; never authoritative live state."),
14
+ })
15
+ .strict()
16
+ .describe("Best-effort last-known Lakebox service definitions for an unavailable machine.");
17
+ /** Projects saved definitions into explicitly non-live stopped service records. */
18
+ export function stoppedSnapshotServices(snapshot) {
19
+ return new Map(snapshot.definitions.map((definition) => [
20
+ definition.name,
21
+ { name: definition.name, state: "stopped", definition },
22
+ ]));
23
+ }
24
+ /** Best-effort persistent snapshots backed by AppKit's configured cache. */
25
+ export class LakeboxServiceSnapshots {
26
+ cache;
27
+ constructor(cache = () => CacheManager.getInstanceSync()) {
28
+ this.cache = cache;
29
+ }
30
+ async read(lakeboxId, userHash) {
31
+ try {
32
+ const value = await this.cache().get(this.key(lakeboxId, userHash));
33
+ if (value === null)
34
+ return undefined;
35
+ const parsed = LakeboxServiceSnapshotSchema.safeParse(value);
36
+ if (parsed.success)
37
+ return parsed.data;
38
+ logger.warn("ignored invalid cached service snapshot", { lakeboxId, userHash });
39
+ }
40
+ catch (error) {
41
+ logger.warn("unable to read cached service snapshot", {
42
+ lakeboxId,
43
+ userHash,
44
+ error: errorUtils.toError(error),
45
+ });
46
+ }
47
+ return undefined;
48
+ }
49
+ async write(lakeboxId, userHash, snapshot) {
50
+ try {
51
+ await this.cache().set(this.key(lakeboxId, userHash), LakeboxServiceSnapshotSchema.parse(snapshot), { ttl: SNAPSHOT_TTL_SECONDS });
52
+ }
53
+ catch (error) {
54
+ logger.warn("unable to cache service snapshot", {
55
+ lakeboxId,
56
+ userHash,
57
+ error: errorUtils.toError(error),
58
+ });
59
+ }
60
+ }
61
+ key(lakeboxId, userHash) {
62
+ return this.cache().generateKey([CACHE_NAMESPACE, lakeboxId], userHash);
63
+ }
64
+ }
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX3NlcnZpY2Utc25hcHNob3RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL19zZXJ2aWNlLXNuYXBzaG90cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN6RCxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBQ3hCLE9BQU8sRUFBRSxpQ0FBaUMsRUFBaUMsTUFBTSxlQUFlLENBQUM7QUFFakcsTUFBTSxlQUFlLEdBQUcsaUNBQWlDLENBQUM7QUFDMUQsTUFBTSxvQkFBb0IsR0FBRyxHQUFHLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFDaEQsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO0FBRTdELE1BQU0sQ0FBQyxNQUFNLDRCQUE0QixHQUFHLENBQUM7S0FDMUMsTUFBTSxDQUFDO0lBQ04sVUFBVSxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsOENBQThDLENBQUM7SUFDMUYsV0FBVyxFQUFFLENBQUM7U0FDWCxLQUFLLENBQUMsaUNBQWlDLENBQUM7U0FDeEMsUUFBUSxDQUFDLDBFQUEwRSxDQUFDO0NBQ3hGLENBQUM7S0FDRCxNQUFNLEVBQUU7S0FDUixRQUFRLENBQUMsZ0ZBQWdGLENBQUMsQ0FBQztBQUk5RixtRkFBbUY7QUFDbkYsTUFBTSxVQUFVLHVCQUF1QixDQUNyQyxRQUFnQztJQUVoQyxPQUFPLElBQUksR0FBRyxDQUNaLFFBQVEsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQztRQUN2QyxVQUFVLENBQUMsSUFBSTtRQUNmLEVBQUUsSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUU7S0FDeEQsQ0FBQyxDQUNILENBQUM7QUFDSixDQUFDO0FBUUQsNEVBQTRFO0FBQzVFLE1BQU0sT0FBTyx1QkFBdUI7SUFDTDtJQUE3QixZQUE2QixRQUFRLEdBQWtCLEVBQUUsQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFO1FBQTNELFVBQUssR0FBTCxLQUFLLENBQXNEO0lBQUcsQ0FBQztJQUU1RixLQUFLLENBQUMsSUFBSSxDQUFDLFNBQWlCLEVBQUUsUUFBZ0I7UUFDNUMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsR0FBRyxDQUFVLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDN0UsSUFBSSxLQUFLLEtBQUssSUFBSTtnQkFBRSxPQUFPLFNBQVMsQ0FBQztZQUNyQyxNQUFNLE1BQU0sR0FBRyw0QkFBNEIsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDN0QsSUFBSSxNQUFNLENBQUMsT0FBTztnQkFBRSxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDdkMsTUFBTSxDQUFDLElBQUksQ0FBQyx5Q0FBeUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQ2xGLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsTUFBTSxDQUFDLElBQUksQ0FBQyx3Q0FBd0MsRUFBRTtnQkFDcEQsU0FBUztnQkFDVCxRQUFRO2dCQUNSLEtBQUssRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQzthQUNqQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELEtBQUssQ0FBQyxLQUFLLENBQ1QsU0FBaUIsRUFDakIsUUFBZ0IsRUFDaEIsUUFBZ0M7UUFFaEMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsR0FBRyxDQUNwQixJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsRUFDN0IsNEJBQTRCLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxFQUM1QyxFQUFFLEdBQUcsRUFBRSxvQkFBb0IsRUFBRSxDQUM5QixDQUFDO1FBQ0osQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxFQUFFO2dCQUM5QyxTQUFTO2dCQUNULFFBQVE7Z0JBQ1IsS0FBSyxFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO2FBQ2pDLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0lBRU8sR0FBRyxDQUFDLFNBQWlCLEVBQUUsUUFBZ0I7UUFDN0MsT0FBTyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsZUFBZSxFQUFFLFNBQVMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzFFLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENhY2hlTWFuYWdlciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGVycm9yVXRpbHMsIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHsgTGFrZWJveENvbnRyb2xsZXJEZWZpbml0aW9uU2NoZW1hLCB0eXBlIExha2Vib3hDb250cm9sbGVyU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzLnRzXCI7XG5cbmNvbnN0IENBQ0hFX05BTUVTUEFDRSA9IFwiYXBwa2l0LWxha2Vib3g6c2VydmljZS1zbmFwc2hvdFwiO1xuY29uc3QgU05BUFNIT1RfVFRMX1NFQ09ORFMgPSAzNjUgKiAyNCAqIDYwICogNjA7XG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiYXBwa2l0LWxha2Vib3g6c2VydmljZS1zbmFwc2hvdFwiKTtcblxuZXhwb3J0IGNvbnN0IExha2Vib3hTZXJ2aWNlU25hcHNob3RTY2hlbWEgPSB6XG4gIC5vYmplY3Qoe1xuICAgIG9ic2VydmVkQXQ6IHouc3RyaW5nKCkuZGF0ZXRpbWUoKS5kZXNjcmliZShcIlRpbWUgdGhlIGNvbnRyb2xsZXIgbGFzdCByZXR1cm5lZCB0aGlzIGxpc3QuXCIpLFxuICAgIGRlZmluaXRpb25zOiB6XG4gICAgICAuYXJyYXkoTGFrZWJveENvbnRyb2xsZXJEZWZpbml0aW9uU2NoZW1hKVxuICAgICAgLmRlc2NyaWJlKFwiTGFzdCBvYnNlcnZlZCBzYXZlZCBzZXJ2aWNlIGRlZmluaXRpb25zOyBuZXZlciBhdXRob3JpdGF0aXZlIGxpdmUgc3RhdGUuXCIpLFxuICB9KVxuICAuc3RyaWN0KClcbiAgLmRlc2NyaWJlKFwiQmVzdC1lZmZvcnQgbGFzdC1rbm93biBMYWtlYm94IHNlcnZpY2UgZGVmaW5pdGlvbnMgZm9yIGFuIHVuYXZhaWxhYmxlIG1hY2hpbmUuXCIpO1xuXG5leHBvcnQgdHlwZSBMYWtlYm94U2VydmljZVNuYXBzaG90ID0gei5pbmZlcjx0eXBlb2YgTGFrZWJveFNlcnZpY2VTbmFwc2hvdFNjaGVtYT47XG5cbi8qKiBQcm9qZWN0cyBzYXZlZCBkZWZpbml0aW9ucyBpbnRvIGV4cGxpY2l0bHkgbm9uLWxpdmUgc3RvcHBlZCBzZXJ2aWNlIHJlY29yZHMuICovXG5leHBvcnQgZnVuY3Rpb24gc3RvcHBlZFNuYXBzaG90U2VydmljZXMoXG4gIHNuYXBzaG90OiBMYWtlYm94U2VydmljZVNuYXBzaG90LFxuKTogTWFwPHN0cmluZywgTGFrZWJveENvbnRyb2xsZXJTZXJ2aWNlPiB7XG4gIHJldHVybiBuZXcgTWFwKFxuICAgIHNuYXBzaG90LmRlZmluaXRpb25zLm1hcCgoZGVmaW5pdGlvbikgPT4gW1xuICAgICAgZGVmaW5pdGlvbi5uYW1lLFxuICAgICAgeyBuYW1lOiBkZWZpbml0aW9uLm5hbWUsIHN0YXRlOiBcInN0b3BwZWRcIiwgZGVmaW5pdGlvbiB9LFxuICAgIF0pLFxuICApO1xufVxuXG5pbnRlcmZhY2UgU25hcHNob3RDYWNoZSB7XG4gIGdlbmVyYXRlS2V5KHBhcnRzOiAoc3RyaW5nIHwgbnVtYmVyIHwgb2JqZWN0KVtdLCB1c2VyS2V5OiBzdHJpbmcpOiBzdHJpbmc7XG4gIGdldDxUPihrZXk6IHN0cmluZyk6IFByb21pc2U8VCB8IG51bGw+O1xuICBzZXQ8VD4oa2V5OiBzdHJpbmcsIHZhbHVlOiBULCBvcHRpb25zPzogeyB0dGw/OiBudW1iZXIgfSk6IFByb21pc2U8dm9pZD47XG59XG5cbi8qKiBCZXN0LWVmZm9ydCBwZXJzaXN0ZW50IHNuYXBzaG90cyBiYWNrZWQgYnkgQXBwS2l0J3MgY29uZmlndXJlZCBjYWNoZS4gKi9cbmV4cG9ydCBjbGFzcyBMYWtlYm94U2VydmljZVNuYXBzaG90cyB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgY2FjaGUgPSAoKTogU25hcHNob3RDYWNoZSA9PiBDYWNoZU1hbmFnZXIuZ2V0SW5zdGFuY2VTeW5jKCkpIHt9XG5cbiAgYXN5bmMgcmVhZChsYWtlYm94SWQ6IHN0cmluZywgdXNlckhhc2g6IHN0cmluZyk6IFByb21pc2U8TGFrZWJveFNlcnZpY2VTbmFwc2hvdCB8IHVuZGVmaW5lZD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IHRoaXMuY2FjaGUoKS5nZXQ8dW5rbm93bj4odGhpcy5rZXkobGFrZWJveElkLCB1c2VySGFzaCkpO1xuICAgICAgaWYgKHZhbHVlID09PSBudWxsKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgY29uc3QgcGFyc2VkID0gTGFrZWJveFNlcnZpY2VTbmFwc2hvdFNjaGVtYS5zYWZlUGFyc2UodmFsdWUpO1xuICAgICAgaWYgKHBhcnNlZC5zdWNjZXNzKSByZXR1cm4gcGFyc2VkLmRhdGE7XG4gICAgICBsb2dnZXIud2FybihcImlnbm9yZWQgaW52YWxpZCBjYWNoZWQgc2VydmljZSBzbmFwc2hvdFwiLCB7IGxha2Vib3hJZCwgdXNlckhhc2ggfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKFwidW5hYmxlIHRvIHJlYWQgY2FjaGVkIHNlcnZpY2Ugc25hcHNob3RcIiwge1xuICAgICAgICBsYWtlYm94SWQsXG4gICAgICAgIHVzZXJIYXNoLFxuICAgICAgICBlcnJvcjogZXJyb3JVdGlscy50b0Vycm9yKGVycm9yKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgYXN5bmMgd3JpdGUoXG4gICAgbGFrZWJveElkOiBzdHJpbmcsXG4gICAgdXNlckhhc2g6IHN0cmluZyxcbiAgICBzbmFwc2hvdDogTGFrZWJveFNlcnZpY2VTbmFwc2hvdCxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuY2FjaGUoKS5zZXQoXG4gICAgICAgIHRoaXMua2V5KGxha2Vib3hJZCwgdXNlckhhc2gpLFxuICAgICAgICBMYWtlYm94U2VydmljZVNuYXBzaG90U2NoZW1hLnBhcnNlKHNuYXBzaG90KSxcbiAgICAgICAgeyB0dGw6IFNOQVBTSE9UX1RUTF9TRUNPTkRTIH0sXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIud2FybihcInVuYWJsZSB0byBjYWNoZSBzZXJ2aWNlIHNuYXBzaG90XCIsIHtcbiAgICAgICAgbGFrZWJveElkLFxuICAgICAgICB1c2VySGFzaCxcbiAgICAgICAgZXJyb3I6IGVycm9yVXRpbHMudG9FcnJvcihlcnJvciksXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGtleShsYWtlYm94SWQ6IHN0cmluZywgdXNlckhhc2g6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGUoKS5nZW5lcmF0ZUtleShbQ0FDSEVfTkFNRVNQQUNFLCBsYWtlYm94SWRdLCB1c2VySGFzaCk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,40 @@
1
+ import type { BasePluginConfig } from "@databricks/appkit";
2
+ import { z } from "zod";
3
+ export declare const LakeboxPluginConfigSchema: z.ZodObject<{
4
+ auto: z.ZodDefault<z.ZodBoolean>;
5
+ application: z.ZodString;
6
+ idleTimeoutSeconds: z.ZodDefault<z.ZodNumber>;
7
+ routePrefix: z.ZodDefault<z.ZodString>;
8
+ gatewayPort: z.ZodDefault<z.ZodNumber>;
9
+ connectTimeoutMs: z.ZodDefault<z.ZodNumber>;
10
+ commandTimeoutMs: z.ZodDefault<z.ZodNumber>;
11
+ metricsIntervalSeconds: z.ZodDefault<z.ZodNumber>;
12
+ sshTransport: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodEnum<{
13
+ auto: "auto";
14
+ openssh: "openssh";
15
+ ssh2: "ssh2";
16
+ }>>>;
17
+ ssh2Patch: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodEnum<{
18
+ true: "true";
19
+ false: "false";
20
+ auto: "auto";
21
+ }>>>;
22
+ keyDirectory: z.ZodOptional<z.ZodString>;
23
+ }, z.core.$strict>;
24
+ export type SerializableLakeboxPluginConfig = z.input<typeof LakeboxPluginConfigSchema>;
25
+ export type ResolvedLakeboxPluginConfig = z.output<typeof LakeboxPluginConfigSchema>;
26
+ /**
27
+ * Configuration accepted by the Lakebox AppKit plugin.
28
+ *
29
+ * Pass a shared runtime when the plugin and the Mastra workspace resolver must
30
+ * use the same sessions, routes, and metrics.
31
+ */
32
+ export type LakeboxPluginConfig = BasePluginConfig & Partial<SerializableLakeboxPluginConfig> & {
33
+ runtime?: import("./runtime.ts").LakeboxRuntime;
34
+ };
35
+ /**
36
+ * Resolves defaults through configUtils and removes AppKit-only fields.
37
+ *
38
+ * @throws A Zod validation error when a field has an invalid type or range.
39
+ */
40
+ export declare function resolveLakeboxPluginConfig(config?: LakeboxPluginConfig): ResolvedLakeboxPluginConfig;
@@ -0,0 +1,86 @@
1
+ import { basename } from "node:path";
2
+ import { configUtils, projectUtils } from "@dbx-tools/core";
3
+ import { Ssh2PatchModeSchema, SshTransportModeSchema } from "@dbx-tools/lakebox/transport";
4
+ import { LAKEBOX_DEFAULT_ROUTE_PREFIX } from "@dbx-tools/shared-lakebox";
5
+ import { z } from "zod";
6
+ const APPLICATION_CONFIG_KEY = "LAKEBOX_APPLICATION";
7
+ const IDLE_TIMEOUT_CONFIG_KEY = "LAKEBOX_IDLE_TIMEOUT_SECONDS";
8
+ const SSH_TRANSPORT_CONFIG_KEY = "LAKEBOX_SSH_TRANSPORT";
9
+ const SSH2_PATCH_CONFIG_KEY = "LAKEBOX_SSH_SSH2_PATCH";
10
+ export const LakeboxPluginConfigSchema = z
11
+ .object({
12
+ auto: z
13
+ .boolean()
14
+ .default(true)
15
+ .describe("Whether commands, services, and routes create or start the app Lakebox on demand. Defaults to true."),
16
+ application: z
17
+ .string()
18
+ .trim()
19
+ .min(1)
20
+ .describe(`Stable application key for the persisted Lakebox resource ID. Defaults to ${configUtils.name(APPLICATION_CONFIG_KEY)}, then DATABRICKS_APP_NAME, then the project directory name.`),
21
+ idleTimeoutSeconds: z
22
+ .number()
23
+ .int()
24
+ .min(60)
25
+ .max(86_400)
26
+ .default(3_600)
27
+ .describe(`Platform idle timeout that stops the Lakebox after inactivity, from 60 to 86400 seconds. Defaults to 3600; configure with ${configUtils.name(IDLE_TIMEOUT_CONFIG_KEY)}.`),
28
+ routePrefix: z
29
+ .string()
30
+ .startsWith("/")
31
+ .default(LAKEBOX_DEFAULT_ROUTE_PREFIX)
32
+ .describe("AppKit root path for user service routes. Defaults to /lakebox."),
33
+ gatewayPort: z
34
+ .number()
35
+ .int()
36
+ .min(1)
37
+ .max(65535)
38
+ .default(2222)
39
+ .describe("Lakebox SSH gateway port. Defaults to 2222."),
40
+ connectTimeoutMs: z
41
+ .number()
42
+ .int()
43
+ .positive()
44
+ .default(30_000)
45
+ .describe("SSH connection timeout in milliseconds. Defaults to 30000."),
46
+ commandTimeoutMs: z
47
+ .number()
48
+ .int()
49
+ .positive()
50
+ .default(120_000)
51
+ .describe("Default command timeout in milliseconds. Defaults to 120000."),
52
+ metricsIntervalSeconds: z
53
+ .number()
54
+ .int()
55
+ .min(1)
56
+ .max(300)
57
+ .default(5)
58
+ .describe("Interval between metrics samples while the Lakebox runs. Defaults to 5."),
59
+ sshTransport: SshTransportModeSchema.describe(`SSH transport: auto, openssh, or ssh2. Configure with ${configUtils.name(SSH_TRANSPORT_CONFIG_KEY)}.`),
60
+ ssh2Patch: Ssh2PatchModeSchema.describe(`ssh2 missing-exec-reply workaround: auto, true, or false. Configure with ${configUtils.name(SSH2_PATCH_CONFIG_KEY)}.`),
61
+ keyDirectory: z
62
+ .string()
63
+ .min(1)
64
+ .optional()
65
+ .describe("Server-side directory for the app SSH key and gateway host keys."),
66
+ })
67
+ .strict()
68
+ .describe("Serializable Lakebox AppKit plugin configuration.");
69
+ /**
70
+ * Resolves defaults through configUtils and removes AppKit-only fields.
71
+ *
72
+ * @throws A Zod validation error when a field has an invalid type or range.
73
+ */
74
+ export function resolveLakeboxPluginConfig(config = {}) {
75
+ const { runtime: _runtime, name: _name, host: _host, context: _context, telemetry: _telemetry, streamConfig: _stream, application, idleTimeoutSeconds, sshTransport, ssh2Patch, ...serializable } = config;
76
+ return LakeboxPluginConfigSchema.parse({
77
+ ...serializable,
78
+ application: configUtils.string(application, APPLICATION_CONFIG_KEY) ??
79
+ configUtils.string(undefined, "DATABRICKS_APP_NAME", configUtils.ENV_ONLY) ??
80
+ basename(projectUtils.root() ?? process.cwd()),
81
+ idleTimeoutSeconds: configUtils.positiveInt(idleTimeoutSeconds, IDLE_TIMEOUT_CONFIG_KEY, 3_600),
82
+ sshTransport: configUtils.string(sshTransport, SSH_TRANSPORT_CONFIG_KEY),
83
+ ssh2Patch: configUtils.string(ssh2Patch, SSH2_PATCH_CONFIG_KEY),
84
+ });
85
+ }
86
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXJDLE9BQU8sRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLHNCQUFzQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDM0YsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDekUsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUV4QixNQUFNLHNCQUFzQixHQUFHLHFCQUFxQixDQUFDO0FBQ3JELE1BQU0sdUJBQXVCLEdBQUcsOEJBQThCLENBQUM7QUFDL0QsTUFBTSx3QkFBd0IsR0FBRyx1QkFBdUIsQ0FBQztBQUN6RCxNQUFNLHFCQUFxQixHQUFHLHdCQUF3QixDQUFDO0FBRXZELE1BQU0sQ0FBQyxNQUFNLHlCQUF5QixHQUFHLENBQUM7S0FDdkMsTUFBTSxDQUFDO0lBQ04sSUFBSSxFQUFFLENBQUM7U0FDSixPQUFPLEVBQUU7U0FDVCxPQUFPLENBQUMsSUFBSSxDQUFDO1NBQ2IsUUFBUSxDQUNQLHFHQUFxRyxDQUN0RztJQUNILFdBQVcsRUFBRSxDQUFDO1NBQ1gsTUFBTSxFQUFFO1NBQ1IsSUFBSSxFQUFFO1NBQ04sR0FBRyxDQUFDLENBQUMsQ0FBQztTQUNOLFFBQVEsQ0FDUCw2RUFBNkUsV0FBVyxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyw4REFBOEQsQ0FDcEw7SUFDSCxrQkFBa0IsRUFBRSxDQUFDO1NBQ2xCLE1BQU0sRUFBRTtTQUNSLEdBQUcsRUFBRTtTQUNMLEdBQUcsQ0FBQyxFQUFFLENBQUM7U0FDUCxHQUFHLENBQUMsTUFBTSxDQUFDO1NBQ1gsT0FBTyxDQUFDLEtBQUssQ0FBQztTQUNkLFFB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OlsiaW1wb3J0IHsgYmFzZW5hbWUgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgdHlwZSB7IEJhc2VQbHVnaW5Db25maWcgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBjb25maWdVdGlscywgcHJvamVjdFV0aWxzIH0gZnJvbSBcIkBkYngtdG9vbHMvY29yZVwiO1xuaW1wb3J0IHsgU3NoMlBhdGNoTW9kZVNjaGVtYSwgU3NoVHJhbnNwb3J0TW9kZVNjaGVtYSB9IGZyb20gXCJAZGJ4LXRvb2xzL2xha2Vib3gvdHJhbnNwb3J0XCI7XG5pbXBvcnQgeyBMQUtFQk9YX0RFRkFVTFRfUk9VVEVfUFJFRklYIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWxha2Vib3hcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbmNvbnN0IEFQUExJQ0FUSU9OX0NPTkZJR19LRVkgPSBcIkxBS0VCT1hfQVBQTElDQVRJT05cIjtcbmNvbnN0IElETEVfVElNRU9VVF9DT05GSUdfS0VZID0gXCJMQUtFQk9YX0lETEVfVElNRU9VVF9TRUNPTkRTXCI7XG5jb25zdCBTU0hfVFJBTlNQT1JUX0NPTkZJR19LRVkgPSBcIkxBS0VCT1hfU1NIX1RSQU5TUE9SVFwiO1xuY29uc3QgU1NIMl9QQVRDSF9DT05GSUdfS0VZID0gXCJMQUtFQk9YX1NTSF9TU0gyX1BBVENIXCI7XG5cbmV4cG9ydCBjb25zdCBMYWtlYm94UGx1Z2luQ29uZmlnU2NoZW1hID0gelxuICAub2JqZWN0KHtcbiAgICBhdXRvOiB6XG4gICAgICAuYm9vbGVhbigpXG4gICAgICAuZGVmYXVsdCh0cnVlKVxuICAgICAgLmRlc2NyaWJlKFxuICAgICAgICBcIldoZXRoZXIgY29tbWFuZHMsIHNlcnZpY2VzLCBhbmQgcm91dGVzIGNyZWF0ZSBvciBzdGFydCB0aGUgYXBwIExha2Vib3ggb24gZGVtYW5kLiBEZWZhdWx0cyB0byB0cnVlLlwiLFxuICAgICAgKSxcbiAgICBhcHBsaWNhdGlvbjogelxuICAgICAgLnN0cmluZygpXG4gICAgICAudHJpbSgpXG4gICAgICAubWluKDEpXG4gICAgICAuZGVzY3JpYmUoXG4gICAgICAgIGBTdGFibGUgYXBwbGljYXRpb24ga2V5IGZvciB0aGUgcGVyc2lzdGVkIExha2Vib3ggcmVzb3VyY2UgSUQuIERlZmF1bHRzIHRvICR7Y29uZmlnVXRpbHMubmFtZShBUFBMSUNBVElPTl9DT05GSUdfS0VZKX0sIHRoZW4gREFUQUJSSUNLU19BUFBfTkFNRSwgdGhlbiB0aGUgcHJvamVjdCBkaXJlY3RvcnkgbmFtZS5gLFxuICAgICAgKSxcbiAgICBpZGxlVGltZW91dFNlY29uZHM6IHpcbiAgICAgIC5udW1iZXIoKVxuICAgICAgLmludCgpXG4gICAgICAubWluKDYwKVxuICAgICAgLm1heCg4Nl80MDApXG4gICAgICAuZGVmYXVsdCgzXzYwMClcbiAgICAgIC5kZXNjcmliZShcbiAgICAgICAgYFBsYXRmb3JtIGlkbGUgdGltZW91dCB0aGF0IHN0b3BzIHRoZSBMYWtlYm94IGFmdGVyIGluYWN0aXZpdHksIGZyb20gNjAgdG8gODY0MDAgc2Vjb25kcy4gRGVmYXVsdHMgdG8gMzYwMDsgY29uZmlndXJlIHdpdGggJHtjb25maWdVdGlscy5uYW1lKElETEVfVElNRU9VVF9DT05GSUdfS0VZKX0uYCxcbiAgICAgICksXG4gICAgcm91dGVQcmVmaXg6IHpcbiAgICAgIC5zdHJpbmcoKVxuICAgICAgLnN0YXJ0c1dpdGgoXCIvXCIpXG4gICAgICAuZGVmYXVsdChMQUtFQk9YX0RFRkFVTFRfUk9VVEVfUFJFRklYKVxuICAgICAgLmRlc2NyaWJlKFwiQXBwS2l0IHJvb3QgcGF0aCBmb3IgdXNlciBzZXJ2aWNlIHJvdXRlcy4gRGVmYXVsdHMgdG8gL2xha2Vib3guXCIpLFxuICAgIGdhdGV3YXlQb3J0OiB6XG4gICAgICAubnVtYmVyKClcbiAgICAgIC5pbnQoKVxuICAgICAgLm1pbigxKVxuICAgICAgLm1heCg2NTUzNSlcbiAgICAgIC5kZWZhdWx0KDIyMjIpXG4gICAgICAuZGVzY3JpYmUoXCJMYWtlYm94IFNTSCBnYXRld2F5IHBvcnQuIERlZmF1bHRzIHRvIDIyMjIuXCIpLFxuICAgIGNvbm5lY3RUaW1lb3V0TXM6IHpcbiAgICAgIC5udW1iZXIoKVxuICAgICAgLmludCgpXG4gICAgICAucG9zaXRpdmUoKVxuICAgICAgLmRlZmF1bHQoMzBfMDAwKVxuICAgICAgLmRlc2NyaWJlKFwiU1NIIGNvbm5lY3Rpb24gdGltZW91dCBpbiBtaWxsaXNlY29uZHMuIERlZmF1bHRzIHRvIDMwMDAwLlwiKSxcbiAgICBjb21tYW5kVGltZW91dE1zOiB6XG4gICAgICAubnVtYmVyKClcbiAgICAgIC5pbnQoKVxuICAgICAgLnBvc2l0aXZlKClcbiAgICAgIC5kZWZhdWx0KDEyMF8wMDApXG4gICAgICAuZGVzY3JpYmUoXCJEZWZhdWx0IGNvbW1hbmQgdGltZW91dCBpbiBtaWxsaXNlY29uZHMuIERlZmF1bHRzIHRvIDEyMDAwMC5cIiksXG4gICAgbWV0cmljc0ludGVydmFsU2Vjb25kczogelxuICAgICAgLm51bWJlcigpXG4gICAgICAuaW50KClcbiAgICAgIC5taW4oMSlcbiAgICAgIC5tYXgoMzAwKVxuICAgICAgLmRlZmF1bHQoNSlcbiAgICAgIC5kZXNjcmliZShcIkludGVydmFsIGJldHdlZW4gbWV0cmljcyBzYW1wbGVzIHdoaWxlIHRoZSBMYWtlYm94IHJ1bnMuIERlZmF1bHRzIHRvIDUuXCIpLFxuICAgIHNzaFRyYW5zcG9ydDogU3NoVHJhbnNwb3J0TW9kZVNjaGVtYS5kZXNjcmliZShcbiAgICAgIGBTU0ggdHJhbnNwb3J0OiBhdXRvLCBvcGVuc3NoLCBvciBzc2gyLiBDb25maWd1cmUgd2l0aCAke2NvbmZpZ1V0aWxzLm5hbWUoU1NIX1RSQU5TUE9SVF9DT05GSUdfS0VZKX0uYCxcbiAgICApLFxuICAgIHNzaDJQYXRjaDogU3NoMlBhdGNoTW9kZVNjaGVtYS5kZXNjcmliZShcbiAgICAgIGBzc2gyIG1pc3NpbmctZXhlYy1yZXBseSB3b3JrYXJvdW5kOiBhdXRvLCB0cnVlLCBvciBmYWxzZS4gQ29uZmlndXJlIHdpdGggJHtjb25maWdVdGlscy5uYW1lKFNTSDJfUEFUQ0hfQ09ORklHX0tFWSl9LmAsXG4gICAgKSxcbiAgICBrZXlEaXJlY3Rvcnk6IHpcbiAgICAgIC5zdHJpbmcoKVxuICAgICAgLm1pbigxKVxuICAgICAgLm9wdGlvbmFsKClcbiAgICAgIC5kZXNjcmliZShcIlNlcnZlci1zaWRlIGRpcmVjdG9yeSBmb3IgdGhlIGFwcCBTU0gga2V5IGFuZCBnYXRld2F5IGhvc3Qga2V5cy5cIiksXG4gIH0pXG4gIC5zdHJpY3QoKVxuICAuZGVzY3JpYmUoXCJTZXJpYWxpemFibGUgTGFrZWJveCBBcHBLaXQgcGx1Z2luIGNvbmZpZ3VyYXRpb24uXCIpO1xuXG5leHBvcnQgdHlwZSBTZXJpYWxpemFibGVMYWtlYm94UGx1Z2luQ29uZmlnID0gei5pbnB1dDx0eXBlb2YgTGFrZWJveFBsdWdpbkNvbmZpZ1NjaGVtYT47XG5leHBvcnQgdHlwZSBSZXNvbHZlZExha2Vib3hQbHVnaW5Db25maWcgPSB6Lm91dHB1dDx0eXBlb2YgTGFrZWJveFBsdWdpbkNvbmZpZ1NjaGVtYT47XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBhY2NlcHRlZCBieSB0aGUgTGFrZWJveCBBcHBLaXQgcGx1Z2luLlxuICpcbiAqIFBhc3MgYSBzaGFyZWQgcnVudGltZSB3aGVuIHRoZSBwbHVnaW4gYW5kIHRoZSBNYXN0cmEgd29ya3NwYWNlIHJlc29sdmVyIG11c3RcbiAqIHVzZSB0aGUgc2FtZSBzZXNzaW9ucywgcm91dGVzLCBhbmQgbWV0cmljcy5cbiAqL1xuZXhwb3J0IHR5cGUgTGFrZWJveFBsdWdpbkNvbmZpZyA9IEJhc2VQbHVnaW5Db25maWcgJlxuICBQYXJ0aWFsPFNlcmlhbGl6YWJsZUxha2Vib3hQbHVnaW5Db25maWc+ICYge1xuICAgIHJ1bnRpbWU/OiBpbXBvcnQoXCIuL3J1bnRpbWUudHNcIikuTGFrZWJveFJ1bnRpbWU7XG4gIH07XG5cbi8qKlxuICogUmVzb2x2ZXMgZGVmYXVsdHMgdGhyb3VnaCBjb25maWdVdGlscyBhbmQgcmVtb3ZlcyBBcHBLaXQtb25seSBmaWVsZHMuXG4gKlxuICogQHRocm93cyBBIFpvZCB2YWxpZGF0aW9uIGVycm9yIHdoZW4gYSBmaWVsZCBoYXMgYW4gaW52YWxpZCB0eXBlIG9yIHJhbmdlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUxha2Vib3hQbHVnaW5Db25maWcoXG4gIGNvbmZpZzogTGFrZWJveFBsdWdpbkNvbmZpZyA9IHt9LFxuKTogUmVzb2x2ZWRMYWtlYm94UGx1Z2luQ29uZmlnIHtcbiAgY29uc3Qge1xuICAgIHJ1bnRpbWU6IF9ydW50aW1lLFxuICAgIG5hbWU6IF9uYW1lLFxuICAgIGhvc3Q6IF9ob3N0LFxuICAgIGNvbnRleHQ6IF9jb250ZXh0LFxuICAgIHRlbGVtZXRyeTogX3RlbGVtZXRyeSxcbiAgICBzdHJlYW1Db25maWc6IF9zdHJlYW0sXG4gICAgYXBwbGljYXRpb24sXG4gICAgaWRsZVRpbWVvdXRTZWNvbmRzLFxuICAgIHNzaFRyYW5zcG9ydCxcbiAgICBzc2gyUGF0Y2gsXG4gICAgLi4uc2VyaWFsaXphYmxlXG4gIH0gPSBjb25maWc7XG4gIHJldHVybiBMYWtlYm94UGx1Z2luQ29uZmlnU2NoZW1hLnBhcnNlKHtcbiAgICAuLi5zZXJpYWxpemFibGUsXG4gICAgYXBwbGljYXRpb246XG4gICAgICBjb25maWdVdGlscy5zdHJpbmcoYXBwbGljYXRpb24sIEFQUExJQ0FUSU9OX0NPTkZJR19LRVkpID8/XG4gICAgICBjb25maWdVdGlscy5zdHJpbmcodW5kZWZpbmVkLCBcIkRBVEFCUklDS1NfQVBQX05BTUVcIiwgY29uZmlnVXRpbHMuRU5WX09OTFkpID8/XG4gICAgICBiYXNlbmFtZShwcm9qZWN0VXRpbHMucm9vdCgpID8/IHByb2Nlc3MuY3dkKCkpLFxuICAgIGlkbGVUaW1lb3V0U2Vjb25kczogY29uZmlnVXRpbHMucG9zaXRpdmVJbnQoaWRsZVRpbWVvdXRTZWNvbmRzLCBJRExFX1RJTUVPVVRfQ09ORklHX0tFWSwgM182MDApLFxuICAgIHNzaFRyYW5zcG9ydDogY29uZmlnVXRpbHMuc3RyaW5nKHNzaFRyYW5zcG9ydCwgU1NIX1RSQU5TUE9SVF9DT05GSUdfS0VZKSxcbiAgICBzc2gyUGF0Y2g6IGNvbmZpZ1V0aWxzLnN0cmluZyhzc2gyUGF0Y2gsIFNTSDJfUEFUQ0hfQ09ORklHX0tFWSksXG4gIH0pO1xufVxuIl19
@@ -0,0 +1,6 @@
1
+ /** Markup injected into the KasmVNC client page to apply dbx-tools branding. */
2
+ export declare const desktopHtmlHead: string;
3
+ /** Browser entry URL for the built-in KasmVNC desktop. */
4
+ export declare function desktopOpenUrl(path: string): string;
5
+ /** Branding environment consumed by the packaged desktop session entrypoint. */
6
+ export declare function desktopEnvironment(): Readonly<Record<string, string>>;
@@ -0,0 +1,88 @@
1
+ import { brandUtils } from "@dbx-tools/shared-core";
2
+ import { dbxToolsAssetDataUrls, dbxToolsAssetSvg } from "@dbx-tools/ui/branding/assets";
3
+ const BRAND = brandUtils.defaultBrandContext;
4
+ const BRAND_COLORS = BRAND.colors;
5
+ const WALLPAPER_LOGO = dbxToolsAssetSvg.logoDark.replace("<svg ", '<svg x="500" y="378" width="600" height="135" ');
6
+ const DBX_TOOLS_WALLPAPER =
7
+ // ============================================================================
8
+ /*xml*/ `
9
+ <svg xmlns="http://www.w3.org/2000/svg" width="1600" height="1000" viewBox="0 0 1600 1000">
10
+ <defs>
11
+ <linearGradient id="background" x1="0" y1="0" x2="1" y2="1">
12
+ <stop offset="0" stop-color="#0B161B"/>
13
+ <stop offset="0.55" stop-color="${BRAND_COLORS.primary}"/>
14
+ <stop offset="1" stop-color="${BRAND_COLORS.primaryHover}"/>
15
+ </linearGradient>
16
+ <pattern id="grid" width="64" height="64" patternUnits="userSpaceOnUse">
17
+ <path d="M64 0H0V64" fill="none" stroke="${BRAND_COLORS.surface}" stroke-opacity="0.045"/>
18
+ </pattern>
19
+ </defs>
20
+ <rect width="1600" height="1000" fill="url(#background)"/>
21
+ <rect width="1600" height="1000" fill="url(#grid)"/>
22
+ <path d="M0 780C310 650 475 920 780 775s500-220 820-55v280H0Z" fill="${BRAND_COLORS.accent}" fill-opacity="0.13"/>
23
+ <path d="M0 835c300-125 510 105 790-10s500-170 810-65" fill="none" stroke="${BRAND_COLORS.accent}" stroke-width="4" stroke-opacity="0.7"/>
24
+ ${WALLPAPER_LOGO}
25
+ <text x="800" y="558" text-anchor="middle" fill="${BRAND_COLORS.muted}" font-family="${BRAND.typography.sans}" font-size="24" letter-spacing="5">LAKEBOX DESKTOP</text>
26
+ </svg>
27
+ `
28
+ // ============================================================================
29
+ .trim();
30
+ const DBX_TOOLS_TERMINAL_ICON =
31
+ // ============================================================================
32
+ /*xml*/ `
33
+ <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
34
+ <rect x="4" y="6" width="56" height="52" rx="12" fill="${BRAND_COLORS.primary}"/>
35
+ <rect x="8" y="10" width="48" height="44" rx="8" fill="${BRAND_COLORS.primaryHover}"/>
36
+ <path d="m18 23 9 9-9 9" fill="none" stroke="${BRAND_COLORS.surface}" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
37
+ <path d="M34 41h12" fill="none" stroke="${BRAND_COLORS.accent}" stroke-width="4" stroke-linecap="round"/>
38
+ </svg>
39
+ `
40
+ // ============================================================================
41
+ .trim();
42
+ const DESKTOP_BRAND_HEAD =
43
+ // ============================================================================
44
+ /*html*/ `
45
+ <style id="dbx-tools-desktop-brand">
46
+ html,body{width:100%;max-width:100%;height:100%;max-height:100%;min-width:0;min-height:0;overflow:hidden}
47
+ body{position:fixed;inset:0;width:var(--dbx-tools-viewport-width,100vw);height:var(--dbx-tools-viewport-height,100dvh)}
48
+ #noVNC_container{width:100%!important;max-width:100%;height:100%!important;max-height:100%;overflow:hidden}
49
+ .noVNC_logo,h1.noVNC_logo,a[title="KasmVNC Learn More"]{display:none!important}
50
+ #noVNC_fallback_errormsg{overflow-wrap:anywhere}
51
+ </style>
52
+ <link data-dbx-tools-desktop-icon rel="icon" href="${dbxToolsAssetDataUrls.iconDark}">
53
+ <script id="dbx-tools-kasm-mobile-guard">(()=>{const ignored=(error)=>error instanceof ReferenceError&&/^Can't find variable: W[0-9A-F]{32}$/.test(error.message);window.addEventListener("error",(event)=>{if(ignored(event.error)){event.preventDefault();event.stopImmediatePropagation()}},true);window.addEventListener("unhandledrejection",(event)=>{if(ignored(event.reason)){event.preventDefault();event.stopImmediatePropagation()}},true);let timer;const sync=()=>{const viewport=window.visualViewport;document.documentElement.style.setProperty("--dbx-tools-viewport-width",String(Math.round(viewport?.width??window.innerWidth))+"px");document.documentElement.style.setProperty("--dbx-tools-viewport-height",String(Math.round(viewport?.height??window.innerHeight))+"px");window.dispatchEvent(new Event("resize"))};const schedule=()=>{clearTimeout(timer);sync();setTimeout(sync,250);timer=setTimeout(sync,750)};window.visualViewport?.addEventListener("resize",schedule);window.visualViewport?.addEventListener("scroll",schedule);window.addEventListener("orientationchange",schedule);window.addEventListener("pageshow",schedule);document.readyState==="loading"?document.addEventListener("DOMContentLoaded",schedule,{once:true}):schedule()})();</script>
54
+ <script id="dbx-tools-desktop-brand-script">(()=>{const icon=${JSON.stringify(dbxToolsAssetDataUrls.iconDark)};const rewrite=(root)=>{if(root.nodeType===Node.TEXT_NODE){if(root.nodeValue?.includes("KasmVNC"))root.nodeValue=root.nodeValue.replaceAll("KasmVNC","dbx tools Desktop");return}const walker=document.createTreeWalker(root,NodeFilter.SHOW_TEXT);let node;while(node=walker.nextNode())if(node.nodeValue?.includes("KasmVNC"))node.nodeValue=node.nodeValue.replaceAll("KasmVNC","dbx tools Desktop")};const apply=()=>{document.title="dbx tools Desktop";for(const link of document.querySelectorAll('link[rel~="icon"],link[rel="apple-touch-icon"]'))link.setAttribute("href",icon);if(document.body)rewrite(document.body)};if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",apply,{once:true});else apply();new MutationObserver((entries)=>{for(const entry of entries){if(entry.type==="characterData")rewrite(entry.target);else for(const node of entry.addedNodes)rewrite(node)}}).observe(document.documentElement,{childList:true,subtree:true,characterData:true})})();</script>
55
+ `
56
+ // ============================================================================
57
+ .trim();
58
+ /** Markup injected into the KasmVNC client page to apply dbx-tools branding. */
59
+ export const desktopHtmlHead = DESKTOP_BRAND_HEAD;
60
+ /** Browser entry URL for the built-in KasmVNC desktop. */
61
+ export function desktopOpenUrl(path) {
62
+ const normalized = path.replace(/\/+$/, "");
63
+ const websocketPath = `${normalized.replace(/^\/+/, "")}/websockify`;
64
+ const parameters = new URLSearchParams({
65
+ autoconnect: "1",
66
+ resize: "remote",
67
+ show_dot: "1",
68
+ clipboard_seamless: "0",
69
+ enable_webp: "0",
70
+ kasmvnc_mode_preference: "-1027",
71
+ path: websocketPath,
72
+ });
73
+ return `${normalized}/?${parameters.toString()}`;
74
+ }
75
+ /** Branding environment consumed by the packaged desktop session entrypoint. */
76
+ export function desktopEnvironment() {
77
+ return {
78
+ DBX_TOOLS_DESKTOP_WALLPAPER_BASE64: Buffer.from(DBX_TOOLS_WALLPAPER).toString("base64"),
79
+ DBX_TOOLS_DESKTOP_BRAND_ICON_BASE64: Buffer.from(dbxToolsAssetSvg.iconDark).toString("base64"),
80
+ DBX_TOOLS_DESKTOP_TERMINAL_ICON_BASE64: Buffer.from(DBX_TOOLS_TERMINAL_ICON).toString("base64"),
81
+ DBX_TOOLS_DESKTOP_HOMEPAGE_BASE64: Buffer.from(BRAND.links.website).toString("base64"),
82
+ DBX_TOOLS_DESKTOP_PRIMARY: BRAND_COLORS.primary,
83
+ DBX_TOOLS_DESKTOP_PRIMARY_HOVER: BRAND_COLORS.primaryHover,
84
+ DBX_TOOLS_DESKTOP_SURFACE: BRAND_COLORS.surface,
85
+ DBX_TOOLS_DESKTOP_FONT: "DejaVu Sans",
86
+ };
87
+ }
88
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVza3RvcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kZXNrdG9wLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUV4RixNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsbUJBQW1CLENBQUM7QUFDN0MsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztBQUNsQyxNQUFNLGNBQWMsR0FBRyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUN0RCxPQUFPLEVBQ1AsZ0RBQWdELENBQ2pELENBQUM7QUFFRixNQUFNLG1CQUFtQjtBQUN2QiwrRUFBK0U7QUFDL0UsT0FBTyxDQUFDOzs7Ozt3Q0FLOEIsWUFBWSxDQUFDLE9BQU87cUNBQ3ZCLFlBQVksQ0FBQyxZQUFZOzs7aURBR2IsWUFBWSxDQUFDLE9BQU87Ozs7O3lFQUtJLFlBQVksQ0FBQyxNQUFNOytFQUNiLFlBQVksQ0FBQyxNQUFNO0lBQzlGLGNBQWM7cURBQ21DLFlBQVksQ0FBQyxLQUFLLGtCQUFrQixLQUFLLENBQUMsVUFBVSxDQUFDLElBQUk7O0NBRTdHO0lBQ0csK0VBQStFO0tBQzlFLElBQUksRUFBRSxDQUFDO0FBRVosTUFBTSx1QkFBdUI7QUFDM0IsK0VBQStFO0FBQy9FLE9BQU8sQ0FBQzs7MkRBRWlELFlBQVksQ0FBQyxPQUFPOzJEQUNwQixZQUFZLENBQUMsWUFBWTtpREFDbkMsWUFBWSxDQUFDLE9BQU87NENBQ3pCLFlBQVksQ0FBQyxNQUFNOztDQUU5RDtJQUNHLCtFQUErRTtLQUM5RSxJQUFJLEVBQUUsQ0FBQztBQUVaLE1BQU0sa0JBQWtCO0FBQ3RCLCtFQUErRTtBQUMvRSxRQUFRLENBQUM7Ozs7Ozs7O3FEQVEwQyxxQkFBcUIsQ0FBQyxRQUFROzsrREFFcEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLENBQUM7Q0FDNUc7SUFDRywrRUFBK0U7S0FDOUUsSUFBSSxFQUFFLENBQUM7QUFFWixnRkFBZ0Y7QUFDaEYsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLGtCQUFrQixDQUFDO0FBRWxELDBEQUEwRDtBQUMxRCxNQUFNLFVBQVUsY0FBYyxDQUFDLElBQVk7SUFDekMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDNUMsTUFBTSxhQUFhLEdBQUcsR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsYUFBYSxDQUFDO0lBQ3JFLE1BQU0sVUFBVSxHQUFHLElBQUksZUFBZSxDQUFDO1FBQ3JDLFdBQVcsRUFBRSxHQUFHO1FBQ2hCLE1BQU0sRUFBRSxRQUFRO1FBQ2hCLFFBQVEsRUFBRSxHQUFHO1FBQ2Isa0JBQWtCLEVBQUUsR0FBRztRQUN2QixXQUFXLEVBQUUsR0FBRztRQUNoQix1QkFBdUIsRUFBRSxPQUFPO1FBQ2hDLElBQUksRUFBRSxhQUFhO0tBQ3BCLENBQUMsQ0FBQztJQUNILE9BQU8sR0FBRyxVQUFVLEtBQUssVUFBVSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7QUFDbkQsQ0FBQztBQUVELGdGQUFnRjtBQUNoRixNQUFNLFVBQVUsa0JBQWtCO0lBQ2hDLE9BQU87UUFDTCxrQ0FBa0MsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztRQUN2RixtQ0FBbUMsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFDOUYsc0NBQXNDLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFDL0YsaUNBQWlDLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFDdEYseUJBQXlCLEVBQUUsWUFBWSxDQUFDLE9BQU87UUFDL0MsK0JBQStCLEVBQUUsWUFBWSxDQUFDLFlBQVk7UUFDMUQseUJBQXlCLEVBQUUsWUFBWSxDQUFDLE9BQU87UUFDL0Msc0JBQXNCLEVBQUUsYUFBYTtLQUN0QyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGJyYW5kVXRpbHMgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgZGJ4VG9vbHNBc3NldERhdGFVcmxzLCBkYnhUb29sc0Fzc2V0U3ZnIH0gZnJvbSBcIkBkYngtdG9vbHMvdWkvYnJhbmRpbmcvYXNzZXRzXCI7XG5cbmNvbnN0IEJSQU5EID0gYnJhbmRVdGlscy5kZWZhdWx0QnJhbmRDb250ZXh0O1xuY29uc3QgQlJBTkRfQ09MT1JTID0gQlJBTkQuY29sb3JzO1xuY29uc3QgV0FMTFBBUEVSX0xPR08gPSBkYnhUb29sc0Fzc2V0U3ZnLmxvZ29EYXJrLnJlcGxhY2UoXG4gIFwiPHN2ZyBcIixcbiAgJzxzdmcgeD1cIjUwMFwiIHk9XCIzNzhcIiB3aWR0aD1cIjYwMFwiIGhlaWdodD1cIjEzNVwiICcsXG4pO1xuXG5jb25zdCBEQlhfVE9PTFNfV0FMTFBBUEVSID1cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvKnhtbCovIGBcbjxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiMTYwMFwiIGhlaWdodD1cIjEwMDBcIiB2aWV3Qm94PVwiMCAwIDE2MDAgMTAwMFwiPlxuICA8ZGVmcz5cbiAgICA8bGluZWFyR3JhZGllbnQgaWQ9XCJiYWNrZ3JvdW5kXCIgeDE9XCIwXCIgeTE9XCIwXCIgeDI9XCIxXCIgeTI9XCIxXCI+XG4gICAgICA8c3RvcCBvZmZzZXQ9XCIwXCIgc3RvcC1jb2xvcj1cIiMwQjE2MUJcIi8+XG4gICAgICA8c3RvcCBvZmZzZXQ9XCIwLjU1XCIgc3RvcC1jb2xvcj1cIiR7QlJBTkRfQ09MT1JTLnByaW1hcnl9XCIvPlxuICAgICAgPHN0b3Agb2Zmc2V0PVwiMVwiIHN0b3AtY29sb3I9XCIke0JSQU5EX0NPTE9SUy5wcmltYXJ5SG92ZXJ9XCIvPlxuICAgIDwvbGluZWFyR3JhZGllbnQ+XG4gICAgPHBhdHRlcm4gaWQ9XCJncmlkXCIgd2lkdGg9XCI2NFwiIGhlaWdodD1cIjY0XCIgcGF0dGVyblVuaXRzPVwidXNlclNwYWNlT25Vc2VcIj5cbiAgICAgIDxwYXRoIGQ9XCJNNjQgMEgwVjY0XCIgZmlsbD1cIm5vbmVcIiBzdHJva2U9XCIke0JSQU5EX0NPTE9SUy5zdXJmYWNlfVwiIHN0cm9rZS1vcGFjaXR5PVwiMC4wNDVcIi8+XG4gICAgPC9wYXR0ZXJuPlxuICA8L2RlZnM+XG4gIDxyZWN0IHdpZHRoPVwiMTYwMFwiIGhlaWdodD1cIjEwMDBcIiBmaWxsPVwidXJsKCNiYWNrZ3JvdW5kKVwiLz5cbiAgPHJlY3Qgd2lkdGg9XCIxNjAwXCIgaGVpZ2h0PVwiMTAwMFwiIGZpbGw9XCJ1cmwoI2dyaWQpXCIvPlxuICA8cGF0aCBkPVwiTTAgNzgwQzMxMCA2NTAgNDc1IDkyMCA3ODAgNzc1czUwMC0yMjAgODIwLTU1djI4MEgwWlwiIGZpbGw9XCIke0JSQU5EX0NPTE9SUy5hY2NlbnR9XCIgZmlsbC1vcGFjaXR5PVwiMC4xM1wiLz5cbiAgPHBhdGggZD1cIk0wIDgzNWMzMDAtMTI1IDUxMCAxMDUgNzkwLTEwczUwMC0xNzAgODEwLTY1XCIgZmlsbD1cIm5vbmVcIiBzdHJva2U9XCIke0JSQU5EX0NPTE9SUy5hY2NlbnR9XCIgc3Ryb2tlLXdpZHRoPVwiNFwiIHN0cm9rZS1vcGFjaXR5PVwiMC43XCIvPlxuICAke1dBTExQQVBFUl9MT0dPfVxuICA8dGV4dCB4PVwiODAwXCIgeT1cIjU1OFwiIHRleHQtYW5jaG9yPVwibWlkZGxlXCIgZmlsbD1cIiR7QlJBTkRfQ09MT1JTLm11dGVkfVwiIGZvbnQtZmFtaWx5PVwiJHtCUkFORC50eXBvZ3JhcGh5LnNhbnN9XCIgZm9udC1zaXplPVwiMjRcIiBsZXR0ZXItc3BhY2luZz1cIjVcIj5MQUtFQk9YIERFU0tUT1A8L3RleHQ+XG48L3N2Zz5cbmBcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLnRyaW0oKTtcblxuY29uc3QgREJYX1RPT0xTX1RFUk1JTkFMX0lDT04gPVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8qeG1sKi8gYFxuPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCI2NFwiIGhlaWdodD1cIjY0XCIgdmlld0JveD1cIjAgMCA2NCA2NFwiPlxuICA8cmVjdCB4PVwiNFwiIHk9XCI2XCIgd2lkdGg9XCI1NlwiIGhlaWdodD1cIjUyXCIgcng9XCIxMlwiIGZpbGw9XCIke0JSQU5EX0NPTE9SUy5wcmltYXJ5fVwiLz5cbiAgPHJlY3QgeD1cIjhcIiB5PVwiMTBcIiB3aWR0aD1cIjQ4XCIgaGVpZ2h0PVwiNDRcIiByeD1cIjhcIiBmaWxsPVwiJHtCUkFORF9DT0xPUlMucHJpbWFyeUhvdmVyfVwiLz5cbiAgPHBhdGggZD1cIm0xOCAyMyA5IDktOSA5XCIgZmlsbD1cIm5vbmVcIiBzdHJva2U9XCIke0JSQU5EX0NPTE9SUy5zdXJmYWNlfVwiIHN0cm9rZS13aWR0aD1cIjRcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIi8+XG4gIDxwYXRoIGQ9XCJNMzQgNDFoMTJcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cIiR7QlJBTkRfQ09MT1JTLmFjY2VudH1cIiBzdHJva2Utd2lkdGg9XCI0XCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiLz5cbjwvc3ZnPlxuYFxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAudHJpbSgpO1xuXG5jb25zdCBERVNLVE9QX0JSQU5EX0hFQUQgPVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8qaHRtbCovIGBcbjxzdHlsZSBpZD1cImRieC10b29scy1kZXNrdG9wLWJyYW5kXCI+XG5odG1sLGJvZHl7d2lkdGg6MTAwJTttYXgtd2lkdGg6MTAwJTtoZWlnaHQ6MTAwJTttYXgtaGVpZ2h0OjEwMCU7bWluLXdpZHRoOjA7bWluLWhlaWdodDowO292ZXJmbG93OmhpZGRlbn1cbmJvZHl7cG9zaXRpb246Zml4ZWQ7aW5zZXQ6MDt3aWR0aDp2YXIoLS1kYngtdG9vbHMtdmlld3BvcnQtd2lkdGgsMTAwdncpO2hlaWdodDp2YXIoLS1kYngtdG9vbHMtdmlld3BvcnQtaGVpZ2h0LDEwMGR2aCl9XG4jbm9WTkNfY29udGFpbmVye3dpZHRoOjEwMCUhaW1wb3J0YW50O21heC13aWR0aDoxMDAlO2hlaWdodDoxMDAlIWltcG9ydGFudDttYXgtaGVpZ2h0OjEwMCU7b3ZlcmZsb3c6aGlkZGVufVxuLm5vVk5DX2xvZ28saDEubm9WTkNfbG9nbyxhW3RpdGxlPVwiS2FzbVZOQyBMZWFybiBNb3JlXCJde2Rpc3BsYXk6bm9uZSFpbXBvcnRhbnR9XG4jbm9WTkNfZmFsbGJhY2tfZXJyb3Jtc2d7b3ZlcmZsb3ctd3JhcDphbnl3aGVyZX1cbjwvc3R5bGU+XG48bGluayBkYXRhLWRieC10b29scy1kZXNrdG9wLWljb24gcmVsPVwiaWNvblwiIGhyZWY9XCIke2RieFRvb2xzQXNzZXREYXRhVXJscy5pY29uRGFya31cIj5cbjxzY3JpcHQgaWQ9XCJkYngtdG9vbHMta2FzbS1tb2JpbGUtZ3VhcmRcIj4oKCk9Pntjb25zdCBpZ25vcmVkPShlcnJvcik9PmVycm9yIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3ImJi9eQ2FuJ3QgZmluZCB2YXJpYWJsZTogV1swLTlBLUZdezMyfSQvLnRlc3QoZXJyb3IubWVzc2FnZSk7d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLChldmVudCk9PntpZihpZ25vcmVkKGV2ZW50LmVycm9yKSl7ZXZlbnQucHJldmVudERlZmF1bHQoKTtldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKX19LHRydWUpO3dpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwidW5oYW5kbGVkcmVqZWN0aW9uXCIsKGV2ZW50KT0+e2lmKGlnbm9yZWQoZXZlbnQucmVhc29uKSl7ZXZlbnQucHJldmVudERlZmF1bHQoKTtldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKX19LHRydWUpO2xldCB0aW1lcjtjb25zdCBzeW5jPSgpPT57Y29uc3Qgdmlld3BvcnQ9d2luZG93LnZpc3VhbFZpZXdwb3J0O2RvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5zZXRQcm9wZXJ0eShcIi0tZGJ4LXRvb2xzLXZpZXdwb3J0LXdpZHRoXCIsU3RyaW5nKE1hdGgucm91bmQodmlld3BvcnQ/LndpZHRoPz93aW5kb3cuaW5uZXJXaWR0aCkpK1wicHhcIik7ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLnNldFByb3BlcnR5KFwiLS1kYngtdG9vbHMtdmlld3BvcnQtaGVpZ2h0XCIsU3RyaW5nKE1hdGgucm91bmQodmlld3BvcnQ/LmhlaWdodD8/d2luZG93LmlubmVySGVpZ2h0KSkrXCJweFwiKTt3aW5kb3cuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoXCJyZXNpemVcIikpfTtjb25zdCBzY2hlZHVsZT0oKT0+e2NsZWFyVGltZW91dCh0aW1lcik7c3luYygpO3NldFRpbWVvdXQoc3luYywyNTApO3RpbWVyPXNldFRpbWVvdXQoc3luYyw3NTApfTt3aW5kb3cudmlzdWFsVmlld3BvcnQ/LmFkZEV2ZW50TGlzdGVuZXIoXCJyZXNpemVcIixzY2hlZHVsZSk7d2luZG93LnZpc3VhbFZpZXdwb3J0Py5hZGRFdmVudExpc3RlbmVyKFwic2Nyb2xsXCIsc2NoZWR1bGUpO3dpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwib3JpZW50YXRpb25jaGFuZ2VcIixzY2hlZHVsZSk7d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJwYWdlc2hvd1wiLHNjaGVkdWxlKTtkb2N1bWVudC5yZWFkeVN0YXRlPT09XCJsb2FkaW5nXCI/ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIixzY2hlZHVsZSx7b25jZTp0cnVlfSk6c2NoZWR1bGUoKX0pKCk7PC9zY3JpcHQ+XG48c2NyaXB0IGlkPVwiZGJ4LXRvb2xzLWRlc2t0b3AtYnJhbmQtc2NyaXB0XCI+KCgpPT57Y29uc3QgaWNvbj0ke0pTT04uc3RyaW5naWZ5KGRieFRvb2xzQXNzZXREYXRhVXJscy5pY29uRGFyayl9O2NvbnN0IHJld3JpdGU9KHJvb3QpPT57aWYocm9vdC5ub2RlVHlwZT09PU5vZGUuVEVYVF9OT0RFKXtpZihyb290Lm5vZGVWYWx1ZT8uaW5jbHVkZXMoXCJLYXNtVk5DXCIpKXJvb3Qubm9kZVZhbHVlPXJvb3Qubm9kZVZhbHVlLnJlcGxhY2VBbGwoXCJLYXNtVk5DXCIsXCJkYnggdG9vbHMgRGVza3RvcFwiKTtyZXR1cm59Y29uc3Qgd2Fsa2VyPWRvY3VtZW50LmNyZWF0ZVRyZWVXYWxrZXIocm9vdCxOb2RlRmlsdGVyLlNIT1dfVEVYVCk7bGV0IG5vZGU7d2hpbGUobm9kZT13YWxrZXIubmV4dE5vZGUoKSlpZihub2RlLm5vZGVWYWx1ZT8uaW5jbHVkZXMoXCJLYXNtVk5DXCIpKW5vZGUubm9kZVZhbHVlPW5vZGUubm9kZVZhbHVlLnJlcGxhY2VBbGwoXCJLYXNtVk5DXCIsXCJkYnggdG9vbHMgRGVza3RvcFwiKX07Y29uc3QgYXBwbHk9KCk9Pntkb2N1bWVudC50aXRsZT1cImRieCB0b29scyBEZXNrdG9wXCI7Zm9yKGNvbnN0IGxpbmsgb2YgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnbGlua1tyZWx+PVwiaWNvblwiXSxsaW5rW3JlbD1cImFwcGxlLXRvdWNoLWljb25cIl0nKSlsaW5rLnNldEF0dHJpYnV0ZShcImhyZWZcIixpY29uKTtpZihkb2N1bWVudC5ib2R5KXJld3JpdGUoZG9jdW1lbnQuYm9keSl9O2lmKGRvY3VtZW50LnJlYWR5U3RhdGU9PT1cImxvYWRpbmdcIilkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLGFwcGx5LHtvbmNlOnRydWV9KTtlbHNlIGFwcGx5KCk7bmV3IE11dGF0aW9uT2JzZXJ2ZXIoKGVudHJpZXMpPT57Zm9yKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpe2lmKGVudHJ5LnR5cGU9PT1cImNoYXJhY3RlckRhdGFcIilyZXdyaXRlKGVudHJ5LnRhcmdldCk7ZWxzZSBmb3IoY29uc3Qgbm9kZSBvZiBlbnRyeS5hZGRlZE5vZGVzKXJld3JpdGUobm9kZSl9fSkub2JzZXJ2ZShkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQse2NoaWxkTGlzdDp0cnVlLHN1YnRyZWU6dHJ1ZSxjaGFyYWN0ZXJEYXRhOnRydWV9KX0pKCk7PC9zY3JpcHQ+XG5gXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC50cmltKCk7XG5cbi8qKiBNYXJrdXAgaW5qZWN0ZWQgaW50byB0aGUgS2FzbVZOQyBjbGllbnQgcGFnZSB0byBhcHBseSBkYngtdG9vbHMgYnJhbmRpbmcuICovXG5leHBvcnQgY29uc3QgZGVza3RvcEh0bWxIZWFkID0gREVTS1RPUF9CUkFORF9IRUFEO1xuXG4vKiogQnJvd3NlciBlbnRyeSBVUkwgZm9yIHRoZSBidWlsdC1pbiBLYXNtVk5DIGRlc2t0b3AuICovXG5leHBvcnQgZnVuY3Rpb24gZGVza3RvcE9wZW5VcmwocGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgbm9ybWFsaXplZCA9IHBhdGgucmVwbGFjZSgvXFwvKyQvLCBcIlwiKTtcbiAgY29uc3Qgd2Vic29ja2V0UGF0aCA9IGAke25vcm1hbGl6ZWQucmVwbGFjZSgvXlxcLysvLCBcIlwiKX0vd2Vic29ja2lmeWA7XG4gIGNvbnN0IHBhcmFtZXRlcnMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcbiAgICBhdXRvY29ubmVjdDogXCIxXCIsXG4gICAgcmVzaXplOiBcInJlbW90ZVwiLFxuICAgIHNob3dfZG90OiBcIjFcIixcbiAgICBjbGlwYm9hcmRfc2VhbWxlc3M6IFwiMFwiLFxuICAgIGVuYWJsZV93ZWJwOiBcIjBcIixcbiAgICBrYXNtdm5jX21vZGVfcHJlZmVyZW5jZTogXCItMTAyN1wiLFxuICAgIHBhdGg6IHdlYnNvY2tldFBhdGgsXG4gIH0pO1xuICByZXR1cm4gYCR7bm9ybWFsaXplZH0vPyR7cGFyYW1ldGVycy50b1N0cmluZygpfWA7XG59XG5cbi8qKiBCcmFuZGluZyBlbnZpcm9ubWVudCBjb25zdW1lZCBieSB0aGUgcGFja2FnZWQgZGVza3RvcCBzZXNzaW9uIGVudHJ5cG9pbnQuICovXG5leHBvcnQgZnVuY3Rpb24gZGVza3RvcEVudmlyb25tZW50KCk6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHN0cmluZz4+IHtcbiAgcmV0dXJuIHtcbiAgICBEQlhfVE9PTFNfREVTS1RPUF9XQUxMUEFQRVJfQkFTRTY0OiBCdWZmZXIuZnJvbShEQlhfVE9PTFNfV0FMTFBBUEVSKS50b1N0cmluZyhcImJhc2U2NFwiKSxcbiAgICBEQlhfVE9PTFNfREVTS1RPUF9CUkFORF9JQ09OX0JBU0U2NDogQnVmZmVyLmZyb20oZGJ4VG9vbHNBc3NldFN2Zy5pY29uRGFyaykudG9TdHJpbmcoXCJiYXNlNjRcIiksXG4gICAgREJYX1RPT0xTX0RFU0tUT1BfVEVSTUlOQUxfSUNPTl9CQVNFNjQ6IEJ1ZmZlci5mcm9tKERCWF9UT09MU19URVJNSU5BTF9JQ09OKS50b1N0cmluZyhcImJhc2U2NFwiKSxcbiAgICBEQlhfVE9PTFNfREVTS1RPUF9IT01FUEFHRV9CQVNFNjQ6IEJ1ZmZlci5mcm9tKEJSQU5ELmxpbmtzLndlYnNpdGUpLnRvU3RyaW5nKFwiYmFzZTY0XCIpLFxuICAgIERCWF9UT09MU19ERVNLVE9QX1BSSU1BUlk6IEJSQU5EX0NPTE9SUy5wcmltYXJ5LFxuICAgIERCWF9UT09MU19ERVNLVE9QX1BSSU1BUllfSE9WRVI6IEJSQU5EX0NPTE9SUy5wcmltYXJ5SG92ZXIsXG4gICAgREJYX1RPT0xTX0RFU0tUT1BfU1VSRkFDRTogQlJBTkRfQ09MT1JTLnN1cmZhY2UsXG4gICAgREJYX1RPT0xTX0RFU0tUT1BfRk9OVDogXCJEZWphVnUgU2Fuc1wiLFxuICB9O1xufVxuIl19
@@ -0,0 +1,59 @@
1
+ import { EventEmitter } from "node:events";
2
+ import type { LakeboxMetricsSnapshot } from "@dbx-tools/shared-lakebox";
3
+ /** Raw cumulative counters read from one sample. */
4
+ export interface LakeboxCounters {
5
+ at: number;
6
+ cores: number;
7
+ cpuBusy: number;
8
+ cpuTotal: number;
9
+ load1: number;
10
+ memoryTotalBytes: number;
11
+ memoryAvailableBytes: number;
12
+ storageTotalBytes: number;
13
+ storageUsedBytes: number;
14
+ rxBytes: number;
15
+ txBytes: number;
16
+ }
17
+ /** Events emitted by {@link LakeboxMetrics}. */
18
+ export interface LakeboxMetricsEvents {
19
+ snapshot: [LakeboxMetricsSnapshot];
20
+ }
21
+ /**
22
+ * In-process metrics emitter for the app Lakebox.
23
+ *
24
+ * Sampling runs only between {@link start} and {@link stop}, which the runtime
25
+ * ties to the Lakebox running state. Samples contain machine-level CPU,
26
+ * memory, persistent storage, and network counters; they never contain
27
+ * process names, arguments, environment, or per-process usage.
28
+ */
29
+ export declare class LakeboxMetrics extends EventEmitter<LakeboxMetricsEvents> {
30
+ private readonly read;
31
+ private readonly intervalMs;
32
+ private readonly capacity;
33
+ private readonly samples;
34
+ private previous?;
35
+ private timer?;
36
+ private controller?;
37
+ /** Creates a stopped emitter that reads raw counters with `read`. */
38
+ constructor(read: (signal: AbortSignal) => Promise<string>, intervalMs: number, capacity?: number);
39
+ /** Whether sampling is active. */
40
+ get running(): boolean;
41
+ /** Recent samples, oldest first. */
42
+ series(): readonly LakeboxMetricsSnapshot[];
43
+ /** Seeds one validated sample without starting the recurring sampler or emitting an event. */
44
+ seed(output: string, at?: number): LakeboxMetricsSnapshot;
45
+ /** Starts sampling. Repeated calls are ignored. */
46
+ start(): void;
47
+ /** Stops sampling and clears the series. */
48
+ stop(): void;
49
+ private tick;
50
+ private record;
51
+ }
52
+ /**
53
+ * Parses the package-owned metrics command output.
54
+ *
55
+ * @throws When a required counter is missing.
56
+ */
57
+ export declare function parseLakeboxCounters(output: string, at?: number): LakeboxCounters;
58
+ /** Converts cumulative counters to one snapshot using the previous sample for rates. */
59
+ export declare function toSnapshot(current: LakeboxCounters, previous?: LakeboxCounters): LakeboxMetricsSnapshot;