mixdog 0.7.16 → 0.7.18

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 (41) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/UNINSTALL.md +7 -4
  4. package/bin/statusline-lib.mjs +29 -6
  5. package/bin/statusline-route.mjs +273 -0
  6. package/bin/statusline.mjs +31 -8
  7. package/commands/model.md +61 -0
  8. package/hooks/session-start.cjs +15 -1
  9. package/native/prebuilt/linux-aarch64/mixdog-shim +0 -0
  10. package/native/prebuilt/linux-x86_64/mixdog-shim +0 -0
  11. package/native/prebuilt/macos-aarch64/mixdog-shim +0 -0
  12. package/native/prebuilt/macos-x86_64/mixdog-shim +0 -0
  13. package/native/prebuilt/windows-x86_64/mixdog-shim.exe +0 -0
  14. package/package.json +1 -1
  15. package/rules/lead/01-general.md +3 -0
  16. package/scripts/gateway-model.mjs +596 -0
  17. package/scripts/lib/gateway-inventory.mjs +178 -0
  18. package/scripts/lib/gateway-settings.mjs +78 -0
  19. package/scripts/run-mcp.mjs +26 -1
  20. package/scripts/statusline-launcher-smoke.mjs +155 -2
  21. package/scripts/uninstall.mjs +44 -7
  22. package/server-main.mjs +252 -11
  23. package/setup/setup.html +1 -1
  24. package/src/agent/index.mjs +96 -5
  25. package/src/agent/orchestrator/bridge-trace.mjs +18 -0
  26. package/src/agent/orchestrator/providers/anthropic-oauth.mjs +4 -1
  27. package/src/agent/orchestrator/providers/anthropic.mjs +6 -2
  28. package/src/agent/orchestrator/session/loop.mjs +145 -4
  29. package/src/agent/orchestrator/session/trim.mjs +1 -1
  30. package/src/agent/orchestrator/tools/builtin/arg-guard.mjs +62 -6
  31. package/src/agent/orchestrator/tools/graph-manifest.json +11 -11
  32. package/src/agent/orchestrator/tools/patch-manifest.json +7 -7
  33. package/src/agent/tool-defs.mjs +10 -3
  34. package/src/channels/lib/runtime-paths.mjs +39 -4
  35. package/src/gateway/claude-current.mjs +255 -0
  36. package/src/gateway/oauth-usage.mjs +598 -0
  37. package/src/gateway/route-meta.mjs +629 -0
  38. package/src/gateway/server.mjs +713 -0
  39. package/src/shared/llm/cost.mjs +1 -1
  40. package/src/shared/seed.mjs +25 -0
  41. package/tools.json +21 -3
@@ -45,7 +45,7 @@ export function isInclusiveProvider(provider) {
45
45
  * @returns {number} USD, rounded to 6 decimal places.
46
46
  */
47
47
  export function computeCostUsd(args) {
48
- const meta = getModelMetadataSync(args?.model);
48
+ const meta = getModelMetadataSync(args?.model, args?.provider);
49
49
  if (!meta) return 0;
50
50
  const inputTokens = args.inputTokens || 0;
51
51
  const outputTokens = args.outputTokens || 0;
@@ -5,9 +5,17 @@ import { DEFAULT_PRESETS, DEFAULT_MAINTENANCE } from '../agent/orchestrator/conf
5
5
  import { writeFileAtomicSync, withFileLockSync } from './atomic-file.mjs';
6
6
  import { backupUserData, hasUserDataInitMarker, markUserDataInitialized, shouldSeedMissingUserData } from './user-data-guard.mjs';
7
7
  import { disableClaudeBuiltinsOnFirstInstall } from './disable-claude-builtins.mjs';
8
+ import { setAnthropicBaseUrl } from '../../scripts/lib/gateway-settings.mjs';
9
+ import { hasAnthropicOAuthCredentials } from '../agent/orchestrator/providers/anthropic-oauth.mjs';
8
10
 
9
11
  const DEFAULTS_DIR = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'defaults');
10
12
 
13
+ // Fresh installs default the local gateway ON, routing Claude Code's main model
14
+ // through the local gateway while inheriting Claude Code's own /model setting.
15
+ // Seed-time port is the gateway default (3468); see
16
+ // DEFAULT_GATEWAY_PORT in src/gateway/server.mjs.
17
+ const SEED_GATEWAY_PORT = 3468;
18
+
11
19
  // Idempotent seed of the unified mixdog-config.json so first-time installs
12
20
  // land with the Config UI already populated with defaults (presets, search
13
21
  // scaffold, memory config) instead of presenting empty lists.
@@ -46,6 +54,8 @@ const SEEDS = {
46
54
  default: 'opus-high',
47
55
  },
48
56
  search: template.search,
57
+ gateway: { mode: 'claude-current' },
58
+ modules: { gateway: { enabled: true } },
49
59
  };
50
60
  return JSON.stringify(composed, null, 2) + '\n';
51
61
  },
