blun-king-cli 9.1.601 → 9.1.603
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/CHANGELOG.md +105 -94
- package/LIESMICH.txt +57 -57
- package/README.md +90 -90
- package/bin/agentspine-king-goal-inbox.mjs +127 -127
- package/bin/agentspine-king-goal-intake.mjs +106 -106
- package/bin/agentspine-king-host-runner.mjs +109 -109
- package/bin/agentspine-king-snapshot-policy.cjs +80 -80
- package/bin/agentspine-king-status-policy.mjs +226 -226
- package/bin/agentspine-king-worker-host.mjs +160 -160
- package/bin/core-bootstrap.js +77 -77
- package/bin/launcher-mode.js +93 -93
- package/bin/launcher-restart-policy.cjs +131 -131
- package/bin/launcher-runtime.js +491 -491
- package/bin/managed-node.js +186 -186
- package/bin/managed-plugin-selection.cjs +115 -115
- package/bin/native-module-repair.js +201 -201
- package/bin/node-runtime.js +34 -34
- package/bin/node-version.js +49 -49
- package/bin/plugin-bootstrap.js +162 -162
- package/bin/private-paths.js +1606 -1606
- package/bin/runtime-exit-ledger.cjs +144 -144
- package/bin/runtime-exit-ledger.d.cts +23 -23
- package/bin/standard-tools-bootstrap.js +272 -272
- package/bin/turn-thinking-policy.cjs +82 -82
- package/bin/update-copy.js +200 -200
- package/bin/update-lease.js +597 -597
- package/bin/update-notice.js +1568 -1568
- package/bin/verify-agent-behavior.cjs +122 -122
- package/bin/verify-agent-components.cjs +104 -104
- package/bin/verify-bundled-agent-sources.cjs +83 -83
- package/bin/windows-node-crash-dump.cjs +289 -289
- package/blun.mjs +1709 -1601
- package/codebase-index/codebase_index.py +470 -470
- package/dist-web/assets/{CodeBlockNode-CXnTLMNr.js → CodeBlockNode-TKKkJX8L.js} +1 -1
- package/dist-web/assets/{CodeBlockShell.vue_vue_type_style_index_0_lang-CCF8Ntnq.js → CodeBlockShell.vue_vue_type_style_index_0_lang-CUj2Ds5x.js} +1 -1
- package/dist-web/assets/DesignSystemView-DwK1aQMo.js +12 -0
- package/dist-web/assets/DesignSystemView-szjTj7ns.css +1 -0
- package/dist-web/assets/{Tooltip-CFQEzqC-.js → Tooltip-CTWv7WCU.js} +1 -1
- package/dist-web/assets/{abnfDiagram-N423BO3Z-Z1APZG5m.js → abnfDiagram-N423BO3Z-DA8V8Zjh.js} +1 -1
- package/dist-web/assets/{arc-C4VyWloT.js → arc-YtddKbdY.js} +1 -1
- package/dist-web/assets/{architectureDiagram-T3A2C74G-DpddbUcM.js → architectureDiagram-T3A2C74G-CGEiObmo.js} +1 -1
- package/dist-web/assets/{blockDiagram-VBNYF7ZC-BqccOSMr.js → blockDiagram-VBNYF7ZC-Bd5Vt50e.js} +1 -1
- package/dist-web/assets/{c4Diagram-5PPSVZJV-OHAcJrTy.js → c4Diagram-5PPSVZJV-D2ApPM54.js} +1 -1
- package/dist-web/assets/channel-BnluexuN.js +1 -0
- package/dist-web/assets/{chunk-2GRJ4B5K-DqJHs8Fw.js → chunk-2GRJ4B5K-BDcIEZSl.js} +1 -1
- package/dist-web/assets/{chunk-2Q5K7J3B-B1nCd91o.js → chunk-2Q5K7J3B-6aSabCX7.js} +1 -1
- package/dist-web/assets/{chunk-5RXB4S5H-neG70kZx.js → chunk-5RXB4S5H-BFRQvIJS.js} +1 -1
- package/dist-web/assets/{chunk-5VM5RSS4-l7biGqeH.js → chunk-5VM5RSS4-ChAa-DNY.js} +1 -1
- package/dist-web/assets/{chunk-6Q2QTUOP-BO-F11Gs.js → chunk-6Q2QTUOP-BIfrb2Jc.js} +1 -1
- package/dist-web/assets/{chunk-GF5L2VYU-BtC69fw0.js → chunk-GF5L2VYU-BR0gvtWI.js} +1 -1
- package/dist-web/assets/{chunk-JWPE2WC7-DIOubEqr.js → chunk-JWPE2WC7-BgXKsx5E.js} +1 -1
- package/dist-web/assets/{chunk-KBJHAD2P-DDUeH_Ba.js → chunk-KBJHAD2P-I8mrZhpz.js} +1 -1
- package/dist-web/assets/{chunk-RYQCIY6F-B9gFMVbS.js → chunk-RYQCIY6F-BMPaem92.js} +1 -1
- package/dist-web/assets/{chunk-XXDRQBXY-Bn1Xz6TQ.js → chunk-XXDRQBXY-COy0J-0j.js} +1 -1
- package/dist-web/assets/classDiagram-JCYQIIEL-BliFdSD9.js +1 -0
- package/dist-web/assets/classDiagram-v2-OCEON4UE-BliFdSD9.js +1 -0
- package/dist-web/assets/{cose-bilkent-JH36ORCC-DqigO3T4.js → cose-bilkent-JH36ORCC-MosTTRdo.js} +1 -1
- package/dist-web/assets/{cynefin-VYW2F7L2-rpD93tQ-.js → cynefin-VYW2F7L2-5tjPgrkP.js} +1 -1
- package/dist-web/assets/{cynefinDiagram-MW4NZA55-DbTqnkVJ.js → cynefinDiagram-MW4NZA55-CbDcdInR.js} +1 -1
- package/dist-web/assets/{dagre-VZM6K2ZE-DcM8aEVY.js → dagre-VZM6K2ZE-YaBom1ZH.js} +1 -1
- package/dist-web/assets/{diagram-7IWD3JNH-UymgsBNa.js → diagram-7IWD3JNH-Da4m-Hgz.js} +1 -1
- package/dist-web/assets/{diagram-B4RE2ZJO-BiYu5WPF.js → diagram-B4RE2ZJO-CAUUegxg.js} +1 -1
- package/dist-web/assets/{diagram-LBJQPF4R-BD3kkgOO.js → diagram-LBJQPF4R-o21mWKG4.js} +1 -1
- package/dist-web/assets/{diagram-Q27KOJAE-D1mYQ_cI.js → diagram-Q27KOJAE-BA3z3sXf.js} +1 -1
- package/dist-web/assets/{diagram-UB23O5K3-BtX8u6HG.js → diagram-UB23O5K3-CGRdSSDK.js} +1 -1
- package/dist-web/assets/{ebnfDiagram-BXEA7PRR-CBAnFkRF.js → ebnfDiagram-BXEA7PRR-Bw-iU9FP.js} +1 -1
- package/dist-web/assets/{erDiagram-JOGREHBK-3vKcWsxm.js → erDiagram-JOGREHBK-BwM1yiR0.js} +1 -1
- package/dist-web/assets/{flowDiagram-UKHOOZJN-D9wBbHm2.js → flowDiagram-UKHOOZJN-z05eOR1Q.js} +1 -1
- package/dist-web/assets/{ganttDiagram-PKOTCBZU-Cd_dViF-.js → ganttDiagram-PKOTCBZU-BMUubNTl.js} +1 -1
- package/dist-web/assets/{gitGraphDiagram-DS77QQ5N-BiEEtTo7.js → gitGraphDiagram-DS77QQ5N-Dccbi1wU.js} +1 -1
- package/dist-web/assets/{index-DdEakFJM.js → index-BBbC5LRF.js} +1 -1
- package/dist-web/assets/{index-BmKj7CB1.css → index-C9eDH3u-.css} +1 -1
- package/dist-web/assets/{index-Ba1OvLjf.js → index-D48p0M2S.js} +2 -2
- package/dist-web/assets/{index-CiPA8Kex.js → index-h0KEOmkU.js} +14 -14
- package/dist-web/assets/{index10-CNr4U-Nw.js → index10-Qbuw1N6u.js} +1 -1
- package/dist-web/assets/{index11-Dto_yZNz.js → index11-g8v025wN.js} +1 -1
- package/dist-web/assets/{index5-B2PldaO2.js → index5-BYNcV8BY.js} +1 -1
- package/dist-web/assets/{index6-CBdZmmyx.js → index6-BetANtnV.js} +1 -1
- package/dist-web/assets/{index7-Dz9oCsUF.js → index7-BcPbgCKN.js} +1 -1
- package/dist-web/assets/{index8-B6k25jtU.js → index8-B1lp-RvF.js} +2 -2
- package/dist-web/assets/{infoDiagram-6WML65LV-D4ph2sIH.js → infoDiagram-6WML65LV-BF_pbUnN.js} +1 -1
- package/dist-web/assets/{ishikawaDiagram-WSZJBQD7-DjKjbMm9.js → ishikawaDiagram-WSZJBQD7-Dedv4urS.js} +1 -1
- package/dist-web/assets/{journeyDiagram-NVQOT4AX-DttHDfPQ.js → journeyDiagram-NVQOT4AX-B1Ex3b6o.js} +1 -1
- package/dist-web/assets/{kanban-definition-27J2QSJJ-C5gB-W0d.js → kanban-definition-27J2QSJJ-BtCGliBH.js} +1 -1
- package/dist-web/assets/{linear-BRGe4-d6.js → linear-ByItc8Qr.js} +1 -1
- package/dist-web/assets/{mermaid.core-D-9Sx1No.js → mermaid.core-B1M2O7nN.js} +4 -4
- package/dist-web/assets/{mindmap-definition-FAOFIHXS-Cg_hoVIq.js → mindmap-definition-FAOFIHXS-D0UHKUyj.js} +1 -1
- package/dist-web/assets/{pegDiagram-VL7TDLO6-CSX9hitD.js → pegDiagram-VL7TDLO6-D7zYCVmG.js} +1 -1
- package/dist-web/assets/{pieDiagram-7S7Q4E2Y-0L0mxahZ.js → pieDiagram-7S7Q4E2Y-Bd0i9CHa.js} +1 -1
- package/dist-web/assets/{quadrantDiagram-CIZ2JOQS-U483z0er.js → quadrantDiagram-CIZ2JOQS-MG-Ug47d.js} +1 -1
- package/dist-web/assets/{railroadDiagram-AXF67PYL-D80a2_DJ.js → railroadDiagram-AXF67PYL-AZdl90Gj.js} +1 -1
- package/dist-web/assets/{requirementDiagram-LRYGKXZP-CeyHfq8t.js → requirementDiagram-LRYGKXZP-DjplF9kt.js} +1 -1
- package/dist-web/assets/{sankeyDiagram-W5VNT64P-CCISkkrR.js → sankeyDiagram-W5VNT64P-Bi9Zgfjs.js} +1 -1
- package/dist-web/assets/{sequenceDiagram-SI44F4Z6-jQfm2XS7.js → sequenceDiagram-SI44F4Z6-ChEpdCvb.js} +1 -1
- package/dist-web/assets/{sizeCapture-X5ZJPWSS-lRZsmCoS.js → sizeCapture-X5ZJPWSS-B5RFUdaa.js} +1 -1
- package/dist-web/assets/{stateDiagram-OKZ733FA-ClCgTdUm.js → stateDiagram-OKZ733FA-BkRblSKp.js} +1 -1
- package/dist-web/assets/stateDiagram-v2-UEYNNEHI-fVkQcACW.js +1 -0
- package/dist-web/assets/{swimlanes-SLNWSIFB-BCdOUN05.js → swimlanes-SLNWSIFB-DLXH6Zhc.js} +2 -2
- package/dist-web/assets/swimlanesDiagram-ULZ7WXOC-Bg-BiZJQ.js +8 -0
- package/dist-web/assets/{timeline-definition-Z64GVDOM-DpWutSKa.js → timeline-definition-Z64GVDOM-C_N88siO.js} +1 -1
- package/dist-web/assets/{vennDiagram-T6HMQDX7-DVC5JVsc.js → vennDiagram-T6HMQDX7-DMsnvDt0.js} +1 -1
- package/dist-web/assets/{vue.runtime.esm-bundler-BwwRtQwQ.js → vue.runtime.esm-bundler-B-3uIy85.js} +1 -1
- package/dist-web/assets/{wardleyDiagram-T6FBY63Y-BK2mrq7L.js → wardleyDiagram-T6FBY63Y-C9SJIPzq.js} +1 -1
- package/dist-web/assets/{xychartDiagram-ELKLHX3M-DUJu9F7-.js → xychartDiagram-ELKLHX3M-DZLWA6Go.js} +1 -1
- package/dist-web/index.html +32 -32
- package/dist-web/vis/index.html.gz +0 -0
- package/package.json +1 -1
- package/scripts/fix-node-pty-perms.js +53 -53
- package/standard-skills/blun-app-design-system/SKILL.md +30 -30
- package/standard-skills/blun-app-design-system/provenance.json +17 -17
- package/standard-skills/blun-app-design-system/references/tokens.md +48 -48
- package/standard-skills/blun-app-design-system/scripts/check-blun-design.mjs +49 -49
- package/telegram-plugin/blun.plugin.json +20 -20
- package/telegram-plugin/commands/access.md +37 -37
- package/telegram-plugin/dist/bridge.mjs +81 -81
- package/telegram-plugin/dist/mcp-server.mjs +158 -158
- package/worker-host.mjs +932 -932
- package/dist-web/assets/DesignSystemView-6HgAUEmC.css +0 -1
- package/dist-web/assets/DesignSystemView-BbMOu-XO.js +0 -12
- package/dist-web/assets/channel-B2VOQOI-.js +0 -1
- package/dist-web/assets/classDiagram-JCYQIIEL-BA1TjAxj.js +0 -1
- package/dist-web/assets/classDiagram-v2-OCEON4UE-BA1TjAxj.js +0 -1
- package/dist-web/assets/stateDiagram-v2-UEYNNEHI-fi_lrTAx.js +0 -1
- package/dist-web/assets/swimlanesDiagram-ULZ7WXOC-BUd_uYK3.js +0 -8
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { appendFile, mkdir, readFile, realpath } from 'node:fs/promises';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
5
|
-
import { setTimeout as delay } from 'node:timers/promises';
|
|
6
|
-
import { createGoalHostFactory } from './agentspine-king-host-runner.mjs';
|
|
7
|
-
import { ingestGoalInbox } from './agentspine-king-goal-inbox.mjs';
|
|
8
|
-
import { createGoalStatusReporter, goalResultRejectionCode } from './agentspine-king-status-policy.mjs';
|
|
9
|
-
import snapshotPolicy from './agentspine-king-snapshot-policy.cjs';
|
|
10
|
-
|
|
11
|
-
const packageRoot = path.resolve(import.meta.dirname, '..');
|
|
12
|
-
const required = ['blunHome', 'profile', 'projectRoot', 'projectId', 'standFile', 'expectedStandSha256',
|
|
13
|
-
'expectedSnapshotSha256', 'exchangeDirectory', 'telegramQueueFile', 'instructionSenderId', 'instructionChatId',
|
|
14
|
-
'logicalPersonaId', 'runtimePersonaId', 'groupId', 'ownerSubjectId', 'permission', 'gatewayStateDirectory'];
|
|
15
|
-
|
|
16
|
-
export async function loadWorkerConfig(file) {
|
|
17
|
-
const config = JSON.parse(await readFile(path.resolve(file), 'utf8'));
|
|
18
|
-
if (config?.schema !== 'blun.king-goal-worker-config/v1'
|
|
19
|
-
|| required.some(key => typeof config[key] !== 'string' || !config[key])
|
|
20
|
-
|| (config.instructionThreadId !== null && config.instructionThreadId !== undefined && (typeof config.instructionThreadId !== 'string'
|
|
21
|
-
|| !/^[1-9][0-9]*$/.test(config.instructionThreadId) || !Number.isSafeInteger(Number(config.instructionThreadId))))
|
|
22
|
-
|| !['manual', 'auto', 'yolo'].includes(config.permission)) throw new Error('KING_WORKER_CONFIG_INVALID');
|
|
23
|
-
for (const key of ['blunHome', 'projectRoot', 'exchangeDirectory', 'telegramQueueFile', 'gatewayStateDirectory']) {
|
|
24
|
-
if (!path.isAbsolute(config[key])) throw new Error('KING_WORKER_ABSOLUTE_PATH_REQUIRED');
|
|
25
|
-
}
|
|
26
|
-
const blunHome = await realpath(config.blunHome);
|
|
27
|
-
const relative = path.relative(blunHome, path.resolve(config.gatewayStateDirectory));
|
|
28
|
-
if (path.isAbsolute(relative) || relative === '..' || relative.startsWith('..' + path.sep)) throw new Error('KING_WORKER_STATE_OUTSIDE_APP_HOME');
|
|
29
|
-
const state = await realpath(config.gatewayStateDirectory);
|
|
30
|
-
const canonicalRelative = path.relative(blunHome, state);
|
|
31
|
-
if (path.isAbsolute(canonicalRelative) || canonicalRelative === '..' || canonicalRelative.startsWith('..' + path.sep)) {
|
|
32
|
-
throw new Error('KING_WORKER_STATE_OUTSIDE_APP_HOME');
|
|
33
|
-
}
|
|
34
|
-
return Object.freeze({ ...config, blunHome, gatewayStateDirectory: state, projectRoot: await realpath(config.projectRoot) });
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export async function runGuardedWorkerTick(context) {
|
|
38
|
-
const { config, gateway, hostFactory, env, adapter } = context;
|
|
39
|
-
const snapshot = snapshotPolicy.verifyWorkspaceSnapshot({ root: config.projectRoot, projectId: config.projectId,
|
|
40
|
-
standFile: config.standFile, expectedStandSha256: config.expectedStandSha256,
|
|
41
|
-
expectedSnapshotSha256: config.expectedSnapshotSha256 });
|
|
42
|
-
const personas = await gateway.loadPersonaRuntime(snapshot.root);
|
|
43
|
-
const persona = personas.runtime.personas.find(item => item.personaId === config.runtimePersonaId && item.status === 'active');
|
|
44
|
-
const binding = personas.policy.bindings.find(item => item.id === persona?.bindingId && item.active);
|
|
45
|
-
if (!binding || binding.profileId !== config.profile || binding.groupId !== config.groupId) {
|
|
46
|
-
throw new Error('KING_WORKER_IDENTITY_MISMATCH');
|
|
47
|
-
}
|
|
48
|
-
const { withOwnedFileLock } = await import(pathToFileURL(path.join(packageRoot,
|
|
49
|
-
'agent-spine-plugin/src/lib/owned-file-lock.js')).href);
|
|
50
|
-
const statusReporter = createGoalStatusReporter({
|
|
51
|
-
stateFile: path.join(config.blunHome, 'worker', 'goal-status-v2.json'),
|
|
52
|
-
scope: { logicalPersonaId: config.logicalPersonaId, runtimePersonaId: config.runtimePersonaId,
|
|
53
|
-
projectId: config.projectId, groupId: config.groupId, ownerSubjectId: config.ownerSubjectId,
|
|
54
|
-
chatId: config.instructionChatId, senderId: config.instructionSenderId,
|
|
55
|
-
threadId: config.instructionThreadId ?? null },
|
|
56
|
-
withOwnedFileLock, loadPolicy: () => gateway.loadChannelPolicy(snapshot.root), adapter,
|
|
57
|
-
});
|
|
58
|
-
const statusReports = [];
|
|
59
|
-
const reportCommittedStatus = async () => {
|
|
60
|
-
const context = await gateway.gatewayContext({ root: snapshot.root, agentId: config.runtimePersonaId });
|
|
61
|
-
if (!context.enabled || context.killSwitch) return;
|
|
62
|
-
await statusReporter.reconcile(context);
|
|
63
|
-
statusReports.push(...await statusReporter.flush());
|
|
64
|
-
};
|
|
65
|
-
// Reconcile the saved goal state first: a prior process may have stopped after committing its tick.
|
|
66
|
-
await reportCommittedStatus();
|
|
67
|
-
const intake = await ingestGoalInbox({ exchangeDirectory: config.exchangeDirectory,
|
|
68
|
-
queueFile: config.telegramQueueFile, checkpointFile: path.join(config.blunHome, 'worker', 'goal-queue-checkpoint.json'),
|
|
69
|
-
instructionSenderId: config.instructionSenderId, instructionChatId: config.instructionChatId,
|
|
70
|
-
instructionThreadId: config.instructionThreadId,
|
|
71
|
-
logicalPersonaId: config.logicalPersonaId, runtimePersonaId: config.runtimePersonaId,
|
|
72
|
-
projectId: config.projectId, groupId: config.groupId, ownerSubjectId: config.ownerSubjectId,
|
|
73
|
-
snapshot, assignGoal: gateway.assignGoal,
|
|
74
|
-
recordResult: result => result.status === 'rejected'
|
|
75
|
-
? statusReporter.record({ kind: 'intake-rejected', eventId: result.eventId,
|
|
76
|
-
messageId: result.messageId, error: result.error }) : undefined });
|
|
77
|
-
const result = await gateway.runWorkerTick({ root: snapshot.root, workerId: 'gateway-worker:blun:' + process.pid,
|
|
78
|
-
agentId: config.runtimePersonaId, projectId: config.projectId, groupId: config.groupId,
|
|
79
|
-
goalOnly: true, env,
|
|
80
|
-
hostFactory: async item => {
|
|
81
|
-
const host = await hostFactory(item);
|
|
82
|
-
return { ...host, async run() {
|
|
83
|
-
try { return await host.run(); }
|
|
84
|
-
catch (error) {
|
|
85
|
-
const rejection = goalResultRejectionCode(error);
|
|
86
|
-
if (rejection) {
|
|
87
|
-
// Record the concrete parser failure before the gateway replaces it with an execution hold.
|
|
88
|
-
await statusReporter.record({ kind: 'result-rejected', eventId: `${item.queueId}:${item.attempts}`,
|
|
89
|
-
goalId: item.goal.goalId, goalStepId: item.goalStep?.stepId ?? null,
|
|
90
|
-
attempt: item.attempts, error: rejection });
|
|
91
|
-
}
|
|
92
|
-
throw error;
|
|
93
|
-
}
|
|
94
|
-
} };
|
|
95
|
-
},
|
|
96
|
-
adapter: { send: item => adapter.send(item) } });
|
|
97
|
-
await reportCommittedStatus();
|
|
98
|
-
return { ...result, intake, statusReports };
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export async function runWorkerHost(config, { once = false, signal, onResult = () => {} } = {}) {
|
|
102
|
-
const gateway = await import(pathToFileURL(path.join(packageRoot, 'agent-spine-plugin/src/index.js')).href);
|
|
103
|
-
const { createKingWorkerHarness, LocalKaos } = await import(pathToFileURL(path.join(packageRoot, 'worker-host.mjs')).href);
|
|
104
|
-
const env = { ...process.env, BLUN_HOME: config.blunHome, BLUN_PROFILE: config.profile };
|
|
105
|
-
const harness = createKingWorkerHarness({ homeDir: config.blunHome, configPath: config.settingsPath });
|
|
106
|
-
const hostFactory = createGoalHostFactory({ harness, workDir: config.projectRoot, model: config.model,
|
|
107
|
-
permission: config.permission, tickTimeoutMs: config.tickTimeoutMs, cleanupTimeoutMs: config.cleanupTimeoutMs,
|
|
108
|
-
sessionOptions: { kaos: (await LocalKaos.create()).withCwd(config.projectRoot).withEnv({
|
|
109
|
-
BLUN_HOME: config.blunHome, BLUN_PROFILE: config.profile, AGENTSPINE_STATE_DIR: config.gatewayStateDirectory,
|
|
110
|
-
}) },
|
|
111
|
-
signal });
|
|
112
|
-
const adapter = gateway.createTelegramAdapter({ root: config.projectRoot, env });
|
|
113
|
-
try {
|
|
114
|
-
do {
|
|
115
|
-
if (signal?.aborted) return { status: 'stopped', processed: false };
|
|
116
|
-
const result = await runGuardedWorkerTick({ config, gateway, hostFactory, env, adapter });
|
|
117
|
-
await mkdir(path.join(config.blunHome, 'worker'), { recursive: true });
|
|
118
|
-
await appendFile(path.join(config.blunHome, 'worker', 'worker.log'), JSON.stringify({
|
|
119
|
-
schema: 'blun.king-goal-worker-log/v1', at: new Date().toISOString(), status: result.status,
|
|
120
|
-
queueId: result.queueId ?? null, hostSettlement: result.hostSettlement ?? null,
|
|
121
|
-
statusReports: result.statusReports,
|
|
122
|
-
intake: result.intake.map(item => ({ status: item.status, messageId: item.messageId, error: item.error }))
|
|
123
|
-
}) + '\n', { mode: 0o600 });
|
|
124
|
-
await onResult(result);
|
|
125
|
-
if (once || result.status === 'stopped' || result.status === 'blocked') return result;
|
|
126
|
-
await delay(result.processed ? 1000 : 15000, undefined, { signal }).catch(error => {
|
|
127
|
-
if (error.name !== 'AbortError') throw error;
|
|
128
|
-
});
|
|
129
|
-
} while (!signal?.aborted);
|
|
130
|
-
return { status: 'stopped', processed: false };
|
|
131
|
-
} finally {
|
|
132
|
-
let quiet = true;
|
|
133
|
-
for (const session of harness.sessions.values()) {
|
|
134
|
-
const proof = await session.quiesce({ deadlineAt: Date.now() + (config.cleanupTimeoutMs ?? 10000) }).catch(() => null);
|
|
135
|
-
if (!proof || proof.status !== 'quiescent' || proof.remaining.length) quiet = false;
|
|
136
|
-
}
|
|
137
|
-
// Never turn a cleanup deadline into a successful host termination acknowledgement.
|
|
138
|
-
if (quiet) await harness.close();
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async function main() {
|
|
143
|
-
const args = process.argv.slice(2);
|
|
144
|
-
const index = args.indexOf('--config');
|
|
145
|
-
if (index < 0 || !args[index + 1] || args[index + 1].startsWith('--')) throw new Error('--config requires a path');
|
|
146
|
-
const config = await loadWorkerConfig(args[index + 1]);
|
|
147
|
-
process.env.BLUN_HOME = config.blunHome;
|
|
148
|
-
process.env.BLUN_PROFILE = config.profile;
|
|
149
|
-
process.env.AGENTSPINE_STATE_DIR = config.gatewayStateDirectory;
|
|
150
|
-
const controller = new AbortController();
|
|
151
|
-
const stop = () => controller.abort();
|
|
152
|
-
process.once('SIGINT', stop); process.once('SIGTERM', stop);
|
|
153
|
-
try { await runWorkerHost(config, { once: args.includes('--once'), signal: controller.signal,
|
|
154
|
-
onResult: result => process.stdout.write(JSON.stringify(result) + '\n') }); }
|
|
155
|
-
finally { process.removeListener('SIGINT', stop); process.removeListener('SIGTERM', stop); }
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
159
|
-
main().catch(error => { process.stderr.write(String(error.message).slice(0, 500) + '\n'); process.exitCode = 1; });
|
|
160
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { appendFile, mkdir, readFile, realpath } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
5
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
6
|
+
import { createGoalHostFactory } from './agentspine-king-host-runner.mjs';
|
|
7
|
+
import { ingestGoalInbox } from './agentspine-king-goal-inbox.mjs';
|
|
8
|
+
import { createGoalStatusReporter, goalResultRejectionCode } from './agentspine-king-status-policy.mjs';
|
|
9
|
+
import snapshotPolicy from './agentspine-king-snapshot-policy.cjs';
|
|
10
|
+
|
|
11
|
+
const packageRoot = path.resolve(import.meta.dirname, '..');
|
|
12
|
+
const required = ['blunHome', 'profile', 'projectRoot', 'projectId', 'standFile', 'expectedStandSha256',
|
|
13
|
+
'expectedSnapshotSha256', 'exchangeDirectory', 'telegramQueueFile', 'instructionSenderId', 'instructionChatId',
|
|
14
|
+
'logicalPersonaId', 'runtimePersonaId', 'groupId', 'ownerSubjectId', 'permission', 'gatewayStateDirectory'];
|
|
15
|
+
|
|
16
|
+
export async function loadWorkerConfig(file) {
|
|
17
|
+
const config = JSON.parse(await readFile(path.resolve(file), 'utf8'));
|
|
18
|
+
if (config?.schema !== 'blun.king-goal-worker-config/v1'
|
|
19
|
+
|| required.some(key => typeof config[key] !== 'string' || !config[key])
|
|
20
|
+
|| (config.instructionThreadId !== null && config.instructionThreadId !== undefined && (typeof config.instructionThreadId !== 'string'
|
|
21
|
+
|| !/^[1-9][0-9]*$/.test(config.instructionThreadId) || !Number.isSafeInteger(Number(config.instructionThreadId))))
|
|
22
|
+
|| !['manual', 'auto', 'yolo'].includes(config.permission)) throw new Error('KING_WORKER_CONFIG_INVALID');
|
|
23
|
+
for (const key of ['blunHome', 'projectRoot', 'exchangeDirectory', 'telegramQueueFile', 'gatewayStateDirectory']) {
|
|
24
|
+
if (!path.isAbsolute(config[key])) throw new Error('KING_WORKER_ABSOLUTE_PATH_REQUIRED');
|
|
25
|
+
}
|
|
26
|
+
const blunHome = await realpath(config.blunHome);
|
|
27
|
+
const relative = path.relative(blunHome, path.resolve(config.gatewayStateDirectory));
|
|
28
|
+
if (path.isAbsolute(relative) || relative === '..' || relative.startsWith('..' + path.sep)) throw new Error('KING_WORKER_STATE_OUTSIDE_APP_HOME');
|
|
29
|
+
const state = await realpath(config.gatewayStateDirectory);
|
|
30
|
+
const canonicalRelative = path.relative(blunHome, state);
|
|
31
|
+
if (path.isAbsolute(canonicalRelative) || canonicalRelative === '..' || canonicalRelative.startsWith('..' + path.sep)) {
|
|
32
|
+
throw new Error('KING_WORKER_STATE_OUTSIDE_APP_HOME');
|
|
33
|
+
}
|
|
34
|
+
return Object.freeze({ ...config, blunHome, gatewayStateDirectory: state, projectRoot: await realpath(config.projectRoot) });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function runGuardedWorkerTick(context) {
|
|
38
|
+
const { config, gateway, hostFactory, env, adapter } = context;
|
|
39
|
+
const snapshot = snapshotPolicy.verifyWorkspaceSnapshot({ root: config.projectRoot, projectId: config.projectId,
|
|
40
|
+
standFile: config.standFile, expectedStandSha256: config.expectedStandSha256,
|
|
41
|
+
expectedSnapshotSha256: config.expectedSnapshotSha256 });
|
|
42
|
+
const personas = await gateway.loadPersonaRuntime(snapshot.root);
|
|
43
|
+
const persona = personas.runtime.personas.find(item => item.personaId === config.runtimePersonaId && item.status === 'active');
|
|
44
|
+
const binding = personas.policy.bindings.find(item => item.id === persona?.bindingId && item.active);
|
|
45
|
+
if (!binding || binding.profileId !== config.profile || binding.groupId !== config.groupId) {
|
|
46
|
+
throw new Error('KING_WORKER_IDENTITY_MISMATCH');
|
|
47
|
+
}
|
|
48
|
+
const { withOwnedFileLock } = await import(pathToFileURL(path.join(packageRoot,
|
|
49
|
+
'agent-spine-plugin/src/lib/owned-file-lock.js')).href);
|
|
50
|
+
const statusReporter = createGoalStatusReporter({
|
|
51
|
+
stateFile: path.join(config.blunHome, 'worker', 'goal-status-v2.json'),
|
|
52
|
+
scope: { logicalPersonaId: config.logicalPersonaId, runtimePersonaId: config.runtimePersonaId,
|
|
53
|
+
projectId: config.projectId, groupId: config.groupId, ownerSubjectId: config.ownerSubjectId,
|
|
54
|
+
chatId: config.instructionChatId, senderId: config.instructionSenderId,
|
|
55
|
+
threadId: config.instructionThreadId ?? null },
|
|
56
|
+
withOwnedFileLock, loadPolicy: () => gateway.loadChannelPolicy(snapshot.root), adapter,
|
|
57
|
+
});
|
|
58
|
+
const statusReports = [];
|
|
59
|
+
const reportCommittedStatus = async () => {
|
|
60
|
+
const context = await gateway.gatewayContext({ root: snapshot.root, agentId: config.runtimePersonaId });
|
|
61
|
+
if (!context.enabled || context.killSwitch) return;
|
|
62
|
+
await statusReporter.reconcile(context);
|
|
63
|
+
statusReports.push(...await statusReporter.flush());
|
|
64
|
+
};
|
|
65
|
+
// Reconcile the saved goal state first: a prior process may have stopped after committing its tick.
|
|
66
|
+
await reportCommittedStatus();
|
|
67
|
+
const intake = await ingestGoalInbox({ exchangeDirectory: config.exchangeDirectory,
|
|
68
|
+
queueFile: config.telegramQueueFile, checkpointFile: path.join(config.blunHome, 'worker', 'goal-queue-checkpoint.json'),
|
|
69
|
+
instructionSenderId: config.instructionSenderId, instructionChatId: config.instructionChatId,
|
|
70
|
+
instructionThreadId: config.instructionThreadId,
|
|
71
|
+
logicalPersonaId: config.logicalPersonaId, runtimePersonaId: config.runtimePersonaId,
|
|
72
|
+
projectId: config.projectId, groupId: config.groupId, ownerSubjectId: config.ownerSubjectId,
|
|
73
|
+
snapshot, assignGoal: gateway.assignGoal,
|
|
74
|
+
recordResult: result => result.status === 'rejected'
|
|
75
|
+
? statusReporter.record({ kind: 'intake-rejected', eventId: result.eventId,
|
|
76
|
+
messageId: result.messageId, error: result.error }) : undefined });
|
|
77
|
+
const result = await gateway.runWorkerTick({ root: snapshot.root, workerId: 'gateway-worker:blun:' + process.pid,
|
|
78
|
+
agentId: config.runtimePersonaId, projectId: config.projectId, groupId: config.groupId,
|
|
79
|
+
goalOnly: true, env,
|
|
80
|
+
hostFactory: async item => {
|
|
81
|
+
const host = await hostFactory(item);
|
|
82
|
+
return { ...host, async run() {
|
|
83
|
+
try { return await host.run(); }
|
|
84
|
+
catch (error) {
|
|
85
|
+
const rejection = goalResultRejectionCode(error);
|
|
86
|
+
if (rejection) {
|
|
87
|
+
// Record the concrete parser failure before the gateway replaces it with an execution hold.
|
|
88
|
+
await statusReporter.record({ kind: 'result-rejected', eventId: `${item.queueId}:${item.attempts}`,
|
|
89
|
+
goalId: item.goal.goalId, goalStepId: item.goalStep?.stepId ?? null,
|
|
90
|
+
attempt: item.attempts, error: rejection });
|
|
91
|
+
}
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
} };
|
|
95
|
+
},
|
|
96
|
+
adapter: { send: item => adapter.send(item) } });
|
|
97
|
+
await reportCommittedStatus();
|
|
98
|
+
return { ...result, intake, statusReports };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export async function runWorkerHost(config, { once = false, signal, onResult = () => {} } = {}) {
|
|
102
|
+
const gateway = await import(pathToFileURL(path.join(packageRoot, 'agent-spine-plugin/src/index.js')).href);
|
|
103
|
+
const { createKingWorkerHarness, LocalKaos } = await import(pathToFileURL(path.join(packageRoot, 'worker-host.mjs')).href);
|
|
104
|
+
const env = { ...process.env, BLUN_HOME: config.blunHome, BLUN_PROFILE: config.profile };
|
|
105
|
+
const harness = createKingWorkerHarness({ homeDir: config.blunHome, configPath: config.settingsPath });
|
|
106
|
+
const hostFactory = createGoalHostFactory({ harness, workDir: config.projectRoot, model: config.model,
|
|
107
|
+
permission: config.permission, tickTimeoutMs: config.tickTimeoutMs, cleanupTimeoutMs: config.cleanupTimeoutMs,
|
|
108
|
+
sessionOptions: { kaos: (await LocalKaos.create()).withCwd(config.projectRoot).withEnv({
|
|
109
|
+
BLUN_HOME: config.blunHome, BLUN_PROFILE: config.profile, AGENTSPINE_STATE_DIR: config.gatewayStateDirectory,
|
|
110
|
+
}) },
|
|
111
|
+
signal });
|
|
112
|
+
const adapter = gateway.createTelegramAdapter({ root: config.projectRoot, env });
|
|
113
|
+
try {
|
|
114
|
+
do {
|
|
115
|
+
if (signal?.aborted) return { status: 'stopped', processed: false };
|
|
116
|
+
const result = await runGuardedWorkerTick({ config, gateway, hostFactory, env, adapter });
|
|
117
|
+
await mkdir(path.join(config.blunHome, 'worker'), { recursive: true });
|
|
118
|
+
await appendFile(path.join(config.blunHome, 'worker', 'worker.log'), JSON.stringify({
|
|
119
|
+
schema: 'blun.king-goal-worker-log/v1', at: new Date().toISOString(), status: result.status,
|
|
120
|
+
queueId: result.queueId ?? null, hostSettlement: result.hostSettlement ?? null,
|
|
121
|
+
statusReports: result.statusReports,
|
|
122
|
+
intake: result.intake.map(item => ({ status: item.status, messageId: item.messageId, error: item.error }))
|
|
123
|
+
}) + '\n', { mode: 0o600 });
|
|
124
|
+
await onResult(result);
|
|
125
|
+
if (once || result.status === 'stopped' || result.status === 'blocked') return result;
|
|
126
|
+
await delay(result.processed ? 1000 : 15000, undefined, { signal }).catch(error => {
|
|
127
|
+
if (error.name !== 'AbortError') throw error;
|
|
128
|
+
});
|
|
129
|
+
} while (!signal?.aborted);
|
|
130
|
+
return { status: 'stopped', processed: false };
|
|
131
|
+
} finally {
|
|
132
|
+
let quiet = true;
|
|
133
|
+
for (const session of harness.sessions.values()) {
|
|
134
|
+
const proof = await session.quiesce({ deadlineAt: Date.now() + (config.cleanupTimeoutMs ?? 10000) }).catch(() => null);
|
|
135
|
+
if (!proof || proof.status !== 'quiescent' || proof.remaining.length) quiet = false;
|
|
136
|
+
}
|
|
137
|
+
// Never turn a cleanup deadline into a successful host termination acknowledgement.
|
|
138
|
+
if (quiet) await harness.close();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function main() {
|
|
143
|
+
const args = process.argv.slice(2);
|
|
144
|
+
const index = args.indexOf('--config');
|
|
145
|
+
if (index < 0 || !args[index + 1] || args[index + 1].startsWith('--')) throw new Error('--config requires a path');
|
|
146
|
+
const config = await loadWorkerConfig(args[index + 1]);
|
|
147
|
+
process.env.BLUN_HOME = config.blunHome;
|
|
148
|
+
process.env.BLUN_PROFILE = config.profile;
|
|
149
|
+
process.env.AGENTSPINE_STATE_DIR = config.gatewayStateDirectory;
|
|
150
|
+
const controller = new AbortController();
|
|
151
|
+
const stop = () => controller.abort();
|
|
152
|
+
process.once('SIGINT', stop); process.once('SIGTERM', stop);
|
|
153
|
+
try { await runWorkerHost(config, { once: args.includes('--once'), signal: controller.signal,
|
|
154
|
+
onResult: result => process.stdout.write(JSON.stringify(result) + '\n') }); }
|
|
155
|
+
finally { process.removeListener('SIGINT', stop); process.removeListener('SIGTERM', stop); }
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
159
|
+
main().catch(error => { process.stderr.write(String(error.message).slice(0, 500) + '\n'); process.exitCode = 1; });
|
|
160
|
+
}
|
package/bin/core-bootstrap.js
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('node:fs');
|
|
4
|
-
const path = require('node:path');
|
|
5
|
-
const { pathToFileURL } = require('node:url');
|
|
6
|
-
|
|
7
|
-
const { acquireSharedRuntimeLease } = require('./update-lease');
|
|
8
|
-
const { installWindowsNodeCrashDump } = require('./windows-node-crash-dump.cjs');
|
|
9
|
-
const { recordRuntimeExit } = require('./runtime-exit-ledger.cjs');
|
|
10
|
-
const { isStandaloneHelpRequest } = require('./launcher-mode');
|
|
11
|
-
|
|
12
|
-
const CORE_LOADED_MESSAGE = 'blun-core-bootstrap-loaded';
|
|
13
|
-
|
|
14
|
-
async function runCoreBootstrap() {
|
|
15
|
-
const informational = isStandaloneHelpRequest(process.argv.slice(2));
|
|
16
|
-
let diagnostics;
|
|
17
|
-
if (!informational) {
|
|
18
|
-
try { diagnostics = installWindowsNodeCrashDump({ homeDir: process.env.BLUN_HOME }); } catch {}
|
|
19
|
-
}
|
|
20
|
-
const packageRoot = path.resolve(__dirname, '..');
|
|
21
|
-
const mainPath = path.join(packageRoot, 'blun.mjs');
|
|
22
|
-
let leaseResult;
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
leaseResult = await acquireSharedRuntimeLease({ packageRoot });
|
|
26
|
-
if (!leaseResult.acquired) throw new Error('RUNTIME_PROTECTION_UNAVAILABLE');
|
|
27
|
-
leaseResult.lease.assertOwned();
|
|
28
|
-
process.argv = [process.execPath, mainPath, ...process.argv.slice(2)];
|
|
29
|
-
await import(pathToFileURL(mainPath).href);
|
|
30
|
-
leaseResult.lease.assertOwned();
|
|
31
|
-
} catch (error) {
|
|
32
|
-
if (!informational) {
|
|
33
|
-
try {
|
|
34
|
-
if (diagnostics?.enabled) diagnostics.write(error, 'bootstrap-failure');
|
|
35
|
-
else recordRuntimeExit({ homeDir: process.env.BLUN_HOME, source: 'bootstrap',
|
|
36
|
-
kind: 'bootstrap-failure', phase: 'startup', error });
|
|
37
|
-
} catch {}
|
|
38
|
-
}
|
|
39
|
-
try { diagnostics?.dispose(); } catch {}
|
|
40
|
-
try { await leaseResult?.lease?.release(); }
|
|
41
|
-
catch (leaseError) {
|
|
42
|
-
if (!informational) {
|
|
43
|
-
try {
|
|
44
|
-
recordRuntimeExit({ homeDir: process.env.BLUN_HOME, source: 'bootstrap',
|
|
45
|
-
kind: 'lease-release-failure', phase: 'cleanup', error: leaseError });
|
|
46
|
-
} catch {}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
throw error;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// The bundled CLI loads package assets lazily after module evaluation. Keep
|
|
53
|
-
// the install lease for this process's lifetime, without keeping print/help
|
|
54
|
-
// commands alive solely because of the owner server.
|
|
55
|
-
leaseResult.lease.unref();
|
|
56
|
-
|
|
57
|
-
if (process.connected) {
|
|
58
|
-
try {
|
|
59
|
-
process.send({ type: CORE_LOADED_MESSAGE }, () => {
|
|
60
|
-
try {
|
|
61
|
-
process.disconnect();
|
|
62
|
-
} catch {}
|
|
63
|
-
});
|
|
64
|
-
} catch {}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (require.main === module) {
|
|
69
|
-
// oxlint-disable-next-line unicorn/prefer-top-level-await -- Worker entry is CommonJS.
|
|
70
|
-
void runCoreBootstrap().catch((error) => {
|
|
71
|
-
const message = error && error.message ? error.message : String(error);
|
|
72
|
-
fs.writeSync(process.stderr.fd, `BLUN Start fehlgeschlagen: ${message}\n`);
|
|
73
|
-
process.exit(1);
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
module.exports = { CORE_LOADED_MESSAGE, runCoreBootstrap };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const { pathToFileURL } = require('node:url');
|
|
6
|
+
|
|
7
|
+
const { acquireSharedRuntimeLease } = require('./update-lease');
|
|
8
|
+
const { installWindowsNodeCrashDump } = require('./windows-node-crash-dump.cjs');
|
|
9
|
+
const { recordRuntimeExit } = require('./runtime-exit-ledger.cjs');
|
|
10
|
+
const { isStandaloneHelpRequest } = require('./launcher-mode');
|
|
11
|
+
|
|
12
|
+
const CORE_LOADED_MESSAGE = 'blun-core-bootstrap-loaded';
|
|
13
|
+
|
|
14
|
+
async function runCoreBootstrap() {
|
|
15
|
+
const informational = isStandaloneHelpRequest(process.argv.slice(2));
|
|
16
|
+
let diagnostics;
|
|
17
|
+
if (!informational) {
|
|
18
|
+
try { diagnostics = installWindowsNodeCrashDump({ homeDir: process.env.BLUN_HOME }); } catch {}
|
|
19
|
+
}
|
|
20
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
21
|
+
const mainPath = path.join(packageRoot, 'blun.mjs');
|
|
22
|
+
let leaseResult;
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
leaseResult = await acquireSharedRuntimeLease({ packageRoot });
|
|
26
|
+
if (!leaseResult.acquired) throw new Error('RUNTIME_PROTECTION_UNAVAILABLE');
|
|
27
|
+
leaseResult.lease.assertOwned();
|
|
28
|
+
process.argv = [process.execPath, mainPath, ...process.argv.slice(2)];
|
|
29
|
+
await import(pathToFileURL(mainPath).href);
|
|
30
|
+
leaseResult.lease.assertOwned();
|
|
31
|
+
} catch (error) {
|
|
32
|
+
if (!informational) {
|
|
33
|
+
try {
|
|
34
|
+
if (diagnostics?.enabled) diagnostics.write(error, 'bootstrap-failure');
|
|
35
|
+
else recordRuntimeExit({ homeDir: process.env.BLUN_HOME, source: 'bootstrap',
|
|
36
|
+
kind: 'bootstrap-failure', phase: 'startup', error });
|
|
37
|
+
} catch {}
|
|
38
|
+
}
|
|
39
|
+
try { diagnostics?.dispose(); } catch {}
|
|
40
|
+
try { await leaseResult?.lease?.release(); }
|
|
41
|
+
catch (leaseError) {
|
|
42
|
+
if (!informational) {
|
|
43
|
+
try {
|
|
44
|
+
recordRuntimeExit({ homeDir: process.env.BLUN_HOME, source: 'bootstrap',
|
|
45
|
+
kind: 'lease-release-failure', phase: 'cleanup', error: leaseError });
|
|
46
|
+
} catch {}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// The bundled CLI loads package assets lazily after module evaluation. Keep
|
|
53
|
+
// the install lease for this process's lifetime, without keeping print/help
|
|
54
|
+
// commands alive solely because of the owner server.
|
|
55
|
+
leaseResult.lease.unref();
|
|
56
|
+
|
|
57
|
+
if (process.connected) {
|
|
58
|
+
try {
|
|
59
|
+
process.send({ type: CORE_LOADED_MESSAGE }, () => {
|
|
60
|
+
try {
|
|
61
|
+
process.disconnect();
|
|
62
|
+
} catch {}
|
|
63
|
+
});
|
|
64
|
+
} catch {}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (require.main === module) {
|
|
69
|
+
// oxlint-disable-next-line unicorn/prefer-top-level-await -- Worker entry is CommonJS.
|
|
70
|
+
void runCoreBootstrap().catch((error) => {
|
|
71
|
+
const message = error && error.message ? error.message : String(error);
|
|
72
|
+
fs.writeSync(process.stderr.fd, `BLUN Start fehlgeschlagen: ${message}\n`);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = { CORE_LOADED_MESSAGE, runCoreBootstrap };
|