pikiloop 0.4.0

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 (154) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +353 -0
  3. package/README.v2.md +287 -0
  4. package/README.zh-CN.md +352 -0
  5. package/dashboard/dist/assets/AgentTab-UZPIhlkr.js +1 -0
  6. package/dashboard/dist/assets/DirBrowser-Ckcmi-Pi.js +1 -0
  7. package/dashboard/dist/assets/ExtensionsTab-KZhEDrdu.js +1 -0
  8. package/dashboard/dist/assets/IMAccessTab-Bd_IY1GQ.js +1 -0
  9. package/dashboard/dist/assets/Modal-CTeL0y7P.js +1 -0
  10. package/dashboard/dist/assets/Modals-axftHasy.js +1 -0
  11. package/dashboard/dist/assets/Select-C8tOdPhe.js +1 -0
  12. package/dashboard/dist/assets/SessionPanel-C1geSRxw.js +1 -0
  13. package/dashboard/dist/assets/SystemTab-DBDkaPiO.js +1 -0
  14. package/dashboard/dist/assets/anthropic-BAdojD7P.ico +0 -0
  15. package/dashboard/dist/assets/codex-DYadqqp0.png +0 -0
  16. package/dashboard/dist/assets/deepseek-BeYNZEk0.ico +0 -0
  17. package/dashboard/dist/assets/doubao-DloFDuFR.png +0 -0
  18. package/dashboard/dist/assets/feishu-C4OMrjCW.ico +0 -0
  19. package/dashboard/dist/assets/gemini-BYkEpiWr.svg +1 -0
  20. package/dashboard/dist/assets/hermes-BAarh-tH.png +0 -0
  21. package/dashboard/dist/assets/index-CpM4CqZJ.js +23 -0
  22. package/dashboard/dist/assets/index-DXSohzrE.js +3 -0
  23. package/dashboard/dist/assets/index-reSbuley.css +1 -0
  24. package/dashboard/dist/assets/markdown-DxQYQFeH.js +29 -0
  25. package/dashboard/dist/assets/minimax-PuEGTfrF.ico +0 -0
  26. package/dashboard/dist/assets/mlx-DhWwjtMw.png +0 -0
  27. package/dashboard/dist/assets/ollama-Bt9O-2K_.png +0 -0
  28. package/dashboard/dist/assets/openrouter-CsJ_bD5Q.ico +0 -0
  29. package/dashboard/dist/assets/playwright-BldPFZgC.ico +0 -0
  30. package/dashboard/dist/assets/qwen-xykkX0_y.png +0 -0
  31. package/dashboard/dist/assets/react-vendor-C7Sl8SE7.js +9 -0
  32. package/dashboard/dist/assets/router-DHISdpPk.js +3 -0
  33. package/dashboard/dist/assets/shared-BIP_4k4I.js +1 -0
  34. package/dashboard/dist/favicon.svg +28 -0
  35. package/dashboard/dist/index.html +17 -0
  36. package/dist/agent/acp-client.js +261 -0
  37. package/dist/agent/auto-update.js +432 -0
  38. package/dist/agent/await-resume.js +50 -0
  39. package/dist/agent/cli/auth.js +325 -0
  40. package/dist/agent/cli/catalog.js +40 -0
  41. package/dist/agent/cli/detector.js +136 -0
  42. package/dist/agent/cli/index.js +7 -0
  43. package/dist/agent/cli/registry.js +33 -0
  44. package/dist/agent/driver.js +39 -0
  45. package/dist/agent/drivers/claude-tui.js +2297 -0
  46. package/dist/agent/drivers/claude.js +2689 -0
  47. package/dist/agent/drivers/codex.js +2210 -0
  48. package/dist/agent/drivers/gemini.js +1059 -0
  49. package/dist/agent/drivers/hermes.js +795 -0
  50. package/dist/agent/goal.js +274 -0
  51. package/dist/agent/handover.js +130 -0
  52. package/dist/agent/images.js +355 -0
  53. package/dist/agent/index.js +50 -0
  54. package/dist/agent/mcp/bridge.js +791 -0
  55. package/dist/agent/mcp/extensions.js +637 -0
  56. package/dist/agent/mcp/oauth.js +353 -0
  57. package/dist/agent/mcp/registry.js +119 -0
  58. package/dist/agent/mcp/session-server.js +229 -0
  59. package/dist/agent/mcp/tools/ask-user.js +113 -0
  60. package/dist/agent/mcp/tools/await-resume.js +77 -0
  61. package/dist/agent/mcp/tools/goal.js +144 -0
  62. package/dist/agent/mcp/tools/types.js +12 -0
  63. package/dist/agent/mcp/tools/workspace.js +212 -0
  64. package/dist/agent/npm.js +31 -0
  65. package/dist/agent/session.js +1206 -0
  66. package/dist/agent/skill-installer.js +160 -0
  67. package/dist/agent/skills.js +257 -0
  68. package/dist/agent/stream.js +743 -0
  69. package/dist/agent/types.js +13 -0
  70. package/dist/agent/utils.js +687 -0
  71. package/dist/bot/bot.js +2499 -0
  72. package/dist/bot/command-ui.js +633 -0
  73. package/dist/bot/commands.js +513 -0
  74. package/dist/bot/headless-bot.js +36 -0
  75. package/dist/bot/host.js +192 -0
  76. package/dist/bot/human-loop.js +168 -0
  77. package/dist/bot/menu.js +48 -0
  78. package/dist/bot/orchestration.js +79 -0
  79. package/dist/bot/render-shared.js +309 -0
  80. package/dist/bot/session-hub.js +361 -0
  81. package/dist/bot/session-status.js +55 -0
  82. package/dist/bot/streaming.js +309 -0
  83. package/dist/browser-profile.js +579 -0
  84. package/dist/browser-supervisor.js +249 -0
  85. package/dist/catalog/cli-tools.js +421 -0
  86. package/dist/catalog/index.js +21 -0
  87. package/dist/catalog/local-models.js +94 -0
  88. package/dist/catalog/mcp-servers.js +315 -0
  89. package/dist/catalog/skill-repos.js +173 -0
  90. package/dist/channels/base.js +55 -0
  91. package/dist/channels/dingtalk/bot.js +549 -0
  92. package/dist/channels/dingtalk/channel.js +268 -0
  93. package/dist/channels/discord/bot.js +552 -0
  94. package/dist/channels/discord/channel.js +245 -0
  95. package/dist/channels/feishu/bot.js +1275 -0
  96. package/dist/channels/feishu/channel.js +911 -0
  97. package/dist/channels/feishu/markdown.js +91 -0
  98. package/dist/channels/feishu/render.js +619 -0
  99. package/dist/channels/health.js +109 -0
  100. package/dist/channels/slack/bot.js +554 -0
  101. package/dist/channels/slack/channel.js +283 -0
  102. package/dist/channels/states.js +6 -0
  103. package/dist/channels/telegram/bot.js +1310 -0
  104. package/dist/channels/telegram/channel.js +820 -0
  105. package/dist/channels/telegram/directory.js +111 -0
  106. package/dist/channels/telegram/live-preview.js +220 -0
  107. package/dist/channels/telegram/render.js +384 -0
  108. package/dist/channels/wecom/bot.js +558 -0
  109. package/dist/channels/wecom/channel.js +479 -0
  110. package/dist/channels/weixin/api.js +520 -0
  111. package/dist/channels/weixin/bot.js +1000 -0
  112. package/dist/channels/weixin/channel.js +222 -0
  113. package/dist/cli/autostart.js +262 -0
  114. package/dist/cli/channel-supervisor.js +313 -0
  115. package/dist/cli/channels.js +54 -0
  116. package/dist/cli/main.js +726 -0
  117. package/dist/cli/onboarding.js +227 -0
  118. package/dist/cli/run.js +308 -0
  119. package/dist/cli/setup-wizard.js +235 -0
  120. package/dist/core/config/runtime-config.js +201 -0
  121. package/dist/core/config/user-config.js +510 -0
  122. package/dist/core/config/validation.js +521 -0
  123. package/dist/core/constants.js +400 -0
  124. package/dist/core/git.js +145 -0
  125. package/dist/core/legacy-compat.js +60 -0
  126. package/dist/core/logging.js +101 -0
  127. package/dist/core/platform.js +59 -0
  128. package/dist/core/process-control.js +315 -0
  129. package/dist/core/secrets/index.js +42 -0
  130. package/dist/core/secrets/inline-seal.js +60 -0
  131. package/dist/core/secrets/ref.js +33 -0
  132. package/dist/core/secrets/resolver.js +65 -0
  133. package/dist/core/secrets/store.js +63 -0
  134. package/dist/core/utils.js +233 -0
  135. package/dist/core/version.js +15 -0
  136. package/dist/dashboard/platform.js +219 -0
  137. package/dist/dashboard/routes/agents.js +450 -0
  138. package/dist/dashboard/routes/cli.js +174 -0
  139. package/dist/dashboard/routes/config.js +523 -0
  140. package/dist/dashboard/routes/extensions.js +745 -0
  141. package/dist/dashboard/routes/local-models.js +290 -0
  142. package/dist/dashboard/routes/models.js +324 -0
  143. package/dist/dashboard/routes/sessions.js +838 -0
  144. package/dist/dashboard/runtime.js +410 -0
  145. package/dist/dashboard/server.js +237 -0
  146. package/dist/dashboard/session-control.js +347 -0
  147. package/dist/model/catalog.js +104 -0
  148. package/dist/model/index.js +20 -0
  149. package/dist/model/injector.js +272 -0
  150. package/dist/model/provider-models.js +112 -0
  151. package/dist/model/store.js +212 -0
  152. package/dist/model/types.js +13 -0
  153. package/dist/model/validation.js +203 -0
  154. package/package.json +82 -0
