@anhlp/alp 0.0.1-beta.4 → 0.0.1-beta.7
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 +11 -412
- package/bin/alp.js +3 -0
- package/package.json +11 -103
- package/dist/THIRD-PARTY-NOTICES.txt +0 -626
- package/dist/acp.js +0 -19936
- package/dist/alpd.js +0 -49562
- package/docs/modular-monorepo.md +0 -214
- package/packages/cli/README.md +0 -7
- package/packages/cli/dist/THIRD-PARTY-NOTICES.txt +0 -651
- package/packages/cli/dist/acp/agent.d.ts +0 -37
- package/packages/cli/dist/acp/agent.js +0 -489
- package/packages/cli/dist/acp/main.d.ts +0 -4
- package/packages/cli/dist/acp/main.js +0 -23
- package/packages/cli/dist/acp.js +0 -19936
- package/packages/cli/dist/alp-web/THIRD-PARTY-NOTICES.txt +0 -2590
- package/packages/cli/dist/alp-web/alp-boundary.json +0 -15
- package/packages/cli/dist/alp-web/apple-touch-icon.png +0 -0
- package/packages/cli/dist/alp-web/assets/TerminalPanel-DLuoa74B.css +0 -1
- package/packages/cli/dist/alp-web/assets/TerminalPanel-PrU2l3u5.js +0 -16
- package/packages/cli/dist/alp-web/assets/index-BJdBTDFX.css +0 -1
- package/packages/cli/dist/alp-web/assets/index-DpfiPv5s.js +0 -52
- package/packages/cli/dist/alp-web/favicon-attention.svg +0 -6
- package/packages/cli/dist/alp-web/favicon-running.svg +0 -6
- package/packages/cli/dist/alp-web/favicon.svg +0 -5
- package/packages/cli/dist/alp-web/index.html +0 -20
- package/packages/cli/dist/alp-web.js +0 -9640
- package/packages/cli/dist/alpd.js +0 -49562
- package/packages/cli/dist/backup.d.ts +0 -4
- package/packages/cli/dist/backup.js +0 -146
- package/packages/cli/dist/build-manifest.json +0 -240
- package/packages/cli/dist/cli.d.ts +0 -2
- package/packages/cli/dist/cli.js +0 -30
- package/packages/cli/dist/daemon.d.ts +0 -35
- package/packages/cli/dist/daemon.js +0 -126
- package/packages/cli/dist/index.d.ts +0 -1
- package/packages/cli/dist/index.js +0 -5
- package/packages/cli/dist/interfaces.d.ts +0 -24
- package/packages/cli/dist/interfaces.js +0 -156
- package/packages/cli/dist/library.d.ts +0 -140
- package/packages/cli/dist/library.js +0 -319
- package/packages/cli/dist/paths.d.ts +0 -3
- package/packages/cli/dist/paths.js +0 -18
- package/packages/cli/dist/projects.d.ts +0 -9
- package/packages/cli/dist/projects.js +0 -159
- package/packages/cli/dist/schedules.d.ts +0 -2
- package/packages/cli/dist/schedules.js +0 -45
- package/packages/cli/dist/sessions.d.ts +0 -43
- package/packages/cli/dist/sessions.js +0 -458
- package/packages/cli/dist/tasks.d.ts +0 -29
- package/packages/cli/dist/tasks.js +0 -345
- package/packages/cli/dist/terminal.d.ts +0 -8
- package/packages/cli/dist/terminal.js +0 -79
- package/packages/cli/dist/usage.d.ts +0 -3
- package/packages/cli/dist/usage.js +0 -78
- package/packages/cli/dist/web-service.d.ts +0 -38
- package/packages/cli/dist/web-service.js +0 -119
- package/packages/client/README.md +0 -29
- package/packages/client/dist/acp-probe.d.ts +0 -44
- package/packages/client/dist/acp-probe.js +0 -37
- package/packages/client/dist/antigravity-probe.d.ts +0 -34
- package/packages/client/dist/antigravity-probe.js +0 -95
- package/packages/client/dist/command.d.ts +0 -5
- package/packages/client/dist/command.js +0 -33
- package/packages/client/dist/doctor.d.ts +0 -13
- package/packages/client/dist/doctor.js +0 -587
- package/packages/client/dist/index.d.ts +0 -151
- package/packages/client/dist/index.js +0 -533
- package/packages/client/dist/integration-lock.d.ts +0 -35
- package/packages/client/dist/integration-lock.js +0 -179
- package/packages/client/dist/ipc.d.ts +0 -42
- package/packages/client/dist/ipc.js +0 -69
- package/packages/client/dist/library-test.d.ts +0 -94
- package/packages/client/dist/library-test.js +0 -37
- package/packages/client/dist/mcp-probe.d.ts +0 -24
- package/packages/client/dist/mcp-probe.js +0 -147
- package/packages/client/dist/portable.d.ts +0 -19
- package/packages/client/dist/portable.js +0 -33
- package/packages/client/dist/prompt.d.ts +0 -32
- package/packages/client/dist/prompt.js +0 -59
- package/packages/client/dist/render.d.ts +0 -6
- package/packages/client/dist/render.js +0 -120
- package/packages/client/dist/rpc/client.d.ts +0 -82
- package/packages/client/dist/rpc/client.js +0 -292
- package/packages/client/dist/rpc/errors.d.ts +0 -42
- package/packages/client/dist/rpc/errors.js +0 -34
- package/packages/client/dist/rpc/framing.d.ts +0 -21
- package/packages/client/dist/rpc/framing.js +0 -57
- package/packages/client/dist/rpc/handshake.d.ts +0 -19
- package/packages/client/dist/rpc/handshake.js +0 -8
- package/packages/client/dist/rpc/reconnect.d.ts +0 -97
- package/packages/client/dist/rpc/reconnect.js +0 -227
- package/packages/client/dist/rpc/registry.d.ts +0 -211
- package/packages/client/dist/rpc/registry.js +0 -145
- package/packages/client/dist/rpc/timers.d.ts +0 -11
- package/packages/client/dist/rpc/timers.js +0 -11
- package/packages/client/dist/service.d.ts +0 -50
- package/packages/client/dist/service.js +0 -143
- package/packages/client/dist/setup.d.ts +0 -2
- package/packages/client/dist/setup.js +0 -146
- package/packages/client/dist/supervise.d.ts +0 -14
- package/packages/client/dist/supervise.js +0 -87
- package/packages/client/dist/websocket.d.ts +0 -51
- package/packages/client/dist/websocket.js +0 -190
- package/packages/core/README.md +0 -7
- package/packages/core/dist/adapter.d.ts +0 -20
- package/packages/core/dist/adapter.js +0 -30
- package/packages/core/dist/atomic.d.ts +0 -2
- package/packages/core/dist/atomic.js +0 -28
- package/packages/core/dist/backup.d.ts +0 -27
- package/packages/core/dist/backup.js +0 -681
- package/packages/core/dist/beads.d.ts +0 -65
- package/packages/core/dist/beads.js +0 -213
- package/packages/core/dist/delegation.d.ts +0 -2
- package/packages/core/dist/delegation.js +0 -32
- package/packages/core/dist/errors.d.ts +0 -4
- package/packages/core/dist/errors.js +0 -11
- package/packages/core/dist/formulas.d.ts +0 -25
- package/packages/core/dist/formulas.js +0 -201
- package/packages/core/dist/hook-run.d.ts +0 -44
- package/packages/core/dist/hook-run.js +0 -60
- package/packages/core/dist/hooks.d.ts +0 -35
- package/packages/core/dist/hooks.js +0 -30
- package/packages/core/dist/index.d.ts +0 -31
- package/packages/core/dist/index.js +0 -65
- package/packages/core/dist/init.d.ts +0 -30
- package/packages/core/dist/init.js +0 -89
- package/packages/core/dist/library-edit.d.ts +0 -93
- package/packages/core/dist/library-edit.js +0 -368
- package/packages/core/dist/library.d.ts +0 -28
- package/packages/core/dist/library.js +0 -108
- package/packages/core/dist/log.d.ts +0 -37
- package/packages/core/dist/log.js +0 -156
- package/packages/core/dist/migrations.d.ts +0 -9
- package/packages/core/dist/migrations.js +0 -95
- package/packages/core/dist/models.d.ts +0 -11
- package/packages/core/dist/models.js +0 -44
- package/packages/core/dist/permissions.d.ts +0 -14
- package/packages/core/dist/permissions.js +0 -229
- package/packages/core/dist/profiles.d.ts +0 -27
- package/packages/core/dist/profiles.js +0 -122
- package/packages/core/dist/promptsafe.d.ts +0 -1
- package/packages/core/dist/promptsafe.js +0 -13
- package/packages/core/dist/providers.d.ts +0 -90
- package/packages/core/dist/providers.js +0 -101
- package/packages/core/dist/resolver.d.ts +0 -41
- package/packages/core/dist/resolver.js +0 -240
- package/packages/core/dist/safe-path.d.ts +0 -2
- package/packages/core/dist/safe-path.js +0 -24
- package/packages/core/dist/shell.d.ts +0 -16
- package/packages/core/dist/shell.js +0 -22
- package/packages/core/dist/state-schema.d.ts +0 -9
- package/packages/core/dist/state-schema.js +0 -54
- package/packages/core/dist/task-rows.d.ts +0 -47
- package/packages/core/dist/task-rows.js +0 -45
- package/packages/core/dist/tasks.d.ts +0 -128
- package/packages/core/dist/tasks.js +0 -835
- package/packages/core/dist/teams.d.ts +0 -80
- package/packages/core/dist/teams.js +0 -159
- package/packages/core/dist/template-path.d.ts +0 -2
- package/packages/core/dist/template-path.js +0 -10
- package/packages/core/dist/trust.d.ts +0 -8
- package/packages/core/dist/trust.js +0 -47
- package/packages/core/dist/types.d.ts +0 -51
- package/packages/core/dist/upgrade.d.ts +0 -10
- package/packages/core/dist/upgrade.js +0 -200
- package/packages/core/dist/user-settings.d.ts +0 -6
- package/packages/core/dist/user-settings.js +0 -72
- package/packages/core/dist/user-worktree.d.ts +0 -29
- package/packages/core/dist/user-worktree.js +0 -242
- package/packages/core/dist/validation.d.ts +0 -17
- package/packages/core/dist/validation.js +0 -296
- package/packages/core/dist/verify.d.ts +0 -15
- package/packages/core/dist/verify.js +0 -123
- package/packages/core/dist/workflow.d.ts +0 -45
- package/packages/core/dist/workflow.js +0 -33
- package/templates/ALP.md +0 -52
- package/templates/agents/lead/AGENT.md +0 -90
- package/templates/agents/main/AGENT.md +0 -150
- package/templates/agents/oracle/AGENT.md +0 -44
- package/templates/agents/peer/AGENT.md +0 -55
- package/templates/agents/reviewer/AGENT.md +0 -80
- package/templates/agents/supervisor/AGENT.md +0 -72
- package/templates/providers/antigravity.json +0 -6
- package/templates/providers/opencode.json +0 -7
- package/templates/role-skills.json +0 -8
- package/templates/skills/bug-loop/SKILL.md +0 -44
- package/templates/skills/bug-loop/references/test-proof.md +0 -25
- package/templates/skills/goal-griller/SKILL.md +0 -49
- package/templates/skills/prompt-leverage/SKILL.md +0 -37
- package/templates/skills/prompt-leverage/references/brief-template.md +0 -27
- package/templates/skills/sequence-execution-plan/SKILL.md +0 -42
- package/templates/skills/sequence-execution-plan/references/plan-template.md +0 -22
- package/templates/skills/smart-commits/SKILL.md +0 -40
- package/templates/skills/xia/SKILL.md +0 -42
- package/templates/teams/cafe/HOUSE_RULES.md +0 -1
- package/templates/teams/cafe/team.json +0 -15
- package/templates/teams/pho/HOUSE_RULES.md +0 -1
- package/templates/teams/pho/team.json +0 -14
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
// packages/core/src/log.js
|
|
2
|
-
import { open, stat } from "node:fs/promises";
|
|
3
|
-
var LEVELS = Object.freeze({ debug: 10, info: 20, warn: 30, error: 40 });
|
|
4
|
-
var REDACTED = "[redacted]";
|
|
5
|
-
var OMITTED = "[omitted]";
|
|
6
|
-
var MAX_STRING = 2e3;
|
|
7
|
-
var MAX_DEPTH = 5;
|
|
8
|
-
var MAX_KEYS = 50;
|
|
9
|
-
var MAX_ITEMS = 20;
|
|
10
|
-
var STACK_LINES = 8;
|
|
11
|
-
var SECRET_KEY = /pass(word|wd)?|secret|token|api[-_]?key|authorization|credential|cookie|private[-_]?key|bearer|signature/i;
|
|
12
|
-
var OMITTED_KEY = /^(env|environment|prompt|prompts|instructions|content|text|input|headers|body|args|argv)$/i;
|
|
13
|
-
var SECRET_NAME = /KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH|COOKIE|PRIVATE/i;
|
|
14
|
-
var PATTERNS = [
|
|
15
|
-
[/\b(Bearer|Basic)\s+[A-Za-z0-9._~+/=-]{8,}/gi, `$1 ${REDACTED}`],
|
|
16
|
-
[/\b(sk|rk|pk)-[A-Za-z0-9_-]{16,}/g, REDACTED],
|
|
17
|
-
[/\bgh[pousr]_[A-Za-z0-9]{20,}/g, REDACTED],
|
|
18
|
-
[/\bgithub_pat_[A-Za-z0-9_]{20,}/g, REDACTED],
|
|
19
|
-
[/\bxox[abprs]-[A-Za-z0-9-]{10,}/g, REDACTED],
|
|
20
|
-
[/\bAKIA[0-9A-Z]{16}\b/g, REDACTED],
|
|
21
|
-
[/\bAIza[0-9A-Za-z_-]{30,}/g, REDACTED],
|
|
22
|
-
[/\beyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{4,}/g, REDACTED],
|
|
23
|
-
[/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?(-----END [A-Z ]*PRIVATE KEY-----|$)/g, REDACTED],
|
|
24
|
-
[/(\b[a-z][a-z0-9+.-]*:\/\/)[^\s/@:]+:[^\s/@]+@/gi, `$1${REDACTED}@`],
|
|
25
|
-
// NAME=value and NAME: value for names that look like secrets; also JSON "token": "value".
|
|
26
|
-
[/(\b[\w.-]*(?:key|token|secret|passw(?:or)?d|credential|authorization|cookie)[\w.-]*["']?\s*[=:]\s*)(?:"[^"]{4,}"|'[^']{4,}'|[^\s,;&"']{8,})/gi, `$1${REDACTED}`],
|
|
27
|
-
// --token value, --api-key value
|
|
28
|
-
[/(--[\w-]*(?:key|token|secret|passw(?:or)?d|credential)[\w-]*\s+)[^\s-][^\s]*/gi, `$1${REDACTED}`]
|
|
29
|
-
];
|
|
30
|
-
function secretValues(env) {
|
|
31
|
-
const values = /* @__PURE__ */ new Set();
|
|
32
|
-
for (const [name, value] of Object.entries(env ?? {})) if (typeof value === "string" && value.length >= 8 && SECRET_NAME.test(name)) values.add(value);
|
|
33
|
-
return [...values].sort((a, b) => b.length - a.length);
|
|
34
|
-
}
|
|
35
|
-
function scrubText(text, { env = process.env, max = MAX_STRING } = {}) {
|
|
36
|
-
let result = String(text);
|
|
37
|
-
for (const value of secretValues(env)) result = result.split(value).join(REDACTED);
|
|
38
|
-
for (const [pattern, replacement] of PATTERNS) result = result.replace(pattern, replacement);
|
|
39
|
-
return result.length > max ? `${result.slice(0, max)}... (${result.length - max} more characters)` : result;
|
|
40
|
-
}
|
|
41
|
-
function describeError(error, options = {}) {
|
|
42
|
-
if (!(error instanceof Error)) return { message: scrubText(error, options) };
|
|
43
|
-
const stack = typeof error.stack === "string" ? error.stack.split("\n").slice(0, STACK_LINES).join("\n") : void 0;
|
|
44
|
-
return {
|
|
45
|
-
name: error.name,
|
|
46
|
-
...typeof error.code === "string" || typeof error.code === "number" ? { code: error.code } : {},
|
|
47
|
-
message: scrubText(error.message, options),
|
|
48
|
-
...stack ? { stack: scrubText(stack, options) } : {},
|
|
49
|
-
...error.cause !== void 0 ? { cause: describeError(error.cause, options) } : {}
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
function redact(value, options = {}, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
|
|
53
|
-
if (value === null || value === void 0 || typeof value === "boolean" || typeof value === "number") return value;
|
|
54
|
-
if (typeof value === "string") return scrubText(value, options);
|
|
55
|
-
if (typeof value === "bigint") return String(value);
|
|
56
|
-
if (typeof value !== "object") return void 0;
|
|
57
|
-
if (value instanceof Error) return describeError(value, options);
|
|
58
|
-
if (seen.has(value)) return "[circular]";
|
|
59
|
-
if (depth >= MAX_DEPTH) return "[too deep]";
|
|
60
|
-
seen.add(value);
|
|
61
|
-
if (Array.isArray(value)) {
|
|
62
|
-
const items = value.slice(0, MAX_ITEMS).map((item) => redact(item, options, depth + 1, seen));
|
|
63
|
-
return value.length > MAX_ITEMS ? [...items, `... ${value.length - MAX_ITEMS} more`] : items;
|
|
64
|
-
}
|
|
65
|
-
const result = {};
|
|
66
|
-
for (const [key, item] of Object.entries(value).slice(0, MAX_KEYS)) {
|
|
67
|
-
result[key] = OMITTED_KEY.test(key) ? OMITTED : SECRET_KEY.test(key) ? REDACTED : redact(item, options, depth + 1, seen);
|
|
68
|
-
}
|
|
69
|
-
return result;
|
|
70
|
-
}
|
|
71
|
-
var CORRELATION = ["sessionId", "rootId", "assignmentId", "clientMessageId", "requestId", "agent"];
|
|
72
|
-
var stderrSink = (line) => {
|
|
73
|
-
try {
|
|
74
|
-
process.stderr.write(`${line}
|
|
75
|
-
`);
|
|
76
|
-
} catch {
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
function createLogger({ component, level, context = {}, write = stderrSink, now = () => /* @__PURE__ */ new Date(), env = process.env } = {}) {
|
|
80
|
-
const threshold = LEVELS[level ?? env.ALP_LOG_LEVEL] ?? LEVELS.info;
|
|
81
|
-
const options = { env };
|
|
82
|
-
const emit = (name, message, fields = {}) => {
|
|
83
|
-
if (LEVELS[name] < threshold) return;
|
|
84
|
-
try {
|
|
85
|
-
const { code, error, ...rest } = { ...context, ...fields };
|
|
86
|
-
const record = {
|
|
87
|
-
time: now().toISOString(),
|
|
88
|
-
level: name,
|
|
89
|
-
component,
|
|
90
|
-
...code ? { code: String(code) } : {},
|
|
91
|
-
msg: scrubText(message, options)
|
|
92
|
-
};
|
|
93
|
-
for (const key of CORRELATION) if (rest[key] !== void 0) record[key] = redact(String(rest[key]), options);
|
|
94
|
-
if (error !== void 0) {
|
|
95
|
-
record.error = describeError(error, options);
|
|
96
|
-
if (!record.code && record.error.code !== void 0) record.code = String(record.error.code);
|
|
97
|
-
}
|
|
98
|
-
for (const [key, value] of Object.entries(rest)) {
|
|
99
|
-
if (CORRELATION.includes(key)) continue;
|
|
100
|
-
record[key] = OMITTED_KEY.test(key) ? OMITTED : SECRET_KEY.test(key) ? REDACTED : redact(value, options);
|
|
101
|
-
}
|
|
102
|
-
write(JSON.stringify(record));
|
|
103
|
-
} catch {
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
return {
|
|
107
|
-
component,
|
|
108
|
-
debug: (message, fields) => emit("debug", message, fields),
|
|
109
|
-
info: (message, fields) => emit("info", message, fields),
|
|
110
|
-
warn: (message, fields) => emit("warn", message, fields),
|
|
111
|
-
error: (message, fields) => emit("error", message, fields),
|
|
112
|
-
child: (extra = {}, name = component) => createLogger({ component: name, level, context: { ...context, ...extra }, write, now, env })
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
var TAIL_BYTES = 256 * 1024;
|
|
116
|
-
async function readLogTail(file, { bytes = TAIL_BYTES, env = process.env } = {}) {
|
|
117
|
-
let handle;
|
|
118
|
-
try {
|
|
119
|
-
handle = await open(file, "r");
|
|
120
|
-
const { size } = await stat(file);
|
|
121
|
-
const start = Math.max(0, size - bytes);
|
|
122
|
-
const buffer = Buffer.alloc(size - start);
|
|
123
|
-
await handle.read(buffer, 0, buffer.length, start);
|
|
124
|
-
const lines = buffer.toString("utf8").split("\n");
|
|
125
|
-
if (start > 0) lines.shift();
|
|
126
|
-
const records = [];
|
|
127
|
-
for (const line of lines) {
|
|
128
|
-
if (!line.trim()) continue;
|
|
129
|
-
try {
|
|
130
|
-
const record = JSON.parse(line);
|
|
131
|
-
if (record && typeof record === "object" && typeof record.time === "string" && typeof record.level === "string" && typeof record.msg === "string") {
|
|
132
|
-
records.push(redact(record, { env }));
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
} catch {
|
|
136
|
-
}
|
|
137
|
-
records.push({ legacy: scrubText(line, { env, max: 500 }) });
|
|
138
|
-
}
|
|
139
|
-
return records;
|
|
140
|
-
} catch (error) {
|
|
141
|
-
if (error?.code === "ENOENT") return [];
|
|
142
|
-
throw error;
|
|
143
|
-
} finally {
|
|
144
|
-
await handle?.close();
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
export {
|
|
148
|
-
LEVELS,
|
|
149
|
-
OMITTED,
|
|
150
|
-
REDACTED,
|
|
151
|
-
createLogger,
|
|
152
|
-
describeError,
|
|
153
|
-
readLogTail,
|
|
154
|
-
redact,
|
|
155
|
-
scrubText
|
|
156
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export type Migration = { from: number; to: number; name: string; run(home: string): Promise<void> };
|
|
2
|
-
export const MIGRATIONS: Migration[];
|
|
3
|
-
export type MigrationResult = { from: number; to: number; steps: Array<{ name: string; from: number; to: number; backup: string; resumed: boolean }> };
|
|
4
|
-
export function migrateState(home: string, options?: {
|
|
5
|
-
by?: string;
|
|
6
|
-
migrations?: Migration[];
|
|
7
|
-
target?: number;
|
|
8
|
-
log?: { info(message: string, fields?: object): void; warn(message: string, fields?: object): void };
|
|
9
|
-
}): Promise<MigrationResult>;
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
// packages/core/src/migrations.js
|
|
2
|
-
import { readdir, readFile, rm, stat } from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { AlpError } from "./errors.js";
|
|
5
|
-
import { writeAtomic } from "./atomic.js";
|
|
6
|
-
import { STATE_SCHEMA, assertStateSupported, migrationFile, readStateSchema, stateDir, writeStateSchema } from "./state-schema.js";
|
|
7
|
-
import { STATE_UNITS, automaticBackup, restoreBackup } from "./backup.js";
|
|
8
|
-
async function timelineCursors(home) {
|
|
9
|
-
const directory = path.join(stateDir(home), "timeline");
|
|
10
|
-
const names = await readdir(directory).catch((error) => {
|
|
11
|
-
if (error?.code === "ENOENT") return [];
|
|
12
|
-
throw error;
|
|
13
|
-
});
|
|
14
|
-
for (const name of names.filter((name2) => name2.endsWith(".jsonl"))) {
|
|
15
|
-
const file = path.join(directory, name);
|
|
16
|
-
const lines = [];
|
|
17
|
-
let cursor = 0;
|
|
18
|
-
let changed = false;
|
|
19
|
-
for (const line of (await readFile(file, "utf8")).split("\n")) {
|
|
20
|
-
if (!line) continue;
|
|
21
|
-
let envelope;
|
|
22
|
-
try {
|
|
23
|
-
envelope = JSON.parse(line);
|
|
24
|
-
} catch {
|
|
25
|
-
lines.push(line);
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
cursor = typeof envelope?.cursor === "number" && envelope.cursor > cursor ? envelope.cursor : cursor + 1;
|
|
29
|
-
if (envelope?.cursor === cursor) {
|
|
30
|
-
lines.push(line);
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
lines.push(JSON.stringify({ ...envelope, cursor }));
|
|
34
|
-
changed = true;
|
|
35
|
-
}
|
|
36
|
-
if (changed) await writeAtomic(file, lines.map((line) => `${line}
|
|
37
|
-
`).join(""));
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
var MIGRATIONS = [
|
|
41
|
-
{ from: 1, to: 2, name: "timeline-cursors", run: timelineCursors }
|
|
42
|
-
];
|
|
43
|
-
async function readJournal(home) {
|
|
44
|
-
try {
|
|
45
|
-
return JSON.parse(await readFile(migrationFile(home), "utf8"));
|
|
46
|
-
} catch (error) {
|
|
47
|
-
if (error?.code === "ENOENT") return void 0;
|
|
48
|
-
return {};
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
var exists = (file) => stat(file).then(() => true, () => false);
|
|
52
|
-
async function migrateState(home, { by = "alp", migrations = MIGRATIONS, target = STATE_SCHEMA, log } = {}) {
|
|
53
|
-
const info = assertStateSupported(await readStateSchema(home), home);
|
|
54
|
-
let journal = await readJournal(home);
|
|
55
|
-
if (journal && Number.isSafeInteger(journal.to) && journal.to <= info.schema) {
|
|
56
|
-
await rm(migrationFile(home), { force: true });
|
|
57
|
-
journal = void 0;
|
|
58
|
-
}
|
|
59
|
-
if (info.fresh && !journal) {
|
|
60
|
-
await writeStateSchema(home, target, by);
|
|
61
|
-
return { from: target, to: target, steps: [] };
|
|
62
|
-
}
|
|
63
|
-
let schema = info.schema;
|
|
64
|
-
const steps = [];
|
|
65
|
-
while (schema < target) {
|
|
66
|
-
const step = migrations.find((candidate) => candidate.from === schema);
|
|
67
|
-
if (!step) throw new AlpError("STATE_MIGRATION_MISSING", `ALP has no migration from state schema ${schema}; the state was not changed`);
|
|
68
|
-
const resumed = journal?.to === step.to && typeof journal.backup === "string" && await exists(journal.backup);
|
|
69
|
-
const backup = resumed ? journal.backup : await automaticBackup(home, `pre-migrate-v${step.from}-v${step.to}`, { units: STATE_UNITS, by });
|
|
70
|
-
if (!resumed) await writeAtomic(migrationFile(home), JSON.stringify({ from: step.from, to: step.to, name: step.name, backup, by, startedAt: (/* @__PURE__ */ new Date()).toISOString() }) + "\n");
|
|
71
|
-
log?.info(`${resumed ? "continuing" : "running"} state migration ${step.name} (schema ${step.from} \u2192 ${step.to}); backup ${backup}`, { code: "ALP_STATE_MIGRATING", from: step.from, to: step.to, migration: step.name, resumed });
|
|
72
|
-
try {
|
|
73
|
-
await step.run(home);
|
|
74
|
-
} catch (error) {
|
|
75
|
-
try {
|
|
76
|
-
await restoreBackup({ home, file: backup, projects: false, safety: false, clearLive: false, by });
|
|
77
|
-
} catch (rollback) {
|
|
78
|
-
throw new AlpError("STATE_MIGRATION_ROLLBACK_FAILED", `state migration ${step.name} failed (${error?.message ?? error}) and putting the state back from ${backup} failed too (${rollback?.message ?? rollback}); the next start tries the migration again. See docs/alp/data-recovery.md`, { cause: error });
|
|
79
|
-
}
|
|
80
|
-
await rm(migrationFile(home), { force: true });
|
|
81
|
-
throw new AlpError("STATE_MIGRATION_FAILED", `state migration ${step.name} (schema ${step.from} \u2192 ${step.to}) failed: ${error?.message ?? error}; data was restored from ${backup} with workspace authority checks. See docs/alp/data-recovery.md`, { cause: error });
|
|
82
|
-
}
|
|
83
|
-
await writeStateSchema(home, step.to, by);
|
|
84
|
-
await rm(migrationFile(home), { force: true });
|
|
85
|
-
steps.push({ name: step.name, from: step.from, to: step.to, backup, resumed });
|
|
86
|
-
schema = step.to;
|
|
87
|
-
journal = void 0;
|
|
88
|
-
}
|
|
89
|
-
if (!info.marked && !steps.length) await writeStateSchema(home, schema, by);
|
|
90
|
-
return { from: info.schema, to: schema, steps };
|
|
91
|
-
}
|
|
92
|
-
export {
|
|
93
|
-
MIGRATIONS,
|
|
94
|
-
migrateState
|
|
95
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @type {Array<{ runtime: 'codex' | 'claude' | 'antigravity', id: string, label: string, description: string, efforts: string[], effort?: string }>}
|
|
3
|
-
*/
|
|
4
|
-
export const MODELS: Array<{
|
|
5
|
-
runtime: "codex" | "claude" | "antigravity";
|
|
6
|
-
id: string;
|
|
7
|
-
label: string;
|
|
8
|
-
description: string;
|
|
9
|
-
efforts: string[];
|
|
10
|
-
effort?: string;
|
|
11
|
-
}>;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// packages/core/src/models.js
|
|
2
|
-
var codexFull = ["low", "medium", "high", "xhigh", "max", "ultra"];
|
|
3
|
-
var codexStandard = ["low", "medium", "high", "xhigh", "max"];
|
|
4
|
-
var claudeFull = ["low", "medium", "high", "xhigh", "max", "ultracode"];
|
|
5
|
-
var claudeLegacy = ["off", "low", "medium", "high", "xhigh", "max", "ultracode"];
|
|
6
|
-
var claude46 = ["off", "low", "medium", "high", "max"];
|
|
7
|
-
var MODELS = [
|
|
8
|
-
["codex", "gpt-6.1-sol", "GPT-6.1-Sol", "Latest workhorse model for coding and everyday work.", codexFull, "low"],
|
|
9
|
-
// ALP runs GPT-6 Astra at low effort only.
|
|
10
|
-
["codex", "gpt-6-astra", "GPT-6-Astra", "Frontier intelligence for the most demanding work.", ["low"], "low"],
|
|
11
|
-
["codex", "gpt-6-sol", "GPT-6-Sol", "Previous generation workhorse model.", codexFull, "low"],
|
|
12
|
-
["codex", "gpt-6-luna", "GPT-6-Luna", "Fast and affordable model for easier tasks.", codexStandard, "low"],
|
|
13
|
-
["codex", "gpt-5.6-sol", "GPT-5.6-Sol", "Older generation workhorse model.", codexFull, "low"],
|
|
14
|
-
["codex", "gpt-5.6-terra", "GPT-5.6-Terra", "Older balanced model for straightforward work.", codexFull, "low"],
|
|
15
|
-
["codex", "gpt-5.6-luna", "GPT-5.6-Luna", "Older fast and efficient model.", codexStandard, "low"],
|
|
16
|
-
["claude", "claude-opus-5-5", "Opus 5.5", "Latest release.", claudeFull, "medium"],
|
|
17
|
-
["claude", "claude-opus-5", "Opus 5", "Previous release.", claudeLegacy, "high"],
|
|
18
|
-
["claude", "claude-fable-5-1", "Fable 5.1", "Most powerful model.", claudeFull, "high"],
|
|
19
|
-
["claude", "claude-fable-5", "Fable 5", "Previous release.", claudeFull, "high"],
|
|
20
|
-
["claude", "claude-opus-4-8[1m]", "Opus 4.8 1M", "Opus 4.8 with 1M context window.", claudeLegacy, "high"],
|
|
21
|
-
["claude", "claude-opus-4-8", "Opus 4.8", "Previous release.", claudeLegacy, "high"],
|
|
22
|
-
["claude", "claude-sonnet-5-5", "Sonnet 5.5", "Best for everyday tasks.", claudeFull, "medium"],
|
|
23
|
-
["claude", "claude-sonnet-5", "Sonnet 5", "Previous release.", claudeLegacy, "high"],
|
|
24
|
-
["claude", "claude-sonnet-5[1m]", "Sonnet 5 1M", "Sonnet 5 with 1M context window.", claudeLegacy, "high"],
|
|
25
|
-
["claude", "claude-opus-4-7[1m]", "Opus 4.7 1M", "Opus 4.7 with 1M context window.", claudeLegacy, "high"],
|
|
26
|
-
["claude", "claude-opus-4-7", "Opus 4.7", "Previous release.", claudeLegacy, "high"],
|
|
27
|
-
["claude", "claude-opus-4-6[1m]", "Opus 4.6 1M", "Opus 4.6 with 1M context window.", claude46, "high"],
|
|
28
|
-
["claude", "claude-opus-4-6", "Opus 4.6", "Most capable for complex work.", claude46, "high"],
|
|
29
|
-
["claude", "claude-sonnet-4-6[1m]", "Sonnet 4.6 1M", "Sonnet 4.6 with 1M context window.", claude46, "high"],
|
|
30
|
-
["claude", "claude-sonnet-4-6", "Sonnet 4.6", "Best for everyday tasks.", claude46, "high"],
|
|
31
|
-
["claude", "claude-haiku-4-5", "Haiku 4.5", "Fastest for quick answers.", [], void 0],
|
|
32
|
-
["claude", "sonnet", "sonnet", "From Claude settings.json model.", [], void 0],
|
|
33
|
-
["antigravity", "gemini-3.8-flash-high", "Gemini 3.8 Flash (High)", "High reasoning effort workhorse for complex tasks.", [], void 0],
|
|
34
|
-
["antigravity", "gemini-3.8-flash-medium", "Gemini 3.8 Flash (Medium)", "Balanced speed and reasoning.", [], void 0],
|
|
35
|
-
["antigravity", "gemini-3.8-flash-low", "Gemini 3.8 Flash (Low)", "Fast and efficient for straightforward work.", [], void 0],
|
|
36
|
-
["antigravity", "gemini-2.5-pro", "Gemini 2.5 Pro", "Deep reasoning for coding and analysis.", [], void 0],
|
|
37
|
-
["antigravity", "gemini-2.5-flash", "Gemini 2.5 Flash", "Fast and versatile everyday model.", [], void 0],
|
|
38
|
-
["antigravity", "claude-sonnet-4-6", "Claude Sonnet 4.6", "Sonnet 4.6 via Antigravity.", [], void 0],
|
|
39
|
-
["antigravity", "claude-opus-4-6-thinking", "Claude Opus 4.6 Thinking", "Opus 4.6 with thinking via Antigravity.", [], void 0],
|
|
40
|
-
["antigravity", "gpt-oss-120b-medium", "GPT-OSS 120B (Medium)", "Open weights model via Antigravity.", [], void 0]
|
|
41
|
-
].map(([runtime, id, label, description, efforts, effort]) => ({ runtime, id, label, description, efforts, ...effort ? { effort } : {} }));
|
|
42
|
-
export {
|
|
43
|
-
MODELS
|
|
44
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export type PermissionBase = 'read-only' | 'workspace-write' | 'full-access';
|
|
2
|
-
export type PermissionProfile = { name: string; base: PermissionBase; allow: string[]; ask: string[]; deny: string[]; beyondMode: 'refuse' | 'ask'; workdir?: 'copy' };
|
|
3
|
-
export const BASES: PermissionBase[];
|
|
4
|
-
export const ADVISORS: string[];
|
|
5
|
-
export const MAX_RULES: number;
|
|
6
|
-
export const TOOLS: string[];
|
|
7
|
-
export function parseRule(rule: unknown, source?: string): { tool: string; specifier?: string };
|
|
8
|
-
export function validatePermissions(value: unknown, source: string): { profiles: Record<string, { base?: PermissionBase; beyondMode?: 'refuse' | 'ask'; workdir?: 'copy'; allow: string[]; ask: string[]; deny: string[] }>; agents: Record<string, string> };
|
|
9
|
-
export function addAllowRule(projectRoot: string, home: string | undefined, profileName: string, rule: string): Promise<string>;
|
|
10
|
-
export function profileFor(projectRoot: string, home: string | undefined, agent: string): Promise<PermissionProfile | null>;
|
|
11
|
-
export function capMode(mode: string, base: string): string;
|
|
12
|
-
export function unwrapShell(command: string): string;
|
|
13
|
-
export function simpleCommands(line: string): string[] | null;
|
|
14
|
-
export function commandDecision(profile: Pick<PermissionProfile, 'allow' | 'deny'> & { ask?: string[] }, command: string): 'allow' | 'ask' | 'deny' | undefined;
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
// packages/core/src/permissions.js
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { randomUUID } from "node:crypto";
|
|
4
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
5
|
-
import { moveFile } from "./atomic.js";
|
|
6
|
-
import { AlpError } from "./errors.js";
|
|
7
|
-
var BASES = ["read-only", "workspace-write", "full-access"];
|
|
8
|
-
var RANK = { "read-only": 0, "workspace-write": 1, "full-access": 2 };
|
|
9
|
-
var ADVISORS = ["oracle", "reviewer", "supervisor"];
|
|
10
|
-
var MAX_RULES = 200;
|
|
11
|
-
var NAME = /^[\w.-]{1,64}$/;
|
|
12
|
-
var RULE = /^([A-Za-z][\w-]*)(?:\((.*)\))?$/s;
|
|
13
|
-
var TOOLS = ["Bash", "Read", "Edit", "Write", "MultiEdit", "NotebookEdit", "Glob", "Grep", "WebFetch", "WebSearch", "Skill"];
|
|
14
|
-
var own = (value, key) => Object.hasOwn(value, key) ? value[key] : void 0;
|
|
15
|
-
var setOwn = (value, key, entry) => Object.defineProperty(value, key, { value: entry, enumerable: true, writable: true, configurable: true });
|
|
16
|
-
var object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
17
|
-
var fail = (source, message) => {
|
|
18
|
-
throw new AlpError("INVALID_SETTINGS", `${source}: ${message}`);
|
|
19
|
-
};
|
|
20
|
-
function parseRule(rule, source = "rule") {
|
|
21
|
-
if (typeof rule !== "string" || rule.length > 500) fail(source, "a rule is text of at most 500 characters");
|
|
22
|
-
const match = RULE.exec(rule.trim());
|
|
23
|
-
if (!match) fail(source, `${JSON.stringify(rule)} is not Tool or Tool(specifier)`);
|
|
24
|
-
const [, tool, specifier] = match;
|
|
25
|
-
if (!TOOLS.includes(tool) && !/^mcp__[\w-]+(__[\w-]+)?$/.test(tool)) fail(source, `${JSON.stringify(rule)} names unknown tool ${tool}; use ${TOOLS.join(", ")} or mcp__<server>__<tool>`);
|
|
26
|
-
if (specifier !== void 0 && !specifier.trim()) fail(source, `${JSON.stringify(rule)} has an empty specifier`);
|
|
27
|
-
return { tool, ...specifier !== void 0 && specifier.trim() !== "*" ? { specifier: specifier.trim() } : {} };
|
|
28
|
-
}
|
|
29
|
-
function validatePermissions(value, source) {
|
|
30
|
-
if (value === void 0) return { profiles: {}, agents: {} };
|
|
31
|
-
if (!object(value)) fail(source, "permissions must be an object");
|
|
32
|
-
for (const key of Object.keys(value)) if (!["profiles", "agents"].includes(key)) fail(source, `unsupported permissions field '${key}'`);
|
|
33
|
-
const profiles = {};
|
|
34
|
-
if (value.profiles !== void 0) {
|
|
35
|
-
if (!object(value.profiles)) fail(source, "permissions.profiles must be an object");
|
|
36
|
-
for (const [name, profile] of Object.entries(value.profiles)) {
|
|
37
|
-
const where = `permissions.profiles.${name}`;
|
|
38
|
-
if (!NAME.test(name)) fail(source, `${where}: a profile name has letters, digits, dots, dashes and underscores`);
|
|
39
|
-
if (!object(profile)) fail(source, `${where} must be an object`);
|
|
40
|
-
for (const key of Object.keys(profile)) if (!["base", "allow", "ask", "deny", "beyondMode", "workdir"].includes(key)) fail(source, `${where}: unsupported field '${key}'`);
|
|
41
|
-
if (profile.workdir !== void 0 && profile.workdir !== "copy") fail(source, `${where}.workdir must be copy`);
|
|
42
|
-
if (profile.workdir === "copy" && profile.base !== void 0 && profile.base !== "read-only") fail(source, `${where}: workdir copy is for read-only profiles; writers use worktree isolation`);
|
|
43
|
-
if (profile.base !== void 0 && !BASES.includes(profile.base)) fail(source, `${where}.base must be ${BASES.join(", ")}`);
|
|
44
|
-
if (profile.beyondMode !== void 0 && !["refuse", "ask"].includes(profile.beyondMode)) fail(source, `${where}.beyondMode must be refuse or ask`);
|
|
45
|
-
const rules = {};
|
|
46
|
-
for (const kind of ["allow", "ask", "deny"]) {
|
|
47
|
-
const list = profile[kind] ?? [];
|
|
48
|
-
if (!Array.isArray(list) || list.length > MAX_RULES) fail(source, `${where}.${kind} must list at most ${MAX_RULES} rules`);
|
|
49
|
-
for (const rule of list) parseRule(rule, `${source}: ${where}.${kind}`);
|
|
50
|
-
rules[kind] = list.map((rule) => rule.trim());
|
|
51
|
-
}
|
|
52
|
-
setOwn(profiles, name, { ...profile.base ? { base: profile.base } : {}, ...profile.beyondMode ? { beyondMode: profile.beyondMode } : {}, ...profile.workdir ? { workdir: profile.workdir } : {}, ...rules });
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
const agents = {};
|
|
56
|
-
if (value.agents !== void 0) {
|
|
57
|
-
if (!object(value.agents)) fail(source, "permissions.agents must be an object");
|
|
58
|
-
for (const [agent, profile] of Object.entries(value.agents)) {
|
|
59
|
-
if (typeof profile !== "string" || !NAME.test(profile)) fail(source, `permissions.agents.${agent} must name a profile`);
|
|
60
|
-
setOwn(agents, agent, profile);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return { profiles, agents };
|
|
64
|
-
}
|
|
65
|
-
async function settingsPermissions(file) {
|
|
66
|
-
let text;
|
|
67
|
-
try {
|
|
68
|
-
text = await readFile(file, "utf8");
|
|
69
|
-
} catch (error) {
|
|
70
|
-
if (error.code === "ENOENT") return { profiles: {}, agents: {} };
|
|
71
|
-
throw error;
|
|
72
|
-
}
|
|
73
|
-
let settings;
|
|
74
|
-
try {
|
|
75
|
-
settings = JSON.parse(text);
|
|
76
|
-
} catch (error) {
|
|
77
|
-
fail(file, `invalid JSON: ${error.message}`);
|
|
78
|
-
}
|
|
79
|
-
if (!object(settings)) fail(file, "expected an object");
|
|
80
|
-
return validatePermissions(settings.permissions, file);
|
|
81
|
-
}
|
|
82
|
-
async function profileFor(projectRoot, home, agent) {
|
|
83
|
-
const project = await settingsPermissions(path.join(projectRoot, ".alp", "settings.json"));
|
|
84
|
-
const user = home ? await settingsPermissions(path.join(home, "settings.json")) : { profiles: {}, agents: {} };
|
|
85
|
-
const name = own(project.agents, agent) ?? own(user.agents, agent);
|
|
86
|
-
const advisor = ADVISORS.includes(agent);
|
|
87
|
-
if (!name) return advisor ? { name: "read-only", base: "read-only", allow: [], ask: [], deny: [], beyondMode: "refuse" } : null;
|
|
88
|
-
const defined = [own(project.profiles, name), own(user.profiles, name)].filter(Boolean);
|
|
89
|
-
if (!defined.length && !BASES.includes(name)) {
|
|
90
|
-
throw new AlpError("INVALID_SETTINGS", `permissions.agents.${agent} names profile '${name}', which no settings file defines`);
|
|
91
|
-
}
|
|
92
|
-
const base = defined.find((profile) => profile.base)?.base ?? (BASES.includes(name) ? name : advisor ? "read-only" : "full-access");
|
|
93
|
-
const copy = defined.some((profile) => profile.workdir === "copy");
|
|
94
|
-
if (copy && base !== "read-only") throw new AlpError("INVALID_SETTINGS", `Profile '${name}' has workdir copy, which needs base read-only`);
|
|
95
|
-
if (advisor && base !== "read-only") throw new AlpError("INVALID_SETTINGS", `${agent} is an advisor; its profile '${name}' must have base read-only`);
|
|
96
|
-
return {
|
|
97
|
-
name,
|
|
98
|
-
base,
|
|
99
|
-
allow: [...new Set(defined.flatMap((profile) => profile.allow ?? []))],
|
|
100
|
-
ask: [...new Set(defined.flatMap((profile) => profile.ask ?? []))],
|
|
101
|
-
deny: [...new Set(defined.flatMap((profile) => profile.deny ?? []))],
|
|
102
|
-
beyondMode: defined.find((profile) => profile.beyondMode)?.beyondMode ?? "refuse",
|
|
103
|
-
...copy ? { workdir: "copy" } : {}
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
async function addAllowRule(projectRoot, home, profileName, rule) {
|
|
107
|
-
parseRule(rule);
|
|
108
|
-
for (const file of [path.join(projectRoot, ".alp", "settings.json"), ...home ? [path.join(home, "settings.json")] : []]) {
|
|
109
|
-
let settings;
|
|
110
|
-
try {
|
|
111
|
-
settings = JSON.parse(await readFile(file, "utf8"));
|
|
112
|
-
} catch (error) {
|
|
113
|
-
if (error.code === "ENOENT") continue;
|
|
114
|
-
throw error;
|
|
115
|
-
}
|
|
116
|
-
const profile = settings?.permissions?.profiles?.[profileName];
|
|
117
|
-
if (!object(profile)) continue;
|
|
118
|
-
profile.allow = [.../* @__PURE__ */ new Set([...profile.allow ?? [], rule])];
|
|
119
|
-
validatePermissions(settings.permissions, file);
|
|
120
|
-
const temporary = `${file}.${randomUUID().slice(0, 8)}.tmp`;
|
|
121
|
-
await writeFile(temporary, `${JSON.stringify(settings, null, 2)}
|
|
122
|
-
`);
|
|
123
|
-
await moveFile(temporary, file);
|
|
124
|
-
return file;
|
|
125
|
-
}
|
|
126
|
-
throw new AlpError("INVALID_SETTINGS", `No settings file defines profile ${profileName}`);
|
|
127
|
-
}
|
|
128
|
-
var capMode = (mode, base) => (RANK[mode] ?? 0) <= (RANK[base] ?? 0) ? mode : base;
|
|
129
|
-
function unwrapShell(command) {
|
|
130
|
-
const match = /^(?:\/\S*\/)?(?:ba|z|da)?sh\s+-l?c\s+(['"])([\s\S]*)\1\s*$/.exec(command.trim());
|
|
131
|
-
if (!match) return command.trim();
|
|
132
|
-
return match[1] === "'" ? match[2].replace(/'\\''/g, "'") : match[2].replace(/\\(["\\$`])/g, "$1");
|
|
133
|
-
}
|
|
134
|
-
function simpleCommands(line) {
|
|
135
|
-
const parts = [];
|
|
136
|
-
let current = "";
|
|
137
|
-
let quote = null;
|
|
138
|
-
for (let i = 0; i < line.length; i++) {
|
|
139
|
-
const char = line[i];
|
|
140
|
-
if (quote) {
|
|
141
|
-
if (char === "\\" && quote === '"') {
|
|
142
|
-
current += char + (line[++i] ?? "");
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
if (char === quote) quote = null;
|
|
146
|
-
if (quote === '"' && (char === "`" || char === "$" && line[i + 1] === "(")) return null;
|
|
147
|
-
current += char;
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
if (char === "\\") {
|
|
151
|
-
current += char + (line[++i] ?? "");
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
if (char === "'" || char === '"') {
|
|
155
|
-
quote = char;
|
|
156
|
-
current += char;
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
if (char === "`" || char === "$" && line[i + 1] === "(" || (char === "<" || char === ">") && line[i + 1] === "(") return null;
|
|
160
|
-
const two = line.slice(i, i + 2);
|
|
161
|
-
if (two === ">&" || two === "<&" || two === "&>") {
|
|
162
|
-
current += two;
|
|
163
|
-
i++;
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
if (two === "&&" || two === "||") {
|
|
167
|
-
parts.push(current);
|
|
168
|
-
current = "";
|
|
169
|
-
i++;
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
172
|
-
if (char === ";" || char === "|" || char === "\n" || char === "&") {
|
|
173
|
-
parts.push(current);
|
|
174
|
-
current = "";
|
|
175
|
-
continue;
|
|
176
|
-
}
|
|
177
|
-
current += char;
|
|
178
|
-
}
|
|
179
|
-
if (quote) return null;
|
|
180
|
-
parts.push(current);
|
|
181
|
-
return parts.map((part) => part.trim()).filter(Boolean);
|
|
182
|
-
}
|
|
183
|
-
function covers(specifier, command) {
|
|
184
|
-
if (specifier === void 0) return true;
|
|
185
|
-
const normalized = command.replace(/\s+/g, " ");
|
|
186
|
-
if (specifier.endsWith(":*") || specifier.endsWith(" *")) {
|
|
187
|
-
const prefix = specifier.slice(0, -2).trim().replace(/\s+/g, " ");
|
|
188
|
-
return normalized === prefix || normalized.startsWith(`${prefix} `);
|
|
189
|
-
}
|
|
190
|
-
if (specifier.endsWith("*")) return normalized.startsWith(specifier.slice(0, -1).replace(/\s+/g, " "));
|
|
191
|
-
return normalized === specifier.replace(/\s+/g, " ");
|
|
192
|
-
}
|
|
193
|
-
function redirects(command) {
|
|
194
|
-
const unquoted = command.replace(/'[^']*'|"(?:[^"\\]|\\.)*"/g, '""');
|
|
195
|
-
for (const match of unquoted.matchAll(/(?:\d*|&)>>?\s*(&?)(\S*)/g)) {
|
|
196
|
-
if (match[1] === "&" && /^\d+$/.test(match[2])) continue;
|
|
197
|
-
if (match[2] === "/dev/null") continue;
|
|
198
|
-
return true;
|
|
199
|
-
}
|
|
200
|
-
return false;
|
|
201
|
-
}
|
|
202
|
-
var bashRules = (rules) => rules.map((rule) => parseRule(rule)).filter((rule) => rule.tool === "Bash");
|
|
203
|
-
function commandDecision(profile, command) {
|
|
204
|
-
const line = unwrapShell(command);
|
|
205
|
-
const parts = simpleCommands(line);
|
|
206
|
-
const deny = bashRules(profile.deny);
|
|
207
|
-
if (deny.some((rule) => rule.specifier === void 0)) return "deny";
|
|
208
|
-
if (!parts) return deny.length ? "deny" : (profile.ask ?? []).length ? "ask" : void 0;
|
|
209
|
-
if (parts.some((part) => deny.some((rule) => covers(rule.specifier, part)))) return "deny";
|
|
210
|
-
const ask = bashRules(profile.ask ?? []);
|
|
211
|
-
if (ask.some((rule) => rule.specifier === void 0) || parts.some((part) => ask.some((rule) => covers(rule.specifier, part)))) return "ask";
|
|
212
|
-
const allow = bashRules(profile.allow);
|
|
213
|
-
if (parts.every((part) => !redirects(part) && allow.some((rule) => covers(rule.specifier, part)))) return "allow";
|
|
214
|
-
return void 0;
|
|
215
|
-
}
|
|
216
|
-
export {
|
|
217
|
-
ADVISORS,
|
|
218
|
-
BASES,
|
|
219
|
-
MAX_RULES,
|
|
220
|
-
TOOLS,
|
|
221
|
-
addAllowRule,
|
|
222
|
-
capMode,
|
|
223
|
-
commandDecision,
|
|
224
|
-
parseRule,
|
|
225
|
-
profileFor,
|
|
226
|
-
simpleCommands,
|
|
227
|
-
unwrapShell,
|
|
228
|
-
validatePermissions
|
|
229
|
-
};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/** Migrate complete choices while leaving legacy partial overrides readable. */
|
|
2
|
-
export function normalizeAgentProfiles(config: any, name: any): any;
|
|
3
|
-
/** Snapshot current user team choices into editable project profiles. */
|
|
4
|
-
export function projectProfiles({ root, library, templates, runtime, teamIds }?: {
|
|
5
|
-
library?: string | undefined;
|
|
6
|
-
}): Promise<{}>;
|
|
7
|
-
/** Apply per-project agent choices without replacing the team's graph or rules. */
|
|
8
|
-
export function applyProfile(team: any, profile: any): any;
|
|
9
|
-
/** Refresh only inherited profiles; older scaffolds are recognized by their shipped defaults. */
|
|
10
|
-
export function syncTemplateProfiles(settings: any, options?: {}): Promise<any>;
|
|
11
|
-
export function userLibrary(): string;
|
|
12
|
-
export function oracleProfiles(config: import("./types.js").AgentProfilesConfig | undefined): Array<import("./types.js").AgentModelConfig>;
|
|
13
|
-
export function agentProfiles(config: import("./types.js").AgentProfilesConfig | undefined, name: string): Array<import("./types.js").AgentModelConfig>;
|
|
14
|
-
export function parseProfile(profile: any): any;
|
|
15
|
-
export function profileString(profile: any): string;
|
|
16
|
-
export function modelEfforts(id: any): string[] | undefined;
|
|
17
|
-
export function fitEffort(id: any, effort: any): any;
|
|
18
|
-
export function anyModel(profile: any): boolean;
|
|
19
|
-
export function offers(profiles: any, model: any): any;
|
|
20
|
-
export function selectedProfile(profiles: Array<import("./types.js").AgentModelConfig>, model: string | undefined): import("./types.js").AgentModelConfig | undefined;
|
|
21
|
-
export function profileModel(config: any): any;
|
|
22
|
-
export function profileFingerprint(config: any, name: any): string;
|
|
23
|
-
export function profileDefaults(profiles: any): {
|
|
24
|
-
[k: string]: {
|
|
25
|
-
[k: string]: string;
|
|
26
|
-
};
|
|
27
|
-
};
|