agent-relay-server 0.4.34 → 0.4.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/package.json +1 -1
- package/public/dashboard.js +41 -20
- package/public/index.html +40 -24
- package/src/config.ts +0 -3
- package/src/daemon.ts +6 -6
- package/src/setup.ts +4 -4
- package/src/upgrade.ts +5 -5
package/package.json
CHANGED
package/public/dashboard.js
CHANGED
|
@@ -12,12 +12,16 @@
|
|
|
12
12
|
const LIVE_REFRESH_MS = 5_000;
|
|
13
13
|
const AGENT_TYPE_ICONS = {
|
|
14
14
|
codex: "ti-terminal-2",
|
|
15
|
-
claude: "
|
|
15
|
+
claude: "claude-sol",
|
|
16
|
+
user: "ti-user",
|
|
17
|
+
system: "ti-server",
|
|
16
18
|
agent: "ti-robot",
|
|
17
19
|
};
|
|
18
20
|
const AGENT_TYPE_TITLES = {
|
|
19
21
|
codex: "Codex agent",
|
|
20
22
|
claude: "Claude agent",
|
|
23
|
+
user: "Human operator",
|
|
24
|
+
system: "System",
|
|
21
25
|
agent: "Agent",
|
|
22
26
|
};
|
|
23
27
|
|
|
@@ -62,6 +66,8 @@
|
|
|
62
66
|
inboxArchivedThreads: loadPref("inboxArchivedThreads", {}),
|
|
63
67
|
inboxDrafts: loadPref("inboxDrafts", {}),
|
|
64
68
|
inboxSearch: "",
|
|
69
|
+
inboxSort: loadPref("inboxSort", "attention"),
|
|
70
|
+
inboxSortDir: loadPref("inboxSortDir", "desc"),
|
|
65
71
|
inboxShowArchived: loadPref("inboxShowArchived", false),
|
|
66
72
|
operatorActivity: loadPref("operatorActivity", []),
|
|
67
73
|
activityEvents: [],
|
|
@@ -121,6 +127,8 @@
|
|
|
121
127
|
vm.$watch("agentStatusFilter", (value) => vm.save("agentStatusFilter", value));
|
|
122
128
|
vm.$watch("agentTagFilter", (value) => vm.save("agentTagFilter", value));
|
|
123
129
|
vm.$watch("pairStatusFilter", (value) => vm.save("pairStatusFilter", value));
|
|
130
|
+
vm.$watch("inboxSort", (value) => vm.save("inboxSort", value));
|
|
131
|
+
vm.$watch("inboxSortDir", (value) => vm.save("inboxSortDir", value));
|
|
124
132
|
vm.$watch("inboxShowArchived", (value) => vm.save("inboxShowArchived", value));
|
|
125
133
|
vm.$watch("activityFilter", (value) => vm.save("activityFilter", value));
|
|
126
134
|
vm.$watch("view", (value, oldValue) => {
|
|
@@ -580,11 +588,32 @@
|
|
|
580
588
|
|
|
581
589
|
function getInboxThreads() {
|
|
582
590
|
const search = this.inboxSearch.trim().toLowerCase();
|
|
583
|
-
|
|
591
|
+
const filtered = this.allInboxThreads.filter((thread) => {
|
|
584
592
|
if (!this.inboxShowArchived && thread.archived) return false;
|
|
585
593
|
if (search && !threadMatchesSearch(this, thread, search)) return false;
|
|
586
594
|
return true;
|
|
587
595
|
});
|
|
596
|
+
return sortInboxThreads(filtered, this.inboxSort, this.inboxSortDir);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
function sortInboxThreads(threads, sort, dir) {
|
|
600
|
+
const mul = dir === "asc" ? 1 : -1;
|
|
601
|
+
return [...threads].sort((a, b) => {
|
|
602
|
+
switch (sort) {
|
|
603
|
+
case "updated":
|
|
604
|
+
return mul * ((b.lastMessage?.id || 0) - (a.lastMessage?.id || 0));
|
|
605
|
+
case "created": {
|
|
606
|
+
const aFirst = a.messages[0]?.id || 0;
|
|
607
|
+
const bFirst = b.messages[0]?.id || 0;
|
|
608
|
+
return mul * (bFirst - aFirst);
|
|
609
|
+
}
|
|
610
|
+
case "name":
|
|
611
|
+
return mul * String(a.peer).localeCompare(String(b.peer));
|
|
612
|
+
case "attention":
|
|
613
|
+
default:
|
|
614
|
+
return compareInboxThreads(a, b) * mul;
|
|
615
|
+
}
|
|
616
|
+
});
|
|
588
617
|
}
|
|
589
618
|
|
|
590
619
|
function buildInboxThreads(vm) {
|
|
@@ -647,16 +676,15 @@
|
|
|
647
676
|
const pendingPairInvites = this.pairs.filter((pair) => pair.status === "pending").length;
|
|
648
677
|
const claimableTasks = countClaimableWaiting(this);
|
|
649
678
|
const unreadInbox = threads.reduce((sum, thread) => sum + (thread.attention?.unread || 0), 0);
|
|
650
|
-
const needsHumanResponse = threads.filter((thread) => thread.attention?.needsHumanResponse).length;
|
|
651
679
|
const agentQuestions = threads.filter((thread) => thread.attention?.agentQuestion).length;
|
|
652
680
|
|
|
653
681
|
return {
|
|
654
682
|
unreadInbox,
|
|
655
|
-
needsHumanResponse,
|
|
683
|
+
needsHumanResponse: 0,
|
|
656
684
|
agentQuestions,
|
|
657
685
|
pendingPairInvites,
|
|
658
686
|
claimableTasks,
|
|
659
|
-
total: unreadInbox +
|
|
687
|
+
total: unreadInbox + agentQuestions + pendingPairInvites + claimableTasks,
|
|
660
688
|
};
|
|
661
689
|
}
|
|
662
690
|
|
|
@@ -910,18 +938,16 @@
|
|
|
910
938
|
|
|
911
939
|
function getThreadAttention(vm, thread) {
|
|
912
940
|
const lastHumanReplyId = maxMessageId(thread.messages, (msg) => msg.from === HUMAN_AGENT_ID);
|
|
913
|
-
const lastInboundId = maxMessageId(thread.messages, isHumanInboundMessage);
|
|
914
941
|
const unread = thread.messages.filter((msg) => isUnreadHumanMessage(vm, thread.peer, msg)).length;
|
|
915
|
-
const needsHumanResponse = lastInboundId > lastHumanReplyId;
|
|
916
942
|
const agentQuestion = thread.messages.some((msg) =>
|
|
917
943
|
isHumanInboundMessage(msg) && msg.id > lastHumanReplyId && messageLooksLikeQuestion(msg)
|
|
918
944
|
);
|
|
919
945
|
|
|
920
946
|
return {
|
|
921
947
|
unread,
|
|
922
|
-
needsHumanResponse,
|
|
948
|
+
needsHumanResponse: false,
|
|
923
949
|
agentQuestion,
|
|
924
|
-
score: unread * 10 + (
|
|
950
|
+
score: unread * 10 + (agentQuestion ? 3 : 0),
|
|
925
951
|
};
|
|
926
952
|
}
|
|
927
953
|
|
|
@@ -1219,6 +1245,7 @@
|
|
|
1219
1245
|
agentStatusClass,
|
|
1220
1246
|
severityClass,
|
|
1221
1247
|
agentStatusTitle,
|
|
1248
|
+
isBuiltInAgent,
|
|
1222
1249
|
agentChannels,
|
|
1223
1250
|
channelPresence,
|
|
1224
1251
|
integrationPresence,
|
|
@@ -1301,18 +1328,16 @@
|
|
|
1301
1328
|
const claimableTasks = countAgentClaimableWaiting(this, agent);
|
|
1302
1329
|
const attention = {
|
|
1303
1330
|
unread: thread?.attention?.unread || 0,
|
|
1304
|
-
needsHumanResponse:
|
|
1331
|
+
needsHumanResponse: false,
|
|
1305
1332
|
agentQuestion: Boolean(thread?.attention?.agentQuestion),
|
|
1306
1333
|
pendingPairInvite,
|
|
1307
1334
|
claimableTasks,
|
|
1308
1335
|
};
|
|
1309
1336
|
attention.total = attention.unread +
|
|
1310
|
-
(attention.needsHumanResponse ? 1 : 0) +
|
|
1311
1337
|
(attention.agentQuestion ? 1 : 0) +
|
|
1312
1338
|
(attention.pendingPairInvite ? 1 : 0) +
|
|
1313
1339
|
attention.claimableTasks;
|
|
1314
1340
|
attention.score = attention.unread * 10 +
|
|
1315
|
-
(attention.needsHumanResponse ? 5 : 0) +
|
|
1316
1341
|
(attention.agentQuestion ? 3 : 0) +
|
|
1317
1342
|
(attention.pendingPairInvite ? 4 : 0) +
|
|
1318
1343
|
attention.claimableTasks * 2;
|
|
@@ -1322,7 +1347,6 @@
|
|
|
1322
1347
|
function emptyAttention() {
|
|
1323
1348
|
return {
|
|
1324
1349
|
unread: 0,
|
|
1325
|
-
needsHumanResponse: false,
|
|
1326
1350
|
agentQuestion: false,
|
|
1327
1351
|
pendingPairInvite: false,
|
|
1328
1352
|
claimableTasks: 0,
|
|
@@ -1335,7 +1359,6 @@
|
|
|
1335
1359
|
const attention = agentAttention.call(this, agent);
|
|
1336
1360
|
const parts = [];
|
|
1337
1361
|
if (attention.unread) parts.push(`${attention.unread} unread`);
|
|
1338
|
-
if (attention.needsHumanResponse) parts.push("needs human response");
|
|
1339
1362
|
if (attention.agentQuestion) parts.push("agent asked a question");
|
|
1340
1363
|
if (attention.pendingPairInvite) parts.push("pair invite pending");
|
|
1341
1364
|
if (attention.claimableTasks) parts.push(`${attention.claimableTasks} claimable waiting`);
|
|
@@ -1343,6 +1366,9 @@
|
|
|
1343
1366
|
}
|
|
1344
1367
|
|
|
1345
1368
|
function agentType(agent) {
|
|
1369
|
+
if (agent?.id === HUMAN_AGENT_ID) return "user";
|
|
1370
|
+
if (agent?.id === "system") return "system";
|
|
1371
|
+
|
|
1346
1372
|
const values = [
|
|
1347
1373
|
...(agent?.tags || []),
|
|
1348
1374
|
agent?.meta?.provider,
|
|
@@ -1397,18 +1423,13 @@
|
|
|
1397
1423
|
return { label: agent?.status === "idle" ? "idle" : "ready", tone: "success", icon: "ti-circle-check", stale, reconnecting, badges: presenceBadges(attention, pair, {}) };
|
|
1398
1424
|
}
|
|
1399
1425
|
|
|
1400
|
-
function presenceBadges(attention, pair,
|
|
1426
|
+
function presenceBadges(attention, pair, _flags) {
|
|
1401
1427
|
const badges = [];
|
|
1402
|
-
if (flags.reconnecting) badges.push({ label: "reconnecting", className: "bg-danger-lt" });
|
|
1403
|
-
if (flags.starting) badges.push({ label: "online, not ready", className: "bg-warning-lt" });
|
|
1404
|
-
if (flags.busy) badges.push({ label: "busy in turn", className: "bg-warning-lt" });
|
|
1405
1428
|
if (pair?.status === "active") badges.push({ label: "paired", className: "bg-success-lt" });
|
|
1406
1429
|
if (pair?.status === "pending") badges.push({ label: "pair invite pending", className: "bg-warning-lt" });
|
|
1407
1430
|
if (attention.unread) badges.push({ label: attention.unread + " unread", className: "bg-danger-lt" });
|
|
1408
|
-
if (attention.needsHumanResponse) badges.push({ label: "needs response", className: "bg-warning-lt" });
|
|
1409
1431
|
if (attention.agentQuestion) badges.push({ label: "question", className: "bg-info-lt" });
|
|
1410
1432
|
if (attention.claimableTasks) badges.push({ label: attention.claimableTasks + " claimable", className: "bg-orange-lt" });
|
|
1411
|
-
if (!badges.length && !flags.offline) badges.push({ label: "ready", className: "bg-success-lt" });
|
|
1412
1433
|
return badges;
|
|
1413
1434
|
}
|
|
1414
1435
|
|
package/public/index.html
CHANGED
|
@@ -74,6 +74,24 @@
|
|
|
74
74
|
background: rgba(var(--tblr-warning-rgb), 0.12);
|
|
75
75
|
border-color: rgba(var(--tblr-warning-rgb), 0.25);
|
|
76
76
|
}
|
|
77
|
+
.agent-type-icon.claude .claude-sol {
|
|
78
|
+
display: inline-block;
|
|
79
|
+
width: 14px;
|
|
80
|
+
height: 14px;
|
|
81
|
+
background-color: currentColor;
|
|
82
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='black' transform='translate(12,12)'%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8'/%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8' transform='rotate(60)'/%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8' transform='rotate(120)'/%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8' transform='rotate(180)'/%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8' transform='rotate(240)'/%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8' transform='rotate(300)'/%3E%3C/g%3E%3C/svg%3E") center/contain no-repeat;
|
|
83
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='black' transform='translate(12,12)'%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8'/%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8' transform='rotate(60)'/%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8' transform='rotate(120)'/%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8' transform='rotate(180)'/%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8' transform='rotate(240)'/%3E%3Crect x='-1.8' y='-10' width='3.6' height='7' rx='1.8' transform='rotate(300)'/%3E%3C/g%3E%3C/svg%3E") center/contain no-repeat;
|
|
84
|
+
}
|
|
85
|
+
.agent-type-icon.user {
|
|
86
|
+
color: var(--tblr-green);
|
|
87
|
+
background: rgba(var(--tblr-green-rgb), 0.12);
|
|
88
|
+
border-color: rgba(var(--tblr-green-rgb), 0.25);
|
|
89
|
+
}
|
|
90
|
+
.agent-type-icon.system {
|
|
91
|
+
color: var(--tblr-purple);
|
|
92
|
+
background: rgba(var(--tblr-purple-rgb), 0.12);
|
|
93
|
+
border-color: rgba(var(--tblr-purple-rgb), 0.25);
|
|
94
|
+
}
|
|
77
95
|
.agent-type-icon.agent {
|
|
78
96
|
color: var(--tblr-secondary);
|
|
79
97
|
background: var(--tblr-bg-surface-secondary);
|
|
@@ -389,14 +407,6 @@
|
|
|
389
407
|
</div>
|
|
390
408
|
</button>
|
|
391
409
|
</div>
|
|
392
|
-
<div class="col-md-6 col-xl">
|
|
393
|
-
<button class="card attention-card w-100 text-start" :class="{ 'attention-empty': attentionSummary.needsHumanResponse === 0 }" @click="switchView('inbox')">
|
|
394
|
-
<div class="card-body py-3">
|
|
395
|
-
<div class="text-secondary small">Needs response</div>
|
|
396
|
-
<div class="h2 mb-0" :class="attentionSummary.needsHumanResponse ? 'text-warning' : ''" x-text="attentionSummary.needsHumanResponse"></div>
|
|
397
|
-
</div>
|
|
398
|
-
</button>
|
|
399
|
-
</div>
|
|
400
410
|
<div class="col-md-6 col-xl">
|
|
401
411
|
<button class="card attention-card w-100 text-start" :class="{ 'attention-empty': attentionSummary.agentQuestions === 0 }" @click="switchView('inbox')">
|
|
402
412
|
<div class="card-body py-3">
|
|
@@ -597,7 +607,7 @@
|
|
|
597
607
|
</span>
|
|
598
608
|
</template>
|
|
599
609
|
</div>
|
|
600
|
-
<div class="text-secondary small mt-1" x-text="'Last seen: ' + timeAgo(a.lastSeen)"></div>
|
|
610
|
+
<div class="text-secondary small mt-1" x-show="!isBuiltInAgent(a)" x-text="'Last seen: ' + timeAgo(a.lastSeen)"></div>
|
|
601
611
|
</div>
|
|
602
612
|
<div class="agent-actions d-flex gap-1">
|
|
603
613
|
<button class="btn btn-sm btn-ghost-secondary p-1" title="Send message" @click.stop="openComposeToAgent(a)">
|
|
@@ -801,10 +811,18 @@
|
|
|
801
811
|
<div class="d-flex align-items-center mb-3 gap-2 flex-wrap">
|
|
802
812
|
<h2 class="page-title mb-0">Inbox</h2>
|
|
803
813
|
<span class="badge bg-danger-lt" x-show="attentionSummary.unreadInbox > 0" x-text="attentionSummary.unreadInbox + ' unread'"></span>
|
|
804
|
-
<span class="badge bg-warning-lt" x-show="attentionSummary.needsHumanResponse > 0" x-text="attentionSummary.needsHumanResponse + ' need response'"></span>
|
|
805
814
|
<span class="badge bg-info-lt" x-show="attentionSummary.agentQuestions > 0" x-text="attentionSummary.agentQuestions + ' questions'"></span>
|
|
806
815
|
<div class="ms-auto d-flex gap-2 align-items-center flex-wrap">
|
|
807
|
-
<input type="search" class="form-control form-control-sm" style="width:
|
|
816
|
+
<input type="search" class="form-control form-control-sm" style="width: 180px" placeholder="Search inbox" x-model.debounce.200ms="inboxSearch">
|
|
817
|
+
<select class="form-select form-select-sm" style="width: 130px" x-model="inboxSort">
|
|
818
|
+
<option value="attention">Sort: Attention</option>
|
|
819
|
+
<option value="updated">Sort: Updated</option>
|
|
820
|
+
<option value="created">Sort: Created</option>
|
|
821
|
+
<option value="name">Sort: Name</option>
|
|
822
|
+
</select>
|
|
823
|
+
<button class="btn btn-sm btn-ghost-secondary" @click="inboxSortDir = inboxSortDir === 'asc' ? 'desc' : 'asc'">
|
|
824
|
+
<i class="ti" :class="inboxSortDir === 'asc' ? 'ti-sort-ascending' : 'ti-sort-descending'"></i>
|
|
825
|
+
</button>
|
|
808
826
|
<label class="form-check form-switch mb-0">
|
|
809
827
|
<input type="checkbox" class="form-check-input" x-model="inboxShowArchived">
|
|
810
828
|
<span class="form-check-label small">Archived</span>
|
|
@@ -876,10 +894,11 @@
|
|
|
876
894
|
<span class="text-secondary small ms-auto" x-text="timeAgo(thread.lastMessage?.createdAt)"></span>
|
|
877
895
|
</div>
|
|
878
896
|
<div class="text-secondary small text-truncate mt-1 inbox-thread-snippet" x-text="messagePreview(thread.lastMessage)"></div>
|
|
879
|
-
<
|
|
880
|
-
<
|
|
881
|
-
|
|
882
|
-
|
|
897
|
+
<template x-if="thread.attention?.agentQuestion">
|
|
898
|
+
<div class="d-flex gap-1 mt-1 flex-wrap">
|
|
899
|
+
<span class="badge bg-info-lt">agent asked a question</span>
|
|
900
|
+
</div>
|
|
901
|
+
</template>
|
|
883
902
|
<div class="d-flex align-items-center gap-1 mt-2">
|
|
884
903
|
<span class="badge bg-secondary-lt" x-show="thread.archived">archived</span>
|
|
885
904
|
<span class="badge bg-primary-lt" x-show="thread.draft">draft</span>
|
|
@@ -912,7 +931,6 @@
|
|
|
912
931
|
<h3 class="card-title mb-0 text-truncate" x-text="conversationTitle(selectedInboxThreadData)"></h3>
|
|
913
932
|
<div class="attention-badges d-flex gap-1 flex-wrap">
|
|
914
933
|
<span class="badge bg-danger-lt" x-show="selectedInboxThreadData.attention?.unread" x-text="selectedInboxThreadData.attention.unread + ' unread'"></span>
|
|
915
|
-
<span class="badge bg-warning-lt" x-show="selectedInboxThreadData.attention?.needsHumanResponse">needs response</span>
|
|
916
934
|
<span class="badge bg-info-lt" x-show="selectedInboxThreadData.attention?.agentQuestion">agent asked a question</span>
|
|
917
935
|
<span class="badge bg-secondary-lt" x-show="selectedInboxThreadData.archived">archived</span>
|
|
918
936
|
</div>
|
|
@@ -1603,7 +1621,6 @@
|
|
|
1603
1621
|
<div class="fw-bold small mb-1">Needs attention</div>
|
|
1604
1622
|
<div class="attention-badges d-flex gap-1 flex-wrap">
|
|
1605
1623
|
<span class="badge bg-danger-lt" x-show="agentAttention(selectedAgentDetail).unread" x-text="agentAttention(selectedAgentDetail).unread + ' unread'"></span>
|
|
1606
|
-
<span class="badge bg-warning-lt" x-show="agentAttention(selectedAgentDetail).needsHumanResponse">needs human response</span>
|
|
1607
1624
|
<span class="badge bg-info-lt" x-show="agentAttention(selectedAgentDetail).agentQuestion">agent asked a question</span>
|
|
1608
1625
|
<span class="badge bg-warning-lt" x-show="agentAttention(selectedAgentDetail).pendingPairInvite">pair invite pending</span>
|
|
1609
1626
|
<span class="badge bg-orange-lt" x-show="agentAttention(selectedAgentDetail).claimableTasks" x-text="agentAttention(selectedAgentDetail).claimableTasks + ' claimable waiting'"></span>
|
|
@@ -1619,15 +1636,14 @@
|
|
|
1619
1636
|
<template x-for="badge in agentPresenceBadges(selectedAgentDetail)" :key="badge.label">
|
|
1620
1637
|
<span class="badge ms-1" :class="badge.className" x-text="badge.label"></span>
|
|
1621
1638
|
</template>
|
|
1622
|
-
<template x-if="selectedAgentDetail.ready">
|
|
1623
|
-
<span class="badge bg-success-lt ms-1">ready</span>
|
|
1624
|
-
</template>
|
|
1625
1639
|
</div>
|
|
1626
1640
|
</div>
|
|
1627
|
-
<
|
|
1628
|
-
<div class="
|
|
1629
|
-
|
|
1630
|
-
|
|
1641
|
+
<template x-if="!isBuiltInAgent(selectedAgentDetail)">
|
|
1642
|
+
<div class="detail-row mb-2">
|
|
1643
|
+
<div class="text-secondary small">Last seen</div>
|
|
1644
|
+
<div class="small" x-text="timeAgo(selectedAgentDetail.lastSeen)"></div>
|
|
1645
|
+
</div>
|
|
1646
|
+
</template>
|
|
1631
1647
|
<div class="detail-row mb-2">
|
|
1632
1648
|
<div class="text-secondary small">Created</div>
|
|
1633
1649
|
<div class="small" x-text="fmtTime(selectedAgentDetail.createdAt)"></div>
|
package/src/config.ts
CHANGED
package/src/daemon.ts
CHANGED
|
@@ -22,9 +22,9 @@ export type DaemonAction =
|
|
|
22
22
|
| "logs";
|
|
23
23
|
|
|
24
24
|
export type DaemonScope = "user" | "system";
|
|
25
|
-
|
|
25
|
+
type DaemonKind = "systemd" | "launchd" | "unsupported";
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
type DaemonOptions = {
|
|
28
28
|
action: DaemonAction;
|
|
29
29
|
name?: string;
|
|
30
30
|
envFile?: string;
|
|
@@ -36,17 +36,17 @@ export type DaemonOptions = {
|
|
|
36
36
|
enable?: boolean;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
type DaemonEnvironment = SetupEnvironment & {
|
|
40
40
|
uid?: number;
|
|
41
41
|
hasSystemctl?: boolean;
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
type DaemonFilePlan = {
|
|
45
45
|
path: string;
|
|
46
46
|
content: string;
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
type DaemonPlan = {
|
|
50
50
|
action: DaemonAction;
|
|
51
51
|
kind: DaemonKind;
|
|
52
52
|
scope: DaemonScope;
|
|
@@ -66,7 +66,7 @@ export type DaemonPlan = {
|
|
|
66
66
|
manualCommand: string;
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
type DaemonExecutionResult = {
|
|
70
70
|
plan: DaemonPlan;
|
|
71
71
|
output: string;
|
|
72
72
|
};
|
package/src/setup.ts
CHANGED
|
@@ -8,7 +8,7 @@ const SETUP_MARKER = "agent-relay-managed-env";
|
|
|
8
8
|
export const DEFAULT_PORT = 4850;
|
|
9
9
|
export const DEFAULT_HOST = "127.0.0.1";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
type SetupOptions = {
|
|
12
12
|
envFile?: string;
|
|
13
13
|
host?: string;
|
|
14
14
|
port?: number;
|
|
@@ -25,7 +25,7 @@ export type SetupEnvironment = {
|
|
|
25
25
|
xdgStateHome?: string;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
type SetupPlan = {
|
|
29
29
|
envFile: string;
|
|
30
30
|
configDir: string;
|
|
31
31
|
stateDir: string;
|
|
@@ -35,14 +35,14 @@ export type SetupPlan = {
|
|
|
35
35
|
warnings: string[];
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
function defaultConfigDir(env: SetupEnvironment = {}): string {
|
|
39
39
|
const home = env.homeDir ?? homedir();
|
|
40
40
|
const platform = env.platform ?? process.platform;
|
|
41
41
|
if (platform === "darwin") return join(home, "Library", "Application Support", "agent-relay");
|
|
42
42
|
return join(env.xdgConfigHome ?? join(home, ".config"), "agent-relay");
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
function defaultStateDir(env: SetupEnvironment = {}): string {
|
|
46
46
|
const home = env.homeDir ?? homedir();
|
|
47
47
|
const platform = env.platform ?? process.platform;
|
|
48
48
|
if (platform === "darwin") return join(home, "Library", "Application Support", "agent-relay");
|
package/src/upgrade.ts
CHANGED
|
@@ -5,19 +5,19 @@ import { VERSION } from "./config";
|
|
|
5
5
|
|
|
6
6
|
export type UpgradeProvider = "auto" | "all" | "codex" | "claude";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
type UpgradeOptions = {
|
|
9
9
|
targetVersion?: string;
|
|
10
10
|
providers?: UpgradeProvider[];
|
|
11
11
|
noRestart?: boolean;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
type InstalledPackage = {
|
|
15
15
|
version?: string;
|
|
16
16
|
source: "bun" | "npm" | "copied" | "claude-plugin";
|
|
17
17
|
path?: string;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
type ClaudePluginInstall = {
|
|
21
21
|
id: string;
|
|
22
22
|
version?: string;
|
|
23
23
|
scope?: string;
|
|
@@ -37,14 +37,14 @@ export type UpgradeSnapshot = {
|
|
|
37
37
|
packageManager: "bun" | "npm" | "none";
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
type UpgradeAction = {
|
|
41
41
|
label: string;
|
|
42
42
|
command: string[];
|
|
43
43
|
reason: string;
|
|
44
44
|
mutates: boolean;
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
type UpgradePlan = {
|
|
48
48
|
targetVersion: string;
|
|
49
49
|
providers: { codex: boolean; claude: boolean };
|
|
50
50
|
snapshot: UpgradeSnapshot;
|