@ai-devkit/agent-manager 0.27.0 → 0.28.1
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/README.md +12 -4
- package/dist/__tests__/adapters/CodexAdapter.test.js +199 -0
- package/dist/__tests__/adapters/CodexAdapter.test.js.map +1 -1
- package/dist/__tests__/database/DurableAgentsDatabase.test.js +100 -0
- package/dist/__tests__/database/DurableAgentsDatabase.test.js.map +1 -0
- package/dist/__tests__/print/ClaudePrintAgent.integration.test.js +7 -7
- package/dist/__tests__/print/ClaudePrintAgent.integration.test.js.map +1 -1
- package/dist/__tests__/print/ClaudePrintAgentService.test.js +7 -7
- package/dist/__tests__/print/ClaudePrintAgentService.test.js.map +1 -1
- package/dist/__tests__/print/ClaudePrintRunner.test.js +1 -1
- package/dist/__tests__/print/ClaudePrintRunner.test.js.map +1 -1
- package/dist/__tests__/print/DurableAgent.test.js +17 -0
- package/dist/__tests__/print/DurableAgent.test.js.map +1 -0
- package/dist/__tests__/print/DurableAgentRepository.sqlite.test.js +186 -0
- package/dist/__tests__/print/DurableAgentRepository.sqlite.test.js.map +1 -0
- package/dist/__tests__/print/{PrintAgentStore.test.js → DurableAgentRepository.test.js} +63 -110
- package/dist/__tests__/print/DurableAgentRepository.test.js.map +1 -0
- package/dist/adapters/CodexAdapter.d.ts +1 -0
- package/dist/adapters/CodexAdapter.d.ts.map +1 -1
- package/dist/adapters/CodexAdapter.js +16 -6
- package/dist/adapters/CodexAdapter.js.map +1 -1
- package/dist/database/connection.d.ts.map +1 -1
- package/dist/database/connection.js +17 -9
- package/dist/database/connection.js.map +1 -1
- package/dist/database/migrations/003_durable_agents.sql +43 -0
- package/dist/durable/ClaudeCliProbe.d.ts.map +1 -0
- package/dist/{print → durable}/ClaudeCliProbe.js +1 -1
- package/dist/durable/ClaudeCliProbe.js.map +1 -0
- package/dist/{print → durable}/ClaudePrintAgentService.d.ts +11 -11
- package/dist/durable/ClaudePrintAgentService.d.ts.map +1 -0
- package/dist/{print → durable}/ClaudePrintAgentService.js +12 -12
- package/dist/durable/ClaudePrintAgentService.js.map +1 -0
- package/dist/{print → durable}/ClaudePrintRunner.d.ts +3 -3
- package/dist/durable/ClaudePrintRunner.d.ts.map +1 -0
- package/dist/{print → durable}/ClaudePrintRunner.js +2 -2
- package/dist/durable/ClaudePrintRunner.js.map +1 -0
- package/dist/durable/DurableAgent.d.ts +61 -0
- package/dist/durable/DurableAgent.d.ts.map +1 -0
- package/dist/durable/DurableAgent.js +46 -0
- package/dist/durable/DurableAgent.js.map +1 -0
- package/dist/durable/DurableAgentRepository.d.ts +60 -0
- package/dist/durable/DurableAgentRepository.d.ts.map +1 -0
- package/dist/durable/DurableAgentRepository.js +325 -0
- package/dist/durable/DurableAgentRepository.js.map +1 -0
- package/dist/index.d.ts +11 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/adapters/CodexAdapter.test.ts +132 -0
- package/src/__tests__/database/DurableAgentsDatabase.test.ts +77 -0
- package/src/__tests__/print/ClaudePrintAgent.integration.test.ts +6 -6
- package/src/__tests__/print/ClaudePrintAgentService.test.ts +7 -7
- package/src/__tests__/print/ClaudePrintRunner.test.ts +3 -3
- package/src/__tests__/print/{PrintAgent.test.ts → DurableAgent.test.ts} +6 -6
- package/src/__tests__/print/DurableAgentRepository.sqlite.test.ts +105 -0
- package/src/__tests__/print/DurableAgentRepository.test.ts +163 -0
- package/src/adapters/CodexAdapter.ts +14 -11
- package/src/database/connection.ts +15 -9
- package/src/database/migrations/003_durable_agents.sql +43 -0
- package/src/{print → durable}/ClaudeCliProbe.ts +1 -1
- package/src/{print → durable}/ClaudePrintAgentService.ts +21 -21
- package/src/{print → durable}/ClaudePrintRunner.ts +4 -4
- package/src/durable/DurableAgent.ts +91 -0
- package/src/durable/DurableAgentRepository.ts +307 -0
- package/src/index.ts +26 -25
- package/dist/__tests__/print/PrintAgent.test.js +0 -17
- package/dist/__tests__/print/PrintAgent.test.js.map +0 -1
- package/dist/__tests__/print/PrintAgentStore.test.js.map +0 -1
- package/dist/print/ClaudeCliProbe.d.ts.map +0 -1
- package/dist/print/ClaudeCliProbe.js.map +0 -1
- package/dist/print/ClaudePrintAgentService.d.ts.map +0 -1
- package/dist/print/ClaudePrintAgentService.js.map +0 -1
- package/dist/print/ClaudePrintRunner.d.ts.map +0 -1
- package/dist/print/ClaudePrintRunner.js.map +0 -1
- package/dist/print/PrintAgent.d.ts +0 -57
- package/dist/print/PrintAgent.d.ts.map +0 -1
- package/dist/print/PrintAgent.js +0 -42
- package/dist/print/PrintAgent.js.map +0 -1
- package/dist/print/PrintAgentStore.d.ts +0 -69
- package/dist/print/PrintAgentStore.d.ts.map +0 -1
- package/dist/print/PrintAgentStore.js +0 -484
- package/dist/print/PrintAgentStore.js.map +0 -1
- package/src/__tests__/print/PrintAgentStore.test.ts +0 -192
- package/src/print/PrintAgent.ts +0 -86
- package/src/print/PrintAgentStore.ts +0 -503
- /package/dist/{print → durable}/ClaudeCliProbe.d.ts +0 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { randomUUID } from 'crypto';
|
|
3
|
+
import { execFileSync } from 'child_process';
|
|
4
|
+
import { DatabaseConnection, DEFAULT_AGENT_REGISTRY_DB_PATH } from '../database/index.js';
|
|
5
|
+
import { AGENT_MODES, type DurableActiveRun, type DurableAgent, type ProcessIdentity, type DurableRunStatus, type DurableSessionHealth } from './DurableAgent.js';
|
|
6
|
+
import {
|
|
7
|
+
DurableAgentBusyError,
|
|
8
|
+
DurableAgentNameConflictError,
|
|
9
|
+
DurableAgentNotFoundError,
|
|
10
|
+
DurableAgentRepositoryError,
|
|
11
|
+
} from './DurableAgent.js';
|
|
12
|
+
|
|
13
|
+
interface DurableAgentRow {
|
|
14
|
+
id: string; name: string; provider: 'claude'; mode: typeof AGENT_MODES.DURABLE; cwd: string; provider_session_id: string;
|
|
15
|
+
state: DurableAgent['state']; session_health: DurableSessionHealth; created_at: string; updated_at: string;
|
|
16
|
+
last_active_at: string | null; last_result_status: DurableRunStatus | null;
|
|
17
|
+
last_result_completed_at: string | null; last_result_exit_code: number | null; last_result_summary: string | null;
|
|
18
|
+
active_run_token: string | null; active_owner_pid: number | null; active_owner_started_at: string | null;
|
|
19
|
+
active_provider_pid: number | null; active_provider_started_at: string | null; active_run_started_at: string | null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface CreateDurableAgentInput { name: string; cwd: string }
|
|
23
|
+
|
|
24
|
+
export interface DurableAgentRepositoryOptions {
|
|
25
|
+
dbPath?: string;
|
|
26
|
+
readonly?: boolean;
|
|
27
|
+
/** @deprecated SQLite busy_timeout replaces filesystem lock polling. */
|
|
28
|
+
lockTimeoutMs?: number;
|
|
29
|
+
now?: () => Date;
|
|
30
|
+
processInspector?: ProcessInspector;
|
|
31
|
+
/** @deprecated Active ownership is committed atomically. */
|
|
32
|
+
incompleteLockGraceMs?: number;
|
|
33
|
+
/** @deprecated SQLite transactions replace mutation lock directories. */
|
|
34
|
+
mutationLockStaleMs?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface ProcessInspector { getIdentity(pid: number): ProcessIdentity | null }
|
|
38
|
+
export interface DurableRunCompletion {
|
|
39
|
+
status: DurableRunStatus; exitCode: number | null; summary: string; sessionHealth: DurableSessionHealth;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class DurableAgentRepository {
|
|
43
|
+
readonly dbPath: string;
|
|
44
|
+
private readonly now: () => Date;
|
|
45
|
+
private readonly processInspector: ProcessInspector;
|
|
46
|
+
private readonly readonly: boolean;
|
|
47
|
+
private readonly db: DatabaseConnection;
|
|
48
|
+
|
|
49
|
+
constructor(options: DurableAgentRepositoryOptions = {}) {
|
|
50
|
+
this.dbPath = options.dbPath ?? DEFAULT_AGENT_REGISTRY_DB_PATH;
|
|
51
|
+
this.now = options.now ?? (() => new Date());
|
|
52
|
+
this.processInspector = options.processInspector ?? new LocalProcessInspector();
|
|
53
|
+
this.readonly = options.readonly ?? false;
|
|
54
|
+
try {
|
|
55
|
+
this.db = new DatabaseConnection({ dbPath: this.dbPath, readonly: this.readonly });
|
|
56
|
+
} catch (error) {
|
|
57
|
+
if (error instanceof DurableAgentRepositoryError) throw error;
|
|
58
|
+
throw new DurableAgentRepositoryError(`Cannot open durable-agent database: ${(error as Error).message}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async create(input: CreateDurableAgentInput): Promise<DurableAgent> {
|
|
63
|
+
this.assertWritable();
|
|
64
|
+
const cwd = this.canonicalDirectory(input.cwd);
|
|
65
|
+
const timestamp = this.now().toISOString();
|
|
66
|
+
const id = randomUUID();
|
|
67
|
+
let providerSessionId = randomUUID();
|
|
68
|
+
while (providerSessionId === id) providerSessionId = randomUUID();
|
|
69
|
+
try {
|
|
70
|
+
this.db.execute(`INSERT INTO durable_agents (
|
|
71
|
+
id, name, provider, mode, cwd, provider_session_id, state, session_health, created_at, updated_at
|
|
72
|
+
) VALUES (?, ?, 'claude', ?, ?, ?, 'ready', 'uninitialized', ?, ?)`,
|
|
73
|
+
[id, input.name, AGENT_MODES.DURABLE, cwd, providerSessionId, timestamp, timestamp]);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (/UNIQUE constraint failed: durable_agents\.name/i.test((error as Error).message)) {
|
|
76
|
+
throw new DurableAgentNameConflictError(input.name);
|
|
77
|
+
}
|
|
78
|
+
throw this.storageError('Failed to create durable agent', error);
|
|
79
|
+
}
|
|
80
|
+
return this.requireById(id);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async list(): Promise<DurableAgent[]> {
|
|
84
|
+
if (!this.readonly) await this.reconcile();
|
|
85
|
+
return this.listRaw();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async getById(id: string): Promise<DurableAgent | null> {
|
|
89
|
+
if (!this.readonly) await this.reconcile();
|
|
90
|
+
return this.findById(id);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async resolve(reference: string): Promise<DurableAgent | DurableAgent[] | null> {
|
|
94
|
+
const agents = await this.list();
|
|
95
|
+
const byId = agents.find((agent) => agent.id === reference);
|
|
96
|
+
if (byId) return byId;
|
|
97
|
+
const matches = agents.filter((agent) => agent.name.toLowerCase() === reference.toLowerCase());
|
|
98
|
+
return matches.length === 0 ? null : matches.length === 1 ? matches[0]! : matches;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async acquireRun(id: string): Promise<{ agent: DurableAgent; token: string }> {
|
|
102
|
+
this.assertWritable();
|
|
103
|
+
const snapshot = this.findById(id);
|
|
104
|
+
if (!snapshot) throw new DurableAgentNotFoundError(id);
|
|
105
|
+
this.validateBoundCwd(snapshot.cwd);
|
|
106
|
+
const observed = snapshot.activeRun;
|
|
107
|
+
const observedLive = observed ? this.isActive(observed) : false;
|
|
108
|
+
if (observedLive) throw new DurableAgentBusyError(id, snapshot.name);
|
|
109
|
+
const owner = this.processInspector.getIdentity(process.pid);
|
|
110
|
+
if (!owner) throw new DurableAgentRepositoryError('Cannot determine the current process identity.');
|
|
111
|
+
const token = randomUUID();
|
|
112
|
+
const startedAt = this.now().toISOString();
|
|
113
|
+
let recovered = false;
|
|
114
|
+
try {
|
|
115
|
+
this.immediate(() => {
|
|
116
|
+
const current = this.findById(id);
|
|
117
|
+
if (!current) throw new DurableAgentNotFoundError(id);
|
|
118
|
+
if (current.state === 'running') {
|
|
119
|
+
if (!observed || current.activeRun?.token !== observed.token || observedLive) {
|
|
120
|
+
throw new DurableAgentBusyError(id, current.name);
|
|
121
|
+
}
|
|
122
|
+
recovered = true;
|
|
123
|
+
}
|
|
124
|
+
const changed = this.db.execute(`UPDATE durable_agents SET
|
|
125
|
+
state = 'running', active_run_token = ?, active_owner_pid = ?, active_owner_started_at = ?,
|
|
126
|
+
active_provider_pid = NULL, active_provider_started_at = NULL, active_run_started_at = ?, updated_at = ?,
|
|
127
|
+
session_health = CASE WHEN state = 'running' THEN 'unknown' ELSE session_health END,
|
|
128
|
+
last_result_status = CASE WHEN state = 'running' THEN 'interrupted' ELSE last_result_status END,
|
|
129
|
+
last_result_completed_at = CASE WHEN state = 'running' THEN ? ELSE last_result_completed_at END,
|
|
130
|
+
last_result_exit_code = CASE WHEN state = 'running' THEN NULL ELSE last_result_exit_code END,
|
|
131
|
+
last_result_summary = CASE WHEN state = 'running' THEN 'Previous print run was interrupted.' ELSE last_result_summary END
|
|
132
|
+
WHERE id = ? AND (state <> 'running' OR (
|
|
133
|
+
active_run_token = ? AND active_owner_started_at = ? AND active_run_started_at = ?
|
|
134
|
+
))
|
|
135
|
+
`, [token, owner.pid, owner.startedAt, startedAt, startedAt, startedAt, id,
|
|
136
|
+
observed?.token ?? null, observed?.owner.startedAt ?? null, observed?.startedAt ?? null]);
|
|
137
|
+
if (changed.changes !== 1) throw new DurableAgentBusyError(id, current.name);
|
|
138
|
+
});
|
|
139
|
+
} catch (error) {
|
|
140
|
+
if (error instanceof DurableAgentBusyError || error instanceof DurableAgentNotFoundError) throw error;
|
|
141
|
+
if (/busy|locked/i.test((error as Error).message)) throw new DurableAgentBusyError(id, snapshot.name);
|
|
142
|
+
throw this.storageError('Failed to acquire durable-agent run', error);
|
|
143
|
+
}
|
|
144
|
+
const agent = this.requireById(id);
|
|
145
|
+
if (recovered && agent.lastResult?.status !== 'interrupted') {
|
|
146
|
+
throw new DurableAgentRepositoryError('Failed to record interrupted print run.');
|
|
147
|
+
}
|
|
148
|
+
return { agent, token };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async recordProviderProcess(id: string, token: string, identity: ProcessIdentity): Promise<void> {
|
|
152
|
+
this.assertWritable();
|
|
153
|
+
const changed = this.db.execute(`UPDATE durable_agents SET
|
|
154
|
+
active_provider_pid = ?, active_provider_started_at = ?, updated_at = ?
|
|
155
|
+
WHERE id = ? AND state = 'running' AND active_run_token = ?`,
|
|
156
|
+
[identity.pid, identity.startedAt, this.now().toISOString(), id, token]);
|
|
157
|
+
if (changed.changes !== 1) throw new DurableAgentRepositoryError('Print run ownership changed.');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async completeRun(id: string, token: string, result: DurableRunCompletion): Promise<DurableAgent> {
|
|
161
|
+
this.assertWritable();
|
|
162
|
+
const completedAt = this.now().toISOString();
|
|
163
|
+
const changed = this.db.execute(`UPDATE durable_agents SET
|
|
164
|
+
state = ?, session_health = ?, active_run_token = NULL, active_owner_pid = NULL,
|
|
165
|
+
active_owner_started_at = NULL, active_provider_pid = NULL, active_provider_started_at = NULL,
|
|
166
|
+
active_run_started_at = NULL, last_active_at = ?, updated_at = ?, last_result_status = ?,
|
|
167
|
+
last_result_completed_at = ?, last_result_exit_code = ?, last_result_summary = ?
|
|
168
|
+
WHERE id = ? AND state = 'running' AND active_run_token = ?`, [
|
|
169
|
+
result.status === 'succeeded' ? 'ready' : 'degraded', result.sessionHealth, completedAt, completedAt,
|
|
170
|
+
result.status, completedAt, result.exitCode, result.summary.slice(0, 4096), id, token,
|
|
171
|
+
]);
|
|
172
|
+
if (changed.changes !== 1) throw new DurableAgentRepositoryError('Print run ownership changed.');
|
|
173
|
+
return this.requireById(id);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async reconcile(): Promise<void> {
|
|
177
|
+
this.assertWritable();
|
|
178
|
+
const running = this.listRaw().filter((agent) => agent.state === 'running' && agent.activeRun);
|
|
179
|
+
for (const snapshot of running) {
|
|
180
|
+
if (this.isActive(snapshot.activeRun!)) continue;
|
|
181
|
+
const completedAt = this.now().toISOString();
|
|
182
|
+
this.db.execute(`UPDATE durable_agents SET
|
|
183
|
+
state = 'degraded', session_health = 'unknown', active_run_token = NULL,
|
|
184
|
+
active_owner_pid = NULL, active_owner_started_at = NULL, active_provider_pid = NULL,
|
|
185
|
+
active_provider_started_at = NULL, active_run_started_at = NULL, updated_at = ?, last_active_at = ?,
|
|
186
|
+
last_result_status = 'interrupted', last_result_completed_at = ?, last_result_exit_code = NULL,
|
|
187
|
+
last_result_summary = 'Previous print run was interrupted.'
|
|
188
|
+
WHERE id = ? AND state = 'running' AND active_run_token = ?
|
|
189
|
+
AND active_owner_started_at = ? AND active_run_started_at = ?`, [
|
|
190
|
+
completedAt, completedAt, completedAt, snapshot.id, snapshot.activeRun!.token,
|
|
191
|
+
snapshot.activeRun!.owner.startedAt, snapshot.activeRun!.startedAt,
|
|
192
|
+
]);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private immediate<T>(operation: () => T): T {
|
|
197
|
+
this.db.instance.exec('BEGIN IMMEDIATE');
|
|
198
|
+
try {
|
|
199
|
+
const result = operation();
|
|
200
|
+
this.db.instance.exec('COMMIT');
|
|
201
|
+
return result;
|
|
202
|
+
} catch (error) {
|
|
203
|
+
try { this.db.instance.exec('ROLLBACK'); } catch { /* retain original failure */ }
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private listRaw(): DurableAgent[] {
|
|
209
|
+
try {
|
|
210
|
+
return this.db.query<DurableAgentRow>(
|
|
211
|
+
'SELECT * FROM durable_agents ORDER BY updated_at DESC, name COLLATE NOCASE',
|
|
212
|
+
).map((row) => this.fromRow(row));
|
|
213
|
+
} catch (error) {
|
|
214
|
+
throw this.storageError('Failed to read durable-agent database', error);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private findById(id: string): DurableAgent | null {
|
|
219
|
+
const row = this.db.queryOne<DurableAgentRow>('SELECT * FROM durable_agents WHERE id = ?', [id]);
|
|
220
|
+
return row ? this.fromRow(row) : null;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private requireById(id: string): DurableAgent {
|
|
224
|
+
const agent = this.findById(id);
|
|
225
|
+
if (!agent) throw new DurableAgentNotFoundError(id);
|
|
226
|
+
return agent;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private fromRow(row: DurableAgentRow): DurableAgent {
|
|
230
|
+
const activeRun: DurableActiveRun | null = row.active_run_token === null ? null : {
|
|
231
|
+
token: row.active_run_token,
|
|
232
|
+
owner: { pid: row.active_owner_pid!, startedAt: row.active_owner_started_at! },
|
|
233
|
+
provider: row.active_provider_pid === null ? null : {
|
|
234
|
+
pid: row.active_provider_pid, startedAt: row.active_provider_started_at!,
|
|
235
|
+
},
|
|
236
|
+
startedAt: row.active_run_started_at!,
|
|
237
|
+
};
|
|
238
|
+
return {
|
|
239
|
+
id: row.id, name: row.name, provider: row.provider, mode: row.mode, cwd: row.cwd,
|
|
240
|
+
providerSessionId: row.provider_session_id, state: row.state, sessionHealth: row.session_health,
|
|
241
|
+
createdAt: row.created_at, updatedAt: row.updated_at, lastActiveAt: row.last_active_at,
|
|
242
|
+
lastResult: row.last_result_status === null ? null : {
|
|
243
|
+
status: row.last_result_status, completedAt: row.last_result_completed_at!,
|
|
244
|
+
exitCode: row.last_result_exit_code, summary: row.last_result_summary ?? '',
|
|
245
|
+
},
|
|
246
|
+
activeRun,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private canonicalDirectory(input: string): string {
|
|
251
|
+
try {
|
|
252
|
+
const resolved = fs.realpathSync(input);
|
|
253
|
+
if (!fs.statSync(resolved).isDirectory()) throw new Error('not a directory');
|
|
254
|
+
return resolved;
|
|
255
|
+
} catch {
|
|
256
|
+
throw new DurableAgentRepositoryError(`Durable agent cwd is not an existing directory: ${input}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
private validateBoundCwd(bound: string): void {
|
|
261
|
+
try {
|
|
262
|
+
const stat = fs.lstatSync(bound);
|
|
263
|
+
if (!stat.isDirectory() || stat.isSymbolicLink() || fs.realpathSync(bound) !== bound) throw new Error('binding changed');
|
|
264
|
+
} catch {
|
|
265
|
+
throw new DurableAgentRepositoryError(`Durable agent cwd binding is no longer safe: ${bound}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private isActive(metadata: DurableActiveRun): boolean {
|
|
270
|
+
return this.sameProcess(metadata.owner) || (metadata.provider !== null && this.sameProcess(metadata.provider));
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private sameProcess(expected: ProcessIdentity): boolean {
|
|
274
|
+
const actual = this.processInspector.getIdentity(expected.pid);
|
|
275
|
+
return actual !== null && actual.startedAt === expected.startedAt;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
private assertWritable(): void {
|
|
279
|
+
if (this.readonly) throw new DurableAgentRepositoryError('Durable-agent repository is readonly.');
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private storageError(prefix: string, error: unknown): DurableAgentRepositoryError {
|
|
283
|
+
return error instanceof DurableAgentRepositoryError ? error
|
|
284
|
+
: new DurableAgentRepositoryError(`${prefix}: ${(error as Error).message}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export class LocalProcessInspector implements ProcessInspector {
|
|
289
|
+
getIdentity(pid: number): ProcessIdentity | null {
|
|
290
|
+
if (!Number.isInteger(pid) || pid <= 0) return null;
|
|
291
|
+
try {
|
|
292
|
+
if (process.platform === 'linux') {
|
|
293
|
+
const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
294
|
+
const close = stat.lastIndexOf(')');
|
|
295
|
+
const fields = stat.slice(close + 2).split(' ');
|
|
296
|
+
const startTicks = fields[19];
|
|
297
|
+
return startTicks ? { pid, startedAt: `linux:${startTicks}` } : null;
|
|
298
|
+
}
|
|
299
|
+
const startedAt = execFileSync('ps', ['-o', 'lstart=', '-p', String(pid)], {
|
|
300
|
+
encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
|
|
301
|
+
}).trim();
|
|
302
|
+
return startedAt ? { pid, startedAt } : null;
|
|
303
|
+
} catch {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -38,40 +38,41 @@ export type { AgentRequest } from './utils/agent-requests.js';
|
|
|
38
38
|
export { getAgentRequestPath, readLatestAgentRequest, writeAgentRequest } from './utils/agent-requests.js';
|
|
39
39
|
|
|
40
40
|
export {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
AGENT_MODES,
|
|
42
|
+
DurableAgentError,
|
|
43
|
+
DurableAgentBusyError,
|
|
44
|
+
DurableAgentNotFoundError,
|
|
45
|
+
DurableAgentRepositoryError,
|
|
46
|
+
DurableAgentNameConflictError,
|
|
46
47
|
ClaudePrintError,
|
|
47
|
-
} from './
|
|
48
|
+
} from './durable/DurableAgent.js';
|
|
48
49
|
export type {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
DurableAgent,
|
|
51
|
+
DurableAgentState,
|
|
52
|
+
DurableSessionHealth,
|
|
53
|
+
DurableRunStatus,
|
|
54
|
+
DurableActiveRun,
|
|
55
|
+
DurableLastResult,
|
|
55
56
|
ProcessIdentity,
|
|
56
|
-
} from './
|
|
57
|
-
export {
|
|
58
|
-
export { LocalProcessInspector } from './
|
|
57
|
+
} from './durable/DurableAgent.js';
|
|
58
|
+
export { DurableAgentRepository } from './durable/DurableAgentRepository.js';
|
|
59
|
+
export { LocalProcessInspector } from './durable/DurableAgentRepository.js';
|
|
59
60
|
export type {
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
CreateDurableAgentInput,
|
|
62
|
+
DurableAgentRepositoryOptions,
|
|
62
63
|
ProcessInspector,
|
|
63
|
-
|
|
64
|
-
} from './
|
|
65
|
-
export { ClaudeCliProbe } from './
|
|
66
|
-
export type { ClaudeCliProbeOptions } from './
|
|
67
|
-
export { ClaudePrintRunner } from './
|
|
64
|
+
DurableRunCompletion,
|
|
65
|
+
} from './durable/DurableAgentRepository.js';
|
|
66
|
+
export { ClaudeCliProbe } from './durable/ClaudeCliProbe.js';
|
|
67
|
+
export type { ClaudeCliProbeOptions } from './durable/ClaudeCliProbe.js';
|
|
68
|
+
export { ClaudePrintRunner } from './durable/ClaudePrintRunner.js';
|
|
68
69
|
export type {
|
|
69
70
|
ClaudePrintRunnerOptions,
|
|
70
71
|
ClaudePrintRunRequest,
|
|
71
72
|
ClaudePrintRunResult,
|
|
72
|
-
} from './
|
|
73
|
-
export { ClaudePrintAgentService } from './
|
|
73
|
+
} from './durable/ClaudePrintRunner.js';
|
|
74
|
+
export { ClaudePrintAgentService } from './durable/ClaudePrintAgentService.js';
|
|
74
75
|
export type {
|
|
75
76
|
ClaudePrintAgentServiceOptions,
|
|
76
77
|
ClaudePrintSendResult,
|
|
77
|
-
} from './
|
|
78
|
+
} from './durable/ClaudePrintAgentService.js';
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
describe('print-agent public domain', ()=>{
|
|
3
|
-
it('exports a classified busy error without exposing prompt data', async ()=>{
|
|
4
|
-
const api = await import('../../index.js');
|
|
5
|
-
expect(api).toHaveProperty('PrintAgentBusyError');
|
|
6
|
-
const ErrorType = api.PrintAgentBusyError;
|
|
7
|
-
const error = new ErrorType('agent-id', 'reviewer');
|
|
8
|
-
expect(error).toMatchObject({
|
|
9
|
-
name: 'PrintAgentBusyError',
|
|
10
|
-
code: 'PRINT_AGENT_BUSY',
|
|
11
|
-
agentId: 'agent-id',
|
|
12
|
-
message: 'Print agent "reviewer" is busy.'
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
//# sourceMappingURL=PrintAgent.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/__tests__/print/PrintAgent.test.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest';\n\ndescribe('print-agent public domain', () => {\n it('exports a classified busy error without exposing prompt data', async () => {\n const api = await import('../../index.js') as Record<string, unknown>;\n\n expect(api).toHaveProperty('PrintAgentBusyError');\n const ErrorType = api.PrintAgentBusyError as new (agentId: string, name: string) => Error & {\n code: string;\n agentId: string;\n };\n const error = new ErrorType('agent-id', 'reviewer');\n\n expect(error).toMatchObject({\n name: 'PrintAgentBusyError',\n code: 'PRINT_AGENT_BUSY',\n agentId: 'agent-id',\n message: 'Print agent \"reviewer\" is busy.',\n });\n });\n});\n"],"names":["describe","expect","it","api","toHaveProperty","ErrorType","PrintAgentBusyError","error","toMatchObject","name","code","agentId","message"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAS;AAE9CF,SAAS,6BAA6B;IAClCE,GAAG,gEAAgE;QAC/D,MAAMC,MAAM,MAAM,MAAM,CAAC;QAEzBF,OAAOE,KAAKC,cAAc,CAAC;QAC3B,MAAMC,YAAYF,IAAIG,mBAAmB;QAIzC,MAAMC,QAAQ,IAAIF,UAAU,YAAY;QAExCJ,OAAOM,OAAOC,aAAa,CAAC;YACxBC,MAAM;YACNC,MAAM;YACNC,SAAS;YACTC,SAAS;QACb;IACJ;AACJ"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/__tests__/print/PrintAgentStore.test.ts"],"sourcesContent":["import fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport { afterEach, describe, expect, it } from 'vitest';\n\nconst tempDirs: string[] = [];\n\nafterEach(() => {\n for (const dir of tempDirs.splice(0)) fs.rmSync(dir, { recursive: true, force: true });\n});\n\nasync function loadStore(): Promise<any> {\n const api = await import('../../index.js') as Record<string, unknown>;\n expect(api).toHaveProperty('PrintAgentStore');\n return api.PrintAgentStore;\n}\n\nfunction fixture(): { root: string; cwd: string; filePath: string } {\n const root = fs.mkdtempSync(path.join(os.tmpdir(), 'print-agent-store-'));\n tempDirs.push(root);\n const cwd = path.join(root, 'project');\n fs.mkdirSync(cwd);\n return { root, cwd, filePath: path.join(root, 'state', 'print-agents.json') };\n}\n\ndescribe('PrintAgentStore create/list/resolve', () => {\n it('creates distinct durable identities with a canonical cwd and lists them', async () => {\n const PrintAgentStore = await loadStore();\n const { cwd, filePath } = fixture();\n const store = new PrintAgentStore({ filePath, now: () => new Date('2026-08-07T09:00:00Z') });\n\n const agent = await store.create({ name: 'reviewer', cwd });\n\n expect(agent).toMatchObject({\n name: 'reviewer',\n provider: 'claude',\n mode: 'print',\n cwd: fs.realpathSync(cwd),\n state: 'ready',\n sessionHealth: 'uninitialized',\n activeRun: null,\n });\n expect(agent.id).toMatch(/^[0-9a-f-]{36}$/);\n expect(agent.providerSessionId).toMatch(/^[0-9a-f-]{36}$/);\n expect(agent.id).not.toBe(agent.providerSessionId);\n expect(await store.list()).toEqual([agent]);\n expect(fs.statSync(filePath).mode & 0o777).toBe(0o600);\n });\n\n it('resolves exact ids and names and rejects duplicate names', async () => {\n const PrintAgentStore = await loadStore();\n const { cwd, filePath } = fixture();\n const store = new PrintAgentStore({ filePath });\n const agent = await store.create({ name: 'Reviewer', cwd });\n\n expect(await store.resolve(agent.id)).toMatchObject({ id: agent.id });\n expect(await store.resolve('reviewer')).toMatchObject({ id: agent.id });\n expect(await store.resolve('view')).toBeNull();\n await expect(store.create({ name: 'reviewer', cwd })).rejects.toMatchObject({\n code: 'PRINT_AGENT_NAME_CONFLICT',\n });\n });\n\n it('rejects missing cwd, malformed storage, and symlinked store targets', async () => {\n const PrintAgentStore = await loadStore();\n const { root, cwd, filePath } = fixture();\n const store = new PrintAgentStore({ filePath });\n\n await expect(store.create({ name: 'missing', cwd: path.join(root, 'missing') }))\n .rejects.toMatchObject({ code: 'PRINT_AGENT_STORE' });\n\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, '{bad json', { mode: 0o600 });\n await expect(store.list()).rejects.toMatchObject({ code: 'PRINT_AGENT_STORE' });\n\n fs.rmSync(filePath);\n const target = path.join(root, 'target.json');\n fs.writeFileSync(target, JSON.stringify({ version: 1, agents: [] }));\n fs.symlinkSync(target, filePath);\n await expect(store.create({ name: 'unsafe', cwd })).rejects.toMatchObject({\n code: 'PRINT_AGENT_STORE',\n });\n });\n\n it('recovers an abandoned old mutation lock after a crash', async () => {\n const PrintAgentStore = await loadStore();\n const { cwd, filePath } = fixture();\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const lockPath = `${filePath}.lock`;\n fs.mkdirSync(lockPath);\n const old = new Date(Date.now() - 60_000);\n fs.utimesSync(lockPath, old, old);\n const store = new PrintAgentStore({ filePath, mutationLockStaleMs: 10 });\n\n await expect(store.create({ name: 'recovered', cwd })).resolves.toMatchObject({ name: 'recovered' });\n });\n});\n\ndescribe('PrintAgentStore run ownership', () => {\n it('fails fast when another exact owner is live and completes only for its token', async () => {\n const PrintAgentStore = await loadStore();\n const { cwd, filePath } = fixture();\n const live = new Map<number, string>([[process.pid, 'owner-start']]);\n const processInspector = { getIdentity: (pid: number) => {\n const startedAt = live.get(pid);\n return startedAt ? { pid, startedAt } : null;\n } };\n const store = new PrintAgentStore({ filePath, processInspector });\n const agent = await store.create({ name: 'runner', cwd });\n\n const acquired = await store.acquireRun(agent.id);\n await expect(store.acquireRun(agent.id)).rejects.toMatchObject({ code: 'PRINT_AGENT_BUSY' });\n await expect(store.completeRun(agent.id, 'wrong-token', {\n status: 'succeeded', exitCode: 0, summary: 'done', sessionHealth: 'healthy',\n })).rejects.toMatchObject({ code: 'PRINT_AGENT_STORE' });\n\n const completed = await store.completeRun(agent.id, acquired.token, {\n status: 'succeeded', exitCode: 0, summary: 'done', sessionHealth: 'healthy',\n });\n expect(completed).toMatchObject({ state: 'ready', sessionHealth: 'healthy', activeRun: null });\n });\n\n it('retains busy for a live provider then recovers a dead run without signaling it', async () => {\n const PrintAgentStore = await loadStore();\n const { cwd, filePath } = fixture();\n const live = new Map<number, string>([[process.pid, 'owner-start'], [4242, 'provider-start']]);\n const processInspector = { getIdentity: (pid: number) => {\n const startedAt = live.get(pid);\n return startedAt ? { pid, startedAt } : null;\n } };\n const first = new PrintAgentStore({ filePath, processInspector });\n const agent = await first.create({ name: 'recoverable', cwd });\n const run = await first.acquireRun(agent.id);\n await first.recordProviderProcess(agent.id, run.token, { pid: 4242, startedAt: 'provider-start' });\n\n live.delete(process.pid);\n await expect(first.acquireRun(agent.id)).rejects.toMatchObject({ code: 'PRINT_AGENT_BUSY' });\n\n live.delete(4242);\n live.set(process.pid, 'replacement-owner-start');\n const recovered = await first.acquireRun(agent.id);\n expect(recovered.agent).toMatchObject({\n state: 'running',\n lastResult: { status: 'interrupted' },\n });\n await first.completeRun(agent.id, recovered.token, {\n status: 'failed', exitCode: 1, summary: 'failed', sessionHealth: 'unknown',\n });\n });\n\n it('reconciles an old incomplete lock to degraded during list', async () => {\n const PrintAgentStore = await loadStore();\n const { root, cwd, filePath } = fixture();\n const live = new Map<number, string>([[process.pid, 'owner-start']]);\n const store = new PrintAgentStore({ filePath, incompleteLockGraceMs: 10, processInspector: {\n getIdentity: (pid: number) => {\n const startedAt = live.get(pid);\n return startedAt ? { pid, startedAt } : null;\n },\n } });\n const agent = await store.create({ name: 'crashed', cwd });\n await store.acquireRun(agent.id);\n const lockPath = path.join(root, 'state', 'print-agent-locks', `${agent.id}.lock`);\n fs.unlinkSync(path.join(lockPath, 'owner.json'));\n const old = new Date(Date.now() - 1000);\n fs.utimesSync(lockPath, old, old);\n live.clear();\n\n const listed = await store.list();\n\n expect(listed[0]).toMatchObject({\n state: 'degraded',\n sessionHealth: 'unknown',\n activeRun: null,\n lastResult: { status: 'interrupted' },\n });\n });\n\n it('rejects send acquisition when the bound cwd is replaced by a symlink', async () => {\n const PrintAgentStore = await loadStore();\n const { root, cwd, filePath } = fixture();\n const store = new PrintAgentStore({ filePath });\n const agent = await store.create({ name: 'bound', cwd });\n const moved = path.join(root, 'moved-project');\n const other = path.join(root, 'other-project');\n fs.renameSync(cwd, moved);\n fs.mkdirSync(other);\n fs.symlinkSync(other, cwd);\n\n await expect(store.acquireRun(agent.id)).rejects.toMatchObject({ code: 'PRINT_AGENT_STORE' });\n });\n});\n"],"names":["fs","os","path","afterEach","describe","expect","it","tempDirs","dir","splice","rmSync","recursive","force","loadStore","api","toHaveProperty","PrintAgentStore","fixture","root","mkdtempSync","join","tmpdir","push","cwd","mkdirSync","filePath","store","now","Date","agent","create","name","toMatchObject","provider","mode","realpathSync","state","sessionHealth","activeRun","id","toMatch","providerSessionId","not","toBe","list","toEqual","statSync","resolve","toBeNull","rejects","code","dirname","writeFileSync","target","JSON","stringify","version","agents","symlinkSync","lockPath","old","utimesSync","mutationLockStaleMs","resolves","live","Map","process","pid","processInspector","getIdentity","startedAt","get","acquired","acquireRun","completeRun","status","exitCode","summary","completed","token","first","run","recordProviderProcess","delete","set","recovered","lastResult","incompleteLockGraceMs","unlinkSync","clear","listed","moved","other","renameSync"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ClaudeCliProbe.d.ts","sourceRoot":"","sources":["../../src/print/ClaudeCliProbe.ts"],"names":[],"mappings":"AAIA,KAAK,UAAU,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACrD,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAKlE,MAAM,WAAW,qBAAqB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,IAAI,CAAC;CACf;AAED,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAO;gBAEhB,OAAO,GAAE,qBAA0B;IAQzC,QAAQ,IAAI,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAuBrE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/print/ClaudeCliProbe.ts"],"sourcesContent":["import { execFile } from 'child_process';\nimport { promisify } from 'util';\nimport { ClaudePrintError } from './PrintAgent.js';\n\ntype ExecResult = { stdout: string; stderr: string };\ntype Exec = (file: string, args: string[]) => Promise<ExecResult>;\n\nconst execFileAsync = promisify(execFile);\nconst REQUIRED = ['--print', '--session-id', '--resume', '--output-format', 'stream-json'];\n\nexport interface ClaudeCliProbeOptions {\n executable?: string;\n exec?: Exec;\n}\n\nexport class ClaudeCliProbe {\n private readonly executable: string;\n private readonly exec: Exec;\n\n constructor(options: ClaudeCliProbeOptions = {}) {\n this.executable = options.executable ?? 'claude';\n this.exec = options.exec ?? (async (file, args) => {\n const result = await execFileAsync(file, args, { encoding: 'utf8', maxBuffer: 1024 * 1024 });\n return { stdout: result.stdout, stderr: result.stderr };\n });\n }\n\n async validate(): Promise<{ executable: string; version: string }> {\n try {\n const versionResult = await this.exec(this.executable, ['--version']);\n const helpResult = await this.exec(this.executable, ['--help']);\n const missing = REQUIRED.filter((capability) => !helpResult.stdout.includes(capability));\n if (missing.length > 0) {\n throw new ClaudePrintError(\n `Claude CLI does not support required print-mode capabilities: ${missing.join(', ')}.`,\n 'CLAUDE_CLI_UNSUPPORTED',\n );\n }\n return {\n executable: this.executable,\n version: sanitize(versionResult.stdout, 256) || 'unknown',\n };\n } catch (error) {\n if (error instanceof ClaudePrintError) throw error;\n throw new ClaudePrintError(\n `Claude CLI validation failed: ${sanitize((error as Error).message, 512)}`,\n 'CLAUDE_CLI_UNAVAILABLE',\n );\n }\n }\n}\n\nfunction sanitize(value: string, max: number): string {\n return Array.from(value, (character) => {\n const code = character.charCodeAt(0);\n return code <= 31 || code === 127 ? ' ' : character;\n }).join('').trim().slice(0, max);\n}\n"],"names":["execFile","promisify","ClaudePrintError","execFileAsync","REQUIRED","ClaudeCliProbe","executable","exec","options","file","args","result","encoding","maxBuffer","stdout","stderr","validate","versionResult","helpResult","missing","filter","capability","includes","length","join","version","sanitize","error","message","value","max","Array","from","character","code","charCodeAt","trim","slice"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,gBAAgB;AACzC,SAASC,SAAS,QAAQ,OAAO;AACjC,SAASC,gBAAgB,QAAQ,kBAAkB;AAKnD,MAAMC,gBAAgBF,UAAUD;AAChC,MAAMI,WAAW;IAAC;IAAW;IAAgB;IAAY;IAAmB;CAAc;AAO1F,OAAO,MAAMC;IACQC,WAAmB;IACnBC,KAAW;IAE5B,YAAYC,UAAiC,CAAC,CAAC,CAAE;QAC7C,IAAI,CAACF,UAAU,GAAGE,QAAQF,UAAU,IAAI;QACxC,IAAI,CAACC,IAAI,GAAGC,QAAQD,IAAI,IAAK,CAAA,OAAOE,MAAMC;YACtC,MAAMC,SAAS,MAAMR,cAAcM,MAAMC,MAAM;gBAAEE,UAAU;gBAAQC,WAAW,OAAO;YAAK;YAC1F,OAAO;gBAAEC,QAAQH,OAAOG,MAAM;gBAAEC,QAAQJ,OAAOI,MAAM;YAAC;QAC1D,CAAA;IACJ;IAEA,MAAMC,WAA6D;QAC/D,IAAI;YACA,MAAMC,gBAAgB,MAAM,IAAI,CAACV,IAAI,CAAC,IAAI,CAACD,UAAU,EAAE;gBAAC;aAAY;YACpE,MAAMY,aAAa,MAAM,IAAI,CAACX,IAAI,CAAC,IAAI,CAACD,UAAU,EAAE;gBAAC;aAAS;YAC9D,MAAMa,UAAUf,SAASgB,MAAM,CAAC,CAACC,aAAe,CAACH,WAAWJ,MAAM,CAACQ,QAAQ,CAACD;YAC5E,IAAIF,QAAQI,MAAM,GAAG,GAAG;gBACpB,MAAM,IAAIrB,iBACN,CAAC,8DAA8D,EAAEiB,QAAQK,IAAI,CAAC,MAAM,CAAC,CAAC,EACtF;YAER;YACA,OAAO;gBACHlB,YAAY,IAAI,CAACA,UAAU;gBAC3BmB,SAASC,SAAST,cAAcH,MAAM,EAAE,QAAQ;YACpD;QACJ,EAAE,OAAOa,OAAO;YACZ,IAAIA,iBAAiBzB,kBAAkB,MAAMyB;YAC7C,MAAM,IAAIzB,iBACN,CAAC,8BAA8B,EAAEwB,SAAS,AAACC,MAAgBC,OAAO,EAAE,MAAM,EAC1E;QAER;IACJ;AACJ;AAEA,SAASF,SAASG,KAAa,EAAEC,GAAW;IACxC,OAAOC,MAAMC,IAAI,CAACH,OAAO,CAACI;QACtB,MAAMC,OAAOD,UAAUE,UAAU,CAAC;QAClC,OAAOD,QAAQ,MAAMA,SAAS,MAAM,MAAMD;IAC9C,GAAGT,IAAI,CAAC,IAAIY,IAAI,GAAGC,KAAK,CAAC,GAAGP;AAChC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ClaudePrintAgentService.d.ts","sourceRoot":"","sources":["../../src/print/ClaudePrintAgentService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGnE,OAAO,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAmB,KAAK,qBAAqB,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE5G,UAAU,SAAS;IACf,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1D,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9B,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;IACtE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3F,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC3F;AAED,UAAU,SAAS;IAAG,QAAQ,IAAI,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE;AACpF,UAAU,UAAU;IAAG,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;CAAE;AAE7G,MAAM,WAAW,8BAA8B;IAC3C,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAsB,SAAQ,oBAAoB;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,uBAAuB;IAChC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAS;gBAEzB,OAAO,GAAE,8BAAmC;IAOlD,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC;IAKzD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAoChF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/print/ClaudePrintAgentService.ts"],"sourcesContent":["import type { PrintAgent, ProcessIdentity } from './PrintAgent.js';\nimport { ClaudePrintError, PrintAgentNotFoundError } from './PrintAgent.js';\nimport { ClaudeCliProbe } from './ClaudeCliProbe.js';\nimport { ClaudePrintRunner, type ClaudePrintRunResult } from './ClaudePrintRunner.js';\nimport { PrintAgentStore, type CreatePrintAgentInput, type PrintRunCompletion } from './PrintAgentStore.js';\n\ninterface StoreLike {\n create(input: CreatePrintAgentInput): Promise<PrintAgent>;\n list(): Promise<PrintAgent[]>;\n resolve(reference: string): Promise<PrintAgent | PrintAgent[] | null>;\n acquireRun(id: string): Promise<{ agent: PrintAgent; token: string }>;\n recordProviderProcess(id: string, token: string, identity: ProcessIdentity): Promise<void>;\n completeRun(id: string, token: string, result: PrintRunCompletion): Promise<PrintAgent>;\n}\n\ninterface ProbeLike { validate(): Promise<{ executable: string; version: string }> }\ninterface RunnerLike { run(request: Parameters<ClaudePrintRunner['run']>[0]): Promise<ClaudePrintRunResult> }\n\nexport interface ClaudePrintAgentServiceOptions {\n store?: StoreLike;\n probe?: ProbeLike;\n runner?: RunnerLike;\n executable?: string;\n}\n\nexport interface ClaudePrintSendResult extends ClaudePrintRunResult {\n agentId: string;\n agentName: string;\n}\n\nexport class ClaudePrintAgentService {\n readonly store: StoreLike;\n private readonly probe: ProbeLike;\n private readonly runner: RunnerLike;\n private readonly executable?: string;\n\n constructor(options: ClaudePrintAgentServiceOptions = {}) {\n this.store = options.store ?? new PrintAgentStore();\n this.probe = options.probe ?? new ClaudeCliProbe();\n this.runner = options.runner ?? new ClaudePrintRunner();\n this.executable = options.executable;\n }\n\n async create(input: CreatePrintAgentInput): Promise<PrintAgent> {\n await this.probe.validate();\n return this.store.create(input);\n }\n\n async send(reference: string, prompt: string): Promise<ClaudePrintSendResult> {\n const resolved = await this.store.resolve(reference);\n if (!resolved) throw new PrintAgentNotFoundError(reference);\n if (Array.isArray(resolved)) {\n throw new ClaudePrintError(`Multiple print agents match \"${reference}\".`, 'PRINT_AGENT_AMBIGUOUS');\n }\n const acquired = await this.store.acquireRun(resolved.id);\n try {\n const result = await this.runner.run({\n agent: acquired.agent,\n prompt,\n executable: this.executable,\n firstRun: acquired.agent.sessionHealth === 'uninitialized',\n onSpawn: (identity) => this.store.recordProviderProcess(resolved.id, acquired.token, identity),\n });\n await this.store.completeRun(resolved.id, acquired.token, {\n status: 'succeeded',\n exitCode: result.exitCode,\n summary: sanitize(result.result, 4096),\n sessionHealth: 'healthy',\n });\n return { ...result, agentId: resolved.id, agentName: resolved.name };\n } catch (error) {\n const failure = error instanceof Error ? error : new Error(String(error));\n const sessionHealth = error instanceof ClaudePrintError && error.code === 'CLAUDE_SESSION_MISMATCH'\n ? 'mismatch' as const\n : 'unknown' as const;\n await this.store.completeRun(resolved.id, acquired.token, {\n status: 'failed',\n exitCode: null,\n summary: sanitize(failure.message, 4096),\n sessionHealth,\n });\n throw error;\n }\n }\n}\n\nfunction sanitize(value: string, max: number): string {\n return Array.from(value, (character) => {\n const code = character.charCodeAt(0);\n return (code <= 8 || code === 11 || code === 12 || (code >= 14 && code <= 31) || code === 127)\n ? ' '\n : character;\n }).join('').trim().slice(0, max);\n}\n"],"names":["ClaudePrintError","PrintAgentNotFoundError","ClaudeCliProbe","ClaudePrintRunner","PrintAgentStore","ClaudePrintAgentService","store","probe","runner","executable","options","create","input","validate","send","reference","prompt","resolved","resolve","Array","isArray","acquired","acquireRun","id","result","run","agent","firstRun","sessionHealth","onSpawn","identity","recordProviderProcess","token","completeRun","status","exitCode","summary","sanitize","agentId","agentName","name","error","failure","Error","String","code","message","value","max","from","character","charCodeAt","join","trim","slice"],"mappings":"AACA,SAASA,gBAAgB,EAAEC,uBAAuB,QAAQ,kBAAkB;AAC5E,SAASC,cAAc,QAAQ,sBAAsB;AACrD,SAASC,iBAAiB,QAAmC,yBAAyB;AACtF,SAASC,eAAe,QAA6D,uBAAuB;AA0B5G,OAAO,MAAMC;IACAC,MAAiB;IACTC,MAAiB;IACjBC,OAAmB;IACnBC,WAAoB;IAErC,YAAYC,UAA0C,CAAC,CAAC,CAAE;QACtD,IAAI,CAACJ,KAAK,GAAGI,QAAQJ,KAAK,IAAI,IAAIF;QAClC,IAAI,CAACG,KAAK,GAAGG,QAAQH,KAAK,IAAI,IAAIL;QAClC,IAAI,CAACM,MAAM,GAAGE,QAAQF,MAAM,IAAI,IAAIL;QACpC,IAAI,CAACM,UAAU,GAAGC,QAAQD,UAAU;IACxC;IAEA,MAAME,OAAOC,KAA4B,EAAuB;QAC5D,MAAM,IAAI,CAACL,KAAK,CAACM,QAAQ;QACzB,OAAO,IAAI,CAACP,KAAK,CAACK,MAAM,CAACC;IAC7B;IAEA,MAAME,KAAKC,SAAiB,EAAEC,MAAc,EAAkC;QAC1E,MAAMC,WAAW,MAAM,IAAI,CAACX,KAAK,CAACY,OAAO,CAACH;QAC1C,IAAI,CAACE,UAAU,MAAM,IAAIhB,wBAAwBc;QACjD,IAAII,MAAMC,OAAO,CAACH,WAAW;YACzB,MAAM,IAAIjB,iBAAiB,CAAC,6BAA6B,EAAEe,UAAU,EAAE,CAAC,EAAE;QAC9E;QACA,MAAMM,WAAW,MAAM,IAAI,CAACf,KAAK,CAACgB,UAAU,CAACL,SAASM,EAAE;QACxD,IAAI;YACA,MAAMC,SAAS,MAAM,IAAI,CAAChB,MAAM,CAACiB,GAAG,CAAC;gBACjCC,OAAOL,SAASK,KAAK;gBACrBV;gBACAP,YAAY,IAAI,CAACA,UAAU;gBAC3BkB,UAAUN,SAASK,KAAK,CAACE,aAAa,KAAK;gBAC3CC,SAAS,CAACC,WAAa,IAAI,CAACxB,KAAK,CAACyB,qBAAqB,CAACd,SAASM,EAAE,EAAEF,SAASW,KAAK,EAAEF;YACzF;YACA,MAAM,IAAI,CAACxB,KAAK,CAAC2B,WAAW,CAAChB,SAASM,EAAE,EAAEF,SAASW,KAAK,EAAE;gBACtDE,QAAQ;gBACRC,UAAUX,OAAOW,QAAQ;gBACzBC,SAASC,SAASb,OAAOA,MAAM,EAAE;gBACjCI,eAAe;YACnB;YACA,OAAO;gBAAE,GAAGJ,MAAM;gBAAEc,SAASrB,SAASM,EAAE;gBAAEgB,WAAWtB,SAASuB,IAAI;YAAC;QACvE,EAAE,OAAOC,OAAO;YACZ,MAAMC,UAAUD,iBAAiBE,QAAQF,QAAQ,IAAIE,MAAMC,OAAOH;YAClE,MAAMb,gBAAgBa,iBAAiBzC,oBAAoByC,MAAMI,IAAI,KAAK,4BACpE,aACA;YACN,MAAM,IAAI,CAACvC,KAAK,CAAC2B,WAAW,CAAChB,SAASM,EAAE,EAAEF,SAASW,KAAK,EAAE;gBACtDE,QAAQ;gBACRC,UAAU;gBACVC,SAASC,SAASK,QAAQI,OAAO,EAAE;gBACnClB;YACJ;YACA,MAAMa;QACV;IACJ;AACJ;AAEA,SAASJ,SAASU,KAAa,EAAEC,GAAW;IACxC,OAAO7B,MAAM8B,IAAI,CAACF,OAAO,CAACG;QACtB,MAAML,OAAOK,UAAUC,UAAU,CAAC;QAClC,OAAO,AAACN,QAAQ,KAAKA,SAAS,MAAMA,SAAS,MAAOA,QAAQ,MAAMA,QAAQ,MAAOA,SAAS,MACpF,MACAK;IACV,GAAGE,IAAI,CAAC,IAAIC,IAAI,GAAGC,KAAK,CAAC,GAAGN;AAChC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ClaudePrintRunner.d.ts","sourceRoot":"","sources":["../../src/print/ClaudePrintRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,8BAA8B,EAAE,KAAK,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACvH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEnE,OAAO,EAAyB,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEpF,KAAK,KAAK,GAAG,CACT,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,wBAAwB,GAAG;IAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,KACtE,8BAA8B,CAAC;AAEpC,MAAM,WAAW,qBAAqB;IAClC,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,oBAAoB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACrC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,OAAO,GAAE,wBAA6B;IAM5C,GAAG,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAgG3E"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/print/ClaudePrintRunner.ts"],"sourcesContent":["import { spawn as nodeSpawn, type ChildProcessWithoutNullStreams, type SpawnOptionsWithoutStdio } from 'child_process';\nimport type { PrintAgent, ProcessIdentity } from './PrintAgent.js';\nimport { ClaudePrintError } from './PrintAgent.js';\nimport { LocalProcessInspector, type ProcessInspector } from './PrintAgentStore.js';\n\ntype Spawn = (\n command: string,\n args: readonly string[],\n options: SpawnOptionsWithoutStdio & { stdio: ['pipe', 'pipe', 'pipe'] },\n) => ChildProcessWithoutNullStreams;\n\nexport interface ClaudePrintRunRequest {\n agent: PrintAgent;\n prompt: string;\n executable?: string;\n firstRun: boolean;\n onSpawn(identity: ProcessIdentity): Promise<void>;\n}\n\nexport interface ClaudePrintRunResult {\n sessionId: string;\n result: string;\n exitCode: number;\n}\n\nexport interface ClaudePrintRunnerOptions {\n spawn?: Spawn;\n processInspector?: ProcessInspector;\n maxLineBytes?: number;\n}\n\nexport class ClaudePrintRunner {\n private readonly spawn: Spawn;\n private readonly processInspector: ProcessInspector;\n private readonly maxLineBytes: number;\n\n constructor(options: ClaudePrintRunnerOptions = {}) {\n this.spawn = options.spawn ?? (nodeSpawn as Spawn);\n this.processInspector = options.processInspector ?? new LocalProcessInspector();\n this.maxLineBytes = options.maxLineBytes ?? 1024 * 1024;\n }\n\n async run(request: ClaudePrintRunRequest): Promise<ClaudePrintRunResult> {\n const sessionArgs = request.firstRun\n ? ['--session-id', request.agent.providerSessionId]\n : ['--resume', request.agent.providerSessionId];\n const args = ['-p', ...sessionArgs, '--output-format', 'stream-json', '--verbose'];\n const child = this.spawn(request.executable ?? 'claude', args, {\n cwd: request.agent.cwd,\n shell: false,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n if (!child.pid) {\n child.kill();\n throw new ClaudePrintError('Claude process did not provide a PID.', 'CLAUDE_PROCESS_IDENTITY');\n }\n const identity = this.processInspector.getIdentity(child.pid);\n if (!identity) {\n child.kill();\n throw new ClaudePrintError('Cannot verify Claude process identity.', 'CLAUDE_PROCESS_IDENTITY');\n }\n\n let buffer = Buffer.alloc(0);\n let terminal: ClaudePrintRunResult | null = null;\n let protocolError: ClaudePrintError | null = null;\n\n child.stdout.on('data', (chunk: Buffer | string) => {\n if (protocolError) return;\n buffer = Buffer.concat([buffer, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)]);\n if (buffer.length > this.maxLineBytes && buffer.indexOf(0x0a) < 0) {\n protocolError = new ClaudePrintError('Claude stream line exceeded the safety limit.', 'CLAUDE_STREAM_OVERSIZED');\n return;\n }\n let newline: number;\n while ((newline = buffer.indexOf(0x0a)) >= 0) {\n const line = buffer.subarray(0, newline);\n buffer = buffer.subarray(newline + 1);\n if (line.length === 0) continue;\n if (line.length > this.maxLineBytes) {\n protocolError = new ClaudePrintError('Claude stream line exceeded the safety limit.', 'CLAUDE_STREAM_OVERSIZED');\n return;\n }\n try {\n const value = JSON.parse(line.toString('utf8')) as unknown;\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new ClaudePrintError('Claude emitted a non-object stream message.', 'CLAUDE_STREAM_INVALID');\n }\n const event = value as Record<string, unknown>;\n if (typeof event.session_id === 'string' && event.session_id !== request.agent.providerSessionId) {\n throw new ClaudePrintError('Claude returned a different session identity.', 'CLAUDE_SESSION_MISMATCH');\n }\n if (event.type === 'result') {\n if (terminal) throw new ClaudePrintError('Claude emitted more than one terminal result.', 'CLAUDE_STREAM_INVALID');\n if (typeof event.session_id !== 'string' || typeof event.result !== 'string') {\n throw new ClaudePrintError('Claude emitted an invalid terminal result.', 'CLAUDE_STREAM_INVALID');\n }\n terminal = { sessionId: event.session_id, result: event.result, exitCode: 0 };\n }\n } catch (error) {\n protocolError = error instanceof ClaudePrintError\n ? error\n : new ClaudePrintError('Claude emitted malformed stream JSON.', 'CLAUDE_STREAM_INVALID');\n return;\n }\n }\n });\n // Drain provider diagnostics without reflecting potentially sensitive prompt/tool data.\n child.stderr.resume();\n\n const closed = new Promise<{ code: number | null; signal: NodeJS.Signals | null }>((resolve, reject) => {\n child.once('error', reject);\n child.once('close', (code, signal) => resolve({ code, signal }));\n });\n\n try {\n await request.onSpawn(identity);\n } catch (error) {\n child.kill();\n throw error;\n }\n\n child.stdin.end(request.prompt);\n const { code, signal } = await closed;\n\n if (protocolError) throw protocolError;\n if (buffer.length > 0) {\n throw new ClaudePrintError('Claude stream ended with incomplete JSON.', 'CLAUDE_STREAM_INVALID');\n }\n if (code !== 0) {\n throw new ClaudePrintError(\n `Claude print run failed${signal ? ` (${signal})` : '.'}`,\n 'CLAUDE_PROCESS_FAILED',\n );\n }\n if (!terminal) throw new ClaudePrintError('Claude stream ended without a terminal result.', 'CLAUDE_RESULT_MISSING');\n const finalResult = terminal as ClaudePrintRunResult;\n return { sessionId: finalResult.sessionId, result: finalResult.result, exitCode: code };\n }\n}\n"],"names":["spawn","nodeSpawn","ClaudePrintError","LocalProcessInspector","ClaudePrintRunner","processInspector","maxLineBytes","options","run","request","sessionArgs","firstRun","agent","providerSessionId","args","child","executable","cwd","shell","stdio","pid","kill","identity","getIdentity","buffer","Buffer","alloc","terminal","protocolError","stdout","on","chunk","concat","isBuffer","from","length","indexOf","newline","line","subarray","value","JSON","parse","toString","Array","isArray","event","session_id","type","result","sessionId","exitCode","error","stderr","resume","closed","Promise","resolve","reject","once","code","signal","onSpawn","stdin","end","prompt","finalResult"],"mappings":"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"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
export type PrintAgentState = 'ready' | 'running' | 'degraded';
|
|
2
|
-
export type PrintSessionHealth = 'uninitialized' | 'healthy' | 'unknown' | 'mismatch';
|
|
3
|
-
export type PrintRunStatus = 'succeeded' | 'failed' | 'interrupted';
|
|
4
|
-
export interface ProcessIdentity {
|
|
5
|
-
pid: number;
|
|
6
|
-
startedAt: string;
|
|
7
|
-
}
|
|
8
|
-
export interface PrintActiveRun {
|
|
9
|
-
token: string;
|
|
10
|
-
owner: ProcessIdentity;
|
|
11
|
-
provider: ProcessIdentity | null;
|
|
12
|
-
startedAt: string;
|
|
13
|
-
}
|
|
14
|
-
export interface PrintLastResult {
|
|
15
|
-
status: PrintRunStatus;
|
|
16
|
-
completedAt: string;
|
|
17
|
-
exitCode: number | null;
|
|
18
|
-
summary: string;
|
|
19
|
-
}
|
|
20
|
-
export interface PrintAgent {
|
|
21
|
-
id: string;
|
|
22
|
-
name: string;
|
|
23
|
-
provider: 'claude';
|
|
24
|
-
mode: 'print';
|
|
25
|
-
cwd: string;
|
|
26
|
-
providerSessionId: string;
|
|
27
|
-
state: PrintAgentState;
|
|
28
|
-
sessionHealth: PrintSessionHealth;
|
|
29
|
-
createdAt: string;
|
|
30
|
-
updatedAt: string;
|
|
31
|
-
lastActiveAt: string | null;
|
|
32
|
-
lastResult: PrintLastResult | null;
|
|
33
|
-
activeRun: PrintActiveRun | null;
|
|
34
|
-
}
|
|
35
|
-
export declare class PrintAgentError extends Error {
|
|
36
|
-
readonly code: string;
|
|
37
|
-
constructor(message: string, code: string);
|
|
38
|
-
}
|
|
39
|
-
export declare class PrintAgentBusyError extends PrintAgentError {
|
|
40
|
-
readonly agentId: string;
|
|
41
|
-
constructor(agentId: string, agentName: string);
|
|
42
|
-
}
|
|
43
|
-
export declare class PrintAgentNotFoundError extends PrintAgentError {
|
|
44
|
-
readonly reference: string;
|
|
45
|
-
constructor(reference: string);
|
|
46
|
-
}
|
|
47
|
-
export declare class PrintAgentStoreError extends PrintAgentError {
|
|
48
|
-
constructor(message: string);
|
|
49
|
-
}
|
|
50
|
-
export declare class PrintAgentNameConflictError extends PrintAgentError {
|
|
51
|
-
readonly agentName: string;
|
|
52
|
-
constructor(agentName: string);
|
|
53
|
-
}
|
|
54
|
-
export declare class ClaudePrintError extends PrintAgentError {
|
|
55
|
-
constructor(message: string, code?: string);
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=PrintAgent.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PrintAgent.d.ts","sourceRoot":"","sources":["../../src/print/PrintAgent.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;AAC/D,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AACtF,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEpE,MAAM,WAAW,eAAe;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,cAAc,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,eAAe,CAAC;IACvB,aAAa,EAAE,kBAAkB,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,cAAc,GAAG,IAAI,CAAC;CACpC;AAED,qBAAa,eAAgB,SAAQ,KAAK;aAGlB,IAAI,EAAE,MAAM;gBAD5B,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM;CAKnC;AAED,qBAAa,mBAAoB,SAAQ,eAAe;aAEhC,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM,EAC/B,SAAS,EAAE,MAAM;CAKxB;AAED,qBAAa,uBAAwB,SAAQ,eAAe;aAC5B,SAAS,EAAE,MAAM;gBAAjB,SAAS,EAAE,MAAM;CAIhD;AAED,qBAAa,oBAAqB,SAAQ,eAAe;gBACzC,OAAO,EAAE,MAAM;CAI9B;AAED,qBAAa,2BAA4B,SAAQ,eAAe;aAChC,SAAS,EAAE,MAAM;gBAAjB,SAAS,EAAE,MAAM;CAIhD;AAED,qBAAa,gBAAiB,SAAQ,eAAe;gBACrC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAwB;CAI5D"}
|
package/dist/print/PrintAgent.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
export class PrintAgentError extends Error {
|
|
2
|
-
code;
|
|
3
|
-
constructor(message, code){
|
|
4
|
-
super(message), this.code = code;
|
|
5
|
-
this.name = 'PrintAgentError';
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
export class PrintAgentBusyError extends PrintAgentError {
|
|
9
|
-
agentId;
|
|
10
|
-
constructor(agentId, agentName){
|
|
11
|
-
super(`Print agent "${agentName}" is busy.`, 'PRINT_AGENT_BUSY'), this.agentId = agentId;
|
|
12
|
-
this.name = 'PrintAgentBusyError';
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
export class PrintAgentNotFoundError extends PrintAgentError {
|
|
16
|
-
reference;
|
|
17
|
-
constructor(reference){
|
|
18
|
-
super(`Print agent "${reference}" was not found.`, 'PRINT_AGENT_NOT_FOUND'), this.reference = reference;
|
|
19
|
-
this.name = 'PrintAgentNotFoundError';
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
export class PrintAgentStoreError extends PrintAgentError {
|
|
23
|
-
constructor(message){
|
|
24
|
-
super(message, 'PRINT_AGENT_STORE');
|
|
25
|
-
this.name = 'PrintAgentStoreError';
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
export class PrintAgentNameConflictError extends PrintAgentError {
|
|
29
|
-
agentName;
|
|
30
|
-
constructor(agentName){
|
|
31
|
-
super(`Print agent name "${agentName}" is already in use.`, 'PRINT_AGENT_NAME_CONFLICT'), this.agentName = agentName;
|
|
32
|
-
this.name = 'PrintAgentNameConflictError';
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
export class ClaudePrintError extends PrintAgentError {
|
|
36
|
-
constructor(message, code = 'CLAUDE_PRINT_FAILED'){
|
|
37
|
-
super(message, code);
|
|
38
|
-
this.name = 'ClaudePrintError';
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
//# sourceMappingURL=PrintAgent.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/print/PrintAgent.ts"],"sourcesContent":["export type PrintAgentState = 'ready' | 'running' | 'degraded';\nexport type PrintSessionHealth = 'uninitialized' | 'healthy' | 'unknown' | 'mismatch';\nexport type PrintRunStatus = 'succeeded' | 'failed' | 'interrupted';\n\nexport interface ProcessIdentity {\n pid: number;\n startedAt: string;\n}\n\nexport interface PrintActiveRun {\n token: string;\n owner: ProcessIdentity;\n provider: ProcessIdentity | null;\n startedAt: string;\n}\n\nexport interface PrintLastResult {\n status: PrintRunStatus;\n completedAt: string;\n exitCode: number | null;\n summary: string;\n}\n\nexport interface PrintAgent {\n id: string;\n name: string;\n provider: 'claude';\n mode: 'print';\n cwd: string;\n providerSessionId: string;\n state: PrintAgentState;\n sessionHealth: PrintSessionHealth;\n createdAt: string;\n updatedAt: string;\n lastActiveAt: string | null;\n lastResult: PrintLastResult | null;\n activeRun: PrintActiveRun | null;\n}\n\nexport class PrintAgentError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n ) {\n super(message);\n this.name = 'PrintAgentError';\n }\n}\n\nexport class PrintAgentBusyError extends PrintAgentError {\n constructor(\n public readonly agentId: string,\n agentName: string,\n ) {\n super(`Print agent \"${agentName}\" is busy.`, 'PRINT_AGENT_BUSY');\n this.name = 'PrintAgentBusyError';\n }\n}\n\nexport class PrintAgentNotFoundError extends PrintAgentError {\n constructor(public readonly reference: string) {\n super(`Print agent \"${reference}\" was not found.`, 'PRINT_AGENT_NOT_FOUND');\n this.name = 'PrintAgentNotFoundError';\n }\n}\n\nexport class PrintAgentStoreError extends PrintAgentError {\n constructor(message: string) {\n super(message, 'PRINT_AGENT_STORE');\n this.name = 'PrintAgentStoreError';\n }\n}\n\nexport class PrintAgentNameConflictError extends PrintAgentError {\n constructor(public readonly agentName: string) {\n super(`Print agent name \"${agentName}\" is already in use.`, 'PRINT_AGENT_NAME_CONFLICT');\n this.name = 'PrintAgentNameConflictError';\n }\n}\n\nexport class ClaudePrintError extends PrintAgentError {\n constructor(message: string, code = 'CLAUDE_PRINT_FAILED') {\n super(message, code);\n this.name = 'ClaudePrintError';\n }\n}\n"],"names":["PrintAgentError","Error","message","code","name","PrintAgentBusyError","agentId","agentName","PrintAgentNotFoundError","reference","PrintAgentStoreError","PrintAgentNameConflictError","ClaudePrintError"],"mappings":"AAuCA,OAAO,MAAMA,wBAAwBC;;IACjC,YACIC,OAAe,EACf,AAAgBC,IAAY,CAC9B;QACE,KAAK,CAACD,eAFUC,OAAAA;QAGhB,IAAI,CAACC,IAAI,GAAG;IAChB;AACJ;AAEA,OAAO,MAAMC,4BAA4BL;;IACrC,YACI,AAAgBM,OAAe,EAC/BC,SAAiB,CACnB;QACE,KAAK,CAAC,CAAC,aAAa,EAAEA,UAAU,UAAU,CAAC,EAAE,0BAH7BD,UAAAA;QAIhB,IAAI,CAACF,IAAI,GAAG;IAChB;AACJ;AAEA,OAAO,MAAMI,gCAAgCR;;IACzC,YAAY,AAAgBS,SAAiB,CAAE;QAC3C,KAAK,CAAC,CAAC,aAAa,EAAEA,UAAU,gBAAgB,CAAC,EAAE,+BAD3BA,YAAAA;QAExB,IAAI,CAACL,IAAI,GAAG;IAChB;AACJ;AAEA,OAAO,MAAMM,6BAA6BV;IACtC,YAAYE,OAAe,CAAE;QACzB,KAAK,CAACA,SAAS;QACf,IAAI,CAACE,IAAI,GAAG;IAChB;AACJ;AAEA,OAAO,MAAMO,oCAAoCX;;IAC7C,YAAY,AAAgBO,SAAiB,CAAE;QAC3C,KAAK,CAAC,CAAC,kBAAkB,EAAEA,UAAU,oBAAoB,CAAC,EAAE,mCADpCA,YAAAA;QAExB,IAAI,CAACH,IAAI,GAAG;IAChB;AACJ;AAEA,OAAO,MAAMQ,yBAAyBZ;IAClC,YAAYE,OAAe,EAAEC,OAAO,qBAAqB,CAAE;QACvD,KAAK,CAACD,SAASC;QACf,IAAI,CAACC,IAAI,GAAG;IAChB;AACJ"}
|