@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.
@@ -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
- await preloadAgentExtensions(runtime, plan, args.instanceKey);
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 runLifecycle(runningConnectors);
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
- stopWatching();
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
- void main().catch((error) => {
2785
- const message = unknownToErrorMessage(error);
2786
- const startErrorMessage = {
2787
- type: 'start_error',
2788
- message,
2789
- };
2790
- sendMessage(startErrorMessage);
2791
- console.error(`[goondan-runtime] startup failure: ${message}`);
2792
- process.exit(1);
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