@clawstore/clawstore 1.0.2 → 1.0.7

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.
Files changed (47) hide show
  1. package/dist/src/cli.d.ts.map +1 -1
  2. package/dist/src/cli.js +11 -1
  3. package/dist/src/cli.js.map +1 -1
  4. package/dist/src/commands.d.ts.map +1 -1
  5. package/dist/src/commands.js +8 -1
  6. package/dist/src/commands.js.map +1 -1
  7. package/dist/src/core/agent-register.d.ts +6 -0
  8. package/dist/src/core/agent-register.d.ts.map +1 -0
  9. package/dist/src/core/agent-register.js +48 -0
  10. package/dist/src/core/agent-register.js.map +1 -0
  11. package/dist/src/core/api-health.d.ts +9 -0
  12. package/dist/src/core/api-health.d.ts.map +1 -0
  13. package/dist/src/core/api-health.js +17 -0
  14. package/dist/src/core/api-health.js.map +1 -0
  15. package/dist/src/core/diagnostics.d.ts +7 -0
  16. package/dist/src/core/diagnostics.d.ts.map +1 -0
  17. package/dist/src/core/diagnostics.js +145 -0
  18. package/dist/src/core/diagnostics.js.map +1 -0
  19. package/dist/src/core/openclaw-profile.d.ts +6 -0
  20. package/dist/src/core/openclaw-profile.d.ts.map +1 -0
  21. package/dist/src/core/openclaw-profile.js +12 -0
  22. package/dist/src/core/openclaw-profile.js.map +1 -0
  23. package/dist/src/core/workspace.d.ts +0 -9
  24. package/dist/src/core/workspace.d.ts.map +1 -1
  25. package/dist/src/core/workspace.js +7 -154
  26. package/dist/src/core/workspace.js.map +1 -1
  27. package/openclaw.plugin.json +1 -1
  28. package/package.json +18 -3
  29. package/src/cli.ts +12 -1
  30. package/src/commands.ts +9 -1
  31. package/src/core/agent-register.ts +57 -0
  32. package/src/core/api-health.ts +17 -0
  33. package/src/core/diagnostics.ts +163 -0
  34. package/src/core/openclaw-profile.ts +10 -0
  35. package/src/core/workspace.ts +7 -168
  36. package/clawstore-clawstore-1.0.2.tgz +0 -0
  37. package/dist/src/__tests__/cli-sim.test.d.ts +0 -9
  38. package/dist/src/__tests__/cli-sim.test.d.ts.map +0 -1
  39. package/dist/src/__tests__/cli-sim.test.js +0 -275
  40. package/dist/src/__tests__/cli-sim.test.js.map +0 -1
  41. package/dist/src/__tests__/e2e.test.d.ts +0 -10
  42. package/dist/src/__tests__/e2e.test.d.ts.map +0 -1
  43. package/dist/src/__tests__/e2e.test.js +0 -159
  44. package/dist/src/__tests__/e2e.test.js.map +0 -1
  45. package/src/__tests__/cli-sim.test.ts +0 -303
  46. package/src/__tests__/e2e.test.ts +0 -186
  47. package/tsconfig.json +0 -23
@@ -1,7 +1,8 @@
1
1
  import { readFile, access, readdir } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { homedir } from "node:os";
4
- import { OPENCLAW_HOME, CLAWSTORE_DIR, DEFAULT_AGENT, REQUIRED_FILES, OPTIONAL_FILES, agentRegistryFile, agentBackupDir, } from "../constants.js";
4
+ import { OPENCLAW_HOME, CLAWSTORE_DIR, DEFAULT_AGENT, agentRegistryFile, } from "../constants.js";
5
+ import { readOpenclawProfileLabel } from "./openclaw-profile.js";
5
6
  /**
6
7
  * Resolve the workspace directory for a given OpenClaw agent.
7
8
  *
@@ -26,6 +27,10 @@ export async function resolveWorkspace(agent) {
26
27
  workspace =
27
28
  config?.agents?.[target]?.workspace ??
28
29
  config?.agents?.entries?.[target]?.workspace;
30
+ if (!workspace && Array.isArray(config?.agents?.list)) {
31
+ const entry = config.agents.list.find((e) => e?.id === target);
32
+ workspace = entry?.workspace;
33
+ }
29
34
  }
30
35
  else {
31
36
  workspace =
@@ -40,7 +45,7 @@ export async function resolveWorkspace(agent) {
40
45
  // config not found or invalid — fall through
41
46
  }
42
47
  if (target === DEFAULT_AGENT) {
43
- const profile = process.env.OPENCLAW_PROFILE ?? "default";
48
+ const profile = readOpenclawProfileLabel();
44
49
  if (profile !== "default") {
45
50
  return join(OPENCLAW_HOME, `workspace-${profile}`);
46
51
  }
@@ -62,11 +67,9 @@ function expandHome(p) {
62
67
  */
