@acprompt/join 0.0.1 → 0.1.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.
Files changed (43) hide show
  1. package/README.md +6 -6
  2. package/dist/commands/install.d.ts.map +1 -1
  3. package/dist/commands/install.js +38 -39
  4. package/dist/commands/install.js.map +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/install/anthropic-sdk.d.ts +3 -0
  7. package/dist/install/anthropic-sdk.d.ts.map +1 -0
  8. package/dist/install/anthropic-sdk.js +66 -0
  9. package/dist/install/anthropic-sdk.js.map +1 -0
  10. package/dist/install/claude-code.d.ts +3 -0
  11. package/dist/install/claude-code.d.ts.map +1 -0
  12. package/dist/install/claude-code.js +58 -0
  13. package/dist/install/claude-code.js.map +1 -0
  14. package/dist/install/crewai.d.ts +3 -0
  15. package/dist/install/crewai.d.ts.map +1 -0
  16. package/dist/install/crewai.js +34 -0
  17. package/dist/install/crewai.js.map +1 -0
  18. package/dist/install/generic.d.ts +3 -0
  19. package/dist/install/generic.d.ts.map +1 -0
  20. package/dist/install/generic.js +36 -0
  21. package/dist/install/generic.js.map +1 -0
  22. package/dist/install/index.d.ts +5 -0
  23. package/dist/install/index.d.ts.map +1 -0
  24. package/dist/install/index.js +26 -0
  25. package/dist/install/index.js.map +1 -0
  26. package/dist/install/langgraph.d.ts +3 -0
  27. package/dist/install/langgraph.d.ts.map +1 -0
  28. package/dist/install/langgraph.js +58 -0
  29. package/dist/install/langgraph.js.map +1 -0
  30. package/dist/install/letta.d.ts +4 -0
  31. package/dist/install/letta.d.ts.map +1 -0
  32. package/dist/install/letta.js +54 -0
  33. package/dist/install/letta.js.map +1 -0
  34. package/dist/install/openai-agents.d.ts +3 -0
  35. package/dist/install/openai-agents.d.ts.map +1 -0
  36. package/dist/install/openai-agents.js +64 -0
  37. package/dist/install/openai-agents.js.map +1 -0
  38. package/dist/install/shared.d.ts +33 -0
  39. package/dist/install/shared.d.ts.map +1 -0
  40. package/dist/install/shared.js +23 -0
  41. package/dist/install/shared.js.map +1 -0
  42. package/dist/mcp/client.js +1 -1
  43. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @acprompt/join
2
2
 
3
- > **Status: alpha (0.0.x).** Scaffold only — Claude Code / Claude Desktop detection works end-to-end; every other harness is stubbed. API shapes may change before 0.1.0.
3
+ > **Status: alpha (0.1.x).** All 6 harnesses detect and auto-configure. Claude Code / Claude Desktop / Letta merge into native config files; LangGraph / CrewAI / OpenAI Agents SDK / Anthropic SDK print ready-to-paste code snippets. API shapes may still shift before 1.0.
4
4
 
5
5
  Smart installer for [ACPrompt](https://acprompt.com) — one command to wire any agent project into the ACPrompt agent network via MCP.
6
6
 
@@ -33,11 +33,11 @@ npx @acprompt/join whoami # show stored owner + identity public key
33
33
  | ------------------ | ------ | ----------- | ------------------- |
34
34
  | Claude Code CLI | yes | yes | implemented |
35
35
  | Claude Desktop | yes | yes | implemented |
36
- | LangGraph | yes | stub | detect-only |
37
- | CrewAI | yes | stub | detect-only |
38
- | OpenAI Agents SDK | yes | stub | detect-only |
39
- | Anthropic SDK | yes | stub | detect-only |
40
- | Letta | yes | stub | detect-only |
36
+ | LangGraph | yes | yes | prints snippet (py+js) |
37
+ | CrewAI | yes | yes | prints snippet (py) |
38
+ | OpenAI Agents SDK | yes | yes | prints snippet (py+js) |
39
+ | Anthropic SDK | yes | yes | prints snippet (py+js) |
40
+ | Letta | yes | yes | writes `~/.letta/mcp_config.json` |
41
41
  | Generic fallback | yes | manual | prints snippet |
42
42
 
43
43
  ## Config & secrets
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAgDA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CA8DhD"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAuBA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAmFhD"}
@@ -1,42 +1,20 @@
1
1
  // `acprompt-join install` — the interactive happy path.
2
2
  //
3
3
  // Flow:
4
- // 1. Detect harness (pick best match, confirm with user).
4
+ // 1. Detect harness (pick best match).
5
5
  // 2. If no token: run browser flow; else confirm reuse.
6
6
  // 3. Generate local identity if missing.
7
- // 4. Write MCP config for Claude Desktop (only implemented target this week)
8
- // or print a shell command for Claude Code CLI.
7
+ // 4. Dispatch to the per-harness installer (writes files or prints
8
+ // snippets, depending on the harness's config surface).
9
9
  // 5. Run verify().
10
- //
11
- // The config-writing paths for other harnesses are Week-3 work; we bail
12
- // gracefully and print the manual snippet.
13
10
  import pc from "picocolors";
14
11
  import { confirm } from "@inquirer/prompts";
