@goondan/runtime 0.0.3-alpha5 → 0.0.3-alpha8
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/dist/events/runtime-events.d.ts +1 -0
- package/dist/events/runtime-events.d.ts.map +1 -1
- package/dist/events/runtime-events.js +11 -0
- package/dist/events/runtime-events.js.map +1 -1
- package/dist/pipeline/registry.d.ts +3 -1
- package/dist/pipeline/registry.d.ts.map +1 -1
- package/dist/pipeline/registry.js +8 -0
- package/dist/pipeline/registry.js.map +1 -1
- package/dist/runner/runtime-runner.d.ts +9 -0
- package/dist/runner/runtime-runner.d.ts.map +1 -1
- package/dist/runner/runtime-runner.js +332 -57
- package/dist/runner/runtime-runner.js.map +1 -1
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/workspace/paths.d.ts +1 -0
- package/dist/workspace/paths.d.ts.map +1 -1
- package/dist/workspace/paths.js +3 -0
- package/dist/workspace/paths.js.map +1 -1
- package/dist/workspace/storage.d.ts +2 -0
- package/dist/workspace/storage.d.ts.map +1 -1
- package/dist/workspace/storage.js +6 -0
- package/dist/workspace/storage.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,10 +9,13 @@ import { generateText, jsonSchema, stepCountIs, tool, } from 'ai';
|
|
|
9
9
|
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
10
10
|
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
11
11
|
import { createOpenAI } from '@ai-sdk/openai';
|
|
12
|
-
import { BundleLoader, ConversationStateImpl, ExtensionApiImpl, ExtensionStateManagerImpl, PipelineRegistryImpl, buildToolName, createMinimalToolContext, isJsonObject, loadExtensions, normalizeObjectRef, FileWorkspaceStorage, ToolExecutor, ToolRegistryImpl, WorkspacePaths, } from '../index.js';
|
|
12
|
+
import { BundleLoader, ConversationStateImpl, ExtensionApiImpl, ExtensionStateManagerImpl, PipelineRegistryImpl, RUNTIME_EVENT_TYPES, RuntimeEventBusImpl, buildToolName, createMinimalToolContext, isJsonObject, loadExtensions, normalizeObjectRef, FileWorkspaceStorage, ToolExecutor, ToolRegistryImpl, WorkspacePaths, } from '../index.js';
|
|
13
13
|
import { formatRuntimeInboundUserText, parseAgentToolEventPayload, parseConnectorEventPayload, selectMatchingIngressRule, resolveInboundInstanceKey, resolveRuntimeWorkdir, } from './runtime-routing.js';
|
|
14
14
|
import { buildStepLimitResponse } from './turn-policy.js';
|
|
15
15
|
import { toConversationTurns, toPersistentMessages, } from './conversation-state.js';
|
|
16
|
+
const DEFAULT_MIDDLEWARE_AGENT_REQUEST_TIMEOUT_MS = 15_000;
|
|
17
|
+
const EXTENSION_AGENT_CALL_SOURCE = 'extension-middleware';
|
|
18
|
+
const AGENT_CALL_STACK_METADATA_KEY = '__goondanAgentCallStack';
|
|
16
19
|
const ORCHESTRATOR_PROCESS_NAME = 'orchestrator';
|
|
17
20
|
const REPLACEMENT_STARTUP_TIMEOUT_MS = 5000;
|
|
18
21
|
const CONNECTOR_CHILD_STARTUP_TIMEOUT_MS = 5000;
|
|
@@ -1243,6 +1246,163 @@ function buildRuntimeAgentCatalog(runnerPlan, selfAgent) {
|
|
|
1243
1246
|
callableAgents,
|
|
1244
1247
|
};
|
|
1245
1248
|
}
|
|
1249
|
+
function createAgentCallNode(agentName, instanceKey) {
|
|
1250
|
+
return `${agentName}@${instanceKey}`;
|
|
1251
|
+
}
|
|
1252
|
+
function readAgentCallStack(metadata) {
|
|
1253
|
+
if (!metadata) {
|
|
1254
|
+
return [];
|
|
1255
|
+
}
|
|
1256
|
+
const value = metadata[AGENT_CALL_STACK_METADATA_KEY];
|
|
1257
|
+
if (!Array.isArray(value)) {
|
|
1258
|
+
return [];
|
|
1259
|
+
}
|
|
1260
|
+
const stack = [];
|
|
1261
|
+
for (const item of value) {
|
|
1262
|
+
if (typeof item !== 'string' || item.length === 0) {
|
|
1263
|
+
continue;
|
|
1264
|
+
}
|
|
1265
|
+
stack.push(item);
|
|
1266
|
+
}
|
|
1267
|
+
return stack;
|
|
1268
|
+
}
|
|
1269
|
+
function appendAgentCallStack(stack, node) {
|
|
1270
|
+
if (stack.includes(node)) {
|
|
1271
|
+
return [...stack];
|
|
1272
|
+
}
|
|
1273
|
+
return [...stack, node];
|
|
1274
|
+
}
|
|
1275
|
+
function withAgentCallStack(metadata, stack) {
|
|
1276
|
+
const next = {};
|
|
1277
|
+
if (metadata) {
|
|
1278
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
1279
|
+
next[key] = value;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
next[AGENT_CALL_STACK_METADATA_KEY] = stack;
|
|
1283
|
+
return next;
|
|
1284
|
+
}
|
|
1285
|
+
function toMiddlewareAgentResponseText(response) {
|
|
1286
|
+
if (typeof response === 'string') {
|
|
1287
|
+
return response;
|
|
1288
|
+
}
|
|
1289
|
+
if (response === undefined || response === null) {
|
|
1290
|
+
return '';
|
|
1291
|
+
}
|
|
1292
|
+
return safeJsonStringify(response);
|
|
1293
|
+
}
|
|
1294
|
+
function createMiddlewareAgentMetadata(input) {
|
|
1295
|
+
const next = {};
|
|
1296
|
+
if (input.metadata) {
|
|
1297
|
+
for (const [key, value] of Object.entries(input.metadata)) {
|
|
1298
|
+
next[key] = value;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
const callerNode = createAgentCallNode(input.callerAgentName, input.callerInstanceKey);
|
|
1302
|
+
const inheritedStack = readAgentCallStack(input.inheritedMetadata);
|
|
1303
|
+
const callStack = appendAgentCallStack(inheritedStack, callerNode);
|
|
1304
|
+
next.callerAgent = input.callerAgentName;
|
|
1305
|
+
next.callerInstanceKey = input.callerInstanceKey;
|
|
1306
|
+
next.callerTurnId = input.callerTurnId;
|
|
1307
|
+
next.callSource = EXTENSION_AGENT_CALL_SOURCE;
|
|
1308
|
+
next[AGENT_CALL_STACK_METADATA_KEY] = callStack;
|
|
1309
|
+
return next;
|
|
1310
|
+
}
|
|
1311
|
+
function createMiddlewareAgentEvent(input) {
|
|
1312
|
+
const event = {
|
|
1313
|
+
id: createId('agent_event'),
|
|
1314
|
+
type: input.eventType,
|
|
1315
|
+
createdAt: new Date(),
|
|
1316
|
+
traceId: input.traceId,
|
|
1317
|
+
source: {
|
|
1318
|
+
kind: 'agent',
|
|
1319
|
+
name: input.callerAgentName,
|
|
1320
|
+
},
|
|
1321
|
+
input: input.eventInput,
|
|
1322
|
+
instanceKey: input.targetInstanceKey,
|
|
1323
|
+
metadata: input.metadata,
|
|
1324
|
+
};
|
|
1325
|
+
if (input.correlationId) {
|
|
1326
|
+
return {
|
|
1327
|
+
...event,
|
|
1328
|
+
replyTo: {
|
|
1329
|
+
target: input.callerAgentName,
|
|
1330
|
+
correlationId: input.correlationId,
|
|
1331
|
+
},
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
return event;
|
|
1335
|
+
}
|
|
1336
|
+
function normalizeMiddlewareTarget(target) {
|
|
1337
|
+
const resolved = target.trim();
|
|
1338
|
+
if (resolved.length === 0) {
|
|
1339
|
+
throw new Error('ctx.agents 호출에는 target이 필요합니다.');
|
|
1340
|
+
}
|
|
1341
|
+
return resolved;
|
|
1342
|
+
}
|
|
1343
|
+
function normalizeMiddlewareInstanceKey(instanceKey, fallback) {
|
|
1344
|
+
if (!instanceKey) {
|
|
1345
|
+
return fallback;
|
|
1346
|
+
}
|
|
1347
|
+
const resolved = instanceKey.trim();
|
|
1348
|
+
return resolved.length > 0 ? resolved : fallback;
|
|
1349
|
+
}
|
|
1350
|
+
function normalizeMiddlewareTimeoutMs(timeoutMs) {
|
|
1351
|
+
if (typeof timeoutMs === 'number' &&
|
|
1352
|
+
Number.isFinite(timeoutMs) &&
|
|
1353
|
+
Number.isInteger(timeoutMs) &&
|
|
1354
|
+
timeoutMs > 0) {
|
|
1355
|
+
return timeoutMs;
|
|
1356
|
+
}
|
|
1357
|
+
return DEFAULT_MIDDLEWARE_AGENT_REQUEST_TIMEOUT_MS;
|
|
1358
|
+
}
|
|
1359
|
+
function createMiddlewareAgentsApi(input) {
|
|
1360
|
+
const resolveMetadata = (metadata) => createMiddlewareAgentMetadata({
|
|
1361
|
+
callerAgentName: input.callerAgentName,
|
|
1362
|
+
callerInstanceKey: input.callerInstanceKey,
|
|
1363
|
+
callerTurnId: input.callerTurnId,
|
|
1364
|
+
inheritedMetadata: input.inboundMetadata,
|
|
1365
|
+
metadata,
|
|
1366
|
+
});
|
|
1367
|
+
return {
|
|
1368
|
+
request: async (params) => {
|
|
1369
|
+
const target = normalizeMiddlewareTarget(params.target);
|
|
1370
|
+
const targetInstanceKey = normalizeMiddlewareInstanceKey(params.instanceKey, input.callerInstanceKey);
|
|
1371
|
+
const timeoutMs = normalizeMiddlewareTimeoutMs(params.timeoutMs);
|
|
1372
|
+
const correlationId = createId('corr');
|
|
1373
|
+
const event = createMiddlewareAgentEvent({
|
|
1374
|
+
callerAgentName: input.callerAgentName,
|
|
1375
|
+
traceId: input.traceId,
|
|
1376
|
+
eventType: 'agent.request',
|
|
1377
|
+
eventInput: params.input,
|
|
1378
|
+
targetInstanceKey,
|
|
1379
|
+
metadata: resolveMetadata(params.metadata),
|
|
1380
|
+
correlationId,
|
|
1381
|
+
});
|
|
1382
|
+
const result = await input.runtime.request(target, event, { timeoutMs });
|
|
1383
|
+
return {
|
|
1384
|
+
target: result.target,
|
|
1385
|
+
response: toMiddlewareAgentResponseText(result.response),
|
|
1386
|
+
};
|
|
1387
|
+
},
|
|
1388
|
+
send: async (params) => {
|
|
1389
|
+
const target = normalizeMiddlewareTarget(params.target);
|
|
1390
|
+
const targetInstanceKey = normalizeMiddlewareInstanceKey(params.instanceKey, input.callerInstanceKey);
|
|
1391
|
+
const event = createMiddlewareAgentEvent({
|
|
1392
|
+
callerAgentName: input.callerAgentName,
|
|
1393
|
+
traceId: input.traceId,
|
|
1394
|
+
eventType: 'agent.send',
|
|
1395
|
+
eventInput: params.input,
|
|
1396
|
+
targetInstanceKey,
|
|
1397
|
+
metadata: resolveMetadata(params.metadata),
|
|
1398
|
+
});
|
|
1399
|
+
const result = await input.runtime.send(target, event);
|
|
1400
|
+
return {
|
|
1401
|
+
accepted: result.accepted,
|
|
1402
|
+
};
|
|
1403
|
+
},
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1246
1406
|
function mergeToolCatalog(baseCatalog, extensionCatalog) {
|
|
1247
1407
|
const merged = [];
|
|
1248
1408
|
for (const item of baseCatalog) {
|
|
@@ -1919,6 +2079,15 @@ function createAgentToolRuntime(input) {
|
|
|
1919
2079
|
if (!parsed) {
|
|
1920
2080
|
throw new Error('agents__request 입력 이벤트 형식이 올바르지 않습니다.');
|
|
1921
2081
|
}
|
|
2082
|
+
if (target === input.callerAgentName && parsed.instanceKey === input.callerInstanceKey) {
|
|
2083
|
+
throw new Error('agents__request는 동일 agent+instance를 대상으로 호출할 수 없습니다.');
|
|
2084
|
+
}
|
|
2085
|
+
const callerNode = createAgentCallNode(input.callerAgentName, input.callerInstanceKey);
|
|
2086
|
+
const targetNode = createAgentCallNode(target, parsed.instanceKey);
|
|
2087
|
+
const currentCallStack = appendAgentCallStack(readAgentCallStack(parsed.metadata), callerNode);
|
|
2088
|
+
if (currentCallStack.includes(targetNode)) {
|
|
2089
|
+
throw new Error(`agents__request 순환 호출이 감지되었습니다: ${[...currentCallStack, targetNode].join(' -> ')}`);
|
|
2090
|
+
}
|
|
1922
2091
|
const inboundEvent = {
|
|
1923
2092
|
sourceKind: 'agent',
|
|
1924
2093
|
sourceName: parsed.sourceName,
|
|
@@ -1929,11 +2098,8 @@ function createAgentToolRuntime(input) {
|
|
|
1929
2098
|
from_agent: input.callerAgentName,
|
|
1930
2099
|
from_instance: input.callerInstanceKey,
|
|
1931
2100
|
},
|
|
1932
|
-
metadata: parsed.metadata,
|
|
2101
|
+
metadata: withAgentCallStack(parsed.metadata, currentCallStack),
|
|
1933
2102
|
};
|
|
1934
|
-
if (target === input.callerAgentName && inboundEvent.instanceKey === input.callerInstanceKey) {
|
|
1935
|
-
throw new Error('agents__request는 동일 agent+instance를 대상으로 호출할 수 없습니다.');
|
|
1936
|
-
}
|
|
1937
2103
|
const timeoutMs = options?.timeoutMs;
|
|
1938
2104
|
const turnResult = await withOptionalTimeout(executeInboundTurn({
|
|
1939
2105
|
runtime: input.runtime,
|
|
@@ -1955,6 +2121,8 @@ function createAgentToolRuntime(input) {
|
|
|
1955
2121
|
if (!parsed) {
|
|
1956
2122
|
throw new Error('agents__send 입력 이벤트 형식이 올바르지 않습니다.');
|
|
1957
2123
|
}
|
|
2124
|
+
const callerNode = createAgentCallNode(input.callerAgentName, input.callerInstanceKey);
|
|
2125
|
+
const currentCallStack = appendAgentCallStack(readAgentCallStack(parsed.metadata), callerNode);
|
|
1958
2126
|
const inboundEvent = {
|
|
1959
2127
|
sourceKind: 'agent',
|
|
1960
2128
|
sourceName: parsed.sourceName,
|
|
@@ -1965,7 +2133,7 @@ function createAgentToolRuntime(input) {
|
|
|
1965
2133
|
from_agent: input.callerAgentName,
|
|
1966
2134
|
from_instance: input.callerInstanceKey,
|
|
1967
2135
|
},
|
|
1968
|
-
metadata: parsed.metadata,
|
|
2136
|
+
metadata: withAgentCallStack(parsed.metadata, currentCallStack),
|
|
1969
2137
|
};
|
|
1970
2138
|
void executeInboundTurn({
|
|
1971
2139
|
runtime: input.runtime,
|
|
@@ -2047,7 +2215,7 @@ async function getOrCreateAgentExtensionEnvironment(input) {
|
|
|
2047
2215
|
await extensionStateManager.loadAll();
|
|
2048
2216
|
const extensionToolRegistry = new ToolRegistryImpl();
|
|
2049
2217
|
const environment = {
|
|
2050
|
-
pipelineRegistry: new PipelineRegistryImpl(),
|
|
2218
|
+
pipelineRegistry: new PipelineRegistryImpl(input.runtime.runtimeEventBus),
|
|
2051
2219
|
extensionToolRegistry,
|
|
2052
2220
|
extensionToolExecutor: new ToolExecutor(extensionToolRegistry),
|
|
2053
2221
|
extensionStateManager,
|
|
@@ -2082,6 +2250,14 @@ async function runAgentTurn(input) {
|
|
|
2082
2250
|
callerInstanceKey: input.instanceKey,
|
|
2083
2251
|
logger: input.logger,
|
|
2084
2252
|
});
|
|
2253
|
+
const middlewareAgentsApi = createMiddlewareAgentsApi({
|
|
2254
|
+
runtime: agentRuntime,
|
|
2255
|
+
callerAgentName: input.plan.name,
|
|
2256
|
+
callerInstanceKey: input.instanceKey,
|
|
2257
|
+
callerTurnId: input.turnId,
|
|
2258
|
+
traceId: input.traceId,
|
|
2259
|
+
inboundMetadata: input.inputEvent.metadata,
|
|
2260
|
+
});
|
|
2085
2261
|
const extensionEnvironment = await getOrCreateAgentExtensionEnvironment({
|
|
2086
2262
|
runtime: input.runtime,
|
|
2087
2263
|
plan: input.plan,
|
|
@@ -2102,6 +2278,7 @@ async function runAgentTurn(input) {
|
|
|
2102
2278
|
traceId: input.traceId,
|
|
2103
2279
|
inputEvent: input.inputEvent,
|
|
2104
2280
|
conversationState,
|
|
2281
|
+
agents: middlewareAgentsApi,
|
|
2105
2282
|
emitMessageEvent(event) {
|
|
2106
2283
|
conversationState.emitMessageEvent(event);
|
|
2107
2284
|
},
|
|
@@ -2148,6 +2325,7 @@ async function runAgentTurn(input) {
|
|
|
2148
2325
|
turn: turnSnapshot,
|
|
2149
2326
|
stepIndex: step,
|
|
2150
2327
|
conversationState,
|
|
2328
|
+
agents: middlewareAgentsApi,
|
|
2151
2329
|
emitMessageEvent(event) {
|
|
2152
2330
|
conversationState.emitMessageEvent(event);
|
|
2153
2331
|
},
|
|
@@ -2319,6 +2497,19 @@ async function runAgentTurn(input) {
|
|
|
2319
2497
|
function logConnectorEvent(plan, event) {
|
|
2320
2498
|
console.info(`[goondan-runtime][${plan.connectionName}/${plan.connectorName}] emitted event name=${event.name} instanceKey=${event.instanceKey}`);
|
|
2321
2499
|
}
|
|
2500
|
+
function readRuntimeEventInstanceKey(event) {
|
|
2501
|
+
if (!('instanceKey' in event)) {
|
|
2502
|
+
return undefined;
|
|
2503
|
+
}
|
|
2504
|
+
if (typeof event.instanceKey !== 'string') {
|
|
2505
|
+
return undefined;
|
|
2506
|
+
}
|
|
2507
|
+
const trimmedInstanceKey = event.instanceKey.trim();
|
|
2508
|
+
if (trimmedInstanceKey.length === 0) {
|
|
2509
|
+
return undefined;
|
|
2510
|
+
}
|
|
2511
|
+
return trimmedInstanceKey;
|
|
2512
|
+
}
|
|
2322
2513
|
function buildRuntimeEngine(args, plan) {
|
|
2323
2514
|
const workspacePaths = new WorkspacePaths({
|
|
2324
2515
|
stateRoot: args.stateRoot,
|
|
@@ -2334,6 +2525,68 @@ function buildRuntimeEngine(args, plan) {
|
|
|
2334
2525
|
spawnedAgentsByOwner: new Map(),
|
|
2335
2526
|
instanceWorkdirs: new Map(),
|
|
2336
2527
|
extensionEnvironments: new Map(),
|
|
2528
|
+
runtimeEventBus: new RuntimeEventBusImpl(),
|
|
2529
|
+
runtimeEventTurnQueueKeys: new Map(),
|
|
2530
|
+
};
|
|
2531
|
+
}
|
|
2532
|
+
function resolveRuntimeEventQueueKey(runtime, event) {
|
|
2533
|
+
if (event.type === 'turn.started') {
|
|
2534
|
+
const explicitInstanceKey = readRuntimeEventInstanceKey(event);
|
|
2535
|
+
if (explicitInstanceKey !== undefined) {
|
|
2536
|
+
runtime.runtimeEventTurnQueueKeys.set(event.turnId, explicitInstanceKey);
|
|
2537
|
+
return explicitInstanceKey;
|
|
2538
|
+
}
|
|
2539
|
+
return runtime.runtimeEventTurnQueueKeys.get(event.turnId);
|
|
2540
|
+
}
|
|
2541
|
+
const trackedInstanceKey = runtime.runtimeEventTurnQueueKeys.get(event.turnId);
|
|
2542
|
+
if (trackedInstanceKey !== undefined) {
|
|
2543
|
+
return trackedInstanceKey;
|
|
2544
|
+
}
|
|
2545
|
+
const explicitInstanceKey = readRuntimeEventInstanceKey(event);
|
|
2546
|
+
if (explicitInstanceKey !== undefined) {
|
|
2547
|
+
return explicitInstanceKey;
|
|
2548
|
+
}
|
|
2549
|
+
if (event.type === 'turn.completed' || event.type === 'turn.failed') {
|
|
2550
|
+
return undefined;
|
|
2551
|
+
}
|
|
2552
|
+
return undefined;
|
|
2553
|
+
}
|
|
2554
|
+
function shouldReleaseRuntimeEventTurnKey(event) {
|
|
2555
|
+
return event.type === 'turn.completed' || event.type === 'turn.failed';
|
|
2556
|
+
}
|
|
2557
|
+
export function attachRuntimeEventPersistence(runtime) {
|
|
2558
|
+
const listener = async (event) => {
|
|
2559
|
+
const instanceKey = resolveRuntimeEventQueueKey(runtime, event);
|
|
2560
|
+
if (instanceKey === undefined) {
|
|
2561
|
+
console.warn(`[goondan-runtime] runtime event dropped type=${event.type} turnId=${event.turnId}: unresolved instance`);
|
|
2562
|
+
if (shouldReleaseRuntimeEventTurnKey(event)) {
|
|
2563
|
+
runtime.runtimeEventTurnQueueKeys.delete(event.turnId);
|
|
2564
|
+
}
|
|
2565
|
+
return;
|
|
2566
|
+
}
|
|
2567
|
+
try {
|
|
2568
|
+
await runtime.storage.appendRuntimeEvent(instanceKey, event);
|
|
2569
|
+
}
|
|
2570
|
+
catch (error) {
|
|
2571
|
+
console.warn(`[goondan-runtime] runtime event persistence failed type=${event.type} instanceKey=${instanceKey}: ${unknownToErrorMessage(error)}`);
|
|
2572
|
+
}
|
|
2573
|
+
finally {
|
|
2574
|
+
if (shouldReleaseRuntimeEventTurnKey(event)) {
|
|
2575
|
+
runtime.runtimeEventTurnQueueKeys.delete(event.turnId);
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
};
|
|
2579
|
+
const unsubscribers = [];
|
|
2580
|
+
for (const eventType of RUNTIME_EVENT_TYPES) {
|
|
2581
|
+
const unsubscribe = runtime.runtimeEventBus.on(eventType, listener);
|
|
2582
|
+
unsubscribers.push(unsubscribe);
|
|
2583
|
+
}
|
|
2584
|
+
return () => {
|
|
2585
|
+
for (const unsubscribe of unsubscribers) {
|
|
2586
|
+
unsubscribe();
|
|
2587
|
+
}
|
|
2588
|
+
runtime.runtimeEventBus.clear();
|
|
2589
|
+
runtime.runtimeEventTurnQueueKeys.clear();
|
|
2337
2590
|
};
|
|
2338
2591
|
}
|
|
2339
2592
|
async function requestRuntimeRestart(runtime, reason) {
|
|
@@ -2735,60 +2988,82 @@ async function main() {
|
|
|
2735
2988
|
const args = parseRunnerArguments(process.argv.slice(2));
|
|
2736
2989
|
const plan = await preflight(args);
|
|
2737
2990
|
const runtime = buildRuntimeEngine(args, plan);
|
|
2738
|
-
|
|
2739
|
-
const stopWatching = args.watch ? startWatchMode(runtime, plan) : () => {
|
|
2740
|
-
// no-op
|
|
2741
|
-
};
|
|
2742
|
-
const runningConnectors = await startConnectors(plan, runtime);
|
|
2743
|
-
console.info(`[goondan-runtime] started instanceKey=${args.instanceKey} pid=${process.pid} swarm=${plan.selectedSwarm.name} connectors=${runningConnectors.length}`);
|
|
2744
|
-
console.info(`[goondan-runtime] active connectors: ${summarizeConnectorPlans(plan.connectors)}`);
|
|
2745
|
-
console.info(`[goondan-runtime] active agents: ${summarizeAgentPlans(plan.agents)}`);
|
|
2746
|
-
const readyMessage = {
|
|
2747
|
-
type: 'ready',
|
|
2748
|
-
instanceKey: args.instanceKey,
|
|
2749
|
-
pid: process.pid,
|
|
2750
|
-
};
|
|
2751
|
-
sendMessage(readyMessage);
|
|
2991
|
+
const detachRuntimeEventPersistence = attachRuntimeEventPersistence(runtime);
|
|
2752
2992
|
try {
|
|
2753
|
-
await
|
|
2993
|
+
await preloadAgentExtensions(runtime, plan, args.instanceKey);
|
|
2994
|
+
const stopWatching = args.watch ? startWatchMode(runtime, plan) : () => {
|
|
2995
|
+
// no-op
|
|
2996
|
+
};
|
|
2997
|
+
let runningConnectors = [];
|
|
2998
|
+
try {
|
|
2999
|
+
runningConnectors = await startConnectors(plan, runtime);
|
|
3000
|
+
console.info(`[goondan-runtime] started instanceKey=${args.instanceKey} pid=${process.pid} swarm=${plan.selectedSwarm.name} connectors=${runningConnectors.length}`);
|
|
3001
|
+
console.info(`[goondan-runtime] active connectors: ${summarizeConnectorPlans(plan.connectors)}`);
|
|
3002
|
+
console.info(`[goondan-runtime] active agents: ${summarizeAgentPlans(plan.agents)}`);
|
|
3003
|
+
const readyMessage = {
|
|
3004
|
+
type: 'ready',
|
|
3005
|
+
instanceKey: args.instanceKey,
|
|
3006
|
+
pid: process.pid,
|
|
3007
|
+
};
|
|
3008
|
+
sendMessage(readyMessage);
|
|
3009
|
+
await runLifecycle(runningConnectors);
|
|
3010
|
+
}
|
|
3011
|
+
finally {
|
|
3012
|
+
stopWatching();
|
|
3013
|
+
await stopConnectors(runningConnectors);
|
|
3014
|
+
}
|
|
3015
|
+
if (runtime.restartRequestedReason !== undefined) {
|
|
3016
|
+
const runnerModulePath = process.argv[1];
|
|
3017
|
+
if (typeof runnerModulePath !== 'string' || runnerModulePath.trim().length === 0) {
|
|
3018
|
+
throw new Error('runtime-runner 모듈 경로를 확인할 수 없습니다.');
|
|
3019
|
+
}
|
|
3020
|
+
const reason = runtime.restartRequestedReason;
|
|
3021
|
+
const replacementPlan = await buildRunnerPlan(runtime.runnerArgs);
|
|
3022
|
+
const replacementInstanceKey = replacementPlan.selectedSwarm.instanceKey;
|
|
3023
|
+
const replacementSwarmName = replacementPlan.selectedSwarm.name;
|
|
3024
|
+
const replacementRunnerArgsWithInstanceKey = upsertRunnerOption(process.argv.slice(2), '--instance-key', replacementInstanceKey);
|
|
3025
|
+
const replacementRunnerArgs = upsertRunnerOption(replacementRunnerArgsWithInstanceKey, '--swarm', replacementSwarmName);
|
|
3026
|
+
const replacementPid = await spawnReplacementRunner({
|
|
3027
|
+
runnerModulePath,
|
|
3028
|
+
runnerArgs: replacementRunnerArgs,
|
|
3029
|
+
stateRoot: runtime.runnerArgs.stateRoot,
|
|
3030
|
+
instanceKey: replacementInstanceKey,
|
|
3031
|
+
bundlePath: runtime.runnerArgs.bundlePath,
|
|
3032
|
+
watch: runtime.runnerArgs.watch,
|
|
3033
|
+
swarmName: replacementSwarmName,
|
|
3034
|
+
env: process.env,
|
|
3035
|
+
});
|
|
3036
|
+
console.info(`[goondan-runtime] replacement orchestrator started pid=${replacementPid} reason=${reason}`);
|
|
3037
|
+
}
|
|
2754
3038
|
}
|
|
2755
3039
|
finally {
|
|
2756
|
-
|
|
2757
|
-
await stopConnectors(runningConnectors);
|
|
2758
|
-
}
|
|
2759
|
-
if (runtime.restartRequestedReason !== undefined) {
|
|
2760
|
-
const runnerModulePath = process.argv[1];
|
|
2761
|
-
if (typeof runnerModulePath !== 'string' || runnerModulePath.trim().length === 0) {
|
|
2762
|
-
throw new Error('runtime-runner 모듈 경로를 확인할 수 없습니다.');
|
|
2763
|
-
}
|
|
2764
|
-
const reason = runtime.restartRequestedReason;
|
|
2765
|
-
const replacementPlan = await buildRunnerPlan(runtime.runnerArgs);
|
|
2766
|
-
const replacementInstanceKey = replacementPlan.selectedSwarm.instanceKey;
|
|
2767
|
-
const replacementSwarmName = replacementPlan.selectedSwarm.name;
|
|
2768
|
-
const replacementRunnerArgsWithInstanceKey = upsertRunnerOption(process.argv.slice(2), '--instance-key', replacementInstanceKey);
|
|
2769
|
-
const replacementRunnerArgs = upsertRunnerOption(replacementRunnerArgsWithInstanceKey, '--swarm', replacementSwarmName);
|
|
2770
|
-
const replacementPid = await spawnReplacementRunner({
|
|
2771
|
-
runnerModulePath,
|
|
2772
|
-
runnerArgs: replacementRunnerArgs,
|
|
2773
|
-
stateRoot: runtime.runnerArgs.stateRoot,
|
|
2774
|
-
instanceKey: replacementInstanceKey,
|
|
2775
|
-
bundlePath: runtime.runnerArgs.bundlePath,
|
|
2776
|
-
watch: runtime.runnerArgs.watch,
|
|
2777
|
-
swarmName: replacementSwarmName,
|
|
2778
|
-
env: process.env,
|
|
2779
|
-
});
|
|
2780
|
-
console.info(`[goondan-runtime] replacement orchestrator started pid=${replacementPid} reason=${reason}`);
|
|
3040
|
+
detachRuntimeEventPersistence();
|
|
2781
3041
|
}
|
|
2782
3042
|
process.exit(0);
|
|
2783
3043
|
}
|
|
2784
|
-
|
|
2785
|
-
const
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
3044
|
+
function isRuntimeRunnerEntryPoint() {
|
|
3045
|
+
const entryArg = process.argv[1];
|
|
3046
|
+
if (typeof entryArg !== 'string' || entryArg.trim().length === 0) {
|
|
3047
|
+
return false;
|
|
3048
|
+
}
|
|
3049
|
+
try {
|
|
3050
|
+
const entryUrl = pathToFileURL(path.resolve(entryArg)).href;
|
|
3051
|
+
return entryUrl === import.meta.url;
|
|
3052
|
+
}
|
|
3053
|
+
catch {
|
|
3054
|
+
return false;
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
if (isRuntimeRunnerEntryPoint()) {
|
|
3058
|
+
void main().catch((error) => {
|
|
3059
|
+
const message = unknownToErrorMessage(error);
|
|
3060
|
+
const startErrorMessage = {
|
|
3061
|
+
type: 'start_error',
|
|
3062
|
+
message,
|
|
3063
|
+
};
|
|
3064
|
+
sendMessage(startErrorMessage);
|
|
3065
|
+
console.error(`[goondan-runtime] startup failure: ${message}`);
|
|
3066
|
+
process.exit(1);
|
|
3067
|
+
});
|
|
3068
|
+
}
|
|
2794
3069
|
//# sourceMappingURL=runtime-runner.js.map
|