mixdog 1.1.0 → 1.1.2
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 +13 -6
- package/package.json +1 -2
- package/scripts/latest-guard.mjs +63 -0
- package/scripts/lib/run-node-tests.mjs +103 -27
- package/scripts/lib/test-failure-summary.mjs +7 -2
- package/scripts/merge-mac-update-feed.mjs +107 -0
- package/scripts/mobile-release.mjs +210 -0
- package/scripts/post-release-check.mjs +353 -0
- package/scripts/publish-asset-release.mjs +43 -0
- package/scripts/release-guard.mjs +63 -0
- package/scripts/release-paths.mjs +39 -2
- package/scripts/test.mjs +29 -7
- package/src/defaults/shipped-history.json +2 -0
- package/src/defaults/skills/computer-use/SKILL.md +1 -1
- package/src/defaults/skills/setup/references/actions.md +1 -0
- package/src/headless-role.mjs +2 -2
- package/src/lib/keychain-cjs.cjs +582 -17
- package/src/lib/rules-builder.cjs +0 -23
- package/src/rules/lead/LEAD.md +2 -2
- package/src/runtime/agent/orchestrator/config-storage.mjs +32 -4
- package/src/runtime/agent/orchestrator/config.mjs +18 -0
- package/src/runtime/agent/orchestrator/context/instruction-files.mjs +130 -0
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/open-login-url.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +254 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +218 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +239 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +233 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth-login.mjs +247 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +225 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +542 -0
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +25 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +14 -6
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +99 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +4 -8
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +2 -7
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +1 -5
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +12 -14
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-call-ids.mjs +90 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +19 -11
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +1 -5
- package/src/runtime/agent/orchestrator/session/read-dedup.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/turn-effort.mjs +18 -0
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +11 -8
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +9 -4
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +245 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +13 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +49 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +9 -7
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +61 -8
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +28 -3
- package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +73 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +17 -6
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +23 -5
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +93 -43
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +32 -6
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +9 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +124 -91
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +19 -4
- package/src/runtime/channels/index.mjs +1 -5
- package/src/runtime/channels/lib/runtime-paths.mjs +8 -23
- package/src/runtime/channels/lib/tool-dispatch.mjs +1 -13
- package/src/runtime/channels/lib/worker-ipc.mjs +2 -2
- package/src/runtime/channels/lib/worker-main.mjs +4 -34
- package/src/runtime/computer-bridge/client.mjs +25 -1
- package/src/runtime/computer-bridge/linux-action-capabilities.mjs +84 -0
- package/src/runtime/computer-bridge/linux-readiness.d.mts +52 -0
- package/src/runtime/computer-bridge/linux-readiness.mjs +411 -0
- package/src/runtime/computer-bridge/test-linux-display.mjs +5 -0
- package/src/runtime/effort-judge/compact-tokenizer.mjs +13 -8
- package/src/runtime/effort-judge/judge-input.mjs +5 -2
- package/src/runtime/effort-judge/model-install.mjs +9 -3
- package/src/runtime/effort-judge/model-manifest.json +7 -7
- package/src/runtime/memory/lib/embedding-worker.mjs +9 -3
- package/src/runtime/memory/lib/pg/supervisor.mjs +3 -0
- package/src/runtime/shared/config.mjs +50 -2
- package/src/runtime/shared/developer-options.mjs +7 -0
- package/src/runtime/shared/instruction-files-mode.mjs +9 -0
- package/src/runtime/shared/llm/model-catalog.mjs +2 -1
- package/src/runtime/shared/llm/openai-daybreak.mjs +79 -0
- package/src/runtime/shared/pristine-execution-contract.json +9 -0
- package/src/runtime/shared/pristine-execution.mjs +1 -1
- package/src/runtime/shared/provider-accounts.mjs +2 -0
- package/src/runtime/shared/resource-admission.mjs +10 -3
- package/src/runtime/shared/schedule-model-ref.mjs +11 -0
- package/src/runtime/shared/semver.d.mts +1 -0
- package/src/runtime/shared/semver.mjs +57 -0
- package/src/runtime/shared/session-approval-wait.mjs +35 -0
- package/src/runtime/shared/shell-display.mjs +4 -2
- package/src/runtime/shared/tool-surface.mjs +2 -2
- package/src/runtime/shared/turn-worktree-snapshot.mjs +11 -10
- package/src/runtime/shared/update-checker.mjs +2 -31
- package/src/session-runtime/boot/apis.mjs +5 -0
- package/src/session-runtime/boot/begin.mjs +0 -2
- package/src/session-runtime/boot/tools.mjs +5 -4
- package/src/session-runtime/model-recency.mjs +3 -0
- package/src/session-runtime/provider-auth/login.mjs +10 -10
- package/src/session-runtime/provider-auth/setup.mjs +22 -2
- package/src/session-runtime/provider-models/row-hydration.mjs +12 -4
- package/src/session-runtime/provider-readiness.mjs +4 -0
- package/src/session-runtime/resource-mcp-api.mjs +7 -3
- package/src/session-runtime/runtime-bootstrap.mjs +0 -4
- package/src/session-runtime/runtime-facade.mjs +5 -0
- package/src/session-runtime/runtime-paths.mjs +0 -1
- package/src/session-runtime/schedule-session-run.mjs +3 -1
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +55 -14
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +15 -3
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/approval-wait.mjs +97 -0
- package/src/session-runtime/services/agent-tool/worker-index/mutation-batch.mjs +4 -2
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -2
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +3 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +58 -2
- package/src/session-runtime/services/agent-tool/worker-index.mjs +69 -15
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +2 -0
- package/src/session-runtime/services/channel-admin.mjs +4 -2
- package/src/session-runtime/services/channel-worker.mjs +1 -1
- package/src/session-runtime/services/provider-admin.mjs +80 -17
- package/src/session-runtime/services/seeds.mjs +7 -10
- package/src/session-runtime/services/usage-dashboard-model.mjs +6 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +15 -0
- package/src/session-runtime/settings-profile-api.mjs +27 -2
- package/src/session-runtime/setup-tool/executor.mjs +5 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
- package/src/session-runtime/starter-guide-state.mjs +62 -0
- package/src/session-runtime/tool-policy-refresh.mjs +3 -0
- package/src/session-runtime/webhook-session-run.mjs +3 -1
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -2
- package/src/standalone/channel-binding.mjs +1 -2
- package/src/standalone/channel-transport/call-dispatch.mjs +4 -10
- package/src/standalone/daemon-channels-loader.mjs +2 -3
- package/src/standalone/local-session-runtime.mjs +2 -78
- package/src/standalone/session-protocol.mjs +2 -0
- package/src/tui/app/model-options.mjs +13 -1
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +10 -4
- package/src/tui/app/provider-setup/oauth-actions.mjs +5 -0
- package/src/tui/dist/index.mjs +84 -34
- package/src/tui/session/context-state.mjs +2 -0
- package/src/tui/session/live-share/owner.mjs +17 -0
- package/src/tui/session/oauth-flows.mjs +2 -0
- package/src/tui/session/session-api/extensions.mjs +12 -8
- package/src/tui/session/session-api/integrations.mjs +9 -8
- package/src/tui/session/session-api/routes.mjs +2 -2
- package/src/tui/session/session-api/settings.mjs +1 -0
- package/src/tui/session/session-api/shared.mjs +10 -6
- package/src/tui/session/tool-card-results/grouped-result.mjs +11 -2
- package/src/tui/session/transcript-spill/spill-dir.mjs +22 -6
- package/src/tui/spinner-meta.mjs +26 -10
- package/src/runtime/channels/tool-defs.mjs +0 -17
|
@@ -4,7 +4,6 @@ import { createRequire } from 'node:module';
|
|
|
4
4
|
import { loadConfig, createProvider, DATA_DIR } from './config.mjs';
|
|
5
5
|
import { resolveVoiceRuntime } from './voice-runtime-fetcher.mjs';
|
|
6
6
|
import { whisperThreadCount } from './voice-transcription.mjs';
|
|
7
|
-
import { TOOL_DEFS } from '../tool-defs.mjs';
|
|
8
7
|
import { ensureReady, stopVoiceWhisperServer } from './whisper-server.mjs';
|
|
9
8
|
import { ensurePrivateRuntimeRoot, resolveRuntimeRoot } from '../../shared/runtime-root.mjs';
|
|
10
9
|
import { Scheduler } from './scheduler.mjs';
|
|
@@ -102,7 +101,6 @@ runWorkerBootstrap({
|
|
|
102
101
|
pruneStalePluginDataLogSiblings,
|
|
103
102
|
DEFAULT_STALE_LOG_SIBLING_MAX,
|
|
104
103
|
});
|
|
105
|
-
const INSTRUCTIONS = '';
|
|
106
104
|
|
|
107
105
|
// ── Parent notification helper ───────────────────────────────────────
|
|
108
106
|
// This worker has no MCP transport of its own. All notifications flow
|
|
@@ -129,10 +127,7 @@ let _reloadDebounce = null;
|
|
|
129
127
|
const STATUS_FILE = getStatusPath(INSTANCE_ID);
|
|
130
128
|
const statusState = new JsonStateFile(STATUS_FILE, {});
|
|
131
129
|
statusState.ensure();
|
|
132
|
-
const scheduler = new Scheduler(
|
|
133
|
-
config.nonInteractive ?? [],
|
|
134
|
-
config.interactive ?? []
|
|
135
|
-
);
|
|
130
|
+
const scheduler = new Scheduler(config.nonInteractive ?? [], config.interactive ?? []);
|
|
136
131
|
// Schedules fire as visible sessions; the session runner belongs to the
|
|
137
132
|
// session-runtime layer, so this worker entry injects it (lazy, like webhooks).
|
|
138
133
|
scheduler.setScheduleRunner(async (schedule, opts) => {
|
|
@@ -250,19 +245,12 @@ function wireEventQueueHandlers(eventQueue) {
|
|
|
250
245
|
// re-read at probe time so a stale-connected flag cannot mask a lost seat.
|
|
251
246
|
eventQueue.setOwnerGetter(() => bridgeRuntimeConnected && currentOwnerState().owned);
|
|
252
247
|
}
|
|
253
|
-
// Inbound messaging, provider interaction handlers, and channel voice-message
|
|
254
|
-
// transcription are DELETED with Discord/Telegram (user decision: PWA replaces
|
|
255
|
-
// channels). The headless provider emits no events, so nothing wires here.
|
|
256
|
-
// Tool dispatch in worker mode goes through the IPC `call` handler at the
|
|
257
|
-
// bottom of this file (parent's `callWorker` → `handleToolCall`). There is no
|
|
258
|
-
// orphan worker-level MCP Server: the parent (server.mjs) owns the single
|
|
259
|
-
// connected transport and routes CallTool through the IPC `call` path.
|
|
260
248
|
// ── Worker/HTTP tool-call dispatch ──────────────────────────────────────────
|
|
261
249
|
// Runtime lifecycle dispatch only (activate_channel_bridge / reload_config):
|
|
262
250
|
// threaded as a lifecycle bag of lazy getters so the module reads live
|
|
263
251
|
// file-level references at call time. Used by the HTTP MCP CallTool path and
|
|
264
252
|
// the worker IPC `call` handler at the bottom of this file.
|
|
265
|
-
const { handleToolCall
|
|
253
|
+
const { handleToolCall } = createToolDispatch({
|
|
266
254
|
isChannelsDegraded,
|
|
267
255
|
lifecycle: {
|
|
268
256
|
getChannelBridgeActive: () => channelBridgeActive,
|
|
@@ -277,14 +265,6 @@ const { handleToolCall, handleToolCallWithBridgeRetry } = createToolDispatch({
|
|
|
277
265
|
reloadRuntimeConfig,
|
|
278
266
|
},
|
|
279
267
|
});
|
|
280
|
-
async function init(_sharedMcp) {
|
|
281
|
-
// _sharedMcp is no longer used. Notifications now flow via IPC to the parent
|
|
282
|
-
// (sendNotifyToParent above). The parameter is retained for backward
|
|
283
|
-
// compatibility with any caller that still passes a Server reference.
|
|
284
|
-
scheduler.setInjectHandler((channelId, name, content, options) => {
|
|
285
|
-
injectAndRecord(channelId, name, content, options);
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
268
|
function ensureConfigWatcher() {
|
|
289
269
|
if (_configWatcher) return;
|
|
290
270
|
try {
|
|
@@ -374,19 +354,9 @@ if (_isWorkerMode && process.send && process.env.MIXDOG_DAEMON_HOST !== '1') {
|
|
|
374
354
|
getProvider: () => provider,
|
|
375
355
|
getConfig: () => config,
|
|
376
356
|
handleMemoryCallResponse,
|
|
377
|
-
|
|
357
|
+
handleToolCall,
|
|
378
358
|
bootProfile,
|
|
379
359
|
});
|
|
380
360
|
}
|
|
381
361
|
|
|
382
|
-
export {
|
|
383
|
-
TOOL_DEFS,
|
|
384
|
-
handleToolCall,
|
|
385
|
-
handleToolCallWithBridgeRetry,
|
|
386
|
-
init,
|
|
387
|
-
INSTRUCTIONS as instructions,
|
|
388
|
-
isChannelBridgeActive,
|
|
389
|
-
isChannelsDegraded,
|
|
390
|
-
start,
|
|
391
|
-
stop,
|
|
392
|
-
};
|
|
362
|
+
export { handleToolCall, isChannelBridgeActive, isChannelsDegraded, start, stop };
|
|
@@ -23,6 +23,7 @@ import { computerErrorCode } from './error-code.mjs';
|
|
|
23
23
|
import { bridgeDiscoveryChanged, readBridgeDiscovery } from '../bridge-discovery.mjs';
|
|
24
24
|
import { MAX_COMPUTER_REQUEST_BYTES, readComputerBridgeJson, validateComputerReply } from './limits.mjs';
|
|
25
25
|
import { computerActionHas } from './actions.mjs';
|
|
26
|
+
import { linuxCaptureFallback, linuxComputerPreflight } from './linux-readiness.mjs';
|
|
26
27
|
import { continuePendingComputerWork, isPendingComputerWork } from './pending-continuation.mjs';
|
|
27
28
|
|
|
28
29
|
export { canonicalComputerResultText };
|
|
@@ -245,6 +246,13 @@ function computerToolResult(value, args) {
|
|
|
245
246
|
/** Execute one `computer` tool call. Returns MCP-shaped content so the
|
|
246
247
|
* internal-tools normalizer forwards text and screenshot images as-is. */
|
|
247
248
|
export async function executeComputerTool(rawArgs, context = {}) {
|
|
249
|
+
const note = { text: '' };
|
|
250
|
+
const result = await executeComputerToolInner(rawArgs, context, note);
|
|
251
|
+
// The fallback note rides as its own block so the JSON result text stays intact.
|
|
252
|
+
return note.text && !result.isError ? { ...result, content: [...result.content, { type: 'text', text: note.text }] } : result;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async function executeComputerToolInner(rawArgs, context, note) {
|
|
248
256
|
const discovery = readBridgeDiscovery(DISCOVERY_FILE);
|
|
249
257
|
if (!discovery) return computerErrorResult(`Error: ${BRIDGE_UNAVAILABLE_MESSAGE}`);
|
|
250
258
|
// Resolve the argument shape once so validation, host translation, and the
|
|
@@ -252,12 +260,28 @@ export async function executeComputerTool(rawArgs, context = {}) {
|
|
|
252
260
|
const args = normalizeComputerToolArgs(rawArgs);
|
|
253
261
|
const validationError = validateComputerToolArgs(args);
|
|
254
262
|
if (validationError) return computerErrorResult(`Error: ${validationError}`);
|
|
255
|
-
|
|
263
|
+
let command = toComputerHostCommand(args);
|
|
256
264
|
const sessionId = context?.sessionId ? String(context.sessionId) : '';
|
|
265
|
+
const fallback = await linuxCaptureFallback({ command });
|
|
266
|
+
if (fallback) {
|
|
267
|
+
command = fallback.command;
|
|
268
|
+
note.text = fallback.note;
|
|
269
|
+
}
|
|
257
270
|
const encoded = JSON.stringify({ ...command, ...(sessionId ? { session_id: sessionId } : {}) });
|
|
258
271
|
if (Buffer.byteLength(encoded) > MAX_COMPUTER_REQUEST_BYTES) {
|
|
259
272
|
return computerErrorResult('Error: computer request exceeds byte limit; no input was dispatched');
|
|
260
273
|
}
|
|
274
|
+
// Linux: refuse an action whose own capability (input device, window
|
|
275
|
+
// control, AT-SPI, ...) is missing, before anything is dispatched, instead of
|
|
276
|
+
// failing mid-task. Actions that need none of it still run.
|
|
277
|
+
const notReady = await linuxComputerPreflight({ command });
|
|
278
|
+
if (notReady) {
|
|
279
|
+
return {
|
|
280
|
+
...computerErrorResult(`Error: ${notReady.message}`),
|
|
281
|
+
// Structured twin of the text for the transcript card (no text parsing).
|
|
282
|
+
toolMeta: { code: notReady.code, missing: [...new Set(notReady.missing.map((item) => item.capability))] },
|
|
283
|
+
};
|
|
284
|
+
}
|
|
261
285
|
const releaseError = await awaitPendingSessionRelease(sessionId, args, context);
|
|
262
286
|
if (releaseError) return releaseError;
|
|
263
287
|
trackComputerSession(sessionId, command);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Which Linux capability each host command really needs, read from
|
|
2
|
+
// native/mixdog-computer (host/*.rs) and the desktop app's observation layer.
|
|
3
|
+
// Only a hard requirement is listed: an action that merely works better with a
|
|
4
|
+
// capability (OCR for capture, AT-SPI for a state capture, which degrades to
|
|
5
|
+
// pixels) does not name it, so a missing optional piece never blocks it.
|
|
6
|
+
//
|
|
7
|
+
// windows a window list/handle (X11 EWMH, sway, Hyprland, GNOME Window
|
|
8
|
+
// Calls). Every native window target (window_id, app, the
|
|
9
|
+
// foreground window) resolves through it.
|
|
10
|
+
// accessibility the AT-SPI bus.
|
|
11
|
+
// semanticActions AT-SPI actions (invoke, toggle, set_value, menu): they act
|
|
12
|
+
// on an accessible found through a window handle, so they need
|
|
13
|
+
// both and use no input device.
|
|
14
|
+
// pointer/keyboard the input device (uinput on Wayland, XTest on X11).
|
|
15
|
+
|
|
16
|
+
const WINDOW_ACTIONS = new Set([
|
|
17
|
+
'list_windows', 'window_snapshot', 'related_windows', 'window_bounds', 'window_capture',
|
|
18
|
+
'window_integrity', 'validate_background_input', 'list_apps', 'verify', 'focus_window',
|
|
19
|
+
'move_window', 'window_state', 'close_window', 'terminate_process',
|
|
20
|
+
]);
|
|
21
|
+
const ACCESSIBILITY_ACTIONS = new Set(['snapshot', 'find', 'window_predicates', 'accessibility_probe']);
|
|
22
|
+
const SEMANTIC_ACTIONS = new Set(['invoke', 'set_value', 'toggle', 'invoke_menu']);
|
|
23
|
+
const POINTER_ACTIONS = new Set([
|
|
24
|
+
'click', 'double_click', 'right_click', 'middle_click', 'triple_click',
|
|
25
|
+
'mouse_down', 'mouse_up', 'mouse_move', 'drag', 'scroll',
|
|
26
|
+
]);
|
|
27
|
+
const KEYBOARD_ACTIONS = new Set(['type', 'key', 'key_down', 'key_up']);
|
|
28
|
+
|
|
29
|
+
const namesWindow = (command) => Boolean(command?.window_id || command?.app || command?.window);
|
|
30
|
+
|
|
31
|
+
function addStepNeeds(need, step, delivery) {
|
|
32
|
+
const action = String(step?.action || '');
|
|
33
|
+
const foreground = delivery === 'foreground';
|
|
34
|
+
if (step?.ref || step?.element) need.add('accessibility');
|
|
35
|
+
if (SEMANTIC_ACTIONS.has(action)) {
|
|
36
|
+
// A foreground invoke is a real click; every other semantic action is AT-SPI.
|
|
37
|
+
if (action === 'invoke' && foreground) need.add('pointer');
|
|
38
|
+
else need.add('semanticActions');
|
|
39
|
+
if (action === 'invoke_menu') need.add('windows');
|
|
40
|
+
} else if (POINTER_ACTIONS.has(action)) {
|
|
41
|
+
need.add('pointer');
|
|
42
|
+
} else if (KEYBOARD_ACTIONS.has(action)) {
|
|
43
|
+
// Background typing into a settable element goes through its value.
|
|
44
|
+
if (action === 'type' && step.ref && !foreground) need.add('semanticActions');
|
|
45
|
+
else need.add('keyboard');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** A capture that names no window or screen: it resolves the foreground window. */
|
|
50
|
+
export function isForegroundWindowCapture(command) {
|
|
51
|
+
return String(command?.action) === 'capture' && !namesWindow(command) && command.screen === undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** The capabilities a host command (as toComputerHostCommand emits it) requires. */
|
|
55
|
+
export function requiredCapabilities(command) {
|
|
56
|
+
const need = new Set();
|
|
57
|
+
const action = String(command?.action || '');
|
|
58
|
+
if (WINDOW_ACTIONS.has(action)) need.add('windows');
|
|
59
|
+
else if (ACCESSIBILITY_ACTIONS.has(action)) {
|
|
60
|
+
need.add('windows');
|
|
61
|
+
need.add('accessibility');
|
|
62
|
+
} else if (action === 'capture') {
|
|
63
|
+
need.add('capture');
|
|
64
|
+
const mode = String(command.mode || 'state');
|
|
65
|
+
// Only a screen-index vision capture needs no window: every other mode
|
|
66
|
+
// resolves a named window or the foreground one.
|
|
67
|
+
const screenOnly = mode === 'vision' && command.screen !== undefined && !namesWindow(command);
|
|
68
|
+
if (!screenOnly) need.add('windows');
|
|
69
|
+
if (mode === 'ax') need.add('accessibility');
|
|
70
|
+
} else if (action === 'screenshot' || action === 'zoom') {
|
|
71
|
+
need.add('capture');
|
|
72
|
+
} else if (action === 'clipboard_read' || action === 'clipboard_write') {
|
|
73
|
+
need.add('clipboard');
|
|
74
|
+
} else if (action === 'sequence') {
|
|
75
|
+
// An act always names its window (the schema requires it).
|
|
76
|
+
need.add('windows');
|
|
77
|
+
const delivery = String(command.delivery || 'background');
|
|
78
|
+
for (const step of Array.isArray(command.steps) ? command.steps : []) addStepNeeds(need, step, delivery);
|
|
79
|
+
} else {
|
|
80
|
+
addStepNeeds(need, command, String(command?.delivery || 'background'));
|
|
81
|
+
if (need.size > 0 && namesWindow(command)) need.add('windows');
|
|
82
|
+
}
|
|
83
|
+
return need;
|
|
84
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export type LinuxComputerCapabilityState = 'ready' | 'needs_setup' | 'unsupported' | 'unknown';
|
|
2
|
+
export interface LinuxComputerCapability {
|
|
3
|
+
state: LinuxComputerCapabilityState;
|
|
4
|
+
fix?: 'allow_input' | 'relogin' | 'enable_window_helper' | 'install_package';
|
|
5
|
+
package?: string;
|
|
6
|
+
optional?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export type LinuxComputerCapabilityName =
|
|
9
|
+
| 'capture'
|
|
10
|
+
| 'windows'
|
|
11
|
+
| 'accessibility'
|
|
12
|
+
| 'semanticActions'
|
|
13
|
+
| 'pointer'
|
|
14
|
+
| 'keyboard'
|
|
15
|
+
| 'clipboard'
|
|
16
|
+
| 'ocr';
|
|
17
|
+
export interface LinuxComputerReadiness {
|
|
18
|
+
session: 'wayland' | 'x11';
|
|
19
|
+
desktop: 'gnome' | 'kde' | 'sway' | 'hyprland' | 'other';
|
|
20
|
+
capabilities: Record<LinuxComputerCapabilityName, LinuxComputerCapability>;
|
|
21
|
+
}
|
|
22
|
+
export interface LinuxComputerMissingCapability {
|
|
23
|
+
capability: LinuxComputerCapabilityName;
|
|
24
|
+
state: LinuxComputerCapabilityState;
|
|
25
|
+
fix?: LinuxComputerCapability['fix'];
|
|
26
|
+
package?: string;
|
|
27
|
+
code: string;
|
|
28
|
+
message: string;
|
|
29
|
+
}
|
|
30
|
+
export interface LinuxComputerRefusal {
|
|
31
|
+
code: 'computer_capability_unavailable';
|
|
32
|
+
missing: LinuxComputerMissingCapability[];
|
|
33
|
+
message: string;
|
|
34
|
+
}
|
|
35
|
+
export const MIN_WINDOW_HELPER_VERSION: number;
|
|
36
|
+
export const CAPABILITY_UNAVAILABLE_CODE: 'computer_capability_unavailable';
|
|
37
|
+
export function detectSession(env: Record<string, string | undefined>): 'wayland' | 'x11';
|
|
38
|
+
export function detectDesktop(env: Record<string, string | undefined>, session: 'wayland' | 'x11'): LinuxComputerReadiness['desktop'];
|
|
39
|
+
export function checkLinuxComputerReadiness(options?: Record<string, unknown>): Promise<LinuxComputerReadiness>;
|
|
40
|
+
export function getLinuxComputerReadiness(options?: Record<string, unknown>): Promise<LinuxComputerReadiness>;
|
|
41
|
+
export function missingCapabilities(
|
|
42
|
+
readiness: LinuxComputerReadiness,
|
|
43
|
+
command: Record<string, unknown>
|
|
44
|
+
): LinuxComputerMissingCapability[];
|
|
45
|
+
export function linuxComputerPreflight(options?: Record<string, unknown>): Promise<LinuxComputerRefusal | null>;
|
|
46
|
+
export function resetLinuxComputerPreflightCache(): void;
|
|
47
|
+
export const GNOME_EXTENSION_UUID: 'mixdog-windows@mixdog.io';
|
|
48
|
+
export function gnomeExtensionDirs(env?: Record<string, string | undefined>): string[];
|
|
49
|
+
export const FIX_MESSAGES: Readonly<Record<'allow_input' | 'relogin' | 'enable_window_helper' | 'install_package', string>>;
|
|
50
|
+
export const REFUSAL_MESSAGE: string;
|
|
51
|
+
export const CAPTURE_FALLBACK_NOTE: string;
|
|
52
|
+
export function linuxCaptureFallback(options?: Record<string, unknown>): Promise<{ command: Record<string, unknown>; note: string } | null>;
|