@coreyuan/vector-mind 1.0.54 → 1.1.1
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 +107 -72
- package/admin-panel/README.md +77 -0
- package/admin-panel/dist/client/assets/index-Bzyjdhh2.css +1 -0
- package/admin-panel/dist/client/assets/index-Ph73ewzt.js +9 -0
- package/admin-panel/dist/client/index.html +14 -0
- package/admin-panel/package.json +25 -0
- package/admin-panel/server/index.mjs +1424 -0
- package/admin-panel/server/security.mjs +117 -0
- package/admin-panel/server/security.test.mjs +113 -0
- package/admin-panel/server/storage.mjs +49 -0
- package/admin-panel/server/storage.test.mjs +36 -0
- package/dist/builtin-conventions.js +6 -1
- package/dist/builtin-conventions.js.map +1 -1
- package/dist/builtin-instructions.d.ts +1 -1
- package/dist/builtin-instructions.js +1 -1
- package/dist/builtin-instructions.js.map +1 -1
- package/dist/checkpoint-snapshot.d.ts +56 -0
- package/dist/checkpoint-snapshot.js +411 -0
- package/dist/checkpoint-snapshot.js.map +1 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/context-governance.d.ts +56 -0
- package/dist/context-governance.js +176 -0
- package/dist/context-governance.js.map +1 -0
- package/dist/database-runtime.d.ts +3 -1
- package/dist/database-runtime.js +232 -127
- package/dist/database-runtime.js.map +1 -1
- package/dist/development-warnings.d.ts +2 -1
- package/dist/development-warnings.js +90 -20
- package/dist/development-warnings.js.map +1 -1
- package/dist/file-indexing.d.ts +2 -1
- package/dist/file-indexing.js +127 -47
- package/dist/file-indexing.js.map +1 -1
- package/dist/grep.js +4 -0
- package/dist/grep.js.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/large-file-split.d.ts +52 -8
- package/dist/large-file-split.js +290 -76
- package/dist/large-file-split.js.map +1 -1
- package/dist/memory-maintenance/compaction.js +3 -2
- package/dist/memory-maintenance/compaction.js.map +1 -1
- package/dist/memory-maintenance/metrics.d.ts +1 -1
- package/dist/memory-maintenance/metrics.js +11 -3
- package/dist/memory-maintenance/metrics.js.map +1 -1
- package/dist/memory-maintenance/purge.js +1 -1
- package/dist/memory-maintenance/purge.js.map +1 -1
- package/dist/memory-maintenance/runner.d.ts +1 -0
- package/dist/memory-maintenance/runner.js +15 -3
- package/dist/memory-maintenance/runner.js.map +1 -1
- package/dist/memory-maintenance/types.d.ts +1 -0
- package/dist/memory-mutations.d.ts +3 -3
- package/dist/memory-mutations.js +109 -43
- package/dist/memory-mutations.js.map +1 -1
- package/dist/memory-recall.js +16 -1
- package/dist/memory-recall.js.map +1 -1
- package/dist/operation-scope.js +42 -12
- package/dist/operation-scope.js.map +1 -1
- package/dist/path-containment.d.ts +5 -0
- package/dist/path-containment.js +64 -0
- package/dist/path-containment.js.map +1 -0
- package/dist/path-filters.d.ts +1 -1
- package/dist/path-filters.js +7 -6
- package/dist/path-filters.js.map +1 -1
- package/dist/pending-changes.d.ts +5 -0
- package/dist/pending-changes.js +26 -16
- package/dist/pending-changes.js.map +1 -1
- package/dist/project-files.d.ts +1 -0
- package/dist/project-files.js +19 -10
- package/dist/project-files.js.map +1 -1
- package/dist/root.d.ts +4 -1
- package/dist/root.js +34 -4
- package/dist/root.js.map +1 -1
- package/dist/rtk-integrity.d.ts +5 -0
- package/dist/rtk-integrity.js +35 -0
- package/dist/rtk-integrity.js.map +1 -0
- package/dist/rtk-shim.js +22 -9
- package/dist/rtk-shim.js.map +1 -1
- package/dist/rtk-tools.d.ts +8 -0
- package/dist/rtk-tools.js +59 -42
- package/dist/rtk-tools.js.map +1 -1
- package/dist/server-instructions.js +9 -88
- package/dist/server-instructions.js.map +1 -1
- package/dist/tool-catalog.d.ts +2 -0
- package/dist/tool-catalog.js +76 -23
- package/dist/tool-catalog.js.map +1 -1
- package/dist/tool-handlers/context-recovery.js +79 -54
- package/dist/tool-handlers/context-recovery.js.map +1 -1
- package/dist/tool-handlers/large-files.js +600 -44
- package/dist/tool-handlers/large-files.js.map +1 -1
- package/dist/tool-handlers/memory-diagnostics.js +240 -45
- package/dist/tool-handlers/memory-diagnostics.js.map +1 -1
- package/dist/tool-handlers/memory.js +167 -22
- package/dist/tool-handlers/memory.js.map +1 -1
- package/dist/tool-handlers/operations.js +28 -8
- package/dist/tool-handlers/operations.js.map +1 -1
- package/dist/tool-handlers/requirement-status.d.ts +5 -0
- package/dist/tool-handlers/requirement-status.js +267 -0
- package/dist/tool-handlers/requirement-status.js.map +1 -0
- package/dist/tool-handlers/requirements.js +786 -97
- package/dist/tool-handlers/requirements.js.map +1 -1
- package/dist/tool-handlers.d.ts +4 -0
- package/dist/tool-handlers.js +183 -10
- package/dist/tool-handlers.js.map +1 -1
- package/dist/tool-output.d.ts +32 -1
- package/dist/tool-output.js +31 -12
- package/dist/tool-output.js.map +1 -1
- package/dist/tool-schemas.d.ts +235 -0
- package/dist/tool-schemas.js +98 -26
- package/dist/tool-schemas.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/docs/capability-matrix.md +24 -17
- package/package.json +19 -6
- package/skills/vector-mind-autopilot/SKILL.md +82 -23
- package/skills/vector-mind-autopilot/references/claude-project-instructions.md +14 -11
- package/skills/vector-mind-autopilot/references/universal-system-prompt.md +24 -16
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
|
|
3
|
+
export const ADMIN_TOKEN_HEADER = "x-vectormind-admin-token";
|
|
4
|
+
|
|
5
|
+
function normalizeHostname(value) {
|
|
6
|
+
return String(value ?? "")
|
|
7
|
+
.trim()
|
|
8
|
+
.toLowerCase()
|
|
9
|
+
.replace(/^\[|\]$/g, "")
|
|
10
|
+
.replace(/\.$/, "");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function effectivePort(protocol, port) {
|
|
14
|
+
if (port) return Number(port);
|
|
15
|
+
return protocol === "https:" ? 443 : 80;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function parseRequestHost(hostHeader, protocol = "http") {
|
|
19
|
+
if (!hostHeader) return null;
|
|
20
|
+
const normalizedProtocol = String(protocol).endsWith(":") ? String(protocol) : `${protocol}:`;
|
|
21
|
+
try {
|
|
22
|
+
const url = new URL(`${normalizedProtocol}//${hostHeader}`);
|
|
23
|
+
return {
|
|
24
|
+
hostname: normalizeHostname(url.hostname),
|
|
25
|
+
port: effectivePort(url.protocol, url.port),
|
|
26
|
+
protocol: url.protocol,
|
|
27
|
+
};
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function isLoopbackHostname(hostname) {
|
|
34
|
+
const normalized = normalizeHostname(hostname);
|
|
35
|
+
if (normalized === "localhost" || normalized === "::1") return true;
|
|
36
|
+
const match = normalized.match(/^127\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
|
|
37
|
+
return Boolean(match && match.slice(1).every((part) => Number(part) <= 255));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isLoopbackAddress(address) {
|
|
41
|
+
const normalized = String(address ?? "").trim().toLowerCase().split("%")[0];
|
|
42
|
+
if (normalized === "::1") return true;
|
|
43
|
+
if (normalized.startsWith("::ffff:")) return isLoopbackHostname(normalized.slice(7));
|
|
44
|
+
return isLoopbackHostname(normalized);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function isAllowedAdminOrigin({ origin, hostHeader, protocol = "http" }) {
|
|
48
|
+
if (!origin) return true;
|
|
49
|
+
const requestHost = parseRequestHost(hostHeader, protocol);
|
|
50
|
+
if (!requestHost) return false;
|
|
51
|
+
try {
|
|
52
|
+
const parsedOrigin = new URL(origin);
|
|
53
|
+
if (parsedOrigin.protocol !== "http:" && parsedOrigin.protocol !== "https:") return false;
|
|
54
|
+
return (
|
|
55
|
+
normalizeHostname(parsedOrigin.hostname) === requestHost.hostname &&
|
|
56
|
+
effectivePort(parsedOrigin.protocol, parsedOrigin.port) === requestHost.port &&
|
|
57
|
+
parsedOrigin.protocol === requestHost.protocol
|
|
58
|
+
);
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function tokensEqual(providedToken, expectedToken) {
|
|
65
|
+
if (!providedToken || !expectedToken) return false;
|
|
66
|
+
const provided = Buffer.from(String(providedToken));
|
|
67
|
+
const expected = Buffer.from(String(expectedToken));
|
|
68
|
+
return provided.length === expected.length && crypto.timingSafeEqual(provided, expected);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function createAdminSecurityPolicy({ host, port, configuredToken, generateToken } = {}) {
|
|
72
|
+
const normalizedHost = normalizeHostname(host);
|
|
73
|
+
const normalizedPort = Number(port);
|
|
74
|
+
if (!normalizedHost || !Number.isInteger(normalizedPort) || normalizedPort < 1 || normalizedPort > 65535) {
|
|
75
|
+
throw new Error("管理面板监听地址或端口无效。");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const mode = isLoopbackHostname(normalizedHost) ? "automatic" : "explicit";
|
|
79
|
+
const explicitToken = String(configuredToken ?? "").trim();
|
|
80
|
+
if (mode === "explicit" && !explicitToken) {
|
|
81
|
+
throw new Error("非回环监听必须设置 VECTORMIND_ADMIN_TOKEN。");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const token = explicitToken || (generateToken ? generateToken() : crypto.randomBytes(32).toString("hex"));
|
|
85
|
+
return Object.freeze({ host: normalizedHost, port: normalizedPort, mode, token });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function evaluateAdminRequest({
|
|
89
|
+
policy,
|
|
90
|
+
path,
|
|
91
|
+
origin,
|
|
92
|
+
hostHeader,
|
|
93
|
+
protocol = "http",
|
|
94
|
+
remoteAddress,
|
|
95
|
+
providedToken,
|
|
96
|
+
}) {
|
|
97
|
+
const originAllowed = isAllowedAdminOrigin({ origin, hostHeader, protocol });
|
|
98
|
+
const requestHost = parseRequestHost(hostHeader, protocol);
|
|
99
|
+
const tokenValid = tokensEqual(providedToken, policy.token);
|
|
100
|
+
const publicEndpoint = path === "/config" || path === "/health";
|
|
101
|
+
const automaticSessionAvailable = Boolean(
|
|
102
|
+
policy.mode === "automatic" &&
|
|
103
|
+
originAllowed &&
|
|
104
|
+
requestHost &&
|
|
105
|
+
requestHost.port === policy.port &&
|
|
106
|
+
isLoopbackHostname(requestHost.hostname) &&
|
|
107
|
+
isLoopbackAddress(remoteAddress),
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
originAllowed,
|
|
112
|
+
tokenValid,
|
|
113
|
+
publicEndpoint,
|
|
114
|
+
authorized: originAllowed && (publicEndpoint || tokenValid),
|
|
115
|
+
exposeSessionToken: path === "/config" && automaticSessionAvailable,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
createAdminSecurityPolicy,
|
|
6
|
+
evaluateAdminRequest,
|
|
7
|
+
isAllowedAdminOrigin,
|
|
8
|
+
isLoopbackAddress,
|
|
9
|
+
isLoopbackHostname,
|
|
10
|
+
} from "./security.mjs";
|
|
11
|
+
|
|
12
|
+
test("loopback detection accepts only concrete loopback hosts and addresses", () => {
|
|
13
|
+
assert.equal(isLoopbackHostname("localhost"), true);
|
|
14
|
+
assert.equal(isLoopbackHostname("127.15.2.9"), true);
|
|
15
|
+
assert.equal(isLoopbackHostname("localhost.example.com"), false);
|
|
16
|
+
assert.equal(isLoopbackAddress("::1"), true);
|
|
17
|
+
assert.equal(isLoopbackAddress("::ffff:127.0.0.1"), true);
|
|
18
|
+
assert.equal(isLoopbackAddress("192.168.1.8"), false);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("origin validation requires the browser origin to match the request host", () => {
|
|
22
|
+
assert.equal(
|
|
23
|
+
isAllowedAdminOrigin({ origin: "http://localhost:16860", hostHeader: "localhost:16860", protocol: "http" }),
|
|
24
|
+
true,
|
|
25
|
+
);
|
|
26
|
+
assert.equal(
|
|
27
|
+
isAllowedAdminOrigin({ origin: "http://evil.example:16860", hostHeader: "localhost:16860", protocol: "http" }),
|
|
28
|
+
false,
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("loopback mode exposes an automatic session only to a loopback request host", () => {
|
|
33
|
+
const policy = createAdminSecurityPolicy({
|
|
34
|
+
host: "127.0.0.1",
|
|
35
|
+
port: 16860,
|
|
36
|
+
generateToken: () => "automatic-test-token",
|
|
37
|
+
});
|
|
38
|
+
const localConfig = evaluateAdminRequest({
|
|
39
|
+
policy,
|
|
40
|
+
path: "/config",
|
|
41
|
+
hostHeader: "localhost:16860",
|
|
42
|
+
remoteAddress: "::ffff:127.0.0.1",
|
|
43
|
+
});
|
|
44
|
+
const reboundConfig = evaluateAdminRequest({
|
|
45
|
+
policy,
|
|
46
|
+
path: "/config",
|
|
47
|
+
hostHeader: "attacker.example:16860",
|
|
48
|
+
remoteAddress: "127.0.0.1",
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
assert.equal(policy.mode, "automatic");
|
|
52
|
+
assert.equal(localConfig.exposeSessionToken, true);
|
|
53
|
+
assert.equal(reboundConfig.exposeSessionToken, false);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("non-loopback mode requires an explicit token and never exposes it through config", () => {
|
|
57
|
+
assert.throws(
|
|
58
|
+
() => createAdminSecurityPolicy({ host: "0.0.0.0", port: 16860 }),
|
|
59
|
+
/VECTORMIND_ADMIN_TOKEN/,
|
|
60
|
+
);
|
|
61
|
+
const policy = createAdminSecurityPolicy({ host: "0.0.0.0", port: 16860, configuredToken: "explicit-test-token" });
|
|
62
|
+
const configRequest = evaluateAdminRequest({
|
|
63
|
+
policy,
|
|
64
|
+
path: "/config",
|
|
65
|
+
hostHeader: "192.168.1.20:16860",
|
|
66
|
+
remoteAddress: "192.168.1.30",
|
|
67
|
+
});
|
|
68
|
+
const unauthenticatedRequest = evaluateAdminRequest({
|
|
69
|
+
policy,
|
|
70
|
+
path: "/projects",
|
|
71
|
+
hostHeader: "192.168.1.20:16860",
|
|
72
|
+
remoteAddress: "192.168.1.30",
|
|
73
|
+
});
|
|
74
|
+
const authenticatedRequest = evaluateAdminRequest({
|
|
75
|
+
policy,
|
|
76
|
+
path: "/projects",
|
|
77
|
+
hostHeader: "192.168.1.20:16860",
|
|
78
|
+
remoteAddress: "192.168.1.30",
|
|
79
|
+
providedToken: "explicit-test-token",
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
assert.equal(policy.mode, "explicit");
|
|
83
|
+
assert.equal(configRequest.exposeSessionToken, false);
|
|
84
|
+
assert.equal(unauthenticatedRequest.authorized, false);
|
|
85
|
+
assert.equal(authenticatedRequest.authorized, true);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("a missing Origin does not authorize a protected endpoint without a token", () => {
|
|
89
|
+
const policy = createAdminSecurityPolicy({ host: "10.0.0.4", port: 16860, configuredToken: "explicit-test-token" });
|
|
90
|
+
const decision = evaluateAdminRequest({
|
|
91
|
+
policy,
|
|
92
|
+
path: "/projects/discover",
|
|
93
|
+
origin: undefined,
|
|
94
|
+
hostHeader: "10.0.0.4:16860",
|
|
95
|
+
remoteAddress: "10.0.0.5",
|
|
96
|
+
});
|
|
97
|
+
assert.equal(decision.originAllowed, true);
|
|
98
|
+
assert.equal(decision.authorized, false);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("a mismatched Origin is rejected even when the token is valid", () => {
|
|
102
|
+
const policy = createAdminSecurityPolicy({ host: "0.0.0.0", port: 16860, configuredToken: "explicit-test-token" });
|
|
103
|
+
const decision = evaluateAdminRequest({
|
|
104
|
+
policy,
|
|
105
|
+
path: "/projects",
|
|
106
|
+
origin: "http://evil.example:16860",
|
|
107
|
+
hostHeader: "192.168.1.20:16860",
|
|
108
|
+
remoteAddress: "192.168.1.30",
|
|
109
|
+
providedToken: "explicit-test-token",
|
|
110
|
+
});
|
|
111
|
+
assert.equal(decision.originAllowed, false);
|
|
112
|
+
assert.equal(decision.authorized, false);
|
|
113
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
export function projectPathIdentity(projectPath, platform = process.platform) {
|
|
6
|
+
const raw = String(projectPath ?? "").trim();
|
|
7
|
+
if (!raw) return "";
|
|
8
|
+
const resolved = path.resolve(raw);
|
|
9
|
+
return platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function atomicWriteTextFile(filePath, content, options = {}) {
|
|
13
|
+
const fsImpl = options.fsImpl ?? fs;
|
|
14
|
+
const directory = path.dirname(filePath);
|
|
15
|
+
const tempPath = path.join(
|
|
16
|
+
directory,
|
|
17
|
+
`.${path.basename(filePath)}.${process.pid}.${crypto.randomUUID()}.tmp`,
|
|
18
|
+
);
|
|
19
|
+
let fd = null;
|
|
20
|
+
fsImpl.mkdirSync(directory, { recursive: true });
|
|
21
|
+
try {
|
|
22
|
+
fd = fsImpl.openSync(tempPath, "wx", 0o600);
|
|
23
|
+
fsImpl.writeFileSync(fd, content, "utf8");
|
|
24
|
+
fsImpl.fsyncSync(fd);
|
|
25
|
+
fsImpl.closeSync(fd);
|
|
26
|
+
fd = null;
|
|
27
|
+
fsImpl.renameSync(tempPath, filePath);
|
|
28
|
+
try {
|
|
29
|
+
const directoryFd = fsImpl.openSync(directory, "r");
|
|
30
|
+
try {
|
|
31
|
+
fsImpl.fsyncSync(directoryFd);
|
|
32
|
+
} finally {
|
|
33
|
+
fsImpl.closeSync(directoryFd);
|
|
34
|
+
}
|
|
35
|
+
} catch {
|
|
36
|
+
// Directory fsync is not available on every platform/filesystem.
|
|
37
|
+
}
|
|
38
|
+
} catch (err) {
|
|
39
|
+
if (fd != null) {
|
|
40
|
+
try {
|
|
41
|
+
fsImpl.closeSync(fd);
|
|
42
|
+
} catch {}
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
fsImpl.rmSync(tempPath, { force: true });
|
|
46
|
+
} catch {}
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
|
|
7
|
+
import { atomicWriteTextFile, projectPathIdentity } from "./storage.mjs";
|
|
8
|
+
|
|
9
|
+
test("project path identity is case-sensitive except on Windows", () => {
|
|
10
|
+
assert.equal(projectPathIdentity("", "linux"), "");
|
|
11
|
+
assert.notEqual(projectPathIdentity("/tmp/VectorMind", "linux"), projectPathIdentity("/tmp/vectormind", "linux"));
|
|
12
|
+
assert.equal(projectPathIdentity("/tmp/VectorMind", "win32"), projectPathIdentity("/tmp/vectormind", "win32"));
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("atomic writes replace the index and preserve the prior file when rename fails", () => {
|
|
16
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "vectormind-admin-storage-"));
|
|
17
|
+
const indexFile = path.join(root, "projects.json");
|
|
18
|
+
try {
|
|
19
|
+
fs.writeFileSync(indexFile, "old\n", "utf8");
|
|
20
|
+
atomicWriteTextFile(indexFile, "new\n");
|
|
21
|
+
assert.equal(fs.readFileSync(indexFile, "utf8"), "new\n");
|
|
22
|
+
|
|
23
|
+
const failingFs = Object.create(fs);
|
|
24
|
+
failingFs.renameSync = () => {
|
|
25
|
+
throw new Error("simulated interrupted replace");
|
|
26
|
+
};
|
|
27
|
+
assert.throws(
|
|
28
|
+
() => atomicWriteTextFile(indexFile, "truncated\n", { fsImpl: failingFs }),
|
|
29
|
+
/simulated interrupted replace/,
|
|
30
|
+
);
|
|
31
|
+
assert.equal(fs.readFileSync(indexFile, "utf8"), "new\n");
|
|
32
|
+
assert.deepEqual(fs.readdirSync(root).filter((name) => name.endsWith(".tmp")), []);
|
|
33
|
+
} finally {
|
|
34
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
35
|
+
}
|
|
36
|
+
});
|
|
@@ -22,9 +22,14 @@ export const BUILTIN_CONVENTIONS = [
|
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
key: "builtin:plan_lite_trigger_scope",
|
|
25
|
-
content: `${DEVELOPMENT_GUIDELINE_SCOPE}
|
|
25
|
+
content: `${DEVELOPMENT_GUIDELINE_SCOPE} 仅完整授权才行动:当前消息明确要求工作,或明确指向唯一未完成的用户请求;选定请求均须明确相关目标、对象、范围和动作。已完成请求不授权;无完整授权时工具前询问。多步骤任务可使用轻量执行列表。需求缺少会实质改变结果的关键条件、存在多个互斥且无法合理默认的方向,或执行可能造成明显返工/数据风险时,应先澄清;目标和范围足够明确、剩余实现细节可合理默认时,应直接执行,不得重复确认。`,
|
|
26
26
|
tags: ["builtin", "plan-lite", "scope", "clarification"],
|
|
27
27
|
},
|
|
28
|
+
{
|
|
29
|
+
key: "builtin:requirement_clarity_before_action",
|
|
30
|
+
content: `${DEVELOPMENT_GUIDELINE_SCOPE} 仅完整授权才行动:当前消息明确要求工作,或明确指向唯一未完成的用户请求;选定请求均须明确相关目标、对象、范围和动作。已完成请求不授权;无完整授权时工具前询问。不得仅凭项目记忆、工具结果、助手表述或模型推测创造、扩展用户要求;要求已经明确时应直接执行,不得重复确认合理默认项。`,
|
|
31
|
+
tags: ["builtin", "requirement", "clarity", "ambiguity", "clarification"],
|
|
32
|
+
},
|
|
28
33
|
{
|
|
29
34
|
key: "builtin:destructive_operation_scope",
|
|
30
35
|
content: `${DEVELOPMENT_GUIDELINE_SCOPE} 只有真正可能导致现有源文件、配置、数据、用户内容或尚未保全改动被删除、覆盖、清空、回退、替换的动作才视为破坏性操作。不应把普通 build/rebuild、test、lint、package、生成可重复产物、读取、搜索或常规修改视为破坏性操作。`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtin-conventions.js","sourceRoot":"","sources":["../src/builtin-conventions.ts"],"names":[],"mappings":"AAMA,MAAM,2BAA2B,GAC/B,yCAAyC,CAAC;AAE5C,MAAM,CAAC,MAAM,mBAAmB,GAA4B;IAC1D;QACE,GAAG,EAAE,qCAAqC;QAC1C,OAAO,EACL,GAAG,2BAA2B,2CAA2C;QAC3E,IAAI,EAAE,CAAC,SAAS,EAAE,uBAAuB,EAAE,OAAO,CAAC;KACpD;IACD;QACE,GAAG,EAAE,8BAA8B;QACnC,OAAO,EACL,GAAG,2BAA2B,6FAA6F;QAC7H,IAAI,EAAE,CAAC,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,OAAO,CAAC;KAC9D;IACD;QACE,GAAG,EAAE,+BAA+B;QACpC,OAAO,EACL,GAAG,2BAA2B,mEAAmE;QACnG,IAAI,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,gBAAgB,CAAC;KAC9C;IACD;QACE,GAAG,EAAE,iCAAiC;QACtC,OAAO,EACL,GAAG,2BAA2B,kDAAkD;QAClF,IAAI,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,CAAC;KACzD;IACD;QACE,GAAG,EAAE,iCAAiC;QACtC,OAAO,EACL,GAAG,2BAA2B,
|
|
1
|
+
{"version":3,"file":"builtin-conventions.js","sourceRoot":"","sources":["../src/builtin-conventions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const BUILTIN_WRITE_POLICY_INSTRUCTIONS = "\u5F00\u53D1\u89C4\u8303\u8303\u56F4\uFF1A\u4EE5\u4E0B\u5185\u5BB9\u53EA\u5B9A\u4E49\u5F00\u53D1\u89C4\u8303\u3001\u9879\u76EE\u8BB0\u5FC6\u89C4\u8303\u3001\u4EE3\u7801\u7EC4\u7EC7\u89C4\u8303\u4E0E\u4EA4\u4ED8\u8D28\u91CF\u8981\u6C42\u3002 \u4EE5\u4E0B\u89C4\u5219\u4EC5\u5728\u4EE3\u7801\u5F00\u53D1\u3001\u6587\u4EF6\u521B\u5EFA\u3001\u6587\u4EF6\u4FEE\u6539\u3001\u6587\u4EF6\u5220\u9664\u3001\u6587\u4EF6\u79FB\u52A8\u7B49\u5199\u64CD\u4F5C\u4EFB\u52A1\u4E2D\u751F\u6548\uFF1B\u4E0D\u9650\u5236\u6A21\u578B\u7684\u5206\u6790\u3001\u51B3\u7B56\u3001\u5B9E\u73B0\u8DEF\u5F84\u4E0E\u666E\u901A\u975E\u5199\u64CD\u4F5C\u6D41\u7A0B\u3002\u6240\u6709\u4EE3\u7801\u6216\u6587\u4EF6\u6539\u52A8\u9ED8\u8BA4\u5728\u5F53\u524D\u6D3B\u8DC3\u5206\u652F\u4E2D\u8FDB\u884C\uFF1B\u7981\u6B62\u521B\u5EFA\u3001\u5207\u6362\u6216\u4F7F\u7528\u4E34\u65F6\u5206\u652F\u3001\u4E34\u65F6\u5B50\u5206\u652F\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u6216\u65E2\u6709\u5DE5\u4F5C\u6D41\u5DF2\u7ECF\u8FD9\u6837\u5B89\u6392\u3002\u4E3A\u907F\u514D\u5E76\u53D1\u8986\u76D6\uFF0C\u540C\u4E00\u4F1A\u8BDD\u5185\u540C\u4E00\u6587\u4EF6\u5E94\u4E32\u884C\u7F16\u8F91\uFF1B\u591A\u6587\u4EF6\u4EFB\u52A1\u5E94\u5148\u660E\u786E\u76EE\u6807\u6587\u4EF6\u96C6\u5408\u5E76\u6309\u7A33\u5B9A\u987A\u5E8F\u5904\u7406\u3002";
|
|
2
|
-
export declare const BUILTIN_PLAN_LITE_INSTRUCTIONS = "\u5F00\u53D1\u89C4\u8303\u8303\u56F4\uFF1A\u4EE5\u4E0B\u5185\u5BB9\u53EA\u5B9A\u4E49\u5F00\u53D1\u89C4\u8303\u3001\u9879\u76EE\u8BB0\u5FC6\u89C4\u8303\u3001\u4EE3\u7801\u7EC4\u7EC7\u89C4\u8303\u4E0E\u4EA4\u4ED8\u8D28\u91CF\u8981\u6C42\u3002 \u4EE5\u4E0B\u89C4\u5219\u4EC5\u5728\u5206\u6790\u3001\u6392\u67E5\u3001\u5F00\u53D1\u3001\u8C03\u8BD5\u3001\u91CD\u6784\u3001\u6587\u4EF6\u4FEE\u6539\u3001\u65B9\u6848\u8BBE\u8BA1\u7B49\u591A\u6B65\u9AA4\u4EFB\u52A1\u578B\u8BF7\u6C42\u4E2D\u751F\u6548\uFF1B\u4E0D\u9650\u5236\u6A21\u578B\u5185\u90E8\u63A8\u7406\uFF0C\u53EA\u7EA6\u675F\u5916\u663E\u4EFB\u52A1\u7BA1\u7406\u4E0E\u5FC5\u8981\u6F84\u6E05\u3002\u5BF9\u8FD9\u7C7B\u8BF7\u6C42\uFF0C\u53EF\u7ED9\u51FA\u8F7B\u91CF\u6267\u884C\u5217\u8868\uFF1B\u82E5\u5BBF\u4E3B\u63D0\u4F9B\u539F\u751F\u8BA1\u5212/\u4EFB\u52A1\u5217\u8868\u5DE5\u5177\uFF0C\u5219\u4F18\u5148\u540C\u6B65\u5230\u8BE5\u5DE5\u5177\uFF0C\u5426\u5219\u4EE5\u7CBE\u7B80\u6587\u672C\u5217\u8868\u5C55\u793A\u3002\u53EA\u6709\u5F53\u9700\u6C42\u7F3A\u5C11\u4F1A\u5B9E\u8D28\u6539\u53D8\u7ED3\u679C\u7684\u5173\u952E\u6761\u4EF6\u3001\u5B58\u5728\u591A\u4E2A\u4E92\u65A5\u4E14\u65E0\u6CD5\u5408\u7406\u9ED8\u8BA4\u7684\u65B9\u5411\uFF0C\u6216\
|
|
2
|
+
export declare const BUILTIN_PLAN_LITE_INSTRUCTIONS = "\u5F00\u53D1\u89C4\u8303\u8303\u56F4\uFF1A\u4EE5\u4E0B\u5185\u5BB9\u53EA\u5B9A\u4E49\u5F00\u53D1\u89C4\u8303\u3001\u9879\u76EE\u8BB0\u5FC6\u89C4\u8303\u3001\u4EE3\u7801\u7EC4\u7EC7\u89C4\u8303\u4E0E\u4EA4\u4ED8\u8D28\u91CF\u8981\u6C42\u3002 \u4EE5\u4E0B\u89C4\u5219\u4EC5\u5728\u5206\u6790\u3001\u6392\u67E5\u3001\u5F00\u53D1\u3001\u8C03\u8BD5\u3001\u91CD\u6784\u3001\u6587\u4EF6\u4FEE\u6539\u3001\u65B9\u6848\u8BBE\u8BA1\u7B49\u591A\u6B65\u9AA4\u4EFB\u52A1\u578B\u8BF7\u6C42\u4E2D\u751F\u6548\uFF1B\u4E0D\u9650\u5236\u6A21\u578B\u5185\u90E8\u63A8\u7406\uFF0C\u53EA\u7EA6\u675F\u5916\u663E\u4EFB\u52A1\u7BA1\u7406\u4E0E\u5FC5\u8981\u6F84\u6E05\u3002\u5BF9\u8FD9\u7C7B\u8BF7\u6C42\uFF0C\u53EF\u7ED9\u51FA\u8F7B\u91CF\u6267\u884C\u5217\u8868\uFF1B\u82E5\u5BBF\u4E3B\u63D0\u4F9B\u539F\u751F\u8BA1\u5212/\u4EFB\u52A1\u5217\u8868\u5DE5\u5177\uFF0C\u5219\u4F18\u5148\u540C\u6B65\u5230\u8BE5\u5DE5\u5177\uFF0C\u5426\u5219\u4EE5\u7CBE\u7B80\u6587\u672C\u5217\u8868\u5C55\u793A\u3002\u53EA\u6709\u5B8C\u6574\u6388\u6743\u624D\u53EF\u884C\u52A8\uFF1A\u5F53\u524D\u6D88\u606F\u660E\u786E\u8981\u6C42\u5DE5\u4F5C\uFF0C\u6216\u5F53\u524D\u6D88\u606F\u660E\u786E\u6307\u5411\u552F\u4E00\u672A\u5B8C\u6210\u7684\u7528\u6237\u8BF7\u6C42\uFF1B\u4E24\u79CD\u8DEF\u5F84\u7684\u9009\u5B9A\u8BF7\u6C42\u5747\u987B\u660E\u786E\u6240\u6709\u76F8\u5173\u76EE\u6807\u3001\u5BF9\u8C61\u3001\u8303\u56F4\u548C\u52A8\u4F5C\u3002\u5DF2\u5B8C\u6210\u8BF7\u6C42\u4E0D\u6388\u6743\u65B0\u52A8\u4F5C\u3002\u6CA1\u6709\u5B8C\u6574\u6388\u6743\u65F6\uFF0C\u5E94\u5728\u8C03\u7528\u5DE5\u5177\u6216\u91C7\u53D6\u884C\u52A8\u524D\u7B80\u77ED\u8BE2\u95EE\u3002\u9700\u6C42\u7F3A\u5C11\u4F1A\u5B9E\u8D28\u6539\u53D8\u7ED3\u679C\u7684\u5173\u952E\u6761\u4EF6\u3001\u5B58\u5728\u591A\u4E2A\u4E92\u65A5\u4E14\u65E0\u6CD5\u5408\u7406\u9ED8\u8BA4\u7684\u65B9\u5411\uFF0C\u6216\u6267\u884C\u53EF\u80FD\u9020\u6210\u660E\u663E\u8FD4\u5DE5/\u6570\u636E\u98CE\u9669\u65F6\uFF0C\u4E5F\u5E94\u5148\u6F84\u6E05\u3002\u76EE\u6807\u548C\u8303\u56F4\u8DB3\u591F\u660E\u786E\u3001\u5269\u4F59\u5B9E\u73B0\u7EC6\u8282\u53EF\u5408\u7406\u9ED8\u8BA4\u65F6\uFF0C\u5E94\u76F4\u63A5\u6267\u884C\uFF0C\u4E0D\u5F97\u91CD\u590D\u786E\u8BA4\u3002\u4E0D\u5F97\u4EC5\u51ED\u9879\u76EE\u8BB0\u5FC6\u3001\u5DE5\u5177\u7ED3\u679C\u3001\u52A9\u624B\u8868\u8FF0\u6216\u6A21\u578B\u63A8\u6D4B\u521B\u9020\u3001\u6269\u5C55\u7528\u6237\u8981\u6C42\u3002\u6267\u884C\u5217\u8868\u4FDD\u6301\u8F7B\u91CF\uFF0C\u901A\u5E38 3 \u81F3 7 \u9879\uFF1B\u4EC5\u5728\u4EFB\u52A1\u72B6\u6001\u53D8\u5316\u3001\u8303\u56F4\u53D8\u5316\u3001\u4EFB\u52A1\u9879\u53D8\u5316\u6216\u7528\u6237\u8981\u6C42\u65F6\u66F4\u65B0\uFF0C\u4E0D\u5F97\u4E3A\u4E86\u5C55\u793A\u8BA1\u5212\u800C\u5236\u9020\u5197\u957F\u6D41\u7A0B\u3002";
|
|
3
3
|
export declare const BUILTIN_DESTRUCTIVE_OPERATION_GUARD_INSTRUCTIONS = "\u5F00\u53D1\u89C4\u8303\u8303\u56F4\uFF1A\u4EE5\u4E0B\u5185\u5BB9\u53EA\u5B9A\u4E49\u5F00\u53D1\u89C4\u8303\u3001\u9879\u76EE\u8BB0\u5FC6\u89C4\u8303\u3001\u4EE3\u7801\u7EC4\u7EC7\u89C4\u8303\u4E0E\u4EA4\u4ED8\u8D28\u91CF\u8981\u6C42\u3002 \u4EE5\u4E0B\u89C4\u5219\u4EC5\u5728\u771F\u6B63\u53EF\u80FD\u5BFC\u81F4\u73B0\u6709\u6E90\u6587\u4EF6\u3001\u914D\u7F6E\u3001\u6570\u636E\u3001\u7528\u6237\u5185\u5BB9\u6216\u5C1A\u672A\u4FDD\u5168\u6539\u52A8\u88AB\u5220\u9664\u3001\u8986\u76D6\u3001\u6E05\u7A7A\u3001\u56DE\u9000\u3001\u66FF\u6362\u7684\u7834\u574F\u6027\u64CD\u4F5C\u4E2D\u751F\u6548\uFF0C\u4F8B\u5982 reset\u3001clean\u3001\u5F3A\u5236\u8986\u76D6\u3001\u6279\u91CF\u5220\u9664/\u79FB\u52A8\u3001\u8986\u76D6\u5F0F\u540C\u6B65\u3001\u5371\u9669\u8FC1\u79FB\u6216\u4F1A\u8986\u76D6\u91CD\u8981\u76EE\u6807\u7684\u53D1\u5E03\u3002\u4E0D\u5E94\u628A\u666E\u901A build/rebuild\u3001test\u3001lint\u3001package\u3001\u751F\u6210\u53EF\u91CD\u590D\u4EA7\u7269\u3001\u8BFB\u53D6\u3001\u641C\u7D22\u6216\u5E38\u89C4\u4FEE\u6539\u89C6\u4E3A\u7834\u574F\u6027\u64CD\u4F5C\u3002\u9047\u5230\u771F\u6B63\u7834\u574F\u6027\u64CD\u4F5C\u65F6\uFF0C\u5E94\u5148\u8BC6\u522B\u53D7\u5F71\u54CD\u8303\u56F4\u4E0E\u98CE\u9669\uFF1B\u82E5\u7528\u6237\u5DF2\u7ECF\u660E\u786E\u8981\u6C42\u8BE5\u7834\u574F\u6027\u52A8\u4F5C\u6216\u76EE\u6807\u662F\u53EF\u518D\u751F\u4EA7\u7269\u3001\u4E34\u65F6\u6587\u4EF6\u3001\u660E\u786E\u6307\u5B9A\u5BF9\u8C61\uFF0C\u4E0D\u8981\u91CD\u590D\u7D22\u8981\u786E\u8BA4\u3002";
|
|
4
4
|
export declare const BUILTIN_ARCHITECTURE_AND_CODE_ORGANIZATION_INSTRUCTIONS = "\u5F00\u53D1\u89C4\u8303\u8303\u56F4\uFF1A\u4EE5\u4E0B\u5185\u5BB9\u53EA\u5B9A\u4E49\u5F00\u53D1\u89C4\u8303\u3001\u9879\u76EE\u8BB0\u5FC6\u89C4\u8303\u3001\u4EE3\u7801\u7EC4\u7EC7\u89C4\u8303\u4E0E\u4EA4\u4ED8\u8D28\u91CF\u8981\u6C42\u3002 \u4EE5\u4E0B\u89C4\u5219\u4EC5\u5728\u9879\u76EE\u642D\u5EFA\u3001\u67B6\u6784\u8BBE\u8BA1\u3001\u529F\u80FD\u5B9E\u73B0\u3001\u6A21\u5757\u6269\u5C55\u3001\u91CD\u6784\u3001\u6587\u4EF6\u65B0\u589E\u6216\u4FEE\u6539\u7B49\u5DE5\u7A0B\u4EFB\u52A1\u4E2D\u751F\u6548\uFF1B\u4E0D\u9650\u5236\u6A21\u578B\u5185\u90E8\u63A8\u7406\uFF0C\u53EA\u7EA6\u675F\u67B6\u6784\u4E0E\u4EE3\u7801\u7EC4\u7EC7\u3002\u5F00\u59CB\u5B9E\u73B0\u524D\uFF0C\u5224\u65AD\u5F53\u524D\u9700\u6C42\u6240\u5C5E\u8FB9\u754C\uFF0C\u5E76\u8BA9\u76EE\u5F55\u7ED3\u6784\u3001\u6A21\u5757\u5212\u5206\u3001\u6587\u4EF6\u5F52\u5C5E\u3001\u547D\u540D\u65B9\u5F0F\u548C\u4F9D\u8D56\u65B9\u5411\u4E0E\u8BE5\u8FB9\u754C\u4E00\u81F4\uFF1B\u5E38\u89C1\u8FB9\u754C\u5305\u62EC\u63A5\u53E3\u5C42\u3001\u5E94\u7528\u5C42\u3001\u9886\u57DF\u5C42\u3001\u57FA\u7840\u8BBE\u65BD\u5C42\u3001\u5171\u4EAB\u5C42\u3001\u914D\u7F6E\u5C42\u3001\u811A\u672C\u5C42\u548C\u6D4B\u8BD5\u5C42\u3002\u65B0\u589E\u4EE3\u7801\u65F6\u4F18\u5148\u590D\u7528\u73B0\u6709\u7A33\u5B9A\u6A21\u5757\uFF1B\u53EA\u6709\u5F53\u76F4\u63A5\u590D\u7528\u4F1A\u9020\u6210\u8FB9\u754C\u6C61\u67D3\u3001\u804C\u8D23\u6DF7\u4E71\u3001\u8026\u5408\u5347\u9AD8\u6216\u9519\u8BEF\u62BD\u8C61\u65F6\uFF0C\u624D\u65B0\u589E\u62BD\u8C61\u3001\u6A21\u5757\u6216\u76EE\u5F55\u3002\u516C\u5171\u80FD\u529B\u5E94\u6C89\u6DC0\u4E3A\u53EF\u590D\u7528\u7EC4\u4EF6\u3001\u670D\u52A1\u3001\u5DE5\u5177\u6216\u5E93\uFF0C\u4F46\u4E0D\u5F97\u4E3A\u4E86\u590D\u7528\u800C\u8FC7\u5EA6\u62BD\u8C61\u3002\u5355\u4E2A\u6587\u4EF6\u548C\u5355\u4E2A\u6A21\u5757\u5FC5\u987B\u4FDD\u6301\u5355\u4E00\u4E3B\u804C\u8D23\uFF1B\u82E5\u4E00\u4E2A\u6587\u4EF6\u540C\u65F6\u627F\u62C5\u8DEF\u7531\u3001\u63A7\u5236\u3001\u4E1A\u52A1\u89C4\u5219\u3001\u6570\u636E\u8BBF\u95EE\u3001\u72B6\u6001\u7BA1\u7406\u3001\u89C6\u56FE\u6E32\u67D3\u3001\u5DE5\u5177\u51FD\u6570\u6216\u914D\u7F6E\u88C5\u914D\u7B49\u591A\u7C7B\u804C\u8D23\uFF0C\u5E94\u7ACB\u5373\u62C6\u5206\uFF0C\u4E0D\u5F97\u7EE7\u7EED\u628A\u65B0\u9700\u6C42\u5806\u8FDB\u8BE5\u6587\u4EF6\u3002\u5B9E\u73B0\u6587\u4EF6\u63A5\u8FD1 800 \u884C\u65F6\u5E94\u4F18\u5148\u62C6\u6A21\u5757\uFF1B\u8D85\u8FC7 1200 \u884C\u65F6\u9ED8\u8BA4\u7981\u6B62\u7EE7\u7EED\u8FFD\u52A0\u65B0\u529F\u80FD\uFF0C\u9664\u975E\u672C\u6B21\u4EFB\u52A1\u5C31\u662F\u6709\u8BA1\u5212\u5730\u62C6\u5206\u5B83\uFF1B\u8FBE\u5230\u5DE8\u91CF\u6587\u4EF6\u9608\u503C\u65F6\uFF0C\u5E94\u5148\u505A\u673A\u68B0\u642C\u8FC1\u5F0F\u6A21\u5757\u5316\u62C6\u5206\uFF0C\u79FB\u52A8\u5B8C\u6574\u58F0\u660E\u5230\u771F\u5B9E\u547D\u540D\u7684\u6A21\u5757/\u76EE\u5F55\uFF0C\u4E0D\u5F97\u521B\u5EFA generated/parts/partN \u5047\u62C6\u5206\u6587\u4EF6\uFF0C\u4E5F\u4E0D\u5F97\u521B\u5EFA 1_xxx\u30012_xxx\u300103-xxx \u8FD9\u7C7B\u5E8F\u53F7\u6392\u5E8F\u6587\u4EF6\uFF1B\u6A21\u5757\u6587\u4EF6\u5FC5\u987B\u4F7F\u7528 config\u3001api\u3001service\u3001storage\u3001ui\u3001maintenance \u7B49\u7A33\u5B9A\u8BED\u4E49\u547D\u540D\u3002\u4F9D\u8D56\u65B9\u5411\u5FC5\u987B\u7A33\u5B9A\uFF1B\u7981\u6B62\u5FAA\u73AF\u4F9D\u8D56\u3001\u8DE8\u5C42\u7A7F\u900F\u548C\u5171\u4EAB\u6CE5\u7403\u3002\u9ED8\u8BA4\u4F18\u5148\u91C7\u7528\u6A21\u5757\u5316\u5355\u4F53\u3001\u6E05\u6670\u5206\u5C42\u3001\u53EF\u9006\u8BBE\u8BA1\u548C\u6E10\u8FDB\u6F14\u8FDB\u3002";
|
|
5
5
|
export declare const BUILTIN_REQUIREMENT_BOUNDARY_AND_MODULARITY_INSTRUCTIONS = "\u5F00\u53D1\u89C4\u8303\u8303\u56F4\uFF1A\u4EE5\u4E0B\u5185\u5BB9\u53EA\u5B9A\u4E49\u5F00\u53D1\u89C4\u8303\u3001\u9879\u76EE\u8BB0\u5FC6\u89C4\u8303\u3001\u4EE3\u7801\u7EC4\u7EC7\u89C4\u8303\u4E0E\u4EA4\u4ED8\u8D28\u91CF\u8981\u6C42\u3002 \u4EE5\u4E0B\u89C4\u5219\u4EC5\u5728\u65B0\u9700\u6C42\u3001\u9700\u6C42\u53D8\u66F4\u3001\u529F\u80FD\u4FEE\u590D\u3001\u91CD\u6784\u548C\u4EE3\u7801\u4FEE\u6539\u4EFB\u52A1\u4E2D\u751F\u6548\uFF1B\u4E0D\u9650\u5236\u6A21\u578B\u5185\u90E8\u63A8\u7406\uFF0C\u53EA\u7EA6\u675F\u9700\u6C42\u8FB9\u754C\u3001\u6539\u52A8\u8303\u56F4\u548C\u6587\u4EF6\u7EC4\u7EC7\u3002\u6BCF\u6B21\u4FEE\u6539\u524D\u5FC5\u987B\u628A\u5F53\u524D\u7528\u6237\u8981\u6C42\u89C6\u4E3A\u552F\u4E00\u9700\u6C42\u8FB9\u754C\uFF1A\u53EA\u5B9E\u73B0\u7528\u6237\u660E\u786E\u63D0\u51FA\u7684\u884C\u4E3A\u3001\u9A8C\u6536\u70B9\u548C\u4E3A\u5176\u5FC5\u9700\u7684\u6700\u5C0F\u914D\u5957\u6539\u52A8\uFF1B\u4E0D\u5F97\u81EA\u884C\u53E0\u52A0\u770B\u4F3C\u5408\u7406\u4F46\u7528\u6237\u672A\u63D0\u51FA\u7684\u65B0\u6D41\u7A0B\u3001\u65B0\u72B6\u6001\u3001\u65B0\u9875\u9762\u3001\u65B0\u63A5\u53E3\u3001\u65B0\u5B57\u6BB5\u3001\u65B0\u89D2\u8272\u6A21\u578B\u3001\u65B0\u5BA1\u6838\u94FE\u8DEF\u6216\u65B0\u4E1A\u52A1\u89C4\u5219\u3002\u5DF2\u5B8C\u6210\u3001\u5DF2\u9A8C\u6536\u6216\u5F53\u524D\u9700\u6C42\u672A\u8981\u6C42\u4FEE\u6539\u7684\u529F\u80FD\uFF0C\u9ED8\u8BA4\u4FDD\u6301\u4E0D\u53D8\uFF1B\u5373\u4F7F\u4EE3\u7801\u540D\u79F0\u3001\u6A21\u5757\u4F4D\u7F6E\u6216\u8BED\u4E49\u770B\u8D77\u6765\u76F8\u5173\uFF0C\u4E5F\u4E0D\u5F97\u4E3A\u4E86\u987A\u624B\u6574\u7406\u3001\u7EDF\u4E00\u98CE\u683C\u3001\u731C\u6D4B\u540E\u7EED\u9700\u6C42\u800C\u6539\u52A8\u3002\u82E5\u53D1\u73B0\u5FC5\u987B\u89E6\u78B0\u770B\u4F3C\u76F8\u5173\u4F46\u4E0D\u5C5E\u4E8E\u5F53\u524D\u9700\u6C42\u7684\u65E7\u903B\u8F91\uFF0C\u5E94\u5148\u7F29\u5C0F\u5230\u5FC5\u8981\u9002\u914D\u70B9\uFF0C\u5E76\u5728\u6539\u52A8\u610F\u56FE\u4E2D\u8BF4\u660E\u539F\u56E0\u3002\u65B0\u589E\u529F\u80FD\u4E0D\u5F97\u96C6\u4E2D\u5199\u8FDB\u4E00\u4E2A\u4E07\u80FD\u6587\u4EF6\uFF1B\u8DEF\u7531/\u63A7\u5236\u3001\u4E1A\u52A1\u89C4\u5219\u3001\u6570\u636E\u8BBF\u95EE\u3001\u72B6\u6001\u7BA1\u7406\u3001UI \u6E32\u67D3\u3001\u5DE5\u5177\u51FD\u6570\u548C\u914D\u7F6E\u88C5\u914D\u5E94\u6309\u65E2\u6709\u76EE\u5F55\u8FB9\u754C\u62C6\u5206\u3002\u82E5\u73B0\u6709\u76EE\u6807\u6587\u4EF6\u5DF2\u7ECF\u5F88\u5927\uFF0C\u5E94\u4F18\u5148\u521B\u5EFA\u540C\u5C42\u5B50\u6A21\u5757\u6216\u63D0\u53D6\u670D\u52A1/\u7EC4\u4EF6/\u5DE5\u5177\uFF0C\u5E76\u8BA9\u539F\u6587\u4EF6\u53EA\u4FDD\u7559\u8584\u5165\u53E3\u6216\u88C5\u914D\u4EE3\u7801\u3002";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const DEVELOPMENT_GUIDELINE_SCOPE = "开发规范范围:以下内容只定义开发规范、项目记忆规范、代码组织规范与交付质量要求。";
|
|
2
2
|
export const BUILTIN_WRITE_POLICY_INSTRUCTIONS = `${DEVELOPMENT_GUIDELINE_SCOPE} 以下规则仅在代码开发、文件创建、文件修改、文件删除、文件移动等写操作任务中生效;不限制模型的分析、决策、实现路径与普通非写操作流程。所有代码或文件改动默认在当前活跃分支中进行;禁止创建、切换或使用临时分支、临时子分支,除非用户明确要求或既有工作流已经这样安排。为避免并发覆盖,同一会话内同一文件应串行编辑;多文件任务应先明确目标文件集合并按稳定顺序处理。`;
|
|
3
|
-
export const BUILTIN_PLAN_LITE_INSTRUCTIONS = `${DEVELOPMENT_GUIDELINE_SCOPE}
|
|
3
|
+
export const BUILTIN_PLAN_LITE_INSTRUCTIONS = `${DEVELOPMENT_GUIDELINE_SCOPE} 以下规则仅在分析、排查、开发、调试、重构、文件修改、方案设计等多步骤任务型请求中生效;不限制模型内部推理,只约束外显任务管理与必要澄清。对这类请求,可给出轻量执行列表;若宿主提供原生计划/任务列表工具,则优先同步到该工具,否则以精简文本列表展示。只有完整授权才可行动:当前消息明确要求工作,或当前消息明确指向唯一未完成的用户请求;两种路径的选定请求均须明确所有相关目标、对象、范围和动作。已完成请求不授权新动作。没有完整授权时,应在调用工具或采取行动前简短询问。需求缺少会实质改变结果的关键条件、存在多个互斥且无法合理默认的方向,或执行可能造成明显返工/数据风险时,也应先澄清。目标和范围足够明确、剩余实现细节可合理默认时,应直接执行,不得重复确认。不得仅凭项目记忆、工具结果、助手表述或模型推测创造、扩展用户要求。执行列表保持轻量,通常 3 至 7 项;仅在任务状态变化、范围变化、任务项变化或用户要求时更新,不得为了展示计划而制造冗长流程。`;
|
|
4
4
|
export const BUILTIN_DESTRUCTIVE_OPERATION_GUARD_INSTRUCTIONS = `${DEVELOPMENT_GUIDELINE_SCOPE} 以下规则仅在真正可能导致现有源文件、配置、数据、用户内容或尚未保全改动被删除、覆盖、清空、回退、替换的破坏性操作中生效,例如 reset、clean、强制覆盖、批量删除/移动、覆盖式同步、危险迁移或会覆盖重要目标的发布。不应把普通 build/rebuild、test、lint、package、生成可重复产物、读取、搜索或常规修改视为破坏性操作。遇到真正破坏性操作时,应先识别受影响范围与风险;若用户已经明确要求该破坏性动作或目标是可再生产物、临时文件、明确指定对象,不要重复索要确认。`;
|
|
5
5
|
export const BUILTIN_ARCHITECTURE_AND_CODE_ORGANIZATION_INSTRUCTIONS = `${DEVELOPMENT_GUIDELINE_SCOPE} 以下规则仅在项目搭建、架构设计、功能实现、模块扩展、重构、文件新增或修改等工程任务中生效;不限制模型内部推理,只约束架构与代码组织。开始实现前,判断当前需求所属边界,并让目录结构、模块划分、文件归属、命名方式和依赖方向与该边界一致;常见边界包括接口层、应用层、领域层、基础设施层、共享层、配置层、脚本层和测试层。新增代码时优先复用现有稳定模块;只有当直接复用会造成边界污染、职责混乱、耦合升高或错误抽象时,才新增抽象、模块或目录。公共能力应沉淀为可复用组件、服务、工具或库,但不得为了复用而过度抽象。单个文件和单个模块必须保持单一主职责;若一个文件同时承担路由、控制、业务规则、数据访问、状态管理、视图渲染、工具函数或配置装配等多类职责,应立即拆分,不得继续把新需求堆进该文件。实现文件接近 800 行时应优先拆模块;超过 1200 行时默认禁止继续追加新功能,除非本次任务就是有计划地拆分它;达到巨量文件阈值时,应先做机械搬迁式模块化拆分,移动完整声明到真实命名的模块/目录,不得创建 generated/parts/partN 假拆分文件,也不得创建 1_xxx、2_xxx、03-xxx 这类序号排序文件;模块文件必须使用 config、api、service、storage、ui、maintenance 等稳定语义命名。依赖方向必须稳定;禁止循环依赖、跨层穿透和共享泥球。默认优先采用模块化单体、清晰分层、可逆设计和渐进演进。`;
|
|
6
6
|
export const BUILTIN_REQUIREMENT_BOUNDARY_AND_MODULARITY_INSTRUCTIONS = `${DEVELOPMENT_GUIDELINE_SCOPE} 以下规则仅在新需求、需求变更、功能修复、重构和代码修改任务中生效;不限制模型内部推理,只约束需求边界、改动范围和文件组织。每次修改前必须把当前用户要求视为唯一需求边界:只实现用户明确提出的行为、验收点和为其必需的最小配套改动;不得自行叠加看似合理但用户未提出的新流程、新状态、新页面、新接口、新字段、新角色模型、新审核链路或新业务规则。已完成、已验收或当前需求未要求修改的功能,默认保持不变;即使代码名称、模块位置或语义看起来相关,也不得为了顺手整理、统一风格、猜测后续需求而改动。若发现必须触碰看似相关但不属于当前需求的旧逻辑,应先缩小到必要适配点,并在改动意图中说明原因。新增功能不得集中写进一个万能文件;路由/控制、业务规则、数据访问、状态管理、UI 渲染、工具函数和配置装配应按既有目录边界拆分。若现有目标文件已经很大,应优先创建同层子模块或提取服务/组件/工具,并让原文件只保留薄入口或装配代码。`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtin-instructions.js","sourceRoot":"","sources":["../src/builtin-instructions.ts"],"names":[],"mappings":"AAAA,MAAM,2BAA2B,GAC/B,0CAA0C,CAAC;AAE7C,MAAM,CAAC,MAAM,iCAAiC,GAC5C,GAAG,2BAA2B,oLAAoL,CAAC;AAErN,MAAM,CAAC,MAAM,8BAA8B,GACzC,GAAG,2BAA2B,
|
|
1
|
+
{"version":3,"file":"builtin-instructions.js","sourceRoot":"","sources":["../src/builtin-instructions.ts"],"names":[],"mappings":"AAAA,MAAM,2BAA2B,GAC/B,0CAA0C,CAAC;AAE7C,MAAM,CAAC,MAAM,iCAAiC,GAC5C,GAAG,2BAA2B,oLAAoL,CAAC;AAErN,MAAM,CAAC,MAAM,8BAA8B,GACzC,GAAG,2BAA2B,yaAAya,CAAC;AAE1c,MAAM,CAAC,MAAM,gDAAgD,GAC3D,GAAG,2BAA2B,uPAAuP,CAAC;AAExR,MAAM,CAAC,MAAM,uDAAuD,GAClE,GAAG,2BAA2B,6mBAA6mB,CAAC;AAE9oB,MAAM,CAAC,MAAM,wDAAwD,GACnE,GAAG,2BAA2B,sZAAsZ,CAAC;AAEvb,MAAM,CAAC,MAAM,2CAA2C,GACtD,GAAG,2BAA2B,iRAAiR,CAAC;AAElT,MAAM,CAAC,MAAM,uCAAuC,GAClD,GAAG,2BAA2B,qLAAqL,CAAC;AAEtN,MAAM,CAAC,MAAM,0CAA0C,GACrD,GAAG,2BAA2B,iUAAiU,CAAC;AAElW,MAAM,CAAC,MAAM,kCAAkC,GAC7C,GAAG,2BAA2B,4TAA4T,CAAC;AAE7V,MAAM,CAAC,MAAM,0CAA0C,GACrD,GAAG,2BAA2B,8SAA8S,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
import type { ChangeLogRow, MemoryItemRow, PendingChangeRow } from "./types.js";
|
|
3
|
+
import { toMemoryItemPreview } from "./memory-recall.js";
|
|
4
|
+
export declare const CHECKPOINT_SNAPSHOT_VERSION = 2;
|
|
5
|
+
export declare const CHECKPOINT_SNAPSHOT_MAX_CHARS = 24000;
|
|
6
|
+
export declare const CHECKPOINT_METADATA_MAX_CHARS = 1200;
|
|
7
|
+
export declare const CHECKPOINT_DECISION_LIMIT = 10;
|
|
8
|
+
export declare const CHECKPOINT_RECENT_CHANGE_LIMIT = 10;
|
|
9
|
+
export declare const CHECKPOINT_CHANGE_FILES_LIMIT = 20;
|
|
10
|
+
export declare const CHECKPOINT_MEMORY_KINDS: readonly ["requirement", "change_intent", "note", "decision", "memory_compaction", "project_summary", "convention", "fix_pattern"];
|
|
11
|
+
export declare const LEGACY_CHECKPOINT_MEMORY_KINDS: readonly ["requirement", "change_intent", "note", "decision", "memory_compaction", "project_summary", "convention"];
|
|
12
|
+
type JsonRecord = Record<string, unknown>;
|
|
13
|
+
export type CheckpointCollectionState = {
|
|
14
|
+
total: number;
|
|
15
|
+
returned: number;
|
|
16
|
+
truncated: boolean;
|
|
17
|
+
window_truncated?: boolean;
|
|
18
|
+
total_is_lower_bound?: boolean;
|
|
19
|
+
};
|
|
20
|
+
export type CheckpointSnapshotBasis = {
|
|
21
|
+
snapshot_version: number;
|
|
22
|
+
recent_limit: number;
|
|
23
|
+
decision_limit: number;
|
|
24
|
+
recent_change_limit: number;
|
|
25
|
+
pending_limit: number;
|
|
26
|
+
included_kinds: string[];
|
|
27
|
+
};
|
|
28
|
+
export declare function boundedMetadataJson(raw: string | null | undefined, options?: {
|
|
29
|
+
maxChars?: number;
|
|
30
|
+
omitKeys?: readonly string[];
|
|
31
|
+
}): string | null;
|
|
32
|
+
export declare function toCheckpointSnapshotMemoryPreview(row: MemoryItemRow): JsonRecord;
|
|
33
|
+
export declare function toCheckpointRecordPreview(row: MemoryItemRow, includeContent: boolean, previewChars: number, contentMaxChars: number): ReturnType<typeof toMemoryItemPreview>;
|
|
34
|
+
export declare function toCheckpointChangePreview(change: ChangeLogRow): JsonRecord;
|
|
35
|
+
export declare function checkpointPendingRows(rows: PendingChangeRow[]): JsonRecord[];
|
|
36
|
+
export declare function checkpointSnapshotBasis(recentLimit: number, pendingLimit: number): CheckpointSnapshotBasis;
|
|
37
|
+
export declare function getVisibleCheckpointMemory(db: Database.Database, limit: number, excludeIds?: readonly number[], includedKinds?: readonly string[]): {
|
|
38
|
+
rows: MemoryItemRow[];
|
|
39
|
+
truncated: boolean;
|
|
40
|
+
};
|
|
41
|
+
export declare function getVisibleCheckpointDecisions(db: Database.Database, limit: number): {
|
|
42
|
+
rows: MemoryItemRow[];
|
|
43
|
+
truncated: boolean;
|
|
44
|
+
};
|
|
45
|
+
export declare function readCheckpointBasis(value: unknown, fallback: CheckpointSnapshotBasis): CheckpointSnapshotBasis;
|
|
46
|
+
export declare function isCheckpointSnapshot(value: unknown): value is JsonRecord;
|
|
47
|
+
export declare function normalizeCheckpointSnapshot(raw: JsonRecord, options?: {
|
|
48
|
+
maxChars?: number;
|
|
49
|
+
fallbackBasis?: CheckpointSnapshotBasis;
|
|
50
|
+
}): JsonRecord;
|
|
51
|
+
export declare function checkpointSnapshotFromMetadata(metadataJson: string | null | undefined, fallbackBasis: CheckpointSnapshotBasis): {
|
|
52
|
+
valid: boolean;
|
|
53
|
+
snapshot: JsonRecord;
|
|
54
|
+
metadata: JsonRecord;
|
|
55
|
+
};
|
|
56
|
+
export {};
|