@next-open-ai/openclawx 0.6.6

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 (198) hide show
  1. package/README.md +523 -0
  2. package/apps/desktop/README.md +210 -0
  3. package/apps/desktop/renderer/dist/assets/index-CYkSfhcp.css +10 -0
  4. package/apps/desktop/renderer/dist/assets/index-FI6O25Ms.js +89 -0
  5. package/apps/desktop/renderer/dist/index.html +22 -0
  6. package/dist/cli/cli.d.ts +2 -0
  7. package/dist/cli/cli.js +198 -0
  8. package/dist/cli/service.d.ts +13 -0
  9. package/dist/cli/service.js +243 -0
  10. package/dist/cli.d.ts +5 -0
  11. package/dist/cli.js +5 -0
  12. package/dist/core/agent/agent-dir.d.ts +14 -0
  13. package/dist/core/agent/agent-dir.js +75 -0
  14. package/dist/core/agent/agent-manager.d.ts +64 -0
  15. package/dist/core/agent/agent-manager.js +278 -0
  16. package/dist/core/agent/config-manager.d.ts +25 -0
  17. package/dist/core/agent/config-manager.js +84 -0
  18. package/dist/core/agent/run.d.ts +26 -0
  19. package/dist/core/agent/run.js +65 -0
  20. package/dist/core/agent/skills.d.ts +20 -0
  21. package/dist/core/agent/skills.js +86 -0
  22. package/dist/core/config/desktop-config.d.ts +90 -0
  23. package/dist/core/config/desktop-config.js +521 -0
  24. package/dist/core/config/provider-support-default.d.ts +21 -0
  25. package/dist/core/config/provider-support-default.js +57 -0
  26. package/dist/core/installer/index.d.ts +1 -0
  27. package/dist/core/installer/index.js +1 -0
  28. package/dist/core/installer/skill-installer.d.ts +39 -0
  29. package/dist/core/installer/skill-installer.js +215 -0
  30. package/dist/core/mcp/adapter.d.ts +17 -0
  31. package/dist/core/mcp/adapter.js +49 -0
  32. package/dist/core/mcp/client.d.ts +24 -0
  33. package/dist/core/mcp/client.js +70 -0
  34. package/dist/core/mcp/config.d.ts +22 -0
  35. package/dist/core/mcp/config.js +69 -0
  36. package/dist/core/mcp/index.d.ts +18 -0
  37. package/dist/core/mcp/index.js +20 -0
  38. package/dist/core/mcp/operator.d.ts +15 -0
  39. package/dist/core/mcp/operator.js +72 -0
  40. package/dist/core/mcp/transport/index.d.ts +11 -0
  41. package/dist/core/mcp/transport/index.js +16 -0
  42. package/dist/core/mcp/transport/sse.d.ts +20 -0
  43. package/dist/core/mcp/transport/sse.js +82 -0
  44. package/dist/core/mcp/transport/stdio.d.ts +32 -0
  45. package/dist/core/mcp/transport/stdio.js +132 -0
  46. package/dist/core/mcp/types.d.ts +72 -0
  47. package/dist/core/mcp/types.js +5 -0
  48. package/dist/core/memory/build-summary.d.ts +6 -0
  49. package/dist/core/memory/build-summary.js +27 -0
  50. package/dist/core/memory/compaction-extension.d.ts +6 -0
  51. package/dist/core/memory/compaction-extension.js +23 -0
  52. package/dist/core/memory/embedding.d.ts +4 -0
  53. package/dist/core/memory/embedding.js +15 -0
  54. package/dist/core/memory/index.d.ts +29 -0
  55. package/dist/core/memory/index.js +70 -0
  56. package/dist/core/memory/remote-embedding.d.ts +10 -0
  57. package/dist/core/memory/remote-embedding.js +36 -0
  58. package/dist/core/memory/types.d.ts +16 -0
  59. package/dist/core/memory/types.js +1 -0
  60. package/dist/core/memory/vector-store.d.ts +15 -0
  61. package/dist/core/memory/vector-store.js +65 -0
  62. package/dist/core/tools/bookmark-tool.d.ts +9 -0
  63. package/dist/core/tools/bookmark-tool.js +118 -0
  64. package/dist/core/tools/browser-tool.d.ts +10 -0
  65. package/dist/core/tools/browser-tool.js +362 -0
  66. package/dist/core/tools/index.d.ts +4 -0
  67. package/dist/core/tools/index.js +4 -0
  68. package/dist/core/tools/install-skill-tool.d.ts +6 -0
  69. package/dist/core/tools/install-skill-tool.js +53 -0
  70. package/dist/core/tools/save-experience-tool.d.ts +5 -0
  71. package/dist/core/tools/save-experience-tool.js +54 -0
  72. package/dist/gateway/auth-hooks.d.ts +17 -0
  73. package/dist/gateway/auth-hooks.js +19 -0
  74. package/dist/gateway/backend-url.d.ts +2 -0
  75. package/dist/gateway/backend-url.js +11 -0
  76. package/dist/gateway/channel-handler.d.ts +6 -0
  77. package/dist/gateway/channel-handler.js +3 -0
  78. package/dist/gateway/clients.d.ts +5 -0
  79. package/dist/gateway/clients.js +4 -0
  80. package/dist/gateway/connection-handler.d.ts +6 -0
  81. package/dist/gateway/connection-handler.js +48 -0
  82. package/dist/gateway/index.d.ts +3 -0
  83. package/dist/gateway/index.js +2 -0
  84. package/dist/gateway/message-handler.d.ts +5 -0
  85. package/dist/gateway/message-handler.js +65 -0
  86. package/dist/gateway/methods/agent-cancel.d.ts +10 -0
  87. package/dist/gateway/methods/agent-cancel.js +17 -0
  88. package/dist/gateway/methods/agent-chat.d.ts +8 -0
  89. package/dist/gateway/methods/agent-chat.js +148 -0
  90. package/dist/gateway/methods/connect.d.ts +9 -0
  91. package/dist/gateway/methods/connect.js +18 -0
  92. package/dist/gateway/methods/install-skill-from-path.d.ts +13 -0
  93. package/dist/gateway/methods/install-skill-from-path.js +15 -0
  94. package/dist/gateway/methods/install-skill-from-upload.d.ts +14 -0
  95. package/dist/gateway/methods/install-skill-from-upload.js +13 -0
  96. package/dist/gateway/methods/run-scheduled-task.d.ts +15 -0
  97. package/dist/gateway/methods/run-scheduled-task.js +127 -0
  98. package/dist/gateway/paths.d.ts +20 -0
  99. package/dist/gateway/paths.js +19 -0
  100. package/dist/gateway/server.d.ts +8 -0
  101. package/dist/gateway/server.js +190 -0
  102. package/dist/gateway/sse-handler.d.ts +6 -0
  103. package/dist/gateway/sse-handler.js +3 -0
  104. package/dist/gateway/types.d.ts +90 -0
  105. package/dist/gateway/types.js +1 -0
  106. package/dist/gateway/utils.d.ts +22 -0
  107. package/dist/gateway/utils.js +67 -0
  108. package/dist/gateway/voice-handler.d.ts +12 -0
  109. package/dist/gateway/voice-handler.js +18 -0
  110. package/dist/index.d.ts +5 -0
  111. package/dist/index.js +5 -0
  112. package/dist/server/agent-config/agent-config.controller.d.ts +30 -0
  113. package/dist/server/agent-config/agent-config.controller.js +83 -0
  114. package/dist/server/agent-config/agent-config.module.d.ts +2 -0
  115. package/dist/server/agent-config/agent-config.module.js +19 -0
  116. package/dist/server/agent-config/agent-config.service.d.ts +53 -0
  117. package/dist/server/agent-config/agent-config.service.js +213 -0
  118. package/dist/server/agents/agents.controller.d.ts +41 -0
  119. package/dist/server/agents/agents.controller.js +118 -0
  120. package/dist/server/agents/agents.gateway.d.ts +21 -0
  121. package/dist/server/agents/agents.gateway.js +103 -0
  122. package/dist/server/agents/agents.module.d.ts +2 -0
  123. package/dist/server/agents/agents.module.js +20 -0
  124. package/dist/server/agents/agents.service.d.ts +63 -0
  125. package/dist/server/agents/agents.service.js +169 -0
  126. package/dist/server/app.module.d.ts +2 -0
  127. package/dist/server/app.module.js +38 -0
  128. package/dist/server/auth/auth.controller.d.ts +20 -0
  129. package/dist/server/auth/auth.controller.js +64 -0
  130. package/dist/server/auth/auth.module.d.ts +2 -0
  131. package/dist/server/auth/auth.module.js +19 -0
  132. package/dist/server/bootstrap.d.ts +15 -0
  133. package/dist/server/bootstrap.js +38 -0
  134. package/dist/server/config/config.controller.d.ts +73 -0
  135. package/dist/server/config/config.controller.js +95 -0
  136. package/dist/server/config/config.module.d.ts +2 -0
  137. package/dist/server/config/config.module.js +21 -0
  138. package/dist/server/config/config.service.d.ts +82 -0
  139. package/dist/server/config/config.service.js +123 -0
  140. package/dist/server/database/database.module.d.ts +2 -0
  141. package/dist/server/database/database.module.js +18 -0
  142. package/dist/server/database/database.service.d.ts +26 -0
  143. package/dist/server/database/database.service.js +253 -0
  144. package/dist/server/main.d.ts +1 -0
  145. package/dist/server/main.js +9 -0
  146. package/dist/server/saved-items/saved-items.controller.d.ts +57 -0
  147. package/dist/server/saved-items/saved-items.controller.js +229 -0
  148. package/dist/server/saved-items/saved-items.module.d.ts +2 -0
  149. package/dist/server/saved-items/saved-items.module.js +25 -0
  150. package/dist/server/saved-items/saved-items.service.d.ts +31 -0
  151. package/dist/server/saved-items/saved-items.service.js +105 -0
  152. package/dist/server/saved-items/tags.controller.d.ts +30 -0
  153. package/dist/server/saved-items/tags.controller.js +85 -0
  154. package/dist/server/saved-items/tags.service.d.ts +24 -0
  155. package/dist/server/saved-items/tags.service.js +84 -0
  156. package/dist/server/skills/skills.controller.d.ts +63 -0
  157. package/dist/server/skills/skills.controller.js +194 -0
  158. package/dist/server/skills/skills.module.d.ts +2 -0
  159. package/dist/server/skills/skills.module.js +22 -0
  160. package/dist/server/skills/skills.service.d.ts +65 -0
  161. package/dist/server/skills/skills.service.js +388 -0
  162. package/dist/server/tasks/tasks.controller.d.ts +52 -0
  163. package/dist/server/tasks/tasks.controller.js +163 -0
  164. package/dist/server/tasks/tasks.module.d.ts +2 -0
  165. package/dist/server/tasks/tasks.module.js +23 -0
  166. package/dist/server/tasks/tasks.service.d.ts +86 -0
  167. package/dist/server/tasks/tasks.service.js +327 -0
  168. package/dist/server/usage/usage.controller.d.ts +12 -0
  169. package/dist/server/usage/usage.controller.js +46 -0
  170. package/dist/server/usage/usage.module.d.ts +2 -0
  171. package/dist/server/usage/usage.module.js +19 -0
  172. package/dist/server/usage/usage.service.d.ts +21 -0
  173. package/dist/server/usage/usage.service.js +55 -0
  174. package/dist/server/users/users.controller.d.ts +35 -0
  175. package/dist/server/users/users.controller.js +69 -0
  176. package/dist/server/users/users.module.d.ts +2 -0
  177. package/dist/server/users/users.module.js +19 -0
  178. package/dist/server/users/users.service.d.ts +39 -0
  179. package/dist/server/users/users.service.js +140 -0
  180. package/dist/server/workspace/workspace.controller.d.ts +24 -0
  181. package/dist/server/workspace/workspace.controller.js +132 -0
  182. package/dist/server/workspace/workspace.module.d.ts +2 -0
  183. package/dist/server/workspace/workspace.module.js +21 -0
  184. package/dist/server/workspace/workspace.service.d.ts +36 -0
  185. package/dist/server/workspace/workspace.service.js +142 -0
  186. package/package.json +90 -0
  187. package/skills/agent-browser/SKILL.md +207 -0
  188. package/skills/agent-browser/references/authentication.md +202 -0
  189. package/skills/agent-browser/references/commands.md +259 -0
  190. package/skills/agent-browser/references/proxy-support.md +188 -0
  191. package/skills/agent-browser/references/session-management.md +193 -0
  192. package/skills/agent-browser/references/snapshot-refs.md +194 -0
  193. package/skills/agent-browser/references/video-recording.md +173 -0
  194. package/skills/agent-browser/templates/authenticated-session.sh +97 -0
  195. package/skills/agent-browser/templates/capture-workflow.sh +69 -0
  196. package/skills/agent-browser/templates/form-automation.sh +62 -0
  197. package/skills/find-skills/SKILL.md +140 -0
  198. package/skills/url-bookmark/SKILL.md +36 -0
