mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-15 02:49:33 +01:00
Merge pull request #755: feat(custom-model): DeepSeek Harness injection through a per-session patch
This commit is contained in:
commit
4c29aedbc5
20 files changed
+866
-151
No files matched your search
+47
-5
@@ -81,7 +81,12 @@ import { folderGrants } from '../folder-listing.js';
|
||||
import { getCli, enabledClis, listClis } from '../config/cli-registry/registry.js';
|
||||
import { isCliEntryInstalled, probeStockCliAvailability } from '../utils/cli-installed-probes.js';
|
||||
import { readCustomModelHosts, resolveCustomModelContextLength } from '../custom-model-hosts.js';
|
||||
import { applyCustomModelInjection, customModelConfigDir, removeConfigDir } from '../custom-model-injection-apply.js';
|
||||
import {
|
||||
applyCustomModelInjection,
|
||||
customModelConfigDir,
|
||||
removeConfigDir,
|
||||
type AppliedCustomModel,
|
||||
} from '../custom-model-injection-apply.js';
|
||||
import type { CustomModelBookkeeping } from '../types/session.js';
|
||||
import { registerGeneratedArtifactAttachment } from '../generated-artifact-attachments.js';
|
||||
import {
|
||||
@@ -1454,7 +1459,7 @@ export class WebServer extends EventEmitter {
|
||||
private async _rebuildCustomModelEnv(
|
||||
session: Session,
|
||||
saved: CustomModelBookkeeping
|
||||
): Promise<Record<string, string> | undefined> {
|
||||
): Promise<AppliedCustomModel | undefined> {
|
||||
const entry = getCli(session.mode);
|
||||
if (!entry) return undefined;
|
||||
const endpoint = (await readCustomModelHosts(getDataDir())).find((h) => h.id === saved.endpointId);
|
||||
@@ -1465,19 +1470,56 @@ export class WebServer extends EventEmitter {
|
||||
return undefined;
|
||||
}
|
||||
try {
|
||||
// Boot recovery omits both `workingDir` (no reason to re-answer a trust dialog that
|
||||
// already fired once) and the session-env real-home lookup: the injected VALUES are
|
||||
// never persisted, so after a real restart the session can no longer carry its
|
||||
// allowlisted `DSH_HOME` either (`getEnvOverridesForPersist()` keeps only
|
||||
// `CLAUDE_CODE_*`/`CLAUDE_CONFIG_DIR`) — the lookup could only ever hit on the first
|
||||
// apply in-process. Real-home resolution therefore falls back to the SERVER's
|
||||
// `DSH_HOME` or the recipe's `realHomeFallback` (~/.dsh).
|
||||
return applyCustomModelInjection(
|
||||
entry,
|
||||
endpoint,
|
||||
saved.modelId,
|
||||
session.id,
|
||||
resolveCustomModelContextLength(endpoint, saved.modelId)
|
||||
)?.envOverrides;
|
||||
);
|
||||
} catch (err) {
|
||||
console.warn('[WebServer] Failed to rebuild custom-model env on recovery:', err);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore one persisted custom-model selection (both boot-recovery paths). The rebuilt
|
||||
* bookkeeping must come from the CURRENT recipe, not from the saved record: this is the
|
||||
* first feature where a shipped recipe changed KIND (deepseek: env redirect -> per-session
|
||||
* patch home), so a selection saved by an old build restores with e.g. no `configDir`
|
||||
* while the new recipe writes one — and clearing it later could then never delete the
|
||||
* generated dir. `envKeys` is the UNION of saved and applied keys: the tmux session may
|
||||
* still carry `setenv`s from both, and a clear has to unset every one.
|
||||
*/
|
||||
private async _restoreCustomModel(session: Session, saved: CustomModelBookkeeping): Promise<void> {
|
||||
const applied = await this._rebuildCustomModelEnv(session, saved);
|
||||
if (!applied) {
|
||||
// Endpoint gone or CLI unregistered: restore the bookkeeping exactly as saved, which
|
||||
// is what a later clear needs.
|
||||
session.setCustomModel(saved);
|
||||
return;
|
||||
}
|
||||
session.setCustomModel(
|
||||
{
|
||||
...saved,
|
||||
// Prefer the current recipe's dir; keep the saved one when the recipe writes none,
|
||||
// so a clear can still delete a directory an older recipe created.
|
||||
configDir: applied.configDir ?? saved.configDir,
|
||||
launchModel: applied.launchModel,
|
||||
envKeys: [...new Set([...saved.envKeys, ...applied.envKeys])],
|
||||
},
|
||||
applied.envOverrides
|
||||
);
|
||||
}
|
||||
|
||||
/** Persists full session state including respawn config to state.json */
|
||||
private _persistSessionStateNow(session: Session): void {
|
||||
// See session-manager.updateSessionState: __envOverrides is an internal disk-only
|
||||
@@ -3604,7 +3646,7 @@ export class WebServer extends EventEmitter {
|
||||
// bookkeeping survives a restart and the values are re-derived here.
|
||||
const savedCustomModel = (saved as { __customModel?: CustomModelBookkeeping }).__customModel;
|
||||
if (savedCustomModel) {
|
||||
session.setCustomModel(savedCustomModel, await this._rebuildCustomModelEnv(session, savedCustomModel));
|
||||
await this._restoreCustomModel(session, savedCustomModel);
|
||||
}
|
||||
if (saved.niceEnabled !== undefined || saved.niceValue !== undefined) {
|
||||
session.setNice({ enabled: saved.niceEnabled, niceValue: saved.niceValue });
|
||||
@@ -3906,7 +3948,7 @@ export class WebServer extends EventEmitter {
|
||||
// the isolated config dir; an endpoint that has since been deleted still gets
|
||||
// the bookkeeping restored, which is what a later clear needs to unset.
|
||||
if (savedCustomModel) {
|
||||
session.setCustomModel(savedCustomModel, await this._rebuildCustomModelEnv(session, savedCustomModel));
|
||||
await this._restoreCustomModel(session, savedCustomModel);
|
||||
}
|
||||
|
||||
// Update session name if it was a "Restored:" placeholder or doesn't match saved name
|
||||
|
||||
Reference in new issue
Block a user