63
68
  export async function listClawstoreAgents() {
64
69
  const agents = [];
65
- // "main" agent uses the root-level registry file
66
70
  if (await exists(agentRegistryFile(DEFAULT_AGENT))) {
67
71
  agents.push(DEFAULT_AGENT);
68
72
  }
69
- // Non-main agents live under clawstore/agents/<name>/
70
73
  const agentsDir = join(CLAWSTORE_DIR, "agents");
71
74
  if (await exists(agentsDir)) {
72
75
  const entries = await readdir(agentsDir, { withFileTypes: true });
@@ -89,154 +92,4 @@ async function exists(p) {
89
92
  return false;
90
93
  }
91
94
  }
92
- async function dirItemCount(p) {
93
- try {
94
- const entries = await readdir(p);
95
- return entries.length;
96
- }
97
- catch {
98
- return -1;
99
- }
100
- }
101
- /**
102
- * Run a full diagnostic for a specific OpenClaw agent.
103
- */
104
- export async function diagnose(apiBaseUrl, agent) {
105
- const target = agent ?? DEFAULT_AGENT;
106
- const checks = [];
107
- let allOk = true;
108
- const workspace = await resolveWorkspace(target);
109
- const registryFile = agentRegistryFile(target);
110
- const backupDir = agentBackupDir(target);
111
- if (target !== DEFAULT_AGENT) {
112
- checks.push({
113
- label: "Target agent",
114
- status: "ok",
115
- detail: target,
116
- });
117
- }
118
- // 1. OpenClaw home
119
- const homeOk = await exists(OPENCLAW_HOME);
120
- checks.push({
121
- label: "OpenClaw home",
122
- path: OPENCLAW_HOME,
123
- status: homeOk ? "ok" : "fail",
124
- detail: homeOk ? undefined : "NOT FOUND",
125
- });
126
- if (!homeOk)
127
- allOk = false;
128
- // 2. Workspace
129
- const wsOk = await exists(workspace);
130
- checks.push({
131
- label: "Workspace",
132
- path: workspace,
133
- status: wsOk ? "ok" : "fail",
134
- detail: wsOk ? undefined : "NOT FOUND",
135
- });
136
- if (!wsOk)
137
- allOk = false;
138
- // 3. Workspace files
139
- for (const f of [...REQUIRED_FILES, ...OPTIONAL_FILES]) {
140
- const fp = join(workspace, f);
141
- const found = await exists(fp);
142
- checks.push({
143
- label: `Workspace file: ${f}`,
144
- path: fp,
145
- status: found ? "ok" : "warn",
146
- detail: found ? "found" : "missing",
147
- });
148
- }
149
- // 4. Registry
150
- const regOk = await exists(registryFile);
151
- if (regOk) {
152
- try {
153
- const raw = await readFile(registryFile, "utf-8");
154
- const reg = JSON.parse(raw);
155
- const count = Object.keys(reg.agents ?? {}).length;
156
- checks.push({
157
- label: "Agent registry",
158
- path: registryFile,
159
- status: "ok",
160
- detail: `${count} agent(s) registered`,
161
- });
162
- }
163
- catch {
164
- checks.push({
165
- label: "Agent registry",
166
- path: registryFile,
167
- status: "warn",
168
- detail: "exists but cannot be parsed",
169
- });
170
- }
171
- }
172
- else {
173
- checks.push({
174
- label: "Agent registry",
175
- path: registryFile,
176
- status: "ok",
177
- detail: "not created yet (OK for first run)",
178
- });
179
- }
180
- // 5. Skills directory
181
- const skillsDir = join(workspace, "skills");
182
- const skillCount = await dirItemCount(skillsDir);
183
- checks.push({
184
- label: "Skills directory",
185
- path: skillsDir,
186
- status: skillCount >= 0 ? "ok" : "warn",
187
- detail: skillCount >= 0 ? `${skillCount} skill(s)` : "NOT FOUND",
188
- });
189
- // 6. Backup directory
190
- const backupCount = await dirItemCount(backupDir);
191
- checks.push({
192
- label: "Backup directory",
193
- path: backupDir,
194
- status: "ok",
195
- detail: backupCount >= 0 ? `${backupCount} backup(s)` : "will be created on first install",
196
- });
197
- // 7. Cache directory
198
- const cacheCount = await dirItemCount(join(CLAWSTORE_DIR, "cache"));
199
- checks.push({
200
- label: "Cache directory",
201
- path: join(CLAWSTORE_DIR, "cache"),
202
- status: "ok",
203
- detail: cacheCount >= 0 ? `${cacheCount} item(s)` : "will be created on first install",
204
- });
205
- // 8. API connectivity (optional)
206
- if (apiBaseUrl) {
207
- try {
208
- const res = await fetch(`${apiBaseUrl}/health`, { signal: AbortSignal.timeout(5000) });
209
- checks.push({
210
- label: "Clawstore API",
211
- status: res.ok ? "ok" : "warn",
212
- detail: res.ok ? "reachable" : `HTTP ${res.status}`,
213
- });
214
- }
215
- catch (err) {
216
- checks.push({
217
- label: "Clawstore API",
218
- status: "warn",
219
- detail: `unreachable (${err.message})`,
220
- });
221
- }
222
- }
223
- return { checks, allOk };
224
- }
225
- /**
226
- * Format a diagnostic report for CLI output.
227
- */
228
- export function formatDiagnosticReport(report) {
229
- const lines = ["\n Clawstore Doctor\n"];
230
- for (const c of report.checks) {
231
- const icon = c.status === "ok" ? "OK" : c.status === "warn" ? "WARN" : "FAIL";
232
- const pathPart = c.path ? ` ${c.path}` : "";
233
- const detailPart = c.detail ? ` (${c.detail})` : "";
234
- lines.push(` ${c.label}:${pathPart} ... ${icon}${detailPart}`);
235
- }
236
- lines.push("");
237
- lines.push(report.allOk
238
- ? " All checks passed.\n"
239
- : " Some issues found. Run `openclaw setup` to initialize missing directories.\n");
240
- return lines.join("\n");
241
- }
242
95
  //# sourceMappingURL=workspace.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../src/core/workspace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../src/core/workspace.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "clawstore",
3
3
  "name": "Clawstore",
4
- "version": "1.0.0",
4
+ "version": "1.0.7",
5
5
  "description": "Agent marketplace plugin for OpenClaw — browse, install, manage and pack AI employee agents.",
6
6
  "configSchema": {
7
7
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawstore/clawstore",
3
- "version": "1.0.2",
3
+ "version": "1.0.7",
4
4
  "description": "Agent marketplace plugin for OpenClaw — browse, install, manage and pack AI employee agents.",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -15,7 +15,10 @@
15
15
  },
16
16
  "scripts": {
17
17
  "build": "tsc",
18
- "test": "node --import tsx src/__tests__/e2e.test.ts"
18
+ "test": "node --import tsx src/__tests__/e2e.test.ts",
19
+ "clean": "node -e \"try{require('fs').rmSync('dist',{recursive:true,force:true})}catch(e){if(e.code!=='ENOENT')throw e}\"",
20
+ "prepack": "npm run clean && npm run build",
21
+ "pack:release": "npm pack --pack-destination ../../dist"
19
22
  },
20
23
  "dependencies": {
21
24
  "adm-zip": "^0.5.16",
@@ -28,5 +31,17 @@
28
31
  "typescript": "^5.5.0",
29
32
  "tsx": "^4.19.0"
30
33
  },
31
- "license": "MIT"
34
+ "license": "MIT",
35
+ "files": [
36
+ "index.ts",
37
+ "openclaw.plugin.json",
38
+ "src/cli.ts",
39
+ "src/commands.ts",
40
+ "src/constants.ts",
41
+ "src/types.ts",
42
+ "src/core/*.ts",
43
+ "src/utils/*.ts",
44
+ "dist",
45
+ "typings"
46
+ ]
32
47
  }
