@agent-spaces/server 0.3.67 → 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.
- package/dist/adapters/agent-runtime.js +4 -0
- package/dist/adapters/codex-function-tool-bridge.js +9 -1
- package/dist/adapters/git.js +13 -2
- package/dist/adapters/hermes-runtime.js +711 -108
- package/dist/adapters/langchain-runtime.js +384 -21
- package/dist/adapters/oh-my-pi-runtime.js +858 -0
- package/dist/adapters/open-agent-sdk-runtime.js +202 -5
- package/dist/adapters/open-agent-sdk-runtime.test.js +35 -0
- package/dist/agents/agent-message-parts.js +52 -2
- package/dist/agents/issue-task-controller.js +4 -2
- package/dist/agents/title-generator-agent.js +120 -0
- package/dist/app.js +59 -6
- package/dist/routes/agent-sse.js +70 -7
- package/dist/routes/channel.js +23 -2
- package/dist/routes/chat-run.js +191 -0
- package/dist/routes/chat.js +142 -0
- package/dist/routes/command.js +16 -0
- package/dist/routes/data.js +189 -0
- package/dist/routes/git.js +10 -1
- package/dist/routes/import.js +199 -0
- package/dist/routes/issue.js +16 -4
- package/dist/routes/plugin.js +69 -0
- package/dist/routes/version.js +2 -1
- package/dist/routes/workflow-hook.js +71 -0
- package/dist/routes/workflow.js +282 -7
- package/dist/routes/workspace.js +13 -4
- package/dist/services/agent.js +123 -36
- package/dist/services/ai-text.js +185 -0
- package/dist/services/builtin-tools/index.js +1 -0
- package/dist/services/builtin-tools/workflow-editor-tools.js +509 -0
- package/dist/services/builtin-tools/workflow-exec-tools.js +320 -0
- package/dist/services/chat.js +134 -0
- package/dist/services/command-process-manager.js +16 -0
- package/dist/services/execution-manager.js +1346 -0
- package/dist/services/generated-title.js +59 -0
- package/dist/services/gitignore.js +22 -18
- package/dist/services/interaction-manager.js +114 -0
- package/dist/services/issue-retry.js +25 -0
- package/dist/services/output-style.js +8 -1
- package/dist/services/plugin.js +257 -0
- package/dist/services/prompt-template.js +8 -1
- package/dist/services/pty.js +20 -0
- package/dist/services/search.js +16 -6
- package/dist/services/skill.js +2 -0
- package/dist/services/version.js +17 -7
- package/dist/services/workflow-command-runner.js +5 -4
- package/dist/services/workflow-trigger-service.js +137 -0
- package/dist/services/workflow.js +199 -36
- package/dist/storage/agent-store.js +8 -0
- package/dist/storage/chat-store.js +151 -0
- package/dist/storage/database-store.js +6 -0
- package/dist/storage/json-store.js +2 -1
- package/dist/storage/kanban-store.js +6 -0
- package/dist/storage/workflow-store.js +386 -22
- package/dist/ws/agent-prompt.js +6 -2
- package/dist/ws/agent-runner.js +29 -18
- package/dist/ws/chat-handler.js +89 -0
- package/dist/ws/connection-manager.js +49 -2
- package/dist/ws/execution-channels.js +88 -0
- package/dist/ws/handler.js +32 -5
- package/dist/ws/message-parts.js +130 -12
- package/dist/ws/terminal-handler.js +26 -0
- package/package.json +12 -1
- package/public/avatars/user.jpg +0 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
export async function requestAiText(config, input) {
|
|
2
|
+
const provider = config.modelProvider ?? inferProvider(config.apiBase);
|
|
3
|
+
if (provider === 'anthropic-messages')
|
|
4
|
+
return requestAnthropic(config, input.systemPrompt, input.userPrompt);
|
|
5
|
+
if (provider === 'gemini-generate-content')
|
|
6
|
+
return requestGemini(config, input.systemPrompt, input.userPrompt);
|
|
7
|
+
return requestOpenAICompatible(config, input.systemPrompt, input.userPrompt, provider === 'openai-responses' || provider === 'openai-responses-to-anthropic-messages');
|
|
8
|
+
}
|
|
9
|
+
export function maskAiTextUrl(url) {
|
|
10
|
+
if (!url)
|
|
11
|
+
return undefined;
|
|
12
|
+
try {
|
|
13
|
+
const parsed = new URL(url);
|
|
14
|
+
return `${parsed.origin}${parsed.pathname}`;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return url.slice(0, 80);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function requestOpenAICompatible(config, systemPrompt, userPrompt, useResponsesApi) {
|
|
21
|
+
const response = await fetch(joinUrl(config.apiBase, useResponsesApi ? '/responses' : '/chat/completions'), {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
headers: {
|
|
24
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
25
|
+
'Content-Type': 'application/json',
|
|
26
|
+
},
|
|
27
|
+
body: JSON.stringify(useResponsesApi
|
|
28
|
+
? {
|
|
29
|
+
model: config.modelId,
|
|
30
|
+
input: `${systemPrompt}\n\n${userPrompt}`,
|
|
31
|
+
temperature: config.temperature ?? 0.2,
|
|
32
|
+
max_output_tokens: config.maxTokens ?? 1024,
|
|
33
|
+
}
|
|
34
|
+
: {
|
|
35
|
+
model: config.modelId,
|
|
36
|
+
messages: [
|
|
37
|
+
{ role: 'system', content: systemPrompt },
|
|
38
|
+
{ role: 'user', content: userPrompt },
|
|
39
|
+
],
|
|
40
|
+
temperature: config.temperature ?? 0.2,
|
|
41
|
+
max_tokens: config.maxTokens ?? 1024,
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
const body = await readResponseBody(response);
|
|
45
|
+
if (!response.ok || body.error)
|
|
46
|
+
throw new Error(body.error || `AI text request failed with status ${response.status}`);
|
|
47
|
+
return body.text;
|
|
48
|
+
}
|
|
49
|
+
async function requestAnthropic(config, systemPrompt, userPrompt) {
|
|
50
|
+
const response = await fetch(getAnthropicMessagesUrl(config.apiBase), {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: {
|
|
53
|
+
'x-api-key': config.apiKey,
|
|
54
|
+
'anthropic-version': '2023-06-01',
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
},
|
|
57
|
+
body: JSON.stringify({
|
|
58
|
+
model: config.modelId,
|
|
59
|
+
system: systemPrompt,
|
|
60
|
+
messages: [{ role: 'user', content: userPrompt }],
|
|
61
|
+
max_tokens: config.maxTokens ?? 1024,
|
|
62
|
+
temperature: config.temperature ?? 0.2,
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
const body = await readResponseBody(response);
|
|
66
|
+
if (!response.ok || body.error)
|
|
67
|
+
throw new Error(body.error || `AI text request failed with status ${response.status}`);
|
|
68
|
+
return body.text;
|
|
69
|
+
}
|
|
70
|
+
async function requestGemini(config, systemPrompt, userPrompt) {
|
|
71
|
+
const response = await fetch(joinUrl(config.apiBase, `/models/${encodeURIComponent(config.modelId)}:generateContent`), {
|
|
72
|
+
method: 'POST',
|
|
73
|
+
headers: {
|
|
74
|
+
'x-goog-api-key': config.apiKey,
|
|
75
|
+
'Content-Type': 'application/json',
|
|
76
|
+
},
|
|
77
|
+
body: JSON.stringify({
|
|
78
|
+
systemInstruction: { parts: [{ text: systemPrompt }] },
|
|
79
|
+
contents: [{ role: 'user', parts: [{ text: userPrompt }] }],
|
|
80
|
+
generationConfig: {
|
|
81
|
+
temperature: config.temperature ?? 0.2,
|
|
82
|
+
maxOutputTokens: config.maxTokens ?? 1024,
|
|
83
|
+
},
|
|
84
|
+
}),
|
|
85
|
+
});
|
|
86
|
+
const body = await readResponseBody(response);
|
|
87
|
+
if (!response.ok || body.error)
|
|
88
|
+
throw new Error(body.error || `AI text request failed with status ${response.status}`);
|
|
89
|
+
return body.text;
|
|
90
|
+
}
|
|
91
|
+
async function readResponseBody(response) {
|
|
92
|
+
const raw = await response.text();
|
|
93
|
+
if (!raw)
|
|
94
|
+
return { text: '' };
|
|
95
|
+
try {
|
|
96
|
+
const json = JSON.parse(raw);
|
|
97
|
+
return {
|
|
98
|
+
text: extractText(json),
|
|
99
|
+
error: extractError(json),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return { text: raw };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function extractText(json) {
|
|
107
|
+
const outputText = json.output_text;
|
|
108
|
+
if (typeof outputText === 'string')
|
|
109
|
+
return outputText;
|
|
110
|
+
const output = Array.isArray(json.output) ? json.output : [];
|
|
111
|
+
const responseOutputText = output
|
|
112
|
+
.flatMap((item) => Array.isArray(item.content) ? item.content : [])
|
|
113
|
+
.map((part) => typeof part.text === 'string' ? part.text : '')
|
|
114
|
+
.filter(Boolean)
|
|
115
|
+
.join('\n');
|
|
116
|
+
if (responseOutputText)
|
|
117
|
+
return responseOutputText;
|
|
118
|
+
const choices = Array.isArray(json.choices) ? json.choices : [];
|
|
119
|
+
const firstChoice = choices[0];
|
|
120
|
+
if (typeof firstChoice?.text === 'string')
|
|
121
|
+
return firstChoice.text;
|
|
122
|
+
const message = firstChoice?.message;
|
|
123
|
+
if (typeof message?.content === 'string')
|
|
124
|
+
return message.content;
|
|
125
|
+
if (Array.isArray(message?.content)) {
|
|
126
|
+
const messageText = message.content
|
|
127
|
+
.map((part) => typeof part.text === 'string' ? part.text : '')
|
|
128
|
+
.filter(Boolean)
|
|
129
|
+
.join('\n');
|
|
130
|
+
if (messageText)
|
|
131
|
+
return messageText;
|
|
132
|
+
}
|
|
133
|
+
const content = Array.isArray(json.content) ? json.content : [];
|
|
134
|
+
const anthropicText = content
|
|
135
|
+
.map((part) => typeof part.text === 'string' ? part.text : '')
|
|
136
|
+
.filter(Boolean)
|
|
137
|
+
.join('\n');
|
|
138
|
+
if (anthropicText)
|
|
139
|
+
return anthropicText;
|
|
140
|
+
const candidates = Array.isArray(json.candidates) ? json.candidates : [];
|
|
141
|
+
const firstCandidate = candidates[0];
|
|
142
|
+
const parts = (firstCandidate?.content?.parts ?? []);
|
|
143
|
+
return parts
|
|
144
|
+
.map((part) => typeof part.text === 'string' ? part.text : '')
|
|
145
|
+
.filter(Boolean)
|
|
146
|
+
.join('\n');
|
|
147
|
+
}
|
|
148
|
+
function extractError(json) {
|
|
149
|
+
if (json.success === false) {
|
|
150
|
+
return typeof json.msg === 'string' ? json.msg : 'Provider returned success=false';
|
|
151
|
+
}
|
|
152
|
+
const error = json.error;
|
|
153
|
+
if (typeof error === 'string')
|
|
154
|
+
return error;
|
|
155
|
+
if (error && typeof error === 'object') {
|
|
156
|
+
const message = error.message;
|
|
157
|
+
if (typeof message === 'string')
|
|
158
|
+
return message;
|
|
159
|
+
}
|
|
160
|
+
return typeof json.message === 'string' ? json.message : undefined;
|
|
161
|
+
}
|
|
162
|
+
function inferProvider(apiBase) {
|
|
163
|
+
if (apiBase?.includes('anthropic.com'))
|
|
164
|
+
return 'anthropic-messages';
|
|
165
|
+
if (apiBase?.includes('generativelanguage.googleapis.com'))
|
|
166
|
+
return 'gemini-generate-content';
|
|
167
|
+
return 'openai-chat-completions';
|
|
168
|
+
}
|
|
169
|
+
function joinUrl(base, path) {
|
|
170
|
+
return `${base.replace(/\/+$/, '')}${path}`;
|
|
171
|
+
}
|
|
172
|
+
function getAnthropicMessagesUrl(apiBase) {
|
|
173
|
+
try {
|
|
174
|
+
const url = new URL(apiBase);
|
|
175
|
+
if (url.pathname.endsWith('/messages'))
|
|
176
|
+
return apiBase;
|
|
177
|
+
if (url.hostname === 'api.anthropic.com')
|
|
178
|
+
return joinUrl(apiBase, '/messages');
|
|
179
|
+
return joinUrl(apiBase, '/v1/messages');
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return apiBase;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=ai-text.js.map
|
|
@@ -2,4 +2,5 @@ export { createIssueFunctionTools, isBuiltInIssueToolName } from './issue-tools.
|
|
|
2
2
|
export { createCommandFunctionTools } from './command-tools.js';
|
|
3
3
|
export { createDatabaseFunctionTools } from './database-tools.js';
|
|
4
4
|
export { createKanbanFunctionTools } from './kanban-tools.js';
|
|
5
|
+
export { createWorkflowExecutionFunctionTools, setWorkflowExecutionManager } from './workflow-exec-tools.js';
|
|
5
6
|
//# sourceMappingURL=index.js.map
|