@agent-relay/factory 0.0.0 → 0.1.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 +240 -22
- package/bin/factory.mjs +7 -0
- package/dist/cli/fleet.d.ts +77 -0
- package/dist/cli/fleet.d.ts.map +1 -0
- package/dist/cli/fleet.js +500 -0
- package/dist/cli/fleet.js.map +1 -0
- package/dist/config/schema.d.ts +1313 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +309 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/constants/linear.d.ts +4 -0
- package/dist/constants/linear.d.ts.map +1 -0
- package/dist/constants/linear.js +15 -0
- package/dist/constants/linear.js.map +1 -0
- package/dist/constants/slack.d.ts +3 -0
- package/dist/constants/slack.d.ts.map +1 -0
- package/dist/constants/slack.js +3 -0
- package/dist/constants/slack.js.map +1 -0
- package/dist/dispatch/templates.d.ts +36 -0
- package/dist/dispatch/templates.d.ts.map +1 -0
- package/dist/dispatch/templates.js +110 -0
- package/dist/dispatch/templates.js.map +1 -0
- package/dist/fleet/create-fleet.d.ts +13 -0
- package/dist/fleet/create-fleet.d.ts.map +1 -0
- package/dist/fleet/create-fleet.js +14 -0
- package/dist/fleet/create-fleet.js.map +1 -0
- package/dist/fleet/internal-fleet-client.d.ts +85 -0
- package/dist/fleet/internal-fleet-client.d.ts.map +1 -0
- package/dist/fleet/internal-fleet-client.js +575 -0
- package/dist/fleet/internal-fleet-client.js.map +1 -0
- package/dist/fleet/relay-fleet-client.d.ts +28 -0
- package/dist/fleet/relay-fleet-client.d.ts.map +1 -0
- package/dist/fleet/relay-fleet-client.js +33 -0
- package/dist/fleet/relay-fleet-client.js.map +1 -0
- package/dist/github/index.d.ts +5 -0
- package/dist/github/index.d.ts.map +1 -0
- package/dist/github/index.js +3 -0
- package/dist/github/index.js.map +1 -0
- package/dist/github/merge-gate.d.ts +47 -0
- package/dist/github/merge-gate.d.ts.map +1 -0
- package/dist/github/merge-gate.js +147 -0
- package/dist/github/merge-gate.js.map +1 -0
- package/dist/github/probe-closer.d.ts +15 -0
- package/dist/github/probe-closer.d.ts.map +1 -0
- package/dist/github/probe-closer.js +67 -0
- package/dist/github/probe-closer.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/issue-key-match.d.ts +3 -0
- package/dist/issue-key-match.d.ts.map +1 -0
- package/dist/issue-key-match.js +22 -0
- package/dist/issue-key-match.js.map +1 -0
- package/dist/linear/state-resolver.d.ts +25 -0
- package/dist/linear/state-resolver.d.ts.map +1 -0
- package/dist/linear/state-resolver.js +221 -0
- package/dist/linear/state-resolver.js.map +1 -0
- package/dist/mount/local-mount-preflight.d.ts +8 -0
- package/dist/mount/local-mount-preflight.d.ts.map +1 -0
- package/dist/mount/local-mount-preflight.js +97 -0
- package/dist/mount/local-mount-preflight.js.map +1 -0
- package/dist/mount/relayfile-binary.d.ts +7 -0
- package/dist/mount/relayfile-binary.d.ts.map +1 -0
- package/dist/mount/relayfile-binary.js +143 -0
- package/dist/mount/relayfile-binary.js.map +1 -0
- package/dist/mount/relayfile-cloud-mount-client.d.ts +123 -0
- package/dist/mount/relayfile-cloud-mount-client.d.ts.map +1 -0
- package/dist/mount/relayfile-cloud-mount-client.js +427 -0
- package/dist/mount/relayfile-cloud-mount-client.js.map +1 -0
- package/dist/orchestrator/batch-tracker.d.ts +42 -0
- package/dist/orchestrator/batch-tracker.d.ts.map +1 -0
- package/dist/orchestrator/batch-tracker.js +125 -0
- package/dist/orchestrator/batch-tracker.js.map +1 -0
- package/dist/orchestrator/factory.d.ts +55 -0
- package/dist/orchestrator/factory.d.ts.map +1 -0
- package/dist/orchestrator/factory.js +4018 -0
- package/dist/orchestrator/factory.js.map +1 -0
- package/dist/orchestrator/index.d.ts +5 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/index.js +4 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/process-identity.d.ts +23 -0
- package/dist/orchestrator/process-identity.d.ts.map +1 -0
- package/dist/orchestrator/process-identity.js +122 -0
- package/dist/orchestrator/process-identity.js.map +1 -0
- package/dist/orchestrator/reaper.d.ts +60 -0
- package/dist/orchestrator/reaper.d.ts.map +1 -0
- package/dist/orchestrator/reaper.js +293 -0
- package/dist/orchestrator/reaper.js.map +1 -0
- package/dist/ports/fleet.d.ts +95 -0
- package/dist/ports/fleet.d.ts.map +1 -0
- package/dist/ports/fleet.js +2 -0
- package/dist/ports/fleet.js.map +1 -0
- package/dist/ports/index.d.ts +5 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +2 -0
- package/dist/ports/index.js.map +1 -0
- package/dist/ports/mount.d.ts +56 -0
- package/dist/ports/mount.d.ts.map +1 -0
- package/dist/ports/mount.js +2 -0
- package/dist/ports/mount.js.map +1 -0
- package/dist/ports/state.d.ts +61 -0
- package/dist/ports/state.d.ts.map +1 -0
- package/dist/ports/state.js +2 -0
- package/dist/ports/state.js.map +1 -0
- package/dist/ports/system.d.ts +15 -0
- package/dist/ports/system.d.ts.map +1 -0
- package/dist/ports/system.js +2 -0
- package/dist/ports/system.js.map +1 -0
- package/dist/ports/writeback.d.ts +25 -0
- package/dist/ports/writeback.d.ts.map +1 -0
- package/dist/ports/writeback.js +2 -0
- package/dist/ports/writeback.js.map +1 -0
- package/dist/safety/factory-scope.d.ts +16 -0
- package/dist/safety/factory-scope.d.ts.map +1 -0
- package/dist/safety/factory-scope.js +107 -0
- package/dist/safety/factory-scope.js.map +1 -0
- package/dist/state/in-memory-state-store.d.ts +31 -0
- package/dist/state/in-memory-state-store.d.ts.map +1 -0
- package/dist/state/in-memory-state-store.js +115 -0
- package/dist/state/in-memory-state-store.js.map +1 -0
- package/dist/state/index.d.ts +3 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +2 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/store.d.ts +29 -0
- package/dist/state/store.d.ts.map +1 -0
- package/dist/state/store.js +26 -0
- package/dist/state/store.js.map +1 -0
- package/dist/subscriptions/common.d.ts +7 -0
- package/dist/subscriptions/common.d.ts.map +1 -0
- package/dist/subscriptions/common.js +59 -0
- package/dist/subscriptions/common.js.map +1 -0
- package/dist/subscriptions/event-client.d.ts +40 -0
- package/dist/subscriptions/event-client.d.ts.map +1 -0
- package/dist/subscriptions/event-client.js +234 -0
- package/dist/subscriptions/event-client.js.map +1 -0
- package/dist/subscriptions/globs.d.ts +5 -0
- package/dist/subscriptions/globs.d.ts.map +1 -0
- package/dist/subscriptions/globs.js +50 -0
- package/dist/subscriptions/globs.js.map +1 -0
- package/dist/subscriptions/index.d.ts +8 -0
- package/dist/subscriptions/index.d.ts.map +1 -0
- package/dist/subscriptions/index.js +5 -0
- package/dist/subscriptions/index.js.map +1 -0
- package/dist/subscriptions/linear-filter.d.ts +26 -0
- package/dist/subscriptions/linear-filter.d.ts.map +1 -0
- package/dist/subscriptions/linear-filter.js +143 -0
- package/dist/subscriptions/linear-filter.js.map +1 -0
- package/dist/subscriptions/specs.d.ts +44 -0
- package/dist/subscriptions/specs.d.ts.map +1 -0
- package/dist/subscriptions/specs.js +195 -0
- package/dist/subscriptions/specs.js.map +1 -0
- package/dist/testing/fakes.d.ts +114 -0
- package/dist/testing/fakes.d.ts.map +1 -0
- package/dist/testing/fakes.js +219 -0
- package/dist/testing/fakes.js.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +2 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/triage/heuristic.d.ts +38 -0
- package/dist/triage/heuristic.d.ts.map +1 -0
- package/dist/triage/heuristic.js +262 -0
- package/dist/triage/heuristic.js.map +1 -0
- package/dist/triage/index.d.ts +7 -0
- package/dist/triage/index.d.ts.map +1 -0
- package/dist/triage/index.js +5 -0
- package/dist/triage/index.js.map +1 -0
- package/dist/triage/llm.d.ts +11 -0
- package/dist/triage/llm.d.ts.map +1 -0
- package/dist/triage/llm.js +46 -0
- package/dist/triage/llm.js.map +1 -0
- package/dist/triage/schema.d.ts +240 -0
- package/dist/triage/schema.d.ts.map +1 -0
- package/dist/triage/schema.js +34 -0
- package/dist/triage/schema.js.map +1 -0
- package/dist/triage/tiered.d.ts +8 -0
- package/dist/triage/tiered.d.ts.map +1 -0
- package/dist/triage/tiered.js +40 -0
- package/dist/triage/tiered.js.map +1 -0
- package/dist/types.d.ts +211 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/webhook/handler.d.ts +22 -0
- package/dist/webhook/handler.d.ts.map +1 -0
- package/dist/webhook/handler.js +57 -0
- package/dist/webhook/handler.js.map +1 -0
- package/dist/webhook/index.d.ts +5 -0
- package/dist/webhook/index.d.ts.map +1 -0
- package/dist/webhook/index.js +3 -0
- package/dist/webhook/index.js.map +1 -0
- package/dist/webhook/registrar.d.ts +16 -0
- package/dist/webhook/registrar.d.ts.map +1 -0
- package/dist/webhook/registrar.js +50 -0
- package/dist/webhook/registrar.js.map +1 -0
- package/dist/writeback/github.d.ts +6 -0
- package/dist/writeback/github.d.ts.map +1 -0
- package/dist/writeback/github.js +48 -0
- package/dist/writeback/github.js.map +1 -0
- package/dist/writeback/index.d.ts +6 -0
- package/dist/writeback/index.d.ts.map +1 -0
- package/dist/writeback/index.js +4 -0
- package/dist/writeback/index.js.map +1 -0
- package/dist/writeback/linear.d.ts +41 -0
- package/dist/writeback/linear.d.ts.map +1 -0
- package/dist/writeback/linear.js +243 -0
- package/dist/writeback/linear.js.map +1 -0
- package/dist/writeback/shared.d.ts +7 -0
- package/dist/writeback/shared.d.ts.map +1 -0
- package/dist/writeback/shared.js +29 -0
- package/dist/writeback/shared.js.map +1 -0
- package/dist/writeback/slack.d.ts +16 -0
- package/dist/writeback/slack.d.ts.map +1 -0
- package/dist/writeback/slack.js +104 -0
- package/dist/writeback/slack.js.map +1 -0
- package/package.json +46 -9
- package/index.d.ts +0 -2
- package/index.js +0 -7
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { BrokerEvent, ListAgent, SendMessageInput, SpawnPtyInput } from '@agent-relay/harness-driver';
|
|
2
|
+
import type { AgentMessage, AgentPidResolution, Capability, FleetClient, RosterEntry, SendInput, SpawnInput, SpawnResult } from '../ports/fleet';
|
|
3
|
+
import type { Logger } from '../ports/system';
|
|
4
|
+
type SpawnedHandleLike = {
|
|
5
|
+
name: string;
|
|
6
|
+
sessionId?: string;
|
|
7
|
+
session_ref?: string;
|
|
8
|
+
sessionRef?: string;
|
|
9
|
+
pid?: number;
|
|
10
|
+
};
|
|
11
|
+
type HarnessEventListener = (event: BrokerEvent) => void;
|
|
12
|
+
type DriverAgentLike = {
|
|
13
|
+
name: string;
|
|
14
|
+
sessionId?: string;
|
|
15
|
+
pid?: number;
|
|
16
|
+
};
|
|
17
|
+
type DriverDeliveryEventLike = BrokerEvent;
|
|
18
|
+
type AgentRelayMcpCommand = {
|
|
19
|
+
command: string;
|
|
20
|
+
args: string[];
|
|
21
|
+
};
|
|
22
|
+
export interface HarnessDriverClientLike {
|
|
23
|
+
readonly brokerPid?: number;
|
|
24
|
+
spawnPty(input: SpawnPtyInput): Promise<SpawnedHandleLike>;
|
|
25
|
+
release(name: string, reason?: string): Promise<{
|
|
26
|
+
name: string;
|
|
27
|
+
}>;
|
|
28
|
+
listAgents(): Promise<Array<Pick<ListAgent, 'name'> & {
|
|
29
|
+
pid?: number;
|
|
30
|
+
}>>;
|
|
31
|
+
sendMessage(input: SendMessageInput): Promise<{
|
|
32
|
+
event_id: string;
|
|
33
|
+
targets?: string[];
|
|
34
|
+
}>;
|
|
35
|
+
sendInput(name: string, data: string): Promise<unknown>;
|
|
36
|
+
connectEvents?(sinceSeq?: number): void;
|
|
37
|
+
disconnect?(): void;
|
|
38
|
+
onEvent?(listener: HarnessEventListener): () => void;
|
|
39
|
+
addListener?(event: 'agentExited', listener: (agent: DriverAgentLike) => void): () => void;
|
|
40
|
+
addListener?(event: 'deliveryUpdate', listener: (event: DriverDeliveryEventLike) => void): () => void;
|
|
41
|
+
}
|
|
42
|
+
export interface InternalFleetClientOptions {
|
|
43
|
+
client?: HarnessDriverClientLike;
|
|
44
|
+
cwd?: string;
|
|
45
|
+
connectionPath?: string;
|
|
46
|
+
resumeCapability?: Capability;
|
|
47
|
+
logger?: Logger;
|
|
48
|
+
resolveAgentRelayMcpCommand?: () => AgentRelayMcpCommand | undefined;
|
|
49
|
+
}
|
|
50
|
+
type AgentExitListener = (name: string, reason?: string) => void;
|
|
51
|
+
type DeliveryFailedListener = (info: {
|
|
52
|
+
to: string;
|
|
53
|
+
msgId?: string;
|
|
54
|
+
reason?: string;
|
|
55
|
+
}) => void;
|
|
56
|
+
type AgentMessageListener = (message: AgentMessage) => void;
|
|
57
|
+
export declare class InternalFleetClient implements FleetClient {
|
|
58
|
+
#private;
|
|
59
|
+
constructor(options?: InternalFleetClientOptions);
|
|
60
|
+
spawn(input: SpawnInput): Promise<SpawnResult>;
|
|
61
|
+
resume(input: {
|
|
62
|
+
name?: string;
|
|
63
|
+
sessionRef: string;
|
|
64
|
+
node?: 'self' | string;
|
|
65
|
+
capability?: Capability;
|
|
66
|
+
}): Promise<SpawnResult>;
|
|
67
|
+
release(name: string, reason?: string): Promise<void>;
|
|
68
|
+
roster(): Promise<RosterEntry>;
|
|
69
|
+
protectedPids(): Promise<number[]>;
|
|
70
|
+
resolveAgentPid(name: string): Promise<AgentPidResolution>;
|
|
71
|
+
sendMessage(input: SendInput): Promise<void>;
|
|
72
|
+
waitForInjected(input: SendInput, opts?: {
|
|
73
|
+
timeoutMs?: number;
|
|
74
|
+
}): Promise<{
|
|
75
|
+
eventId: string;
|
|
76
|
+
targets: string[];
|
|
77
|
+
}>;
|
|
78
|
+
sendInput(name: string, data: string): Promise<void>;
|
|
79
|
+
onDeliveryFailed(listener: DeliveryFailedListener): () => void;
|
|
80
|
+
onAgentMessage(listener: AgentMessageListener): () => void;
|
|
81
|
+
onAgentExit(listener: AgentExitListener): () => void;
|
|
82
|
+
dispose(): Promise<void>;
|
|
83
|
+
}
|
|
84
|
+
export {};
|
|
85
|
+
//# sourceMappingURL=internal-fleet-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal-fleet-client.d.ts","sourceRoot":"","sources":["../../src/fleet/internal-fleet-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
import { HarnessDriverClient } from '@agent-relay/harness-driver';
|
|
2
|
+
import { accessSync, constants } from 'node:fs';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import { readFile } from 'node:fs/promises';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
const requireForResolve = createRequire(import.meta.url);
|
|
7
|
+
const capabilityCli = {
|
|
8
|
+
'spawn:claude': 'claude',
|
|
9
|
+
'spawn:codex': 'codex',
|
|
10
|
+
};
|
|
11
|
+
const selfNode = {
|
|
12
|
+
name: 'self',
|
|
13
|
+
capabilities: ['spawn:claude', 'spawn:codex'],
|
|
14
|
+
live: true,
|
|
15
|
+
};
|
|
16
|
+
const PID_RESOLVE_ATTEMPTS = 3;
|
|
17
|
+
const PID_RESOLVE_BACKOFF_MS = 75;
|
|
18
|
+
export class InternalFleetClient {
|
|
19
|
+
#client;
|
|
20
|
+
#cwd;
|
|
21
|
+
#connectionPath;
|
|
22
|
+
#resumeCapability;
|
|
23
|
+
#logger;
|
|
24
|
+
#resolveAgentRelayMcpCommand;
|
|
25
|
+
#agentExitListeners = new Set();
|
|
26
|
+
#deliveryFailedListeners = new Set();
|
|
27
|
+
#agentMessageListeners = new Set();
|
|
28
|
+
#eventUnsubscribers = [];
|
|
29
|
+
#seenEvents = [];
|
|
30
|
+
#seenEventKeys = new Set();
|
|
31
|
+
#pendingInjected = new Map();
|
|
32
|
+
#injectedEventIds = [];
|
|
33
|
+
#injectedEventIdSet = new Set();
|
|
34
|
+
#failedDeliveries = new Map();
|
|
35
|
+
#failedDeliveryIds = [];
|
|
36
|
+
#exitedAgentNames = new Set();
|
|
37
|
+
#suppressedDuplicateEvents = 0;
|
|
38
|
+
#suppressedDuplicateAgentExits = 0;
|
|
39
|
+
#missingIdentityEvents = 0;
|
|
40
|
+
#subscribed = false;
|
|
41
|
+
#disposed = false;
|
|
42
|
+
constructor(options = {}) {
|
|
43
|
+
this.#cwd = options.cwd;
|
|
44
|
+
this.#connectionPath = options.connectionPath;
|
|
45
|
+
this.#resumeCapability = options.resumeCapability ?? 'spawn:codex';
|
|
46
|
+
this.#logger = options.logger;
|
|
47
|
+
this.#resolveAgentRelayMcpCommand = options.resolveAgentRelayMcpCommand ?? resolveAgentRelayMcpCommand;
|
|
48
|
+
this.#client = options.client ?? HarnessDriverClient.connect({ cwd: options.cwd, connectionPath: options.connectionPath });
|
|
49
|
+
}
|
|
50
|
+
async spawn(input) {
|
|
51
|
+
assertSelfNode(input.node);
|
|
52
|
+
const spawnInput = this.#withAgentRelayMcpHarness({
|
|
53
|
+
name: input.name,
|
|
54
|
+
cli: capabilityCli[input.capability],
|
|
55
|
+
channels: input.channel ? [input.channel] : undefined,
|
|
56
|
+
task: input.task,
|
|
57
|
+
model: input.model,
|
|
58
|
+
cwd: input.cwd ?? this.#cwd,
|
|
59
|
+
restartPolicy: input.restartPolicy,
|
|
60
|
+
continueFrom: input.sessionRef,
|
|
61
|
+
});
|
|
62
|
+
const handle = await this.#client.spawnPty(spawnInput);
|
|
63
|
+
this.#clearAgentExitLatch(handle.name);
|
|
64
|
+
return spawnResultFrom(handle);
|
|
65
|
+
}
|
|
66
|
+
async resume(input) {
|
|
67
|
+
assertSelfNode(input.node);
|
|
68
|
+
const spawnInput = this.#withAgentRelayMcpHarness({
|
|
69
|
+
name: input.name ?? input.sessionRef,
|
|
70
|
+
// followups [fleet→W6]: W6 owns resume-vs-respawn and passes the per-agent capability.
|
|
71
|
+
cli: capabilityCli[input.capability ?? this.#resumeCapability],
|
|
72
|
+
cwd: this.#cwd,
|
|
73
|
+
continueFrom: input.sessionRef,
|
|
74
|
+
});
|
|
75
|
+
const handle = await this.#client.spawnPty(spawnInput);
|
|
76
|
+
this.#clearAgentExitLatch(handle.name);
|
|
77
|
+
return { ...spawnResultFrom(handle), sessionRef: sessionRefFrom(handle) ?? input.sessionRef };
|
|
78
|
+
}
|
|
79
|
+
#withAgentRelayMcpHarness(input) {
|
|
80
|
+
if (input.harnessConfig || (input.cli !== 'codex' && input.cli !== 'claude')) {
|
|
81
|
+
return input;
|
|
82
|
+
}
|
|
83
|
+
const command = this.#resolveAgentRelayMcpCommand();
|
|
84
|
+
if (!command) {
|
|
85
|
+
this.#logger?.warn?.('[factory-sdk] agent-relay MCP command not found; spawning without MCP injection', {
|
|
86
|
+
agent: input.name,
|
|
87
|
+
cli: input.cli,
|
|
88
|
+
});
|
|
89
|
+
return input;
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
...input,
|
|
93
|
+
harnessConfig: buildRelayMcpHarnessConfig(input, command),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async release(name, reason) {
|
|
97
|
+
await this.#client.release(name, reason);
|
|
98
|
+
}
|
|
99
|
+
async roster() {
|
|
100
|
+
const agents = await this.#client.listAgents();
|
|
101
|
+
return {
|
|
102
|
+
agents: agents.map((agent) => ({ name: agent.name })),
|
|
103
|
+
nodes: [selfNode],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async protectedPids() {
|
|
107
|
+
const pids = new Set();
|
|
108
|
+
if (Number.isInteger(this.#client.brokerPid) && this.#client.brokerPid > 0) {
|
|
109
|
+
pids.add(this.#client.brokerPid);
|
|
110
|
+
}
|
|
111
|
+
const connectionPid = await this.#connectionFilePid();
|
|
112
|
+
if (connectionPid) {
|
|
113
|
+
pids.add(connectionPid);
|
|
114
|
+
}
|
|
115
|
+
return [...pids].sort((a, b) => a - b);
|
|
116
|
+
}
|
|
117
|
+
async resolveAgentPid(name) {
|
|
118
|
+
try {
|
|
119
|
+
let sawAgent = false;
|
|
120
|
+
for (let attempt = 1; attempt <= PID_RESOLVE_ATTEMPTS; attempt += 1) {
|
|
121
|
+
const agent = (await this.#client.listAgents()).find((candidate) => candidate.name === name);
|
|
122
|
+
if (agent) {
|
|
123
|
+
sawAgent = true;
|
|
124
|
+
}
|
|
125
|
+
if (typeof agent?.pid === 'number') {
|
|
126
|
+
return { status: 'found', pid: agent.pid };
|
|
127
|
+
}
|
|
128
|
+
if (attempt < PID_RESOLVE_ATTEMPTS) {
|
|
129
|
+
await sleep(PID_RESOLVE_BACKOFF_MS);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return sawAgent ? { status: 'unresolved' } : { status: 'missing' };
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
this.#logger?.warn?.('[factory-sdk] unable to resolve spawned agent pid from roster', error);
|
|
136
|
+
return { status: 'unresolved' };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
async #connectionFilePid() {
|
|
140
|
+
const path = this.#connectionPath ?? connectionPathForCwd(this.#cwd);
|
|
141
|
+
if (!path)
|
|
142
|
+
return undefined;
|
|
143
|
+
try {
|
|
144
|
+
const parsed = JSON.parse(await readFile(path, 'utf8'));
|
|
145
|
+
const pid = parsed.pid;
|
|
146
|
+
return typeof pid === 'number' && Number.isInteger(pid) && pid > 0 ? pid : undefined;
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async sendMessage(input) {
|
|
153
|
+
await this.#client.sendMessage(messageInputFrom(input));
|
|
154
|
+
}
|
|
155
|
+
async waitForInjected(input, opts) {
|
|
156
|
+
this.#ensureEventSubscription();
|
|
157
|
+
const result = await this.#client.sendMessage(messageInputFrom(input));
|
|
158
|
+
const eventId = result.event_id;
|
|
159
|
+
const targets = result.targets ?? [];
|
|
160
|
+
if (this.#injectedEventIdSet.has(eventId)) {
|
|
161
|
+
return { eventId, targets };
|
|
162
|
+
}
|
|
163
|
+
const priorFailure = this.#failedDeliveries.get(eventId);
|
|
164
|
+
if (priorFailure) {
|
|
165
|
+
throw priorFailure;
|
|
166
|
+
}
|
|
167
|
+
return await new Promise((resolve, reject) => {
|
|
168
|
+
const timeoutMs = opts?.timeoutMs ?? 30_000;
|
|
169
|
+
const timeout = setTimeout(() => {
|
|
170
|
+
this.#pendingInjected.delete(eventId);
|
|
171
|
+
reject(new Error(`Timed out waiting for delivery_injected for ${eventId}`));
|
|
172
|
+
}, timeoutMs);
|
|
173
|
+
this.#pendingInjected.set(eventId, {
|
|
174
|
+
targets,
|
|
175
|
+
timeout,
|
|
176
|
+
resolve,
|
|
177
|
+
reject,
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
async sendInput(name, data) {
|
|
182
|
+
await this.#client.sendInput(name, data);
|
|
183
|
+
}
|
|
184
|
+
onDeliveryFailed(listener) {
|
|
185
|
+
this.#ensureEventSubscription();
|
|
186
|
+
this.#deliveryFailedListeners.add(listener);
|
|
187
|
+
return () => {
|
|
188
|
+
this.#deliveryFailedListeners.delete(listener);
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
onAgentMessage(listener) {
|
|
192
|
+
this.#ensureEventSubscription();
|
|
193
|
+
this.#agentMessageListeners.add(listener);
|
|
194
|
+
return () => {
|
|
195
|
+
this.#agentMessageListeners.delete(listener);
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
onAgentExit(listener) {
|
|
199
|
+
this.#ensureEventSubscription();
|
|
200
|
+
this.#agentExitListeners.add(listener);
|
|
201
|
+
return () => {
|
|
202
|
+
this.#agentExitListeners.delete(listener);
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
async dispose() {
|
|
206
|
+
if (this.#disposed) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
this.#disposed = true;
|
|
210
|
+
const pending = [...this.#pendingInjected.values()];
|
|
211
|
+
this.#pendingInjected.clear();
|
|
212
|
+
for (const entry of pending) {
|
|
213
|
+
clearTimeout(entry.timeout);
|
|
214
|
+
entry.reject(new Error('InternalFleetClient disposed before delivery was confirmed'));
|
|
215
|
+
}
|
|
216
|
+
for (const unsubscribe of this.#eventUnsubscribers.splice(0)) {
|
|
217
|
+
unsubscribe();
|
|
218
|
+
}
|
|
219
|
+
this.#agentExitListeners.clear();
|
|
220
|
+
this.#deliveryFailedListeners.clear();
|
|
221
|
+
this.#agentMessageListeners.clear();
|
|
222
|
+
this.#failedDeliveries.clear();
|
|
223
|
+
this.#failedDeliveryIds.length = 0;
|
|
224
|
+
this.#client.disconnect?.();
|
|
225
|
+
this.#subscribed = false;
|
|
226
|
+
}
|
|
227
|
+
#ensureEventSubscription() {
|
|
228
|
+
if (this.#subscribed) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
this.#subscribed = true;
|
|
232
|
+
const offEvent = this.#client.onEvent?.((event) => this.#handleBrokerEvent(event));
|
|
233
|
+
if (offEvent)
|
|
234
|
+
this.#eventUnsubscribers.push(offEvent);
|
|
235
|
+
const offDeliveryUpdate = this.#client.addListener?.('deliveryUpdate', (event) => this.#handleBrokerEvent(event));
|
|
236
|
+
if (offDeliveryUpdate)
|
|
237
|
+
this.#eventUnsubscribers.push(offDeliveryUpdate);
|
|
238
|
+
const offAgentExited = this.#client.addListener?.('agentExited', (agent) => this.#emitAgentExit(agent.name, 'exited', {
|
|
239
|
+
key: `agentExited:${JSON.stringify(agent)}`,
|
|
240
|
+
hasStableId: false,
|
|
241
|
+
}));
|
|
242
|
+
if (offAgentExited)
|
|
243
|
+
this.#eventUnsubscribers.push(offAgentExited);
|
|
244
|
+
this.#client.connectEvents?.();
|
|
245
|
+
}
|
|
246
|
+
#handleBrokerEvent(event) {
|
|
247
|
+
if (event.kind === 'delivery_injected') {
|
|
248
|
+
this.#resolveInjected(event.event_id);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (event.kind === 'delivery_failed') {
|
|
252
|
+
this.#rejectInjected(event.event_id, event.reason);
|
|
253
|
+
this.#emitDeliveryFailed({
|
|
254
|
+
to: event.name,
|
|
255
|
+
msgId: event.event_id,
|
|
256
|
+
reason: event.reason,
|
|
257
|
+
}, eventIdentity(event));
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (event.kind === 'message_delivery_failed') {
|
|
261
|
+
if (event.event_id) {
|
|
262
|
+
this.#rejectInjected(event.event_id, event.lastError);
|
|
263
|
+
}
|
|
264
|
+
this.#emitDeliveryFailed({
|
|
265
|
+
to: event.to,
|
|
266
|
+
msgId: event.event_id,
|
|
267
|
+
reason: event.lastError,
|
|
268
|
+
}, eventIdentity(event));
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (event.kind === 'relay_inbound') {
|
|
272
|
+
this.#emitAgentMessage({
|
|
273
|
+
from: event.from,
|
|
274
|
+
target: event.target,
|
|
275
|
+
body: event.body,
|
|
276
|
+
threadId: event.thread_id,
|
|
277
|
+
eventId: event.event_id,
|
|
278
|
+
}, eventIdentity(event));
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (event.kind === 'agent_exit') {
|
|
282
|
+
this.#emitAgentExit(event.name, event.reason, eventIdentity(event));
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
if (event.kind === 'agent_exited') {
|
|
286
|
+
this.#emitAgentExit(event.name, event.reason ?? exitReason(event), eventIdentity(event));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
#resolveInjected(eventId) {
|
|
290
|
+
rememberRecent(eventId, this.#injectedEventIds, this.#injectedEventIdSet);
|
|
291
|
+
const pending = this.#pendingInjected.get(eventId);
|
|
292
|
+
if (!pending) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
clearTimeout(pending.timeout);
|
|
296
|
+
this.#pendingInjected.delete(eventId);
|
|
297
|
+
pending.resolve({ eventId, targets: pending.targets });
|
|
298
|
+
}
|
|
299
|
+
#rejectInjected(eventId, reason) {
|
|
300
|
+
const error = new Error(reason ? `Delivery failed for ${eventId}: ${reason}` : `Delivery failed for ${eventId}`);
|
|
301
|
+
this.#failedDeliveries.set(eventId, error);
|
|
302
|
+
this.#failedDeliveryIds.push(eventId);
|
|
303
|
+
if (this.#failedDeliveryIds.length > 500) {
|
|
304
|
+
const oldest = this.#failedDeliveryIds.shift();
|
|
305
|
+
if (oldest) {
|
|
306
|
+
this.#failedDeliveries.delete(oldest);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const pending = this.#pendingInjected.get(eventId);
|
|
310
|
+
if (!pending) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
clearTimeout(pending.timeout);
|
|
314
|
+
this.#pendingInjected.delete(eventId);
|
|
315
|
+
pending.reject(error);
|
|
316
|
+
}
|
|
317
|
+
#emitDeliveryFailed(info, identity) {
|
|
318
|
+
if (this.#rememberEvent(identity)) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
for (const listener of this.#deliveryFailedListeners) {
|
|
322
|
+
listener(info);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
#emitAgentMessage(message, identity) {
|
|
326
|
+
if (this.#rememberEvent(identity)) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
for (const listener of this.#agentMessageListeners) {
|
|
330
|
+
listener(message);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
#emitAgentExit(name, reason, identity) {
|
|
334
|
+
if (this.#rememberEvent(identity)) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (this.#rememberAgentExit(name)) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
for (const listener of this.#agentExitListeners) {
|
|
341
|
+
listener(name, reason);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
#rememberAgentExit(name) {
|
|
345
|
+
if (this.#exitedAgentNames.has(name)) {
|
|
346
|
+
this.#suppressedDuplicateAgentExits += 1;
|
|
347
|
+
if (this.#suppressedDuplicateAgentExits <= 3 || this.#suppressedDuplicateAgentExits % 100 === 0) {
|
|
348
|
+
this.#logger?.debug?.('[factory-sdk] suppressed duplicate agent exit', {
|
|
349
|
+
count: this.#suppressedDuplicateAgentExits,
|
|
350
|
+
name,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
this.#exitedAgentNames.add(name);
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
#clearAgentExitLatch(name) {
|
|
359
|
+
this.#exitedAgentNames.delete(name);
|
|
360
|
+
}
|
|
361
|
+
#rememberEvent(identity) {
|
|
362
|
+
const { key } = identity;
|
|
363
|
+
if (!identity.hasStableId) {
|
|
364
|
+
this.#missingIdentityEvents += 1;
|
|
365
|
+
if (this.#missingIdentityEvents === 1) {
|
|
366
|
+
this.#logger?.warn?.('[factory-sdk] broker event missing stable identity; deduping by full event content');
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
if (this.#seenEventKeys.has(key)) {
|
|
370
|
+
this.#suppressedDuplicateEvents += 1;
|
|
371
|
+
if (this.#suppressedDuplicateEvents <= 3 || this.#suppressedDuplicateEvents % 100 === 0) {
|
|
372
|
+
this.#logger?.debug?.('[factory-sdk] suppressed duplicate broker event', {
|
|
373
|
+
count: this.#suppressedDuplicateEvents,
|
|
374
|
+
key,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
this.#seenEventKeys.add(key);
|
|
380
|
+
this.#seenEvents.push(key);
|
|
381
|
+
if (this.#seenEvents.length > 500) {
|
|
382
|
+
const oldest = this.#seenEvents.shift();
|
|
383
|
+
if (oldest) {
|
|
384
|
+
this.#seenEventKeys.delete(oldest);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
function connectionPathForCwd(cwd) {
|
|
391
|
+
const stateDir = process.env.AGENT_RELAY_STATE_DIR;
|
|
392
|
+
if (stateDir)
|
|
393
|
+
return join(stateDir, 'connection.json');
|
|
394
|
+
return cwd ? join(cwd, '.agentworkforce', 'relay', 'connection.json') : undefined;
|
|
395
|
+
}
|
|
396
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
397
|
+
function assertSelfNode(node) {
|
|
398
|
+
if (node && node !== 'self') {
|
|
399
|
+
throw new Error(`InternalFleetClient only supports node 'self' tonight; received ${node}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
function sessionRefFrom(handle) {
|
|
403
|
+
return handle.session_ref ?? handle.sessionRef ?? handle.sessionId;
|
|
404
|
+
}
|
|
405
|
+
function spawnResultFrom(handle, resolvedPid = handle.pid) {
|
|
406
|
+
const result = { name: handle.name };
|
|
407
|
+
const sessionRef = sessionRefFrom(handle);
|
|
408
|
+
if (sessionRef)
|
|
409
|
+
result.sessionRef = sessionRef;
|
|
410
|
+
if (typeof resolvedPid === 'number')
|
|
411
|
+
result.pid = resolvedPid;
|
|
412
|
+
return result;
|
|
413
|
+
}
|
|
414
|
+
function resolveAgentRelayMcpCommand() {
|
|
415
|
+
try {
|
|
416
|
+
const packageJsonPath = requireForResolve.resolve('agent-relay/package.json');
|
|
417
|
+
const cliPath = join(dirname(packageJsonPath), 'dist', 'cli', 'index.js');
|
|
418
|
+
accessSync(cliPath, constants.R_OK);
|
|
419
|
+
return { command: process.execPath, args: [cliPath, 'mcp'] };
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
return undefined;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function buildRelayMcpHarnessConfig(input, command) {
|
|
426
|
+
const relayEnv = relayMcpEnv(input.name, input.agentToken);
|
|
427
|
+
return {
|
|
428
|
+
runtime: 'pty',
|
|
429
|
+
command: input.cli,
|
|
430
|
+
args: input.cli === 'claude'
|
|
431
|
+
? claudeHarnessArgs(input, command, relayEnv)
|
|
432
|
+
: codexHarnessArgs(input, command, relayEnv),
|
|
433
|
+
...(input.cwd ? { cwd: input.cwd } : {}),
|
|
434
|
+
env: relayEnv,
|
|
435
|
+
metadata: {
|
|
436
|
+
factoryRelayMcp: true,
|
|
437
|
+
relayMcpCommand: command.command,
|
|
438
|
+
relayMcpArgs: command.args,
|
|
439
|
+
},
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
function claudeHarnessArgs(input, command, relayEnv) {
|
|
443
|
+
return [
|
|
444
|
+
...modelArgs(input.model),
|
|
445
|
+
'--mcp-config',
|
|
446
|
+
JSON.stringify({
|
|
447
|
+
mcpServers: {
|
|
448
|
+
'agent-relay': stdioMcpServer(command, relayEnv),
|
|
449
|
+
},
|
|
450
|
+
}),
|
|
451
|
+
'--strict-mcp-config',
|
|
452
|
+
...(input.args ?? []),
|
|
453
|
+
...taskArgs(input.task),
|
|
454
|
+
];
|
|
455
|
+
}
|
|
456
|
+
function codexHarnessArgs(input, command, relayEnv) {
|
|
457
|
+
const prefix = 'mcp_servers.agent-relay';
|
|
458
|
+
return [
|
|
459
|
+
...modelArgs(stripProviderPrefix(input.model)),
|
|
460
|
+
'--config',
|
|
461
|
+
`${prefix}.command=${tomlString(command.command)}`,
|
|
462
|
+
'--config',
|
|
463
|
+
`${prefix}.args=${tomlArray(command.args)}`,
|
|
464
|
+
'--config',
|
|
465
|
+
`${prefix}.env=${tomlInlineTable(relayEnv)}`,
|
|
466
|
+
...(input.args ?? []),
|
|
467
|
+
...taskArgs(input.task),
|
|
468
|
+
];
|
|
469
|
+
}
|
|
470
|
+
function stdioMcpServer(command, relayEnv) {
|
|
471
|
+
return {
|
|
472
|
+
type: 'stdio',
|
|
473
|
+
command: command.command,
|
|
474
|
+
args: command.args,
|
|
475
|
+
env: relayEnv,
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function relayMcpEnv(agentName, agentToken) {
|
|
479
|
+
const env = {
|
|
480
|
+
RELAY_AGENT_NAME: agentName,
|
|
481
|
+
RELAY_AGENT_TYPE: 'agent',
|
|
482
|
+
RELAY_STRICT_AGENT_NAME: '1',
|
|
483
|
+
};
|
|
484
|
+
const workspaceKey = nonEmpty(process.env.RELAY_WORKSPACE_KEY) ??
|
|
485
|
+
nonEmpty(process.env.AGENT_RELAY_WORKSPACE_KEY) ??
|
|
486
|
+
relayWorkspaceKeyFromApiKey(process.env.RELAY_API_KEY);
|
|
487
|
+
if (workspaceKey) {
|
|
488
|
+
env.RELAY_WORKSPACE_KEY = workspaceKey;
|
|
489
|
+
env.RELAY_API_KEY = workspaceKey;
|
|
490
|
+
}
|
|
491
|
+
const baseUrl = nonEmpty(process.env.RELAY_BASE_URL);
|
|
492
|
+
if (baseUrl)
|
|
493
|
+
env.RELAY_BASE_URL = baseUrl;
|
|
494
|
+
const defaultWorkspace = nonEmpty(process.env.RELAY_DEFAULT_WORKSPACE);
|
|
495
|
+
if (defaultWorkspace)
|
|
496
|
+
env.RELAY_DEFAULT_WORKSPACE = defaultWorkspace;
|
|
497
|
+
const workspacesJson = nonEmpty(process.env.RELAY_WORKSPACES_JSON);
|
|
498
|
+
if (workspacesJson)
|
|
499
|
+
env.RELAY_WORKSPACES_JSON = workspacesJson;
|
|
500
|
+
const relayAgentToken = nonEmpty(agentToken);
|
|
501
|
+
if (relayAgentToken)
|
|
502
|
+
env.RELAY_AGENT_TOKEN = relayAgentToken;
|
|
503
|
+
return env;
|
|
504
|
+
}
|
|
505
|
+
function modelArgs(model) {
|
|
506
|
+
return model ? ['--model', model] : [];
|
|
507
|
+
}
|
|
508
|
+
function taskArgs(task) {
|
|
509
|
+
return task ? [task] : [];
|
|
510
|
+
}
|
|
511
|
+
function stripProviderPrefix(model) {
|
|
512
|
+
if (!model)
|
|
513
|
+
return undefined;
|
|
514
|
+
const idx = model.indexOf('/');
|
|
515
|
+
return idx >= 0 ? model.slice(idx + 1) : model;
|
|
516
|
+
}
|
|
517
|
+
function tomlString(value) {
|
|
518
|
+
return JSON.stringify(value);
|
|
519
|
+
}
|
|
520
|
+
function tomlArray(values) {
|
|
521
|
+
return `[${values.map(tomlString).join(', ')}]`;
|
|
522
|
+
}
|
|
523
|
+
function tomlInlineTable(values) {
|
|
524
|
+
return `{ ${Object.entries(values)
|
|
525
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
526
|
+
.map(([key, value]) => `${tomlString(key)} = ${tomlString(value)}`)
|
|
527
|
+
.join(', ')} }`;
|
|
528
|
+
}
|
|
529
|
+
function nonEmpty(value) {
|
|
530
|
+
const trimmed = value?.trim();
|
|
531
|
+
return trimmed || undefined;
|
|
532
|
+
}
|
|
533
|
+
function relayWorkspaceKeyFromApiKey(value) {
|
|
534
|
+
const trimmed = nonEmpty(value);
|
|
535
|
+
return trimmed?.startsWith('rk_live_') ? trimmed : undefined;
|
|
536
|
+
}
|
|
537
|
+
function messageInputFrom(input) {
|
|
538
|
+
return {
|
|
539
|
+
to: input.to,
|
|
540
|
+
text: input.text,
|
|
541
|
+
from: input.from,
|
|
542
|
+
data: input.data,
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
function eventIdentity(event) {
|
|
546
|
+
const record = event;
|
|
547
|
+
const stable = record.event_id ?? record.delivery_id;
|
|
548
|
+
return {
|
|
549
|
+
key: `${event.kind}:${stable ?? ''}:${JSON.stringify(event)}`,
|
|
550
|
+
hasStableId: Boolean(stable),
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
function rememberRecent(value, values, set) {
|
|
554
|
+
if (set.has(value)) {
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
set.add(value);
|
|
558
|
+
values.push(value);
|
|
559
|
+
if (values.length > 500) {
|
|
560
|
+
const oldest = values.shift();
|
|
561
|
+
if (oldest) {
|
|
562
|
+
set.delete(oldest);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
function exitReason(event) {
|
|
567
|
+
if (event.signal) {
|
|
568
|
+
return `signal:${event.signal}`;
|
|
569
|
+
}
|
|
570
|
+
if (typeof event.code === 'number') {
|
|
571
|
+
return `code:${event.code}`;
|
|
572
|
+
}
|
|
573
|
+
return 'exited';
|
|
574
|
+
}
|
|
575
|
+
//# sourceMappingURL=internal-fleet-client.js.map
|