@phuetz/code-buddy 1.0.0 → 1.2.0
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/README.md +160 -164
- package/dist/agent/autonomous/agentic-coding-contract.d.ts +6 -6
- package/dist/agent/codebuddy-agent.d.ts +1 -1
- package/dist/agent/codebuddy-agent.js +101 -13
- package/dist/agent/execution/agent-executor.js +122 -12
- package/dist/agent/execution/tool-dependency-graph.js +7 -0
- package/dist/agent/execution/tool-hooks.d.ts +6 -0
- package/dist/agent/execution/tool-hooks.js +13 -5
- package/dist/agent/execution/tool-selection-strategy.d.ts +11 -2
- package/dist/agent/execution/tool-selection-strategy.js +67 -10
- package/dist/agent/extended-thinking.d.ts +8 -0
- package/dist/agent/extended-thinking.js +27 -0
- package/dist/agent/hermes-browser-backends.js +151 -11
- package/dist/agent/hermes-claw-migrate.d.ts +59 -0
- package/dist/agent/hermes-claw-migrate.js +427 -26
- package/dist/agent/hermes-parity-manifest.js +78 -71
- package/dist/agent/hermes-runtime-lifecycle.d.ts +67 -0
- package/dist/agent/hermes-runtime-lifecycle.js +468 -0
- package/dist/agent/lesson-auto-proposer.js +10 -0
- package/dist/agent/middleware/index.d.ts +1 -0
- package/dist/agent/middleware/index.js +1 -0
- package/dist/agent/middleware/session-duration.d.ts +36 -0
- package/dist/agent/middleware/session-duration.js +78 -0
- package/dist/agent/middleware/visual-validation-middleware.d.ts +17 -0
- package/dist/agent/middleware/visual-validation-middleware.js +67 -0
- package/dist/agent/model-benchmark.d.ts +77 -0
- package/dist/agent/model-benchmark.js +309 -0
- package/dist/agent/model-tier.d.ts +14 -0
- package/dist/agent/model-tier.js +71 -0
- package/dist/agent/multi-agent/agents/orchestrator-agent.js +17 -6
- package/dist/agent/multi-agent/multi-agent-system.js +3 -1
- package/dist/agent/multi-agent/session-fleet-bridge.d.ts +2 -0
- package/dist/agent/multi-agent/session-fleet-bridge.js +9 -1
- package/dist/agent/multi-agent/session-tools.js +22 -5
- package/dist/agent/reasoning/mcts.js +20 -6
- package/dist/agent/session-end-flush.d.ts +71 -0
- package/dist/agent/session-end-flush.js +233 -0
- package/dist/agent/streaming/streaming-handler.d.ts +7 -0
- package/dist/agent/streaming/streaming-handler.js +8 -1
- package/dist/agent/tool-executor.js +1 -0
- package/dist/agent/tool-handler.d.ts +5 -0
- package/dist/agent/tool-handler.js +130 -4
- package/dist/browser-automation/browser-operator-executor.js +15 -0
- package/dist/browser-automation/browser-use-runner.d.ts +96 -0
- package/dist/browser-automation/browser-use-runner.js +492 -0
- package/dist/browser-automation/camofox-runner.d.ts +107 -0
- package/dist/browser-automation/camofox-runner.js +287 -0
- package/dist/channels/dingtalk/index.js +3 -0
- package/dist/channels/discord/client.d.ts +9 -0
- package/dist/channels/discord/client.js +12 -0
- package/dist/channels/feishu/index.d.ts +167 -1
- package/dist/channels/feishu/index.js +432 -7
- package/dist/channels/gateway-lifecycle.d.ts +132 -0
- package/dist/channels/gateway-lifecycle.js +219 -0
- package/dist/channels/google-chat/index.d.ts +5 -1
- package/dist/channels/google-chat/index.js +5 -1
- package/dist/channels/imessage/index.d.ts +14 -0
- package/dist/channels/imessage/index.js +64 -17
- package/dist/channels/index.d.ts +4 -0
- package/dist/channels/index.js +4 -0
- package/dist/channels/irc/index.d.ts +73 -3
- package/dist/channels/irc/index.js +446 -11
- package/dist/channels/line/index.js +3 -0
- package/dist/channels/mattermost/index.d.ts +51 -4
- package/dist/channels/mattermost/index.js +303 -20
- package/dist/channels/nextcloud-talk/index.d.ts +89 -8
- package/dist/channels/nextcloud-talk/index.js +367 -16
- package/dist/channels/nostr/index.d.ts +121 -1
- package/dist/channels/nostr/index.js +396 -8
- package/dist/channels/ntfy/index.js +3 -0
- package/dist/channels/qq/index.js +3 -0
- package/dist/channels/slash-parity.d.ts +117 -0
- package/dist/channels/slash-parity.js +185 -0
- package/dist/channels/synology-chat/index.js +3 -0
- package/dist/channels/teams/index.d.ts +3 -0
- package/dist/channels/teams/index.js +3 -0
- package/dist/channels/telegram/client.d.ts +9 -0
- package/dist/channels/telegram/client.js +12 -0
- package/dist/channels/twilio-voice/index.js +3 -0
- package/dist/channels/webchat/index.d.ts +7 -1
- package/dist/channels/webchat/index.js +7 -1
- package/dist/channels/wecom/index.js +3 -0
- package/dist/channels/weixin/index.js +3 -0
- package/dist/channels/zalo/index.js +3 -0
- package/dist/cli/config-loader.js +1 -1
- package/dist/codebuddy/client.d.ts +30 -1
- package/dist/codebuddy/client.js +167 -20
- package/dist/codebuddy/providers/provider-chatgpt-responses.d.ts +5 -0
- package/dist/codebuddy/providers/provider-chatgpt-responses.js +1 -0
- package/dist/codebuddy/providers/provider-gemini-native.js +1 -1
- package/dist/codebuddy/providers/provider-openai-compat.d.ts +5 -0
- package/dist/codebuddy/providers/provider-openai-compat.js +82 -2
- package/dist/codebuddy/tool-definitions/computer-control-tools.js +32 -2
- package/dist/codebuddy/tool-definitions/core-tools.js +3 -3
- package/dist/codebuddy/tool-definitions/index.d.ts +2 -1
- package/dist/codebuddy/tool-definitions/index.js +2 -1
- package/dist/codebuddy/tool-definitions/multimodal-tools.d.ts +1 -0
- package/dist/codebuddy/tool-definitions/multimodal-tools.js +44 -1
- package/dist/codebuddy/tool-definitions/windows-tools.d.ts +2 -0
- package/dist/codebuddy/tool-definitions/windows-tools.js +34 -0
- package/dist/codebuddy/tools.d.ts +1 -1
- package/dist/codebuddy/tools.js +27 -24
- package/dist/commands/cli/hermes-commands.js +108 -0
- package/dist/commands/cli/native-engine-commands.js +107 -3
- package/dist/commands/cli/utility-commands.js +45 -0
- package/dist/commands/enhanced-command-handler.js +5 -0
- package/dist/commands/goal-cli.d.ts +71 -0
- package/dist/commands/goal-cli.js +280 -0
- package/dist/commands/handlers/goal-handler.d.ts +34 -0
- package/dist/commands/handlers/goal-handler.js +155 -0
- package/dist/commands/handlers/index.d.ts +1 -0
- package/dist/commands/handlers/index.js +2 -0
- package/dist/commands/handlers/infra-handlers.js +36 -0
- package/dist/commands/handlers/memory-handlers.js +96 -1
- package/dist/commands/headless-slash.d.ts +2 -0
- package/dist/commands/headless-slash.js +12 -0
- package/dist/commands/llm-provider-resolution.d.ts +5 -3
- package/dist/commands/llm-provider-resolution.js +87 -33
- package/dist/commands/ollama.d.ts +25 -0
- package/dist/commands/ollama.js +100 -0
- package/dist/commands/provider.d.ts +5 -0
- package/dist/commands/provider.js +106 -55
- package/dist/commands/slash/builtin-commands.js +20 -0
- package/dist/commands/spec-next.js +2 -1
- package/dist/commands/spec-plan.js +5 -16
- package/dist/commands/tunnel.d.ts +2 -0
- package/dist/commands/tunnel.js +48 -0
- package/dist/config/config-resolver.d.ts +2 -1
- package/dist/config/config-resolver.js +54 -41
- package/dist/config/constants.d.ts +28 -0
- package/dist/config/constants.js +7 -0
- package/dist/config/env-schema.js +770 -0
- package/dist/config/feature-flags.js +7 -0
- package/dist/config/model-tools.js +4 -4
- package/dist/config/toml-config.d.ts +16 -0
- package/dist/config/toml-config.js +3 -0
- package/dist/context/context-manager-v2.d.ts +39 -0
- package/dist/context/context-manager-v2.js +91 -0
- package/dist/daemon/agent-task-executor.js +12 -1
- package/dist/daemon/autonomous-daemon.d.ts +1 -1
- package/dist/daemon/autonomous-daemon.js +5 -3
- package/dist/daemon/autonomous-loop.d.ts +21 -1
- package/dist/daemon/autonomous-loop.js +69 -0
- package/dist/daemon/colab-goal.d.ts +38 -0
- package/dist/daemon/colab-goal.js +81 -0
- package/dist/daemon/cron-agent-bridge.d.ts +12 -3
- package/dist/daemon/cron-agent-bridge.js +25 -9
- package/dist/desktop/codebuddy-engine-adapter.d.ts +32 -0
- package/dist/desktop/codebuddy-engine-adapter.js +257 -80
- package/dist/desktop/engine-adapter.d.ts +14 -0
- package/dist/desktop-automation/automation-manager.js +16 -0
- package/dist/desktop-automation/omniparser-runner.d.ts +63 -0
- package/dist/desktop-automation/omniparser-runner.js +115 -0
- package/dist/desktop-automation/smart-snapshot.d.ts +11 -0
- package/dist/desktop-automation/smart-snapshot.js +72 -5
- package/dist/doctor/index.js +40 -23
- package/dist/events/types.d.ts +11 -0
- package/dist/fleet/colab-store.d.ts +21 -0
- package/dist/fleet/colab-store.js +28 -0
- package/dist/fleet/peer-session-bridge.d.ts +1 -1
- package/dist/fleet/peer-session-bridge.js +243 -2
- package/dist/fleet/peer-session-store.d.ts +3 -0
- package/dist/fleet/peer-tool-bridge.js +14 -0
- package/dist/fleet/privacy-lint.d.ts +8 -0
- package/dist/fleet/privacy-lint.js +22 -0
- package/dist/goals/goal-decomposer.d.ts +27 -0
- package/dist/goals/goal-decomposer.js +293 -0
- package/dist/goals/goal-judge-client.d.ts +15 -0
- package/dist/goals/goal-judge-client.js +45 -0
- package/dist/goals/goal-judge.d.ts +38 -0
- package/dist/goals/goal-judge.js +158 -0
- package/dist/goals/goal-loop.d.ts +37 -0
- package/dist/goals/goal-loop.js +101 -0
- package/dist/goals/goal-manager.d.ts +77 -0
- package/dist/goals/goal-manager.js +289 -0
- package/dist/goals/goal-state.d.ts +99 -0
- package/dist/goals/goal-state.js +315 -0
- package/dist/goals/goal-store.d.ts +28 -0
- package/dist/goals/goal-store.js +87 -0
- package/dist/goals/index.d.ts +5 -0
- package/dist/goals/index.js +6 -0
- package/dist/hooks/use-input-handler.js +36 -1
- package/dist/hooks/user-hooks.js +17 -3
- package/dist/index.js +506 -25
- package/dist/input/text-to-speech.d.ts +2 -6
- package/dist/input/text-to-speech.js +2 -27
- package/dist/integrations/screenpipe/screenpipe-client.d.ts +10 -0
- package/dist/integrations/screenpipe/screenpipe-client.js +12 -2
- package/dist/integrations/tailscale.d.ts +13 -0
- package/dist/integrations/tailscale.js +87 -34
- package/dist/knowledge/workspace-indexer.js +53 -9
- package/dist/mcp/client.js +1 -0
- package/dist/mcp/mcp-desktop-tools.d.ts +23 -0
- package/dist/mcp/mcp-desktop-tools.js +158 -0
- package/dist/mcp/mcp-server.js +2 -0
- package/dist/memory/enhanced-memory.d.ts +10 -0
- package/dist/memory/enhanced-memory.js +33 -2
- package/dist/memory/index.d.ts +3 -1
- package/dist/memory/index.js +4 -1
- package/dist/memory/memory-auto-proposer.d.ts +23 -0
- package/dist/memory/memory-auto-proposer.js +308 -0
- package/dist/memory/memory-candidate-queue.d.ts +92 -0
- package/dist/memory/memory-candidate-queue.js +261 -0
- package/dist/memory/persistent-memory.d.ts +45 -2
- package/dist/memory/persistent-memory.js +236 -40
- package/dist/ml/bayesian-qualifier.d.ts +1 -1
- package/dist/ml/bayesian-qualifier.js +35 -2
- package/dist/observability/run-store.d.ts +1 -1
- package/dist/openclaw/gateway-bridge.js +5 -0
- package/dist/plugins/marketplace.d.ts +1 -0
- package/dist/plugins/marketplace.js +7 -0
- package/dist/prompts/execution-discipline.d.ts +14 -0
- package/dist/prompts/execution-discipline.js +29 -0
- package/dist/prompts/variation-injector.js +9 -2
- package/dist/protocols/acp/acp-agentic-runner.d.ts +7 -6
- package/dist/protocols/acp/acp-agentic-runner.js +115 -18
- package/dist/protocols/acp/acp-session-store.d.ts +23 -0
- package/dist/protocols/acp/acp-session-store.js +77 -0
- package/dist/protocols/acp/acp-stdio-server.d.ts +7 -0
- package/dist/protocols/acp/acp-stdio-server.js +71 -16
- package/dist/providers/active-llm-registry.d.ts +37 -0
- package/dist/providers/active-llm-registry.js +186 -0
- package/dist/providers/auxiliary-provider.d.ts +25 -0
- package/dist/providers/auxiliary-provider.js +192 -0
- package/dist/providers/codex-oauth.d.ts +1 -1
- package/dist/providers/codex-oauth.js +27 -4
- package/dist/providers/index.d.ts +3 -0
- package/dist/providers/index.js +4 -0
- package/dist/providers/provider-catalog.d.ts +70 -0
- package/dist/providers/provider-catalog.js +738 -0
- package/dist/providers/provider-fallback.d.ts +35 -0
- package/dist/providers/provider-fallback.js +171 -0
- package/dist/providers/xai-oauth.d.ts +128 -0
- package/dist/providers/xai-oauth.js +735 -0
- package/dist/scheduler/cron-scheduler.d.ts +15 -3
- package/dist/scheduler/cron-scheduler.js +53 -7
- package/dist/scheduler/script-runner.d.ts +2 -0
- package/dist/scheduler/script-runner.js +19 -4
- package/dist/scheduler/watchdog-handlers.js +7 -20
- package/dist/search/usearch-index.js +7 -2
- package/dist/security/tool-policy/tool-groups.js +2 -0
- package/dist/server/index.js +17 -2
- package/dist/server/routes/mobile.d.ts +12 -4
- package/dist/server/routes/mobile.js +116 -1
- package/dist/server/tls-config.d.ts +35 -0
- package/dist/server/tls-config.js +142 -0
- package/dist/server/tunnel-manager.d.ts +20 -0
- package/dist/server/tunnel-manager.js +58 -0
- package/dist/server/websocket/fleet-bridge.d.ts +13 -1
- package/dist/server/websocket/fleet-bridge.js +16 -0
- package/dist/services/prompt-builder.d.ts +1 -0
- package/dist/services/prompt-builder.js +49 -8
- package/dist/shared/engine-types.d.ts +15 -1
- package/dist/sidecar/sidecar-bridge.d.ts +1 -0
- package/dist/sidecar/sidecar-bridge.js +21 -10
- package/dist/spec/spec-store.js +8 -1
- package/dist/talk-mode/providers/audioreader-tts.d.ts +1 -1
- package/dist/talk-mode/providers/audioreader-tts.js +8 -8
- package/dist/templates/project-scaffolding.js +3 -2
- package/dist/themes/theme-schema.d.ts +10 -10
- package/dist/tools/application-profiles.js +38 -0
- package/dist/tools/bash/bash-tool.d.ts +1 -0
- package/dist/tools/bash/bash-tool.js +16 -2
- package/dist/tools/bash/command-validator.js +3 -0
- package/dist/tools/bash/rtk-rewrite.d.ts +16 -0
- package/dist/tools/bash/rtk-rewrite.js +100 -0
- package/dist/tools/bash/streaming-executor.js +14 -1
- package/dist/tools/computer-control-tool.d.ts +16 -1
- package/dist/tools/computer-control-tool.js +317 -5
- package/dist/tools/document-generator.d.ts +14 -0
- package/dist/tools/document-generator.js +79 -0
- package/dist/tools/execute-code-rpc-invoker.d.ts +26 -2
- package/dist/tools/execute-code-rpc-invoker.js +46 -5
- package/dist/tools/metadata.js +28 -0
- package/dist/tools/office-macro-tool.d.ts +10 -0
- package/dist/tools/office-macro-tool.js +93 -0
- package/dist/tools/registry/index.d.ts +2 -1
- package/dist/tools/registry/index.js +2 -1
- package/dist/tools/registry/memory-tools.d.ts +20 -0
- package/dist/tools/registry/memory-tools.js +225 -3
- package/dist/tools/registry/multimodal-tools.js +2 -2
- package/dist/tools/registry/vision-tools.d.ts +33 -0
- package/dist/tools/registry/vision-tools.js +308 -6
- package/dist/tools/registry/windows-tools.d.ts +2 -0
- package/dist/tools/registry/windows-tools.js +47 -0
- package/dist/tools/route-peer-tool.js +14 -0
- package/dist/tools/screenshot-tool.js +14 -2
- package/dist/tools/text-to-speech-tool.d.ts +1 -1
- package/dist/tools/text-to-speech-tool.js +2 -12
- package/dist/tools/tool-selector.js +3 -59
- package/dist/utils/config-validation/schema.d.ts +40 -7
- package/dist/utils/config-validation/schema.js +130 -1
- package/dist/utils/cost-tracker.js +21 -1
- package/dist/utils/disk-guard.d.ts +180 -0
- package/dist/utils/disk-guard.js +404 -0
- package/dist/utils/interactive-setup.js +35 -2
- package/dist/utils/model-utils.js +11 -2
- package/dist/utils/output-sanitizer.js +11 -0
- package/dist/utils/provider-detector.d.ts +8 -7
- package/dist/utils/provider-detector.js +19 -77
- package/dist/utils/settings-manager.d.ts +7 -0
- package/dist/utils/token-display.d.ts +3 -3
- package/dist/utils/token-display.js +22 -4
- package/dist/wizard/onboarding.d.ts +39 -0
- package/dist/wizard/onboarding.js +433 -21
- package/dist/wizard/provider-onboarding.d.ts +8 -23
- package/dist/wizard/provider-onboarding.js +39 -158
- package/package.json +4 -2
- package/dist/plugins/provider-onboarding.d.ts +0 -23
- package/dist/plugins/provider-onboarding.js +0 -116
- package/dist/utils/kokoro-tts.d.ts +0 -8
- package/dist/utils/kokoro-tts.js +0 -67
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { decomposeGoal, formatGoalPlan, shouldAutoDecomposeGoal, } from '../../goals/goal-decomposer.js';
|
|
2
|
+
import { getGoalManager } from '../../goals/goal-manager.js';
|
|
3
|
+
/**
|
|
4
|
+
* /goal — standing goal with judge + auto-continue loop (the Ralph loop,
|
|
5
|
+
* ported from Hermes Agent).
|
|
6
|
+
*
|
|
7
|
+
* Forms:
|
|
8
|
+
* /goal <text> set a new goal (replaces any old one) and start turn 1
|
|
9
|
+
* /goal | status show current state
|
|
10
|
+
* /goal pause halt auto-continuation, keep the goal
|
|
11
|
+
* /goal resume restart the loop (resets the turn budget)
|
|
12
|
+
* /goal clear discard the goal (aliases: stop, done)
|
|
13
|
+
*/
|
|
14
|
+
export async function handleGoal(args, options = {}) {
|
|
15
|
+
const arg = args.join(' ').trim();
|
|
16
|
+
const lower = arg.toLowerCase();
|
|
17
|
+
const mgr = getGoalManager(options.sessionKey);
|
|
18
|
+
if (!arg || lower === 'status') {
|
|
19
|
+
return textResult(mgr.statusLine());
|
|
20
|
+
}
|
|
21
|
+
if (lower === 'pause') {
|
|
22
|
+
const state = mgr.pause('user-paused');
|
|
23
|
+
return textResult(state ? `⏸ Goal paused: ${state.goal}` : 'No goal set.');
|
|
24
|
+
}
|
|
25
|
+
if (lower === 'resume') {
|
|
26
|
+
const state = mgr.resume();
|
|
27
|
+
if (!state) {
|
|
28
|
+
return textResult('No goal to resume.');
|
|
29
|
+
}
|
|
30
|
+
return textResult(`▶ Goal resumed: ${state.goal}\n` +
|
|
31
|
+
'Send any message to kick the loop off (e.g. "continue").');
|
|
32
|
+
}
|
|
33
|
+
if (['clear', 'stop', 'done'].includes(lower)) {
|
|
34
|
+
const had = mgr.hasGoal();
|
|
35
|
+
mgr.clear();
|
|
36
|
+
return textResult(had ? '✓ Goal cleared.' : 'No active goal.');
|
|
37
|
+
}
|
|
38
|
+
// Otherwise treat the arg as the goal text.
|
|
39
|
+
let plan = null;
|
|
40
|
+
let planAttempted = false;
|
|
41
|
+
let planError = '';
|
|
42
|
+
if (options.client && shouldAutoDecomposeGoal(arg)) {
|
|
43
|
+
planAttempted = true;
|
|
44
|
+
try {
|
|
45
|
+
plan = await (options.planner ?? decomposeGoal)(arg, options.client);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
planError = error instanceof Error ? error.message : String(error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
let state;
|
|
52
|
+
try {
|
|
53
|
+
state = mgr.set(arg, {
|
|
54
|
+
...(plan ? { goalPlan: plan } : {}),
|
|
55
|
+
...(planAttempted ? { goalPlanAttempted: true } : {}),
|
|
56
|
+
});
|
|
57
|
+
if (planAttempted && !plan && planError) {
|
|
58
|
+
mgr.markGoalPlanAttempted(planError);
|
|
59
|
+
state = mgr.state ?? state;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
return textResult(`Invalid goal: ${error instanceof Error ? error.message : String(error)}`);
|
|
64
|
+
}
|
|
65
|
+
const planBlock = state.goalPlan
|
|
66
|
+
? `\n\nHermes-style task graph attached:\n${formatGoalPlan(state.goalPlan)}`
|
|
67
|
+
: planError
|
|
68
|
+
? `\n\nGoal planning was skipped after an LLM planner error: ${planError}`
|
|
69
|
+
: '';
|
|
70
|
+
return {
|
|
71
|
+
handled: true,
|
|
72
|
+
entry: {
|
|
73
|
+
type: 'assistant',
|
|
74
|
+
content: `⊙ Goal set (${state.maxTurns}-turn budget): ${state.goal}\n` +
|
|
75
|
+
'After each turn, a judge model checks if the goal is done. Code Buddy ' +
|
|
76
|
+
'keeps working until it is, you pause/clear it, or the budget is ' +
|
|
77
|
+
'exhausted. Use /goal status, /goal pause, /goal resume, /goal clear. ' +
|
|
78
|
+
'Tip: for unattended runs, enable auto-approval (/yolo or auto-edit) so ' +
|
|
79
|
+
'the loop is not blocked on confirmations.' +
|
|
80
|
+
planBlock,
|
|
81
|
+
timestamp: new Date(),
|
|
82
|
+
},
|
|
83
|
+
// Kick the loop off immediately — the dispatcher feeds the goal text as
|
|
84
|
+
// the first turn, then the after-turn hook drives the continuation loop.
|
|
85
|
+
passToAI: true,
|
|
86
|
+
prompt: state.goal,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* /subgoal — extra acceptance criteria added mid-loop.
|
|
91
|
+
*
|
|
92
|
+
* Forms:
|
|
93
|
+
* /subgoal show current subgoals
|
|
94
|
+
* /subgoal <text> append a criterion
|
|
95
|
+
* /subgoal remove <n> drop subgoal n (1-based)
|
|
96
|
+
* /subgoal clear wipe all subgoals
|
|
97
|
+
*
|
|
98
|
+
* Subgoals get appended to both the judge prompt (verdict must consider
|
|
99
|
+
* them) and the continuation prompt (agent sees them) on the next turn
|
|
100
|
+
* boundary — no special kick needed.
|
|
101
|
+
*/
|
|
102
|
+
export async function handleSubgoal(args, options = {}) {
|
|
103
|
+
const arg = args.join(' ').trim();
|
|
104
|
+
const mgr = getGoalManager(options.sessionKey);
|
|
105
|
+
if (!mgr.hasGoal()) {
|
|
106
|
+
return textResult('No active goal. Set one with /goal <text>.');
|
|
107
|
+
}
|
|
108
|
+
if (!arg) {
|
|
109
|
+
return textResult(`${mgr.statusLine()}\n${mgr.renderSubgoals()}`);
|
|
110
|
+
}
|
|
111
|
+
const [verb, ...restTokens] = arg.split(/\s+/);
|
|
112
|
+
const rest = restTokens.join(' ').trim();
|
|
113
|
+
if (verb?.toLowerCase() === 'remove') {
|
|
114
|
+
if (!rest) {
|
|
115
|
+
return textResult('Usage: /subgoal remove <n>');
|
|
116
|
+
}
|
|
117
|
+
const indexToken = rest.split(/\s+/)[0] ?? '';
|
|
118
|
+
const idx = Number(indexToken);
|
|
119
|
+
if (!/^[1-9]\d*$/.test(indexToken) || !Number.isSafeInteger(idx)) {
|
|
120
|
+
return textResult('/subgoal remove: <n> must be a positive integer (1-based index).');
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
const removed = mgr.removeSubgoal(idx);
|
|
124
|
+
return textResult(`✓ Removed subgoal ${idx}: ${removed}`);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
return textResult(`/subgoal remove: ${error instanceof Error ? error.message : String(error)}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (verb?.toLowerCase() === 'clear') {
|
|
131
|
+
try {
|
|
132
|
+
const prev = mgr.clearSubgoals();
|
|
133
|
+
return textResult(prev ? `✓ Cleared ${prev} subgoal${prev !== 1 ? 's' : ''}.` : 'No subgoals to clear.');
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
return textResult(`/subgoal clear: ${error instanceof Error ? error.message : String(error)}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Otherwise — append the whole arg as a new subgoal.
|
|
140
|
+
try {
|
|
141
|
+
const text = mgr.addSubgoal(arg);
|
|
142
|
+
const idx = mgr.state?.subgoals.length ?? 0;
|
|
143
|
+
return textResult(`✓ Added subgoal ${idx}: ${text}`);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
return textResult(`/subgoal: ${error instanceof Error ? error.message : String(error)}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function textResult(content) {
|
|
150
|
+
return {
|
|
151
|
+
handled: true,
|
|
152
|
+
entry: { type: 'assistant', content, timestamp: new Date() },
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=goal-handler.js.map
|
|
@@ -36,6 +36,7 @@ export { handleFastMode, isFastModeEnabled, getFastModeModel, getFastModeService
|
|
|
36
36
|
export { handleBackup, } from './backup-handlers.js';
|
|
37
37
|
export { handleBtw, setBtwClient, } from './btw-handler.js';
|
|
38
38
|
export { handleHeartbeat } from './heartbeat-handler.js';
|
|
39
|
+
export { handleGoal, handleSubgoal } from './goal-handler.js';
|
|
39
40
|
export { handleDailyReset } from './daily-reset-handler.js';
|
|
40
41
|
export { handleShare } from './team-session-handler.js';
|
|
41
42
|
export { handleAgents } from './agents-handler.js';
|
|
@@ -74,6 +74,8 @@ export { handleBackup, } from './backup-handlers.js';
|
|
|
74
74
|
export { handleBtw, setBtwClient, } from './btw-handler.js';
|
|
75
75
|
// Heartbeat handler (fleet AUTONOMOUS-FLEET-PROTOCOL v0.1)
|
|
76
76
|
export { handleHeartbeat } from './heartbeat-handler.js';
|
|
77
|
+
// Goal handler (Hermes Agent parity — Ralph loop)
|
|
78
|
+
export { handleGoal, handleSubgoal } from './goal-handler.js';
|
|
77
79
|
// Daily reset handler (audit OpenClaw heritage activation)
|
|
78
80
|
export { handleDailyReset } from './daily-reset-handler.js';
|
|
79
81
|
// Team session handler — slash /share (audit OpenClaw heritage activation, TeamSessionManager wake)
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* and the current TurboQuant routing statistics.
|
|
7
7
|
*/
|
|
8
8
|
import { logger } from '../../utils/logger.js';
|
|
9
|
+
import { fetchOllamaStatus } from '../ollama.js';
|
|
9
10
|
async function checkEndpoint(name, url, timeoutMs = 4000) {
|
|
10
11
|
const start = Date.now();
|
|
11
12
|
try {
|
|
@@ -49,6 +50,35 @@ function formatRoutingStats(stats) {
|
|
|
49
50
|
}
|
|
50
51
|
return lines.join('\n');
|
|
51
52
|
}
|
|
53
|
+
function formatOllamaSummary(status) {
|
|
54
|
+
const lines = [
|
|
55
|
+
` Reachable: ${status.reachable ? 'YES' : 'NO'}`,
|
|
56
|
+
` Version: ${status.version ?? '(unknown)'}`,
|
|
57
|
+
` Models: ${status.models.length > 0 ? status.models.join(', ') : '(none)'}`,
|
|
58
|
+
];
|
|
59
|
+
if (status.error) {
|
|
60
|
+
lines.push(` Error: ${status.error}`);
|
|
61
|
+
}
|
|
62
|
+
lines.push(` Gemma 4 ready: ${isGemma4Ready(status.version, status.models) ? 'YES' : 'NO'}`);
|
|
63
|
+
return lines.join('\n');
|
|
64
|
+
}
|
|
65
|
+
function isGemma4Ready(version, models) {
|
|
66
|
+
if (!version)
|
|
67
|
+
return false;
|
|
68
|
+
const [majorRaw, minorRaw, patchRaw] = version.split('.');
|
|
69
|
+
const major = Number.parseInt(majorRaw ?? '', 10);
|
|
70
|
+
const minor = Number.parseInt(minorRaw ?? '', 10);
|
|
71
|
+
const patch = Number.parseInt(patchRaw ?? '', 10);
|
|
72
|
+
if (!Number.isFinite(major) || !Number.isFinite(minor) || !Number.isFinite(patch))
|
|
73
|
+
return false;
|
|
74
|
+
if (major > 0)
|
|
75
|
+
return true;
|
|
76
|
+
if (minor > 24)
|
|
77
|
+
return true;
|
|
78
|
+
if (minor === 24 && patch >= 1)
|
|
79
|
+
return true;
|
|
80
|
+
return models.some((model) => model.toLowerCase().includes('gemma4'));
|
|
81
|
+
}
|
|
52
82
|
// ---------------------------------------------------------------------------
|
|
53
83
|
// Main handler
|
|
54
84
|
// ---------------------------------------------------------------------------
|
|
@@ -102,6 +132,9 @@ async function handleInfraDashboard() {
|
|
|
102
132
|
lines.push(formatStatus(s));
|
|
103
133
|
}
|
|
104
134
|
lines.push('');
|
|
135
|
+
lines.push('Ollama Summary:');
|
|
136
|
+
lines.push(formatOllamaSummary(await fetchOllamaStatus(ollamaUrl)));
|
|
137
|
+
lines.push('');
|
|
105
138
|
// Routing stats from TurboQuant plugin
|
|
106
139
|
try {
|
|
107
140
|
const { getTurboQuantStats } = await import('../../plugins/bundled/turboquant-plugin.js');
|
|
@@ -159,6 +192,9 @@ async function handleInfraHealth() {
|
|
|
159
192
|
for (const s of statuses) {
|
|
160
193
|
lines.push(formatStatus(s));
|
|
161
194
|
}
|
|
195
|
+
lines.push('');
|
|
196
|
+
lines.push('Ollama Summary:');
|
|
197
|
+
lines.push(formatOllamaSummary(await fetchOllamaStatus(ollamaUrl)));
|
|
162
198
|
return { handled: true, response: lines.join('\n') };
|
|
163
199
|
}
|
|
164
200
|
//# sourceMappingURL=infra-handlers.js.map
|
|
@@ -27,6 +27,9 @@ function formatTimeAgo(date, now = new Date()) {
|
|
|
27
27
|
const yr = Math.floor(day / 365);
|
|
28
28
|
return `${yr} year${yr === 1 ? "" : "s"} ago`;
|
|
29
29
|
}
|
|
30
|
+
function clip(text, max = 180) {
|
|
31
|
+
return text.length > max ? text.slice(0, max - 1) + "…" : text;
|
|
32
|
+
}
|
|
30
33
|
/**
|
|
31
34
|
* Memory - Manage persistent memory using PersistentMemoryManager (Markdown) and EnhancedMemory (SQLite/Vector)
|
|
32
35
|
*/
|
|
@@ -103,10 +106,10 @@ export async function handleMemory(args) {
|
|
|
103
106
|
content = `Usage: /memory remember <key> <content> [project|user]`;
|
|
104
107
|
break;
|
|
105
108
|
}
|
|
106
|
-
const value = args.slice(2).join(" ");
|
|
107
109
|
const scope = (args[args.length - 1] === "user" || args[args.length - 1] === "project")
|
|
108
110
|
? args.pop()
|
|
109
111
|
: "project";
|
|
112
|
+
const value = args.slice(2).join(" ");
|
|
110
113
|
// Store in both for redundancy and better retrieval
|
|
111
114
|
await persistentMemory.remember(key, value, { scope, category: "custom" });
|
|
112
115
|
await enhancedMemory.store({
|
|
@@ -121,6 +124,30 @@ export async function handleMemory(args) {
|
|
|
121
124
|
content = `Usage: /memory remember <key> <content> [project|user]`;
|
|
122
125
|
}
|
|
123
126
|
break;
|
|
127
|
+
case "replace":
|
|
128
|
+
case "update":
|
|
129
|
+
if (args.length >= 3) {
|
|
130
|
+
const key = args[1];
|
|
131
|
+
if (key === undefined) {
|
|
132
|
+
content = `Usage: /memory replace <key> <content> [project|user]`;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
const scope = (args[args.length - 1] === "user" || args[args.length - 1] === "project")
|
|
136
|
+
? args.pop()
|
|
137
|
+
: "project";
|
|
138
|
+
const value = args.slice(2).join(" ");
|
|
139
|
+
const result = await persistentMemory.replace(key, value, { scope });
|
|
140
|
+
if (result.status === 'missing') {
|
|
141
|
+
content = result.message;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
content = `✅ ${result.message}\nCapacity: ${result.usage.used}/${result.usage.limit} chars (${result.usage.percent}%).`;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
content = `Usage: /memory replace <key> <content> [project|user]`;
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
124
151
|
case "context":
|
|
125
152
|
const enhancedContext = await enhancedMemory.buildContext({
|
|
126
153
|
includeProject: true,
|
|
@@ -154,6 +181,74 @@ export async function handleMemory(args) {
|
|
|
154
181
|
}
|
|
155
182
|
break;
|
|
156
183
|
}
|
|
184
|
+
case "candidates":
|
|
185
|
+
case "candidate":
|
|
186
|
+
case "pending": {
|
|
187
|
+
const { getMemoryCandidateQueue } = await import("../../memory/memory-candidate-queue.js");
|
|
188
|
+
const statusArg = args[1];
|
|
189
|
+
const status = statusArg === "pending" || statusArg === "accepted" || statusArg === "rejected"
|
|
190
|
+
? statusArg
|
|
191
|
+
: undefined;
|
|
192
|
+
const rawLimit = parseInt(args[status ? 2 : 1] ?? "20", 10);
|
|
193
|
+
const limit = Math.min(50, Math.max(1, Number.isFinite(rawLimit) ? rawLimit : 20));
|
|
194
|
+
const candidates = getMemoryCandidateQueue(process.cwd()).list(status).slice(0, limit);
|
|
195
|
+
if (candidates.length === 0) {
|
|
196
|
+
content = status ? `No ${status} memory candidates.` : "No memory candidates yet.";
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
const lines = [`🧠 Memory candidates (${candidates.length}${status ? ` ${status}` : ""})`, "═".repeat(50)];
|
|
200
|
+
for (const candidate of candidates) {
|
|
201
|
+
const created = formatTimeAgo(new Date(candidate.createdAt));
|
|
202
|
+
const confidence = typeof candidate.confidence === "number"
|
|
203
|
+
? ` | confidence ${(candidate.confidence * 100).toFixed(0)}%`
|
|
204
|
+
: "";
|
|
205
|
+
lines.push(`[${candidate.status}] ${candidate.id} | ${candidate.scope}/${candidate.category}${confidence} | ${created}`);
|
|
206
|
+
lines.push(` ${candidate.key}: ${clip(candidate.value)}`);
|
|
207
|
+
const citation = candidate.citations?.[0];
|
|
208
|
+
if (citation) {
|
|
209
|
+
const label = citation.sessionId
|
|
210
|
+
? `${citation.sessionId}${citation.messageId ? `#${citation.messageId}` : citation.messageIndex ? `#${citation.messageIndex}` : ""}`
|
|
211
|
+
: citation.messageIndex ? `message ${citation.messageIndex}` : "evidence";
|
|
212
|
+
lines.push(` citation: ${label}${citation.role ? ` (${citation.role})` : ""} — ${clip(citation.snippet, 140)}`);
|
|
213
|
+
}
|
|
214
|
+
lines.push("");
|
|
215
|
+
}
|
|
216
|
+
lines.push("Approve: /memory accept <id> [reviewer]");
|
|
217
|
+
lines.push("Reject: /memory reject <id> [reason]");
|
|
218
|
+
content = lines.join("\n").trimEnd();
|
|
219
|
+
}
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
case "accept":
|
|
223
|
+
case "approve": {
|
|
224
|
+
const id = args[1];
|
|
225
|
+
if (!id) {
|
|
226
|
+
content = `Usage: /memory accept <candidate-id> [reviewer]`;
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
const reviewedBy = args.slice(2).join(" ").trim() || "user";
|
|
230
|
+
const { getMemoryCandidateQueue } = await import("../../memory/memory-candidate-queue.js");
|
|
231
|
+
const { candidate, write } = await getMemoryCandidateQueue(process.cwd()).accept(id, { reviewedBy });
|
|
232
|
+
content = `✅ Accepted ${candidate.id} into ${candidate.scope} memory as "${candidate.key}".\n` +
|
|
233
|
+
`Write status: ${write.status}. Capacity: ${write.usage.used}/${write.usage.limit} chars (${write.usage.percent}%).`;
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
case "reject":
|
|
237
|
+
case "discard": {
|
|
238
|
+
const id = args[1];
|
|
239
|
+
if (!id) {
|
|
240
|
+
content = `Usage: /memory reject <candidate-id> [reason]`;
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
const reason = args.slice(2).join(" ").trim();
|
|
244
|
+
const { getMemoryCandidateQueue } = await import("../../memory/memory-candidate-queue.js");
|
|
245
|
+
const candidate = getMemoryCandidateQueue(process.cwd()).reject(id, {
|
|
246
|
+
reviewedBy: "user",
|
|
247
|
+
...(reason ? { reason } : {}),
|
|
248
|
+
});
|
|
249
|
+
content = `🗑️ Rejected memory candidate ${candidate.id}.`;
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
157
252
|
case "status":
|
|
158
253
|
case "list":
|
|
159
254
|
default:
|
|
@@ -33,6 +33,8 @@ export interface HeadlessSlashContext {
|
|
|
33
33
|
conversationHistory?: ChatEntry[];
|
|
34
34
|
/** LLM client, for tokens that call the model directly (ai-test, btw). */
|
|
35
35
|
client?: CodeBuddyClient;
|
|
36
|
+
/** Optional goal-state key for non-TUI surfaces with their own session ids. */
|
|
37
|
+
goalSessionKey?: string;
|
|
36
38
|
}
|
|
37
39
|
/** Result of running a special token outside the TUI. */
|
|
38
40
|
export interface HeadlessSlashResult {
|
|
@@ -55,6 +55,18 @@ export async function executeHeadlessSlashToken(token, args, allow, ctx = {}) {
|
|
|
55
55
|
if (ctx.client)
|
|
56
56
|
handler.setCodeBuddyClient(ctx.client);
|
|
57
57
|
try {
|
|
58
|
+
if (ctx.goalSessionKey && (token === '__GOAL__' || token === '__SUBGOAL__')) {
|
|
59
|
+
const { handleGoal, handleSubgoal } = await import('./handlers/goal-handler.js');
|
|
60
|
+
const result = token === '__GOAL__'
|
|
61
|
+
? await handleGoal(args, { sessionKey: ctx.goalSessionKey, client: ctx.client ?? null })
|
|
62
|
+
: await handleSubgoal(args, { sessionKey: ctx.goalSessionKey });
|
|
63
|
+
return {
|
|
64
|
+
handled: result.handled,
|
|
65
|
+
output: result.entry?.content,
|
|
66
|
+
prompt: result.prompt,
|
|
67
|
+
passToAI: result.passToAI,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
58
70
|
const result = await handler.handleCommand(token, args, [token, ...args].join(" "));
|
|
59
71
|
return {
|
|
60
72
|
handled: result.handled,
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* provider + the `PROVIDERS` map (paid keys), so a machine running on
|
|
7
7
|
* local Ollama (`CODEBUDDY_PROVIDER=ollama`, $0) hit the "no API key"
|
|
8
8
|
* exit even though the rest of Code Buddy — including the autonomous
|
|
9
|
-
* daemon — runs fine there. This resolver keeps the legacy path
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* daemon — runs fine there. This resolver keeps the legacy path for
|
|
10
|
+
* ambient paid-key defaults, but honors explicit local / ChatGPT
|
|
11
|
+
* subscription model choices before a cloud key can hijack them. It
|
|
12
|
+
* falls back to {@link detectProviderFromEnv} (ollama / chatgpt-oauth /
|
|
13
|
+
* env-detected providers) when either:
|
|
12
14
|
* - `CODEBUDDY_PROVIDER` is explicitly set (operator intent wins), or
|
|
13
15
|
* - the legacy path found no key.
|
|
14
16
|
*/
|
|
@@ -6,58 +6,69 @@
|
|
|
6
6
|
* provider + the `PROVIDERS` map (paid keys), so a machine running on
|
|
7
7
|
* local Ollama (`CODEBUDDY_PROVIDER=ollama`, $0) hit the "no API key"
|
|
8
8
|
* exit even though the rest of Code Buddy — including the autonomous
|
|
9
|
-
* daemon — runs fine there. This resolver keeps the legacy path
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* daemon — runs fine there. This resolver keeps the legacy path for
|
|
10
|
+
* ambient paid-key defaults, but honors explicit local / ChatGPT
|
|
11
|
+
* subscription model choices before a cloud key can hijack them. It
|
|
12
|
+
* falls back to {@link detectProviderFromEnv} (ollama / chatgpt-oauth /
|
|
13
|
+
* env-detected providers) when either:
|
|
12
14
|
* - `CODEBUDDY_PROVIDER` is explicitly set (operator intent wins), or
|
|
13
15
|
* - the legacy path found no key.
|
|
14
16
|
*/
|
|
15
17
|
import { getSettingsManager } from '../utils/settings-manager.js';
|
|
16
18
|
import { detectProviderFromEnv } from '../utils/provider-detector.js';
|
|
17
|
-
import {
|
|
19
|
+
import { inferProvider } from '../config/resolve-model.js';
|
|
20
|
+
import { hasCodexCredentials } from '../providers/codex-oauth.js';
|
|
21
|
+
import { resolveProviderFromCatalog } from '../providers/provider-catalog.js';
|
|
22
|
+
import { PROVIDERS, resolveProviderCommandKey } from './provider.js';
|
|
18
23
|
export function resolveCommandProvider(options = {}) {
|
|
24
|
+
const settingsManager = getSettingsManager();
|
|
25
|
+
const settings = settingsManager.loadUserSettings();
|
|
26
|
+
const configuredModel = options.explicitModel || settingsManager.getCurrentModel();
|
|
19
27
|
const detectFirst = Boolean(process.env.CODEBUDDY_PROVIDER);
|
|
20
28
|
if (detectFirst) {
|
|
21
29
|
const detected = fromEnvDetection(options.explicitModel);
|
|
22
30
|
if (detected)
|
|
23
31
|
return detected;
|
|
24
32
|
}
|
|
25
|
-
const
|
|
26
|
-
|
|
33
|
+
const explicitLocal = resolveExplicitOllamaModel(configuredModel);
|
|
34
|
+
if (explicitLocal)
|
|
35
|
+
return explicitLocal;
|
|
36
|
+
const explicitChatGpt = resolveExplicitChatGptModel(configuredModel);
|
|
37
|
+
if (explicitChatGpt)
|
|
38
|
+
return explicitChatGpt;
|
|
27
39
|
const currentProviderKey = settings.provider || 'grok';
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
const providerInfoKey = resolveProviderCommandKey(currentProviderKey) || currentProviderKey;
|
|
41
|
+
const providerInfo = PROVIDERS[providerInfoKey];
|
|
42
|
+
if (providerInfo) {
|
|
43
|
+
const configuredProvider = resolveProviderFromCatalog({
|
|
44
|
+
providerOverride: providerInfo.providerId,
|
|
45
|
+
hasChatGptOAuth: hasCodexCredentials(),
|
|
46
|
+
requireConfigured: providerInfo.authMode === 'api-key',
|
|
47
|
+
});
|
|
48
|
+
if (configuredProvider) {
|
|
49
|
+
return {
|
|
50
|
+
apiKey: configuredProvider.apiKey,
|
|
51
|
+
baseURL: configuredProvider.baseURL,
|
|
52
|
+
model: configuredModel || configuredProvider.defaultModel,
|
|
53
|
+
providerLabel: configuredProvider.provider,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
41
56
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
gemini: process.env.GEMINI_BASE_URL,
|
|
48
|
-
};
|
|
57
|
+
const ambientProvider = resolveProviderFromCatalog({
|
|
58
|
+
hasChatGptOAuth: hasCodexCredentials(),
|
|
59
|
+
requireConfigured: true,
|
|
60
|
+
});
|
|
61
|
+
if (ambientProvider) {
|
|
49
62
|
return {
|
|
50
|
-
apiKey,
|
|
51
|
-
baseURL:
|
|
52
|
-
model:
|
|
53
|
-
|
|
54
|
-
providerInfo?.defaultModel,
|
|
55
|
-
providerLabel: providerInfo?.name || currentProviderKey,
|
|
63
|
+
apiKey: ambientProvider.apiKey,
|
|
64
|
+
baseURL: ambientProvider.baseURL,
|
|
65
|
+
model: configuredModel || ambientProvider.defaultModel,
|
|
66
|
+
providerLabel: ambientProvider.provider,
|
|
56
67
|
};
|
|
57
68
|
}
|
|
58
69
|
// Legacy path found nothing — fall back to env detection (local
|
|
59
70
|
// Ollama, ChatGPT OAuth, …) so a $0 local machine can still run.
|
|
60
|
-
return fromEnvDetection(
|
|
71
|
+
return fromEnvDetection(configuredModel);
|
|
61
72
|
}
|
|
62
73
|
function fromEnvDetection(explicitModel) {
|
|
63
74
|
const detected = detectProviderFromEnv();
|
|
@@ -70,4 +81,47 @@ function fromEnvDetection(explicitModel) {
|
|
|
70
81
|
providerLabel: detected.provider,
|
|
71
82
|
};
|
|
72
83
|
}
|
|
84
|
+
function resolveExplicitOllamaModel(explicitModel) {
|
|
85
|
+
const model = explicitModel?.trim();
|
|
86
|
+
if (!model || !isLocalOllamaModel(model))
|
|
87
|
+
return null;
|
|
88
|
+
let host = process.env.OLLAMA_HOST || 'http://localhost:11434';
|
|
89
|
+
if (!/^https?:\/\//i.test(host))
|
|
90
|
+
host = `http://${host}`;
|
|
91
|
+
if (!host.endsWith('/v1'))
|
|
92
|
+
host = host.replace(/\/+$/, '') + '/v1';
|
|
93
|
+
return {
|
|
94
|
+
apiKey: 'ollama',
|
|
95
|
+
baseURL: host,
|
|
96
|
+
model,
|
|
97
|
+
providerLabel: 'ollama',
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function isLocalOllamaModel(model) {
|
|
101
|
+
const normalized = model.trim().toLowerCase();
|
|
102
|
+
return inferProvider(normalized) === 'ollama' || normalized.startsWith('devstral-small-2');
|
|
103
|
+
}
|
|
104
|
+
function resolveExplicitChatGptModel(explicitModel) {
|
|
105
|
+
const model = explicitModel?.trim();
|
|
106
|
+
if (!model || !isChatGptSubscriptionModel(model))
|
|
107
|
+
return null;
|
|
108
|
+
const detected = detectProviderFromEnv();
|
|
109
|
+
if (detected?.provider !== 'chatgpt')
|
|
110
|
+
return null;
|
|
111
|
+
return {
|
|
112
|
+
apiKey: detected.apiKey,
|
|
113
|
+
baseURL: detected.baseURL,
|
|
114
|
+
model,
|
|
115
|
+
providerLabel: detected.provider,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function isChatGptSubscriptionModel(model) {
|
|
119
|
+
const m = model.trim().toLowerCase();
|
|
120
|
+
return (m === 'gpt-5.2' ||
|
|
121
|
+
m === 'gpt-5.5' ||
|
|
122
|
+
m.startsWith('gpt-5.5-') ||
|
|
123
|
+
m.includes('-codex') ||
|
|
124
|
+
m === 'codex-1' ||
|
|
125
|
+
m.startsWith('codex-mini'));
|
|
126
|
+
}
|
|
73
127
|
//# sourceMappingURL=llm-provider-resolution.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface OllamaStatus {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
reachable: boolean;
|
|
4
|
+
version: string | null;
|
|
5
|
+
models: string[];
|
|
6
|
+
error: string | null;
|
|
7
|
+
}
|
|
8
|
+
export interface OllamaUpdatePlan {
|
|
9
|
+
supported: boolean;
|
|
10
|
+
platform: NodeJS.Platform;
|
|
11
|
+
repoRoot: string;
|
|
12
|
+
scriptPath: string;
|
|
13
|
+
scriptUrl: string;
|
|
14
|
+
command?: string;
|
|
15
|
+
args?: string[];
|
|
16
|
+
message: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function normalizeOllamaBaseUrl(rawUrl?: string): string;
|
|
19
|
+
export declare function fetchOllamaStatus(baseUrl?: string): Promise<OllamaStatus>;
|
|
20
|
+
export declare function buildOllamaUpdatePlan(options: {
|
|
21
|
+
platform?: NodeJS.Platform;
|
|
22
|
+
repoRoot: string;
|
|
23
|
+
scriptUrl?: string;
|
|
24
|
+
}): OllamaUpdatePlan;
|
|
25
|
+
export declare function runOllamaUpdatePlan(plan: OllamaUpdatePlan): Promise<void>;
|