@bytetrue/byspace 0.17.0 → 0.18.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/node_modules/@bytetrue/client/package.json +3 -3
- package/node_modules/@bytetrue/highlight/package.json +1 -1
- package/node_modules/@bytetrue/protocol/package.json +1 -1
- package/node_modules/@bytetrue/relay/package.json +1 -1
- package/node_modules/@bytetrue/server/dist/server/server/agent/agent-manager.d.ts +30 -0
- package/node_modules/@bytetrue/server/dist/server/server/agent/agent-manager.js +118 -8
- package/node_modules/@bytetrue/server/dist/server/server/agent/mcp-shared.d.ts +1 -1
- package/node_modules/@bytetrue/server/dist/server/server/agent/{providers/claude/subagents → provider-subagents}/observation.d.ts +2 -2
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/claude/agent.js +1 -1
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/claude/subagents/live-source.d.ts +1 -1
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/claude/subagents/replay-source.d.ts +1 -1
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/claude/subagents/workflow-replay-source.d.ts +1 -1
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/omp/rpc-types.d.ts +6 -6
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/pi/agent-subagents.d.ts +45 -0
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/pi/agent-subagents.js +159 -0
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/pi/agent.d.ts +2 -2
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/pi/agent.js +86 -151
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/pi/runtime.d.ts +0 -2
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/pi/runtime.js +0 -4
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/pi/session-descriptor.d.ts +2 -0
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/pi/session-descriptor.js +2 -2
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/pi/subagent-session-tailer.d.ts +47 -0
- package/node_modules/@bytetrue/server/dist/server/server/agent/providers/pi/subagent-session-tailer.js +212 -0
- package/node_modules/@bytetrue/server/dist/server/server/bootstrap.d.ts +6 -0
- package/node_modules/@bytetrue/server/dist/server/server/bootstrap.js +49 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/{index-8d553cf4f8b1937dcd7c1da125243e39.js → index-5762beef0f3c7a285c88f6cb383d0f16.js} +485 -484
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/index-5762beef0f3c7a285c88f6cb383d0f16.js.br +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/index-5762beef0f3c7a285c88f6cb383d0f16.js.gz +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-9f3696181e42915ed4f9cb01f7595007.js → indexeddb-attachment-store-433f8ff1c621845eba95cc633f47b72d.js} +1 -1
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-433f8ff1c621845eba95cc633f47b72d.js.br +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-433f8ff1c621845eba95cc633f47b72d.js.gz +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/{native-file-attachment-store-f829a425d0a064f4a9b4b153d185a3fb.js → native-file-attachment-store-6ed537a199e954caec287e6d28945868.js} +3 -3
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-6ed537a199e954caec287e6d28945868.js.br +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-6ed537a199e954caec287e6d28945868.js.gz +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/index.html +1 -1
- package/node_modules/@bytetrue/server/dist/server/web-ui/index.html.br +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/index.html.gz +0 -0
- package/node_modules/@bytetrue/server/dist/src/server/agent/agent-manager.js +118 -8
- package/node_modules/@bytetrue/server/dist/src/server/agent/providers/claude/agent.js +1 -1
- package/node_modules/@bytetrue/server/dist/src/server/agent/providers/pi/agent-subagents.js +159 -0
- package/node_modules/@bytetrue/server/dist/src/server/agent/providers/pi/agent.js +86 -151
- package/node_modules/@bytetrue/server/dist/src/server/agent/providers/pi/runtime.js +0 -4
- package/node_modules/@bytetrue/server/dist/src/server/agent/providers/pi/session-descriptor.js +2 -2
- package/node_modules/@bytetrue/server/dist/src/server/agent/providers/pi/subagent-session-tailer.js +212 -0
- package/node_modules/@bytetrue/server/package.json +5 -5
- package/package.json +7 -7
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/index-8d553cf4f8b1937dcd7c1da125243e39.js.br +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/index-8d553cf4f8b1937dcd7c1da125243e39.js.gz +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-9f3696181e42915ed4f9cb01f7595007.js.br +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-9f3696181e42915ed4f9cb01f7595007.js.gz +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-f829a425d0a064f4a9b4b153d185a3fb.js.br +0 -0
- package/node_modules/@bytetrue/server/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-f829a425d0a064f4a9b4b153d185a3fb.js.gz +0 -0
- /package/node_modules/@bytetrue/server/dist/server/server/agent/{providers/claude/subagents → provider-subagents}/observation.js +0 -0
- /package/node_modules/@bytetrue/server/dist/src/server/agent/{providers/claude/subagents → provider-subagents}/observation.js +0 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { open, stat } from "node:fs/promises";
|
|
2
|
+
import { mapPiSubagentStatus } from "./agent-subagents.js";
|
|
3
|
+
import { PiHistoryMapper } from "./history-mapper.js";
|
|
4
|
+
import { resolvePiSessionsDir, walkJsonlFiles } from "./session-descriptor.js";
|
|
5
|
+
export const PI_SUBAGENT_TERMINAL_STATUSES = ["completed", "failed", "canceled"];
|
|
6
|
+
const DEFAULT_POLL_MS = 1000;
|
|
7
|
+
const LOCATE_RETRY_MS = 5000;
|
|
8
|
+
const TERMINAL_DRAIN_GRACE_MS = 3000;
|
|
9
|
+
/**
|
|
10
|
+
* Extract the tailer-relevant fields from a pi-subagent report record. The subagent id is
|
|
11
|
+
* required (it keys the tailer); session references start the tail, status tracks the end.
|
|
12
|
+
* Status-only snapshots matter too: they flip the entry to terminal so the tail stops.
|
|
13
|
+
*/
|
|
14
|
+
export function parsePiSubagentTailerSnapshot(record) {
|
|
15
|
+
if (typeof record !== "object" || record === null)
|
|
16
|
+
return null;
|
|
17
|
+
const source = record;
|
|
18
|
+
const subagentId = readString(source.id);
|
|
19
|
+
if (!subagentId)
|
|
20
|
+
return null;
|
|
21
|
+
const snapshot = { subagentId };
|
|
22
|
+
for (const key of ["sessionId", "sessionFile", "cwd", "status"]) {
|
|
23
|
+
const value = source[key];
|
|
24
|
+
if (typeof value === "string" && value.trim())
|
|
25
|
+
snapshot[key] = value;
|
|
26
|
+
}
|
|
27
|
+
return snapshot.sessionId || snapshot.sessionFile || snapshot.cwd || snapshot.status
|
|
28
|
+
? snapshot
|
|
29
|
+
: null;
|
|
30
|
+
}
|
|
31
|
+
function readString(value) {
|
|
32
|
+
return typeof value === "string" && value.trim() ? value : null;
|
|
33
|
+
}
|
|
34
|
+
async function drainPiSessionTailer(tailer, onTimeline) {
|
|
35
|
+
const info = await stat(tailer.file).catch(() => null);
|
|
36
|
+
if (!info?.isFile())
|
|
37
|
+
return;
|
|
38
|
+
if (info.size < tailer.offset) {
|
|
39
|
+
// File shrank (recreated): restart from the beginning with fresh mapper state.
|
|
40
|
+
tailer.offset = 0;
|
|
41
|
+
tailer.mapper = new PiHistoryMapper("pi");
|
|
42
|
+
}
|
|
43
|
+
if (info.size === tailer.offset)
|
|
44
|
+
return;
|
|
45
|
+
const handle = await open(tailer.file, "r");
|
|
46
|
+
try {
|
|
47
|
+
const length = info.size - tailer.offset;
|
|
48
|
+
const buffer = Buffer.alloc(length);
|
|
49
|
+
// A short read means the file was truncated between stat and read; parse only
|
|
50
|
+
// the bytes that actually arrived.
|
|
51
|
+
const { bytesRead } = await handle.read(buffer, 0, length, tailer.offset);
|
|
52
|
+
const text = buffer.toString("utf8", 0, bytesRead);
|
|
53
|
+
const lastNewline = text.lastIndexOf("\n");
|
|
54
|
+
if (lastNewline === -1)
|
|
55
|
+
return;
|
|
56
|
+
const chunk = text.slice(0, lastNewline + 1);
|
|
57
|
+
tailer.offset += Buffer.byteLength(chunk);
|
|
58
|
+
for (const line of chunk.split("\n")) {
|
|
59
|
+
const trimmed = line.trim();
|
|
60
|
+
if (!trimmed)
|
|
61
|
+
continue;
|
|
62
|
+
let entry;
|
|
63
|
+
try {
|
|
64
|
+
entry = JSON.parse(trimmed);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (typeof entry !== "object" || entry === null)
|
|
70
|
+
continue;
|
|
71
|
+
const message = entry.message;
|
|
72
|
+
if (typeof message !== "object" || message === null)
|
|
73
|
+
continue;
|
|
74
|
+
const timestamp = readString(entry.timestamp) ?? undefined;
|
|
75
|
+
const events = tailer.mapper.mapMessages([message]);
|
|
76
|
+
for (const event of events) {
|
|
77
|
+
if (event.type === "timeline") {
|
|
78
|
+
onTimeline(event.item, timestamp);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
await handle.close();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export async function locatePiSubagentSessionFile(sessionId, options = {}) {
|
|
88
|
+
const sessionsDir = await resolvePiSessionsDir({
|
|
89
|
+
cwd: options.cwd ?? undefined,
|
|
90
|
+
env: options.env ?? process.env,
|
|
91
|
+
homeDir: options.homeDir,
|
|
92
|
+
});
|
|
93
|
+
const suffix = `_${sessionId}.jsonl`;
|
|
94
|
+
const files = await walkJsonlFiles(sessionsDir);
|
|
95
|
+
return files.find((file) => file.endsWith(suffix)) ?? null;
|
|
96
|
+
}
|
|
97
|
+
export class PiSubagentSessionTailers {
|
|
98
|
+
constructor(options) {
|
|
99
|
+
this.entries = new Map();
|
|
100
|
+
this.timer = null;
|
|
101
|
+
this.queue = Promise.resolve();
|
|
102
|
+
this.options = options;
|
|
103
|
+
}
|
|
104
|
+
start() {
|
|
105
|
+
if (this.timer)
|
|
106
|
+
return;
|
|
107
|
+
this.timer = setInterval(() => {
|
|
108
|
+
void this.tick();
|
|
109
|
+
}, DEFAULT_POLL_MS);
|
|
110
|
+
this.timer.unref?.();
|
|
111
|
+
}
|
|
112
|
+
stop() {
|
|
113
|
+
if (this.timer) {
|
|
114
|
+
clearInterval(this.timer);
|
|
115
|
+
this.timer = null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
update(agentId, snapshot) {
|
|
119
|
+
const subagentId = snapshot.subagentId;
|
|
120
|
+
const key = `${agentId}\u0000${subagentId}`;
|
|
121
|
+
let entry = this.entries.get(key);
|
|
122
|
+
if (!entry) {
|
|
123
|
+
entry = {
|
|
124
|
+
agentId,
|
|
125
|
+
subagentId,
|
|
126
|
+
sessionId: null,
|
|
127
|
+
sessionFile: null,
|
|
128
|
+
cwd: null,
|
|
129
|
+
tailer: null,
|
|
130
|
+
lastLocateAttempt: 0,
|
|
131
|
+
terminalAt: null,
|
|
132
|
+
};
|
|
133
|
+
this.entries.set(key, entry);
|
|
134
|
+
this.start();
|
|
135
|
+
}
|
|
136
|
+
if (snapshot.sessionId)
|
|
137
|
+
entry.sessionId = snapshot.sessionId;
|
|
138
|
+
if (snapshot.sessionFile)
|
|
139
|
+
entry.sessionFile = snapshot.sessionFile;
|
|
140
|
+
if (snapshot.cwd)
|
|
141
|
+
entry.cwd = snapshot.cwd;
|
|
142
|
+
const status = mapPiSubagentStatus(snapshot.status ?? "");
|
|
143
|
+
if (status &&
|
|
144
|
+
PI_SUBAGENT_TERMINAL_STATUSES.includes(status) &&
|
|
145
|
+
entry.terminalAt === null) {
|
|
146
|
+
entry.terminalAt = Date.now();
|
|
147
|
+
}
|
|
148
|
+
// No reopen-on-running: reports have no ordering guarantee, so a stale running
|
|
149
|
+
// snapshot must not resurrect a finished subagent's tail. New launches are new ids.
|
|
150
|
+
}
|
|
151
|
+
removeAgent(agentId) {
|
|
152
|
+
for (const [key, entry] of this.entries) {
|
|
153
|
+
if (entry.agentId === agentId)
|
|
154
|
+
this.entries.delete(key);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
dispose() {
|
|
158
|
+
this.stop();
|
|
159
|
+
this.entries.clear();
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Drain every entry once. Timer and manual (test) ticks serialize through a promise
|
|
163
|
+
* chain instead of skipping, so an awaited tick never no-ops behind an in-flight one.
|
|
164
|
+
*/
|
|
165
|
+
tick() {
|
|
166
|
+
const run = this.queue.then(() => this.drain());
|
|
167
|
+
this.queue = run.catch(() => { });
|
|
168
|
+
return run;
|
|
169
|
+
}
|
|
170
|
+
async drain() {
|
|
171
|
+
const now = Date.now();
|
|
172
|
+
for (const [key, entry] of this.entries) {
|
|
173
|
+
if (!entry.tailer && now - entry.lastLocateAttempt >= LOCATE_RETRY_MS) {
|
|
174
|
+
entry.lastLocateAttempt = now;
|
|
175
|
+
entry.tailer = await this.locate(entry);
|
|
176
|
+
}
|
|
177
|
+
if (entry.tailer) {
|
|
178
|
+
try {
|
|
179
|
+
await drainPiSessionTailer(entry.tailer, (item, timestamp) => {
|
|
180
|
+
this.options.emit(entry.agentId, {
|
|
181
|
+
kind: "timeline",
|
|
182
|
+
id: entry.subagentId,
|
|
183
|
+
item,
|
|
184
|
+
...(timestamp ? { timestamp } : {}),
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// Transient read failures (rotation, permissions): retry next tick.
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (entry.terminalAt !== null &&
|
|
193
|
+
now >= entry.terminalAt + (this.options.terminalGraceMs ?? TERMINAL_DRAIN_GRACE_MS)) {
|
|
194
|
+
this.entries.delete(key);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async locate(entry) {
|
|
199
|
+
const file = entry.sessionFile ??
|
|
200
|
+
(entry.sessionId
|
|
201
|
+
? await locatePiSubagentSessionFile(entry.sessionId, {
|
|
202
|
+
cwd: entry.cwd,
|
|
203
|
+
env: this.options.env,
|
|
204
|
+
homeDir: this.options.homeDir,
|
|
205
|
+
})
|
|
206
|
+
: null);
|
|
207
|
+
if (!file)
|
|
208
|
+
return null;
|
|
209
|
+
return { file, offset: 0, mapper: new PiHistoryMapper("pi") };
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=subagent-session-tailer.js.map
|
|
@@ -34,6 +34,12 @@ import { WorkspaceScriptRuntimeStore } from "./workspace-script-runtime-store.js
|
|
|
34
34
|
import { type ManagedProcessRegistry } from "./managed-processes/managed-processes.js";
|
|
35
35
|
import { type HostnamesConfig } from "./hostnames.js";
|
|
36
36
|
import { type DaemonAuthConfig } from "./auth.js";
|
|
37
|
+
/**
|
|
38
|
+
* Local, token-gated snapshots reported by the BySpace-installed subagent extension;
|
|
39
|
+
* deliberately skips daemon auth. The manager is created after route mounting, so it resolves
|
|
40
|
+
* through a getter filled in once construction finishes (503 until then).
|
|
41
|
+
*/
|
|
42
|
+
export declare function createPiSubagentReportRouteHandler(getAgentManager: () => AgentManager | null): express.RequestHandler;
|
|
37
43
|
export declare function createTerminalActivityRouteHandler(terminalManager: TerminalManager): express.RequestHandler;
|
|
38
44
|
export type DaemonLifecycleIntent = {
|
|
39
45
|
type: "shutdown";
|
|
@@ -175,6 +175,13 @@ function resolveAgentMcpClientHost(host) {
|
|
|
175
175
|
}
|
|
176
176
|
return host;
|
|
177
177
|
}
|
|
178
|
+
function createLocalApiBaseUrl(listenTarget) {
|
|
179
|
+
if (!listenTarget || listenTarget.type !== "tcp") {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
const host = resolveAgentMcpClientHost(listenTarget.host);
|
|
183
|
+
return `http://${formatHostForHttpUrl(host)}:${listenTarget.port}`;
|
|
184
|
+
}
|
|
178
185
|
function createAgentMcpBaseUrl(listenTarget) {
|
|
179
186
|
if (!listenTarget || listenTarget.type !== "tcp") {
|
|
180
187
|
return null;
|
|
@@ -203,6 +210,40 @@ const LOOPBACK_REMOTE_ADDRESSES = new Set(["127.0.0.1", "::1", "::ffff:127.0.0.1
|
|
|
203
210
|
function isLoopbackRemoteAddress(remoteAddress) {
|
|
204
211
|
return remoteAddress !== undefined && LOOPBACK_REMOTE_ADDRESSES.has(remoteAddress);
|
|
205
212
|
}
|
|
213
|
+
const PiSubagentReportSchema = z.object({
|
|
214
|
+
token: z.string().min(1),
|
|
215
|
+
observations: z.array(z.record(z.string(), z.unknown())).min(1),
|
|
216
|
+
});
|
|
217
|
+
/**
|
|
218
|
+
* Local, token-gated snapshots reported by the BySpace-installed subagent extension;
|
|
219
|
+
* deliberately skips daemon auth. The manager is created after route mounting, so it resolves
|
|
220
|
+
* through a getter filled in once construction finishes (503 until then).
|
|
221
|
+
*/
|
|
222
|
+
export function createPiSubagentReportRouteHandler(getAgentManager) {
|
|
223
|
+
return async (req, res) => {
|
|
224
|
+
const agentManager = getAgentManager();
|
|
225
|
+
if (!agentManager) {
|
|
226
|
+
res.status(503).json({ error: "Daemon is still starting" });
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (!isLoopbackRemoteAddress(req.socket.remoteAddress)) {
|
|
230
|
+
res.status(403).json({ error: "Forbidden" });
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const parsed = PiSubagentReportSchema.safeParse(req.body);
|
|
234
|
+
if (!parsed.success) {
|
|
235
|
+
res.status(400).json({ error: "Invalid subagent report" });
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const { token, observations } = parsed.data;
|
|
239
|
+
const outcome = agentManager.applyPiSubagentReport(token, observations);
|
|
240
|
+
if (outcome === "unauthorized") {
|
|
241
|
+
res.status(403).json({ error: "Forbidden" });
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
res.status(204).end();
|
|
245
|
+
};
|
|
246
|
+
}
|
|
206
247
|
export function createTerminalActivityRouteHandler(terminalManager) {
|
|
207
248
|
return async (req, res) => {
|
|
208
249
|
if (!isLoopbackRemoteAddress(req.socket.remoteAddress)) {
|
|
@@ -520,6 +561,12 @@ export async function createBySpaceDaemon(config, rootLogger, dependencies = {})
|
|
|
520
561
|
});
|
|
521
562
|
// Local, harmless, and token-gated; deliberately skips daemon auth.
|
|
522
563
|
app.post("/api/terminal-activity", express.json(), createTerminalActivityRouteHandler(terminalManager));
|
|
564
|
+
// Subagent progress snapshots reported by the BySpace-installed subagent extension. Local,
|
|
565
|
+
// token-gated per agent launch; deliberately skips daemon auth. The route must mount before
|
|
566
|
+
// the bearer middleware below, but the manager is created later in this function, so it
|
|
567
|
+
// resolves through a holder filled in right after construction.
|
|
568
|
+
let piSubagentReportAgentManager = null;
|
|
569
|
+
app.post("/api/subagent-report", express.json(), createPiSubagentReportRouteHandler(() => piSubagentReportAgentManager));
|
|
523
570
|
// Serve the bundled browser web UI when enabled. Mounted after service-proxy
|
|
524
571
|
// classification and host/CORS handling, but before daemon bearer auth, so
|
|
525
572
|
// static app files load without the daemon password while API/WebSocket calls
|
|
@@ -667,6 +714,7 @@ export async function createBySpaceDaemon(config, rootLogger, dependencies = {})
|
|
|
667
714
|
resolveBySpaceToolPolicy: (provider) => resolveBySpaceToolPolicy(provider, daemonConfigStore.get().providers),
|
|
668
715
|
logger,
|
|
669
716
|
});
|
|
717
|
+
piSubagentReportAgentManager = agentManager;
|
|
670
718
|
const detachAgentStoragePersistence = attachAgentStoragePersistence(logger, agentManager, agentStorage);
|
|
671
719
|
await agentStorage.initialize();
|
|
672
720
|
logger.info({ elapsed: elapsed() }, "Agent storage initialized");
|
|
@@ -1155,6 +1203,7 @@ export async function createBySpaceDaemon(config, rootLogger, dependencies = {})
|
|
|
1155
1203
|
agentMcpBaseUrl =
|
|
1156
1204
|
!mcpEnabled || config.mcpInjectIntoAgents === false ? null : mcpBaseUrl;
|
|
1157
1205
|
agentManager.setMcpBaseUrl(agentMcpBaseUrl);
|
|
1206
|
+
agentManager.setPiSubagentReportBaseUrl(createLocalApiBaseUrl(boundListenTarget));
|
|
1158
1207
|
agentManager.setBySpaceToolsEnabled(mcpEnabled && config.mcpInjectIntoAgents !== false);
|
|
1159
1208
|
daemonConfigStore.onFieldChange("mcp.enabled", (value) => {
|
|
1160
1209
|
mcpEnabled = value !== false;
|