@@ -0,0 +1,2 @@
1
+ export declare class UsersModule {
2
+ }
@@ -0,0 +1,19 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Module } from '@nestjs/common';
8
+ import { UsersController } from './users.controller.js';
9
+ import { UsersService } from './users.service.js';
10
+ let UsersModule = class UsersModule {
11
+ };
12
+ UsersModule = __decorate([
13
+ Module({
14
+ controllers: [UsersController],
15
+ providers: [UsersService],
16
+ exports: [UsersService],
17
+ })
18
+ ], UsersModule);
19
+ export { UsersModule };
@@ -0,0 +1,39 @@
1
+ export interface UserItem {
2
+ id: string;
3
+ username: string;
4
+ password: string;
5
+ }
6
+ export declare class UsersService {
7
+ private usersPath;
8
+ constructor();
9
+ private load;
10
+ private save;
11
+ list(): Promise<{
12
+ id: string;
13
+ username: string;
14
+ }[]>;
15
+ create(username: string, password: string): Promise<{
16
+ id: string;
17
+ username: string;
18
+ }>;
19
+ update(id: string, updates: {
20
+ username?: string;
21
+ password?: string;
22
+ }): Promise<{
23
+ id: string;
24
+ username: string;
25
+ }>;
26
+ delete(id: string): Promise<void>;
27
+ validateCredentials(username: string, password: string): Promise<boolean>;
28
+ /** 根据用户名查找用户(用于登录后返回当前用户信息) */
29
+ findByUsername(username: string): Promise<{
30
+ id: string;
31
+ username: string;
32
+ } | null>;
33
+ hasUsers(): Promise<boolean>;
34
+ /** 确保缺省 admin 用户存在,若不存在则创建并保存。返回该用户的 { id, username } */
35
+ ensureDefaultAdmin(): Promise<{
36
+ id: string;
37
+ username: string;
38
+ }>;
39
+ }
@@ -0,0 +1,140 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Injectable, ConflictException, NotFoundException } from '@nestjs/common';
11
+ import { readFile, writeFile, mkdir } from 'fs/promises';
12
+ import { join } from 'path';
13
+ import { existsSync } from 'fs';
14
+ import { randomUUID } from 'crypto';
15
+ const DEFAULT_ADMIN_USERNAME = 'admin';
16
+ const DEFAULT_ADMIN_PASSWORD = '123456';
17
+ let UsersService = class UsersService {
18
+ usersPath;
19
+ constructor() {
20
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '';
21
+ const configDir = join(homeDir, '.openbot', 'desktop');
22
+ this.usersPath = join(configDir, 'users.json');
23
+ if (!existsSync(configDir)) {
24
+ mkdir(configDir, { recursive: true });
25
+ }
26
+ }
27
+ async load() {
28
+ let users = [];
29
+ try {
30
+ if (existsSync(this.usersPath)) {
31
+ const content = await readFile(this.usersPath, 'utf-8');
32
+ const data = JSON.parse(content);
33
+ users = Array.isArray(data.users) ? data.users : [];
34
+ }
35
+ }
36
+ catch (e) {
37
+ console.error('Load users failed:', e);
38
+ }
39
+ if (users.length === 0) {
40
+ const defaultAdmin = {
41
+ id: randomUUID(),
42
+ username: DEFAULT_ADMIN_USERNAME,
43
+ password: DEFAULT_ADMIN_PASSWORD,
44
+ };
45
+ users = [defaultAdmin];
46
+ await this.save(users);
47
+ }
48
+ return users;
49
+ }
50
+ async save(users) {
51
+ await writeFile(this.usersPath, JSON.stringify({ users }, null, 2));
52
+ }
53
+ async list() {
54
+ const users = await this.load();
55
+ return users.map((u) => ({ id: u.id, username: u.username }));
56
+ }
57
+ async create(username, password) {
58
+ const trimmed = (username ?? '').trim();
59
+ const pass = (password ?? '').trim();
60
+ if (!trimmed)
61
+ throw new ConflictException('Username is required');
62
+ const users = await this.load();
63
+ const lower = trimmed.toLowerCase();
64
+ if (users.some((u) => u.username.toLowerCase() === lower)) {
65
+ throw new ConflictException('Username already exists');
66
+ }
67
+ const id = randomUUID();
68
+ users.push({ id, username: trimmed, password: pass });
69
+ await this.save(users);
70
+ return { id, username: trimmed };
71
+ }
72
+ async update(id, updates) {
73
+ const users = await this.load();
74
+ const idx = users.findIndex((u) => u.id === id);
75
+ if (idx < 0)
76
+ throw new NotFoundException('User not found');
77
+ if (updates.username !== undefined) {
78
+ const trimmed = updates.username.trim();
79
+ if (!trimmed)
80
+ throw new ConflictException('Username is required');
81
+ const lower = trimmed.toLowerCase();
82
+ if (users.some((u, i) => i !== idx && u.username.toLowerCase() === lower)) {
83
+ throw new ConflictException('Username already exists');
84
+ }
85
+ users[idx].username = trimmed;
86
+ }
87
+ if (updates.password !== undefined) {
88
+ users[idx].password = updates.password.trim();
89
+ }
90
+ await this.save(users);
91
+ return { id: users[idx].id, username: users[idx].username };
92
+ }
93
+ async delete(id) {
94
+ const users = await this.load();
95
+ const filtered = users.filter((u) => u.id !== id);
96
+ if (filtered.length === users.length)
97
+ throw new NotFoundException('User not found');
98
+ await this.save(filtered);
99
+ }
100
+ async validateCredentials(username, password) {
101
+ const users = await this.load();
102
+ if (users.length === 0)
103
+ return false;
104
+ const user = (username ?? '').trim().toLowerCase();
105
+ const pass = (password ?? '').trim();
106
+ const found = users.find((u) => u.username.toLowerCase() === user);
107
+ return found ? found.password === pass : false;
108
+ }
109
+ /** 根据用户名查找用户(用于登录后返回当前用户信息) */
110
+ async findByUsername(username) {
111
+ const users = await this.load();
112
+ const lower = (username ?? '').trim().toLowerCase();
113
+ const found = users.find((u) => u.username.toLowerCase() === lower);
114
+ return found ? { id: found.id, username: found.username } : null;
115
+ }
116
+ async hasUsers() {
117
+ const users = await this.load();
118
+ return users.length > 0;
119
+ }
120
+ /** 确保缺省 admin 用户存在,若不存在则创建并保存。返回该用户的 { id, username } */
121
+ async ensureDefaultAdmin() {
122
+ const users = await this.load();
123
+ const existing = users.find((u) => u.username.toLowerCase() === DEFAULT_ADMIN_USERNAME.toLowerCase());
124
+ if (existing)
125
+ return { id: existing.id, username: existing.username };
126
+ const defaultAdmin = {
127
+ id: randomUUID(),
128
+ username: DEFAULT_ADMIN_USERNAME,
129
+ password: DEFAULT_ADMIN_PASSWORD,
130
+ };
131
+ users.push(defaultAdmin);
132
+ await this.save(users);
133
+ return { id: defaultAdmin.id, username: defaultAdmin.username };
134
+ }
135
+ };
136
+ UsersService = __decorate([
137
+ Injectable(),
138
+ __metadata("design:paramtypes", [])
139
+ ], UsersService);
140
+ export { UsersService };
@@ -0,0 +1,24 @@
1
+ import { Response } from 'express';
2
+ import { WorkspaceService } from './workspace.service.js';
3
+ import { ConfigService } from '../config/config.service.js';
4
+ export declare class WorkspaceController {
5
+ private readonly workspaceService;
6
+ private readonly configService;
7
+ constructor(workspaceService: WorkspaceService, configService: ConfigService);
8
+ listWorkspaces(): Promise<{
9
+ success: boolean;
10
+ data: string[];
11
+ }>;
12
+ getCurrentWorkspace(): Promise<{
13
+ success: boolean;
14
+ data: string;
15
+ }>;
16
+ listDocuments(workspace: string, path?: string): Promise<{
17
+ success: boolean;
18
+ data: import("./workspace.service.js").WorkspaceItem[];
19
+ }>;
20
+ serveFile(workspace: string, path: string, download: string, res: Response): Promise<void>;
21
+ deleteDocument(workspace: string, path: string): Promise<{
22
+ success: boolean;
23
+ }>;
24
+ }
@@ -0,0 +1,132 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Controller, Get, Delete, Query, Res, HttpException, HttpStatus, NotFoundException, } from '@nestjs/common';
14
+ import { createReadStream } from 'fs';
15
+ import { existsSync } from 'fs';
16
+ import { stat } from 'fs/promises';
17
+ import { WorkspaceService } from './workspace.service.js';
18
+ import { ConfigService } from '../config/config.service.js';
19
+ const PREVIEW_TYPES = new Set([
20
+ 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml',
21
+ 'application/pdf',
22
+ 'text/plain', 'text/html', 'text/markdown', 'application/json',
23
+ ]);
24
+ function getMimeType(filename) {
25
+ const ext = filename.split('.').pop()?.toLowerCase() || '';
26
+ const map = {
27
+ jpg: 'image/jpeg', jpeg: 'image/jpeg', png: 'image/png', gif: 'image/gif',
28
+ webp: 'image/webp', svg: 'image/svg+xml', pdf: 'application/pdf',
29
+ txt: 'text/plain', html: 'text/html', htm: 'text/html', md: 'text/markdown',
30
+ json: 'application/json',
31
+ };
32
+ return map[ext] || 'application/octet-stream';
33
+ }
34
+ let WorkspaceController = class WorkspaceController {
35
+ workspaceService;
36
+ configService;
37
+ constructor(workspaceService, configService) {
38
+ this.workspaceService = workspaceService;
39
+ this.configService = configService;
40
+ }
41
+ async listWorkspaces() {
42
+ const list = await this.workspaceService.listWorkspaces();
43
+ return { success: true, data: list };
44
+ }
45
+ async getCurrentWorkspace() {
46
+ const config = await this.configService.getConfig();
47
+ return { success: true, data: this.configService.getDefaultAgentId(config) };
48
+ }
49
+ async listDocuments(workspace, path = '') {
50
+ const name = workspace || this.configService.getDefaultAgentId(await this.configService.getConfig());
51
+ const items = await this.workspaceService.listDocuments(name, path);
52
+ return { success: true, data: items };
53
+ }
54
+ async serveFile(workspace, path, download, res) {
55
+ if (!path) {
56
+ throw new HttpException('path is required', HttpStatus.BAD_REQUEST);
57
+ }
58
+ const name = workspace || this.configService.getDefaultAgentId(await this.configService.getConfig());
59
+ const { absolutePath, safe } = this.workspaceService.resolveFilePath(name, path);
60
+ if (!safe || !existsSync(absolutePath)) {
61
+ throw new NotFoundException('File not found');
62
+ }
63
+ const fileStat = await stat(absolutePath);
64
+ if (!fileStat.isFile()) {
65
+ throw new HttpException('Not a file', HttpStatus.BAD_REQUEST);
66
+ }
67
+ const filename = path.split('/').pop() || path;
68
+ const mime = getMimeType(filename);
69
+ const isPreview = !download && PREVIEW_TYPES.has(mime);
70
+ res.setHeader('Content-Type', mime);
71
+ if (!isPreview) {
72
+ res.setHeader('Content-Disposition', `attachment; filename="${encodeURIComponent(filename)}"`);
73
+ }
74
+ const stream = createReadStream(absolutePath);
75
+ stream.pipe(res);
76
+ }
77
+ async deleteDocument(workspace, path) {
78
+ if (!path) {
79
+ throw new HttpException('path is required', HttpStatus.BAD_REQUEST);
80
+ }
81
+ const name = workspace || this.configService.getDefaultAgentId(await this.configService.getConfig());
82
+ const deleted = await this.workspaceService.deletePath(name, path);
83
+ if (!deleted) {
84
+ throw new NotFoundException('File or folder not found');
85
+ }
86
+ return { success: true };
87
+ }
88
+ };
89
+ __decorate([
90
+ Get(),
91
+ __metadata("design:type", Function),
92
+ __metadata("design:paramtypes", []),
93
+ __metadata("design:returntype", Promise)
94
+ ], WorkspaceController.prototype, "listWorkspaces", null);
95
+ __decorate([
96
+ Get('current'),
97
+ __metadata("design:type", Function),
98
+ __metadata("design:paramtypes", []),
99
+ __metadata("design:returntype", Promise)
100
+ ], WorkspaceController.prototype, "getCurrentWorkspace", null);
101
+ __decorate([
102
+ Get('documents'),
103
+ __param(0, Query('workspace')),
104
+ __param(1, Query('path')),
105
+ __metadata("design:type", Function),
106
+ __metadata("design:paramtypes", [String, String]),
107
+ __metadata("design:returntype", Promise)
108
+ ], WorkspaceController.prototype, "listDocuments", null);
109
+ __decorate([
110
+ Get('files/serve'),
111
+ __param(0, Query('workspace')),
112
+ __param(1, Query('path')),
113
+ __param(2, Query('download')),
114
+ __param(3, Res({ passthrough: false })),
115
+ __metadata("design:type", Function),
116
+ __metadata("design:paramtypes", [String, String, String, Object]),
117
+ __metadata("design:returntype", Promise)
118
+ ], WorkspaceController.prototype, "serveFile", null);
119
+ __decorate([
120
+ Delete('files'),
121
+ __param(0, Query('workspace')),
122
+ __param(1, Query('path')),
123
+ __metadata("design:type", Function),
124
+ __metadata("design:paramtypes", [String, String]),
125
+ __metadata("design:returntype", Promise)
126
+ ], WorkspaceController.prototype, "deleteDocument", null);
127
+ WorkspaceController = __decorate([
128
+ Controller('workspace'),
129
+ __metadata("design:paramtypes", [WorkspaceService,
130
+ ConfigService])
131
+ ], WorkspaceController);
132
+ export { WorkspaceController };
@@ -0,0 +1,2 @@
1
+ export declare class WorkspaceModule {
2
+ }
@@ -0,0 +1,21 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Module } from '@nestjs/common';
8
+ import { WorkspaceController } from './workspace.controller.js';
9
+ import { WorkspaceService } from './workspace.service.js';
10
+ import { ConfigModule } from '../config/config.module.js';
11
+ let WorkspaceModule = class WorkspaceModule {
12
+ };
13
+ WorkspaceModule = __decorate([
14
+ Module({
15
+ imports: [ConfigModule],
16
+ controllers: [WorkspaceController],
17
+ providers: [WorkspaceService],
18
+ exports: [WorkspaceService],
19
+ })
20
+ ], WorkspaceModule);
21
+ export { WorkspaceModule };
@@ -0,0 +1,36 @@
1
+ export interface WorkspaceItem {
2
+ name: string;
3
+ path: string;
4
+ isDirectory: boolean;
5
+ size?: number;
6
+ mtime?: number;
7
+ }
8
+ export declare class WorkspaceService {
9
+ private getWorkspaceRoot;
10
+ /** List workspace names (directories under OPENBOT_WORKSPACE_DIR, default ~/.openbot/workspace) */
11
+ listWorkspaces(): Promise<string[]>;
12
+ /** List files and folders under a path relative to workspace root. Empty path = root. */
13
+ listDocuments(workspaceName: string, relativePath?: string): Promise<WorkspaceItem[]>;
14
+ /**
15
+ * Resolve a relative path and ensure it stays under workspace root.
16
+ * Returns path suitable for join(workspaceRoot, result).
17
+ */
18
+ resolveFilePath(workspaceName: string, relativePath: string): {
19
+ absolutePath: string;
20
+ safe: boolean;
21
+ };
22
+ /** Delete a file or directory (recursive) under workspace. Returns true if deleted. skills 与 .skills 目录禁止删除。 */
23
+ deletePath(workspaceName: string, relativePath: string): Promise<boolean>;
24
+ private safeRelativePath;
25
+ /** Ensure workspace/.favorite directory exists. */
26
+ ensureFavoriteDir(workspaceName: string): Promise<string>;
27
+ /**
28
+ * Write buffer to workspace/.favorite/{filename}. Returns relative path (e.g. .favorite/xxx).
29
+ */
30
+ writeFileInFavorite(workspaceName: string, filename: string, buffer: Buffer): Promise<string>;
31
+ /**
32
+ * Write buffer to a user-chosen directory. targetDir must be absolute and under homedir or workspace root.
33
+ * Returns the full path of the written file.
34
+ */
35
+ writeFileToDir(targetDir: string, filename: string, buffer: Buffer): Promise<string>;
36
+ }
@@ -0,0 +1,142 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Injectable } from '@nestjs/common';
8
+ import { readdir, stat, rm, mkdir, writeFile } from 'fs/promises';
9
+ import { join, resolve, relative } from 'path';
10
+ import { existsSync } from 'fs';
11
+ import { homedir } from 'os';
12
+ import { getOpenbotWorkspaceDir } from '../../core/agent/agent-dir.js';
13
+ let WorkspaceService = class WorkspaceService {
14
+ getWorkspaceRoot(name) {
15
+ return join(getOpenbotWorkspaceDir(), name);
16
+ }
17
+ /** List workspace names (directories under OPENBOT_WORKSPACE_DIR, default ~/.openbot/workspace) */
18
+ async listWorkspaces() {
19
+ const base = getOpenbotWorkspaceDir();
20
+ if (!existsSync(base)) {
21
+ return [];
22
+ }
23
+ const entries = await readdir(base, { withFileTypes: true });
24
+ return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
25
+ }
26
+ /** List files and folders under a path relative to workspace root. Empty path = root. */
27
+ async listDocuments(workspaceName, relativePath = '') {
28
+ const root = resolve(this.getWorkspaceRoot(workspaceName));
29
+ if (!existsSync(root)) {
30
+ return [];
31
+ }
32
+ const safePath = this.safeRelativePath(relativePath);
33
+ const dir = resolve(root, safePath);
34
+ const dirNormalized = resolve(dir);
35
+ const rootNormalized = resolve(root);
36
+ if (!dirNormalized.startsWith(rootNormalized) || !existsSync(dirNormalized)) {
37
+ return [];
38
+ }
39
+ const entries = await readdir(dirNormalized, { withFileTypes: true });
40
+ const items = [];
41
+ const hiddenDirNames = new Set(['skills', '.skills']);
42
+ for (const e of entries) {
43
+ if (e.isDirectory() && hiddenDirNames.has(e.name))
44
+ continue;
45
+ const fullPath = join(dirNormalized, e.name);
46
+ const rel = relative(rootNormalized, fullPath);
47
+ let st;
48
+ try {
49
+ st = await stat(fullPath);
50
+ }
51
+ catch (err) {
52
+ if (err?.code === 'ENOENT')
53
+ continue;
54
+ throw err;
55
+ }
56
+ items.push({
57
+ name: e.name,
58
+ path: rel,
59
+ isDirectory: st.isDirectory(),
60
+ size: st.isFile() ? st.size : undefined,
61
+ mtime: st.mtimeMs,
62
+ });
63
+ }
64
+ return items.sort((a, b) => {
65
+ if (a.isDirectory !== b.isDirectory)
66
+ return a.isDirectory ? -1 : 1;
67
+ return a.name.localeCompare(b.name);
68
+ });
69
+ }
70
+ /**
71
+ * Resolve a relative path and ensure it stays under workspace root.
72
+ * Returns path suitable for join(workspaceRoot, result).
73
+ */
74
+ resolveFilePath(workspaceName, relativePath) {
75
+ const root = resolve(this.getWorkspaceRoot(workspaceName));
76
+ const safe = this.safeRelativePath(relativePath);
77
+ const absolute = resolve(root, safe);
78
+ const ok = resolve(absolute).startsWith(root) && existsSync(absolute);
79
+ return { absolutePath: absolute, safe: ok };
80
+ }
81
+ /** Delete a file or directory (recursive) under workspace. Returns true if deleted. skills 与 .skills 目录禁止删除。 */
82
+ async deletePath(workspaceName, relativePath) {
83
+ const safe = this.safeRelativePath(relativePath);
84
+ const topDir = safe.split('/')[0];
85
+ if (topDir === 'skills' || topDir === '.skills')
86
+ return false;
87
+ const { absolutePath, safe: resolved } = this.resolveFilePath(workspaceName, relativePath);
88
+ if (!resolved || !existsSync(absolutePath))
89
+ return false;
90
+ await rm(absolutePath, { recursive: true });
91
+ return true;
92
+ }
93
+ safeRelativePath(relativePath) {
94
+ if (!relativePath || relativePath === '.')
95
+ return '';
96
+ const normalized = relativePath.replace(/\\/g, '/').replace(/\/+/g, '/').replace(/^\/+/, '');
97
+ const parts = normalized.split('/').filter((p) => p !== '..' && p !== '.');
98
+ return parts.join('/');
99
+ }
100
+ /** Ensure workspace/.favorite directory exists. */
101
+ async ensureFavoriteDir(workspaceName) {
102
+ const root = resolve(this.getWorkspaceRoot(workspaceName));
103
+ const favoriteDir = join(root, '.favorite');
104
+ if (!existsSync(favoriteDir)) {
105
+ await mkdir(favoriteDir, { recursive: true });
106
+ }
107
+ return favoriteDir;
108
+ }
109
+ /**
110
+ * Write buffer to workspace/.favorite/{filename}. Returns relative path (e.g. .favorite/xxx).
111
+ */
112
+ async writeFileInFavorite(workspaceName, filename, buffer) {
113
+ const dir = await this.ensureFavoriteDir(workspaceName);
114
+ const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, '_').slice(0, 200) || 'download';
115
+ const absolutePath = join(dir, safeName);
116
+ await writeFile(absolutePath, buffer);
117
+ return `.favorite/${safeName}`;
118
+ }
119
+ /**
120
+ * Write buffer to a user-chosen directory. targetDir must be absolute and under homedir or workspace root.
121
+ * Returns the full path of the written file.
122
+ */
123
+ async writeFileToDir(targetDir, filename, buffer) {
124
+ const home = homedir();
125
+ const workspaceRoot = getOpenbotWorkspaceDir();
126
+ const normalized = resolve(targetDir);
127
+ if (!normalized.startsWith(resolve(home)) && !normalized.startsWith(resolve(workspaceRoot))) {
128
+ throw new Error('Target directory must be under user home or workspace root');
129
+ }
130
+ if (!existsSync(normalized)) {
131
+ await mkdir(normalized, { recursive: true });
132
+ }
133
+ const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, '_').slice(0, 200) || 'download';
134
+ const absolutePath = join(normalized, safeName);
135
+ await writeFile(absolutePath, buffer);
136
+ return absolutePath;
137
+ }
138
+ };
139
+ WorkspaceService = __decorate([
140
+ Injectable()
141
+ ], WorkspaceService);
142
+ export { WorkspaceService };
package/package.json ADDED
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "@next-open-ai/openclawx",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "0.6.6",
7
+ "description": "CLI and library to run prompts with skill paths (Agent Skills style). Use as npm package or openclawx CLI.",
8
+ "type": "module",
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "default": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "skills",
21
+ "README.md",
22
+ "apps/desktop/renderer/dist"
23
+ ],
24
+ "bin": {
25
+ "openbot": "./dist/cli/cli.js"
26
+ },
27
+ "dependencies": {
28
+ "@mariozechner/pi-ai": "^0.51.2",
29
+ "@mariozechner/pi-coding-agent": "^0.51.2",
30
+ "@nestjs/common": "^10.3.0",
31
+ "@nestjs/core": "^10.3.0",
32
+ "@nestjs/platform-express": "^10.3.0",
33
+ "@nestjs/platform-socket.io": "^10.3.0",
34
+ "@nestjs/websockets": "^10.3.0",
35
+ "@sinclair/typebox": "^0.34.41",
36
+ "adm-zip": "^0.5.16",
37
+ "agent-browser": "^0.8.5",
38
+ "commander": "^14.0.2",
39
+ "croner": "^9.1.0",
40
+ "multer": "^1.4.5-lts.1",
41
+ "reflect-metadata": "^0.2.1",
42
+ "rxjs": "^7.8.1",
43
+ "sql.js": "^1.13.0",
44
+ "vectra": "^0.12.3",
45
+ "ws": "^8.19.0"
46
+ },
47
+ "devDependencies": {
48
+ "@nestjs/testing": "^10.3.0",
49
+ "@types/adm-zip": "^0.5.7",
50
+ "@types/express": "^4.17.21",
51
+ "@types/jest": "^29.5.14",
52
+ "@types/multer": "^2.0.0",
53
+ "@types/node": "^22.0.0",
54
+ "@types/sql.js": "^1.4.9",
55
+ "@types/ws": "^8.18.1",
56
+ "jest": "^29.7.0",
57
+ "rimraf": "^5.0.5",
58
+ "ts-jest": "^29.2.5",
59
+ "typescript": "^5.7.0"
60
+ },
61
+ "scripts": {
62
+ "clean": "rimraf dist",
63
+ "build": "npm run clean && tsc",
64
+ "build:web": "cd apps/desktop && npm run build:renderer",
65
+ "build:all": "npm run build && npm run build:web",
66
+ "prepublishOnly": "npm run build && cd apps/desktop && npm run build:renderer",
67
+ "start": "node dist/cli/cli.js",
68
+ "run": "node dist/cli/cli.js",
69
+ "dev": "npm run build && node dist/cli/cli.js",
70
+ "desktop:dev": "cd apps/desktop && npm run dev",
71
+ "desktop:build": "cd apps/desktop && npm run build",
72
+ "desktop:pack": "npm run build && cd apps/desktop && npm run build",
73
+ "desktop:install": "cd apps/desktop && npm install",
74
+ "test": "jest --config test/jest.config.cjs",
75
+ "test:memory": "node test/run-memory.mjs",
76
+ "test:e2e": "OPENBOT_DB_PATH=:memory: jest --config test/jest.config.cjs --testPathPattern=e2e",
77
+ "test:gateway-e2e": "npm run build && node test/gateway/server.e2e.mjs"
78
+ },
79
+ "engines": {
80
+ "node": ">=20.0.0"
81
+ },
82
+ "keywords": [
83
+ "skill",
84
+ "agent",
85
+ "cli",
86
+ "llm",
87
+ "openbot"
88
+ ],
89
+ "license": "MIT"
90
+ }