denchclaw 2.4.1 → 2.4.3
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/apps/web/.next/standalone/apps/web/.next/BUILD_ID +1 -1
- package/apps/web/.next/standalone/apps/web/.next/app-build-manifest.json +82 -82
- package/apps/web/.next/standalone/apps/web/.next/app-path-routes-manifest.json +25 -25
- package/apps/web/.next/standalone/apps/web/.next/build-manifest.json +2 -2
- package/apps/web/.next/standalone/apps/web/.next/cache/config.json +3 -3
- package/apps/web/.next/standalone/apps/web/.next/prerender-manifest.json +3 -3
- package/apps/web/.next/standalone/apps/web/.next/required-server-files.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/routes-manifest.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/cron/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/proxy/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/serve/[...path]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/store/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/webhooks/[...path]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/active/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/runs/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stop/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stop/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stream/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/subagents/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/jobs/[jobId]/runs/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/jobs/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/runs/[sessionId]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/runs/search-transcript/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/feedback/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/feedback/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/gateway/channels/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/gateway/chat/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/gateway/chat/stream/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/gateway/sessions/[id]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/gateway/sessions/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/memories/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/profiles/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/profiles/switch/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/sessions/[sessionId]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/sessions/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/terminal/port/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/[id]/messages/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/[id]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/assets/[...path]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/browse/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/browse-file/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/context/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/copy/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/db/introspect/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/db/query/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/delete/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/delete/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/execute/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/file/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/init/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/init/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/link-preview/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/list/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/mkdir/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/move/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/actions/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/actions/runs/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/display-field/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/[id]/content/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/[id]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/bulk-delete/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/options/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/fields/[fieldId]/enum-rename/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/fields/[fieldId]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/fields/reorder/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/fields/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/views/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/open-file/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/path-info/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/query/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/raw-file/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/rename/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/reports/execute/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/reports/execute/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/search-index/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/suggest-files/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/switch/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/switch/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/thumbnail/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/tree/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/upload/route.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/upload/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/virtual-file/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/watch/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/write-binary/route_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/page.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app/workspace/page_client-reference-manifest.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/app-paths-manifest.json +25 -25
- package/apps/web/.next/standalone/apps/web/.next/server/chunks/6787.js +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/functions-config-manifest.json +9 -9
- package/apps/web/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/server-reference-manifest.json +1 -1
- package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/{layout-27fe4dc768717757.js → layout-5b42eb12bc6891b1.js} +1 -1
- package/apps/web/.next/{static/chunks/app/page-6a172dc187a2f128.js → standalone/apps/web/.next/static/chunks/app/page-4dfaa52589c03e51.js} +1 -1
- package/apps/web/.next/standalone/apps/web/server.js +1 -1
- package/apps/web/.next/standalone/package.json +2 -1
- package/apps/web/.next/static/chunks/app/{layout-27fe4dc768717757.js → layout-5b42eb12bc6891b1.js} +1 -1
- package/apps/web/.next/{standalone/apps/web/.next/static/chunks/app/page-6a172dc187a2f128.js → static/chunks/app/page-4dfaa52589c03e51.js} +1 -1
- package/dist/entry.js +1 -1
- package/dist/{program-DcrLV9Z2.js → program-D2RfLoKh.js} +16 -37
- package/dist/{run-main-D7Ux65aN.js → run-main-giTi_or5.js} +1 -1
- package/extensions/dench-identity/index.test.ts +136 -0
- package/extensions/dench-identity/index.ts +3 -2
- package/extensions/posthog-analytics/lib/build-env.js +1 -1
- package/extensions/vitest.config.ts +13 -0
- package/package.json +2 -1
- package/skills/crm/SKILL.md +46 -1
- /package/apps/web/.next/standalone/apps/web/.next/static/{nF9C2TCY9WzJYkr3LhlED → yotM7sjmc2mLN7mGVWai0}/_buildManifest.js +0 -0
- /package/apps/web/.next/standalone/apps/web/.next/static/{nF9C2TCY9WzJYkr3LhlED → yotM7sjmc2mLN7mGVWai0}/_ssgManifest.js +0 -0
- /package/apps/web/.next/static/{nF9C2TCY9WzJYkr3LhlED → yotM7sjmc2mLN7mGVWai0}/_buildManifest.js +0 -0
- /package/apps/web/.next/static/{nF9C2TCY9WzJYkr3LhlED → yotM7sjmc2mLN7mGVWai0}/_ssgManifest.js +0 -0
package/dist/entry.js
CHANGED
|
@@ -1147,7 +1147,7 @@ if (!ensureExperimentalWarningSuppressed()) {
|
|
|
1147
1147
|
const appliedProfile = applyCliProfileEnv({ profile: parsed.profile ?? void 0 });
|
|
1148
1148
|
if (appliedProfile.warning) console.warn(`[denchclaw] ${appliedProfile.warning}`);
|
|
1149
1149
|
process$1.argv = parsed.argv;
|
|
1150
|
-
import("./run-main-
|
|
1150
|
+
import("./run-main-giTi_or5.js").then(({ runCli }) => runCli(process$1.argv)).then(() => import("./telemetry-DguRjCZq.js").then((n) => n.n).then(({ shutdownTelemetry }) => shutdownTelemetry())).catch((error) => {
|
|
1151
1151
|
console.error("[denchclaw] Failed to start CLI:", error instanceof Error ? error.stack ?? error.message : error);
|
|
1152
1152
|
process$1.exitCode = 1;
|
|
1153
1153
|
});
|
|
@@ -2406,21 +2406,17 @@ async function attemptGatewayAutoFix(params) {
|
|
|
2406
2406
|
params.profile,
|
|
2407
2407
|
"gateway",
|
|
2408
2408
|
"install",
|
|
2409
|
-
"--force"
|
|
2410
|
-
"--port",
|
|
2411
|
-
String(params.gatewayPort)
|
|
2409
|
+
"--force"
|
|
2412
2410
|
],
|
|
2413
2411
|
timeoutMs: 2 * 6e4
|
|
2414
2412
|
},
|
|
2415
2413
|
{
|
|
2416
|
-
name: "openclaw gateway
|
|
2414
|
+
name: "openclaw gateway restart",
|
|
2417
2415
|
args: [
|
|
2418
2416
|
"--profile",
|
|
2419
2417
|
params.profile,
|
|
2420
2418
|
"gateway",
|
|
2421
|
-
"
|
|
2422
|
-
"--port",
|
|
2423
|
-
String(params.gatewayPort)
|
|
2419
|
+
"restart"
|
|
2424
2420
|
],
|
|
2425
2421
|
timeoutMs: 2 * 6e4
|
|
2426
2422
|
}
|
|
@@ -2630,7 +2626,8 @@ function resolveDenchCloudApiKeyCandidate(params) {
|
|
|
2630
2626
|
}
|
|
2631
2627
|
async function promptForDenchCloudApiKey(initialValue) {
|
|
2632
2628
|
const value = await text({
|
|
2633
|
-
message: stylePromptMessage("
|
|
2629
|
+
message: stylePromptMessage("Paste your Dench Cloud API key"),
|
|
2630
|
+
placeholder: "dench_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
2634
2631
|
...initialValue ? { initialValue } : {},
|
|
2635
2632
|
validate: (input) => input?.trim().length ? void 0 : "API key is required."
|
|
2636
2633
|
});
|
|
@@ -2732,10 +2729,11 @@ async function resolveDenchCloudBootstrapSelection(params) {
|
|
|
2732
2729
|
};
|
|
2733
2730
|
}
|
|
2734
2731
|
const wantsDenchCloud = explicitRequest ? true : await confirm({
|
|
2735
|
-
message: stylePromptMessage("Use Dench
|
|
2732
|
+
message: stylePromptMessage("Use Dench Cloud for inference? Get your API key at dench.com/api"),
|
|
2736
2733
|
initialValue: existingDenchConfigured || !currentProvider
|
|
2737
2734
|
});
|
|
2738
2735
|
if (isCancel(wantsDenchCloud) || !wantsDenchCloud) return { enabled: false };
|
|
2736
|
+
if (!params.nonInteractive) await openUrl$1("https://dench.com/api").catch(() => {});
|
|
2739
2737
|
let apiKey = resolveDenchCloudApiKeyCandidate({
|
|
2740
2738
|
opts: params.opts,
|
|
2741
2739
|
existingApiKey: existing.apiKey
|
|
@@ -3529,22 +3527,7 @@ async function restartGatewayDaemon(params) {
|
|
|
3529
3527
|
};
|
|
3530
3528
|
}
|
|
3531
3529
|
const s = !params.json ? spinner() : null;
|
|
3532
|
-
s?.start("
|
|
3533
|
-
await runOpenClawCommand({
|
|
3534
|
-
openclawCommand,
|
|
3535
|
-
args: [
|
|
3536
|
-
"--profile",
|
|
3537
|
-
params.profile,
|
|
3538
|
-
"gateway",
|
|
3539
|
-
"stop"
|
|
3540
|
-
],
|
|
3541
|
-
timeoutMs: 9e4
|
|
3542
|
-
}).catch(() => ({
|
|
3543
|
-
code: 1,
|
|
3544
|
-
stdout: "",
|
|
3545
|
-
stderr: "stop timed out"
|
|
3546
|
-
}));
|
|
3547
|
-
s?.message("Installing gateway daemon…");
|
|
3530
|
+
s?.start("Refreshing gateway service definition…");
|
|
3548
3531
|
await runOpenClawCommand({
|
|
3549
3532
|
openclawCommand,
|
|
3550
3533
|
args: [
|
|
@@ -3552,9 +3535,7 @@ async function restartGatewayDaemon(params) {
|
|
|
3552
3535
|
params.profile,
|
|
3553
3536
|
"gateway",
|
|
3554
3537
|
"install",
|
|
3555
|
-
"--force"
|
|
3556
|
-
"--port",
|
|
3557
|
-
String(params.gatewayPort)
|
|
3538
|
+
"--force"
|
|
3558
3539
|
],
|
|
3559
3540
|
timeoutMs: 2 * 6e4
|
|
3560
3541
|
}).catch(() => ({
|
|
@@ -3562,29 +3543,27 @@ async function restartGatewayDaemon(params) {
|
|
|
3562
3543
|
stdout: "",
|
|
3563
3544
|
stderr: "install failed"
|
|
3564
3545
|
}));
|
|
3565
|
-
s?.message("
|
|
3566
|
-
const
|
|
3546
|
+
s?.message("Restarting gateway daemon…");
|
|
3547
|
+
const restartResult = await runOpenClawCommand({
|
|
3567
3548
|
openclawCommand,
|
|
3568
3549
|
args: [
|
|
3569
3550
|
"--profile",
|
|
3570
3551
|
params.profile,
|
|
3571
3552
|
"gateway",
|
|
3572
|
-
"
|
|
3573
|
-
"--port",
|
|
3574
|
-
String(params.gatewayPort)
|
|
3553
|
+
"restart"
|
|
3575
3554
|
],
|
|
3576
3555
|
timeoutMs: 2 * 6e4
|
|
3577
3556
|
}).catch(() => ({
|
|
3578
3557
|
code: 1,
|
|
3579
3558
|
stdout: "",
|
|
3580
|
-
stderr: "
|
|
3559
|
+
stderr: "restart failed"
|
|
3581
3560
|
}));
|
|
3582
|
-
if (
|
|
3583
|
-
const detail = firstNonEmptyLine(
|
|
3561
|
+
if (restartResult.code !== 0) {
|
|
3562
|
+
const detail = firstNonEmptyLine(restartResult.stderr, restartResult.stdout);
|
|
3584
3563
|
s?.stop(detail ? `Gateway restart failed: ${detail}` : "Gateway restart failed.");
|
|
3585
3564
|
return {
|
|
3586
3565
|
restarted: false,
|
|
3587
|
-
error: detail ?? "gateway
|
|
3566
|
+
error: detail ?? "gateway restart failed"
|
|
3588
3567
|
};
|
|
3589
3568
|
}
|
|
3590
3569
|
s?.stop("Gateway daemon restarted.");
|
|
@@ -220,7 +220,7 @@ async function runCli(argv = process$1.argv) {
|
|
|
220
220
|
process$1.exitCode = await delegateToGlobalOpenClaw(parseArgv);
|
|
221
221
|
return;
|
|
222
222
|
}
|
|
223
|
-
const { buildProgram } = await import("./program-
|
|
223
|
+
const { buildProgram } = await import("./program-D2RfLoKh.js");
|
|
224
224
|
await buildProgram().parseAsync(parseArgv);
|
|
225
225
|
}
|
|
226
226
|
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { buildIdentityPrompt, resolveWorkspaceDir } from "./index.ts";
|
|
3
|
+
import register from "./index.ts";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
describe("buildIdentityPrompt", () => {
|
|
7
|
+
const workspaceDir = "/home/user/workspace";
|
|
8
|
+
|
|
9
|
+
it("includes chat history path so agent can reference past conversations", () => {
|
|
10
|
+
const prompt = buildIdentityPrompt(workspaceDir);
|
|
11
|
+
expect(prompt).toContain(".openclaw/web-chat/");
|
|
12
|
+
expect(prompt).toContain(
|
|
13
|
+
path.join(workspaceDir, ".openclaw/web-chat/"),
|
|
14
|
+
);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("includes all workspace context paths (prevents agent losing orientation)", () => {
|
|
18
|
+
const prompt = buildIdentityPrompt(workspaceDir);
|
|
19
|
+
expect(prompt).toContain(`**Root**: \`${workspaceDir}\``);
|
|
20
|
+
expect(prompt).toContain(path.join(workspaceDir, "workspace.duckdb"));
|
|
21
|
+
expect(prompt).toContain(path.join(workspaceDir, "skills"));
|
|
22
|
+
expect(prompt).toContain(path.join(workspaceDir, "apps"));
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("includes CRM skill path for delegation (prevents agent using wrong skill path)", () => {
|
|
26
|
+
const prompt = buildIdentityPrompt(workspaceDir);
|
|
27
|
+
expect(prompt).toContain(
|
|
28
|
+
path.join(workspaceDir, "skills", "crm", "SKILL.md"),
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("includes exec approval policy (prevents agent stalling on exec confirmation)", () => {
|
|
33
|
+
const prompt = buildIdentityPrompt(workspaceDir);
|
|
34
|
+
expect(prompt).toContain("elevated: true");
|
|
35
|
+
expect(prompt).toContain("automatically approved");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("references DenchClaw branding, not OpenClaw (prevents identity confusion)", () => {
|
|
39
|
+
const prompt = buildIdentityPrompt(workspaceDir);
|
|
40
|
+
expect(prompt).toContain("You are **DenchClaw**");
|
|
41
|
+
expect(prompt).toContain("always use **DenchClaw** (not OpenClaw)");
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("resolveWorkspaceDir", () => {
|
|
46
|
+
it("returns workspace path when config is a valid string", () => {
|
|
47
|
+
const api = { config: { agents: { defaults: { workspace: "/home/user/ws" } } } };
|
|
48
|
+
expect(resolveWorkspaceDir(api)).toBe("/home/user/ws");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("returns undefined when api is null (prevents crash on missing config)", () => {
|
|
52
|
+
expect(resolveWorkspaceDir(null)).toBeUndefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("returns undefined when api is undefined (prevents crash on missing config)", () => {
|
|
56
|
+
expect(resolveWorkspaceDir(undefined)).toBeUndefined();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("returns undefined when config chain is missing (prevents crash on partial config)", () => {
|
|
60
|
+
expect(resolveWorkspaceDir({})).toBeUndefined();
|
|
61
|
+
expect(resolveWorkspaceDir({ config: {} })).toBeUndefined();
|
|
62
|
+
expect(resolveWorkspaceDir({ config: { agents: {} } })).toBeUndefined();
|
|
63
|
+
expect(resolveWorkspaceDir({ config: { agents: { defaults: {} } } })).toBeUndefined();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("returns undefined when workspace is empty string (prevents empty path injection)", () => {
|
|
67
|
+
const api = { config: { agents: { defaults: { workspace: "" } } } };
|
|
68
|
+
expect(resolveWorkspaceDir(api)).toBeUndefined();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("returns undefined when workspace is whitespace-only (prevents whitespace path injection)", () => {
|
|
72
|
+
const api = { config: { agents: { defaults: { workspace: " " } } } };
|
|
73
|
+
expect(resolveWorkspaceDir(api)).toBeUndefined();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("returns undefined when workspace is not a string (prevents type coercion)", () => {
|
|
77
|
+
expect(resolveWorkspaceDir({ config: { agents: { defaults: { workspace: 42 } } } })).toBeUndefined();
|
|
78
|
+
expect(resolveWorkspaceDir({ config: { agents: { defaults: { workspace: true } } } })).toBeUndefined();
|
|
79
|
+
expect(resolveWorkspaceDir({ config: { agents: { defaults: { workspace: null } } } })).toBeUndefined();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("trims leading/trailing whitespace from valid paths", () => {
|
|
83
|
+
const api = { config: { agents: { defaults: { workspace: " /home/user/ws " } } } };
|
|
84
|
+
expect(resolveWorkspaceDir(api)).toBe("/home/user/ws");
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe("register", () => {
|
|
89
|
+
it("hooks into before_prompt_build event when enabled", () => {
|
|
90
|
+
const api = {
|
|
91
|
+
config: { plugins: { entries: {} }, agents: { defaults: { workspace: "/ws" } } },
|
|
92
|
+
on: vi.fn(),
|
|
93
|
+
};
|
|
94
|
+
register(api);
|
|
95
|
+
expect(api.on).toHaveBeenCalledWith(
|
|
96
|
+
"before_prompt_build",
|
|
97
|
+
expect.any(Function),
|
|
98
|
+
{ priority: 100 },
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("does not register handler when plugin is explicitly disabled (respects config)", () => {
|
|
103
|
+
const api = {
|
|
104
|
+
config: { plugins: { entries: { "dench-identity": { config: { enabled: false } } } } },
|
|
105
|
+
on: vi.fn(),
|
|
106
|
+
};
|
|
107
|
+
register(api);
|
|
108
|
+
expect(api.on).not.toHaveBeenCalled();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("handler returns system context when workspace is configured", () => {
|
|
112
|
+
const api = {
|
|
113
|
+
config: { plugins: { entries: {} }, agents: { defaults: { workspace: "/ws" } } },
|
|
114
|
+
on: vi.fn(),
|
|
115
|
+
};
|
|
116
|
+
register(api);
|
|
117
|
+
|
|
118
|
+
const handler = api.on.mock.calls[0][1];
|
|
119
|
+
const result = handler({}, {});
|
|
120
|
+
expect(result).toEqual({
|
|
121
|
+
prependSystemContext: expect.stringContaining("DenchClaw"),
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("handler returns undefined when workspace is not configured (prevents empty prompt)", () => {
|
|
126
|
+
const api = {
|
|
127
|
+
config: { plugins: { entries: {} }, agents: { defaults: {} } },
|
|
128
|
+
on: vi.fn(),
|
|
129
|
+
};
|
|
130
|
+
register(api);
|
|
131
|
+
|
|
132
|
+
const handler = api.on.mock.calls[0][1];
|
|
133
|
+
const result = handler({}, {});
|
|
134
|
+
expect(result).toBeUndefined();
|
|
135
|
+
});
|
|
136
|
+
});
|
|
@@ -2,7 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
|
|
3
3
|
export const id = "dench-identity";
|
|
4
4
|
|
|
5
|
-
function buildIdentityPrompt(workspaceDir: string): string {
|
|
5
|
+
export function buildIdentityPrompt(workspaceDir: string): string {
|
|
6
6
|
const skillsDir = path.join(workspaceDir, "skills");
|
|
7
7
|
const crmSkillPath = path.join(skillsDir, "crm", "SKILL.md");
|
|
8
8
|
const browserSkillPath = path.join(skillsDir, "browser", "SKILL.md");
|
|
@@ -94,6 +94,7 @@ For multi-session projects, write a session handoff summary to \`${workspaceDir}
|
|
|
94
94
|
- **Skills**: \`${skillsDir}\` — scan this directory for all available skills; new skills may be installed at any time
|
|
95
95
|
- **Apps**: \`${appsDir}\` — \`.dench.app\` folders with \`.dench.yaml\` manifests
|
|
96
96
|
- **Exec Approvals**: All commands are automatically approved by default. All exec calls must be elevated: true.
|
|
97
|
+
- **Chat History**: All chat history is stored in \`${workspaceDir}/.openclaw/web-chat/\`. This is where you can find all your past conversations and the context for the current session.
|
|
97
98
|
|
|
98
99
|
## Links
|
|
99
100
|
|
|
@@ -102,7 +103,7 @@ For multi-session projects, write a session handoff summary to \`${workspaceDir}
|
|
|
102
103
|
- Skills Store: https://skills.sh`;
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
function resolveWorkspaceDir(api: any): string | undefined {
|
|
106
|
+
export function resolveWorkspaceDir(api: any): string | undefined {
|
|
106
107
|
const ws = api?.config?.agents?.defaults?.workspace;
|
|
107
108
|
return typeof ws === "string" ? ws.trim() || undefined : undefined;
|
|
108
109
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import baseConfig from "../vitest.config.ts";
|
|
2
|
+
import { defineConfig } from "vitest/config";
|
|
3
|
+
|
|
4
|
+
const base = baseConfig as unknown as Record<string, unknown>;
|
|
5
|
+
const baseTest = (baseConfig as { test?: Record<string, unknown> }).test ?? {};
|
|
6
|
+
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
...base,
|
|
9
|
+
test: {
|
|
10
|
+
...baseTest,
|
|
11
|
+
include: ["extensions/**/*.test.ts"],
|
|
12
|
+
},
|
|
13
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "denchclaw",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.3",
|
|
4
4
|
"description": "Fully Managed OpenClaw Framework for managing your CRM, Sales Automation and Outreach agents. The only local productivity tool you need.",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://github.com/DenchHQ/DenchClaw#readme",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@clack/prompts": "^1.0.1",
|
|
65
|
+
"axios": "^1.13.5",
|
|
65
66
|
"chalk": "^5.6.2",
|
|
66
67
|
"commander": "^14.0.3",
|
|
67
68
|
"gradient-string": "^3.0.0",
|
package/skills/crm/SKILL.md
CHANGED
|
@@ -95,6 +95,51 @@ Never rename partially. If you can't complete all steps, don't start the rename
|
|
|
95
95
|
- **DuckDB SQL errors**: See the "Common DuckDB Pitfalls" section in the **duckdb-operations** child skill. The most frequent causes: unquoted field names with spaces (use `"Full Name"` not `Full Name`), wrong transaction syntax (`BEGIN TRANSACTION` not `BEGIN`), unescaped single quotes, and PIVOT views without the `IN (...)` field list.
|
|
96
96
|
- **"Script not found" on action buttons**: The `.actions/` directory and/or script files were not created. See the **actions** child skill post-creation checklist.
|
|
97
97
|
|
|
98
|
+
## Relation Fields — Link Objects Automatically
|
|
99
|
+
|
|
100
|
+
**Every time you create or modify objects, check whether relation fields should connect them. Do NOT wait for the user to ask — proactively link objects that are obviously related.**
|
|
101
|
+
|
|
102
|
+
Relation fields (`type: "relation"`) let an entry in one object reference an entry in another. They render as a searchable dropdown in the UI and are the backbone of any useful CRM.
|
|
103
|
+
|
|
104
|
+
### Mandatory auto-linking rules
|
|
105
|
+
|
|
106
|
+
When you create an object, scan all existing objects (run `SELECT name FROM objects`) and add relation fields for every obvious link:
|
|
107
|
+
|
|
108
|
+
| If you're creating... | And this object exists... | Auto-create this relation field |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| people / contact | company | "Company" on people → company (`many_to_one`) |
|
|
111
|
+
| lead / prospect | company | "Company" on lead → company (`many_to_one`) |
|
|
112
|
+
| deal / opportunity | people | "Primary Contact" on deal → people (`many_to_one`) |
|
|
113
|
+
| deal / opportunity | company | "Company" on deal → company (`many_to_one`) |
|
|
114
|
+
| task | people | "Assigned Contact" on task → people (`many_to_one`) |
|
|
115
|
+
| task | project / deal | "Related To" on task → parent (`many_to_one`) |
|
|
116
|
+
| case | people or company | "Client" on case → people/company (`many_to_one`) |
|
|
117
|
+
| invoice / payment | company | "Company" on invoice → company (`many_to_one`) |
|
|
118
|
+
| invoice / payment | deal | "Deal" on invoice → deal (`many_to_one`) |
|
|
119
|
+
| property / listing | people | "Agent" on property → people (`many_to_one`) |
|
|
120
|
+
| any child concept | its parent concept | relation to parent (`many_to_one`) |
|
|
121
|
+
|
|
122
|
+
**Use this SQL pattern** (safe — does nothing if the target object doesn't exist):
|
|
123
|
+
|
|
124
|
+
```sql
|
|
125
|
+
INSERT INTO fields (object_id, name, type, related_object_id, relationship_type, sort_order)
|
|
126
|
+
SELECT
|
|
127
|
+
(SELECT id FROM objects WHERE name = 'people'),
|
|
128
|
+
'Company',
|
|
129
|
+
'relation',
|
|
130
|
+
(SELECT id FROM objects WHERE name = 'company'),
|
|
131
|
+
'many_to_one',
|
|
132
|
+
3
|
|
133
|
+
WHERE EXISTS (SELECT 1 FROM objects WHERE name = 'company')
|
|
134
|
+
ON CONFLICT (object_id, name) DO NOTHING;
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**General rule**: If you're creating object B and object A already exists, ask: "Would an entry in B logically belong to or reference an entry in A?" If yes, add a `many_to_one` relation. Use `many_to_many` only when an entry can link to multiple entries (e.g. project → team members).
|
|
138
|
+
|
|
139
|
+
Relation fields **must be created via SQL** — the API does not support the `relation` type.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
98
143
|
## Critical Reminders
|
|
99
144
|
|
|
100
145
|
- Handle the ENTIRE CRM operation from analysis to SQL execution to filesystem projection to summary
|
|
@@ -111,7 +156,7 @@ Never rename partially. If you can't complete all steps, don't start the rename
|
|
|
111
156
|
- **ENTRY DOCUMENTS**: New entry detail pages should use human-readable filenames (for example `yt-mikemurphy-001.md`, `jane-smith-001.md`, `acme-corp-001.md`) and MUST be registered in DuckDB `documents` with `file_path`, `parent_object_id`, and `entry_id`. Do NOT default to raw `{entry_id}.md` filenames for new docs. See **documents** child skill.
|
|
112
157
|
- **USER FIELDS**: Resolve member name to ID from `workspace_context.yaml` BEFORE inserting
|
|
113
158
|
- **ENUM FIELDS**: Use type "enum" with `enum_values` JSON array
|
|
114
|
-
- **RELATION FIELDS (PROACTIVE
|
|
159
|
+
- **RELATION FIELDS (PROACTIVE — SEE SECTION ABOVE)**: ALWAYS create relation fields when objects are obviously linked — don't wait for the user to ask. See the **"Relation Fields — Link Objects Automatically"** section above for the full table of mandatory auto-linking rules and the SQL pattern.
|
|
115
160
|
- **TAGS FIELDS**: Use type "tags" for free-form string arrays. Value stored as `'["tag1","tag2"]'`
|
|
116
161
|
- **URL FIELDS**: Use type "url" for website addresses and links
|
|
117
162
|
- **FILE FIELDS**: Use type "file" for file attachments (stores file path or URL)
|
|
File without changes
|
|
File without changes
|
/package/apps/web/.next/static/{nF9C2TCY9WzJYkr3LhlED → yotM7sjmc2mLN7mGVWai0}/_buildManifest.js
RENAMED
|
File without changes
|
/package/apps/web/.next/static/{nF9C2TCY9WzJYkr3LhlED → yotM7sjmc2mLN7mGVWai0}/_ssgManifest.js
RENAMED
|
File without changes
|