baxian 1.2.57 → 1.2.59
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/dist/agent/branch.d.ts +6 -1
- package/dist/agent/branch.d.ts.map +1 -1
- package/dist/agent/branch.js +45 -9
- package/dist/agent/branch.js.map +1 -1
- package/dist/agent/manager.d.ts +182 -5
- package/dist/agent/manager.d.ts.map +1 -1
- package/dist/agent/manager.js +2235 -147
- package/dist/agent/manager.js.map +1 -1
- package/dist/agent/phase-signal-watcher.d.ts +8 -1
- package/dist/agent/phase-signal-watcher.d.ts.map +1 -1
- package/dist/agent/phase-signal-watcher.js +66 -15
- package/dist/agent/phase-signal-watcher.js.map +1 -1
- package/dist/agent/phase-signal.d.ts +3 -1
- package/dist/agent/phase-signal.d.ts.map +1 -1
- package/dist/agent/phase-signal.js +27 -4
- package/dist/agent/phase-signal.js.map +1 -1
- package/dist/agent/tmux.d.ts +8 -1
- package/dist/agent/tmux.d.ts.map +1 -1
- package/dist/agent/tmux.js +61 -1
- package/dist/agent/tmux.js.map +1 -1
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +16 -4
- package/dist/api/config.js.map +1 -1
- package/dist/api/platform-guard.d.ts +7 -0
- package/dist/api/platform-guard.d.ts.map +1 -0
- package/dist/api/platform-guard.js +32 -0
- package/dist/api/platform-guard.js.map +1 -0
- package/dist/api/projects.d.ts.map +1 -1
- package/dist/api/projects.js +34 -6
- package/dist/api/projects.js.map +1 -1
- package/dist/config/normalizer.d.ts.map +1 -1
- package/dist/config/normalizer.js +1 -0
- package/dist/config/normalizer.js.map +1 -1
- package/dist/config/validator.d.ts +3 -1
- package/dist/config/validator.d.ts.map +1 -1
- package/dist/config/validator.js +104 -7
- package/dist/config/validator.js.map +1 -1
- package/dist/event/handlers.d.ts +1 -0
- package/dist/event/handlers.d.ts.map +1 -1
- package/dist/event/handlers.js +661 -89
- package/dist/event/handlers.js.map +1 -1
- package/dist/github/mapper.d.ts +1 -6
- package/dist/github/mapper.d.ts.map +1 -1
- package/dist/github/mapper.js.map +1 -1
- package/dist/github/poller.d.ts +3 -3
- package/dist/github/poller.d.ts.map +1 -1
- package/dist/github/poller.js +2 -11
- package/dist/github/poller.js.map +1 -1
- package/dist/github/resolver.js +1 -1
- package/dist/github/resolver.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -2
- package/dist/index.js.map +1 -1
- package/dist/platform/body-digest.d.ts +4 -0
- package/dist/platform/body-digest.d.ts.map +1 -0
- package/dist/platform/body-digest.js +13 -0
- package/dist/platform/body-digest.js.map +1 -0
- package/dist/platform/command-renderer.d.ts +22 -0
- package/dist/platform/command-renderer.d.ts.map +1 -0
- package/dist/platform/command-renderer.js +82 -0
- package/dist/platform/command-renderer.js.map +1 -0
- package/dist/platform/comment-cursor.d.ts +36 -0
- package/dist/platform/comment-cursor.d.ts.map +1 -0
- package/dist/platform/comment-cursor.js +235 -0
- package/dist/platform/comment-cursor.js.map +1 -0
- package/dist/platform/driver-host.d.ts +7 -0
- package/dist/platform/driver-host.d.ts.map +1 -0
- package/dist/platform/driver-host.js +18 -0
- package/dist/platform/driver-host.js.map +1 -0
- package/dist/platform/driver-spec.d.ts +7 -0
- package/dist/platform/driver-spec.d.ts.map +1 -0
- package/dist/platform/driver-spec.js +475 -0
- package/dist/platform/driver-spec.js.map +1 -0
- package/dist/platform/feedback.d.ts +31 -0
- package/dist/platform/feedback.d.ts.map +1 -0
- package/dist/platform/feedback.js +85 -0
- package/dist/platform/feedback.js.map +1 -0
- package/dist/platform/field-mapper.d.ts +7 -0
- package/dist/platform/field-mapper.d.ts.map +1 -0
- package/dist/platform/field-mapper.js +117 -0
- package/dist/platform/field-mapper.js.map +1 -0
- package/dist/platform/git-driver.d.ts +55 -0
- package/dist/platform/git-driver.d.ts.map +1 -0
- package/dist/platform/git-driver.js +171 -0
- package/dist/platform/git-driver.js.map +1 -0
- package/dist/platform/manifest.d.ts +12 -0
- package/dist/platform/manifest.d.ts.map +1 -0
- package/dist/platform/manifest.js +57 -0
- package/dist/platform/manifest.js.map +1 -0
- package/dist/platform/markers.d.ts +46 -0
- package/dist/platform/markers.d.ts.map +1 -0
- package/dist/platform/markers.js +121 -0
- package/dist/platform/markers.js.map +1 -0
- package/dist/platform/platform-poller.d.ts +68 -0
- package/dist/platform/platform-poller.d.ts.map +1 -0
- package/dist/platform/platform-poller.js +605 -0
- package/dist/platform/platform-poller.js.map +1 -0
- package/dist/platform/plugin-registry.d.ts +31 -0
- package/dist/platform/plugin-registry.d.ts.map +1 -0
- package/dist/platform/plugin-registry.js +238 -0
- package/dist/platform/plugin-registry.js.map +1 -0
- package/dist/platform/plugin-roots.d.ts +3 -0
- package/dist/platform/plugin-roots.d.ts.map +1 -0
- package/dist/platform/plugin-roots.js +11 -0
- package/dist/platform/plugin-roots.js.map +1 -0
- package/dist/platform/plugins/github/baxian-plugin.json +8 -0
- package/dist/platform/plugins/github/driver.json +134 -0
- package/dist/platform/plugins/github/skills/baxian-cli-gh/SKILL.md +99 -0
- package/dist/platform/poller-health.d.ts +3 -0
- package/dist/platform/poller-health.d.ts.map +1 -0
- package/dist/platform/poller-health.js +12 -0
- package/dist/platform/poller-health.js.map +1 -0
- package/dist/platform/pr-binding.d.ts +22 -0
- package/dist/platform/pr-binding.d.ts.map +1 -0
- package/dist/platform/pr-binding.js +28 -0
- package/dist/platform/pr-binding.js.map +1 -0
- package/dist/platform/response-parser.d.ts +6 -0
- package/dist/platform/response-parser.d.ts.map +1 -0
- package/dist/platform/response-parser.js +92 -0
- package/dist/platform/response-parser.js.map +1 -0
- package/dist/platform/row-schema.d.ts +12 -0
- package/dist/platform/row-schema.d.ts.map +1 -0
- package/dist/platform/row-schema.js +127 -0
- package/dist/platform/row-schema.js.map +1 -0
- package/dist/platform/startup.d.ts +16 -0
- package/dist/platform/startup.d.ts.map +1 -0
- package/dist/platform/startup.js +52 -0
- package/dist/platform/startup.js.map +1 -0
- package/dist/platform/types.d.ts +62 -0
- package/dist/platform/types.d.ts.map +1 -0
- package/dist/platform/types.js +32 -0
- package/dist/platform/types.js.map +1 -0
- package/dist/platform/verdict-engine.d.ts +61 -0
- package/dist/platform/verdict-engine.d.ts.map +1 -0
- package/dist/platform/verdict-engine.js +134 -0
- package/dist/platform/verdict-engine.js.map +1 -0
- package/dist/shared/constants.d.ts +2 -0
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +3 -0
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/git-url.d.ts +8 -0
- package/dist/shared/git-url.d.ts.map +1 -1
- package/dist/shared/git-url.js +38 -0
- package/dist/shared/git-url.js.map +1 -1
- package/dist/shared/types.d.ts +52 -1
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/state/agent-store.js +2 -0
- package/dist/state/agent-store.js.map +1 -1
- package/dist/state/task-store.d.ts.map +1 -1
- package/dist/state/task-store.js +91 -4
- package/dist/state/task-store.js.map +1 -1
- package/dist/web/assets/index-DskVWe7e.js +13 -0
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/assets/index-3Ypk8Gfo.js +0 -13
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-mapper.d.ts","sourceRoot":"","sources":["../../src/platform/field-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,YAAY,CAAC;AAEzD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEhD,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AA0FD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,CAkCvF"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
export class FieldMappingError extends Error {
|
|
2
|
+
constructor(message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = 'FieldMappingError';
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
const MISSING = Symbol('missing');
|
|
8
|
+
function getPath(obj, path) {
|
|
9
|
+
let cur = obj;
|
|
10
|
+
for (const seg of path.split('.')) {
|
|
11
|
+
if (cur === null || typeof cur !== 'object' || !Object.hasOwn(cur, seg))
|
|
12
|
+
return MISSING;
|
|
13
|
+
cur = cur[seg];
|
|
14
|
+
}
|
|
15
|
+
return cur;
|
|
16
|
+
}
|
|
17
|
+
// map 源路径取值器:点路径 + 单层 [] 展平(spec §5.3),供 resolveField 使用;
|
|
18
|
+
// op 级 flatten(上面的 getPath)语义不同(缺失/非数组按形状损坏拒绝),两者不合并。
|
|
19
|
+
function resolveSourceSegments(obj, segments, fullPath, opName, field) {
|
|
20
|
+
if (segments.length === 0)
|
|
21
|
+
return obj;
|
|
22
|
+
if (obj === null || typeof obj !== 'object')
|
|
23
|
+
return MISSING;
|
|
24
|
+
const record = obj;
|
|
25
|
+
const [seg, ...rest] = segments;
|
|
26
|
+
if (!seg.endsWith('[]')) {
|
|
27
|
+
if (!Object.hasOwn(record, seg))
|
|
28
|
+
return MISSING;
|
|
29
|
+
return resolveSourceSegments(record[seg], rest, fullPath, opName, field);
|
|
30
|
+
}
|
|
31
|
+
const key = seg.slice(0, -2);
|
|
32
|
+
if (!Object.hasOwn(record, key))
|
|
33
|
+
return MISSING; // 数组键本身不存在 → MISSING,走必需/optional 语义
|
|
34
|
+
const arr = record[key];
|
|
35
|
+
// null-as-present(spec §5.3):键存在值 null 不触发任何缺失语义;集合投影统一空数组,
|
|
36
|
+
// 与 [] 响应同构、required 不抛。仅键不存在才是 MISSING。
|
|
37
|
+
if (arr === null)
|
|
38
|
+
return [];
|
|
39
|
+
if (!Array.isArray(arr)) {
|
|
40
|
+
throw new FieldMappingError(`op ${opName}: field '${field}' source path '${fullPath}' expects an array at '${key}' (got ${typeof arr})`);
|
|
41
|
+
}
|
|
42
|
+
const results = [];
|
|
43
|
+
for (const element of arr) {
|
|
44
|
+
const v = resolveSourceSegments(element, rest, fullPath, opName, field);
|
|
45
|
+
if (v !== MISSING)
|
|
46
|
+
results.push(v); // 元素缺剩余路径键则跳过该元素(宽松聚合)
|
|
47
|
+
}
|
|
48
|
+
return results;
|
|
49
|
+
}
|
|
50
|
+
function compileMap(opName, map) {
|
|
51
|
+
return Object.entries(map).map(([field, spec]) => {
|
|
52
|
+
const rawSources = typeof spec === 'string' ? [spec] : spec.sources;
|
|
53
|
+
const optional = typeof spec === 'string' ? false : spec.optional === true;
|
|
54
|
+
const values = typeof spec === 'string' ? undefined : spec.values;
|
|
55
|
+
const sources = rawSources.map((raw) => {
|
|
56
|
+
const fromParent = raw.startsWith('_discussion.');
|
|
57
|
+
const path = fromParent ? raw.slice('_discussion.'.length) : raw;
|
|
58
|
+
const segments = path.split('.');
|
|
59
|
+
if (segments.filter(seg => seg.endsWith('[]')).length > 1) {
|
|
60
|
+
throw new FieldMappingError(`op ${opName}: field '${field}' source path '${path}' has more than one '[]' level, which is unsupported`);
|
|
61
|
+
}
|
|
62
|
+
return { fromParent, segments, raw: path };
|
|
63
|
+
});
|
|
64
|
+
return { field, sources, sourceKeys: rawSources.join(', '), optional, values };
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function resolveField(opName, compiled, element, parent) {
|
|
68
|
+
for (const src of compiled.sources) {
|
|
69
|
+
const v = resolveSourceSegments(src.fromParent ? parent : element, src.segments, src.raw, opName, compiled.field);
|
|
70
|
+
if (v !== MISSING) {
|
|
71
|
+
// values 翻译只作用于字符串命中(spec §5.3 增量③):null/数字等命中原样透传。
|
|
72
|
+
if (compiled.values && typeof v === 'string' && Object.hasOwn(compiled.values, v))
|
|
73
|
+
return compiled.values[v];
|
|
74
|
+
return v; // null 是合法值,键存在即命中
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (compiled.optional)
|
|
78
|
+
return undefined;
|
|
79
|
+
throw new FieldMappingError(`op ${opName}: required field '${compiled.field}' missing (tried keys: ${compiled.sourceKeys})`);
|
|
80
|
+
}
|
|
81
|
+
export function mapResponse(opName, op, payload) {
|
|
82
|
+
const compiledFields = compileMap(opName, op.map ?? {});
|
|
83
|
+
const units = [];
|
|
84
|
+
// null 或非对象 payload 按零行处理
|
|
85
|
+
if (payload === null || typeof payload !== 'object') {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
const top = Array.isArray(payload) ? payload : [payload];
|
|
89
|
+
for (const item of top) {
|
|
90
|
+
if (op.flatten) {
|
|
91
|
+
const arr = getPath(item, op.flatten);
|
|
92
|
+
// 键缺失/非数组是响应形状损坏而非空集合:静默跳过会把整页伪装成合法空页,被跳过的
|
|
93
|
+
// discussion 若含令牌或人类反馈,完整性门照样放行——fail closed;显式 null/[] 才是空集合。
|
|
94
|
+
if (arr === MISSING) {
|
|
95
|
+
throw new FieldMappingError(`op ${opName}: flatten path '${op.flatten}' missing on a response item`);
|
|
96
|
+
}
|
|
97
|
+
if (arr === null)
|
|
98
|
+
continue;
|
|
99
|
+
if (!Array.isArray(arr)) {
|
|
100
|
+
throw new FieldMappingError(`op ${opName}: flatten path '${op.flatten}' expects an array (got ${typeof arr})`);
|
|
101
|
+
}
|
|
102
|
+
for (const child of arr)
|
|
103
|
+
units.push({ element: child, parent: item });
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
units.push({ element: item, parent: item });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return units.map(({ element, parent }) => {
|
|
110
|
+
const row = {};
|
|
111
|
+
for (const compiled of compiledFields) {
|
|
112
|
+
row[compiled.field] = resolveField(opName, compiled, element, parent);
|
|
113
|
+
}
|
|
114
|
+
return row;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=field-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-mapper.js","sourceRoot":"","sources":["../../src/platform/field-mapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type CommentSourceOp, type DriverSpec } from './types.js';
|
|
2
|
+
import { type RenderContext } from './command-renderer.js';
|
|
3
|
+
import { type NormalizedRow } from './row-schema.js';
|
|
4
|
+
export declare const DRIVER_MAX_BUFFER: number;
|
|
5
|
+
export declare const DRIVER_EXEC_TIMEOUT_MS = 60000;
|
|
6
|
+
export declare const LIST_PRS_PAGE_CAP = 10;
|
|
7
|
+
export declare const COMMENT_SOURCE_PAGE_CAP = 100;
|
|
8
|
+
export interface DriverExecResult {
|
|
9
|
+
stdout: string;
|
|
10
|
+
stderr: string;
|
|
11
|
+
exitCode: number;
|
|
12
|
+
}
|
|
13
|
+
export type DriverExec = (command: string, opts: {
|
|
14
|
+
timeout: number;
|
|
15
|
+
maxBuffer: number;
|
|
16
|
+
}) => Promise<DriverExecResult>;
|
|
17
|
+
export declare class DriverOpError extends Error {
|
|
18
|
+
readonly info: {
|
|
19
|
+
opName: string;
|
|
20
|
+
errorClass?: string;
|
|
21
|
+
exitCode?: number;
|
|
22
|
+
stderrTail?: string;
|
|
23
|
+
};
|
|
24
|
+
constructor(message: string, info: {
|
|
25
|
+
opName: string;
|
|
26
|
+
errorClass?: string;
|
|
27
|
+
exitCode?: number;
|
|
28
|
+
stderrTail?: string;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export interface OpVars {
|
|
32
|
+
prNumber?: number;
|
|
33
|
+
expectedHeadSha?: string;
|
|
34
|
+
branch?: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function buildDriverRunContext(repoUrl: string, binary: string): RenderContext;
|
|
37
|
+
export declare class GitDriver {
|
|
38
|
+
private readonly plugin;
|
|
39
|
+
private readonly ctx;
|
|
40
|
+
private readonly exec;
|
|
41
|
+
private readonly errorMatchers;
|
|
42
|
+
constructor(plugin: {
|
|
43
|
+
spec: DriverSpec;
|
|
44
|
+
}, ctx: RenderContext, exec: DriverExec);
|
|
45
|
+
get visibilityLagMs(): number;
|
|
46
|
+
get commentSources(): CommentSourceOp[];
|
|
47
|
+
classify(text: string): string | undefined;
|
|
48
|
+
runOp(opName: string, vars?: OpVars): Promise<NormalizedRow[]>;
|
|
49
|
+
runListPrs(vars: OpVars, shouldStop?: (pageRows: NormalizedRow[], page: number) => boolean): Promise<NormalizedRow[]>;
|
|
50
|
+
runCommentSource(source: CommentSourceOp, vars: OpVars, projectPage?: (pageRows: NormalizedRow[]) => NormalizedRow[]): Promise<NormalizedRow[]>;
|
|
51
|
+
private namedOp;
|
|
52
|
+
private execRendered;
|
|
53
|
+
private runPaged;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=git-driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-driver.d.ts","sourceRoot":"","sources":["../../src/platform/git-driver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,eAAe,EAAiB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AACvG,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG1E,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGnE,eAAO,MAAM,iBAAiB,QAAmB,CAAC;AAClD,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAG7C,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAG3C,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAEtH,qBAAa,aAAc,SAAQ,KAAK;IAGpC,QAAQ,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;gBAD9F,OAAO,EAAE,MAAM,EACN,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;CAKjG;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAepF;AAgBD,qBAAa,SAAS;IAIlB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IALvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA8C;gBAGzD,MAAM,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,EAC5B,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,UAAU;IASnC,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED,IAAI,cAAc,IAAI,eAAe,EAAE,CAEtC;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAOpC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,MAAW,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IA8BlE,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,GAChE,OAAO,CAAC,aAAa,EAAE,CAAC;IAMrB,gBAAgB,CACpB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,GAC3D,OAAO,CAAC,aAAa,EAAE,CAAC;IAM3B,OAAO,CAAC,OAAO;YAMD,YAAY;YAgBZ,QAAQ;CA0DvB"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { SINGLE_RESOURCE_OPS } from './types.js';
|
|
2
|
+
import { renderCommand } from './command-renderer.js';
|
|
3
|
+
import { parseJsonResponse, parseJsonPagedPage } from './response-parser.js';
|
|
4
|
+
import { mapResponse } from './field-mapper.js';
|
|
5
|
+
import { validateRows } from './row-schema.js';
|
|
6
|
+
import { isGitHubRepo, repoSlug, parseRepoUrlParts } from '../shared/git-url.js';
|
|
7
|
+
export const DRIVER_MAX_BUFFER = 64 * 1024 * 1024;
|
|
8
|
+
export const DRIVER_EXEC_TIMEOUT_MS = 60_000;
|
|
9
|
+
// listPrs 的 10 页封顶是发现窗口(v1 §6,正常终止);评论源无业务水位上限,
|
|
10
|
+
// 命中 100 页即 fail closed——「最终必有空页」不是声明式输出可验证的契约(spec §5.3 增量⑦)。
|
|
11
|
+
export const LIST_PRS_PAGE_CAP = 10;
|
|
12
|
+
export const COMMENT_SOURCE_PAGE_CAP = 100;
|
|
13
|
+
const STDERR_TAIL_CHARS = 500;
|
|
14
|
+
export class DriverOpError extends Error {
|
|
15
|
+
info;
|
|
16
|
+
constructor(message, info) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.info = info;
|
|
19
|
+
this.name = 'DriverOpError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function buildDriverRunContext(repoUrl, binary) {
|
|
23
|
+
const t = repoUrl.trim();
|
|
24
|
+
if (isGitHubRepo(t)) {
|
|
25
|
+
return { scheme: 'https', hostname: 'github.com', host: 'github.com', repoPath: repoSlug(t), binary };
|
|
26
|
+
}
|
|
27
|
+
// 与 repoIdentityKey 同一分解(shared/git-url):cursor 身份与命令渲染对同一 URL 的解读不分叉。
|
|
28
|
+
const parts = parseRepoUrlParts(t);
|
|
29
|
+
if (parts === null)
|
|
30
|
+
throw new Error(`cannot derive driver context from repo URL: ${t}`);
|
|
31
|
+
return {
|
|
32
|
+
scheme: parts.scheme,
|
|
33
|
+
hostname: parts.hostname,
|
|
34
|
+
host: parts.port === '' ? parts.hostname : `${parts.hostname}:${parts.port}`,
|
|
35
|
+
repoPath: parts.path,
|
|
36
|
+
binary,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const tail = (s) => (s.length > STDERR_TAIL_CHARS ? s.slice(-STDERR_TAIL_CHARS) : s);
|
|
40
|
+
export class GitDriver {
|
|
41
|
+
plugin;
|
|
42
|
+
ctx;
|
|
43
|
+
exec;
|
|
44
|
+
errorMatchers;
|
|
45
|
+
constructor(plugin, ctx, exec) {
|
|
46
|
+
this.plugin = plugin;
|
|
47
|
+
this.ctx = ctx;
|
|
48
|
+
this.exec = exec;
|
|
49
|
+
// 声明期常量模式一次编译(无 g 标志,test 无 lastIndex 状态);失败风暴期每次 exec 免重编译。
|
|
50
|
+
this.errorMatchers = plugin.spec.errorClasses.map(c => ({
|
|
51
|
+
class: c.class,
|
|
52
|
+
regexes: c.regex.map(r => new RegExp(r)),
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
get visibilityLagMs() {
|
|
56
|
+
return this.plugin.spec.visibilityLagSeconds * 1000;
|
|
57
|
+
}
|
|
58
|
+
get commentSources() {
|
|
59
|
+
return this.plugin.spec.commentSources;
|
|
60
|
+
}
|
|
61
|
+
classify(text) {
|
|
62
|
+
for (const c of this.errorMatchers) {
|
|
63
|
+
if (c.regexes.some(r => r.test(text)))
|
|
64
|
+
return c.class;
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
async runOp(opName, vars = {}) {
|
|
69
|
+
const op = this.namedOp(opName);
|
|
70
|
+
if (op.parse === 'json-paged') {
|
|
71
|
+
throw new DriverOpError(`op ${opName} is paged; use the paged runner`, { opName });
|
|
72
|
+
}
|
|
73
|
+
let rows;
|
|
74
|
+
try {
|
|
75
|
+
const result = await this.execRendered(opName, op, vars);
|
|
76
|
+
rows = result === 'treated-success' || op.parse === undefined
|
|
77
|
+
? []
|
|
78
|
+
: validateRows(opName, mapResponse(opName, op, parseJsonResponse(result.stdout)));
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
// optional op 不可用仅能力降级、不计健康度(spec §5.3/§7 listApprovals 语义);生命周期
|
|
82
|
+
// 必需 op 与评论源在加载期即拒绝 optional。降级只吞执行失败(DriverOpError)——命令
|
|
83
|
+
// 成功后的 parse/schema 错误是插件缺陷,照常 fail loud。
|
|
84
|
+
if (op.optional === true && e instanceof DriverOpError)
|
|
85
|
+
return [];
|
|
86
|
+
throw e;
|
|
87
|
+
}
|
|
88
|
+
// 单资源 op 的空/多行响应是 fail-open 洞:null/标量被归一成零行后上层只会静默跳过,
|
|
89
|
+
// 项目/PR 永久停摆而健康度仍显示成功——按 op 契约恰好一行,违例 fail closed。
|
|
90
|
+
// 检查对 parse 缺失/treated-success 的零行同样生效(加载期契约之外的运行时纵深)。
|
|
91
|
+
if (SINGLE_RESOURCE_OPS.has(opName) && rows.length !== 1) {
|
|
92
|
+
throw new DriverOpError(`op ${opName} must yield exactly one row (got ${rows.length})`, { opName });
|
|
93
|
+
}
|
|
94
|
+
return rows;
|
|
95
|
+
}
|
|
96
|
+
async runListPrs(vars, shouldStop) {
|
|
97
|
+
return this.runPaged('listPrs', this.namedOp('listPrs'), vars, {
|
|
98
|
+
pageCap: LIST_PRS_PAGE_CAP, capBehavior: 'stop', idField: 'prNumber', shouldStop,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async runCommentSource(source, vars, projectPage) {
|
|
102
|
+
return this.runPaged('listComments', source, vars, {
|
|
103
|
+
pageCap: COMMENT_SOURCE_PAGE_CAP, capBehavior: 'fail', idField: 'id', sourceKey: source.key, projectPage,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
namedOp(opName) {
|
|
107
|
+
const op = this.plugin.spec.ops[opName];
|
|
108
|
+
if (!op)
|
|
109
|
+
throw new DriverOpError(`op ${opName} is not declared by the driver`, { opName });
|
|
110
|
+
return op;
|
|
111
|
+
}
|
|
112
|
+
async execRendered(opName, op, vars) {
|
|
113
|
+
const cmd = renderCommand(op, { ...this.ctx, ...vars });
|
|
114
|
+
const result = await this.exec(cmd, { timeout: DRIVER_EXEC_TIMEOUT_MS, maxBuffer: DRIVER_MAX_BUFFER });
|
|
115
|
+
if (result.exitCode === 0)
|
|
116
|
+
return result;
|
|
117
|
+
const cls = this.classify(`${result.stderr}\n${result.stdout}`);
|
|
118
|
+
if (cls !== undefined && op.treatAsSuccess?.includes(cls))
|
|
119
|
+
return 'treated-success';
|
|
120
|
+
throw new DriverOpError(`op ${opName} failed (exit ${result.exitCode}${cls ? `, class ${cls}` : ''}): ${tail(result.stderr || result.stdout)}`, { opName, errorClass: cls, exitCode: result.exitCode, stderrTail: tail(result.stderr) });
|
|
121
|
+
}
|
|
122
|
+
async runPaged(rowOp, op, vars, opts) {
|
|
123
|
+
const label = opts.sourceKey === undefined ? rowOp : `${rowOp}[${opts.sourceKey}]`;
|
|
124
|
+
const { idField } = opts;
|
|
125
|
+
const all = [];
|
|
126
|
+
// 页码分页在扫描期间有排序前移时,相邻页可部分重叠(GitHub sort=updated 已知形态):
|
|
127
|
+
// 同身份同内容 = 位移重复、静默去重;同身份异内容 = 同扫描内版本冲突,fail closed 下轮重扫。
|
|
128
|
+
const seen = new Map();
|
|
129
|
+
let prevIds;
|
|
130
|
+
for (let page = 1; page <= opts.pageCap; page++) {
|
|
131
|
+
const result = await this.execRendered(label, op, { ...vars, page });
|
|
132
|
+
if (result === 'treated-success') {
|
|
133
|
+
throw new DriverOpError(`op ${label}: treatAsSuccess is not valid on a paged read`, { opName: label });
|
|
134
|
+
}
|
|
135
|
+
const rawPage = parseJsonPagedPage(result.stdout);
|
|
136
|
+
if (rawPage.length === 0)
|
|
137
|
+
return all;
|
|
138
|
+
// 投影先于指纹:指纹对原文 stringify 会把整页 body 再序列化一遍并在 seen 里滞留到扫描
|
|
139
|
+
// 结束,绕开「跨页只聚合投影行」的内存界;bodyDigest 已入投影行,任何正文差异仍必然
|
|
140
|
+
// 改变指纹,冲突检测语义等价。
|
|
141
|
+
const rows = validateRows(rowOp, mapResponse(rowOp, op, rawPage), opts.sourceKey === undefined ? undefined : { sourceKey: opts.sourceKey });
|
|
142
|
+
const projected = opts.projectPage === undefined ? rows : opts.projectPage(rows);
|
|
143
|
+
const ids = new Set(projected.map(r => String(r[idField])));
|
|
144
|
+
// flatten 源可能整页映射零行,空集合相等不构成「后端未消费 {page}」的证据。
|
|
145
|
+
if (prevIds !== undefined && prevIds.size > 0 && ids.size === prevIds.size && [...ids].every(i => prevIds.has(i))) {
|
|
146
|
+
throw new DriverOpError(`op ${label}: pagination did not advance at page ${page} (backend ignoring {page}?)`, { opName: label });
|
|
147
|
+
}
|
|
148
|
+
prevIds = ids;
|
|
149
|
+
for (const row of projected) {
|
|
150
|
+
const key = String(row[idField]);
|
|
151
|
+
const fingerprint = JSON.stringify(row);
|
|
152
|
+
const prior = seen.get(key);
|
|
153
|
+
if (prior === undefined) {
|
|
154
|
+
seen.set(key, fingerprint);
|
|
155
|
+
all.push(row);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (prior === fingerprint)
|
|
159
|
+
continue;
|
|
160
|
+
throw new DriverOpError(`op ${label}: conflicting duplicate row for ${idField}=${key} across pages (mid-scan mutation)`, { opName: label });
|
|
161
|
+
}
|
|
162
|
+
if (opts.shouldStop?.(projected, page) === true)
|
|
163
|
+
return all;
|
|
164
|
+
}
|
|
165
|
+
if (opts.capBehavior === 'fail') {
|
|
166
|
+
throw new DriverOpError(`op ${label}: exceeded page cap ${opts.pageCap} (refusing silent truncation)`, { opName: label });
|
|
167
|
+
}
|
|
168
|
+
return all;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=git-driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-driver.js","sourceRoot":"","sources":["../../src/platform/git-driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PluginManifest, PluginValidationError } from './types.js';
|
|
2
|
+
export declare function compareSemver(a: string, b: string): number;
|
|
3
|
+
export interface ManifestIdentity {
|
|
4
|
+
name?: string;
|
|
5
|
+
tool?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function parseManifest(raw: string, pluginPath: string): {
|
|
8
|
+
manifest: PluginManifest;
|
|
9
|
+
} | ({
|
|
10
|
+
errors: PluginValidationError[];
|
|
11
|
+
} & ManifestIdentity);
|
|
12
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/platform/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAKnE,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAS1D;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,GACjB;IAAE,QAAQ,EAAE,cAAc,CAAA;CAAE,GAAG,CAAC;IAAE,MAAM,EAAE,qBAAqB,EAAE,CAAA;CAAE,GAAG,gBAAgB,CAAC,CAoCzF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { isRecord, TOOL_PATTERN } from '../shared/index.js';
|
|
2
|
+
const SEMVER = /^(\d{1,10})\.(\d{1,10})\.(\d{1,10})$/;
|
|
3
|
+
export function compareSemver(a, b) {
|
|
4
|
+
const ma = SEMVER.exec(a);
|
|
5
|
+
const mb = SEMVER.exec(b);
|
|
6
|
+
if (!ma || !mb)
|
|
7
|
+
throw new Error(`invalid semver: ${!ma ? a : b}`);
|
|
8
|
+
for (let i = 1; i <= 3; i++) {
|
|
9
|
+
const d = Number(ma[i]) - Number(mb[i]);
|
|
10
|
+
if (d !== 0)
|
|
11
|
+
return d > 0 ? 1 : -1;
|
|
12
|
+
}
|
|
13
|
+
return 0;
|
|
14
|
+
}
|
|
15
|
+
export function parseManifest(raw, pluginPath) {
|
|
16
|
+
const errors = [];
|
|
17
|
+
const err = (message) => errors.push({ pluginPath, message });
|
|
18
|
+
let obj;
|
|
19
|
+
try {
|
|
20
|
+
obj = JSON.parse(raw);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
err(`baxian-plugin.json is not valid JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
24
|
+
return { errors };
|
|
25
|
+
}
|
|
26
|
+
if (!isRecord(obj)) {
|
|
27
|
+
err('baxian-plugin.json must be a JSON object');
|
|
28
|
+
return { errors };
|
|
29
|
+
}
|
|
30
|
+
const m = obj;
|
|
31
|
+
if (typeof m.name !== 'string' || m.name === '')
|
|
32
|
+
err('name must be a non-empty string');
|
|
33
|
+
// version 是插件元数据:spec §5.2 未声明格式契约、无消费者对其做 semver 比较(仅 minToolVersion 比较)——非空串即可,勿收成 semver。
|
|
34
|
+
if (typeof m.version !== 'string' || m.version.trim() === '')
|
|
35
|
+
err(`version must be a non-empty string (got ${JSON.stringify(m.version)})`);
|
|
36
|
+
if (m.kind !== 'git-driver')
|
|
37
|
+
err(`kind must be 'git-driver', got ${JSON.stringify(m.kind)}`);
|
|
38
|
+
if (typeof m.tool !== 'string' || !TOOL_PATTERN.test(m.tool)) {
|
|
39
|
+
err(`tool must match ${TOOL_PATTERN} (got ${JSON.stringify(m.tool)})`);
|
|
40
|
+
}
|
|
41
|
+
if (typeof m.minToolVersion !== 'string' || !SEMVER.test(m.minToolVersion)) {
|
|
42
|
+
err(`minToolVersion must be x.y.z semver (got ${JSON.stringify(m.minToolVersion)})`);
|
|
43
|
+
}
|
|
44
|
+
if (m.driverSchema !== 1)
|
|
45
|
+
err(`driverSchema must be 1 (got ${JSON.stringify(m.driverSchema)})`);
|
|
46
|
+
if (errors.length > 0) {
|
|
47
|
+
// schema 失败仍保留各自通过格式校验的 name/tool 作 best-effort 身份——
|
|
48
|
+
// startup 的同名覆盖下毒靠它识别「坏损覆盖」,丢弃会静默回退内置(spec §5.4)。
|
|
49
|
+
return {
|
|
50
|
+
errors,
|
|
51
|
+
name: typeof m.name === 'string' && m.name !== '' ? m.name : undefined,
|
|
52
|
+
tool: typeof m.tool === 'string' && TOOL_PATTERN.test(m.tool) ? m.tool : undefined,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return { manifest: m };
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/platform/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type NormalizedRow } from './row-schema.js';
|
|
2
|
+
export interface ReviewTokenMarker {
|
|
3
|
+
kind: 'pass' | 'fail';
|
|
4
|
+
anchorSha: string;
|
|
5
|
+
token: string;
|
|
6
|
+
}
|
|
7
|
+
export interface AckMarker {
|
|
8
|
+
sourceKey: string;
|
|
9
|
+
commentId: string;
|
|
10
|
+
bodyDigest: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function buildReviewTokenLine(m: ReviewTokenMarker): string;
|
|
13
|
+
export declare function extractReviewTokens(body: string): ReviewTokenMarker[];
|
|
14
|
+
export declare function buildAckMarker(m: AckMarker): string;
|
|
15
|
+
export declare function extractAckMarkers(body: string): AckMarker[];
|
|
16
|
+
export declare function stripBaxianMarkerLines(body: string): string;
|
|
17
|
+
export declare function projectCommentRow(row: NormalizedRow): void;
|
|
18
|
+
export declare function rowBodyDigest(row: NormalizedRow): string;
|
|
19
|
+
export declare function rowTokens(row: NormalizedRow): ReviewTokenMarker[];
|
|
20
|
+
export declare function rowAcks(row: NormalizedRow): AckMarker[];
|
|
21
|
+
export declare function rowHasBody(row: NormalizedRow): boolean;
|
|
22
|
+
export type CommentSourceClass = 'reviews' | 'threaded' | 'top-level';
|
|
23
|
+
export declare function classifyCommentSource(source: {
|
|
24
|
+
map?: Record<string, unknown>;
|
|
25
|
+
}): CommentSourceClass;
|
|
26
|
+
export interface AckActorContext {
|
|
27
|
+
replyActorId?: string;
|
|
28
|
+
replyActorStatus?: 'verified' | 'provisional';
|
|
29
|
+
}
|
|
30
|
+
export interface AckCarrierRow {
|
|
31
|
+
sourceKey: string;
|
|
32
|
+
sourceClass: CommentSourceClass;
|
|
33
|
+
id: string;
|
|
34
|
+
authorId?: string;
|
|
35
|
+
discussionId?: string | null;
|
|
36
|
+
acks: AckMarker[];
|
|
37
|
+
carriesToken: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface AckCollection {
|
|
40
|
+
acks: Set<string>;
|
|
41
|
+
carrierRowKeys: Set<string>;
|
|
42
|
+
}
|
|
43
|
+
export declare const ackRevisionKey: (sourceKey: string, id: string, digest: string) => string;
|
|
44
|
+
export declare const ackCarrierKey: (sourceKey: string, id: string) => string;
|
|
45
|
+
export declare function collectValidAcks(rows: AckCarrierRow[], ctx: AckActorContext): AckCollection;
|
|
46
|
+
//# sourceMappingURL=markers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../../src/platform/markers.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkC,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAeD,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAEjE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAMrE;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAEnD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAE3D;AAGD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK3D;AAOD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAU1D;AAOD,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAExD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,iBAAiB,EAAE,CAEjE;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,SAAS,EAAE,CAEvD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAEtD;AAED,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;AAItE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,kBAAkB,CAKnG;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC;CAC/C;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,kBAAkB,CAAC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC7B;AAGD,eAAO,MAAM,cAAc,GAAI,WAAW,MAAM,EAAE,IAAI,MAAM,EAAE,QAAQ,MAAM,WAAmC,CAAC;AAChH,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,EAAE,IAAI,MAAM,WAAyB,CAAC;AAQrF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,eAAe,GAAG,aAAa,CA0B3F"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// baxian 标记线协议(spec §6/§7/§8):verdict 令牌行与逐 revision ack 行的唯一定义,
|
|
2
|
+
// verdict engine / 事件过滤 / ack 完成集 / 展示剥离共用,防多处正则漂移。
|
|
3
|
+
import { BODY_DIGEST_SOURCE, bodyDigest } from './body-digest.js';
|
|
4
|
+
import { SHA_HEX_SOURCE, SOURCE_KEY_PATTERN } from './types.js';
|
|
5
|
+
import { LINE_SAFE_ID_RE, versionTimeOf } from './row-schema.js';
|
|
6
|
+
// 段文法取自各自的具名定义:装机校验放行的键/id/digest 形态与线协议能解析回来的
|
|
7
|
+
// 必须是同一形态——各自内联会在任一侧收放后静默失配(ack 永判无效、反馈重派循环)。
|
|
8
|
+
const unanchored = (re) => re.source.replace(/^\^/, '').replace(/\$$/, '');
|
|
9
|
+
const REVIEW_TOKEN_RE = new RegExp(`<!--\\s*baxian:review:(pass|fail):(${SHA_HEX_SOURCE}):([A-Za-z0-9_-]{6,64})\\s*-->`, 'g');
|
|
10
|
+
const ACK_RE = new RegExp(`<!--\\s*baxian:reply:ack:(${unanchored(SOURCE_KEY_PATTERN)}):(${unanchored(LINE_SAFE_ID_RE)}):(${BODY_DIGEST_SOURCE})\\s*-->`, 'g');
|
|
11
|
+
// (?:(?!-->).)* 禁止注释体内提前出现 -->:贪婪 .* 会从行首标记吞到行尾另一条注释,
|
|
12
|
+
// 把夹在中间的可见正文一并剥掉——只有「单条完整注释占满整行」才可剥。
|
|
13
|
+
const MARKER_ONLY_LINE_RE = /^<!--\s*baxian:(?:(?!-->).)*-->$/;
|
|
14
|
+
export function buildReviewTokenLine(m) {
|
|
15
|
+
return `<!-- baxian:review:${m.kind}:${m.anchorSha}:${m.token} -->`;
|
|
16
|
+
}
|
|
17
|
+
export function extractReviewTokens(body) {
|
|
18
|
+
return [...body.matchAll(REVIEW_TOKEN_RE)].map(m => ({
|
|
19
|
+
kind: m[1],
|
|
20
|
+
anchorSha: m[2].toLowerCase(),
|
|
21
|
+
token: m[3],
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
export function buildAckMarker(m) {
|
|
25
|
+
return `<!-- baxian:reply:ack:${m.sourceKey}:${m.commentId}:${m.bodyDigest} -->`;
|
|
26
|
+
}
|
|
27
|
+
export function extractAckMarkers(body) {
|
|
28
|
+
return [...body.matchAll(ACK_RE)].map(m => ({ sourceKey: m[1], commentId: m[2], bodyDigest: m[3] }));
|
|
29
|
+
}
|
|
30
|
+
// 仅剥「整行只有 baxian 标记」的行——verdict engine 恒读原文,此函数只服务展示/正文投影(v1 分离原则)。
|
|
31
|
+
export function stripBaxianMarkerLines(body) {
|
|
32
|
+
return body
|
|
33
|
+
.split('\n')
|
|
34
|
+
.filter(line => !MARKER_ONLY_LINE_RE.test(line.trim()))
|
|
35
|
+
.join('\n');
|
|
36
|
+
}
|
|
37
|
+
// 行投影(spec v1 §6 页内管线,v2 §5.3 继承):正文一次性折算成 digest/令牌/ack/非空标记后
|
|
38
|
+
// 原文即释放——分页聚合与 scans 跨源滞留的都是投影行,内存不随评论原文总量线性增长。
|
|
39
|
+
// 读取端一律走 rowXxx 助手:投影行取 stash、未投影行(测试直构)现算,单点防两套语义漂移。
|
|
40
|
+
const PROJECTED = Symbol('bodyProjected');
|
|
41
|
+
export function projectCommentRow(row) {
|
|
42
|
+
const body = typeof row.body === 'string' ? row.body : '';
|
|
43
|
+
const versionTime = versionTimeOf(row);
|
|
44
|
+
row.bodyDigest = bodyDigest(body);
|
|
45
|
+
row.bodyTokens = extractReviewTokens(body);
|
|
46
|
+
row.bodyAcks = extractAckMarkers(body);
|
|
47
|
+
row.hasBody = body !== '';
|
|
48
|
+
if (versionTime !== undefined)
|
|
49
|
+
row.versionTime = versionTime;
|
|
50
|
+
row[PROJECTED] = true;
|
|
51
|
+
delete row.body;
|
|
52
|
+
}
|
|
53
|
+
const isProjected = (row) => row[PROJECTED] === true;
|
|
54
|
+
const rawBody = (row) => (typeof row.body === 'string' ? row.body : '');
|
|
55
|
+
export function rowBodyDigest(row) {
|
|
56
|
+
return isProjected(row) ? row.bodyDigest : bodyDigest(rawBody(row));
|
|
57
|
+
}
|
|
58
|
+
export function rowTokens(row) {
|
|
59
|
+
return isProjected(row) ? row.bodyTokens : extractReviewTokens(rawBody(row));
|
|
60
|
+
}
|
|
61
|
+
export function rowAcks(row) {
|
|
62
|
+
return isProjected(row) ? row.bodyAcks : extractAckMarkers(rawBody(row));
|
|
63
|
+
}
|
|
64
|
+
export function rowHasBody(row) {
|
|
65
|
+
return isProjected(row) ? row.hasBody === true : rawBody(row) !== '';
|
|
66
|
+
}
|
|
67
|
+
// 载体类按声明结构推导而非 key 字面(用户插件的 key 集合任意,spec §6 矩阵须平台中立):
|
|
68
|
+
// 声明 reviewState 的源承载 native review(恒非 ack 载体),声明 discussionId 的源有线程结构。
|
|
69
|
+
export function classifyCommentSource(source) {
|
|
70
|
+
const map = source.map ?? {};
|
|
71
|
+
if ('reviewState' in map)
|
|
72
|
+
return 'reviews';
|
|
73
|
+
if ('discussionId' in map)
|
|
74
|
+
return 'threaded';
|
|
75
|
+
return 'top-level';
|
|
76
|
+
}
|
|
77
|
+
// 集合成员键的拼法与产出同居:消费侧手工重拼在键形变更时会静默 miss(已 ack 反馈重发)。
|
|
78
|
+
export const ackRevisionKey = (sourceKey, id, digest) => `${sourceKey}:${id}:${digest}`;
|
|
79
|
+
export const ackCarrierKey = (sourceKey, id) => `${sourceKey}:${id}`;
|
|
80
|
+
// ack 载体矩阵(spec §6 矩阵修订③④):唯一授权谓词 = verified 且 authorId 相等;
|
|
81
|
+
// reviews 类行与携令牌行恒非载体(同账号 confused-deputy 结构隔离);threaded 行可 ack
|
|
82
|
+
// **同一线程内任意成员**(根或回复 revision——poller 对 reply 行投递的 revision id 即行自身 id,
|
|
83
|
+
// 只认线程根会让合法 ack 永判无效并把 dev 回复再当新反馈);隶属以传入行集解析,
|
|
84
|
+
// 目标行不在集合内按 fail-closed 拒绝。行集可跨源(issue 类顶层 ack 可指向任意源),
|
|
85
|
+
// 载体键与隶属表一律 (sourceKey, id)——三源是不同对象表、数值 id 无跨表唯一性契约(spec §5.3 增量①)。
|
|
86
|
+
export function collectValidAcks(rows, ctx) {
|
|
87
|
+
const acks = new Set();
|
|
88
|
+
const carrierRowKeys = new Set();
|
|
89
|
+
if (ctx.replyActorStatus !== 'verified' || ctx.replyActorId === undefined)
|
|
90
|
+
return { acks, carrierRowKeys };
|
|
91
|
+
const threadRootById = new Map();
|
|
92
|
+
for (const row of rows) {
|
|
93
|
+
threadRootById.set(ackCarrierKey(row.sourceKey, row.id), row.discussionId ?? row.id);
|
|
94
|
+
}
|
|
95
|
+
for (const row of rows) {
|
|
96
|
+
if (row.authorId === undefined || row.authorId !== ctx.replyActorId)
|
|
97
|
+
continue;
|
|
98
|
+
if (row.sourceClass === 'reviews')
|
|
99
|
+
continue;
|
|
100
|
+
if (row.carriesToken)
|
|
101
|
+
continue;
|
|
102
|
+
if (row.sourceClass === 'threaded' && (row.discussionId === null || row.discussionId === undefined))
|
|
103
|
+
continue;
|
|
104
|
+
let carried = false;
|
|
105
|
+
for (const m of row.acks) {
|
|
106
|
+
if (row.sourceClass === 'threaded') {
|
|
107
|
+
if (m.sourceKey !== row.sourceKey)
|
|
108
|
+
continue;
|
|
109
|
+
const targetRoot = threadRootById.get(ackCarrierKey(m.sourceKey, m.commentId));
|
|
110
|
+
if (targetRoot === undefined || targetRoot !== row.discussionId)
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
acks.add(ackRevisionKey(m.sourceKey, m.commentId, m.bodyDigest));
|
|
114
|
+
carried = true;
|
|
115
|
+
}
|
|
116
|
+
if (carried)
|
|
117
|
+
carrierRowKeys.add(ackCarrierKey(row.sourceKey, row.id));
|
|
118
|
+
}
|
|
119
|
+
return { acks, carrierRowKeys };
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=markers.js.map
|