gnosys 5.12.0 → 5.12.3

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.
Files changed (78) hide show
  1. package/dist/cli.js +48 -7
  2. package/dist/index.js +199 -14
  3. package/dist/lib/addCommand.js +0 -1
  4. package/dist/lib/archive.js +10 -6
  5. package/dist/lib/askCommand.js +1 -1
  6. package/dist/lib/attachCommand.d.ts +17 -0
  7. package/dist/lib/attachCommand.js +66 -0
  8. package/dist/lib/attachments.d.ts +43 -2
  9. package/dist/lib/attachments.js +81 -2
  10. package/dist/lib/chat/choose.js +2 -2
  11. package/dist/lib/clientReadOverlay.js +3 -0
  12. package/dist/lib/config.d.ts +1 -48
  13. package/dist/lib/configCommand.js +2 -2
  14. package/dist/lib/db.d.ts +16 -1
  15. package/dist/lib/db.js +248 -133
  16. package/dist/lib/dbWrite.d.ts +1 -1
  17. package/dist/lib/dearchiveCommand.js +1 -1
  18. package/dist/lib/docxExtract.js +1 -1
  19. package/dist/lib/dream.d.ts +8 -0
  20. package/dist/lib/dream.js +35 -1
  21. package/dist/lib/dreamLogCommand.js +1 -1
  22. package/dist/lib/dreamRunLog.d.ts +1 -1
  23. package/dist/lib/dreamRunLog.js +26 -4
  24. package/dist/lib/embeddings.js +0 -3
  25. package/dist/lib/exportProject.d.ts +3 -2
  26. package/dist/lib/exportProject.js +2 -1
  27. package/dist/lib/federated.js +1 -1
  28. package/dist/lib/ftsQuery.d.ts +25 -0
  29. package/dist/lib/ftsQuery.js +42 -0
  30. package/dist/lib/hybridSearch.d.ts +9 -0
  31. package/dist/lib/hybridSearch.js +14 -0
  32. package/dist/lib/hybridSearchCommand.js +6 -1
  33. package/dist/lib/importProject.js +2 -1
  34. package/dist/lib/llm.js +1 -1
  35. package/dist/lib/lock.d.ts +1 -1
  36. package/dist/lib/lock.js +5 -3
  37. package/dist/lib/migrate.js +0 -1
  38. package/dist/lib/multimodalIngest.js +1 -1
  39. package/dist/lib/platform.d.ts +0 -6
  40. package/dist/lib/platform.js +0 -28
  41. package/dist/lib/readCommand.js +11 -10
  42. package/dist/lib/remoteWizard.d.ts +1 -1
  43. package/dist/lib/remoteWizard.js +4 -4
  44. package/dist/lib/resolver.d.ts +17 -0
  45. package/dist/lib/resolver.js +43 -17
  46. package/dist/lib/rulesGen.d.ts +8 -0
  47. package/dist/lib/rulesGen.js +16 -0
  48. package/dist/lib/search.d.ts +0 -2
  49. package/dist/lib/search.js +33 -27
  50. package/dist/lib/semanticSearchCommand.js +1 -1
  51. package/dist/lib/setup/sections/providers.js +56 -4
  52. package/dist/lib/setup/sections/routing.js +42 -5
  53. package/dist/lib/setup/sections/taskRoutingEditor.d.ts +1 -5
  54. package/dist/lib/setup/sections/taskRoutingEditor.js +0 -10
  55. package/dist/lib/setup/ui/header.js +0 -1
  56. package/dist/lib/setup/ui/status.d.ts +0 -1
  57. package/dist/lib/setup/ui/status.js +0 -2
  58. package/dist/lib/setup.d.ts +0 -15
  59. package/dist/lib/setup.js +13 -158
  60. package/dist/lib/staleCommand.js +2 -2
  61. package/dist/lib/syncClient.d.ts +0 -6
  62. package/dist/lib/syncClient.js +36 -14
  63. package/dist/lib/syncDoctorCommand.js +2 -2
  64. package/dist/lib/syncIngest.d.ts +11 -0
  65. package/dist/lib/syncIngest.js +24 -1
  66. package/dist/lib/syncIngestStartup.js +2 -2
  67. package/dist/lib/syncSnapshot.d.ts +2 -0
  68. package/dist/lib/syncSnapshot.js +4 -0
  69. package/dist/lib/syncStaging.d.ts +0 -2
  70. package/dist/lib/syncStaging.js +0 -2
  71. package/dist/lib/updateCommand.js +1 -1
  72. package/dist/lib/webBuildCommand.js +1 -1
  73. package/dist/lib/webIndex.js +0 -1
  74. package/dist/lib/webIngestCommand.js +1 -1
  75. package/dist/sandbox/client.js +1 -1
  76. package/dist/sandbox/manager.js +1 -14
  77. package/dist/sandbox/server.js +3 -5
  78. package/package.json +5 -2
