@arcfold/dsh 0.0.0-stage → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +8 -2
- package/THIRD_PARTY_NOTICES.md +11 -0
- package/cordis.patch.yml +138 -0
- package/package.json +70 -4
- package/patches/deepseek-0.2.2-rc.1-transport.json +65 -0
- package/patches/deepseek-0.2.2-rc.1-transport.patch +61 -0
- package/presets/arcfold.patch.yml +110 -0
- package/runtime/README.md +19 -0
- package/runtime/bootstrap.json +15 -0
- package/runtime/desktop-python.tar.gz +0 -0
- package/runtime/host/package.json +11 -0
- package/runtime/host/pnpm-workspace.yaml +9 -0
- package/runtime/initial-policy.json +94 -0
- package/runtime/profile/pnpm-workspace.yaml +7 -0
- package/scripts/exact-package-patch.mjs +106 -0
- package/scripts/patch-deepseek-transport.mjs +14 -0
- package/src/agent.mjs +56 -0
- package/src/browse-scope.mjs +14 -0
- package/src/budget.mjs +369 -0
- package/src/business.mjs +334 -0
- package/src/context-material.mjs +119 -0
- package/src/deepseek-budget-plugin.mjs +58 -0
- package/src/deepseek-provider.mjs +57 -0
- package/src/deepseek-receipt.mjs +97 -0
- package/src/deepseek-transport.mjs +97 -0
- package/src/desktop/adapter.mjs +16 -0
- package/src/desktop/bootstrap.mjs +84 -0
- package/src/desktop/configuration.mjs +117 -0
- package/src/desktop/provider.mjs +46 -0
- package/src/desktop/python-runtime.mjs +105 -0
- package/src/desktop/setup-service.mjs +81 -0
- package/src/desktop/vendor/LICENSE.deepseek +21 -0
- package/src/desktop/vendor/NOTICE.md +5 -0
- package/src/desktop/vendor/deepseek-0.2.2-rc.1.mjs +2919 -0
- package/src/evidence-ownership.mjs +51 -0
- package/src/evidence.mjs +35 -0
- package/src/goal-context.mjs +52 -0
- package/src/goal-execution-tool.mjs +74 -0
- package/src/goal-execution.mjs +333 -0
- package/src/goal-tool.mjs +56 -0
- package/src/goal-work-control.mjs +63 -0
- package/src/goal-work.mjs +257 -0
- package/src/goals.mjs +578 -0
- package/src/importer.mjs +298 -0
- package/src/index.mjs +53 -0
- package/src/learning-contracts.mjs +220 -0
- package/src/learning-defaults.mjs +98 -0
- package/src/learning-goals.mjs +165 -0
- package/src/learning-plugin.mjs +28 -0
- package/src/learning-runner.mjs +275 -0
- package/src/learning.mjs +534 -0
- package/src/legacy-export.mjs +332 -0
- package/src/legacy-import-source.mjs +356 -0
- package/src/metered-provider-host.mjs +101 -0
- package/src/metered-transport.mjs +435 -0
- package/src/method-context.mjs +57 -0
- package/src/method-lifecycle.mjs +34 -0
- package/src/method-tool.mjs +61 -0
- package/src/methods.mjs +425 -0
- package/src/model-selection.mjs +41 -0
- package/src/native-context-call.mjs +88 -0
- package/src/native-continuation.mjs +217 -0
- package/src/native-request-authority.mjs +90 -0
- package/src/openai-models.mjs +4 -0
- package/src/openai-receipt.mjs +98 -0
- package/src/openai-transport.mjs +167 -0
- package/src/openai-usage.mjs +194 -0
- package/src/opportunities.mjs +295 -0
- package/src/preparation-artifacts.mjs +213 -0
- package/src/preparation-plugin.mjs +290 -0
- package/src/runtime-command.mjs +264 -0
- package/src/runtime-config.mjs +417 -0
- package/src/runtime-guard.mjs +284 -0
- package/src/runtime-host.mjs +212 -0
- package/src/runtime-init.mjs +278 -0
- package/src/runtime-installation.mjs +518 -0
- package/src/runtime-lifecycle.mjs +227 -0
- package/src/runtime-model-settings.mjs +111 -0
- package/src/runtime-readiness.mjs +285 -0
- package/src/runtime-workspace.mjs +18 -0
- package/src/session-bridge.mjs +365 -0
- package/src/store.mjs +394 -0
- package/src/tree/LICENSE +21 -0
- package/src/tree/attribution.mjs +120 -0
- package/src/tree/clusters.mjs +61 -0
- package/src/tree/consolidation.mjs +103 -0
- package/src/tree/context.mjs +211 -0
- package/src/tree/contracts.mjs +142 -0
- package/src/tree/experience.mjs +140 -0
- package/src/tree/experiment-budget.mjs +84 -0
- package/src/tree/hooks.mjs +254 -0
- package/src/tree/host-context.mjs +107 -0
- package/src/tree/host-process.mjs +288 -0
- package/src/tree/host.mjs +37 -0
- package/src/tree/improvement.mjs +106 -0
- package/src/tree/items.mjs +294 -0
- package/src/tree/jobs.mjs +184 -0
- package/src/tree/learning.mjs +202 -0
- package/src/tree/metrics.mjs +203 -0
- package/src/tree/model-owner.mjs +254 -0
- package/src/tree/observations.mjs +73 -0
- package/src/tree/prompts.mjs +500 -0
- package/src/tree/reports.mjs +67 -0
- package/src/tree/repository.mjs +236 -0
- package/src/tree/runtime.mjs +745 -0
- package/src/tree/script-writer.mjs +149 -0
- package/src/tree/scripts.mjs +208 -0
- package/src/tree/signals.mjs +118 -0
- package/src/tree/snapshots.mjs +379 -0
- package/src/tree/token-counter.mjs +75 -0
- package/src/tree/token-counter.py +37 -0
- package/src/tree/tokenizer-resources/LICENSE +21 -0
- package/src/tree/tokenizer-resources/README.md +31 -0
- package/src/tree/tokenizer-resources/deepseek_recipe-0.2.0-cp310-abi3-macosx_11_0_arm64.whl +0 -0
- package/src/tree/tokenizer-resources/manifest.json +61 -0
- package/src/tree/tokenizer-resources/native.pyi +1042 -0
- package/src/tree/tokenizer-resources/tokenizer-NOTICE.md +26 -0
- package/src/tree/tokenizer-resources/tokenizer-v4-NOTICE.md +27 -0
- package/src/tree/tokenizer-resources/tokenizer-v4.json +267359 -0
- package/src/tree/tokenizer-resources/tokenizer.json +267359 -0
- package/src/tree/tools.mjs +99 -0
- package/src/tree/tree.mjs +202 -0
- package/src/tree/ui.mjs +285 -0
- package/src/tree/verification.mjs +143 -0
- package/src/understandings.mjs +309 -0
- package/src/web-budget-recovery.mjs +181 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { canonicalJson } from './store.mjs';
|
|
2
|
+
import { learningExecutionConfig } from './learning-defaults.mjs';
|
|
3
|
+
import { symbols } from '@deepseek-ai/cordis';
|
|
4
|
+
|
|
5
|
+
const guards = new WeakMap();
|
|
6
|
+
const ACTIVE = 2; // Cordis 4.1.0 FiberState.ACTIVE (the TS const enum has no JS export).
|
|
7
|
+
const SERVICE = 'arcfoldRuntimeGuard';
|
|
8
|
+
const REQUIRED = ['llm', 'arcfold-business', 'preset-arcfold-main'];
|
|
9
|
+
const ROUTE_FIELDS = ['provider', 'model', 'reasoningEffort', 'maxTokens'];
|
|
10
|
+
|
|
11
|
+
function frozen(value) {
|
|
12
|
+
if (value && typeof value === 'object') {
|
|
13
|
+
for (const child of Object.values(value)) frozen(child);
|
|
14
|
+
Object.freeze(value);
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function failure(code, message) {
|
|
20
|
+
const error = new Error(message);
|
|
21
|
+
error.code = code;
|
|
22
|
+
return error;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function configuration(value) {
|
|
26
|
+
return frozen(JSON.parse(canonicalJson({
|
|
27
|
+
modelSelectionRequired: value.modelSelectionRequired === true,
|
|
28
|
+
initialMain: value.initialMain ?? { provider: '', model: '' },
|
|
29
|
+
mainMaxTokens: value.mainMaxTokens ?? null,
|
|
30
|
+
routeAvailability: value.routeAvailability ?? { main: { available: false }, learn: { available: false } },
|
|
31
|
+
learn: value.learn ?? null,
|
|
32
|
+
modelPolicies: value.modelPolicies ?? {},
|
|
33
|
+
...(value.routes === undefined ? {} : { routes: value.routes }),
|
|
34
|
+
})));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function provision(fiber, name) {
|
|
38
|
+
const matches = [...(fiber?.provisions ?? [])].filter(item => item.name === name);
|
|
39
|
+
if (matches.length !== 1 || matches[0].ctx.fiber !== fiber)
|
|
40
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', `The runtime has no unique owned ${name} service`);
|
|
41
|
+
return matches[0];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Cordis exports this read-only tracing identity symbol. Event callbacks see
|
|
45
|
+
// caller-scoped proxies, not the raw service retained by Fiber.provisions.
|
|
46
|
+
export function serviceIdentity(value) {
|
|
47
|
+
const seen = new Set();
|
|
48
|
+
while (value && value[symbols.original]) {
|
|
49
|
+
if (seen.has(value)) return null;
|
|
50
|
+
seen.add(value); value = value[symbols.original];
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Read the real optional child, never a guessed Loader entry or provider label. */
|
|
56
|
+
export function assertOpenAIIdentity(root, wrapper, llm, metered) {
|
|
57
|
+
const record = provision(wrapper, 'arcfoldOpenAIProviderIdentity'), identity = record.value;
|
|
58
|
+
const child = identity?.nativeFiber;
|
|
59
|
+
if (!Object.isFrozen(identity) || !Object.isFrozen(identity.configuration) || identity.wrapperFiber !== wrapper ||
|
|
60
|
+
!child || child.state !== ACTIVE || child.ctx.root !== root || child.parent.fiber !== wrapper ||
|
|
61
|
+
child.committed?.llm !== llm || wrapper.committed?.llm !== llm || wrapper.committed?.arcfoldMeteredTransport !== metered ||
|
|
62
|
+
typeof identity.moduleURL !== 'string' || typeof identity.transportHookActive !== 'function' || identity.transportHookActive() !== true ||
|
|
63
|
+
canonicalJson(child.rawConfig) !== canonicalJson(identity.configuration))
|
|
64
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The actual OpenAI child, fixed profile or owned transport callback changed.');
|
|
65
|
+
return identity;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Root ownership deliberately survives profile-entry disposal. No entry may re-arm it. */
|
|
69
|
+
export function getRuntimeGuard(ctx) {
|
|
70
|
+
return guards.get(ctx.root) ?? ctx.root.get(SERVICE);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const name = 'arcfold-runtime-guard';
|
|
74
|
+
// No injection: the official llm entry depends on the root service this installs.
|
|
75
|
+
export function apply(ctx, input = {}) {
|
|
76
|
+
const root = ctx.root, config = configuration(input), existing = getRuntimeGuard(root);
|
|
77
|
+
if (existing) {
|
|
78
|
+
if (canonicalJson(existing.configuration) !== canonicalJson(config)) existing.requireRestart('guard-configuration-changed');
|
|
79
|
+
return; // Never return a root-owned disposer to the replaceable plugin fiber.
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let phase = 'starting', reason = null, armed = false, adapterUpdates = 0;
|
|
83
|
+
let releaseReady;
|
|
84
|
+
const ready = new Promise(resolve => { releaseReady = resolve; });
|
|
85
|
+
let pinned = [], identifyRequest, transport, rootLlm, openAI, business, models;
|
|
86
|
+
const providerIdentitiesCurrent = () => {
|
|
87
|
+
if (models && models.identity.hookActive() !== true) return false;
|
|
88
|
+
if (openAI) { try { if (assertOpenAIIdentity(root, openAI.wrapper, rootLlm, transport) !== openAI.identity) return false; } catch { return false; } }
|
|
89
|
+
return true;
|
|
90
|
+
};
|
|
91
|
+
const identitiesCurrent = () => providerIdentitiesCurrent() && pinned.every(saved => saved.fiber.uid === saved.uid && saved.fiber.state === ACTIVE &&
|
|
92
|
+
saved.provisions.every(item => saved.fiber.provisions.has(item.record) && item.record.value === item.value && item.record.uid === item.uid) &&
|
|
93
|
+
Object.entries(saved.committed).every(([key, item]) => saved.fiber.committed?.[key] === item.record &&
|
|
94
|
+
item.record.value === item.value && item.record.uid === item.uid));
|
|
95
|
+
const snapshot = () => Object.freeze(phase === 'ready' && !identitiesCurrent()
|
|
96
|
+
? { phase: 'requires-restart', reason: 'critical-component-changed', armed, adapterUpdates }
|
|
97
|
+
: { phase, reason, armed, adapterUpdates });
|
|
98
|
+
const stop = (next, why) => {
|
|
99
|
+
if (phase === 'closed' || phase === 'failed' || phase === 'requires-restart') return;
|
|
100
|
+
phase = next; reason = why; releaseReady();
|
|
101
|
+
};
|
|
102
|
+
const requireRestart = why => stop('requires-restart', why);
|
|
103
|
+
const rejectState = () => {
|
|
104
|
+
if (phase !== 'ready') throw failure(
|
|
105
|
+
phase === 'requires-restart' ? 'ARCFOLD_RUNTIME_RESTART_REQUIRED' : 'ARCFOLD_RUNTIME_NOT_READY',
|
|
106
|
+
phase === 'requires-restart' ? 'The model configuration changed; restart Arcfold through its launcher before sending another request.'
|
|
107
|
+
: 'Arcfold is not ready to send model requests. Its configuration page remains available.',
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
const assertIdentities = () => {
|
|
111
|
+
if (!identitiesCurrent()) { requireRestart('critical-component-changed'); rejectState(); }
|
|
112
|
+
};
|
|
113
|
+
const assertInput = options => {
|
|
114
|
+
rejectState(); assertIdentities();
|
|
115
|
+
options.signal?.throwIfAborted();
|
|
116
|
+
if (!transport) throw failure('ARCFOLD_ROUTE_UNAVAILABLE', 'No supported metered model route is configured.');
|
|
117
|
+
if (!Object.isFrozen(options)) throw failure('ARCFOLD_RUNTIME_INPUT', 'Only a frozen native session request may use this runtime.');
|
|
118
|
+
const policies = config.routes === undefined ? (options.provider === 'deepseek-official' ? config.modelPolicies : undefined) : config.routes[options.provider]?.modelPolicies;
|
|
119
|
+
const policy = policies?.[options.model];
|
|
120
|
+
if (!policy ||
|
|
121
|
+
!policy.reasoningEfforts?.includes(options.reasoningEffort) ||
|
|
122
|
+
!Number.isSafeInteger(options.maxTokens) || options.maxTokens < 1 ||
|
|
123
|
+
options.maxTokens > (policy.requestMaxTokens ?? policy.maxOutputTokens))
|
|
124
|
+
throw failure('ARCFOLD_ROUTE_UNAVAILABLE', 'The selected model or request controls are not supported by this metered runtime.');
|
|
125
|
+
};
|
|
126
|
+
// Full business ownership is checked at the owned transport, after the
|
|
127
|
+
// learning middleware has validated and recorded its single-call intent.
|
|
128
|
+
const assertDispatch = options => {
|
|
129
|
+
assertInput(options);
|
|
130
|
+
const identity = identifyRequest(options);
|
|
131
|
+
if (identity && typeof identity.then === 'function') {
|
|
132
|
+
void Promise.resolve(identity).catch(() => {});
|
|
133
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'Native request identity must be checked synchronously.');
|
|
134
|
+
}
|
|
135
|
+
const role = identity?.metadata?.role;
|
|
136
|
+
if (!['main', 'learning', 'preparation'].includes(role)) throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The request has no supported Arcfold owner.');
|
|
137
|
+
if (role === 'main' && config.mainMaxTokens !== null && options.maxTokens !== config.mainMaxTokens)
|
|
138
|
+
throw failure('ARCFOLD_ROUTE_UNAVAILABLE', 'The native model default cannot represent the explicitly configured main output limit. Update the main configuration before sending.');
|
|
139
|
+
if (role === 'learning') {
|
|
140
|
+
const run = business?.get('learning_runs', identity.metadata.learningPendingId);
|
|
141
|
+
if (!config.routeAvailability.learn?.available || !run || run.sessionId !== options.sessionId ||
|
|
142
|
+
run.inputHash !== identity.metadata.learningInputHash)
|
|
143
|
+
throw failure('ARCFOLD_ROUTE_UNAVAILABLE', 'This learning request has no matching saved execution configuration.');
|
|
144
|
+
const execution = learningExecutionConfig(run);
|
|
145
|
+
if (ROUTE_FIELDS.some(key => options[key] !== execution[key]))
|
|
146
|
+
throw failure('ARCFOLD_ROUTE_UNAVAILABLE', 'This learning request does not match its independently configured model saved at start.');
|
|
147
|
+
}
|
|
148
|
+
if (role === 'preparation') {
|
|
149
|
+
const run = business?.get('preparation_runs', identity.metadata.preparationRunId);
|
|
150
|
+
if (!run || run.sessionId !== options.sessionId || run.inputHash !== identity.metadata.preparationInputHash ||
|
|
151
|
+
run.state !== 'submitted' || ROUTE_FIELDS.some(key => options[key] !== run.executionConfig?.[key]) ||
|
|
152
|
+
!root.get('arcfoldPreparation'))
|
|
153
|
+
throw failure('ARCFOLD_ROUTE_UNAVAILABLE', 'Preparation has no matching bounded native owner.');
|
|
154
|
+
}
|
|
155
|
+
return identity;
|
|
156
|
+
};
|
|
157
|
+
const waitReady = async signal => {
|
|
158
|
+
signal?.throwIfAborted();
|
|
159
|
+
if (phase === 'starting') {
|
|
160
|
+
if (!signal) await ready;
|
|
161
|
+
else await new Promise((resolve, reject) => {
|
|
162
|
+
const abort = () => { signal.removeEventListener('abort', abort); reject(signal.reason); };
|
|
163
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
164
|
+
ready.then(() => { signal.removeEventListener('abort', abort); resolve(); });
|
|
165
|
+
if (signal.aborted) abort();
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
signal?.throwIfAborted(); rejectState();
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const guard = Object.freeze({
|
|
172
|
+
configuration: config, snapshot, requireRestart, assertDispatch,
|
|
173
|
+
assertReady() { rejectState(); assertIdentities(); },
|
|
174
|
+
fail: () => stop('failed', 'startup-failed'),
|
|
175
|
+
close: () => stop('closed', 'runtime-closed'),
|
|
176
|
+
arm({ criticalFibers, identifyRequest: identify, expectedAdapterUpdates = adapterUpdates } = {}) {
|
|
177
|
+
if (armed || phase !== 'starting') throw failure('ARCFOLD_RUNTIME_ARM', 'A runtime guard can be armed only once, by startup readiness.');
|
|
178
|
+
try {
|
|
179
|
+
if (!criticalFibers || typeof criticalFibers !== 'object' || Array.isArray(criticalFibers))
|
|
180
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'Startup must supply the actual critical plugin fibers.');
|
|
181
|
+
for (const id of REQUIRED) if (!criticalFibers[id]) throw failure('ARCFOLD_RUNTIME_IDENTITY', `Startup is missing ${id}.`);
|
|
182
|
+
pinned = Object.entries(criticalFibers).map(([id, fiber]) => {
|
|
183
|
+
if (fiber?.state !== ACTIVE || !Number.isSafeInteger(fiber.uid) || fiber.uid < 1 || fiber.ctx.root !== root)
|
|
184
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', `The ${id} plugin is not an active child of this host.`);
|
|
185
|
+
const pin = record => ({ record, value: record.value, uid: record.uid });
|
|
186
|
+
return { id, fiber, uid: fiber.uid, provisions: [...fiber.provisions].map(pin),
|
|
187
|
+
committed: Object.fromEntries(Object.entries(fiber.committed ?? {}).map(([key, record]) => [key, pin(record)])) };
|
|
188
|
+
});
|
|
189
|
+
rootLlm = provision(criticalFibers.llm, 'llm');
|
|
190
|
+
business = provision(criticalFibers['arcfold-business'], 'arcfoldBusiness').value;
|
|
191
|
+
if (config.modelSelectionRequired) {
|
|
192
|
+
const modelFiber = criticalFibers['arcfold-runtime-model-settings'];
|
|
193
|
+
models = provision(modelFiber, 'arcfoldRuntimeModels').value;
|
|
194
|
+
const expected = { sessionController: 'session-controller', agentDefaultModel: 'agent-default-model', sessions: 'session', configEditor: 'config-editor' };
|
|
195
|
+
for (const [name, id] of Object.entries(expected))
|
|
196
|
+
if (modelFiber.committed?.[name] !== provision(criticalFibers[id], name))
|
|
197
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'Native model settings uses an unverified service.');
|
|
198
|
+
const identity = models.identity;
|
|
199
|
+
if (!Object.isFrozen(identity) || identity.fiber !== modelFiber || identity.hookActive() !== true ||
|
|
200
|
+
identity.controller !== provision(criticalFibers['session-controller'], 'sessionController').value ||
|
|
201
|
+
identity.defaults !== provision(criticalFibers['agent-default-model'], 'agentDefaultModel').value ||
|
|
202
|
+
identity.sessions !== provision(criticalFibers.session, 'sessions').value)
|
|
203
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The mandatory native model selection handler is absent or changed.');
|
|
204
|
+
}
|
|
205
|
+
const provider = criticalFibers['arcfold-metered-provider'];
|
|
206
|
+
const shared = criticalFibers['arcfold-shared-metered-host'];
|
|
207
|
+
const expectedProviders = config.routes === undefined ? (provider ? ['deepseek-official'] : []) : Object.keys(config.routes).sort();
|
|
208
|
+
if (canonicalJson(rootLlm.value.listProviders().map(p => p.id).sort()) !== canonicalJson(expectedProviders) ||
|
|
209
|
+
serviceIdentity(root.get('llm')) !== rootLlm.value || expectedAdapterUpdates !== adapterUpdates)
|
|
210
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The actual model topology changed before the final readiness check.');
|
|
211
|
+
if (config.routes !== undefined) {
|
|
212
|
+
if (Boolean(shared) !== Boolean(expectedProviders.length)) throw failure('ARCFOLD_RUNTIME_IDENTITY', 'Shared accounting and actual model routes must be mounted together.');
|
|
213
|
+
if (shared) {
|
|
214
|
+
transport = provision(shared, 'arcfoldMeteredTransport');
|
|
215
|
+
if (shared.committed?.llm !== rootLlm || typeof transport.value?.createTransport !== 'function' ||
|
|
216
|
+
canonicalJson(transport.value.configuration.routes) !== canonicalJson(config.routes))
|
|
217
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The shared accounting policies or LLM ownership differ from startup configuration.');
|
|
218
|
+
const business = provision(criticalFibers['arcfold-business'], 'arcfoldBusiness');
|
|
219
|
+
const sessions = provision(criticalFibers.session, 'sessions');
|
|
220
|
+
if (shared.committed?.arcfoldBusiness !== business || shared.committed?.sessions !== sessions)
|
|
221
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The shared host uses a different business or native session service.');
|
|
222
|
+
}
|
|
223
|
+
const deepseek = config.routes['deepseek-official'];
|
|
224
|
+
if (Boolean(provider) !== Boolean(deepseek)) throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The configured DeepSeek wrapper is absent or unexpected.');
|
|
225
|
+
if (provider && (provider.committed?.llm !== rootLlm || provider.committed?.arcfoldDeepSeekTransport !== provision(shared, 'arcfoldDeepSeekTransport')))
|
|
226
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The DeepSeek wrapper is not owned by the shared host.');
|
|
227
|
+
const wrapper = criticalFibers['arcfold-openai-provider'];
|
|
228
|
+
if (Boolean(wrapper) !== Boolean(config.routes.openai)) throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The configured OpenAI wrapper is absent or unexpected.');
|
|
229
|
+
if (wrapper) {
|
|
230
|
+
const identity = assertOpenAIIdentity(root, wrapper, rootLlm, transport);
|
|
231
|
+
if (criticalFibers['arcfold-openai-native'] !== identity.nativeFiber)
|
|
232
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'Readiness did not pin the actual native OpenAI child.');
|
|
233
|
+
openAI = { wrapper, identity };
|
|
234
|
+
}
|
|
235
|
+
if (expectedProviders.length) {
|
|
236
|
+
const credentials = provision(criticalFibers.credentials, 'credentials');
|
|
237
|
+
for (const wrapper of [provider, criticalFibers['arcfold-openai-provider']].filter(Boolean))
|
|
238
|
+
if (wrapper.committed?.credentials !== credentials) throw failure('ARCFOLD_RUNTIME_IDENTITY', 'A provider uses a foreign credential service.');
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
const budget = criticalFibers['arcfold-metered-budget'];
|
|
242
|
+
if (Boolean(budget) !== Boolean(provider)) throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The model provider and its accounting service must be mounted together.');
|
|
243
|
+
if (provider) {
|
|
244
|
+
transport = provision(budget, 'arcfoldDeepSeekTransport');
|
|
245
|
+
if (provider.committed?.llm !== rootLlm || provider.committed?.arcfoldDeepSeekTransport !== transport || budget.committed?.llm !== rootLlm ||
|
|
246
|
+
transport.value?.configuration?.provider !== 'deepseek-official' || canonicalJson(transport.value.configuration.modelPolicies) !== canonicalJson(config.modelPolicies))
|
|
247
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The metered provider is not bound to the verified LLM and accounting instances.');
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (expectedProviders.length && typeof identify !== 'function') throw failure('ARCFOLD_RUNTIME_IDENTITY', 'A native request identity check is required.');
|
|
251
|
+
if (config.routeAvailability.learn?.available && (!transport || !criticalFibers['arcfold-learning'] || !criticalFibers['preset-arcfold-learning']))
|
|
252
|
+
throw failure('ARCFOLD_RUNTIME_IDENTITY', 'The independently configured learning route is incomplete.');
|
|
253
|
+
identifyRequest = identify; armed = true; phase = 'ready'; releaseReady();
|
|
254
|
+
return snapshot();
|
|
255
|
+
} catch (error) { stop('failed', 'startup-identity-failed'); throw error; }
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
guards.set(root, guard);
|
|
259
|
+
root.on('llm/adapters-updated', () => {
|
|
260
|
+
adapterUpdates++;
|
|
261
|
+
if (armed) requireRestart('model-topology-changed');
|
|
262
|
+
}, { global: true });
|
|
263
|
+
root.on('internal/status', fiber => {
|
|
264
|
+
if (armed && pinned.some(item => item.fiber === fiber) && fiber.state !== ACTIVE) requireRestart('critical-component-changed');
|
|
265
|
+
}, { global: true });
|
|
266
|
+
root.on('loader/volatile-update', function () {
|
|
267
|
+
// Native default fields are explicitly volatile; a normal daily selection
|
|
268
|
+
// retains the same service and must not tear down an active learning run.
|
|
269
|
+
if (armed && pinned.some(item => item.fiber === this.fiber && item.id !== 'agent-default-model')) requireRestart('critical-configuration-changed');
|
|
270
|
+
}, { global: true });
|
|
271
|
+
root.on('llm/stream', function (options, next) {
|
|
272
|
+
const sender = serviceIdentity(this);
|
|
273
|
+
return (async function* () {
|
|
274
|
+
await waitReady(options.signal);
|
|
275
|
+
if (sender !== rootLlm.value) requireRestart('llm-instance-changed');
|
|
276
|
+
// The outer gate runs before downstream learning validation. It
|
|
277
|
+
// checks host/route readiness, not a dispatch intent that does not yet exist.
|
|
278
|
+
assertInput(options);
|
|
279
|
+
yield* next();
|
|
280
|
+
})();
|
|
281
|
+
}, { global: true, prepend: true });
|
|
282
|
+
root.effect(() => () => guard.close(), 'close the model gate with the official host');
|
|
283
|
+
root.provide(SERVICE, guard);
|
|
284
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { randomBytes, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
|
+
import { mkdir, readFile } from 'node:fs/promises';
|
|
4
|
+
import { writeFileSync } from 'node:fs';
|
|
5
|
+
import { createServer } from 'node:net';
|
|
6
|
+
import { createRequire } from 'node:module';
|
|
7
|
+
import { join, resolve } from 'node:path';
|
|
8
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
9
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
10
|
+
import { RUNTIME_PROTOCOL, acquireRuntimeLease, lifecycleError, writeRuntimeRecord } from './runtime-lifecycle.mjs';
|
|
11
|
+
|
|
12
|
+
const errorView = error => ({ code: error.code || 'runtime_failure', message: String(error.message || error) });
|
|
13
|
+
const launchBrowser = (command, args) => new Promise((resolveDone, reject) => {
|
|
14
|
+
execFile(command, args, { timeout:5000, maxBuffer:65536 }, error => error ? reject(error) : resolveDone());
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
/** The URL is obtained from this host only and never leaves the opener boundary. */
|
|
18
|
+
export async function openRuntimeBrowser(ctx, { platform = process.platform, opener = launchBrowser } = {}) {
|
|
19
|
+
if (platform !== 'darwin') throw lifecycleError('unsupported_platform', 'Opening the authenticated page is currently supported only on macOS.');
|
|
20
|
+
try {
|
|
21
|
+
const url = ctx.get('connection').authenticatedUrl(ctx.get('webApp').getAdvertisedUrl());
|
|
22
|
+
await opener('/usr/bin/open', [url]);
|
|
23
|
+
return { opened:true };
|
|
24
|
+
} catch { throw lifecycleError('browser_open_failed', 'The authenticated page could not be opened.'); }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Own one host lifetime. Injected functions isolate lifecycle tests, not a CLI plugin hook. */
|
|
28
|
+
export async function runOwnedRuntime({ plan, runId, runDirectory }, { prepareBoot, loadOfficialHost, inspectReady, refreshReady }) {
|
|
29
|
+
const lease = await acquireRuntimeLease(plan.runtimeDirectory);
|
|
30
|
+
let server, controlAddress, official, stopping, cancelled = false, phase = 'starting', ready, failure, bootStarted = false;
|
|
31
|
+
const controlToken = randomBytes(32);
|
|
32
|
+
let officialClosed = false, shutdownEvidence = 'unconfirmed', teardownError;
|
|
33
|
+
const sockets = new Set();
|
|
34
|
+
const state = observation => {
|
|
35
|
+
const view = { ...(ready ?? {}), ...(observation ?? {}) };
|
|
36
|
+
if (ready && (phase !== 'ready' || cancelled)) {
|
|
37
|
+
const reason = 'runtime-' + phase;
|
|
38
|
+
view.mode = 'configuration-only';
|
|
39
|
+
view.routeAvailability = { ...view.routeAvailability, main:{available:false,reason}, learn:{available:false,reason} };
|
|
40
|
+
view.issues = [...new Set([...(view.issues ?? []),reason])];
|
|
41
|
+
delete view.modelGate;
|
|
42
|
+
}
|
|
43
|
+
// Observation fields cannot replace the owned process identity or phase.
|
|
44
|
+
return { ...view, schema:RUNTIME_PROTOCOL, dataRoot:plan.dataRoot, runId, pid:process.pid,
|
|
45
|
+
phase, configurationHash:plan.configurationHash, controlAddress,
|
|
46
|
+
...(failure ? {error:failure} : {}), ...(teardownError ? {teardownError} : {}), shutdownEvidence };
|
|
47
|
+
};
|
|
48
|
+
const status = async () => {
|
|
49
|
+
if (phase !== 'ready' || cancelled || !official) return state();
|
|
50
|
+
const observedHost = official; let observation, timer;
|
|
51
|
+
try {
|
|
52
|
+
observation = await Promise.race([
|
|
53
|
+
Promise.resolve().then(() => refreshReady(observedHost.ctx, plan)),
|
|
54
|
+
new Promise((_, reject) => { timer = setTimeout(() => reject(lifecycleError('readiness_refresh_timeout', 'Readiness observation timed out.')), 750); }),
|
|
55
|
+
]);
|
|
56
|
+
if (!observation || !['execution-ready','configuration-only'].includes(observation.mode) ||
|
|
57
|
+
typeof observation.routeAvailability?.main?.available !== 'boolean' ||
|
|
58
|
+
typeof observation.routeAvailability?.learn?.available !== 'boolean' || !Array.isArray(observation.issues))
|
|
59
|
+
throw lifecycleError('readiness_refresh_failed', 'Invalid readiness observation.');
|
|
60
|
+
observation = { mode:observation.mode, routeAvailability:observation.routeAvailability,
|
|
61
|
+
issues:observation.issues, modelGate:observation.modelGate ?? null };
|
|
62
|
+
} catch (error) {
|
|
63
|
+
const code = error.code === 'readiness_refresh_timeout' ? error.code : 'readiness_refresh_failed';
|
|
64
|
+
observation = { mode:'configuration-only', modelGate:null,
|
|
65
|
+
routeAvailability:{main:{available:false,reason:code},learn:{available:false,reason:code},credentialConfigured:null,providerCredentialValidated:false},
|
|
66
|
+
issues:[code], statusObservationError:{code,message:'Current runtime readiness could not be confirmed.'} };
|
|
67
|
+
} finally { clearTimeout(timer); }
|
|
68
|
+
// A delayed read is never allowed to restore availability after stop/fail.
|
|
69
|
+
if (phase !== 'ready' || cancelled || official !== observedHost) return state();
|
|
70
|
+
return state(observation);
|
|
71
|
+
};
|
|
72
|
+
let writes = Promise.resolve();
|
|
73
|
+
const publish = () => { const value = state(); return writes = writes.catch(() => {}).then(async () => {
|
|
74
|
+
await writeRuntimeRecord(join(runDirectory, 'state.json'), value);
|
|
75
|
+
await writeRuntimeRecord(join(plan.runtimeDirectory, 'current.json'), value);
|
|
76
|
+
}); };
|
|
77
|
+
let resolveStopped;
|
|
78
|
+
const stopped = new Promise(resolveDone => { resolveStopped = resolveDone; });
|
|
79
|
+
const stop = () => {
|
|
80
|
+
cancelled = true;
|
|
81
|
+
if (stopping) return stopping;
|
|
82
|
+
// Before runProfile returns, the startup path will observe cancellation and
|
|
83
|
+
// join this same shutdown operation once the official handle is available.
|
|
84
|
+
if (!official) { phase = 'stopping'; void publish().catch(() => {}); return null; }
|
|
85
|
+
phase = failure ? 'failed' : 'stopping';
|
|
86
|
+
stopping = (async () => {
|
|
87
|
+
try { official.ctx.get?.('arcfoldRuntimeGuard')?.close(); }
|
|
88
|
+
catch (error) { failure ??= errorView(error); }
|
|
89
|
+
await publish().catch(error => { failure ??= errorView(error); });
|
|
90
|
+
await official.shutdown.shutdown(0);
|
|
91
|
+
officialClosed = true;
|
|
92
|
+
await writeRuntimeRecord(join(runDirectory, 'official-shutdown-returned.json'), {
|
|
93
|
+
kind: 'official-shutdown-returned', schema: RUNTIME_PROTOCOL, runId, dataRoot: plan.dataRoot,
|
|
94
|
+
returnedAt: new Date().toISOString(), scope: 'official profile teardown returned; user work and unknown outcomes are not declared successful',
|
|
95
|
+
}, { exclusive: true });
|
|
96
|
+
shutdownEvidence = 'official-shutdown-returned';
|
|
97
|
+
phase = failure ? 'failed' : 'stopped'; await publish(); resolveStopped();
|
|
98
|
+
})();
|
|
99
|
+
void stopping.catch(error => { failure ??= errorView(error); teardownError = errorView(error); resolveStopped(); });
|
|
100
|
+
return stopping;
|
|
101
|
+
};
|
|
102
|
+
// Do not call shutdown again in this listener. runProfile installs its own
|
|
103
|
+
// SIGTERM handler; repeated interrupt would force an early process exit.
|
|
104
|
+
const onTerm = () => { cancelled = true; };
|
|
105
|
+
process.on('SIGTERM', onTerm);
|
|
106
|
+
const exitReceipt = code => {
|
|
107
|
+
try { writeFileSync(join(runDirectory, 'process-exit.json'), JSON.stringify({ runId, code, phase, at: new Date().toISOString() }) + '\n', { flag: 'wx', mode: 0o600 }); } catch {}
|
|
108
|
+
};
|
|
109
|
+
process.once('exit', exitReceipt);
|
|
110
|
+
try {
|
|
111
|
+
await mkdir(runDirectory, { recursive: true, mode: 0o700 });
|
|
112
|
+
server = createServer(socket => {
|
|
113
|
+
if (socket.remoteAddress !== '127.0.0.1') { socket.destroy(); return; }
|
|
114
|
+
sockets.add(socket); socket.on('close', () => sockets.delete(socket)); socket.on('error', () => {});
|
|
115
|
+
socket.setTimeout(2000, () => socket.destroy()); let input = '', handled = false;
|
|
116
|
+
socket.on('data', chunk => {
|
|
117
|
+
if (handled) return; input += chunk;
|
|
118
|
+
if (Buffer.byteLength(input) > 2048) { socket.destroy(); return; }
|
|
119
|
+
if (!input.includes('\n')) return; handled = true;
|
|
120
|
+
try {
|
|
121
|
+
const request = JSON.parse(input.slice(0, input.indexOf('\n')));
|
|
122
|
+
if (request.schema !== RUNTIME_PROTOCOL || request.runId !== runId || request.dataRoot !== plan.dataRoot || !['status', 'stop', 'open'].includes(request.method) ||
|
|
123
|
+
Object.keys(request).some(key => !['schema','runId','dataRoot','method','token'].includes(key)) ||
|
|
124
|
+
typeof request.token !== 'string' || !/^[a-f0-9]{64}$/.test(request.token) ||
|
|
125
|
+
!timingSafeEqual(Buffer.from(request.token, 'hex'), controlToken)) { socket.destroy(); return; }
|
|
126
|
+
if (request.method === 'open') {
|
|
127
|
+
socket.setTimeout(7000, () => socket.destroy());
|
|
128
|
+
const opening = phase === 'ready' && official && !cancelled ? openRuntimeBrowser(official.ctx)
|
|
129
|
+
: Promise.reject(lifecycleError('runtime_not_ready', 'The runtime is not ready to open its page.'));
|
|
130
|
+
void opening.then(() => socket.end(JSON.stringify({schema:RUNTIME_PROTOCOL,runId,dataRoot:plan.dataRoot,opened:true})+'\n'),
|
|
131
|
+
error => socket.end(JSON.stringify({schema:RUNTIME_PROTOCOL,runId,dataRoot:plan.dataRoot,
|
|
132
|
+
controlError:{code:['unsupported_platform','runtime_not_ready'].includes(error.code) ? error.code : 'browser_open_failed'}})+'\n'));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (request.method === 'status') {
|
|
136
|
+
void status().then(value => { if (!socket.destroyed) socket.end(JSON.stringify(value)+'\n'); }, () => socket.destroy());
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (request.method === 'stop') { cancelled = true; phase = failure ? 'failed' : 'stopping'; }
|
|
140
|
+
socket.end(JSON.stringify(state()) + '\n');
|
|
141
|
+
if (request.method === 'stop') void stop();
|
|
142
|
+
} catch { socket.destroy(); }
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
server.maxConnections = 16;
|
|
146
|
+
await new Promise((listening, reject) => { server.once('error', reject); server.listen({ host:'127.0.0.1', port:0, exclusive:true }, listening); });
|
|
147
|
+
controlAddress = { host:'127.0.0.1', port:server.address().port };
|
|
148
|
+
// Only this 0600 record contains the independent control secret. Public
|
|
149
|
+
// state, logs, errors, and command responses never include it.
|
|
150
|
+
await writeRuntimeRecord(join(runDirectory, 'control.json'), { schema:RUNTIME_PROTOCOL, runId, dataRoot:plan.dataRoot,
|
|
151
|
+
address:controlAddress, token:controlToken.toString('hex') }, { exclusive:true });
|
|
152
|
+
await publish();
|
|
153
|
+
if (!cancelled) {
|
|
154
|
+
await mkdir(plan.nativeHome, { recursive: true, mode: 0o700 });
|
|
155
|
+
const options = await prepareBoot(plan, runDirectory);
|
|
156
|
+
if (!cancelled) {
|
|
157
|
+
const { runProfile } = await loadOfficialHost(plan);
|
|
158
|
+
if (!cancelled) { bootStarted = true; official = await runProfile(options); }
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (official) {
|
|
162
|
+
if (cancelled) await stop();
|
|
163
|
+
else {
|
|
164
|
+
ready = await inspectReady(official.ctx, plan);
|
|
165
|
+
if (cancelled) await stop();
|
|
166
|
+
else { phase = 'ready'; await writeRuntimeRecord(join(runDirectory, 'ready.json'), state(), { exclusive: true }); await publish(); await stopped; await stopping; }
|
|
167
|
+
}
|
|
168
|
+
} else { phase = 'cancelled'; await publish(); }
|
|
169
|
+
} catch (error) {
|
|
170
|
+
failure = errorView(error); phase = 'failed';
|
|
171
|
+
try { official?.ctx.get?.('arcfoldRuntimeGuard')?.fail(error); }
|
|
172
|
+
catch (guardError) { teardownError = errorView(guardError); }
|
|
173
|
+
await writeRuntimeRecord(join(runDirectory, 'failure.json'), { ...failure, runId, bootStarted }, { exclusive: true }).catch(() => {});
|
|
174
|
+
await publish().catch(() => {});
|
|
175
|
+
if (official) try { await stop(); } catch {}
|
|
176
|
+
throw error;
|
|
177
|
+
} finally {
|
|
178
|
+
await writes.catch(() => {});
|
|
179
|
+
for (const socket of sockets) socket.destroy();
|
|
180
|
+
if (server?.listening) await new Promise(done => server.close(done));
|
|
181
|
+
process.off('SIGTERM', onTerm);
|
|
182
|
+
if (!official || officialClosed) await lease.close();
|
|
183
|
+
// An unexpected rejected teardown is not proof that the host stopped.
|
|
184
|
+
// Keep a strong reference and its kernel lock until this private child exits.
|
|
185
|
+
else process.once('exit', () => { void lease.fd; });
|
|
186
|
+
}
|
|
187
|
+
return { runId, phase, bootStarted };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function main() {
|
|
191
|
+
if (process.argv.length !== 4 || process.argv[2] !== '--launch') throw new Error('Private runtime entry requires one launch record.');
|
|
192
|
+
const launch = JSON.parse(await readFile(resolve(process.argv[3]), 'utf8'));
|
|
193
|
+
if (launch.schema !== RUNTIME_PROTOCOL || typeof launch.runId !== 'string' || !/^[a-zA-Z0-9_-]{1,128}$/.test(launch.runId) || launch.runDirectory !== join(launch.plan.runtimeDirectory, 'runs', launch.runId))
|
|
194
|
+
throw new Error('Invalid runtime launch identity.');
|
|
195
|
+
// Set these before root boot helpers or any official module is imported.
|
|
196
|
+
process.chdir(launch.plan.workspace); process.env.DSH_HOME = launch.plan.nativeHome;
|
|
197
|
+
const { loadRuntimePlan, prepareRuntimeBoot } = await import('./runtime-config.mjs');
|
|
198
|
+
const plan = await loadRuntimePlan(launch.plan.configPath);
|
|
199
|
+
if (!isDeepStrictEqual(plan, launch.plan)) throw new Error('Runtime configuration or installation changed after the launch request.');
|
|
200
|
+
await runOwnedRuntime({ ...launch, plan }, { prepareBoot: prepareRuntimeBoot,
|
|
201
|
+
// The profile's Cordis peer becomes resolvable only after runProfile installs
|
|
202
|
+
// official package resolution. Keep imports inside the owned error/teardown path.
|
|
203
|
+
inspectReady: async (...args) => (await import('./runtime-readiness.mjs')).inspectRuntimeReady(...args),
|
|
204
|
+
refreshReady: async (...args) => (await import('./runtime-readiness.mjs')).refreshRuntimeReadiness(...args),
|
|
205
|
+
loadOfficialHost: async () => {
|
|
206
|
+
const require = createRequire(plan.installation.installAnchor);
|
|
207
|
+
return import(pathToFileURL(require.resolve('@deepseek-ai/dsh/profile-boot')).href);
|
|
208
|
+
} });
|
|
209
|
+
}
|
|
210
|
+
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
211
|
+
try { await main(); } catch (error) { console.error(JSON.stringify(errorView(error))); process.exit(1); }
|
|
212
|
+
}
|