autodev-cli 1.4.86 → 1.4.93
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/layout.js +1 -0
- package/out/agentBackup/layout.js.map +1 -1
- package/out/commands/mcpOperate.js +368 -28
- package/out/commands/mcpOperate.js.map +1 -1
- package/out/configManager.d.ts +7 -0
- package/out/configManager.js +36 -0
- package/out/configManager.js.map +1 -1
- package/out/core/modelInfo.d.ts +28 -0
- package/out/core/modelInfo.js +97 -0
- package/out/core/modelInfo.js.map +1 -0
- package/out/core/projectSkills.d.ts +44 -0
- package/out/core/projectSkills.js +266 -0
- package/out/core/projectSkills.js.map +1 -0
- package/out/core/redactSecrets.d.ts +15 -0
- package/out/core/redactSecrets.js +110 -0
- package/out/core/redactSecrets.js.map +1 -0
- package/out/core/settingsLoader.d.ts +9 -0
- package/out/core/settingsLoader.js +1 -0
- package/out/core/settingsLoader.js.map +1 -1
- package/out/taskLoop.d.ts +8 -0
- package/out/taskLoop.js +55 -2
- package/out/taskLoop.js.map +1 -1
- package/out/webSocketPoller.d.ts +3 -0
- package/out/webSocketPoller.js +11 -0
- package/out/webSocketPoller.js.map +1 -1
- package/out/webhookPoller.d.ts +1 -0
- package/out/webhookPoller.js +5 -0
- package/out/webhookPoller.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.providerConsumesSkills = providerConsumesSkills;
|
|
37
|
+
exports.sanitizeRemoteSkills = sanitizeRemoteSkills;
|
|
38
|
+
exports.saveProjectSkills = saveProjectSkills;
|
|
39
|
+
exports.foldSkillsIntoProfile = foldSkillsIntoProfile;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const pathSafe_1 = require("./pathSafe");
|
|
43
|
+
// A skill slug is a plain directory name: lowercase alnum + hyphen only. No
|
|
44
|
+
// separators, no dots — this alone rejects "../evil", "a/b", ".hidden", etc.
|
|
45
|
+
const SKILL_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
46
|
+
// Caps — the whole point of the sanitizer. Keep them strict.
|
|
47
|
+
const MAX_SKILLS = 100; // total number of skills per sync
|
|
48
|
+
const MAX_NAME_LEN = 64; // slug length
|
|
49
|
+
const MAX_DESC_BYTES = 4 * 1024; // 4 KB per description
|
|
50
|
+
const MAX_BODY_BYTES = 64 * 1024; // 64 KB per body
|
|
51
|
+
const MAX_TOTAL_BYTES = 4 * 1024 * 1024; // 4 MB across all skills
|
|
52
|
+
const SKILLS_REL_DIR = path.posix.join('.claude', 'skills');
|
|
53
|
+
const MANIFEST_REL = path.join('.autodev', 'synced-skills.json');
|
|
54
|
+
/** True for providers that natively load `.claude/skills/<slug>/SKILL.md` (Claude only). */
|
|
55
|
+
function providerConsumesSkills(provider) {
|
|
56
|
+
return provider === 'claude-cli' || provider === 'claude-tui';
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Validate an untrusted `skills` array (from a `skill_update` frame) down to the
|
|
60
|
+
* subset that is safe to write. Enforces slug shape, string types, per-file and
|
|
61
|
+
* aggregate size caps, a total count cap, and workspace path containment.
|
|
62
|
+
* Returns the accepted list (in order) plus the rejected entries with reasons.
|
|
63
|
+
* Callers must still gate the whole path behind an opt-in (skillUpdateEnabled).
|
|
64
|
+
*/
|
|
65
|
+
function sanitizeRemoteSkills(root, skills) {
|
|
66
|
+
const safe = [];
|
|
67
|
+
const rejected = [];
|
|
68
|
+
if (!Array.isArray(skills)) {
|
|
69
|
+
return { safe, rejected };
|
|
70
|
+
}
|
|
71
|
+
const seen = new Set();
|
|
72
|
+
let totalBytes = 0;
|
|
73
|
+
for (const raw of skills) {
|
|
74
|
+
const entry = raw;
|
|
75
|
+
const rawName = typeof entry?.name === 'string' ? entry.name.trim() : '';
|
|
76
|
+
const label = rawName || '(unnamed)';
|
|
77
|
+
if (!entry || typeof entry !== 'object') {
|
|
78
|
+
rejected.push({ name: label, reason: 'not an object' });
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (!SKILL_NAME_RE.test(rawName)) {
|
|
82
|
+
rejected.push({ name: label, reason: 'invalid slug (must match ^[a-z0-9][a-z0-9-]*$)' });
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (rawName.length > MAX_NAME_LEN) {
|
|
86
|
+
rejected.push({ name: label, reason: 'slug too long' });
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (seen.has(rawName)) {
|
|
90
|
+
rejected.push({ name: rawName, reason: 'duplicate slug' });
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (typeof entry.description !== 'string') {
|
|
94
|
+
rejected.push({ name: rawName, reason: 'description not a string' });
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (typeof entry.body !== 'string') {
|
|
98
|
+
rejected.push({ name: rawName, reason: 'body not a string' });
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const descBytes = Buffer.byteLength(entry.description, 'utf8');
|
|
102
|
+
const bodyBytes = Buffer.byteLength(entry.body, 'utf8');
|
|
103
|
+
if (descBytes > MAX_DESC_BYTES) {
|
|
104
|
+
rejected.push({ name: rawName, reason: `description too large (${descBytes} > ${MAX_DESC_BYTES})` });
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (bodyBytes > MAX_BODY_BYTES) {
|
|
108
|
+
rejected.push({ name: rawName, reason: `body too large (${bodyBytes} > ${MAX_BODY_BYTES})` });
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
// Path-safety: the composed target must resolve INSIDE the workspace, even
|
|
112
|
+
// after symlink resolution. (The slug regex already blocks ../ and /, this
|
|
113
|
+
// is belt-and-suspenders + symlink defence.)
|
|
114
|
+
const target = (0, pathSafe_1.resolveWithinRoot)(root, path.posix.join(SKILLS_REL_DIR, rawName, 'SKILL.md'), false);
|
|
115
|
+
if (!target) {
|
|
116
|
+
rejected.push({ name: rawName, reason: 'path escapes workspace' });
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (safe.length >= MAX_SKILLS) {
|
|
120
|
+
rejected.push({ name: rawName, reason: `over skill count cap (${MAX_SKILLS})` });
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (totalBytes + descBytes + bodyBytes > MAX_TOTAL_BYTES) {
|
|
124
|
+
rejected.push({ name: rawName, reason: `over total bytes cap (${MAX_TOTAL_BYTES})` });
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
totalBytes += descBytes + bodyBytes;
|
|
128
|
+
seen.add(rawName);
|
|
129
|
+
safe.push({ name: rawName, description: entry.description, body: entry.body });
|
|
130
|
+
}
|
|
131
|
+
return { safe, rejected };
|
|
132
|
+
}
|
|
133
|
+
/** Compose the on-disk SKILL.md (frontmatter + body). Description newlines are
|
|
134
|
+
* collapsed to keep the YAML frontmatter valid. */
|
|
135
|
+
function _composeSkillFile(s) {
|
|
136
|
+
const desc = s.description.replace(/[\r\n]+/g, ' ').trim();
|
|
137
|
+
const body = s.body.replace(/\s+$/, '');
|
|
138
|
+
return `---\nname: ${s.name}\ndescription: ${desc}\n---\n\n${body}\n`;
|
|
139
|
+
}
|
|
140
|
+
function _readManifest(root) {
|
|
141
|
+
try {
|
|
142
|
+
const f = path.join(root, MANIFEST_REL);
|
|
143
|
+
if (!fs.existsSync(f)) {
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
const arr = JSON.parse(fs.readFileSync(f, 'utf8'));
|
|
147
|
+
return Array.isArray(arr) ? arr.filter((x) => typeof x === 'string') : [];
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function _writeManifest(root, slugs) {
|
|
154
|
+
const f = path.join(root, MANIFEST_REL);
|
|
155
|
+
const dir = path.dirname(f);
|
|
156
|
+
if (!fs.existsSync(dir)) {
|
|
157
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
158
|
+
}
|
|
159
|
+
fs.writeFileSync(f, JSON.stringify(slugs, null, 2) + '\n', 'utf8');
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Write the supplied (already-sanitized) skills to `<root>/.claude/skills/<slug>/SKILL.md`
|
|
163
|
+
* as a FULL REPLACE: every previously-synced skill (tracked in the manifest) that
|
|
164
|
+
* is NOT in the new set is removed, and its now-empty dir pruned. Skills we did
|
|
165
|
+
* not write (CLI-bundled via applyAllSkills, or user hand-made) are never touched.
|
|
166
|
+
* Returns the slugs written and removed.
|
|
167
|
+
*/
|
|
168
|
+
function saveProjectSkills(root, safeSkills) {
|
|
169
|
+
const prev = _readManifest(root);
|
|
170
|
+
const nextSet = new Set(safeSkills.map(s => s.name));
|
|
171
|
+
const written = [];
|
|
172
|
+
const removed = [];
|
|
173
|
+
// Write / overwrite each safe skill.
|
|
174
|
+
for (const s of safeSkills) {
|
|
175
|
+
const target = (0, pathSafe_1.resolveWithinRoot)(root, path.posix.join(SKILLS_REL_DIR, s.name, 'SKILL.md'), false);
|
|
176
|
+
if (!target) {
|
|
177
|
+
continue;
|
|
178
|
+
} // defensive — sanitizer already validated
|
|
179
|
+
try {
|
|
180
|
+
const dir = path.dirname(target);
|
|
181
|
+
if (!fs.existsSync(dir)) {
|
|
182
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
183
|
+
}
|
|
184
|
+
fs.writeFileSync(target, _composeSkillFile(s), 'utf8');
|
|
185
|
+
written.push(s.name);
|
|
186
|
+
}
|
|
187
|
+
catch { /* ignore individual write errors */ }
|
|
188
|
+
}
|
|
189
|
+
// Remove previously-synced skills that are gone from the new set — but ONLY
|
|
190
|
+
// ones we own (in the manifest), never bundled or hand-made skills.
|
|
191
|
+
for (const slug of prev) {
|
|
192
|
+
if (nextSet.has(slug)) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (!SKILL_NAME_RE.test(slug)) {
|
|
196
|
+
continue;
|
|
197
|
+
} // defensive
|
|
198
|
+
const target = (0, pathSafe_1.resolveWithinRoot)(root, path.posix.join(SKILLS_REL_DIR, slug, 'SKILL.md'), false);
|
|
199
|
+
if (!target) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
if (fs.existsSync(target)) {
|
|
204
|
+
fs.unlinkSync(target);
|
|
205
|
+
}
|
|
206
|
+
const dir = path.dirname(target);
|
|
207
|
+
if (fs.existsSync(dir) && fs.readdirSync(dir).length === 0) {
|
|
208
|
+
fs.rmdirSync(dir);
|
|
209
|
+
}
|
|
210
|
+
removed.push(slug);
|
|
211
|
+
}
|
|
212
|
+
catch { /* ignore */ }
|
|
213
|
+
}
|
|
214
|
+
_writeManifest(root, written);
|
|
215
|
+
return { written, removed };
|
|
216
|
+
}
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
// Prose fold — for non-Claude providers (opencode/grok/copilot) that cannot
|
|
219
|
+
// load SKILL.md, fold a short managed "## Skills" section into AGENTS.md so
|
|
220
|
+
// those agents still benefit. Idempotent: replaces a marker block, never
|
|
221
|
+
// appends forever. Passing an empty list removes the block.
|
|
222
|
+
// ---------------------------------------------------------------------------
|
|
223
|
+
const SKILLS_FOLD_BEGIN = '<!-- autodev:skills:begin -->';
|
|
224
|
+
const SKILLS_FOLD_END = '<!-- autodev:skills:end -->';
|
|
225
|
+
const SKILLS_FOLD_RE = /\n*<!-- autodev:skills:begin -->[\s\S]*?<!-- autodev:skills:end -->\n*/;
|
|
226
|
+
/**
|
|
227
|
+
* Fold the given skills into a managed "## Skills" block in `<root>/AGENTS.md`
|
|
228
|
+
* (best-effort, idempotent). Non-Claude agents read AGENTS.md but cannot load
|
|
229
|
+
* `.claude/skills`, so this is how they gain the skill instructions. An empty
|
|
230
|
+
* list strips the block.
|
|
231
|
+
*/
|
|
232
|
+
function foldSkillsIntoProfile(root, safeSkills) {
|
|
233
|
+
if (!root) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const target = path.join(root, 'AGENTS.md');
|
|
237
|
+
let block = '';
|
|
238
|
+
if (safeSkills.length > 0) {
|
|
239
|
+
const parts = safeSkills.map(s => {
|
|
240
|
+
const desc = s.description.replace(/[\r\n]+/g, ' ').trim();
|
|
241
|
+
return `### ${s.name}\n\n${desc}\n\n${s.body.trim()}`;
|
|
242
|
+
});
|
|
243
|
+
block = `${SKILLS_FOLD_BEGIN}\n\n## Skills\n\n${parts.join('\n\n')}\n\n${SKILLS_FOLD_END}`;
|
|
244
|
+
}
|
|
245
|
+
let content = '';
|
|
246
|
+
try {
|
|
247
|
+
if (fs.existsSync(target)) {
|
|
248
|
+
content = fs.readFileSync(target, 'utf8');
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch { /* treat as empty */ }
|
|
252
|
+
if (SKILLS_FOLD_RE.test(content)) {
|
|
253
|
+
content = content.replace(SKILLS_FOLD_RE, block ? `\n\n${block}\n` : '\n');
|
|
254
|
+
}
|
|
255
|
+
else if (block) {
|
|
256
|
+
content = content ? `${content.replace(/\s+$/, '')}\n\n${block}\n` : `${block}\n`;
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
return; // nothing to add, nothing to strip
|
|
260
|
+
}
|
|
261
|
+
try {
|
|
262
|
+
fs.writeFileSync(target, content, 'utf8');
|
|
263
|
+
}
|
|
264
|
+
catch { /* best-effort */ }
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=projectSkills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectSkills.js","sourceRoot":"","sources":["../../src/core/projectSkills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redact known secret shapes from a single string. Applies every pattern in
|
|
3
|
+
* order (specific before generic). Returns the string unchanged when it holds
|
|
4
|
+
* no secrets. Safe on empty / non-secret prose.
|
|
5
|
+
*/
|
|
6
|
+
export declare function redactSecrets(text: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Deep-redact every STRING value inside an object/array, leaving structure and
|
|
9
|
+
* KEYS intact. Hook events forwarded to the office are objects (not flat
|
|
10
|
+
* strings) — their tool_input.command, tool_response, message text, etc. can
|
|
11
|
+
* each carry a secret — so we walk the whole value and run `redactSecrets` on
|
|
12
|
+
* every string leaf. Non-string leaves (numbers, booleans, null) pass through
|
|
13
|
+
* untouched. Returns a NEW value; the input is not mutated.
|
|
14
|
+
*/
|
|
15
|
+
export declare function redactDeep<T>(value: T): T;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Secrets anonymizer for OUTBOUND agent content.
|
|
3
|
+
//
|
|
4
|
+
// Agent-originated content (tool calls/output, bash output, file reads,
|
|
5
|
+
// assistant prose) is forwarded from the CLI to the pixel-office, where it is
|
|
6
|
+
// STORED and DISPLAYED in the office feed/chat. Secrets (API keys, tokens) can
|
|
7
|
+
// leak into that stream. We redact them HERE, before the content leaves the
|
|
8
|
+
// machine — mirroring how the tutor project redacts its trace files.
|
|
9
|
+
//
|
|
10
|
+
// Scope: this is applied ONLY to outbound content going to the office (hook
|
|
11
|
+
// events, assistant narration, autonomy task results / A2A replies). It is NOT
|
|
12
|
+
// applied to the model's actual input, local files on disk, or the api_key used
|
|
13
|
+
// for auth (that travels as an HTTP header, not as content).
|
|
14
|
+
//
|
|
15
|
+
// Performance: the pattern list is compiled ONCE at module load (the const
|
|
16
|
+
// array below) and reused for every call. `redactSecrets` runs on every
|
|
17
|
+
// forwarded event, so we never rebuild RegExp objects per-call.
|
|
18
|
+
//
|
|
19
|
+
// Ordering: patterns run in array order — SPECIFIC shapes before GENERIC ones
|
|
20
|
+
// (e.g. `sk-ant-` before the generic `sk-` key, so an Anthropic key is labelled
|
|
21
|
+
// as such and its remainder can't be re-matched by a broader rule).
|
|
22
|
+
//
|
|
23
|
+
// The min-length bounds in each pattern are deliberate: they stop the generic
|
|
24
|
+
// rules from mangling ordinary prose. Do NOT loosen them.
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.redactSecrets = redactSecrets;
|
|
27
|
+
exports.redactDeep = redactDeep;
|
|
28
|
+
// NOTE on emails: the reference trace-redactor also maps plain email addresses
|
|
29
|
+
// (PII). We DELIBERATELY do NOT redact emails here — user emails legitimately
|
|
30
|
+
// appear in the office UI (character owners, teammates), and redacting them
|
|
31
|
+
// would mangle normal content. So no email pattern is included.
|
|
32
|
+
const PATTERNS = [
|
|
33
|
+
// Anthropic API keys — must run BEFORE the generic `sk-` rule.
|
|
34
|
+
{ name: 'anthropic_key', re: /sk-ant-[A-Za-z0-9_-]{15,}/g, replacement: 'sk-ant-REDACTED' },
|
|
35
|
+
// Generic OpenAI-style `sk-…` keys.
|
|
36
|
+
{ name: 'openai_style_key', re: /sk-[A-Za-z0-9]{20,}/g, replacement: 'sk-REDACTED' },
|
|
37
|
+
// GitHub tokens: gho_/ghp_/ghr_/ghs_/ghu_.
|
|
38
|
+
{ name: 'gh_token', re: /gh[oprsu]_[A-Za-z0-9]{20,}/g, replacement: 'gh_REDACTED' },
|
|
39
|
+
// GitHub fine-grained PATs.
|
|
40
|
+
{ name: 'gh_pat', re: /github_pat_[A-Za-z0-9_]{20,}/g, replacement: 'github_pat_REDACTED' },
|
|
41
|
+
// Google API keys.
|
|
42
|
+
{ name: 'google_api_key', re: /AIza[0-9A-Za-z_-]{25,}/g, replacement: 'AIza_REDACTED' },
|
|
43
|
+
// Slack tokens: xoxb/xoxa/xoxp/xoxr/xoxs.
|
|
44
|
+
{ name: 'slack_token', re: /xox[baprs]-[0-9A-Za-z-]{20,}/g, replacement: 'xoxX-REDACTED' },
|
|
45
|
+
// AWS access key IDs.
|
|
46
|
+
{ name: 'aws_access_key', re: /AKIA[0-9A-Z]{16}/g, replacement: 'AKIA_REDACTED' },
|
|
47
|
+
// Stripe secret/publishable/restricted live+test keys.
|
|
48
|
+
{ name: 'stripe_key', re: /(?:sk|pk|rk)_(?:live|test)_[0-9A-Za-z]{20,}/g, replacement: 'stripe_REDACTED' },
|
|
49
|
+
// JWTs (three base64url segments).
|
|
50
|
+
{ name: 'jwt_token', re: /eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g, replacement: 'eyJ.REDACTED.JWT' },
|
|
51
|
+
// `Bearer <token>` — keep the "Bearer " prefix, redact the credential.
|
|
52
|
+
{ name: 'bearer_token', re: /([Bb]earer\s+)[A-Za-z0-9._~+/=-]{20,}/g, replacement: '$1REDACTED_BEARER' },
|
|
53
|
+
// PEM private-key blocks (RSA / EC / OPENSSH / generic).
|
|
54
|
+
{ name: 'private_key', re: /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g, replacement: '-----REDACTED_PRIVATE_KEY-----' },
|
|
55
|
+
// JSON `"password": "…"` values.
|
|
56
|
+
{ name: 'password_json', re: /("[Pp]ass(?:word|wd)"\s*:\s*")[^"\\]+(")/g, replacement: '$1REDACTED$2' },
|
|
57
|
+
// JSON `"token"/"auth_token"/"api_token"` values.
|
|
58
|
+
{ name: 'token_json', re: /("(?:[Aa]uth|[Aa]pi)?_?[Tt]oken"\s*:\s*")[^"\\]{15,}(")/g, replacement: '$1REDACTED$2' },
|
|
59
|
+
// Shell/env `FOO_TOKEN=…`, `API_KEY: …`, `*_SECRET=…`, `*_PASSWORD=…`.
|
|
60
|
+
{ name: 'env_var_secret', re: /([A-Z][A-Z0-9_]*(?:TOKEN|SECRET|API[_-]?KEY|PASSWORD|PASSWD)[A-Z0-9_]*\s*[:=]\s*["']?)[A-Za-z0-9/_+.=-]{15,}/g, replacement: '$1REDACTED' },
|
|
61
|
+
// ── Our own pixel-office agent credential shapes ────────────────────────────
|
|
62
|
+
// These are the office agent api_keys (`agt_…`) and personal access tokens
|
|
63
|
+
// (`pat_…`). They authenticate a character to the office and must NEVER show
|
|
64
|
+
// up in the office feed itself.
|
|
65
|
+
{ name: 'agt_key', re: /agt_[A-Za-z0-9]{16,}/g, replacement: 'agt_REDACTED' },
|
|
66
|
+
{ name: 'pat_key', re: /pat_[A-Za-z0-9]{16,}/g, replacement: 'pat_REDACTED' },
|
|
67
|
+
];
|
|
68
|
+
/**
|
|
69
|
+
* Redact known secret shapes from a single string. Applies every pattern in
|
|
70
|
+
* order (specific before generic). Returns the string unchanged when it holds
|
|
71
|
+
* no secrets. Safe on empty / non-secret prose.
|
|
72
|
+
*/
|
|
73
|
+
function redactSecrets(text) {
|
|
74
|
+
if (!text) {
|
|
75
|
+
return text;
|
|
76
|
+
}
|
|
77
|
+
let out = text;
|
|
78
|
+
for (const p of PATTERNS) {
|
|
79
|
+
// `re` is a shared module-level RegExp with the global flag. String.replace
|
|
80
|
+
// does not rely on / advance its lastIndex, so reuse is safe and allocation-
|
|
81
|
+
// free (unlike RegExp.exec, which would need a lastIndex reset).
|
|
82
|
+
out = out.replace(p.re, p.replacement);
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Deep-redact every STRING value inside an object/array, leaving structure and
|
|
88
|
+
* KEYS intact. Hook events forwarded to the office are objects (not flat
|
|
89
|
+
* strings) — their tool_input.command, tool_response, message text, etc. can
|
|
90
|
+
* each carry a secret — so we walk the whole value and run `redactSecrets` on
|
|
91
|
+
* every string leaf. Non-string leaves (numbers, booleans, null) pass through
|
|
92
|
+
* untouched. Returns a NEW value; the input is not mutated.
|
|
93
|
+
*/
|
|
94
|
+
function redactDeep(value) {
|
|
95
|
+
if (typeof value === 'string') {
|
|
96
|
+
return redactSecrets(value);
|
|
97
|
+
}
|
|
98
|
+
if (Array.isArray(value)) {
|
|
99
|
+
return value.map((v) => redactDeep(v));
|
|
100
|
+
}
|
|
101
|
+
if (value && typeof value === 'object') {
|
|
102
|
+
const out = {};
|
|
103
|
+
for (const [k, v] of Object.entries(value)) {
|
|
104
|
+
out[k] = redactDeep(v);
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
return value;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=redactSecrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redactSecrets.js","sourceRoot":"","sources":["../../src/core/redactSecrets.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,6 +40,15 @@ export interface AutodevSettings {
|
|
|
40
40
|
* enableFileBrowser / gitEnabled). Even when enabled, entries are validated.
|
|
41
41
|
*/
|
|
42
42
|
mcpUpdateEnabled: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Opt-in: honor `skill_update` frames pushed over the WS channel. When false
|
|
45
|
+
* (default), inbound skill_update frames are ignored. Writing remote-supplied
|
|
46
|
+
* skills drops instruction files into `.claude/skills/` that a running Claude
|
|
47
|
+
* agent live-reads, so it is an instruction-injection surface and must be
|
|
48
|
+
* explicitly enabled (mirrors mcpUpdateEnabled). Even when enabled, each skill
|
|
49
|
+
* is validated (slug shape, size caps, workspace path containment).
|
|
50
|
+
*/
|
|
51
|
+
skillUpdateEnabled: boolean;
|
|
43
52
|
hooksEnabled: boolean;
|
|
44
53
|
hooksScope: 'project' | 'global';
|
|
45
54
|
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/taskLoop.d.ts
CHANGED
|
@@ -108,6 +108,14 @@ export declare class TaskLoopRunner {
|
|
|
108
108
|
restart(): Promise<void>;
|
|
109
109
|
/** Handle mcp_update pushed from pixel-office: write .mcp.json, sync all providers, restart loop. */
|
|
110
110
|
private _handleMcpUpdate;
|
|
111
|
+
/**
|
|
112
|
+
* Handle skill_update pushed from pixel-office: validate + write the agent's
|
|
113
|
+
* FULL effective skill set to `.claude/skills/<slug>/SKILL.md`. Skills
|
|
114
|
+
* live-reload (Claude re-reads them each run), so this does NOT restart the
|
|
115
|
+
* loop — it just sanitizes, full-replaces on disk, folds a prose block into
|
|
116
|
+
* AGENTS.md for non-Claude providers, and reports the applied names.
|
|
117
|
+
*/
|
|
118
|
+
private _handleSkillUpdate;
|
|
111
119
|
/** Handle export_request from pixel-office: create backup zip and upload. */
|
|
112
120
|
private _handleExportRequest;
|
|
113
121
|
/** Handle restore_request from pixel-office: download zip and restore workspace. */
|
package/out/taskLoop.js
CHANGED
|
@@ -61,7 +61,9 @@ const periodicActions_1 = require("./periodicActions");
|
|
|
61
61
|
const discordGateway_1 = require("./discordGateway");
|
|
62
62
|
const webhookPoller_1 = require("./webhookPoller");
|
|
63
63
|
const emailPoller_1 = require("./emailPoller");
|
|
64
|
+
const modelInfo_1 = require("./core/modelInfo");
|
|
64
65
|
const projectMcp_1 = require("./core/projectMcp");
|
|
66
|
+
const projectSkills_1 = require("./core/projectSkills");
|
|
65
67
|
const configManager_1 = require("./configManager");
|
|
66
68
|
const agentBackup_1 = require("./agentBackup");
|
|
67
69
|
const version_1 = require("./version");
|
|
@@ -71,6 +73,7 @@ const version_1 = require("./version");
|
|
|
71
73
|
const rateLimit_1 = require("./rateLimit");
|
|
72
74
|
const cliExit_1 = require("./cliExit");
|
|
73
75
|
const liveNarration_1 = require("./core/liveNarration");
|
|
76
|
+
const redactSecrets_1 = require("./core/redactSecrets");
|
|
74
77
|
class ContextLengthError extends Error {
|
|
75
78
|
rawMessage;
|
|
76
79
|
constructor(rawMessage) {
|
|
@@ -393,7 +396,13 @@ class TaskLoopRunner {
|
|
|
393
396
|
// `cliVersion` rides in the meta merged into every webhook frame — notably
|
|
394
397
|
// the agent_online (hello) frame — so pixel-office can record which CLI
|
|
395
398
|
// version each agent runs (surfacing stale, steer-incapable agents).
|
|
396
|
-
|
|
399
|
+
// `model` — the effective friendly model name (Opus 4.8 / kimi-k2.7-code /
|
|
400
|
+
// grok-code). Resolved from the provider's configured override; undefined
|
|
401
|
+
// when the provider runs its account default (office gates the field). Rides
|
|
402
|
+
// in setMeta so it merges into every frame, notably agent_online, where the
|
|
403
|
+
// office records it against the agent for the per-agent model badge.
|
|
404
|
+
const effectiveModel = (0, modelInfo_1.resolveConfiguredModel)(settings);
|
|
405
|
+
this._webhook?.setMeta({ provider: settings.provider, cliVersion: version_1.CLI_VERSION, model: effectiveModel, workDir: root, hostname: this._hostname, gitRepo: this._gitRepo, gitBranch: this._gitBranch });
|
|
397
406
|
this._discordPoller = (settings.discordToken && settings.discordChannelId && settings.discordOwners)
|
|
398
407
|
? new discordPoller_1.DiscordPoller(settings.discordToken, settings.discordChannelId, settings.discordOwners)
|
|
399
408
|
: null;
|
|
@@ -440,6 +449,7 @@ class TaskLoopRunner {
|
|
|
440
449
|
// mis-detected as 'claude' by the office's hook-based fallback.
|
|
441
450
|
provider: this._settings?.provider,
|
|
442
451
|
cliVersion: version_1.CLI_VERSION,
|
|
452
|
+
model: this._settings ? (0, modelInfo_1.resolveConfiguredModel)(this._settings) : undefined,
|
|
443
453
|
hostname: this._hostname,
|
|
444
454
|
workDir: this._workspaceRoot ?? '',
|
|
445
455
|
gitRepo: this._gitRepo,
|
|
@@ -491,6 +501,7 @@ class TaskLoopRunner {
|
|
|
491
501
|
this._webhookPoller.setOnSteer((text, onDelivered) => void this._handleSteer(text, onDelivered));
|
|
492
502
|
this._webhookPoller.setOnCommand((cmd) => this._handleCommand(cmd));
|
|
493
503
|
this._webhookPoller.setOnMcpUpdate((entries) => this._handleMcpUpdate(entries));
|
|
504
|
+
this._webhookPoller.setOnSkillUpdate((skills) => this._handleSkillUpdate(skills));
|
|
494
505
|
this._webhookPoller.setOnExportRequest((agentId) => void this._handleExportRequest(agentId));
|
|
495
506
|
this._webhookPoller.setOnRestoreRequest((agentId, downloadUrl) => void this._handleRestoreRequest(agentId, downloadUrl));
|
|
496
507
|
this._webhookPoller.setOnExportConfig((exportEnabled, exportDailyBackup, agentId) => this._handleExportConfig(exportEnabled, exportDailyBackup, agentId));
|
|
@@ -562,6 +573,7 @@ class TaskLoopRunner {
|
|
|
562
573
|
this._notifyWebhook('agent_online', {
|
|
563
574
|
provider: settings.provider,
|
|
564
575
|
cliVersion: version_1.CLI_VERSION,
|
|
576
|
+
model: effectiveModel,
|
|
565
577
|
hostname: this._hostname,
|
|
566
578
|
workDir: root,
|
|
567
579
|
gitRepo: this._gitRepo,
|
|
@@ -710,6 +722,44 @@ class TaskLoopRunner {
|
|
|
710
722
|
}
|
|
711
723
|
void this.restart();
|
|
712
724
|
}
|
|
725
|
+
/**
|
|
726
|
+
* Handle skill_update pushed from pixel-office: validate + write the agent's
|
|
727
|
+
* FULL effective skill set to `.claude/skills/<slug>/SKILL.md`. Skills
|
|
728
|
+
* live-reload (Claude re-reads them each run), so this does NOT restart the
|
|
729
|
+
* loop — it just sanitizes, full-replaces on disk, folds a prose block into
|
|
730
|
+
* AGENTS.md for non-Claude providers, and reports the applied names.
|
|
731
|
+
*/
|
|
732
|
+
_handleSkillUpdate(skills) {
|
|
733
|
+
const root = this._workspaceRoot;
|
|
734
|
+
if (!root)
|
|
735
|
+
return;
|
|
736
|
+
// Opt-in gate: remote-supplied skills become instruction files a running
|
|
737
|
+
// Claude agent live-reads. Ignore unless explicitly enabled, mirroring
|
|
738
|
+
// mcpUpdateEnabled / enableFileBrowser / gitEnabled.
|
|
739
|
+
if (!this._settings?.skillUpdateEnabled) {
|
|
740
|
+
this._cb?.log('🔒 skill_update ignored — skillUpdateEnabled is off (set it in .autodev/settings.json to allow)');
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
this._cb?.log('🧩 skill_update received — validating and writing .claude/skills…');
|
|
744
|
+
const { safe, rejected } = (0, projectSkills_1.sanitizeRemoteSkills)(root, skills);
|
|
745
|
+
if (rejected.length) {
|
|
746
|
+
this._cb?.log(`⚠️ skill_update dropped ${rejected.length} entr${rejected.length === 1 ? 'y' : 'ies'}: ${rejected.map(r => `${r.name} (${r.reason})`).join(', ')}`);
|
|
747
|
+
}
|
|
748
|
+
try {
|
|
749
|
+
// Full-replace: writes the safe set and prunes previously-synced skills
|
|
750
|
+
// that are gone (even when `safe` is empty — that clears them all).
|
|
751
|
+
const { written, removed } = (0, projectSkills_1.saveProjectSkills)(root, safe);
|
|
752
|
+
// Non-Claude providers can't load SKILL.md — fold a prose block into AGENTS.md.
|
|
753
|
+
if (!(0, projectSkills_1.providerConsumesSkills)(this._settings?.provider)) {
|
|
754
|
+
(0, projectSkills_1.foldSkillsIntoProfile)(root, safe);
|
|
755
|
+
}
|
|
756
|
+
void configManager_1.ConfigManager.reportProjectSkills(root, written, (m) => this._cb?.log(m));
|
|
757
|
+
this._cb?.log(`✅ skills synced — wrote ${written.length}, removed ${removed.length} (.claude/skills). Live-reloads on the next run — no restart.`);
|
|
758
|
+
}
|
|
759
|
+
catch (err) {
|
|
760
|
+
this._cb?.log(`⚠️ skill update failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
713
763
|
/** Handle export_request from pixel-office: create backup zip and upload. */
|
|
714
764
|
async _handleExportRequest(agentId) {
|
|
715
765
|
const root = this._workspaceRoot;
|
|
@@ -1168,7 +1218,10 @@ class TaskLoopRunner {
|
|
|
1168
1218
|
if (sessionName) {
|
|
1169
1219
|
ev._session_name = sessionName;
|
|
1170
1220
|
}
|
|
1171
|
-
|
|
1221
|
+
// Redact secrets from the whole hook object (tool_input/tool_response/
|
|
1222
|
+
// assistant narration/file contents) before it leaves the machine —
|
|
1223
|
+
// this stream is stored + rendered in the office feed/chat.
|
|
1224
|
+
this._webhookPoller.sendFrame({ type: 'hook_event', data: (0, redactSecrets_1.redactDeep)(ev) });
|
|
1172
1225
|
}
|
|
1173
1226
|
catch { /* skip malformed lines */ }
|
|
1174
1227
|
}
|