farming-code 2.2.28 → 2.2.30

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 (83) hide show
  1. package/README.md +27 -90
  2. package/README.zh_cn.md +17 -90
  3. package/THIRD_PARTY_NOTICES.md +25 -6
  4. package/backend/acp/packaged-claude-acp.js +13 -0
  5. package/backend/acp/packaged-codex-acp.js +2 -2
  6. package/backend/acp-runtime.js +38 -17
  7. package/backend/acp-session-state.js +78 -88
  8. package/backend/acp-transcript.js +174 -9
  9. package/backend/agent-manager.js +27 -2
  10. package/backend/agent-session-history.js +45 -12
  11. package/backend/codex-session-history.js +1 -1
  12. package/backend/codex-transcript.js +0 -202
  13. package/backend/config-manager.js +44 -16
  14. package/backend/data/LICENSE.agent-browser +201 -0
  15. package/backend/data/runtime-dependency-manifest.json +199 -0
  16. package/backend/data/runtime-dependency-sources.json +5 -0
  17. package/backend/executable-discovery.js +7 -0
  18. package/backend/farming-agent-bootstrap.zh_cn.md +4 -2
  19. package/backend/farming-app-cli.js +161 -65
  20. package/backend/farming-cli.js +7 -59
  21. package/backend/index-html.js +31 -0
  22. package/backend/main-agent-skills.js +7 -28
  23. package/backend/npm-update-helper.js +43 -6
  24. package/backend/provider-adapters.js +10 -0
  25. package/backend/runtime-dependency-manager.js +759 -0
  26. package/backend/runtime-executable-invocation.js +20 -0
  27. package/backend/server-process-identity.js +47 -0
  28. package/backend/server.js +145 -204
  29. package/backend/slash-command-discovery.js +138 -1
  30. package/backend/storage-layout.js +30 -0
  31. package/backend/update-service.js +60 -914
  32. package/config/farming.deploy.env.example +1 -1
  33. package/config/farming.install.env.example +5 -1
  34. package/dist/acp/LICENSE.claude-agent-acp +191 -0
  35. package/dist/acp/LICENSE.claude-agent-sdk +1 -0
  36. package/dist/acp/claude-agent-acp-0.59.0.mjs +41606 -0
  37. package/dist/acp/{codex-acp-1.1.4.js → codex-acp-1.1.4.mjs} +387 -7
  38. package/dist/assets/{App-CM7Cy-l4.css → App-BKNUILuL.css} +1 -1
  39. package/dist/assets/App-Z1N7T0eM.js +695 -0
  40. package/dist/assets/{FileEditorMarkdownPreview-DYOMm-b1.js → FileEditorMarkdownPreview-Cs9cLv8a.js} +1 -1
  41. package/dist/assets/FileEditorPane-CNtuGjQ3.js +2 -0
  42. package/dist/assets/IconGlyphs-BClgag6E.js +1 -0
  43. package/dist/assets/ProjectFilesSection-K3GHuQ4U.js +12 -0
  44. package/dist/assets/ReviewPage-BRuxFaH5.js +3 -0
  45. package/dist/assets/code-dark-kLsQLvpf.css +1 -0
  46. package/dist/assets/{index-BzQO3pUr.js → index-D-zetSol.js} +2 -2
  47. package/dist/assets/main-DUTz-Rd2.css +1 -0
  48. package/dist/assets/{workspace-editor-monaco-tXA-udGx.js → workspace-editor-monaco-CJNwbpCy.js} +1 -1
  49. package/dist/assets/workspace-editor-monaco-CO9w8YV0.js +1 -0
  50. package/dist/assets/workspace-view-state-BjKPYp0E.js +7 -0
  51. package/dist/index.html +33 -3
  52. package/extensions/browser/backend/agent-browser-runtime.js +1041 -0
  53. package/extensions/browser/backend/browser-mcp-server.js +352 -0
  54. package/extensions/browser/backend/browser-resource-manager.js +921 -114
  55. package/extensions/browser/backend/browser-resource-store.js +47 -6
  56. package/extensions/browser/backend/browser-router.js +15 -2
  57. package/extensions/browser/backend/executable-discovery.js +164 -17
  58. package/extensions/browser/backend/managed-chromium-installer.js +593 -0
  59. package/extensions/browser/bin/farming-browser +384 -30
  60. package/extensions/browser/frontend/BrowserSidebarPortals.tsx +17 -19
  61. package/extensions/browser/frontend/BrowserViewer.tsx +217 -46
  62. package/extensions/browser/frontend/browser.css +68 -17
  63. package/extensions/browser/frontend/types.ts +13 -0
  64. package/extensions/browser/frontend/useBrowserResources.ts +18 -3
  65. package/index.html +32 -2
  66. package/package.json +10 -6
  67. package/shared/backend-connection-status.d.ts +12 -0
  68. package/shared/backend-connection-status.js +35 -4
  69. package/backend/agent-activity.js +0 -35
  70. package/backend/agent-memory-report.js +0 -583
  71. package/backend/bundle-update-helper.js +0 -113
  72. package/backend/codex-rollout-follower.js +0 -326
  73. package/dist/assets/App-CPG4WcjO.js +0 -658
  74. package/dist/assets/FileEditorPane-DXXq82aM.js +0 -2
  75. package/dist/assets/IconGlyphs-DrdPjYXr.js +0 -1
  76. package/dist/assets/ProjectFilesSection-CP66XVPl.js +0 -12
  77. package/dist/assets/ReviewPage-w21MEPD6.js +0 -3
  78. package/dist/assets/code-dark-BDjwj7Um.css +0 -1
  79. package/dist/assets/main-BlVUXfxa.css +0 -1
  80. package/dist/assets/workspace-editor-monaco-CFEfFNcA.js +0 -1
  81. package/dist/assets/workspace-view-state-BS_V8JVs.js +0 -7
  82. package/extensions/browser/backend/cdp-browser-runtime.js +0 -648
  83. package/extensions/browser/backend/cdp-client.js +0 -167