@@ -79,8 +79,13 @@ export class GnosysResolver {
79
79
  }
80
80
  }
81
81
  catch {
82
- // Store doesn't exist at projectRoot — fall through to empty resolver
82
+ // No project store at projectRoot — still load the env tiers below.
83
83
  }
84
+ // Even when scoped to a projectRoot, load the personal/global/optional
85
+ // tiers so cross-project + global memories stay reachable (write store:
86
+ // "global"/"personal", and read them back from any project). Without this,
87
+ // the universal "always pass projectRoot" guidance silently disabled them.
88
+ await resolver.loadEnvTiers();
84
89
  return resolver;
85
90
  }
86
91
  /**
@@ -104,7 +109,30 @@ export class GnosysResolver {
104
109
  path: projectPath,
105
110
  });
106
111
  }
107
- // 2. Optional stores (GNOSYS_STORES colon-separated)
112
+ // 2-4. Env-configured tiers (optional, personal, global). Shared with
113
+ // resolveForProject so passing a projectRoot does NOT strip the
114
+ // cross-project tiers.
115
+ await this.loadEnvTiers();
116
+ return this.stores;
117
+ }
118
+ /**
119
+ * Load the env-configured store tiers (optional `GNOSYS_STORES`, personal
120
+ * `GNOSYS_PERSONAL`, global `GNOSYS_GLOBAL`) onto `this.stores`.
121
+ *
122
+ * Shared by {@link resolve} and {@link resolveForProject}: a per-tool
123
+ * `projectRoot` call must STILL see personal/global, otherwise cross-project
124
+ * and global memories are unreachable — you couldn't write `store: "global"`
125
+ * / `"personal"` nor read them back from another project. Since every tool
126
+ * is told to always pass `projectRoot`, omitting these here silently
127
+ * disabled the entire cross-project tier system.
128
+ *
129
+ * Global is loaded whenever `GNOSYS_GLOBAL` is set, creating its directory on
130
+ * demand (parity with personal) so a configured-but-empty global store still
131
+ * works. It remains write-only-when-explicitly-targeted: {@link getWriteTarget}
132
+ * never auto-selects it.
133
+ */
134
+ async loadEnvTiers() {
135
+ // Optional stores (GNOSYS_STORES — colon-separated, read-only)
108
136
  const optionalPaths = process.env.GNOSYS_STORES;
109
137
  if (optionalPaths) {
110
138
  const paths = optionalPaths.split(":").filter(Boolean);
@@ -124,7 +152,7 @@ export class GnosysResolver {
124
152
  }
125
153
  }
126
154
  }
127
- // 3. Personal store (GNOSYS_PERSONAL)
155
+ // Personal store (GNOSYS_PERSONAL — writable fallback target)
128
156
  const personalPath = process.env.GNOSYS_PERSONAL;
129
157
  if (personalPath) {
130
158
  const p = path.resolve(personalPath);
@@ -138,24 +166,22 @@ export class GnosysResolver {
138
166
  path: p,
139
167
  });
140
168
  }
141
- // 4. Global store (GNOSYS_GLOBAL)
142
- // Writable, but only when explicitly targeted never auto-selected.
169
+ // Global store (GNOSYS_GLOBAL — writable, but never auto-selected). Loaded
170
+ // whenever set; store.init() creates the dir on demand (parity with
171
+ // personal), so a configured-but-empty GNOSYS_GLOBAL still works.
143
172
  const globalPath = process.env.GNOSYS_GLOBAL;
144
173
  if (globalPath) {
145
174
  const p = path.resolve(globalPath);
146
- if (await this.isValidStore(p)) {
147
- const store = new GnosysStore(p);
148
- await store.init();
149
- this.stores.push({
150
- layer: "global",
151
- label: "global",
152
- store,
153
- writable: true,
154
- path: p,
155
- });
156
- }
175
+ const store = new GnosysStore(p);
176
+ await store.init();
177
+ this.stores.push({
178
+ layer: "global",
179
+ label: "global",
180
+ store,
181
+ writable: true,
182
+ path: p,
183
+ });
157
184
  }
