blun-king-cli 9.1.624 → 9.1.626
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 +62 -213
- package/LIESMICH.txt +57 -74
- package/README.md +76 -119
- package/agent-spine-plugin/scripts/check-install.js +4 -4
- package/agent-spine-plugin/src/hook.js +0 -4
- package/agent-spine-plugin/src/lib/documents.js +1 -1
- package/agent-spine-plugin/src/lib/hook-context.js +0 -1
- package/agent-spine-plugin/src/lib/host-instruction-budget.js +2 -1
- package/agent-spine-plugin/src/lib/preflight.js +9 -38
- package/agent-spine-plugin/src/lib/source-roots.js +1 -1
- 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 +83 -97
- package/bin/launcher-mode.js +93 -93
- package/bin/launcher-restart-policy.cjs +131 -131
- package/bin/launcher-runtime.js +91 -254
- package/bin/managed-node.js +186 -186
- package/bin/managed-plugin-selection.cjs +109 -116
- 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 +149 -172
- package/bin/private-paths.js +1578 -1624
- package/bin/runtime-exit-ledger.cjs +144 -144
- package/bin/runtime-exit-ledger.d.cts +23 -23
- package/bin/standard-tools-bootstrap.js +277 -272
- package/bin/turn-thinking-policy.cjs +82 -82
- package/bin/update-copy.js +200 -200
- package/bin/update-lease.js +597 -599
- 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 +91 -96
- package/bin/windows-node-crash-dump.cjs +289 -289
- package/blun.mjs +187640 -180475
- package/bundled-agent-sources.json +26 -30
- package/codebase-index/codebase_index.py +462 -470
- package/dist-web/assets/{CodeBlockNode-TKKkJX8L.js → CodeBlockNode-BMbuG85x.js} +1 -1
- package/dist-web/assets/{CodeBlockShell.vue_vue_type_style_index_0_lang-CUj2Ds5x.js → CodeBlockShell.vue_vue_type_style_index_0_lang-C1fv7l_Z.js} +1 -1
- package/dist-web/assets/DesignSystemView-6HgAUEmC.css +1 -0
- package/dist-web/assets/DesignSystemView-CEEBqXSX.js +12 -0
- package/dist-web/assets/{Tooltip-CTWv7WCU.js → Tooltip--YoauJ24.js} +1 -1
- package/dist-web/assets/{abnfDiagram-N423BO3Z-DA8V8Zjh.js → abnfDiagram-N423BO3Z-DZvBWkRg.js} +1 -1
- package/dist-web/assets/{arc-YtddKbdY.js → arc-B04JATeX.js} +1 -1
- package/dist-web/assets/{architectureDiagram-T3A2C74G-CGEiObmo.js → architectureDiagram-T3A2C74G-DmYnMep2.js} +1 -1
- package/dist-web/assets/{blockDiagram-VBNYF7ZC-Bd5Vt50e.js → blockDiagram-VBNYF7ZC-DJ1gPS1C.js} +1 -1
- package/dist-web/assets/{c4Diagram-5PPSVZJV-D2ApPM54.js → c4Diagram-5PPSVZJV-DmjxvUbd.js} +1 -1
- package/dist-web/assets/channel-472fcEvw.js +1 -0
- package/dist-web/assets/{chunk-2GRJ4B5K-BDcIEZSl.js → chunk-2GRJ4B5K-AB0raj3I.js} +1 -1
- package/dist-web/assets/{chunk-2Q5K7J3B-6aSabCX7.js → chunk-2Q5K7J3B-Drf039vM.js} +1 -1
- package/dist-web/assets/{chunk-5RXB4S5H-BFRQvIJS.js → chunk-5RXB4S5H-D5ILttmz.js} +1 -1
- package/dist-web/assets/{chunk-5VM5RSS4-ChAa-DNY.js → chunk-5VM5RSS4-DrLSdi8y.js} +1 -1
- package/dist-web/assets/{chunk-6Q2QTUOP-BIfrb2Jc.js → chunk-6Q2QTUOP-LiaqdEOQ.js} +1 -1
- package/dist-web/assets/{chunk-GF5L2VYU-BR0gvtWI.js → chunk-GF5L2VYU-AIYkb--o.js} +1 -1
- package/dist-web/assets/{chunk-JWPE2WC7-BgXKsx5E.js → chunk-JWPE2WC7-CogdNl0i.js} +1 -1
- package/dist-web/assets/{chunk-KBJHAD2P-I8mrZhpz.js → chunk-KBJHAD2P-DHjpNtZv.js} +1 -1
- package/dist-web/assets/{chunk-RYQCIY6F-BMPaem92.js → chunk-RYQCIY6F-BUSOqH2X.js} +1 -1
- package/dist-web/assets/{chunk-XXDRQBXY-COy0J-0j.js → chunk-XXDRQBXY-BpoMV0bh.js} +1 -1
- package/dist-web/assets/classDiagram-JCYQIIEL-BTZeLngj.js +1 -0
- package/dist-web/assets/classDiagram-v2-OCEON4UE-BTZeLngj.js +1 -0
- package/dist-web/assets/{cose-bilkent-JH36ORCC-MosTTRdo.js → cose-bilkent-JH36ORCC-BJr2I61o.js} +1 -1
- package/dist-web/assets/{cynefin-VYW2F7L2-5tjPgrkP.js → cynefin-VYW2F7L2-HtysQZ4A.js} +1 -1
- package/dist-web/assets/{cynefinDiagram-MW4NZA55-CbDcdInR.js → cynefinDiagram-MW4NZA55-CcpC_2uv.js} +1 -1
- package/dist-web/assets/{dagre-VZM6K2ZE-YaBom1ZH.js → dagre-VZM6K2ZE-D8Ao0LUg.js} +1 -1
- package/dist-web/assets/{diagram-7IWD3JNH-Da4m-Hgz.js → diagram-7IWD3JNH-BITiLhjX.js} +1 -1
- package/dist-web/assets/{diagram-B4RE2ZJO-CAUUegxg.js → diagram-B4RE2ZJO-CJtwfy9f.js} +1 -1
- package/dist-web/assets/{diagram-LBJQPF4R-o21mWKG4.js → diagram-LBJQPF4R-BsVTh6w8.js} +1 -1
- package/dist-web/assets/{diagram-Q27KOJAE-BA3z3sXf.js → diagram-Q27KOJAE-pA_MUCUf.js} +1 -1
- package/dist-web/assets/{diagram-UB23O5K3-CGRdSSDK.js → diagram-UB23O5K3-CIY8z7vu.js} +1 -1
- package/dist-web/assets/{ebnfDiagram-BXEA7PRR-Bw-iU9FP.js → ebnfDiagram-BXEA7PRR-C3FMioqp.js} +1 -1
- package/dist-web/assets/{erDiagram-JOGREHBK-BwM1yiR0.js → erDiagram-JOGREHBK-CzoyKmKc.js} +1 -1
- package/dist-web/assets/{flowDiagram-UKHOOZJN-z05eOR1Q.js → flowDiagram-UKHOOZJN-DOqfushy.js} +1 -1
- package/dist-web/assets/{ganttDiagram-PKOTCBZU-BMUubNTl.js → ganttDiagram-PKOTCBZU-Cf9XQSWl.js} +1 -1
- package/dist-web/assets/{gitGraphDiagram-DS77QQ5N-Dccbi1wU.js → gitGraphDiagram-DS77QQ5N-DHUDofE5.js} +1 -1
- package/dist-web/assets/{index-h0KEOmkU.js → index-B6qEMQMx.js} +14 -14
- package/dist-web/assets/{index-C9eDH3u-.css → index-BmKj7CB1.css} +1 -1
- package/dist-web/assets/{index-BBbC5LRF.js → index-DokxDX1w.js} +1 -1
- package/dist-web/assets/{index-D48p0M2S.js → index-auojtiAA.js} +2 -2
- package/dist-web/assets/{index10-Qbuw1N6u.js → index10-Drb2n5e5.js} +1 -1
- package/dist-web/assets/{index11-g8v025wN.js → index11-Cx-aV4G2.js} +1 -1
- package/dist-web/assets/{index5-BYNcV8BY.js → index5-Dg3qGTyH.js} +1 -1
- package/dist-web/assets/{index6-BetANtnV.js → index6-BgvtIICP.js} +1 -1
- package/dist-web/assets/{index7-BcPbgCKN.js → index7-uEnniPQG.js} +1 -1
- package/dist-web/assets/{index8-B1lp-RvF.js → index8-h4IKc0ek.js} +2 -2
- package/dist-web/assets/{infoDiagram-6WML65LV-BF_pbUnN.js → infoDiagram-6WML65LV-D-3tvEiJ.js} +1 -1
- package/dist-web/assets/{ishikawaDiagram-WSZJBQD7-Dedv4urS.js → ishikawaDiagram-WSZJBQD7-DIIBNv7a.js} +1 -1
- package/dist-web/assets/{journeyDiagram-NVQOT4AX-B1Ex3b6o.js → journeyDiagram-NVQOT4AX-DP4r1Vlx.js} +1 -1
- package/dist-web/assets/{kanban-definition-27J2QSJJ-BtCGliBH.js → kanban-definition-27J2QSJJ-C3_Ztgxv.js} +1 -1
- package/dist-web/assets/{linear-ByItc8Qr.js → linear-DnqhIw-y.js} +1 -1
- package/dist-web/assets/{mermaid.core-B1M2O7nN.js → mermaid.core-xYUgBa3T.js} +4 -4
- package/dist-web/assets/{mindmap-definition-FAOFIHXS-D0UHKUyj.js → mindmap-definition-FAOFIHXS-l-dq-zfr.js} +1 -1
- package/dist-web/assets/{pegDiagram-VL7TDLO6-D7zYCVmG.js → pegDiagram-VL7TDLO6-C8vXQiaJ.js} +1 -1
- package/dist-web/assets/{pieDiagram-7S7Q4E2Y-Bd0i9CHa.js → pieDiagram-7S7Q4E2Y-CyNRSsI6.js} +1 -1
- package/dist-web/assets/{quadrantDiagram-CIZ2JOQS-MG-Ug47d.js → quadrantDiagram-CIZ2JOQS-D-w8AD_g.js} +1 -1
- package/dist-web/assets/{railroadDiagram-AXF67PYL-AZdl90Gj.js → railroadDiagram-AXF67PYL-BLkyQCWy.js} +1 -1
- package/dist-web/assets/{requirementDiagram-LRYGKXZP-DjplF9kt.js → requirementDiagram-LRYGKXZP-CEWO7XfT.js} +1 -1
- package/dist-web/assets/{sankeyDiagram-W5VNT64P-Bi9Zgfjs.js → sankeyDiagram-W5VNT64P-ByGoAaGj.js} +1 -1
- package/dist-web/assets/{sequenceDiagram-SI44F4Z6-ChEpdCvb.js → sequenceDiagram-SI44F4Z6-Bhn9GQtd.js} +1 -1
- package/dist-web/assets/{sizeCapture-X5ZJPWSS-B5RFUdaa.js → sizeCapture-X5ZJPWSS-jVKR9CTu.js} +1 -1
- package/dist-web/assets/{stateDiagram-OKZ733FA-BkRblSKp.js → stateDiagram-OKZ733FA-wW3XbegA.js} +1 -1
- package/dist-web/assets/stateDiagram-v2-UEYNNEHI-B8aids-Z.js +1 -0
- package/dist-web/assets/{swimlanes-SLNWSIFB-DLXH6Zhc.js → swimlanes-SLNWSIFB-B8QyFS7G.js} +2 -2
- package/dist-web/assets/swimlanesDiagram-ULZ7WXOC-B8XAkdSm.js +8 -0
- package/dist-web/assets/{timeline-definition-Z64GVDOM-C_N88siO.js → timeline-definition-Z64GVDOM-DpvxS-1A.js} +1 -1
- package/dist-web/assets/{vennDiagram-T6HMQDX7-DMsnvDt0.js → vennDiagram-T6HMQDX7-BzGM0ihY.js} +1 -1
- package/dist-web/assets/{vue.runtime.esm-bundler-B-3uIy85.js → vue.runtime.esm-bundler-BOcpwIX1.js} +1 -1
- package/dist-web/assets/{wardleyDiagram-T6FBY63Y-C9SJIPzq.js → wardleyDiagram-T6FBY63Y-2DKAOs5e.js} +1 -1
- package/dist-web/assets/{xychartDiagram-ELKLHX3M-DZLWA6Go.js → xychartDiagram-ELKLHX3M-B0SP0TXd.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/standard-skills/translate-native/README.md +1 -1
- package/standard-skills/translate-native/scripts/blun_language_guard.py +2 -0
- package/standard-skills/translate-native/scripts/language_gateway.py +2 -0
- package/standard-skills/translate-native/scripts/pre_output_guard.py +2 -0
- package/standard-tools/language-guard/blun_language_guard.py +2 -0
- package/standard-tools/language-guard/language_gateway.py +2 -0
- package/standard-tools/language-guard/pre_output_guard.py +2 -0
- package/telegram-plugin/blun.plugin.json +20 -20
- package/telegram-plugin/commands/access.md +37 -37
- package/telegram-plugin/dist/bridge.mjs +310 -187
- package/telegram-plugin/dist/mcp-server.mjs +174 -261
- package/telegram-plugin/dist/noise.mjs +1 -19
- package/worker-host.mjs +13747 -16824
- package/bin/profile-handoff.cjs +0 -152
- package/bin/profile-launch.cjs +0 -120
- package/dist-web/assets/DesignSystemView-DwK1aQMo.js +0 -12
- package/dist-web/assets/DesignSystemView-szjTj7ns.css +0 -1
- package/dist-web/assets/channel-BnluexuN.js +0 -1
- package/dist-web/assets/classDiagram-JCYQIIEL-BliFdSD9.js +0 -1
- package/dist-web/assets/classDiagram-v2-OCEON4UE-BliFdSD9.js +0 -1
- package/dist-web/assets/stateDiagram-v2-UEYNNEHI-fVkQcACW.js +0 -1
- package/dist-web/assets/swimlanesDiagram-ULZ7WXOC-Bg-BiZJQ.js +0 -8
package/bin/profile-handoff.cjs
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('node:fs');
|
|
4
|
-
const path = require('node:path');
|
|
5
|
-
const { randomUUID } = require('node:crypto');
|
|
6
|
-
const { listExistingProfiles, resolveSelectedProfile } = require('./profile-launch.cjs');
|
|
7
|
-
|
|
8
|
-
const PROFILE_HANDOFF_REQUEST = 'blun-profile-handoff-request';
|
|
9
|
-
const PROFILE_HANDOFF_REPLY = 'blun-profile-handoff-reply';
|
|
10
|
-
const PROFILE_HANDOFF_CANCEL = 'blun-profile-handoff-cancel';
|
|
11
|
-
const PROFILE_HANDOFF_READY = 'blun-profile-handoff-ready';
|
|
12
|
-
const PROFILE_HANDOFF_EXIT = 76;
|
|
13
|
-
const REQUEST_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
|
|
14
|
-
const SESSION_ID = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/u;
|
|
15
|
-
const samePath = (a, b) => process.platform === 'win32' ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
16
|
-
const unavailable = () => Object.assign(new Error('PROFILE_HANDOFF_UNAVAILABLE'), { code: 'PROFILE_HANDOFF_UNAVAILABLE' });
|
|
17
|
-
|
|
18
|
-
function createProfileHandoff(env, isBusy = () => false) {
|
|
19
|
-
let pending;
|
|
20
|
-
const validate = (name) => {
|
|
21
|
-
if (typeof env.BLUN_HOME !== 'string' || !path.isAbsolute(env.BLUN_HOME)
|
|
22
|
-
|| (env.BLUN_SHARED_HOME !== undefined && !path.isAbsolute(env.BLUN_SHARED_HOME))) throw unavailable();
|
|
23
|
-
const sharedHome = path.resolve(env.BLUN_SHARED_HOME || env.BLUN_HOME);
|
|
24
|
-
const homeDir = path.resolve(env.BLUN_HOME);
|
|
25
|
-
const current = env.BLUN_PROFILE;
|
|
26
|
-
if (current !== undefined) {
|
|
27
|
-
if (!env.BLUN_SHARED_HOME || path.basename(resolveSelectedProfile(sharedHome, current)) !== current
|
|
28
|
-
|| !samePath(homeDir, resolveSelectedProfile(sharedHome, current))) throw unavailable();
|
|
29
|
-
} else if (!samePath(homeDir, sharedHome)) throw unavailable();
|
|
30
|
-
const names = listExistingProfiles(sharedHome);
|
|
31
|
-
if (typeof name !== 'string' || !names.includes(name) || name === current
|
|
32
|
-
|| (current !== undefined && !names.includes(current))) throw unavailable();
|
|
33
|
-
const target = resolveSelectedProfile(sharedHome, name);
|
|
34
|
-
if (isBusy(target)) throw unavailable();
|
|
35
|
-
const identities = [sharedHome, path.join(sharedHome, 'profile'), homeDir, target]
|
|
36
|
-
.map(file => ({ file, stat: fs.lstatSync(file, { bigint: true }) }));
|
|
37
|
-
if (identities.some(({ stat }) => !stat.isDirectory() || stat.isSymbolicLink())) throw unavailable();
|
|
38
|
-
return { name, sharedHome, homeDir: target, identities };
|
|
39
|
-
};
|
|
40
|
-
return {
|
|
41
|
-
hasPending: () => pending !== undefined,
|
|
42
|
-
getSourceSessionId: () => pending?.sourceSessionId,
|
|
43
|
-
prepare(message) {
|
|
44
|
-
if (message?.type === PROFILE_HANDOFF_CANCEL && typeof message.requestId === 'string'
|
|
45
|
-
&& REQUEST_ID.test(message.requestId) && Object.keys(message).sort().join(',') === 'requestId,type') {
|
|
46
|
-
if (pending?.requestId === message.requestId) pending = undefined;
|
|
47
|
-
return { type: PROFILE_HANDOFF_REPLY, requestId: message.requestId, status: 'cancelled' };
|
|
48
|
-
}
|
|
49
|
-
if (!message || message.type !== PROFILE_HANDOFF_REQUEST || typeof message.requestId !== 'string' || !REQUEST_ID.test(message.requestId)) return undefined;
|
|
50
|
-
const shape = Object.keys(message).sort().join(',');
|
|
51
|
-
if (shape !== 'name,requestId,type' && shape !== 'name,requestId,sourceSessionId,type') return undefined;
|
|
52
|
-
if (shape === 'name,requestId,sourceSessionId,type'
|
|
53
|
-
&& (typeof message.sourceSessionId !== 'string' || !SESSION_ID.test(message.sourceSessionId))) return undefined;
|
|
54
|
-
let status = 'rejected';
|
|
55
|
-
try {
|
|
56
|
-
if (pending) {
|
|
57
|
-
if (pending.requestId === message.requestId && pending.name === message.name
|
|
58
|
-
&& pending.sourceSessionId === message.sourceSessionId) status = 'prepared';
|
|
59
|
-
} else {
|
|
60
|
-
pending = { ...validate(message.name), requestId: message.requestId, sourceSessionId: message.sourceSessionId };
|
|
61
|
-
status = 'prepared';
|
|
62
|
-
}
|
|
63
|
-
} catch {}
|
|
64
|
-
return { type: PROFILE_HANDOFF_REPLY, requestId: message.requestId, status };
|
|
65
|
-
},
|
|
66
|
-
commit() {
|
|
67
|
-
try {
|
|
68
|
-
if (!pending) throw unavailable();
|
|
69
|
-
const fresh = validate(pending.name);
|
|
70
|
-
for (let index = 0; index < pending.identities.length; index++) {
|
|
71
|
-
const before = pending.identities[index];
|
|
72
|
-
const after = fresh.identities[index];
|
|
73
|
-
if (before.file !== after.file || before.stat.dev !== after.stat.dev || before.stat.ino !== after.stat.ino) throw unavailable();
|
|
74
|
-
}
|
|
75
|
-
return Object.freeze({ name: fresh.name, sharedHome: fresh.sharedHome, homeDir: fresh.homeDir,
|
|
76
|
-
...(pending.sourceSessionId === undefined ? {} : { sourceSessionId: pending.sourceSessionId }) });
|
|
77
|
-
} catch {
|
|
78
|
-
throw unavailable();
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function createProfileHandoffClient(channel = process) {
|
|
85
|
-
const enabled = channel.env?.BLUN_PROFILE_HANDOFF === '1';
|
|
86
|
-
let pending;
|
|
87
|
-
let disposed = false;
|
|
88
|
-
const available = () => !disposed && enabled && channel.connected === true
|
|
89
|
-
&& typeof channel.send === 'function';
|
|
90
|
-
const cancel = () => {
|
|
91
|
-
const request = pending;
|
|
92
|
-
if (!request) return;
|
|
93
|
-
pending = undefined;
|
|
94
|
-
request.finish(false);
|
|
95
|
-
if (channel.connected === true) {
|
|
96
|
-
try { channel.send({ type: PROFILE_HANDOFF_CANCEL, requestId: request.id }, () => {}); } catch {}
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
return Object.freeze({
|
|
100
|
-
isPrepared: () => available() && pending?.prepared === true,
|
|
101
|
-
cancel,
|
|
102
|
-
dispose() { cancel(); disposed = true; },
|
|
103
|
-
/** @param {string} name @param {{ signal?: AbortSignal, timeoutMs?: number, sourceSessionId?: string }} [options] */
|
|
104
|
-
prepare(name, { signal, timeoutMs = 5000, sourceSessionId } = {}) {
|
|
105
|
-
try {
|
|
106
|
-
if (!available() || pending || signal?.aborted || typeof name !== 'string'
|
|
107
|
-
|| path.basename(resolveSelectedProfile(path.parse(__dirname).root, name)) !== name
|
|
108
|
-
|| !Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 30000
|
|
109
|
-
|| (sourceSessionId !== undefined && (typeof sourceSessionId !== 'string' || !SESSION_ID.test(sourceSessionId)))) return Promise.resolve(false);
|
|
110
|
-
} catch { return Promise.resolve(false); }
|
|
111
|
-
return new Promise(resolve => {
|
|
112
|
-
const request = { id: randomUUID(), prepared: false, finish: undefined };
|
|
113
|
-
let settled = false;
|
|
114
|
-
let timer;
|
|
115
|
-
const aborted = () => cancel();
|
|
116
|
-
const disconnected = () => cancel();
|
|
117
|
-
const message = reply => {
|
|
118
|
-
if (pending !== request || reply?.type !== PROFILE_HANDOFF_REPLY || reply.requestId !== request.id
|
|
119
|
-
|| Object.keys(reply).sort().join(',') !== 'requestId,status,type') return;
|
|
120
|
-
if (reply.status === 'prepared') request.finish(true);
|
|
121
|
-
else if (reply.status === 'rejected' || reply.status === 'cancelled') cancel();
|
|
122
|
-
};
|
|
123
|
-
request.finish = prepared => {
|
|
124
|
-
if (!prepared) signal?.removeEventListener('abort', aborted);
|
|
125
|
-
if (settled) return;
|
|
126
|
-
settled = true;
|
|
127
|
-
clearTimeout(timer);
|
|
128
|
-
channel.removeListener('message', message);
|
|
129
|
-
channel.removeListener('disconnect', disconnected);
|
|
130
|
-
try { channel.channel?.unref(); } catch {}
|
|
131
|
-
request.prepared = prepared;
|
|
132
|
-
resolve(prepared);
|
|
133
|
-
};
|
|
134
|
-
pending = request;
|
|
135
|
-
channel.on('message', message);
|
|
136
|
-
channel.once('disconnect', disconnected);
|
|
137
|
-
signal?.addEventListener('abort', aborted, { once: true });
|
|
138
|
-
timer = setTimeout(aborted, timeoutMs);
|
|
139
|
-
try {
|
|
140
|
-
channel.channel?.ref();
|
|
141
|
-
channel.send({ type: PROFILE_HANDOFF_REQUEST, requestId: request.id, name,
|
|
142
|
-
...(sourceSessionId === undefined ? {} : { sourceSessionId }) }, error => {
|
|
143
|
-
if (error && pending === request) cancel();
|
|
144
|
-
});
|
|
145
|
-
} catch { cancel(); }
|
|
146
|
-
});
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
module.exports = { createProfileHandoff, createProfileHandoffClient, PROFILE_HANDOFF_CANCEL, PROFILE_HANDOFF_REQUEST, PROFILE_HANDOFF_REPLY,
|
|
152
|
-
PROFILE_HANDOFF_READY, PROFILE_HANDOFF_EXIT };
|
package/bin/profile-launch.cjs
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const path = require('node:path');
|
|
4
|
-
const fs = require('node:fs');
|
|
5
|
-
|
|
6
|
-
const PROFILE_NAME = /^[a-z0-9][a-z0-9_-]{0,31}$/u;
|
|
7
|
-
const RESERVED = new Set(['doctor', 'export', 'help', 'login', 'mcp', 'server', 'tools', 'update', 'upgrade', 'version']);
|
|
8
|
-
|
|
9
|
-
function profileName(value) {
|
|
10
|
-
const name = String(value || '').trim().toLowerCase();
|
|
11
|
-
if (!PROFILE_NAME.test(name)) {
|
|
12
|
-
throw new Error('Profilnamen duerfen nur Buchstaben, Zahlen, Unterstriche und Bindestriche enthalten.');
|
|
13
|
-
}
|
|
14
|
-
return name;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function parseProfileLaunchArgs(args, mode) {
|
|
18
|
-
const remaining = [...args];
|
|
19
|
-
if (mode !== 'king') return { args: remaining, name: undefined };
|
|
20
|
-
|
|
21
|
-
const flag = remaining.indexOf('--profile');
|
|
22
|
-
if (flag >= 0) {
|
|
23
|
-
if (flag + 1 >= remaining.length) throw new Error('--profile braucht einen Profilnamen.');
|
|
24
|
-
const name = profileName(remaining[flag + 1]);
|
|
25
|
-
remaining.splice(flag, 2);
|
|
26
|
-
return { args: remaining, name };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (remaining.length === 1 && !remaining[0].startsWith('-') && !RESERVED.has(remaining[0].toLowerCase())) {
|
|
30
|
-
return { args: [], name: profileName(remaining[0]), implicit: true };
|
|
31
|
-
}
|
|
32
|
-
if (remaining.length === 2 && remaining.includes('-c')) {
|
|
33
|
-
const candidate = remaining.find(value => value !== '-c');
|
|
34
|
-
if (candidate && !candidate.startsWith('-')) return { args: ['-c'], name: profileName(candidate), implicit: true };
|
|
35
|
-
}
|
|
36
|
-
return { args: remaining, name: undefined };
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function resolveSelectedProfile(sharedHome, name, pathImpl = path) {
|
|
40
|
-
return pathImpl.join(sharedHome, 'profile', profileName(name));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function catalogUnavailable() {
|
|
44
|
-
return Object.assign(new Error('PROFILE_CATALOG_UNAVAILABLE'), { code: 'PROFILE_CATALOG_UNAVAILABLE' });
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function directoryIdentity(target, fsImpl) {
|
|
48
|
-
let stat;
|
|
49
|
-
try { stat = fsImpl.lstatSync(target, { bigint: true }); }
|
|
50
|
-
catch (error) {
|
|
51
|
-
if (error.code === 'ENOENT') return undefined;
|
|
52
|
-
throw error;
|
|
53
|
-
}
|
|
54
|
-
if (!stat.isDirectory() || stat.isSymbolicLink()) throw catalogUnavailable();
|
|
55
|
-
return stat;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function homeIdentity(home, fsImpl) {
|
|
59
|
-
const root = path.parse(home).root;
|
|
60
|
-
let current = root;
|
|
61
|
-
let stat = directoryIdentity(current, fsImpl);
|
|
62
|
-
for (const part of home.slice(root.length).split(path.sep).filter(Boolean)) {
|
|
63
|
-
if (stat === undefined) return undefined;
|
|
64
|
-
current = path.join(current, part);
|
|
65
|
-
stat = directoryIdentity(current, fsImpl);
|
|
66
|
-
}
|
|
67
|
-
return stat;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function sameDirectory(before, after) {
|
|
71
|
-
return before !== undefined && after !== undefined && before.dev === after.dev && before.ino === after.ino;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** Directory names only; selection must revalidate them before changing owner. */
|
|
75
|
-
function listExistingProfiles(sharedHome, options = {}) {
|
|
76
|
-
const fsImpl = options.fsImpl || fs;
|
|
77
|
-
try {
|
|
78
|
-
if (typeof sharedHome !== 'string' || !path.isAbsolute(sharedHome)) throw catalogUnavailable();
|
|
79
|
-
const home = path.resolve(sharedHome);
|
|
80
|
-
if (process.platform === 'win32' && home.startsWith('\\\\')) throw catalogUnavailable();
|
|
81
|
-
const beforeHome = homeIdentity(home, fsImpl);
|
|
82
|
-
if (beforeHome === undefined) return [];
|
|
83
|
-
const profileRoot = path.join(home, 'profile');
|
|
84
|
-
const beforeProfiles = directoryIdentity(profileRoot, fsImpl);
|
|
85
|
-
if (beforeProfiles === undefined) {
|
|
86
|
-
if (!sameDirectory(beforeHome, homeIdentity(home, fsImpl))) throw catalogUnavailable();
|
|
87
|
-
return [];
|
|
88
|
-
}
|
|
89
|
-
const rows = [];
|
|
90
|
-
const dir = fsImpl.opendirSync(profileRoot);
|
|
91
|
-
try {
|
|
92
|
-
let count = 0;
|
|
93
|
-
for (let entry; (entry = dir.readSync()) !== null;) {
|
|
94
|
-
if (++count > 4096) throw catalogUnavailable();
|
|
95
|
-
const name = entry.name;
|
|
96
|
-
if (!PROFILE_NAME.test(name)) continue;
|
|
97
|
-
const target = resolveSelectedProfile(home, name);
|
|
98
|
-
let stat;
|
|
99
|
-
try { stat = fsImpl.lstatSync(target, { bigint: true }); }
|
|
100
|
-
catch (error) {
|
|
101
|
-
if (error.code === 'ENOENT') continue;
|
|
102
|
-
throw error;
|
|
103
|
-
}
|
|
104
|
-
if (stat.isDirectory() && !stat.isSymbolicLink()) rows.push({ name, target, stat });
|
|
105
|
-
}
|
|
106
|
-
} finally { dir.closeSync(); }
|
|
107
|
-
if (!sameDirectory(beforeHome, homeIdentity(home, fsImpl))
|
|
108
|
-
|| !sameDirectory(beforeProfiles, directoryIdentity(profileRoot, fsImpl))) throw catalogUnavailable();
|
|
109
|
-
for (const row of rows) {
|
|
110
|
-
if (!sameDirectory(row.stat, directoryIdentity(row.target, fsImpl))) throw catalogUnavailable();
|
|
111
|
-
}
|
|
112
|
-
if (!sameDirectory(beforeHome, homeIdentity(home, fsImpl))
|
|
113
|
-
|| !sameDirectory(beforeProfiles, directoryIdentity(profileRoot, fsImpl))) throw catalogUnavailable();
|
|
114
|
-
return rows.map(row => row.name).sort();
|
|
115
|
-
} catch {
|
|
116
|
-
throw catalogUnavailable();
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
module.exports = { parseProfileLaunchArgs, resolveSelectedProfile, listExistingProfiles };
|