@tokenfactory/acc-runner 0.42.0 → 0.44.0
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 +52 -3
- package/dist/companion-run.d.ts.map +1 -1
- package/dist/companion-run.js +20 -0
- package/dist/companion-run.js.map +1 -1
- package/dist/config.d.ts +72 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +117 -3
- package/dist/config.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +13 -3
- package/dist/doctor.js.map +1 -1
- package/dist/engines/account-probe.d.ts +24 -0
- package/dist/engines/account-probe.d.ts.map +1 -1
- package/dist/engines/account-probe.js +18 -1
- package/dist/engines/account-probe.js.map +1 -1
- package/dist/engines/registry.d.ts +17 -6
- package/dist/engines/registry.d.ts.map +1 -1
- package/dist/engines/registry.js +38 -13
- package/dist/engines/registry.js.map +1 -1
- package/dist/git-auth/github-token-source.d.ts +54 -0
- package/dist/git-auth/github-token-source.d.ts.map +1 -0
- package/dist/git-auth/github-token-source.js +44 -0
- package/dist/git-auth/github-token-source.js.map +1 -0
- package/dist/git-auth/index.d.ts +4 -0
- package/dist/git-auth/index.d.ts.map +1 -1
- package/dist/git-auth/index.js +4 -0
- package/dist/git-auth/index.js.map +1 -1
- package/dist/git-auth/installation-token.d.ts +95 -0
- package/dist/git-auth/installation-token.d.ts.map +1 -0
- package/dist/git-auth/installation-token.js +192 -0
- package/dist/git-auth/installation-token.js.map +1 -0
- package/dist/local-repo/command.d.ts +28 -0
- package/dist/local-repo/command.d.ts.map +1 -0
- package/dist/local-repo/command.js +178 -0
- package/dist/local-repo/command.js.map +1 -0
- package/dist/local-repo/index.d.ts +119 -0
- package/dist/local-repo/index.d.ts.map +1 -0
- package/dist/local-repo/index.js +141 -0
- package/dist/local-repo/index.js.map +1 -0
- package/dist/machine-capabilities/index.d.ts +21 -0
- package/dist/machine-capabilities/index.d.ts.map +1 -0
- package/dist/machine-capabilities/index.js +21 -0
- package/dist/machine-capabilities/index.js.map +1 -0
- package/dist/machine-capabilities/probe.d.ts +61 -0
- package/dist/machine-capabilities/probe.d.ts.map +1 -0
- package/dist/machine-capabilities/probe.js +243 -0
- package/dist/machine-capabilities/probe.js.map +1 -0
- package/dist/machine-capabilities/redact.d.ts +42 -0
- package/dist/machine-capabilities/redact.d.ts.map +1 -0
- package/dist/machine-capabilities/redact.js +160 -0
- package/dist/machine-capabilities/redact.js.map +1 -0
- package/dist/machine-capabilities/report.d.ts +107 -0
- package/dist/machine-capabilities/report.d.ts.map +1 -0
- package/dist/machine-capabilities/report.js +211 -0
- package/dist/machine-capabilities/report.js.map +1 -0
- package/dist/machine-capabilities/types.d.ts +115 -0
- package/dist/machine-capabilities/types.d.ts.map +1 -0
- package/dist/machine-capabilities/types.js +11 -0
- package/dist/machine-capabilities/types.js.map +1 -0
- package/dist/mcp-spawn.d.ts +19 -0
- package/dist/mcp-spawn.d.ts.map +1 -1
- package/dist/mcp-spawn.js +52 -26
- package/dist/mcp-spawn.js.map +1 -1
- package/dist/migration-seq-guard.d.ts +78 -0
- package/dist/migration-seq-guard.d.ts.map +1 -0
- package/dist/migration-seq-guard.js +304 -0
- package/dist/migration-seq-guard.js.map +1 -0
- package/dist/node-version.d.ts +132 -0
- package/dist/node-version.d.ts.map +1 -0
- package/dist/node-version.js +318 -0
- package/dist/node-version.js.map +1 -0
- package/dist/prepr-gate.d.ts +120 -0
- package/dist/prepr-gate.d.ts.map +1 -1
- package/dist/prepr-gate.js +202 -3
- package/dist/prepr-gate.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +34 -0
- package/dist/program.js.map +1 -1
- package/dist/provider-auth.d.ts +51 -1
- package/dist/provider-auth.d.ts.map +1 -1
- package/dist/provider-auth.js +83 -2
- package/dist/provider-auth.js.map +1 -1
- package/dist/runtime/review-chunking.d.ts +101 -0
- package/dist/runtime/review-chunking.d.ts.map +1 -0
- package/dist/runtime/review-chunking.js +192 -0
- package/dist/runtime/review-chunking.js.map +1 -0
- package/dist/runtime/review-diff.d.ts +30 -0
- package/dist/runtime/review-diff.d.ts.map +1 -0
- package/dist/runtime/review-diff.js +59 -0
- package/dist/runtime/review-diff.js.map +1 -0
- package/dist/runtime/reviewer.d.ts +40 -19
- package/dist/runtime/reviewer.d.ts.map +1 -1
- package/dist/runtime/reviewer.js +283 -68
- package/dist/runtime/reviewer.js.map +1 -1
- package/dist/serve-scope/command.d.ts +12 -0
- package/dist/serve-scope/command.d.ts.map +1 -0
- package/dist/serve-scope/command.js +89 -0
- package/dist/serve-scope/command.js.map +1 -0
- package/dist/serve-scope/index.d.ts +130 -0
- package/dist/serve-scope/index.d.ts.map +1 -0
- package/dist/serve-scope/index.js +148 -0
- package/dist/serve-scope/index.js.map +1 -0
- package/dist/task-runner.d.ts +22 -2
- package/dist/task-runner.d.ts.map +1 -1
- package/dist/task-runner.js +142 -25
- package/dist/task-runner.js.map +1 -1
- package/dist/watch.d.ts +21 -0
- package/dist/watch.d.ts.map +1 -1
- package/dist/watch.js +109 -1
- package/dist/watch.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LOCAL-REPO-CLI — the decidable half of `acc repo add-local`.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is pure: given a path on disk and a few probe results, decide
|
|
5
|
+
* what to register, what to refuse, and what to warn about. The plumbing that
|
|
6
|
+
* needs a keychain, a network and a filesystem lives in ./command.ts, the same
|
|
7
|
+
* split serve-scope uses — so every rule below is unit-testable without either.
|
|
8
|
+
*
|
|
9
|
+
* WHAT A "LOCAL REPO" IS, AND WHAT IT IS NOT
|
|
10
|
+
* ----------------------------------------------------------------------------
|
|
11
|
+
* It is a git working copy on THIS machine that ACC may run tasks in, attached
|
|
12
|
+
* to a project without the GitHub App being installed anywhere. That is the
|
|
13
|
+
* whole of it. In particular it is NOT:
|
|
14
|
+
*
|
|
15
|
+
* * a mirror of a GitHub repo ACC will keep in sync — nothing here clones,
|
|
16
|
+
* fetches or pushes on the server's behalf;
|
|
17
|
+
* * a repo other people on the team can work. The grant the server records is
|
|
18
|
+
* scoped to the registering user, and the path is known only to this
|
|
19
|
+
* machine, so a teammate's runner has neither the right nor the directory;
|
|
20
|
+
* * a way to skip a GitHub write grant on a repo that IS on GitHub. The
|
|
21
|
+
* server derives the slug from the caller's user id into a reserved
|
|
22
|
+
* `local.…` namespace precisely so this cannot be that.
|
|
23
|
+
*
|
|
24
|
+
* WHY THE PATH NEVER LEAVES THE MACHINE
|
|
25
|
+
* ----------------------------------------------------------------------------
|
|
26
|
+
* The server needs to know "machine M serves repo R" to route a task; it does
|
|
27
|
+
* not need to know that R is at /Users/priya/code/side-project. Sending the path
|
|
28
|
+
* would put a filesystem layout — usernames, project names, directory
|
|
29
|
+
* structure — into a shared database for no routing benefit, so the path stays
|
|
30
|
+
* in this machine's own config.json (`local-repos`) and the runner resolves it
|
|
31
|
+
* at task time. See docs/acc/LOCAL_REPO_CLI_SETUP.md.
|
|
32
|
+
*/
|
|
33
|
+
/** The reserved namespace the server mints local slugs into (acc.local_repo_slug). */
|
|
34
|
+
export const LOCAL_REPO_PREFIX = "local.";
|
|
35
|
+
/**
|
|
36
|
+
* Is this slug in the reserved local/CLI namespace? Mirrors
|
|
37
|
+
* acc.is_local_repo_slug (migration 0318) and src/lib/local-repo.ts. A GitHub
|
|
38
|
+
* owner segment can never contain a '.', so the two namespaces cannot collide.
|
|
39
|
+
*/
|
|
40
|
+
export function isLocalRepoSlug(repo) {
|
|
41
|
+
const slug = (repo ?? "").trim().toLowerCase();
|
|
42
|
+
const slash = slug.indexOf("/");
|
|
43
|
+
if (slash <= 0 || slash === slug.length - 1)
|
|
44
|
+
return false;
|
|
45
|
+
return slug.slice(0, slash).startsWith(LOCAL_REPO_PREFIX);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The human-facing name of a local repo — the part after the '/', without the
|
|
49
|
+
* per-user hash fragment that makes the slug unique. `local.9f2c1a/my-app` reads
|
|
50
|
+
* as "my-app (local)" in a list; the full slug is still what gets matched.
|
|
51
|
+
*/
|
|
52
|
+
export function localRepoDisplayName(repo) {
|
|
53
|
+
const slash = repo.lastIndexOf("/");
|
|
54
|
+
return slash >= 0 ? repo.slice(slash + 1) : repo;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Slugify a repo NAME the way acc.local_repo_slug does server-side, so the CLI
|
|
58
|
+
* can predict (and preview) the slug it is about to be handed. Kept in sync
|
|
59
|
+
* deliberately — the server is authoritative and the CLI stores whatever comes
|
|
60
|
+
* back, so a drift here is a cosmetic preview bug, never a wrong write.
|
|
61
|
+
*/
|
|
62
|
+
export function sanitizeLocalRepoName(raw) {
|
|
63
|
+
let name = (raw ?? "").trim().toLowerCase();
|
|
64
|
+
name = name.replace(/[^a-z0-9._-]+/g, "-");
|
|
65
|
+
name = name.replace(/^[-._]+|[-._]+$/g, "");
|
|
66
|
+
name = name.slice(0, 64);
|
|
67
|
+
name = name.replace(/^[-._]+|[-._]+$/g, "");
|
|
68
|
+
return name;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Decide what to register for a probed directory, or throw with the reason it
|
|
72
|
+
* cannot be registered.
|
|
73
|
+
*
|
|
74
|
+
* Refusals are limited to the two facts that make registration meaningless: the
|
|
75
|
+
* path is not a directory, or it is not a git repository (the runner's whole
|
|
76
|
+
* task loop is `git` — branch, commit, diff — so a plain folder would fail at
|
|
77
|
+
* the first step rather than at a legible place).
|
|
78
|
+
*
|
|
79
|
+
* A missing `origin` is NOT a refusal. Running tasks in a local working copy is
|
|
80
|
+
* useful on its own; it is opening a PR at the end that needs a remote, and the
|
|
81
|
+
* warning says exactly that instead of pre-emptively blocking the register.
|
|
82
|
+
*/
|
|
83
|
+
export function planLocalRepoRegistration(probe) {
|
|
84
|
+
if (!probe.isDirectory) {
|
|
85
|
+
throw new Error(`${probe.path} is not a directory — point at a git working copy`);
|
|
86
|
+
}
|
|
87
|
+
if (!probe.isGitRepo) {
|
|
88
|
+
throw new Error(`${probe.path} is not a git repository (no .git) — run \`git init\` there first, ` +
|
|
89
|
+
"or point at the repo root");
|
|
90
|
+
}
|
|
91
|
+
const rawName = probe.nameOverride?.trim() || basename(probe.path);
|
|
92
|
+
const name = sanitizeLocalRepoName(rawName);
|
|
93
|
+
if (!name) {
|
|
94
|
+
throw new Error(`could not derive a repo name from ${probe.path} — pass --name with letters or digits`);
|
|
95
|
+
}
|
|
96
|
+
const warnings = [];
|
|
97
|
+
if (!probe.originUrl) {
|
|
98
|
+
warnings.push("This repo has no `origin` remote. Tasks will run and commit here, but the " +
|
|
99
|
+
"runner cannot push a branch or open a PR — add a remote if you want PRs.");
|
|
100
|
+
}
|
|
101
|
+
warnings.push("The code stays on this machine. Only your own runner can work this repo, " +
|
|
102
|
+
"and only while it is online.");
|
|
103
|
+
return {
|
|
104
|
+
name,
|
|
105
|
+
path: probe.path,
|
|
106
|
+
// A preview, not a claim: the server mints the authoritative slug from the
|
|
107
|
+
// caller's user id, which this side deliberately does not know.
|
|
108
|
+
previewSlug: `${LOCAL_REPO_PREFIX}<you>/${name}`,
|
|
109
|
+
warnings,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Last path segment, tolerating a trailing separator (`~/code/my-app/` must
|
|
114
|
+
* yield "my-app", not ""). Local rather than node:path so this module stays
|
|
115
|
+
* dependency-free and testable as pure text.
|
|
116
|
+
*/
|
|
117
|
+
function basename(p) {
|
|
118
|
+
const parts = p.replace(/[\\/]+$/, "").split(/[\\/]/);
|
|
119
|
+
return parts[parts.length - 1] ?? "";
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Is this error the "migration 0318 has not been applied here yet" shape?
|
|
123
|
+
* HALT-before-apply means every environment has a window where this command
|
|
124
|
+
* ships and the RPC does not exist; "run psql" and "something is broken" have
|
|
125
|
+
* different remedies, so the command says which. Mirrors serve-scope's
|
|
126
|
+
* isMigrationPending.
|
|
127
|
+
*/
|
|
128
|
+
export function isMigrationPending(err) {
|
|
129
|
+
if (!err)
|
|
130
|
+
return false;
|
|
131
|
+
// PostgREST: 404 + PGRST202 for an unknown RPC; Postgres 42883 for an
|
|
132
|
+
// undefined function reached another way.
|
|
133
|
+
if (err.code === "PGRST202" || err.code === "42883")
|
|
134
|
+
return true;
|
|
135
|
+
const msg = (err.message ?? "").toLowerCase();
|
|
136
|
+
return (msg.includes("register_local_repo") &&
|
|
137
|
+
(msg.includes("does not exist") ||
|
|
138
|
+
msg.includes("not find") ||
|
|
139
|
+
msg.includes("schema cache")));
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/local-repo/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AX-H1 (MACHINE-CAPABILITIES): probe and record what a machine can actually do.
|
|
3
|
+
* AUTH_APPROVAL_BRIEF.md §7, Phase H, gap G-17.
|
|
4
|
+
*
|
|
5
|
+
* Three modules, one rule (brief §7.1 — no credential ever transits ACC; presence
|
|
6
|
+
* and identity only):
|
|
7
|
+
*
|
|
8
|
+
* types.ts the CLOSED field set. Presence, identity, provenance. Nothing else.
|
|
9
|
+
* redact.ts the boundary: rebuild + mask every record before it leaves the host.
|
|
10
|
+
* probe.ts the host probe (gh / git / engine logins), read-only and bounded.
|
|
11
|
+
* report.ts the gate + the write, driven by somebody ELSE's cadence.
|
|
12
|
+
*
|
|
13
|
+
* The cadence is the AS-1 account probe (engines/account-probe.ts), reused rather
|
|
14
|
+
* than duplicated: `AccountProbeScheduler` calls the reporter on each of its four
|
|
15
|
+
* triggers, so this package still has exactly one probe loop on a host.
|
|
16
|
+
*/
|
|
17
|
+
export { HOST_TOOLS, type EngineCapability, type HostTool, type MachineCapabilityReport, type MachineCapabilitySnapshot, type ToolCapability, } from "./types.js";
|
|
18
|
+
export { CREDENTIAL_SHAPES, looksLikeCredential, safeScopes, safeText, sanitizeEngine, sanitizeSnapshot, sanitizeTool, } from "./redact.js";
|
|
19
|
+
export { PROBE_TIMEOUT_MS, parseGhAuthStatus, parseVersion, probeMachineCapabilities, type MachineCapabilityProbeDeps, type ProbeExec, type ProbeExecResult, } from "./probe.js";
|
|
20
|
+
export { DEFAULT_PROBE_MIN_INTERVAL_MS, DEFAULT_REFRESH_MIN_INTERVAL_MS, MachineCapabilityReporter, recordMachineCapabilities, snapshotFingerprint, type MachineCapabilityReporterDeps, type MachineCapabilityTickOutcome, type MachineCapabilityTransport, } from "./report.js";
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/machine-capabilities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACb,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,cAAc,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,wBAAwB,EACxB,KAAK,0BAA0B,EAC/B,KAAK,SAAS,EACd,KAAK,eAAe,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,6BAA6B,EAC7B,+BAA+B,EAC/B,yBAAyB,EACzB,yBAAyB,EACzB,mBAAmB,EACnB,KAAK,6BAA6B,EAClC,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,GAChC,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AX-H1 (MACHINE-CAPABILITIES): probe and record what a machine can actually do.
|
|
3
|
+
* AUTH_APPROVAL_BRIEF.md §7, Phase H, gap G-17.
|
|
4
|
+
*
|
|
5
|
+
* Three modules, one rule (brief §7.1 — no credential ever transits ACC; presence
|
|
6
|
+
* and identity only):
|
|
7
|
+
*
|
|
8
|
+
* types.ts the CLOSED field set. Presence, identity, provenance. Nothing else.
|
|
9
|
+
* redact.ts the boundary: rebuild + mask every record before it leaves the host.
|
|
10
|
+
* probe.ts the host probe (gh / git / engine logins), read-only and bounded.
|
|
11
|
+
* report.ts the gate + the write, driven by somebody ELSE's cadence.
|
|
12
|
+
*
|
|
13
|
+
* The cadence is the AS-1 account probe (engines/account-probe.ts), reused rather
|
|
14
|
+
* than duplicated: `AccountProbeScheduler` calls the reporter on each of its four
|
|
15
|
+
* triggers, so this package still has exactly one probe loop on a host.
|
|
16
|
+
*/
|
|
17
|
+
export { HOST_TOOLS, } from "./types.js";
|
|
18
|
+
export { CREDENTIAL_SHAPES, looksLikeCredential, safeScopes, safeText, sanitizeEngine, sanitizeSnapshot, sanitizeTool, } from "./redact.js";
|
|
19
|
+
export { PROBE_TIMEOUT_MS, parseGhAuthStatus, parseVersion, probeMachineCapabilities, } from "./probe.js";
|
|
20
|
+
export { DEFAULT_PROBE_MIN_INTERVAL_MS, DEFAULT_REFRESH_MIN_INTERVAL_MS, MachineCapabilityReporter, recordMachineCapabilities, snapshotFingerprint, } from "./report.js";
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/machine-capabilities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,UAAU,GAMX,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,wBAAwB,GAIzB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,6BAA6B,EAC7B,+BAA+B,EAC/B,yBAAyB,EACzB,yBAAyB,EACzB,mBAAmB,GAIpB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type MachineCapabilitySnapshot } from "./types.js";
|
|
2
|
+
/** One command invocation captured without throwing. */
|
|
3
|
+
export interface ProbeExecResult {
|
|
4
|
+
stdout: string;
|
|
5
|
+
stderr: string;
|
|
6
|
+
exitCode: number | null;
|
|
7
|
+
}
|
|
8
|
+
/** The single I/O seam: run `bin args` and report what happened. Never throws. */
|
|
9
|
+
export type ProbeExec = (bin: string, args: string[]) => Promise<ProbeExecResult>;
|
|
10
|
+
/** Per-probe timeout. A capability probe must never hold up a cadence tick. */
|
|
11
|
+
export declare const PROBE_TIMEOUT_MS = 5000;
|
|
12
|
+
export interface MachineCapabilityProbeDeps {
|
|
13
|
+
/** Command runner (test seam). Defaults to a bounded, non-throwing execa. */
|
|
14
|
+
exec?: ProbeExec;
|
|
15
|
+
/** Host name (test seam). Defaults to os.hostname(). */
|
|
16
|
+
hostname?: () => string;
|
|
17
|
+
/** Engine ids to probe (test seam). Defaults to the chat-engine registry. */
|
|
18
|
+
engineIds?: () => string[];
|
|
19
|
+
/** Reported runner version (test seam). Defaults to the package version. */
|
|
20
|
+
runnerVersion?: string;
|
|
21
|
+
/** platform/arch (test seam). Default to process values. */
|
|
22
|
+
platform?: string;
|
|
23
|
+
arch?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Extract the first dotted version triple from a `--version` line. Tolerant on
|
|
27
|
+
* purpose: `gh version 2.62.0 (2024-11-08)`, `git version 2.46.0`,
|
|
28
|
+
* `1.0.30 (Claude Code)` and a bare `2.4` all resolve; anything else is null
|
|
29
|
+
* rather than a guess (an invented version would make an "is this old enough?"
|
|
30
|
+
* question answerable and wrong).
|
|
31
|
+
*/
|
|
32
|
+
export declare function parseVersion(output: string): string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Parse `gh auth status` output. gh prints a human block per host:
|
|
35
|
+
*
|
|
36
|
+
* github.com
|
|
37
|
+
* ✓ Logged in to github.com account gaurav (keyring)
|
|
38
|
+
* - Active account: true
|
|
39
|
+
* - Git operations protocol: https
|
|
40
|
+
* - Token: gho_************************************
|
|
41
|
+
* - Token scopes: 'gist', 'read:org', 'repo'
|
|
42
|
+
*
|
|
43
|
+
* The `Token:` line is already elided by gh, and we do not read it either way —
|
|
44
|
+
* only the account, the host, and the scope labels. Tolerant of the older
|
|
45
|
+
* `Logged in to github.com as gaurav (…)` spelling, and of `--json`-less GHES
|
|
46
|
+
* output where the host is the bare first line.
|
|
47
|
+
*/
|
|
48
|
+
export declare function parseGhAuthStatus(output: string): {
|
|
49
|
+
account: string | null;
|
|
50
|
+
host: string | null;
|
|
51
|
+
scopes: string[];
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Probe the whole host. Never throws and never rejects: a probe that fails is
|
|
55
|
+
* reported as an absent tool, because "we could not tell" and "it is not there"
|
|
56
|
+
* are both answers a user can act on, whereas an exception on a cadence tick is
|
|
57
|
+
* not. The result is passed through `sanitizeSnapshot` before it is returned, so
|
|
58
|
+
* a caller cannot obtain an unredacted snapshot from this module at all.
|
|
59
|
+
*/
|
|
60
|
+
export declare function probeMachineCapabilities(deps?: MachineCapabilityProbeDeps): Promise<MachineCapabilitySnapshot>;
|
|
61
|
+
//# sourceMappingURL=probe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../src/machine-capabilities/probe.ts"],"names":[],"mappings":"AAsCA,OAAO,EAGL,KAAK,yBAAyB,EAE/B,MAAM,YAAY,CAAC;AAEpB,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,kFAAkF;AAClF,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAElF,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AAqBtC,MAAM,WAAW,0BAA0B;IACzC,6EAA6E;IAC7E,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC;IACxB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IAC3B,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG1D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG;IACjD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAaA;AAkID;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,GAAE,0BAA+B,GACpC,OAAO,CAAC,yBAAyB,CAAC,CAiBpC"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AX-H1 (MACHINE-CAPABILITIES): the host probe. Answers "what does THIS machine
|
|
3
|
+
* actually offer?" — gh, git, and each registered engine's login — so ACC can
|
|
4
|
+
* tell a user what their own machine can do instead of leaving that in the
|
|
5
|
+
* operator's head.
|
|
6
|
+
*
|
|
7
|
+
* WHAT IT READS, AND WHAT IT REFUSES TO READ. Every probe here is a read-only,
|
|
8
|
+
* short-timeout, local invocation of a tool's own status command:
|
|
9
|
+
*
|
|
10
|
+
* gh `gh --version`, `gh auth status` — presence, version, whether the
|
|
11
|
+
* credential works, the account login, the host, and the token's SCOPE
|
|
12
|
+
* LABELS. `--show-token` is NEVER passed: the scopes are the authority,
|
|
13
|
+
* and the authority is the answerable question ("can this machine open a
|
|
14
|
+
* PR?"). The token is not read, so it cannot be sent. The unit suite
|
|
15
|
+
* asserts no argv in this package contains `--show-token`.
|
|
16
|
+
* git `git --version`, `git config --get user.email` — presence, version and
|
|
17
|
+
* the committing identity. Git has no host-level login of its own, so
|
|
18
|
+
* `authenticated` is false and the credential-health question is answered
|
|
19
|
+
* by the separate GIT-AUTH-ALERT `ls-remote` probe (git-auth/probe.ts),
|
|
20
|
+
* which is where a remote round-trip belongs.
|
|
21
|
+
* engines the AS-1 `accountIdentity()` surface plus a `--version` presence
|
|
22
|
+
* check. NOT a second credential probe: the identity is exactly what the
|
|
23
|
+
* AS-1 cadence already computes, so the engine rows are a projection of
|
|
24
|
+
* a fact this process already has.
|
|
25
|
+
*
|
|
26
|
+
* Nothing here reads a keychain, a token file, or an environment variable's
|
|
27
|
+
* VALUE. Every free-text field goes through redact.ts before it leaves the host.
|
|
28
|
+
*
|
|
29
|
+
* FULLY injectable (exec / hostname / engines / version) so the whole probe is
|
|
30
|
+
* exercised with zero real subprocesses.
|
|
31
|
+
*/
|
|
32
|
+
import { execa } from "execa";
|
|
33
|
+
import os from "node:os";
|
|
34
|
+
import { buildEnv } from "../bin-resolve.js";
|
|
35
|
+
import { chatEngineIds, getChatEngine } from "../engines/registry.js";
|
|
36
|
+
import { unknownAccountIdentity } from "../engines/account-identity.js";
|
|
37
|
+
import { PACKAGE_VERSION } from "../pkg-version.js";
|
|
38
|
+
import { sanitizeSnapshot } from "./redact.js";
|
|
39
|
+
import { HOST_TOOLS, } from "./types.js";
|
|
40
|
+
/** Per-probe timeout. A capability probe must never hold up a cadence tick. */
|
|
41
|
+
export const PROBE_TIMEOUT_MS = 5_000;
|
|
42
|
+
const defaultExec = async (bin, args) => {
|
|
43
|
+
try {
|
|
44
|
+
const res = await execa(bin, args, {
|
|
45
|
+
env: buildEnv(),
|
|
46
|
+
timeout: PROBE_TIMEOUT_MS,
|
|
47
|
+
reject: false,
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
stdout: res.stdout ?? "",
|
|
51
|
+
stderr: res.stderr ?? "",
|
|
52
|
+
exitCode: res.exitCode ?? null,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
// A missing binary throws ENOENT rather than exiting non-zero. That is
|
|
57
|
+
// "absent", not "broken", and it is reported as such.
|
|
58
|
+
return { stdout: "", stderr: err?.message ?? "spawn failed", exitCode: null };
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Extract the first dotted version triple from a `--version` line. Tolerant on
|
|
63
|
+
* purpose: `gh version 2.62.0 (2024-11-08)`, `git version 2.46.0`,
|
|
64
|
+
* `1.0.30 (Claude Code)` and a bare `2.4` all resolve; anything else is null
|
|
65
|
+
* rather than a guess (an invented version would make an "is this old enough?"
|
|
66
|
+
* question answerable and wrong).
|
|
67
|
+
*/
|
|
68
|
+
export function parseVersion(output) {
|
|
69
|
+
const m = /\b(\d+(?:\.\d+){1,3})\b/.exec(output ?? "");
|
|
70
|
+
return m ? m[1] : null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Parse `gh auth status` output. gh prints a human block per host:
|
|
74
|
+
*
|
|
75
|
+
* github.com
|
|
76
|
+
* ✓ Logged in to github.com account gaurav (keyring)
|
|
77
|
+
* - Active account: true
|
|
78
|
+
* - Git operations protocol: https
|
|
79
|
+
* - Token: gho_************************************
|
|
80
|
+
* - Token scopes: 'gist', 'read:org', 'repo'
|
|
81
|
+
*
|
|
82
|
+
* The `Token:` line is already elided by gh, and we do not read it either way —
|
|
83
|
+
* only the account, the host, and the scope labels. Tolerant of the older
|
|
84
|
+
* `Logged in to github.com as gaurav (…)` spelling, and of `--json`-less GHES
|
|
85
|
+
* output where the host is the bare first line.
|
|
86
|
+
*/
|
|
87
|
+
export function parseGhAuthStatus(output) {
|
|
88
|
+
const text = output ?? "";
|
|
89
|
+
const account = /Logged in to \S+ account ([A-Za-z0-9._-]+)/.exec(text)?.[1] ??
|
|
90
|
+
/Logged in to \S+ as ([A-Za-z0-9._-]+)/.exec(text)?.[1] ??
|
|
91
|
+
null;
|
|
92
|
+
const host = /Logged in to (\S+?)(?: account| as)\b/.exec(text)?.[1] ?? null;
|
|
93
|
+
const scopeLine = /Token scopes:\s*(.+)/.exec(text)?.[1] ?? "";
|
|
94
|
+
const scopes = scopeLine
|
|
95
|
+
.split(",")
|
|
96
|
+
.map((s) => s.trim().replace(/^['"]|['"]$/g, ""))
|
|
97
|
+
.filter((s) => s.length > 0 && s !== "none");
|
|
98
|
+
return { account, host, scopes };
|
|
99
|
+
}
|
|
100
|
+
/** Probe `gh`: presence, version, whether it authenticates, and as whom. */
|
|
101
|
+
async function probeGh(exec) {
|
|
102
|
+
const ver = await exec("gh", ["--version"]);
|
|
103
|
+
const present = ver.exitCode === 0;
|
|
104
|
+
const version = present ? parseVersion(ver.stdout) : null;
|
|
105
|
+
if (!present) {
|
|
106
|
+
return {
|
|
107
|
+
tool: "gh",
|
|
108
|
+
present: false,
|
|
109
|
+
version: null,
|
|
110
|
+
authenticated: false,
|
|
111
|
+
identity: null,
|
|
112
|
+
host: null,
|
|
113
|
+
scopes: [],
|
|
114
|
+
detail: "gh not installed (or not on PATH)",
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
// `gh auth status` is a LOCAL token check, not a GitHub API call (see gh.ts),
|
|
118
|
+
// so it is unbudgeted and safe to run on every capability probe.
|
|
119
|
+
const status = await exec("gh", ["auth", "status"]);
|
|
120
|
+
const authenticated = status.exitCode === 0;
|
|
121
|
+
// gh has printed the status block on stdout since 2.x and on stderr before
|
|
122
|
+
// that; read both so an older install still resolves an identity.
|
|
123
|
+
const { account, host, scopes } = parseGhAuthStatus(`${status.stdout}\n${status.stderr}`);
|
|
124
|
+
return {
|
|
125
|
+
tool: "gh",
|
|
126
|
+
present: true,
|
|
127
|
+
version,
|
|
128
|
+
authenticated,
|
|
129
|
+
identity: authenticated ? account : null,
|
|
130
|
+
host: authenticated ? host : null,
|
|
131
|
+
scopes: authenticated ? scopes : [],
|
|
132
|
+
detail: authenticated
|
|
133
|
+
? `gh ${version ?? "?"} authenticated${account ? ` as ${account}` : ""}${host ? ` on ${host}` : ""}`
|
|
134
|
+
: `gh ${version ?? "?"} installed but not authenticated (run \`gh auth login\`)`,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/** Probe `git`: presence, version and the committing identity. */
|
|
138
|
+
async function probeGit(exec) {
|
|
139
|
+
const ver = await exec("git", ["--version"]);
|
|
140
|
+
const present = ver.exitCode === 0;
|
|
141
|
+
if (!present) {
|
|
142
|
+
return {
|
|
143
|
+
tool: "git",
|
|
144
|
+
present: false,
|
|
145
|
+
version: null,
|
|
146
|
+
authenticated: false,
|
|
147
|
+
identity: null,
|
|
148
|
+
host: null,
|
|
149
|
+
scopes: [],
|
|
150
|
+
detail: "git not installed (or not on PATH)",
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
const version = parseVersion(ver.stdout);
|
|
154
|
+
const email = await exec("git", ["config", "--get", "user.email"]);
|
|
155
|
+
const identity = email.exitCode === 0 ? email.stdout.trim() || null : null;
|
|
156
|
+
return {
|
|
157
|
+
tool: "git",
|
|
158
|
+
present: true,
|
|
159
|
+
version,
|
|
160
|
+
// git holds no host login of its own; remote credential health is the
|
|
161
|
+
// GIT-AUTH-ALERT ls-remote probe's job, and duplicating it here would mean
|
|
162
|
+
// a second remote round trip on every cadence tick.
|
|
163
|
+
authenticated: false,
|
|
164
|
+
identity,
|
|
165
|
+
host: null,
|
|
166
|
+
scopes: [],
|
|
167
|
+
detail: identity
|
|
168
|
+
? `git ${version ?? "?"} committing as ${identity}`
|
|
169
|
+
: `git ${version ?? "?"} (no user.email configured)`,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Probe one engine: is the binary there, and who is it logged in as? The identity
|
|
174
|
+
* comes from the AS-1 `accountIdentity()` surface — this is a PROJECTION of the
|
|
175
|
+
* probe the cadence already runs, not a second credential probe. An engine that
|
|
176
|
+
* predates AS-1 degrades to the honest unknown-account identity rather than being
|
|
177
|
+
* reported as logged out.
|
|
178
|
+
*/
|
|
179
|
+
async function probeEngine(engineId, exec) {
|
|
180
|
+
let binary = engineId;
|
|
181
|
+
let channel = "none";
|
|
182
|
+
let identity = unknownAccountIdentity({
|
|
183
|
+
engineId,
|
|
184
|
+
channel: "none",
|
|
185
|
+
detail: `engine ${engineId} is not registered in this runner build`,
|
|
186
|
+
});
|
|
187
|
+
try {
|
|
188
|
+
const engine = getChatEngine(engineId);
|
|
189
|
+
binary = engine.binary;
|
|
190
|
+
channel = engine.authMode;
|
|
191
|
+
identity = engine.accountIdentity
|
|
192
|
+
? await engine.accountIdentity()
|
|
193
|
+
: unknownAccountIdentity({
|
|
194
|
+
engineId: engine.id,
|
|
195
|
+
channel: engine.authMode,
|
|
196
|
+
detail: "no account-identity probe on this engine build",
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// An unknown / unresolvable engine id is reported as absent, never thrown:
|
|
201
|
+
// one bad engine must not cost the whole snapshot.
|
|
202
|
+
}
|
|
203
|
+
const ver = await exec(binary, ["--version"]);
|
|
204
|
+
const present = ver.exitCode === 0;
|
|
205
|
+
return {
|
|
206
|
+
engine_id: engineId,
|
|
207
|
+
present,
|
|
208
|
+
version: present ? parseVersion(ver.stdout) : null,
|
|
209
|
+
// "Logged in" means a REAL named account resolved. The AS-1 honest-unknown
|
|
210
|
+
// identity always carries a synthetic account, so presence of that id is not
|
|
211
|
+
// evidence of a login — the email is.
|
|
212
|
+
logged_in: identity.account_email !== null,
|
|
213
|
+
channel: identity.channel ?? channel,
|
|
214
|
+
account_email: identity.account_email,
|
|
215
|
+
plan_hint: identity.plan_hint,
|
|
216
|
+
synthetic_account: identity.synthetic_account,
|
|
217
|
+
detail: present
|
|
218
|
+
? identity.detail
|
|
219
|
+
: `${engineId} not installed (or not on PATH); ${identity.detail}`,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Probe the whole host. Never throws and never rejects: a probe that fails is
|
|
224
|
+
* reported as an absent tool, because "we could not tell" and "it is not there"
|
|
225
|
+
* are both answers a user can act on, whereas an exception on a cadence tick is
|
|
226
|
+
* not. The result is passed through `sanitizeSnapshot` before it is returned, so
|
|
227
|
+
* a caller cannot obtain an unredacted snapshot from this module at all.
|
|
228
|
+
*/
|
|
229
|
+
export async function probeMachineCapabilities(deps = {}) {
|
|
230
|
+
const exec = deps.exec ?? defaultExec;
|
|
231
|
+
const engineIds = (deps.engineIds ?? chatEngineIds)();
|
|
232
|
+
const tools = await Promise.all(HOST_TOOLS.map((tool) => (tool === "gh" ? probeGh(exec) : probeGit(exec))));
|
|
233
|
+
const engines = await Promise.all(engineIds.map((id) => probeEngine(id, exec)));
|
|
234
|
+
return sanitizeSnapshot({
|
|
235
|
+
machine: (deps.hostname ?? (() => os.hostname()))() || "unknown-host",
|
|
236
|
+
platform: deps.platform ?? process.platform,
|
|
237
|
+
arch: deps.arch ?? process.arch,
|
|
238
|
+
runner_version: deps.runnerVersion ?? PACKAGE_VERSION,
|
|
239
|
+
tools,
|
|
240
|
+
engines,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../../src/machine-capabilities/probe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type EngineCapability, type MachineCapabilitySnapshot, type ToolCapability } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Credential SHAPES a developer machine actually holds, plus the two generic
|
|
4
|
+
* carriers. Mirrors the regexes in `acc.machine_capability_material_free`
|
|
5
|
+
* (0310 §2); `tests/unit/t1785160000000035-machine-capabilities.test.ts` asserts
|
|
6
|
+
* the mirror by running the same vectors through both spellings.
|
|
7
|
+
*/
|
|
8
|
+
export declare const CREDENTIAL_SHAPES: readonly RegExp[];
|
|
9
|
+
/** True when `value` contains anything shaped like a credential. */
|
|
10
|
+
export declare function looksLikeCredential(value: string | null | undefined): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Mask + bound one free-text field. Applies `maskGitCredentials` first (the
|
|
13
|
+
* GIT-AUTH-ALERT masker, so URL userinfo and bare gh tokens are rewritten rather
|
|
14
|
+
* than dropped), then DROPS the value entirely if a credential shape survived —
|
|
15
|
+
* an unmaskable value is not worth a field. Length-bounded so a whitelisted
|
|
16
|
+
* field cannot become the smuggling channel.
|
|
17
|
+
*/
|
|
18
|
+
export declare function safeText(value: string | null | undefined, maxLength: number): string | null;
|
|
19
|
+
/**
|
|
20
|
+
* Bound, dedupe and sort gh scope labels. Sorted so two snapshots of the same
|
|
21
|
+
* machine compare equal regardless of the order gh printed them, which is what
|
|
22
|
+
* makes the "did anything change?" fingerprint in report.ts stable. A label that
|
|
23
|
+
* looks like a credential is dropped rather than masked — a scope label is a
|
|
24
|
+
* short well-known word, so an unmaskable one is not a scope.
|
|
25
|
+
*/
|
|
26
|
+
export declare function safeScopes(scopes: readonly string[] | null | undefined): string[];
|
|
27
|
+
/** Rebuild one tool row from the closed field set. */
|
|
28
|
+
export declare function sanitizeTool(tool: ToolCapability): ToolCapability;
|
|
29
|
+
/** Rebuild one engine row from the closed field set. */
|
|
30
|
+
export declare function sanitizeEngine(engine: EngineCapability): EngineCapability;
|
|
31
|
+
/**
|
|
32
|
+
* Rebuild a whole snapshot. The ONLY function the reporter is allowed to send
|
|
33
|
+
* the output of — `recordMachineCapabilities` calls it unconditionally, even on a
|
|
34
|
+
* snapshot this package built itself, because the point is that no future probe
|
|
35
|
+
* can add a field that bypasses it.
|
|
36
|
+
*
|
|
37
|
+
* Rows for tools outside `HOST_TOOLS` and engines with a blank id are dropped:
|
|
38
|
+
* the server-side whitelist would drop them anyway, and sending them would make
|
|
39
|
+
* the local snapshot disagree with the recorded one.
|
|
40
|
+
*/
|
|
41
|
+
export declare function sanitizeSnapshot(snapshot: MachineCapabilitySnapshot): MachineCapabilitySnapshot;
|
|
42
|
+
//# sourceMappingURL=redact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/machine-capabilities/redact.ts"],"names":[],"mappings":"AA6BA,OAAO,EAEL,KAAK,gBAAgB,EAErB,KAAK,yBAAyB,EAC9B,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EAkB9C,CAAC;AAEF,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAG7E;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAMf;AAOD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAWjF;AAED,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc,CAWjE;AAED,wDAAwD;AACxD,wBAAgB,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAYzE;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,yBAAyB,GAClC,yBAAyB,CAgB3B"}
|