farming-code 2.2.20 → 2.2.22
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 +5 -5
- package/README.zh_cn.md +5 -5
- package/THIRD_PARTY_NOTICES.md +5 -8
- package/backend/acp/client-services.js +37 -5
- package/backend/acp/patch-decisions.js +19 -3
- package/backend/acp-runtime.js +1201 -198
- package/backend/acp-transcript.js +66 -0
- package/backend/agent-lifecycle-journal.js +133 -0
- package/backend/agent-manager.js +2715 -354
- package/backend/agent-order.js +8 -4
- package/backend/agent-runtime-binding.js +1 -0
- package/backend/bundle-update-helper.js +5 -1
- package/backend/config-manager.js +16 -0
- package/backend/control-api.js +146 -20
- package/backend/farming-app-cli.js +335 -10
- package/backend/farming-session-store.js +283 -36
- package/backend/json-cli-runtime.js +120 -6
- package/backend/npm-update-helper.js +97 -18
- package/backend/provider-adapters.js +18 -6
- package/backend/review-session-service.js +31 -17
- package/backend/server.js +332 -102
- package/backend/storage-layout.js +10 -0
- package/backend/theme-manager.js +23 -5
- package/backend/update-service.js +239 -27
- package/backend/workspace-file-router.js +9 -3
- package/backend/workspace-file-service.js +292 -62
- package/dist/acp/codex-acp-1.1.4.js +32 -1
- package/dist/assets/App-CmZdNavW.js +210 -0
- package/dist/assets/{FileEditorMarkdownPreview-R0jwwLME.js → FileEditorMarkdownPreview-KbnE8VC8.js} +1 -1
- package/dist/assets/FileEditorPane-5_HUejjd.js +2 -0
- package/dist/assets/IconGlyphs-C2WFcoJS.js +1 -0
- package/dist/assets/ProjectFilesSection-C1RAJWOE.js +12 -0
- package/dist/assets/{ReviewPage-DBKNOWsJ.js → ReviewPage-L1vh1Ggs.js} +3 -3
- package/dist/assets/code-dark-BKtvf0Xc.css +1 -0
- package/dist/assets/file-icons-CHWt5nSy.js +1 -0
- package/dist/assets/{index-DuMjesL2.js → index-RvUiMpGP.js} +2 -2
- package/dist/assets/main-XMXgyJJt.css +1 -0
- package/dist/assets/workspace-view-state-BqB4HM7r.js +7 -0
- package/dist/index.html +1 -1
- package/frontend/skins/crt/app.js +199 -81
- package/package.json +9 -3
- package/dist/assets/App-BupehIbc.js +0 -210
- package/dist/assets/FileEditorPane-CJs6kfZO.js +0 -2
- package/dist/assets/IconGlyphs-CZzDr5o2.js +0 -1
- package/dist/assets/ProjectFilesSection-DWCV07lA.js +0 -12
- package/dist/assets/code-dark-BAt0Q_Op.css +0 -1
- package/dist/assets/file-icons-DpbrD5ZP.js +0 -1
- package/dist/assets/main-y2aK_56c.css +0 -1
- package/dist/assets/workspace-view-state-BpPINu84.js +0 -7
|
@@ -3,6 +3,10 @@ const { createTwoFilesPatch, diffLines } = require('diff');
|
|
|
3
3
|
const MAX_RENDERED_DIFF_CHARS = 64 * 1024;
|
|
4
4
|
const MAX_INLINE_TOOL_DETAIL_CHARS = 4 * 1024;
|
|
5
5
|
const MAX_EMBEDDED_RESOURCE_TEXT_CHARS = 4 * 1024;
|
|
6
|
+
const MAX_COLLABORATION_AGENTS = 16;
|
|
7
|
+
const MAX_COLLABORATION_ID_CHARS = 160;
|
|
8
|
+
const MAX_COLLABORATION_PATH_CHARS = 512;
|
|
9
|
+
const MAX_COLLABORATION_MESSAGE_CHARS = 160;
|
|
6
10
|
|
|
7
11
|
function diffBlocks(content) {
|
|
8
12
|
return (Array.isArray(content) ? content : [])
|
|
@@ -232,6 +236,66 @@ function generatedMediaTool(entry) {
|
|
|
232
236
|
|| String(output.savedPath || '').includes('/generated_images/');
|
|
233
237
|
}
|
|
234
238
|
|
|
239
|
+
function boundedCollaborationString(value, maxChars) {
|
|
240
|
+
return String(value || '').trim().slice(0, maxChars);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function boundedCollaborationIds(value) {
|
|
244
|
+
const seen = new Set();
|
|
245
|
+
return (Array.isArray(value) ? value : []).flatMap(item => {
|
|
246
|
+
const id = boundedCollaborationString(item, MAX_COLLABORATION_ID_CHARS);
|
|
247
|
+
if (!id || seen.has(id) || seen.size >= MAX_COLLABORATION_AGENTS) return [];
|
|
248
|
+
seen.add(id);
|
|
249
|
+
return [id];
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function transcriptCodexToolMeta(entry) {
|
|
254
|
+
const codex = entry?._meta?.codex && typeof entry._meta.codex === 'object'
|
|
255
|
+
? entry._meta.codex
|
|
256
|
+
: {};
|
|
257
|
+
const compact = {};
|
|
258
|
+
if (codex.collaboration && typeof codex.collaboration === 'object') {
|
|
259
|
+
const rawInput = entry?.rawInput && typeof entry.rawInput === 'object' && !Array.isArray(entry.rawInput)
|
|
260
|
+
? entry.rawInput
|
|
261
|
+
: {};
|
|
262
|
+
const receiverThreadIds = boundedCollaborationIds(
|
|
263
|
+
codex.collaboration.receiverThreadIds || rawInput.receiverThreadIds
|
|
264
|
+
);
|
|
265
|
+
const rawStates = rawInput.agentsStates && typeof rawInput.agentsStates === 'object' && !Array.isArray(rawInput.agentsStates)
|
|
266
|
+
? rawInput.agentsStates
|
|
267
|
+
: {};
|
|
268
|
+
const agentsStates = {};
|
|
269
|
+
const stateIds = boundedCollaborationIds([...receiverThreadIds, ...Object.keys(rawStates)]);
|
|
270
|
+
for (const threadId of stateIds) {
|
|
271
|
+
const state = rawStates[threadId] && typeof rawStates[threadId] === 'object'
|
|
272
|
+
? rawStates[threadId]
|
|
273
|
+
: {};
|
|
274
|
+
agentsStates[threadId] = {
|
|
275
|
+
status: boundedCollaborationString(state.status, 32),
|
|
276
|
+
message: boundedCollaborationString(state.message, MAX_COLLABORATION_MESSAGE_CHARS),
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
compact.collaboration = {
|
|
280
|
+
tool: boundedCollaborationString(codex.collaboration.tool, 48),
|
|
281
|
+
senderThreadId: boundedCollaborationString(
|
|
282
|
+
codex.collaboration.senderThreadId || rawInput.senderThreadId,
|
|
283
|
+
MAX_COLLABORATION_ID_CHARS
|
|
284
|
+
),
|
|
285
|
+
receiverThreadIds,
|
|
286
|
+
agentsStates,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
if (codex.subagent && typeof codex.subagent === 'object') {
|
|
290
|
+
compact.subagent = {
|
|
291
|
+
threadId: boundedCollaborationString(codex.subagent.threadId, MAX_COLLABORATION_ID_CHARS),
|
|
292
|
+
path: boundedCollaborationString(codex.subagent.path, MAX_COLLABORATION_PATH_CHARS),
|
|
293
|
+
activity: boundedCollaborationString(codex.subagent.activity, 32),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
return Object.keys(compact).length > 0 ? compact : null;
|
|
297
|
+
}
|
|
298
|
+
|
|
235
299
|
function acpTranscriptToolEntry(entry) {
|
|
236
300
|
if (!entry || entry.type !== 'tool') return entry;
|
|
237
301
|
const detail = detailForTool(entry);
|
|
@@ -254,6 +318,8 @@ function acpTranscriptToolEntry(entry) {
|
|
|
254
318
|
if (entry?._meta?.farming_patch_decisions) {
|
|
255
319
|
meta.farming_patch_decisions = JSON.parse(JSON.stringify(entry._meta.farming_patch_decisions));
|
|
256
320
|
}
|
|
321
|
+
const codexMeta = transcriptCodexToolMeta(entry);
|
|
322
|
+
if (codexMeta) meta.codex = codexMeta;
|
|
257
323
|
return {
|
|
258
324
|
id: String(entry.id || ''),
|
|
259
325
|
type: 'tool',
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const MAX_LIFECYCLE_OPERATIONS = 32;
|
|
2
|
+
const TERMINAL_OPERATION_STATES = new Set(['succeeded', 'failed', 'cancelled']);
|
|
3
|
+
|
|
4
|
+
function compactLifecycleEntries(entries) {
|
|
5
|
+
const recentIds = new Set(entries.slice(-MAX_LIFECYCLE_OPERATIONS).map(operation => operation.id));
|
|
6
|
+
return entries.filter(operation => (
|
|
7
|
+
recentIds.has(operation.id)
|
|
8
|
+
|| operation.requestKey.startsWith('create-request:')
|
|
9
|
+
));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function normalizeOperation(operation) {
|
|
13
|
+
if (!operation || typeof operation !== 'object') return null;
|
|
14
|
+
const id = String(operation.id || '').trim();
|
|
15
|
+
const type = String(operation.type || '').trim();
|
|
16
|
+
const state = String(operation.state || '').trim();
|
|
17
|
+
if (!id || !type || !state) return null;
|
|
18
|
+
return {
|
|
19
|
+
id,
|
|
20
|
+
type,
|
|
21
|
+
state,
|
|
22
|
+
requestKey: String(operation.requestKey || ''),
|
|
23
|
+
request: operation.request && typeof operation.request === 'object'
|
|
24
|
+
? JSON.parse(JSON.stringify(operation.request))
|
|
25
|
+
: {},
|
|
26
|
+
result: operation.result && typeof operation.result === 'object'
|
|
27
|
+
? JSON.parse(JSON.stringify(operation.result))
|
|
28
|
+
: null,
|
|
29
|
+
startedAt: Number(operation.startedAt) || 0,
|
|
30
|
+
updatedAt: Number(operation.updatedAt) || 0,
|
|
31
|
+
finishedAt: Number(operation.finishedAt) || null,
|
|
32
|
+
error: String(operation.error || ''),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function lifecycleJournal(source) {
|
|
37
|
+
const raw = source?.lifecycleJournal;
|
|
38
|
+
const entries = Array.isArray(raw?.entries)
|
|
39
|
+
? compactLifecycleEntries(raw.entries.map(normalizeOperation).filter(Boolean))
|
|
40
|
+
: [];
|
|
41
|
+
return {
|
|
42
|
+
sequence: Math.max(0, Math.floor(Number(raw?.sequence) || 0)),
|
|
43
|
+
entries,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function activeLifecycleOperation(source) {
|
|
48
|
+
const journal = lifecycleJournal(source);
|
|
49
|
+
for (let index = journal.entries.length - 1; index >= 0; index -= 1) {
|
|
50
|
+
const operation = journal.entries[index];
|
|
51
|
+
if (!TERMINAL_OPERATION_STATES.has(operation.state)) return operation;
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function latestLifecycleOperation(source) {
|
|
57
|
+
const entries = lifecycleJournal(source).entries;
|
|
58
|
+
return entries.length > 0 ? entries[entries.length - 1] : null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function beginLifecycleOperation(source, type, requestKey, request = {}, now = Date.now()) {
|
|
62
|
+
const journal = lifecycleJournal(source);
|
|
63
|
+
const active = activeLifecycleOperation({ lifecycleJournal: journal });
|
|
64
|
+
if (active) {
|
|
65
|
+
if (active.type === type && active.requestKey === String(requestKey || '')) {
|
|
66
|
+
source.lifecycleJournal = journal;
|
|
67
|
+
return { operation: active, joined: true };
|
|
68
|
+
}
|
|
69
|
+
return { conflict: active };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
journal.sequence += 1;
|
|
73
|
+
const operation = {
|
|
74
|
+
id: `aop_${journal.sequence}`,
|
|
75
|
+
type: String(type || ''),
|
|
76
|
+
state: 'pending',
|
|
77
|
+
requestKey: String(requestKey || ''),
|
|
78
|
+
request: request && typeof request === 'object' ? JSON.parse(JSON.stringify(request)) : {},
|
|
79
|
+
result: null,
|
|
80
|
+
startedAt: now,
|
|
81
|
+
updatedAt: now,
|
|
82
|
+
finishedAt: null,
|
|
83
|
+
error: '',
|
|
84
|
+
};
|
|
85
|
+
journal.entries.push(operation);
|
|
86
|
+
journal.entries = compactLifecycleEntries(journal.entries);
|
|
87
|
+
source.lifecycleJournal = journal;
|
|
88
|
+
return { operation, joined: false };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function transitionLifecycleOperation(source, operationId, state, error = '', now = Date.now()) {
|
|
92
|
+
const journal = lifecycleJournal(source);
|
|
93
|
+
const operation = journal.entries.find(candidate => candidate.id === operationId);
|
|
94
|
+
if (!operation) return null;
|
|
95
|
+
if (TERMINAL_OPERATION_STATES.has(operation.state)) return operation;
|
|
96
|
+
operation.state = String(state || operation.state);
|
|
97
|
+
operation.error = String(error || '');
|
|
98
|
+
operation.updatedAt = now;
|
|
99
|
+
operation.finishedAt = TERMINAL_OPERATION_STATES.has(operation.state) ? now : null;
|
|
100
|
+
if (
|
|
101
|
+
operation.type === 'create'
|
|
102
|
+
&& operation.finishedAt !== null
|
|
103
|
+
&& operation.request
|
|
104
|
+
&& Object.prototype.hasOwnProperty.call(operation.request, 'previousState')
|
|
105
|
+
) {
|
|
106
|
+
delete operation.request.previousState;
|
|
107
|
+
}
|
|
108
|
+
source.lifecycleJournal = journal;
|
|
109
|
+
return operation;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function setLifecycleOperationResult(source, operationId, result, now = Date.now()) {
|
|
113
|
+
const journal = lifecycleJournal(source);
|
|
114
|
+
const operation = journal.entries.find(candidate => candidate.id === operationId);
|
|
115
|
+
if (!operation) return null;
|
|
116
|
+
operation.result = result && typeof result === 'object'
|
|
117
|
+
? JSON.parse(JSON.stringify(result))
|
|
118
|
+
: null;
|
|
119
|
+
operation.updatedAt = now;
|
|
120
|
+
source.lifecycleJournal = journal;
|
|
121
|
+
return operation;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
module.exports = {
|
|
125
|
+
MAX_LIFECYCLE_OPERATIONS,
|
|
126
|
+
TERMINAL_OPERATION_STATES,
|
|
127
|
+
activeLifecycleOperation,
|
|
128
|
+
beginLifecycleOperation,
|
|
129
|
+
latestLifecycleOperation,
|
|
130
|
+
lifecycleJournal,
|
|
131
|
+
setLifecycleOperationResult,
|
|
132
|
+
transitionLifecycleOperation,
|
|
133
|
+
};
|