@vicfei/dsh-super-agent 0.5.1 → 0.6.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 +23 -1
- package/README.zh-CN.md +23 -2
- package/dist/cli.js +62 -11
- package/dist/cli.js.map +1 -1
- package/dist/domain.d.ts +21 -0
- package/dist/domain.js +13 -0
- package/dist/domain.js.map +1 -1
- package/dist/engine.d.ts +25 -0
- package/dist/engine.js +49 -0
- package/dist/engine.js.map +1 -1
- package/dist/executor.js +15 -8
- package/dist/executor.js.map +1 -1
- package/dist/github/app-auth.d.ts +33 -0
- package/dist/github/app-auth.js +102 -0
- package/dist/github/app-auth.js.map +1 -0
- package/dist/github/client.d.ts +44 -0
- package/dist/github/client.js +27 -2
- package/dist/github/client.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/merge.d.ts +28 -0
- package/dist/merge.js +129 -0
- package/dist/merge.js.map +1 -0
- package/dist/panel.d.ts +1 -0
- package/dist/panel.html +44 -0
- package/dist/panel.js +1 -0
- package/dist/panel.js.map +1 -1
- package/dist/usage.d.ts +2 -2
- package/dist/usage.js +7 -5
- package/dist/usage.js.map +1 -1
- package/dist/watch.js +5 -2
- package/dist/watch.js.map +1 -1
- package/dist/work.d.ts +10 -0
- package/dist/work.js +20 -2
- package/dist/work.js.map +1 -1
- package/examples/policy.json +7 -0
- package/package.json +3 -2
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// GitHub App auth (M6-2, issue #28) — installation access tokens without a runtime dependency:
|
|
2
|
+
// the RS256 JWT is signed with node:crypto, exchanged for a 1-hour installation token, cached
|
|
3
|
+
// with an expiry margin, and re-exchanged transparently. A PAT stays as fallback (client just
|
|
4
|
+
// gets a static token); replies posted with an App token carry the app[bot] identity, which the
|
|
5
|
+
// gate already caps at inferred strength and the self-echo filter never re-ingests.
|
|
6
|
+
//
|
|
7
|
+
// Credentials live in the environment only (repo discipline):
|
|
8
|
+
// GITHUB_APP_ID — the App's numeric id
|
|
9
|
+
// GITHUB_APP_PRIVATE_KEY — the PEM, \n-escaped inline (or GITHUB_APP_PRIVATE_KEY_PATH)
|
|
10
|
+
// GITHUB_APP_INSTALLATION_ID — optional; discovered from --repo when absent
|
|
11
|
+
import { createSign } from "node:crypto";
|
|
12
|
+
import { readFileSync } from "node:fs";
|
|
13
|
+
const EXPIRY_MARGIN_MS = 5 * 60 * 1000; // refresh a 60-minute token 5 minutes early
|
|
14
|
+
function b64url(input) {
|
|
15
|
+
return Buffer.from(input).toString("base64url");
|
|
16
|
+
}
|
|
17
|
+
/** RS256 JWT for the App — GitHub accepts a maximum 10-minute window (docs: /apps/creating). */
|
|
18
|
+
export function signAppJwt(appId, privateKeyPem, now = new Date()) {
|
|
19
|
+
const iat = Math.floor((now.getTime() - 60_000) / 1000); // 60s clock-skew allowance
|
|
20
|
+
const exp = iat + 180; // 3 minutes, well under the 10-minute cap
|
|
21
|
+
const header = b64url(JSON.stringify({ alg: "RS256", typ: "JWT" }));
|
|
22
|
+
const claims = b64url(JSON.stringify({ iat, exp, iss: appId }));
|
|
23
|
+
const signature = createSign("RSA-SHA256").update(`${header}.${claims}`).sign(privateKeyPem);
|
|
24
|
+
return `${header}.${claims}.${b64url(signature)}`;
|
|
25
|
+
}
|
|
26
|
+
export class AppTokenProvider {
|
|
27
|
+
opts;
|
|
28
|
+
cached = null;
|
|
29
|
+
installationId;
|
|
30
|
+
fetchImpl;
|
|
31
|
+
apiBase;
|
|
32
|
+
constructor(opts) {
|
|
33
|
+
this.opts = opts;
|
|
34
|
+
this.installationId = opts.installationId ?? null;
|
|
35
|
+
this.fetchImpl = opts.fetchImpl ?? fetch;
|
|
36
|
+
this.apiBase = opts.apiBase ?? "https://api.github.com";
|
|
37
|
+
}
|
|
38
|
+
/** Current token, exchanging/refreshing as needed. Throws with actionable messages. */
|
|
39
|
+
async get() {
|
|
40
|
+
if (this.cached && this.cached.expiresAt - EXPIRY_MARGIN_MS > Date.now())
|
|
41
|
+
return this.cached.token;
|
|
42
|
+
const installationId = await this.resolveInstallation();
|
|
43
|
+
const res = await this.fetchImpl(`${this.apiBase}/app/installations/${installationId}/access_tokens`, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers: {
|
|
46
|
+
accept: "application/vnd.github+json",
|
|
47
|
+
authorization: `Bearer ${signAppJwt(this.opts.appId, this.opts.privateKeyPem)}`,
|
|
48
|
+
"x-github-api-version": "2022-11-28",
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
if (!res.ok) {
|
|
52
|
+
const text = await res.text().catch(() => "");
|
|
53
|
+
throw new Error(`GitHub App token exchange failed (${res.status}): ${text.slice(0, 200)} — check GITHUB_APP_ID and the private key`);
|
|
54
|
+
}
|
|
55
|
+
const data = (await res.json());
|
|
56
|
+
this.cached = { token: data.token, expiresAt: Date.parse(data.expires_at) };
|
|
57
|
+
return data.token;
|
|
58
|
+
}
|
|
59
|
+
/** Client 401 hook — drop the cached token so the retry exchanges a fresh one. */
|
|
60
|
+
onAuthFailure() {
|
|
61
|
+
this.cached = null;
|
|
62
|
+
}
|
|
63
|
+
async resolveInstallation() {
|
|
64
|
+
if (this.installationId !== null)
|
|
65
|
+
return this.installationId;
|
|
66
|
+
if (!this.opts.repo) {
|
|
67
|
+
throw new Error("GitHub App auth needs GITHUB_APP_INSTALLATION_ID (or a --repo to discover it from)");
|
|
68
|
+
}
|
|
69
|
+
const res = await this.fetchImpl(`${this.apiBase}/repos/${this.opts.repo}/installation`, {
|
|
70
|
+
headers: {
|
|
71
|
+
accept: "application/vnd.github+json",
|
|
72
|
+
authorization: `Bearer ${signAppJwt(this.opts.appId, this.opts.privateKeyPem)}`,
|
|
73
|
+
"x-github-api-version": "2022-11-28",
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
if (!res.ok) {
|
|
77
|
+
const text = await res.text().catch(() => "");
|
|
78
|
+
throw new Error(`cannot find an installation of this App on ${this.opts.repo} (${res.status}): ${text.slice(0, 200)} — is the App installed on the repo?`);
|
|
79
|
+
}
|
|
80
|
+
const data = (await res.json());
|
|
81
|
+
this.installationId = data.id;
|
|
82
|
+
return data.id;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Read App credentials from the environment. Null when not configured (PAT/anonymous path). */
|
|
86
|
+
export function appAuthFromEnv(env = process.env) {
|
|
87
|
+
const appId = env.GITHUB_APP_ID;
|
|
88
|
+
const inlineKey = env.GITHUB_APP_PRIVATE_KEY;
|
|
89
|
+
const keyPath = env.GITHUB_APP_PRIVATE_KEY_PATH;
|
|
90
|
+
if (!appId)
|
|
91
|
+
return null;
|
|
92
|
+
const key = inlineKey ? inlineKey.replace(/\\n/g, "\n") : keyPath ? readFileSync(keyPath, "utf8") : undefined;
|
|
93
|
+
if (!key || !key.includes("PRIVATE KEY")) {
|
|
94
|
+
throw new Error("GITHUB_APP_ID is set but no private key — set GITHUB_APP_PRIVATE_KEY (\\n-escaped PEM) or GITHUB_APP_PRIVATE_KEY_PATH");
|
|
95
|
+
}
|
|
96
|
+
const installationId = env.GITHUB_APP_INSTALLATION_ID ? Number(env.GITHUB_APP_INSTALLATION_ID) : undefined;
|
|
97
|
+
if (installationId !== undefined && !Number.isFinite(installationId)) {
|
|
98
|
+
throw new Error("GITHUB_APP_INSTALLATION_ID must be a number");
|
|
99
|
+
}
|
|
100
|
+
return { appId, privateKeyPem: key, ...(installationId !== undefined ? { installationId } : {}) };
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=app-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-auth.js","sourceRoot":"","sources":["../../src/github/app-auth.ts"],"names":[],"mappings":"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"}
|
package/dist/github/client.d.ts
CHANGED
|
@@ -22,20 +22,53 @@ export interface GhPull extends GhItemBase {
|
|
|
22
22
|
number: number;
|
|
23
23
|
title: string | null;
|
|
24
24
|
}
|
|
25
|
+
/** Full pull detail for the merge gate (GET /repos/:o/:r/pulls/:n). */
|
|
26
|
+
export interface GhPullDetail {
|
|
27
|
+
number: number;
|
|
28
|
+
state: "open" | "closed";
|
|
29
|
+
draft: boolean;
|
|
30
|
+
merged: boolean;
|
|
31
|
+
/** null while GitHub has not computed mergeability — treat as "not yet", fail-closed. */
|
|
32
|
+
mergeable: boolean | null;
|
|
33
|
+
head: {
|
|
34
|
+
ref: string;
|
|
35
|
+
sha: string;
|
|
36
|
+
};
|
|
37
|
+
additions: number;
|
|
38
|
+
deletions: number;
|
|
39
|
+
}
|
|
40
|
+
export interface GhReview {
|
|
41
|
+
id: number;
|
|
42
|
+
user: GhActor | null;
|
|
43
|
+
/** APPROVED | CHANGES_REQUESTED | COMMENTED | PENDING | DISMISSED — a reviewer's latest non-comment stance is their effective one. */
|
|
44
|
+
state: string;
|
|
45
|
+
commit_id: string;
|
|
46
|
+
submitted_at: string;
|
|
47
|
+
}
|
|
25
48
|
export interface GhReviewComment extends GhItemBase {
|
|
26
49
|
/** api url of the parent pull. */
|
|
27
50
|
pull_request_url: string;
|
|
28
51
|
in_reply_to_id?: number;
|
|
29
52
|
}
|
|
53
|
+
/** Mutable credential source (App installation tokens): fetched per request, invalidated on 401. */
|
|
54
|
+
export interface TokenProvider {
|
|
55
|
+
get(): Promise<string>;
|
|
56
|
+
/** The client calls this when a request got 401 — drop cached state before the single retry. */
|
|
57
|
+
onAuthFailure(): void;
|
|
58
|
+
}
|
|
30
59
|
export declare class GitHubClient {
|
|
31
60
|
private readonly fetchImpl;
|
|
32
61
|
private readonly apiBase;
|
|
33
62
|
constructor(opts?: {
|
|
34
63
|
token?: string;
|
|
64
|
+
tokenProvider?: TokenProvider;
|
|
35
65
|
fetchImpl?: typeof fetch;
|
|
36
66
|
apiBase?: string;
|
|
37
67
|
});
|
|
38
68
|
private readonly token;
|
|
69
|
+
private readonly tokenProvider;
|
|
70
|
+
/** The credential actually in use — PAT, installation token, or undefined (anonymous). */
|
|
71
|
+
currentToken(): Promise<string | undefined>;
|
|
39
72
|
private request;
|
|
40
73
|
/** Newest-first single page. Filtering by read position happens in the Source. */
|
|
41
74
|
private list;
|
|
@@ -59,5 +92,16 @@ export declare class GitHubClient {
|
|
|
59
92
|
number: number;
|
|
60
93
|
html_url: string;
|
|
61
94
|
}>;
|
|
95
|
+
getPull(repo: string, number: number): Promise<GhPullDetail>;
|
|
96
|
+
listReviews(repo: string, number: number): Promise<GhReview[]>;
|
|
97
|
+
/** SHA-pinned merge: if the head moved since evaluation, GitHub rejects — we never merge unreviewed bytes. */
|
|
98
|
+
mergePullRequest(repo: string, number: number, opts: {
|
|
99
|
+
sha: string;
|
|
100
|
+
merge_method: "squash" | "merge" | "rebase";
|
|
101
|
+
}): Promise<{
|
|
102
|
+
merged: boolean;
|
|
103
|
+
sha?: string;
|
|
104
|
+
}>;
|
|
105
|
+
deleteBranch(repo: string, branch: string): Promise<unknown>;
|
|
62
106
|
}
|
|
63
107
|
export {};
|
package/dist/github/client.js
CHANGED
|
@@ -7,19 +7,31 @@ export class GitHubClient {
|
|
|
7
7
|
this.fetchImpl = opts.fetchImpl ?? fetch;
|
|
8
8
|
this.apiBase = opts.apiBase ?? "https://api.github.com";
|
|
9
9
|
this.token = opts.token ?? "";
|
|
10
|
+
this.tokenProvider = opts.tokenProvider ?? null;
|
|
10
11
|
}
|
|
11
12
|
token;
|
|
12
|
-
|
|
13
|
+
tokenProvider;
|
|
14
|
+
/** The credential actually in use — PAT, installation token, or undefined (anonymous). */
|
|
15
|
+
async currentToken() {
|
|
16
|
+
return this.tokenProvider ? this.tokenProvider.get() : this.token || undefined;
|
|
17
|
+
}
|
|
18
|
+
async request(method, path, body, retry = true) {
|
|
19
|
+
const token = this.tokenProvider ? await this.tokenProvider.get() : this.token;
|
|
13
20
|
const res = await this.fetchImpl(`${this.apiBase}${path}`, {
|
|
14
21
|
method,
|
|
15
22
|
headers: {
|
|
16
23
|
accept: "application/vnd.github+json",
|
|
17
24
|
"x-github-api-version": "2022-11-28",
|
|
18
|
-
...(
|
|
25
|
+
...(token ? { authorization: `Bearer ${token}` } : {}),
|
|
19
26
|
...(body !== undefined ? { "content-type": "application/json" } : {}),
|
|
20
27
|
},
|
|
21
28
|
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
22
29
|
});
|
|
30
|
+
if (res.status === 401 && retry && this.tokenProvider) {
|
|
31
|
+
// A cached installation token expired mid-cycle: drop it and try exactly once more.
|
|
32
|
+
this.tokenProvider.onAuthFailure();
|
|
33
|
+
return this.request(method, path, body, false);
|
|
34
|
+
}
|
|
23
35
|
if (!res.ok) {
|
|
24
36
|
const text = await res.text().catch(() => "");
|
|
25
37
|
// The three failures a fresh install hits; the raw body alone is cryptic (M5-5).
|
|
@@ -67,5 +79,18 @@ export class GitHubClient {
|
|
|
67
79
|
createPullRequest(repo, pr) {
|
|
68
80
|
return this.request("POST", `/repos/${repo}/pulls`, pr);
|
|
69
81
|
}
|
|
82
|
+
getPull(repo, number) {
|
|
83
|
+
return this.request("GET", `/repos/${repo}/pulls/${number}`);
|
|
84
|
+
}
|
|
85
|
+
listReviews(repo, number) {
|
|
86
|
+
return this.request("GET", `/repos/${repo}/pulls/${number}/reviews`);
|
|
87
|
+
}
|
|
88
|
+
/** SHA-pinned merge: if the head moved since evaluation, GitHub rejects — we never merge unreviewed bytes. */
|
|
89
|
+
mergePullRequest(repo, number, opts) {
|
|
90
|
+
return this.request("PUT", `/repos/${repo}/pulls/${number}/merge`, opts);
|
|
91
|
+
}
|
|
92
|
+
deleteBranch(repo, branch) {
|
|
93
|
+
return this.request("DELETE", `/repos/${repo}/git/refs/heads/${branch}`);
|
|
94
|
+
}
|
|
70
95
|
}
|
|
71
96
|
//# sourceMappingURL=client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/github/client.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,0FAA0F;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/github/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
export * from "./domain.js";
|
|
2
2
|
export { evaluateGate, resolveCandidate, type GateResult, type Resolution, type Assessment } from "./gate.js";
|
|
3
3
|
export { Engine, type IngestItem, type TicketView, type DecisionView, type IngestReport } from "./engine.js";
|
|
4
|
-
export { GitHubClient } from "./github/client.js";
|
|
4
|
+
export { GitHubClient, type TokenProvider } from "./github/client.js";
|
|
5
|
+
export { AppTokenProvider, appAuthFromEnv, signAppJwt, type AppAuthEnv, type AppAuthOptions } from "./github/app-auth.js";
|
|
5
6
|
export { GitHubSource, isBotActor } from "./github/source.js";
|
|
6
7
|
export { FileSourceState, type StateStore, type SourceState } from "./github/state.js";
|
|
7
8
|
export { Executor, renderPrompt, type ExecutorConfig, type ExecutorResult } from "./executor.js";
|
|
8
9
|
export { runWork, deliverPullRequest, type WorkReport } from "./work.js";
|
|
9
10
|
export { runWatch, type WatchOptions } from "./watch.js";
|
|
11
|
+
export { evaluateMerge, runMergeSweep, type MergeCheck, type MergeSweepLine } from "./merge.js";
|
|
10
12
|
export { classify, formatOutcome, type PollOutcome } from "./runner.js";
|
|
11
13
|
export { llmAssessor, stubAssessor, type Assessor } from "./assess.js";
|
|
12
14
|
export { clipReply, wordCount } from "./clip.js";
|
package/dist/index.js
CHANGED
|
@@ -4,11 +4,13 @@ export * from "./domain.js";
|
|
|
4
4
|
export { evaluateGate, resolveCandidate } from "./gate.js";
|
|
5
5
|
export { Engine } from "./engine.js";
|
|
6
6
|
export { GitHubClient } from "./github/client.js";
|
|
7
|
+
export { AppTokenProvider, appAuthFromEnv, signAppJwt } from "./github/app-auth.js";
|
|
7
8
|
export { GitHubSource, isBotActor } from "./github/source.js";
|
|
8
9
|
export { FileSourceState } from "./github/state.js";
|
|
9
10
|
export { Executor, renderPrompt } from "./executor.js";
|
|
10
11
|
export { runWork, deliverPullRequest } from "./work.js";
|
|
11
12
|
export { runWatch } from "./watch.js";
|
|
13
|
+
export { evaluateMerge, runMergeSweep } from "./merge.js";
|
|
12
14
|
export { classify, formatOutcome } from "./runner.js";
|
|
13
15
|
export { llmAssessor, stubAssessor } from "./assess.js";
|
|
14
16
|
export { clipReply, wordCount } from "./clip.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,iFAAiF;AAEjF,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAqD,MAAM,WAAW,CAAC;AAC9G,OAAO,EAAE,MAAM,EAA0E,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,iFAAiF;AAEjF,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAqD,MAAM,WAAW,CAAC;AAC9G,OAAO,EAAE,MAAM,EAA0E,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAE,YAAY,EAAsB,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAwC,MAAM,sBAAsB,CAAC;AAC1H,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAqC,MAAM,mBAAmB,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAE,YAAY,EAA4C,MAAM,eAAe,CAAC;AACjG,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAmB,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAqB,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAwC,MAAM,YAAY,CAAC;AAChG,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAoB,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAiB,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/merge.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { MergePolicy, Policy } from "./domain.js";
|
|
2
|
+
import type { Engine } from "./engine.js";
|
|
3
|
+
import type { GitHubClient, GhPullDetail, GhReview } from "./github/client.js";
|
|
4
|
+
export interface MergeCheck {
|
|
5
|
+
ok: boolean;
|
|
6
|
+
reasons: string[];
|
|
7
|
+
/** Set when ok: the allowed-list reviewer whose approval covers the head. */
|
|
8
|
+
approvedBy?: string;
|
|
9
|
+
changedLines: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Pure evaluation (unit-tested like the gate): would this PR merge under this policy?
|
|
13
|
+
* Structural first (draft / conflict / branch / size), then review stances — a reviewer's
|
|
14
|
+
* latest APPROVED | CHANGES_REQUESTED | DISMISSED review is their effective stance
|
|
15
|
+
* (COMMENTED/PENDING don't move it; a dismissal clears it).
|
|
16
|
+
*/
|
|
17
|
+
export declare function evaluateMerge(pr: GhPullDetail, reviews: GhReview[], policy: MergePolicy, allowedList: string[]): MergeCheck;
|
|
18
|
+
export interface MergeSweepLine {
|
|
19
|
+
pr: number;
|
|
20
|
+
action: "merged" | "waiting" | "closed" | "already-merged";
|
|
21
|
+
reasons?: string[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Idempotent sweep over our open deliveries: sync PRs closed on GitHub, evaluate the rest,
|
|
25
|
+
* merge only zero-reason PRs, post a clipped merge reply through the outbox, prune the branch.
|
|
26
|
+
* Per-delivery errors degrade to "waiting" — the next cycle retries (fail-closed).
|
|
27
|
+
*/
|
|
28
|
+
export declare function runMergeSweep(engine: Engine, client: GitHubClient, repo: string, policy: Policy, log?: (l: string) => void): Promise<MergeSweepLine[]>;
|
package/dist/merge.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// Auto-merge with delivery requirements (docs/ROADMAP M6-1) — the structural brakes:
|
|
2
|
+
// every merge condition is a checkable fact about the PR, never model judgment. Fail-closed:
|
|
3
|
+
// any miss is a recorded reason, ok requires zero reasons, and the merge PUT is pinned to the
|
|
4
|
+
// exact SHA that was approved — if the head moved, GitHub rejects and the next cycle re-evaluates.
|
|
5
|
+
import { clipReply } from "./clip.js";
|
|
6
|
+
import { mergePolicyOf } from "./domain.js";
|
|
7
|
+
import { drainReplyEffects } from "./work.js";
|
|
8
|
+
const TICKET_BRANCH = /^dsh\/ticket-\d+$/;
|
|
9
|
+
function isBotReview(r) {
|
|
10
|
+
return !r.user || r.user.type === "Bot" || r.user.login.endsWith("[bot]");
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Pure evaluation (unit-tested like the gate): would this PR merge under this policy?
|
|
14
|
+
* Structural first (draft / conflict / branch / size), then review stances — a reviewer's
|
|
15
|
+
* latest APPROVED | CHANGES_REQUESTED | DISMISSED review is their effective stance
|
|
16
|
+
* (COMMENTED/PENDING don't move it; a dismissal clears it).
|
|
17
|
+
*/
|
|
18
|
+
export function evaluateMerge(pr, reviews, policy, allowedList) {
|
|
19
|
+
const reasons = [];
|
|
20
|
+
const changedLines = pr.additions + pr.deletions;
|
|
21
|
+
let approvedBy;
|
|
22
|
+
if (pr.merged)
|
|
23
|
+
reasons.push("already merged");
|
|
24
|
+
if (pr.draft)
|
|
25
|
+
reasons.push("draft PR");
|
|
26
|
+
if (pr.mergeable === false)
|
|
27
|
+
reasons.push("merge conflict");
|
|
28
|
+
else if (pr.mergeable === null)
|
|
29
|
+
reasons.push("mergeability not computed yet");
|
|
30
|
+
if (!TICKET_BRANCH.test(pr.head.ref))
|
|
31
|
+
reasons.push(`not a ticket branch: ${pr.head.ref}`);
|
|
32
|
+
if (changedLines > policy.maxChangedLines)
|
|
33
|
+
reasons.push(`±${changedLines} lines > cap ${policy.maxChangedLines}`);
|
|
34
|
+
if (reasons.length === 0) {
|
|
35
|
+
const allowed = new Set(allowedList.map((s) => s.toLowerCase()));
|
|
36
|
+
const stance = new Map();
|
|
37
|
+
for (const r of reviews) {
|
|
38
|
+
if (isBotReview(r))
|
|
39
|
+
continue; // bots have no standing — neither approve nor veto
|
|
40
|
+
const login = r.user.login;
|
|
41
|
+
if (!allowed.has(login.toLowerCase()))
|
|
42
|
+
continue; // only allowed-list reviewers count
|
|
43
|
+
if (r.state !== "APPROVED" && r.state !== "CHANGES_REQUESTED" && r.state !== "DISMISSED")
|
|
44
|
+
continue;
|
|
45
|
+
const prev = stance.get(login);
|
|
46
|
+
if (!prev || r.submitted_at > prev.at || (r.submitted_at === prev.at && r.id > prev.id)) {
|
|
47
|
+
stance.set(login, { state: r.state, commitId: r.commit_id, at: r.submitted_at, id: r.id });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
let hasApproval = false;
|
|
51
|
+
let hasCoveringApproval = false;
|
|
52
|
+
for (const [login, s] of stance) {
|
|
53
|
+
if (s.state === "CHANGES_REQUESTED")
|
|
54
|
+
reasons.push(`changes requested by @${login} — blocks until re-reviewed`);
|
|
55
|
+
if (s.state === "APPROVED") {
|
|
56
|
+
hasApproval = true;
|
|
57
|
+
if (!policy.requireApprovalCoveringHead || s.commitId === pr.head.sha) {
|
|
58
|
+
hasCoveringApproval = true;
|
|
59
|
+
approvedBy = login;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!hasApproval)
|
|
64
|
+
reasons.push("no approving review from an allowed-list member");
|
|
65
|
+
else if (!hasCoveringApproval)
|
|
66
|
+
reasons.push(`no approval covers head ${pr.head.sha.slice(0, 7)} — stale approvals do not count`);
|
|
67
|
+
}
|
|
68
|
+
return { ok: reasons.length === 0, reasons, ...(approvedBy ? { approvedBy } : {}), changedLines };
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Idempotent sweep over our open deliveries: sync PRs closed on GitHub, evaluate the rest,
|
|
72
|
+
* merge only zero-reason PRs, post a clipped merge reply through the outbox, prune the branch.
|
|
73
|
+
* Per-delivery errors degrade to "waiting" — the next cycle retries (fail-closed).
|
|
74
|
+
*/
|
|
75
|
+
export async function runMergeSweep(engine, client, repo, policy, log = () => { }) {
|
|
76
|
+
const merge = mergePolicyOf(policy);
|
|
77
|
+
if (!merge.enabled)
|
|
78
|
+
return [];
|
|
79
|
+
const out = [];
|
|
80
|
+
for (const d of engine.openDeliveries(repo)) {
|
|
81
|
+
try {
|
|
82
|
+
const pr = await client.getPull(repo, d.prNumber);
|
|
83
|
+
if (pr.state === "closed") {
|
|
84
|
+
engine.finishDelivery(d.id, pr.merged ? "merged" : "closed");
|
|
85
|
+
out.push({ pr: d.prNumber, action: pr.merged ? "merged" : "closed" });
|
|
86
|
+
log(`#${d.prNumber} ${pr.merged ? "merged" : "closed"} on GitHub — delivery synced`);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (pr.merged) {
|
|
90
|
+
engine.finishDelivery(d.id, "merged");
|
|
91
|
+
out.push({ pr: d.prNumber, action: "already-merged" });
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const reviews = await client.listReviews(repo, d.prNumber);
|
|
95
|
+
const check = evaluateMerge(pr, reviews, merge, policy.allowedList);
|
|
96
|
+
if (!check.ok) {
|
|
97
|
+
out.push({ pr: d.prNumber, action: "waiting", reasons: check.reasons });
|
|
98
|
+
log(`#${d.prNumber} holds: ${check.reasons.join("; ")}`);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const m = await client.mergePullRequest(repo, pr.number, { sha: pr.head.sha, merge_method: merge.method });
|
|
102
|
+
if (!m.merged) {
|
|
103
|
+
out.push({ pr: d.prNumber, action: "waiting", reasons: ["merge API declined (head moved?) — will re-evaluate"] });
|
|
104
|
+
log(`#${d.prNumber} merge declined — re-evaluating next cycle`);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
engine.enqueueReply(`merge-report:${d.prNumber}`, d.threadId, clipReply(`PR #${pr.number} merged (${merge.method}) — approved by @${check.approvedBy} covering ${pr.head.sha.slice(0, 7)} · ±${check.changedLines} lines. This is by an automated agent, not a human.`, 150));
|
|
108
|
+
engine.finishDelivery(d.id, "merged");
|
|
109
|
+
if (merge.deleteBranch) {
|
|
110
|
+
try {
|
|
111
|
+
await client.deleteBranch(repo, d.branch);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
log(`#${d.prNumber} branch ${d.branch} not deleted (best effort)`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
out.push({ pr: d.prNumber, action: "merged" });
|
|
118
|
+
log(`#${d.prNumber} merged (${merge.method}) — approved by @${check.approvedBy}`);
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
out.push({ pr: d.prNumber, action: "waiting", reasons: [e instanceof Error ? e.message : String(e)] });
|
|
122
|
+
log(`#${d.prNumber} sweep error: ${e instanceof Error ? e.message : e}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (out.length > 0)
|
|
126
|
+
await drainReplyEffects(engine, client, repo);
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"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"}
|
package/dist/panel.d.ts
CHANGED
|
@@ -4,5 +4,6 @@ export interface PanelState {
|
|
|
4
4
|
policy: ReturnType<Engine["policy"]>;
|
|
5
5
|
tickets: ReturnType<Engine["tickets"]>;
|
|
6
6
|
decisions: ReturnType<Engine["decisions"]>;
|
|
7
|
+
deliveries: ReturnType<Engine["deliveries"]>;
|
|
7
8
|
}
|
|
8
9
|
export declare function startPanel(engine: Engine, port: number, host?: string): Promise<Server>;
|
package/dist/panel.html
CHANGED
|
@@ -50,6 +50,12 @@
|
|
|
50
50
|
<h2>Awaiting a human</h2>
|
|
51
51
|
<div id="awaiting"></div>
|
|
52
52
|
|
|
53
|
+
<h2>By person</h2>
|
|
54
|
+
<div id="persons"></div>
|
|
55
|
+
|
|
56
|
+
<h2>Pull requests</h2>
|
|
57
|
+
<div id="deliveries"></div>
|
|
58
|
+
|
|
53
59
|
<h2>Observe records — would accept</h2>
|
|
54
60
|
<div id="shadows"></div>
|
|
55
61
|
|
|
@@ -89,6 +95,44 @@ async function render() {
|
|
|
89
95
|
+ revoked.map(t => `<div class="card"><span class="badge b-ignore">revoked</span>
|
|
90
96
|
ticket #${t.id} — ${esc(t.revokedReason)}</div>`).join('');
|
|
91
97
|
|
|
98
|
+
// By person (M6-3): the opener is who the work is *for* — one card per person with their
|
|
99
|
+
// stage counts and where their delivered PRs stand.
|
|
100
|
+
const openerOf = new Map(s.tickets.map(t => [t.id, t.opener]));
|
|
101
|
+
const persons = new Map();
|
|
102
|
+
for (const t of s.tickets) {
|
|
103
|
+
const p = persons.get(t.opener) ?? { tickets: [], deliveries: [] };
|
|
104
|
+
p.tickets.push(t);
|
|
105
|
+
persons.set(t.opener, p);
|
|
106
|
+
}
|
|
107
|
+
for (const d of s.deliveries || []) {
|
|
108
|
+
const who = openerOf.get(d.ticketId) ?? '(unknown opener)';
|
|
109
|
+
const p = persons.get(who) ?? { tickets: [], deliveries: [] };
|
|
110
|
+
p.deliveries.push(d);
|
|
111
|
+
persons.set(who, p);
|
|
112
|
+
}
|
|
113
|
+
document.getElementById('persons').innerHTML = persons.size === 0
|
|
114
|
+
? '<div class="quiet">no tickets yet</div>'
|
|
115
|
+
: [...persons.entries()].map(([who, p]) => {
|
|
116
|
+
const counts = ['queued', 'working', 'needs-person', 'ended']
|
|
117
|
+
.map(st => p.tickets.filter(t => t.stage === st).length)
|
|
118
|
+
.map((n, i) => n > 0 ? `<span class="quiet">${['queued','working','needs-person','ended'][i]}:${n}</span>` : '')
|
|
119
|
+
.filter(Boolean).join(' · ');
|
|
120
|
+
const dels = p.deliveries.map(d => `PR #${d.prNumber} ${d.state}`).join(' · ');
|
|
121
|
+
return `<div class="card"><b>${esc(who)}</b> — ${counts || 'no open work'}${dels ? `<div class="quiet">${dels}</div>` : ''}</div>`;
|
|
122
|
+
}).join('');
|
|
123
|
+
|
|
124
|
+
const deliveries = s.deliveries || [];
|
|
125
|
+
const mergeOn = !!(s.policy && s.policy.merge && s.policy.merge.enabled);
|
|
126
|
+
document.getElementById('deliveries').innerHTML = deliveries.length === 0
|
|
127
|
+
? '<div class="quiet">no pull requests opened</div>'
|
|
128
|
+
: deliveries.map(d => {
|
|
129
|
+
const cls = d.state === 'merged' ? 'b-accept' : d.state === 'closed' ? 'b-ignore' : 'b-shadow';
|
|
130
|
+
const note = d.state === 'open' ? (mergeOn ? 'awaiting merge requirements' : 'auto-merge off (policy.merge)') : '';
|
|
131
|
+
return `<div class="card"><span class="badge ${cls}">${d.state}</span>
|
|
132
|
+
PR #${esc(d.prNumber)} ${esc(d.branch)} · ticket #${d.ticketId}
|
|
133
|
+
<span class="quiet">${esc(note)}</span></div>`;
|
|
134
|
+
}).join('');
|
|
135
|
+
|
|
92
136
|
const shadows = s.decisions.filter(d => d.wouldAccept);
|
|
93
137
|
document.getElementById('shadows').innerHTML = shadows.length === 0
|
|
94
138
|
? '<div class="quiet">no shadow records</div>'
|
package/dist/panel.js
CHANGED
|
@@ -19,6 +19,7 @@ export function startPanel(engine, port, host = "127.0.0.1") {
|
|
|
19
19
|
policy: engine.policy(),
|
|
20
20
|
tickets: engine.tickets(),
|
|
21
21
|
decisions: engine.decisions(50),
|
|
22
|
+
deliveries: engine.deliveries(30),
|
|
22
23
|
};
|
|
23
24
|
send(200, "application/json", JSON.stringify(state));
|
|
24
25
|
return;
|
package/dist/panel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panel.js","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,wFAAwF;AAExF,OAAO,EAAE,YAAY,EAAe,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAIvC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"panel.js","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,wFAAwF;AAExF,OAAO,EAAE,YAAY,EAAe,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAIvC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AAS5E,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,IAAY,EAAE,IAAI,GAAG,WAAW;IACzE,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACvC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,cAAc,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,CAAC,MAAc,EAAE,IAAY,EAAE,IAAY,EAAE,EAAE;YAC1D,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,CAAC,CAAC;YAC7E,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC;QAEF,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;YACjD,IAAI,CAAC,GAAG,EAAE,0BAA0B,EAAE,IAAI,CAAC,CAAC;YAC5C,OAAO;QACT,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC1D,MAAM,KAAK,GAAe;gBACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;gBACvB,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE;gBACzB,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC/B,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;aAClC,CAAC;YACF,IAAI,CAAC,GAAG,EAAE,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YACrD,OAAO;QACT,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,CAAC,EAAE,CAAC;YAC5F,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;YACnC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAmC,CAAC;oBAC1E,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;wBACjC,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;4BACjF,IAAI,CAAC,GAAG,EAAE,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC,CAAC,CAAC;4BAC1F,OAAO;wBACT,CAAC;wBACD,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;wBAC/C,IAAI,CAAC,GAAG,EAAE,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;wBAChE,OAAO;oBACT,CAAC;oBACD,MAAM,EAAE,GAAG,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;oBACzF,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC5E,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,IAAI,CAAC,GAAG,EAAE,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBACvG,CAAC;YACH,CAAC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACpF,CAAC"}
|
package/dist/usage.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export declare const USAGE = "dsh-super-agent \u2014 admission control, observe mode & tickets for any CLI coding agent\n\nUsage: dsh-super-agent <command> [options]\n\nCommands:\n poll one pass: poll GitHub \u2192 gate \u2192 (assessment) \u2192 record; --post also drains queued replies\n work claim queued tickets \u2192 run the executor in a worktree \u2192 report\n watch poll + work + panel as one daemon (Ctrl-C stops after the current cycle)\n tickets list tickets; \"tickets stop <id>\" ends one\n panel serve the awaiting-human panel (http://127.0.0.1:8787)\n help show this usage\n\nCommon options:\n --repo owner/name repository to watch\n --agent-login <login> the agent's GitHub login (mention detection)\n --config <file> policy config (default policy.json, auto-scaffolded from examples/)\n --executor-config <file> executor config (default executor.json, auto-scaffolded from examples/)\n --db <file> state database (default .state/engine.db)\n --token <token> GitHub token (or env GITHUB_TOKEN)\n --assessment <mode> stub-positive | stub-negative | llm\n --interval <seconds> watch poll interval (\u00B120% jitter)\n --no-panel watch without the panel server\n --post poll also posts queued replies (needs a token)\n\nEnvironment: GITHUB_TOKEN, ASSESS_BASE_URL, ASSESS_MODEL, ASSESS_API_KEY, PANEL_PORT.\nDocs: https://github.com/vicfei/dsh-super-agent#quick-start";
|
|
1
|
+
export declare const USAGE = "dsh-super-agent \u2014 admission control, observe mode & tickets for any CLI coding agent\n\nUsage: dsh-super-agent <command> [options]\n\nCommands:\n poll one pass: poll GitHub \u2192 gate \u2192 (assessment) \u2192 record; --post also drains queued replies\n work claim queued tickets \u2192 run the executor in a worktree \u2192 report\n watch poll + work + panel as one daemon (Ctrl-C stops after the current cycle)\n tickets list tickets; \"tickets stop <id>\" ends one\n panel serve the awaiting-human panel (http://127.0.0.1:8787)\n merge sweep open ticket PRs \u2014 merge those meeting policy.merge requirements (default off)\n help show this usage\n\nCommon options:\n --repo owner/name repository to watch\n --agent-login <login> the agent's GitHub login (mention detection)\n --config <file> policy config (default policy.json, auto-scaffolded from examples/)\n --executor-config <file> executor config (default executor.json, auto-scaffolded from examples/)\n --db <file> state database (default .state/engine.db)\n --token <token> GitHub token (or env GITHUB_TOKEN)\n --assessment <mode> stub-positive | stub-negative | llm\n --interval <seconds> watch poll interval (\u00B120% jitter)\n --no-panel watch without the panel server\n --post poll also posts queued replies (needs a token)\n\nEnvironment: GITHUB_TOKEN, or GitHub App auth (GITHUB_APP_ID + GITHUB_APP_PRIVATE_KEY[_PATH],\noptional GITHUB_APP_INSTALLATION_ID), ASSESS_BASE_URL, ASSESS_MODEL, ASSESS_API_KEY, PANEL_PORT.\nDocs: https://github.com/vicfei/dsh-super-agent#quick-start";
|
|
2
2
|
export declare function examplePath(name: string): string | null;
|
|
3
3
|
/** Copy the packaged example to `target` when neither exists yet. True ⇒ caller should tell the user to edit & rerun. */
|
|
4
4
|
export declare function scaffoldFromExample(target: string, example: string): boolean;
|
|
5
|
-
export declare const NO_TOKEN_HINT = "[warn]
|
|
5
|
+
export declare const NO_TOKEN_HINT = "[warn] no GitHub credential \u2014 anonymous mode: public repos only, ~60 requests/hour,\n replies & PRs stay queued in the local outbox until a credential appears.\n export GITHUB_TOKEN (a read-only PAT is enough to start:\n https://github.com/settings/personal-access-tokens/new), or set up GitHub App auth \u2014 see README";
|
package/dist/usage.js
CHANGED
|
@@ -14,6 +14,7 @@ Commands:
|
|
|
14
14
|
watch poll + work + panel as one daemon (Ctrl-C stops after the current cycle)
|
|
15
15
|
tickets list tickets; "tickets stop <id>" ends one
|
|
16
16
|
panel serve the awaiting-human panel (http://127.0.0.1:8787)
|
|
17
|
+
merge sweep open ticket PRs — merge those meeting policy.merge requirements (default off)
|
|
17
18
|
help show this usage
|
|
18
19
|
|
|
19
20
|
Common options:
|
|
@@ -28,7 +29,8 @@ Common options:
|
|
|
28
29
|
--no-panel watch without the panel server
|
|
29
30
|
--post poll also posts queued replies (needs a token)
|
|
30
31
|
|
|
31
|
-
Environment: GITHUB_TOKEN,
|
|
32
|
+
Environment: GITHUB_TOKEN, or GitHub App auth (GITHUB_APP_ID + GITHUB_APP_PRIVATE_KEY[_PATH],
|
|
33
|
+
optional GITHUB_APP_INSTALLATION_ID), ASSESS_BASE_URL, ASSESS_MODEL, ASSESS_API_KEY, PANEL_PORT.
|
|
32
34
|
Docs: https://github.com/vicfei/dsh-super-agent#quick-start`;
|
|
33
35
|
const examplesDir = join(dirname(fileURLToPath(import.meta.url)), "..", "examples");
|
|
34
36
|
export function examplePath(name) {
|
|
@@ -43,8 +45,8 @@ export function scaffoldFromExample(target, example) {
|
|
|
43
45
|
copyFileSync(src, target);
|
|
44
46
|
return true;
|
|
45
47
|
}
|
|
46
|
-
export const NO_TOKEN_HINT = `[warn]
|
|
47
|
-
replies & PRs stay queued in the local outbox until a
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
export const NO_TOKEN_HINT = `[warn] no GitHub credential — anonymous mode: public repos only, ~60 requests/hour,
|
|
49
|
+
replies & PRs stay queued in the local outbox until a credential appears.
|
|
50
|
+
export GITHUB_TOKEN (a read-only PAT is enough to start:
|
|
51
|
+
https://github.com/settings/personal-access-tokens/new), or set up GitHub App auth — see README`;
|
|
50
52
|
//# sourceMappingURL=usage.js.map
|
package/dist/usage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,4FAA4F;AAC5F,yEAAyE;AAEzE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,CAAC,MAAM,KAAK,GAAG
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,4FAA4F;AAC5F,yEAAyE;AAEzE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,CAAC,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;4DA2BuC,CAAC;AAE7D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AAEpF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAClC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAClC,CAAC;AAED,yHAAyH;AACzH,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,OAAe;IACjE,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC1B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;;;uGAG0E,CAAC"}
|