dsh-theone 0.3.22 → 0.3.23

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/dist/client.js CHANGED
@@ -620,6 +620,7 @@ function apply(ctx) {
620
620
  await ctx.sessions.using(target, { source: "controllerOperation", signal: lifetime.signal }, async (reference) => {
621
621
  await reference.ready;
622
622
  lifetime.signal.throwIfAborted();
623
+ await fetch("/api/theone/gateway/hold", { method: "POST", signal: lifetime.signal }).catch(() => void 0);
623
624
  const selected = await ctx.modelDirectories.directoryFor(target).select({ provider: "theone", model: "gateway" });
624
625
  if (!selected.ok) throw selected.error;
625
626
  const renamed = await reference.binding.session.rename(t("gateway.title"));
package/dist/index.d.ts CHANGED
@@ -119,6 +119,16 @@ export default class TheOne extends Service {
119
119
  private routerFor;
120
120
  /** Saved settings take effect for the next message; only the background catalog waits for a restart. */
121
121
  private applySettings;
122
+ /**
123
+ * DSH saves any session's model choice as its global default, so main chat choosing TheOne used
124
+ * to make every new ordinary chat a TheOne chat. TheOne must not change the user's settings:
125
+ * before main chat picks its model the default is held, and put back right after.
126
+ */
127
+ private heldDefault?;
128
+ holdDefaultModel(): void;
129
+ restoreDefaultModel(): Promise<void>;
130
+ /** Once: undo the default earlier versions left as TheOne, back to the model in use before it. */
131
+ private repairDefaultModel;
122
132
  /** Capture before Web saves the gateway itself as DSH's new default. */
123
133
  captureDefaultModel(): void;
124
134
  private backingModel;
package/dist/index.js CHANGED
@@ -266,6 +266,7 @@ export default class TheOne extends Service {
266
266
  if (!!config.workerProvider !== !!config.workerModel)
267
267
  throw new Error('Set both workerProvider and workerModel, or neither');
268
268
  this.captureDefaultModel();
269
+ this.repairDefaultModel();
269
270
  this.router = this.routerFor(config.routerMode);
270
271
  if (config.historyCatalog ?? true) {
271
272
  this.catalog = new HistoryCatalog(ctx, this.store, () => this.backingModel(), config.catalogIntervalMs);
@@ -593,6 +594,11 @@ export default class TheOne extends Service {
593
594
  await mkdir(this.gatewayDirectory, { recursive: true });
594
595
  return Response.json({ cwd: this.gatewayDirectory }, { headers: { 'cache-control': 'no-store' } });
595
596
  } }));
597
+ // Main chat is about to pick its model; DSH would save that as the user's default.
598
+ scope.effect(() => connection.fetch.register({ path: '/api/theone/gateway/hold', methods: ['POST'], requestBody: 'buffered', fetch: async () => {
599
+ this.holdDefaultModel();
600
+ return Response.json({ held: true });
601
+ } }));
596
602
  scope.effect(() => connection.fetch.register({ path: '/api/theone/gateway/prepare', methods: ['POST'], requestBody: 'buffered', fetch: async (request) => {
597
603
  let value;
598
604
  try {
@@ -623,6 +629,7 @@ export default class TheOne extends Service {
623
629
  await scope.workspaceRegistry.unarchiveSession(id);
624
630
  const locale = 'locale' in value && typeof value.locale === 'string' ? value.locale.slice(0, 16) : 'en';
625
631
  this.welcomeGateway(id, locale);
632
+ await this.restoreDefaultModel().catch(error => console.warn('TheOne could not restore DSH\'s default model.', error));
626
633
  return Response.json({ prepared: true, workspaceId: null });
627
634
  } }));
628
635
  });
@@ -977,6 +984,34 @@ export default class TheOne extends Service {
977
984
  catch { /* Released during shutdown. */ }
978
985
  this.store.seed(descriptors);
979
986
  }
987
+ /**
988
+ * DSH saves any session's model choice as its global default, so main chat choosing TheOne used
989
+ * to make every new ordinary chat a TheOne chat. TheOne must not change the user's settings:
990
+ * before main chat picks its model the default is held, and put back right after.
991
+ */
992
+ heldDefault;
993
+ holdDefaultModel() {
994
+ const current = this.ctx.agentDefaultModel.currentSelection();
995
+ // A default the user set to TheOne themselves stays as it is.
996
+ this.heldDefault = current.provider && current.provider !== 'theone' ? current : undefined;
997
+ }
998
+ async restoreDefaultModel() {
999
+ const held = this.heldDefault;
1000
+ this.heldDefault = undefined;
1001
+ // Saves run in order, so this lands after the one DSH queued for main chat's selection.
1002
+ if (held)
1003
+ await this.ctx.agentDefaultModel.saveSelection?.(held);
1004
+ }
1005
+ /** Once: undo the default earlier versions left as TheOne, back to the model in use before it. */
1006
+ repairDefaultModel() {
1007
+ const current = this.ctx.agentDefaultModel.currentSelection();
1008
+ if (current.provider !== 'theone')
1009
+ return;
1010
+ const before = this.store.rememberedModel(this.config.gatewayKey);
1011
+ if (!before || !this.store.markOnce('default-model-restored'))
1012
+ return;
1013
+ void this.ctx.agentDefaultModel.saveSelection?.(before)?.catch(error => console.warn('TheOne could not restore DSH\'s default model.', error));
1014
+ }
980
1015
  /** Capture before Web saves the gateway itself as DSH's new default. */
981
1016
  captureDefaultModel() {
982
1017
  const current = this.ctx.agentDefaultModel.currentSelection();
package/dist/store.d.ts CHANGED
@@ -250,6 +250,8 @@ export declare class ContextStore {
250
250
  private purgeFacts;
251
251
  /** Notices the user closed; they are not shown again on any browser. */
252
252
  dismissNotice(id: string, now?: number): void;
253
+ /** True the first time `name` is marked, false ever after: for one-time repairs. */
254
+ markOnce(name: string, now?: number): boolean;
253
255
  dismissedNotices(): Set<string>;
254
256
  /**
255
257
  * Topics kept in the directory but hidden from routing and briefings: every conversation they can
package/dist/store.js CHANGED
@@ -95,6 +95,7 @@ export class ContextStore {
95
95
  context_id TEXT NOT NULL, term TEXT NOT NULL, weight REAL NOT NULL, updated_at INTEGER NOT NULL, PRIMARY KEY(context_id, term)
96
96
  );
97
97
  CREATE TABLE IF NOT EXISTS dismissed_notices (id TEXT PRIMARY KEY, dismissed_at INTEGER NOT NULL);
98
+ CREATE TABLE IF NOT EXISTS plugin_flags (name TEXT PRIMARY KEY, set_at INTEGER NOT NULL);
98
99
  CREATE TABLE IF NOT EXISTS route_details (
99
100
  message_id TEXT PRIMARY KEY, excerpt TEXT NOT NULL, receipt TEXT, corrected_to TEXT, corrected_at INTEGER
100
101
  );
@@ -932,6 +933,10 @@ export class ContextStore {
932
933
  dismissNotice(id, now = Date.now()) {
933
934
  this.db.prepare('INSERT OR IGNORE INTO dismissed_notices VALUES (?, ?)').run(id, now);
934
935
  }
936
+ /** True the first time `name` is marked, false ever after: for one-time repairs. */
937
+ markOnce(name, now = Date.now()) {
938
+ return this.db.prepare('INSERT OR IGNORE INTO plugin_flags VALUES (?, ?)').run(name, now).changes === 1;
939
+ }
935
940
  dismissedNotices() {
936
941
  return new Set(this.db.prepare('SELECT id FROM dismissed_notices').all().map(row => String(row.id)));
937
942
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-theone",
3
- "version": "0.3.22",
3
+ "version": "0.3.23",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "One chat for everything in DeepSeek Harness (DSH): no more hunting for old conversations. Each message goes to the topic it belongs to, with its own context.",