@khoavu882/doflow 2.0.0-beta.3 → 2.0.0-beta.4

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 (167) hide show
  1. package/bin/doflow.js +2 -2
  2. package/core/.claude-plugin/plugin.json +1 -1
  3. package/core/.codex-plugin/plugin.json +1 -1
  4. package/core/.plugin/plugin.json +1 -1
  5. package/core/registry/storage.json +87 -83
  6. package/core/registry/verification.json +1 -1
  7. package/core/shared/scripts/doflow/bash/render-puml.sh +2 -2
  8. package/core/shared/skills/do-execute-plan/references/scaffold.md +2 -2
  9. package/package.json +4 -2
  10. package/src/adapters/antigravity/{index.ts → index.js} +60 -60
  11. package/src/adapters/claude/{index.ts → index.js} +48 -48
  12. package/src/adapters/claude/{mcp.ts → mcp.js} +16 -16
  13. package/src/adapters/codex/{agents.ts → agents.js} +24 -24
  14. package/src/adapters/codex/{config.ts → config.js} +49 -49
  15. package/src/adapters/codex/{hooks.ts → hooks.js} +23 -23
  16. package/src/adapters/codex/{index.ts → index.js} +98 -98
  17. package/src/adapters/codex/{mcp.ts → mcp.js} +38 -38
  18. package/src/adapters/codex/{native-projection.ts → native-projection.js} +5 -5
  19. package/src/adapters/copilot/{index.ts → index.js} +42 -42
  20. package/src/adapters/{copy-tree.ts → copy-tree.js} +70 -70
  21. package/src/adapters/gemini/{hooks.ts → hooks.js} +24 -24
  22. package/src/adapters/gemini/{index.ts → index.js} +41 -41
  23. package/src/adapters/{hook-commands.ts → hook-commands.js} +8 -8
  24. package/src/adapters/{index.ts → index.js} +13 -13
  25. package/src/adapters/kiro/{index.ts → index.js} +34 -34
  26. package/src/adapters/{mcp-entries.ts → mcp-entries.js} +55 -55
  27. package/src/adapters/opencode/{index.ts → index.js} +52 -52
  28. package/src/adapters/pi/{index.ts → index.js} +30 -30
  29. package/src/adapters/pi/{json-members.ts → json-members.js} +23 -23
  30. package/src/adapters/pi/{mcp.ts → mcp.js} +70 -70
  31. package/src/adapters/{resolve-source.ts → resolve-source.js} +1 -1
  32. package/src/cli/commands/{install.ts → install.js} +24 -24
  33. package/src/cli/commands/{list-backups.ts → list-backups.js} +4 -4
  34. package/src/cli/commands/{reconcile.ts → reconcile.js} +19 -19
  35. package/src/cli/commands/{remove.ts → remove.js} +10 -10
  36. package/src/cli/commands/{rollback.ts → rollback.js} +17 -17
  37. package/src/cli/commands/{self-update.ts → self-update.js} +3 -3
  38. package/src/cli/commands/{status.ts → status.js} +24 -24
  39. package/src/cli/commands/{tools.ts → tools.js} +16 -16
  40. package/src/cli/commands/{update.ts → update.js} +19 -19
  41. package/src/cli/{index.ts → index.js} +26 -26
  42. package/src/cli/{runtime-commands.ts → runtime-commands.js} +48 -48
  43. package/src/cli/{shared.ts → shared.js} +40 -40
  44. package/src/helper/{bash-helper.ts → bash-helper.js} +7 -7
  45. package/src/helper/{git.ts → git.js} +2 -2
  46. package/src/helper/{guardrails.ts → guardrails.js} +10 -10
  47. package/src/helper/{harness-paths.ts → harness-paths.js} +24 -24
  48. package/src/helper/{marker-merge.ts → marker-merge.js} +4 -4
  49. package/src/helper/{prompt.ts → prompt.js} +5 -5
  50. package/src/helper/{repo-root.ts → repo-root.js} +2 -2
  51. package/src/helper/{settings-merge.ts → settings-merge.js} +27 -27
  52. package/src/helper/{settings-scope.ts → settings-scope.js} +3 -3
  53. package/src/helper/{toml.ts → toml.js} +48 -48
  54. package/src/install/{backup-set.ts → backup-set.js} +16 -16
  55. package/src/install/{backup.ts → backup.js} +65 -65
  56. package/src/install/{context.ts → context.js} +15 -15
  57. package/src/install/{manifest.ts → manifest.js} +27 -27
  58. package/src/install/{mcp.ts → mcp.js} +30 -30
  59. package/src/install/{paths.ts → paths.js} +15 -15
  60. package/src/install/{targets.ts → targets.js} +10 -10
  61. package/src/install/{tool-lifecycle.ts → tool-lifecycle.js} +20 -20
  62. package/src/lifecycle/{bash-availability.ts → bash-availability.js} +1 -1
  63. package/src/lifecycle/{index.ts → index.js} +140 -140
  64. package/src/lifecycle/{mcp-index.ts → mcp-index.js} +1 -1
  65. package/src/lifecycle/{policies.ts → policies.js} +11 -11
  66. package/src/lifecycle/{view.ts → view.js} +28 -28
  67. package/src/registry/{index.ts → index.js} +60 -60
  68. package/src/release/build-package.js +91 -0
  69. package/src/release/changelog-section.js +70 -0
  70. package/src/release/{sync-plugin-versions.ts → sync-plugin-versions.js} +4 -4
  71. package/src/runtime/advice/{cli.ts → cli.js} +31 -31
  72. package/src/runtime/advice/{client.ts → client.js} +44 -44
  73. package/src/runtime/advice/{config.ts → config.js} +16 -16
  74. package/src/runtime/advice/{doctor.ts → doctor.js} +32 -32
  75. package/src/runtime/advice/{endpoint-guard.ts → endpoint-guard.js} +20 -20
  76. package/src/runtime/advice/{kinds.ts → kinds.js} +16 -16
  77. package/src/runtime/advice/providers/{ollama-systemone.ts → ollama-systemone.js} +21 -21
  78. package/src/runtime/advice/{record.ts → record.js} +19 -19
  79. package/src/runtime/advice/{registry.ts → registry.js} +16 -16
  80. package/src/runtime/advice/{strength.ts → strength.js} +7 -7
  81. package/src/runtime/{brief-tools.ts → brief-tools.js} +50 -50
  82. package/src/runtime/{c4-project.ts → c4-project.js} +27 -27
  83. package/src/runtime/{capability-router.ts → capability-router.js} +39 -39
  84. package/src/runtime/{checkouts.ts → checkouts.js} +21 -21
  85. package/src/runtime/{claims.ts → claims.js} +30 -30
  86. package/src/runtime/{cli-result.ts → cli-result.js} +4 -4
  87. package/src/runtime/{cli.ts → cli.js} +37 -37
  88. package/src/runtime/{command-detect.ts → command-detect.js} +47 -47
  89. package/src/runtime/{context-pack.ts → context-pack.js} +20 -20
  90. package/src/runtime/{decision-register.ts → decision-register.js} +67 -67
  91. package/src/runtime/{evidence-ledger.ts → evidence-ledger.js} +25 -25
  92. package/src/runtime/failure/{capture.ts → capture.js} +29 -29
  93. package/src/runtime/failure/{classifier.ts → classifier.js} +4 -4
  94. package/src/runtime/failure/{cli.ts → cli.js} +30 -30
  95. package/src/runtime/failure/{home.ts → home.js} +6 -6
  96. package/src/runtime/failure/{store.ts → store.js} +32 -32
  97. package/src/runtime/{feature-resolve.ts → feature-resolve.js} +6 -6
  98. package/src/runtime/{freshness.ts → freshness.js} +15 -15
  99. package/src/runtime/{health.ts → health.js} +72 -72
  100. package/src/runtime/{history-compactor.ts → history-compactor.js} +25 -25
  101. package/src/runtime/{implementation-gate.ts → implementation-gate.js} +30 -30
  102. package/src/runtime/inventory/{coverage.ts → coverage.js} +10 -10
  103. package/src/runtime/inventory/{identity.ts → identity.js} +2 -2
  104. package/src/runtime/inventory/{index.ts → index.js} +36 -36
  105. package/src/runtime/inventory/{precedence.ts → precedence.js} +2 -2
  106. package/src/runtime/inventory/{read-scopes.ts → read-scopes.js} +9 -9
  107. package/src/runtime/inventory/{siblings.ts → siblings.js} +15 -15
  108. package/src/runtime/knowledge/{chunker.ts → chunker.js} +12 -12
  109. package/src/runtime/knowledge/{hybrid.ts → hybrid.js} +17 -17
  110. package/src/runtime/knowledge/{index-store.ts → index-store.js} +23 -23
  111. package/src/runtime/knowledge/{retrieval.ts → retrieval.js} +27 -27
  112. package/src/runtime/{leak-scan.ts → leak-scan.js} +12 -12
  113. package/src/runtime/lifecycle/{cli.ts → cli.js} +32 -32
  114. package/src/runtime/lifecycle/{event-store.ts → event-store.js} +48 -48
  115. package/src/runtime/lifecycle/{fold.ts → fold.js} +41 -41
  116. package/src/runtime/lifecycle/{followup.ts → followup.js} +54 -54
  117. package/src/runtime/lifecycle/{goal.ts → goal.js} +50 -50
  118. package/src/runtime/lifecycle/{intent-writer.ts → intent-writer.js} +5 -5
  119. package/src/runtime/lifecycle/{overview.ts → overview.js} +47 -47
  120. package/src/runtime/lifecycle/{release.ts → release.js} +29 -29
  121. package/src/runtime/lifecycle/{report-store.ts → report-store.js} +25 -25
  122. package/src/runtime/lifecycle/{retention.ts → retention.js} +37 -37
  123. package/src/runtime/lifecycle/{root.ts → root.js} +9 -9
  124. package/src/runtime/lifecycle/{status.ts → status.js} +64 -64
  125. package/src/runtime/lifecycle/{store-upkeep.ts → store-upkeep.js} +46 -46
  126. package/src/runtime/{locator-resolve.ts → locator-resolve.js} +7 -7
  127. package/src/runtime/{mask.ts → mask.js} +22 -22
  128. package/src/runtime/{mcp-consultations.ts → mcp-consultations.js} +54 -54
  129. package/src/runtime/{mcp-reach.ts → mcp-reach.js} +24 -24
  130. package/src/runtime/{model-router.ts → model-router.js} +20 -20
  131. package/src/runtime/{outcome.ts → outcome.js} +27 -27
  132. package/src/runtime/{reach.ts → reach.js} +21 -21
  133. package/src/runtime/{readiness-record.ts → readiness-record.js} +12 -12
  134. package/src/runtime/{readiness.ts → readiness.js} +35 -35
  135. package/src/runtime/{recovery.ts → recovery.js} +15 -15
  136. package/src/runtime/{research-request.ts → research-request.js} +34 -34
  137. package/src/runtime/{retrieval-plan.ts → retrieval-plan.js} +40 -40
  138. package/src/runtime/scaffold/{artifacts.ts → artifacts.js} +19 -19
  139. package/src/runtime/scaffold/{fingerprint.ts → fingerprint.js} +3 -3
  140. package/src/runtime/scaffold/{generate.ts → generate.js} +109 -109
  141. package/src/runtime/scaffold/{languages.ts → languages.js} +34 -34
  142. package/src/runtime/storage/{cli.ts → cli.js} +9 -9
  143. package/src/runtime/storage/{engine.ts → engine.js} +37 -37
  144. package/src/runtime/storage/{registry.ts → registry.js} +19 -19
  145. package/src/runtime/storage/{roots.ts → roots.js} +8 -8
  146. package/src/runtime/storage/{rules.ts → rules.js} +26 -26
  147. package/src/runtime/storage/{upkeep.ts → upkeep.js} +35 -35
  148. package/src/runtime/storage/{work-status.ts → work-status.js} +39 -39
  149. package/src/runtime/{task-attempts.ts → task-attempts.js} +61 -61
  150. package/src/runtime/{task-classifier.ts → task-classifier.js} +34 -34
  151. package/src/runtime/{task-scope.ts → task-scope.js} +13 -13
  152. package/src/runtime/{task-state.ts → task-state.js} +15 -15
  153. package/src/runtime/trace/{indicators.ts → indicators.js} +22 -22
  154. package/src/runtime/trace/{ledger.ts → ledger.js} +42 -42
  155. package/src/runtime/trace/{render.ts → render.js} +7 -7
  156. package/src/runtime/trace/{views.ts → views.js} +40 -40
  157. package/src/runtime/verification/{contract-runner.ts → contract-runner.js} +23 -23
  158. package/src/runtime/verification/{engine.ts → engine.js} +143 -143
  159. package/src/runtime/verification/{registry.ts → registry.js} +6 -6
  160. package/src/runtime/verification/{scope-bound.ts → scope-bound.js} +50 -50
  161. package/src/runtime/verification/{test-selection.ts → test-selection.js} +28 -28
  162. package/src/runtime/{workflow-engine.ts → workflow-engine.js} +50 -50
  163. package/src/runtime/{workflow-orchestrator.ts → workflow-orchestrator.js} +91 -91
  164. package/src/runtime/{worktree.ts → worktree.js} +31 -31
  165. package/src/state/{index.ts → index.js} +26 -26
  166. package/src/state/{lockfile.ts → lockfile.js} +20 -20
  167. package/src/state/{run-lock.ts → run-lock.js} +44 -44
