@dbx-tools/appkit-lakebox 0.9.136 → 0.9.139
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -2
- package/package.json +10 -10
- package/scripts/__pycache__/lakebox-service.cpython-310.pyc +0 -0
- package/scripts/lakebox-service.py +83 -42
package/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/appkit-lakebox";
|
|
6
|
-
export const PACKAGE_VERSION = "0.9.
|
|
6
|
+
export const PACKAGE_VERSION = "0.9.139";
|
|
7
7
|
export * as config from "./src/config.ts";
|
|
8
8
|
export * as desktop from "./src/desktop.ts";
|
|
9
9
|
export * as metrics from "./src/metrics.ts";
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const PACKAGE_IDENTIFIER = "@dbx-tools/appkit-lakebox";
|
|
2
|
-
export declare const PACKAGE_VERSION = "0.9.
|
|
2
|
+
export declare const PACKAGE_VERSION = "0.9.139";
|
|
3
3
|
export * as config from "./src/config.ts";
|
|
4
4
|
export * as desktop from "./src/desktop.ts";
|
|
5
5
|
export * as metrics from "./src/metrics.ts";
|
package/lib/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Regenerated from the exporting modules in ./src.
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/appkit-lakebox";
|
|
5
|
-
export const PACKAGE_VERSION = "0.9.
|
|
5
|
+
export const PACKAGE_VERSION = "0.9.139";
|
|
6
6
|
export * as config from "./src/config.js";
|
|
7
7
|
export * as desktop from "./src/desktop.js";
|
|
8
8
|
export * as metrics from "./src/metrics.js";
|
|
@@ -23,4 +23,4 @@ export { LakeboxControllerDefinitionSchema, LakeboxControllerServiceSchema } fro
|
|
|
23
23
|
export { LAKEBOX_SKILLS_MOUNT } from "./src/skills.js";
|
|
24
24
|
export { LAKEBOX_AGENT_USER, LAKEBOX_AGENT_HOME, LAKEBOX_STATE_ROOT, LAKEBOX_USERS_ROOT, LAKEBOX_RUNTIME_ROOT, LAKEBOX_RUN_ROOT, LAKEBOX_UID_MIN, LAKEBOX_UID_COUNT, LAKEBOX_PORT_MIN, LAKEBOX_PORT_COUNT } from "./src/user.js";
|
|
25
25
|
export { LakeboxWorkspaceSandbox } from "./src/workspace.js";
|
|
26
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRywyQkFBMkIsQ0FBQztBQUM5RCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sS0FBSyxRQUFRLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssSUFBSSxNQUFNLGVBQWUsQ0FBQztBQUN0QyxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTVELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNuRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFbEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE9BQU8sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXZELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVsRCxPQUFPLEVBQUUsaUNBQWlDLEVBQUUsOEJBQThCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUV0RyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQUUsb0JBQW9CLEVBQUUsZ0JBQWdCLEVBQUUsZUFBZSxFQUFFLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLGtCQUFrQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pPLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gR0VORVJBVEVEIGJ5IHByb2plbiB3YXRjaCAtIERPIE5PVCBFRElULlxuLy8gUmVnZW5lcmF0ZWQgZnJvbSB0aGUgZXhwb3J0aW5nIG1vZHVsZXMgaW4gLi9zcmMuXG4vLyBIYW5kIGVkaXRzIGFyZSBvdmVyd3JpdHRlbiBvbiB0aGUgbmV4dCB3YXRjaDsgdGhpcyBmaWxlIGlzIHJlYWQtb25seS5cblxuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfSURFTlRJRklFUiA9IFwiQGRieC10b29scy9hcHBraXQtbGFrZWJveFwiO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9IFwiMC45LjEzOVwiO1xuZXhwb3J0ICogYXMgY29uZmlnIGZyb20gXCIuL3NyYy9jb25maWcudHNcIjtcbmV4cG9ydCAqIGFzIGRlc2t0b3AgZnJvbSBcIi4vc3JjL2Rlc2t0b3AudHNcIjtcbmV4cG9ydCAqIGFzIG1ldHJpY3MgZnJvbSBcIi4vc3JjL21ldHJpY3MudHNcIjtcbmV4cG9ydCAqIGFzIHBsdWdpbiBmcm9tIFwiLi9zcmMvcGx1Z2luLnRzXCI7XG5leHBvcnQgKiBhcyByb3V0ZXMgZnJvbSBcIi4vc3JjL3JvdXRlcy50c1wiO1xuZXhwb3J0ICogYXMgcnVudGltZSBmcm9tIFwiLi9zcmMvcnVudGltZS50c1wiO1xuZXhwb3J0ICogYXMgc2VydmljZXMgZnJvbSBcIi4vc3JjL3NlcnZpY2VzLnRzXCI7XG5leHBvcnQgKiBhcyBza2lsbHMgZnJvbSBcIi4vc3JjL3NraWxscy50c1wiO1xuZXhwb3J0ICogYXMgdXNlciBmcm9tIFwiLi9zcmMvdXNlci50c1wiO1xuZXhwb3J0ICogYXMgd29ya3NwYWNlIGZyb20gXCIuL3NyYy93b3Jrc3BhY2UudHNcIjtcbmV4cG9ydCB7IExha2Vib3hQbHVnaW5Db25maWdTY2hlbWEgfSBmcm9tIFwiLi9zcmMvY29uZmlnLnRzXCI7XG5leHBvcnQgdHlwZSB7IFNlcmlhbGl6YWJsZUxha2Vib3hQbHVnaW5Db25maWcsIFJlc29sdmVkTGFrZWJveFBsdWdpbkNvbmZpZywgTGFrZWJveFBsdWdpbkNvbmZpZyB9IGZyb20gXCIuL3NyYy9jb25maWcudHNcIjtcbmV4cG9ydCB7IGRlc2t0b3BIdG1sSGVhZCB9IGZyb20gXCIuL3NyYy9kZXNrdG9wLnRzXCI7XG5leHBvcnQgeyBMYWtlYm94TWV0cmljcyB9IGZyb20gXCIuL3NyYy9tZXRyaWNzLnRzXCI7XG5leHBvcnQgdHlwZSB7IExha2Vib3hDb3VudGVycywgTGFrZWJveE1ldHJpY3NFdmVudHMgfSBmcm9tIFwiLi9zcmMvbWV0cmljcy50c1wiO1xuZXhwb3J0IHsgQXBwS2l0TGFrZWJveFBsdWdpbiwgbGFrZWJveCB9IGZyb20gXCIuL3NyYy9wbHVnaW4udHNcIjtcbmV4cG9ydCB7IExha2Vib3hSb3V0ZVJlZ2lzdHJ5IH0gZnJvbSBcIi4vc3JjL3JvdXRlcy50c1wiO1xuZXhwb3J0IHR5cGUgeyBMYWtlYm94Um91dGVSZXNvbHV0aW9uLCBMYWtlYm94Um91dGVSZXNvbHZlciB9IGZyb20gXCIuL3NyYy9yb3V0ZXMudHNcIjtcbmV4cG9ydCB7IExha2Vib3hSdW50aW1lIH0gZnJvbSBcIi4vc3JjL3J1bnRpbWUudHNcIjtcbmV4cG9ydCB0eXBlIHsgTGFrZWJveElkZW50aXR5UmVzb2x2ZXIsIExha2Vib3hMZWdhY3lQb29sIH0gZnJvbSBcIi4vc3JjL3J1bnRpbWUudHNcIjtcbmV4cG9ydCB7IExha2Vib3hDb250cm9sbGVyRGVmaW5pdGlvblNjaGVtYSwgTGFrZWJveENvbnRyb2xsZXJTZXJ2aWNlU2NoZW1hIH0gZnJvbSBcIi4vc3JjL3NlcnZpY2VzLnRzXCI7XG5leHBvcnQgdHlwZSB7IExha2Vib3hDb250cm9sbGVyRGVmaW5pdGlvbiwgTGFrZWJveENvbnRyb2xsZXJTZXJ2aWNlLCBMYWtlYm94U2VydmljZVJvdXRlIH0gZnJvbSBcIi4vc3JjL3NlcnZpY2VzLnRzXCI7XG5leHBvcnQgeyBMQUtFQk9YX1NLSUxMU19NT1VOVCB9IGZyb20gXCIuL3NyYy9za2lsbHMudHNcIjtcbmV4cG9ydCB7IExBS0VCT1hfQUdFTlRfVVNFUiwgTEFLRUJPWF9BR0VOVF9IT01FLCBMQUtFQk9YX1NUQVRFX1JPT1QsIExBS0VCT1hfVVNFUlNfUk9PVCwgTEFLRUJPWF9SVU5USU1FX1JPT1QsIExBS0VCT1hfUlVOX1JPT1QsIExBS0VCT1hfVUlEX01JTiwgTEFLRUJPWF9VSURfQ09VTlQsIExBS0VCT1hfUE9SVF9NSU4sIExBS0VCT1hfUE9SVF9DT1VOVCB9IGZyb20gXCIuL3NyYy91c2VyLnRzXCI7XG5leHBvcnQgeyBMYWtlYm94V29ya3NwYWNlU2FuZGJveCB9IGZyb20gXCIuL3NyYy93b3Jrc3BhY2UudHNcIjtcbmV4cG9ydCB0eXBlIHsgTGFrZWJveFdvcmtzcGFjZVNhbmRib3hPcHRpb25zIH0gZnJvbSBcIi4vc3JjL3dvcmtzcGFjZS50c1wiO1xuIl19
|
package/package.json
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"projen": "projen"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@dbx-tools/auth": "^0.9.
|
|
22
|
+
"@dbx-tools/auth": "^0.9.139",
|
|
23
23
|
"@types/express": "^5.0.5",
|
|
24
24
|
"@types/json-schema": "^7",
|
|
25
25
|
"@types/node": "^24.6.0",
|
|
@@ -29,14 +29,14 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@databricks/appkit": "0.81.0",
|
|
32
|
-
"@dbx-tools/appkit": "^0.9.
|
|
33
|
-
"@dbx-tools/appkit-mastra": "^0.9.
|
|
34
|
-
"@dbx-tools/core": "^0.9.
|
|
35
|
-
"@dbx-tools/lakebox": "^0.9.
|
|
36
|
-
"@dbx-tools/postgres": "^0.9.
|
|
37
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
38
|
-
"@dbx-tools/shared-lakebox": "^0.9.
|
|
39
|
-
"@dbx-tools/ui": "^0.9.
|
|
32
|
+
"@dbx-tools/appkit": "^0.9.139",
|
|
33
|
+
"@dbx-tools/appkit-mastra": "^0.9.139",
|
|
34
|
+
"@dbx-tools/core": "^0.9.139",
|
|
35
|
+
"@dbx-tools/lakebox": "^0.9.139",
|
|
36
|
+
"@dbx-tools/postgres": "^0.9.139",
|
|
37
|
+
"@dbx-tools/shared-core": "^0.9.139",
|
|
38
|
+
"@dbx-tools/shared-lakebox": "^0.9.139",
|
|
39
|
+
"@dbx-tools/ui": "^0.9.139",
|
|
40
40
|
"@mastra/core": "1.71.0",
|
|
41
41
|
"http-proxy-3": "^1.23.1",
|
|
42
42
|
"zod": "4.3.6"
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"./package.json": "./package.json"
|
|
100
100
|
}
|
|
101
101
|
},
|
|
102
|
-
"version": "0.9.
|
|
102
|
+
"version": "0.9.139",
|
|
103
103
|
"types": "./lib/index.d.ts",
|
|
104
104
|
"dbxToolsConfig": {
|
|
105
105
|
"tags": [
|
|
Binary file
|
|
@@ -62,6 +62,7 @@ def namespaced(args, log=None, check=True, capture=False):
|
|
|
62
62
|
stdout=subprocess.PIPE if capture else sink,
|
|
63
63
|
stderr=sink,
|
|
64
64
|
text=True,
|
|
65
|
+
check=False,
|
|
65
66
|
)
|
|
66
67
|
if check and result.returncode != 0:
|
|
67
68
|
raise RuntimeError(f"{args[0]} {args[1] if len(args) > 1 else ''} exited {result.returncode}")
|
|
@@ -135,9 +136,8 @@ def listener_owner(port):
|
|
|
135
136
|
|
|
136
137
|
|
|
137
138
|
def port_open(port):
|
|
138
|
-
with contextlib.suppress(OSError):
|
|
139
|
-
|
|
140
|
-
return True
|
|
139
|
+
with contextlib.suppress(OSError), socket.create_connection(("127.0.0.1", port), timeout=0.5):
|
|
140
|
+
return True
|
|
141
141
|
return False
|
|
142
142
|
|
|
143
143
|
|
|
@@ -150,7 +150,10 @@ def ensure_storage():
|
|
|
150
150
|
f'runroot = "{RUN}/storage"\ngraphroot = "{STORAGE}/storage"\n'
|
|
151
151
|
'[storage.options.vfs]\nignore_chown_errors = "true"\n'
|
|
152
152
|
)
|
|
153
|
-
|
|
153
|
+
existing = None
|
|
154
|
+
with contextlib.suppress(FileNotFoundError), open(conf, encoding="utf-8") as handle:
|
|
155
|
+
existing = handle.read()
|
|
156
|
+
if existing != content:
|
|
154
157
|
with open(conf, "w", encoding="utf-8") as handle:
|
|
155
158
|
handle.write(content)
|
|
156
159
|
|
|
@@ -368,18 +371,31 @@ def remove(name):
|
|
|
368
371
|
return {"removed": True}
|
|
369
372
|
|
|
370
373
|
|
|
371
|
-
def
|
|
372
|
-
definition = read_definition(name)
|
|
374
|
+
def read_status(name):
|
|
373
375
|
status = {}
|
|
374
|
-
with
|
|
375
|
-
|
|
376
|
-
|
|
376
|
+
with (
|
|
377
|
+
contextlib.suppress(FileNotFoundError, json.JSONDecodeError),
|
|
378
|
+
open(f"{service_dir(name)}/status.json", encoding="utf-8") as handle,
|
|
379
|
+
):
|
|
380
|
+
status = json.load(handle)
|
|
381
|
+
return status
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def resolve_service_state(status, running, lock_is_held):
|
|
377
385
|
state = status.get("state", "stopped")
|
|
378
|
-
running = crun_state(name) == "running"
|
|
379
386
|
if state == "ready" and not running:
|
|
380
|
-
|
|
381
|
-
if state == "starting" and not running and not
|
|
382
|
-
|
|
387
|
+
return "stopped"
|
|
388
|
+
if state == "starting" and not running and not lock_is_held:
|
|
389
|
+
return "error" if status.get("error") else "stopped"
|
|
390
|
+
return state
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def describe(name, include_log=False):
|
|
394
|
+
definition = read_definition(name)
|
|
395
|
+
status = read_status(name)
|
|
396
|
+
running = crun_state(name) == "running"
|
|
397
|
+
lock_is_held = lock_held(name) if status.get("state") == "starting" and not running else False
|
|
398
|
+
state = resolve_service_state(status, running, lock_is_held)
|
|
383
399
|
result = {"name": name, "state": state, "definition": definition}
|
|
384
400
|
if status.get("error") and state == "error":
|
|
385
401
|
result["error"] = status["error"]
|
|
@@ -389,12 +405,14 @@ def describe(name, include_log=False):
|
|
|
389
405
|
|
|
390
406
|
|
|
391
407
|
def lock_held(name):
|
|
392
|
-
with
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
408
|
+
with (
|
|
409
|
+
contextlib.suppress(FileNotFoundError),
|
|
410
|
+
open(f"{service_dir(name)}/.lock", "w", encoding="utf-8") as handle,
|
|
411
|
+
):
|
|
412
|
+
try:
|
|
413
|
+
fcntl.flock(handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
414
|
+
except BlockingIOError:
|
|
415
|
+
return True
|
|
398
416
|
return False
|
|
399
417
|
|
|
400
418
|
|
|
@@ -418,30 +436,53 @@ def tail(name, max_lines, max_chars):
|
|
|
418
436
|
return "\n".join(text.splitlines()[-max_lines:])[-max_chars:]
|
|
419
437
|
|
|
420
438
|
|
|
439
|
+
def put_command(encoded_definition):
|
|
440
|
+
definition = json.loads(base64.b64decode(encoded_definition))
|
|
441
|
+
name = definition["name"]
|
|
442
|
+
with locked(name):
|
|
443
|
+
write_json(f"{service_dir(name)}/service.json", definition)
|
|
444
|
+
return describe(name)
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
def list_command():
|
|
448
|
+
return {"services": [describe(name, include_log=True) for name in names()]}
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
def logs_command(name, max_lines, max_chars):
|
|
452
|
+
return {"log": tail(name, int(max_lines), int(max_chars))}
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
def start_all_command():
|
|
456
|
+
return {"services": [start(name) for name in names() if read_definition(name).get("autostart")]}
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
COMMANDS = {
|
|
460
|
+
"put": put_command,
|
|
461
|
+
"start": start,
|
|
462
|
+
"stop": stop,
|
|
463
|
+
"remove": remove,
|
|
464
|
+
"list": list_command,
|
|
465
|
+
"logs": logs_command,
|
|
466
|
+
"start-all": start_all_command,
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def usage():
|
|
471
|
+
print(f"usage: lakebox-service {'|'.join(COMMANDS)}", file=sys.stderr)
|
|
472
|
+
raise SystemExit(2)
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
def dispatch(command, args):
|
|
476
|
+
handler = COMMANDS.get(command)
|
|
477
|
+
if handler is None:
|
|
478
|
+
usage()
|
|
479
|
+
return handler(*args)
|
|
480
|
+
|
|
481
|
+
|
|
421
482
|
def main():
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
name = definition["name"]
|
|
426
|
-
with locked(name):
|
|
427
|
-
write_json(f"{service_dir(name)}/service.json", definition)
|
|
428
|
-
output = describe(name)
|
|
429
|
-
elif command == "start":
|
|
430
|
-
output = start(sys.argv[2])
|
|
431
|
-
elif command == "stop":
|
|
432
|
-
output = stop(sys.argv[2])
|
|
433
|
-
elif command == "remove":
|
|
434
|
-
output = remove(sys.argv[2])
|
|
435
|
-
elif command == "list":
|
|
436
|
-
output = {"services": [describe(name, include_log=True) for name in names()]}
|
|
437
|
-
elif command == "logs":
|
|
438
|
-
output = {"log": tail(sys.argv[2], int(sys.argv[3]), int(sys.argv[4]))}
|
|
439
|
-
elif command == "start-all":
|
|
440
|
-
output = {"services": [start(name) for name in names() if read_definition(name).get("autostart")]}
|
|
441
|
-
else:
|
|
442
|
-
print("usage: lakebox-service put|start|stop|remove|list|logs|start-all", file=sys.stderr)
|
|
443
|
-
sys.exit(2)
|
|
444
|
-
json.dump(output, sys.stdout)
|
|
483
|
+
if len(sys.argv) < 2:
|
|
484
|
+
usage()
|
|
485
|
+
json.dump(dispatch(sys.argv[1], sys.argv[2:]), sys.stdout)
|
|
445
486
|
|
|
446
487
|
|
|
447
488
|
if __name__ == "__main__":
|