@junctionpanel/server 0.1.35 → 0.1.36
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/server/client/daemon-client.d.ts +9 -6
- package/dist/server/client/daemon-client.d.ts.map +1 -1
- package/dist/server/client/daemon-client.js +15 -1
- package/dist/server/client/daemon-client.js.map +1 -1
- package/dist/server/server/agent/agent-manager.d.ts +24 -1
- package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
- package/dist/server/server/agent/agent-manager.js +23 -0
- package/dist/server/server/agent/agent-manager.js.map +1 -1
- package/dist/server/server/agent/agent-projections.d.ts.map +1 -1
- package/dist/server/server/agent/agent-projections.js +11 -0
- package/dist/server/server/agent/agent-projections.js.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.d.ts +20 -0
- package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.js.map +1 -1
- package/dist/server/server/agent/agent-storage.d.ts +4 -4
- package/dist/server/server/agent/pending-plan-review.d.ts +12 -0
- package/dist/server/server/agent/pending-plan-review.d.ts.map +1 -0
- package/dist/server/server/agent/pending-plan-review.js +85 -0
- package/dist/server/server/agent/pending-plan-review.js.map +1 -0
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -1
- package/dist/server/server/agent-attention-policy.d.ts +2 -3
- package/dist/server/server/agent-attention-policy.d.ts.map +1 -1
- package/dist/server/server/agent-attention-policy.js +2 -2
- package/dist/server/server/agent-attention-policy.js.map +1 -1
- package/dist/server/server/notifications/relay-client.d.ts +9 -0
- package/dist/server/server/notifications/relay-client.d.ts.map +1 -0
- package/dist/server/server/notifications/relay-client.js +55 -0
- package/dist/server/server/notifications/relay-client.js.map +1 -0
- package/dist/server/server/notifications/relay-ownership.d.ts +5 -0
- package/dist/server/server/notifications/relay-ownership.d.ts.map +1 -0
- package/dist/server/server/notifications/relay-ownership.js +25 -0
- package/dist/server/server/notifications/relay-ownership.js.map +1 -0
- package/dist/server/server/notifications/relay-store.d.ts +22 -0
- package/dist/server/server/notifications/relay-store.d.ts.map +1 -0
- package/dist/server/server/notifications/relay-store.js +72 -0
- package/dist/server/server/notifications/relay-store.js.map +1 -0
- package/dist/server/server/session.d.ts +3 -0
- package/dist/server/server/session.d.ts.map +1 -1
- package/dist/server/server/session.js +125 -74
- package/dist/server/server/session.js.map +1 -1
- package/dist/server/server/websocket-server.d.ts +1 -0
- package/dist/server/server/websocket-server.d.ts.map +1 -1
- package/dist/server/server/websocket-server.js +31 -5
- package/dist/server/server/websocket-server.js.map +1 -1
- package/dist/server/shared/agent-attention-notification.d.ts +2 -0
- package/dist/server/shared/agent-attention-notification.d.ts.map +1 -1
- package/dist/server/shared/agent-attention-notification.js +23 -5
- package/dist/server/shared/agent-attention-notification.js.map +1 -1
- package/dist/server/shared/messages.d.ts +1488 -1148
- package/dist/server/shared/messages.d.ts.map +1 -1
- package/dist/server/shared/messages.js +47 -12
- package/dist/server/shared/messages.js.map +1 -1
- package/package.json +2 -2
|
@@ -33,6 +33,8 @@ import { deriveProjectGroupingKey, deriveProjectGroupingName } from '../shared/p
|
|
|
33
33
|
import { DEFAULT_DAEMON_PACKAGE_NAME, resolveDaemonPackageVersion, } from './daemon-package-context.js';
|
|
34
34
|
import { runDaemonDoctor } from './daemon-doctor.js';
|
|
35
35
|
import { MANAGED_DAEMON_PROVIDERS, autoRouteProviderExecutable, loadDaemonProviderSettings, saveDaemonProviderExecutablePath, } from './daemon-provider-settings.js';
|
|
36
|
+
import { applyNotificationRelayOwnerLabel, preserveNotificationRelayOwnerLabel, } from './notifications/relay-ownership.js';
|
|
37
|
+
import { saveNotificationRelayConfig } from './notifications/relay-store.js';
|
|
36
38
|
import { resolvePackageUpdateInfo } from './package-update.js';
|
|
37
39
|
import { loadPersistedConfig } from './persisted-config.js';
|
|
38
40
|
const execAsync = promisify(exec);
|
|
@@ -42,6 +44,7 @@ const READ_ONLY_GIT_ENV = {
|
|
|
42
44
|
};
|
|
43
45
|
const DEFAULT_STORED_TIMELINE_FETCH_LIMIT = 200;
|
|
44
46
|
const pendingAgentInitializations = new Map();
|
|
47
|
+
const pendingAgentMessageExecutions = new Map();
|
|
45
48
|
const DEFAULT_AGENT_PROVIDER = AGENT_PROVIDER_IDS[0];
|
|
46
49
|
const CHECKOUT_DIFF_WATCH_DEBOUNCE_MS = 150;
|
|
47
50
|
const CHECKOUT_DIFF_FALLBACK_REFRESH_MS = 5000;
|
|
@@ -247,6 +250,61 @@ export class Session {
|
|
|
247
250
|
},
|
|
248
251
|
});
|
|
249
252
|
}
|
|
253
|
+
enqueueAcceptedAgentMessageExecution(input) {
|
|
254
|
+
const previous = pendingAgentMessageExecutions.get(input.agentId) ?? Promise.resolve();
|
|
255
|
+
const execution = previous
|
|
256
|
+
.catch(() => undefined)
|
|
257
|
+
.then(async () => {
|
|
258
|
+
const startedAt = Date.now();
|
|
259
|
+
const phaseTimings = {
|
|
260
|
+
performSendMs: 0,
|
|
261
|
+
waitForRunStartMs: 0,
|
|
262
|
+
};
|
|
263
|
+
const performSendStartedAt = Date.now();
|
|
264
|
+
await this.performAgentMessageSend(input);
|
|
265
|
+
phaseTimings.performSendMs = Date.now() - performSendStartedAt;
|
|
266
|
+
const waitForRunStartStartedAt = Date.now();
|
|
267
|
+
await this.agentManager.waitForAgentRunStart(input.agentId);
|
|
268
|
+
phaseTimings.waitForRunStartMs = Date.now() - waitForRunStartStartedAt;
|
|
269
|
+
this.sessionLogger.debug({
|
|
270
|
+
agentId: input.agentId,
|
|
271
|
+
durationMs: Date.now() - startedAt,
|
|
272
|
+
...phaseTimings,
|
|
273
|
+
}, 'Accepted send_agent_message_request execution started');
|
|
274
|
+
});
|
|
275
|
+
const trackedExecution = execution.finally(() => {
|
|
276
|
+
if (pendingAgentMessageExecutions.get(input.agentId) === trackedExecution) {
|
|
277
|
+
pendingAgentMessageExecutions.delete(input.agentId);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
pendingAgentMessageExecutions.set(input.agentId, trackedExecution);
|
|
281
|
+
return trackedExecution;
|
|
282
|
+
}
|
|
283
|
+
async performAgentMessageSend(input) {
|
|
284
|
+
await this.ensureAgentLoaded(input.agentId);
|
|
285
|
+
await this.interruptAgentIfRunning(input.agentId);
|
|
286
|
+
try {
|
|
287
|
+
this.agentManager.recordUserMessage(input.agentId, input.text, {
|
|
288
|
+
messageId: input.messageId,
|
|
289
|
+
emitState: false,
|
|
290
|
+
images: input.images?.map((image) => ({
|
|
291
|
+
data: image.preview?.data ?? image.data,
|
|
292
|
+
mimeType: image.preview?.mimeType ?? image.mimeType,
|
|
293
|
+
...(image.label ? { label: image.label } : {}),
|
|
294
|
+
...(image.preview?.width != null ? { width: image.preview.width } : {}),
|
|
295
|
+
...(image.preview?.height != null ? { height: image.preview.height } : {}),
|
|
296
|
+
})),
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
this.sessionLogger.error({ err: error, agentId: input.agentId }, `Failed to record user message for agent ${input.agentId}`);
|
|
301
|
+
}
|
|
302
|
+
const prompt = this.buildAgentPrompt(input.text, input.images);
|
|
303
|
+
const started = this.startAgentStream(input.agentId, prompt, input.runOptions);
|
|
304
|
+
if (!started.ok) {
|
|
305
|
+
throw new Error(started.error);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
250
308
|
/**
|
|
251
309
|
* Initialize Agent MCP client for this session using in-memory transport
|
|
252
310
|
*/
|
|
@@ -889,6 +947,9 @@ export class Session {
|
|
|
889
947
|
case 'auto_route_provider_request':
|
|
890
948
|
await this.handleAutoRouteProviderRequest(msg);
|
|
891
949
|
break;
|
|
950
|
+
case 'update_notification_relay_config_request':
|
|
951
|
+
await this.handleUpdateNotificationRelayConfigRequest(msg);
|
|
952
|
+
break;
|
|
892
953
|
case 'clear_agent_attention':
|
|
893
954
|
await this.handleClearAgentAttention(msg.agentId);
|
|
894
955
|
break;
|
|
@@ -1357,7 +1418,7 @@ export class Session {
|
|
|
1357
1418
|
await this.agentManager.setTitle(agentId, normalizedName);
|
|
1358
1419
|
}
|
|
1359
1420
|
if (normalizedLabels) {
|
|
1360
|
-
await this.agentManager.setLabels(agentId, normalizedLabels);
|
|
1421
|
+
await this.agentManager.setLabels(agentId, preserveNotificationRelayOwnerLabel(liveAgent.labels, normalizedLabels));
|
|
1361
1422
|
}
|
|
1362
1423
|
}
|
|
1363
1424
|
else {
|
|
@@ -1368,7 +1429,11 @@ export class Session {
|
|
|
1368
1429
|
await this.agentStorage.upsert({
|
|
1369
1430
|
...existing,
|
|
1370
1431
|
...(normalizedName ? { title: normalizedName } : {}),
|
|
1371
|
-
...(normalizedLabels
|
|
1432
|
+
...(normalizedLabels
|
|
1433
|
+
? {
|
|
1434
|
+
labels: preserveNotificationRelayOwnerLabel(existing.labels, normalizedLabels),
|
|
1435
|
+
}
|
|
1436
|
+
: {}),
|
|
1372
1437
|
});
|
|
1373
1438
|
}
|
|
1374
1439
|
this.emit({
|
|
@@ -1409,30 +1474,17 @@ export class Session {
|
|
|
1409
1474
|
return;
|
|
1410
1475
|
}
|
|
1411
1476
|
try {
|
|
1412
|
-
await this.
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
this.handleAgentRunError(agentId, error, 'Failed to initialize agent before sending prompt');
|
|
1416
|
-
return;
|
|
1417
|
-
}
|
|
1418
|
-
try {
|
|
1419
|
-
await this.interruptAgentIfRunning(agentId);
|
|
1420
|
-
}
|
|
1421
|
-
catch (error) {
|
|
1422
|
-
this.handleAgentRunError(agentId, error, 'Failed to interrupt running agent before sending prompt');
|
|
1423
|
-
return;
|
|
1424
|
-
}
|
|
1425
|
-
const prompt = this.buildAgentPrompt(text, images);
|
|
1426
|
-
try {
|
|
1427
|
-
this.agentManager.recordUserMessage(agentId, text, {
|
|
1477
|
+
await this.performAgentMessageSend({
|
|
1478
|
+
agentId,
|
|
1479
|
+
text,
|
|
1428
1480
|
messageId,
|
|
1429
|
-
|
|
1481
|
+
images,
|
|
1482
|
+
runOptions,
|
|
1430
1483
|
});
|
|
1431
1484
|
}
|
|
1432
1485
|
catch (error) {
|
|
1433
|
-
this.
|
|
1486
|
+
this.handleAgentRunError(agentId, error, 'Failed to send prompt to agent');
|
|
1434
1487
|
}
|
|
1435
|
-
this.startAgentStream(agentId, prompt, runOptions);
|
|
1436
1488
|
}
|
|
1437
1489
|
/**
|
|
1438
1490
|
* Handle create agent request
|
|
@@ -1445,7 +1497,9 @@ export class Session {
|
|
|
1445
1497
|
const mergedLabels = autoWorkspaceName
|
|
1446
1498
|
? { ...labels, 'junction:workspace': autoWorkspaceName }
|
|
1447
1499
|
: labels;
|
|
1448
|
-
const snapshot = await this.agentManager.createAgent(sessionConfig, undefined, {
|
|
1500
|
+
const snapshot = await this.agentManager.createAgent(sessionConfig, undefined, {
|
|
1501
|
+
labels: applyNotificationRelayOwnerLabel(mergedLabels, this.userId),
|
|
1502
|
+
});
|
|
1449
1503
|
await this.forwardAgentUpdate(snapshot);
|
|
1450
1504
|
if (requestId) {
|
|
1451
1505
|
const agentPayload = await this.getAgentPayloadById(snapshot.id);
|
|
@@ -1941,6 +1995,46 @@ export class Session {
|
|
|
1941
1995
|
});
|
|
1942
1996
|
}
|
|
1943
1997
|
}
|
|
1998
|
+
async handleUpdateNotificationRelayConfigRequest(msg) {
|
|
1999
|
+
try {
|
|
2000
|
+
const relayUrl = msg.relayUrl?.trim();
|
|
2001
|
+
const token = msg.token?.trim();
|
|
2002
|
+
const expiresAt = msg.expiresAt?.trim();
|
|
2003
|
+
const providedCount = [msg.relayUrl, msg.token, msg.expiresAt].filter((value) => value !== undefined).length;
|
|
2004
|
+
if (providedCount === 0) {
|
|
2005
|
+
saveNotificationRelayConfig(this.junctionHome, this.userId, null);
|
|
2006
|
+
}
|
|
2007
|
+
else if (providedCount !== 3 || !relayUrl || !token || !expiresAt) {
|
|
2008
|
+
throw new SessionRequestError('invalid_notification_relay_config', 'relayUrl, token, and expiresAt must be provided together');
|
|
2009
|
+
}
|
|
2010
|
+
else {
|
|
2011
|
+
saveNotificationRelayConfig(this.junctionHome, this.userId, {
|
|
2012
|
+
relayUrl,
|
|
2013
|
+
token,
|
|
2014
|
+
expiresAt,
|
|
2015
|
+
});
|
|
2016
|
+
}
|
|
2017
|
+
this.emit({
|
|
2018
|
+
type: 'update_notification_relay_config_response',
|
|
2019
|
+
payload: {
|
|
2020
|
+
success: true,
|
|
2021
|
+
error: null,
|
|
2022
|
+
requestId: msg.requestId,
|
|
2023
|
+
},
|
|
2024
|
+
});
|
|
2025
|
+
}
|
|
2026
|
+
catch (error) {
|
|
2027
|
+
this.sessionLogger.error({ err: error }, 'Failed to update notification relay config');
|
|
2028
|
+
this.emit({
|
|
2029
|
+
type: 'update_notification_relay_config_response',
|
|
2030
|
+
payload: {
|
|
2031
|
+
success: false,
|
|
2032
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2033
|
+
requestId: msg.requestId,
|
|
2034
|
+
},
|
|
2035
|
+
});
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
1944
2038
|
normalizeGitOptions(gitOptions, legacyWorktreeName) {
|
|
1945
2039
|
const fallbackOptions = legacyWorktreeName
|
|
1946
2040
|
? {
|
|
@@ -4423,7 +4517,8 @@ export class Session {
|
|
|
4423
4517
|
}
|
|
4424
4518
|
try {
|
|
4425
4519
|
const agentId = resolved.agentId;
|
|
4426
|
-
const
|
|
4520
|
+
const storedRecord = await this.agentStorage.get(agentId);
|
|
4521
|
+
const archivedAt = storedRecord?.archivedAt ?? null;
|
|
4427
4522
|
if (archivedAt) {
|
|
4428
4523
|
this.emit({
|
|
4429
4524
|
type: 'send_agent_message_response',
|
|
@@ -4436,57 +4531,13 @@ export class Session {
|
|
|
4436
4531
|
});
|
|
4437
4532
|
return;
|
|
4438
4533
|
}
|
|
4439
|
-
await this.
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
}
|
|
4447
|
-
catch (error) {
|
|
4448
|
-
this.sessionLogger.error({ err: error, agentId }, 'Failed to record user message for send_agent_message_request');
|
|
4449
|
-
}
|
|
4450
|
-
const prompt = this.buildAgentPrompt(msg.text, msg.images);
|
|
4451
|
-
const started = this.startAgentStream(agentId, prompt, normalizeAgentRunOptions(msg.runOptions));
|
|
4452
|
-
if (!started.ok) {
|
|
4453
|
-
this.emit({
|
|
4454
|
-
type: 'send_agent_message_response',
|
|
4455
|
-
payload: {
|
|
4456
|
-
requestId: msg.requestId,
|
|
4457
|
-
agentId,
|
|
4458
|
-
accepted: false,
|
|
4459
|
-
error: started.error,
|
|
4460
|
-
},
|
|
4461
|
-
});
|
|
4462
|
-
return;
|
|
4463
|
-
}
|
|
4464
|
-
const startAbort = new AbortController();
|
|
4465
|
-
const startTimeoutMs = 15000;
|
|
4466
|
-
const startTimeout = setTimeout(() => startAbort.abort('timeout'), startTimeoutMs);
|
|
4467
|
-
try {
|
|
4468
|
-
await this.agentManager.waitForAgentRunStart(agentId, { signal: startAbort.signal });
|
|
4469
|
-
}
|
|
4470
|
-
catch (error) {
|
|
4471
|
-
const message = error instanceof Error
|
|
4472
|
-
? error.message
|
|
4473
|
-
: typeof error === 'string'
|
|
4474
|
-
? error
|
|
4475
|
-
: 'Unknown error';
|
|
4476
|
-
this.emit({
|
|
4477
|
-
type: 'send_agent_message_response',
|
|
4478
|
-
payload: {
|
|
4479
|
-
requestId: msg.requestId,
|
|
4480
|
-
agentId,
|
|
4481
|
-
accepted: false,
|
|
4482
|
-
error: message,
|
|
4483
|
-
},
|
|
4484
|
-
});
|
|
4485
|
-
return;
|
|
4486
|
-
}
|
|
4487
|
-
finally {
|
|
4488
|
-
clearTimeout(startTimeout);
|
|
4489
|
-
}
|
|
4534
|
+
await this.enqueueAcceptedAgentMessageExecution({
|
|
4535
|
+
agentId,
|
|
4536
|
+
text: msg.text,
|
|
4537
|
+
...(msg.messageId ? { messageId: msg.messageId } : {}),
|
|
4538
|
+
...(msg.images ? { images: msg.images } : {}),
|
|
4539
|
+
runOptions: normalizeAgentRunOptions(msg.runOptions),
|
|
4540
|
+
});
|
|
4490
4541
|
this.emit({
|
|
4491
4542
|
type: 'send_agent_message_response',
|
|
4492
4543
|
payload: {
|