@dench.com/cli 2.0.3 → 2.0.4
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/agent-config.ts +55 -13
- package/chat-spawn.ts +12 -2
- package/dench.ts +38 -114
- package/package.json +1 -1
package/agent-config.ts
CHANGED
|
@@ -34,11 +34,51 @@ import { mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
|
34
34
|
import { tmpdir } from "node:os";
|
|
35
35
|
import { join } from "node:path";
|
|
36
36
|
import type { ConvexHttpClient } from "convex/browser";
|
|
37
|
-
import {
|
|
37
|
+
import { makeFunctionReference } from "convex/server";
|
|
38
38
|
import { CliArgError, getFlag, hasFlag } from "./lib/cli-args";
|
|
39
39
|
|
|
40
40
|
class AgentConfigCliError extends Error {}
|
|
41
41
|
|
|
42
|
+
const api = {
|
|
43
|
+
functions: {
|
|
44
|
+
agentConfig: {
|
|
45
|
+
getAgentConfig: makeFunctionReference<"query">(
|
|
46
|
+
"functions/agentConfig:getAgentConfig",
|
|
47
|
+
),
|
|
48
|
+
updateIdentity: makeFunctionReference<"mutation">(
|
|
49
|
+
"functions/agentConfig:updateIdentity",
|
|
50
|
+
),
|
|
51
|
+
updateOrganisation: makeFunctionReference<"mutation">(
|
|
52
|
+
"functions/agentConfig:updateOrganisation",
|
|
53
|
+
),
|
|
54
|
+
updateMemory: makeFunctionReference<"mutation">(
|
|
55
|
+
"functions/agentConfig:updateMemory",
|
|
56
|
+
),
|
|
57
|
+
updateToolsNotes: makeFunctionReference<"mutation">(
|
|
58
|
+
"functions/agentConfig:updateToolsNotes",
|
|
59
|
+
),
|
|
60
|
+
updateUserProfile: makeFunctionReference<"mutation">(
|
|
61
|
+
"functions/agentConfig:updateUserProfile",
|
|
62
|
+
),
|
|
63
|
+
updateHeartbeat: makeFunctionReference<"mutation">(
|
|
64
|
+
"functions/agentConfig:updateHeartbeat",
|
|
65
|
+
),
|
|
66
|
+
updateBootstrapTemplate: makeFunctionReference<"mutation">(
|
|
67
|
+
"functions/agentConfig:updateBootstrapTemplate",
|
|
68
|
+
),
|
|
69
|
+
completeBootstrap: makeFunctionReference<"mutation">(
|
|
70
|
+
"functions/agentConfig:completeBootstrap",
|
|
71
|
+
),
|
|
72
|
+
setDefaultChatModelV2: makeFunctionReference<"mutation">(
|
|
73
|
+
"functions/agentConfig:setDefaultChatModelV2",
|
|
74
|
+
),
|
|
75
|
+
setThreadModelOverride: makeFunctionReference<"mutation">(
|
|
76
|
+
"functions/agentConfig:setThreadModelOverride",
|
|
77
|
+
),
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
42
82
|
type CliCtx = {
|
|
43
83
|
convex: ConvexHttpClient;
|
|
44
84
|
args: string[];
|
|
@@ -86,7 +126,9 @@ async function readContentFromStdin(): Promise<string> {
|
|
|
86
126
|
return new Promise((resolve, reject) => {
|
|
87
127
|
const chunks: Buffer[] = [];
|
|
88
128
|
process.stdin.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
89
|
-
process.stdin.on("end", () =>
|
|
129
|
+
process.stdin.on("end", () =>
|
|
130
|
+
resolve(Buffer.concat(chunks).toString("utf8")),
|
|
131
|
+
);
|
|
90
132
|
process.stdin.on("error", reject);
|
|
91
133
|
});
|
|
92
134
|
}
|
|
@@ -150,7 +192,10 @@ async function loadAgentConfig(ctx: CliCtx): Promise<{
|
|
|
150
192
|
userProfile: { content: string; updatedAt: number } | null;
|
|
151
193
|
organizationId: string;
|
|
152
194
|
}> {
|
|
153
|
-
const result = (await runQuery(
|
|
195
|
+
const result = (await runQuery(
|
|
196
|
+
ctx,
|
|
197
|
+
api.functions.agentConfig.getAgentConfig,
|
|
198
|
+
)) as {
|
|
154
199
|
agentConfig: {
|
|
155
200
|
identity: { content: string; updatedAt: number } | null;
|
|
156
201
|
organisation: { content: string; updatedAt: number } | null;
|
|
@@ -212,14 +257,14 @@ async function handleSimpleMagicFile(
|
|
|
212
257
|
} else {
|
|
213
258
|
const config = await loadAgentConfig(ctx);
|
|
214
259
|
const initial = opts.perMember
|
|
215
|
-
? config.userProfile?.content ?? ""
|
|
260
|
+
? (config.userProfile?.content ?? "")
|
|
216
261
|
: opts.field === "memoryAggregate"
|
|
217
|
-
? config.agentConfig.memoryAggregate?.content ?? ""
|
|
262
|
+
? (config.agentConfig.memoryAggregate?.content ?? "")
|
|
218
263
|
: opts.field === "toolsNotes"
|
|
219
|
-
? config.agentConfig.toolsNotes?.content ?? ""
|
|
264
|
+
? (config.agentConfig.toolsNotes?.content ?? "")
|
|
220
265
|
: opts.field === "identity"
|
|
221
|
-
? config.agentConfig.identity?.content ?? ""
|
|
222
|
-
: config.agentConfig.organisation?.content ?? "";
|
|
266
|
+
? (config.agentConfig.identity?.content ?? "")
|
|
267
|
+
: (config.agentConfig.organisation?.content ?? "");
|
|
223
268
|
content = openEditor(initial, opts.label);
|
|
224
269
|
}
|
|
225
270
|
if (!content.trim().length) {
|
|
@@ -519,8 +564,7 @@ export async function runMemoryAggregateCommand(ctx: CliCtx): Promise<void> {
|
|
|
519
564
|
}
|
|
520
565
|
if (sub === "append") {
|
|
521
566
|
const text = ctx.args.slice(1).join(" ").trim();
|
|
522
|
-
if (!text)
|
|
523
|
-
throw new AgentConfigCliError("Usage: dench mem append <text>");
|
|
567
|
+
if (!text) throw new AgentConfigCliError("Usage: dench mem append <text>");
|
|
524
568
|
await runMutation(ctx, api.functions.agentConfig.updateMemory, {
|
|
525
569
|
content: text,
|
|
526
570
|
append: true,
|
|
@@ -593,9 +637,7 @@ export async function runDailyCommand(ctx: CliCtx): Promise<void> {
|
|
|
593
637
|
if (sub === "show") {
|
|
594
638
|
const date = ctx.args[1];
|
|
595
639
|
if (!date) {
|
|
596
|
-
throw new AgentConfigCliError(
|
|
597
|
-
"Usage: dench daily show <YYYY-MM-DD>",
|
|
598
|
-
);
|
|
640
|
+
throw new AgentConfigCliError("Usage: dench daily show <YYYY-MM-DD>");
|
|
599
641
|
}
|
|
600
642
|
out(
|
|
601
643
|
ctx,
|
package/chat-spawn.ts
CHANGED
|
@@ -16,8 +16,6 @@
|
|
|
16
16
|
* (`/api/chat/[runId]/stream`) and pretty-prints text deltas + tool
|
|
17
17
|
* calls until the workflow finishes.
|
|
18
18
|
*/
|
|
19
|
-
|
|
20
|
-
import { getCurrentRuntimeTimeZone } from "@/lib/timezone";
|
|
21
19
|
import { hasFlag } from "./lib/cli-args";
|
|
22
20
|
|
|
23
21
|
class ChatSpawnError extends Error {}
|
|
@@ -33,6 +31,18 @@ type ChatSpawnContext = {
|
|
|
33
31
|
jsonOutput: boolean;
|
|
34
32
|
};
|
|
35
33
|
|
|
34
|
+
function getCurrentRuntimeTimeZone(): string | null {
|
|
35
|
+
try {
|
|
36
|
+
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
37
|
+
if (!timeZone || timeZone.length > 100) return null;
|
|
38
|
+
// Validate that Intl accepts the resolved value before forwarding it.
|
|
39
|
+
Intl.DateTimeFormat("en-US", { timeZone }).format(new Date());
|
|
40
|
+
return timeZone;
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
36
46
|
function consumeFlagValue(args: string[], name: string): string | undefined {
|
|
37
47
|
const idx = args.indexOf(name);
|
|
38
48
|
if (idx === -1) return undefined;
|
package/dench.ts
CHANGED
|
@@ -440,13 +440,13 @@ Workspace members (for CRM \`user\`-type fields):
|
|
|
440
440
|
cells assign to real members instead of being stored as unlinked
|
|
441
441
|
display-name strings. See \`dench members help\`.
|
|
442
442
|
|
|
443
|
-
Live web search (Exa via the Dench
|
|
443
|
+
Live web search (Exa via the Dench Gateway, auths with the active \`dench signin\` agent session or DENCH_API_KEY):
|
|
444
444
|
dench search "<query>" [--num-results N] [--type auto|fast|deep|deep-reasoning|neural] [--category news|company|people|...] [--include-domains a.com,b.com] [--exclude-domains c.com] [--max-chars 800] [--json]
|
|
445
445
|
dench search contents <url> [<url>...] [--max-chars 4000] [--summary "..."] [--json]
|
|
446
446
|
dench search answer "<query>" [--json]
|
|
447
447
|
Help: dench search help
|
|
448
448
|
|
|
449
|
-
Image generation / editing (
|
|
449
|
+
Image generation / editing (via the Dench Gateway):
|
|
450
450
|
dench image generate "<prompt>" [--size 1024x1024] [--quality auto|low|medium|high] [--format png|jpeg|webp] [--save-path /workspace/path/file.png] [--output <local file>] [--no-write] [--json]
|
|
451
451
|
dench image edit "<prompt>" --input <path> [--input <path> ...] [--mask <path>] [--size ...] [--quality ...] [--format ...] [--save-path ...] [--output ...] [--json]
|
|
452
452
|
Help: dench image help
|
|
@@ -472,7 +472,7 @@ Spawn a new chat-turn workflow (same as the web UI):
|
|
|
472
472
|
|
|
473
473
|
Help: dench chat help
|
|
474
474
|
|
|
475
|
-
File sync
|
|
475
|
+
File sync:
|
|
476
476
|
dench fs status [--json] [--workspace /workspace] [--no-hash] [--drift-limit N]
|
|
477
477
|
dench fs sync --initial --org-id <orgId> [--workspace /workspace]
|
|
478
478
|
dench fs stream-open <path>
|
|
@@ -488,7 +488,7 @@ returns ENOSYS on the FUSE-backed volume mount):
|
|
|
488
488
|
Persist scratch -> workspace (cp from /tmp into /workspace + Convex sync):
|
|
489
489
|
dench stage <local-path> [<workspace-dest>] [--clean] [--json]
|
|
490
490
|
|
|
491
|
-
Subagents
|
|
491
|
+
Subagents:
|
|
492
492
|
dench agent spawn '<goal>' [--parent-run-id <id>] [--sandbox own|share_parent] [--time-budget-ms N]
|
|
493
493
|
dench agent await --hook <token> | --children id1,id2,id3
|
|
494
494
|
dench agent message <toRunId> '<text>' [--from-run-id <id>]
|
|
@@ -501,7 +501,7 @@ Subagents (Daytona-native rewrite):
|
|
|
501
501
|
|
|
502
502
|
dench --version
|
|
503
503
|
|
|
504
|
-
Self-updating agent harness
|
|
504
|
+
Self-updating agent harness:
|
|
505
505
|
dench identity show | edit IDENTITY.md (org-wide)
|
|
506
506
|
dench organisation show | edit ORGANISATION.md
|
|
507
507
|
dench user show | edit USER.md (per-member)
|
|
@@ -2038,25 +2038,31 @@ function parseBillingTopupAmountUsd() {
|
|
|
2038
2038
|
}
|
|
2039
2039
|
|
|
2040
2040
|
async function billingStatus(runtime: Runtime) {
|
|
2041
|
-
const
|
|
2042
|
-
|
|
2041
|
+
const authedRuntime = requireAuthenticatedRuntime(
|
|
2042
|
+
runtime,
|
|
2043
|
+
"dench billing status",
|
|
2044
|
+
);
|
|
2045
|
+
const status = await authedRuntime.client.query(
|
|
2043
2046
|
api.functions.agentWorkspace.getAgentBillingStatus,
|
|
2044
|
-
{ sessionToken:
|
|
2047
|
+
{ sessionToken: authedRuntime.sessionToken },
|
|
2045
2048
|
);
|
|
2046
2049
|
print(json ? status : formatBillingStatus(status));
|
|
2047
2050
|
}
|
|
2048
2051
|
|
|
2049
2052
|
async function billingTopup(runtime: Runtime) {
|
|
2050
|
-
const
|
|
2053
|
+
const authedRuntime = requireAuthenticatedRuntime(
|
|
2054
|
+
runtime,
|
|
2055
|
+
"dench billing topup",
|
|
2056
|
+
);
|
|
2051
2057
|
const amountUsd = parseBillingTopupAmountUsd();
|
|
2052
2058
|
const response = await fetch(
|
|
2053
|
-
`${
|
|
2059
|
+
`${authedRuntime.host.replace(/\/+$/, "")}/api/stripe/create-ai-topup`,
|
|
2054
2060
|
{
|
|
2055
2061
|
method: "POST",
|
|
2056
2062
|
headers: {
|
|
2057
2063
|
accept: "application/json",
|
|
2058
2064
|
"content-type": "application/json",
|
|
2059
|
-
authorization: `Bearer ${
|
|
2065
|
+
authorization: `Bearer ${authedRuntime.sessionToken}`,
|
|
2060
2066
|
},
|
|
2061
2067
|
body: JSON.stringify({
|
|
2062
2068
|
amountUsd,
|
|
@@ -2123,7 +2129,7 @@ async function billingTopup(runtime: Runtime) {
|
|
|
2123
2129
|
* needed in that case). We surface either outcome cleanly.
|
|
2124
2130
|
*/
|
|
2125
2131
|
async function denchUpgrade(runtime: Runtime) {
|
|
2126
|
-
const
|
|
2132
|
+
const authedRuntime = requireAuthenticatedRuntime(runtime, "dench upgrade");
|
|
2127
2133
|
const tierFlag = option("--tier")?.trim().toLowerCase() || "pro";
|
|
2128
2134
|
const cycleFlag =
|
|
2129
2135
|
option("--cycle")?.trim().toLowerCase() ||
|
|
@@ -2146,13 +2152,13 @@ async function denchUpgrade(runtime: Runtime) {
|
|
|
2146
2152
|
const internalTier = tierFlag === "pro" ? "desktop" : "cloud";
|
|
2147
2153
|
|
|
2148
2154
|
const response = await fetch(
|
|
2149
|
-
`${
|
|
2155
|
+
`${authedRuntime.host.replace(/\/+$/, "")}/api/stripe/create-checkout`,
|
|
2150
2156
|
{
|
|
2151
2157
|
method: "POST",
|
|
2152
2158
|
headers: {
|
|
2153
2159
|
accept: "application/json",
|
|
2154
2160
|
"content-type": "application/json",
|
|
2155
|
-
authorization: `Bearer ${
|
|
2161
|
+
authorization: `Bearer ${authedRuntime.sessionToken}`,
|
|
2156
2162
|
},
|
|
2157
2163
|
body: JSON.stringify({
|
|
2158
2164
|
tier: internalTier,
|
|
@@ -2394,25 +2400,6 @@ function stripRuntimeFlags(args: string[]) {
|
|
|
2394
2400
|
return stripped;
|
|
2395
2401
|
}
|
|
2396
2402
|
|
|
2397
|
-
/**
|
|
2398
|
-
* `session` mode is required for `agentWorkspace.*` calls because they
|
|
2399
|
-
* gate on `validateAgentSession` server-side, which only accepts the
|
|
2400
|
-
* `dch_agent_*` token format. Sandboxes that only have a unified
|
|
2401
|
-
* `DENCH_API_KEY` (apiKey mode) cannot impersonate a specific agent
|
|
2402
|
-
* and will fail at the server with `Invalid agent session` — surface
|
|
2403
|
-
* that here as a clear error instead.
|
|
2404
|
-
*/
|
|
2405
|
-
function requireSessionRuntime(
|
|
2406
|
-
runtime: Runtime,
|
|
2407
|
-
command: string,
|
|
2408
|
-
): Extract<Runtime, { mode: "session" }> {
|
|
2409
|
-
if (runtime.mode === "session") return runtime;
|
|
2410
|
-
if (runtime.mode === "apiKey") {
|
|
2411
|
-
throw agentSessionRequiredError(command);
|
|
2412
|
-
}
|
|
2413
|
-
throw loginRequiredError(command);
|
|
2414
|
-
}
|
|
2415
|
-
|
|
2416
2403
|
/**
|
|
2417
2404
|
* Org-scoped commands (`dench crm`, `dench files`, etc.) accept either
|
|
2418
2405
|
* a `dch_agent_*` agent session token OR a unified Dench API key
|
|
@@ -2543,36 +2530,6 @@ function encodeDevCrmSessionToken(args: {
|
|
|
2543
2530
|
return `dch_dev_${encodeURIComponent(args.workspaceSlug)}:${encodeURIComponent(args.devKey)}`;
|
|
2544
2531
|
}
|
|
2545
2532
|
|
|
2546
|
-
function agentSessionRequiredError(command: string) {
|
|
2547
|
-
return new CliError(
|
|
2548
|
-
`${command} requires an agent session — DENCH_API_KEY is org-scoped and cannot impersonate a specific agent`,
|
|
2549
|
-
{
|
|
2550
|
-
code: "agent_session_required",
|
|
2551
|
-
nextActions: [
|
|
2552
|
-
'Run dench signin --kind <kind> --name "AI Agent - Project" to mint an agent session for this command.',
|
|
2553
|
-
"Or run the equivalent action via the workspace UI / dench crm if it is org-level (e.g. CRM data, files).",
|
|
2554
|
-
],
|
|
2555
|
-
},
|
|
2556
|
-
);
|
|
2557
|
-
}
|
|
2558
|
-
|
|
2559
|
-
/**
|
|
2560
|
-
* `dench approval request` has separate session vs dev branches. With
|
|
2561
|
-
* apiKey mode added, the dev branch would silently receive partial args.
|
|
2562
|
-
* Use this to short-circuit that branch with a clear error.
|
|
2563
|
-
*
|
|
2564
|
-
* Asserts away the `apiKey` mode so the caller's downstream type
|
|
2565
|
-
* narrowing (e.g. `runtime.workspaceArgs`) keeps working.
|
|
2566
|
-
*/
|
|
2567
|
-
function rejectApiKeyForAgentCommand(
|
|
2568
|
-
runtime: Runtime,
|
|
2569
|
-
command: string,
|
|
2570
|
-
): asserts runtime is Exclude<Runtime, { mode: "apiKey" }> {
|
|
2571
|
-
if (runtime.mode === "apiKey") {
|
|
2572
|
-
throw agentSessionRequiredError(command);
|
|
2573
|
-
}
|
|
2574
|
-
}
|
|
2575
|
-
|
|
2576
2533
|
function asRecord(value: unknown): JsonRecord | undefined {
|
|
2577
2534
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2578
2535
|
return undefined;
|
|
@@ -2679,7 +2636,7 @@ async function connectedAppsContext(runtime: Runtime) {
|
|
|
2679
2636
|
async function buildContext(runtime: Runtime) {
|
|
2680
2637
|
let mine: JsonRecord;
|
|
2681
2638
|
let urls: JsonRecord;
|
|
2682
|
-
if (runtime.mode === "session") {
|
|
2639
|
+
if (runtime.mode === "session" || runtime.mode === "apiKey") {
|
|
2683
2640
|
mine = (await runtime.client.query(
|
|
2684
2641
|
api.functions.agentWorkspace.whatCanIDoHere,
|
|
2685
2642
|
{ sessionToken: runtime.sessionToken },
|
|
@@ -2692,20 +2649,7 @@ async function buildContext(runtime: Runtime) {
|
|
|
2692
2649
|
);
|
|
2693
2650
|
urls = {};
|
|
2694
2651
|
} else {
|
|
2695
|
-
|
|
2696
|
-
// `whatCanIDoHere` (it gates on `validateAgentSession`). Return a
|
|
2697
|
-
// minimal context derived from sandbox envVars so dench-cli help
|
|
2698
|
-
// surfaces still work without a full login.
|
|
2699
|
-
mine = {
|
|
2700
|
-
authMode: "apiKey",
|
|
2701
|
-
organization: runtime.organization ?? null,
|
|
2702
|
-
runId: process.env.DENCH_RUN_ID?.trim() ?? null,
|
|
2703
|
-
parentRunId: process.env.DENCH_PARENT_RUN_ID?.trim() ?? null,
|
|
2704
|
-
rootRunId: process.env.DENCH_ROOT_RUN_ID?.trim() ?? null,
|
|
2705
|
-
};
|
|
2706
|
-
urls = runtime.host
|
|
2707
|
-
? workspaceUrls(runtime.host, runtime.organization?.slug)
|
|
2708
|
-
: {};
|
|
2652
|
+
throw loginRequiredError("dench context");
|
|
2709
2653
|
}
|
|
2710
2654
|
|
|
2711
2655
|
return {
|
|
@@ -2933,7 +2877,7 @@ function summarizeDevMine(workspaceSlug: string, data: WorkspaceOverview) {
|
|
|
2933
2877
|
}
|
|
2934
2878
|
|
|
2935
2879
|
async function listArtifacts(runtime: Runtime, limit?: number) {
|
|
2936
|
-
if (runtime.mode === "session") {
|
|
2880
|
+
if (runtime.mode === "session" || runtime.mode === "apiKey") {
|
|
2937
2881
|
try {
|
|
2938
2882
|
return (await runtime.client.query(
|
|
2939
2883
|
api.functions.agentWorkspace.agentListArtifacts,
|
|
@@ -2951,12 +2895,6 @@ async function listArtifacts(runtime: Runtime, limit?: number) {
|
|
|
2951
2895
|
);
|
|
2952
2896
|
}
|
|
2953
2897
|
}
|
|
2954
|
-
if (runtime.mode === "apiKey") {
|
|
2955
|
-
// No agent identity → no artifact list. Return empty so callers
|
|
2956
|
-
// (e.g. `dench artifacts`, `dench suggested-work`) degrade gracefully
|
|
2957
|
-
// instead of throwing for sandbox callers.
|
|
2958
|
-
return [] as JsonRecord[];
|
|
2959
|
-
}
|
|
2960
2898
|
const data = await devOverview(runtime);
|
|
2961
2899
|
return asRecordArray(data.recentArtifacts);
|
|
2962
2900
|
}
|
|
@@ -4165,15 +4103,15 @@ async function main() {
|
|
|
4165
4103
|
}
|
|
4166
4104
|
|
|
4167
4105
|
if (command === "memory") {
|
|
4168
|
-
const
|
|
4106
|
+
const authedRuntime = requireAuthenticatedRuntime(runtime, "dench memory");
|
|
4169
4107
|
if (subcommand === "search") {
|
|
4170
4108
|
const query = positionalsFrom(2).join(" ").trim();
|
|
4171
4109
|
if (!query) throw new Error('Usage: dench memory search "query"');
|
|
4172
4110
|
print(
|
|
4173
|
-
await
|
|
4111
|
+
await authedRuntime.client.query(
|
|
4174
4112
|
api.functions.agentWorkspace.agentSearchMemory,
|
|
4175
4113
|
{
|
|
4176
|
-
sessionToken:
|
|
4114
|
+
sessionToken: authedRuntime.sessionToken,
|
|
4177
4115
|
query,
|
|
4178
4116
|
limit: parseNumberOption("--limit"),
|
|
4179
4117
|
},
|
|
@@ -4188,10 +4126,10 @@ async function main() {
|
|
|
4188
4126
|
throw new Error('Usage: dench memory save <key> "text"');
|
|
4189
4127
|
}
|
|
4190
4128
|
print(
|
|
4191
|
-
await
|
|
4129
|
+
await authedRuntime.client.mutation(
|
|
4192
4130
|
api.functions.agentWorkspace.agentSaveMemory,
|
|
4193
4131
|
{
|
|
4194
|
-
sessionToken:
|
|
4132
|
+
sessionToken: authedRuntime.sessionToken,
|
|
4195
4133
|
key,
|
|
4196
4134
|
kind: (option("--kind") ?? "fact") as never,
|
|
4197
4135
|
text,
|
|
@@ -4216,9 +4154,9 @@ async function main() {
|
|
|
4216
4154
|
}
|
|
4217
4155
|
|
|
4218
4156
|
if (command === "status") {
|
|
4219
|
-
if (runtime.mode === "session") {
|
|
4157
|
+
if (runtime.mode === "session" || runtime.mode === "apiKey") {
|
|
4220
4158
|
const status = (await runtime.client.query(
|
|
4221
|
-
api.functions.agentWorkspace.
|
|
4159
|
+
api.functions.agentWorkspace.whatCanIDoHere,
|
|
4222
4160
|
{
|
|
4223
4161
|
sessionToken: runtime.sessionToken,
|
|
4224
4162
|
},
|
|
@@ -4230,13 +4168,6 @@ async function main() {
|
|
|
4230
4168
|
print(status);
|
|
4231
4169
|
return;
|
|
4232
4170
|
}
|
|
4233
|
-
if (runtime.mode === "apiKey") {
|
|
4234
|
-
// No agent session → no agent-status query. Fall back to a thin
|
|
4235
|
-
// env-derived snapshot so sandbox callers still get something
|
|
4236
|
-
// useful from `dench status`.
|
|
4237
|
-
print(await buildContext(runtime));
|
|
4238
|
-
return;
|
|
4239
|
-
}
|
|
4240
4171
|
const data = await devOverview(runtime);
|
|
4241
4172
|
const output = scopedStatus
|
|
4242
4173
|
? summarizeDevMine(runtime.workspaceArgs.workspaceSlug, data)
|
|
@@ -4248,9 +4179,9 @@ async function main() {
|
|
|
4248
4179
|
}
|
|
4249
4180
|
|
|
4250
4181
|
if (command === "agents") {
|
|
4251
|
-
if (runtime.mode === "session") {
|
|
4182
|
+
if (runtime.mode === "session" || runtime.mode === "apiKey") {
|
|
4252
4183
|
const status = await runtime.client.query(
|
|
4253
|
-
api.functions.agentWorkspace.
|
|
4184
|
+
api.functions.agentWorkspace.whatCanIDoHere,
|
|
4254
4185
|
{
|
|
4255
4186
|
sessionToken: runtime.sessionToken,
|
|
4256
4187
|
},
|
|
@@ -4258,18 +4189,15 @@ async function main() {
|
|
|
4258
4189
|
print(status.agents);
|
|
4259
4190
|
return;
|
|
4260
4191
|
}
|
|
4261
|
-
if (runtime.mode === "apiKey") {
|
|
4262
|
-
throw loginRequiredError("dench agents");
|
|
4263
|
-
}
|
|
4264
4192
|
const data = await devOverview(runtime);
|
|
4265
4193
|
print(data.agents);
|
|
4266
4194
|
return;
|
|
4267
4195
|
}
|
|
4268
4196
|
|
|
4269
4197
|
if (command === "approvals") {
|
|
4270
|
-
if (runtime.mode === "session") {
|
|
4198
|
+
if (runtime.mode === "session" || runtime.mode === "apiKey") {
|
|
4271
4199
|
const status = await runtime.client.query(
|
|
4272
|
-
api.functions.agentWorkspace.
|
|
4200
|
+
api.functions.agentWorkspace.whatCanIDoHere,
|
|
4273
4201
|
{
|
|
4274
4202
|
sessionToken: runtime.sessionToken,
|
|
4275
4203
|
},
|
|
@@ -4277,9 +4205,6 @@ async function main() {
|
|
|
4277
4205
|
print(status.approvals);
|
|
4278
4206
|
return;
|
|
4279
4207
|
}
|
|
4280
|
-
if (runtime.mode === "apiKey") {
|
|
4281
|
-
throw loginRequiredError("dench approvals");
|
|
4282
|
-
}
|
|
4283
4208
|
const data = await devOverview(runtime);
|
|
4284
4209
|
print(data.approvals);
|
|
4285
4210
|
return;
|
|
@@ -4309,7 +4234,7 @@ async function main() {
|
|
|
4309
4234
|
if (command === "approval" && subcommand === "request") {
|
|
4310
4235
|
const title = positional(2);
|
|
4311
4236
|
if (!title) throw new Error("Missing approval title");
|
|
4312
|
-
if (runtime.mode === "session") {
|
|
4237
|
+
if (runtime.mode === "session" || runtime.mode === "apiKey") {
|
|
4313
4238
|
print(
|
|
4314
4239
|
await runtime.client.mutation(
|
|
4315
4240
|
api.functions.agentWorkspace.agentRequestApproval,
|
|
@@ -4323,7 +4248,6 @@ async function main() {
|
|
|
4323
4248
|
);
|
|
4324
4249
|
return;
|
|
4325
4250
|
}
|
|
4326
|
-
rejectApiKeyForAgentCommand(runtime, "dench approval request");
|
|
4327
4251
|
const approvalId = await runtime.client.mutation(
|
|
4328
4252
|
api.functions.agentWorkspace.devRequestApproval,
|
|
4329
4253
|
{
|
|
@@ -4346,15 +4270,15 @@ async function main() {
|
|
|
4346
4270
|
) {
|
|
4347
4271
|
const approvalId = positional(2);
|
|
4348
4272
|
if (!approvalId) throw new Error("Missing approval id");
|
|
4349
|
-
const
|
|
4273
|
+
const authedRuntime = requireAuthenticatedRuntime(
|
|
4350
4274
|
runtime,
|
|
4351
4275
|
"dench approval approve/reject",
|
|
4352
4276
|
);
|
|
4353
4277
|
const decision = subcommand === "approve" ? "approved" : "rejected";
|
|
4354
|
-
const result = await
|
|
4278
|
+
const result = await authedRuntime.client.mutation(
|
|
4355
4279
|
api.functions.agentWorkspace.agentDecideApproval,
|
|
4356
4280
|
{
|
|
4357
|
-
sessionToken:
|
|
4281
|
+
sessionToken: authedRuntime.sessionToken,
|
|
4358
4282
|
approvalId: approvalId as never,
|
|
4359
4283
|
decision,
|
|
4360
4284
|
evidence: option("--evidence"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dench.com/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "Dench agent workspace CLI. v2 unifies auth behind `dench signin`; the legacy `dench login` / `dench onboard` / `dench setup` / `dench what-can-i-do` / `dench register` commands now error with a redirect.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|