@beeos-ai/device-agent 0.8.0 → 0.9.3
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/app/fixed-session-id.d.ts +19 -0
- package/dist/app/fixed-session-id.js +26 -0
- package/dist/app/fixed-session-id.js.map +1 -0
- package/dist/app/jsonl-session-sweeper.d.ts +90 -0
- package/dist/app/jsonl-session-sweeper.js +162 -0
- package/dist/app/jsonl-session-sweeper.js.map +1 -0
- package/dist/app/jsonl-store.d.ts +10 -0
- package/dist/app/jsonl-store.js +10 -4
- package/dist/app/jsonl-store.js.map +1 -1
- package/dist/app/session-manager.d.ts +135 -1
- package/dist/app/session-manager.js +195 -12
- package/dist/app/session-manager.js.map +1 -1
- package/dist/bootstrap.js +146 -2
- package/dist/bootstrap.js.map +1 -1
- package/dist/config/loader.js +2 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +2 -0
- package/dist/config/schema.js +41 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/fleet/domain/device.d.ts +17 -0
- package/dist/fleet/domain/device.js +1 -0
- package/dist/fleet/domain/device.js.map +1 -1
- package/dist/fleet/domain/fsm.d.ts +30 -1
- package/dist/fleet/domain/fsm.js +100 -4
- package/dist/fleet/domain/fsm.js.map +1 -1
- package/dist/fleet/supervisor.js +38 -18
- package/dist/fleet/supervisor.js.map +1 -1
- package/dist/plugins/acp/index.d.ts +27 -30
- package/dist/plugins/acp/index.js +44 -137
- package/dist/plugins/acp/index.js.map +1 -1
- package/dist/plugins/message-bus/busy-reply.js +13 -5
- package/dist/plugins/message-bus/busy-reply.js.map +1 -1
- package/dist/plugins/message-bus/cancel.d.ts +48 -0
- package/dist/plugins/message-bus/cancel.js +66 -0
- package/dist/plugins/message-bus/cancel.js.map +1 -0
- package/dist/plugins/message-bus/inbound.d.ts +38 -22
- package/dist/plugins/message-bus/inbound.js +113 -50
- package/dist/plugins/message-bus/inbound.js.map +1 -1
- package/dist/plugins/message-bus/index.d.ts +1 -2
- package/dist/plugins/message-bus/index.js +39 -37
- package/dist/plugins/message-bus/index.js.map +1 -1
- package/dist/plugins/message-bus/ms-channel-notifier.d.ts +113 -0
- package/dist/plugins/message-bus/ms-channel-notifier.js +206 -0
- package/dist/plugins/message-bus/ms-channel-notifier.js.map +1 -0
- package/dist/plugins/message-bus/ms-inflight-tracker.d.ts +36 -0
- package/dist/plugins/message-bus/ms-inflight-tracker.js +42 -0
- package/dist/plugins/message-bus/ms-inflight-tracker.js.map +1 -0
- package/dist/ports/plugin.d.ts +12 -0
- package/package.json +2 -2
- package/dist/agent-runtime/skills/sqlite-store.d.ts +0 -60
- package/dist/agent-runtime/skills/sqlite-store.js +0 -234
- package/dist/agent-runtime/skills/sqlite-store.js.map +0 -1
- package/dist/plugins/message-bus/outbound.d.ts +0 -43
- package/dist/plugins/message-bus/outbound.js +0 -149
- package/dist/plugins/message-bus/outbound.js.map +0 -1
- package/dist/plugins/message-bus/turn-context.d.ts +0 -57
- package/dist/plugins/message-bus/turn-context.js +0 -53
- package/dist/plugins/message-bus/turn-context.js.map +0 -1
- package/dist/test-lan-autoglm.d.ts +0 -7
- package/dist/test-lan-autoglm.js +0 -46
- package/dist/test-lan-autoglm.js.map +0 -1
- package/dist/test-mem-breakdown.d.ts +0 -1
- package/dist/test-mem-breakdown.js +0 -103
- package/dist/test-mem-breakdown.js.map +0 -1
- package/dist/test-mem.d.ts +0 -1
- package/dist/test-mem.js +0 -60
- package/dist/test-mem.js.map +0 -1
- package/dist/test-mobile-use.d.ts +0 -1
- package/dist/test-mobile-use.js +0 -18
- package/dist/test-mobile-use.js.map +0 -1
- package/dist/test-screenshot-loop.d.ts +0 -1
- package/dist/test-screenshot-loop.js +0 -43
- package/dist/test-screenshot-loop.js.map +0 -1
- package/dist/test-screenshot.d.ts +0 -1
- package/dist/test-screenshot.js +0 -10
- package/dist/test-screenshot.js.map +0 -1
- package/dist/test-ui-xml-dump.d.ts +0 -15
- package/dist/test-ui-xml-dump.js +0 -49
- package/dist/test-ui-xml-dump.js.map +0 -1
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* agent-runtime/skills/sqlite-store — SQLite-backed
|
|
3
|
-
* {@link SkillCacheStore}.
|
|
4
|
-
*
|
|
5
|
-
* Phase 3.1 of the [device-agent reflector upgrade plan](../../../../../../.cursor/plans/device-agent-reflector-skills_d5599350.plan.md).
|
|
6
|
-
*
|
|
7
|
-
* Schema (kept verbatim with the plan):
|
|
8
|
-
* ```sql
|
|
9
|
-
* CREATE TABLE skills (
|
|
10
|
-
* id TEXT PRIMARY KEY,
|
|
11
|
-
* app_package TEXT NOT NULL,
|
|
12
|
-
* task_summary TEXT NOT NULL,
|
|
13
|
-
* task_embedding BLOB,
|
|
14
|
-
* action_sequence_json TEXT NOT NULL,
|
|
15
|
-
* success_count INTEGER NOT NULL DEFAULT 1,
|
|
16
|
-
* fail_count INTEGER NOT NULL DEFAULT 0,
|
|
17
|
-
* last_used_at INTEGER NOT NULL,
|
|
18
|
-
* created_at INTEGER NOT NULL
|
|
19
|
-
* );
|
|
20
|
-
* CREATE INDEX idx_skills_app ON skills(app_package);
|
|
21
|
-
* ```
|
|
22
|
-
*
|
|
23
|
-
* Default DB path: `~/.beeos/device-agent/skills.sqlite`. Containerised
|
|
24
|
-
* deployments mount `/var/lib/beeos/device-agent` and override
|
|
25
|
-
* `SKILL_CACHE_PATH` accordingly.
|
|
26
|
-
*
|
|
27
|
-
* Search is implemented as a full scan over the matching app rows —
|
|
28
|
-
* the cache is intentionally small (<10k rows / device), so a brute
|
|
29
|
-
* cosine pass is cheaper than maintaining an ANN index. If profile
|
|
30
|
-
* data shows that's wrong we can plug in `sqlite-vss` / `pgvector`
|
|
31
|
-
* later behind the same {@link SkillCacheStore} interface.
|
|
32
|
-
*/
|
|
33
|
-
import { mkdirSync } from "node:fs";
|
|
34
|
-
import path from "node:path";
|
|
35
|
-
import { homedir } from "node:os";
|
|
36
|
-
import { randomUUID } from "node:crypto";
|
|
37
|
-
import Database from "better-sqlite3";
|
|
38
|
-
import { bufferToEmbedding, cosine, embeddingToBuffer, } from "./embedding.js";
|
|
39
|
-
const SCHEMA_VERSION = 1;
|
|
40
|
-
const SCHEMA_SQL = `
|
|
41
|
-
PRAGMA journal_mode=WAL;
|
|
42
|
-
PRAGMA synchronous=NORMAL;
|
|
43
|
-
PRAGMA foreign_keys=ON;
|
|
44
|
-
|
|
45
|
-
CREATE TABLE IF NOT EXISTS skills (
|
|
46
|
-
id TEXT PRIMARY KEY,
|
|
47
|
-
app_package TEXT NOT NULL,
|
|
48
|
-
task_summary TEXT NOT NULL,
|
|
49
|
-
task_embedding BLOB,
|
|
50
|
-
action_sequence_json TEXT NOT NULL,
|
|
51
|
-
success_count INTEGER NOT NULL DEFAULT 1,
|
|
52
|
-
fail_count INTEGER NOT NULL DEFAULT 0,
|
|
53
|
-
last_used_at INTEGER NOT NULL,
|
|
54
|
-
created_at INTEGER NOT NULL
|
|
55
|
-
);
|
|
56
|
-
CREATE INDEX IF NOT EXISTS idx_skills_app ON skills(app_package);
|
|
57
|
-
|
|
58
|
-
CREATE TABLE IF NOT EXISTS skill_meta (
|
|
59
|
-
key TEXT PRIMARY KEY,
|
|
60
|
-
value TEXT NOT NULL
|
|
61
|
-
);
|
|
62
|
-
`;
|
|
63
|
-
export function defaultSkillCachePath() {
|
|
64
|
-
const env = process.env.SKILL_CACHE_PATH;
|
|
65
|
-
if (env && env.length > 0)
|
|
66
|
-
return env;
|
|
67
|
-
return path.join(homedir(), ".beeos", "device-agent", "skills.sqlite");
|
|
68
|
-
}
|
|
69
|
-
export class SQLiteSkillCacheStore {
|
|
70
|
-
db;
|
|
71
|
-
stmts;
|
|
72
|
-
closed = false;
|
|
73
|
-
constructor(opts = {}) {
|
|
74
|
-
const dbPath = opts.path ?? defaultSkillCachePath();
|
|
75
|
-
if (opts.db) {
|
|
76
|
-
this.db = opts.db;
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
if (!opts.noMkdir && dbPath !== ":memory:") {
|
|
80
|
-
mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
81
|
-
}
|
|
82
|
-
this.db = new Database(dbPath);
|
|
83
|
-
}
|
|
84
|
-
this.db.exec(SCHEMA_SQL);
|
|
85
|
-
this.applyMigrations();
|
|
86
|
-
this.stmts = prepareStatements(this.db);
|
|
87
|
-
}
|
|
88
|
-
insert(input) {
|
|
89
|
-
if (this.closed)
|
|
90
|
-
throw new Error("SQLiteSkillCacheStore: handle closed");
|
|
91
|
-
const now = Date.now();
|
|
92
|
-
const id = randomUUID();
|
|
93
|
-
this.stmts.insert.run({
|
|
94
|
-
id,
|
|
95
|
-
app: input.appPackage,
|
|
96
|
-
summary: input.taskSummary,
|
|
97
|
-
embed: input.taskEmbedding ? embeddingToBuffer(input.taskEmbedding) : null,
|
|
98
|
-
seq: serialiseSequence(input.actionSequence),
|
|
99
|
-
now,
|
|
100
|
-
});
|
|
101
|
-
return {
|
|
102
|
-
id,
|
|
103
|
-
appPackage: input.appPackage,
|
|
104
|
-
taskSummary: input.taskSummary,
|
|
105
|
-
taskEmbedding: input.taskEmbedding ? new Float32Array(input.taskEmbedding) : undefined,
|
|
106
|
-
actionSequence: input.actionSequence,
|
|
107
|
-
successCount: 1,
|
|
108
|
-
failCount: 0,
|
|
109
|
-
lastUsedAt: now,
|
|
110
|
-
createdAt: now,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
get(id) {
|
|
114
|
-
const row = this.stmts.getById.get({ id });
|
|
115
|
-
return row ? rowToSkill(row) : undefined;
|
|
116
|
-
}
|
|
117
|
-
listByApp(appPackage, limit = 50) {
|
|
118
|
-
const rows = this.stmts.listByApp.all({ app: appPackage, limit });
|
|
119
|
-
return rows.map(rowToSkill);
|
|
120
|
-
}
|
|
121
|
-
listAll(limit = 200) {
|
|
122
|
-
const rows = this.stmts.listAll.all({ limit });
|
|
123
|
-
return rows.map(rowToSkill);
|
|
124
|
-
}
|
|
125
|
-
search(appPackage, query, k) {
|
|
126
|
-
const rows = this.stmts.searchByApp.all({ app: appPackage });
|
|
127
|
-
const matches = [];
|
|
128
|
-
for (const row of rows) {
|
|
129
|
-
if (!row.task_embedding)
|
|
130
|
-
continue;
|
|
131
|
-
const v = bufferToEmbedding(row.task_embedding);
|
|
132
|
-
if (v.length !== query.length)
|
|
133
|
-
continue;
|
|
134
|
-
const score = cosine(query, v);
|
|
135
|
-
matches.push({ skill: rowToSkill(row), score });
|
|
136
|
-
}
|
|
137
|
-
matches.sort((a, b) => b.score - a.score);
|
|
138
|
-
return matches.slice(0, Math.max(0, k));
|
|
139
|
-
}
|
|
140
|
-
recordSuccess(id, now = Date.now()) {
|
|
141
|
-
this.stmts.success.run({ id, now });
|
|
142
|
-
}
|
|
143
|
-
recordFailure(id, now = Date.now()) {
|
|
144
|
-
this.stmts.failure.run({ id, now });
|
|
145
|
-
}
|
|
146
|
-
delete(id) {
|
|
147
|
-
const res = this.stmts.delete.run({ id });
|
|
148
|
-
return res.changes > 0;
|
|
149
|
-
}
|
|
150
|
-
clear() {
|
|
151
|
-
this.db.exec("DELETE FROM skills;");
|
|
152
|
-
}
|
|
153
|
-
close() {
|
|
154
|
-
if (this.closed)
|
|
155
|
-
return;
|
|
156
|
-
this.closed = true;
|
|
157
|
-
try {
|
|
158
|
-
this.db.close();
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
/* swallow — close is best-effort */
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
applyMigrations() {
|
|
165
|
-
const row = this.db
|
|
166
|
-
.prepare("SELECT value FROM skill_meta WHERE key = 'schema_version'")
|
|
167
|
-
.get();
|
|
168
|
-
if (!row) {
|
|
169
|
-
this.db
|
|
170
|
-
.prepare("INSERT INTO skill_meta(key, value) VALUES('schema_version', ?)")
|
|
171
|
-
.run(String(SCHEMA_VERSION));
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
// Future migrations would diff `row.value` against SCHEMA_VERSION here.
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
function prepareStatements(db) {
|
|
178
|
-
return {
|
|
179
|
-
insert: db.prepare(`INSERT INTO skills (
|
|
180
|
-
id, app_package, task_summary, task_embedding,
|
|
181
|
-
action_sequence_json, success_count, fail_count, last_used_at, created_at
|
|
182
|
-
) VALUES (
|
|
183
|
-
@id, @app, @summary, @embed,
|
|
184
|
-
@seq, 1, 0, @now, @now
|
|
185
|
-
);`),
|
|
186
|
-
getById: db.prepare(`SELECT * FROM skills WHERE id = @id`),
|
|
187
|
-
listByApp: db.prepare(`SELECT * FROM skills
|
|
188
|
-
WHERE app_package = @app
|
|
189
|
-
ORDER BY last_used_at DESC
|
|
190
|
-
LIMIT @limit`),
|
|
191
|
-
listAll: db.prepare(`SELECT * FROM skills
|
|
192
|
-
ORDER BY last_used_at DESC
|
|
193
|
-
LIMIT @limit`),
|
|
194
|
-
searchByApp: db.prepare(`SELECT * FROM skills WHERE app_package = @app`),
|
|
195
|
-
success: db.prepare(`UPDATE skills SET success_count = success_count + 1,
|
|
196
|
-
last_used_at = @now
|
|
197
|
-
WHERE id = @id`),
|
|
198
|
-
failure: db.prepare(`UPDATE skills SET fail_count = fail_count + 1,
|
|
199
|
-
last_used_at = @now
|
|
200
|
-
WHERE id = @id`),
|
|
201
|
-
delete: db.prepare(`DELETE FROM skills WHERE id = @id`),
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
function serialiseSequence(seq) {
|
|
205
|
-
return JSON.stringify(seq);
|
|
206
|
-
}
|
|
207
|
-
function deserialiseSequence(raw) {
|
|
208
|
-
if (!raw)
|
|
209
|
-
return [];
|
|
210
|
-
try {
|
|
211
|
-
const v = JSON.parse(raw);
|
|
212
|
-
if (Array.isArray(v)) {
|
|
213
|
-
return v;
|
|
214
|
-
}
|
|
215
|
-
return [];
|
|
216
|
-
}
|
|
217
|
-
catch {
|
|
218
|
-
return [];
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
function rowToSkill(row) {
|
|
222
|
-
return {
|
|
223
|
-
id: row.id,
|
|
224
|
-
appPackage: row.app_package,
|
|
225
|
-
taskSummary: row.task_summary,
|
|
226
|
-
taskEmbedding: row.task_embedding ? bufferToEmbedding(row.task_embedding) : undefined,
|
|
227
|
-
actionSequence: deserialiseSequence(row.action_sequence_json),
|
|
228
|
-
successCount: row.success_count,
|
|
229
|
-
failCount: row.fail_count,
|
|
230
|
-
lastUsedAt: row.last_used_at,
|
|
231
|
-
createdAt: row.created_at,
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
//# sourceMappingURL=sqlite-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-store.js","sourceRoot":"","sources":["../../../src/agent-runtime/skills/sqlite-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Outbound — bridge AgentHost events back to the MS IM channel.
|
|
3
|
-
*
|
|
4
|
-
* Subscribes to `AgentHost.on(listener)` ONCE at plugin start, then
|
|
5
|
-
* publishes Centrifugo `ch:{channelId}` envelopes whose shape matches
|
|
6
|
-
* the contract the rest of the BeeOS platform expects:
|
|
7
|
-
*
|
|
8
|
-
* - `agent_reply_delta` — streaming chunks. Carries an inner
|
|
9
|
-
* `update.sessionUpdate` field that callers (A2A / OpenAPI) demux
|
|
10
|
-
* on. Only `agent_message_chunk` is treated as user-visible
|
|
11
|
-
* reply text by `backend/pkg/convmsg/extract.go::extractNestedDelta`;
|
|
12
|
-
* `agent_thought_chunk` is intentionally filtered out so reasoning
|
|
13
|
-
* never leaks into status text.
|
|
14
|
-
*
|
|
15
|
-
* - `agent_reply` — terminal reply on `task:end`. `payload.text` for
|
|
16
|
-
* success, `payload.error` for failure. Matches
|
|
17
|
-
* `chatinvoke/invoker.go::extractReplyFinal`.
|
|
18
|
-
*
|
|
19
|
-
* Each envelope carries `in_reply_to` set to the original request's
|
|
20
|
-
* `message_id`, which is what the L0 `/channels/{id}/wait` endpoint
|
|
21
|
-
* matches on.
|
|
22
|
-
*
|
|
23
|
-
* The listener filters by taskId via the in-flight register — events
|
|
24
|
-
* for tasks NOT submitted through the message-bus inbound (e.g. ACP
|
|
25
|
-
* `session/prompt` traffic) are ignored, so the two surfaces never
|
|
26
|
-
* collide.
|
|
27
|
-
*/
|
|
28
|
-
import type { MessageSDK } from "@beeos-ai/message-sdk";
|
|
29
|
-
import type { AgentHost } from "../../ports/agent-host.js";
|
|
30
|
-
import type { Logger } from "../../logger/index.js";
|
|
31
|
-
import type { TurnContextRegister } from "./turn-context.js";
|
|
32
|
-
export interface MessageBusOutboundOptions {
|
|
33
|
-
host: AgentHost;
|
|
34
|
-
sdk: MessageSDK;
|
|
35
|
-
register: TurnContextRegister;
|
|
36
|
-
logger: Logger;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Install the outbound listener on the host. Returns an `unsubscribe`
|
|
40
|
-
* function — call it from the plugin's `stop()` so we don't keep
|
|
41
|
-
* publishing after the SDK has been disconnected.
|
|
42
|
-
*/
|
|
43
|
-
export declare function installMessageBusOutbound(opts: MessageBusOutboundOptions): () => void;
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Outbound — bridge AgentHost events back to the MS IM channel.
|
|
3
|
-
*
|
|
4
|
-
* Subscribes to `AgentHost.on(listener)` ONCE at plugin start, then
|
|
5
|
-
* publishes Centrifugo `ch:{channelId}` envelopes whose shape matches
|
|
6
|
-
* the contract the rest of the BeeOS platform expects:
|
|
7
|
-
*
|
|
8
|
-
* - `agent_reply_delta` — streaming chunks. Carries an inner
|
|
9
|
-
* `update.sessionUpdate` field that callers (A2A / OpenAPI) demux
|
|
10
|
-
* on. Only `agent_message_chunk` is treated as user-visible
|
|
11
|
-
* reply text by `backend/pkg/convmsg/extract.go::extractNestedDelta`;
|
|
12
|
-
* `agent_thought_chunk` is intentionally filtered out so reasoning
|
|
13
|
-
* never leaks into status text.
|
|
14
|
-
*
|
|
15
|
-
* - `agent_reply` — terminal reply on `task:end`. `payload.text` for
|
|
16
|
-
* success, `payload.error` for failure. Matches
|
|
17
|
-
* `chatinvoke/invoker.go::extractReplyFinal`.
|
|
18
|
-
*
|
|
19
|
-
* Each envelope carries `in_reply_to` set to the original request's
|
|
20
|
-
* `message_id`, which is what the L0 `/channels/{id}/wait` endpoint
|
|
21
|
-
* matches on.
|
|
22
|
-
*
|
|
23
|
-
* The listener filters by taskId via the in-flight register — events
|
|
24
|
-
* for tasks NOT submitted through the message-bus inbound (e.g. ACP
|
|
25
|
-
* `session/prompt` traffic) are ignored, so the two surfaces never
|
|
26
|
-
* collide.
|
|
27
|
-
*/
|
|
28
|
-
/**
|
|
29
|
-
* Install the outbound listener on the host. Returns an `unsubscribe`
|
|
30
|
-
* function — call it from the plugin's `stop()` so we don't keep
|
|
31
|
-
* publishing after the SDK has been disconnected.
|
|
32
|
-
*/
|
|
33
|
-
export function installMessageBusOutbound(opts) {
|
|
34
|
-
const listener = (event) => {
|
|
35
|
-
void handleEvent(event, opts);
|
|
36
|
-
};
|
|
37
|
-
return opts.host.on(listener);
|
|
38
|
-
}
|
|
39
|
-
async function handleEvent(event, opts) {
|
|
40
|
-
const ctx = opts.register.getByTaskId(event.taskId);
|
|
41
|
-
if (!ctx)
|
|
42
|
-
return; // Not an MS-originated turn — ignored.
|
|
43
|
-
try {
|
|
44
|
-
switch (event.type) {
|
|
45
|
-
case "task:start":
|
|
46
|
-
// Intentionally not emitted. beeos-claw does not publish an
|
|
47
|
-
// `agent_status` delta on prompt start either — see
|
|
48
|
-
// [acp-server.ts onStreamDelta](agents/beeos-claw/src/acp-server.ts);
|
|
49
|
-
// the first wire publish is the first real LLM delta. The
|
|
50
|
-
// server-side `extractNestedDelta` only honours
|
|
51
|
-
// `agent_message_chunk` anyway, so synthesising an extra
|
|
52
|
-
// `agent_status` envelope would be pure noise. KISS — skip.
|
|
53
|
-
return;
|
|
54
|
-
case "task:text":
|
|
55
|
-
await sendDelta(opts, ctx, "agent_message_chunk", event.text);
|
|
56
|
-
return;
|
|
57
|
-
case "task:reasoning":
|
|
58
|
-
await sendDelta(opts, ctx, "agent_thought_chunk", event.text);
|
|
59
|
-
return;
|
|
60
|
-
case "task:notice":
|
|
61
|
-
// Notices (warnings / non-fatal errors) surface as user-visible
|
|
62
|
-
// chunks so the operator sees something. Same `agent_message_chunk`
|
|
63
|
-
// sessionUpdate so they get included in the final concatenated
|
|
64
|
-
// text by extractNestedDelta. Payload is the canonical
|
|
65
|
-
// `{ session_key, update }` shape — no extra fields, matching
|
|
66
|
-
// beeos-claw's onStreamDelta output exactly.
|
|
67
|
-
await sendDelta(opts, ctx, "agent_message_chunk", event.text);
|
|
68
|
-
return;
|
|
69
|
-
case "task:tool":
|
|
70
|
-
case "task:step":
|
|
71
|
-
// Tool calls and step transitions are debug-grade today —
|
|
72
|
-
// streaming them would dilute the agent_message_chunk text.
|
|
73
|
-
// Skip silently; callers that want richer telemetry should
|
|
74
|
-
// subscribe to the personal channel directly.
|
|
75
|
-
return;
|
|
76
|
-
case "task:end": {
|
|
77
|
-
const ok = !event.error;
|
|
78
|
-
const finalText = (event.result?.finalMessage ??
|
|
79
|
-
event.result?.text ??
|
|
80
|
-
"") || "";
|
|
81
|
-
// Wire shape mirrors beeos-claw `[acp-server.ts:498/:514]`
|
|
82
|
-
// (agents/beeos-claw/src/acp-server.ts):
|
|
83
|
-
// success → { session_key, text }
|
|
84
|
-
// failure → { session_key, error } (text optional)
|
|
85
|
-
const payload = ok
|
|
86
|
-
? { session_key: ctx.sessionKey, text: finalText }
|
|
87
|
-
: {
|
|
88
|
-
session_key: ctx.sessionKey,
|
|
89
|
-
error: event.error ?? "unknown_error",
|
|
90
|
-
text: finalText,
|
|
91
|
-
};
|
|
92
|
-
await opts.sdk.sendToChannel(ctx.channelId, "agent_reply", payload, { inReplyTo: ctx.inboundMessageId });
|
|
93
|
-
opts.logger.info({
|
|
94
|
-
taskId: event.taskId,
|
|
95
|
-
channelId: ctx.channelId,
|
|
96
|
-
ok,
|
|
97
|
-
durationMs: event.completedAt - ctx.startedAt,
|
|
98
|
-
}, "message-bus: turn finished");
|
|
99
|
-
opts.register.clear(event.taskId);
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
catch (err) {
|
|
105
|
-
// Never throw out of the AgentHost listener — that would crash the
|
|
106
|
-
// entire event fan-out. Log and continue; the next event for the
|
|
107
|
-
// same task will retry the publish path.
|
|
108
|
-
opts.logger.error({
|
|
109
|
-
err: err instanceof Error ? err.message : String(err),
|
|
110
|
-
eventType: event.type,
|
|
111
|
-
taskId: event.taskId,
|
|
112
|
-
channelId: ctx.channelId,
|
|
113
|
-
}, "message-bus: outbound publish failed");
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Publish a single `agent_reply_delta` envelope.
|
|
118
|
-
*
|
|
119
|
-
* Wire shape locked-in to match beeos-claw
|
|
120
|
-
* [`acp-server.ts onStreamDelta` (acp-server.ts:438-450)](agents/beeos-claw/src/acp-server.ts):
|
|
121
|
-
*
|
|
122
|
-
* ```json
|
|
123
|
-
* {
|
|
124
|
-
* "session_key": "agent:{id}:invoke:ctx-...",
|
|
125
|
-
* "update": {
|
|
126
|
-
* "sessionUpdate": "agent_message_chunk" | "agent_thought_chunk",
|
|
127
|
-
* "content": { "type": "text", "text": "..." }
|
|
128
|
-
* }
|
|
129
|
-
* }
|
|
130
|
-
* ```
|
|
131
|
-
*
|
|
132
|
-
* Server-side `backend/pkg/convmsg/extract.go::extractNestedDelta`
|
|
133
|
-
* filters on `update.sessionUpdate === "agent_message_chunk"` for
|
|
134
|
-
* user-visible reply text — `agent_thought_chunk` is dropped so
|
|
135
|
-
* reasoning never leaks into status text. The `session_key` field is
|
|
136
|
-
* forward-compatible: no current backend consumer reads it (verified
|
|
137
|
-
* via `rg session_key backend/`), but emitting it preserves byte-for-
|
|
138
|
-
* byte parity with beeos-claw for downstream observers.
|
|
139
|
-
*/
|
|
140
|
-
async function sendDelta(opts, ctx, sessionUpdate, text) {
|
|
141
|
-
await opts.sdk.sendToChannel(ctx.channelId, "agent_reply_delta", {
|
|
142
|
-
session_key: ctx.sessionKey,
|
|
143
|
-
update: {
|
|
144
|
-
sessionUpdate,
|
|
145
|
-
content: { type: "text", text },
|
|
146
|
-
},
|
|
147
|
-
}, { inReplyTo: ctx.inboundMessageId });
|
|
148
|
-
}
|
|
149
|
-
//# sourceMappingURL=outbound.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"outbound.js","sourceRoot":"","sources":["../../../src/plugins/message-bus/outbound.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* In-flight Message-Service turn register.
|
|
3
|
-
*
|
|
4
|
-
* Holds the channel + reply correlator for the SINGLE turn that's
|
|
5
|
-
* currently executing on the host. Single-entry by design — device-agent
|
|
6
|
-
* runs one ACP session and the SessionManager serialises turns inside
|
|
7
|
-
* that session, so a second concurrent `chat_message` would be a logic
|
|
8
|
-
* error and is rejected via `busy-reply.ts`.
|
|
9
|
-
*
|
|
10
|
-
* The taskId is allocated by `host.submitTask(...)` and used to filter
|
|
11
|
-
* the `host.on(listener)` event stream so we never publish another
|
|
12
|
-
* turn's deltas to the wrong MS channel.
|
|
13
|
-
*/
|
|
14
|
-
export interface MessagingTurnContext {
|
|
15
|
-
/** Allocated by `host.submitTask` — used to filter AgentEvent stream. */
|
|
16
|
-
taskId: string;
|
|
17
|
-
/** IM channel the reply is published on (`ch:{channelId}`). */
|
|
18
|
-
channelId: string;
|
|
19
|
-
/** Request `message_id` echoed back as `in_reply_to` on every reply. */
|
|
20
|
-
inboundMessageId: string;
|
|
21
|
-
/**
|
|
22
|
-
* Stable session anchor (e.g. `agent:{id}:invoke:ctx-{contextId}` or
|
|
23
|
-
* `agent:{id}:invoke:ch-{channelId}`) derived by `extractChatPrompt`.
|
|
24
|
-
* Embedded as `payload.session_key` on every outbound publish so the
|
|
25
|
-
* wire format matches beeos-claw `[acp-server.ts:443]`
|
|
26
|
-
* (agents/beeos-claw/src/acp-server.ts) — downstream consumers
|
|
27
|
-
* (dashboards, A2A SSE projection) use it to group chunks belonging
|
|
28
|
-
* to the same logical conversation turn.
|
|
29
|
-
*/
|
|
30
|
-
sessionKey: string;
|
|
31
|
-
/** Optional context-id, surfaced for logging only. */
|
|
32
|
-
contextId?: string;
|
|
33
|
-
/** Wall-clock timestamp the turn was claimed (ms). For diagnostics. */
|
|
34
|
-
startedAt: number;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Single-entry in-flight register.
|
|
38
|
-
*
|
|
39
|
-
* Methods are intentionally synchronous — they run on the WS publication
|
|
40
|
-
* callback (low latency) and on AgentHost listener invocations.
|
|
41
|
-
*/
|
|
42
|
-
export declare class TurnContextRegister {
|
|
43
|
-
private current;
|
|
44
|
-
isBusy(): boolean;
|
|
45
|
-
/**
|
|
46
|
-
* Claim the register for a new turn. Returns the entry on success or
|
|
47
|
-
* `null` when a previous turn is still in flight (caller MUST then
|
|
48
|
-
* use the busy-reply path).
|
|
49
|
-
*/
|
|
50
|
-
claim(entry: Omit<MessagingTurnContext, "startedAt">): MessagingTurnContext | null;
|
|
51
|
-
current_(): MessagingTurnContext | null;
|
|
52
|
-
getByTaskId(taskId: string): MessagingTurnContext | null;
|
|
53
|
-
/** Idempotent — clearing twice is a no-op. */
|
|
54
|
-
clear(taskId: string): void;
|
|
55
|
-
/** Force-clear (used during plugin stop / disconnect). */
|
|
56
|
-
reset(): void;
|
|
57
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* In-flight Message-Service turn register.
|
|
3
|
-
*
|
|
4
|
-
* Holds the channel + reply correlator for the SINGLE turn that's
|
|
5
|
-
* currently executing on the host. Single-entry by design — device-agent
|
|
6
|
-
* runs one ACP session and the SessionManager serialises turns inside
|
|
7
|
-
* that session, so a second concurrent `chat_message` would be a logic
|
|
8
|
-
* error and is rejected via `busy-reply.ts`.
|
|
9
|
-
*
|
|
10
|
-
* The taskId is allocated by `host.submitTask(...)` and used to filter
|
|
11
|
-
* the `host.on(listener)` event stream so we never publish another
|
|
12
|
-
* turn's deltas to the wrong MS channel.
|
|
13
|
-
*/
|
|
14
|
-
/**
|
|
15
|
-
* Single-entry in-flight register.
|
|
16
|
-
*
|
|
17
|
-
* Methods are intentionally synchronous — they run on the WS publication
|
|
18
|
-
* callback (low latency) and on AgentHost listener invocations.
|
|
19
|
-
*/
|
|
20
|
-
export class TurnContextRegister {
|
|
21
|
-
current = null;
|
|
22
|
-
isBusy() {
|
|
23
|
-
return this.current !== null;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Claim the register for a new turn. Returns the entry on success or
|
|
27
|
-
* `null` when a previous turn is still in flight (caller MUST then
|
|
28
|
-
* use the busy-reply path).
|
|
29
|
-
*/
|
|
30
|
-
claim(entry) {
|
|
31
|
-
if (this.current)
|
|
32
|
-
return null;
|
|
33
|
-
this.current = { ...entry, startedAt: Date.now() };
|
|
34
|
-
return this.current;
|
|
35
|
-
}
|
|
36
|
-
current_() {
|
|
37
|
-
return this.current;
|
|
38
|
-
}
|
|
39
|
-
getByTaskId(taskId) {
|
|
40
|
-
return this.current && this.current.taskId === taskId ? this.current : null;
|
|
41
|
-
}
|
|
42
|
-
/** Idempotent — clearing twice is a no-op. */
|
|
43
|
-
clear(taskId) {
|
|
44
|
-
if (this.current && this.current.taskId === taskId) {
|
|
45
|
-
this.current = null;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
/** Force-clear (used during plugin stop / disconnect). */
|
|
49
|
-
reset() {
|
|
50
|
-
this.current = null;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
//# sourceMappingURL=turn-context.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"turn-context.js","sourceRoot":"","sources":["../../../src/plugins/message-bus/turn-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAyBH;;;;;GAKG;AACH,MAAM,OAAO,mBAAmB;IACtB,OAAO,GAAgC,IAAI,CAAC;IAEpD,MAAM;QACJ,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAA8C;QAClD,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACnD,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,WAAW,CAAC,MAAc;QACxB,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,CAAC;IAED,8CAA8C;IAC9C,KAAK,CAAC,MAAc;QAClB,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACnD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;CACF"}
|
package/dist/test-lan-autoglm.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 验证局域网 OpenAI 兼容 AutoGLM 与 device-agent-ts 内层链路(adapter=autoglm + OpenAIClient)。
|
|
3
|
-
* 需要:adb 已连机、本机可访问 GUI_AGENT_BASE_URL、.env 已配置。
|
|
4
|
-
*
|
|
5
|
-
* npx tsx src/test-lan-autoglm.ts
|
|
6
|
-
*/
|
|
7
|
-
import "dotenv/config";
|
|
8
|
-
import { AndroidDevice } from "./device/android.js";
|
|
9
|
-
import { OpenAIClient } from "./model/client.js";
|
|
10
|
-
const TASK = process.env.LAN_VLM_SMOKE_TASK ??
|
|
11
|
-
"看当前截图,只输出一行下一步操作(不要复述用户原话里的示例代码):用 do(action=\"Tap\", element=[x,y]) 点击你认为该点的位置,坐标 0–1000。";
|
|
12
|
-
async function main() {
|
|
13
|
-
const base = process.env.GUI_AGENT_BASE_URL ?? "";
|
|
14
|
-
const model = process.env.GUI_AGENT_MODEL ?? "";
|
|
15
|
-
if (!base || !model) {
|
|
16
|
-
console.error("请设置 GUI_AGENT_BASE_URL、GUI_AGENT_MODEL(及 API_KEY)");
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
console.log(`[lan-autoglm] base=${base} model=${model} adapter=${process.env.GUI_AGENT_ADAPTER ?? "(auto)"} stream=${process.env.GUI_AGENT_STREAM ?? "1"}`);
|
|
20
|
-
const device = new AndroidDevice(process.env.GUI_AGENT_DEVICE_ID ?? undefined);
|
|
21
|
-
const ss = await device.takeScreenshot();
|
|
22
|
-
const currentApp = await device.getCurrentApp();
|
|
23
|
-
const client = new OpenAIClient({
|
|
24
|
-
adapter: process.env.GUI_AGENT_ADAPTER ?? "autoglm",
|
|
25
|
-
});
|
|
26
|
-
const screenInfo = {
|
|
27
|
-
screenshotB64: ss.base64Data,
|
|
28
|
-
width: ss.width,
|
|
29
|
-
height: ss.height,
|
|
30
|
-
currentApp,
|
|
31
|
-
uiXml: null,
|
|
32
|
-
};
|
|
33
|
-
const messages = client.buildMessages(TASK, screenInfo, [], true, (process.env.GUI_AGENT_LANG ?? "cn"));
|
|
34
|
-
console.log(`[lan-autoglm] requesting… (${messages.length} messages, jpeg b64 ~${Math.round(ss.base64Data.length / 1024)} KB)`);
|
|
35
|
-
const t0 = Date.now();
|
|
36
|
-
const resp = await client.request(messages, true);
|
|
37
|
-
const ms = Date.now() - t0;
|
|
38
|
-
console.log("\n--- raw (prefix) ---\n", resp.rawContent.slice(0, 1500), resp.rawContent.length > 1500 ? "\n…" : "");
|
|
39
|
-
console.log("\n--- parsed ---\n", JSON.stringify(client.parseResponse(resp.rawContent), null, 2));
|
|
40
|
-
console.log(`\n[lan-autoglm] ok in ${ms} ms`);
|
|
41
|
-
}
|
|
42
|
-
main().catch((e) => {
|
|
43
|
-
console.error(e);
|
|
44
|
-
process.exit(1);
|
|
45
|
-
});
|
|
46
|
-
//# sourceMappingURL=test-lan-autoglm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test-lan-autoglm.js","sourceRoot":"","sources":["../src/test-lan-autoglm.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "dotenv/config";
|