@agentconnect.md/daemon 1.0.0-rc.21 → 1.0.0-rc.210
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-list-D-RwgYN7.js +21 -0
- package/dist/agent-list-D-RwgYN7.js.map +1 -0
- package/dist/bridge-C8-TYXsj.js +9901 -0
- package/dist/bridge-C8-TYXsj.js.map +1 -0
- package/dist/git-credential-DWH0EUV6.js +98 -0
- package/dist/git-credential-DWH0EUV6.js.map +1 -0
- package/dist/index.js +23392 -713
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { s as resolveRoot, t as gitcredSocketPath } from "./index.js";
|
|
2
|
+
import { createConnection } from "node:net";
|
|
3
|
+
//#region src/cli/git-credential.ts
|
|
4
|
+
/**
|
|
5
|
+
* `agentconnect git-credential --agent <id>` — the git credential helper
|
|
6
|
+
* (docs/designs/github-app-git-credentials.md §本地 helper 通道).
|
|
7
|
+
*
|
|
8
|
+
* Speaks git's credential-helper protocol on stdin/stdout and proxies to the
|
|
9
|
+
* daemon's gitcred.sock; the token exists only on the reply pipe. Actions:
|
|
10
|
+
* get → username=x-access-token / password=<token> (host must be github.com)
|
|
11
|
+
* erase → forward to the daemon (invalidate the cached token git just had rejected)
|
|
12
|
+
* store → no-op
|
|
13
|
+
*
|
|
14
|
+
* Exit style: on ANY failure print a human-actionable line to stderr and exit 1
|
|
15
|
+
* — since #251 surfaces turn failures to end users, this text is user-facing.
|
|
16
|
+
* NEVER print or log the token outside the protocol response.
|
|
17
|
+
*/
|
|
18
|
+
async function runGitCredential(action, agentId) {
|
|
19
|
+
if (action === "store") return;
|
|
20
|
+
const input = parseStdin(await readStdin());
|
|
21
|
+
if (action === "erase") {
|
|
22
|
+
await ipc({
|
|
23
|
+
op: "erase",
|
|
24
|
+
agentId,
|
|
25
|
+
password: input.password
|
|
26
|
+
}).catch(() => void 0);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (action !== "get") return;
|
|
30
|
+
if (input.host !== void 0 && input.host.toLowerCase() !== "github.com") return;
|
|
31
|
+
const res = await ipc({
|
|
32
|
+
op: "get",
|
|
33
|
+
agentId
|
|
34
|
+
});
|
|
35
|
+
if (!res.ok || !res.username || !res.password) {
|
|
36
|
+
process.stderr.write(`agentconnect: no git credentials for agent ${agentId}: ${res.error ?? "unknown error"}\n(the daemon must be running and connected to the control plane)\n`);
|
|
37
|
+
process.exitCode = 1;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (input.path !== void 0) {
|
|
41
|
+
const want = normalizeRepoPath(res.repoFullName ?? "");
|
|
42
|
+
const got = normalizeRepoPath(input.path);
|
|
43
|
+
if (want && got && got !== want && !got.startsWith(`${want}/`)) process.stderr.write(`agentconnect: note — git asked for ${got} but this agent's repo is ${want} (repo renamed? recreate the agent to re-point it)\n`);
|
|
44
|
+
}
|
|
45
|
+
process.stdout.write(`username=${res.username}\npassword=${res.password}\n`);
|
|
46
|
+
}
|
|
47
|
+
function normalizeRepoPath(p) {
|
|
48
|
+
return p.replace(/^\/+/, "").replace(/\.git$/i, "").toLowerCase();
|
|
49
|
+
}
|
|
50
|
+
function parseStdin(text) {
|
|
51
|
+
const out = {};
|
|
52
|
+
for (const line of text.split("\n")) {
|
|
53
|
+
const eq = line.indexOf("=");
|
|
54
|
+
if (eq > 0) out[line.slice(0, eq)] = line.slice(eq + 1);
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
function readStdin() {
|
|
59
|
+
return new Promise((resolve) => {
|
|
60
|
+
let buf = "";
|
|
61
|
+
process.stdin.setEncoding("utf8");
|
|
62
|
+
process.stdin.on("data", (c) => buf += c);
|
|
63
|
+
process.stdin.on("end", () => resolve(buf));
|
|
64
|
+
process.stdin.on("error", () => resolve(buf));
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function ipc(msg) {
|
|
68
|
+
const path = gitcredSocketPath(resolveRoot());
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
const sock = createConnection(path);
|
|
71
|
+
let buf = "";
|
|
72
|
+
const fail = (error) => resolve({
|
|
73
|
+
ok: false,
|
|
74
|
+
error
|
|
75
|
+
});
|
|
76
|
+
sock.setTimeout(15e3, () => {
|
|
77
|
+
sock.destroy();
|
|
78
|
+
fail("daemon did not answer in time");
|
|
79
|
+
});
|
|
80
|
+
sock.on("connect", () => sock.write(JSON.stringify(msg) + "\n"));
|
|
81
|
+
sock.on("data", (c) => {
|
|
82
|
+
buf += c.toString("utf8");
|
|
83
|
+
const nl = buf.indexOf("\n");
|
|
84
|
+
if (nl === -1) return;
|
|
85
|
+
sock.destroy();
|
|
86
|
+
try {
|
|
87
|
+
resolve(JSON.parse(buf.slice(0, nl)));
|
|
88
|
+
} catch {
|
|
89
|
+
fail("malformed daemon reply");
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
sock.on("error", (e) => fail(`cannot reach the daemon socket at ${path}: ${e.message}`));
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { runGitCredential };
|
|
97
|
+
|
|
98
|
+
//# sourceMappingURL=git-credential-DWH0EUV6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-credential-DWH0EUV6.js","names":[],"sources":["../src/cli/git-credential.ts"],"sourcesContent":["/**\n * `agentconnect git-credential --agent <id>` — the git credential helper\n * (docs/designs/github-app-git-credentials.md §本地 helper 通道).\n *\n * Speaks git's credential-helper protocol on stdin/stdout and proxies to the\n * daemon's gitcred.sock; the token exists only on the reply pipe. Actions:\n * get → username=x-access-token / password=<token> (host must be github.com)\n * erase → forward to the daemon (invalidate the cached token git just had rejected)\n * store → no-op\n *\n * Exit style: on ANY failure print a human-actionable line to stderr and exit 1\n * — since #251 surfaces turn failures to end users, this text is user-facing.\n * NEVER print or log the token outside the protocol response.\n */\nimport { createConnection } from 'node:net'\nimport { resolveRoot } from '../paths.js'\nimport { gitcredSocketPath } from '../cp/gitcred-server.js'\n\ninterface HelperInput {\n protocol?: string\n host?: string\n path?: string\n password?: string\n}\n\nexport async function runGitCredential(action: string, agentId: string): Promise<void> {\n if (action === 'store') return // git offers the accepted credential back — nothing to do\n\n const input = parseStdin(await readStdin())\n\n if (action === 'erase') {\n await ipc({ op: 'erase', agentId, password: input.password }).catch(() => undefined) // best-effort\n return\n }\n if (action !== 'get') return // unknown actions are ignored per the helper contract\n\n if (input.host !== undefined && input.host.toLowerCase() !== 'github.com') {\n // Not ours — stay silent so git can try other helpers / fail cleanly.\n return\n }\n\n const res = await ipc({ op: 'get', agentId })\n if (!res.ok || !res.username || !res.password) {\n process.stderr.write(\n `agentconnect: no git credentials for agent ${agentId}: ${res.error ?? 'unknown error'}\\n` +\n `(the daemon must be running and connected to the control plane)\\n`\n )\n process.exitCode = 1\n return\n }\n // Path check is diagnostics-only (requires useHttpPath=true to even arrive):\n // token scope enforces the real boundary at GitHub. Tolerate case + .git +\n // LFS-ish subpaths; on a hard mismatch, hint at the rename story.\n if (input.path !== undefined) {\n const want = normalizeRepoPath(res.repoFullName ?? '')\n const got = normalizeRepoPath(input.path)\n if (want && got && got !== want && !got.startsWith(`${want}/`)) {\n process.stderr.write(\n `agentconnect: note — git asked for ${got} but this agent's repo is ${want} ` +\n `(repo renamed? recreate the agent to re-point it)\\n`\n )\n }\n }\n process.stdout.write(`username=${res.username}\\npassword=${res.password}\\n`)\n}\n\nfunction normalizeRepoPath(p: string): string {\n return p\n .replace(/^\\/+/, '')\n .replace(/\\.git$/i, '')\n .toLowerCase()\n}\n\nfunction parseStdin(text: string): HelperInput {\n const out: Record<string, string> = {}\n for (const line of text.split('\\n')) {\n const eq = line.indexOf('=')\n if (eq > 0) out[line.slice(0, eq)] = line.slice(eq + 1)\n }\n return out\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let buf = ''\n process.stdin.setEncoding('utf8')\n process.stdin.on('data', (c) => (buf += c))\n process.stdin.on('end', () => resolve(buf))\n process.stdin.on('error', () => resolve(buf))\n })\n}\n\ninterface IpcReply {\n ok: boolean\n username?: string\n password?: string\n repoFullName?: string\n error?: string\n}\n\nfunction ipc(msg: unknown): Promise<IpcReply> {\n const path = gitcredSocketPath(resolveRoot())\n return new Promise((resolve) => {\n const sock = createConnection(path)\n let buf = ''\n const fail = (error: string) => resolve({ ok: false, error })\n sock.setTimeout(15_000, () => {\n sock.destroy()\n fail('daemon did not answer in time')\n })\n sock.on('connect', () => sock.write(JSON.stringify(msg) + '\\n'))\n sock.on('data', (c) => {\n buf += c.toString('utf8')\n const nl = buf.indexOf('\\n')\n if (nl === -1) return\n sock.destroy()\n try {\n resolve(JSON.parse(buf.slice(0, nl)) as IpcReply)\n } catch {\n fail('malformed daemon reply')\n }\n })\n sock.on('error', (e) => fail(`cannot reach the daemon socket at ${path}: ${e.message}`))\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAyBA,eAAsB,iBAAiB,QAAgB,SAAgC;CACrF,IAAI,WAAW,SAAS;CAExB,MAAM,QAAQ,WAAW,MAAM,UAAU,CAAC;CAE1C,IAAI,WAAW,SAAS;EACtB,MAAM,IAAI;GAAE,IAAI;GAAS;GAAS,UAAU,MAAM;EAAS,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;EACnF;CACF;CACA,IAAI,WAAW,OAAO;CAEtB,IAAI,MAAM,SAAS,KAAA,KAAa,MAAM,KAAK,YAAY,MAAM,cAE3D;CAGF,MAAM,MAAM,MAAM,IAAI;EAAE,IAAI;EAAO;CAAQ,CAAC;CAC5C,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,YAAY,CAAC,IAAI,UAAU;EAC7C,QAAQ,OAAO,MACb,8CAA8C,QAAQ,IAAI,IAAI,SAAS,gBAAgB,oEAEzF;EACA,QAAQ,WAAW;EACnB;CACF;CAIA,IAAI,MAAM,SAAS,KAAA,GAAW;EAC5B,MAAM,OAAO,kBAAkB,IAAI,gBAAgB,EAAE;EACrD,MAAM,MAAM,kBAAkB,MAAM,IAAI;EACxC,IAAI,QAAQ,OAAO,QAAQ,QAAQ,CAAC,IAAI,WAAW,GAAG,KAAK,EAAE,GAC3D,QAAQ,OAAO,MACb,sCAAsC,IAAI,4BAA4B,KAAK,qDAE7E;CAEJ;CACA,QAAQ,OAAO,MAAM,YAAY,IAAI,SAAS,aAAa,IAAI,SAAS,GAAG;AAC7E;AAEA,SAAS,kBAAkB,GAAmB;CAC5C,OAAO,EACJ,QAAQ,QAAQ,EAAE,CAAC,CACnB,QAAQ,WAAW,EAAE,CAAC,CACtB,YAAY;AACjB;AAEA,SAAS,WAAW,MAA2B;CAC7C,MAAM,MAA8B,CAAC;CACrC,KAAK,MAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;EACnC,MAAM,KAAK,KAAK,QAAQ,GAAG;EAC3B,IAAI,KAAK,GAAG,IAAI,KAAK,MAAM,GAAG,EAAE,KAAK,KAAK,MAAM,KAAK,CAAC;CACxD;CACA,OAAO;AACT;AAEA,SAAS,YAA6B;CACpC,OAAO,IAAI,SAAS,YAAY;EAC9B,IAAI,MAAM;EACV,QAAQ,MAAM,YAAY,MAAM;EAChC,QAAQ,MAAM,GAAG,SAAS,MAAO,OAAO,CAAE;EAC1C,QAAQ,MAAM,GAAG,aAAa,QAAQ,GAAG,CAAC;EAC1C,QAAQ,MAAM,GAAG,eAAe,QAAQ,GAAG,CAAC;CAC9C,CAAC;AACH;AAUA,SAAS,IAAI,KAAiC;CAC5C,MAAM,OAAO,kBAAkB,YAAY,CAAC;CAC5C,OAAO,IAAI,SAAS,YAAY;EAC9B,MAAM,OAAO,iBAAiB,IAAI;EAClC,IAAI,MAAM;EACV,MAAM,QAAQ,UAAkB,QAAQ;GAAE,IAAI;GAAO;EAAM,CAAC;EAC5D,KAAK,WAAW,YAAc;GAC5B,KAAK,QAAQ;GACb,KAAK,+BAA+B;EACtC,CAAC;EACD,KAAK,GAAG,iBAAiB,KAAK,MAAM,KAAK,UAAU,GAAG,IAAI,IAAI,CAAC;EAC/D,KAAK,GAAG,SAAS,MAAM;GACrB,OAAO,EAAE,SAAS,MAAM;GACxB,MAAM,KAAK,IAAI,QAAQ,IAAI;GAC3B,IAAI,OAAO,IAAI;GACf,KAAK,QAAQ;GACb,IAAI;IACF,QAAQ,KAAK,MAAM,IAAI,MAAM,GAAG,EAAE,CAAC,CAAa;GAClD,QAAQ;IACN,KAAK,wBAAwB;GAC/B;EACF,CAAC;EACD,KAAK,GAAG,UAAU,MAAM,KAAK,qCAAqC,KAAK,IAAI,EAAE,SAAS,CAAC;CACzF,CAAC;AACH"}
|