made-bridge 0.2.2 → 0.3.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/package.json +1 -1
- package/public/app.js +85 -2
- package/public/i18n-static.js +23 -0
- package/public/index.html +16 -0
- package/src/agent-sprites.mjs +124 -9
- package/src/agents/events.mjs +4 -0
- package/src/agents/shared.mjs +8 -5
- package/src/agents/toolbox.mjs +15 -0
- package/src/board-link.mjs +17 -1
- package/src/config.mjs +8 -5
- package/src/firmware-store.mjs +166 -0
- package/src/installed.mjs +3 -2
- package/src/jobs.mjs +93 -7
- package/src/plugin-package.mjs +13 -3
- package/src/plugins/contracts.d.ts +44 -0
- package/src/plugins/enhance.mjs +5 -1
- package/src/plugins/hot-reload.mjs +189 -0
- package/src/plugins/registry.mjs +8 -4
- package/src/providers.mjs +27 -22
- package/src/server.mjs +106 -5
- package/src/sessions.mjs +1 -2
- package/src/usb-receiver.mjs +74 -26
- package/src/agents/codex.mjs +0 -94
- package/src/agents/cursor.mjs +0 -31
- package/src/agents/index.mjs +0 -7
- package/src/agents/qoder.mjs +0 -34
- package/src/agents/workbuddy.mjs +0 -121
package/src/agents/workbuddy.mjs
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { builtinAgentIcons } from '../agent-icons.mjs';
|
|
2
|
-
import { translateKnownMessage } from '../i18n.mjs';
|
|
3
|
-
async function run({ job, config, signal }) {
|
|
4
|
-
if (!config.workbuddy?.allowUnscopedDispatch || !config.workbuddyToken) {
|
|
5
|
-
throw new Error('WorkBuddy 开放平台尚未授权或未开启转交模式');
|
|
6
|
-
}
|
|
7
|
-
const response = await fetch('https://www.workbuddy.cn/openapi/v2/localassistant/message', {
|
|
8
|
-
method: 'POST',
|
|
9
|
-
signal: AbortSignal.any([signal, AbortSignal.timeout(30000)]),
|
|
10
|
-
headers: {
|
|
11
|
-
Authorization: `Bearer ${config.workbuddyToken}`,
|
|
12
|
-
'Content-Type': 'application/json',
|
|
13
|
-
Accept: 'application/json',
|
|
14
|
-
},
|
|
15
|
-
body: JSON.stringify({ content: job.instruction, msg_type: 'text' }),
|
|
16
|
-
});
|
|
17
|
-
const data = await response.json();
|
|
18
|
-
if (!response.ok || data.code !== 0) {
|
|
19
|
-
throw new Error(`WorkBuddy 转交失败:${data.msg || response.status}`);
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
status: 'handed_off',
|
|
23
|
-
result: config.locale === 'en'
|
|
24
|
-
? `Sent to WorkBuddy. Local message ID: ${data.data?.message_id || 'unknown'}. Continue in WorkBuddy for execution and permission requests.`
|
|
25
|
-
: `已转交给 WorkBuddy,本机消息 ID:${data.data?.message_id || '未知'}。请在 WorkBuddy 中查看后续执行与权限请求。`,
|
|
26
|
-
handoff: { cursor: data.data?.message_id || '', readState: 'retrying', replyCount: 0 },
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async function readMessages(job, config) {
|
|
31
|
-
if (!config.workbuddyToken || !job.handoff?.cursor) return { messages: [] };
|
|
32
|
-
const url = new URL('https://www.workbuddy.cn/openapi/v2/localassistant/message');
|
|
33
|
-
url.searchParams.set('message_id', job.handoff?.cursor);
|
|
34
|
-
const response = await fetch(url, {
|
|
35
|
-
method: 'GET',
|
|
36
|
-
signal: AbortSignal.timeout(15000),
|
|
37
|
-
headers: {
|
|
38
|
-
Authorization: `Bearer ${config.workbuddyToken}`,
|
|
39
|
-
Accept: 'application/json',
|
|
40
|
-
},
|
|
41
|
-
});
|
|
42
|
-
if (response.status === 401 || response.status === 403) {
|
|
43
|
-
return { unreadable: true };
|
|
44
|
-
}
|
|
45
|
-
const data = await response.json();
|
|
46
|
-
if (!response.ok || data.code !== 0) {
|
|
47
|
-
throw new Error(`WorkBuddy 消息读取失败:${data.msg || response.status}`);
|
|
48
|
-
}
|
|
49
|
-
if (!Array.isArray(data.data?.messages)) {
|
|
50
|
-
throw new Error('WorkBuddy 消息历史格式无效');
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
messages: data.data.messages.slice(0, 100).map((message) => ({
|
|
54
|
-
id: typeof message.message_id === 'string' ? message.message_id : '',
|
|
55
|
-
role: message.role,
|
|
56
|
-
type: message.msg_type,
|
|
57
|
-
text: Array.isArray(message.content)
|
|
58
|
-
? message.content.filter((part) => typeof part === 'string').join('\n').slice(0, 2000)
|
|
59
|
-
: '',
|
|
60
|
-
})),
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Migration aliases are confined to this builtin adapter so existing state and
|
|
65
|
-
// older desktop clients remain compatible without shaping the plugin protocol.
|
|
66
|
-
function syncJobState(job) {
|
|
67
|
-
if (!job.handoff && job.workbuddyCursor) {
|
|
68
|
-
job.handoff = { cursor: job.workbuddyCursor, readState: job.workbuddyReadState || 'retrying', replyCount: job.workbuddyReplyCount || 0 };
|
|
69
|
-
}
|
|
70
|
-
if (!job.handoff) return;
|
|
71
|
-
job.workbuddyMessageId ||= job.handoff.cursor || '';
|
|
72
|
-
job.workbuddyCursor = job.handoff.cursor;
|
|
73
|
-
job.workbuddyReadState = job.handoff.readState;
|
|
74
|
-
job.workbuddyReplyCount = job.handoff.replyCount || 0;
|
|
75
|
-
if (job.handoffReadError) job.workbuddyReadError = job.handoffReadError;
|
|
76
|
-
else delete job.workbuddyReadError;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async function readUpdates({ job, config }) {
|
|
80
|
-
const localize = (value) => translateKnownMessage(value, config.locale);
|
|
81
|
-
const update = await readMessages(job, config);
|
|
82
|
-
const handoff = { ...job.handoff };
|
|
83
|
-
const additions = [];
|
|
84
|
-
if (update.unreadable) {
|
|
85
|
-
handoff.readState = 'unavailable';
|
|
86
|
-
const notice = localize('当前授权不能读取 WorkBuddy 消息;需 user.localassistant.readable 权限。请在 WorkBuddy 中查看回复。');
|
|
87
|
-
if (!job.result?.includes(notice)) additions.push(notice);
|
|
88
|
-
} else {
|
|
89
|
-
handoff.readState = 'readable';
|
|
90
|
-
for (const message of update.messages || []) {
|
|
91
|
-
if (!message.id || message.id === handoff.cursor) continue;
|
|
92
|
-
// This API is a shared stream: another user prompt makes association
|
|
93
|
-
// ambiguous, so later replies must not be attached to this handoff.
|
|
94
|
-
if (message.role === 'user') {
|
|
95
|
-
handoff.readState = 'ambiguous';
|
|
96
|
-
additions.push(localize('出现其他 WorkBuddy 用户消息;后续回复无法可靠归属此任务,请在 WorkBuddy 中查看。'));
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
handoff.cursor = message.id;
|
|
100
|
-
if (message.role !== 'assistant') continue;
|
|
101
|
-
const reply = message.text || (message.type === 'permission'
|
|
102
|
-
? localize('助理请求进一步确认,请在 WorkBuddy 中处理。')
|
|
103
|
-
: localize('助理有一条新消息,请在 WorkBuddy 中查看详情。'));
|
|
104
|
-
additions.push(`${localize('WorkBuddy 后续助理消息(任务关联未验证):')}\n${reply}`);
|
|
105
|
-
handoff.replyCount = (handoff.replyCount || 0) + 1;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return { handoff, appendResult: additions.join('\n\n') };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export default {
|
|
112
|
-
apiVersion: 1, kind: 'coding-agent', id: 'workbuddy', label: 'WorkBuddy', icon: builtinAgentIcons.panda,
|
|
113
|
-
capabilities: { session: 'external_unscoped', model: false, cancel: false, progress: false },
|
|
114
|
-
probe(config) {
|
|
115
|
-
const available = Boolean(config.workbuddyToken && config.workbuddy?.allowUnscopedDispatch);
|
|
116
|
-
return { available, mode: 'dispatch_only', reason: available
|
|
117
|
-
? '可转交任务;如获消息读取授权可回显回复,无法保证指定代码目录或撤回'
|
|
118
|
-
: '需 WorkBuddy 开放平台授权,并显式允许无项目目录保证的转交模式' };
|
|
119
|
-
},
|
|
120
|
-
run, readUpdates, syncJobState,
|
|
121
|
-
};
|