@@ -117,6 +127,21 @@ export function ensureDataSeeds(dataDir) {
117
127
  // breaks seeding.
118
128
  if (rel === 'mixdog-config.json') {
119
129
  disableClaudeBuiltinsOnFirstInstall();
130
+ // Route Claude Code's main model through the local
131
+ // gateway on fresh installs. INVARIANT GUARD: only
132
+ // rewrite settings.json when Anthropic OAuth is
133
+ // authenticated — rerouting to an unauthenticated
134
+ // inherited target would break the main model.
135
+ // The gateway+modules sections are seeded regardless;
136
+ // only the settings.json write is gated. Best-effort —
137
+ // never throws out of seeding.
138
+ try {
139
+ if (hasAnthropicOAuthCredentials()) {
140
+ setAnthropicBaseUrl(`http://127.0.0.1:${SEED_GATEWAY_PORT}`);
141
+ }
142
+ } catch (e) {
143
+ process.stderr.write(`[seed] gateway base-url skip: ${e.message}\n`);
144
+ }
120
145
  }
121
146
  } else {
122
147
  skipped.push(rel);
package/tools.json CHANGED
@@ -686,6 +686,24 @@
686
686
  },
687
687
  "module": "agent"
688
688
  },
689
+ {
690
+ "name": "gateway_select_model",
691
+ "title": "Select Gateway Model",
692
+ "annotations": {
693
+ "title": "Select Gateway Model",
694
+ "readOnlyHint": false,
695
+ "destructiveHint": false,
696
+ "idempotentHint": false,
697
+ "openWorldHint": false
698
+ },
699
+ "description": "Interactively choose how the mixdog gateway routes Claude Code's main model. The first choice follows Claude Code's own current /model setting (including effort/fast where available); the rest list enabled providers + models. On selection, writes the gateway target/mode (+ enables the gateway module) — live on the next gateway request, no restart. If the client does not support elicitation, it falls back to listing the models and tells you to run /mixdog:model. Opt-in: only runs when you invoke it.",
700
+ "inputSchema": {
701
+ "type": "object",
702
+ "properties": {},
703
+ "additionalProperties": false
704
+ },
705
+ "module": "agent"
706
+ },
689
707
  {
690
708
  "name": "explore",
691
709
  "title": "Explore",
@@ -741,7 +759,7 @@
741
759
  "openWorldHint": true,
742
760
  "bridgeHidden": true
743
761
  },
744
- "description": "Unified worker session control. type selects the action (default \"spawn\"). spawn: dispatch a detached worker — requires role + message (alias: prompt); optional tag names the session for later send/close (auto \"<role><n>\" if omitted). send: resume a worker by tag (or raw sess_ id) — requires tag + message. To CONTINUE the same task on the same files/context — fix rounds, re-reviews, iterative refinement, or any follow-up — PREFER reusing the original tag over a new spawn: it preserves the worker's transcript + file context + change history, so it is faster, cheaper (the prompt cache stays warm), and more accurate than re-discovering from scratch. The return's respawned flag = false when the live session continued (context kept), true when a closed/cold tag was respawned fresh (context reset). close: stop a worker — requires tag. list: enumerate active worker sessions with stage/staleness — no args (optional role/status filter).",
762
+ "description": "Unified worker session control. type selects the action (default \"spawn\"). spawn: dispatch a detached worker — requires role + prompt; optional tag names the session for later send/close (auto \"<role><n>\" if omitted). send: resume a worker by tag (or raw sess_ id) — requires tag + message. To CONTINUE the same task on the same files/context — fix rounds, re-reviews, iterative refinement, or any follow-up — PREFER reusing the original tag over a new spawn: it preserves the worker's transcript + file context + change history, so it is faster, cheaper (the prompt cache stays warm), and more accurate than re-discovering from scratch. The return's respawned flag = false when the live session continued (context kept), true when a closed/cold tag was respawned fresh (context reset). close: stop a worker — requires tag. list: enumerate active worker sessions with stage/staleness — no args (optional role/status filter).",
745
763
  "inputSchema": {
746
764
  "type": "object",
747
765
  "properties": {
@@ -765,11 +783,11 @@
765
783
  },
766
784
  "message": {
767
785
  "type": "string",
768
- "description": "Brief for spawn / follow-up for send. `prompt` is accepted as an alias on spawn. A spawn brief must state: goal+why, mode (write-code vs research-only), anchor (file:line/symbol/command), and done (output shape + stop condition)."
786
+ "description": "Follow-up text for send. For spawn, use prompt. A spawn brief must state: goal+why, mode (write-code vs research-only), anchor (file:line/symbol/command), and done (output shape + stop condition)."
769
787
  },
770
788
  "prompt": {
771
789
  "type": "string",
772
- "description": "Alias of message for spawn (backward compat)."
790
+ "description": "Brief for spawn. Prefer this over message; must contain non-whitespace content unless file/ref is provided."
773
791
  },
774
792
  "status": {
775
793
  "type": "string",