nexus-agentd 0.2.6 → 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/LICENSE +22 -22
- package/README.md +103 -14
- package/dist/a2a/runtime.d.ts +4 -1
- package/dist/a2a/runtime.js +213 -10
- package/dist/acp/runtime.js +13 -6
- package/dist/artifact-store.d.ts +162 -0
- package/dist/artifact-store.js +1081 -0
- package/dist/cli.js +13 -14
- package/dist/config.js +45 -5
- package/dist/control-plane-validation.d.ts +54 -0
- package/dist/control-plane-validation.js +152 -0
- package/dist/control-plane.d.ts +9 -32
- package/dist/control-plane.js +41 -157
- package/dist/drivers/index.js +12 -0
- package/dist/drivers/pi.js +1 -1
- package/dist/drivers/stdio.d.ts +4 -1
- package/dist/drivers/stdio.js +135 -19
- package/dist/events.d.ts +9 -0
- package/dist/events.js +17 -4
- package/dist/index.js +10 -1
- package/dist/process-tree.js +15 -6
- package/dist/run-store.d.ts +52 -7
- package/dist/run-store.js +178 -22
- package/dist/server/auth-policy.d.ts +27 -0
- package/dist/server/auth-policy.js +143 -0
- package/dist/server/connection.d.ts +8 -0
- package/dist/server/connection.js +67 -0
- package/dist/server/diagnostics.d.ts +40 -0
- package/dist/server/diagnostics.js +130 -0
- package/dist/server/metrics.d.ts +51 -0
- package/dist/server/metrics.js +56 -0
- package/dist/server/quota.d.ts +59 -0
- package/dist/server/quota.js +176 -0
- package/dist/server/validation.d.ts +29 -0
- package/dist/server/validation.js +221 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +682 -418
- package/dist/session/admin-runs.d.ts +73 -0
- package/dist/session/admin-runs.js +297 -0
- package/dist/session/admission.d.ts +32 -0
- package/dist/session/admission.js +62 -0
- package/dist/session/readiness.d.ts +33 -0
- package/dist/session/readiness.js +174 -0
- package/dist/session.d.ts +58 -6
- package/dist/session.js +244 -109
- package/dist/sse-writer.d.ts +7 -0
- package/dist/sse-writer.js +60 -0
- package/dist/types.d.ts +44 -2
- package/dist/types.js +1 -0
- package/dist/webui/app/sources.js +16 -8
- package/dist/webui/index.js +11 -11
- package/dist/webui/markup.js +2 -0
- package/dist/webui/styles.js +46 -1
- package/examples/client.mjs +102 -0
- package/nexus-agentd.example.json +53 -34
- package/package.json +3 -2
package/dist/webui/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { markup } from './markup.js';
|
|
2
2
|
import { styles } from './styles.js';
|
|
3
3
|
import { sources } from './app/sources.js';
|
|
4
|
-
const page = `<!doctype html>
|
|
5
|
-
<html lang="zh-CN">
|
|
6
|
-
<head>
|
|
7
|
-
<meta charset="utf-8">
|
|
8
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
9
|
-
<meta name="color-scheme" content="light dark">
|
|
10
|
-
<title>Agent Nexus</title>
|
|
11
|
-
<style>${styles}</style>
|
|
12
|
-
<script type="module" defer src="/ui/app.js"></script>
|
|
13
|
-
</head>
|
|
14
|
-
<body>${markup}</body>
|
|
4
|
+
const page = `<!doctype html>
|
|
5
|
+
<html lang="zh-CN">
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="utf-8">
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
9
|
+
<meta name="color-scheme" content="light dark">
|
|
10
|
+
<title>Agent Nexus</title>
|
|
11
|
+
<style>${styles}</style>
|
|
12
|
+
<script type="module" defer src="/ui/app.js"></script>
|
|
13
|
+
</head>
|
|
14
|
+
<body>${markup}</body>
|
|
15
15
|
</html>`;
|
|
16
16
|
const entryModule = `import './app/main.js'\n`;
|
|
17
17
|
const modules = { '/ui/app.js': entryModule };
|
package/dist/webui/markup.js
CHANGED
|
@@ -5,6 +5,7 @@ export const markup = String.raw `
|
|
|
5
5
|
<form id="setup-form" class="auth-card">
|
|
6
6
|
<header><span class="brand-mark">N</span><h1>初始化 Agent Nexus</h1></header>
|
|
7
7
|
<p>此密码仅用于登录控制台;客户端 API 密钥在登录后单独创建。</p>
|
|
8
|
+
<div class="field"><label for="setup-token">初始化令牌</label><input id="setup-token" name="setupToken" type="password" autocomplete="off" required><small class="field-help">从网关启动终端复制 Setup token。重启后令牌会更新;远程初始化请使用可信网络或 HTTPS。</small></div>
|
|
8
9
|
<div class="field"><label for="setup-password">控制台密码</label><input id="setup-password" name="password" type="password" minlength="12" autocomplete="new-password" required></div>
|
|
9
10
|
<div class="field"><label for="setup-confirm">确认密码</label><input id="setup-confirm" name="confirmPassword" type="password" minlength="12" autocomplete="new-password" required></div>
|
|
10
11
|
<button class="button primary auth-submit" type="submit">完成初始化</button>
|
|
@@ -48,6 +49,7 @@ export const markup = String.raw `
|
|
|
48
49
|
<div id="page-actions" class="page-actions"></div>
|
|
49
50
|
</header>
|
|
50
51
|
<section id="page-content" class="page-content">
|
|
52
|
+
<p id="connection-status" class="connection-status hidden" role="status"></p>
|
|
51
53
|
<div id="page-stats"></div>
|
|
52
54
|
<div id="page-toolbar"></div>
|
|
53
55
|
<div id="page-results"></div>
|
package/dist/webui/styles.js
CHANGED
|
@@ -126,7 +126,7 @@ h1, h2, h3, p { margin: 0; }
|
|
|
126
126
|
button, input, select, textarea { font: inherit; color: inherit; }
|
|
127
127
|
button { background: none; border: 0; cursor: pointer; padding: 0; }
|
|
128
128
|
code, .mono { font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; }
|
|
129
|
-
.hidden { display: none !important; }
|
|
129
|
+
.hidden, [hidden] { display: none !important; }
|
|
130
130
|
.muted { color: hsl(var(--muted-foreground)); font-size: var(--fs-xs); }
|
|
131
131
|
|
|
132
132
|
:focus-visible {
|
|
@@ -365,6 +365,8 @@ tr[data-run-detail] { cursor: pointer; }
|
|
|
365
365
|
.error-detail { color: hsl(var(--destructive-text)); font-size: var(--fs-sm); overflow-wrap: anywhere; line-height: 1.4; }
|
|
366
366
|
.row-actions { display: flex; justify-content: flex-end; gap: var(--sp-2); }
|
|
367
367
|
.agent-table { min-width: 1050px; table-layout: fixed; }
|
|
368
|
+
.connection-status { padding: var(--sp-3) var(--sp-4); border: 1px solid currentColor; border-radius: var(--radius-lg); color: hsl(var(--destructive-text)); margin-bottom: var(--sp-4); overflow-wrap: anywhere; }
|
|
369
|
+
.run-pagination { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; margin-bottom: 16px; }
|
|
368
370
|
.agent-table th:nth-child(1) { width: 22%; }
|
|
369
371
|
.agent-table th:nth-child(2) { width: 8%; }
|
|
370
372
|
.agent-table th:nth-child(3), .agent-table th:nth-child(4), .agent-table th:nth-child(6) { width: 10%; }
|
|
@@ -456,6 +458,13 @@ tr[data-run-detail] { cursor: pointer; }
|
|
|
456
458
|
.run-task-cell small { display: block; margin-top: 2px; color: hsl(var(--muted-foreground)); font-size: var(--fs-2xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
457
459
|
|
|
458
460
|
/* Run detail (drawer) */
|
|
461
|
+
.run-detail-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-3); }
|
|
462
|
+
.run-output-heading { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-2); }
|
|
463
|
+
.run-output-heading h3 { margin: 0; }
|
|
464
|
+
.run-pending { padding: var(--sp-3); margin-bottom: var(--sp-4); border: 1px solid hsl(var(--border)); border-radius: var(--radius); }
|
|
465
|
+
.run-pending-prompt { white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
466
|
+
.run-pending h3 { font-size: var(--fs-md); }
|
|
467
|
+
.run-pending .row-actions { flex-wrap: wrap; }
|
|
459
468
|
.run-detail-grid {
|
|
460
469
|
display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
|
|
461
470
|
margin-bottom: var(--sp-4);
|
|
@@ -734,6 +743,42 @@ tr[data-run-detail] { cursor: pointer; }
|
|
|
734
743
|
.toast-region { right: var(--sp-4); bottom: var(--sp-4); left: var(--sp-4); max-width: none; }
|
|
735
744
|
}
|
|
736
745
|
|
|
746
|
+
/* Keep row actions and task context in the viewport on laptops and phones. */
|
|
747
|
+
@media (max-width: 1400px) {
|
|
748
|
+
.agent-table, .run-table { min-width: 0; }
|
|
749
|
+
.agent-table thead, .run-table thead {
|
|
750
|
+
position: absolute; width: 1px; height: 1px; padding: 0;
|
|
751
|
+
overflow: hidden; clip-path: inset(50%); white-space: nowrap;
|
|
752
|
+
}
|
|
753
|
+
.agent-table tbody, .run-table tbody { display: grid; }
|
|
754
|
+
.agent-table tbody tr, .run-table tbody tr {
|
|
755
|
+
display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
756
|
+
gap: var(--sp-3) var(--sp-6); padding: var(--sp-4); border-bottom: 1px solid hsl(var(--border));
|
|
757
|
+
}
|
|
758
|
+
.agent-table td, .run-table td {
|
|
759
|
+
min-width: 0; max-width: none !important; padding: 0; height: auto;
|
|
760
|
+
border: 0; white-space: normal !important; overflow-wrap: anywhere; text-align: left !important;
|
|
761
|
+
}
|
|
762
|
+
.agent-table td::before, .run-table td::before { display: block; font-size: var(--fs-xs); color: hsl(var(--muted-foreground)); margin-bottom: var(--sp-1); }
|
|
763
|
+
.agent-table td:nth-child(2)::before { content: '协议'; }
|
|
764
|
+
.agent-table td:nth-child(3)::before { content: '驱动'; }
|
|
765
|
+
.agent-table td:nth-child(4)::before { content: '探测状态'; }
|
|
766
|
+
.agent-table td:nth-child(5)::before { content: '默认工作区'; }
|
|
767
|
+
.agent-table td:nth-child(6)::before { content: '权限策略'; }
|
|
768
|
+
.run-table td:nth-child(2)::before { content: '任务'; }
|
|
769
|
+
.run-table td:nth-child(3)::before { content: '结果'; }
|
|
770
|
+
.run-table td:nth-child(4)::before { content: '状态'; }
|
|
771
|
+
.run-table td:nth-child(5)::before { content: '开始时间'; }
|
|
772
|
+
.run-table td:nth-child(6)::before { content: '耗时'; }
|
|
773
|
+
.agent-table td:last-child, .run-table td:last-child, td[colspan] { grid-column: 1 / -1; }
|
|
774
|
+
.agent-table .row-actions { justify-content: flex-start; }
|
|
775
|
+
.agent-table .button.small, .run-table .button.small { min-height: 36px; }
|
|
776
|
+
}
|
|
777
|
+
@media (max-width: 560px) {
|
|
778
|
+
.agent-table tbody tr, .run-table tbody tr { grid-template-columns: minmax(0, 1fr); }
|
|
779
|
+
.run-pagination { align-items: flex-start; }
|
|
780
|
+
}
|
|
781
|
+
|
|
737
782
|
/* ── Reduced motion ───────────────────────────────────────────────── */
|
|
738
783
|
/* 统一压制而不是逐个列举消费者,这样以后新增的 transition 不会漏掉。
|
|
739
784
|
running/waiting 的 pulse 停下后,色点和文字标签仍然表达状态。 */
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { setTimeout as delay } from 'node:timers/promises'
|
|
2
|
+
|
|
3
|
+
/** Minimal Node 20+ client. Keep API Keys out of URLs and browser storage. */
|
|
4
|
+
export function createGatewayClient(baseUrl, apiKey) {
|
|
5
|
+
const base = new URL(baseUrl)
|
|
6
|
+
const headers = { Authorization: `Bearer ${apiKey}` }
|
|
7
|
+
const route = (sessionId) => `/v1/sessions/${encodeURIComponent(sessionId)}`
|
|
8
|
+
async function request(path, method = 'GET', body, signal) {
|
|
9
|
+
const response = await fetch(new URL(path, base), {
|
|
10
|
+
method, headers: { ...headers, ...(body === undefined ? {} : { 'Content-Type': 'application/json' }) },
|
|
11
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
12
|
+
signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(30_000)]) : AbortSignal.timeout(30_000),
|
|
13
|
+
redirect: 'error'
|
|
14
|
+
})
|
|
15
|
+
if (!response.ok) {
|
|
16
|
+
const error = new Error(`Gateway request failed (${response.status})`)
|
|
17
|
+
error.status = response.status
|
|
18
|
+
await response.body?.cancel()
|
|
19
|
+
throw error
|
|
20
|
+
}
|
|
21
|
+
return response.json()
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
createSession: (agentId, workspace) => request('/v1/sessions', 'POST', { agentId, workspace }),
|
|
25
|
+
snapshot: (id) => request(route(id)),
|
|
26
|
+
message: (id, message) => request(`${route(id)}/message`, 'POST', { message }),
|
|
27
|
+
resolve: (id, requestId, answer) => request(`${route(id)}/requests/${encodeURIComponent(requestId)}/resolve`, 'POST', answer),
|
|
28
|
+
cancel: (id) => request(`${route(id)}/cancel`, 'POST', {}),
|
|
29
|
+
close: (id) => request(route(id), 'DELETE'),
|
|
30
|
+
/** A reset yields a replacement snapshot; old discarded events are not replayed. */
|
|
31
|
+
async *events(id, { after, signal = new AbortController().signal } = {}) {
|
|
32
|
+
let cursor = after
|
|
33
|
+
let retries = 0
|
|
34
|
+
while (!signal.aborted) {
|
|
35
|
+
const connection = new AbortController()
|
|
36
|
+
const combined = AbortSignal.any([signal, connection.signal])
|
|
37
|
+
let timer = setTimeout(() => connection.abort(new Error('SSE connection timeout')), 15_000)
|
|
38
|
+
let reader
|
|
39
|
+
let reset = false
|
|
40
|
+
try {
|
|
41
|
+
const response = await fetch(new URL(`${route(id)}/events`, base), {
|
|
42
|
+
headers: { ...headers, ...(cursor === undefined ? {} : { 'Last-Event-ID': cursor }) },
|
|
43
|
+
signal: combined, redirect: 'error'
|
|
44
|
+
})
|
|
45
|
+
clearTimeout(timer)
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
const error = new Error(`SSE request failed (${response.status})`)
|
|
48
|
+
error.status = response.status
|
|
49
|
+
await response.body?.cancel()
|
|
50
|
+
throw error
|
|
51
|
+
}
|
|
52
|
+
reader = response.body.getReader()
|
|
53
|
+
const decoder = new TextDecoder()
|
|
54
|
+
let buffer = ''
|
|
55
|
+
while (!signal.aborted && !reset) {
|
|
56
|
+
timer = setTimeout(() => connection.abort(new Error('SSE heartbeat timeout')), 45_000)
|
|
57
|
+
const { value, done } = await reader.read()
|
|
58
|
+
clearTimeout(timer)
|
|
59
|
+
if (done) break
|
|
60
|
+
buffer += decoder.decode(value, { stream: true }).replace(/\r/g, '')
|
|
61
|
+
if (buffer.length > 2 * 1024 * 1024) throw new Error('SSE frame limit exceeded')
|
|
62
|
+
let end
|
|
63
|
+
while ((end = buffer.indexOf('\n\n')) >= 0) {
|
|
64
|
+
const frame = buffer.slice(0, end)
|
|
65
|
+
buffer = buffer.slice(end + 2)
|
|
66
|
+
const lines = frame.split('\n')
|
|
67
|
+
const data = lines.filter((line) => line.startsWith('data:')).map((line) => line.slice(5).trimStart()).join('\n')
|
|
68
|
+
if (!data) continue // Heartbeat comments carry no event.
|
|
69
|
+
const type = lines.find((line) => line.startsWith('event:'))?.slice(6).trim()
|
|
70
|
+
const eventId = lines.find((line) => line.startsWith('id:'))?.slice(3).trim()
|
|
71
|
+
if (type === 'reset') {
|
|
72
|
+
// Use our fixed same-origin Session route, never a remote recovery URL.
|
|
73
|
+
const snapshot = await request(route(id), 'GET', undefined, signal)
|
|
74
|
+
cursor = snapshot.lastEventId || '0'
|
|
75
|
+
yield { type: 'reset', data: snapshot, recovery: JSON.parse(data) }
|
|
76
|
+
reset = true
|
|
77
|
+
break
|
|
78
|
+
}
|
|
79
|
+
if (!eventId || !/^\d+$/.test(eventId)) continue
|
|
80
|
+
if (cursor !== undefined && BigInt(eventId) <= BigInt(cursor)) continue
|
|
81
|
+
cursor = eventId
|
|
82
|
+
retries = 0
|
|
83
|
+
yield JSON.parse(data)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (signal.aborted) return
|
|
88
|
+
// A revoked Key, narrowed scope or deleted/restarted Session needs user action.
|
|
89
|
+
if ([401, 403, 404].includes(error.status)) throw error
|
|
90
|
+
} finally {
|
|
91
|
+
clearTimeout(timer)
|
|
92
|
+
connection.abort()
|
|
93
|
+
await reader?.cancel().catch(() => {})
|
|
94
|
+
}
|
|
95
|
+
if (!reset && !signal.aborted) {
|
|
96
|
+
await delay(Math.min(30_000, 500 * 2 ** Math.min(retries++, 6)) + Math.random() * 250,
|
|
97
|
+
undefined, { signal }).catch((error) => { if (!signal.aborted) throw error })
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -1,40 +1,59 @@
|
|
|
1
|
-
{
|
|
2
|
-
"initialized": false,
|
|
3
|
-
"listen": {
|
|
4
|
-
"host": "0.0.0.0",
|
|
5
|
-
"port": 8787
|
|
6
|
-
},
|
|
7
|
-
"workspaceRoots": [
|
|
8
|
-
"/data/repos"
|
|
9
|
-
],
|
|
10
|
-
"apiKeys": [],
|
|
11
|
-
"maxRequestBytes": 1048576,
|
|
12
|
-
"maxAttachmentBytes": 33554432,
|
|
13
|
-
"requestTimeoutMs": 30000,
|
|
14
|
-
"promptTimeoutMs": 1800000,
|
|
15
|
-
"cleanupIntervalMs": 60000,
|
|
16
|
-
"maxSessions": 64,
|
|
17
|
-
"maxSseConnections": 128,
|
|
18
|
-
"maxConnections": 256,
|
|
1
|
+
{
|
|
2
|
+
"initialized": false,
|
|
3
|
+
"listen": {
|
|
4
|
+
"host": "0.0.0.0",
|
|
5
|
+
"port": 8787
|
|
6
|
+
},
|
|
7
|
+
"workspaceRoots": [
|
|
8
|
+
"/data/repos"
|
|
9
|
+
],
|
|
10
|
+
"apiKeys": [],
|
|
11
|
+
"maxRequestBytes": 1048576,
|
|
12
|
+
"maxAttachmentBytes": 33554432,
|
|
13
|
+
"requestTimeoutMs": 30000,
|
|
14
|
+
"promptTimeoutMs": 1800000,
|
|
15
|
+
"cleanupIntervalMs": 60000,
|
|
16
|
+
"maxSessions": 64,
|
|
17
|
+
"maxSseConnections": 128,
|
|
18
|
+
"maxConnections": 256,
|
|
19
19
|
"sessionTtlMs": 86400000,
|
|
20
|
+
"quotas": {
|
|
21
|
+
"maxSessionsPerKey": 16,
|
|
22
|
+
"maxRunningRunsPerKey": 4,
|
|
23
|
+
"maxSsePerKey": 8,
|
|
24
|
+
"maxUploadBytesPerKey": 33554432
|
|
25
|
+
},
|
|
26
|
+
"history": { "maxRuns": 1000, "retentionDays": 30, "maxBytes": 67108864 },
|
|
27
|
+
"artifacts": { "retentionDays": 30, "maxBytes": 536870912, "maxArtifactBytes": 12582912, "maxQueuedBytes": 67108864 },
|
|
20
28
|
"agents": {
|
|
21
|
-
"
|
|
29
|
+
"custom": {
|
|
22
30
|
"protocol": "acp",
|
|
23
|
-
"driver": "
|
|
24
|
-
"name": "
|
|
25
|
-
"
|
|
31
|
+
"driver": "stdio",
|
|
32
|
+
"name": "Custom ACP",
|
|
33
|
+
"enabled": false,
|
|
34
|
+
"command": "your-acp-agent",
|
|
35
|
+
"args": [],
|
|
36
|
+
"probeArgs": ["--version"],
|
|
26
37
|
"workspace": "/data/repos/project",
|
|
27
38
|
"permissionPolicy": "ask"
|
|
28
39
|
},
|
|
29
|
-
"
|
|
30
|
-
"protocol": "
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
"codex": {
|
|
41
|
+
"protocol": "acp",
|
|
42
|
+
"driver": "codex",
|
|
43
|
+
"name": "Codex",
|
|
44
|
+
"command": "codex-acp",
|
|
45
|
+
"workspace": "/data/repos/project",
|
|
46
|
+
"permissionPolicy": "ask"
|
|
47
|
+
},
|
|
48
|
+
"research": {
|
|
49
|
+
"protocol": "a2a",
|
|
50
|
+
"name": "Research Agent",
|
|
51
|
+
"agentCardUrl": "http://192.168.1.20:8080/.well-known/agent-card.json",
|
|
52
|
+
"preferredTransport": "auto",
|
|
53
|
+
"auth": {
|
|
54
|
+
"type": "none"
|
|
55
|
+
},
|
|
56
|
+
"timeoutMs": 60000
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexus-agentd",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Local Nexus Gateway daemon with an HTTP/SSE API and WebUI for allowlisted ACP and remote A2A agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
|
+
"examples",
|
|
13
14
|
"nexus-agentd.example.json",
|
|
14
15
|
"README.md"
|
|
15
16
|
],
|
|
@@ -34,7 +35,7 @@
|
|
|
34
35
|
],
|
|
35
36
|
"scripts": {
|
|
36
37
|
"build": "node scripts/generate-webui-sources.mjs && node scripts/clean-dist.mjs && tsc -p tsconfig.json",
|
|
37
|
-
"typecheck": "node scripts/generate-webui-sources.mjs && tsc -p tsconfig.json --noEmit",
|
|
38
|
+
"typecheck": "node scripts/generate-webui-sources.mjs && tsc -p tsconfig.json --noEmit && tsc -p tsconfig.webui.json",
|
|
38
39
|
"test": "tsx --test test/*.test.ts",
|
|
39
40
|
"test:webui": "node scripts/generate-webui-sources.mjs && playwright test",
|
|
40
41
|
"prepack": "npm run build"
|