@dench.com/cli 3.6.6-staging.386 → 3.8.0-staging.389
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/README.md +43 -44
- package/agent-config.ts +21 -57
- package/app-sdk.d.ts +367 -24
- package/chat-spawn.ts +11 -2
- package/chat.ts +1 -1
- package/context-settings.ts +86 -0
- package/crm.ts +92 -24
- package/cron.ts +19 -0
- package/dench.ts +318 -90
- package/email-inbox.ts +169 -0
- package/email.ts +103 -21
- package/environments.ts +694 -0
- package/lib/api-schemas.ts +160 -14
- package/lib/app-sdk-catalog.generated.ts +39 -19
- package/lib/bundled-references.ts +17 -0
- package/lib/cli-args.ts +30 -3
- package/lib/command-args.ts +252 -0
- package/lib/command-help.ts +93 -0
- package/lib/command-registry.ts +296 -10
- package/lib/environment-archive.ts +255 -0
- package/lib/environment-cli-args.ts +96 -0
- package/lib/environment-contract.ts +237 -0
- package/lib/environment-execution.ts +769 -0
- package/lib/environment-source.ts +165 -0
- package/lib/load-dev-env.mjs +3 -1
- package/lib/load-dev-env.test.mjs +26 -9
- package/lib/native-email-wait.ts +75 -0
- package/lib/parent-argv.ts +20 -0
- package/lib/public-error.ts +82 -0
- package/lib/references.generated.json +74 -0
- package/package.json +7 -3
- package/reference.ts +47 -0
- package/workspace-secrets.ts +231 -0
- package/agent.ts +0 -37
package/dench.ts
CHANGED
|
@@ -28,10 +28,13 @@ import {
|
|
|
28
28
|
resolveHostFromArgs,
|
|
29
29
|
STAGING_HOST,
|
|
30
30
|
} from "./host";
|
|
31
|
+
import { CliArgError, isHelpRequest } from "./lib/cli-args";
|
|
31
32
|
import { cliVersion } from "./lib/cli-version";
|
|
33
|
+
import { assertDeclaredCommandFlags } from "./lib/command-args";
|
|
32
34
|
import { denchConfigDirectory } from "./lib/config-path.mjs";
|
|
33
35
|
import { resolveOrganizationBySelector } from "./lib/organizationSelector";
|
|
34
|
-
import {
|
|
36
|
+
import { normalizeParentArgv } from "./lib/parent-argv";
|
|
37
|
+
import { backendErrorText, publicErrorDetails } from "./lib/public-error";
|
|
35
38
|
import { formatApprovalOpenMessage, openUrl } from "./openUrl";
|
|
36
39
|
import {
|
|
37
40
|
explicitSessionKeyInput,
|
|
@@ -215,10 +218,13 @@ const api = {
|
|
|
215
218
|
};
|
|
216
219
|
const CONFIG_DIR = denchConfigDirectory();
|
|
217
220
|
const CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const
|
|
221
|
-
const
|
|
221
|
+
// A child process owns every token after `--`, including --host and --json.
|
|
222
|
+
// Normalize only Dench's parent arguments; pass child argv through byte for byte.
|
|
223
|
+
const { args, runtimeArgs } = normalizeParentArgv(process.argv.slice(2));
|
|
224
|
+
const json = runtimeArgs.includes("--json");
|
|
225
|
+
const filteredArgs = runtimeArgs.filter((arg) => arg !== "--json");
|
|
226
|
+
const scopedStatus =
|
|
227
|
+
runtimeArgs.includes("--mine") || runtimeArgs.includes("--self");
|
|
222
228
|
|
|
223
229
|
function readEnv(name: string) {
|
|
224
230
|
const value = process.env[name]?.trim();
|
|
@@ -321,13 +327,18 @@ function throwIfCliError(value: unknown) {
|
|
|
321
327
|
}
|
|
322
328
|
const record = value as JsonRecord;
|
|
323
329
|
if (record.ok === false && typeof record.error === "string") {
|
|
324
|
-
throw new
|
|
330
|
+
throw new CliError(record.error, publicErrorDetails(record));
|
|
325
331
|
}
|
|
326
332
|
}
|
|
327
333
|
|
|
328
334
|
function normalizeCliError(error: unknown): CliError {
|
|
329
|
-
if (error instanceof CliError)
|
|
335
|
+
if (error instanceof CliError) {
|
|
336
|
+
error.payload = { ...error.payload, ...publicErrorDetails(error.payload) };
|
|
337
|
+
return error;
|
|
338
|
+
}
|
|
330
339
|
const message = backendErrorText(error);
|
|
340
|
+
if (error instanceof CliArgError)
|
|
341
|
+
return new CliError(message, { code: error.code, retryable: false });
|
|
331
342
|
if (message.includes("Invalid dev agent key")) {
|
|
332
343
|
return new CliError("Invalid dev agent key", {
|
|
333
344
|
code: "invalid_dev_agent_key",
|
|
@@ -369,7 +380,10 @@ function normalizeCliError(error: unknown): CliError {
|
|
|
369
380
|
],
|
|
370
381
|
});
|
|
371
382
|
}
|
|
372
|
-
return new CliError(message
|
|
383
|
+
return new CliError(message, {
|
|
384
|
+
code: "cli_error",
|
|
385
|
+
...publicErrorDetails(error),
|
|
386
|
+
});
|
|
373
387
|
}
|
|
374
388
|
|
|
375
389
|
function _parseJsonObjectOption(name: string) {
|
|
@@ -632,14 +646,11 @@ Past chat threads (own + shared in this workspace):
|
|
|
632
646
|
dench chat delete --ids id1,id2 [--yes] [--json] (PERMANENTLY deletes threads)
|
|
633
647
|
|
|
634
648
|
Spawn a new chat-turn workflow (same as the web UI):
|
|
635
|
-
dench chat new "<prompt>" [--model <m>] [--file-context <path>] [--visibility private|shared] [--title T] [--yolo] [--follow] [--json]
|
|
649
|
+
dench chat new "<prompt>" [--environment NAME] [--model <m>] [--file-context <path>] [--visibility private|shared] [--title T] [--yolo] [--follow] [--json]
|
|
636
650
|
dench chat send <thread-id> "<message>" [--model <m>] [--yolo] [--follow] [--json]
|
|
637
651
|
dench chat follow <thread-id> [--json] (tail a live thread by id)
|
|
638
652
|
dench chat tree [<root-thread-id>] [--limit N] [--json]
|
|
639
653
|
(parent-child thread tree)
|
|
640
|
-
dench agent new ... (alias for dench chat new)
|
|
641
|
-
dench agent send ... (alias for dench chat send)
|
|
642
|
-
dench agent follow ... (alias for dench chat follow)
|
|
643
654
|
|
|
644
655
|
Help: dench chat help
|
|
645
656
|
|
|
@@ -661,30 +672,23 @@ returns ENOSYS on the FUSE-backed volume mount):
|
|
|
661
672
|
Persist scratch -> workspace (cp from /tmp into /workspace + cloud sync):
|
|
662
673
|
dench stage <local-path> [<workspace-dest>] [--clean] [--json]
|
|
663
674
|
|
|
664
|
-
|
|
665
|
-
dench
|
|
666
|
-
dench
|
|
667
|
-
dench
|
|
668
|
-
dench
|
|
669
|
-
dench agent pause <runId>
|
|
670
|
-
dench agent resume <runId> ['optional prompt']
|
|
671
|
-
dench agent continue <prevRunId> '<prompt>'
|
|
672
|
-
dench agent tree [<rootRunId>]
|
|
673
|
-
Help: dench agent help
|
|
675
|
+
Reusable workspace setup:
|
|
676
|
+
dench env list | show <name> | save <name> --path <directory> | run <name> -- <command> | delete <name>
|
|
677
|
+
dench secrets set <NAME> --stdin [--kind env|file]
|
|
678
|
+
dench secrets list | delete <NAME> metadata only; values are never printed
|
|
679
|
+
Help: dench env --help, dench secrets --help
|
|
674
680
|
|
|
675
681
|
dench --version
|
|
682
|
+
dench reference <name> [--json] Offline CLI-version-matched skill/reference
|
|
683
|
+
dench reference --list [--json] Bundled reference index and revision
|
|
676
684
|
|
|
677
|
-
|
|
678
|
-
dench
|
|
679
|
-
dench
|
|
680
|
-
dench
|
|
681
|
-
dench
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
dench model default <id|clear>
|
|
685
|
-
dench model thread <threadId> <id|clear>
|
|
686
|
-
dench daily today | show <YYYY-MM-DD>
|
|
687
|
-
Help: dench identity help
|
|
685
|
+
Standing context and memory:
|
|
686
|
+
dench context --sections identity,organisation,user,memory,rules,tools [--json]
|
|
687
|
+
dench context set <identity|organisation|user|tools|rules> --stdin
|
|
688
|
+
dench memory search "<query>" | save <key> "<fact>"
|
|
689
|
+
dench model default <id|clear> | thread <threadId> <id|clear>
|
|
690
|
+
Context describes preferences and instructions. Environments store setup;
|
|
691
|
+
secrets store credentials. A memory note does not install or save either.
|
|
688
692
|
|
|
689
693
|
External tools:
|
|
690
694
|
dench integrations is an alias for dench tool status -- it lists connected apps.
|
|
@@ -746,13 +750,14 @@ function contextHelp() {
|
|
|
746
750
|
Usage:
|
|
747
751
|
dench context [--instructions] [--json]
|
|
748
752
|
dench context --sections organisation,user,memory [--json]
|
|
749
|
-
dench
|
|
753
|
+
dench context set <identity|organisation|user|tools|rules> --stdin | --content "text" [--json]
|
|
750
754
|
|
|
751
755
|
Shows the current workspace, current agent, assigned tasks, pending approvals
|
|
752
756
|
requested by this agent, connected apps when available, and useful next commands.
|
|
753
757
|
|
|
754
758
|
Use --instructions (or dench instructions) to print the standing workspace
|
|
755
|
-
instructions
|
|
759
|
+
instructions for the current workspace. Context and memory do not persist
|
|
760
|
+
credentials or installed software: use dench secrets and dench env.
|
|
756
761
|
`);
|
|
757
762
|
}
|
|
758
763
|
|
|
@@ -2694,19 +2699,33 @@ type Runtime = Awaited<ReturnType<typeof getRuntime>>;
|
|
|
2694
2699
|
* `dench members list --json` print the human table and `dench crm … --json`
|
|
2695
2700
|
* fall back to text on empty results (`(no rows)`), breaking `| jq` pipelines.
|
|
2696
2701
|
*/
|
|
2697
|
-
function stripRuntimeFlags(args: string[]) {
|
|
2702
|
+
function stripRuntimeFlags(args: string[], validateValues = true) {
|
|
2698
2703
|
const booleanFlags = new Set([
|
|
2699
2704
|
"--dev",
|
|
2700
2705
|
"--prod",
|
|
2701
2706
|
"--staging",
|
|
2702
2707
|
"--use-dev-env",
|
|
2703
2708
|
]);
|
|
2704
|
-
const valueFlags = new Set([
|
|
2709
|
+
const valueFlags = new Set([
|
|
2710
|
+
"--convex-url",
|
|
2711
|
+
"--host",
|
|
2712
|
+
"--backend",
|
|
2713
|
+
"--session-key",
|
|
2714
|
+
"--session",
|
|
2715
|
+
]);
|
|
2705
2716
|
const stripped: string[] = [];
|
|
2706
2717
|
for (let i = 0; i < args.length; i++) {
|
|
2707
2718
|
const arg = args[i];
|
|
2719
|
+
if (arg === "--") {
|
|
2720
|
+
stripped.push(...args.slice(i));
|
|
2721
|
+
break;
|
|
2722
|
+
}
|
|
2708
2723
|
if (booleanFlags.has(arg)) continue;
|
|
2709
2724
|
if (valueFlags.has(arg)) {
|
|
2725
|
+
if (!args[i + 1] || args[i + 1].startsWith("-")) {
|
|
2726
|
+
if (validateValues) throw new CliArgError(`Missing value for ${arg}`);
|
|
2727
|
+
continue;
|
|
2728
|
+
}
|
|
2710
2729
|
i++;
|
|
2711
2730
|
continue;
|
|
2712
2731
|
}
|
|
@@ -3392,7 +3411,7 @@ async function resolveFsDaemonEnv(): Promise<NodeJS.ProcessEnv> {
|
|
|
3392
3411
|
}
|
|
3393
3412
|
|
|
3394
3413
|
async function runFsCommand() {
|
|
3395
|
-
const subArgs = args.slice(args.indexOf("fs") + 1);
|
|
3414
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf("fs") + 1));
|
|
3396
3415
|
const configuredBinary = process.env.DENCH_FS_DAEMON_BIN?.trim();
|
|
3397
3416
|
const binary = configuredBinary || "dench-fs-daemon";
|
|
3398
3417
|
const daemonEnv = await resolveFsDaemonEnv();
|
|
@@ -4303,10 +4322,234 @@ function isCommandNotFound(error: unknown) {
|
|
|
4303
4322
|
}
|
|
4304
4323
|
|
|
4305
4324
|
async function main() {
|
|
4325
|
+
if (isHelpRequest(runtimeArgs)) {
|
|
4326
|
+
const helpArgs = stripRuntimeFlags(runtimeArgs, false).filter(
|
|
4327
|
+
(arg) => !["--json", "--help", "-h"].includes(arg),
|
|
4328
|
+
);
|
|
4329
|
+
if (helpArgs[0] === "help") helpArgs.shift();
|
|
4330
|
+
if (!helpArgs.length) {
|
|
4331
|
+
help();
|
|
4332
|
+
return;
|
|
4333
|
+
}
|
|
4334
|
+
const path = helpArgs.filter(
|
|
4335
|
+
(arg) => !["help", "--help", "-h"].includes(arg),
|
|
4336
|
+
);
|
|
4337
|
+
if (path[0] === "daily") {
|
|
4338
|
+
console.log(
|
|
4339
|
+
`dench ${path.join(" ")} was retired. Search history with dench chat search or read existing daily files with dench files download. Harness A does not automatically write daily logs.`,
|
|
4340
|
+
);
|
|
4341
|
+
return;
|
|
4342
|
+
}
|
|
4343
|
+
// Root help retains domain-specific setup, account and pagination guidance.
|
|
4344
|
+
// These are explicit help-only paths; never pass mutation arguments to a handler.
|
|
4345
|
+
if (path.length === 1) {
|
|
4346
|
+
const roots: Record<string, () => void | Promise<void>> = {
|
|
4347
|
+
reference: async () =>
|
|
4348
|
+
console.log((await import("./reference")).REFERENCE_HELP),
|
|
4349
|
+
env: async () =>
|
|
4350
|
+
console.log((await import("./environments")).environmentHelpText()),
|
|
4351
|
+
secrets: async () =>
|
|
4352
|
+
console.log(
|
|
4353
|
+
(await import("./workspace-secrets")).workspaceSecretsHelpText(),
|
|
4354
|
+
),
|
|
4355
|
+
tool: toolHelp,
|
|
4356
|
+
integrations: integrationsHelp,
|
|
4357
|
+
backend: backendHelp,
|
|
4358
|
+
signin: signinHelp,
|
|
4359
|
+
login: signinHelp,
|
|
4360
|
+
onboard: signinHelp,
|
|
4361
|
+
setup: signinHelp,
|
|
4362
|
+
"what-can-i-do": signinHelp,
|
|
4363
|
+
register: signinHelp,
|
|
4364
|
+
memory: memoryHelp,
|
|
4365
|
+
billing: billingHelp,
|
|
4366
|
+
logout: logoutHelp,
|
|
4367
|
+
context: contextHelp,
|
|
4368
|
+
artifacts: artifactsHelp,
|
|
4369
|
+
"suggested-work": artifactsHelp,
|
|
4370
|
+
lists: listsCliHelp,
|
|
4371
|
+
leads: leadsHelp,
|
|
4372
|
+
companies: companiesHelp,
|
|
4373
|
+
jobs: jobsHelp,
|
|
4374
|
+
status: statusHelp,
|
|
4375
|
+
web: async () => (await import("./web")).webHelp(),
|
|
4376
|
+
crm: async () =>
|
|
4377
|
+
(await import("./crm")).runCrmCommand({
|
|
4378
|
+
convex: {} as ConvexHttpClient,
|
|
4379
|
+
args: ["help"],
|
|
4380
|
+
}),
|
|
4381
|
+
apps: async () =>
|
|
4382
|
+
(await import("./apps")).runAppsCommand({
|
|
4383
|
+
convex: {} as ConvexHttpClient,
|
|
4384
|
+
args: ["help"],
|
|
4385
|
+
}),
|
|
4386
|
+
};
|
|
4387
|
+
if (roots[path[0]]) {
|
|
4388
|
+
await roots[path[0]]();
|
|
4389
|
+
return;
|
|
4390
|
+
}
|
|
4391
|
+
}
|
|
4392
|
+
if (helpArgs[0] === "reference") {
|
|
4393
|
+
console.log((await import("./reference")).REFERENCE_HELP);
|
|
4394
|
+
return;
|
|
4395
|
+
}
|
|
4396
|
+
// Preserve the small, established CRM read help including its cursor contract.
|
|
4397
|
+
if (helpArgs[0] === "crm" && ["query", "aggregate"].includes(helpArgs[1])) {
|
|
4398
|
+
const { runCrmCommand } = await import("./crm");
|
|
4399
|
+
await runCrmCommand({
|
|
4400
|
+
convex: {} as ConvexHttpClient,
|
|
4401
|
+
args: [...helpArgs.slice(1), "--help"],
|
|
4402
|
+
});
|
|
4403
|
+
return;
|
|
4404
|
+
}
|
|
4405
|
+
const { commandHelp } = await import("./lib/command-help");
|
|
4406
|
+
const usage =
|
|
4407
|
+
helpArgs[0] === "email"
|
|
4408
|
+
? (await import("./email")).emailHelpText()
|
|
4409
|
+
: helpArgs[0] === "crm"
|
|
4410
|
+
? (await import("./crm")).crmHelpText()
|
|
4411
|
+
: helpArgs[0] === "env"
|
|
4412
|
+
? (await import("./environments")).environmentHelpText()
|
|
4413
|
+
: helpArgs[0] === "secrets"
|
|
4414
|
+
? (await import("./workspace-secrets")).workspaceSecretsHelpText()
|
|
4415
|
+
: "";
|
|
4416
|
+
console.log(commandHelp(helpArgs, usage));
|
|
4417
|
+
return;
|
|
4418
|
+
}
|
|
4306
4419
|
const command = positional(0);
|
|
4307
4420
|
const subcommand = positional(1);
|
|
4308
4421
|
|
|
4309
|
-
|
|
4422
|
+
assertDeclaredCommandFlags(stripRuntimeFlags(runtimeArgs));
|
|
4423
|
+
|
|
4424
|
+
// New setup commands validate before authentication and never consume child flags.
|
|
4425
|
+
if (command === "env" || command === "secrets") {
|
|
4426
|
+
const rawSubArgs = args.slice(args.indexOf(command) + 1);
|
|
4427
|
+
const helpRequested =
|
|
4428
|
+
runtimeArgs.includes("--help") ||
|
|
4429
|
+
runtimeArgs.includes("-h") ||
|
|
4430
|
+
subcommand === "help";
|
|
4431
|
+
const subArgs = helpRequested ? rawSubArgs : stripRuntimeFlags(rawSubArgs);
|
|
4432
|
+
const mod =
|
|
4433
|
+
command === "env"
|
|
4434
|
+
? await import("./environments")
|
|
4435
|
+
: await import("./workspace-secrets");
|
|
4436
|
+
if ("validateEnvironmentArgs" in mod) {
|
|
4437
|
+
const parsed = mod.validateEnvironmentArgs(subArgs);
|
|
4438
|
+
if (parsed.verb === "help") {
|
|
4439
|
+
console.log(mod.environmentHelpText());
|
|
4440
|
+
return;
|
|
4441
|
+
}
|
|
4442
|
+
const runtime = requireAuthenticatedRuntime(
|
|
4443
|
+
await getRuntime(),
|
|
4444
|
+
"dench env",
|
|
4445
|
+
);
|
|
4446
|
+
await mod.runEnvironmentCommand({
|
|
4447
|
+
convex: runtime.client,
|
|
4448
|
+
args: subArgs,
|
|
4449
|
+
sessionToken: runtime.sessionToken,
|
|
4450
|
+
apiUrl: runtime.host,
|
|
4451
|
+
});
|
|
4452
|
+
} else {
|
|
4453
|
+
const parsed = mod.validateWorkspaceSecretsArgs(subArgs);
|
|
4454
|
+
if (parsed.verb === "help") {
|
|
4455
|
+
console.log(mod.workspaceSecretsHelpText());
|
|
4456
|
+
return;
|
|
4457
|
+
}
|
|
4458
|
+
const runtime = requireAuthenticatedRuntime(
|
|
4459
|
+
await getRuntime(),
|
|
4460
|
+
"dench secrets",
|
|
4461
|
+
);
|
|
4462
|
+
await mod.runWorkspaceSecretsCommand({
|
|
4463
|
+
convex: runtime.client,
|
|
4464
|
+
args: subArgs,
|
|
4465
|
+
sessionToken: runtime.sessionToken,
|
|
4466
|
+
});
|
|
4467
|
+
}
|
|
4468
|
+
return;
|
|
4469
|
+
}
|
|
4470
|
+
if (
|
|
4471
|
+
command === "context" &&
|
|
4472
|
+
(runtimeArgs.includes("--help") ||
|
|
4473
|
+
runtimeArgs.includes("-h") ||
|
|
4474
|
+
subcommand === "help")
|
|
4475
|
+
) {
|
|
4476
|
+
contextHelp();
|
|
4477
|
+
return;
|
|
4478
|
+
}
|
|
4479
|
+
if (command === "daily") {
|
|
4480
|
+
const guidance =
|
|
4481
|
+
"Daily-log commands were retired. Search actual history with dench chat search or read existing daily files with dench files download. Nothing writes daily logs automatically in Harness A.";
|
|
4482
|
+
if (
|
|
4483
|
+
runtimeArgs.includes("--help") ||
|
|
4484
|
+
runtimeArgs.includes("-h") ||
|
|
4485
|
+
subcommand === "help"
|
|
4486
|
+
) {
|
|
4487
|
+
console.log(guidance);
|
|
4488
|
+
return;
|
|
4489
|
+
}
|
|
4490
|
+
throw new CliError(guidance, {
|
|
4491
|
+
code: "deprecated_command",
|
|
4492
|
+
retryable: false,
|
|
4493
|
+
});
|
|
4494
|
+
}
|
|
4495
|
+
if (command === "context" && subcommand === "set") {
|
|
4496
|
+
const { validateContextSet, runContextSet } = await import(
|
|
4497
|
+
"./context-settings"
|
|
4498
|
+
);
|
|
4499
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf(command) + 1));
|
|
4500
|
+
validateContextSet(subArgs);
|
|
4501
|
+
const runtime = requireAuthenticatedRuntime(
|
|
4502
|
+
await getRuntime(),
|
|
4503
|
+
"dench context set",
|
|
4504
|
+
);
|
|
4505
|
+
await runContextSet({
|
|
4506
|
+
convex: runtime.client,
|
|
4507
|
+
args: subArgs,
|
|
4508
|
+
sessionToken: runtime.sessionToken,
|
|
4509
|
+
});
|
|
4510
|
+
return;
|
|
4511
|
+
}
|
|
4512
|
+
if (
|
|
4513
|
+
command === "memory" &&
|
|
4514
|
+
(runtimeArgs.includes("--help") || runtimeArgs.includes("-h"))
|
|
4515
|
+
) {
|
|
4516
|
+
memoryHelp();
|
|
4517
|
+
return;
|
|
4518
|
+
}
|
|
4519
|
+
if (command === "memory" && subcommand === "save") {
|
|
4520
|
+
const kind = option("--kind") ?? "fact";
|
|
4521
|
+
if (
|
|
4522
|
+
![
|
|
4523
|
+
"fact",
|
|
4524
|
+
"decision",
|
|
4525
|
+
"preference",
|
|
4526
|
+
"goal",
|
|
4527
|
+
"tool_note",
|
|
4528
|
+
"other",
|
|
4529
|
+
"convention",
|
|
4530
|
+
"project_context",
|
|
4531
|
+
"agent_lesson",
|
|
4532
|
+
"docs_knowledge",
|
|
4533
|
+
"open_goal",
|
|
4534
|
+
].includes(kind)
|
|
4535
|
+
)
|
|
4536
|
+
throw new CliError(
|
|
4537
|
+
"Unsupported memory kind. Use memory for facts/preferences; use dench secrets set NAME --stdin for credentials and dench env save for reusable setup.",
|
|
4538
|
+
{ code: "validation_failed", retryable: false },
|
|
4539
|
+
);
|
|
4540
|
+
}
|
|
4541
|
+
|
|
4542
|
+
if (command === "reference") {
|
|
4543
|
+
await (await import("./reference")).runReferenceCommand(
|
|
4544
|
+
stripRuntimeFlags(args.slice(args.indexOf("reference") + 1)),
|
|
4545
|
+
);
|
|
4546
|
+
return;
|
|
4547
|
+
}
|
|
4548
|
+
|
|
4549
|
+
if (
|
|
4550
|
+
command === "version" ||
|
|
4551
|
+
stripRuntimeFlags(runtimeArgs)[0] === "--version"
|
|
4552
|
+
) {
|
|
4310
4553
|
console.log(await cliVersion());
|
|
4311
4554
|
return;
|
|
4312
4555
|
}
|
|
@@ -4741,7 +4984,7 @@ async function main() {
|
|
|
4741
4984
|
}
|
|
4742
4985
|
|
|
4743
4986
|
if (command === "web") {
|
|
4744
|
-
const subArgs = args.slice(args.indexOf("web") + 1);
|
|
4987
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf("web") + 1));
|
|
4745
4988
|
const filteredSubArgs = subArgs.filter((a) => a !== "--json");
|
|
4746
4989
|
const { runWebCommand, webHelp } = await import("./web");
|
|
4747
4990
|
const sub = filteredSubArgs[0];
|
|
@@ -4761,7 +5004,7 @@ async function main() {
|
|
|
4761
5004
|
}
|
|
4762
5005
|
|
|
4763
5006
|
if (command === "search") {
|
|
4764
|
-
const subArgs = args.slice(args.indexOf("search") + 1);
|
|
5007
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf("search") + 1));
|
|
4765
5008
|
const filteredSubArgs = subArgs.filter((a) => a !== "--json");
|
|
4766
5009
|
const { runSearchCommand } = await import("./search");
|
|
4767
5010
|
const sub = filteredSubArgs[0];
|
|
@@ -4784,7 +5027,7 @@ async function main() {
|
|
|
4784
5027
|
}
|
|
4785
5028
|
|
|
4786
5029
|
if (command === "image") {
|
|
4787
|
-
const subArgs = args.slice(args.indexOf("image") + 1);
|
|
5030
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf("image") + 1));
|
|
4788
5031
|
const filteredSubArgs = subArgs.filter((a) => a !== "--json");
|
|
4789
5032
|
const { runImageCommand } = await import("./image");
|
|
4790
5033
|
const sub = filteredSubArgs[0];
|
|
@@ -4804,7 +5047,7 @@ async function main() {
|
|
|
4804
5047
|
}
|
|
4805
5048
|
|
|
4806
5049
|
if (command === "email") {
|
|
4807
|
-
const subArgs = args.slice(args.indexOf("email") + 1);
|
|
5050
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf("email") + 1));
|
|
4808
5051
|
const { runEmailCommand } = await import("./email");
|
|
4809
5052
|
const runtime = await getRuntime();
|
|
4810
5053
|
const authedRuntime = requireAuthenticatedRuntime(runtime, "dench email");
|
|
@@ -4813,7 +5056,7 @@ async function main() {
|
|
|
4813
5056
|
| undefined;
|
|
4814
5057
|
try {
|
|
4815
5058
|
if (
|
|
4816
|
-
|
|
5059
|
+
!["draft", "inbox", "send"].includes(subArgs[0]) &&
|
|
4817
5060
|
!subArgs.some(
|
|
4818
5061
|
(arg) => arg === "--mailbox" || arg.startsWith("--mailbox="),
|
|
4819
5062
|
)
|
|
@@ -4922,7 +5165,7 @@ async function main() {
|
|
|
4922
5165
|
}
|
|
4923
5166
|
|
|
4924
5167
|
if (command === "browser") {
|
|
4925
|
-
const subArgs = args.slice(args.indexOf("browser") + 1);
|
|
5168
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf("browser") + 1));
|
|
4926
5169
|
const { runBrowserCommand } = await import("./browser");
|
|
4927
5170
|
const runtime = await getRuntime();
|
|
4928
5171
|
const authedRuntime = requireAuthenticatedRuntime(runtime, "dench browser");
|
|
@@ -4947,7 +5190,7 @@ async function main() {
|
|
|
4947
5190
|
// `dench ads` is canonical; `dench ad` and `dench adline` are aliases for
|
|
4948
5191
|
// the same command (one code path in ./ads).
|
|
4949
5192
|
if (command === "ads" || command === "ad" || command === "adline") {
|
|
4950
|
-
const subArgs = args.slice(args.indexOf(command) + 1);
|
|
5193
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf(command) + 1));
|
|
4951
5194
|
const { runAdsCommand } = await import("./ads");
|
|
4952
5195
|
// Earning is opt-in: resolve the agent session token best-effort so a
|
|
4953
5196
|
// signed-in developer gets credited on flush, but never require login —
|
|
@@ -4983,7 +5226,7 @@ async function main() {
|
|
|
4983
5226
|
}
|
|
4984
5227
|
|
|
4985
5228
|
if (command === "chat") {
|
|
4986
|
-
const subArgs = args.slice(args.indexOf("chat") + 1);
|
|
5229
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf("chat") + 1));
|
|
4987
5230
|
const sub = subArgs[0];
|
|
4988
5231
|
if (!sub || sub === "help" || sub === "--help") {
|
|
4989
5232
|
const { runChatCommand } = await import("./chat");
|
|
@@ -5033,43 +5276,33 @@ async function main() {
|
|
|
5033
5276
|
}
|
|
5034
5277
|
|
|
5035
5278
|
if (command === "agent") {
|
|
5036
|
-
const subArgs = args.slice(args.indexOf("agent") + 1);
|
|
5279
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf("agent") + 1));
|
|
5037
5280
|
const sub = subArgs[0];
|
|
5038
|
-
if (
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
// `agent` so users who associate chat threads with the agent
|
|
5047
|
-
// surface still find them; the actual workflow is identical to
|
|
5048
|
-
// `dench chat new` / `dench chat send` / `dench chat follow`.
|
|
5049
|
-
if (sub === "new" || sub === "send" || sub === "follow") {
|
|
5050
|
-
const { runChatSpawnCommand } = await import("./chat-spawn");
|
|
5051
|
-
const runtime = await getRuntime();
|
|
5052
|
-
const authedRuntime = requireAuthenticatedRuntime(
|
|
5053
|
-
runtime,
|
|
5054
|
-
`dench agent ${sub}`,
|
|
5281
|
+
if (
|
|
5282
|
+
!sub ||
|
|
5283
|
+
sub === "help" ||
|
|
5284
|
+
subArgs.includes("--help") ||
|
|
5285
|
+
subArgs.includes("-h")
|
|
5286
|
+
) {
|
|
5287
|
+
console.log(
|
|
5288
|
+
"Use dench chat new, send, follow, or tree. agent new/send/follow remain compatibility aliases. In Harness A, use spawn_task/read_task for child tasks.",
|
|
5055
5289
|
);
|
|
5056
|
-
await runChatSpawnCommand({
|
|
5057
|
-
runtime: {
|
|
5058
|
-
host: authedRuntime.host,
|
|
5059
|
-
bearerToken: authedRuntime.sessionToken,
|
|
5060
|
-
},
|
|
5061
|
-
args: subArgs.slice(1),
|
|
5062
|
-
subcommand: sub,
|
|
5063
|
-
});
|
|
5064
5290
|
return;
|
|
5065
5291
|
}
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5292
|
+
if (sub !== "new" && sub !== "send" && sub !== "follow")
|
|
5293
|
+
throw new CliError(
|
|
5294
|
+
"Unsupported agent command. Use dench chat new/send/follow/tree or the harness subagent tools.",
|
|
5295
|
+
{ code: "unsupported_capability", retryable: false },
|
|
5296
|
+
);
|
|
5297
|
+
const { runChatSpawnCommand } = await import("./chat-spawn");
|
|
5298
|
+
const runtime = requireAuthenticatedRuntime(
|
|
5299
|
+
await getRuntime(),
|
|
5300
|
+
`dench chat ${sub}`,
|
|
5301
|
+
);
|
|
5302
|
+
await runChatSpawnCommand({
|
|
5303
|
+
runtime: { host: runtime.host, bearerToken: runtime.sessionToken },
|
|
5304
|
+
args: subArgs.slice(1),
|
|
5305
|
+
subcommand: sub,
|
|
5073
5306
|
});
|
|
5074
5307
|
return;
|
|
5075
5308
|
}
|
|
@@ -5110,7 +5343,7 @@ async function main() {
|
|
|
5110
5343
|
// `dench cron`. Same dispatch, same auth, same handler — only the
|
|
5111
5344
|
// top-level command name differs to match the workspace UI rename.
|
|
5112
5345
|
if (command === "cron" || command === "routine" || command === "routines") {
|
|
5113
|
-
const subArgs = args.slice(args.indexOf(command) + 1);
|
|
5346
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf(command) + 1));
|
|
5114
5347
|
const sub = subArgs[0];
|
|
5115
5348
|
// Help is a no-auth path so users can read the surface without a
|
|
5116
5349
|
// session — mirrors `dench crm help`.
|
|
@@ -5144,7 +5377,7 @@ async function main() {
|
|
|
5144
5377
|
// ── OpenClaw-parity self-update CLI surface ──────────────────────────
|
|
5145
5378
|
//
|
|
5146
5379
|
// Dispatch all `dench identity / organisation / user / tools / mem /
|
|
5147
|
-
// bootstrap / model
|
|
5380
|
+
// bootstrap / model` traffic through the shared
|
|
5148
5381
|
// agent-config CLI module. Each command requires the same auth shape
|
|
5149
5382
|
// as `dench cron` (Bearer DENCH_API_KEY or `dench signin` session
|
|
5150
5383
|
// token) so server-side `requireCronAccess` accepts both.
|
|
@@ -5156,10 +5389,9 @@ async function main() {
|
|
|
5156
5389
|
"mem",
|
|
5157
5390
|
"bootstrap",
|
|
5158
5391
|
"model",
|
|
5159
|
-
"daily",
|
|
5160
5392
|
]);
|
|
5161
5393
|
if (AGENT_CONFIG_COMMANDS.has(command)) {
|
|
5162
|
-
const subArgs = args.slice(args.indexOf(command) + 1);
|
|
5394
|
+
const subArgs = stripRuntimeFlags(args.slice(args.indexOf(command) + 1));
|
|
5163
5395
|
if (
|
|
5164
5396
|
subArgs[0] === "help" ||
|
|
5165
5397
|
subArgs.includes("--help") ||
|
|
@@ -5209,10 +5441,6 @@ async function main() {
|
|
|
5209
5441
|
await mod.runModelCommand(ctxBase);
|
|
5210
5442
|
return;
|
|
5211
5443
|
}
|
|
5212
|
-
if (command === "daily") {
|
|
5213
|
-
await mod.runDailyCommand(ctxBase);
|
|
5214
|
-
return;
|
|
5215
|
-
}
|
|
5216
5444
|
}
|
|
5217
5445
|
|
|
5218
5446
|
if (command === "signin") {
|
|
@@ -5260,7 +5488,7 @@ async function main() {
|
|
|
5260
5488
|
return;
|
|
5261
5489
|
}
|
|
5262
5490
|
|
|
5263
|
-
if (command === "context" &&
|
|
5491
|
+
if (command === "context" && runtimeArgs.includes("--sections")) {
|
|
5264
5492
|
const raw = args[args.indexOf("--sections") + 1];
|
|
5265
5493
|
const sections = raw
|
|
5266
5494
|
?.split(",")
|
|
@@ -5298,7 +5526,7 @@ async function main() {
|
|
|
5298
5526
|
return;
|
|
5299
5527
|
}
|
|
5300
5528
|
|
|
5301
|
-
if (command === "context" &&
|
|
5529
|
+
if (command === "context" && runtimeArgs.includes("--instructions")) {
|
|
5302
5530
|
const instructions = await buildWorkspaceInstructionsContext(runtime);
|
|
5303
5531
|
print(
|
|
5304
5532
|
json ? instructions : (stringField(instructions, "instructions") ?? ""),
|