158
- return this.stores;
159
185
  }
160
186
  /**
161
187
  * Get all stores in precedence order.
@@ -47,6 +47,14 @@ export declare function syncRules(centralDb: GnosysDB, projectDir: string, agent
47
47
  * If target is "global", syncs to ~/.claude/CLAUDE.md.
48
48
  */
49
49
  export declare function syncToTarget(centralDb: GnosysDB, projectDir: string, target: string, projectId: string | null): Promise<RulesGenResult[]>;
50
+ /**
51
+ * Remove the GNOSYS block from every known agent rules file in a project —
52
+ * the uninstall counterpart of syncToTarget (v5.12.1: wired into
53
+ * `gnosys cleanup --rules`). Checks every known target rather than only
54
+ * detected ones, so leftovers survive even if the agent dir was removed.
55
+ * Returns the relative paths actually cleaned.
56
+ */
57
+ export declare function removeRulesFromProject(projectDir: string): Promise<string[]>;
50
58
  /**
51
59
  * Remove the GNOSYS block from a rules file (cleanup).
52
60
  */
@@ -254,6 +254,22 @@ export async function syncToTarget(centralDb, projectDir, target, projectId) {
254
254
  }
255
255
  return results;
256
256
  }
257
+ /**
258
+ * Remove the GNOSYS block from every known agent rules file in a project —
259
+ * the uninstall counterpart of syncToTarget (v5.12.1: wired into
260
+ * `gnosys cleanup --rules`). Checks every known target rather than only
261
+ * detected ones, so leftovers survive even if the agent dir was removed.
262
+ * Returns the relative paths actually cleaned.
263
+ */
264
+ export async function removeRulesFromProject(projectDir) {
265
+ const cleaned = [];
266
+ for (const relPath of Object.values(TARGET_PATHS)) {
267
+ const filePath = path.join(projectDir, relPath);
268
+ if (await removeRulesBlock(filePath))
269
+ cleaned.push(relPath);
270
+ }
271
+ return cleaned;
272
+ }
257
273
  /**
258
274
  * Remove the GNOSYS block from a rules file (cleanup).
259
275
  */
@@ -17,8 +17,6 @@ export interface DiscoverResult {
17
17
  }
