mixdog 0.9.166 → 0.9.167
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/package.json +1 -1
- package/scripts/audit-usage-ledger.mjs +86 -0
- package/scripts/generate-voice-runtime-manifest.mjs +22 -17
- package/scripts/memory-chunk-quality.mjs +128 -0
- package/scripts/memory-layer2-check.mjs +133 -0
- package/scripts/model-catalog-audit.mjs +6 -0
- package/scripts/native-tool-download.mjs +14 -0
- package/scripts/prepare-native-assets.mjs +2 -7
- package/scripts/tool-failures.mjs +7 -2
- package/scripts/verify-release-assets.mjs +48 -90
- package/src/defaults/skills/browser-use/SKILL.md +33 -18
- package/src/defaults/skills/computer-use/SKILL.md +16 -8
- package/src/lib/keychain-cjs.cjs +0 -1
- package/src/lib/rules-builder.cjs +4 -1
- package/src/rules/agent/40-cycle1-agent.md +21 -13
- package/src/rules/lead/01-general.md +8 -3
- package/src/rules/shared/10-tool-workflow.md +20 -11
- package/src/rules/shared/30-exploration.md +11 -4
- package/src/rules/shared/40-editing.md +2 -3
- package/src/rules/shared/50-execution.md +6 -3
- package/src/rules/shared/60-verification.md +3 -2
- package/src/rules/shared/70-delivery.md +0 -4
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +51 -45
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +3 -4
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +44 -7
- package/src/runtime/agent/orchestrator/agent-trace.mjs +9 -0
- package/src/runtime/agent/orchestrator/config.mjs +9 -4
- package/src/runtime/agent/orchestrator/context/collect.mjs +25 -1055
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +272 -0
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +296 -0
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +523 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +13 -14
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +214 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +220 -116
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +74 -44
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +191 -29
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +13 -12
- package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +1 -9
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +48 -25
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +28 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +1 -8
- package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +32 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +21 -6
- package/src/runtime/agent/orchestrator/providers/lib/grok-tool-schema.mjs +61 -13
- package/src/runtime/agent/orchestrator/providers/model-catalog-projection.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +123 -118
- package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +34 -3
- package/src/runtime/agent/orchestrator/providers/openai-codex-endpoints.mjs +21 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +154 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +322 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +243 -702
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-startup-prewarm.mjs +221 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/provider-catalog-cache.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/provider-model-identities.mjs +40 -0
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +120 -710
- package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +36 -15
- package/src/runtime/agent/orchestrator/session/cache/util.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +17 -4
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +36 -31
- package/src/runtime/agent/orchestrator/session/compact.mjs +4 -5
- package/src/runtime/agent/orchestrator/session/context-compaction-policy.mjs +6 -5
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +8 -6
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +121 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/loop/diagnostics.mjs +74 -0
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +44 -17
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +266 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +111 -0
- package/src/runtime/agent/orchestrator/session/loop/request-projection.mjs +99 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +91 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +20 -11
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +3 -5
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +9 -3
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +39 -0
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +21 -3
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +2 -3
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +25 -25
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +62 -10
- package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +17 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +61 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +13 -9
- package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +12 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +8 -3
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +69 -6
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +14 -17
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +1 -1
- package/src/runtime/bridge-discovery.mjs +8 -0
- package/src/runtime/browser-bridge/action-schema.mjs +37 -43
- package/src/runtime/browser-bridge/client.mjs +111 -99
- package/src/runtime/browser-bridge/input-fields.mjs +187 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +12 -227
- package/src/runtime/computer-bridge/action-schema.mjs +2 -46
- package/src/runtime/computer-bridge/client.mjs +69 -77
- package/src/runtime/computer-bridge/core-actions.mjs +7 -5
- package/src/runtime/computer-bridge/error-recovery.mjs +41 -37
- package/src/runtime/computer-bridge/tool-defs.mjs +1 -1
- package/src/runtime/github/commands.mjs +4 -1
- package/src/runtime/github/contract.mjs +1 -1
- package/src/runtime/github/tool.mjs +2 -2
- package/src/runtime/media/adapters/antigravity-image.mjs +72 -0
- package/src/runtime/media/adapters/gemini-image.mjs +20 -11
- package/src/runtime/media/auth.mjs +12 -0
- package/src/runtime/media/catalog.mjs +30 -10
- package/src/runtime/media/jobs.mjs +4 -0
- package/src/runtime/media/lanes.mjs +40 -31
- package/src/runtime/memory/index.mjs +2 -9
- package/src/runtime/memory/lib/compact-handoff.mjs +26 -18
- package/src/runtime/memory/lib/memory-chunk-audit.mjs +41 -0
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +388 -0
- package/src/runtime/memory/lib/memory-cycle1.mjs +95 -394
- package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +29 -4
- package/src/runtime/memory/lib/memory-recall-store.mjs +8 -12
- package/src/runtime/memory/lib/memory-retrievers.mjs +8 -11
- package/src/runtime/memory/lib/memory.mjs +2 -0
- package/src/runtime/memory/lib/query-handlers.mjs +98 -144
- package/src/runtime/memory/lib/query-ranking.mjs +23 -9
- package/src/runtime/memory/lib/recall-format.mjs +37 -27
- package/src/runtime/memory/lib/session-ingest-runtime.mjs +14 -8
- package/src/runtime/memory/lib/session-ingest.mjs +45 -84
- package/src/runtime/memory/lib/transcript-ingest.mjs +19 -21
- package/src/runtime/memory/tool-defs.mjs +2 -2
- package/src/runtime/office/authoring/pptx-author-session.mjs +3 -7
- package/src/runtime/office/core/office-actions-batch.mjs +2 -8
- package/src/runtime/office/core/office-actions-open.mjs +124 -0
- package/src/runtime/office/core/office-actions-read.mjs +127 -0
- package/src/runtime/office/core/office-core.mjs +80 -1
- package/src/runtime/office/core/office-sessions.mjs +116 -138
- package/src/runtime/office/index.mjs +18 -271
- package/src/runtime/office/pdf/pdf-analysis.mjs +2 -2
- package/src/runtime/office/pdf/pdf-limits.mjs +2 -0
- package/src/runtime/office/tool-defs.mjs +7 -6
- package/src/runtime/shared/agent-route-config.mjs +8 -8
- package/src/runtime/shared/child-spawn-gate.mjs +10 -13
- package/src/runtime/shared/config.mjs +2 -7
- package/src/runtime/shared/env.mjs +3 -3
- package/src/runtime/shared/err-text.mjs +1 -1
- package/src/runtime/shared/extension-scopes.mjs +3 -2
- package/src/runtime/shared/heap-cap.mjs +10 -6
- package/src/runtime/shared/llm/cost.mjs +35 -10
- package/src/runtime/shared/llm/usage-accounting.mjs +11 -1
- package/src/runtime/shared/llm/usage-context.mjs +6 -0
- package/src/runtime/shared/llm/usage-ledger-import.mjs +5 -0
- package/src/runtime/shared/llm/usage-ledger-repair.mjs +109 -0
- package/src/runtime/shared/llm/usage-ledger.mjs +59 -20
- package/src/runtime/shared/llm/usage-pricing-refresh.mjs +26 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +17 -15
- package/src/runtime/shared/native-asset.mjs +3 -4
- package/src/runtime/shared/object.mjs +4 -0
- package/src/runtime/shared/pg-schema-db.mjs +21 -0
- package/src/runtime/shared/plugin-metadata.mjs +3 -1
- package/src/runtime/shared/resource-admission.mjs +1 -6
- package/src/runtime/shared/schedules-db.mjs +8 -24
- package/src/runtime/shared/schema-value-error.d.mts +2 -0
- package/src/runtime/shared/schema-value-error.mjs +68 -0
- package/src/runtime/shared/singleton-owner.mjs +11 -24
- package/src/runtime/shared/staged-update.mjs +1 -10
- package/src/runtime/shared/tool-card-model.mjs +8 -5
- package/src/runtime/shared/tool-execution-contract.mjs +1 -1
- package/src/runtime/shared/tool-surface.mjs +1 -5
- package/src/runtime/shared/user-data-guard.mjs +1 -4
- package/src/runtime/shared/webhooks-db.mjs +8 -24
- package/src/runtime/web-search/index.mjs +32 -8
- package/src/runtime/web-search/tool-defs.mjs +4 -4
- package/src/session-runtime/config-lifecycle.mjs +34 -0
- package/src/session-runtime/context-status.mjs +19 -0
- package/src/session-runtime/cwd-plugins.mjs +12 -29
- package/src/session-runtime/goal-tasks.mjs +2 -2
- package/src/session-runtime/goal-tool-defs.mjs +3 -2
- package/src/session-runtime/internal-tool-executor.mjs +7 -0
- package/src/session-runtime/lifecycle-api.mjs +5 -11
- package/src/session-runtime/notification-bus.mjs +41 -0
- package/src/session-runtime/prewarm.mjs +22 -0
- package/src/session-runtime/runtime-bootstrap.mjs +90 -0
- package/src/session-runtime/runtime-core.mjs +88 -202
- package/src/session-runtime/runtime-feature-gates.mjs +37 -0
- package/src/session-runtime/session-lifecycle.mjs +5 -5
- package/src/session-runtime/session-turn-api.mjs +1 -12
- package/src/session-runtime/setup-tool/executor.mjs +13 -5
- package/src/session-runtime/setup-tool/tool-defs.mjs +52 -46
- package/src/session-runtime/tool-defs.mjs +73 -4
- package/src/session-runtime/usage-stats-api.mjs +4 -1
- package/src/session-runtime/warmup-schedulers.mjs +8 -2
- package/src/session-runtime/workflow.mjs +14 -0
- package/src/standalone/channel-session-router.mjs +3 -1
- package/src/standalone/channel-worker.mjs +18 -9
- package/src/standalone/daemon-crash-capture.mjs +534 -0
- package/src/standalone/daemon-telemetry.mjs +175 -0
- package/src/standalone/daemon.mjs +31 -21
- package/src/standalone/session-client.mjs +31 -23
- package/src/standalone/usage-dashboard-model.mjs +2 -0
- package/src/standalone/usage-stats-hours.mjs +18 -11
- package/src/standalone/usage-stats-model.mjs +39 -28
- package/src/standalone/usage-stats-period.mjs +43 -45
- package/src/tui/app/use-transcript-window.mjs +1 -1
- package/src/tui/components/StatusLine.jsx +13 -42
- package/src/tui/dist/index.mjs +256 -239
- package/src/tui/session/session-api-ext.mjs +44 -41
- package/src/tui/session/session-api.mjs +4 -0
- package/src/tui/session/tool-card-results.mjs +25 -78
- package/src/tui/session/tool-result-status.mjs +94 -1
- package/src/tui/session/turn-aggregate-cards.mjs +17 -54
- package/src/ui/statusline-format.mjs +6 -26
- package/src/workflows/default/WORKFLOW.md +5 -0
|
@@ -14,52 +14,61 @@ function targetLabel(args) {
|
|
|
14
14
|
return 'the exact target window';
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
const LIST_WINDOW_CODES = new Set([
|
|
18
|
+
'ambiguous_window_target', 'window_stale', 'window_target_not_found',
|
|
19
|
+
]);
|
|
20
|
+
const STALE_TARGET_CODES = new Set(['stale_frame', 'stale_target', 'target_mismatch']);
|
|
21
|
+
const USER_YIELD_CODES = new Set([
|
|
22
|
+
'computer_user_control_active', 'computer_user_takeover', 'user_input_active',
|
|
23
|
+
]);
|
|
24
|
+
const DIAGNOSE_CODES = new Set([
|
|
25
|
+
'input_observation_unavailable', 'input_recovery_unconfirmed', 'computer_cursor_unavailable',
|
|
26
|
+
]);
|
|
27
|
+
const CLEANUP_CODES = new Set([
|
|
28
|
+
'computer_cleanup_pending', 'computer_abort_cleanup_unconfirmed',
|
|
29
|
+
'input_cleanup_unconfirmed', 'privileged_worker_cleanup_unconfirmed',
|
|
30
|
+
]);
|
|
31
|
+
const PIXEL_CODES = new Set(['pixel_unavailable', 'observation_unavailable']);
|
|
32
|
+
|
|
33
|
+
function recaptureLeaseGuidance(code, target) {
|
|
34
|
+
if (code === 'computer_target_in_use') {
|
|
35
|
+
return `Another session owns ${target}. Do not retry the stale action; wait for its lease to release, then capture fresh state.`;
|
|
36
|
+
}
|
|
37
|
+
if (code === 'computer_foreground_available_recapture_required') {
|
|
38
|
+
return `The foreground lane is now available. Capture ${target} again before issuing any input.`;
|
|
39
|
+
}
|
|
40
|
+
return `The target lease is now available. Capture ${target} again before issuing any input.`;
|
|
41
|
+
}
|
|
42
|
+
|
|
17
43
|
function recoveryForCode(code, args) {
|
|
18
44
|
const target = targetLabel(args);
|
|
19
|
-
if (code
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
code,
|
|
23
|
-
next: 'list',
|
|
24
|
-
guidance: 'List windows and retry with one current exact window_id.',
|
|
25
|
-
};
|
|
45
|
+
if (LIST_WINDOW_CODES.has(code)) {
|
|
46
|
+
return { code, next: 'list', guidance: 'List windows and retry with one current exact window_id.' };
|
|
26
47
|
}
|
|
27
|
-
if (code
|
|
48
|
+
if (STALE_TARGET_CODES.has(code)) {
|
|
28
49
|
return {
|
|
29
|
-
code,
|
|
30
|
-
next: 'capture',
|
|
50
|
+
code, next: 'capture',
|
|
31
51
|
guidance: `Capture ${target} again and use only the fresh ref, OCR mark, or frame_id.`,
|
|
32
52
|
};
|
|
33
53
|
}
|
|
34
54
|
if (code === 'computer_target_available_recapture_required'
|
|
35
55
|
|| code === 'computer_foreground_available_recapture_required'
|
|
36
56
|
|| code === 'computer_target_in_use') {
|
|
37
|
-
return {
|
|
38
|
-
code,
|
|
39
|
-
next: 'capture',
|
|
40
|
-
guidance: code === 'computer_target_in_use'
|
|
41
|
-
? `Another session owns ${target}. Do not retry the stale action; wait for its lease to release, then capture fresh state.`
|
|
42
|
-
: code === 'computer_foreground_available_recapture_required'
|
|
43
|
-
? `The foreground lane is now available. Capture ${target} again before issuing any input.`
|
|
44
|
-
: `The target lease is now available. Capture ${target} again before issuing any input.`,
|
|
45
|
-
};
|
|
57
|
+
return { code, next: 'capture', guidance: recaptureLeaseGuidance(code, target) };
|
|
46
58
|
}
|
|
47
|
-
if (code
|
|
59
|
+
if (USER_YIELD_CODES.has(code)) {
|
|
48
60
|
return {
|
|
49
|
-
code,
|
|
50
|
-
next: 'wait_for_user',
|
|
61
|
+
code, next: 'wait_for_user',
|
|
51
62
|
guidance: 'Computer Use yielded to the user. Call wait_for_user for bounded waiting. Ordinary physical input may resume after the host-configured quiet interval (default 5 seconds); explicit stops and uncertain cleanup/observation require the user. Timeout does not authorize input. After resumed, capture fresh state; never replay interrupted input. Manual Resume is also available on the overlay.',
|
|
52
63
|
};
|
|
53
64
|
}
|
|
54
|
-
if (code
|
|
55
|
-
|| code === 'computer_cursor_unavailable') {
|
|
65
|
+
if (DIAGNOSE_CODES.has(code)) {
|
|
56
66
|
return {
|
|
57
67
|
code, next: 'diagnose',
|
|
58
68
|
guidance: 'Input or recovery could not be verified. Do not repeat the mutation. Diagnose the exact target and inspect fresh state only when user control is not active.',
|
|
59
69
|
};
|
|
60
70
|
}
|
|
61
|
-
if (code
|
|
62
|
-
|| code === 'input_cleanup_unconfirmed' || code === 'privileged_worker_cleanup_unconfirmed') {
|
|
71
|
+
if (CLEANUP_CODES.has(code)) {
|
|
63
72
|
return {
|
|
64
73
|
code, next: 'user',
|
|
65
74
|
guidance: 'Worker exit and input release are not confirmed. Do not resume or reset the guard; wait for cleanup. Failed cleanup requires an explicitly approved host restart.',
|
|
@@ -67,36 +76,31 @@ function recoveryForCode(code, args) {
|
|
|
67
76
|
}
|
|
68
77
|
if (code.startsWith('menu_') || code === 'computer_command_timeout') {
|
|
69
78
|
return {
|
|
70
|
-
code,
|
|
71
|
-
next: 'capture',
|
|
79
|
+
code, next: 'capture',
|
|
72
80
|
guidance: `Capture ${target} again; empty accessibility automatically uses OCR. Use a fresh OCR mark or frame point and do not retry the same menu path unchanged.`,
|
|
73
81
|
};
|
|
74
82
|
}
|
|
75
83
|
if (code === 'foreground_changed') {
|
|
76
84
|
return {
|
|
77
|
-
code,
|
|
78
|
-
next: 'user',
|
|
85
|
+
code, next: 'user',
|
|
79
86
|
guidance: 'Focus changed during dispatch. Do not pull it back or retry input automatically. Check user control, then obtain fresh state when control is available.',
|
|
80
87
|
};
|
|
81
88
|
}
|
|
82
89
|
if (code === 'foreground_unavailable') {
|
|
83
90
|
return {
|
|
84
|
-
code,
|
|
85
|
-
next: 'user',
|
|
91
|
+
code, next: 'user',
|
|
86
92
|
guidance: `Windows did not grant foreground focus. Ask the user to activate ${target}, then capture fresh state. Do not substitute background input or repeat the failed gesture.`,
|
|
87
93
|
};
|
|
88
94
|
}
|
|
89
95
|
if (code.startsWith('background_')) {
|
|
90
96
|
return {
|
|
91
|
-
code,
|
|
92
|
-
next: 'capture',
|
|
97
|
+
code, next: 'capture',
|
|
93
98
|
guidance: `Capture ${target} and inspect whether any input was delivered. Consider foreground only if no input was sent and visible control is within the user's scope; never silently change delivery or replay uncertain input.`,
|
|
94
99
|
};
|
|
95
100
|
}
|
|
96
|
-
if (code
|
|
101
|
+
if (PIXEL_CODES.has(code)) {
|
|
97
102
|
return {
|
|
98
|
-
code,
|
|
99
|
-
next: 'capture',
|
|
103
|
+
code, next: 'capture',
|
|
100
104
|
guidance: `Recapture ${target}; do not use coordinates until a fresh frame reports pixel_status="available".`,
|
|
101
105
|
};
|
|
102
106
|
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
// recovery, and flows live in the built-in `computer-use` skill; the schema
|
|
9
9
|
// below owns every field.
|
|
10
10
|
const COMPUTER_TOOL_DESCRIPTION = [
|
|
11
|
-
'Operate
|
|
11
|
+
'Operate local Windows desktop apps, external browser windows, and OS dialogs through Mixdog. Last resort after an MCP tool, shell/CLI, and Browser Use where applicable; never a stand-in for a page action browser refused.',
|
|
12
12
|
'Load the computer-use skill before first use.',
|
|
13
13
|
'At most one computer call per model turn; chain same-window steps inside one act.',
|
|
14
14
|
'Every window action names one exact target (window_id, or app resolving to one window); input requires a fresh observation from capture or the previous result.',
|
|
@@ -78,7 +78,10 @@ export function buildGithubCommand(value) {
|
|
|
78
78
|
return api(`${root}/actions/workflows/${encodeURIComponent(text('workflow'))}/dispatches`, 'POST', {
|
|
79
79
|
ref: text('ref'), inputs: input.inputs || {},
|
|
80
80
|
});
|
|
81
|
-
case 'run.list':
|
|
81
|
+
case 'run.list':
|
|
82
|
+
return api(input.workflow
|
|
83
|
+
? `${root}/actions/workflows/${encodeURIComponent(text('workflow'))}/runs?${query}`
|
|
84
|
+
: `${root}/actions/runs?${query}`);
|
|
82
85
|
case 'run.view': return api(`${root}/actions/runs/${id()}`);
|
|
83
86
|
case 'run.logs':
|
|
84
87
|
return cli(['run', 'view', String(id()), '--repo', repo, input.failed ? '--log-failed' : '--log']);
|
|
@@ -23,7 +23,7 @@ export const GITHUB_ACTIONS = Object.freeze({
|
|
|
23
23
|
'pr.comments': { fields: ['number', 'page', 'limit'], list: true },
|
|
24
24
|
'workflow.list': { fields: ['page', 'limit'], list: true, collection: 'workflows' },
|
|
25
25
|
'workflow.run': { fields: ['workflow', 'ref', 'inputs'], write: true },
|
|
26
|
-
'run.list': { fields: ['page', 'limit'], list: true, collection: 'workflow_runs' },
|
|
26
|
+
'run.list': { fields: ['workflow', 'page', 'limit'], list: true, collection: 'workflow_runs' },
|
|
27
27
|
'run.view': { fields: ['id'] },
|
|
28
28
|
'run.logs': { fields: ['id', 'failed'] },
|
|
29
29
|
'run.rerun': { fields: ['id', 'failed'], write: true },
|
|
@@ -17,7 +17,7 @@ export const GITHUB_TOOL_DEF = {
|
|
|
17
17
|
page: { type: 'integer', minimum: 1 },
|
|
18
18
|
limit: { type: 'integer', minimum: 1, maximum: 100 },
|
|
19
19
|
owner: { type: 'string', description: 'repo.list owner; omit for authenticated repositories.' },
|
|
20
|
-
state: { type: 'string', enum: ['open', 'closed', 'all'] },
|
|
20
|
+
state: { type: 'string', enum: ['open', 'closed', 'all'], description: 'issue.list/pr.list only.' },
|
|
21
21
|
title: { type: 'string' },
|
|
22
22
|
body: { type: 'string' },
|
|
23
23
|
description: { type: 'string' },
|
|
@@ -31,7 +31,7 @@ export const GITHUB_TOOL_DEF = {
|
|
|
31
31
|
sha: { type: 'string', description: 'Full PR head commit hash; review/merge only.' },
|
|
32
32
|
method: { type: 'string', enum: ['merge', 'squash', 'rebase'] },
|
|
33
33
|
event: { type: 'string', enum: ['COMMENT', 'APPROVE', 'REQUEST_CHANGES'] },
|
|
34
|
-
workflow: { type: 'string', description: '
|
|
34
|
+
workflow: { type: 'string', description: 'workflow.run target or run.list filter: workflow file name or numeric id as text.' },
|
|
35
35
|
ref: { type: 'string', description: 'Explicit branch/tag to dispatch workflow on.' },
|
|
36
36
|
inputs: { type: 'object', additionalProperties: { type: 'string' }, description: 'workflow.run named string inputs.' },
|
|
37
37
|
failed: { type: 'boolean', description: 'run.logs/rerun: failed jobs only.' },
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antigravity image adapter (`antigravity-oauth` lane).
|
|
3
|
+
*
|
|
4
|
+
* Nano Banana models behind the Cloud Code Assist gateway take the same
|
|
5
|
+
* Gemini `generateContent` payload as the API-key lane, wrapped in the gateway
|
|
6
|
+
* envelope the chat provider sends. Only the streaming route returns image
|
|
7
|
+
* parts: the unary route answers 200 with an empty candidate list. The image
|
|
8
|
+
* arrives as one inline part; the whole SSE body is read before decoding.
|
|
9
|
+
*/
|
|
10
|
+
import { randomUUID } from 'node:crypto';
|
|
11
|
+
import { resolveAntigravityAuth } from '../auth.mjs';
|
|
12
|
+
import { upstreamError } from '../upstream-error.mjs';
|
|
13
|
+
import { geminiImageRequestBody, pickGeminiImagePart } from './gemini-image.mjs';
|
|
14
|
+
import { CONTENT_ENDPOINTS, antigravityHeaders } from '../../agent/orchestrator/providers/antigravity-oauth-tokens.mjs';
|
|
15
|
+
import { frameAndParseSse } from '../../agent/orchestrator/providers/lib/sse-framing.mjs';
|
|
16
|
+
|
|
17
|
+
const REQUEST_TIMEOUT_MS = 180_000;
|
|
18
|
+
|
|
19
|
+
export function antigravityImageRequestBody({ projectId, model, prompt, options = {}, references = [] }) {
|
|
20
|
+
return {
|
|
21
|
+
project: projectId,
|
|
22
|
+
model,
|
|
23
|
+
userAgent: 'antigravity',
|
|
24
|
+
requestType: 'agent',
|
|
25
|
+
requestId: `agent-${randomUUID()}`,
|
|
26
|
+
request: {
|
|
27
|
+
...geminiImageRequestBody(prompt, options, references),
|
|
28
|
+
sessionId: `-${randomUUID()}`,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Candidate parts across the stream; the gateway nests each chunk under `response`. */
|
|
34
|
+
export function antigravityImageParts(sseText) {
|
|
35
|
+
const parts = [];
|
|
36
|
+
let failure = null;
|
|
37
|
+
for (const event of frameAndParseSse(sseText).events) {
|
|
38
|
+
if (event.error) continue;
|
|
39
|
+
const value = event.value;
|
|
40
|
+
// In-band error events stay top level; content chunks are nested.
|
|
41
|
+
if (value?.error) failure = value.error.message || JSON.stringify(value.error);
|
|
42
|
+
const chunk = value?.response && typeof value.response === 'object' ? value.response : value;
|
|
43
|
+
const candidate = chunk?.candidates?.[0];
|
|
44
|
+
parts.push(...(candidate?.content?.parts || []));
|
|
45
|
+
const blocked = chunk?.promptFeedback?.blockReason;
|
|
46
|
+
if (blocked && !failure) failure = `prompt blocked (${blocked})`;
|
|
47
|
+
}
|
|
48
|
+
return { parts, failure };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function generateImage({ model, prompt, options = {}, references = [], signal }, {
|
|
52
|
+
fetchFn = fetch, resolveAuth = resolveAntigravityAuth, endpoint = CONTENT_ENDPOINTS[0],
|
|
53
|
+
} = {}) {
|
|
54
|
+
const auth = await resolveAuth();
|
|
55
|
+
const body = antigravityImageRequestBody({ projectId: auth.projectId, model, prompt, options, references });
|
|
56
|
+
const timeout = AbortSignal.timeout(REQUEST_TIMEOUT_MS);
|
|
57
|
+
const res = await fetchFn(`${endpoint}/v1internal:streamGenerateContent?alt=sse`, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: {
|
|
60
|
+
Authorization: `Bearer ${auth.token}`,
|
|
61
|
+
'Content-Type': 'application/json',
|
|
62
|
+
Accept: 'text/event-stream',
|
|
63
|
+
...antigravityHeaders(),
|
|
64
|
+
},
|
|
65
|
+
body: JSON.stringify(body),
|
|
66
|
+
redirect: 'error',
|
|
67
|
+
signal: signal ? AbortSignal.any([signal, timeout]) : timeout,
|
|
68
|
+
});
|
|
69
|
+
if (!res.ok) throw upstreamError('Antigravity image', res.status, await res.text().catch(() => ''));
|
|
70
|
+
const { parts, failure } = antigravityImageParts(await res.text());
|
|
71
|
+
return pickGeminiImagePart(parts, 'Antigravity', failure);
|
|
72
|
+
}
|
|
@@ -44,26 +44,35 @@ async function post(model, key, body, signal, fetchFn) {
|
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (!res.ok) throw upstreamError('Gemini image', res.status, await res.text().catch(() => ''));
|
|
53
|
-
const data = await res.json();
|
|
54
|
-
const parts = data?.candidates?.[0]?.content?.parts || [];
|
|
47
|
+
/**
|
|
48
|
+
* First inline image among a candidate's parts. A text-only answer is the
|
|
49
|
+
* model's refusal and surfaces as such; it is never retried.
|
|
50
|
+
*/
|
|
51
|
+
export function pickGeminiImagePart(parts, label, failure = null) {
|
|
55
52
|
const image = parts.find((part) => part?.inlineData?.data);
|
|
56
53
|
if (!image) {
|
|
57
|
-
const refusal =
|
|
54
|
+
const refusal = failure
|
|
55
|
+
|| parts.find((part) => typeof part?.text === 'string' && part.text.trim())?.text
|
|
56
|
+
|| '';
|
|
58
57
|
throw mediaError(
|
|
59
|
-
|
|
58
|
+
`${label} returned no image data${refusal ? `: ${String(refusal).slice(0, 200)}` : ''}`,
|
|
60
59
|
'MEDIA_EMPTY_RESULT',
|
|
61
60
|
502,
|
|
62
61
|
);
|
|
63
62
|
}
|
|
64
63
|
return {
|
|
65
|
-
bytes: decodeBase64Media(image.inlineData.data,
|
|
64
|
+
bytes: decodeBase64Media(image.inlineData.data, `${label} image`),
|
|
66
65
|
mime: image.inlineData.mimeType || 'image/png',
|
|
67
66
|
revisedPrompt: null,
|
|
68
67
|
};
|
|
69
68
|
}
|
|
69
|
+
|
|
70
|
+
export async function generateImage({ model, prompt, options = {}, references = [], signal }, {
|
|
71
|
+
fetchFn = fetch, resolveKey = resolveGeminiKey,
|
|
72
|
+
} = {}) {
|
|
73
|
+
const key = resolveKey();
|
|
74
|
+
const res = await post(model, key, geminiImageRequestBody(prompt, options, references), signal, fetchFn);
|
|
75
|
+
if (!res.ok) throw upstreamError('Gemini image', res.status, await res.text().catch(() => ''));
|
|
76
|
+
const data = await res.json();
|
|
77
|
+
return pickGeminiImagePart(data?.candidates?.[0]?.content?.parts || [], 'Gemini');
|
|
78
|
+
}
|
|
@@ -39,6 +39,18 @@ export async function resolveCodexAuth() {
|
|
|
39
39
|
return await provider.ensureAuth();
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Antigravity bearer + Cloud project. The chat provider's token store owns the
|
|
44
|
+
* refresh; the client version is warmed so discovery and generation present the
|
|
45
|
+
* same hub identity the gateway version-gates on.
|
|
46
|
+
*/
|
|
47
|
+
export async function resolveAntigravityAuth() {
|
|
48
|
+
const tokens = await import('../agent/orchestrator/providers/antigravity-oauth-tokens.mjs');
|
|
49
|
+
await tokens.ensureAntigravityVersion();
|
|
50
|
+
const current = await tokens.ensureAccessToken();
|
|
51
|
+
return { token: current.access_token, projectId: current.project_id };
|
|
52
|
+
}
|
|
53
|
+
|
|
42
54
|
export function resolveGeminiKey() {
|
|
43
55
|
const key = getAgentApiKey('gemini');
|
|
44
56
|
if (!key) {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { createHash } from 'node:crypto';
|
|
8
8
|
import { makeModelCache } from '../agent/orchestrator/providers/model-cache.mjs';
|
|
9
|
-
import { resolveGeminiKey, resolveXaiAuth } from './auth.mjs';
|
|
9
|
+
import { resolveAntigravityAuth, resolveGeminiKey, resolveXaiAuth } from './auth.mjs';
|
|
10
10
|
import { catalogHttpError, staleCatalog } from './catalog-errors.mjs';
|
|
11
11
|
|
|
12
12
|
const TTL_MS = 24 * 60 * 60_000;
|
|
@@ -29,6 +29,12 @@ function imageToolSupported(row, id) {
|
|
|
29
29
|
return major >= 5 && !/(?:^|-)(?:codex|nano|pro|chat|audio|realtime|search)(?:-|$)/i.test(id);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
// Antigravity serves the same Nano Banana family through the Cloud Code
|
|
33
|
+
// Assist gateway; the ids and labels follow the Gemini API catalog.
|
|
34
|
+
function googleLane(lane) {
|
|
35
|
+
return lane === 'gemini' || lane === 'antigravity-oauth';
|
|
36
|
+
}
|
|
37
|
+
|
|
32
38
|
function kindFor(lane, row, id) {
|
|
33
39
|
if (row.deprecated === true || row.disabled === true) return null;
|
|
34
40
|
if (lane === 'openai-oauth') return imageToolSupported(row, id) ? 'image' : null;
|
|
@@ -40,9 +46,11 @@ function kindFor(lane, row, id) {
|
|
|
40
46
|
&& !/^grok-imagine-video-1\.5(?:-|$)/.test(id)) return 'video';
|
|
41
47
|
return null;
|
|
42
48
|
}
|
|
43
|
-
if (lane
|
|
49
|
+
if (googleLane(lane)) {
|
|
44
50
|
if (/^gemini-.*(?:^|-)image(?:-|$)/.test(id)
|
|
45
51
|
&& methodsAllow(row, 'generateContent')) return 'image';
|
|
52
|
+
}
|
|
53
|
+
if (lane === 'gemini') {
|
|
46
54
|
if (/^gemini-omni-(?:[\d.]+-)?flash(?:-|$)/.test(id)) return 'video';
|
|
47
55
|
if (/^veo-3(?:\.[\d]+)?-.*generate(?:-|$)/.test(id)
|
|
48
56
|
&& methodsAllow(row, 'predictLongRunning')) return 'video';
|
|
@@ -55,6 +63,13 @@ function version(id) {
|
|
|
55
63
|
|| id.match(/(?:image|video|omni)-(\d+(?:\.\d+)*)/))?.[1] || '0';
|
|
56
64
|
}
|
|
57
65
|
|
|
66
|
+
function isPreferredMediaModel(lane, kind, id) {
|
|
67
|
+
if (lane === 'openai-oauth') return !/(?:^|-)mini(?:-|$)/.test(id);
|
|
68
|
+
if (lane === 'gemini' && kind === 'video') return /^gemini-omni-/.test(id);
|
|
69
|
+
if (googleLane(lane) && kind === 'image') return !/-lite-|preview|experimental/.test(id);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
58
73
|
function compareModels(a, b) {
|
|
59
74
|
return Number(/preview|experimental/.test(a.id)) - Number(/preview|experimental/.test(b.id))
|
|
60
75
|
|| (Number(b.created) || 0) - (Number(a.created) || 0)
|
|
@@ -69,7 +84,7 @@ export function mediaModelLabel(lane, row, id) {
|
|
|
69
84
|
label = id.replace(/^grok-imagine-image/, 'Grok Imagine Image')
|
|
70
85
|
.replace(/^grok-imagine-video/, 'Grok Imagine Video')
|
|
71
86
|
.replace(/-quality$/, ' Quality').replace(/-(\d)/, ' $1');
|
|
72
|
-
} else if (lane
|
|
87
|
+
} else if (googleLane(lane)) {
|
|
73
88
|
const names = {
|
|
74
89
|
'gemini-2.5-flash-image': 'Nano Banana · Gemini 2.5 Flash Image',
|
|
75
90
|
'gemini-3.1-flash-image': 'Nano Banana 2 · Gemini 3.1 Flash Image',
|
|
@@ -109,10 +124,7 @@ export function projectMediaModels(lane, rows) {
|
|
|
109
124
|
for (const kind of ['image', 'video']) {
|
|
110
125
|
result[kind].sort(compareModels);
|
|
111
126
|
// Defaults follow a current mainline/Omni model, never a dated hardcoded id.
|
|
112
|
-
const preferred = result[kind].findIndex((row) => lane
|
|
113
|
-
? !/(?:^|-)mini(?:-|$)/.test(row.id)
|
|
114
|
-
: lane === 'gemini' && kind === 'video' ? /^gemini-omni-/.test(row.id)
|
|
115
|
-
: lane === 'gemini' && kind === 'image' ? !/-lite-|preview|experimental/.test(row.id) : true);
|
|
127
|
+
const preferred = result[kind].findIndex((row) => isPreferredMediaModel(lane, kind, row.id));
|
|
116
128
|
if (preferred > 0) result[kind].unshift(...result[kind].splice(preferred, 1));
|
|
117
129
|
result[kind] = result[kind].map(({ created, ...row }) => row);
|
|
118
130
|
}
|
|
@@ -151,10 +163,13 @@ async function providerSource(lane) {
|
|
|
151
163
|
}
|
|
152
164
|
const auth = lane === 'gemini'
|
|
153
165
|
? { token: resolveGeminiKey() }
|
|
154
|
-
:
|
|
166
|
+
: lane === 'antigravity-oauth'
|
|
167
|
+
? await resolveAntigravityAuth()
|
|
168
|
+
: await resolveXaiAuth(lane);
|
|
155
169
|
// API-key and OAuth catalogs must not leak availability across credentials.
|
|
156
|
-
// Persist only a one-way scope hash, never a key or a bearer.
|
|
157
|
-
|
|
170
|
+
// Persist only a one-way scope hash, never a key or a bearer. Antigravity
|
|
171
|
+
// bearers rotate hourly; the Cloud project identifies that account instead.
|
|
172
|
+
const scope = createHash('sha256').update(auth.projectId || auth.token).digest('hex').slice(0, 24);
|
|
158
173
|
return {
|
|
159
174
|
key: `${lane}-${scope}`, revision,
|
|
160
175
|
fetchModels: () => fetchMediaModelRows({ lane, auth }),
|
|
@@ -173,6 +188,11 @@ export async function fetchMediaModelRows({ lane, auth, fetchFn = fetch }) {
|
|
|
173
188
|
return { ok: true, json: async () => data };
|
|
174
189
|
});
|
|
175
190
|
}
|
|
191
|
+
if (lane === 'antigravity-oauth') {
|
|
192
|
+
const { fetchAvailableModels } = await import('../agent/orchestrator/providers/antigravity-oauth-catalog.mjs');
|
|
193
|
+
const models = await fetchAvailableModels({ accessToken: auth.token, projectId: auth.projectId, fetchFn, signal });
|
|
194
|
+
return Object.entries(models).map(([id, row]) => ({ ...(row && typeof row === 'object' ? row : {}), id }));
|
|
195
|
+
}
|
|
176
196
|
const { getLlmDispatcher } = await import('../shared/llm/http-agent.mjs');
|
|
177
197
|
const response = await fetchFn(`${auth.baseURL}/models`, {
|
|
178
198
|
headers: { Authorization: `Bearer ${auth.token}` },
|
|
@@ -58,6 +58,10 @@ async function runAdapter({ lane, kind, model, requestModel, prompt, options, re
|
|
|
58
58
|
const adapter = await import('./adapters/codex-image.mjs');
|
|
59
59
|
return await adapter.generateImage({ model: requestModel || model, prompt, options, references, signal });
|
|
60
60
|
}
|
|
61
|
+
if (lane.id === 'antigravity-oauth') {
|
|
62
|
+
const adapter = await import('./adapters/antigravity-image.mjs');
|
|
63
|
+
return await adapter.generateImage({ model, prompt, options, references, signal });
|
|
64
|
+
}
|
|
61
65
|
if (lane.id === 'gemini') {
|
|
62
66
|
if (kind === 'video') {
|
|
63
67
|
const adapter = await import('./adapters/gemini-video.mjs');
|
|
@@ -11,6 +11,7 @@ import { hasAgentApiKey } from '../shared/provider-api-key.mjs';
|
|
|
11
11
|
// Credential probes are file-level checks: the catalog must not drag the whole
|
|
12
12
|
// provider graph in just to render lane availability.
|
|
13
13
|
import {
|
|
14
|
+
hasAntigravityOAuthCredentials,
|
|
14
15
|
hasGrokOAuthCredentials,
|
|
15
16
|
hasOpenAIOAuthCredentials,
|
|
16
17
|
} from '../agent/orchestrator/providers/oauth-credential-probes.mjs';
|
|
@@ -23,40 +24,37 @@ export const MEDIA_KINDS = Object.freeze(['image', 'video']);
|
|
|
23
24
|
// resolution, Gemini/Codex take pixel sizes. The UI renders whatever the lane
|
|
24
25
|
// declares instead of inventing a cross-provider size model.
|
|
25
26
|
const GROK_ASPECTS = Object.freeze(['auto', '1:1', '16:9', '9:16', '4:3', '3:4', '3:2', '2:3']);
|
|
27
|
+
const GROK_IMAGE = Object.freeze({
|
|
28
|
+
controls: Object.freeze({ aspectRatio: GROK_ASPECTS, resolution: Object.freeze(['1k', '2k']), maxReferences: 5 }),
|
|
29
|
+
});
|
|
30
|
+
const GROK_VIDEO = Object.freeze({
|
|
31
|
+
controls: Object.freeze({
|
|
32
|
+
aspectRatio: GROK_ASPECTS,
|
|
33
|
+
resolution: Object.freeze(['480p', '720p', '1080p']),
|
|
34
|
+
durationRange: Object.freeze([1, 15]),
|
|
35
|
+
// 1 ref = image-to-video, 2-7 = reference-to-video.
|
|
36
|
+
maxReferences: 7,
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
39
|
+
const GEMINI_IMAGE_CONTROLS = Object.freeze({
|
|
40
|
+
aspectRatio: Object.freeze(['auto', '1:1', '16:9', '9:16', '4:3', '3:4']),
|
|
41
|
+
maxReferences: 3,
|
|
42
|
+
});
|
|
26
43
|
|
|
27
44
|
const LANES = Object.freeze([
|
|
28
45
|
Object.freeze({
|
|
29
46
|
id: 'grok-oauth',
|
|
30
47
|
label: 'Grok Imagine',
|
|
31
48
|
auth: Object.freeze({ type: 'oauth', provider: 'grok-oauth' }),
|
|
32
|
-
image:
|
|
33
|
-
|
|
34
|
-
}),
|
|
35
|
-
video: Object.freeze({
|
|
36
|
-
controls: Object.freeze({
|
|
37
|
-
aspectRatio: GROK_ASPECTS,
|
|
38
|
-
resolution: Object.freeze(['480p', '720p', '1080p']),
|
|
39
|
-
durationRange: Object.freeze([1, 15]),
|
|
40
|
-
// 1 ref = image-to-video, 2-7 = reference-to-video.
|
|
41
|
-
maxReferences: 7,
|
|
42
|
-
}),
|
|
43
|
-
}),
|
|
49
|
+
image: GROK_IMAGE,
|
|
50
|
+
video: GROK_VIDEO,
|
|
44
51
|
}),
|
|
45
52
|
Object.freeze({
|
|
46
53
|
id: 'xai',
|
|
47
54
|
label: 'Grok Imagine',
|
|
48
55
|
auth: Object.freeze({ type: 'api-key', provider: 'xai' }),
|
|
49
|
-
image:
|
|
50
|
-
|
|
51
|
-
}),
|
|
52
|
-
video: Object.freeze({
|
|
53
|
-
controls: Object.freeze({
|
|
54
|
-
aspectRatio: GROK_ASPECTS,
|
|
55
|
-
resolution: Object.freeze(['480p', '720p', '1080p']),
|
|
56
|
-
durationRange: Object.freeze([1, 15]),
|
|
57
|
-
maxReferences: 7,
|
|
58
|
-
}),
|
|
59
|
-
}),
|
|
56
|
+
image: GROK_IMAGE,
|
|
57
|
+
video: GROK_VIDEO,
|
|
60
58
|
}),
|
|
61
59
|
Object.freeze({
|
|
62
60
|
id: 'openai-oauth',
|
|
@@ -73,11 +71,8 @@ const LANES = Object.freeze([
|
|
|
73
71
|
label: 'Google Gemini',
|
|
74
72
|
auth: Object.freeze({ type: 'api-key', provider: 'gemini' }),
|
|
75
73
|
image: Object.freeze({
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// Reference caps the image edit path at 3 inline references.
|
|
79
|
-
maxReferences: 3,
|
|
80
|
-
}),
|
|
74
|
+
// Reference caps the image edit path at 3 inline references.
|
|
75
|
+
controls: GEMINI_IMAGE_CONTROLS,
|
|
81
76
|
}),
|
|
82
77
|
video: Object.freeze({
|
|
83
78
|
controls: Object.freeze({
|
|
@@ -90,19 +85,33 @@ const LANES = Object.freeze([
|
|
|
90
85
|
}),
|
|
91
86
|
}),
|
|
92
87
|
}),
|
|
88
|
+
Object.freeze({
|
|
89
|
+
id: 'antigravity-oauth',
|
|
90
|
+
label: 'Google Antigravity',
|
|
91
|
+
auth: Object.freeze({ type: 'oauth', provider: 'antigravity-oauth' }),
|
|
92
|
+
// The gateway lists Nano Banana image models only; no video generation
|
|
93
|
+
// model is exposed, so the lane never advertises a video kind.
|
|
94
|
+
image: Object.freeze({
|
|
95
|
+
controls: GEMINI_IMAGE_CONTROLS,
|
|
96
|
+
}),
|
|
97
|
+
}),
|
|
93
98
|
]);
|
|
94
99
|
|
|
95
100
|
const LANE_BY_ID = new Map(LANES.map((lane) => [lane.id, lane]));
|
|
96
101
|
|
|
102
|
+
const OAUTH_PROBES = Object.freeze({
|
|
103
|
+
'grok-oauth': hasGrokOAuthCredentials,
|
|
104
|
+
'openai-oauth': hasOpenAIOAuthCredentials,
|
|
105
|
+
'antigravity-oauth': hasAntigravityOAuthCredentials,
|
|
106
|
+
});
|
|
107
|
+
|
|
97
108
|
function laneAuthenticated(lane) {
|
|
98
109
|
try {
|
|
99
110
|
if (lane.auth.type === 'api-key') return hasAgentApiKey(lane.auth.provider);
|
|
100
|
-
|
|
101
|
-
if (lane.auth.provider === 'openai-oauth') return hasOpenAIOAuthCredentials();
|
|
111
|
+
return OAUTH_PROBES[lane.auth.provider]?.() === true;
|
|
102
112
|
} catch {
|
|
103
113
|
return false;
|
|
104
114
|
}
|
|
105
|
-
return false;
|
|
106
115
|
}
|
|
107
116
|
|
|
108
117
|
function laneKindView(lane, kind, models) {
|
|
@@ -41,11 +41,7 @@ import {
|
|
|
41
41
|
getMetaValue,
|
|
42
42
|
setMetaValue,
|
|
43
43
|
mergeMetaValue,
|
|
44
|
-
cleanMemoryText,
|
|
45
44
|
} from './lib/memory.mjs'
|
|
46
|
-
import {
|
|
47
|
-
firstTextContent,
|
|
48
|
-
} from './lib/session-ingest.mjs';
|
|
49
45
|
import { configureEmbedding, getEmbeddingDims, getEmbeddingDtype, getEmbeddingModelId, getKnownDimsForCurrentModel, primeEmbeddingDims, shutdownEmbeddingProvider, warmupEmbeddingProvider } from './lib/embedding-provider.mjs'
|
|
50
46
|
import { startLlmWorker, stopLlmWorker } from './lib/llm-worker-host.mjs'
|
|
51
47
|
import { runCycle1, runCycle2, runCycle3, parseInterval, flushEmbeddingDirty, flushRawEmbeddings } from './lib/memory-cycle.mjs'
|
|
@@ -196,8 +192,6 @@ const _transcriptIngest = createTranscriptIngest({
|
|
|
196
192
|
persistMeta: (json) => setMetaValue(db, TRANSCRIPT_OFFSETS_KEY, json),
|
|
197
193
|
projectsRoot: () => path.join(mixdogHome(), 'projects'),
|
|
198
194
|
resolveProjectId,
|
|
199
|
-
firstTextContent,
|
|
200
|
-
cleanMemoryText,
|
|
201
195
|
log: __mixdogMemoryLog,
|
|
202
196
|
})
|
|
203
197
|
const {
|
|
@@ -615,8 +609,7 @@ export async function appendEntry(data = {}) {
|
|
|
615
609
|
await init()
|
|
616
610
|
const role = String(data.role ?? 'user')
|
|
617
611
|
const content = String(data.content ?? '')
|
|
618
|
-
|
|
619
|
-
if (!cleaned || !cleaned.trim()) return { error: content ? 'empty after clean' : 'content required' }
|
|
612
|
+
if (!content.trim()) return { error: 'content required' }
|
|
620
613
|
const sourceRef = String(data.sourceRef ?? `manual:${Date.now()}-${process.pid}`)
|
|
621
614
|
const sessionId = data.sessionId ?? null
|
|
622
615
|
const tsMs = parseTsToMs(data.ts ?? Date.now())
|
|
@@ -626,7 +619,7 @@ export async function appendEntry(data = {}) {
|
|
|
626
619
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
627
620
|
ON CONFLICT DO NOTHING
|
|
628
621
|
RETURNING id
|
|
629
|
-
`, [tsMs, role,
|
|
622
|
+
`, [tsMs, role, content, sourceRef, sessionId, projectId])
|
|
630
623
|
const insertedId = result.rows[0]?.id ?? null
|
|
631
624
|
return {
|
|
632
625
|
ok: true,
|