@@ -4,17 +4,17 @@
4
4
 
5
5
  const fs = require('node:fs');
6
6
  const path = require('node:path');
7
- const { resolveRoots } = require('../storage/roots.ts');
7
+ const { resolveRoots } = require('../storage/roots.js');
8
8
 
9
9
  const SETTING_FILE = 'decision-model.json';
10
10
  const PROJECT_NOTE = 'a project cannot enable the decision model or choose its endpoint';
11
11
  const KNOWN_KEYS = new Set(['schema', 'enabled', 'provider', 'endpoint', 'model']);
12
12
 
13
- function isObject(value: any): boolean {
13
+ function isObject(value ) {
14
14
  return value !== null && typeof value === 'object' && !Array.isArray(value);
15
15
  }
16
16
 
17
- function offResult(reason: string, decidedBy: any, notes: string[] = [], setting: any = {}): any {
17
+ function offResult(reason , decidedBy , notes = [], setting = {}) {
18
18
  return {
19
19
  state: 'off', reason,
20
20
  provider: setting.provider ?? null,
@@ -26,24 +26,24 @@ function offResult(reason: string, decidedBy: any, notes: string[] = [], setting
26
26
  };
27
27
  }
28
28
 
29
- function readJson(file: string | null, fsImpl: any): { exists: boolean; value?: any; error?: any } {
29
+ function readJson(file , fsImpl ) {
30
30
  if (!file) return { exists: false };
31
31
  try {
32
32
  return { exists: true, value: JSON.parse(fsImpl.readFileSync(file, 'utf8')) };
33
- } catch (error: any) {
33
+ } catch (error ) {
34
34
  if (error?.code === 'ENOENT') return { exists: false };
35
35
  return { exists: true, error };
36
36
  }
37
37
  }
38
38
 
39
- function parseUserSetting(value: any, adviceRegistry: any): any {
39
+ function parseUserSetting(value , adviceRegistry ) {
40
40
  if (!isObject(value)) return { error: 'user setting must be a JSON object' };
41
41
  if (value.schema !== 1) return { error: 'user setting schema must be 1' };
42
42
  if (typeof value.enabled !== 'boolean') return { error: 'user setting enabled must be a boolean' };
43
43
 
44
44
  const providers = Array.isArray(adviceRegistry?.providers) ? adviceRegistry.providers : [];
45
45
  const providerId = value.provider === undefined ? 'ollama' : value.provider;
46
- const provider = providers.find((item: any) => item?.id === providerId);
46
+ const provider = providers.find((item ) => item?.id === providerId);
47
47
  if (typeof providerId !== 'string' || !provider) return { error: `user setting provider '${providerId}' is not in advice.json providers` };
48
48
 
49
49
  let endpoint = provider.defaultEndpoint;
@@ -70,13 +70,13 @@ function parseUserSetting(value: any, adviceRegistry: any): any {
70
70
  };
71
71
  }
72
72
 
73
- function parseProjectSetting(value: any): any {
73
+ function parseProjectSetting(value ) {
74
74
  if (!isObject(value)) return { error: 'project setting must be a JSON object' };
75
75
  if (value.schema !== 1) return { error: 'project setting schema must be 1' };
76
76
  if (value.enabled !== undefined && typeof value.enabled !== 'boolean') return { error: 'project setting enabled must be a boolean' };
77
77
  if (value.model !== undefined && (typeof value.model !== 'string' || !value.model.trim())) return { error: 'project setting model must be a non-empty string' };
78
78
 
79
- const notes: string[] = [];
79
+ const notes = [];
80
80
  if (value.enabled === true) notes.push(`project key 'enabled' ignored: ${PROJECT_NOTE}`);
81
81
  for (const key of ['endpoint', 'provider']) {
82
82
  if (Object.hasOwn(value, key)) notes.push(`project key '${key}' ignored: ${PROJECT_NOTE}`);
@@ -95,12 +95,12 @@ function resolveSetting({
95
95
  global = false,
96
96
  env = process.env,
97
97
  fsImpl = fs,
98
- }: any = {}): any {
99
- const notes: string[] = [];
98
+ } = {}) {
99
+ const notes = [];
100
100
  let resolvedRoots = roots;
101
101
  try {
102
102
  if (!resolvedRoots) resolvedRoots = resolveRoots({ registry: storageRegistry, projectRoot, global, env });
103
- } catch (error: any) {
103
+ } catch (error ) {
104
104
  return offResult('config-invalid', { user: null, project: null }, [`storage roots could not be resolved: ${error.message}`]);
105
105
  }
106
106
  const userFile = resolvedRoots?.['config-home'] ? path.join(resolvedRoots['config-home'], SETTING_FILE) : null;
@@ -149,19 +149,19 @@ function resolveSetting({
149
149
  };
150
150
  }
151
151
 
152
- function writeSetting({ file, setting, level = 'user', force = false, fsImpl = fs }: any = {}): any {
152
+ function writeSetting({ file, setting, level = 'user', force = false, fsImpl = fs } = {}) {
153
153
  if (typeof file !== 'string' || !file || !isObject(setting)) {
154
154
  return { ok: false, reason: 'config-invalid', detail: 'file and setting object are required' };
155
155
  }
156
156
  const directory = path.dirname(file);
157
- let existing: any = {};
157
+ let existing = {};
158
158
  try {
159
159
  if (fsImpl.existsSync(file)) {
160
160
  try {
161
161
  const parsed = JSON.parse(fsImpl.readFileSync(file, 'utf8'));
162
162
  if (!isObject(parsed)) throw new Error('setting must be a JSON object');
163
163
  existing = parsed;
164
- } catch (error: any) {
164
+ } catch (error ) {
165
165
  if (!force) return { ok: false, reason: 'config-invalid', detail: `${file}: ${error.message}` };
166
166
  }
167
167
  }
@@ -181,7 +181,7 @@ function writeSetting({ file, setting, level = 'user', force = false, fsImpl = f
181
181
  try { if (fsImpl.existsSync(temporary)) fsImpl.unlinkSync(temporary); } catch { /* keep the primary result */ }
182
182
  }
183
183
  return { ok: true, file, setting: output };
184
- } catch (error: any) {
184
+ } catch (error ) {
185
185
  return { ok: false, reason: 'config-invalid', detail: `${file}: ${error.message}` };
186
186
  }
187
187
  }
@@ -3,64 +3,64 @@
3
3
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
4
4
 
5
5
  const fs = require('node:fs');
6
- const { resolveRoots } = require('../storage/roots.ts');
7
- const { loadStorageRegistry } = require('../storage/registry.ts');
8
- const { loadAdviceRegistry } = require('./registry.ts');
9
- const { resolveSetting } = require('./config.ts');
10
- const { createAdviceClient } = require('./client.ts');
11
- const { readWindow } = require('./record.ts');
12
- const { REPO_ROOT } = require('../../helper/repo-root.ts');
6
+ const { resolveRoots } = require('../storage/roots.js');
7
+ const { loadStorageRegistry } = require('../storage/registry.js');
8
+ const { loadAdviceRegistry } = require('./registry.js');
9
+ const { resolveSetting } = require('./config.js');
10
+ const { createAdviceClient } = require('./client.js');
11
+ const { readWindow } = require('./record.js');
12
+ const { REPO_ROOT } = require('../../helper/repo-root.js');
13
13
 
14
14
  const WINDOW_DAYS = 90;
15
- const DONE_PHRASES: Record<string, string> = Object.freeze({
15
+ const DONE_PHRASES = Object.freeze({
16
16
  'classify-verdict': 'accepted class',
17
17
  'brief-record': 'tier the brief named',
18
18
  caller: 'value the caller recorded',
19
19
  });
20
20
 
21
- function selectedStore(roots: any) {
21
+ function selectedStore(roots ) {
22
22
  if (roots?.['project-state']) return { id: 'advice-picks-project', root: roots['project-state'] };
23
23
  return { id: 'advice-picks-user', root: roots?.['user-state'] || null };
24
24
  }
25
25
 
26
- function latestCall(records: any) {
27
- const calls = records.filter(({ record }: any) => record.type === 'pick' || record.type === 'miss');
26
+ function latestCall(records ) {
27
+ const calls = records.filter(({ record } ) => record.type === 'pick' || record.type === 'miss');
28
28
  if (!calls.length) return null;
29
- const record = calls.reduce((latest: any, entry: any) => !latest || String(entry.record.at).localeCompare(String(latest.record.at)) >= 0
29
+ const record = calls.reduce((latest , entry ) => !latest || String(entry.record.at).localeCompare(String(latest.record.at)) >= 0
30
30
  ? entry : latest).record;
31
31
  return record.type === 'pick'
32
32
  ? { at: record.at, status: 'answered', reason: null }
33
33
  : { at: record.at, status: 'unavailable', reason: record.reason || null };
34
34
  }
35
35
 
36
- function agreementRows(registry: any, records: any) {
37
- const picks = records.filter(({ record }: any) => record.type === 'pick');
36
+ function agreementRows(registry , records ) {
37
+ const picks = records.filter(({ record } ) => record.type === 'pick');
38
38
  const outcomes = new Map();
39
39
  for (const { record } of records) {
40
40
  if (record.type !== 'outcome' || typeof record.pickId !== 'string') continue;
41
41
  const current = outcomes.get(record.pickId);
42
42
  if (!current || String(record.at).localeCompare(String(current.at)) >= 0) outcomes.set(record.pickId, record);
43
43
  }
44
- const misses = records.filter(({ record }: any) => record.type === 'miss');
45
- const ids = [...(registry.kinds || []).map((kind: any) => kind.id)];
46
- if (picks.some(({ record }: any) => record.kind === 'adhoc')) ids.push('adhoc');
44
+ const misses = records.filter(({ record } ) => record.type === 'miss');
45
+ const ids = [...(registry.kinds || []).map((kind ) => kind.id)];
46
+ if (picks.some(({ record } ) => record.kind === 'adhoc')) ids.push('adhoc');
47
47
  return ids.map((kind) => {
48
- const kindPicks = picks.filter(({ record }: any) => record.kind === kind);
49
- const completed = kindPicks.map(({ record }: any) => ({ pick: record.pick, outcome: outcomes.get(record.pickId) }))
50
- .filter(({ outcome }: any) => outcome);
51
- const sources = [...new Set(completed.map(({ outcome }: any) => outcome.source).filter((source: any) => DONE_PHRASES[source]))];
48
+ const kindPicks = picks.filter(({ record } ) => record.kind === kind);
49
+ const completed = kindPicks.map(({ record } ) => ({ pick: record.pick, outcome: outcomes.get(record.pickId) }))
50
+ .filter(({ outcome } ) => outcome);
51
+ const sources = [...new Set(completed.map(({ outcome } ) => outcome.source).filter((source ) => DONE_PHRASES[source]))];
52
52
  return {
53
53
  kind,
54
54
  picks: kindPicks.length,
55
55
  withOutcome: completed.length,
56
- matched: completed.filter(({ pick, outcome }: any) => outcome.actual === pick).length,
57
- unavailable: misses.filter(({ record }: any) => record.kind === kind).length,
56
+ matched: completed.filter(({ pick, outcome } ) => outcome.actual === pick).length,
57
+ unavailable: misses.filter(({ record } ) => record.kind === kind).length,
58
58
  outcomeSources: sources,
59
59
  };
60
60
  });
61
61
  }
62
62
 
63
- function offReason(setting: any) {
63
+ function offReason(setting ) {
64
64
  if (setting.reason === 'not-configured') return 'not configured';
65
65
  if (setting.reason === 'config-invalid') return `unreadable setting in ${setting.decidedBy?.user || setting.decidedBy?.project || 'decision-model.json'}`;
66
66
  if (setting.reason === 'project-disabled') return `switched off in ${setting.decidedBy?.project}`;
@@ -69,7 +69,7 @@ function offReason(setting: any) {
69
69
 
70
70
  async function buildAdviceDoctor({ repoRoot = REPO_ROOT, projectRoot = process.cwd(), env = process.env, fsImpl = fs,
71
71
  adviceRegistry: suppliedRegistry, storageRegistry: suppliedStorage, client: suppliedClient, lookup, httpModule, httpsModule,
72
- probeTimeoutMs, doctorBudgetMs, now = () => new Date() }: any = {}) {
72
+ probeTimeoutMs, doctorBudgetMs, now = () => new Date() } = {}) {
73
73
  try {
74
74
  const root = repoRoot;
75
75
  const loaded = suppliedRegistry ? { ok: true, registry: suppliedRegistry } : loadAdviceRegistry({ repoRoot: root, fsImpl });
@@ -97,15 +97,15 @@ async function buildAdviceDoctor({ repoRoot = REPO_ROOT, projectRoot = process.c
97
97
  doctorBudgetMs: doctorBudgetMs ?? registry.doctorBudgetMs };
98
98
  const client = suppliedClient || createAdviceClient({ adviceRegistry: effectiveRegistry, roots, fsImpl, lookup, httpModule, httpsModule });
99
99
  inspection = await client.inspect({ endpoint: setting.endpoint, model: setting.model, provider: setting.provider,
100
- file: setting.decidedBy?.user, minVersion: registry.providers.find((p: any) => p.id === setting.provider)?.minVersion,
100
+ file: setting.decidedBy?.user, minVersion: registry.providers.find((p ) => p.id === setting.provider)?.minVersion,
101
101
  timeoutMs: probeTimeoutMs ?? registry.probeTimeoutMs });
102
- const provider = registry.providers.find((p: any) => p.id === setting.provider) || {};
102
+ const provider = registry.providers.find((p ) => p.id === setting.provider) || {};
103
103
  decisionModel = {
104
104
  setting: { state: 'on', reason: null, decidedBy: setting.decidedBy, modelFrom: setting.modelFrom, notes: setting.notes || [] },
105
105
  endpoint: { url: setting.endpoint, state: inspection.endpoint.state, version: inspection.endpoint.version,
106
106
  minVersion: provider.minVersion || null, versionOk: inspection.endpoint.versionOk, message: inspection.endpoint.message },
107
107
  model: { name: setting.model, installed: inspection.model.installed, decisionCapable: inspection.model.decisionCapable },
108
- decisionModels: inspection.models.filter((model: any) => model.capabilities?.includes(provider.capability)).map((model: any) => model.name),
108
+ decisionModels: inspection.models.filter((model ) => model.capabilities?.includes(provider.capability)).map((model ) => model.name),
109
109
  lastCall: latestCall(window.records),
110
110
  };
111
111
  } else {
@@ -117,7 +117,7 @@ async function buildAdviceDoctor({ repoRoot = REPO_ROOT, projectRoot = process.c
117
117
  };
118
118
  }
119
119
  return { decisionModel, advice, _inspection: inspection, _offReason: setting.state === 'off' ? offReason(setting) : null };
120
- } catch (error: any) {
120
+ } catch (error ) {
121
121
  return { decisionModel: { setting: { state: 'off', reason: 'config-invalid', decidedBy: { user: null, project: null }, modelFrom: null, notes: [error.message] },
122
122
  endpoint: { url: null, state: 'not-checked', version: null, minVersion: null, versionOk: false, message: null },
123
123
  model: { name: null, installed: false, decisionCapable: false }, decisionModels: [], lastCall: null },
@@ -125,7 +125,7 @@ async function buildAdviceDoctor({ repoRoot = REPO_ROOT, projectRoot = process.c
125
125
  }
126
126
  }
127
127
 
128
- function printAdviceDoctor(report: any) {
128
+ function printAdviceDoctor(report ) {
129
129
  const decision = report.decisionModel;
130
130
  const inspection = report._inspection;
131
131
  console.log('\n[Decision Model] — advisory, never blocking');
@@ -156,10 +156,10 @@ function printAdviceDoctor(report: any) {
156
156
  }
157
157
 
158
158
  console.log('\n[Advice Agreement] — picks kept for 90 days in this project; agreement with what was done, not correctness');
159
- if (!report.advice.kinds.some((row: any) => row.picks) && !report.advice.unreadableLines) console.log(' No picks recorded here.');
159
+ if (!report.advice.kinds.some((row ) => row.picks) && !report.advice.unreadableLines) console.log(' No picks recorded here.');
160
160
  for (const row of report.advice.kinds) {
161
161
  if (!row.picks) { console.log(` ${row.kind.padEnd(17)}no picks recorded`); continue; }
162
- const phrases = row.outcomeSources.map((source: any) => DONE_PHRASES[source]).filter(Boolean);
162
+ const phrases = row.outcomeSources.map((source ) => DONE_PHRASES[source]).filter(Boolean);
163
163
  const done = phrases.length ? ` (done = ${phrases.join(' or ')})` : '';
164
164
  console.log(` ${row.kind.padEnd(17)}${row.picks} picks, ${row.withOutcome} with a known outcome, matched ${row.matched} of ${row.withOutcome}${done}; ${row.unavailable} calls unavailable`);
165
165
  }
@@ -4,17 +4,17 @@
4
4
 
5
5
  const dns = require('node:dns');
6
6
 
7
- function displayEndpoint(value: any): string {
7
+ function displayEndpoint(value ) {
8
8
  return typeof value === 'string' ? value : String(value ?? '');
9
9
  }
10
10
 
11
- function ipv4Octets(address: any): number[] | null {
11
+ function ipv4Octets(address ) {
12
12
  if (typeof address !== 'string' || !/^\d{1,3}(?:\.\d{1,3}){3}$/.test(address)) return null;
13
13
  const octets = address.split('.').map(Number);
14
14
  return octets.every((octet) => octet >= 0 && octet <= 255) ? octets : null;
15
15
  }
16
16
 
17
- function ipv6Words(address: any): number[] | null {
17
+ function ipv6Words(address ) {
18
18
  if (typeof address !== 'string' || !address.includes(':')) return null;
19
19
  let value = address.toLowerCase();
20
20
  if (value.includes('.')) {
@@ -27,7 +27,7 @@ function ipv6Words(address: any): number[] | null {
27
27
  }
28
28
  const doubleColon = value.indexOf('::');
29
29
  if (doubleColon !== -1 && value.indexOf('::', doubleColon + 2) !== -1) return null;
30
- let words: string[];
30
+ let words ;
31
31
  if (doubleColon === -1) {
32
32
  words = value.split(':');
33
33
  if (words.length !== 8) return null;
@@ -42,7 +42,7 @@ function ipv6Words(address: any): number[] | null {
42
42
  return words.map((word) => Number.parseInt(word, 16));
43
43
  }
44
44
 
45
- function isLoopback(address: any): boolean {
45
+ function isLoopback(address ) {
46
46
  const octets = ipv4Octets(address);
47
47
  if (octets) return octets[0] === 127;
48
48
  const words = ipv6Words(address);
@@ -53,25 +53,25 @@ function isLoopback(address: any): boolean {
53
53
  return (words[6] >> 8) === 127;
54
54
  }
55
55
 
56
- function literalFamily(address: any): 4 | 6 {
56
+ function literalFamily(address ) {
57
57
  return ipv4Octets(address) ? 4 : 6;
58
58
  }
59
59
 
60
- function isLiteralIp(host: any): boolean {
60
+ function isLiteralIp(host ) {
61
61
  return Boolean(ipv4Octets(host) || ipv6Words(host));
62
62
  }
63
63
 
64
- function refuse(value: any, file?: string): { ok: false; message: string } {
64
+ function refuse(value , file ) {
65
65
  return {
66
66
  ok: false,
67
67
  message: `decision model: endpoint ${value} refused: only loopback addresses are allowed (127.0.0.0/8, ::1); set in ${file || 'provider default'}`,
68
68
  };
69
69
  }
70
70
 
71
- function lookupAll(host: string, lookup: any, timeoutMs?: number): Promise<any> {
71
+ function lookupAll(host , lookup , timeoutMs ) {
72
72
  return new Promise((resolve, reject) => {
73
73
  let settled = false;
74
- const finish = (error: any, addresses?: any) => {
74
+ const finish = (error , addresses ) => {
75
75
  if (settled) return;
76
76
  settled = true;
77
77
  clearTimeout(timer);
@@ -80,10 +80,10 @@ function lookupAll(host: string, lookup: any, timeoutMs?: number): Promise<any>
80
80
  };
81
81
  const timer = Number.isFinite(timeoutMs) ? setTimeout(() => {
82
82
  finish(Object.assign(new Error('decision model DNS validation timed out'), { code: 'ADVICE_TIMEOUT' }));
83
- }, Math.max(0, timeoutMs as number)) : undefined;
83
+ }, Math.max(0, timeoutMs )) : undefined;
84
84
  try {
85
85
  const returned = lookup(host, { all: true, verbatim: true }, finish);
86
- if (returned && typeof returned.then === 'function') returned.then((addresses: any) => finish(null, addresses), finish);
86
+ if (returned && typeof returned.then === 'function') returned.then((addresses ) => finish(null, addresses), finish);
87
87
  else if (Array.isArray(returned)) finish(null, returned);
88
88
  } catch (error) {
89
89
  finish(error);
@@ -91,8 +91,8 @@ function lookupAll(host: string, lookup: any, timeoutMs?: number): Promise<any>
91
91
  });
92
92
  }
93
93
 
94
- function pinnedLookup(address: string, family: number) {
95
- return (hostname: string, options: any, callback?: any) => {
94
+ function pinnedLookup(address , family ) {
95
+ return (hostname , options , callback ) => {
96
96
  if (typeof options === 'function') {
97
97
  callback = options;
98
98
  options = {};
@@ -103,9 +103,9 @@ function pinnedLookup(address: string, family: number) {
103
103
  };
104
104
  }
105
105
 
106
- async function checkEndpoint(value: any, { lookup = dns.lookup, file, timeoutMs }: any = {}): Promise<any> {
106
+ async function checkEndpoint(value , { lookup = dns.lookup, file, timeoutMs } = {}) {
107
107
  const display = displayEndpoint(value);
108
- let url: any;
108
+ let url ;
109
109
  try { url = new URL(display); } catch { return refuse(display, file); }
110
110
  if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) return refuse(display, file);
111
111
 
@@ -116,17 +116,17 @@ async function checkEndpoint(value: any, { lookup = dns.lookup, file, timeoutMs
116
116
  return { ok: true, address: host, family, pinnedLookup: pinnedLookup(host, family) };
117
117
  }
118
118
 
119
- let addresses: any;
120
- try { addresses = await lookupAll(host, lookup, timeoutMs); } catch (error: any) {
119
+ let addresses ;
120
+ try { addresses = await lookupAll(host, lookup, timeoutMs); } catch (error ) {
121
121
  if (error?.code === 'ADVICE_TIMEOUT') return { ok: false, reason: 'timeout', message: error.message };
122
122
  return refuse(display, file);
123
123
  }
124
124
  if (!Array.isArray(addresses) || addresses.length === 0) return refuse(display, file);
125
- const checked: any[] = addresses.map((entry: any) => {
125
+ const checked = addresses.map((entry ) => {
126
126
  if (!entry || typeof entry.address !== 'string') return null;
127
127
  return { address: entry.address, family: literalFamily(entry.address) };
128
128
  });
129
- if (checked.some((entry: any) => !entry || !isLoopback(entry.address))) return refuse(display, file);
129
+ if (checked.some((entry ) => !entry || !isLoopback(entry.address))) return refuse(display, file);
130
130
  const first = checked[0];
131
131
  return { ok: true, address: first.address, family: first.family, pinnedLookup: pinnedLookup(first.address, first.family) };
132
132
  }
@@ -2,20 +2,20 @@
2
2
 
3
3
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
4
4
 
5
- function isObject(value: any): boolean {
5
+ function isObject(value ) {
6
6
  return value !== null && typeof value === 'object' && !Array.isArray(value);
7
7
  }
8
8
 
9
- function invalid(detail: string, reason: string = 'config-invalid'): { ok: false; reason: string; detail: string } {
9
+ function invalid(detail , reason = 'config-invalid') {
10
10
  return { ok: false, reason, detail };
11
11
  }
12
12
 
13
- function optionCount(question: any): number {
13
+ function optionCount(question ) {
14
14
  if (question.type === 'score') return Array.isArray(question.criteria) ? question.criteria.length : 0;
15
15
  return question.type === 'choice' ? Object.keys(question.options || {}).length : 2;
16
16
  }
17
17
 
18
- function checkOptionRange(count: number, limits: any, owner: string): { ok: false; reason: string; detail: string } | null {
18
+ function checkOptionRange(count , limits , owner ) {
19
19
  if (!Number.isInteger(limits?.minOptions) || !Number.isInteger(limits?.maxOptions)) {
20
20
  return invalid(`${owner} cannot be built: invalid limits in core/registry/advice.json`);
21
21
  }
@@ -28,16 +28,16 @@ function checkOptionRange(count: number, limits: any, owner: string): { ok: fals
28
28
  return null;
29
29
  }
30
30
 
31
- function criteriaFrom(source: string, sources: any): Record<string, any> | null {
32
- let entries: [string, any][];
31
+ function criteriaFrom(source , sources ) {
32
+ let entries ;
33
33
  if (source === 'workflows.classes') {
34
34
  const classes = sources?.workflows?.classes;
35
35
  if (!isObject(classes)) return null;
36
- entries = Object.entries(classes).map(([id, item]: [string, any]) => [id, item?.description]);
36
+ entries = Object.entries(classes).map(([id, item] ) => [id, item?.description]);
37
37
  } else if (source === 'verification.riskLevels') {
38
38
  const levels = sources?.verification?.riskLevels;
39
39
  if (!isObject(levels)) return null;
40
- entries = Object.entries(levels).map(([id, item]: [string, any]) => [id, item?.description]);
40
+ entries = Object.entries(levels).map(([id, item] ) => [id, item?.description]);
41
41
  } else {
42
42
  return null;
43
43
  }
@@ -45,21 +45,21 @@ function criteriaFrom(source: string, sources: any): Record<string, any> | null
45
45
  return Object.fromEntries(entries);
46
46
  }
47
47
 
48
- function materializeKind(kindId: string, { adviceRegistry, sources = {}, server }: any = {}): any {
48
+ function materializeKind(kindId , { adviceRegistry, sources = {}, server } = {}) {
49
49
  const kinds = adviceRegistry?.kinds;
50
50
  if (!Array.isArray(kinds)) return invalid('kinds are missing from core/registry/advice.json');
51
- const kind = kinds.find((entry: any) => entry?.id === kindId);
51
+ const kind = kinds.find((entry ) => entry?.id === kindId);
52
52
  if (!kind) return invalid(`unknown kind '${kindId}'`, 'usage-error');
53
53
 
54
54
  const serverSource = kind.criteriaFrom === 'mcp.servers[].trigger';
55
55
  if (server !== undefined && !serverSource) return invalid('--server is valid only for mcp-need', 'usage-error');
56
56
 
57
- let question: any;
57
+ let question ;
58
58
  if (serverSource) {
59
59
  if (typeof server !== 'string' || !server.trim()) return invalid('--server is required for mcp-need', 'usage-error');
60
60
  const servers = sources?.mcp?.servers;
61
61
  if (!Array.isArray(servers)) return invalid('mcp.servers is missing from core/registry/mcp.json');
62
- const match = servers.find((entry: any) => entry?.id === server);
62
+ const match = servers.find((entry ) => entry?.id === server);
63
63
  if (!match) return invalid(`server '${server}' is not present in core/registry/mcp.json`, 'usage-error');
64
64
  if (typeof match.trigger !== 'string' || !match.trigger.trim()) return invalid(`mcp.servers.${server}.trigger is missing`);
65
65
  question = { name: kind.id, type: 'yesno', instructions: match.trigger, no: kind.no, yes: kind.yes };
@@ -82,7 +82,7 @@ function materializeKind(kindId: string, { adviceRegistry, sources = {}, server
82
82
  return { ok: true, kind: kind.id, question };
83
83
  }
84
84
 
85
- function validateQuestionSet(questionSet: any, { adviceRegistry }: any = {}): any {
85
+ function validateQuestionSet(questionSet , { adviceRegistry } = {}) {
86
86
  const limits = adviceRegistry?.limits;
87
87
  if (!isObject(limits)) return invalid('limits are missing from core/registry/advice.json');
88
88
  if (!isObject(questionSet)) return invalid('question set must be an object (core/registry/advice.json limits.minQuestions)');
@@ -95,7 +95,7 @@ function validateQuestionSet(questionSet: any, { adviceRegistry }: any = {}): an
95
95
  return invalid(`question count exceeds ${limits.maxQuestions} (core/registry/advice.json limits.maxQuestions)`);
96
96
  }
97
97
 
98
- let namePattern: RegExp;
98
+ let namePattern ;
99
99
  try { namePattern = new RegExp(limits.questionName); } catch {
100
100
  return invalid('questionName does not compile (core/registry/advice.json limits.questionName)');
101
101
  }
@@ -128,7 +128,7 @@ function validateQuestionSet(questionSet: any, { adviceRegistry }: any = {}): an
128
128
  if (!Array.isArray(question.criteria)) return invalid(`${prefix}.criteria must be an array of criterion strings (core/registry/advice.json limits.minOptions)`);
129
129
  const rangeError = checkOptionRange(question.criteria.length, limits, `${prefix}.criteria`);
130
130
  if (rangeError) return rangeError;
131
- if (question.criteria.some((criterion: any) => typeof criterion !== 'string' || !criterion.trim())) {
131
+ if (question.criteria.some((criterion ) => typeof criterion !== 'string' || !criterion.trim())) {
132
132
  return invalid(`${prefix}.criteria must be non-empty strings (core/registry/advice.json limits.minOptions)`);
133
133
  }
134
134
  if (new Set(question.criteria).size !== question.criteria.length) {
@@ -141,7 +141,7 @@ function validateQuestionSet(questionSet: any, { adviceRegistry }: any = {}): an
141
141
  return { ok: true, questionSet };
142
142
  }
143
143
 
144
- function validateStaticAnswer(question: any, value: any): { ok: boolean; reason?: string; detail?: string } {
144
+ function validateStaticAnswer(question , value ) {
145
145
  if (value === undefined || value === null) return { ok: true };
146
146
  const validOptions = question?.type === 'choice'
147
147
  ? Object.keys(question.options || {})
@@ -7,7 +7,7 @@ const VERSION_PATH = '/api/version';
7
7
  const TAGS_PATH = '/api/tags';
8
8
  const SHOW_PATH = '/api/show';
9
9
 
10
- function parseJson(bodyText: any): any {
10
+ function parseJson(bodyText ) {
11
11
  if (typeof bodyText !== 'string') return null;
12
12
  try {
13
13
  const value = JSON.parse(bodyText);
@@ -17,12 +17,12 @@ function parseJson(bodyText: any): any {
17
17
  }
18
18
  }
19
19
 
20
- function failure(reason: string, detail: string): { ok: false; reason: string; detail: string } {
20
+ function failure(reason , detail ) {
21
21
  return { ok: false, reason, detail };
22
22
  }
23
23
 
24
- function buildRequest(questionSet: any, { model }: any = {}): { method: string; path: string; body: any } {
25
- const questions = Object.fromEntries(questionSet.questions.map((question: any) => {
24
+ function buildRequest(questionSet , { model } = {}) {
25
+ const questions = Object.fromEntries(questionSet.questions.map((question ) => {
26
26
  if (question.type === 'choice') {
27
27
  return [question.name, {
28
28
  type: 'choice',
@@ -52,19 +52,19 @@ function buildRequest(questionSet: any, { model }: any = {}): { method: string;
52
52
 
53
53
  const SCORE_TOLERANCE = 1e-6;
54
54
 
55
- function inUnit(value: any): boolean {
55
+ function inUnit(value ) {
56
56
  return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= 1;
57
57
  }
58
58
 
59
- function parseScore(question: any, value: any): any {
60
- const bad = (detail: string) => failure('malformed-reply', detail);
59
+ function parseScore(question , value ) {
60
+ const bad = (detail ) => failure('malformed-reply', detail);
61
61
  const { criteria, name } = question;
62
62
  const last = criteria.length - 1;
63
63
  if (value.type !== 'score') return bad(`answer for ${name} is not a score`);
64
- const keys: string[] = criteria.map((criterion: any, index: number) => String(index));
65
- const exact = (object: any) => object && typeof object === 'object' && !Array.isArray(object)
64
+ const keys = criteria.map((criterion , index ) => String(index));
65
+ const exact = (object ) => object && typeof object === 'object' && !Array.isArray(object)
66
66
  && Object.keys(object).length === keys.length && keys.every((key) => Object.hasOwn(object, key));
67
- if (!exact(value.legend) || keys.some((key: string, index: number) => value.legend[key] !== criteria[index])) {
67
+ if (!exact(value.legend) || keys.some((key , index ) => value.legend[key] !== criteria[index])) {
68
68
  return bad(`legend for ${name} does not match its criteria`);
69
69
  }
70
70
  if (!exact(value.probabilities)) return bad(`probabilities for ${name} do not match its criteria`);
@@ -89,7 +89,7 @@ function parseScore(question: any, value: any): any {
89
89
  };
90
90
  }
91
91
 
92
- function parseReply(status: number, bodyText: any, questionSet: any): any {
92
+ function parseReply(status , bodyText , questionSet ) {
93
93
  if (status === 400) {
94
94
  const parsed = parseJson(bodyText);
95
95
  return failure('endpoint-rejected', typeof parsed?.error === 'string' ? parsed.error : 'Ollama rejected the request');
@@ -108,7 +108,7 @@ function parseReply(status: number, bodyText: any, questionSet: any): any {
108
108
  return failure('malformed-reply', 'reply has no answers object');
109
109
  }
110
110
 
111
- const answers: any[] = [];
111
+ const answers = [];
112
112
  for (const question of questionSet.questions) {
113
113
  const value = parsed.answers[question.name];
114
114
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
@@ -159,7 +159,7 @@ function versionRequest() {
159
159
  return { method: 'GET', path: VERSION_PATH };
160
160
  }
161
161
 
162
- function parseVersion(status: number, bodyText: any): { version: string } | null {
162
+ function parseVersion(status , bodyText ) {
163
163
  const parsed = status === 200 ? parseJson(bodyText) : null;
164
164
  return typeof parsed?.version === 'string' && parsed.version.trim() ? { version: parsed.version.trim() } : null;
165
165
  }
@@ -168,31 +168,31 @@ function listRequest() {
168
168
  return { method: 'GET', path: TAGS_PATH };
169
169
  }
170
170
 
171
- function parseList(status: number, bodyText: any): any[] {
171
+ function parseList(status , bodyText ) {
172
172
  const parsed = status === 200 ? parseJson(bodyText) : null;
173
173
  if (!Array.isArray(parsed?.models)) return [];
174
174
  return parsed.models
175
- .filter((model: any) => model && typeof model.name === 'string' && model.name.trim())
176
- .map((model: any) => ({
175
+ .filter((model ) => model && typeof model.name === 'string' && model.name.trim())
176
+ .map((model ) => ({
177
177
  name: model.name,
178
- capabilities: Array.isArray(model.capabilities) && model.capabilities.every((capability: any) => typeof capability === 'string')
178
+ capabilities: Array.isArray(model.capabilities) && model.capabilities.every((capability ) => typeof capability === 'string')
179
179
  ? model.capabilities : null,
180
180
  }));
181
181
  }
182
182
 
183
- function showRequest(name: string): { method: string; path: string; body: any } {
183
+ function showRequest(name ) {
184
184
  return { method: 'POST', path: SHOW_PATH, body: { model: name } };
185
185
  }
186
186
 
187
- function parseShow(status: number, bodyText: any): { capabilities: string[] } | null {
187
+ function parseShow(status , bodyText ) {
188
188
  const parsed = status === 200 ? parseJson(bodyText) : null;
189
- return Array.isArray(parsed?.capabilities) && parsed.capabilities.every((capability: any) => typeof capability === 'string')
189
+ return Array.isArray(parsed?.capabilities) && parsed.capabilities.every((capability ) => typeof capability === 'string')
190
190
  ? { capabilities: parsed.capabilities }
191
191
  : null;
192
192
  }
193
193
 
194
194
  /** A configured name without a tag also matches Ollama's listed `<name>:latest` form. */
195
- function modelMatches(configured: any, listed: any): boolean {
195
+ function modelMatches(configured , listed ) {
196
196
  return configured === listed || (typeof configured === 'string' && !configured.includes(':') && listed === `${configured}:latest`);
197
197
  }
198
198