@ai-devkit/agent-manager 0.25.0 → 0.26.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/README.md +14 -0
- package/dist/__tests__/print/ClaudeCliProbe.test.js +53 -0
- package/dist/__tests__/print/ClaudeCliProbe.test.js.map +1 -0
- package/dist/__tests__/print/ClaudePrintAgent.integration.test.js +69 -0
- package/dist/__tests__/print/ClaudePrintAgent.integration.test.js.map +1 -0
- package/dist/__tests__/print/ClaudePrintAgentService.test.js +108 -0
- package/dist/__tests__/print/ClaudePrintAgentService.test.js.map +1 -0
- package/dist/__tests__/print/ClaudePrintRunner.test.js +187 -0
- package/dist/__tests__/print/ClaudePrintRunner.test.js.map +1 -0
- package/dist/__tests__/print/PrintAgent.test.js +17 -0
- package/dist/__tests__/print/PrintAgent.test.js.map +1 -0
- package/dist/__tests__/print/PrintAgentStore.test.js +307 -0
- package/dist/__tests__/print/PrintAgentStore.test.js.map +1 -0
- package/dist/__tests__/terminal/TmuxManager.test.js +9 -0
- package/dist/__tests__/terminal/TmuxManager.test.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/print/ClaudeCliProbe.d.ts +20 -0
- package/dist/print/ClaudeCliProbe.d.ts.map +1 -0
- package/dist/print/ClaudeCliProbe.js +57 -0
- package/dist/print/ClaudeCliProbe.js.map +1 -0
- package/dist/print/ClaudePrintAgentService.d.ts +44 -0
- package/dist/print/ClaudePrintAgentService.d.ts.map +1 -0
- package/dist/print/ClaudePrintAgentService.js +66 -0
- package/dist/print/ClaudePrintAgentService.js.map +1 -0
- package/dist/print/ClaudePrintRunner.d.ts +32 -0
- package/dist/print/ClaudePrintRunner.d.ts.map +1 -0
- package/dist/print/ClaudePrintRunner.js +128 -0
- package/dist/print/ClaudePrintRunner.js.map +1 -0
- package/dist/print/PrintAgent.d.ts +57 -0
- package/dist/print/PrintAgent.d.ts.map +1 -0
- package/dist/print/PrintAgent.js +42 -0
- package/dist/print/PrintAgent.js.map +1 -0
- package/dist/print/PrintAgentStore.d.ts +69 -0
- package/dist/print/PrintAgentStore.d.ts.map +1 -0
- package/dist/print/PrintAgentStore.js +484 -0
- package/dist/print/PrintAgentStore.js.map +1 -0
- package/dist/terminal/TmuxManager.d.ts +2 -2
- package/dist/terminal/TmuxManager.d.ts.map +1 -1
- package/dist/terminal/TmuxManager.js +5 -7
- package/dist/terminal/TmuxManager.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/fixtures/fake-claude.cjs +24 -0
- package/src/__tests__/print/ClaudeCliProbe.test.ts +32 -0
- package/src/__tests__/print/ClaudePrintAgent.integration.test.ts +56 -0
- package/src/__tests__/print/ClaudePrintAgentService.test.ts +46 -0
- package/src/__tests__/print/ClaudePrintRunner.test.ts +105 -0
- package/src/__tests__/print/PrintAgent.test.ts +21 -0
- package/src/__tests__/print/PrintAgentStore.test.ts +192 -0
- package/src/__tests__/terminal/TmuxManager.test.ts +10 -0
- package/src/index.ts +39 -0
- package/src/print/ClaudeCliProbe.ts +58 -0
- package/src/print/ClaudePrintAgentService.ts +94 -0
- package/src/print/ClaudePrintRunner.ts +139 -0
- package/src/print/PrintAgent.ts +86 -0
- package/src/print/PrintAgentStore.ts +503 -0
- package/src/terminal/TmuxManager.ts +5 -7
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ClaudePrintError, PrintAgentNotFoundError } from './PrintAgent.js';
|
|
2
|
+
import { ClaudeCliProbe } from './ClaudeCliProbe.js';
|
|
3
|
+
import { ClaudePrintRunner } from './ClaudePrintRunner.js';
|
|
4
|
+
import { PrintAgentStore } from './PrintAgentStore.js';
|
|
5
|
+
export class ClaudePrintAgentService {
|
|
6
|
+
store;
|
|
7
|
+
probe;
|
|
8
|
+
runner;
|
|
9
|
+
executable;
|
|
10
|
+
constructor(options = {}){
|
|
11
|
+
this.store = options.store ?? new PrintAgentStore();
|
|
12
|
+
this.probe = options.probe ?? new ClaudeCliProbe();
|
|
13
|
+
this.runner = options.runner ?? new ClaudePrintRunner();
|
|
14
|
+
this.executable = options.executable;
|
|
15
|
+
}
|
|
16
|
+
async create(input) {
|
|
17
|
+
await this.probe.validate();
|
|
18
|
+
return this.store.create(input);
|
|
19
|
+
}
|
|
20
|
+
async send(reference, prompt) {
|
|
21
|
+
const resolved = await this.store.resolve(reference);
|
|
22
|
+
if (!resolved) throw new PrintAgentNotFoundError(reference);
|
|
23
|
+
if (Array.isArray(resolved)) {
|
|
24
|
+
throw new ClaudePrintError(`Multiple print agents match "${reference}".`, 'PRINT_AGENT_AMBIGUOUS');
|
|
25
|
+
}
|
|
26
|
+
const acquired = await this.store.acquireRun(resolved.id);
|
|
27
|
+
try {
|
|
28
|
+
const result = await this.runner.run({
|
|
29
|
+
agent: acquired.agent,
|
|
30
|
+
prompt,
|
|
31
|
+
executable: this.executable,
|
|
32
|
+
firstRun: acquired.agent.sessionHealth === 'uninitialized',
|
|
33
|
+
onSpawn: (identity)=>this.store.recordProviderProcess(resolved.id, acquired.token, identity)
|
|
34
|
+
});
|
|
35
|
+
await this.store.completeRun(resolved.id, acquired.token, {
|
|
36
|
+
status: 'succeeded',
|
|
37
|
+
exitCode: result.exitCode,
|
|
38
|
+
summary: sanitize(result.result, 4096),
|
|
39
|
+
sessionHealth: 'healthy'
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
...result,
|
|
43
|
+
agentId: resolved.id,
|
|
44
|
+
agentName: resolved.name
|
|
45
|
+
};
|
|
46
|
+
} catch (error) {
|
|
47
|
+
const failure = error instanceof Error ? error : new Error(String(error));
|
|
48
|
+
const sessionHealth = error instanceof ClaudePrintError && error.code === 'CLAUDE_SESSION_MISMATCH' ? 'mismatch' : 'unknown';
|
|
49
|
+
await this.store.completeRun(resolved.id, acquired.token, {
|
|
50
|
+
status: 'failed',
|
|
51
|
+
exitCode: null,
|
|
52
|
+
summary: sanitize(failure.message, 4096),
|
|
53
|
+
sessionHealth
|
|
54
|
+
});
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function sanitize(value, max) {
|
|
60
|
+
return Array.from(value, (character)=>{
|
|
61
|
+
const code = character.charCodeAt(0);
|
|
62
|
+
return code <= 8 || code === 11 || code === 12 || code >= 14 && code <= 31 || code === 127 ? ' ' : character;
|
|
63
|
+
}).join('').trim().slice(0, max);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=ClaudePrintAgentService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ChildProcessWithoutNullStreams, type SpawnOptionsWithoutStdio } from 'child_process';
|
|
2
|
+
import type { PrintAgent, ProcessIdentity } from './PrintAgent.js';
|
|
3
|
+
import { type ProcessInspector } from './PrintAgentStore.js';
|
|
4
|
+
type Spawn = (command: string, args: readonly string[], options: SpawnOptionsWithoutStdio & {
|
|
5
|
+
stdio: ['pipe', 'pipe', 'pipe'];
|
|
6
|
+
}) => ChildProcessWithoutNullStreams;
|
|
7
|
+
export interface ClaudePrintRunRequest {
|
|
8
|
+
agent: PrintAgent;
|
|
9
|
+
prompt: string;
|
|
10
|
+
executable?: string;
|
|
11
|
+
firstRun: boolean;
|
|
12
|
+
onSpawn(identity: ProcessIdentity): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export interface ClaudePrintRunResult {
|
|
15
|
+
sessionId: string;
|
|
16
|
+
result: string;
|
|
17
|
+
exitCode: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ClaudePrintRunnerOptions {
|
|
20
|
+
spawn?: Spawn;
|
|
21
|
+
processInspector?: ProcessInspector;
|
|
22
|
+
maxLineBytes?: number;
|
|
23
|
+
}
|
|
24
|
+
export declare class ClaudePrintRunner {
|
|
25
|
+
private readonly spawn;
|
|
26
|
+
private readonly processInspector;
|
|
27
|
+
private readonly maxLineBytes;
|
|
28
|
+
constructor(options?: ClaudePrintRunnerOptions);
|
|
29
|
+
run(request: ClaudePrintRunRequest): Promise<ClaudePrintRunResult>;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=ClaudePrintRunner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { spawn as nodeSpawn } from 'child_process';
|
|
2
|
+
import { ClaudePrintError } from './PrintAgent.js';
|
|
3
|
+
import { LocalProcessInspector } from './PrintAgentStore.js';
|
|
4
|
+
export class ClaudePrintRunner {
|
|
5
|
+
spawn;
|
|
6
|
+
processInspector;
|
|
7
|
+
maxLineBytes;
|
|
8
|
+
constructor(options = {}){
|
|
9
|
+
this.spawn = options.spawn ?? nodeSpawn;
|
|
10
|
+
this.processInspector = options.processInspector ?? new LocalProcessInspector();
|
|
11
|
+
this.maxLineBytes = options.maxLineBytes ?? 1024 * 1024;
|
|
12
|
+
}
|
|
13
|
+
async run(request) {
|
|
14
|
+
const sessionArgs = request.firstRun ? [
|
|
15
|
+
'--session-id',
|
|
16
|
+
request.agent.providerSessionId
|
|
17
|
+
] : [
|
|
18
|
+
'--resume',
|
|
19
|
+
request.agent.providerSessionId
|
|
20
|
+
];
|
|
21
|
+
const args = [
|
|
22
|
+
'-p',
|
|
23
|
+
...sessionArgs,
|
|
24
|
+
'--output-format',
|
|
25
|
+
'stream-json',
|
|
26
|
+
'--verbose'
|
|
27
|
+
];
|
|
28
|
+
const child = this.spawn(request.executable ?? 'claude', args, {
|
|
29
|
+
cwd: request.agent.cwd,
|
|
30
|
+
shell: false,
|
|
31
|
+
stdio: [
|
|
32
|
+
'pipe',
|
|
33
|
+
'pipe',
|
|
34
|
+
'pipe'
|
|
35
|
+
]
|
|
36
|
+
});
|
|
37
|
+
if (!child.pid) {
|
|
38
|
+
child.kill();
|
|
39
|
+
throw new ClaudePrintError('Claude process did not provide a PID.', 'CLAUDE_PROCESS_IDENTITY');
|
|
40
|
+
}
|
|
41
|
+
const identity = this.processInspector.getIdentity(child.pid);
|
|
42
|
+
if (!identity) {
|
|
43
|
+
child.kill();
|
|
44
|
+
throw new ClaudePrintError('Cannot verify Claude process identity.', 'CLAUDE_PROCESS_IDENTITY');
|
|
45
|
+
}
|
|
46
|
+
let buffer = Buffer.alloc(0);
|
|
47
|
+
let terminal = null;
|
|
48
|
+
let protocolError = null;
|
|
49
|
+
child.stdout.on('data', (chunk)=>{
|
|
50
|
+
if (protocolError) return;
|
|
51
|
+
buffer = Buffer.concat([
|
|
52
|
+
buffer,
|
|
53
|
+
Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)
|
|
54
|
+
]);
|
|
55
|
+
if (buffer.length > this.maxLineBytes && buffer.indexOf(0x0a) < 0) {
|
|
56
|
+
protocolError = new ClaudePrintError('Claude stream line exceeded the safety limit.', 'CLAUDE_STREAM_OVERSIZED');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let newline;
|
|
60
|
+
while((newline = buffer.indexOf(0x0a)) >= 0){
|
|
61
|
+
const line = buffer.subarray(0, newline);
|
|
62
|
+
buffer = buffer.subarray(newline + 1);
|
|
63
|
+
if (line.length === 0) continue;
|
|
64
|
+
if (line.length > this.maxLineBytes) {
|
|
65
|
+
protocolError = new ClaudePrintError('Claude stream line exceeded the safety limit.', 'CLAUDE_STREAM_OVERSIZED');
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const value = JSON.parse(line.toString('utf8'));
|
|
70
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
71
|
+
throw new ClaudePrintError('Claude emitted a non-object stream message.', 'CLAUDE_STREAM_INVALID');
|
|
72
|
+
}
|
|
73
|
+
const event = value;
|
|
74
|
+
if (typeof event.session_id === 'string' && event.session_id !== request.agent.providerSessionId) {
|
|
75
|
+
throw new ClaudePrintError('Claude returned a different session identity.', 'CLAUDE_SESSION_MISMATCH');
|
|
76
|
+
}
|
|
77
|
+
if (event.type === 'result') {
|
|
78
|
+
if (terminal) throw new ClaudePrintError('Claude emitted more than one terminal result.', 'CLAUDE_STREAM_INVALID');
|
|
79
|
+
if (typeof event.session_id !== 'string' || typeof event.result !== 'string') {
|
|
80
|
+
throw new ClaudePrintError('Claude emitted an invalid terminal result.', 'CLAUDE_STREAM_INVALID');
|
|
81
|
+
}
|
|
82
|
+
terminal = {
|
|
83
|
+
sessionId: event.session_id,
|
|
84
|
+
result: event.result,
|
|
85
|
+
exitCode: 0
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
} catch (error) {
|
|
89
|
+
protocolError = error instanceof ClaudePrintError ? error : new ClaudePrintError('Claude emitted malformed stream JSON.', 'CLAUDE_STREAM_INVALID');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
// Drain provider diagnostics without reflecting potentially sensitive prompt/tool data.
|
|
95
|
+
child.stderr.resume();
|
|
96
|
+
const closed = new Promise((resolve, reject)=>{
|
|
97
|
+
child.once('error', reject);
|
|
98
|
+
child.once('close', (code, signal)=>resolve({
|
|
99
|
+
code,
|
|
100
|
+
signal
|
|
101
|
+
}));
|
|
102
|
+
});
|
|
103
|
+
try {
|
|
104
|
+
await request.onSpawn(identity);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
child.kill();
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
child.stdin.end(request.prompt);
|
|
110
|
+
const { code, signal } = await closed;
|
|
111
|
+
if (protocolError) throw protocolError;
|
|
112
|
+
if (buffer.length > 0) {
|
|
113
|
+
throw new ClaudePrintError('Claude stream ended with incomplete JSON.', 'CLAUDE_STREAM_INVALID');
|
|
114
|
+
}
|
|
115
|
+
if (code !== 0) {
|
|
116
|
+
throw new ClaudePrintError(`Claude print run failed${signal ? ` (${signal})` : '.'}`, 'CLAUDE_PROCESS_FAILED');
|
|
117
|
+
}
|
|
118
|
+
if (!terminal) throw new ClaudePrintError('Claude stream ended without a terminal result.', 'CLAUDE_RESULT_MISSING');
|
|
119
|
+
const finalResult = terminal;
|
|
120
|
+
return {
|
|
121
|
+
sessionId: finalResult.sessionId,
|
|
122
|
+
result: finalResult.result,
|
|
123
|
+
exitCode: code
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
//# sourceMappingURL=ClaudePrintRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { PrintAgent, ProcessIdentity, PrintRunStatus, PrintSessionHealth } from './PrintAgent.js';
|
|
2
|
+
export interface CreatePrintAgentInput {
|
|
3
|
+
name: string;
|
|
4
|
+
cwd: string;
|
|
5
|
+
}
|
|
6
|
+
export interface PrintAgentStoreOptions {
|
|
7
|
+
filePath?: string;
|
|
8
|
+
lockTimeoutMs?: number;
|
|
9
|
+
now?: () => Date;
|
|
10
|
+
processInspector?: ProcessInspector;
|
|
11
|
+
incompleteLockGraceMs?: number;
|
|
12
|
+
mutationLockStaleMs?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ProcessInspector {
|
|
15
|
+
getIdentity(pid: number): ProcessIdentity | null;
|
|
16
|
+
}
|
|
17
|
+
export interface PrintRunCompletion {
|
|
18
|
+
status: PrintRunStatus;
|
|
19
|
+
exitCode: number | null;
|
|
20
|
+
summary: string;
|
|
21
|
+
sessionHealth: PrintSessionHealth;
|
|
22
|
+
}
|
|
23
|
+
export declare class PrintAgentStore {
|
|
24
|
+
readonly filePath: string;
|
|
25
|
+
private readonly lockPath;
|
|
26
|
+
private readonly lockTimeoutMs;
|
|
27
|
+
private readonly now;
|
|
28
|
+
private readonly processInspector;
|
|
29
|
+
private readonly runLocksRoot;
|
|
30
|
+
private readonly incompleteLockGraceMs;
|
|
31
|
+
private readonly mutationLockStaleMs;
|
|
32
|
+
constructor(options?: PrintAgentStoreOptions);
|
|
33
|
+
create(input: CreatePrintAgentInput): Promise<PrintAgent>;
|
|
34
|
+
list(): Promise<PrintAgent[]>;
|
|
35
|
+
getById(id: string): Promise<PrintAgent | null>;
|
|
36
|
+
reconcile(): Promise<void>;
|
|
37
|
+
resolve(reference: string): Promise<PrintAgent | PrintAgent[] | null>;
|
|
38
|
+
acquireRun(id: string): Promise<{
|
|
39
|
+
agent: PrintAgent;
|
|
40
|
+
token: string;
|
|
41
|
+
}>;
|
|
42
|
+
recordProviderProcess(id: string, token: string, identity: ProcessIdentity): Promise<void>;
|
|
43
|
+
completeRun(id: string, token: string, result: PrintRunCompletion): Promise<PrintAgent>;
|
|
44
|
+
private canonicalDirectory;
|
|
45
|
+
private validateBoundCwd;
|
|
46
|
+
private ensureSafeParent;
|
|
47
|
+
private ensureRunLocksRoot;
|
|
48
|
+
private assertNotSymlink;
|
|
49
|
+
private readFile;
|
|
50
|
+
private listRaw;
|
|
51
|
+
private isStoreFile;
|
|
52
|
+
private writeFile;
|
|
53
|
+
private withMutationLock;
|
|
54
|
+
private isYoungMutationLock;
|
|
55
|
+
private updateAgent;
|
|
56
|
+
private runLockPath;
|
|
57
|
+
private readRunLock;
|
|
58
|
+
private writeRunLock;
|
|
59
|
+
private requireOwnedRun;
|
|
60
|
+
private isActive;
|
|
61
|
+
private sameProcess;
|
|
62
|
+
private isYoungLock;
|
|
63
|
+
private removeOwnedRunLock;
|
|
64
|
+
private removeLockDirectory;
|
|
65
|
+
}
|
|
66
|
+
export declare class LocalProcessInspector implements ProcessInspector {
|
|
67
|
+
getIdentity(pid: number): ProcessIdentity | null;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=PrintAgentStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrintAgentStore.d.ts","sourceRoot":"","sources":["../../src/print/PrintAgentStore.ts"],"names":[],"mappings":"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"}
|