@@ -0,0 +1,212 @@
1
+ /**
2
+ * tools/workspace.ts — Workspace file tools.
3
+ *
4
+ * workspace_list_files — returns workspace path, staged files, and directory listing
5
+ * workspace_send_file — sends a file back to the IM chat
6
+ */
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
9
+ import http from 'node:http';
10
+ import os from 'node:os';
11
+ import { toolResult, toolLog } from './types.js';
12
+ // ---------------------------------------------------------------------------
13
+ // Tool definitions
14
+ // ---------------------------------------------------------------------------
15
+ const tools = [
16
+ {
17
+ name: 'im_list_files',
18
+ description: 'List files in the session workspace.',
19
+ inputSchema: {
20
+ type: 'object',
21
+ properties: {
22
+ subdirectory: {
23
+ type: 'string',
24
+ description: 'Workspace-relative subdirectory.',
25
+ },
26
+ },
27
+ },
28
+ },
29
+ {
30
+ name: 'im_send_file',
31
+ description: 'Send a file to the user in IM.',
32
+ inputSchema: {
33
+ type: 'object',
34
+ properties: {
35
+ path: {
36
+ type: 'string',
37
+ description: 'Path to send. Supports absolute paths, @workspace/..., @workdir/..., @tmp/..., workspace-relative paths, and unique bare filenames.',
38
+ },
39
+ caption: {
40
+ type: 'string',
41
+ description: 'Caption.',
42
+ },
43
+ kind: {
44
+ type: 'string',
45
+ enum: ['photo', 'document'],
46
+ description: 'Optional file kind.',
47
+ },
48
+ },
49
+ required: ['path', 'caption'],
50
+ },
51
+ },
52
+ ];
53
+ // ---------------------------------------------------------------------------
54
+ // Handlers
55
+ // ---------------------------------------------------------------------------
56
+ function summarizeSendFileArgs(filePath, caption, kind) {
57
+ const text = [
58
+ `path=${JSON.stringify(filePath || '')}`,
59
+ `kind=${JSON.stringify(kind || 'auto')}`,
60
+ `caption=${JSON.stringify(caption || '')}`,
61
+ ].join(' ');
62
+ return text.length <= 240 ? text : `${text.slice(0, 237).trimEnd()}...`;
63
+ }
64
+ function handleListFiles(args, ctx) {
65
+ const subdir = typeof args?.subdirectory === 'string' ? args.subdirectory : '';
66
+ const dir = subdir ? path.resolve(ctx.workspace, subdir) : ctx.workspace;
67
+ toolLog('im_list_files', `dir=${dir} subdir=${subdir || '(root)'}`);
68
+ // Security: ensure we stay within workspace
69
+ const realWorkspace = safeRealpath(ctx.workspace);
70
+ const realDir = safeRealpath(dir);
71
+ if (!realWorkspace || !realDir || !realDir.startsWith(realWorkspace)) {
72
+ toolLog('im_list_files', `REJECTED path outside workspace: ${dir}`);
73
+ return toolResult('Error: path is outside the workspace', true);
74
+ }
75
+ try {
76
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
77
+ const workspaceRelDir = path.relative(ctx.workspace, dir);
78
+ const files = entries.map(e => {
79
+ const entry = { name: e.name, type: e.isDirectory() ? 'directory' : 'file' };
80
+ const relPath = workspaceRelDir && workspaceRelDir !== '' && workspaceRelDir !== '.'
81
+ ? path.posix.join(toPosix(workspaceRelDir), e.name)
82
+ : e.name;
83
+ entry.path = relPath;
84
+ entry.alias = `@workspace/${relPath}`;
85
+ if (e.isFile()) {
86
+ try {
87
+ entry.size = fs.statSync(path.join(dir, e.name)).size;
88
+ }
89
+ catch { }
90
+ }
91
+ return entry;
92
+ });
93
+ toolLog('im_list_files', `OK ${files.length} entries`);
94
+ return toolResult(JSON.stringify({
95
+ workspacePath: ctx.workspace,
96
+ workdirPath: ctx.workdir || null,
97
+ tempPath: os.tmpdir(),
98
+ pathAliases: {
99
+ workspaceRoot: '@workspace',
100
+ workdirRoot: ctx.workdir ? '@workdir' : null,
101
+ tempRoot: '@tmp',
102
+ notes: [
103
+ 'Use @workspace/... for files in the session workspace.',
104
+ ctx.workdir ? 'Use @workdir/... for files in the agent workdir.' : null,
105
+ 'Use @tmp/... for screenshots and other temp files.',
106
+ 'A bare filename also works if it uniquely matches a staged file or /tmp file.',
107
+ ].filter(Boolean),
108
+ },
109
+ stagedFiles: ctx.stagedFiles.map(relPath => ({
110
+ path: relPath,
111
+ alias: `@workspace/${toPosix(relPath)}`,
112
+ basename: path.basename(relPath),
113
+ })),
114
+ files,
115
+ }, null, 2));
116
+ }
117
+ catch (e) {
118
+ toolLog('im_list_files', `ERROR ${e.message}`);
119
+ return toolResult(`Error listing directory: ${e.message}`, true);
120
+ }
121
+ }
122
+ async function handleSendFile(args, ctx) {
123
+ const filePath = typeof args?.path === 'string' ? args.path.trim() : '';
124
+ const caption = typeof args?.caption === 'string' ? args.caption.trim() : '';
125
+ const kind = typeof args?.kind === 'string' ? args.kind : undefined;
126
+ const argSummary = summarizeSendFileArgs(filePath, caption, kind);
127
+ toolLog('im_send_file', argSummary);
128
+ if (!filePath) {
129
+ toolLog('im_send_file', 'ERROR missing path');
130
+ return toolResult(`Error: "path" is required (${argSummary})`, true);
131
+ }
132
+ if (!caption) {
133
+ toolLog('im_send_file', 'ERROR missing caption');
134
+ return toolResult(`Error: "caption" is required (${argSummary})`, true);
135
+ }
136
+ if (!ctx.callbackUrl) {
137
+ toolLog('im_send_file', 'ERROR no callback URL');
138
+ return toolResult(`Error: MCP callback URL is not configured (${argSummary})`, true);
139
+ }
140
+ try {
141
+ const result = await callbackSendFile(ctx.callbackUrl, filePath, {
142
+ caption,
143
+ kind,
144
+ });
145
+ if (result.ok) {
146
+ toolLog('im_send_file', `OK sent ${filePath}`);
147
+ return toolResult(`File sent successfully: ${filePath}`);
148
+ }
149
+ else {
150
+ toolLog('im_send_file', `FAILED ${result.error || 'unknown error'}`);
151
+ return toolResult(`Failed to send file: ${result.error || 'unknown error'} (${argSummary})`, true);
152
+ }
153
+ }
154
+ catch (e) {
155
+ toolLog('im_send_file', `ERROR ${e.message}`);
156
+ return toolResult(`Error sending file: ${e.message} (${argSummary})`, true);
157
+ }
158
+ }
159
+ // ---------------------------------------------------------------------------
160
+ // HTTP callback
161
+ // ---------------------------------------------------------------------------
162
+ function callbackSendFile(callbackUrl, filePath, opts) {
163
+ const body = JSON.stringify({ path: filePath, ...opts });
164
+ const url = new URL('/send-file', callbackUrl);
165
+ return new Promise((resolve, reject) => {
166
+ const req = http.request(url, {
167
+ method: 'POST',
168
+ headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) },
169
+ }, res => {
170
+ let data = '';
171
+ res.on('data', (chunk) => { data += chunk; });
172
+ res.on('end', () => {
173
+ try {
174
+ resolve(JSON.parse(data));
175
+ }
176
+ catch {
177
+ resolve({ ok: false, error: 'invalid callback response' });
178
+ }
179
+ });
180
+ });
181
+ req.on('error', e => reject(e));
182
+ req.write(body);
183
+ req.end();
184
+ });
185
+ }
186
+ // ---------------------------------------------------------------------------
187
+ // Helpers
188
+ // ---------------------------------------------------------------------------
189
+ function safeRealpath(p) {
190
+ try {
191
+ return fs.realpathSync(p);
192
+ }
193
+ catch {
194
+ return null;
195
+ }
196
+ }
197
+ function toPosix(p) {
198
+ return p.split(path.sep).join(path.posix.sep);
199
+ }
200
+ // ---------------------------------------------------------------------------
201
+ // Module export
202
+ // ---------------------------------------------------------------------------
203
+ export const workspaceTools = {
204
+ tools,
205
+ handle(name, args, ctx) {
206
+ switch (name) {
207
+ case 'im_list_files': return handleListFiles(args, ctx);
208
+ case 'im_send_file': return handleSendFile(args, ctx);
209
+ default: return toolResult(`Unknown workspace tool: ${name}`, true);
210
+ }
211
+ },
212
+ };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * NPM helper for agent package management.
3
+ */
4
+ const AGENT_PACKAGES = {
5
+ claude: '@anthropic-ai/claude-code',
6
+ codex: '@openai/codex',
7
+ gemini: '@google/gemini-cli',
8
+ };
9
+ /** Known Homebrew cask tokens for agents that publish brew casks. */
10
+ const AGENT_BREW_CASKS = {
11
+ claude: 'claude-code',
12
+ codex: 'codex',
13
+ };
14
+ const AGENT_LABELS = {
15
+ claude: 'Claude Code',
16
+ codex: 'Codex',
17
+ gemini: 'Gemini CLI',
18
+ };
19
+ export function getAgentPackage(agent) {
20
+ return AGENT_PACKAGES[agent] || null;
21
+ }
22
+ export function getAgentBrewCask(agent) {
23
+ return AGENT_BREW_CASKS[agent] || null;
24
+ }
25
+ export function getAgentLabel(agent) {
26
+ return AGENT_LABELS[agent] || agent;
27
+ }
28
+ export function getAgentInstallCommand(agent) {
29
+ const pkg = getAgentPackage(agent);
30
+ return pkg ? `npm install -g ${pkg}` : null;
31
+ }