ghostdock 0.0.15 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-reference.md +2 -0
- package/dist/cli.md +5 -0
- package/dist/index.js +176 -140
- package/package.json +1 -1
package/dist/cli-reference.md
CHANGED
|
@@ -1106,6 +1106,8 @@ ghostdock sandboxes files upload <sandbox-id> [path] [flags]
|
|
|
1106
1106
|
| --- | --- |
|
|
1107
1107
|
| `<sandbox-id>` | Sandbox name or id. Required. |
|
|
1108
1108
|
| `--org <value>` | Organization id or slug, from `ghostdock organizations list` (default: GHOSTDOCK_ORG, then `ghostdock organizations use`). |
|
|
1109
|
+
| `--container <value>` | Container the files land in, by name, from `ghostdock sandboxes containers list`. Default: the sandbox's default container, else the one running container. |
|
|
1110
|
+
| `--start` | Start the container first when it is not running, without asking. |
|
|
1109
1111
|
| `--zip <value>` | Local ZIP file to upload. |
|
|
1110
1112
|
| `<path>` | File or directory to upload (additional paths are allowed). |
|
|
1111
1113
|
|
package/dist/cli.md
CHANGED
|
@@ -451,11 +451,16 @@ multiple files, or a large ZIP, use the dedicated multipart upload command inste
|
|
|
451
451
|
ghostdock sandboxes files upload quiet-harbor ./dist
|
|
452
452
|
ghostdock sandboxes files upload quiet-harbor ./index.html ./assets
|
|
453
453
|
ghostdock sandboxes files upload quiet-harbor --zip ./site.zip
|
|
454
|
+
ghostdock sandboxes files upload quiet-harbor ./dist --container web --start
|
|
454
455
|
```
|
|
455
456
|
|
|
456
457
|
Each positional path may be a file or directory. Directory contents are uploaded recursively,
|
|
457
458
|
preserving their relative paths; a file is uploaded by its basename. A `sandboxes files upload` call needs
|
|
458
459
|
at least one path or `--zip`. Uploading to a stopped sandbox resumes it automatically.
|
|
460
|
+
The files land in a container as the other `files` commands do (see
|
|
461
|
+
[Containers in a sandbox](#containers-in-a-sandbox)): `--container <name>`, else the default,
|
|
462
|
+
else the one running, and the CLI asks which one when it cannot tell. A stopped target container
|
|
463
|
+
is started after a "Start it?" at the keyboard, or at once with `--start`.
|
|
459
464
|
|
|
460
465
|
### `ghostdock env`
|
|
461
466
|
|
package/dist/index.js
CHANGED
|
@@ -9176,7 +9176,7 @@ function getCliName(argv = process.argv) {
|
|
|
9176
9176
|
return CLI_NAMES.find((name) => name === invoked) ?? "ghostdock";
|
|
9177
9177
|
}
|
|
9178
9178
|
// package.json
|
|
9179
|
-
var version = "0.0.
|
|
9179
|
+
var version = "0.0.16";
|
|
9180
9180
|
var package_default = {
|
|
9181
9181
|
name: "ghostdock",
|
|
9182
9182
|
description: "Ghostdock CLI — device login and agent tool invocation from the command line",
|
|
@@ -9781,77 +9781,6 @@ var envCommand = defineCommand({
|
|
|
9781
9781
|
}
|
|
9782
9782
|
});
|
|
9783
9783
|
|
|
9784
|
-
// src/container-logs.ts
|
|
9785
|
-
var FOLLOW_INTERVAL_MS = 2000;
|
|
9786
|
-
function defaultLogsDeps(follow) {
|
|
9787
|
-
let stop = false;
|
|
9788
|
-
if (follow) {
|
|
9789
|
-
process.once("SIGINT", () => {
|
|
9790
|
-
stop = true;
|
|
9791
|
-
});
|
|
9792
|
-
}
|
|
9793
|
-
return {
|
|
9794
|
-
request: (input) => authorizedRequest("/api/v1/tools/sandboxes_containers_logs", {
|
|
9795
|
-
method: "POST",
|
|
9796
|
-
body: JSON.stringify(input)
|
|
9797
|
-
}),
|
|
9798
|
-
out: (line) => process.stdout.write(`${line}
|
|
9799
|
-
`),
|
|
9800
|
-
err: (line) => process.stderr.write(`${line}
|
|
9801
|
-
`),
|
|
9802
|
-
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
9803
|
-
stopped: () => stop
|
|
9804
|
-
};
|
|
9805
|
-
}
|
|
9806
|
-
async function runContainerLogs(input, options, deps = defaultLogsDeps(options.follow)) {
|
|
9807
|
-
const json = isJsonOutput();
|
|
9808
|
-
const color = colorEnabled(process.stdout);
|
|
9809
|
-
const print = (line) => {
|
|
9810
|
-
if (json) {
|
|
9811
|
-
deps.out(JSON.stringify(line));
|
|
9812
|
-
return;
|
|
9813
|
-
}
|
|
9814
|
-
const text = options.timestamps && line.time ? `${dim(line.time, color)} ${line.text}` : line.text;
|
|
9815
|
-
(line.stream === "stderr" ? deps.err : deps.out)(text);
|
|
9816
|
-
};
|
|
9817
|
-
let result = await deps.request(input);
|
|
9818
|
-
if (!result.running) {
|
|
9819
|
-
deps.err("The sandbox is stopped: it has no logs to show.");
|
|
9820
|
-
return 1;
|
|
9821
|
-
}
|
|
9822
|
-
let last = null;
|
|
9823
|
-
for (;; ) {
|
|
9824
|
-
for (const line of result.lines) {
|
|
9825
|
-
print(line);
|
|
9826
|
-
if (line.time)
|
|
9827
|
-
last = line.time;
|
|
9828
|
-
}
|
|
9829
|
-
if (!options.follow) {
|
|
9830
|
-
if (result.truncated && json) {
|
|
9831
|
-
deps.out(JSON.stringify({ truncated: true }));
|
|
9832
|
-
} else if (result.truncated) {
|
|
9833
|
-
deps.err(dim("(older lines left out: use --tail for more)", colorEnabled(process.stderr)));
|
|
9834
|
-
}
|
|
9835
|
-
return 0;
|
|
9836
|
-
}
|
|
9837
|
-
if (!result.truncated)
|
|
9838
|
-
await deps.sleep(FOLLOW_INTERVAL_MS);
|
|
9839
|
-
if (deps.stopped())
|
|
9840
|
-
return 0;
|
|
9841
|
-
const { tail: _tail, ...rest } = input;
|
|
9842
|
-
try {
|
|
9843
|
-
result = await deps.request(last ? { ...rest, after: last } : input);
|
|
9844
|
-
} catch (error) {
|
|
9845
|
-
deps.err(red(error instanceof Error ? error.message : String(error), colorEnabled(process.stderr)));
|
|
9846
|
-
return 1;
|
|
9847
|
-
}
|
|
9848
|
-
if (!result.running) {
|
|
9849
|
-
deps.err("The sandbox stopped.");
|
|
9850
|
-
return 0;
|
|
9851
|
-
}
|
|
9852
|
-
}
|
|
9853
|
-
}
|
|
9854
|
-
|
|
9855
9784
|
// src/container-picker.ts
|
|
9856
9785
|
import { createInterface } from "node:readline/promises";
|
|
9857
9786
|
function notRunningContainerOf(error) {
|
|
@@ -9985,6 +9914,130 @@ async function withProgress(message, work, options) {
|
|
|
9985
9914
|
}
|
|
9986
9915
|
}
|
|
9987
9916
|
|
|
9917
|
+
// src/container-flow.ts
|
|
9918
|
+
async function withContainerPick(call, send, pickers, notice) {
|
|
9919
|
+
try {
|
|
9920
|
+
return await send();
|
|
9921
|
+
} catch (err) {
|
|
9922
|
+
const question = containerQuestionOf(err);
|
|
9923
|
+
if (!pickers || !question || !call.canPick)
|
|
9924
|
+
throw err;
|
|
9925
|
+
const container = await pickers.choose(question);
|
|
9926
|
+
if (!container)
|
|
9927
|
+
throw err;
|
|
9928
|
+
call.setContainer(container);
|
|
9929
|
+
const result = await send();
|
|
9930
|
+
if (call.sandboxId !== undefined && await pickers.confirmDefault(container)) {
|
|
9931
|
+
try {
|
|
9932
|
+
await authorizedRequest("/api/v1/tools/sandboxes_default_container", {
|
|
9933
|
+
method: "POST",
|
|
9934
|
+
body: JSON.stringify({
|
|
9935
|
+
organization: call.organization,
|
|
9936
|
+
sandboxId: call.sandboxId,
|
|
9937
|
+
container
|
|
9938
|
+
})
|
|
9939
|
+
});
|
|
9940
|
+
notice(eventLine("done", `Default container: ${container}.`));
|
|
9941
|
+
} catch (err) {
|
|
9942
|
+
notice(eventLine("failed", `The default container was not set: ${err instanceof Error ? err.message : String(err)}`));
|
|
9943
|
+
}
|
|
9944
|
+
}
|
|
9945
|
+
return result;
|
|
9946
|
+
}
|
|
9947
|
+
}
|
|
9948
|
+
async function withContainerStart(call, send, start, pickers, notice) {
|
|
9949
|
+
try {
|
|
9950
|
+
return await send();
|
|
9951
|
+
} catch (err) {
|
|
9952
|
+
const container = notRunningContainerOf(err);
|
|
9953
|
+
if (!container || call.sandboxId === undefined)
|
|
9954
|
+
throw err;
|
|
9955
|
+
if (!start && !(pickers && await pickers.confirmStart(container)))
|
|
9956
|
+
throw err;
|
|
9957
|
+
await withProgress("Starting container…", () => authorizedRequest("/api/v1/tools/sandboxes_containers_start", {
|
|
9958
|
+
method: "POST",
|
|
9959
|
+
body: JSON.stringify({
|
|
9960
|
+
organization: call.organization,
|
|
9961
|
+
sandboxId: call.sandboxId,
|
|
9962
|
+
container
|
|
9963
|
+
})
|
|
9964
|
+
}));
|
|
9965
|
+
notice(eventLine("done", `Started ${container}.`));
|
|
9966
|
+
return await send();
|
|
9967
|
+
}
|
|
9968
|
+
}
|
|
9969
|
+
|
|
9970
|
+
// src/container-logs.ts
|
|
9971
|
+
var FOLLOW_INTERVAL_MS = 2000;
|
|
9972
|
+
function defaultLogsDeps(follow) {
|
|
9973
|
+
let stop = false;
|
|
9974
|
+
if (follow) {
|
|
9975
|
+
process.once("SIGINT", () => {
|
|
9976
|
+
stop = true;
|
|
9977
|
+
});
|
|
9978
|
+
}
|
|
9979
|
+
return {
|
|
9980
|
+
request: (input) => authorizedRequest("/api/v1/tools/sandboxes_containers_logs", {
|
|
9981
|
+
method: "POST",
|
|
9982
|
+
body: JSON.stringify(input)
|
|
9983
|
+
}),
|
|
9984
|
+
out: (line) => process.stdout.write(`${line}
|
|
9985
|
+
`),
|
|
9986
|
+
err: (line) => process.stderr.write(`${line}
|
|
9987
|
+
`),
|
|
9988
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
9989
|
+
stopped: () => stop
|
|
9990
|
+
};
|
|
9991
|
+
}
|
|
9992
|
+
async function runContainerLogs(input, options, deps = defaultLogsDeps(options.follow)) {
|
|
9993
|
+
const json = isJsonOutput();
|
|
9994
|
+
const color = colorEnabled(process.stdout);
|
|
9995
|
+
const print = (line) => {
|
|
9996
|
+
if (json) {
|
|
9997
|
+
deps.out(JSON.stringify(line));
|
|
9998
|
+
return;
|
|
9999
|
+
}
|
|
10000
|
+
const text = options.timestamps && line.time ? `${dim(line.time, color)} ${line.text}` : line.text;
|
|
10001
|
+
(line.stream === "stderr" ? deps.err : deps.out)(text);
|
|
10002
|
+
};
|
|
10003
|
+
let result = await deps.request(input);
|
|
10004
|
+
if (!result.running) {
|
|
10005
|
+
deps.err("The sandbox is stopped: it has no logs to show.");
|
|
10006
|
+
return 1;
|
|
10007
|
+
}
|
|
10008
|
+
let last = null;
|
|
10009
|
+
for (;; ) {
|
|
10010
|
+
for (const line of result.lines) {
|
|
10011
|
+
print(line);
|
|
10012
|
+
if (line.time)
|
|
10013
|
+
last = line.time;
|
|
10014
|
+
}
|
|
10015
|
+
if (!options.follow) {
|
|
10016
|
+
if (result.truncated && json) {
|
|
10017
|
+
deps.out(JSON.stringify({ truncated: true }));
|
|
10018
|
+
} else if (result.truncated) {
|
|
10019
|
+
deps.err(dim("(older lines left out: use --tail for more)", colorEnabled(process.stderr)));
|
|
10020
|
+
}
|
|
10021
|
+
return 0;
|
|
10022
|
+
}
|
|
10023
|
+
if (!result.truncated)
|
|
10024
|
+
await deps.sleep(FOLLOW_INTERVAL_MS);
|
|
10025
|
+
if (deps.stopped())
|
|
10026
|
+
return 0;
|
|
10027
|
+
const { tail: _tail, ...rest } = input;
|
|
10028
|
+
try {
|
|
10029
|
+
result = await deps.request(last ? { ...rest, after: last } : input);
|
|
10030
|
+
} catch (error) {
|
|
10031
|
+
deps.err(red(error instanceof Error ? error.message : String(error), colorEnabled(process.stderr)));
|
|
10032
|
+
return 1;
|
|
10033
|
+
}
|
|
10034
|
+
if (!result.running) {
|
|
10035
|
+
deps.err("The sandbox stopped.");
|
|
10036
|
+
return 0;
|
|
10037
|
+
}
|
|
10038
|
+
}
|
|
10039
|
+
}
|
|
10040
|
+
|
|
9988
10041
|
// src/human.ts
|
|
9989
10042
|
var ID_KEYS = [
|
|
9990
10043
|
"sandboxId",
|
|
@@ -10288,10 +10341,10 @@ function buildToolInput(schema, rawArgs) {
|
|
|
10288
10341
|
|
|
10289
10342
|
// src/commands/invoke.ts
|
|
10290
10343
|
async function runToolInvoke(tool, rawArgs, log = console.log, error = printError, notice = printNotice, pickers = defaultContainerPickers()) {
|
|
10344
|
+
const properties = tool.inputSchema.properties;
|
|
10291
10345
|
let input;
|
|
10292
10346
|
try {
|
|
10293
10347
|
input = buildToolInput(tool.inputSchema, rawArgs);
|
|
10294
|
-
const properties = tool.inputSchema.properties;
|
|
10295
10348
|
if (properties && "organization" in properties && input.organization === undefined) {
|
|
10296
10349
|
input.organization = await requireOrganizationRef(undefined, notice);
|
|
10297
10350
|
}
|
|
@@ -10310,24 +10363,33 @@ async function runToolInvoke(tool, rawArgs, log = console.log, error = printErro
|
|
|
10310
10363
|
return 1;
|
|
10311
10364
|
}
|
|
10312
10365
|
}
|
|
10366
|
+
const call = {
|
|
10367
|
+
organization: typeof input.organization === "string" ? input.organization : undefined,
|
|
10368
|
+
sandboxId: typeof input.sandboxId === "string" ? input.sandboxId : undefined,
|
|
10369
|
+
canPick: !!properties && "container" in properties && !input.container,
|
|
10370
|
+
setContainer: (container) => {
|
|
10371
|
+
input.container = container;
|
|
10372
|
+
}
|
|
10373
|
+
};
|
|
10313
10374
|
try {
|
|
10314
|
-
const
|
|
10375
|
+
const post = () => authorizedRequest(`/api/v1/tools/${tool.name}`, {
|
|
10315
10376
|
method: "POST",
|
|
10316
10377
|
body: JSON.stringify(input)
|
|
10317
10378
|
});
|
|
10318
|
-
const request = () => withContainerStart(input, send, rawArgs.start === true, pickers, notice);
|
|
10319
10379
|
const waitMessage = PROGRESS_MESSAGES[tool.name];
|
|
10320
|
-
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10324
|
-
|
|
10325
|
-
|
|
10326
|
-
|
|
10380
|
+
let elapsed;
|
|
10381
|
+
const send = async () => {
|
|
10382
|
+
if (!waitMessage)
|
|
10383
|
+
return post();
|
|
10384
|
+
const timed = await withProgress(waitMessage, post);
|
|
10385
|
+
elapsed = timed.elapsed;
|
|
10386
|
+
return timed.value;
|
|
10387
|
+
};
|
|
10388
|
+
const result = await withContainerPick(call, () => withContainerStart(call, send, rawArgs.start === true, pickers, notice), pickers, notice);
|
|
10327
10389
|
printResult(result, () => {
|
|
10328
10390
|
const color = colorEnabled(process.stdout);
|
|
10329
10391
|
const lines = renderResult(result, color);
|
|
10330
|
-
return bootLines(result, color).length > 0 ? lines : withElapsed(lines, elapsed);
|
|
10392
|
+
return elapsed === undefined || bootLines(result, color).length > 0 ? lines : withElapsed(lines, elapsed);
|
|
10331
10393
|
}, log);
|
|
10332
10394
|
stopNote(result, notice);
|
|
10333
10395
|
return 0;
|
|
@@ -10336,59 +10398,6 @@ async function runToolInvoke(tool, rawArgs, log = console.log, error = printErro
|
|
|
10336
10398
|
return 1;
|
|
10337
10399
|
}
|
|
10338
10400
|
}
|
|
10339
|
-
async function withContainerPick(tool, input, send, pickers, notice) {
|
|
10340
|
-
try {
|
|
10341
|
-
return await send();
|
|
10342
|
-
} catch (err) {
|
|
10343
|
-
const properties = tool.inputSchema.properties;
|
|
10344
|
-
const question = containerQuestionOf(err);
|
|
10345
|
-
if (!pickers || !question || !properties || !("container" in properties) || input.container) {
|
|
10346
|
-
throw err;
|
|
10347
|
-
}
|
|
10348
|
-
const container = await pickers.choose(question);
|
|
10349
|
-
if (!container)
|
|
10350
|
-
throw err;
|
|
10351
|
-
input.container = container;
|
|
10352
|
-
const result = await send();
|
|
10353
|
-
if (typeof input.sandboxId === "string" && await pickers.confirmDefault(container)) {
|
|
10354
|
-
try {
|
|
10355
|
-
await authorizedRequest("/api/v1/tools/sandboxes_default_container", {
|
|
10356
|
-
method: "POST",
|
|
10357
|
-
body: JSON.stringify({
|
|
10358
|
-
organization: input.organization,
|
|
10359
|
-
sandboxId: input.sandboxId,
|
|
10360
|
-
container
|
|
10361
|
-
})
|
|
10362
|
-
});
|
|
10363
|
-
notice(eventLine("done", `Default container: ${container}.`));
|
|
10364
|
-
} catch (err) {
|
|
10365
|
-
notice(eventLine("failed", `The default container was not set: ${err instanceof Error ? err.message : String(err)}`));
|
|
10366
|
-
}
|
|
10367
|
-
}
|
|
10368
|
-
return result;
|
|
10369
|
-
}
|
|
10370
|
-
}
|
|
10371
|
-
async function withContainerStart(input, send, start, pickers, notice) {
|
|
10372
|
-
try {
|
|
10373
|
-
return await send();
|
|
10374
|
-
} catch (err) {
|
|
10375
|
-
const container = notRunningContainerOf(err);
|
|
10376
|
-
if (!container || typeof input.sandboxId !== "string")
|
|
10377
|
-
throw err;
|
|
10378
|
-
if (!start && !(pickers && await pickers.confirmStart(container)))
|
|
10379
|
-
throw err;
|
|
10380
|
-
await authorizedRequest("/api/v1/tools/sandboxes_containers_start", {
|
|
10381
|
-
method: "POST",
|
|
10382
|
-
body: JSON.stringify({
|
|
10383
|
-
organization: input.organization,
|
|
10384
|
-
sandboxId: input.sandboxId,
|
|
10385
|
-
container
|
|
10386
|
-
})
|
|
10387
|
-
});
|
|
10388
|
-
notice(eventLine("done", `Started ${container}.`));
|
|
10389
|
-
return await send();
|
|
10390
|
-
}
|
|
10391
|
-
}
|
|
10392
10401
|
function stopNote(result, notice) {
|
|
10393
10402
|
if (!result || typeof result !== "object")
|
|
10394
10403
|
return;
|
|
@@ -12745,7 +12754,7 @@ async function collectPath3(path) {
|
|
|
12745
12754
|
await visit(path);
|
|
12746
12755
|
return files;
|
|
12747
12756
|
}
|
|
12748
|
-
async function runSandboxUpload(options, log = console.log, error = printError) {
|
|
12757
|
+
async function runSandboxUpload(options, log = console.log, error = printError, notice = printNotice, pickers = defaultContainerPickers()) {
|
|
12749
12758
|
if (options.paths.length === 0 && !options.zip) {
|
|
12750
12759
|
error("Provide at least one path or --zip.");
|
|
12751
12760
|
return 1;
|
|
@@ -12761,9 +12770,26 @@ async function runSandboxUpload(options, log = console.log, error = printError)
|
|
|
12761
12770
|
if (options.zip) {
|
|
12762
12771
|
form.append("zip", new Blob([await readFile7(options.zip)]), basename5(options.zip));
|
|
12763
12772
|
}
|
|
12764
|
-
|
|
12773
|
+
let container = options.container;
|
|
12774
|
+
const call = {
|
|
12775
|
+
organization,
|
|
12776
|
+
sandboxId: options.sandboxId,
|
|
12777
|
+
canPick: !container,
|
|
12778
|
+
setContainer: (picked) => {
|
|
12779
|
+
container = picked;
|
|
12780
|
+
}
|
|
12781
|
+
};
|
|
12782
|
+
const send = async () => {
|
|
12783
|
+
const query = new URLSearchParams({ organization });
|
|
12784
|
+
if (container)
|
|
12785
|
+
query.set("container", container);
|
|
12786
|
+
const { value } = await withProgress("Uploading…", () => authorizedRequest(`/api/v1/sandboxes/${encodeURIComponent(options.sandboxId)}/files?${query}`, { method: "POST", body: form }));
|
|
12787
|
+
return value;
|
|
12788
|
+
};
|
|
12789
|
+
const result = await withContainerPick(call, () => withContainerStart(call, send, options.start === true, pickers, notice), pickers, notice);
|
|
12790
|
+
const count = `${result.written.length} file${result.written.length === 1 ? "" : "s"}`;
|
|
12765
12791
|
printResult(result, () => [
|
|
12766
|
-
eventLine("done", `Uploaded ${
|
|
12792
|
+
eventLine("done", result.container ? `Uploaded ${count} to ${result.container} in ${options.sandboxId}.` : `Uploaded ${count} to ${options.sandboxId}.`)
|
|
12767
12793
|
], log);
|
|
12768
12794
|
return 0;
|
|
12769
12795
|
} catch (err) {
|
|
@@ -12787,6 +12813,14 @@ var sandboxUploadCommand = defineCommand({
|
|
|
12787
12813
|
required: true
|
|
12788
12814
|
},
|
|
12789
12815
|
org: orgArg,
|
|
12816
|
+
container: {
|
|
12817
|
+
type: "string",
|
|
12818
|
+
description: `Container the files land in, by name, from \`${getCliName()} sandboxes containers list\`. Default: the sandbox's default container, else the one running container.`
|
|
12819
|
+
},
|
|
12820
|
+
start: {
|
|
12821
|
+
type: "boolean",
|
|
12822
|
+
description: "Start the container first when it is not running, without asking."
|
|
12823
|
+
},
|
|
12790
12824
|
zip: {
|
|
12791
12825
|
type: "string",
|
|
12792
12826
|
description: "Local ZIP file to upload."
|
|
@@ -12802,7 +12836,9 @@ var sandboxUploadCommand = defineCommand({
|
|
|
12802
12836
|
sandboxId: args["sandbox-id"],
|
|
12803
12837
|
org: args.org,
|
|
12804
12838
|
paths: args._.slice(1),
|
|
12805
|
-
zip: args.zip
|
|
12839
|
+
zip: args.zip,
|
|
12840
|
+
container: args.container,
|
|
12841
|
+
start: args.start
|
|
12806
12842
|
});
|
|
12807
12843
|
}
|
|
12808
12844
|
});
|