@aria-cli/tools 1.0.9 → 1.0.11
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 +9 -5
- package/src/__tests__/web-fetch-download.test.ts +0 -433
- package/src/__tests__/web-tools.test.ts +0 -619
- package/src/ask-user-interaction.ts +0 -33
- package/src/cache/web-cache.ts +0 -110
- package/src/definitions/arion.ts +0 -118
- package/src/definitions/browser/browser.ts +0 -502
- package/src/definitions/browser/index.ts +0 -5
- package/src/definitions/browser/pw-downloads.ts +0 -142
- package/src/definitions/browser/pw-interactions.ts +0 -282
- package/src/definitions/browser/pw-responses.ts +0 -98
- package/src/definitions/browser/pw-session.ts +0 -405
- package/src/definitions/browser/pw-shared.ts +0 -85
- package/src/definitions/browser/pw-snapshot.ts +0 -383
- package/src/definitions/browser/pw-state.ts +0 -101
- package/src/definitions/browser/types.ts +0 -203
- package/src/definitions/code-intelligence.ts +0 -526
- package/src/definitions/core.ts +0 -118
- package/src/definitions/delegation.ts +0 -567
- package/src/definitions/deploy.ts +0 -73
- package/src/definitions/filesystem.ts +0 -217
- package/src/definitions/frg.ts +0 -67
- package/src/definitions/index.ts +0 -28
- package/src/definitions/memory.ts +0 -150
- package/src/definitions/messaging.ts +0 -734
- package/src/definitions/meta.ts +0 -392
- package/src/definitions/network.ts +0 -179
- package/src/definitions/outlook.ts +0 -318
- package/src/definitions/patch/apply-patch.ts +0 -235
- package/src/definitions/patch/fuzzy-match.ts +0 -217
- package/src/definitions/patch/index.ts +0 -1
- package/src/definitions/patch/patch-parser.ts +0 -297
- package/src/definitions/patch/sandbox-paths.ts +0 -129
- package/src/definitions/process/index.ts +0 -5
- package/src/definitions/process/process-registry.ts +0 -303
- package/src/definitions/process/process.ts +0 -456
- package/src/definitions/process/pty-keys.ts +0 -298
- package/src/definitions/process/session-slug.ts +0 -147
- package/src/definitions/quip.ts +0 -225
- package/src/definitions/search.ts +0 -67
- package/src/definitions/session-history.ts +0 -79
- package/src/definitions/shell.ts +0 -202
- package/src/definitions/slack.ts +0 -211
- package/src/definitions/web.ts +0 -119
- package/src/executors/apply-patch.ts +0 -1035
- package/src/executors/arion.ts +0 -199
- package/src/executors/code-intelligence.ts +0 -1179
- package/src/executors/deploy.ts +0 -1066
- package/src/executors/filesystem.ts +0 -1428
- package/src/executors/frg-freshness.ts +0 -743
- package/src/executors/frg.ts +0 -394
- package/src/executors/index.ts +0 -280
- package/src/executors/learning-meta.ts +0 -1367
- package/src/executors/lsp-client.ts +0 -355
- package/src/executors/memory.ts +0 -978
- package/src/executors/meta.ts +0 -293
- package/src/executors/process-registry.ts +0 -570
- package/src/executors/pty-session-store.ts +0 -43
- package/src/executors/pty.ts +0 -342
- package/src/executors/restart.ts +0 -133
- package/src/executors/search-freshness.ts +0 -249
- package/src/executors/search-types.ts +0 -98
- package/src/executors/search.ts +0 -89
- package/src/executors/self-diagnose.ts +0 -552
- package/src/executors/session-history.ts +0 -435
- package/src/executors/shell-safety.ts +0 -519
- package/src/executors/shell.ts +0 -1243
- package/src/executors/utils.ts +0 -40
- package/src/executors/web.ts +0 -786
- package/src/extraction/content-extraction.ts +0 -281
- package/src/extraction/index.ts +0 -5
- package/src/headless-control-contract.ts +0 -1149
- package/src/index.ts +0 -788
- package/src/local-control-http-auth.ts +0 -2
- package/src/mcp/client.ts +0 -218
- package/src/mcp/connection.ts +0 -568
- package/src/mcp/index.ts +0 -11
- package/src/mcp/jsonrpc.ts +0 -195
- package/src/mcp/types.ts +0 -199
- package/src/network-control-adapter.ts +0 -88
- package/src/network-runtime/address-types.ts +0 -218
- package/src/network-runtime/db-owner-fencing.ts +0 -91
- package/src/network-runtime/delivery-receipts.ts +0 -372
- package/src/network-runtime/direct-endpoint-authority.ts +0 -35
- package/src/network-runtime/index.ts +0 -316
- package/src/network-runtime/local-control-contract.ts +0 -784
- package/src/network-runtime/node-store-contract.ts +0 -46
- package/src/network-runtime/pair-route-contract.ts +0 -97
- package/src/network-runtime/peer-capabilities.ts +0 -48
- package/src/network-runtime/peer-principal-ref.ts +0 -20
- package/src/network-runtime/peer-state-machine.ts +0 -160
- package/src/network-runtime/protocol-schemas.ts +0 -265
- package/src/network-runtime/runtime-bootstrap-contract.ts +0 -83
- package/src/outlook/desktop-session.ts +0 -409
- package/src/policy.ts +0 -171
- package/src/providers/brave.ts +0 -80
- package/src/providers/duckduckgo.ts +0 -199
- package/src/providers/exa.ts +0 -85
- package/src/providers/firecrawl.ts +0 -77
- package/src/providers/index.ts +0 -8
- package/src/providers/jina.ts +0 -70
- package/src/providers/router.ts +0 -121
- package/src/providers/search-provider.ts +0 -74
- package/src/providers/tavily.ts +0 -74
- package/src/quip/desktop-session.ts +0 -435
- package/src/registry/index.ts +0 -1
- package/src/registry/registry.ts +0 -905
- package/src/runtime-socket-local-control-client.ts +0 -632
- package/src/security/dns-normalization.ts +0 -34
- package/src/security/dns-pinning.ts +0 -138
- package/src/security/external-content.ts +0 -129
- package/src/security/ssrf.ts +0 -207
- package/src/slack/desktop-session.ts +0 -493
- package/src/tool-factory.ts +0 -91
- package/src/types.ts +0 -1341
- package/src/utils/retry.ts +0 -163
- package/src/utils/safe-parse-json.ts +0 -176
- package/src/utils/url.ts +0 -20
- package/tests/benchmarks/registry.bench.ts +0 -57
- package/tests/cache/web-cache.test.ts +0 -147
- package/tests/critical-integration.test.ts +0 -1465
- package/tests/definitions/apply-patch.test.ts +0 -586
- package/tests/definitions/browser.test.ts +0 -495
- package/tests/definitions/delegation-pause-resume.test.ts +0 -758
- package/tests/definitions/execution.test.ts +0 -671
- package/tests/definitions/messaging-inbox-scope.test.ts +0 -229
- package/tests/definitions/messaging.test.ts +0 -1468
- package/tests/definitions/outlook.test.ts +0 -30
- package/tests/definitions/process.test.ts +0 -469
- package/tests/definitions/slack.test.ts +0 -28
- package/tests/definitions/tool-inventory.test.ts +0 -218
- package/tests/e2e/delegation-quest-orchestration.e2e.test.ts +0 -433
- package/tests/e2e/memory-tool-discovery-contract.e2e.test.ts +0 -81
- package/tests/executors/apply-patch.test.ts +0 -538
- package/tests/executors/arion.test.ts +0 -309
- package/tests/executors/conversation-primitives.test.ts +0 -250
- package/tests/executors/deploy.test.ts +0 -746
- package/tests/executors/filesystem-tools.test.ts +0 -357
- package/tests/executors/filesystem.test.ts +0 -959
- package/tests/executors/frg-freshness.test.ts +0 -136
- package/tests/executors/frg-merge.test.ts +0 -70
- package/tests/executors/frg-session-content.test.ts +0 -40
- package/tests/executors/frg.test.ts +0 -56
- package/tests/executors/memory-bugfixes.test.ts +0 -257
- package/tests/executors/memory-real-memoria.integration.test.ts +0 -316
- package/tests/executors/memory.test.ts +0 -853
- package/tests/executors/meta-tools.test.ts +0 -411
- package/tests/executors/meta.test.ts +0 -683
- package/tests/executors/path-containment.test.ts +0 -51
- package/tests/executors/process-registry.test.ts +0 -505
- package/tests/executors/pty.test.ts +0 -664
- package/tests/executors/quest-security.test.ts +0 -249
- package/tests/executors/read-file-media.test.ts +0 -230
- package/tests/executors/recall-knowledge-schema.test.ts +0 -209
- package/tests/executors/recall-tags.test.ts +0 -278
- package/tests/executors/remember-null-safety.contract.test.ts +0 -41
- package/tests/executors/restart.test.ts +0 -67
- package/tests/executors/search-unified.test.ts +0 -381
- package/tests/executors/session-history.test.ts +0 -340
- package/tests/executors/session-transcript.test.ts +0 -561
- package/tests/executors/shell-abort.test.ts +0 -416
- package/tests/executors/shell-env-blocklist.test.ts +0 -648
- package/tests/executors/shell-env-process.test.ts +0 -245
- package/tests/executors/shell-process-registry.test.ts +0 -334
- package/tests/executors/shell-tools.test.ts +0 -393
- package/tests/executors/shell.test.ts +0 -690
- package/tests/executors/web-abort-vs-timeout.test.ts +0 -213
- package/tests/executors/web-integration.test.ts +0 -633
- package/tests/executors/web-symlink.test.ts +0 -18
- package/tests/executors/web.test.ts +0 -1400
- package/tests/executors/write-stdin.test.ts +0 -145
- package/tests/extraction/content-extraction.test.ts +0 -153
- package/tests/guards/tools-default-test-lane.integration.test.ts +0 -21
- package/tests/guards/tools-package-test-commands.e2e.test.ts +0 -43
- package/tests/guards/tools-test-lane-manifest.contract.test.ts +0 -76
- package/tests/guards/tools-vitest-workspace-alias.contract.test.ts +0 -63
- package/tests/helpers/async-waits.ts +0 -53
- package/tests/integration/headless-control-contract.integration.test.ts +0 -153
- package/tests/integration/memory-tool-schema-parity.integration.test.ts +0 -67
- package/tests/integration/meta-tools-round-trip.integration.test.ts +0 -506
- package/tests/integration/quest-round-trip.test.ts +0 -303
- package/tests/integration/registry-executor-flow.test.ts +0 -85
- package/tests/integration.test.ts +0 -177
- package/tests/loading-tier.test.ts +0 -126
- package/tests/mcp/client-reconnect.test.ts +0 -267
- package/tests/mcp/connection.test.ts +0 -846
- package/tests/mcp/injectable-logger.test.ts +0 -83
- package/tests/mcp/jsonrpc.test.ts +0 -109
- package/tests/mcp/lifecycle.test.ts +0 -879
- package/tests/network-runtime/address-types.contract.test.ts +0 -143
- package/tests/network-runtime/continuity-bind-schema.contract.test.ts +0 -203
- package/tests/network-runtime/local-control-contract.test.ts +0 -869
- package/tests/network-runtime/local-control-invite-token.contract.test.ts +0 -146
- package/tests/network-runtime/node-store-contract.test.ts +0 -11
- package/tests/network-runtime/pair-protocol-nodeid.contract.test.ts +0 -15
- package/tests/network-runtime/peer-state-machine.contract.test.ts +0 -148
- package/tests/network-runtime/protocol-schemas.contract.test.ts +0 -512
- package/tests/network-runtime/relay-pending-nodeid.contract.test.ts +0 -62
- package/tests/network-runtime/runtime-bootstrap-contract.test.ts +0 -227
- package/tests/network-runtime/runtime-socket-local-control-client.test.ts +0 -621
- package/tests/network-runtime/wait-for-message-script.test.ts +0 -288
- package/tests/parallel.test.ts +0 -71
- package/tests/policy.test.ts +0 -184
- package/tests/print-default-test-lane.ts +0 -14
- package/tests/print-test-lane-manifest.ts +0 -22
- package/tests/providers/brave.test.ts +0 -159
- package/tests/providers/duckduckgo.test.ts +0 -207
- package/tests/providers/exa.test.ts +0 -175
- package/tests/providers/firecrawl.test.ts +0 -168
- package/tests/providers/jina.test.ts +0 -144
- package/tests/providers/router.test.ts +0 -328
- package/tests/providers/tavily.test.ts +0 -165
- package/tests/registry/discovery.test.ts +0 -154
- package/tests/registry/injectable-logger.test.ts +0 -230
- package/tests/registry/input-validation.test.ts +0 -361
- package/tests/registry/interface-completeness.test.ts +0 -85
- package/tests/registry/mcp-integration.test.ts +0 -103
- package/tests/registry/mcp-read-only-hint.test.ts +0 -60
- package/tests/registry/memoria-discovery.test.ts +0 -390
- package/tests/registry/nested-validation.test.ts +0 -283
- package/tests/registry/pseudo-tool-filtering.test.ts +0 -258
- package/tests/registry/registration-lifecycle.test.ts +0 -133
- package/tests/registry-validation.test.ts +0 -424
- package/tests/registry.test.ts +0 -460
- package/tests/security/dns-pinning.test.ts +0 -162
- package/tests/security/external-content.test.ts +0 -144
- package/tests/security/ssrf.test.ts +0 -118
- package/tests/shell-safety-integration.test.ts +0 -32
- package/tests/shell-safety.test.ts +0 -365
- package/tests/slack/desktop-session.test.ts +0 -50
- package/tests/test-lane-manifest.ts +0 -440
- package/tests/test-utils.ts +0 -27
- package/tests/tool-factory.test.ts +0 -188
- package/tests/utils/retry.test.ts +0 -231
- package/tests/utils/url.test.ts +0 -63
- package/tsconfig.cjs.json +0 -24
- package/tsconfig.json +0 -12
- package/vitest.config.ts +0 -55
- package/vitest.e2e.config.ts +0 -24
- package/vitest.integration.config.ts +0 -24
- package/vitest.native.config.ts +0 -24
|
@@ -1,552 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @aria/tools - Self-diagnose tool executor
|
|
3
|
-
*
|
|
4
|
-
* Pure signal diagnostic tool. 5 sections, zero noise:
|
|
5
|
-
* 1. runtime — process health + resource leaks
|
|
6
|
-
* 2. errors — structured errors from JSONL (active + rotated)
|
|
7
|
-
* 3. crashes — crash markers + dumps
|
|
8
|
-
* 4. databases — sizes, WAL health, schema version
|
|
9
|
-
* 5. daemon — daemon audit + delegation journal
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import * as fs from "node:fs/promises";
|
|
13
|
-
import * as path from "node:path";
|
|
14
|
-
import * as os from "node:os";
|
|
15
|
-
import type { ToolContext, ToolResult } from "../types.js";
|
|
16
|
-
import { success, fail } from "./utils.js";
|
|
17
|
-
|
|
18
|
-
// ============================================================================
|
|
19
|
-
// Types
|
|
20
|
-
// ============================================================================
|
|
21
|
-
|
|
22
|
-
export interface SelfDiagnoseInput {
|
|
23
|
-
focus?: string;
|
|
24
|
-
sections?: string[];
|
|
25
|
-
since?: string;
|
|
26
|
-
limit?: number;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface RuntimeInfo {
|
|
30
|
-
pid: number;
|
|
31
|
-
uptime_s: number;
|
|
32
|
-
heap_mb: number;
|
|
33
|
-
rss_mb: number;
|
|
34
|
-
node_version: string;
|
|
35
|
-
platform: string;
|
|
36
|
-
arch: string;
|
|
37
|
-
cwd: string;
|
|
38
|
-
session_id: string | null;
|
|
39
|
-
socket_dirs: number;
|
|
40
|
-
owner_files: number;
|
|
41
|
-
relaunch_pending: boolean;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface ErrorEntry {
|
|
45
|
-
timestamp: string;
|
|
46
|
-
severity: string;
|
|
47
|
-
category: string;
|
|
48
|
-
message: string;
|
|
49
|
-
stackTrace: string;
|
|
50
|
-
source: string;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface CrashInfo {
|
|
54
|
-
file: string;
|
|
55
|
-
size?: number;
|
|
56
|
-
timestamp?: string;
|
|
57
|
-
error_message?: string;
|
|
58
|
-
content?: Record<string, unknown>;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface DbInfo {
|
|
62
|
-
name: string;
|
|
63
|
-
size_mb: string;
|
|
64
|
-
wal_mb: string | null;
|
|
65
|
-
modified: string;
|
|
66
|
-
schema_version?: number;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface DaemonEntry {
|
|
70
|
-
source: string;
|
|
71
|
-
entries: unknown[];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export interface NetworkInfo {
|
|
75
|
-
node_id: string | null;
|
|
76
|
-
display_name: string | null;
|
|
77
|
-
listen_port: number | null;
|
|
78
|
-
external_endpoint: string | null;
|
|
79
|
-
peer_count: number;
|
|
80
|
-
peers: Array<{
|
|
81
|
-
node_id: string;
|
|
82
|
-
name: string;
|
|
83
|
-
status: string;
|
|
84
|
-
last_seen: string | null;
|
|
85
|
-
}>;
|
|
86
|
-
tls_certs_present: boolean;
|
|
87
|
-
trusted_cas: number;
|
|
88
|
-
recent_tunnel_events: unknown[];
|
|
89
|
-
recent_diagnostics: unknown[];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export interface SelfDiagnoseOutput {
|
|
93
|
-
runtime: RuntimeInfo | null;
|
|
94
|
-
errors: ErrorEntry[] | null;
|
|
95
|
-
crashes: CrashInfo[] | null;
|
|
96
|
-
databases: DbInfo[] | null;
|
|
97
|
-
daemon: DaemonEntry[] | null;
|
|
98
|
-
network: NetworkInfo | null;
|
|
99
|
-
_meta: {
|
|
100
|
-
sections_requested: string[];
|
|
101
|
-
sections_returned: string[];
|
|
102
|
-
elapsed_ms: number;
|
|
103
|
-
errors: string[];
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// ============================================================================
|
|
108
|
-
// Constants
|
|
109
|
-
// ============================================================================
|
|
110
|
-
|
|
111
|
-
const ALL_SECTIONS = ["runtime", "errors", "crashes", "databases", "daemon", "network"];
|
|
112
|
-
const ARIA_HOME = path.join(os.homedir(), ".aria");
|
|
113
|
-
|
|
114
|
-
// ============================================================================
|
|
115
|
-
// Helpers
|
|
116
|
-
// ============================================================================
|
|
117
|
-
|
|
118
|
-
async function safeStat(p: string): Promise<{ size: number; mtime: Date } | null> {
|
|
119
|
-
try {
|
|
120
|
-
const s = await fs.stat(p);
|
|
121
|
-
return { size: s.size, mtime: s.mtime };
|
|
122
|
-
} catch {
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function truncate(s: string | undefined | null, max: number): string {
|
|
128
|
-
if (!s) return "";
|
|
129
|
-
return s.length <= max ? s : s.slice(0, max - 3) + "...";
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async function dirCount(dir: string): Promise<number> {
|
|
133
|
-
try {
|
|
134
|
-
const entries = await fs.readdir(dir);
|
|
135
|
-
return entries.length;
|
|
136
|
-
} catch {
|
|
137
|
-
return 0;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async function tailJsonl(filePath: string, maxLines: number): Promise<unknown[]> {
|
|
142
|
-
try {
|
|
143
|
-
const content = await fs.readFile(filePath, "utf-8");
|
|
144
|
-
const lines = content.trim().split("\n").slice(-maxLines);
|
|
145
|
-
return lines
|
|
146
|
-
.map((l) => {
|
|
147
|
-
try {
|
|
148
|
-
return JSON.parse(l);
|
|
149
|
-
} catch {
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
152
|
-
})
|
|
153
|
-
.filter(Boolean);
|
|
154
|
-
} catch {
|
|
155
|
-
return [];
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// ============================================================================
|
|
160
|
-
// Section: runtime
|
|
161
|
-
// ============================================================================
|
|
162
|
-
|
|
163
|
-
async function getRuntime(ctx: ToolContext): Promise<RuntimeInfo> {
|
|
164
|
-
const mem = process.memoryUsage();
|
|
165
|
-
|
|
166
|
-
// Resource leak detection
|
|
167
|
-
const socketDirs = await dirCount(path.join(ARIA_HOME, "sock"));
|
|
168
|
-
const ownerFiles = await dirCount(path.join(ARIA_HOME, "run/owners"));
|
|
169
|
-
|
|
170
|
-
// Stuck restart detection
|
|
171
|
-
let relaunchPending = false;
|
|
172
|
-
try {
|
|
173
|
-
const entries = await fs.readdir(path.join(ARIA_HOME, "relaunch-pending"));
|
|
174
|
-
relaunchPending = entries.length > 0;
|
|
175
|
-
} catch {
|
|
176
|
-
/* dir may not exist */
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return {
|
|
180
|
-
pid: process.pid,
|
|
181
|
-
uptime_s: Math.round(process.uptime()),
|
|
182
|
-
heap_mb: Math.round(mem.heapUsed / 1e6),
|
|
183
|
-
rss_mb: Math.round(mem.rss / 1e6),
|
|
184
|
-
node_version: process.version,
|
|
185
|
-
platform: process.platform,
|
|
186
|
-
arch: process.arch,
|
|
187
|
-
cwd: process.cwd(),
|
|
188
|
-
session_id: ctx.currentSessionId ?? null,
|
|
189
|
-
socket_dirs: socketDirs,
|
|
190
|
-
owner_files: ownerFiles,
|
|
191
|
-
relaunch_pending: relaunchPending,
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// ============================================================================
|
|
196
|
-
// Section: errors (active + rotated JSONL, merged, filtered)
|
|
197
|
-
// ============================================================================
|
|
198
|
-
|
|
199
|
-
async function getErrors(
|
|
200
|
-
since: Date,
|
|
201
|
-
focus: string | undefined,
|
|
202
|
-
limit: number,
|
|
203
|
-
): Promise<ErrorEntry[]> {
|
|
204
|
-
// Read both active and rotated logs
|
|
205
|
-
const active = path.join(ARIA_HOME, "error-events.jsonl");
|
|
206
|
-
const rotated = path.join(ARIA_HOME, "error-events.jsonl.1");
|
|
207
|
-
|
|
208
|
-
const [activeEntries, rotatedEntries] = await Promise.all([
|
|
209
|
-
tailJsonl(active, 200),
|
|
210
|
-
tailJsonl(rotated, 100),
|
|
211
|
-
]);
|
|
212
|
-
|
|
213
|
-
// Merge: rotated first (older), then active (newer)
|
|
214
|
-
type RawEntry = Record<string, unknown> & { _src: string };
|
|
215
|
-
const all: RawEntry[] = [
|
|
216
|
-
...rotatedEntries.map((e) => ({ ...(e as Record<string, unknown>), _src: "rotated" })),
|
|
217
|
-
...activeEntries.map((e) => ({ ...(e as Record<string, unknown>), _src: "active" })),
|
|
218
|
-
];
|
|
219
|
-
|
|
220
|
-
const filtered = all.filter((entry) => {
|
|
221
|
-
const ts = entry.timestamp as string | undefined;
|
|
222
|
-
if (ts) {
|
|
223
|
-
const d = new Date(ts);
|
|
224
|
-
if (d < since) return false;
|
|
225
|
-
}
|
|
226
|
-
if (focus) {
|
|
227
|
-
const haystack = [
|
|
228
|
-
String(entry.message ?? ""),
|
|
229
|
-
String(entry.category ?? ""),
|
|
230
|
-
String(entry.stackTrace ?? ""),
|
|
231
|
-
]
|
|
232
|
-
.join(" ")
|
|
233
|
-
.toLowerCase();
|
|
234
|
-
if (!haystack.includes(focus)) return false;
|
|
235
|
-
}
|
|
236
|
-
return true;
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
return filtered.slice(-limit).map((entry) => ({
|
|
240
|
-
timestamp: String(entry.timestamp ?? ""),
|
|
241
|
-
severity: String(entry.severity ?? "unknown"),
|
|
242
|
-
category: String(entry.category ?? ""),
|
|
243
|
-
message: String(entry.message ?? ""),
|
|
244
|
-
stackTrace: truncate(String(entry.stackTrace ?? ""), 500),
|
|
245
|
-
source: String(entry._src),
|
|
246
|
-
}));
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// ============================================================================
|
|
250
|
-
// Section: crashes
|
|
251
|
-
// ============================================================================
|
|
252
|
-
|
|
253
|
-
async function getCrashes(limit: number): Promise<CrashInfo[]> {
|
|
254
|
-
const results: CrashInfo[] = [];
|
|
255
|
-
|
|
256
|
-
for (const subdir of ["crash-markers", "crash-dumps"]) {
|
|
257
|
-
const dir = path.join(ARIA_HOME, subdir);
|
|
258
|
-
try {
|
|
259
|
-
const files = await fs.readdir(dir);
|
|
260
|
-
const jsonFiles = files.filter((f) => f.endsWith(".json"));
|
|
261
|
-
const stats = await Promise.all(
|
|
262
|
-
jsonFiles.map(async (f) => {
|
|
263
|
-
const p = path.join(dir, f);
|
|
264
|
-
const s = await safeStat(p);
|
|
265
|
-
return { file: f, path: p, stat: s };
|
|
266
|
-
}),
|
|
267
|
-
);
|
|
268
|
-
const sorted = stats
|
|
269
|
-
.filter((f) => f.stat)
|
|
270
|
-
.sort((a, b) => b.stat!.mtime.getTime() - a.stat!.mtime.getTime());
|
|
271
|
-
|
|
272
|
-
for (const { file, path: fp, stat } of sorted.slice(0, limit)) {
|
|
273
|
-
try {
|
|
274
|
-
const raw = await fs.readFile(fp, "utf-8");
|
|
275
|
-
const parsed = JSON.parse(raw);
|
|
276
|
-
if (subdir === "crash-markers") {
|
|
277
|
-
results.push({
|
|
278
|
-
file: `${subdir}/${file}`,
|
|
279
|
-
timestamp: stat!.mtime.toISOString(),
|
|
280
|
-
content: parsed,
|
|
281
|
-
});
|
|
282
|
-
} else {
|
|
283
|
-
const msg = parsed.error_message ?? parsed.message ?? parsed.error ?? "";
|
|
284
|
-
results.push({
|
|
285
|
-
file: `${subdir}/${file}`,
|
|
286
|
-
size: stat!.size,
|
|
287
|
-
timestamp: stat!.mtime.toISOString(),
|
|
288
|
-
error_message: truncate(String(msg), 200),
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
} catch {
|
|
292
|
-
results.push({
|
|
293
|
-
file: `${subdir}/${file}`,
|
|
294
|
-
timestamp: stat!.mtime.toISOString(),
|
|
295
|
-
error_message: "Failed to parse",
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
} catch {
|
|
300
|
-
/* dir may not exist */
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return results;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// ============================================================================
|
|
308
|
-
// Section: databases (sizes, WAL health, schema version)
|
|
309
|
-
// ============================================================================
|
|
310
|
-
|
|
311
|
-
async function getDatabases(): Promise<DbInfo[]> {
|
|
312
|
-
const results: DbInfo[] = [];
|
|
313
|
-
|
|
314
|
-
// Key database paths (only real ones, not empty legacy ghosts)
|
|
315
|
-
const dbPaths: Array<{ name: string; path: string; checkSchema?: boolean }> = [
|
|
316
|
-
{
|
|
317
|
-
name: "memory.db (main)",
|
|
318
|
-
path: path.join(ARIA_HOME, "arions/ARIA/memory.db"),
|
|
319
|
-
checkSchema: true,
|
|
320
|
-
},
|
|
321
|
-
{ name: "history.db", path: path.join(ARIA_HOME, "history.db") },
|
|
322
|
-
{ name: "investigation-metrics.db", path: path.join(ARIA_HOME, "investigation-metrics.db") },
|
|
323
|
-
{ name: "network/state.db", path: path.join(ARIA_HOME, "network/state.db") },
|
|
324
|
-
{ name: "node/node-state.db", path: path.join(ARIA_HOME, "node/node-state.db") },
|
|
325
|
-
];
|
|
326
|
-
|
|
327
|
-
for (const db of dbPaths) {
|
|
328
|
-
const stat = await safeStat(db.path);
|
|
329
|
-
if (!stat || stat.size === 0) continue;
|
|
330
|
-
|
|
331
|
-
// WAL size — a large WAL means checkpoint isn't running
|
|
332
|
-
const walStat = await safeStat(db.path + "-wal");
|
|
333
|
-
const walMb = walStat && walStat.size > 0 ? (walStat.size / 1e6).toFixed(1) : null;
|
|
334
|
-
|
|
335
|
-
// Schema version for the main DB (lightweight: only reads one int)
|
|
336
|
-
let schemaVersion: number | undefined;
|
|
337
|
-
if (db.checkSchema) {
|
|
338
|
-
try {
|
|
339
|
-
// Use a child process to avoid importing better-sqlite3 / locking the DB
|
|
340
|
-
const { execFileSync } = await import("node:child_process");
|
|
341
|
-
const out = execFileSync("sqlite3", [db.path, "SELECT MAX(version) FROM schema_version;"], {
|
|
342
|
-
timeout: 1000,
|
|
343
|
-
encoding: "utf-8",
|
|
344
|
-
}).trim();
|
|
345
|
-
schemaVersion = parseInt(out, 10) || undefined;
|
|
346
|
-
} catch {
|
|
347
|
-
// sqlite3 CLI not available or query failed — not critical
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
const info: DbInfo = {
|
|
352
|
-
name: db.name,
|
|
353
|
-
size_mb: (stat.size / 1e6).toFixed(1),
|
|
354
|
-
wal_mb: walMb,
|
|
355
|
-
modified: stat.mtime.toISOString(),
|
|
356
|
-
};
|
|
357
|
-
if (schemaVersion !== undefined) info.schema_version = schemaVersion;
|
|
358
|
-
results.push(info);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
return results;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// ============================================================================
|
|
365
|
-
// Section: daemon (audit + delegation journal)
|
|
366
|
-
// ============================================================================
|
|
367
|
-
|
|
368
|
-
async function getDaemon(limit: number): Promise<DaemonEntry[]> {
|
|
369
|
-
const results: DaemonEntry[] = [];
|
|
370
|
-
|
|
371
|
-
// Daemon audit log — restart loops, crashes, startup events
|
|
372
|
-
const auditPath = path.join(ARIA_HOME, "arions/ARIA/daemon/audit.jsonl");
|
|
373
|
-
const auditEntries = await tailJsonl(auditPath, limit);
|
|
374
|
-
if (auditEntries.length > 0) {
|
|
375
|
-
results.push({ source: "daemon/audit", entries: auditEntries });
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// Delegation journal — worker spawn/complete/fail
|
|
379
|
-
const delegationPath = path.join(ARIA_HOME, "arions/ARIA/delegation-journal.jsonl");
|
|
380
|
-
const delegationEntries = await tailJsonl(delegationPath, limit);
|
|
381
|
-
if (delegationEntries.length > 0) {
|
|
382
|
-
results.push({ source: "delegation-journal", entries: delegationEntries });
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
return results;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// ============================================================================
|
|
389
|
-
// Section: network (identity, peers, tunnels, TLS, diagnostics)
|
|
390
|
-
// ============================================================================
|
|
391
|
-
|
|
392
|
-
async function getNetwork(limit: number): Promise<NetworkInfo> {
|
|
393
|
-
// Node identity from network/config.json
|
|
394
|
-
let nodeId: string | null = null;
|
|
395
|
-
let displayName: string | null = null;
|
|
396
|
-
let listenPort: number | null = null;
|
|
397
|
-
let externalEndpoint: string | null = null;
|
|
398
|
-
|
|
399
|
-
try {
|
|
400
|
-
const raw = await fs.readFile(path.join(ARIA_HOME, "network/config.json"), "utf-8");
|
|
401
|
-
const cfg = JSON.parse(raw);
|
|
402
|
-
nodeId = cfg.nodeId ?? null;
|
|
403
|
-
displayName = cfg.localDisplayNameSnapshot ?? null;
|
|
404
|
-
listenPort = cfg.listenPort ?? null;
|
|
405
|
-
if (cfg.externalEndpoint) {
|
|
406
|
-
externalEndpoint = `${cfg.externalEndpoint.address}:${cfg.externalEndpoint.port}`;
|
|
407
|
-
}
|
|
408
|
-
// Never expose private keys — only the fact we have them
|
|
409
|
-
} catch {
|
|
410
|
-
/* config may not exist */
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Peers from network/state.db (using sqlite3 CLI to avoid locking)
|
|
414
|
-
const peers: NetworkInfo["peers"] = [];
|
|
415
|
-
let peerCount = 0;
|
|
416
|
-
try {
|
|
417
|
-
const { execFileSync } = await import("node:child_process");
|
|
418
|
-
const out = execFileSync(
|
|
419
|
-
"sqlite3",
|
|
420
|
-
[
|
|
421
|
-
path.join(ARIA_HOME, "network/state.db"),
|
|
422
|
-
"-json",
|
|
423
|
-
`SELECT nodeId, displayName, status, lastSeen FROM network_peers ORDER BY lastSeen DESC LIMIT ${limit};`,
|
|
424
|
-
],
|
|
425
|
-
{ timeout: 1000, encoding: "utf-8" },
|
|
426
|
-
).trim();
|
|
427
|
-
if (out) {
|
|
428
|
-
const rows = JSON.parse(out);
|
|
429
|
-
for (const row of rows) {
|
|
430
|
-
peers.push({
|
|
431
|
-
node_id: row.nodeId ?? "",
|
|
432
|
-
name: row.displayName ?? "",
|
|
433
|
-
status: row.status ?? "unknown",
|
|
434
|
-
last_seen: row.lastSeen ? new Date(row.lastSeen).toISOString() : null,
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
const countOut = execFileSync(
|
|
439
|
-
"sqlite3",
|
|
440
|
-
[path.join(ARIA_HOME, "network/state.db"), "SELECT COUNT(*) FROM network_peers;"],
|
|
441
|
-
{ timeout: 1000, encoding: "utf-8" },
|
|
442
|
-
).trim();
|
|
443
|
-
peerCount = parseInt(countOut, 10) || 0;
|
|
444
|
-
} catch {
|
|
445
|
-
/* sqlite3 CLI not available or query failed */
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
// TLS state
|
|
449
|
-
let tlsCertsPresent = false;
|
|
450
|
-
let trustedCas = 0;
|
|
451
|
-
try {
|
|
452
|
-
await fs.access(path.join(ARIA_HOME, "network/tls/server.pem"));
|
|
453
|
-
tlsCertsPresent = true;
|
|
454
|
-
} catch {
|
|
455
|
-
/* no TLS certs */
|
|
456
|
-
}
|
|
457
|
-
try {
|
|
458
|
-
const cas = await fs.readdir(path.join(ARIA_HOME, "network/trusted-cas"));
|
|
459
|
-
trustedCas = cas.filter((f) => f.endsWith(".pem")).length;
|
|
460
|
-
} catch {
|
|
461
|
-
/* dir may not exist */
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
// Recent tunnel events (connection attempts, handshakes, failures)
|
|
465
|
-
const tunnelEvents = await tailJsonl(
|
|
466
|
-
path.join(ARIA_HOME, "audit/wireguard-secure-tunnel.jsonl"),
|
|
467
|
-
limit,
|
|
468
|
-
);
|
|
469
|
-
|
|
470
|
-
// Recent diagnostics (disconnects, reconnects, errors)
|
|
471
|
-
const diagnostics = await tailJsonl(
|
|
472
|
-
path.join(ARIA_HOME, "audit/wireguard-diagnostics.jsonl"),
|
|
473
|
-
limit,
|
|
474
|
-
);
|
|
475
|
-
|
|
476
|
-
return {
|
|
477
|
-
node_id: nodeId,
|
|
478
|
-
display_name: displayName,
|
|
479
|
-
listen_port: listenPort,
|
|
480
|
-
external_endpoint: externalEndpoint,
|
|
481
|
-
peer_count: peerCount,
|
|
482
|
-
peers,
|
|
483
|
-
tls_certs_present: tlsCertsPresent,
|
|
484
|
-
trusted_cas: trustedCas,
|
|
485
|
-
recent_tunnel_events: tunnelEvents,
|
|
486
|
-
recent_diagnostics: diagnostics,
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
// ============================================================================
|
|
491
|
-
// Main Executor
|
|
492
|
-
// ============================================================================
|
|
493
|
-
|
|
494
|
-
export async function executeSelfDiagnose(
|
|
495
|
-
input: SelfDiagnoseInput,
|
|
496
|
-
ctx: ToolContext,
|
|
497
|
-
): Promise<ToolResult> {
|
|
498
|
-
if (ctx.abortSignal?.aborted) return fail("Operation cancelled");
|
|
499
|
-
|
|
500
|
-
const startMs = Date.now();
|
|
501
|
-
const limit = input.limit ?? 10;
|
|
502
|
-
const since = input.since ? new Date(input.since) : new Date(Date.now() - 3600_000);
|
|
503
|
-
const focus = input.focus?.toLowerCase();
|
|
504
|
-
const requested = input.sections ?? ALL_SECTIONS;
|
|
505
|
-
const sectionsToRun = requested.filter((s) => ALL_SECTIONS.includes(s));
|
|
506
|
-
|
|
507
|
-
const sectionFns: Record<string, () => Promise<unknown>> = {
|
|
508
|
-
runtime: () => getRuntime(ctx),
|
|
509
|
-
errors: () => getErrors(since, focus, limit),
|
|
510
|
-
crashes: () => getCrashes(limit),
|
|
511
|
-
databases: () => getDatabases(),
|
|
512
|
-
daemon: () => getDaemon(limit),
|
|
513
|
-
network: () => getNetwork(limit),
|
|
514
|
-
};
|
|
515
|
-
|
|
516
|
-
const results: Record<string, unknown> = {};
|
|
517
|
-
const errors: string[] = [];
|
|
518
|
-
const returned: string[] = [];
|
|
519
|
-
|
|
520
|
-
const withTimeout = (fn: () => Promise<unknown>, name: string) =>
|
|
521
|
-
Promise.race([
|
|
522
|
-
fn().then((r) => {
|
|
523
|
-
returned.push(name);
|
|
524
|
-
return r;
|
|
525
|
-
}),
|
|
526
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error(`${name} timed out`)), 2000)),
|
|
527
|
-
]).catch((err) => {
|
|
528
|
-
errors.push(`${name}: ${err.message}`);
|
|
529
|
-
return null;
|
|
530
|
-
});
|
|
531
|
-
|
|
532
|
-
await Promise.all(
|
|
533
|
-
sectionsToRun.map(async (name) => {
|
|
534
|
-
const fn = sectionFns[name];
|
|
535
|
-
if (fn) results[name] = await withTimeout(fn, name);
|
|
536
|
-
}),
|
|
537
|
-
);
|
|
538
|
-
|
|
539
|
-
const elapsed = Date.now() - startMs;
|
|
540
|
-
results._meta = {
|
|
541
|
-
sections_requested: sectionsToRun,
|
|
542
|
-
sections_returned: returned,
|
|
543
|
-
elapsed_ms: elapsed,
|
|
544
|
-
errors,
|
|
545
|
-
};
|
|
546
|
-
|
|
547
|
-
const msg =
|
|
548
|
-
`Diagnostics: ${returned.length}/${sectionsToRun.length} sections in ${elapsed}ms` +
|
|
549
|
-
(errors.length > 0 ? ` (${errors.length} errors)` : "");
|
|
550
|
-
|
|
551
|
-
return success(msg, results as unknown as SelfDiagnoseOutput);
|
|
552
|
-
}
|