@kbediako/codex-orchestrator 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/README.md +238 -0
- package/dist/bin/codex-orchestrator.js +507 -0
- package/dist/orchestrator/src/agents/builder.js +16 -0
- package/dist/orchestrator/src/agents/index.js +4 -0
- package/dist/orchestrator/src/agents/planner.js +17 -0
- package/dist/orchestrator/src/agents/reviewer.js +13 -0
- package/dist/orchestrator/src/agents/tester.js +13 -0
- package/dist/orchestrator/src/cli/adapters/CommandBuilder.js +20 -0
- package/dist/orchestrator/src/cli/adapters/CommandPlanner.js +164 -0
- package/dist/orchestrator/src/cli/adapters/CommandReviewer.js +32 -0
- package/dist/orchestrator/src/cli/adapters/CommandTester.js +33 -0
- package/dist/orchestrator/src/cli/adapters/index.js +4 -0
- package/dist/orchestrator/src/cli/config/userConfig.js +28 -0
- package/dist/orchestrator/src/cli/doctor.js +48 -0
- package/dist/orchestrator/src/cli/events/runEvents.js +84 -0
- package/dist/orchestrator/src/cli/exec/command.js +56 -0
- package/dist/orchestrator/src/cli/exec/context.js +108 -0
- package/dist/orchestrator/src/cli/exec/experience.js +77 -0
- package/dist/orchestrator/src/cli/exec/finalization.js +140 -0
- package/dist/orchestrator/src/cli/exec/learning.js +62 -0
- package/dist/orchestrator/src/cli/exec/stageRunner.js +71 -0
- package/dist/orchestrator/src/cli/exec/summary.js +109 -0
- package/dist/orchestrator/src/cli/exec/telemetry.js +18 -0
- package/dist/orchestrator/src/cli/exec/tfgrpo.js +200 -0
- package/dist/orchestrator/src/cli/exec/tfgrpoArtifacts.js +19 -0
- package/dist/orchestrator/src/cli/exec/types.js +1 -0
- package/dist/orchestrator/src/cli/init.js +64 -0
- package/dist/orchestrator/src/cli/mcp.js +124 -0
- package/dist/orchestrator/src/cli/metrics/metricsAggregator.js +404 -0
- package/dist/orchestrator/src/cli/metrics/metricsRecorder.js +138 -0
- package/dist/orchestrator/src/cli/orchestrator.js +554 -0
- package/dist/orchestrator/src/cli/pipelines/defaultDiagnostics.js +32 -0
- package/dist/orchestrator/src/cli/pipelines/designReference.js +72 -0
- package/dist/orchestrator/src/cli/pipelines/hiFiDesignToolkit.js +71 -0
- package/dist/orchestrator/src/cli/pipelines/index.js +34 -0
- package/dist/orchestrator/src/cli/run/environment.js +24 -0
- package/dist/orchestrator/src/cli/run/manifest.js +367 -0
- package/dist/orchestrator/src/cli/run/manifestPersister.js +88 -0
- package/dist/orchestrator/src/cli/run/runPaths.js +30 -0
- package/dist/orchestrator/src/cli/selfCheck.js +12 -0
- package/dist/orchestrator/src/cli/services/commandRunner.js +420 -0
- package/dist/orchestrator/src/cli/services/controlPlaneService.js +107 -0
- package/dist/orchestrator/src/cli/services/execRuntime.js +69 -0
- package/dist/orchestrator/src/cli/services/pipelineResolver.js +47 -0
- package/dist/orchestrator/src/cli/services/runPreparation.js +82 -0
- package/dist/orchestrator/src/cli/services/runSummaryWriter.js +35 -0
- package/dist/orchestrator/src/cli/services/schedulerService.js +42 -0
- package/dist/orchestrator/src/cli/tasks/taskMetadata.js +19 -0
- package/dist/orchestrator/src/cli/telemetry/schema.js +8 -0
- package/dist/orchestrator/src/cli/types.js +1 -0
- package/dist/orchestrator/src/cli/ui/HudApp.js +112 -0
- package/dist/orchestrator/src/cli/ui/controller.js +26 -0
- package/dist/orchestrator/src/cli/ui/store.js +240 -0
- package/dist/orchestrator/src/cli/utils/enforcementMode.js +12 -0
- package/dist/orchestrator/src/cli/utils/fs.js +8 -0
- package/dist/orchestrator/src/cli/utils/interactive.js +25 -0
- package/dist/orchestrator/src/cli/utils/jsonlWriter.js +10 -0
- package/dist/orchestrator/src/cli/utils/optionalDeps.js +30 -0
- package/dist/orchestrator/src/cli/utils/packageInfo.js +25 -0
- package/dist/orchestrator/src/cli/utils/planFormatter.js +49 -0
- package/dist/orchestrator/src/cli/utils/runId.js +7 -0
- package/dist/orchestrator/src/cli/utils/specGuardRunner.js +26 -0
- package/dist/orchestrator/src/cli/utils/strings.js +8 -0
- package/dist/orchestrator/src/cli/utils/time.js +6 -0
- package/dist/orchestrator/src/control-plane/drift-reporter.js +109 -0
- package/dist/orchestrator/src/control-plane/index.js +3 -0
- package/dist/orchestrator/src/control-plane/request-builder.js +217 -0
- package/dist/orchestrator/src/control-plane/types.js +1 -0
- package/dist/orchestrator/src/control-plane/validator.js +50 -0
- package/dist/orchestrator/src/credentials/CredentialBroker.js +1 -0
- package/dist/orchestrator/src/events/EventBus.js +25 -0
- package/dist/orchestrator/src/learning/crystalizer.js +108 -0
- package/dist/orchestrator/src/learning/harvester.js +146 -0
- package/dist/orchestrator/src/learning/manifest.js +56 -0
- package/dist/orchestrator/src/learning/runner.js +177 -0
- package/dist/orchestrator/src/learning/validator.js +164 -0
- package/dist/orchestrator/src/logger.js +20 -0
- package/dist/orchestrator/src/manager.js +388 -0
- package/dist/orchestrator/src/persistence/ArtifactStager.js +95 -0
- package/dist/orchestrator/src/persistence/ExperienceStore.js +210 -0
- package/dist/orchestrator/src/persistence/PersistenceCoordinator.js +65 -0
- package/dist/orchestrator/src/persistence/RunManifestWriter.js +23 -0
- package/dist/orchestrator/src/persistence/TaskStateStore.js +172 -0
- package/dist/orchestrator/src/persistence/identifierGuards.js +1 -0
- package/dist/orchestrator/src/persistence/lockFile.js +26 -0
- package/dist/orchestrator/src/persistence/sanitizeIdentifier.js +26 -0
- package/dist/orchestrator/src/persistence/sanitizeRunId.js +8 -0
- package/dist/orchestrator/src/persistence/sanitizeTaskId.js +8 -0
- package/dist/orchestrator/src/persistence/writeAtomicFile.js +4 -0
- package/dist/orchestrator/src/privacy/guard.js +111 -0
- package/dist/orchestrator/src/scheduler/index.js +1 -0
- package/dist/orchestrator/src/scheduler/plan.js +171 -0
- package/dist/orchestrator/src/scheduler/types.js +1 -0
- package/dist/orchestrator/src/sync/CloudRunsClient.js +1 -0
- package/dist/orchestrator/src/sync/CloudRunsHttpClient.js +82 -0
- package/dist/orchestrator/src/sync/CloudSyncWorker.js +206 -0
- package/dist/orchestrator/src/sync/createCloudSyncWorker.js +15 -0
- package/dist/orchestrator/src/types.js +1 -0
- package/dist/orchestrator/src/utils/atomicWrite.js +15 -0
- package/dist/orchestrator/src/utils/errorMessage.js +14 -0
- package/dist/orchestrator/src/utils/executionMode.js +69 -0
- package/dist/packages/control-plane-schemas/src/index.js +1 -0
- package/dist/packages/control-plane-schemas/src/run-request.js +548 -0
- package/dist/packages/orchestrator/src/exec/handle-service.js +203 -0
- package/dist/packages/orchestrator/src/exec/session-manager.js +147 -0
- package/dist/packages/orchestrator/src/exec/unified-exec.js +432 -0
- package/dist/packages/orchestrator/src/index.js +3 -0
- package/dist/packages/orchestrator/src/instructions/loader.js +101 -0
- package/dist/packages/orchestrator/src/instructions/promptPacks.js +151 -0
- package/dist/packages/orchestrator/src/notifications/index.js +74 -0
- package/dist/packages/orchestrator/src/telemetry/otel-exporter.js +142 -0
- package/dist/packages/orchestrator/src/tool-orchestrator.js +161 -0
- package/dist/packages/sdk-node/src/orchestrator.js +195 -0
- package/dist/packages/shared/config/designConfig.js +495 -0
- package/dist/packages/shared/config/env.js +37 -0
- package/dist/packages/shared/config/index.js +2 -0
- package/dist/packages/shared/design-artifacts/writer.js +221 -0
- package/dist/packages/shared/events/serializer.js +84 -0
- package/dist/packages/shared/events/types.js +1 -0
- package/dist/packages/shared/manifest/artifactUtils.js +36 -0
- package/dist/packages/shared/manifest/designArtifacts.js +665 -0
- package/dist/packages/shared/manifest/fileIO.js +29 -0
- package/dist/packages/shared/manifest/toolRuns.js +78 -0
- package/dist/packages/shared/manifest/toolkitArtifacts.js +223 -0
- package/dist/packages/shared/manifest/types.js +5 -0
- package/dist/packages/shared/manifest/validator.js +73 -0
- package/dist/packages/shared/manifest/writer.js +2 -0
- package/dist/packages/shared/streams/stdio.js +112 -0
- package/dist/scripts/design/pipeline/advanced-assets.js +466 -0
- package/dist/scripts/design/pipeline/componentize.js +74 -0
- package/dist/scripts/design/pipeline/context.js +34 -0
- package/dist/scripts/design/pipeline/extract.js +249 -0
- package/dist/scripts/design/pipeline/optionalDeps.js +107 -0
- package/dist/scripts/design/pipeline/prepare.js +46 -0
- package/dist/scripts/design/pipeline/reference.js +94 -0
- package/dist/scripts/design/pipeline/state.js +206 -0
- package/dist/scripts/design/pipeline/toolkit/common.js +94 -0
- package/dist/scripts/design/pipeline/toolkit/extract.js +258 -0
- package/dist/scripts/design/pipeline/toolkit/publish.js +202 -0
- package/dist/scripts/design/pipeline/toolkit/publishActions.js +12 -0
- package/dist/scripts/design/pipeline/toolkit/reference.js +846 -0
- package/dist/scripts/design/pipeline/toolkit/snapshot.js +882 -0
- package/dist/scripts/design/pipeline/toolkit/tokens.js +456 -0
- package/dist/scripts/design/pipeline/visual-regression.js +137 -0
- package/dist/scripts/design/pipeline/write-artifacts.js +61 -0
- package/package.json +97 -0
- package/schemas/manifest.json +1064 -0
- package/templates/README.md +12 -0
- package/templates/codex/mcp-client.json +8 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
const DEFAULT_MAX_STORED_FRAMES = 500;
|
|
3
|
+
const DEFAULT_MAX_QUEUE_SIZE = 32;
|
|
4
|
+
export class RemoteExecHandleService {
|
|
5
|
+
handles = new Map();
|
|
6
|
+
maxStoredFrames;
|
|
7
|
+
now;
|
|
8
|
+
guard;
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.maxStoredFrames = options.maxStoredFrames ?? DEFAULT_MAX_STORED_FRAMES;
|
|
11
|
+
this.now = options.now ?? (() => new Date());
|
|
12
|
+
this.guard = options.guard;
|
|
13
|
+
}
|
|
14
|
+
setGuard(guard) {
|
|
15
|
+
this.guard = guard;
|
|
16
|
+
}
|
|
17
|
+
issueHandle(correlationId) {
|
|
18
|
+
const id = randomUUID();
|
|
19
|
+
const createdAt = this.now().toISOString();
|
|
20
|
+
const handle = {
|
|
21
|
+
id,
|
|
22
|
+
correlationId,
|
|
23
|
+
createdAt,
|
|
24
|
+
frames: [],
|
|
25
|
+
status: 'open',
|
|
26
|
+
observers: new Map(),
|
|
27
|
+
nextSequence: 1,
|
|
28
|
+
decisions: []
|
|
29
|
+
};
|
|
30
|
+
this.handles.set(id, handle);
|
|
31
|
+
return this.describeHandle(handle);
|
|
32
|
+
}
|
|
33
|
+
async append(handleId, event) {
|
|
34
|
+
const handle = this.getHandle(handleId);
|
|
35
|
+
if (handle.status === 'closed') {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const frame = {
|
|
39
|
+
sequence: handle.nextSequence,
|
|
40
|
+
event,
|
|
41
|
+
timestamp: event.timestamp
|
|
42
|
+
};
|
|
43
|
+
handle.nextSequence += 1;
|
|
44
|
+
const processed = this.guard
|
|
45
|
+
? await this.guard.process(frame, { handleId })
|
|
46
|
+
: { frame, decision: { action: 'allow' } };
|
|
47
|
+
handle.decisions.push({ sequence: frame.sequence, decision: processed.decision });
|
|
48
|
+
if (processed.frame) {
|
|
49
|
+
handle.frames.push(processed.frame);
|
|
50
|
+
if (handle.frames.length > this.maxStoredFrames) {
|
|
51
|
+
handle.frames.splice(0, handle.frames.length - this.maxStoredFrames);
|
|
52
|
+
}
|
|
53
|
+
this.notifyObservers(handle, processed.frame);
|
|
54
|
+
}
|
|
55
|
+
this.pruneDecisions(handle);
|
|
56
|
+
}
|
|
57
|
+
close(handleId) {
|
|
58
|
+
const handle = this.getHandle(handleId);
|
|
59
|
+
handle.status = 'closed';
|
|
60
|
+
}
|
|
61
|
+
subscribe(handleId, observerId, options, onFrame) {
|
|
62
|
+
const handle = this.getHandle(handleId);
|
|
63
|
+
const state = {
|
|
64
|
+
id: observerId,
|
|
65
|
+
queue: [],
|
|
66
|
+
maxQueueSize: Math.max(1, options.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE),
|
|
67
|
+
delivered: 0,
|
|
68
|
+
dropped: 0,
|
|
69
|
+
flushing: false,
|
|
70
|
+
callback: onFrame
|
|
71
|
+
};
|
|
72
|
+
handle.observers.set(observerId, state);
|
|
73
|
+
// Replay frames from requested sequence.
|
|
74
|
+
const fromSequence = options.fromSequence ?? 1;
|
|
75
|
+
const startIndex = this.findFrameStartIndex(handle.frames, fromSequence);
|
|
76
|
+
for (let index = startIndex; index < handle.frames.length; index += 1) {
|
|
77
|
+
const frame = handle.frames[index];
|
|
78
|
+
if (!frame) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
this.enqueueFrame(state, frame);
|
|
82
|
+
}
|
|
83
|
+
const unsubscribe = () => {
|
|
84
|
+
handle.observers.delete(observerId);
|
|
85
|
+
};
|
|
86
|
+
return {
|
|
87
|
+
unsubscribe,
|
|
88
|
+
stats: () => ({ delivered: state.delivered, dropped: state.dropped })
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
getSnapshot(handleId, fromSequence = 1) {
|
|
92
|
+
const handle = this.getHandle(handleId);
|
|
93
|
+
const startIndex = this.findFrameStartIndex(handle.frames, fromSequence);
|
|
94
|
+
return handle.frames.slice(startIndex);
|
|
95
|
+
}
|
|
96
|
+
getDescriptor(handleId) {
|
|
97
|
+
const handle = this.getHandle(handleId);
|
|
98
|
+
return this.describeHandle(handle);
|
|
99
|
+
}
|
|
100
|
+
getDecisions(handleId) {
|
|
101
|
+
const handle = this.getHandle(handleId);
|
|
102
|
+
return [...handle.decisions];
|
|
103
|
+
}
|
|
104
|
+
getHandle(handleId) {
|
|
105
|
+
const handle = this.handles.get(handleId);
|
|
106
|
+
if (!handle) {
|
|
107
|
+
throw new Error(`Exec handle ${handleId} not found.`);
|
|
108
|
+
}
|
|
109
|
+
return handle;
|
|
110
|
+
}
|
|
111
|
+
enqueueFrame(observer, frame) {
|
|
112
|
+
if (observer.queue.length >= observer.maxQueueSize) {
|
|
113
|
+
observer.queue.shift();
|
|
114
|
+
observer.dropped += 1;
|
|
115
|
+
}
|
|
116
|
+
observer.queue.push(frame);
|
|
117
|
+
this.flush(observer);
|
|
118
|
+
}
|
|
119
|
+
notifyObservers(handle, frame) {
|
|
120
|
+
for (const observer of handle.observers.values()) {
|
|
121
|
+
this.enqueueFrame(observer, frame);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
flush(observer) {
|
|
125
|
+
if (observer.flushing) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
observer.flushing = true;
|
|
129
|
+
queueMicrotask(() => {
|
|
130
|
+
observer.flushing = false;
|
|
131
|
+
while (observer.queue.length > 0) {
|
|
132
|
+
const frame = observer.queue.shift();
|
|
133
|
+
if (!frame) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
observer.delivered += 1;
|
|
137
|
+
observer.callback(frame);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
describeHandle(handle) {
|
|
142
|
+
return {
|
|
143
|
+
id: handle.id,
|
|
144
|
+
correlationId: handle.correlationId,
|
|
145
|
+
createdAt: handle.createdAt,
|
|
146
|
+
frameCount: handle.frames.length,
|
|
147
|
+
status: handle.status,
|
|
148
|
+
latestSequence: handle.nextSequence - 1
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
pruneDecisions(handle) {
|
|
152
|
+
if (handle.decisions.length === 0) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (this.maxStoredFrames <= 0) {
|
|
156
|
+
handle.decisions.length = 0;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const slidingMinSequence = Math.max(1, handle.nextSequence - this.maxStoredFrames);
|
|
160
|
+
const preservedSequences = new Set();
|
|
161
|
+
for (const frame of handle.frames) {
|
|
162
|
+
preservedSequences.add(frame.sequence);
|
|
163
|
+
}
|
|
164
|
+
let writeIndex = 0;
|
|
165
|
+
for (let index = 0; index < handle.decisions.length; index += 1) {
|
|
166
|
+
const entry = handle.decisions[index];
|
|
167
|
+
if (!entry) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const keep = entry.sequence >= slidingMinSequence || preservedSequences.has(entry.sequence);
|
|
171
|
+
if (keep) {
|
|
172
|
+
handle.decisions[writeIndex] = entry;
|
|
173
|
+
writeIndex += 1;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (writeIndex < handle.decisions.length) {
|
|
177
|
+
handle.decisions.length = writeIndex;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
findFrameStartIndex(frames, fromSequence) {
|
|
181
|
+
if (fromSequence <= 1 || frames.length === 0) {
|
|
182
|
+
return 0;
|
|
183
|
+
}
|
|
184
|
+
let low = 0;
|
|
185
|
+
let high = frames.length - 1;
|
|
186
|
+
let result = frames.length;
|
|
187
|
+
while (low <= high) {
|
|
188
|
+
const mid = (low + high) >> 1;
|
|
189
|
+
const frame = frames[mid];
|
|
190
|
+
if (!frame) {
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
if (frame.sequence >= fromSequence) {
|
|
194
|
+
result = mid;
|
|
195
|
+
high = mid - 1;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
low = mid + 1;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
/**
|
|
4
|
+
* Manages reusable exec sessions (e.g. PTY handles) keyed by identifier while
|
|
5
|
+
* providing lifecycle hooks and environment snapshots for observability.
|
|
6
|
+
*/
|
|
7
|
+
export class ExecSessionManager {
|
|
8
|
+
sessions = new Map();
|
|
9
|
+
emitter = new EventEmitter({ captureRejections: false });
|
|
10
|
+
factory;
|
|
11
|
+
baseEnv;
|
|
12
|
+
now;
|
|
13
|
+
idGenerator;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.factory = options.factory;
|
|
16
|
+
this.baseEnv = options.baseEnv ? { ...options.baseEnv } : { ...process.env };
|
|
17
|
+
this.now = options.now ?? (() => new Date());
|
|
18
|
+
this.idGenerator = options.idGenerator ?? (() => randomUUID());
|
|
19
|
+
}
|
|
20
|
+
async acquire(options = {}) {
|
|
21
|
+
const id = options.id ?? this.idGenerator();
|
|
22
|
+
const reuse = options.reuse ?? Boolean(options.id);
|
|
23
|
+
const persisted = options.persist ?? Boolean(options.id);
|
|
24
|
+
const envSnapshot = this.snapshotEnv(options.env);
|
|
25
|
+
if (persisted && reuse) {
|
|
26
|
+
const existing = this.sessions.get(id);
|
|
27
|
+
if (existing) {
|
|
28
|
+
existing.lastUsedAt = this.now().toISOString();
|
|
29
|
+
if (options.env !== undefined) {
|
|
30
|
+
existing.envSnapshot = envSnapshot;
|
|
31
|
+
}
|
|
32
|
+
return this.createLease(existing, true, persisted);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (!reuse && persisted) {
|
|
36
|
+
await this.dispose(id);
|
|
37
|
+
}
|
|
38
|
+
const managed = await this.createSession(id, envSnapshot, persisted);
|
|
39
|
+
if (persisted) {
|
|
40
|
+
this.sessions.set(id, managed);
|
|
41
|
+
}
|
|
42
|
+
return this.createLease(managed, false, persisted);
|
|
43
|
+
}
|
|
44
|
+
async dispose(id) {
|
|
45
|
+
const session = this.sessions.get(id);
|
|
46
|
+
if (!session) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this.sessions.delete(id);
|
|
50
|
+
await this.teardown(session);
|
|
51
|
+
}
|
|
52
|
+
async disposeAll() {
|
|
53
|
+
const disposals = Array.from(this.sessions.values()).map((session) => this.teardown(session));
|
|
54
|
+
this.sessions.clear();
|
|
55
|
+
await Promise.all(disposals);
|
|
56
|
+
}
|
|
57
|
+
getSnapshot(id) {
|
|
58
|
+
const session = this.sessions.get(id);
|
|
59
|
+
return session ? { ...session.envSnapshot } : undefined;
|
|
60
|
+
}
|
|
61
|
+
on(event, listener) {
|
|
62
|
+
this.emitter.on(event, listener);
|
|
63
|
+
return () => {
|
|
64
|
+
this.emitter.off(event, listener);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async createSession(id, envSnapshot, persisted) {
|
|
68
|
+
const createdAt = this.now().toISOString();
|
|
69
|
+
const handle = await this.factory({
|
|
70
|
+
id,
|
|
71
|
+
env: envSnapshot,
|
|
72
|
+
persisted,
|
|
73
|
+
createdAt
|
|
74
|
+
});
|
|
75
|
+
const managed = {
|
|
76
|
+
id,
|
|
77
|
+
handle,
|
|
78
|
+
envSnapshot,
|
|
79
|
+
createdAt,
|
|
80
|
+
lastUsedAt: createdAt,
|
|
81
|
+
persisted
|
|
82
|
+
};
|
|
83
|
+
this.emit('session:created', managed);
|
|
84
|
+
return managed;
|
|
85
|
+
}
|
|
86
|
+
createLease(session, reused, persisted) {
|
|
87
|
+
return {
|
|
88
|
+
id: session.id,
|
|
89
|
+
handle: session.handle,
|
|
90
|
+
envSnapshot: { ...session.envSnapshot },
|
|
91
|
+
createdAt: session.createdAt,
|
|
92
|
+
lastUsedAt: session.lastUsedAt,
|
|
93
|
+
persisted,
|
|
94
|
+
reused,
|
|
95
|
+
release: async () => {
|
|
96
|
+
if (!persisted) {
|
|
97
|
+
await this.teardown(session);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
session.lastUsedAt = this.now().toISOString();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
async teardown(session) {
|
|
106
|
+
try {
|
|
107
|
+
await session.handle.dispose();
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
session.lastUsedAt = this.now().toISOString();
|
|
111
|
+
this.emit('session:disposed', session);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
emit(event, session) {
|
|
115
|
+
const payload = {
|
|
116
|
+
type: event,
|
|
117
|
+
session: {
|
|
118
|
+
id: session.id,
|
|
119
|
+
envSnapshot: { ...session.envSnapshot },
|
|
120
|
+
createdAt: session.createdAt,
|
|
121
|
+
lastUsedAt: session.lastUsedAt,
|
|
122
|
+
persisted: session.persisted,
|
|
123
|
+
handle: session.handle
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
this.emitter.emit(event, payload);
|
|
127
|
+
}
|
|
128
|
+
snapshotEnv(overrides) {
|
|
129
|
+
const snapshot = {};
|
|
130
|
+
for (const [key, value] of Object.entries(this.baseEnv)) {
|
|
131
|
+
if (typeof value === 'string') {
|
|
132
|
+
snapshot[key] = value;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (overrides) {
|
|
136
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
137
|
+
if (value === undefined) {
|
|
138
|
+
delete snapshot[key];
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
snapshot[key] = value;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return snapshot;
|
|
146
|
+
}
|
|
147
|
+
}
|