package/src/cli.ts CHANGED
@@ -17,7 +17,9 @@ import {
17
17
 
18
18
  import { installAgent, updateAgent } from "./core/package-installer.js";
19
19
  import { packAgent, packCurrentAgent } from "./core/packager.js";
20
- import { diagnose, formatDiagnosticReport, listClawstoreAgents } from "./core/workspace.js";
20
+ import { listClawstoreAgents } from "./core/workspace.js";
21
+ import { diagnose, formatDiagnosticReport } from "./core/diagnostics.js";
22
+ import { ensureAgentRegistered } from "./core/agent-register.js";
21
23
  import { StoreClient } from "./core/store-client.js";
22
24
  import { DEFAULT_API_BASE_URL, DEFAULT_AGENT, STORE_DOWNLOAD_BASE_URL } from "./constants.js";
23
25
  import {
@@ -179,6 +181,15 @@ export function registerClawstoreCli(api: OpenClawPluginApi): void {
179
181
  }
180
182
  }
181
183
 
184
+ if (agent !== DEFAULT_AGENT) {
185
+ const ok = await ensureAgentRegistered(agent, console.log);
186
+ if (!ok) {
187
+ console.log(`\n Cannot proceed: agent "${agent}" could not be registered.`);
188
+ console.log(` Register it manually first: openclaw agents add ${agent} --workspace <path>\n`);
189
+ return;
190
+ }
191
+ }
192
+
182
193
  await installAgent({
183
194
  packagePath,
184
195
  force: opts.force === true,
package/src/commands.ts CHANGED
@@ -9,7 +9,8 @@ import {
9
9
  disableAgent,
10
10
  } from "./core/agent-manager.js";
11
11
  import { installAgent } from "./core/package-installer.js";
12
- import { diagnose } from "./core/workspace.js";
12
+ import { diagnose } from "./core/diagnostics.js";
13
+ import { ensureAgentRegistered } from "./core/agent-register.js";
13
14
 
14
15
  /**
15
16
  * Register the `/clawstore` slash command.
@@ -102,6 +103,13 @@ export function registerClawstoreCommand(api: OpenClawPluginApi): void {
102
103
  }
103
104
  }
104
105
 
106
+ if (agent !== DEFAULT_AGENT) {
107
+ const ok = await ensureAgentRegistered(agent, (msg) => lines.push(msg));
108
+ if (!ok) {
109
+ return { text: `Agent "${agent}" is not registered and auto-registration failed.\nRun: \`openclaw agents add ${agent} --workspace <path>\`` };
110
+ }
111
+ }
112
+
105
113
  const result = await installAgent({
106
114
  packagePath,
107
115
  agent,
@@ -0,0 +1,57 @@
1
+ import { exec } from "node:child_process";
2
+ import { readFile, mkdir } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { OPENCLAW_HOME, DEFAULT_AGENT } from "../constants.js";
5
+
6
+ /**
7
+ * If the agent is missing from openclaw.json, run `openclaw agents add`.
8
+ * Lives in a dedicated module (child_process) away from workspace resolution.
9
+ */
10
+ export async function ensureAgentRegistered(
11
+ agent: string,
12
+ log: (msg: string) => void = console.log,
13
+ ): Promise<boolean> {
14
+ if (agent === DEFAULT_AGENT) return true;
15
+
16
+ const configFile = join(OPENCLAW_HOME, "openclaw.json");
17
+ try {
18
+ const raw = await readFile(configFile, "utf-8");
19
+ const config = JSON.parse(raw);
20
+
21
+ const inMap =
22
+ config?.agents?.[agent] !== undefined ||
23
+ config?.agents?.entries?.[agent] !== undefined;
24
+ const inList = Array.isArray(config?.agents?.list) &&
25
+ config.agents.list.some((e: { id?: string }) => e?.id === agent);
26
+
27
+ if (inMap || inList) return true;
28
+ } catch {
29
+ // config missing or unreadable — agent is definitely not registered
30
+ }
31
+
32
+ const workspace = join(OPENCLAW_HOME, `workspace-${agent}`);
33
+ try {
34
+ await mkdir(workspace, { recursive: true });
35
+ } catch { /* directory may already exist */ }
36
+
37
+ log(`\n OpenClaw agent "${agent}" is not registered. Auto-registering ...`);
38
+
39
+ const cmd = `openclaw agents add ${agent} --workspace "${workspace}"`;
40
+ return new Promise<boolean>((resolve) => {
41
+ exec(
42
+ cmd,
43
+ { timeout: 15_000 },
44
+ (err, stdout, stderr) => {
45
+ if (err) {
46
+ log(` Auto-register failed: ${err.message}`);
47
+ if (stderr) log(` ${stderr.trim()}`);
48
+ log(` Please run manually: ${cmd}\n`);
49
+ resolve(false);
50
+ return;
51
+ }
52
+ log(` Registered agent "${agent}" → ${workspace}`);
53
+ resolve(true);
54
+ },
55
+ );
56
+ });
57
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Clawstore API GET /health — used only by clawstore doctor.
3
+ * Standalone module (no process/env reads) for OpenClaw plugin static analysis.
4
+ */
5
+ export async function checkClawstoreApiReachable(apiBaseUrl: string): Promise<{
6
+ ok: boolean;
7
+ detail: string;
8
+ }> {
9
+ const base = apiBaseUrl.replace(/\/+$/, "");
10
+ try {
11
+ const res = await fetch(`${base}/health`, { signal: AbortSignal.timeout(5000) });
12
+ if (res.ok) return { ok: true, detail: "reachable" };
13
+ return { ok: false, detail: `HTTP ${res.status}` };
14
+ } catch (err) {
15
+ return { ok: false, detail: `unreachable (${(err as Error).message})` };
16
+ }
17
+ }
@@ -0,0 +1,163 @@
1
+ import { readFile, access, readdir } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import {
4
+ OPENCLAW_HOME,
5
+ CLAWSTORE_DIR,
6
+ DEFAULT_AGENT,
7
+ REQUIRED_FILES,
8
+ OPTIONAL_FILES,
9
+ agentRegistryFile,
10
+ agentBackupDir,
11
+ } from "../constants.js";
12
+ import type { DiagnosticCheck, DiagnosticReport } from "../types.js";
13
+ import { resolveWorkspace } from "./workspace.js";
14
+ import { checkClawstoreApiReachable } from "./api-health.js";
15
+
16
+ async function pathExists(p: string): Promise<boolean> {
17
+ try {
18
+ await access(p);
19
+ return true;
20
+ } catch {
21
+ return false;
22
+ }
23
+ }
24
+
25
+ async function dirItemCount(p: string): Promise<number> {
26
+ try {
27
+ const entries = await readdir(p);
28
+ return entries.length;
29
+ } catch {
30
+ return -1;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Run a full diagnostic for a specific OpenClaw agent.
36
+ */
37
+ export async function diagnose(apiBaseUrl?: string, agent?: string): Promise<DiagnosticReport> {
38
+ const target = agent ?? DEFAULT_AGENT;
39
+ const checks: DiagnosticCheck[] = [];
40
+ let allOk = true;
41
+ const workspace = await resolveWorkspace(target);
42
+ const registryFile = agentRegistryFile(target);
43
+ const backupDir = agentBackupDir(target);
44
+
45
+ if (target !== DEFAULT_AGENT) {
46
+ checks.push({
47
+ label: "Target agent",
48
+ status: "ok",
49
+ detail: target,
50
+ });
51
+ }
52
+
53
+ const homeOk = await pathExists(OPENCLAW_HOME);
54
+ checks.push({
55
+ label: "OpenClaw home",
56
+ path: OPENCLAW_HOME,
57
+ status: homeOk ? "ok" : "fail",
58
+ detail: homeOk ? undefined : "NOT FOUND",
59
+ });
60
+ if (!homeOk) allOk = false;
61
+
62
+ const wsOk = await pathExists(workspace);
63
+ checks.push({
64
+ label: "Workspace",
65
+ path: workspace,
66
+ status: wsOk ? "ok" : "fail",
67
+ detail: wsOk ? undefined : "NOT FOUND",
68
+ });
69
+ if (!wsOk) allOk = false;
70
+
71
+ for (const f of [...REQUIRED_FILES, ...OPTIONAL_FILES]) {
72
+ const fp = join(workspace, f);
73
+ const found = await pathExists(fp);
74
+ checks.push({
75
+ label: `Workspace file: ${f}`,
76
+ path: fp,
77
+ status: found ? "ok" : "warn",
78
+ detail: found ? "found" : "missing",
79
+ });
80
+ }
81
+
82
+ const regOk = await pathExists(registryFile);
83
+ if (regOk) {
84
+ try {
85
+ const raw = await readFile(registryFile, "utf-8");
86
+ const reg = JSON.parse(raw);
87
+ const count = Object.keys(reg.agents ?? {}).length;
88
+ checks.push({
89
+ label: "Agent registry",
90
+ path: registryFile,
91
+ status: "ok",
92
+ detail: `${count} agent(s) registered`,
93
+ });
94
+ } catch {
95
+ checks.push({
96
+ label: "Agent registry",
97
+ path: registryFile,
98
+ status: "warn",
99
+ detail: "exists but cannot be parsed",
100
+ });
101
+ }
102
+ } else {
103
+ checks.push({
104
+ label: "Agent registry",
105
+ path: registryFile,
106
+ status: "ok",
107
+ detail: "not created yet (OK for first run)",
108
+ });
109
+ }
110
+
111
+ const skillsDir = join(workspace, "skills");
112
+ const skillCount = await dirItemCount(skillsDir);
113
+ checks.push({
114
+ label: "Skills directory",
115
+ path: skillsDir,
116
+ status: skillCount >= 0 ? "ok" : "warn",
117
+ detail: skillCount >= 0 ? `${skillCount} skill(s)` : "NOT FOUND",
118
+ });
119
+
120
+ const backupCount = await dirItemCount(backupDir);
121
+ checks.push({
122
+ label: "Backup directory",
123
+ path: backupDir,
124
+ status: "ok",
125
+ detail: backupCount >= 0 ? `${backupCount} backup(s)` : "will be created on first install",
126
+ });
127
+
128
+ const cacheCount = await dirItemCount(join(CLAWSTORE_DIR, "cache"));
129
+ checks.push({
130
+ label: "Cache directory",
131
+ path: join(CLAWSTORE_DIR, "cache"),
132
+ status: "ok",
133
+ detail: cacheCount >= 0 ? `${cacheCount} item(s)` : "will be created on first install",
134
+ });
135
+
136
+ if (apiBaseUrl) {
137
+ const { ok, detail } = await checkClawstoreApiReachable(apiBaseUrl);
138
+ checks.push({
139
+ label: "Clawstore API",
140
+ status: ok ? "ok" : "warn",
141
+ detail,
142
+ });
143
+ }
144
+
145
+ return { checks, allOk };
146
+ }
147
+
148
+ export function formatDiagnosticReport(report: DiagnosticReport): string {
149
+ const lines: string[] = ["\n Clawstore Doctor\n"];
150
+ for (const c of report.checks) {
151
+ const icon = c.status === "ok" ? "OK" : c.status === "warn" ? "WARN" : "FAIL";
152
+ const pathPart = c.path ? ` ${c.path}` : "";
153
+ const detailPart = c.detail ? ` (${c.detail})` : "";
154
+ lines.push(` ${c.label}:${pathPart} ... ${icon}${detailPart}`);
155
+ }
156
+ lines.push("");
157
+ lines.push(
158
+ report.allOk
159
+ ? " All checks passed.\n"
160
+ : " Some issues found. Run `openclaw setup` to initialize missing directories.\n"
161
+ );
162
+ return lines.join("\n");
163
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Reads OPENCLAW_PROFILE for main-agent workspace path resolution.
3
+ * Isolated from modules that perform HTTP or shell execution (OpenClaw plugin scanner).
4
+ */
5
+ export function readOpenclawProfileLabel(): string {
6
+ const proc = (globalThis as { process?: { env?: NodeJS.ProcessEnv } }).process;
7
+ const raw = proc?.env?.OPENCLAW_PROFILE;
8
+ if (typeof raw === "string" && raw.trim() !== "") return raw.trim();
9
+ return "default";
10
+ }