awb-agent-manager 1.0.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 +21 -0
- package/README.md +246 -0
- package/dist/lib/agent-lockfile.d.ts +37 -0
- package/dist/lib/agent-lockfile.js +205 -0
- package/dist/lib/agent-lockfile.js.map +1 -0
- package/dist/lib/agent-manager-commands.d.ts +34 -0
- package/dist/lib/agent-manager-commands.js +531 -0
- package/dist/lib/agent-manager-commands.js.map +1 -0
- package/dist/lib/base-session-manager.d.ts +127 -0
- package/dist/lib/base-session-manager.js +667 -0
- package/dist/lib/base-session-manager.js.map +1 -0
- package/dist/lib/chat-attachment-prep.d.ts +35 -0
- package/dist/lib/chat-attachment-prep.js +180 -0
- package/dist/lib/chat-attachment-prep.js.map +1 -0
- package/dist/lib/chat-session-manager.d.ts +29 -0
- package/dist/lib/chat-session-manager.js +400 -0
- package/dist/lib/chat-session-manager.js.map +1 -0
- package/dist/lib/circuit-breaker.d.ts +34 -0
- package/dist/lib/circuit-breaker.js +146 -0
- package/dist/lib/circuit-breaker.js.map +1 -0
- package/dist/lib/cli-adapters/antigravity.d.ts +15 -0
- package/dist/lib/cli-adapters/antigravity.js +114 -0
- package/dist/lib/cli-adapters/antigravity.js.map +1 -0
- package/dist/lib/cli-adapters/base.d.ts +115 -0
- package/dist/lib/cli-adapters/base.js +111 -0
- package/dist/lib/cli-adapters/base.js.map +1 -0
- package/dist/lib/cli-adapters/claude.d.ts +19 -0
- package/dist/lib/cli-adapters/claude.js +233 -0
- package/dist/lib/cli-adapters/claude.js.map +1 -0
- package/dist/lib/cli-adapters/codex.d.ts +14 -0
- package/dist/lib/cli-adapters/codex.js +152 -0
- package/dist/lib/cli-adapters/codex.js.map +1 -0
- package/dist/lib/cli-adapters/deepseek.d.ts +15 -0
- package/dist/lib/cli-adapters/deepseek.js +70 -0
- package/dist/lib/cli-adapters/deepseek.js.map +1 -0
- package/dist/lib/cli-adapters/index.d.ts +8 -0
- package/dist/lib/cli-adapters/index.js +27 -0
- package/dist/lib/cli-adapters/index.js.map +1 -0
- package/dist/lib/cli-adapters/model-introspect.d.ts +3 -0
- package/dist/lib/cli-adapters/model-introspect.js +65 -0
- package/dist/lib/cli-adapters/model-introspect.js.map +1 -0
- package/dist/lib/cli-error-signatures.d.ts +9 -0
- package/dist/lib/cli-error-signatures.js +22 -0
- package/dist/lib/cli-error-signatures.js.map +1 -0
- package/dist/lib/cli-output-summary.d.ts +2 -0
- package/dist/lib/cli-output-summary.js +104 -0
- package/dist/lib/cli-output-summary.js.map +1 -0
- package/dist/lib/cli-resolver.d.ts +2 -0
- package/dist/lib/cli-resolver.js +177 -0
- package/dist/lib/cli-resolver.js.map +1 -0
- package/dist/lib/config.d.ts +13 -0
- package/dist/lib/config.js +124 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +36 -0
- package/dist/lib/constants.js +51 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/environment-provisioner.d.ts +31 -0
- package/dist/lib/environment-provisioner.js +182 -0
- package/dist/lib/environment-provisioner.js.map +1 -0
- package/dist/lib/error-log-uploader.d.ts +19 -0
- package/dist/lib/error-log-uploader.js +138 -0
- package/dist/lib/error-log-uploader.js.map +1 -0
- package/dist/lib/event-dispatcher.d.ts +149 -0
- package/dist/lib/event-dispatcher.js +799 -0
- package/dist/lib/event-dispatcher.js.map +1 -0
- package/dist/lib/event-log-recorder.d.ts +11 -0
- package/dist/lib/event-log-recorder.js +77 -0
- package/dist/lib/event-log-recorder.js.map +1 -0
- package/dist/lib/event-stream.d.ts +26 -0
- package/dist/lib/event-stream.js +177 -0
- package/dist/lib/event-stream.js.map +1 -0
- package/dist/lib/fs-browser.d.ts +30 -0
- package/dist/lib/fs-browser.js +287 -0
- package/dist/lib/fs-browser.js.map +1 -0
- package/dist/lib/host-mcp/logs.d.ts +19 -0
- package/dist/lib/host-mcp/logs.js +102 -0
- package/dist/lib/host-mcp/logs.js.map +1 -0
- package/dist/lib/host-mcp/platform.d.ts +24 -0
- package/dist/lib/host-mcp/platform.js +133 -0
- package/dist/lib/host-mcp/platform.js.map +1 -0
- package/dist/lib/host-mcp/screens.d.ts +22 -0
- package/dist/lib/host-mcp/screens.js +172 -0
- package/dist/lib/host-mcp/screens.js.map +1 -0
- package/dist/lib/host-mcp/server.d.ts +3 -0
- package/dist/lib/host-mcp/server.js +233 -0
- package/dist/lib/host-mcp/server.js.map +1 -0
- package/dist/lib/host-mcp/tools.d.ts +172 -0
- package/dist/lib/host-mcp/tools.js +1241 -0
- package/dist/lib/host-mcp/tools.js.map +1 -0
- package/dist/lib/instance-heartbeat.d.ts +55 -0
- package/dist/lib/instance-heartbeat.js +118 -0
- package/dist/lib/instance-heartbeat.js.map +1 -0
- package/dist/lib/legacy-import.d.ts +17 -0
- package/dist/lib/legacy-import.js +70 -0
- package/dist/lib/legacy-import.js.map +1 -0
- package/dist/lib/logging.d.ts +3 -0
- package/dist/lib/logging.js +65 -0
- package/dist/lib/logging.js.map +1 -0
- package/dist/lib/managed-agent-context.d.ts +25 -0
- package/dist/lib/managed-agent-context.js +33 -0
- package/dist/lib/managed-agent-context.js.map +1 -0
- package/dist/lib/managed-agent-store.d.ts +34 -0
- package/dist/lib/managed-agent-store.js +160 -0
- package/dist/lib/managed-agent-store.js.map +1 -0
- package/dist/lib/managed-agents.d.ts +24 -0
- package/dist/lib/managed-agents.js +87 -0
- package/dist/lib/managed-agents.js.map +1 -0
- package/dist/lib/mcp-client.d.ts +8 -0
- package/dist/lib/mcp-client.js +122 -0
- package/dist/lib/mcp-client.js.map +1 -0
- package/dist/lib/orphan-cleanup.d.ts +6 -0
- package/dist/lib/orphan-cleanup.js +108 -0
- package/dist/lib/orphan-cleanup.js.map +1 -0
- package/dist/lib/presence-heartbeat.d.ts +8 -0
- package/dist/lib/presence-heartbeat.js +61 -0
- package/dist/lib/presence-heartbeat.js.map +1 -0
- package/dist/lib/prompts.d.ts +29 -0
- package/dist/lib/prompts.js +208 -0
- package/dist/lib/prompts.js.map +1 -0
- package/dist/lib/rest.d.ts +61 -0
- package/dist/lib/rest.js +307 -0
- package/dist/lib/rest.js.map +1 -0
- package/dist/lib/run-provisioner.d.ts +21 -0
- package/dist/lib/run-provisioner.js +115 -0
- package/dist/lib/run-provisioner.js.map +1 -0
- package/dist/lib/self-path.d.ts +7 -0
- package/dist/lib/self-path.js +29 -0
- package/dist/lib/self-path.js.map +1 -0
- package/dist/lib/self-update.d.ts +46 -0
- package/dist/lib/self-update.js +482 -0
- package/dist/lib/self-update.js.map +1 -0
- package/dist/lib/service-install.d.ts +23 -0
- package/dist/lib/service-install.js +673 -0
- package/dist/lib/service-install.js.map +1 -0
- package/dist/lib/setup.d.ts +16 -0
- package/dist/lib/setup.js +157 -0
- package/dist/lib/setup.js.map +1 -0
- package/dist/lib/subagent-manager.d.ts +84 -0
- package/dist/lib/subagent-manager.js +793 -0
- package/dist/lib/subagent-manager.js.map +1 -0
- package/dist/lib/subagent-monitor.d.ts +43 -0
- package/dist/lib/subagent-monitor.js +229 -0
- package/dist/lib/subagent-monitor.js.map +1 -0
- package/dist/lib/ticket-session-manager.d.ts +23 -0
- package/dist/lib/ticket-session-manager.js +471 -0
- package/dist/lib/ticket-session-manager.js.map +1 -0
- package/dist/lib/worktree-manager.d.ts +39 -0
- package/dist/lib/worktree-manager.js +226 -0
- package/dist/lib/worktree-manager.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +670 -0
- package/dist/main.js.map +1 -0
- package/dist/package.json +57 -0
- package/package.json +57 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { promises as fsp } from 'node:fs';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { MANAGED_AGENTS_DIR } from './constants.js';
|
|
5
|
+
import { resolveSelfCommand } from './self-path.js';
|
|
6
|
+
export function managedAgentDir(agentId) {
|
|
7
|
+
return join(MANAGED_AGENTS_DIR, agentId);
|
|
8
|
+
}
|
|
9
|
+
export function configPathFor(agentId) {
|
|
10
|
+
return join(managedAgentDir(agentId), 'config.json');
|
|
11
|
+
}
|
|
12
|
+
export function apiKeyPathFor(agentId) {
|
|
13
|
+
return join(managedAgentDir(agentId), 'apikey');
|
|
14
|
+
}
|
|
15
|
+
export function mcpConfigPathFor(agentId) {
|
|
16
|
+
return join(managedAgentDir(agentId), 'mcp-config.json');
|
|
17
|
+
}
|
|
18
|
+
export function credentialPathFor(agentId) {
|
|
19
|
+
return join(managedAgentDir(agentId), 'credential.json');
|
|
20
|
+
}
|
|
21
|
+
export async function readAgentCredential(agentId) {
|
|
22
|
+
const path = credentialPathFor(agentId);
|
|
23
|
+
if (!existsSync(path))
|
|
24
|
+
return null;
|
|
25
|
+
try {
|
|
26
|
+
const raw = JSON.parse(readFileSync(path, 'utf8'));
|
|
27
|
+
if (!raw || typeof raw !== 'object')
|
|
28
|
+
return null;
|
|
29
|
+
if (typeof raw.provider !== 'string' || !raw.provider)
|
|
30
|
+
return null;
|
|
31
|
+
return {
|
|
32
|
+
credential_id: typeof raw.credential_id === 'string' ? raw.credential_id : '',
|
|
33
|
+
provider: raw.provider,
|
|
34
|
+
fields: raw.fields && typeof raw.fields === 'object' ? raw.fields : {},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export async function writeAgentCredential(agentId, credential) {
|
|
42
|
+
await ensureManagedAgentDir(agentId);
|
|
43
|
+
await fsp.writeFile(credentialPathFor(agentId), JSON.stringify(credential, null, 2), { mode: 0o600 });
|
|
44
|
+
}
|
|
45
|
+
export async function eraseAgentCredential(agentId) {
|
|
46
|
+
await fsp.unlink(credentialPathFor(agentId)).catch(() => undefined);
|
|
47
|
+
}
|
|
48
|
+
export function subagentLogPathFor(agentId) {
|
|
49
|
+
return join(managedAgentDir(agentId), 'subagent.log');
|
|
50
|
+
}
|
|
51
|
+
export function cliHomeDirFor(agentId) {
|
|
52
|
+
return join(managedAgentDir(agentId), 'cli-home');
|
|
53
|
+
}
|
|
54
|
+
export async function ensureCliHomeDir(agentId) {
|
|
55
|
+
const dir = cliHomeDirFor(agentId);
|
|
56
|
+
await fsp.mkdir(dir, { recursive: true, mode: 0o700 });
|
|
57
|
+
return dir;
|
|
58
|
+
}
|
|
59
|
+
export async function ensureManagedAgentDir(agentId) {
|
|
60
|
+
const dir = managedAgentDir(agentId);
|
|
61
|
+
await fsp.mkdir(dir, { recursive: true, mode: 0o700 });
|
|
62
|
+
return dir;
|
|
63
|
+
}
|
|
64
|
+
export async function readManagedAgentConfig(agentId) {
|
|
65
|
+
const path = configPathFor(agentId);
|
|
66
|
+
if (!existsSync(path))
|
|
67
|
+
return null;
|
|
68
|
+
try {
|
|
69
|
+
const raw = JSON.parse(readFileSync(path, 'utf8'));
|
|
70
|
+
if (raw && typeof raw === 'object' && raw.agent_id === agentId) {
|
|
71
|
+
return raw;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
export async function writeManagedAgentConfig(cfg) {
|
|
79
|
+
await ensureManagedAgentDir(cfg.agent_id);
|
|
80
|
+
await fsp.writeFile(configPathFor(cfg.agent_id), JSON.stringify(cfg, null, 2), { mode: 0o600 });
|
|
81
|
+
}
|
|
82
|
+
export async function readApiKey(agentId) {
|
|
83
|
+
const path = apiKeyPathFor(agentId);
|
|
84
|
+
if (!existsSync(path))
|
|
85
|
+
return null;
|
|
86
|
+
try {
|
|
87
|
+
const raw = readFileSync(path, 'utf8').trim();
|
|
88
|
+
return raw || null;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export async function writeApiKey(agentId, raw) {
|
|
95
|
+
await ensureManagedAgentDir(agentId);
|
|
96
|
+
await fsp.writeFile(apiKeyPathFor(agentId), raw, { mode: 0o600 });
|
|
97
|
+
}
|
|
98
|
+
export async function writeMcpConfig(agentId, awbUrl, rawApiKey) {
|
|
99
|
+
await ensureManagedAgentDir(agentId);
|
|
100
|
+
const path = mcpConfigPathFor(agentId);
|
|
101
|
+
const self = resolveSelfCommand();
|
|
102
|
+
const body = {
|
|
103
|
+
mcpServers: {
|
|
104
|
+
awb: {
|
|
105
|
+
type: 'http',
|
|
106
|
+
url: `${awbUrl.replace(/\/$/, '')}/mcp`,
|
|
107
|
+
headers: {
|
|
108
|
+
Authorization: `Bearer ${rawApiKey}`,
|
|
109
|
+
'X-AWB-Client-Type': 'managed-subagent',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
host: {
|
|
113
|
+
type: 'stdio',
|
|
114
|
+
command: self.command,
|
|
115
|
+
args: [...self.prefixArgs, 'mcp-host'],
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
await fsp.writeFile(path, JSON.stringify(body, null, 2), { mode: 0o600 });
|
|
120
|
+
return path;
|
|
121
|
+
}
|
|
122
|
+
export async function eraseSecrets(agentId) {
|
|
123
|
+
await Promise.allSettled([
|
|
124
|
+
fsp.unlink(apiKeyPathFor(agentId)),
|
|
125
|
+
fsp.unlink(mcpConfigPathFor(agentId)),
|
|
126
|
+
fsp.unlink(credentialPathFor(agentId)),
|
|
127
|
+
]);
|
|
128
|
+
}
|
|
129
|
+
export function maskKey(raw) {
|
|
130
|
+
if (!raw)
|
|
131
|
+
return '';
|
|
132
|
+
if (raw.length <= 12)
|
|
133
|
+
return raw.slice(0, 4) + '***';
|
|
134
|
+
return raw.slice(0, 8) + '***' + raw.slice(-4);
|
|
135
|
+
}
|
|
136
|
+
export async function listManagedAgentDirs() {
|
|
137
|
+
let entries;
|
|
138
|
+
try {
|
|
139
|
+
entries = await fsp.readdir(MANAGED_AGENTS_DIR);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
const out = [];
|
|
145
|
+
for (const name of entries) {
|
|
146
|
+
const full = join(MANAGED_AGENTS_DIR, name);
|
|
147
|
+
try {
|
|
148
|
+
const stat = await fsp.stat(full);
|
|
149
|
+
if (!stat.isDirectory())
|
|
150
|
+
continue;
|
|
151
|
+
const cfg = configPathFor(name);
|
|
152
|
+
if (existsSync(cfg))
|
|
153
|
+
out.push(name);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return out;
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=managed-agent-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"managed-agent-store.js","sourceRoot":"","sources":["../../src/lib/managed-agent-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type ManagedAgentStatus = 'idle' | 'spawning' | 'running' | 'stopped' | 'error';
|
|
2
|
+
export interface ManagedAgentRecord {
|
|
3
|
+
agent_id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
cli: string;
|
|
6
|
+
working_dir: string;
|
|
7
|
+
status: ManagedAgentStatus;
|
|
8
|
+
pid: number | null;
|
|
9
|
+
spawned_at: string | null;
|
|
10
|
+
stopped_at: string | null;
|
|
11
|
+
last_error: string | null;
|
|
12
|
+
}
|
|
13
|
+
export declare class ManagedAgentRegistry {
|
|
14
|
+
#private;
|
|
15
|
+
list(): ManagedAgentRecord[];
|
|
16
|
+
get(agentId: string): ManagedAgentRecord | null;
|
|
17
|
+
upsert(rec: Pick<ManagedAgentRecord, 'agent_id' | 'name' | 'cli' | 'working_dir'>): ManagedAgentRecord;
|
|
18
|
+
setWorkingDir(agentId: string, workingDir: string): ManagedAgentRecord | null;
|
|
19
|
+
markRunning(agentId: string, pid: number): ManagedAgentRecord | null;
|
|
20
|
+
markStopped(agentId: string, reason?: string): ManagedAgentRecord | null;
|
|
21
|
+
markError(agentId: string, message: string): ManagedAgentRecord | null;
|
|
22
|
+
liveAgentIds(): string[];
|
|
23
|
+
workingDirs(): string[];
|
|
24
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { log } from './logging.js';
|
|
2
|
+
export class ManagedAgentRegistry {
|
|
3
|
+
#byId = new Map();
|
|
4
|
+
list() {
|
|
5
|
+
return Array.from(this.#byId.values());
|
|
6
|
+
}
|
|
7
|
+
get(agentId) {
|
|
8
|
+
return this.#byId.get(agentId) ?? null;
|
|
9
|
+
}
|
|
10
|
+
upsert(rec) {
|
|
11
|
+
const existing = this.#byId.get(rec.agent_id);
|
|
12
|
+
if (existing) {
|
|
13
|
+
existing.name = rec.name || existing.name;
|
|
14
|
+
existing.cli = rec.cli || existing.cli;
|
|
15
|
+
existing.working_dir = rec.working_dir || existing.working_dir;
|
|
16
|
+
return existing;
|
|
17
|
+
}
|
|
18
|
+
const fresh = {
|
|
19
|
+
agent_id: rec.agent_id,
|
|
20
|
+
name: rec.name || rec.agent_id.slice(0, 8),
|
|
21
|
+
cli: rec.cli || 'claude',
|
|
22
|
+
working_dir: rec.working_dir || '',
|
|
23
|
+
status: 'idle',
|
|
24
|
+
pid: null,
|
|
25
|
+
spawned_at: null,
|
|
26
|
+
stopped_at: null,
|
|
27
|
+
last_error: null,
|
|
28
|
+
};
|
|
29
|
+
this.#byId.set(rec.agent_id, fresh);
|
|
30
|
+
return fresh;
|
|
31
|
+
}
|
|
32
|
+
setWorkingDir(agentId, workingDir) {
|
|
33
|
+
const rec = this.#byId.get(agentId);
|
|
34
|
+
if (!rec)
|
|
35
|
+
return null;
|
|
36
|
+
rec.working_dir = workingDir;
|
|
37
|
+
return rec;
|
|
38
|
+
}
|
|
39
|
+
markRunning(agentId, pid) {
|
|
40
|
+
const rec = this.#byId.get(agentId);
|
|
41
|
+
if (!rec)
|
|
42
|
+
return null;
|
|
43
|
+
rec.status = 'running';
|
|
44
|
+
rec.pid = pid;
|
|
45
|
+
rec.spawned_at = new Date().toISOString();
|
|
46
|
+
rec.stopped_at = null;
|
|
47
|
+
rec.last_error = null;
|
|
48
|
+
return rec;
|
|
49
|
+
}
|
|
50
|
+
markStopped(agentId, reason) {
|
|
51
|
+
const rec = this.#byId.get(agentId);
|
|
52
|
+
if (!rec)
|
|
53
|
+
return null;
|
|
54
|
+
rec.status = 'stopped';
|
|
55
|
+
rec.pid = null;
|
|
56
|
+
rec.stopped_at = new Date().toISOString();
|
|
57
|
+
if (reason)
|
|
58
|
+
rec.last_error = reason;
|
|
59
|
+
return rec;
|
|
60
|
+
}
|
|
61
|
+
markError(agentId, message) {
|
|
62
|
+
const rec = this.#byId.get(agentId);
|
|
63
|
+
if (!rec)
|
|
64
|
+
return null;
|
|
65
|
+
rec.status = 'error';
|
|
66
|
+
rec.last_error = message;
|
|
67
|
+
log(`[managed-agent ${agentId.slice(0, 8)}] error: ${message}`);
|
|
68
|
+
return rec;
|
|
69
|
+
}
|
|
70
|
+
liveAgentIds() {
|
|
71
|
+
const out = [];
|
|
72
|
+
for (const rec of this.#byId.values()) {
|
|
73
|
+
if (rec.status === 'running' || rec.status === 'spawning')
|
|
74
|
+
out.push(rec.agent_id);
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
workingDirs() {
|
|
79
|
+
const seen = new Set();
|
|
80
|
+
for (const rec of this.#byId.values()) {
|
|
81
|
+
if (rec.working_dir)
|
|
82
|
+
seen.add(rec.working_dir);
|
|
83
|
+
}
|
|
84
|
+
return Array.from(seen);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=managed-agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"managed-agents.js","sourceRoot":"","sources":["../../src/lib/managed-agents.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAgBnC,MAAM,OAAO,oBAAoB;IAC/B,KAAK,GAAG,IAAI,GAAG,EAA8B,CAAC;IAE9C,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,GAAG,CAAC,OAAe;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IACzC,CAAC;IAED,MAAM,CAAC,GAA0E;QAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC;YAC1C,QAAQ,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC;YACvC,QAAQ,CAAC,WAAW,GAAG,GAAG,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,CAAC;YAC/D,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,MAAM,KAAK,GAAuB;YAChC,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YAC1C,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,QAAQ;YACxB,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,EAAE;YAClC,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,IAAI;YACT,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,IAAI;SACjB,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,aAAa,CAAC,OAAe,EAAE,UAAkB;QAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,GAAG,CAAC,WAAW,GAAG,UAAU,CAAC;QAC7B,OAAO,GAAG,CAAC;IACb,CAAC;IAOD,WAAW,CAAC,OAAe,EAAE,GAAW;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;QACvB,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC;QACd,GAAG,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC1C,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC;QACtB,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC;QACtB,OAAO,GAAG,CAAC;IACb,CAAC;IAED,WAAW,CAAC,OAAe,EAAE,MAAe;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;QACvB,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC;QACf,GAAG,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC1C,IAAI,MAAM;YAAE,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC;QACpC,OAAO,GAAG,CAAC;IACb,CAAC;IAED,SAAS,CAAC,OAAe,EAAE,OAAe;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC;QACrB,GAAG,CAAC,UAAU,GAAG,OAAO,CAAC;QACzB,GAAG,CAAC,kBAAkB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,YAAY,OAAO,EAAE,CAAC,CAAC;QAChE,OAAO,GAAG,CAAC;IACb,CAAC;IAED,YAAY;QACV,MAAM,GAAG,GAAa,EAAE,CAAC;QACzB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACtC,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpF,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,WAAW;QACT,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACtC,IAAI,GAAG,CAAC,WAAW;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AwbConfig } from './rest.js';
|
|
2
|
+
export interface McpCallOptions {
|
|
3
|
+
timeoutMs?: number;
|
|
4
|
+
clientName?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function callMcpTool(config: AwbConfig, toolName: string, toolArgs: Record<string, unknown> | undefined, opts?: McpCallOptions): Promise<any>;
|
|
7
|
+
export declare function unwrapToolResult(rpcResponse: any): any;
|
|
8
|
+
export declare function fireAndForgetTool(config: AwbConfig, toolName: string, toolArgs: Record<string, unknown> | undefined): Promise<void>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { REQUEST_TIMEOUT_MS } from './constants.js';
|
|
2
|
+
import { log } from './logging.js';
|
|
3
|
+
export async function callMcpTool(config, toolName, toolArgs, opts = {}) {
|
|
4
|
+
const base = (config?.url ?? '').replace(/\/$/, '');
|
|
5
|
+
if (!base)
|
|
6
|
+
throw new Error('callMcpTool: config.url missing');
|
|
7
|
+
if (!config?.apiKey)
|
|
8
|
+
throw new Error('callMcpTool: config.apiKey missing');
|
|
9
|
+
const url = `${base}/mcp`;
|
|
10
|
+
const timeoutMs = opts.timeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
11
|
+
const baseHeaders = {
|
|
12
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
13
|
+
'Content-Type': 'application/json',
|
|
14
|
+
Accept: 'application/json, text/event-stream',
|
|
15
|
+
};
|
|
16
|
+
const initResp = await fetch(url, {
|
|
17
|
+
method: 'POST',
|
|
18
|
+
headers: baseHeaders,
|
|
19
|
+
body: JSON.stringify({
|
|
20
|
+
jsonrpc: '2.0',
|
|
21
|
+
id: 1,
|
|
22
|
+
method: 'initialize',
|
|
23
|
+
params: {
|
|
24
|
+
protocolVersion: '2025-03-26',
|
|
25
|
+
capabilities: { experimental: { 'awb/schemaVersion': { version: 2 } } },
|
|
26
|
+
clientInfo: { name: opts.clientName || 'awb-agent-manager-tool', version: '1.0.0' },
|
|
27
|
+
},
|
|
28
|
+
}),
|
|
29
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
30
|
+
});
|
|
31
|
+
if (!initResp.ok) {
|
|
32
|
+
throw new Error(`initialize HTTP ${initResp.status}`);
|
|
33
|
+
}
|
|
34
|
+
const sid = initResp.headers.get('mcp-session-id');
|
|
35
|
+
if (!sid)
|
|
36
|
+
throw new Error('initialize did not return Mcp-Session-Id');
|
|
37
|
+
await initResp.text().catch(() => null);
|
|
38
|
+
const sessionHeaders = { ...baseHeaders, 'Mcp-Session-Id': sid };
|
|
39
|
+
await fetch(url, {
|
|
40
|
+
method: 'POST',
|
|
41
|
+
headers: sessionHeaders,
|
|
42
|
+
body: JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized' }),
|
|
43
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
44
|
+
}).then((r) => r.text().catch(() => null));
|
|
45
|
+
let result = null;
|
|
46
|
+
try {
|
|
47
|
+
const callResp = await fetch(url, {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
headers: sessionHeaders,
|
|
50
|
+
body: JSON.stringify({
|
|
51
|
+
jsonrpc: '2.0',
|
|
52
|
+
id: 2,
|
|
53
|
+
method: 'tools/call',
|
|
54
|
+
params: { name: toolName, arguments: toolArgs ?? {} },
|
|
55
|
+
}),
|
|
56
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
57
|
+
});
|
|
58
|
+
if (!callResp.ok) {
|
|
59
|
+
throw new Error(`tools/call ${toolName} HTTP ${callResp.status}`);
|
|
60
|
+
}
|
|
61
|
+
result = await parseStreamableResponse(callResp);
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
fetch(url, {
|
|
65
|
+
method: 'DELETE',
|
|
66
|
+
headers: sessionHeaders,
|
|
67
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
68
|
+
})
|
|
69
|
+
.then((r) => r.text().catch(() => null))
|
|
70
|
+
.catch(() => {
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
async function parseStreamableResponse(resp) {
|
|
76
|
+
const contentType = resp.headers.get('content-type') ?? '';
|
|
77
|
+
const text = await resp.text();
|
|
78
|
+
if (!text)
|
|
79
|
+
return null;
|
|
80
|
+
if (contentType.includes('text/event-stream')) {
|
|
81
|
+
for (const line of text.split('\n')) {
|
|
82
|
+
const m = /^data:\s*(.+)$/.exec(line);
|
|
83
|
+
if (m) {
|
|
84
|
+
try {
|
|
85
|
+
return JSON.parse(m[1]);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
return JSON.parse(text);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export function unwrapToolResult(rpcResponse) {
|
|
101
|
+
const content = rpcResponse?.result?.content;
|
|
102
|
+
if (!Array.isArray(content) || content.length === 0)
|
|
103
|
+
return null;
|
|
104
|
+
const text = content[0]?.text;
|
|
105
|
+
if (typeof text !== 'string')
|
|
106
|
+
return null;
|
|
107
|
+
try {
|
|
108
|
+
return JSON.parse(text);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return text;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export async function fireAndForgetTool(config, toolName, toolArgs) {
|
|
115
|
+
try {
|
|
116
|
+
await callMcpTool(config, toolName, toolArgs);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
log(`MCP tool ${toolName} failed (fire-and-forget): ${err?.message ?? err}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=mcp-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../../src/lib/mcp-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { promises as fsp } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { SUBAGENTS_BASE_DIR } from './constants.js';
|
|
4
|
+
import { log } from './logging.js';
|
|
5
|
+
const KILL_BACKUP_DELAY_MS = 2000;
|
|
6
|
+
async function readPid(pidPath) {
|
|
7
|
+
try {
|
|
8
|
+
const raw = await fsp.readFile(pidPath, 'utf8');
|
|
9
|
+
const pid = parseInt(raw.trim(), 10);
|
|
10
|
+
return Number.isFinite(pid) && pid > 0 ? pid : null;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function isPidAlive(pid) {
|
|
17
|
+
try {
|
|
18
|
+
process.kill(pid, 0);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
return err?.code === 'EPERM';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function readLiveCfgPathsFromProc() {
|
|
26
|
+
let procEntries;
|
|
27
|
+
try {
|
|
28
|
+
procEntries = await fsp.readdir('/proc');
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const live = new Set();
|
|
34
|
+
for (const entry of procEntries) {
|
|
35
|
+
if (!/^\d+$/.test(entry))
|
|
36
|
+
continue;
|
|
37
|
+
try {
|
|
38
|
+
const cmdline = await fsp.readFile(`/proc/${entry}/cmdline`, 'utf8');
|
|
39
|
+
const parts = cmdline.split('\0');
|
|
40
|
+
const idx = parts.indexOf('--mcp-config');
|
|
41
|
+
if (idx >= 0 && parts[idx + 1])
|
|
42
|
+
live.add(parts[idx + 1]);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return live;
|
|
48
|
+
}
|
|
49
|
+
async function reapOne(dir, entry, liveCfgPaths) {
|
|
50
|
+
const pidPath = join(dir, entry);
|
|
51
|
+
const cfgPath = pidPath.replace(/\.pid$/, '.json');
|
|
52
|
+
if (liveCfgPaths && liveCfgPaths.has(cfgPath)) {
|
|
53
|
+
return { skipped: true };
|
|
54
|
+
}
|
|
55
|
+
const pid = await readPid(pidPath);
|
|
56
|
+
if (pid != null && isPidAlive(pid)) {
|
|
57
|
+
log(`[orphan-cleanup] killing stale subagent pid=${pid} (${entry})`);
|
|
58
|
+
try {
|
|
59
|
+
process.kill(pid, 'SIGTERM');
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
}
|
|
63
|
+
const t = setTimeout(() => {
|
|
64
|
+
try {
|
|
65
|
+
process.kill(pid, 'SIGKILL');
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
}
|
|
69
|
+
}, KILL_BACKUP_DELAY_MS);
|
|
70
|
+
if (typeof t.unref === 'function')
|
|
71
|
+
t.unref();
|
|
72
|
+
}
|
|
73
|
+
await fsp.unlink(pidPath).catch(() => { });
|
|
74
|
+
await fsp.unlink(cfgPath).catch(() => { });
|
|
75
|
+
return { skipped: false };
|
|
76
|
+
}
|
|
77
|
+
export async function cleanupOrphanSubagents() {
|
|
78
|
+
let entries;
|
|
79
|
+
try {
|
|
80
|
+
entries = await fsp.readdir(SUBAGENTS_BASE_DIR);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return { scanned: 0, reaped: 0 };
|
|
84
|
+
}
|
|
85
|
+
const pidFiles = entries.filter((e) => e.endsWith('.pid'));
|
|
86
|
+
if (pidFiles.length === 0) {
|
|
87
|
+
return { scanned: 0, reaped: 0 };
|
|
88
|
+
}
|
|
89
|
+
const liveCfgPaths = await readLiveCfgPathsFromProc();
|
|
90
|
+
log(`[orphan-cleanup] scanning ${pidFiles.length} pid sidecar(s) in ${SUBAGENTS_BASE_DIR} (live cfg paths in /proc: ${liveCfgPaths ? liveCfgPaths.size : 'unavailable'})`);
|
|
91
|
+
let reaped = 0;
|
|
92
|
+
let skipped = 0;
|
|
93
|
+
for (const entry of pidFiles) {
|
|
94
|
+
try {
|
|
95
|
+
const r = await reapOne(SUBAGENTS_BASE_DIR, entry, liveCfgPaths);
|
|
96
|
+
if (r.skipped)
|
|
97
|
+
skipped++;
|
|
98
|
+
else
|
|
99
|
+
reaped++;
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
log(`[orphan-cleanup] skipping ${entry}: ${err?.message ?? err}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
log(`[orphan-cleanup] reaped ${reaped}/${pidFiles.length} orphan subagents (${skipped} protected as live-sibling)`);
|
|
106
|
+
return { scanned: pidFiles.length, reaped, skipped };
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=orphan-cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orphan-cleanup.js","sourceRoot":"","sources":["../../src/lib/orphan-cleanup.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAElC,KAAK,UAAU,OAAO,CAAC,OAAe;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACrC,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,GAAG,EAAE,IAAI,KAAK,OAAO,CAAC;IAC/B,CAAC;AACH,CAAC;AAOD,KAAK,UAAU,wBAAwB;IACrC,IAAI,WAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QACnC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,SAAS,KAAK,UAAU,EAAE,MAAM,CAAC,CAAC;YACrE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAC1C,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;gBAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;QAET,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAMD,KAAK,UAAU,OAAO,CACpB,GAAW,EACX,KAAa,EACb,YAAgC;IAEhC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAInD,IAAI,YAAY,IAAI,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,GAAG,IAAI,IAAI,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,GAAG,CAAC,+CAA+C,GAAG,KAAK,KAAK,GAAG,CAAC,CAAC;QACrE,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;QAET,CAAC;QACD,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE;YACxB,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAC/B,CAAC;YAAC,MAAM,CAAC;YAET,CAAC;QACH,CAAC,EAAE,oBAAoB,CAAC,CAAC;QACzB,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,UAAU;YAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAC/C,CAAC;IACD,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC1C,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC;AAaD,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACnC,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACnC,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,wBAAwB,EAAE,CAAC;IACtD,GAAG,CACD,6BAA6B,QAAQ,CAAC,MAAM,sBAAsB,kBAAkB,8BAA8B,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,GAAG,CACtK,CAAC;IACF,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,kBAAkB,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;YACjE,IAAI,CAAC,CAAC,OAAO;gBAAE,OAAO,EAAE,CAAC;;gBACpB,MAAM,EAAE,CAAC;QAChB,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,GAAG,CAAC,6BAA6B,KAAK,KAAK,GAAG,EAAE,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IACD,GAAG,CACD,2BAA2B,MAAM,IAAI,QAAQ,CAAC,MAAM,sBAAsB,OAAO,6BAA6B,CAC/G,CAAC;IACF,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { HEARTBEAT_INTERVAL_MS, REQUEST_TIMEOUT_MS } from './constants.js';
|
|
2
|
+
import { log } from './logging.js';
|
|
3
|
+
export class PresenceHeartbeat {
|
|
4
|
+
#config;
|
|
5
|
+
#agentId;
|
|
6
|
+
#timer = null;
|
|
7
|
+
#stopped = false;
|
|
8
|
+
constructor(config, agentId) {
|
|
9
|
+
this.#config = config;
|
|
10
|
+
this.#agentId = agentId;
|
|
11
|
+
}
|
|
12
|
+
start() {
|
|
13
|
+
if (!this.#agentId) {
|
|
14
|
+
log('Presence heartbeat skipped — agent_id not in agent.json (run pairing first)');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
this.#stopped = false;
|
|
18
|
+
this.#ping().catch((err) => log(`Presence ping (initial) failed: ${err?.message ?? err}`));
|
|
19
|
+
this.#timer = setInterval(() => {
|
|
20
|
+
this.#ping().catch((err) => log(`Presence ping failed: ${err?.message ?? err}`));
|
|
21
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
22
|
+
this.#timer.unref?.();
|
|
23
|
+
log(`Presence heartbeat started (agent=${this.#agentId.slice(0, 8)} interval=${HEARTBEAT_INTERVAL_MS / 1000}s)`);
|
|
24
|
+
}
|
|
25
|
+
stop() {
|
|
26
|
+
this.#stopped = true;
|
|
27
|
+
if (this.#timer) {
|
|
28
|
+
clearInterval(this.#timer);
|
|
29
|
+
this.#timer = null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async pingNow() {
|
|
33
|
+
if (this.#stopped || !this.#agentId)
|
|
34
|
+
return;
|
|
35
|
+
try {
|
|
36
|
+
await this.#ping();
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
log(`Presence ping (forced) failed: ${err?.message ?? err}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async #ping() {
|
|
43
|
+
if (this.#stopped)
|
|
44
|
+
return;
|
|
45
|
+
const url = `${this.#config.url.replace(/\/$/, '')}/api/agent/ping`;
|
|
46
|
+
const resp = await fetch(url, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: {
|
|
49
|
+
'X-Agent-Key': this.#config.apiKey,
|
|
50
|
+
'Content-Type': 'application/json',
|
|
51
|
+
},
|
|
52
|
+
body: JSON.stringify({ agent_id: this.#agentId }),
|
|
53
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
54
|
+
});
|
|
55
|
+
if (!resp.ok) {
|
|
56
|
+
throw new Error(`POST /api/agent/ping HTTP ${resp.status}`);
|
|
57
|
+
}
|
|
58
|
+
await resp.text().catch(() => null);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=presence-heartbeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presence-heartbeat.js","sourceRoot":"","sources":["../../src/lib/presence-heartbeat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ColumnPrompt, PromptComposer } from './event-dispatcher.js';
|
|
2
|
+
import { type PreparedAttachment, type RawChatAttachment } from './chat-attachment-prep.js';
|
|
3
|
+
interface MentionLike {
|
|
4
|
+
actor_name?: string;
|
|
5
|
+
mention_source?: string;
|
|
6
|
+
role_shortcut?: string;
|
|
7
|
+
ticket_id?: string;
|
|
8
|
+
content?: string;
|
|
9
|
+
}
|
|
10
|
+
interface ChatHistoryEntry {
|
|
11
|
+
sender_type?: string;
|
|
12
|
+
sender_name?: string;
|
|
13
|
+
sender_id?: string;
|
|
14
|
+
content?: string;
|
|
15
|
+
created_at?: string;
|
|
16
|
+
attachments?: RawChatAttachment[];
|
|
17
|
+
type?: string;
|
|
18
|
+
}
|
|
19
|
+
interface ChatRoomNewMessage {
|
|
20
|
+
content?: string;
|
|
21
|
+
sender_name?: string;
|
|
22
|
+
sender_id?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function composeTriggerPrompt(ticket: any, _rolePrompt: string, ticketPrompt: string, fallbackTicketId: string, columnPrompt: ColumnPrompt | null, extraInstructions?: string | null): string;
|
|
25
|
+
export declare function composeChatPrompt(_rolePrompt: string, history: ChatHistoryEntry[], newMessage: string, roomId?: string, usesNativeMcp?: boolean): string;
|
|
26
|
+
export declare function composeCommentMentionPrompt(ticket: any, _rolePrompt: string, mention: MentionLike, fallbackTicketId: string): string;
|
|
27
|
+
export declare function composeChatRoomPrompt(roomId: string, history: ChatHistoryEntry[], newMessage: ChatRoomNewMessage, attachments?: PreparedAttachment[], usesNativeMcp?: boolean, historyAttachments?: Map<ChatHistoryEntry, PreparedAttachment[]>): string;
|
|
28
|
+
export declare const promptComposer: PromptComposer;
|
|
29
|
+
export {};
|