@@ -159,6 +159,7 @@ function discoverClaudeSkillCommands(commands, skillsDir, sourceLabel) {
159
159
  label: commandLabel(entry.name),
160
160
  description: `Claude skill from ${sourceLabel}`,
161
161
  source: 'skill',
162
+ scope: sourceLabel === 'home' ? 'Personal' : commandLabel(sourceLabel),
162
163
  });
163
164
  });
164
165
  }
@@ -180,10 +181,100 @@ function discoverClaudeCustomCommands(commands, commandsDir, sourceLabel) {
180
181
  label: commandLabel(name),
181
182
  description: `Claude custom command from ${sourceLabel}`,
182
183
  source: 'custom',
184
+ scope: sourceLabel === 'home' ? 'Personal' : commandLabel(sourceLabel),
183
185
  });
184
186
  });
185
187
  }
186
188
 
189
+ function discoverClaudePluginComponents(commands, pluginPath, pluginName) {
190
+ discoverSkillFiles(path.join(pluginPath, 'skills')).forEach(skillFile => {
191
+ const skillName = path.basename(path.dirname(skillFile));
192
+ const metadata = parseSkillFrontMatter(skillFile);
193
+ addCommand(commands, {
194
+ command: `/${pluginName}:${skillName}`,
195
+ label: commandLabel(metadata.name || skillName),
196
+ description: metadata.description || `Claude skill from ${pluginName}`,
197
+ source: 'skill',
198
+ scope: 'Plugin',
199
+ });
200
+ });
201
+
202
+ let commandEntries = [];
203
+ try {
204
+ commandEntries = fs.readdirSync(path.join(pluginPath, 'commands'), { withFileTypes: true });
205
+ } catch {
206
+ // Plugins do not have to provide commands.
207
+ }
208
+ commandEntries.forEach(entry => {
209
+ if (!entry.isFile() || !entry.name.endsWith('.md')) return;
210
+ const commandName = entry.name.slice(0, -3);
211
+ if (!SAFE_COMMAND_NAME.test(commandName)) return;
212
+ addCommand(commands, {
213
+ command: `/${pluginName}:${commandName}`,
214
+ label: commandLabel(commandName),
215
+ description: `Claude command from ${pluginName}`,
216
+ source: 'custom',
217
+ scope: 'Plugin',
218
+ });
219
+ });
220
+ }
221
+
222
+ function readBoundedJson(filePath, maxBytes = 1024 * 1024) {
223
+ try {
224
+ const stats = fs.statSync(filePath);
225
+ if (!stats.isFile() || stats.size > maxBytes) return null;
226
+ const value = JSON.parse(fs.readFileSync(filePath, 'utf8'));
227
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
228
+ } catch {
229
+ return null;
230
+ }
231
+ }
232
+
233
+ function addClaudePlugin(commands, pluginName, pluginPath, scope = 'Plugin') {
234
+ if (!SAFE_COMMAND_NAME.test(pluginName)) return;
235
+ const manifest = readBoundedJson(path.join(pluginPath, '.claude-plugin', 'plugin.json'));
236
+ addCommand(commands, {
237
+ command: `plugin:${pluginName}`,
238
+ label: String(manifest?.name || commandLabel(pluginName)).slice(0, 100),
239
+ description: String(manifest?.description || 'Claude Code plugin').slice(0, 500),
240
+ source: 'plugin',
241
+ scope,
242
+ });
243
+ discoverClaudePluginComponents(commands, pluginPath, pluginName);
244
+ }
245
+
246
+ function discoverClaudeInstalledPlugins(commands, homePath) {
247
+ const pluginsRoot = path.join(homePath, 'plugins');
248
+ const installed = readBoundedJson(path.join(pluginsRoot, 'installed_plugins.json'));
249
+ Object.entries(installed?.plugins || {}).slice(0, MAX_DISCOVERED_SKILLS).forEach(([key, rawEntries]) => {
250
+ const pluginName = key.split('@')[0];
251
+ const entries = Array.isArray(rawEntries) ? rawEntries : [];
252
+ const installedEntry = entries.find(entry => (
253
+ entry && typeof entry === 'object' && typeof entry.installPath === 'string'
254
+ ));
255
+ if (!installedEntry) return;
256
+ addClaudePlugin(
257
+ commands,
258
+ pluginName,
259
+ installedEntry.installPath,
260
+ String(installedEntry.scope || 'Plugin'),
261
+ );
262
+ });
263
+
264
+ let entries = [];
265
+ try {
266
+ entries = fs.readdirSync(pluginsRoot, { withFileTypes: true });
267
+ } catch {
268
+ return;
269
+ }
270
+ entries.forEach(entry => {
271
+ if (!entry.isDirectory() || !SAFE_COMMAND_NAME.test(entry.name)) return;
272
+ const pluginPath = path.join(pluginsRoot, entry.name);
273
+ if (!fs.existsSync(path.join(pluginPath, '.claude-plugin', 'plugin.json'))) return;
274
+ addClaudePlugin(commands, entry.name, pluginPath);
275
+ });
276
+ }
277
+
187
278
  function discoverClaudeSlashCommands({ homeDir = os.homedir(), workspace } = {}) {
188
279
  const commands = [];
189
280
  const normalizedWorkspace = normalizeWorkspace(workspace, homeDir);
@@ -249,15 +340,26 @@ function discoverPluginSkillFiles(root, depth = 0, skillFiles = []) {
249
340
 
250
341
  function pluginNameForSkillFile(skillFile, pluginsCacheDir) {
251
342
  const parts = path.relative(pluginsCacheDir, skillFile).split(path.sep);
252
- if (parts[0] === 'openai-curated' && parts[1]) return parts[1];
343
+ if ((parts[0] === 'openai-curated' || parts[0] === 'openai-curated-remote') && parts[1]) return parts[1];
253
344
  if ((parts[0] === 'openai-primary-runtime' || parts[0] === 'openai-bundled') && parts[1]) return parts[1];
254
345
  return parts[0] || '';
255
346
  }
256
347
 
257
348
  function discoverCodexPluginSkills(commands, homeDir) {
258
349
  const pluginsCacheDir = path.join(homeDir, '.codex', 'plugins', 'cache');
350
+ discoverCodexPluginSkillsAt(commands, pluginsCacheDir);
351
+ }
352
+
353
+ function discoverCodexPluginSkillsAt(commands, pluginsCacheDir) {
259
354
  discoverPluginSkillFiles(pluginsCacheDir).forEach(skillFile => {
260
355
  const pluginName = pluginNameForSkillFile(skillFile, pluginsCacheDir);
356
+ addCommand(commands, {
357
+ command: `plugin:${pluginName}`,
358
+ label: commandLabel(pluginName),
359
+ description: 'Codex plugin',
360
+ source: 'plugin',
361
+ scope: 'Plugin',
362
+ });
261
363
  addSkillMention(commands, skillFile, {
262
364
  mentionPrefix: pluginName,
263
365
  fallbackName: path.basename(path.dirname(skillFile)),
@@ -278,6 +380,40 @@ function discoverCodexSkillMentions({ homeDir = os.homedir(), workspace } = {})
278
380
  return commands.slice(0, MAX_DISCOVERED_SKILLS);
279
381
  }
280
382
 
383
+ function discoverAgentExtensions({
384
+ provider,
385
+ providerHomePath,
386
+ workspace,
387
+ homeDir = os.homedir(),
388
+ } = {}) {
389
+ const normalizedProvider = normalizeProvider(provider);
390
+ const homePath = normalizeWorkspace(providerHomePath);
391
+ const normalizedHomeDir = normalizeWorkspace(homeDir) || os.homedir();
392
+ if (!normalizedProvider || !homePath) return [];
393
+
394
+ const commands = [];
395
+ if (normalizedProvider === 'claude') {
396
+ const normalizedWorkspace = normalizeWorkspace(workspace);
397
+ if (normalizedWorkspace) {
398
+ discoverClaudeSkillCommands(commands, path.join(normalizedWorkspace, '.claude', 'skills'), 'workspace');
399
+ discoverClaudeCustomCommands(commands, path.join(normalizedWorkspace, '.claude', 'commands'), 'workspace');
400
+ }
401
+ discoverClaudeSkillCommands(commands, path.join(homePath, 'skills'), 'home');
402
+ discoverClaudeCustomCommands(commands, path.join(homePath, 'commands'), 'home');
403
+ discoverClaudeInstalledPlugins(commands, homePath);
404
+ return commands.slice(0, MAX_DISCOVERED_SKILLS);
405
+ }
406
+
407
+ workspaceSkillRoots(workspace, normalizedHomeDir)
408
+ .forEach(root => discoverDirectCodexSkills(commands, root, 'Repo'));
409
+ discoverDirectCodexSkills(commands, path.join(normalizedHomeDir, '.agents', 'skills'), 'Personal');
410
+ discoverDirectCodexSkills(commands, path.join(homePath, 'skills'), 'Personal');
411
+ discoverDirectCodexSkills(commands, path.join(homePath, 'skills', '.system'), 'System');
412
+ discoverDirectCodexSkills(commands, path.join('/etc', 'codex', 'skills'), 'Admin');
413
+ discoverCodexPluginSkillsAt(commands, path.join(homePath, 'plugins', 'cache'));
414
+ return commands.slice(0, MAX_DISCOVERED_SKILLS);
415
+ }
416
+
281
417
  function discoverSlashCommands({ provider, homeDir = os.homedir(), workspace } = {}) {
282
418
  const normalizedProvider = normalizeProvider(provider);
283
419
  if (normalizedProvider === 'codex') {
@@ -290,6 +426,7 @@ function discoverSlashCommands({ provider, homeDir = os.homedir(), workspace } =
290
426
  }
291
427
 
292
428
  module.exports = {
429
+ discoverAgentExtensions,
293
430
  discoverSlashCommands,
294
431
  discoverClaudeSlashCommands,
295
432
  discoverCodexSkillMentions,
@@ -61,6 +61,30 @@ function browserProfileDir(configDir, browserId) {
61
61
  return path.join(browserResourcesDir(configDir), browserId, 'profile');
62
62
  }
63
63
 
64
+ function runtimeDependenciesDir(configDir) {
65
+ return path.join(configDir, 'runtimes');
66
+ }
67
+
68
+ function runtimeDependenciesActiveFile(configDir) {
69
+ return path.join(runtimeDependenciesDir(configDir), 'active.json');
70
+ }
71
+
72
+ function runtimeDependenciesLockDir(configDir) {
73
+ return path.join(runtimeDependenciesDir(configDir), '.prepare.lock');
74
+ }
75
+
76
+ function managedChromiumRootDir(configDir) {
77
+ return path.join(runtimeDependenciesDir(configDir), 'chromium');
78
+ }
79
+
80
+ function managedChromiumVersionDir(configDir, agentBrowserVersion, platformKey) {
81
+ return path.join(managedChromiumRootDir(configDir), agentBrowserVersion, platformKey);
82
+ }
83
+
84
+ function managedChromiumInstallLockDir(configDir) {
85
+ return path.join(managedChromiumRootDir(configDir), '.install.lock');
86
+ }
87
+
64
88
  function farmingAgentBootstrapFile(configDir) {
65
89
  return path.join(configDir, 'farming-agent-bootstrap.zh_cn.md');
66
90
  }
@@ -152,6 +176,12 @@ module.exports = {
152
176
  farmingNetTrustFile,
153
177
  farmingConfigDir,
154
178
  historyDir,
179
+ managedChromiumInstallLockDir,
180
+ managedChromiumRootDir,
181
+ managedChromiumVersionDir,
182
+ runtimeDependenciesActiveFile,
183
+ runtimeDependenciesDir,
184
+ runtimeDependenciesLockDir,
155
185
  nativePtyControllerGenerationFile,
156
186
  nativePtyControllerGenerationLockDir,
157
187
  nativePtyHostLogFile,