denchclaw 2.4.1 → 2.4.2
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 +93 -93
- package/apps/web/.next/standalone/apps/web/.next/app-path-routes-manifest.json +24 -24
- 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 +24 -24
- 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 +8 -8
- package/apps/web/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
- package/apps/web/.next/standalone/apps/web/.next/server/pages-manifest.json +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-63a50b5e299be036.js} +1 -1
- package/apps/web/.next/{static/chunks/app/page-6a172dc187a2f128.js → standalone/apps/web/.next/static/chunks/app/page-95ba68825db8821d.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-63a50b5e299be036.js} +1 -1
- package/apps/web/.next/{standalone/apps/web/.next/static/chunks/app/page-6a172dc187a2f128.js → static/chunks/app/page-95ba68825db8821d.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 → TdAnmJDH-qLpIRoeLSxFc}/_buildManifest.js +0 -0
- /package/apps/web/.next/standalone/apps/web/.next/static/{nF9C2TCY9WzJYkr3LhlED → TdAnmJDH-qLpIRoeLSxFc}/_ssgManifest.js +0 -0
- /package/apps/web/.next/static/{nF9C2TCY9WzJYkr3LhlED → TdAnmJDH-qLpIRoeLSxFc}/_buildManifest.js +0 -0
- /package/apps/web/.next/static/{nF9C2TCY9WzJYkr3LhlED → TdAnmJDH-qLpIRoeLSxFc}/_ssgManifest.js +0 -0
|
@@ -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.2",
|
|
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 → TdAnmJDH-qLpIRoeLSxFc}/_buildManifest.js
RENAMED
|
File without changes
|
/package/apps/web/.next/static/{nF9C2TCY9WzJYkr3LhlED → TdAnmJDH-qLpIRoeLSxFc}/_ssgManifest.js
RENAMED
|
File without changes
|