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.
- package/README.md +27 -90
- package/README.zh_cn.md +17 -90
- package/THIRD_PARTY_NOTICES.md +25 -6
- package/backend/acp/packaged-claude-acp.js +13 -0
- package/backend/acp/packaged-codex-acp.js +2 -2
- package/backend/acp-runtime.js +38 -17
- package/backend/acp-session-state.js +78 -88
- package/backend/acp-transcript.js +174 -9
- package/backend/agent-manager.js +27 -2
- package/backend/agent-session-history.js +45 -12
- package/backend/codex-session-history.js +1 -1
- package/backend/codex-transcript.js +0 -202
- package/backend/config-manager.js +44 -16
- package/backend/data/LICENSE.agent-browser +201 -0
- package/backend/data/runtime-dependency-manifest.json +199 -0
- package/backend/data/runtime-dependency-sources.json +5 -0
- package/backend/executable-discovery.js +7 -0
- package/backend/farming-agent-bootstrap.zh_cn.md +4 -2
- package/backend/farming-app-cli.js +161 -65
- package/backend/farming-cli.js +7 -59
- package/backend/index-html.js +31 -0
- package/backend/main-agent-skills.js +7 -28
- package/backend/npm-update-helper.js +43 -6
- package/backend/provider-adapters.js +10 -0
- package/backend/runtime-dependency-manager.js +759 -0
- package/backend/runtime-executable-invocation.js +20 -0
- package/backend/server-process-identity.js +47 -0
- package/backend/server.js +145 -204
- package/backend/slash-command-discovery.js +138 -1
- package/backend/storage-layout.js +30 -0
- package/backend/update-service.js +60 -914
- package/config/farming.deploy.env.example +1 -1
- package/config/farming.install.env.example +5 -1
- package/dist/acp/LICENSE.claude-agent-acp +191 -0
- package/dist/acp/LICENSE.claude-agent-sdk +1 -0
- package/dist/acp/claude-agent-acp-0.59.0.mjs +41606 -0
- package/dist/acp/{codex-acp-1.1.4.js → codex-acp-1.1.4.mjs} +387 -7
- package/dist/assets/{App-CM7Cy-l4.css → App-BKNUILuL.css} +1 -1
- package/dist/assets/App-Z1N7T0eM.js +695 -0
- package/dist/assets/{FileEditorMarkdownPreview-DYOMm-b1.js → FileEditorMarkdownPreview-Cs9cLv8a.js} +1 -1
- package/dist/assets/FileEditorPane-CNtuGjQ3.js +2 -0
- package/dist/assets/IconGlyphs-BClgag6E.js +1 -0
- package/dist/assets/ProjectFilesSection-K3GHuQ4U.js +12 -0
- package/dist/assets/ReviewPage-BRuxFaH5.js +3 -0
- package/dist/assets/code-dark-kLsQLvpf.css +1 -0
- package/dist/assets/{index-BzQO3pUr.js → index-D-zetSol.js} +2 -2
- package/dist/assets/main-DUTz-Rd2.css +1 -0
- package/dist/assets/{workspace-editor-monaco-tXA-udGx.js → workspace-editor-monaco-CJNwbpCy.js} +1 -1
- package/dist/assets/workspace-editor-monaco-CO9w8YV0.js +1 -0
- package/dist/assets/workspace-view-state-BjKPYp0E.js +7 -0
- package/dist/index.html +33 -3
- package/extensions/browser/backend/agent-browser-runtime.js +1041 -0
- package/extensions/browser/backend/browser-mcp-server.js +352 -0
- package/extensions/browser/backend/browser-resource-manager.js +921 -114
- package/extensions/browser/backend/browser-resource-store.js +47 -6
- package/extensions/browser/backend/browser-router.js +15 -2
- package/extensions/browser/backend/executable-discovery.js +164 -17
- package/extensions/browser/backend/managed-chromium-installer.js +593 -0
- package/extensions/browser/bin/farming-browser +384 -30
- package/extensions/browser/frontend/BrowserSidebarPortals.tsx +17 -19
- package/extensions/browser/frontend/BrowserViewer.tsx +217 -46
- package/extensions/browser/frontend/browser.css +68 -17
- package/extensions/browser/frontend/types.ts +13 -0
- package/extensions/browser/frontend/useBrowserResources.ts +18 -3
- package/index.html +32 -2
- package/package.json +10 -6
- package/shared/backend-connection-status.d.ts +12 -0
- package/shared/backend-connection-status.js +35 -4
- package/backend/agent-activity.js +0 -35
- package/backend/agent-memory-report.js +0 -583
- package/backend/bundle-update-helper.js +0 -113
- package/backend/codex-rollout-follower.js +0 -326
- package/dist/assets/App-CPG4WcjO.js +0 -658
- package/dist/assets/FileEditorPane-DXXq82aM.js +0 -2
- package/dist/assets/IconGlyphs-DrdPjYXr.js +0 -1
- package/dist/assets/ProjectFilesSection-CP66XVPl.js +0 -12
- package/dist/assets/ReviewPage-w21MEPD6.js +0 -3
- package/dist/assets/code-dark-BDjwj7Um.css +0 -1
- package/dist/assets/main-BlVUXfxa.css +0 -1
- package/dist/assets/workspace-editor-monaco-CFEfFNcA.js +0 -1
- package/dist/assets/workspace-view-state-BS_V8JVs.js +0 -7
- package/extensions/browser/backend/cdp-browser-runtime.js +0 -648
- 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,
|