aiden-runtime 4.1.5 → 4.5.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 +250 -847
- package/dist/api/server.js +32 -5
- package/dist/cli/v4/aidenCLI.js +351 -53
- package/dist/cli/v4/callbacks.js +170 -0
- package/dist/cli/v4/chatSession.js +138 -3
- package/dist/cli/v4/commands/_runtimeToggleHelpers.js +92 -0
- package/dist/cli/v4/commands/browserDepth.js +45 -0
- package/dist/cli/v4/commands/cron.js +264 -0
- package/dist/cli/v4/commands/daemon.js +541 -0
- package/dist/cli/v4/commands/daemonStatus.js +253 -0
- package/dist/cli/v4/commands/help.js +7 -0
- package/dist/cli/v4/commands/index.js +20 -1
- package/dist/cli/v4/commands/runs.js +203 -0
- package/dist/cli/v4/commands/sandbox.js +48 -0
- package/dist/cli/v4/commands/suggestions.js +68 -0
- package/dist/cli/v4/commands/tce.js +41 -0
- package/dist/cli/v4/commands/trigger.js +378 -0
- package/dist/cli/v4/commands/update.js +95 -3
- package/dist/cli/v4/daemonAgentBuilder.js +142 -0
- package/dist/cli/v4/defaultSoul.js +1 -1
- package/dist/cli/v4/display/capabilityCard.js +26 -0
- package/dist/cli/v4/display.js +18 -8
- package/dist/cli/v4/replyRenderer.js +31 -23
- package/dist/cli/v4/updateBootPrompt.js +170 -0
- package/dist/core/playwrightBridge.js +129 -0
- package/dist/core/v4/aidenAgent.js +308 -4
- package/dist/core/v4/browserState.js +436 -0
- package/dist/core/v4/checkpoint.js +79 -0
- package/dist/core/v4/daemon/bootstrap.js +604 -0
- package/dist/core/v4/daemon/cleanShutdown.js +154 -0
- package/dist/core/v4/daemon/cron/cronBridge.js +126 -0
- package/dist/core/v4/daemon/cron/cronEmitter.js +173 -0
- package/dist/core/v4/daemon/cron/migration.js +199 -0
- package/dist/core/v4/daemon/cron/misfirePolicy.js +115 -0
- package/dist/core/v4/daemon/daemonConfig.js +90 -0
- package/dist/core/v4/daemon/db/connection.js +106 -0
- package/dist/core/v4/daemon/db/migrations.js +296 -0
- package/dist/core/v4/daemon/db/schema/v1.spec.js +18 -0
- package/dist/core/v4/daemon/dispatcher/agentRunner.js +98 -0
- package/dist/core/v4/daemon/dispatcher/budgetGate.js +127 -0
- package/dist/core/v4/daemon/dispatcher/daemonApproval.js +113 -0
- package/dist/core/v4/daemon/dispatcher/dailyBudgetTracker.js +120 -0
- package/dist/core/v4/daemon/dispatcher/dispatcher.js +389 -0
- package/dist/core/v4/daemon/dispatcher/fireRateLimiter.js +113 -0
- package/dist/core/v4/daemon/dispatcher/index.js +53 -0
- package/dist/core/v4/daemon/dispatcher/promptTemplate.js +95 -0
- package/dist/core/v4/daemon/dispatcher/realAgentRunner.js +356 -0
- package/dist/core/v4/daemon/dispatcher/resolveModel.js +93 -0
- package/dist/core/v4/daemon/dispatcher/sessionId.js +93 -0
- package/dist/core/v4/daemon/drain.js +156 -0
- package/dist/core/v4/daemon/eventLoopLag.js +73 -0
- package/dist/core/v4/daemon/health.js +159 -0
- package/dist/core/v4/daemon/idempotencyStore.js +204 -0
- package/dist/core/v4/daemon/index.js +179 -0
- package/dist/core/v4/daemon/instanceTracker.js +99 -0
- package/dist/core/v4/daemon/resourceRegistry.js +150 -0
- package/dist/core/v4/daemon/restartCode.js +32 -0
- package/dist/core/v4/daemon/restartFailureCounter.js +77 -0
- package/dist/core/v4/daemon/runStore.js +114 -0
- package/dist/core/v4/daemon/runtimeLock.js +167 -0
- package/dist/core/v4/daemon/signals.js +50 -0
- package/dist/core/v4/daemon/supervisor.js +272 -0
- package/dist/core/v4/daemon/triggerBus.js +279 -0
- package/dist/core/v4/daemon/triggers/email/allowlist.js +70 -0
- package/dist/core/v4/daemon/triggers/email/automatedSender.js +78 -0
- package/dist/core/v4/daemon/triggers/email/bodyExtractor.js +0 -0
- package/dist/core/v4/daemon/triggers/email/emailSeenStore.js +99 -0
- package/dist/core/v4/daemon/triggers/email/emailSpec.js +107 -0
- package/dist/core/v4/daemon/triggers/email/imapConnection.js +211 -0
- package/dist/core/v4/daemon/triggers/email/index.js +332 -0
- package/dist/core/v4/daemon/triggers/email/seenUids.js +60 -0
- package/dist/core/v4/daemon/triggers/fileObservationsStore.js +93 -0
- package/dist/core/v4/daemon/triggers/fileWatcher.js +253 -0
- package/dist/core/v4/daemon/triggers/fileWatcherSpec.js +88 -0
- package/dist/core/v4/daemon/triggers/fsIdentity.js +42 -0
- package/dist/core/v4/daemon/triggers/globMatcher.js +100 -0
- package/dist/core/v4/daemon/triggers/reconcile.js +206 -0
- package/dist/core/v4/daemon/triggers/settleStat.js +81 -0
- package/dist/core/v4/daemon/triggers/webhook.js +376 -0
- package/dist/core/v4/daemon/triggers/webhookDeliveriesStore.js +109 -0
- package/dist/core/v4/daemon/triggers/webhookIdempotency.js +72 -0
- package/dist/core/v4/daemon/triggers/webhookRateLimit.js +56 -0
- package/dist/core/v4/daemon/triggers/webhookSpec.js +76 -0
- package/dist/core/v4/daemon/triggers/webhookVerifier.js +128 -0
- package/dist/core/v4/daemon/types.js +15 -0
- package/dist/core/v4/dockerSession.js +461 -0
- package/dist/core/v4/dryRun.js +117 -0
- package/dist/core/v4/failureClassifier.js +779 -0
- package/dist/core/v4/recoveryReport.js +449 -0
- package/dist/core/v4/runtimeToggles.js +187 -0
- package/dist/core/v4/sandboxConfig.js +285 -0
- package/dist/core/v4/sandboxFs.js +316 -0
- package/dist/core/v4/suggestionCatalog.js +41 -0
- package/dist/core/v4/suggestionEngine.js +210 -0
- package/dist/core/v4/toolRegistry.js +18 -0
- package/dist/core/v4/turnState.js +587 -0
- package/dist/core/v4/update/checkUpdate.js +63 -3
- package/dist/core/v4/update/installMethodDetect.js +115 -0
- package/dist/core/v4/update/registryClient.js +121 -0
- package/dist/core/v4/update/skipState.js +75 -0
- package/dist/core/v4/verifier.js +448 -0
- package/dist/core/version.js +1 -1
- package/dist/tools/v4/browser/_observer.js +224 -0
- package/dist/tools/v4/browser/browserBlocker.js +396 -0
- package/dist/tools/v4/browser/browserClick.js +18 -1
- package/dist/tools/v4/browser/browserClose.js +18 -1
- package/dist/tools/v4/browser/browserExtract.js +5 -1
- package/dist/tools/v4/browser/browserFill.js +17 -1
- package/dist/tools/v4/browser/browserGetUrl.js +5 -1
- package/dist/tools/v4/browser/browserNavigate.js +16 -1
- package/dist/tools/v4/browser/browserScreenshot.js +5 -1
- package/dist/tools/v4/browser/browserScroll.js +18 -1
- package/dist/tools/v4/browser/browserType.js +17 -1
- package/dist/tools/v4/browser/captchaCheck.js +5 -1
- package/dist/tools/v4/executeCode.js +1 -0
- package/dist/tools/v4/files/fileCopy.js +56 -2
- package/dist/tools/v4/files/fileDelete.js +38 -1
- package/dist/tools/v4/files/fileList.js +12 -1
- package/dist/tools/v4/files/fileMove.js +59 -2
- package/dist/tools/v4/files/filePatch.js +43 -1
- package/dist/tools/v4/files/fileRead.js +12 -1
- package/dist/tools/v4/files/fileWrite.js +41 -1
- package/dist/tools/v4/index.js +71 -58
- package/dist/tools/v4/memory/memoryAdd.js +14 -0
- package/dist/tools/v4/memory/memoryRemove.js +14 -0
- package/dist/tools/v4/memory/memoryReplace.js +15 -0
- package/dist/tools/v4/memory/sessionSummary.js +12 -0
- package/dist/tools/v4/process/processKill.js +19 -0
- package/dist/tools/v4/process/processList.js +1 -0
- package/dist/tools/v4/process/processLogRead.js +1 -0
- package/dist/tools/v4/process/processSpawn.js +13 -0
- package/dist/tools/v4/process/processWait.js +1 -0
- package/dist/tools/v4/sessions/recallSession.js +1 -0
- package/dist/tools/v4/sessions/sessionList.js +1 -0
- package/dist/tools/v4/sessions/sessionSearch.js +1 -0
- package/dist/tools/v4/skills/lookupToolSchema.js +2 -0
- package/dist/tools/v4/skills/skillManage.js +13 -0
- package/dist/tools/v4/skills/skillView.js +1 -0
- package/dist/tools/v4/skills/skillsList.js +1 -0
- package/dist/tools/v4/subagent/subagentFanout.js +1 -0
- package/dist/tools/v4/system/aidenSelfUpdate.js +16 -0
- package/dist/tools/v4/system/appClose.js +13 -0
- package/dist/tools/v4/system/appInput.js +13 -0
- package/dist/tools/v4/system/appLaunch.js +13 -0
- package/dist/tools/v4/system/clipboardRead.js +1 -0
- package/dist/tools/v4/system/clipboardWrite.js +14 -0
- package/dist/tools/v4/system/mediaKey.js +12 -0
- package/dist/tools/v4/system/mediaSessions.js +1 -0
- package/dist/tools/v4/system/mediaTransport.js +13 -0
- package/dist/tools/v4/system/naturalEvents.js +1 -0
- package/dist/tools/v4/system/nowPlaying.js +1 -0
- package/dist/tools/v4/system/osProcessList.js +1 -0
- package/dist/tools/v4/system/screenshot.js +1 -0
- package/dist/tools/v4/system/systemInfo.js +1 -0
- package/dist/tools/v4/system/volumeSet.js +17 -0
- package/dist/tools/v4/terminal/shellExec.js +81 -9
- package/dist/tools/v4/web/deepResearch.js +1 -0
- package/dist/tools/v4/web/openUrl.js +1 -0
- package/dist/tools/v4/web/webFetch.js +1 -0
- package/dist/tools/v4/web/webPage.js +1 -0
- package/dist/tools/v4/web/webSearch.js +1 -0
- package/dist/tools/v4/web/youtubeSearch.js +1 -0
- package/package.json +7 -1
|
@@ -57,10 +57,14 @@ exports.CAPTCHA_MARKERS = [
|
|
|
57
57
|
'request unsuccessful',
|
|
58
58
|
'reference number',
|
|
59
59
|
'this website is using a security service',
|
|
60
|
-
// hCaptcha / reCAPTCHA explicit
|
|
60
|
+
// hCaptcha / reCAPTCHA / Turnstile explicit
|
|
61
61
|
'hcaptcha.com',
|
|
62
62
|
'recaptcha',
|
|
63
63
|
'g-recaptcha',
|
|
64
|
+
// v4.3 Phase 3 — Cloudflare Turnstile (newer than Cloudflare's
|
|
65
|
+
// older "Just a moment" interstitial; uses its own widget).
|
|
66
|
+
'cf-turnstile',
|
|
67
|
+
'turnstile',
|
|
64
68
|
// PerimeterX
|
|
65
69
|
'press and hold',
|
|
66
70
|
'human verification',
|
|
@@ -21,6 +21,7 @@ exports.fileCopyTool = void 0;
|
|
|
21
21
|
const node_fs_1 = require("node:fs");
|
|
22
22
|
const node_path_1 = __importDefault(require("node:path"));
|
|
23
23
|
const paths_1 = require("../utils/paths");
|
|
24
|
+
const sandboxFs_1 = require("../../../core/v4/sandboxFs");
|
|
24
25
|
exports.fileCopyTool = {
|
|
25
26
|
schema: {
|
|
26
27
|
name: 'file_copy',
|
|
@@ -37,6 +38,42 @@ exports.fileCopyTool = {
|
|
|
37
38
|
category: 'write',
|
|
38
39
|
mutates: true,
|
|
39
40
|
toolset: 'files',
|
|
41
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
42
|
+
// v4.4 Phase 4 — dry-run preview.
|
|
43
|
+
async buildPreview(args, ctx) {
|
|
44
|
+
const fromRaw = String(args.from ?? args.source ?? '').trim();
|
|
45
|
+
const toRaw = String(args.to ?? args.dest ?? args.destination ?? '').trim();
|
|
46
|
+
const src = (0, sandboxFs_1.isPathAllowed)(fromRaw, 'read', ctx.cwd);
|
|
47
|
+
const dst = (0, sandboxFs_1.isPathAllowed)(toRaw, 'write', ctx.cwd);
|
|
48
|
+
let srcExists = false;
|
|
49
|
+
try {
|
|
50
|
+
await node_fs_1.promises.stat(src.resolvedPath);
|
|
51
|
+
srcExists = true;
|
|
52
|
+
}
|
|
53
|
+
catch { /* missing */ }
|
|
54
|
+
if (!src.allowed) {
|
|
55
|
+
return {
|
|
56
|
+
tool: 'file_copy', args, riskTier: 'caution', detectedRisks: [],
|
|
57
|
+
sideEffects: [{ type: 'refuse', reason: src.violation.message }],
|
|
58
|
+
summary: `Refused (source): ${src.violation.code}`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (!dst.allowed) {
|
|
62
|
+
return {
|
|
63
|
+
tool: 'file_copy', args, riskTier: 'caution', detectedRisks: [],
|
|
64
|
+
sideEffects: [{ type: 'refuse', reason: dst.violation.message }],
|
|
65
|
+
summary: `Refused (dest): ${dst.violation.code}`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
tool: 'file_copy',
|
|
70
|
+
args,
|
|
71
|
+
riskTier: 'caution',
|
|
72
|
+
sideEffects: [{ type: 'copy_path', from: src.resolvedPath, to: dst.resolvedPath, src_exists: srcExists }],
|
|
73
|
+
detectedRisks: [],
|
|
74
|
+
summary: `Would copy ${src.resolvedPath} → ${dst.resolvedPath}${srcExists ? '' : ' (source missing)'}`,
|
|
75
|
+
};
|
|
76
|
+
},
|
|
40
77
|
async execute(args, ctx) {
|
|
41
78
|
const fromRaw = String(args.from ?? args.source ?? '').trim();
|
|
42
79
|
const toRaw = String(args.to ?? args.dest ?? args.destination ?? '').trim();
|
|
@@ -46,8 +83,25 @@ exports.fileCopyTool = {
|
|
|
46
83
|
if ((0, paths_1.isProtectedPath)(fromRaw) || (0, paths_1.isProtectedPath)(toRaw)) {
|
|
47
84
|
return { success: false, error: 'Access denied: protected path' };
|
|
48
85
|
}
|
|
49
|
-
|
|
50
|
-
const
|
|
86
|
+
// v4.4 Phase 2 — sandbox preflight (source = read, dest = write).
|
|
87
|
+
const srcPolicy = (0, sandboxFs_1.isPathAllowed)(fromRaw, 'read', ctx.cwd);
|
|
88
|
+
if (!srcPolicy.allowed) {
|
|
89
|
+
return {
|
|
90
|
+
success: false,
|
|
91
|
+
error: srcPolicy.violation.message,
|
|
92
|
+
sandbox_violation: (0, sandboxFs_1.violationEnvelope)(srcPolicy),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const dstPolicy = (0, sandboxFs_1.isPathAllowed)(toRaw, 'write', ctx.cwd);
|
|
96
|
+
if (!dstPolicy.allowed) {
|
|
97
|
+
return {
|
|
98
|
+
success: false,
|
|
99
|
+
error: dstPolicy.violation.message,
|
|
100
|
+
sandbox_violation: (0, sandboxFs_1.violationEnvelope)(dstPolicy),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const from = srcPolicy.resolvedPath;
|
|
104
|
+
const to = dstPolicy.resolvedPath;
|
|
51
105
|
try {
|
|
52
106
|
await node_fs_1.promises.mkdir(node_path_1.default.dirname(to), { recursive: true });
|
|
53
107
|
await node_fs_1.promises.cp(from, to, { recursive: true });
|
|
@@ -19,6 +19,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
19
19
|
exports.fileDeleteTool = void 0;
|
|
20
20
|
const node_fs_1 = require("node:fs");
|
|
21
21
|
const paths_1 = require("../utils/paths");
|
|
22
|
+
const sandboxFs_1 = require("../../../core/v4/sandboxFs");
|
|
22
23
|
exports.fileDeleteTool = {
|
|
23
24
|
schema: {
|
|
24
25
|
name: 'file_delete',
|
|
@@ -38,6 +39,33 @@ exports.fileDeleteTool = {
|
|
|
38
39
|
category: 'write',
|
|
39
40
|
mutates: true,
|
|
40
41
|
toolset: 'files',
|
|
42
|
+
riskTier: 'dangerous', // v4.4 Phase 1 — irreversible filesystem mutation
|
|
43
|
+
// v4.4 Phase 4 — dry-run preview.
|
|
44
|
+
async buildPreview(args, ctx) {
|
|
45
|
+
const raw = String(args.path ?? args.file ?? '').trim();
|
|
46
|
+
const recursive = args.recursive === true;
|
|
47
|
+
const policy = (0, sandboxFs_1.isPathAllowed)(raw, 'delete', ctx.cwd);
|
|
48
|
+
const resolved = policy.resolvedPath;
|
|
49
|
+
let exists = false;
|
|
50
|
+
try {
|
|
51
|
+
await node_fs_1.promises.stat(resolved);
|
|
52
|
+
exists = true;
|
|
53
|
+
}
|
|
54
|
+
catch { /* missing */ }
|
|
55
|
+
const sideEffects = policy.allowed
|
|
56
|
+
? [{ type: 'delete_file', path: resolved, exists, recursive }]
|
|
57
|
+
: [{ type: 'refuse', reason: policy.violation.message }];
|
|
58
|
+
return {
|
|
59
|
+
tool: 'file_delete',
|
|
60
|
+
args,
|
|
61
|
+
riskTier: 'dangerous',
|
|
62
|
+
sideEffects,
|
|
63
|
+
detectedRisks: policy.allowed && recursive ? ['recursive_delete'] : [],
|
|
64
|
+
summary: policy.allowed
|
|
65
|
+
? `Would ${recursive ? 'recursively ' : ''}delete ${resolved}${exists ? '' : ' (does not exist)'}`
|
|
66
|
+
: `Refused: ${policy.violation.code}`,
|
|
67
|
+
};
|
|
68
|
+
},
|
|
41
69
|
async execute(args, ctx) {
|
|
42
70
|
const raw = String(args.path ?? args.file ?? '').trim();
|
|
43
71
|
if (!raw)
|
|
@@ -45,7 +73,16 @@ exports.fileDeleteTool = {
|
|
|
45
73
|
if ((0, paths_1.isProtectedPath)(raw)) {
|
|
46
74
|
return { success: false, error: 'Access denied: protected path' };
|
|
47
75
|
}
|
|
48
|
-
|
|
76
|
+
// v4.4 Phase 2 — sandbox preflight (no-op when AIDEN_SANDBOX!=1).
|
|
77
|
+
const policy = (0, sandboxFs_1.isPathAllowed)(raw, 'delete', ctx.cwd);
|
|
78
|
+
if (!policy.allowed) {
|
|
79
|
+
return {
|
|
80
|
+
success: false,
|
|
81
|
+
error: policy.violation.message,
|
|
82
|
+
sandbox_violation: (0, sandboxFs_1.violationEnvelope)(policy),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const resolved = policy.resolvedPath;
|
|
49
86
|
if ((0, paths_1.isFilesystemRoot)(resolved)) {
|
|
50
87
|
return { success: false, error: 'Refusing to delete filesystem root' };
|
|
51
88
|
}
|
|
@@ -22,6 +22,7 @@ exports.fileListTool = void 0;
|
|
|
22
22
|
const node_fs_1 = require("node:fs");
|
|
23
23
|
const node_path_1 = __importDefault(require("node:path"));
|
|
24
24
|
const node_os_1 = __importDefault(require("node:os"));
|
|
25
|
+
const sandboxFs_1 = require("../../../core/v4/sandboxFs");
|
|
25
26
|
function expandPath(input, cwd) {
|
|
26
27
|
const home = node_os_1.default.homedir();
|
|
27
28
|
let p = input;
|
|
@@ -54,9 +55,19 @@ exports.fileListTool = {
|
|
|
54
55
|
category: 'read',
|
|
55
56
|
mutates: false,
|
|
56
57
|
toolset: 'files',
|
|
58
|
+
riskTier: 'safe', // v4.4 Phase 1
|
|
57
59
|
async execute(args, ctx) {
|
|
58
60
|
const raw = String(args.path ?? args.dir ?? ctx.cwd).trim();
|
|
59
|
-
|
|
61
|
+
// v4.4 Phase 2 — sandbox preflight (no-op when AIDEN_SANDBOX!=1).
|
|
62
|
+
const policy = (0, sandboxFs_1.isPathAllowed)(raw || ctx.cwd, 'read', ctx.cwd);
|
|
63
|
+
if (!policy.allowed) {
|
|
64
|
+
return {
|
|
65
|
+
success: false,
|
|
66
|
+
error: policy.violation.message,
|
|
67
|
+
sandbox_violation: (0, sandboxFs_1.violationEnvelope)(policy),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const resolved = policy.resolvedPath;
|
|
60
71
|
try {
|
|
61
72
|
const entries = await node_fs_1.promises.readdir(resolved, { withFileTypes: true });
|
|
62
73
|
const items = entries.map((e) => ({
|
|
@@ -22,6 +22,7 @@ exports.fileMoveTool = void 0;
|
|
|
22
22
|
const node_fs_1 = require("node:fs");
|
|
23
23
|
const node_path_1 = __importDefault(require("node:path"));
|
|
24
24
|
const paths_1 = require("../utils/paths");
|
|
25
|
+
const sandboxFs_1 = require("../../../core/v4/sandboxFs");
|
|
25
26
|
exports.fileMoveTool = {
|
|
26
27
|
schema: {
|
|
27
28
|
name: 'file_move',
|
|
@@ -38,6 +39,42 @@ exports.fileMoveTool = {
|
|
|
38
39
|
category: 'write',
|
|
39
40
|
mutates: true,
|
|
40
41
|
toolset: 'files',
|
|
42
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
43
|
+
// v4.4 Phase 4 — dry-run preview.
|
|
44
|
+
async buildPreview(args, ctx) {
|
|
45
|
+
const fromRaw = String(args.from ?? args.source ?? '').trim();
|
|
46
|
+
const toRaw = String(args.to ?? args.dest ?? args.destination ?? '').trim();
|
|
47
|
+
const src = (0, sandboxFs_1.isPathAllowed)(fromRaw, 'write', ctx.cwd);
|
|
48
|
+
const dst = (0, sandboxFs_1.isPathAllowed)(toRaw, 'write', ctx.cwd);
|
|
49
|
+
let srcExists = false;
|
|
50
|
+
try {
|
|
51
|
+
await node_fs_1.promises.stat(src.resolvedPath);
|
|
52
|
+
srcExists = true;
|
|
53
|
+
}
|
|
54
|
+
catch { /* missing */ }
|
|
55
|
+
if (!src.allowed) {
|
|
56
|
+
return {
|
|
57
|
+
tool: 'file_move', args, riskTier: 'caution', detectedRisks: [],
|
|
58
|
+
sideEffects: [{ type: 'refuse', reason: src.violation.message }],
|
|
59
|
+
summary: `Refused (source): ${src.violation.code}`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (!dst.allowed) {
|
|
63
|
+
return {
|
|
64
|
+
tool: 'file_move', args, riskTier: 'caution', detectedRisks: [],
|
|
65
|
+
sideEffects: [{ type: 'refuse', reason: dst.violation.message }],
|
|
66
|
+
summary: `Refused (dest): ${dst.violation.code}`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
tool: 'file_move',
|
|
71
|
+
args,
|
|
72
|
+
riskTier: 'caution',
|
|
73
|
+
sideEffects: [{ type: 'move_path', from: src.resolvedPath, to: dst.resolvedPath, src_exists: srcExists }],
|
|
74
|
+
detectedRisks: [],
|
|
75
|
+
summary: `Would move ${src.resolvedPath} → ${dst.resolvedPath}${srcExists ? '' : ' (source missing)'}`,
|
|
76
|
+
};
|
|
77
|
+
},
|
|
41
78
|
async execute(args, ctx) {
|
|
42
79
|
const fromRaw = String(args.from ?? args.source ?? '').trim();
|
|
43
80
|
const toRaw = String(args.to ?? args.dest ?? args.destination ?? '').trim();
|
|
@@ -47,8 +84,28 @@ exports.fileMoveTool = {
|
|
|
47
84
|
if ((0, paths_1.isProtectedPath)(fromRaw) || (0, paths_1.isProtectedPath)(toRaw)) {
|
|
48
85
|
return { success: false, error: 'Access denied: protected path' };
|
|
49
86
|
}
|
|
50
|
-
|
|
51
|
-
|
|
87
|
+
// v4.4 Phase 2 — sandbox preflight. Move = read source + write dest;
|
|
88
|
+
// since the source is also being deleted, this could arguably be
|
|
89
|
+
// 'delete' on source — but delete and write share the same allowlist
|
|
90
|
+
// semantics in the policy. 'read' on source matches copy's shape.
|
|
91
|
+
const srcPolicy = (0, sandboxFs_1.isPathAllowed)(fromRaw, 'write', ctx.cwd);
|
|
92
|
+
if (!srcPolicy.allowed) {
|
|
93
|
+
return {
|
|
94
|
+
success: false,
|
|
95
|
+
error: srcPolicy.violation.message,
|
|
96
|
+
sandbox_violation: (0, sandboxFs_1.violationEnvelope)(srcPolicy),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const dstPolicy = (0, sandboxFs_1.isPathAllowed)(toRaw, 'write', ctx.cwd);
|
|
100
|
+
if (!dstPolicy.allowed) {
|
|
101
|
+
return {
|
|
102
|
+
success: false,
|
|
103
|
+
error: dstPolicy.violation.message,
|
|
104
|
+
sandbox_violation: (0, sandboxFs_1.violationEnvelope)(dstPolicy),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const from = srcPolicy.resolvedPath;
|
|
108
|
+
const to = dstPolicy.resolvedPath;
|
|
52
109
|
try {
|
|
53
110
|
await node_fs_1.promises.mkdir(node_path_1.default.dirname(to), { recursive: true });
|
|
54
111
|
try {
|
|
@@ -19,6 +19,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
19
19
|
exports.filePatchTool = void 0;
|
|
20
20
|
const node_fs_1 = require("node:fs");
|
|
21
21
|
const paths_1 = require("../utils/paths");
|
|
22
|
+
const sandboxFs_1 = require("../../../core/v4/sandboxFs");
|
|
22
23
|
exports.filePatchTool = {
|
|
23
24
|
schema: {
|
|
24
25
|
name: 'file_patch',
|
|
@@ -40,6 +41,38 @@ exports.filePatchTool = {
|
|
|
40
41
|
category: 'write',
|
|
41
42
|
mutates: true,
|
|
42
43
|
toolset: 'files',
|
|
44
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
45
|
+
// v4.4 Phase 4 — dry-run preview.
|
|
46
|
+
async buildPreview(args, ctx) {
|
|
47
|
+
const raw = String(args.path ?? args.file ?? '').trim();
|
|
48
|
+
const find = typeof args.find === 'string' ? args.find : '';
|
|
49
|
+
const replace = typeof args.replace === 'string' ? args.replace : '';
|
|
50
|
+
const policy = (0, sandboxFs_1.isPathAllowed)(raw, 'write', ctx.cwd);
|
|
51
|
+
const resolved = policy.resolvedPath;
|
|
52
|
+
let matches = 0;
|
|
53
|
+
let bytesDelta = 0;
|
|
54
|
+
if (policy.allowed && find) {
|
|
55
|
+
try {
|
|
56
|
+
const txt = await node_fs_1.promises.readFile(resolved, 'utf-8');
|
|
57
|
+
matches = txt.split(find).length - 1;
|
|
58
|
+
bytesDelta = matches * (Buffer.byteLength(replace, 'utf-8') - Buffer.byteLength(find, 'utf-8'));
|
|
59
|
+
}
|
|
60
|
+
catch { /* file may not exist — surfaced as 0 matches */ }
|
|
61
|
+
}
|
|
62
|
+
const sideEffects = policy.allowed
|
|
63
|
+
? [{ type: 'patch_file', path: resolved, matches, bytes_delta: bytesDelta }]
|
|
64
|
+
: [{ type: 'refuse', reason: policy.violation.message }];
|
|
65
|
+
return {
|
|
66
|
+
tool: 'file_patch',
|
|
67
|
+
args,
|
|
68
|
+
riskTier: 'caution',
|
|
69
|
+
sideEffects,
|
|
70
|
+
detectedRisks: [],
|
|
71
|
+
summary: policy.allowed
|
|
72
|
+
? `Would patch ${resolved} (${matches} match${matches === 1 ? '' : 'es'}, Δ ${bytesDelta} bytes)`
|
|
73
|
+
: `Refused: ${policy.violation.code}`,
|
|
74
|
+
};
|
|
75
|
+
},
|
|
43
76
|
async execute(args, ctx) {
|
|
44
77
|
const raw = String(args.path ?? args.file ?? '').trim();
|
|
45
78
|
if (!raw)
|
|
@@ -47,12 +80,21 @@ exports.filePatchTool = {
|
|
|
47
80
|
if ((0, paths_1.isProtectedPath)(raw)) {
|
|
48
81
|
return { success: false, error: 'Access denied: protected path' };
|
|
49
82
|
}
|
|
83
|
+
// v4.4 Phase 2 — sandbox preflight (no-op when AIDEN_SANDBOX!=1).
|
|
84
|
+
const policy = (0, sandboxFs_1.isPathAllowed)(raw, 'write', ctx.cwd);
|
|
85
|
+
if (!policy.allowed) {
|
|
86
|
+
return {
|
|
87
|
+
success: false,
|
|
88
|
+
error: policy.violation.message,
|
|
89
|
+
sandbox_violation: (0, sandboxFs_1.violationEnvelope)(policy),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
50
92
|
const find = typeof args.find === 'string' ? args.find : '';
|
|
51
93
|
const replace = typeof args.replace === 'string' ? args.replace : '';
|
|
52
94
|
if (!find)
|
|
53
95
|
return { success: false, error: 'Empty find string' };
|
|
54
96
|
const replaceAll = args.replace_all === true;
|
|
55
|
-
const resolved =
|
|
97
|
+
const resolved = policy.resolvedPath;
|
|
56
98
|
try {
|
|
57
99
|
const original = await node_fs_1.promises.readFile(resolved, 'utf-8');
|
|
58
100
|
const occurrences = original.split(find).length - 1;
|
|
@@ -24,6 +24,7 @@ exports.fileReadTool = void 0;
|
|
|
24
24
|
const node_fs_1 = require("node:fs");
|
|
25
25
|
const node_path_1 = __importDefault(require("node:path"));
|
|
26
26
|
const node_os_1 = __importDefault(require("node:os"));
|
|
27
|
+
const sandboxFs_1 = require("../../../core/v4/sandboxFs");
|
|
27
28
|
const MAX_OUTPUT = 5000;
|
|
28
29
|
const DENY_PATTERNS = [
|
|
29
30
|
/[\\/]\.ssh[\\/]/i,
|
|
@@ -73,6 +74,7 @@ exports.fileReadTool = {
|
|
|
73
74
|
category: 'read',
|
|
74
75
|
mutates: false,
|
|
75
76
|
toolset: 'files',
|
|
77
|
+
riskTier: 'safe', // v4.4 Phase 1
|
|
76
78
|
async execute(args, ctx) {
|
|
77
79
|
const raw = String(args.path ?? args.file ?? '').trim();
|
|
78
80
|
if (!raw)
|
|
@@ -83,7 +85,16 @@ exports.fileReadTool = {
|
|
|
83
85
|
error: 'Access denied: protected path (credentials/keys/.env)',
|
|
84
86
|
};
|
|
85
87
|
}
|
|
86
|
-
|
|
88
|
+
// v4.4 Phase 2 — sandbox preflight (no-op when AIDEN_SANDBOX!=1).
|
|
89
|
+
const policy = (0, sandboxFs_1.isPathAllowed)(raw, 'read', ctx.cwd);
|
|
90
|
+
if (!policy.allowed) {
|
|
91
|
+
return {
|
|
92
|
+
success: false,
|
|
93
|
+
error: policy.violation.message,
|
|
94
|
+
sandbox_violation: (0, sandboxFs_1.violationEnvelope)(policy),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const resolved = policy.resolvedPath;
|
|
87
98
|
try {
|
|
88
99
|
const content = await node_fs_1.promises.readFile(resolved, 'utf-8');
|
|
89
100
|
return {
|
|
@@ -23,6 +23,8 @@ exports.fileWriteTool = void 0;
|
|
|
23
23
|
const node_fs_1 = require("node:fs");
|
|
24
24
|
const node_path_1 = __importDefault(require("node:path"));
|
|
25
25
|
const paths_1 = require("../utils/paths");
|
|
26
|
+
const sandboxFs_1 = require("../../../core/v4/sandboxFs");
|
|
27
|
+
const dryRun_1 = require("../../../core/v4/dryRun");
|
|
26
28
|
exports.fileWriteTool = {
|
|
27
29
|
schema: {
|
|
28
30
|
name: 'file_write',
|
|
@@ -39,6 +41,35 @@ exports.fileWriteTool = {
|
|
|
39
41
|
category: 'write',
|
|
40
42
|
mutates: true,
|
|
41
43
|
toolset: 'files',
|
|
44
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
45
|
+
// v4.4 Phase 4 — dry-run preview.
|
|
46
|
+
async buildPreview(args, ctx) {
|
|
47
|
+
const raw = String(args.path ?? args.file ?? '').trim();
|
|
48
|
+
const content = typeof args.content === 'string' ? args.content : '';
|
|
49
|
+
const policy = (0, sandboxFs_1.isPathAllowed)(raw, 'write', ctx.cwd);
|
|
50
|
+
const resolved = policy.resolvedPath;
|
|
51
|
+
let prevBytes;
|
|
52
|
+
try {
|
|
53
|
+
prevBytes = (await node_fs_1.promises.stat(resolved)).size;
|
|
54
|
+
}
|
|
55
|
+
catch { /* didn't exist */ }
|
|
56
|
+
const newBytes = Buffer.byteLength(content, 'utf-8');
|
|
57
|
+
const sideEffects = policy.allowed
|
|
58
|
+
? [prevBytes !== undefined
|
|
59
|
+
? { type: 'overwrite_file', path: resolved, prev_bytes: prevBytes, new_bytes: newBytes, preview: (0, dryRun_1.truncatePreview)(content) }
|
|
60
|
+
: { type: 'create_file', path: resolved, bytes: newBytes, preview: (0, dryRun_1.truncatePreview)(content) }]
|
|
61
|
+
: [{ type: 'refuse', reason: policy.violation.message }];
|
|
62
|
+
return {
|
|
63
|
+
tool: 'file_write',
|
|
64
|
+
args,
|
|
65
|
+
riskTier: 'caution',
|
|
66
|
+
sideEffects,
|
|
67
|
+
detectedRisks: [],
|
|
68
|
+
summary: policy.allowed
|
|
69
|
+
? `Would write ${newBytes} bytes to ${resolved}`
|
|
70
|
+
: `Refused: ${policy.violation.code}`,
|
|
71
|
+
};
|
|
72
|
+
},
|
|
42
73
|
async execute(args, ctx) {
|
|
43
74
|
const raw = String(args.path ?? args.file ?? '').trim();
|
|
44
75
|
if (!raw)
|
|
@@ -46,8 +77,17 @@ exports.fileWriteTool = {
|
|
|
46
77
|
if ((0, paths_1.isProtectedPath)(raw)) {
|
|
47
78
|
return { success: false, error: 'Access denied: protected path' };
|
|
48
79
|
}
|
|
80
|
+
// v4.4 Phase 2 — sandbox preflight (no-op when AIDEN_SANDBOX!=1).
|
|
81
|
+
const policy = (0, sandboxFs_1.isPathAllowed)(raw, 'write', ctx.cwd);
|
|
82
|
+
if (!policy.allowed) {
|
|
83
|
+
return {
|
|
84
|
+
success: false,
|
|
85
|
+
error: policy.violation.message,
|
|
86
|
+
sandbox_violation: (0, sandboxFs_1.violationEnvelope)(policy),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
49
89
|
const content = typeof args.content === 'string' ? args.content : '';
|
|
50
|
-
const resolved =
|
|
90
|
+
const resolved = policy.resolvedPath;
|
|
51
91
|
try {
|
|
52
92
|
await node_fs_1.promises.mkdir(node_path_1.default.dirname(resolved), { recursive: true });
|
|
53
93
|
await node_fs_1.promises.writeFile(resolved, content, 'utf-8');
|
package/dist/tools/v4/index.js
CHANGED
|
@@ -26,6 +26,7 @@ exports.sessionSummaryTool = exports.memoryRemoveTool = void 0;
|
|
|
26
26
|
exports.registerReadOnlyTools = registerReadOnlyTools;
|
|
27
27
|
exports.registerWriteTools = registerWriteTools;
|
|
28
28
|
exports.registerAllTools = registerAllTools;
|
|
29
|
+
const dryRun_1 = require("../../core/v4/dryRun");
|
|
29
30
|
const webSearch_1 = require("./web/webSearch");
|
|
30
31
|
const webFetch_1 = require("./web/webFetch");
|
|
31
32
|
const webPage_1 = require("./web/webPage");
|
|
@@ -96,54 +97,61 @@ const subagentFanout_1 = require("./subagent/subagentFanout");
|
|
|
96
97
|
* the full set).
|
|
97
98
|
*/
|
|
98
99
|
function registerReadOnlyTools(registry) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
// v4.4 Phase 4 — every handler is funneled through withDryRun so
|
|
101
|
+
// AIDEN_DRYRUN=1 short-circuits `execute` to a preview. Read-only
|
|
102
|
+
// tools pass through unchanged (the HOC returns the handler as-is
|
|
103
|
+
// when `mutates: false`); the wrapper is cheap (`if (!mutates)
|
|
104
|
+
// return handler`) and keeps the registration call sites uniform
|
|
105
|
+
// across read/write tool sets.
|
|
106
|
+
const register = (h) => registry.register((0, dryRun_1.withDryRun)(h));
|
|
107
|
+
register(webSearch_1.webSearchTool);
|
|
108
|
+
register(webFetch_1.webFetchTool);
|
|
109
|
+
register(webPage_1.webPageTool);
|
|
110
|
+
register(deepResearch_1.deepResearchTool);
|
|
103
111
|
// Phase 16f: open_url uses shell launch (start chrome / open / xdg-open)
|
|
104
112
|
// for "open X in browser" requests — bypasses Playwright detection.
|
|
105
|
-
|
|
113
|
+
register(openUrl_1.openUrlTool);
|
|
106
114
|
// Phase 23.4a: youtube_search returns real /watch?v= URLs scraped
|
|
107
115
|
// from youtube.com/results. media-search uses it before open_url so
|
|
108
116
|
// the URL provenance gate has a candidate set to validate against —
|
|
109
117
|
// closes the URL-hallucination failure mode where the model invented
|
|
110
118
|
// 11-char IDs.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
register(youtubeSearch_1.youtubeSearchTool);
|
|
120
|
+
register(fileRead_1.fileReadTool);
|
|
121
|
+
register(fileList_1.fileListTool);
|
|
122
|
+
register(browserScreenshot_1.browserScreenshotTool);
|
|
123
|
+
register(browserExtract_1.browserExtractTool);
|
|
124
|
+
register(browserGetUrl_1.browserGetUrlTool);
|
|
125
|
+
register(sessionSearch_1.sessionSearchTool);
|
|
126
|
+
register(sessionList_1.sessionListTool);
|
|
119
127
|
// Phase v4.1.2-memory-C: recall_session reads SessionDistillation
|
|
120
128
|
// files written by Phase A+B. Sits alongside session_search — the
|
|
121
129
|
// two have distinct purposes (FTS5-over-messages vs ranked
|
|
122
130
|
// distillation summaries); descriptions force the right model
|
|
123
131
|
// choice.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
132
|
+
register(recallSession_1.recallSessionTool);
|
|
133
|
+
register(skillsList_1.skillsListTool);
|
|
134
|
+
register(skillView_1.skillViewTool);
|
|
135
|
+
register(systemInfo_1.systemInfoTool);
|
|
136
|
+
register(nowPlaying_1.nowPlayingTool);
|
|
137
|
+
register(naturalEvents_1.naturalEventsTool);
|
|
130
138
|
// Phase v4.1.2-followup-3 — computer-control read-only tools.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
register(screenshot_1.screenshotTool);
|
|
140
|
+
register(osProcessList_1.osProcessListTool);
|
|
141
|
+
register(clipboardRead_1.clipboardReadTool);
|
|
134
142
|
// v4.1.4-media — GSMTC session enumeration (read). Pair with
|
|
135
143
|
// mediaTransport (write) in the write-tools registration below.
|
|
136
|
-
|
|
137
|
-
|
|
144
|
+
register(mediaSessions_1.mediaSessionsTool);
|
|
145
|
+
register((0, lookupToolSchema_1.makeLookupToolSchema)(registry));
|
|
138
146
|
// Phase v4.1-subagent — register a stub for subagent_fanout so its
|
|
139
147
|
// schema is visible to the agent loop, the MCP server, and the
|
|
140
148
|
// /tools slash command BEFORE the runtime resolves provider /
|
|
141
149
|
// adapter / agent dependencies. The full runtime calls
|
|
142
|
-
// `
|
|
150
|
+
// `register(makeSubagentFanoutTool({...real opts}))` to
|
|
143
151
|
// replace this stub once `buildAgentRuntime` has those handles.
|
|
144
152
|
// Until then, calling the stub returns a clear "not wired" error
|
|
145
153
|
// rather than crashing.
|
|
146
|
-
|
|
154
|
+
register(makeSubagentFanoutStub());
|
|
147
155
|
}
|
|
148
156
|
/** Stub used until the runtime wires real provider / adapter / agent
|
|
149
157
|
* dependencies. Returns the SAME schema as the real tool so MCP and
|
|
@@ -156,7 +164,7 @@ function makeSubagentFanoutStub() {
|
|
|
156
164
|
apiMode: 'chat_completions',
|
|
157
165
|
async call() {
|
|
158
166
|
throw new Error('subagent_fanout: tool not wired — runtime did not replace the stub. ' +
|
|
159
|
-
'Call
|
|
167
|
+
'Call register(makeSubagentFanoutTool({...})) after buildAgentRuntime.');
|
|
160
168
|
},
|
|
161
169
|
},
|
|
162
170
|
runChild: async () => {
|
|
@@ -170,50 +178,55 @@ function makeSubagentFanoutStub() {
|
|
|
170
178
|
* engine — the registration order doesn't matter for that.
|
|
171
179
|
*/
|
|
172
180
|
function registerWriteTools(registry) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
registry.register(
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
181
|
+
// v4.4 Phase 4 — same withDryRun wrap as registerReadOnlyTools.
|
|
182
|
+
// Write tools are where the preview path is actually hot — when
|
|
183
|
+
// AIDEN_DRYRUN=1, each handler's `buildPreview` is called instead
|
|
184
|
+
// of `execute`.
|
|
185
|
+
const register = (h) => registry.register((0, dryRun_1.withDryRun)(h));
|
|
186
|
+
register(fileWrite_1.fileWriteTool);
|
|
187
|
+
register(filePatch_1.filePatchTool);
|
|
188
|
+
register(fileDelete_1.fileDeleteTool);
|
|
189
|
+
register(fileMove_1.fileMoveTool);
|
|
190
|
+
register(fileCopy_1.fileCopyTool);
|
|
191
|
+
register(shellExec_1.shellExecTool);
|
|
192
|
+
register(browserNavigate_1.browserNavigateTool);
|
|
193
|
+
register(browserClick_1.browserClickTool);
|
|
194
|
+
register(browserType_1.browserTypeTool);
|
|
195
|
+
register(browserFill_1.browserFillTool);
|
|
196
|
+
register(browserScroll_1.browserScrollTool);
|
|
197
|
+
register(browserClose_1.browserCloseTool);
|
|
198
|
+
register(executeCode_1.executeCodeTool);
|
|
199
|
+
register(processSpawn_1.processSpawnTool);
|
|
200
|
+
register(processList_1.processListTool);
|
|
201
|
+
register(processLogRead_1.processLogReadTool);
|
|
202
|
+
register(processKill_1.processKillTool);
|
|
203
|
+
register(processWait_1.processWaitTool);
|
|
191
204
|
// Phase 9: memory write tools (gated by MemoryGuard for read-back
|
|
192
205
|
// verification, then by the approval engine like every other write).
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
206
|
+
register(memoryAdd_1.memoryAddTool);
|
|
207
|
+
register(memoryReplace_1.memoryReplaceTool);
|
|
208
|
+
register(memoryRemove_1.memoryRemoveTool);
|
|
196
209
|
// Phase v4.1.2 alive-core: cross-session continuity via /quit auto-summary.
|
|
197
|
-
|
|
210
|
+
register(sessionSummary_1.sessionSummaryTool);
|
|
198
211
|
// Phase 10: skill_manage — mutating, also goes through the approval
|
|
199
212
|
// engine. skills_list / skill_view stay in registerReadOnlyTools.
|
|
200
|
-
|
|
213
|
+
register(skillManage_1.skillManageTool);
|
|
201
214
|
// Phase v4.1.2-update: natural-language entry to the same install
|
|
202
215
|
// executor that /update install uses. Two-step confirmation gate
|
|
203
216
|
// (confirm:false → status; confirm:true → install).
|
|
204
|
-
|
|
217
|
+
register(aidenSelfUpdate_1.aidenSelfUpdateTool);
|
|
205
218
|
// Phase v4.1.2-followup-3 — computer-control mutating tools. All
|
|
206
219
|
// route through the approval engine like every other write.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
220
|
+
register(mediaKey_1.mediaKeyTool);
|
|
221
|
+
register(volumeSet_1.volumeSetTool);
|
|
222
|
+
register(appLaunch_1.appLaunchTool);
|
|
223
|
+
register(appClose_1.appCloseTool);
|
|
224
|
+
register(clipboardWrite_1.clipboardWriteTool);
|
|
212
225
|
// v4.1.4-media — verified GSMTC transport (replaces mediaKey for
|
|
213
226
|
// the "name an app, play/pause it" case) + focused-window SendKeys
|
|
214
227
|
// (escape hatch when GSMTC doesn't enumerate the surface).
|
|
215
|
-
|
|
216
|
-
|
|
228
|
+
register(mediaTransport_1.mediaTransportTool);
|
|
229
|
+
register(appInput_1.appInputTool);
|
|
217
230
|
}
|
|
218
231
|
/** Register every v4 tool. Most callers want this. */
|
|
219
232
|
function registerAllTools(registry) {
|