@agent-spaces/server 0.3.0 → 0.3.2
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/dist/adapters/claude-code-runtime/index.js +48 -6
- package/dist/adapters/claude-code-runtime/message-format.js +3 -3
- package/dist/adapters/git.js +140 -2
- package/dist/agents/agent-designer.js +334 -0
- package/dist/agents/agent-message-parts.js +8 -0
- package/dist/agents/commit-agent.js +9 -2
- package/dist/agents/issue-agent-runner.js +0 -1
- package/dist/agents/issue-task-controller.js +14 -4
- package/dist/app.js +51 -1
- package/dist/package.json +1 -1
- package/dist/routes/agent-sse.js +4 -1
- package/dist/routes/agent.js +15 -0
- package/dist/routes/channel.js +1 -1
- package/dist/routes/file.js +97 -1
- package/dist/routes/git.js +122 -1
- package/dist/routes/iframe-bookmarks.js +33 -0
- package/dist/routes/issue.js +12 -0
- package/dist/routes/speech-recognition.js +99 -0
- package/dist/services/agent.js +48 -5
- package/dist/services/builtin-tools.js +67 -1
- package/dist/services/channel.js +2 -0
- package/dist/services/command-process-manager.js +14 -1
- package/dist/services/file.js +86 -6
- package/dist/services/gitignore.js +65 -0
- package/dist/services/issue-retry.js +2 -1
- package/dist/services/issue.js +13 -4
- package/dist/services/notification-hub/bot-agent.js +9 -1
- package/dist/services/persistent-agent-context.js +155 -0
- package/dist/services/pty.js +47 -2
- package/dist/services/search.js +11 -3
- package/dist/services/speech-recognition/base.js +3 -0
- package/dist/services/speech-recognition/index.js +16 -0
- package/dist/services/speech-recognition/tencent.js +117 -0
- package/dist/storage/iframe-bookmarks-store.js +46 -0
- package/dist/storage/speech-recognition-store.js +61 -0
- package/dist/web/404.html +1 -1
- package/dist/web/__next.__PAGE__.txt +4 -4
- package/dist/web/__next._full.txt +31 -26
- package/dist/web/__next._head.txt +4 -4
- package/dist/web/__next._index.txt +17 -13
- package/dist/web/__next._tree.txt +2 -2
- package/dist/web/_next/static/chunks/00amm3dvu3po9.js +31 -0
- package/dist/web/_next/static/chunks/01hrib8z5bn-6.js +5 -0
- package/dist/web/_next/static/chunks/08nbjuc5i-ewu.js +3 -0
- package/dist/web/_next/static/chunks/0anuxr11yn5iv.js +2 -0
- package/dist/web/_next/static/chunks/0cxrev-hb8gkk.js +2 -0
- package/dist/web/_next/static/chunks/0egot8y~i-ge3.js +1 -0
- package/dist/web/_next/static/chunks/0e~0o6v_awcod.js +1 -0
- package/dist/web/_next/static/chunks/0f_dcx0nu5z7o.js +1 -0
- package/dist/web/_next/static/chunks/0fpf.rso9mhc0.js +1 -0
- package/dist/web/_next/static/chunks/0jc-4igj54z00.js +189 -0
- package/dist/web/_next/static/chunks/0plreh4_gkxf9.js +1 -0
- package/dist/web/_next/static/chunks/0u7_qd9hzqwac.js +1 -0
- package/dist/web/_next/static/chunks/0uo5x.bu.5u2-.css +1 -0
- package/dist/web/_next/static/chunks/0utxlfbckz4f5.js +1 -0
- package/dist/web/_next/static/chunks/0vesz93a98px4.js +1 -0
- package/dist/web/_next/static/chunks/0w1iudd1d46sw.js +8 -0
- package/dist/web/_next/static/chunks/0w3o.7vi.dlm6.js +1 -0
- package/dist/web/_next/static/chunks/0xtmr0y4vo-~p.js +1 -0
- package/dist/web/_next/static/chunks/11ozf700niy2z.js +1 -0
- package/dist/web/_next/static/chunks/{0jmsjlawtg6oa.js → 145gbwitjxamg.js} +1 -1
- package/dist/web/_next/static/chunks/{turbopack-0lxiiw.jhevml.js → turbopack-0kcwat8.leugk.js} +1 -1
- package/dist/web/_not-found/__next._full.txt +34 -30
- package/dist/web/_not-found/__next._head.txt +4 -4
- package/dist/web/_not-found/__next._index.txt +17 -13
- package/dist/web/_not-found/__next._not-found.__PAGE__.txt +2 -2
- package/dist/web/_not-found/__next._not-found.txt +3 -3
- package/dist/web/_not-found/__next._tree.txt +2 -2
- package/dist/web/_not-found.html +1 -1
- package/dist/web/_not-found.txt +34 -30
- package/dist/web/index.html +1 -1
- package/dist/web/index.txt +31 -26
- package/dist/web/login/__next._full.txt +35 -29
- package/dist/web/login/__next._head.txt +4 -4
- package/dist/web/login/__next._index.txt +17 -13
- package/dist/web/login/__next._tree.txt +2 -2
- package/dist/web/login/__next.login.__PAGE__.txt +4 -4
- package/dist/web/login/__next.login.txt +3 -3
- package/dist/web/login.html +1 -1
- package/dist/web/login.txt +35 -29
- package/dist/web/settings/__next._full.txt +36 -34
- package/dist/web/settings/__next._head.txt +4 -4
- package/dist/web/settings/__next._index.txt +17 -13
- package/dist/web/settings/__next._tree.txt +2 -2
- package/dist/web/settings/__next.settings.__PAGE__.txt +4 -4
- package/dist/web/settings/__next.settings.txt +5 -5
- package/dist/web/settings/agents/__next._full.txt +38 -35
- package/dist/web/settings/agents/__next._head.txt +4 -4
- package/dist/web/settings/agents/__next._index.txt +17 -13
- package/dist/web/settings/agents/__next._tree.txt +2 -2
- package/dist/web/settings/agents/__next.settings.agents.__PAGE__.txt +4 -4
- package/dist/web/settings/agents/__next.settings.agents.txt +3 -3
- package/dist/web/settings/agents/__next.settings.txt +5 -5
- package/dist/web/settings/agents.html +1 -1
- package/dist/web/settings/agents.txt +38 -35
- package/dist/web/settings/mcps/__next._full.txt +38 -35
- package/dist/web/settings/mcps/__next._head.txt +4 -4
- package/dist/web/settings/mcps/__next._index.txt +17 -13
- package/dist/web/settings/mcps/__next._tree.txt +2 -2
- package/dist/web/settings/mcps/__next.settings.mcps.__PAGE__.txt +4 -4
- package/dist/web/settings/mcps/__next.settings.mcps.txt +3 -3
- package/dist/web/settings/mcps/__next.settings.txt +5 -5
- package/dist/web/settings/mcps.html +1 -1
- package/dist/web/settings/mcps.txt +38 -35
- package/dist/web/settings/models/__next._full.txt +38 -35
- package/dist/web/settings/models/__next._head.txt +4 -4
- package/dist/web/settings/models/__next._index.txt +17 -13
- package/dist/web/settings/models/__next._tree.txt +2 -2
- package/dist/web/settings/models/__next.settings.models.__PAGE__.txt +4 -4
- package/dist/web/settings/models/__next.settings.models.txt +3 -3
- package/dist/web/settings/models/__next.settings.txt +5 -5
- package/dist/web/settings/models.html +1 -1
- package/dist/web/settings/models.txt +38 -35
- package/dist/web/settings/providers/__next._full.txt +38 -35
- package/dist/web/settings/providers/__next._head.txt +4 -4
- package/dist/web/settings/providers/__next._index.txt +17 -13
- package/dist/web/settings/providers/__next._tree.txt +2 -2
- package/dist/web/settings/providers/__next.settings.providers.__PAGE__.txt +4 -4
- package/dist/web/settings/providers/__next.settings.providers.txt +3 -3
- package/dist/web/settings/providers/__next.settings.txt +5 -5
- package/dist/web/settings/providers.html +1 -1
- package/dist/web/settings/providers.txt +38 -35
- package/dist/web/settings/skills/__next._full.txt +38 -35
- package/dist/web/settings/skills/__next._head.txt +4 -4
- package/dist/web/settings/skills/__next._index.txt +17 -13
- package/dist/web/settings/skills/__next._tree.txt +2 -2
- package/dist/web/settings/skills/__next.settings.skills.__PAGE__.txt +4 -4
- package/dist/web/settings/skills/__next.settings.skills.txt +3 -3
- package/dist/web/settings/skills/__next.settings.txt +5 -5
- package/dist/web/settings/skills.html +1 -1
- package/dist/web/settings/skills.txt +38 -35
- package/dist/web/settings.html +1 -1
- package/dist/web/settings.txt +36 -34
- package/dist/web/workflows/__next._full.txt +36 -31
- package/dist/web/workflows/__next._head.txt +4 -4
- package/dist/web/workflows/__next._index.txt +17 -13
- package/dist/web/workflows/__next._tree.txt +2 -2
- package/dist/web/workflows/__next.workflows.__PAGE__.txt +4 -4
- package/dist/web/workflows/__next.workflows.txt +3 -3
- package/dist/web/workflows.html +1 -1
- package/dist/web/workflows.txt +36 -31
- package/dist/web/workspace/_/__next._full.txt +39 -34
- package/dist/web/workspace/_/__next._head.txt +4 -4
- package/dist/web/workspace/_/__next._index.txt +17 -13
- package/dist/web/workspace/_/__next._tree.txt +2 -2
- package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +3 -3
- package/dist/web/workspace/_/__next.workspace.$d$id.txt +3 -3
- package/dist/web/workspace/_/__next.workspace.txt +3 -3
- package/dist/web/workspace/_.html +1 -1
- package/dist/web/workspace/_.txt +39 -34
- package/dist/web/workspaces/__next._full.txt +35 -30
- package/dist/web/workspaces/__next._head.txt +4 -4
- package/dist/web/workspaces/__next._index.txt +17 -13
- package/dist/web/workspaces/__next._tree.txt +2 -2
- package/dist/web/workspaces/__next.workspaces.__PAGE__.txt +4 -4
- package/dist/web/workspaces/__next.workspaces.txt +3 -3
- package/dist/web/workspaces.html +1 -1
- package/dist/web/workspaces.txt +35 -30
- package/dist/ws/agent-prompt.js +48 -18
- package/dist/ws/agent-runner.js +10 -3
- package/dist/ws/message-parts.js +8 -0
- package/dist/ws/terminal-handler.js +1 -1
- package/package.json +1 -1
- package/public/avatars/1778953228323-5je54x-user.jpg +0 -0
- package/public/avatars/1778954057880-g01q6y-user.jpg +0 -0
- package/dist/web/_next/static/chunks/002-dxhags4dj.js +0 -2
- package/dist/web/_next/static/chunks/00fu7sjtftd3f.js +0 -1
- package/dist/web/_next/static/chunks/00s_1ft2-qz0r.js +0 -1
- package/dist/web/_next/static/chunks/02wkg1tjv~_t2.js +0 -1
- package/dist/web/_next/static/chunks/03jy~o.gx._e-.js +0 -3
- package/dist/web/_next/static/chunks/07bs5ds68tg38.js +0 -2
- package/dist/web/_next/static/chunks/0b1w9_ne4c2ez.js +0 -1
- package/dist/web/_next/static/chunks/0bzechrx76-ix.js +0 -1
- package/dist/web/_next/static/chunks/0csqa76ud3h4d.js +0 -1
- package/dist/web/_next/static/chunks/0fxdvo63ywaa~.js +0 -1
- package/dist/web/_next/static/chunks/0k5bmi-es-2nj.js +0 -1
- package/dist/web/_next/static/chunks/0pep4mkvt3.rh.js +0 -31
- package/dist/web/_next/static/chunks/0tqwdxb-8t_n1.js +0 -1
- package/dist/web/_next/static/chunks/0y5ipuqgqfrob.js +0 -8
- package/dist/web/_next/static/chunks/0yc41k980zabo.js +0 -1
- package/dist/web/_next/static/chunks/0zhhkzv4.0koq.js +0 -183
- package/dist/web/_next/static/chunks/0zl19l5tuoppw.js +0 -1
- package/dist/web/_next/static/chunks/102lz3yanx8i~.css +0 -1
- package/dist/web/_next/static/chunks/13wm9.vry~.lh.js +0 -5
- /package/dist/web/_next/static/{XzP71HbFE1fuE_bLT-x7i → 9X6R42UNn3h4WL_zj_Yh4}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{XzP71HbFE1fuE_bLT-x7i → 9X6R42UNn3h4WL_zj_Yh4}/_clientMiddlewareManifest.js +0 -0
- /package/dist/web/_next/static/{XzP71HbFE1fuE_bLT-x7i → 9X6R42UNn3h4WL_zj_Yh4}/_ssgManifest.js +0 -0
|
@@ -36,6 +36,7 @@ export class ClaudeCodeRuntime {
|
|
|
36
36
|
d(`starting | cwd=${cwd} model=${model ?? 'default'} targetModel=${this.config.model ?? 'default'} provider=${this.config.provider ?? 'default'} baseURL=${baseURL ?? 'default'} permissionMode=${permissionMode} maxTurns=${options?.maxTurns ?? '∞'} tools=claude_code mcpServers=${Object.keys(options?.mcpServers ?? {}).join(',') || '-'} skills=${skillNames.join(',') || '-'} configDir=${configDir ?? 'default'} sandboxDirs=${additionalDirectories.join(',') || '-'} claudeExecutable=${claudeExecutable ?? 'sdk-default'}`);
|
|
37
37
|
d(`prompt: ${prompt.slice(0, 300)}${prompt.length > 300 ? '...' : ''}`);
|
|
38
38
|
d(`sdk mcp servers | ${sdkMcpServerNames.join(',') || '-'}`);
|
|
39
|
+
const stderrLines = [];
|
|
39
40
|
try {
|
|
40
41
|
const queryOptions = {
|
|
41
42
|
cwd,
|
|
@@ -48,7 +49,7 @@ export class ClaudeCodeRuntime {
|
|
|
48
49
|
managedSettings: {
|
|
49
50
|
strictPluginOnlyCustomization: ['mcp'],
|
|
50
51
|
},
|
|
51
|
-
settingSources: [],
|
|
52
|
+
settingSources: ['user', 'project', 'local'],
|
|
52
53
|
strictMcpConfig: true,
|
|
53
54
|
additionalDirectories,
|
|
54
55
|
permissionMode,
|
|
@@ -57,8 +58,10 @@ export class ClaudeCodeRuntime {
|
|
|
57
58
|
env: buildEnv(this.config, configDir, { baseURL, apiKey }),
|
|
58
59
|
stderr: (data) => {
|
|
59
60
|
const line = data.trim();
|
|
60
|
-
if (line)
|
|
61
|
+
if (line) {
|
|
62
|
+
stderrLines.push(line);
|
|
61
63
|
d(`stderr: ${line}`);
|
|
64
|
+
}
|
|
62
65
|
},
|
|
63
66
|
};
|
|
64
67
|
this.activeQuery = query({ prompt, options: queryOptions });
|
|
@@ -69,6 +72,7 @@ export class ClaudeCodeRuntime {
|
|
|
69
72
|
let usageLine = null;
|
|
70
73
|
let usage;
|
|
71
74
|
let costUsd;
|
|
75
|
+
let sawResult = false;
|
|
72
76
|
const pendingAskUserQuestionToolIds = new Set();
|
|
73
77
|
let waitingForUserAnswer = false;
|
|
74
78
|
for await (const message of this.activeQuery) {
|
|
@@ -106,6 +110,7 @@ export class ClaudeCodeRuntime {
|
|
|
106
110
|
options?.onEvent?.({ type: 'output', line });
|
|
107
111
|
}
|
|
108
112
|
if (message.type === 'result') {
|
|
113
|
+
sawResult = true;
|
|
109
114
|
turns = message.num_turns;
|
|
110
115
|
tokenCount = countUsageTokens(message.usage);
|
|
111
116
|
usageLine = formatUsageLine(message.usage);
|
|
@@ -122,6 +127,22 @@ export class ClaudeCodeRuntime {
|
|
|
122
127
|
}
|
|
123
128
|
}
|
|
124
129
|
const elapsed = Date.now() - startTime;
|
|
130
|
+
if (!sawResult) {
|
|
131
|
+
const runtimeError = extractRuntimeError([...stderrLines, ...output])
|
|
132
|
+
|| 'Claude Code execution stopped before reporting a final result';
|
|
133
|
+
d(`failed ${elapsed}ms | turns=${turns} tokens=${tokenCount} | ${runtimeError}`);
|
|
134
|
+
appendUnique(output, stderrLines);
|
|
135
|
+
appendUnique(output, [runtimeError]);
|
|
136
|
+
return {
|
|
137
|
+
success: false,
|
|
138
|
+
summary: 'Claude Code execution failed',
|
|
139
|
+
artifacts: [],
|
|
140
|
+
error: runtimeError,
|
|
141
|
+
output,
|
|
142
|
+
usage,
|
|
143
|
+
costUsd,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
125
146
|
if (waitingForUserAnswer && (!error || isAskUserQuestionAutoResult(error))) {
|
|
126
147
|
d(`waiting for user answer ${elapsed}ms | turns=${turns} tokens=${tokenCount}`);
|
|
127
148
|
if (usageLine)
|
|
@@ -136,14 +157,16 @@ export class ClaudeCodeRuntime {
|
|
|
136
157
|
};
|
|
137
158
|
}
|
|
138
159
|
if (error) {
|
|
139
|
-
|
|
160
|
+
const runtimeError = extractRuntimeError([error, ...stderrLines, ...output]) || error;
|
|
161
|
+
d(`failed ${elapsed}ms | turns=${turns} tokens=${tokenCount} | ${runtimeError}`);
|
|
162
|
+
appendUnique(output, stderrLines);
|
|
140
163
|
if (usageLine)
|
|
141
164
|
output.push(usageLine);
|
|
142
165
|
return {
|
|
143
166
|
success: false,
|
|
144
167
|
summary: 'Claude Code execution failed',
|
|
145
168
|
artifacts: [],
|
|
146
|
-
error,
|
|
169
|
+
error: runtimeError,
|
|
147
170
|
output,
|
|
148
171
|
usage,
|
|
149
172
|
costUsd,
|
|
@@ -169,10 +192,13 @@ export class ClaudeCodeRuntime {
|
|
|
169
192
|
catch (err) {
|
|
170
193
|
const elapsed = Date.now() - startTime;
|
|
171
194
|
const message = err instanceof Error ? err.message : String(err);
|
|
172
|
-
|
|
195
|
+
const runtimeError = extractRuntimeError([message, ...stderrLines, ...output]) || message;
|
|
196
|
+
d(`failed ${elapsed}ms | ${runtimeError}`);
|
|
173
197
|
if (err instanceof Error && err.stack)
|
|
174
198
|
console.error(err.stack);
|
|
175
|
-
|
|
199
|
+
appendUnique(output, stderrLines);
|
|
200
|
+
appendUnique(output, [runtimeError]);
|
|
201
|
+
return { success: false, summary: 'Claude Code execution failed', artifacts: [], error: runtimeError, output };
|
|
176
202
|
}
|
|
177
203
|
finally {
|
|
178
204
|
this.activeQuery?.close();
|
|
@@ -195,4 +221,20 @@ function readTotalCostUsd(message) {
|
|
|
195
221
|
const value = message.total_cost_usd;
|
|
196
222
|
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
197
223
|
}
|
|
224
|
+
function extractRuntimeError(lines) {
|
|
225
|
+
const text = lines
|
|
226
|
+
.filter((line) => typeof line === 'string' && line.trim().length > 0)
|
|
227
|
+
.join('\n');
|
|
228
|
+
if (!text)
|
|
229
|
+
return undefined;
|
|
230
|
+
const match = text.match(/(?:API Error|Request rejected|Too Many Requests|rate limit|overloaded|429)[^\n]*/i);
|
|
231
|
+
return match?.[0]?.trim();
|
|
232
|
+
}
|
|
233
|
+
function appendUnique(target, lines) {
|
|
234
|
+
for (const line of lines) {
|
|
235
|
+
if (!line || target.includes(line))
|
|
236
|
+
continue;
|
|
237
|
+
target.push(line);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
198
240
|
//# sourceMappingURL=index.js.map
|
|
@@ -5,9 +5,9 @@ export function formatMessage(message) {
|
|
|
5
5
|
case 'result':
|
|
6
6
|
return message.subtype === 'success' ? message.result : message.errors.join('\n');
|
|
7
7
|
case 'system':
|
|
8
|
-
if (message.subtype === 'init') {
|
|
9
|
-
|
|
10
|
-
}
|
|
8
|
+
// if (message.subtype === 'init') {
|
|
9
|
+
// return `Claude Code initialized with ${message.model}`;
|
|
10
|
+
// }
|
|
11
11
|
if (message.subtype === 'task_started') {
|
|
12
12
|
return message.description;
|
|
13
13
|
}
|
package/dist/adapters/git.js
CHANGED
|
@@ -50,6 +50,8 @@ function mapStatus(raw) {
|
|
|
50
50
|
ahead: raw.ahead,
|
|
51
51
|
behind: raw.behind,
|
|
52
52
|
clean: raw.isClean(),
|
|
53
|
+
insertions: 0,
|
|
54
|
+
deletions: 0,
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
57
|
function mapStatusCode(code) {
|
|
@@ -67,7 +69,39 @@ export async function gitStatus(workspaceId) {
|
|
|
67
69
|
throw new Error('Workspace not found');
|
|
68
70
|
const git = getGit(ws);
|
|
69
71
|
const raw = await git.status();
|
|
70
|
-
|
|
72
|
+
const result = mapStatus(raw);
|
|
73
|
+
if (!result.clean) {
|
|
74
|
+
try {
|
|
75
|
+
// Tracked changes: modified/deleted/renamed
|
|
76
|
+
const trackedStat = await git.diff(['--shortstat']);
|
|
77
|
+
let insertions = 0, deletions = 0;
|
|
78
|
+
const mIns = trackedStat.match(/(\d+) insertion/);
|
|
79
|
+
const mDel = trackedStat.match(/(\d+) deletion/);
|
|
80
|
+
if (mIns)
|
|
81
|
+
insertions += parseInt(mIns[1]);
|
|
82
|
+
if (mDel)
|
|
83
|
+
deletions += parseInt(mDel[1]);
|
|
84
|
+
// Staged new files: --cached --shortstat
|
|
85
|
+
const stagedStat = await git.diff(['--cached', '--shortstat']);
|
|
86
|
+
const sIns = stagedStat.match(/(\d+) insertion/);
|
|
87
|
+
const sDel = stagedStat.match(/(\d+) deletion/);
|
|
88
|
+
if (sIns)
|
|
89
|
+
insertions += parseInt(sIns[1]);
|
|
90
|
+
if (sDel)
|
|
91
|
+
deletions += parseInt(sDel[1]);
|
|
92
|
+
result.insertions = insertions;
|
|
93
|
+
result.deletions = deletions;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
result.insertions = 0;
|
|
97
|
+
result.deletions = 0;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
result.insertions = 0;
|
|
102
|
+
result.deletions = 0;
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
71
105
|
}
|
|
72
106
|
export async function gitDiff(workspaceId, filePath) {
|
|
73
107
|
const ws = getWorkspace(workspaceId);
|
|
@@ -148,7 +182,14 @@ export async function gitDiscard(workspaceId, filePath) {
|
|
|
148
182
|
if (!ws)
|
|
149
183
|
throw new Error('Workspace not found');
|
|
150
184
|
const git = getGit(ws);
|
|
151
|
-
await git.
|
|
185
|
+
const status = await git.status();
|
|
186
|
+
const isUntracked = status.not_added.includes(filePath);
|
|
187
|
+
if (isUntracked) {
|
|
188
|
+
await git.clean('f', ['-d', '--', filePath]);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
await git.checkout(['--', filePath]);
|
|
192
|
+
}
|
|
152
193
|
}
|
|
153
194
|
export async function gitDiscardAll(workspaceId) {
|
|
154
195
|
const ws = getWorkspace(workspaceId);
|
|
@@ -247,6 +288,103 @@ export async function gitAddRemote(workspaceId, name, url) {
|
|
|
247
288
|
await git.addRemote(name, url);
|
|
248
289
|
}
|
|
249
290
|
}
|
|
291
|
+
export async function gitCheckoutDetached(workspaceId, commitHash) {
|
|
292
|
+
const ws = getWorkspace(workspaceId);
|
|
293
|
+
if (!ws)
|
|
294
|
+
throw new Error('Workspace not found');
|
|
295
|
+
const git = getGit(ws);
|
|
296
|
+
await git.checkout([commitHash]);
|
|
297
|
+
}
|
|
298
|
+
export async function gitCherryPick(workspaceId, commitHash) {
|
|
299
|
+
const ws = getWorkspace(workspaceId);
|
|
300
|
+
if (!ws)
|
|
301
|
+
throw new Error('Workspace not found');
|
|
302
|
+
const git = getGit(ws);
|
|
303
|
+
await git.raw(['cherry-pick', commitHash]);
|
|
304
|
+
}
|
|
305
|
+
export async function gitCreateBranch(workspaceId, name, startPoint) {
|
|
306
|
+
const ws = getWorkspace(workspaceId);
|
|
307
|
+
if (!ws)
|
|
308
|
+
throw new Error('Workspace not found');
|
|
309
|
+
const git = getGit(ws);
|
|
310
|
+
const args = startPoint ? [name, startPoint] : [name];
|
|
311
|
+
await git.branch(args);
|
|
312
|
+
}
|
|
313
|
+
export async function gitDeleteBranch(workspaceId, name, force = false) {
|
|
314
|
+
const ws = getWorkspace(workspaceId);
|
|
315
|
+
if (!ws)
|
|
316
|
+
throw new Error('Workspace not found');
|
|
317
|
+
const git = getGit(ws);
|
|
318
|
+
await git.branch([force ? '-D' : '-d', name]);
|
|
319
|
+
}
|
|
320
|
+
export async function gitCreateTag(workspaceId, name, commitHash) {
|
|
321
|
+
const ws = getWorkspace(workspaceId);
|
|
322
|
+
if (!ws)
|
|
323
|
+
throw new Error('Workspace not found');
|
|
324
|
+
const git = getGit(ws);
|
|
325
|
+
const args = [name];
|
|
326
|
+
if (commitHash)
|
|
327
|
+
args.push(commitHash);
|
|
328
|
+
await git.addTag(args.join(' '));
|
|
329
|
+
}
|
|
330
|
+
export async function gitCommitDiff(workspaceId, commitHash) {
|
|
331
|
+
const ws = getWorkspace(workspaceId);
|
|
332
|
+
if (!ws)
|
|
333
|
+
throw new Error('Workspace not found');
|
|
334
|
+
const git = getGit(ws);
|
|
335
|
+
const diff = await git.diff([`${commitHash}^`, commitHash]);
|
|
336
|
+
const nameOnlyRaw = await git.diff(['--name-only', `${commitHash}^`, commitHash]);
|
|
337
|
+
const files = nameOnlyRaw.split('\n').filter(Boolean);
|
|
338
|
+
const diffs = [];
|
|
339
|
+
for (const f of files) {
|
|
340
|
+
const oldContent = await git.show([`${commitHash}^:${f}`]).catch(() => '');
|
|
341
|
+
const newContent = await git.show([`${commitHash}:${f}`]).catch(() => '');
|
|
342
|
+
diffs.push({ path: f, oldContent, newContent, isBinary: false, isNew: !oldContent, isDeleted: !newContent });
|
|
343
|
+
}
|
|
344
|
+
return diffs;
|
|
345
|
+
}
|
|
346
|
+
export async function gitGetRemoteUrl(workspaceId) {
|
|
347
|
+
const ws = getWorkspace(workspaceId);
|
|
348
|
+
if (!ws)
|
|
349
|
+
throw new Error('Workspace not found');
|
|
350
|
+
const git = getGit(ws);
|
|
351
|
+
const remotes = await git.getRemotes(true);
|
|
352
|
+
return remotes.find(r => r.name === 'origin')?.refs?.push ?? null;
|
|
353
|
+
}
|
|
354
|
+
export async function gitMergeBase(workspaceId) {
|
|
355
|
+
const ws = getWorkspace(workspaceId);
|
|
356
|
+
if (!ws)
|
|
357
|
+
throw new Error('Workspace not found');
|
|
358
|
+
const git = getGit(ws);
|
|
359
|
+
const result = await git.raw(['merge-base', 'HEAD', 'origin/HEAD']).catch(() => '');
|
|
360
|
+
return result.trim();
|
|
361
|
+
}
|
|
362
|
+
export async function gitGetConfig(scope, workspaceId) {
|
|
363
|
+
const scopeFlag = scope === 'global' ? '--global' : '--local';
|
|
364
|
+
const git = workspaceId ? getGit(getWorkspace(workspaceId)) : simpleGit();
|
|
365
|
+
const get = (key) => git.raw(['config', scopeFlag, '--get', key]).then(v => v.trim()).catch(() => '');
|
|
366
|
+
const [name, email, proxy] = await Promise.all([
|
|
367
|
+
get('user.name'),
|
|
368
|
+
get('user.email'),
|
|
369
|
+
get('http.proxy'),
|
|
370
|
+
]);
|
|
371
|
+
return { name, email, proxy };
|
|
372
|
+
}
|
|
373
|
+
export async function gitSetConfig(scope, config, workspaceId) {
|
|
374
|
+
const scopeFlag = scope === 'global' ? '--global' : '--local';
|
|
375
|
+
const git = workspaceId ? getGit(getWorkspace(workspaceId)) : simpleGit();
|
|
376
|
+
const set = (key, value) => {
|
|
377
|
+
if (value)
|
|
378
|
+
return git.raw(['config', scopeFlag, key, value]);
|
|
379
|
+
return git.raw(['config', scopeFlag, '--unset', key]).catch(() => { });
|
|
380
|
+
};
|
|
381
|
+
await Promise.all([
|
|
382
|
+
config.name !== undefined ? set('user.name', config.name) : Promise.resolve(),
|
|
383
|
+
config.email !== undefined ? set('user.email', config.email) : Promise.resolve(),
|
|
384
|
+
config.proxy !== undefined ? set('http.proxy', config.proxy) : Promise.resolve(),
|
|
385
|
+
config.proxy !== undefined ? set('https.proxy', config.proxy) : Promise.resolve(),
|
|
386
|
+
]);
|
|
387
|
+
}
|
|
250
388
|
export async function gitInit(workspaceId) {
|
|
251
389
|
const ws = getWorkspace(workspaceId);
|
|
252
390
|
if (!ws)
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { AGENT_GENERATOR_PRESET_ID, readAgentTemplate } from '../services/agent.js';
|
|
2
|
+
const SYSTEM_PROMPT = `You generate Agent Spaces agent presets.
|
|
3
|
+
Return only a valid JSON object with this exact schema:
|
|
4
|
+
{
|
|
5
|
+
"name": "short agent name",
|
|
6
|
+
"description": "one sentence description",
|
|
7
|
+
"systemPrompt": "markdown system prompt"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
Rules:
|
|
11
|
+
- Do not wrap the JSON in markdown fences.
|
|
12
|
+
- name must be concise and suitable for a UI label.
|
|
13
|
+
- description must explain the agent's responsibility.
|
|
14
|
+
- systemPrompt must be valid Markdown and include role, responsibilities, workflow, constraints, and output expectations.
|
|
15
|
+
- Keep the systemPrompt actionable and specific to the user's request.`;
|
|
16
|
+
export async function generateAgentDesign(userPrompt) {
|
|
17
|
+
const prompt = userPrompt.trim();
|
|
18
|
+
if (!prompt)
|
|
19
|
+
throw new Error('prompt is required');
|
|
20
|
+
const config = resolveModelConfig();
|
|
21
|
+
if (!config) {
|
|
22
|
+
throw new Error(`Configure model settings for ${AGENT_GENERATOR_PRESET_ID} before generating agents.`);
|
|
23
|
+
}
|
|
24
|
+
console.info('[agent-designer] generating agent design', {
|
|
25
|
+
agentId: AGENT_GENERATOR_PRESET_ID,
|
|
26
|
+
provider: config.modelProvider ?? inferProvider(config.apiBase),
|
|
27
|
+
modelId: config.modelId,
|
|
28
|
+
apiBase: maskUrl(config.apiBase),
|
|
29
|
+
promptLength: prompt.length,
|
|
30
|
+
});
|
|
31
|
+
const content = await requestDesign(config, prompt);
|
|
32
|
+
console.info('[agent-designer] model text extracted', {
|
|
33
|
+
length: content.length,
|
|
34
|
+
preview: content.slice(0, 500),
|
|
35
|
+
});
|
|
36
|
+
return normalizeDesign(parseJsonObject(content));
|
|
37
|
+
}
|
|
38
|
+
function resolveModelConfig() {
|
|
39
|
+
const preset = readAgentTemplate(AGENT_GENERATOR_PRESET_ID);
|
|
40
|
+
if (preset?.apiBase && preset.apiKey && preset.modelId) {
|
|
41
|
+
return {
|
|
42
|
+
modelProvider: preset.modelProvider,
|
|
43
|
+
modelId: preset.modelId,
|
|
44
|
+
apiBase: preset.apiBase,
|
|
45
|
+
apiKey: preset.apiKey,
|
|
46
|
+
systemPrompt: preset.systemPrompt,
|
|
47
|
+
temperature: preset.temperature,
|
|
48
|
+
maxTokens: preset.maxTokens,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
async function requestDesign(config, userPrompt) {
|
|
54
|
+
const provider = config.modelProvider ?? inferProvider(config.apiBase);
|
|
55
|
+
if (provider === 'anthropic-messages')
|
|
56
|
+
return requestAnthropic(config, userPrompt);
|
|
57
|
+
if (provider === 'gemini-generate-content')
|
|
58
|
+
return requestGemini(config, userPrompt);
|
|
59
|
+
return requestOpenAICompatible(config, userPrompt, provider === 'openai-responses' || provider === 'openai-responses-to-anthropic-messages');
|
|
60
|
+
}
|
|
61
|
+
async function requestOpenAICompatible(config, userPrompt, useResponsesApi) {
|
|
62
|
+
const url = joinUrl(config.apiBase, useResponsesApi ? '/responses' : '/chat/completions');
|
|
63
|
+
const response = await fetch(url, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: {
|
|
66
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
67
|
+
'Content-Type': 'application/json',
|
|
68
|
+
},
|
|
69
|
+
body: JSON.stringify(useResponsesApi
|
|
70
|
+
? {
|
|
71
|
+
model: config.modelId,
|
|
72
|
+
input: `${buildSystemPrompt(config)}\n\nUser request:\n${userPrompt}`,
|
|
73
|
+
temperature: config.temperature ?? 0.2,
|
|
74
|
+
max_output_tokens: config.maxTokens,
|
|
75
|
+
}
|
|
76
|
+
: {
|
|
77
|
+
model: config.modelId,
|
|
78
|
+
messages: [
|
|
79
|
+
{ role: 'system', content: buildSystemPrompt(config) },
|
|
80
|
+
{ role: 'user', content: userPrompt },
|
|
81
|
+
],
|
|
82
|
+
temperature: config.temperature ?? 0.2,
|
|
83
|
+
max_tokens: config.maxTokens,
|
|
84
|
+
}),
|
|
85
|
+
});
|
|
86
|
+
const body = await readResponseBody(response);
|
|
87
|
+
if (!response.ok || body.error)
|
|
88
|
+
throw new Error(body.error || `Agent design generation failed with status ${response.status}`);
|
|
89
|
+
return body.text;
|
|
90
|
+
}
|
|
91
|
+
async function requestAnthropic(config, userPrompt) {
|
|
92
|
+
const response = await fetch(getAnthropicMessagesUrl(config.apiBase), {
|
|
93
|
+
method: 'POST',
|
|
94
|
+
headers: {
|
|
95
|
+
'x-api-key': config.apiKey,
|
|
96
|
+
'anthropic-version': '2023-06-01',
|
|
97
|
+
'Content-Type': 'application/json',
|
|
98
|
+
},
|
|
99
|
+
body: JSON.stringify({
|
|
100
|
+
model: config.modelId,
|
|
101
|
+
system: buildSystemPrompt(config),
|
|
102
|
+
messages: [{ role: 'user', content: userPrompt }],
|
|
103
|
+
max_tokens: config.maxTokens ?? 4096,
|
|
104
|
+
temperature: config.temperature ?? 0.2,
|
|
105
|
+
}),
|
|
106
|
+
});
|
|
107
|
+
const body = await readResponseBody(response);
|
|
108
|
+
if (!response.ok || body.error)
|
|
109
|
+
throw new Error(body.error || `Agent design generation failed with status ${response.status}`);
|
|
110
|
+
return body.text;
|
|
111
|
+
}
|
|
112
|
+
async function requestGemini(config, userPrompt) {
|
|
113
|
+
const response = await fetch(joinUrl(config.apiBase, `/models/${encodeURIComponent(config.modelId)}:generateContent`), {
|
|
114
|
+
method: 'POST',
|
|
115
|
+
headers: {
|
|
116
|
+
'x-goog-api-key': config.apiKey,
|
|
117
|
+
'Content-Type': 'application/json',
|
|
118
|
+
},
|
|
119
|
+
body: JSON.stringify({
|
|
120
|
+
systemInstruction: { parts: [{ text: buildSystemPrompt(config) }] },
|
|
121
|
+
contents: [{ role: 'user', parts: [{ text: userPrompt }] }],
|
|
122
|
+
generationConfig: {
|
|
123
|
+
temperature: config.temperature ?? 0.2,
|
|
124
|
+
maxOutputTokens: config.maxTokens,
|
|
125
|
+
},
|
|
126
|
+
}),
|
|
127
|
+
});
|
|
128
|
+
const body = await readResponseBody(response);
|
|
129
|
+
if (!response.ok || body.error)
|
|
130
|
+
throw new Error(body.error || `Agent design generation failed with status ${response.status}`);
|
|
131
|
+
return body.text;
|
|
132
|
+
}
|
|
133
|
+
function buildSystemPrompt(config) {
|
|
134
|
+
const custom = config.systemPrompt?.trim();
|
|
135
|
+
if (!custom)
|
|
136
|
+
return SYSTEM_PROMPT;
|
|
137
|
+
return `${custom}\n\n${SYSTEM_PROMPT}`;
|
|
138
|
+
}
|
|
139
|
+
async function readResponseBody(response) {
|
|
140
|
+
const raw = await response.text();
|
|
141
|
+
if (!raw)
|
|
142
|
+
return { text: '' };
|
|
143
|
+
try {
|
|
144
|
+
const json = JSON.parse(raw);
|
|
145
|
+
console.info('[agent-designer] provider response received', {
|
|
146
|
+
status: response.status,
|
|
147
|
+
keys: Object.keys(json),
|
|
148
|
+
preview: raw.slice(0, 800),
|
|
149
|
+
});
|
|
150
|
+
if (isAgentDesignJson(json))
|
|
151
|
+
return { text: JSON.stringify(json) };
|
|
152
|
+
return {
|
|
153
|
+
text: extractText(json),
|
|
154
|
+
error: extractError(json),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
console.info('[agent-designer] provider raw text received', {
|
|
159
|
+
status: response.status,
|
|
160
|
+
preview: raw.slice(0, 800),
|
|
161
|
+
});
|
|
162
|
+
return { text: raw };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function extractText(json) {
|
|
166
|
+
const outputText = json.output_text;
|
|
167
|
+
if (typeof outputText === 'string')
|
|
168
|
+
return outputText;
|
|
169
|
+
const output = Array.isArray(json.output) ? json.output : [];
|
|
170
|
+
const responseOutputText = output
|
|
171
|
+
.flatMap((item) => Array.isArray(item.content) ? item.content : [])
|
|
172
|
+
.map((part) => {
|
|
173
|
+
const record = part;
|
|
174
|
+
return typeof record.text === 'string' ? record.text : '';
|
|
175
|
+
})
|
|
176
|
+
.filter(Boolean)
|
|
177
|
+
.join('\n');
|
|
178
|
+
if (responseOutputText)
|
|
179
|
+
return responseOutputText;
|
|
180
|
+
const choices = Array.isArray(json.choices) ? json.choices : [];
|
|
181
|
+
const firstChoice = choices[0];
|
|
182
|
+
if (typeof firstChoice?.text === 'string')
|
|
183
|
+
return firstChoice.text;
|
|
184
|
+
const message = firstChoice?.message;
|
|
185
|
+
if (typeof message?.content === 'string')
|
|
186
|
+
return message.content;
|
|
187
|
+
if (Array.isArray(message?.content)) {
|
|
188
|
+
const messageText = message.content
|
|
189
|
+
.map((part) => typeof part.text === 'string' ? part.text : '')
|
|
190
|
+
.filter(Boolean)
|
|
191
|
+
.join('\n');
|
|
192
|
+
if (messageText)
|
|
193
|
+
return messageText;
|
|
194
|
+
}
|
|
195
|
+
const content = Array.isArray(json.content) ? json.content : [];
|
|
196
|
+
const anthropicText = content
|
|
197
|
+
.map((part) => typeof part.text === 'string' ? part.text : '')
|
|
198
|
+
.filter(Boolean)
|
|
199
|
+
.join('\n');
|
|
200
|
+
if (anthropicText)
|
|
201
|
+
return anthropicText;
|
|
202
|
+
const candidates = Array.isArray(json.candidates) ? json.candidates : [];
|
|
203
|
+
const firstCandidate = candidates[0];
|
|
204
|
+
const parts = (firstCandidate?.content?.parts ?? []);
|
|
205
|
+
return parts
|
|
206
|
+
.map((part) => typeof part.text === 'string' ? part.text : '')
|
|
207
|
+
.filter(Boolean)
|
|
208
|
+
.join('\n');
|
|
209
|
+
}
|
|
210
|
+
function isAgentDesignJson(json) {
|
|
211
|
+
return typeof json.name === 'string'
|
|
212
|
+
&& typeof json.description === 'string'
|
|
213
|
+
&& typeof json.systemPrompt === 'string';
|
|
214
|
+
}
|
|
215
|
+
function extractError(json) {
|
|
216
|
+
if (json.success === false) {
|
|
217
|
+
return typeof json.msg === 'string' ? json.msg : 'Provider returned success=false';
|
|
218
|
+
}
|
|
219
|
+
const error = json.error;
|
|
220
|
+
if (typeof error === 'string')
|
|
221
|
+
return error;
|
|
222
|
+
if (error && typeof error === 'object') {
|
|
223
|
+
const message = error.message;
|
|
224
|
+
if (typeof message === 'string')
|
|
225
|
+
return message;
|
|
226
|
+
}
|
|
227
|
+
return typeof json.message === 'string' ? json.message : undefined;
|
|
228
|
+
}
|
|
229
|
+
function parseJsonObject(text) {
|
|
230
|
+
const trimmed = text.trim().replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/i, '');
|
|
231
|
+
try {
|
|
232
|
+
return JSON.parse(trimmed);
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
const fenced = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/i)?.[1]?.trim();
|
|
236
|
+
if (fenced)
|
|
237
|
+
return JSON.parse(fenced);
|
|
238
|
+
const candidate = findFirstJsonObject(trimmed);
|
|
239
|
+
if (candidate)
|
|
240
|
+
return JSON.parse(candidate);
|
|
241
|
+
throw new Error('Model did not return valid JSON.');
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function findFirstJsonObject(text) {
|
|
245
|
+
const starts = [];
|
|
246
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
247
|
+
if (text[index] === '{')
|
|
248
|
+
starts.push(index);
|
|
249
|
+
}
|
|
250
|
+
for (const start of starts) {
|
|
251
|
+
let depth = 0;
|
|
252
|
+
let inString = false;
|
|
253
|
+
let escaped = false;
|
|
254
|
+
for (let index = start; index < text.length; index += 1) {
|
|
255
|
+
const char = text[index];
|
|
256
|
+
if (escaped) {
|
|
257
|
+
escaped = false;
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (char === '\\') {
|
|
261
|
+
escaped = true;
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (char === '"') {
|
|
265
|
+
inString = !inString;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (inString)
|
|
269
|
+
continue;
|
|
270
|
+
if (char === '{')
|
|
271
|
+
depth += 1;
|
|
272
|
+
if (char === '}')
|
|
273
|
+
depth -= 1;
|
|
274
|
+
if (depth === 0) {
|
|
275
|
+
const candidate = text.slice(start, index + 1);
|
|
276
|
+
try {
|
|
277
|
+
JSON.parse(candidate);
|
|
278
|
+
return candidate;
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
function normalizeDesign(value) {
|
|
289
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
290
|
+
throw new Error('Generated agent design must be a JSON object.');
|
|
291
|
+
}
|
|
292
|
+
const data = value;
|
|
293
|
+
const name = typeof data.name === 'string' ? data.name.trim() : '';
|
|
294
|
+
const description = typeof data.description === 'string' ? data.description.trim() : '';
|
|
295
|
+
const systemPrompt = typeof data.systemPrompt === 'string' ? data.systemPrompt.trim() : '';
|
|
296
|
+
if (!name || !description || !systemPrompt) {
|
|
297
|
+
throw new Error('Generated JSON must include name, description, and systemPrompt.');
|
|
298
|
+
}
|
|
299
|
+
return { name, description, systemPrompt };
|
|
300
|
+
}
|
|
301
|
+
function inferProvider(apiBase) {
|
|
302
|
+
if (apiBase?.includes('anthropic.com'))
|
|
303
|
+
return 'anthropic-messages';
|
|
304
|
+
if (apiBase?.includes('generativelanguage.googleapis.com'))
|
|
305
|
+
return 'gemini-generate-content';
|
|
306
|
+
return 'openai-chat-completions';
|
|
307
|
+
}
|
|
308
|
+
function joinUrl(base, path) {
|
|
309
|
+
return `${base.replace(/\/+$/, '')}${path}`;
|
|
310
|
+
}
|
|
311
|
+
function getAnthropicMessagesUrl(apiBase) {
|
|
312
|
+
try {
|
|
313
|
+
const url = new URL(apiBase);
|
|
314
|
+
if (url.pathname.endsWith('/messages'))
|
|
315
|
+
return apiBase;
|
|
316
|
+
if (url.hostname === 'api.anthropic.com') {
|
|
317
|
+
return joinUrl(apiBase, '/messages');
|
|
318
|
+
}
|
|
319
|
+
return joinUrl(apiBase, '/v1/messages');
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
return apiBase;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function maskUrl(value) {
|
|
326
|
+
try {
|
|
327
|
+
const url = new URL(value);
|
|
328
|
+
return `${url.origin}${url.pathname}`;
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
return value.slice(0, 120);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
//# sourceMappingURL=agent-designer.js.map
|
|
@@ -134,6 +134,8 @@ function normalizeOutputLines(output) {
|
|
|
134
134
|
.filter((line) => line.trim());
|
|
135
135
|
const seenInitLines = new Set();
|
|
136
136
|
return lines.filter((line) => {
|
|
137
|
+
if (isIgnorableToolProgressLine(line))
|
|
138
|
+
return false;
|
|
137
139
|
if (!/^Claude Code initialized\b/i.test(line))
|
|
138
140
|
return true;
|
|
139
141
|
if (seenInitLines.has(line))
|
|
@@ -429,6 +431,12 @@ function summarizeMessageTitle(text) {
|
|
|
429
431
|
function isToolLikeLine(line) {
|
|
430
432
|
return /^(Using|Tool:|Read|Write|Edit|MultiEdit|Bash|Search|Grep|Glob|Todo|Task|Web|Fetch|Claude Code initialized|Codex initialized|.+ running \(\d+s\))/i.test(line.trim());
|
|
431
433
|
}
|
|
434
|
+
function isIgnorableToolProgressLine(line) {
|
|
435
|
+
const trimmed = line.trim();
|
|
436
|
+
return /^Claude$/i.test(trimmed)
|
|
437
|
+
|| /^(Reading|Searching)(\.{1,3}|…)?$/i.test(trimmed)
|
|
438
|
+
|| /^(Read|Search|Grep|Glob|SemanticSearch|WebSearch)\s+running\s+\(\d+s\)$/i.test(trimmed);
|
|
439
|
+
}
|
|
432
440
|
function isFinalAnswerLine(line) {
|
|
433
441
|
return !isToolLikeLine(line) && !/^(\[.*\]|Agent runtime configuration:|Conversation history:)/.test(line.trim());
|
|
434
442
|
}
|
|
@@ -2,6 +2,7 @@ import * as agentService from '../services/agent.js';
|
|
|
2
2
|
import { createAgentRuntime } from '../adapters/agent-runtime.js';
|
|
3
3
|
import { getWorkspace } from '../storage/workspace-store.js';
|
|
4
4
|
import { getThinkingRuntimeConfig } from '../services/llm-model-config.js';
|
|
5
|
+
import { prependPersistentAgentContext } from '../services/persistent-agent-context.js';
|
|
5
6
|
import { simpleGit } from 'simple-git';
|
|
6
7
|
const DEFAULT_SYSTEM_PROMPT = [
|
|
7
8
|
'You are a git commit message generator.',
|
|
@@ -36,13 +37,19 @@ export async function runCommitAgent(workspaceId) {
|
|
|
36
37
|
const workingDir = agentService.resolveWorkingDir(workspaceId, commitAgent);
|
|
37
38
|
const systemPrompt = commitAgent.systemPrompt?.trim() || DEFAULT_SYSTEM_PROMPT;
|
|
38
39
|
const truncatedDiff = diff.length > 8000 ? diff.substring(0, 8000) + '\n... (truncated)' : diff;
|
|
39
|
-
const result = await runtime.execute([
|
|
40
|
+
const result = await runtime.execute(prependPersistentAgentContext([
|
|
40
41
|
'Generate exactly one commit message for these changes.',
|
|
41
42
|
'Do not inspect files or run commands. Use only this diff.',
|
|
42
43
|
'Output only the commit message.',
|
|
43
44
|
'',
|
|
44
45
|
truncatedDiff,
|
|
45
|
-
].join('\n'),
|
|
46
|
+
].join('\n'), {
|
|
47
|
+
workspaceId,
|
|
48
|
+
workingDir,
|
|
49
|
+
boundDirs: ws.boundDirs,
|
|
50
|
+
includeWorkspacePrompt: false,
|
|
51
|
+
excludeNativeClaudeMd: commitAgent.runtimeKind === 'claude-code',
|
|
52
|
+
}), workingDir, {
|
|
46
53
|
maxTurns: 1,
|
|
47
54
|
systemPrompt,
|
|
48
55
|
});
|