aiden-runtime 4.1.4 → 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 +379 -53
- package/dist/cli/v4/callbacks.js +248 -0
- package/dist/cli/v4/chatSession.js +292 -4
- 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 +75 -3
- package/dist/cli/v4/display/capabilityCard.js +26 -0
- package/dist/cli/v4/display/progressBar.js +41 -8
- package/dist/cli/v4/display.js +258 -15
- package/dist/cli/v4/replyRenderer.js +31 -23
- package/dist/cli/v4/toolPreview.js +10 -0
- package/dist/cli/v4/updateBootPrompt.js +170 -0
- package/dist/core/playwrightBridge.js +129 -0
- package/dist/core/toolRegistry.js +7 -1
- package/dist/core/v4/aidenAgent.js +371 -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/loopTrace.js +257 -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/core/webSearch.js +64 -24
- 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
- package/plugins/aiden-plugin-cdp-browser/.granted-permissions.json +8 -0
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.browserExtractTool = void 0;
|
|
20
20
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
21
|
-
|
|
21
|
+
const _observer_1 = require("./_observer");
|
|
22
|
+
const _browserExtractTool = {
|
|
22
23
|
schema: {
|
|
23
24
|
name: 'browser_extract',
|
|
24
25
|
description: 'Extract the visible text content of the current browser page. Requires the browser to be on a page (navigate first using a Phase-8 navigation tool, or via the search-then-click flow).',
|
|
@@ -30,6 +31,7 @@ exports.browserExtractTool = {
|
|
|
30
31
|
category: 'browser',
|
|
31
32
|
mutates: false,
|
|
32
33
|
toolset: 'browser',
|
|
34
|
+
riskTier: 'safe', // v4.4 Phase 1
|
|
33
35
|
async execute() {
|
|
34
36
|
const r = await (0, playwrightBridge_1.pwSnapshot)();
|
|
35
37
|
if (r.ok)
|
|
@@ -37,3 +39,5 @@ exports.browserExtractTool = {
|
|
|
37
39
|
return { success: false, error: r.error };
|
|
38
40
|
},
|
|
39
41
|
};
|
|
42
|
+
// v4.3 Phase 1 — observer HOC.
|
|
43
|
+
exports.browserExtractTool = (0, _observer_1.withBrowserState)(_browserExtractTool);
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.browserFillTool = void 0;
|
|
19
19
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
20
|
-
|
|
20
|
+
const _observer_1 = require("./_observer");
|
|
21
|
+
const _browserFillTool = {
|
|
21
22
|
schema: {
|
|
22
23
|
name: 'browser_fill',
|
|
23
24
|
description: 'Fill multiple form fields. Pass `fields` as an object mapping CSS selectors to text values.',
|
|
@@ -35,6 +36,19 @@ exports.browserFillTool = {
|
|
|
35
36
|
category: 'browser',
|
|
36
37
|
mutates: true,
|
|
37
38
|
toolset: 'browser',
|
|
39
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
40
|
+
buildPreview(args) {
|
|
41
|
+
const fields = (args.fields ?? {});
|
|
42
|
+
const keys = fields && typeof fields === 'object' ? Object.keys(fields) : [];
|
|
43
|
+
return {
|
|
44
|
+
tool: 'browser_fill',
|
|
45
|
+
args,
|
|
46
|
+
riskTier: 'caution',
|
|
47
|
+
sideEffects: [{ type: 'browser_action', action: 'fill', target: keys.join(', ') }],
|
|
48
|
+
detectedRisks: [],
|
|
49
|
+
summary: `Would fill ${keys.length} form field${keys.length === 1 ? '' : 's'}: ${keys.join(', ')}`,
|
|
50
|
+
};
|
|
51
|
+
},
|
|
38
52
|
async execute(args) {
|
|
39
53
|
const fields = (args.fields ?? {});
|
|
40
54
|
if (!fields || typeof fields !== 'object' || Array.isArray(fields)) {
|
|
@@ -57,3 +71,5 @@ exports.browserFillTool = {
|
|
|
57
71
|
return { success: true, filled, count: filled.length };
|
|
58
72
|
},
|
|
59
73
|
};
|
|
74
|
+
// v4.3 Phase 1 — observer HOC.
|
|
75
|
+
exports.browserFillTool = (0, _observer_1.withBrowserState)(_browserFillTool);
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.browserGetUrlTool = void 0;
|
|
18
18
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
19
|
-
|
|
19
|
+
const _observer_1 = require("./_observer");
|
|
20
|
+
const _browserGetUrlTool = {
|
|
20
21
|
schema: {
|
|
21
22
|
name: 'browser_get_url',
|
|
22
23
|
description: 'Return the URL of the page currently loaded in the browser. Useful for verifying navigation succeeded after a click.',
|
|
@@ -28,6 +29,7 @@ exports.browserGetUrlTool = {
|
|
|
28
29
|
category: 'browser',
|
|
29
30
|
mutates: false,
|
|
30
31
|
toolset: 'browser',
|
|
32
|
+
riskTier: 'safe', // v4.4 Phase 1
|
|
31
33
|
async execute() {
|
|
32
34
|
const r = await (0, playwrightBridge_1.pwGetUrl)();
|
|
33
35
|
if (r.ok)
|
|
@@ -35,3 +37,5 @@ exports.browserGetUrlTool = {
|
|
|
35
37
|
return { success: false, error: r.error };
|
|
36
38
|
},
|
|
37
39
|
};
|
|
40
|
+
// v4.3 Phase 1 — observer HOC.
|
|
41
|
+
exports.browserGetUrlTool = (0, _observer_1.withBrowserState)(_browserGetUrlTool);
|
|
@@ -18,7 +18,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
18
18
|
exports.browserNavigateTool = void 0;
|
|
19
19
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
20
20
|
const captchaCheck_1 = require("./captchaCheck");
|
|
21
|
-
|
|
21
|
+
const _observer_1 = require("./_observer");
|
|
22
|
+
const _browserNavigateTool = {
|
|
22
23
|
schema: {
|
|
23
24
|
name: 'browser_navigate',
|
|
24
25
|
description: 'Navigate the browser to a URL. Reuses the active tab; opens one if none exists. ' +
|
|
@@ -35,6 +36,18 @@ exports.browserNavigateTool = {
|
|
|
35
36
|
category: 'browser',
|
|
36
37
|
mutates: true,
|
|
37
38
|
toolset: 'browser',
|
|
39
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
40
|
+
buildPreview(args) {
|
|
41
|
+
const url = String(args.url ?? '');
|
|
42
|
+
return {
|
|
43
|
+
tool: 'browser_navigate',
|
|
44
|
+
args,
|
|
45
|
+
riskTier: 'caution',
|
|
46
|
+
sideEffects: [{ type: 'browser_action', action: 'navigate', url }],
|
|
47
|
+
detectedRisks: [],
|
|
48
|
+
summary: `Would navigate browser to: ${url}`,
|
|
49
|
+
};
|
|
50
|
+
},
|
|
38
51
|
async execute(args) {
|
|
39
52
|
const url = String(args.url ?? '').trim();
|
|
40
53
|
if (!url)
|
|
@@ -73,3 +86,5 @@ exports.browserNavigateTool = {
|
|
|
73
86
|
return { success: true, url: r.url };
|
|
74
87
|
},
|
|
75
88
|
};
|
|
89
|
+
// v4.3 Phase 1 — observer HOC.
|
|
90
|
+
exports.browserNavigateTool = (0, _observer_1.withBrowserState)(_browserNavigateTool);
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
exports.browserScreenshotTool = void 0;
|
|
24
24
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
25
|
-
|
|
25
|
+
const _observer_1 = require("./_observer");
|
|
26
|
+
const _browserScreenshotTool = {
|
|
26
27
|
schema: {
|
|
27
28
|
name: 'browser_screenshot',
|
|
28
29
|
description: 'Take a screenshot of the current browser page (the page you previously navigated to). Saves to disk and returns the file path. Requires that the browser was opened earlier in this session.',
|
|
@@ -34,6 +35,7 @@ exports.browserScreenshotTool = {
|
|
|
34
35
|
category: 'browser',
|
|
35
36
|
mutates: false,
|
|
36
37
|
toolset: 'browser',
|
|
38
|
+
riskTier: 'safe', // v4.4 Phase 1
|
|
37
39
|
async execute() {
|
|
38
40
|
const r = await (0, playwrightBridge_1.pwScreenshot)();
|
|
39
41
|
if (r.ok)
|
|
@@ -41,3 +43,5 @@ exports.browserScreenshotTool = {
|
|
|
41
43
|
return { success: false, error: r.error };
|
|
42
44
|
},
|
|
43
45
|
};
|
|
46
|
+
// v4.3 Phase 1 — observer HOC.
|
|
47
|
+
exports.browserScreenshotTool = (0, _observer_1.withBrowserState)(_browserScreenshotTool);
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.browserScrollTool = void 0;
|
|
19
19
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
20
|
-
|
|
20
|
+
const _observer_1 = require("./_observer");
|
|
21
|
+
const _browserScrollTool = {
|
|
21
22
|
schema: {
|
|
22
23
|
name: 'browser_scroll',
|
|
23
24
|
description: 'Scroll the browser page (or a specific element via `selector`). `direction` ∈ up|down|top|bottom; `amount` is pixels for up/down (default 500).',
|
|
@@ -43,6 +44,20 @@ exports.browserScrollTool = {
|
|
|
43
44
|
category: 'browser',
|
|
44
45
|
mutates: true,
|
|
45
46
|
toolset: 'browser',
|
|
47
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
48
|
+
buildPreview(args) {
|
|
49
|
+
const direction = String(args.direction ?? 'down');
|
|
50
|
+
const amount = typeof args.amount === 'number' ? args.amount : 500;
|
|
51
|
+
const selector = typeof args.selector === 'string' ? args.selector : '';
|
|
52
|
+
return {
|
|
53
|
+
tool: 'browser_scroll',
|
|
54
|
+
args,
|
|
55
|
+
riskTier: 'caution',
|
|
56
|
+
sideEffects: [{ type: 'browser_action', action: `scroll:${direction}`, target: selector || 'window' }],
|
|
57
|
+
detectedRisks: [],
|
|
58
|
+
summary: `Would scroll browser ${direction}${direction === 'up' || direction === 'down' ? ` ${amount}px` : ''}${selector ? ` (${selector})` : ''}`,
|
|
59
|
+
};
|
|
60
|
+
},
|
|
46
61
|
async execute(args) {
|
|
47
62
|
const directionRaw = String(args.direction ?? 'down').toLowerCase();
|
|
48
63
|
const direction = ['up', 'down', 'top', 'bottom'].includes(directionRaw)
|
|
@@ -56,3 +71,5 @@ exports.browserScrollTool = {
|
|
|
56
71
|
return { success: false, error: r.error };
|
|
57
72
|
},
|
|
58
73
|
};
|
|
74
|
+
// v4.3 Phase 1 — observer HOC.
|
|
75
|
+
exports.browserScrollTool = (0, _observer_1.withBrowserState)(_browserScrollTool);
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.browserTypeTool = void 0;
|
|
17
17
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
18
|
-
|
|
18
|
+
const _observer_1 = require("./_observer");
|
|
19
|
+
const _browserTypeTool = {
|
|
19
20
|
schema: {
|
|
20
21
|
name: 'browser_type',
|
|
21
22
|
description: 'Type text into a browser input identified by CSS selector. Replaces existing value.',
|
|
@@ -34,6 +35,19 @@ exports.browserTypeTool = {
|
|
|
34
35
|
category: 'browser',
|
|
35
36
|
mutates: true,
|
|
36
37
|
toolset: 'browser',
|
|
38
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
39
|
+
buildPreview(args) {
|
|
40
|
+
const selector = String(args.selector ?? 'input');
|
|
41
|
+
const text = String(args.text ?? '');
|
|
42
|
+
return {
|
|
43
|
+
tool: 'browser_type',
|
|
44
|
+
args,
|
|
45
|
+
riskTier: 'caution',
|
|
46
|
+
sideEffects: [{ type: 'browser_action', action: 'type', target: selector }],
|
|
47
|
+
detectedRisks: [],
|
|
48
|
+
summary: `Would type ${text.length} chars into ${selector}`,
|
|
49
|
+
};
|
|
50
|
+
},
|
|
37
51
|
async execute(args) {
|
|
38
52
|
const selector = String(args.selector ?? 'input').trim();
|
|
39
53
|
const text = String(args.text ?? '');
|
|
@@ -43,3 +57,5 @@ exports.browserTypeTool = {
|
|
|
43
57
|
return { success: false, error: r.error, selector };
|
|
44
58
|
},
|
|
45
59
|
};
|
|
60
|
+
// v4.3 Phase 1 — observer HOC captures pre/post page state.
|
|
61
|
+
exports.browserTypeTool = (0, _observer_1.withBrowserState)(_browserTypeTool);
|
|
@@ -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');
|