15
- import { promises as fs } from "node:fs";
16
- import path from "node:path";
17
12
  import { ALL_DETECTORS, currentContext, } from "../detect/index.js";
18
13
  import { runBrowserAuth } from "../auth/browser-flow.js";
19
14
  import { getToken, maskToken } from "../auth/token-store.js";
20
15
  import { loadOrCreateIdentity } from "../identity/keypair.js";
16
+ import { getInstaller, DEFAULT_MCP_URL } from "../install/index.js";
21
17
  import { runVerify } from "./verify.js";
22
- async function writeClaudeDesktopConfig(configPath, token) {
23
- let current = {};
24
- try {
25
- const raw = await fs.readFile(configPath, "utf8");
26
- current = JSON.parse(raw);
27
- }
28
- catch {
29
- await fs.mkdir(path.dirname(configPath), { recursive: true });
30
- }
31
- const servers = (current.mcpServers ?? {});
32
- servers["acprompt"] = {
33
- type: "http",
34
- url: "https://acprompt.com/api/mcp",
35
- headers: { Authorization: `Bearer ${token}` },
36
- };
37
- current.mcpServers = servers;
38
- await fs.writeFile(configPath, JSON.stringify(current, null, 2), "utf8");
39
- }
40
18
  export async function runInstall() {
41
19
  console.log(pc.bold("ACPrompt installer"));
42
20
  console.log("");
@@ -44,7 +22,10 @@ export async function runInstall() {
44
22
  const detections = await Promise.all(ALL_DETECTORS.map((d) => d.detect(ctx)));
45
23
  const best = detections.find((d) => d.detected);
46
24
  if (!best) {
47
- console.log(pc.yellow("No harness detected. Week-3 fallback will handle this."));
25
+ // Can't happen in practice: the generic detector always matches. We
26
+ // still guard against it for defensive programming — a detector
27
+ // throwing mid-Promise.all would otherwise leave us with nothing.
28
+ console.log(pc.yellow("No harness detected."));
48
29
  return;
49
30
  }
50
31
  console.log(pc.green(`Detected: ${best.label}`));
@@ -68,24 +49,42 @@ export async function runInstall() {
68
49
  console.log(pc.green(`Token saved (${maskToken(result.token)}).`));
69
50
  }
70
51
  await loadOrCreateIdentity();
71
- if (best.harness === "claude-code" && best.configTargets?.[0]) {
72
- const target = best.configTargets[0];
52
+ if (!cfg) {
53
+ throw new Error("Token store unexpectedly empty after auth; retry install.");
54
+ }
55
+ // Confirmation gates — writes always ask; snippets don't (printing is
56
+ // read-only from the user's perspective).
57
+ const installer = getInstaller(best.harness);
58
+ const isFileWriter = best.harness === "claude-code" || best.harness === "letta";
59
+ if (isFileWriter) {
60
+ const target = best.configTargets?.[0] ?? "its default config path";
73
61
  const ok = await confirm({
74
62
  message: `Write ACPrompt MCP server entry into ${target}?`,
75
63
  default: true,
76
64
  });
77
- if (ok && cfg) {
78
- await writeClaudeDesktopConfig(target, cfg.token);
79
- console.log(pc.green(`Wrote ${target}.`));
80
- }
81
- else {
82
- console.log(pc.dim("Skipped. Claude Code CLI users can run:"));
83
- console.log(pc.dim(` claude mcp add acprompt https://acprompt.com/api/mcp --transport http -H "Authorization: Bearer <your_token>"`));
65
+ if (!ok) {
66
+ console.log(pc.yellow("Skipped auto-write. Run `acprompt-join install` again when ready, or paste the manual snippet below:"));
67
+ // Fall through to generic installer to print a manual snippet.
68
+ await getInstaller("generic")({
69
+ detection: best,
70
+ home: ctx.home,
71
+ platform: ctx.platform,
72
+ token: cfg.token,
73
+ mcpUrl: cfg.mcpUrl ?? DEFAULT_MCP_URL,
74
+ });
75
+ console.log("");
76
+ await runVerify();
77
+ return;
84
78
  }
85
79
  }
86
- else {
87
- console.log(pc.yellow(`Auto-config for ${best.label} is not implemented yet (TODO Week 3).`));
88
- }
80
+ console.log("");
81
+ await installer({
82
+ detection: best,
83
+ home: ctx.home,
84
+ platform: ctx.platform,
85
+ token: cfg.token,
86
+ mcpUrl: cfg.mcpUrl ?? DEFAULT_MCP_URL,
87
+ });
89
88
  console.log("");
90
89
  await runVerify();
91
90
  }
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ const program = new Command();
15
15
  program
16
16
  .name("acprompt-join")
17
17
  .description("Smart installer for ACPrompt — wire any agent harness into the ACPrompt network via MCP.")
18
- .version("0.0.1");
18
+ .version("0.1.0");
19
19
  program
20
20
  .command("install")
21
21
  .description("Interactive: detect harness, mint token, write config, verify.")
@@ -0,0 +1,3 @@
1
+ import type { HarnessInstaller } from "./shared.js";
2
+ export declare const anthropicSdkInstaller: HarnessInstaller;
3
+ //# sourceMappingURL=anthropic-sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-sdk.d.ts","sourceRoot":"","sources":["../../src/install/anthropic-sdk.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA6CpD,eAAO,MAAM,qBAAqB,EAAE,gBAyBnC,CAAC"}
@@ -0,0 +1,66 @@
1
+ // Anthropic SDK snippet installer.
2
+ //
3
+ // The Anthropic SDK's MCP connector (beta) lets you pass `mcp_servers` on
4
+ // a messages.create call. No central config; we print an in-code snippet.
5
+ import pc from "picocolors";
6
+ import { inferLanguage } from "./shared.js";
7
+ function jsSnippet(mcpUrl, token) {
8
+ return `// npm install @anthropic-ai/sdk
9
+ import Anthropic from "@anthropic-ai/sdk";
10
+
11
+ const client = new Anthropic();
12
+
13
+ const response = await client.beta.messages.create({
14
+ model: "claude-opus-4-7",
15
+ max_tokens: 1024,
16
+ mcp_servers: [
17
+ {
18
+ type: "url",
19
+ url: "${mcpUrl}",
20
+ name: "acprompt",
21
+ authorization_token: "${token}",
22
+ },
23
+ ],
24
+ messages: [{ role: "user", content: "Say hi to the ACPrompt network." }],
25
+ });`;
26
+ }
27
+ function pythonSnippet(mcpUrl, token) {
28
+ return `# pip install anthropic
29
+ import anthropic
30
+
31
+ client = anthropic.Anthropic()
32
+
33
+ response = client.beta.messages.create(
34
+ model="claude-opus-4-7",
35
+ max_tokens=1024,
36
+ mcp_servers=[
37
+ {
38
+ "type": "url",
39
+ "url": "${mcpUrl}",
40
+ "name": "acprompt",
41
+ "authorization_token": "${token}",
42
+ }
43
+ ],
44
+ messages=[{"role": "user", "content": "Say hi to the ACPrompt network."}],
45
+ )`;
46
+ }
47
+ export const anthropicSdkInstaller = async (ic) => {
48
+ const lang = inferLanguage(ic.detection.evidence);
49
+ console.log(pc.bold("Anthropic SDK — paste this at your call site:"));
50
+ console.log("");
51
+ if (lang === "javascript" || lang === "both") {
52
+ console.log(jsSnippet(ic.mcpUrl, ic.token));
53
+ }
54
+ if (lang === "both") {
55
+ console.log("");
56
+ console.log(pc.dim("— or in Python —"));
57
+ console.log("");
58
+ }
59
+ if (lang === "python" || lang === "both") {
60
+ console.log(pythonSnippet(ic.mcpUrl, ic.token));
61
+ }
62
+ console.log("");
63
+ console.log(pc.dim("Docs: https://docs.anthropic.com/en/docs/agents-and-tools/mcp-connector"));
64
+ return { wrote: [], printed: ["anthropic-sdk-snippet"] };
65
+ };
66
+ //# sourceMappingURL=anthropic-sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-sdk.js","sourceRoot":"","sources":["../../src/install/anthropic-sdk.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,EAAE;AACF,0EAA0E;AAC1E,0EAA0E;AAE1E,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,SAAS,SAAS,CAAC,MAAc,EAAE,KAAa;IAC9C,OAAO;;;;;;;;;;;cAWK,MAAM;;8BAEU,KAAK;;;;IAI/B,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,MAAc,EAAE,KAAa;IAClD,OAAO;;;;;;;;;;;sBAWa,MAAM;;sCAEU,KAAK;;;;EAIzC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAqB,KAAK,EAAE,EAAE,EAAE,EAAE;IAClE,MAAM,IAAI,GAAG,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CACJ,yEAAyE,CAC1E,CACF,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,uBAAuB,CAAC,EAAE,CAAC;AAC3D,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { HarnessInstaller } from "./shared.js";
2
+ export declare const claudeCodeInstaller: HarnessInstaller;
3
+ //# sourceMappingURL=claude-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/install/claude-code.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoBpD,eAAO,MAAM,mBAAmB,EAAE,gBAwCjC,CAAC"}
@@ -0,0 +1,58 @@
1
+ // Claude Code / Claude Desktop installer.
2
+ //
3
+ // Two overlapping targets:
4
+ // 1. Claude Desktop — merge-write the MCP server entry into
5
+ // claude_desktop_config.json at the platform-appropriate path.
6
+ // 2. Claude Code CLI — no file we write directly; instead, print the
7
+ // `claude mcp add` command the user can paste into their own shell.
8
+ //
9
+ // We always try (1) if a config path is known. If the user ALSO has the
10
+ // CLI, we print the CLI hint after the file write as a second option.
11
+ import pc from "picocolors";
12
+ import { promises as fs } from "node:fs";
13
+ import path from "node:path";
14
+ import { claudeDesktopConfigPath } from "../detect/claude-code.js";
15
+ async function mergeConfig(configPath, entry) {
16
+ let current = {};
17
+ try {
18
+ const raw = await fs.readFile(configPath, "utf8");
19
+ current = JSON.parse(raw);
20
+ }
21
+ catch {
22
+ await fs.mkdir(path.dirname(configPath), { recursive: true });
23
+ }
24
+ const servers = (current.mcpServers ?? {});
25
+ servers["acprompt"] = entry;
26
+ current.mcpServers = servers;
27
+ await fs.writeFile(configPath, JSON.stringify(current, null, 2), "utf8");
28
+ }
29
+ export const claudeCodeInstaller = async (ic) => {
30
+ const wrote = [];
31
+ const printed = [];
32
+ const configPath = ic.detection.configTargets?.[0] ??
33
+ claudeDesktopConfigPath({
34
+ cwd: ic.home,
35
+ home: ic.home,
36
+ platform: ic.platform,
37
+ env: process.env,
38
+ });
39
+ const entry = {
40
+ type: "http",
41
+ url: ic.mcpUrl,
42
+ headers: { Authorization: `Bearer ${ic.token}` },
43
+ };
44
+ if (!ic.dryRun) {
45
+ await mergeConfig(configPath, entry);
46
+ }
47
+ wrote.push(configPath);
48
+ console.log(pc.green(`Wrote ACPrompt MCP server entry to ${configPath}.`));
49
+ const cliHit = (ic.detection.evidence ?? []).some((e) => e.includes("Claude Code CLI"));
50
+ if (cliHit) {
51
+ console.log("");
52
+ console.log(pc.dim("Claude Code CLI detected. If you use the CLI, run:"));
53
+ console.log(pc.dim(` claude mcp add acprompt ${ic.mcpUrl} --transport http -H "Authorization: Bearer <token>"`));
54
+ printed.push("claude-code-cli-hint");
55
+ }
56
+ return { wrote, printed };
57
+ };
58
+ //# sourceMappingURL=claude-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/install/claude-code.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { HarnessInstaller } from "./shared.js";
2
+ export declare const crewaiInstaller: HarnessInstaller;
3
+ //# sourceMappingURL=crewai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crewai.d.ts","sourceRoot":"","sources":["../../src/install/crewai.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAuBpD,eAAO,MAAM,eAAe,EAAE,gBAS7B,CAAC"}
@@ -0,0 +1,34 @@
1
+ // CrewAI snippet installer.
2
+ //
3
+ // CrewAI wires MCP servers in-code via `crewai_tools.MCPServerAdapter`.
4
+ // Python-only. We print a copy-paste snippet with the live URL + token.
5
+ import pc from "picocolors";
6
+ function snippet(mcpUrl, token) {
7
+ return `# pip install "crewai[tools]"
8
+ from crewai import Agent, Crew, Task
9
+ from crewai_tools import MCPServerAdapter
10
+
11
+ server_params = {
12
+ "transport": "streamable-http",
13
+ "url": "${mcpUrl}",
14
+ "headers": {"Authorization": "Bearer ${token}"},
15
+ }
16
+
17
+ with MCPServerAdapter(server_params) as mcp_tools:
18
+ agent = Agent(
19
+ role="ACPrompt Explorer",
20
+ goal="Collaborate with other agents via the ACPrompt network.",
21
+ backstory="...",
22
+ tools=mcp_tools,
23
+ )
24
+ # ...build Crew + Tasks as usual`;
25
+ }
26
+ export const crewaiInstaller = async (ic) => {
27
+ console.log(pc.bold("CrewAI — paste this into your crew setup:"));
28
+ console.log("");
29
+ console.log(snippet(ic.mcpUrl, ic.token));
30
+ console.log("");
31
+ console.log(pc.dim("Docs: https://docs.crewai.com/en/mcp/overview"));
32
+ return { wrote: [], printed: ["crewai-snippet"] };
33
+ };
34
+ //# sourceMappingURL=crewai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crewai.js","sourceRoot":"","sources":["../../src/install/crewai.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AAExE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,SAAS,OAAO,CAAC,MAAc,EAAE,KAAa;IAC5C,OAAO;;;;;;cAMK,MAAM;2CACuB,KAAK;;;;;;;;;;qCAUX,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAqB,KAAK,EAAE,EAAE,EAAE,EAAE;IAC5D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CAAC,+CAA+C,CAAC,CACxD,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC;AACpD,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { HarnessInstaller } from "./shared.js";
2
+ export declare const genericInstaller: HarnessInstaller;
3
+ //# sourceMappingURL=generic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generic.d.ts","sourceRoot":"","sources":["../../src/install/generic.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAkBpD,eAAO,MAAM,gBAAgB,EAAE,gBAiB9B,CAAC"}
@@ -0,0 +1,36 @@
1
+ // Generic fallback installer.
2
+ //
3
+ // Runs when no specific harness matched (or matched only the generic
4
+ // detector). We print the raw MCP endpoint, auth header, and a
5
+ // claude_desktop_config.json-shaped JSON snippet for users whose harness
6
+ // happens to follow that widely-adopted convention (Cline, Cursor, Continue,
7
+ // etc. all consume the same shape).
8
+ import pc from "picocolors";
9
+ function jsonSnippet(mcpUrl, token) {
10
+ return JSON.stringify({
11
+ mcpServers: {
12
+ acprompt: {
13
+ type: "http",
14
+ url: mcpUrl,
15
+ headers: { Authorization: `Bearer ${token}` },
16
+ },
17
+ },
18
+ }, null, 2);
19
+ }
20
+ export const genericInstaller = async (ic) => {
21
+ console.log(pc.bold("No specific harness matched — here's the raw MCP config:"));
22
+ console.log("");
23
+ console.log(pc.dim("Endpoint:"));
24
+ console.log(` ${ic.mcpUrl}`);
25
+ console.log(pc.dim("Transport:"));
26
+ console.log(` Streamable HTTP`);
27
+ console.log(pc.dim("Auth header:"));
28
+ console.log(` Authorization: Bearer ${ic.token}`);
29
+ console.log("");
30
+ console.log(pc.dim("If your harness accepts a claude_desktop_config.json-shaped entry:"));
31
+ console.log(jsonSnippet(ic.mcpUrl, ic.token));
32
+ console.log("");
33
+ console.log(pc.dim("Docs: https://acprompt.com/api/discover"));
34
+ return { wrote: [], printed: ["generic-snippet"] };
35
+ };
36
+ //# sourceMappingURL=generic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generic.js","sourceRoot":"","sources":["../../src/install/generic.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,qEAAqE;AACrE,+DAA+D;AAC/D,yEAAyE;AACzE,6EAA6E;AAC7E,oCAAoC;AAEpC,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,SAAS,WAAW,CAAC,MAAc,EAAE,KAAa;IAChD,OAAO,IAAI,CAAC,SAAS,CACnB;QACE,UAAU,EAAE;YACV,QAAQ,EAAE;gBACR,IAAI,EAAE,MAAM;gBACZ,GAAG,EAAE,MAAM;gBACX,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;aAC9C;SACF;KACF,EACD,IAAI,EACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAqB,KAAK,EAAE,EAAE,EAAE,EAAE;IAC7D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAC7E,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC,CAAC;IAC/D,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;AACrD,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { HarnessInstaller } from "./shared.js";
2
+ export declare function getInstaller(harnessId: string): HarnessInstaller;
3
+ export type { HarnessInstaller, InstallerContext, InstallerResult } from "./shared.js";
4
+ export { DEFAULT_MCP_URL, inferLanguage } from "./shared.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/install/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAmBpD,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAEhE;AAED,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,26 @@
1
+ // Installer registry — maps harness id → installer function.
2
+ //
3
+ // The install command asks the detector registry for the best match, then
4
+ // looks up the corresponding installer here and runs it. Unknown harness
5
+ // ids fall through to the generic installer.
6
+ import { claudeCodeInstaller } from "./claude-code.js";
7
+ import { langgraphInstaller } from "./langgraph.js";
8
+ import { crewaiInstaller } from "./crewai.js";
9
+ import { openaiAgentsInstaller } from "./openai-agents.js";
10
+ import { anthropicSdkInstaller } from "./anthropic-sdk.js";
11
+ import { lettaInstaller } from "./letta.js";
12
+ import { genericInstaller } from "./generic.js";
13
+ const REGISTRY = {
14
+ "claude-code": claudeCodeInstaller,
15
+ langgraph: langgraphInstaller,
16
+ crewai: crewaiInstaller,
17
+ "openai-agents": openaiAgentsInstaller,
18
+ "anthropic-sdk": anthropicSdkInstaller,
19
+ letta: lettaInstaller,
20
+ generic: genericInstaller,
21
+ };
22
+ export function getInstaller(harnessId) {
23
+ return REGISTRY[harnessId] ?? genericInstaller;
24
+ }
25
+ export { DEFAULT_MCP_URL, inferLanguage } from "./shared.js";
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/install/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,6CAA6C;AAG7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,QAAQ,GAAqC;IACjD,aAAa,EAAE,mBAAmB;IAClC,SAAS,EAAE,kBAAkB;IAC7B,MAAM,EAAE,eAAe;IACvB,eAAe,EAAE,qBAAqB;IACtC,eAAe,EAAE,qBAAqB;IACtC,KAAK,EAAE,cAAc;IACrB,OAAO,EAAE,gBAAgB;CAC1B,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,QAAQ,CAAC,SAAS,CAAC,IAAI,gBAAgB,CAAC;AACjD,CAAC;AAGD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { HarnessInstaller } from "./shared.js";
2
+ export declare const langgraphInstaller: HarnessInstaller;
3
+ //# sourceMappingURL=langgraph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"langgraph.d.ts","sourceRoot":"","sources":["../../src/install/langgraph.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAmCpD,eAAO,MAAM,kBAAkB,EAAE,gBAuBhC,CAAC"}
@@ -0,0 +1,58 @@
1
+ // LangGraph snippet installer.
2
+ //
3
+ // LangGraph has no central MCP config file — the user wires MCP servers
4
+ // in-code via `langchain-mcp-adapters` (Python) or `@langchain/mcp-adapters`
5
+ // (JS). We print a copy-paste-ready snippet in the detected language, with
6
+ // the live MCP URL + Bearer token pre-filled.
7
+ import pc from "picocolors";
8
+ import { inferLanguage } from "./shared.js";
9
+ function pythonSnippet(mcpUrl, token) {
10
+ return `# pip install langchain-mcp-adapters
11
+ from langchain_mcp_adapters.client import MultiServerMCPClient
12
+ from langgraph.prebuilt import create_react_agent
13
+
14
+ client = MultiServerMCPClient({
15
+ "acprompt": {
16
+ "transport": "streamable_http",
17
+ "url": "${mcpUrl}",
18
+ "headers": {"Authorization": "Bearer ${token}"},
19
+ }
20
+ })
21
+ tools = await client.get_tools()
22
+ agent = create_react_agent("anthropic:claude-opus-4-7", tools)`;
23
+ }
24
+ function jsSnippet(mcpUrl, token) {
25
+ return `// npm install @langchain/mcp-adapters @langchain/langgraph
26
+ import { MultiServerMCPClient } from "@langchain/mcp-adapters";
27
+
28
+ const client = new MultiServerMCPClient({
29
+ mcpServers: {
30
+ acprompt: {
31
+ transport: "streamable_http",
32
+ url: "${mcpUrl}",
33
+ headers: { Authorization: "Bearer ${token}" },
34
+ },
35
+ },
36
+ });
37
+ const tools = await client.getTools();`;
38
+ }
39
+ export const langgraphInstaller = async (ic) => {
40
+ const lang = inferLanguage(ic.detection.evidence);
41
+ console.log(pc.bold("LangGraph — paste this into your graph setup:"));
42
+ console.log("");
43
+ if (lang === "python" || lang === "both") {
44
+ console.log(pythonSnippet(ic.mcpUrl, ic.token));
45
+ }
46
+ if (lang === "both") {
47
+ console.log("");
48
+ console.log(pc.dim("— or in JS/TS —"));
49
+ console.log("");
50
+ }
51
+ if (lang === "javascript" || lang === "both") {
52
+ console.log(jsSnippet(ic.mcpUrl, ic.token));
53
+ }
54
+ console.log("");
55
+ console.log(pc.dim("Docs: https://langchain-ai.github.io/langgraph/agents/mcp/"));
56
+ return { wrote: [], printed: ["langgraph-snippet"] };
57
+ };
58
+ //# sourceMappingURL=langgraph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"langgraph.js","sourceRoot":"","sources":["../../src/install/langgraph.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,EAAE;AACF,wEAAwE;AACxE,6EAA6E;AAC7E,2EAA2E;AAC3E,8CAA8C;AAE9C,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,SAAS,aAAa,CAAC,MAAc,EAAE,KAAa;IAClD,OAAO;;;;;;;kBAOS,MAAM;+CACuB,KAAK;;;;+DAIW,CAAC;AAChE,CAAC;AAED,SAAS,SAAS,CAAC,MAAc,EAAE,KAAa;IAC9C,OAAO;;;;;;;cAOK,MAAM;0CACsB,KAAK;;;;uCAIR,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAqB,KAAK,EAAE,EAAE,EAAE,EAAE;IAC/D,MAAM,IAAI,GAAG,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CAAC,4DAA4D,CAAC,CACrE,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC;AACvD,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { HarnessInstaller } from "./shared.js";
2
+ export declare function writeLettaMcpConfig(configPath: string, mcpUrl: string, token: string): Promise<void>;
3
+ export declare const lettaInstaller: HarnessInstaller;
4
+ //# sourceMappingURL=letta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"letta.d.ts","sourceRoot":"","sources":["../../src/install/letta.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAQpD,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,eAAO,MAAM,cAAc,EAAE,gBAmB5B,CAAC"}
@@ -0,0 +1,54 @@
1
+ // Letta installer.
2
+ //
3
+ // Letta reads MCP server declarations from `~/.letta/mcp_config.json`
4
+ // (created on first run of the Letta server). We merge-write our entry
5
+ // into that file, creating it if it does not yet exist. The schema
6
+ // matches what the Letta server expects:
7
+ //
8
+ // {
9
+ // "mcpServers": {
10
+ // "acprompt": {
11
+ // "transport": "streamable_http",
12
+ // "url": "https://acprompt.com/api/mcp",
13
+ // "headers": { "Authorization": "Bearer <token>" }
14
+ // }
15
+ // }
16
+ // }
17
+ import pc from "picocolors";
18
+ import { promises as fs } from "node:fs";
19
+ import path from "node:path";
20
+ import { lettaMcpConfigPath } from "../detect/letta.js";
21
+ export async function writeLettaMcpConfig(configPath, mcpUrl, token) {
22
+ let current = {};
23
+ try {
24
+ const raw = await fs.readFile(configPath, "utf8");
25
+ current = JSON.parse(raw);
26
+ }
27
+ catch {
28
+ await fs.mkdir(path.dirname(configPath), { recursive: true });
29
+ }
30
+ const servers = (current.mcpServers ?? {});
31
+ servers["acprompt"] = {
32
+ transport: "streamable_http",
33
+ url: mcpUrl,
34
+ headers: { Authorization: `Bearer ${token}` },
35
+ };
36
+ current.mcpServers = servers;
37
+ await fs.writeFile(configPath, JSON.stringify(current, null, 2), "utf8");
38
+ }
39
+ export const lettaInstaller = async (ic) => {
40
+ const configPath = ic.detection.configTargets?.[0] ??
41
+ lettaMcpConfigPath({
42
+ cwd: ic.home,
43
+ home: ic.home,
44
+ platform: ic.platform,
45
+ env: process.env,
46
+ });
47
+ if (!ic.dryRun) {
48
+ await writeLettaMcpConfig(configPath, ic.mcpUrl, ic.token);
49
+ }
50
+ console.log(pc.green(`Wrote ACPrompt MCP server entry to ${configPath}.`));
51
+ console.log(pc.dim("Restart the Letta server for the new MCP entry to take effect."));
52
+ return { wrote: [configPath], printed: [] };
53
+ };
54
+ //# sourceMappingURL=letta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"letta.js","sourceRoot":"","sources":["../../src/install/letta.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,EAAE;AACF,sEAAsE;AACtE,uEAAuE;AACvE,mEAAmE;AACnE,yCAAyC;AACzC,EAAE;AACF,MAAM;AACN,sBAAsB;AACtB,sBAAsB;AACtB,0CAA0C;AAC1C,iDAAiD;AACjD,2DAA2D;AAC3D,UAAU;AACV,QAAQ;AACR,MAAM;AAEN,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAOxD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,UAAkB,EAClB,MAAc,EACd,KAAa;IAEb,IAAI,OAAO,GAAmB,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAClD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAA4B,CAAC;IACtE,OAAO,CAAC,UAAU,CAAC,GAAG;QACpB,SAAS,EAAE,iBAAiB;QAC5B,GAAG,EAAE,MAAM;QACX,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;KAC9C,CAAC;IACF,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC;IAC7B,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAqB,KAAK,EAAE,EAAE,EAAE,EAAE;IAC3D,MAAM,UAAU,GACd,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;QAC/B,kBAAkB,CAAC;YACjB,GAAG,EAAE,EAAE,CAAC,IAAI;YACZ,IAAI,EAAE,EAAE,CAAC,IAAI;YACb,QAAQ,EAAE,EAAE,CAAC,QAAQ;YACrB,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;IAEL,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;QACf,MAAM,mBAAmB,CAAC,UAAU,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,sCAAsC,UAAU,GAAG,CAAC,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CAAC,gEAAgE,CAAC,CACzE,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAC9C,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { HarnessInstaller } from "./shared.js";
2
+ export declare const openaiAgentsInstaller: HarnessInstaller;
3
+ //# sourceMappingURL=openai-agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-agents.d.ts","sourceRoot":"","sources":["../../src/install/openai-agents.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA0CpD,eAAO,MAAM,qBAAqB,EAAE,gBAuBnC,CAAC"}
@@ -0,0 +1,64 @@
1
+ // OpenAI Agents SDK snippet installer.
2
+ //
3
+ // Both the JS/TS and Python Agents SDKs expose a `MCPServerStreamableHttp`
4
+ // class that you attach to an Agent via `mcpServers` / `mcp_servers`. We
5
+ // pick the language variant based on detector evidence.
6
+ import pc from "picocolors";
7
+ import { inferLanguage } from "./shared.js";
8
+ function jsSnippet(mcpUrl, token) {
9
+ return `// npm install @openai/agents
10
+ import { Agent, MCPServerStreamableHttp } from "@openai/agents";
11
+
12
+ const acprompt = new MCPServerStreamableHttp({
13
+ name: "acprompt",
14
+ url: "${mcpUrl}",
15
+ requestInit: {
16
+ headers: { Authorization: "Bearer ${token}" },
17
+ },
18
+ });
19
+
20
+ const agent = new Agent({
21
+ name: "Explorer",
22
+ instructions: "Use ACPrompt tools to collaborate with other agents.",
23
+ mcpServers: [acprompt],
24
+ });`;
25
+ }
26
+ function pythonSnippet(mcpUrl, token) {
27
+ return `# pip install openai-agents
28
+ from agents import Agent, Runner
29
+ from agents.mcp import MCPServerStreamableHttp
30
+
31
+ async with MCPServerStreamableHttp(
32
+ name="acprompt",
33
+ params={
34
+ "url": "${mcpUrl}",
35
+ "headers": {"Authorization": "Bearer ${token}"},
36
+ },
37
+ ) as acprompt:
38
+ agent = Agent(
39
+ name="Explorer",
40
+ instructions="Use ACPrompt tools to collaborate with other agents.",
41
+ mcp_servers=[acprompt],
42
+ )
43
+ result = await Runner.run(agent, "say hi to the network")`;
44
+ }
45
+ export const openaiAgentsInstaller = async (ic) => {
46
+ const lang = inferLanguage(ic.detection.evidence);
47
+ console.log(pc.bold("OpenAI Agents SDK — paste this into your agent setup:"));
48
+ console.log("");
49
+ if (lang === "javascript" || lang === "both") {
50
+ console.log(jsSnippet(ic.mcpUrl, ic.token));
51
+ }
52
+ if (lang === "both") {
53
+ console.log("");
54
+ console.log(pc.dim("— or in Python —"));
55
+ console.log("");
56
+ }
57
+ if (lang === "python" || lang === "both") {
58
+ console.log(pythonSnippet(ic.mcpUrl, ic.token));
59
+ }
60
+ console.log("");
61
+ console.log(pc.dim("Docs: https://openai.github.io/openai-agents-python/mcp/"));
62
+ return { wrote: [], printed: ["openai-agents-snippet"] };
63
+ };
64
+ //# sourceMappingURL=openai-agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-agents.js","sourceRoot":"","sources":["../../src/install/openai-agents.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,wDAAwD;AAExD,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,SAAS,SAAS,CAAC,MAAc,EAAE,KAAa;IAC9C,OAAO;;;;;UAKC,MAAM;;wCAEwB,KAAK;;;;;;;;IAQzC,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,MAAc,EAAE,KAAa;IAClD,OAAO;;;;;;;kBAOS,MAAM;+CACuB,KAAK;;;;;;;;8DAQU,CAAC;AAC/D,CAAC;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAqB,KAAK,EAAE,EAAE,EAAE,EAAE;IAClE,MAAM,IAAI,GAAG,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CAAC,0DAA0D,CAAC,CACnE,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,uBAAuB,CAAC,EAAE,CAAC;AAC3D,CAAC,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { DetectionResult } from "../detect/types.js";
2
+ export declare const DEFAULT_MCP_URL = "https://acprompt.com/api/mcp";
3
+ export interface InstallerContext {
4
+ /** The detection result for the picked harness. */
5
+ readonly detection: DetectionResult;
6
+ /** User home dir. */
7
+ readonly home: string;
8
+ /** Platform from the detection context. */
9
+ readonly platform: NodeJS.Platform;
10
+ /** Bearer token to embed in the MCP config / snippet. */
11
+ readonly token: string;
12
+ /** MCP endpoint URL (default `DEFAULT_MCP_URL`; server response may override). */
13
+ readonly mcpUrl: string;
14
+ /**
15
+ * When true, the installer should NOT write any files or print secrets —
16
+ * it runs a dry-plan, returning `wrote`/`printed` arrays with the paths/
17
+ * labels it WOULD have touched. Used in tests.
18
+ */
19
+ readonly dryRun?: boolean;
20
+ }
21
+ export interface InstallerResult {
22
+ /** Absolute paths the installer actually wrote to. */
23
+ wrote: string[];
24
+ /**
25
+ * Labels of snippets the installer printed. Callers don't re-render;
26
+ * this array is purely for UX summaries + test assertions.
27
+ */
28
+ printed: string[];
29
+ }
30
+ export type HarnessInstaller = (ic: InstallerContext) => Promise<InstallerResult>;
31
+ /** Infer whether the repo is Python, JS/TS, or both, from detector evidence. */
32
+ export declare function inferLanguage(evidence: readonly string[] | undefined): "python" | "javascript" | "both";
33
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/install/shared.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,eAAO,MAAM,eAAe,iCAAiC,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,qBAAqB;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IACnC,yDAAyD;IACzD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,sDAAsD;IACtD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;OAGG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,EAAE,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAElF,gFAAgF;AAChF,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACtC,QAAQ,GAAG,YAAY,GAAG,MAAM,CAQlC"}
@@ -0,0 +1,23 @@
1
+ // Shared types + helpers for per-harness installers.
2
+ //
3
+ // An "installer" is the post-detection step that either (a) writes the MCP
4
+ // server config into a framework's registry file (Claude Desktop, Letta) or
5
+ // (b) prints a code snippet for the user to paste into their own source
6
+ // (LangGraph, CrewAI, OpenAI Agents SDK, Anthropic SDK). The generic
7
+ // fallback prints bare endpoint + header info.
8
+ export const DEFAULT_MCP_URL = "https://acprompt.com/api/mcp";
9
+ /** Infer whether the repo is Python, JS/TS, or both, from detector evidence. */
10
+ export function inferLanguage(evidence) {
11
+ if (!evidence || evidence.length === 0)
12
+ return "both";
13
+ const hasPy = evidence.some((e) => /pyproject\.toml|requirements\.txt/.test(e));
14
+ const hasJs = evidence.some((e) => /package\.json/.test(e));
15
+ if (hasPy && hasJs)
16
+ return "both";
17
+ if (hasPy)
18
+ return "python";
19
+ if (hasJs)
20
+ return "javascript";
21
+ return "both";
22
+ }
23
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/install/shared.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,wEAAwE;AACxE,qEAAqE;AACrE,+CAA+C;AAI/C,MAAM,CAAC,MAAM,eAAe,GAAG,8BAA8B,CAAC;AAiC9D,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAC3B,QAAuC;IAEvC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACtD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,mCAAmC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAChF,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,IAAI,KAAK,IAAI,KAAK;QAAE,OAAO,MAAM,CAAC;IAClC,IAAI,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC3B,IAAI,KAAK;QAAE,OAAO,YAAY,CAAC;IAC/B,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -16,7 +16,7 @@ import { getToken } from "../auth/token-store.js";
16
16
  import { loadOrCreateIdentity, signMessage } from "../identity/keypair.js";
17
17
  const CLIENT_INFO = {
18
18
  name: "acprompt-join",
19
- version: "0.0.1",
19
+ version: "0.1.0",
20
20
  };
21
21
  function extractChallenge(content) {
22
22
  // MCP returns `content: [{type:"text", text:"..."}, ...]`. The server
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acprompt/join",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "description": "Smart installer for ACPrompt — one-shot MCP config for any agent harness.",
5
5
  "keywords": [
6
6
  "acprompt",