18
18
  export declare class GnosysSearch {
19
19
  private db;
20
- private storePath;
21
- private available;
22
20
  constructor(storePath: string);
23
21
  private initSchema;
24
22
  /**
@@ -3,7 +3,6 @@
3
3
  * FTS5-based search and discovery across all Gnosys stores.
4
4
  */
5
5
  // Dynamic import — gracefully handles missing native module (dlopen failures)
6
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
6
  let Database = null;
8
7
  try {
9
8
  Database = (await import("better-sqlite3")).default;
@@ -12,13 +11,10 @@ catch {
12
11
  // better-sqlite3 native module not available — search degrades gracefully
13
12
  }
14
13
  import path from "path";
14
+ import { ftsTerms, ftsAndQuery, ftsOrQuery } from "./ftsQuery.js";
15
15
  export class GnosysSearch {
16
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
16
  db = null;
18
- storePath;
19
- available = false;
20
17
  constructor(storePath) {
21
- this.storePath = storePath;
22
18
  if (!Database) {
23
19
  // Native module not available — search features disabled
24
20
  return;
@@ -34,7 +30,6 @@ export class GnosysSearch {
34
30
  this.initSchema();
35
31
  // Smoke-test: insert + delete to confirm journal ops work
36
32
  this.db.exec("CREATE TABLE IF NOT EXISTS _write_test (v INTEGER); INSERT INTO _write_test VALUES (1); DELETE FROM _write_test; DROP TABLE _write_test;");
37
- this.available = true;
38
33
  }
39
34
  catch {
40
35
  // Fallback to in-memory (works everywhere, rebuilt on each start)
@@ -44,7 +39,6 @@ export class GnosysSearch {
44
39
  catch { /* ignore */ }
45
40
  this.db = new Database(":memory:");
46
41
  this.initSchema();
47
- this.available = true;
48
42
  }
49
43
  }
50
44
  initSchema() {
@@ -140,9 +134,8 @@ export class GnosysSearch {
140
134
  search(query, limit = 20) {
141
135
  if (!this.db)
142
136
  return [];
143
- // FTS5 query — escape special characters
144
- const safeQuery = query.replace(/['"]/g, "").trim();
145
- if (!safeQuery)
137
+ const terms = ftsTerms(query);
138
+ if (terms.length === 0)
146
139
  return [];
147
140
  const stmt = this.db.prepare(`
148
141
  SELECT
@@ -156,7 +149,12 @@ export class GnosysSearch {
156
149
  LIMIT ?
157
150
  `);
158
151
  try {
159
- return stmt.all(safeQuery, limit);
152
+ // v5.12.3: AND first (precision), OR retry when AND finds nothing —
153
+ // multi-word queries previously required every term to match.
154
+ const results = stmt.all(ftsAndQuery(terms), limit);
155
+ if (results.length > 0 || terms.length === 1)
156
+ return results;
157
+ return stmt.all(ftsOrQuery(terms), limit);
160
158
  }
161
159
  catch {
162
160
  // If FTS5 query fails, fall back to simple LIKE search
@@ -170,7 +168,7 @@ export class GnosysSearch {
170
168
  WHERE content LIKE ? OR title LIKE ? OR tags LIKE ?
171
169
  LIMIT ?
172
170
  `);
173
- const pattern = `%${safeQuery}%`;
171
+ const pattern = `%${terms.join(" ")}%`;
174
172
  return likeStmt.all(pattern, pattern, pattern, limit);
175
173
  }
176
174
  }
@@ -182,8 +180,8 @@ export class GnosysSearch {
182
180
  discover(query, limit = 20) {
183
181
  if (!this.db)
184
182
  return [];
185
- const safeQuery = query.replace(/['"]/g, "").trim();
186
- if (!safeQuery)
183
+ const terms = ftsTerms(query);
184
+ if (terms.length === 0)
187
185
  return [];
188
186
  // Search primarily on relevance + title + tags (not content body)
189
187
  // FTS5 column filter: {relevance title tags}
@@ -198,24 +196,32 @@ export class GnosysSearch {
198
196
  ORDER BY rank
199
197
  LIMIT ?
200
198
  `);
201
- try {
202
- // Try column-filtered search on relevance/title/tags first
203
- const colQuery = `{relevance title tags} : ${safeQuery}`;
204
- const results = stmt.all(colQuery, limit);
205
- if (results.length > 0)
206
- return results;
207
- // Fall back to full-text search if column filter finds nothing
208
- return stmt.all(safeQuery, limit);
209
- }
210
- catch {
211
- // If FTS5 column filter syntax fails, fall back to full search
199
+ const tryRun = (match) => {
212
200
  try {
213
- return stmt.all(safeQuery, limit);
201
+ return stmt.all(match, limit);
214
202
  }
215
203
  catch {
216
204
  return [];
217
205
  }
218
- }
206
+ };
207
+ // v5.12.3: precision-to-recall ladder. AND on the metadata columns,
208
+ // AND anywhere, then OR retries — multi-word queries previously
209
+ // required every term to match, so long queries returned nothing.
210
+ // Parens scope the column filter to the whole expression (a bare
211
+ // `{cols} : a b` only filtered the first term).
212
+ const colScoped = (expr) => `{relevance title tags} : (${expr})`;
213
+ const andExpr = ftsAndQuery(terms);
214
+ let results = tryRun(colScoped(andExpr));
215
+ if (results.length > 0)
216
+ return results;
217
+ results = tryRun(andExpr);
218
+ if (results.length > 0 || terms.length === 1)
219
+ return results;
220
+ const orExpr = ftsOrQuery(terms);
221
+ results = tryRun(colScoped(orExpr));
222
+ if (results.length > 0)
223
+ return results;
224
+ return tryRun(orExpr);
219
225
  }
220
226
  close() {
221
227
  this.db?.close();
@@ -24,7 +24,7 @@ export async function runSemanticSearchCommand(getResolver, query, opts) {
24
24
  const { GnosysHybridSearch } = await import("./hybridSearch.js");
25
25
  const embeddings = new GnosysEmbeddings(storePath);
26
26
  const hybridSearch = new GnosysHybridSearch(search, embeddings, resolver, storePath);
27
- const results = await hybridSearch.hybridSearch(query, parseInt(opts.limit), "semantic");
27
+ const results = await hybridSearch.hybridSearch(query, parseInt(opts.limit, 10), "semantic");
28
28
  outputResult(!!opts.json, {
29
29
  query,
30
30
  count: results.length,
@@ -129,14 +129,67 @@ async function manageProviderKeys(rl, storePath, cfg, provider) {
129
129
  }
130
130
  console.log("");
131
131
  }
132
+ const defaultAction = slots.length > 0 ? 2 : 0; // when they have a key, default to "make default + model"
132
133
  const choice = await askChoice(rl, "Actions", [
133
134
  slots.length === 0 ? "Add API key (global)" : "Rotate global API key",
134
135
  "Delete one stored key…",
136
+ "Use this provider as default for everything + pick model",
135
137
  "Back",
136
- ], 2);
137
- if (choice === 2) {
138
+ ], defaultAction);
139
+ if (choice === 3) {
138
140
  return changed;
139
141
  }
142
+ if (choice === 2) {
143
+ // "Use this provider as default for everything + pick model"
144
+ // Set it as the global default provider
145
+ const current = await loadConfig(storePath);
146
+ await updateConfig(storePath, {
147
+ llm: {
148
+ ...current.llm,
149
+ defaultProvider: provider,
150
+ },
151
+ // Clear per-task overrides so this truly becomes the single default for everything
152
+ taskModels: {},
153
+ });
154
+ printStatus("ok", `default provider set to ${provider} (all tasks now default to it)`);
155
+ // Immediately let them pick a model for it (using the same picker the main flow uses)
156
+ try {
157
+ const { fetchDynamicModels } = await import("../../setup.js");
158
+ const { pickModel } = await import("../../setup.js");
159
+ const dynamicModels = await fetchDynamicModels();
160
+ const tiers = dynamicModels[provider] ?? [];
161
+ let chosenModel;
162
+ if (tiers.length > 0) {
163
+ chosenModel = await pickModel(rl, provider, dynamicModels, `Default model for ${provider} (used for all tasks)`, current.llm[provider]?.model);
164
+ }
165
+ else {
166
+ chosenModel = await ask(rl, `Enter default model name for ${provider}: `);
167
+ }
168
+ if (chosenModel) {
169
+ const after = await loadConfig(storePath);
170
+ await updateConfig(storePath, {
171
+ llm: {
172
+ ...after.llm,
173
+ [provider]: {
174
+ ...(after.llm[provider] || {}),
175
+ model: chosenModel,
176
+ },
177
+ },
178
+ });
179
+ printStatus("ok", `default model set · ${provider} / ${chosenModel}`);
180
+ printStatus("progress", "all tasks will now default to this provider + model", "use task routing for per-task overrides");
181
+ changed = true;
182
+ }
183
+ else {
184
+ printStatus("progress", "model left unchanged — you can set it from task routing");
185
+ }
186
+ }
187
+ catch (_err) {
188
+ printStatus("warn", "could not pick model right now", "you can set a default model from the main setup → task routing");
189
+ }
190
+ cfg = await loadConfig(storePath);
191
+ continue;
192
+ }
140
193
  if (choice === 0) {
141
194
  const service = apiKeyServiceName(provider, "global");
142
195
  console.log("");
@@ -188,7 +241,6 @@ async function manageProviderKeys(rl, storePath, cfg, provider) {
188
241
  printStatus("fail", "delete failed or entry not found");
189
242
  }
190
243
  }
191
- continue;
192
244
  }
193
245
  }
194
246
  }
@@ -207,7 +259,7 @@ export async function runProvidersSetup(opts) {
207
259
  console.log("");
208
260
  console.log(Header(["gnosys", "setup", "providers"]));
209
261
  console.log("");
210
- console.log(Title("Providers", "API keys live here · pick task routing separately for models per task"));
262
+ console.log(Title("Providers", "API keys live here. Set a global default (or per-task models) from the main setup menu."));
211
263
  console.log("");
212
264
  for (let i = 0; i < menuProviders.length; i++) {
213
265
  const p = menuProviders[i];
@@ -78,14 +78,49 @@ export async function runRoutingSetup(opts) {
78
78
  console.log("");
79
79
  const choice = await askChoice(opts.rl, "What would you like to do?", [
80
80
  "Keep current routing (no changes)",
81
- "Edit tasks — pick by number, then provider + model for each",
82
- "Reset all task overrides to use default",
81
+ "Edit tasks — set the same provider + model for all tasks (simple global default)",
82
+ "Edit tasks pick different providers/models for specific tasks (advanced)",
83
+ "Reset all task overrides to the current default (the one shown in the main setup summary)",
83
84
  ], 0);
84
85
  if (choice === 0) {
85
86
  console.log(`${DIM}No changes.${RESET}`);
86
87
  return false;
87
88
  }
88
- if (choice === 2) {
89
+ if (choice === 1) {
90
+ // Edit tasks — set the same provider + model for all tasks (simple global default)
91
+ console.log("");
92
+ printStatus("progress", "setting a single default for all tasks…");
93
+ try {
94
+ const { fetchDynamicModels } = await import("../../setup.js");
95
+ const { pickModel } = await import("../../setup.js");
96
+ const dynamicModels = await fetchDynamicModels();
97
+ const currentModel = getProviderModel(cfg, provider);
98
+ const chosenModel = await pickModel(opts.rl, provider, dynamicModels, `Default model for ${provider} (used for all tasks + dream)`, currentModel);
99
+ if (chosenModel && chosenModel !== currentModel) {
100
+ const after = await loadConfig(storePath);
101
+ await updateConfig(storePath, {
102
+ llm: {
103
+ ...after.llm,
104
+ [provider]: {
105
+ ...(after.llm[provider] || {}),
106
+ model: chosenModel,
107
+ },
108
+ },
109
+ // Clear per-task overrides so everything truly uses the single default
110
+ taskModels: {},
111
+ });
112
+ printStatus("ok", `default set for everything · ${provider} / ${chosenModel}`);
113
+ }
114
+ else {
115
+ printStatus("ok", "no change to the global default");
116
+ }
117
+ }
118
+ catch (err) {
119
+ printStatus("warn", "could not update default model", String(err));
120
+ }
121
+ return true;
122
+ }
123
+ if (choice === 3) {
89
124
  const { Diff } = await import("../ui/diff.js");
90
125
  const overridesBeingCleared = Object.entries(cfg.taskModels ?? {})
91
126
  .filter(([, v]) => v.provider !== provider || v.model !== model)
@@ -102,16 +137,18 @@ export async function runRoutingSetup(opts) {
102
137
  else {
103
138
  console.log(`${DIM}No overrides to clear — already using default everywhere.${RESET}`);
104
139
  }
105
- const confirmReset = await askYesNo(opts.rl, "Reset all task overrides?", true);
140
+ console.log(`${DIM}The current default is ${provider} / ${model} (set via the main setup "Default provider" or the simple global option above).${RESET}`);
141
+ const confirmReset = await askYesNo(opts.rl, "Reset all task overrides to the current default?", true);
106
142
  if (!confirmReset) {
107
143
  console.log(`${DIM}Cancelled.${RESET}`);
108
144
  return false;
109
145
  }
110
146
  await updateConfig(storePath, { taskModels: {} });
111
- printStatus("ok", "routing reset", "all tasks use default provider/model");
147
+ printStatus("ok", "routing reset", "all tasks now use the global default provider/model");
112
148
  console.log(Footer("press enter to return"));
113
149
  return true;
114
150
  }
151
+ // choice === 2 → advanced per-task editor (the powerful comma-list path)
115
152
  const patch = await runCommaListRoutingEditor(opts.rl, storePath, cfg);
116
153
  if (!patch) {
117
154
  return false;
@@ -2,7 +2,7 @@
2
2
  * Comma-list task routing editor (provider + model per selected task).
3
3
  */
4
4
  import type { Interface as ReadlineInterface } from "readline/promises";
5
- import { type GnosysConfig } from "../../config.js";
5
+ import type { GnosysConfig } from "../../config.js";
6
6
  /**
7
7
  * Let the user pick tasks by number, then provider + model for each.
8
8
  * Returns a patch for taskModels + dream, or null if cancelled.
@@ -11,7 +11,3 @@ export declare function runCommaListRoutingEditor(rl: ReadlineInterface, storePa
11
11
  taskModels: NonNullable<GnosysConfig["taskModels"]>;
12
12
  dream: GnosysConfig["dream"];
13
13
  } | null>;
14
- export declare function applyRoutingPatch(projectDir: string, patch: {
15
- taskModels: NonNullable<GnosysConfig["taskModels"]>;
16
- dream: GnosysConfig["dream"];
17
- }): Promise<GnosysConfig>;
@@ -1,9 +1,7 @@
1
1
  /**
2
2
  * Comma-list task routing editor (provider + model per selected task).
3
3
  */
4
- import { loadConfig, updateConfig, } from "../../config.js";
5
4
  import { ASSIGNABLE_TASK_LIST, fetchDynamicModels, getAssignableRouting, modelForTaskAssignment, parseCommaSeparatedTaskSelection, pickModel, pickProvider, TASK_DESCRIPTIONS, } from "../../setup.js";
6
- import { resolveActiveStorePath } from "../storePath.js";
7
5
  import { safeQuestion } from "../ui/safePrompt.js";
8
6
  import { renderProviderMark } from "../providerGlyphs.js";
9
7
  import { c, color, glyph } from "../ui/tokens.js";
@@ -139,11 +137,3 @@ export async function runCommaListRoutingEditor(rl, storePath, cfg) {
139
137
  }
140
138
  return { taskModels, dream };
141
139
  }
142
- export async function applyRoutingPatch(projectDir, patch) {
143
- const storePath = resolveActiveStorePath(projectDir);
144
- await updateConfig(storePath, {
145
- taskModels: patch.taskModels,
146
- dream: patch.dream,
147
- });
148
- return loadConfig(storePath);
149
- }
@@ -39,7 +39,6 @@ export function Header(crumbs, opts = {}) {
39
39
  }
40
40
  /** Strip ANSI escapes so we can measure printable width. Exported for callers/tests that need printable measurement. */
41
41
  export function stripAnsi(s) {
42
- // eslint-disable-next-line no-control-regex
43
42
  return s.replace(/\x1b\[[0-9;]*m/g, "");
44
43
  }
45
44
  /** Convenience: print header + trailing blank line to stdout. */
@@ -18,4 +18,3 @@ export type StatusKind = "ok" | "warn" | "fail" | "progress";
18
18
  export declare function Status(kind: StatusKind, text: string, meta?: string): string;
19
19
  /** Convenience: print a single status line. */
20
20
  export declare function printStatus(kind: StatusKind, text: string, meta?: string): void;
21
- export { MASTER_UNREACHABLE_MESSAGE, formatMemoriesWaitingToSync, formatFailedToSyncCount, formatOfflinePushStarting, renderClientSyncStatusLines, type ClientSyncStatusInput, } from "../remoteRender.js";
@@ -46,5 +46,3 @@ export function Status(kind, text, meta) {
46
46
  export function printStatus(kind, text, meta) {
47
47
  process.stdout.write(`${Status(kind, text, meta)}\n`);
48
48
  }
49
- // ─── v13 multi-machine sync (re-export render helpers for CLI/MCP callers) ─
50
- export { MASTER_UNREACHABLE_MESSAGE, formatMemoriesWaitingToSync, formatFailedToSyncCount, formatOfflinePushStarting, renderClientSyncStatusLines, } from "../remoteRender.js";
@@ -138,20 +138,6 @@ export declare function runSetup(opts: {
138
138
  directory?: string;
139
139
  nonInteractive?: boolean;
140
140
  }): Promise<SetupResult>;
141
- export interface ProviderOnlySetupOpts {
142
- directory?: string;
143
- rl?: ReadlineInterface;
144
- }
145
- /**
146
- * Update ONLY `llm.defaultProvider` in gnosys.json. Used by the summary
147
- * panel row 1 ("provider") so it stops dragging the user into the full
148
- * model picker — that's row 2's job.
149
- *
150
- * v5.9.4 Bug 4 — before this split, both summary rows routed through
151
- * `runModelsSetup`, leaving no way to swap provider without also choosing
152
- * a new model. Now row 1 picks a provider, row 2 picks a model.
153
- */
154
- export declare function runProviderOnlySetup(opts?: ProviderOnlySetupOpts): Promise<void>;
155
141
  /** Where validated keys are persisted (§3.10). */
156
142
  export type KeyPersistDestination = "secure" | "dotenv" | "none";
157
143
  /**
@@ -252,4 +238,3 @@ export declare function getApiKeyForProvider(provider: string, opts?: {
252
238
  task?: LlmTaskName;
253
239
  directory?: string;
254
240
  }): Promise<string>;
255
- export { getApiKeyForProviderFromConfig } from "./apiKeyVault.js";