affitor 0.4.4 → 0.4.6

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 (44) hide show
  1. package/README.md +144 -5
  2. package/dist/cli.js +2 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/agent.d.ts +3 -0
  5. package/dist/commands/agent.d.ts.map +1 -0
  6. package/dist/commands/agent.js +117 -0
  7. package/dist/commands/agent.js.map +1 -0
  8. package/dist/commands/init.js +1 -1
  9. package/dist/commands/init.js.map +1 -1
  10. package/dist/commands/onboard.d.ts +39 -0
  11. package/dist/commands/onboard.d.ts.map +1 -1
  12. package/dist/commands/onboard.js +232 -22
  13. package/dist/commands/onboard.js.map +1 -1
  14. package/dist/commands/setup-stripe.d.ts +1 -1
  15. package/dist/commands/setup-stripe.d.ts.map +1 -1
  16. package/dist/commands/setup-stripe.js +2 -2
  17. package/dist/commands/setup-stripe.js.map +1 -1
  18. package/dist/commands/status.js +2 -2
  19. package/dist/commands/status.js.map +1 -1
  20. package/dist/lib/agent-launcher.d.ts +20 -0
  21. package/dist/lib/agent-launcher.d.ts.map +1 -0
  22. package/dist/lib/agent-launcher.js +130 -0
  23. package/dist/lib/agent-launcher.js.map +1 -0
  24. package/dist/lib/agent-setup.d.ts +52 -0
  25. package/dist/lib/agent-setup.d.ts.map +1 -0
  26. package/dist/lib/agent-setup.js +374 -0
  27. package/dist/lib/agent-setup.js.map +1 -0
  28. package/dist/lib/config.js +2 -2
  29. package/dist/lib/program-agent-client.d.ts +38 -0
  30. package/dist/lib/program-agent-client.d.ts.map +1 -0
  31. package/dist/lib/program-agent-client.js +172 -0
  32. package/dist/lib/program-agent-client.js.map +1 -0
  33. package/dist/lib/project-env.d.ts +10 -0
  34. package/dist/lib/project-env.d.ts.map +1 -0
  35. package/dist/lib/project-env.js +85 -0
  36. package/dist/lib/project-env.js.map +1 -0
  37. package/dist/lib/wizard.d.ts +2 -0
  38. package/dist/lib/wizard.d.ts.map +1 -1
  39. package/dist/lib/wizard.js +13 -1
  40. package/dist/lib/wizard.js.map +1 -1
  41. package/dist/types.d.ts +2 -0
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/types.js.map +1 -1
  44. package/package.json +4 -3
@@ -0,0 +1,130 @@
1
+ // Kept as a standalone CommonJS file in the customer's project: a client can
2
+ // start it from any directory, without putting a credential in its MCP config.
3
+ export const MCP_VERSION = "0.2.2";
4
+ /** Shared by doctor and the generated launcher; never evaluates an env file. */
5
+ export function parseProgramCredential(envKey, readText) {
6
+ const valid = (value) => /^[A-Za-z0-9_-]+$/.test(value);
7
+ if (typeof envKey === "string" && envKey !== "")
8
+ return valid(envKey) ? envKey : null;
9
+ try {
10
+ const text = readText();
11
+ if (text === null)
12
+ return null;
13
+ const assignments = text.split(/\r?\n/).filter(line => /^\s*(?:export\s+)?AFFITOR_API_KEY\s*=/.test(line));
14
+ if (assignments.length !== 1)
15
+ return null;
16
+ let value = assignments[0].replace(/^\s*(?:export\s+)?AFFITOR_API_KEY\s*=\s*/, "").trim();
17
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'")))
18
+ value = value.slice(1, -1);
19
+ return valid(value) ? value : null;
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
25
+ /** Shared with the standalone launcher; private files never supply executable code. */
26
+ export function parseStoredAgentCredential(text, client) {
27
+ try {
28
+ const value = JSON.parse(text);
29
+ if (!value || value.version !== 1 || value.client !== client ||
30
+ !["claude_code", "cursor", "codex"].includes(client) ||
31
+ !Number.isSafeInteger(value.id) || value.id <= 0 ||
32
+ !Number.isSafeInteger(value.program_id) || value.program_id <= 0 ||
33
+ typeof value.api_key !== "string" || !/^aff_ag_[A-Za-z0-9_-]{43}$/.test(value.api_key) ||
34
+ typeof value.api_url !== "string")
35
+ return null;
36
+ const url = new URL(value.api_url);
37
+ if (url.origin !== value.api_url || url.username || url.password ||
38
+ (url.protocol !== "https:" && !(url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname))))
39
+ return null;
40
+ return value;
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ }
46
+ /** Minimal runtime environment; never forward parent networking, Node or npm overrides. */
47
+ export function agentChildEnvironment(source, key) {
48
+ const allowed = ["PATH", "HOME", "USERPROFILE", "APPDATA", "LOCALAPPDATA", "SYSTEMROOT", "WINDIR", "COMSPEC", "PATHEXT", "TMP", "TEMP", "TMPDIR", "LANG", "TERM", "COLORTERM", "NO_COLOR", "FORCE_COLOR"];
49
+ const env = {};
50
+ for (const [name, value] of Object.entries(source)) {
51
+ const canonical = name.toUpperCase();
52
+ if (allowed.includes(canonical) || /^LC_[A-Z_]+$/.test(canonical))
53
+ env[canonical] = value;
54
+ }
55
+ env.NoDefaultCurrentDirectoryInExePath = "1";
56
+ env.AFFITOR_API_KEY = key;
57
+ env.AFFITOR_MCP_WRITE = "0";
58
+ return env;
59
+ }
60
+ export const AGENT_LAUNCHER = `// Generated by affitor agent setup. Contains no credentials.
61
+ const { readFileSync, lstatSync } = require('node:fs');
62
+ const { join, resolve } = require('node:path');
63
+ const { spawn } = require('node:child_process');
64
+ const project = resolve(__dirname, '..');
65
+ const parseProgramCredential = ${parseProgramCredential.toString()};
66
+ const selector = process.argv[2];
67
+ const parseStoredAgentCredential = ${parseStoredAgentCredential.toString()};
68
+ let stored = null;
69
+ if (selector !== undefined) {
70
+ try {
71
+ if (!['claude_code', 'cursor', 'codex'].includes(selector) || process.argv.length !== 3) throw new Error();
72
+ const directory = join(__dirname, 'agents');
73
+ const parent = lstatSync(directory);
74
+ const path = join(directory, selector + '.json');
75
+ const stat = lstatSync(path);
76
+ if (!parent.isDirectory() || parent.isSymbolicLink() || !stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1) throw new Error();
77
+ stored = parseStoredAgentCredential(readFileSync(path, 'utf8'), selector);
78
+ } catch {}
79
+ }
80
+ const key = selector !== undefined ? stored?.api_key : parseProgramCredential(process.env.AFFITOR_API_KEY, () => {
81
+ const path = join(__dirname, '.env');
82
+ const stat = lstatSync(path);
83
+ if (!stat.isFile() || stat.isSymbolicLink()) return null;
84
+ return readFileSync(path, 'utf8');
85
+ });
86
+ if (!key) {
87
+ process.stderr.write('Affitor: credential missing or invalid. Run affitor agent setup for this client; no agent call was made.\\n');
88
+ process.exit(1);
89
+ }
90
+ // Setup never opts into the sale/refund tools, including through inherited env.
91
+ const agentChildEnvironment = ${agentChildEnvironment.toString()};
92
+ const env = agentChildEnvironment(process.env, key);
93
+ if (stored) env.AFFITOR_API_URL = stored.api_url;
94
+ // Windows batch files require cmd.exe. The command contains constants only:
95
+ // project paths and credentials travel through cwd/env, never shell text.
96
+ const windows = process.platform === 'win32';
97
+ const command = windows ? (process.env.ComSpec || 'cmd.exe') : 'npx';
98
+ const args = windows ? ['/d', '/s', '/c', 'npx.cmd --registry=https://registry.npmjs.org -y @affitor/mcp@${MCP_VERSION}'] : ['--registry=https://registry.npmjs.org', '-y', '@affitor/mcp@${MCP_VERSION}'];
99
+ const child = spawn(command, args, { cwd: project, env, stdio: 'inherit', shell: false, windowsHide: true });
100
+ child.on('error', () => { process.stderr.write('Affitor: could not start the pinned MCP. Check Node.js, npm and network access.\\n'); process.exitCode = 1; });
101
+ child.on('exit', (code, signal) => { process.exitCode = signal ? 1 : (code ?? 1); });
102
+ for (const signal of ['SIGINT', 'SIGTERM']) process.on(signal, () => child.kill(signal));
103
+ `;
104
+ export const AGENT_SKILL = `---
105
+ name: affitor
106
+ description: Check Affitor affiliate integration readiness and follow its integration runbook.
107
+ metadata:
108
+ version: "1"
109
+ ---
110
+
111
+ # Affitor
112
+
113
+ Connect only when this project needs Affitor. Follow https://affitor.com/docs/skill.md
114
+ and the founder's optional context. Detect the framework and payment provider first.
115
+ Never print, copy into a prompt, or commit credentials. Never treat a user login token
116
+ as a program key. Do not add a second sale writer when Stripe Connect may record sales.
117
+
118
+ Installed, signed in, and verified are different states. After restarting the client,
119
+ call affitor_readiness and check the program identity before changing this project.
120
+ Only describe checks that actually passed. A static doctor cannot prove a live session.
121
+ Do not run sale/refund tools. Ask before running synthetic verification or other writes.
122
+
123
+ | Problem | Next step |
124
+ | --- | --- |
125
+ | Missing or stale local files | Run affitor agent setup --dry-run --json, show the plan, then apply the selected client after approval. |
126
+ | Files aligned, tools absent | Restart the selected agent, then call affitor_readiness. |
127
+ | Credential missing or rejected | Run affitor login, then affitor agent setup for this client and program. Never paste any key into chat. |
128
+ | Readiness fails | Report the failed checks and follow the runbook; do not claim integration is verified. |
129
+ `;
130
+ //# sourceMappingURL=agent-launcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-launcher.js","sourceRoot":"","sources":["../../src/lib/agent-launcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { type StoredAgentCredential } from "./agent-launcher.js";
2
+ export declare const CLIENTS: readonly ["claude_code", "cursor", "codex"];
3
+ export type AgentClient = typeof CLIENTS[number];
4
+ type JsonObject = Record<string, unknown>;
5
+ export interface FileAction {
6
+ path: string;
7
+ operation: "create" | "update" | "unchanged";
8
+ backup: string | null;
9
+ content: string;
10
+ }
11
+ export interface SetupPlan {
12
+ project: string;
13
+ clients: AgentClient[];
14
+ mcpVersion: string;
15
+ entry: {
16
+ command: string;
17
+ args: string[];
18
+ };
19
+ actions: FileAction[];
20
+ manual: string[];
21
+ notes: string[];
22
+ agentKeys?: {
23
+ client: AgentClient;
24
+ path: string;
25
+ id?: number;
26
+ state: "pending" | "reused" | "minted";
27
+ }[];
28
+ }
29
+ export declare function object(value: unknown): value is JsonObject;
30
+ export declare function callerClient(env: NodeJS.ProcessEnv): AgentClient | undefined;
31
+ export declare function selectedClients(names: string[], env: NodeJS.ProcessEnv): AgentClient[];
32
+ export declare function setupProgramId(cwd: string, explicit?: string): number | null;
33
+ export declare function planSetup(cwd: string, clients: AgentClient[], options?: {
34
+ agentKeys?: boolean;
35
+ }): SetupPlan;
36
+ /** These APIs keep credential contents out of the public plan metadata. */
37
+ export declare function readPlannedAgentCredential(plan: SetupPlan, client: AgentClient): StoredAgentCredential | null;
38
+ export declare function stageAgentCredential(plan: SetupPlan, client: AgentClient, record: StoredAgentCredential, minted: boolean): void;
39
+ /** Local, synchronous transaction. It detects ordinary concurrent edits; it is not a local sandbox. */
40
+ export declare function applySetup(plan: SetupPlan, beforeWrite?: (action: FileAction) => void): void;
41
+ export declare function credentialWarnings(project: string, relativePath?: string): string[];
42
+ export declare function doctor(cwd: string, clients: AgentClient[]): {
43
+ client: "claude_code" | "cursor" | "codex";
44
+ warnings: string[];
45
+ notes: string[];
46
+ status: string;
47
+ credential: string;
48
+ liveSession: string;
49
+ manual: string[];
50
+ }[];
51
+ export {};
52
+ //# sourceMappingURL=agent-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-setup.d.ts","sourceRoot":"","sources":["../../src/lib/agent-setup.ts"],"names":[],"mappings":"AAIA,OAAO,EAAuH,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEtL,eAAO,MAAM,OAAO,6CAA8C,CAAC;AACnE,MAAM,MAAM,WAAW,GAAG,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;AACjD,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC1C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC7C,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtB,OAAO,EAAE,MAAM,CAAC;CACjB;AACD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC3C,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;KAAE,EAAE,CAAC;CAC1G;AAGD,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAE1D;AAmCD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,WAAW,GAAG,SAAS,CAK5E;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,WAAW,EAAE,CAKtF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa5E;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,SAAS,CA+F/G;AAED,2EAA2E;AAC3E,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,GAAG,qBAAqB,GAAG,IAAI,CAK7G;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,EAAE,OAAO,QAUxH;AAsBD,uGAAuG;AACvG,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,QA0CrF;AAcD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,SAAkB,GAAG,MAAM,EAAE,CAkB5F;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE;;;;;;;;IAmBzD"}
@@ -0,0 +1,374 @@
1
+ import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
2
+ import { dirname, join, relative, resolve } from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ import { spawnSync } from "node:child_process";
5
+ import { AGENT_LAUNCHER, AGENT_SKILL, MCP_VERSION, parseProgramCredential, agentChildEnvironment, parseStoredAgentCredential } from "./agent-launcher.js";
6
+ export const CLIENTS = ["claude_code", "cursor", "codex"];
7
+ const snapshots = new WeakMap();
8
+ export function object(value) {
9
+ return !!value && typeof value === "object" && !Array.isArray(value);
10
+ }
11
+ /** Refuse symlinks anywhere below the canonical project directory. */
12
+ function safePath(project, path) {
13
+ const rel = relative(project, path);
14
+ if (!rel || rel.startsWith("..") || resolve(project, rel) !== path)
15
+ throw new Error("Unsafe setup target.");
16
+ let current = project;
17
+ for (const part of rel.split(/[\\/]/)) {
18
+ current = join(current, part);
19
+ if (!existsSync(current)) {
20
+ // existsSync follows symlinks, including dangling ones.
21
+ try {
22
+ if (lstatSync(current).isSymbolicLink())
23
+ throw new Error("Setup target is a symlink.");
24
+ }
25
+ catch (error) {
26
+ if (error.code !== "ENOENT")
27
+ throw error;
28
+ }
29
+ continue;
30
+ }
31
+ const stat = lstatSync(current);
32
+ if (stat.isSymbolicLink() || (current === path ? !stat.isFile() || stat.nlink !== 1 : !stat.isDirectory())) {
33
+ throw new Error("Setup target must be a regular file with no symlink parents.");
34
+ }
35
+ }
36
+ }
37
+ function readTarget(project, path) {
38
+ safePath(project, path);
39
+ if (!existsSync(path))
40
+ return null;
41
+ const bytes = readFileSync(path);
42
+ const text = bytes.toString("utf8");
43
+ if (!Buffer.from(text, "utf8").equals(bytes))
44
+ throw new Error("Setup target must contain valid UTF-8. Nothing was written.");
45
+ return text;
46
+ }
47
+ function configFile(client) {
48
+ return client === "claude_code" ? ".mcp.json" : ".cursor/mcp.json";
49
+ }
50
+ export function callerClient(env) {
51
+ if (env.CLAUDECODE)
52
+ return "claude_code";
53
+ if (env.CODEX || env.CODEX_THREAD_ID)
54
+ return "codex";
55
+ if (env.CURSOR_AGENT)
56
+ return "cursor";
57
+ return undefined;
58
+ }
59
+ export function selectedClients(names, env) {
60
+ if (names.some(name => !CLIENTS.includes(name)))
61
+ throw new Error("Unknown client. Choose claude_code, cursor or codex.");
62
+ const caller = callerClient(env);
63
+ if (caller && names.some(name => name !== caller))
64
+ throw new Error("An agent can only configure itself. Run setup in your own terminal for other clients.");
65
+ return [...new Set(names.length ? names : caller ? [caller] : [])];
66
+ }
67
+ export function setupProgramId(cwd, explicit) {
68
+ const valid = (value) => (typeof value === "number" || typeof value === "string") && /^[1-9]\d*$/.test(String(value)) && Number.isSafeInteger(Number(value));
69
+ if (explicit !== undefined) {
70
+ if (!valid(explicit))
71
+ throw new Error("Setup target program id must be a positive decimal integer.");
72
+ return Number(explicit);
73
+ }
74
+ const project = realpathSync(resolve(cwd));
75
+ const raw = readTarget(project, join(project, ".affitor/config.json"));
76
+ if (raw === null)
77
+ return null;
78
+ let value;
79
+ try {
80
+ value = JSON.parse(raw);
81
+ }
82
+ catch {
83
+ throw new Error("Setup target project config is invalid. Resolve it before setup.");
84
+ }
85
+ if (!object(value) || !valid(value.program_id))
86
+ throw new Error("Setup target project config has no valid program id. Pass --program-id explicitly.");
87
+ return Number(value.program_id);
88
+ }
89
+ export function planSetup(cwd, clients, options = {}) {
90
+ const project = realpathSync(resolve(cwd));
91
+ const launcher = join(project, ".affitor/agent-mcp.cjs");
92
+ const entry = { command: "node", args: [launcher] };
93
+ const plan = { project, clients, entry, mcpVersion: MCP_VERSION, actions: [], manual: [], notes: clients.length ? ["MCP entries contain this machine's absolute project path. Keep configs local or regenerate them on each teammate's machine."] : [] };
94
+ const before = new Map();
95
+ const add = (rel, content, expectedOriginal) => {
96
+ const path = join(project, rel);
97
+ const original = readTarget(project, path);
98
+ if (expectedOriginal !== undefined && original !== expectedOriginal)
99
+ throw new Error("A setup file changed while planning. Run setup again.");
100
+ const backup = original !== null && original !== content ? join(project, ".affitor/backups", `${rel}.affitor.bak`) : null;
101
+ if (backup) {
102
+ safePath(project, backup);
103
+ // An earlier first snapshot stays intact; reject an unsafe backup, never overwrite it.
104
+ if (existsSync(backup))
105
+ readTarget(project, backup);
106
+ }
107
+ before.set(path, original);
108
+ plan.actions.push({ path, content, backup, operation: original === content ? "unchanged" : original === null ? "create" : "update" });
109
+ };
110
+ if (!options.agentKeys && clients.some(client => readTarget(project, join(project, `.affitor/agents/${client}.json`)) !== null)) {
111
+ throw new Error("Setup target already has per-client credentials. Pass --program-id before updating.");
112
+ }
113
+ if (options.agentKeys) {
114
+ plan.notes.push("Matching active keys are reused. Replacing an active selected key revokes its previous key after the new files are saved; failed revocations require dashboard cleanup.");
115
+ plan.agentKeys = clients.map(client => {
116
+ const rel = `.affitor/agents/${client}.json`;
117
+ const path = join(project, rel), raw = readTarget(project, path);
118
+ if (raw !== null && process.platform !== "win32" && (lstatSync(path).mode & 0o077) !== 0)
119
+ throw new Error("Setup target private agent credential must have owner-only permissions.");
120
+ if (raw !== null && !parseStoredAgentCredential(raw, client))
121
+ throw new Error("Setup target has an invalid private agent credential. Resolve it before retrying.");
122
+ const backup = join(project, ".affitor/backups", `${rel}.affitor.bak`);
123
+ safePath(project, backup);
124
+ if (existsSync(backup))
125
+ readTarget(project, backup);
126
+ add(rel, "", raw);
127
+ return { client, path, state: "pending" };
128
+ });
129
+ }
130
+ const editable = clients.filter(client => client !== "codex");
131
+ for (const client of editable) {
132
+ const rel = configFile(client);
133
+ const path = join(project, rel);
134
+ const raw = readTarget(project, path);
135
+ let config;
136
+ try {
137
+ config = raw === null ? {} : JSON.parse(raw);
138
+ }
139
+ catch {
140
+ throw new Error(`${rel} is not valid JSON. Nothing was written.`);
141
+ }
142
+ if (!object(config) || (config.mcpServers !== undefined && !object(config.mcpServers))) {
143
+ throw new Error(`${rel} must contain an object with an mcpServers object. Nothing was written.`);
144
+ }
145
+ const existingEntry = config.mcpServers?.affitor;
146
+ if (!options.agentKeys && object(existingEntry) && Array.isArray(existingEntry.args) && existingEntry.args.includes(client))
147
+ throw new Error("Setup target uses per-client credentials. Pass --program-id before updating.");
148
+ config.mcpServers = { ...config.mcpServers, affitor: options.agentKeys ? { command: entry.command, args: [...entry.args, client] } : entry };
149
+ add(rel, JSON.stringify(config, null, 2) + "\n", raw);
150
+ add(client === "claude_code" ? ".claude/skills/affitor/SKILL.md" : ".cursor/skills/affitor/SKILL.md", AGENT_SKILL);
151
+ }
152
+ if (clients.includes("codex")) {
153
+ if (process.platform === "win32") {
154
+ // A path may contain cmd.exe expansion/separator characters. Do not emit
155
+ // executable shell text when the invoking Windows shell is unknown.
156
+ plan.manual.push('Windows: add Affitor in Codex MCP settings using command "node" and the exact arguments in entry.args plus codex when using per-client agent keys. No shell command is generated.');
157
+ }
158
+ else {
159
+ plan.manual.push(`codex mcp add affitor -- node '${launcher.replaceAll("'", "'\"'\"'")}'${options.agentKeys ? ' codex' : ''}`);
160
+ }
161
+ // Installing a shared skill and launcher needs the same explicit consent.
162
+ add(".agents/skills/affitor/SKILL.md", AGENT_SKILL);
163
+ }
164
+ if (clients.length) {
165
+ add(".affitor/agent-mcp.cjs", AGENT_LAUNCHER);
166
+ // The final matching rule wins at each directory level. Existing negations
167
+ // must not cancel protection; a child guard also outranks root ignore rules.
168
+ for (const [rel, entries] of [
169
+ [".gitignore", ["/.affitor/.env", "/.affitor/backups/", "/.affitor/credentials.json", "/.affitor/agents/"]],
170
+ [".affitor/.gitignore", ["/.env", "/backups/", "/credentials.json", "/agents/"]],
171
+ ]) {
172
+ const raw = readTarget(project, join(project, rel));
173
+ const prior = raw ?? "";
174
+ const suffix = entries.join("\n") + "\n";
175
+ add(rel, prior.endsWith(suffix) ? prior : prior + (prior && !prior.endsWith("\n") ? "\n" : "") + suffix, raw);
176
+ }
177
+ }
178
+ if (clients.length) {
179
+ const guard = join(project, ".affitor/backups/.gitignore");
180
+ const raw = readTarget(project, guard);
181
+ if (raw !== null && !["*", "*\n", "*\r\n"].includes(raw))
182
+ throw new Error("Unsafe setup backup directory: its .gitignore must contain only the '*' rule.");
183
+ add(".affitor/backups/.gitignore", raw ?? "*\n", raw);
184
+ // Protect secret-containing backups before creating the first one. Keep this
185
+ // guard with backups on rollback even if the root .gitignore is restored.
186
+ plan.actions.unshift(plan.actions.pop());
187
+ }
188
+ if (options.agentKeys && clients.length) {
189
+ const guard = ".affitor/agents/.gitignore", raw = readTarget(project, join(project, guard));
190
+ if (raw !== null && !["*", "*\n", "*\r\n"].includes(raw))
191
+ throw new Error("Unsafe setup agent directory guard.");
192
+ add(guard, raw ?? "*\n", raw);
193
+ const action = plan.actions.pop();
194
+ plan.actions.splice(1, 0, action);
195
+ }
196
+ snapshots.set(plan, before);
197
+ return plan;
198
+ }
199
+ /** These APIs keep credential contents out of the public plan metadata. */
200
+ export function readPlannedAgentCredential(plan, client) {
201
+ const path = plan.agentKeys?.find(item => item.client === client)?.path;
202
+ if (!path)
203
+ throw new Error("Setup plan does not include this agent credential.");
204
+ const raw = snapshots.get(plan)?.get(path);
205
+ return raw ? parseStoredAgentCredential(raw, client) : null;
206
+ }
207
+ export function stageAgentCredential(plan, client, record, minted) {
208
+ const item = plan.agentKeys?.find(item => item.client === client);
209
+ if (!item || !parseStoredAgentCredential(JSON.stringify(record), client))
210
+ throw new Error("Setup agent credential is invalid.");
211
+ const action = plan.actions.find(action => action.path === item.path);
212
+ const original = snapshots.get(plan).get(item.path);
213
+ action.content = minted ? JSON.stringify(record, null, 2) + "\n" : original;
214
+ action.operation = original === action.content ? "unchanged" : original === null ? "create" : "update";
215
+ action.backup = original !== null && original !== action.content ? join(plan.project, ".affitor/backups", `.affitor/agents/${client}.json.affitor.bak`) : null;
216
+ if (action.backup) {
217
+ safePath(plan.project, action.backup);
218
+ if (existsSync(action.backup))
219
+ readTarget(plan.project, action.backup);
220
+ }
221
+ item.id = record.id;
222
+ item.state = minted ? "minted" : "reused";
223
+ }
224
+ function atomicWrite(project, path, content) {
225
+ safePath(project, path);
226
+ const guard = join(project, ".affitor/backups/.gitignore");
227
+ // The guard bootstrap contains only '*'. Every later temp is protected before
228
+ // merged config bytes reach disk, even if the process exits before finally.
229
+ if (path !== guard) {
230
+ const raw = readTarget(project, guard);
231
+ if (raw === null || !["*", "*\n", "*\r\n"].includes(raw))
232
+ throw new Error("Unsafe setup temporary directory guard.");
233
+ }
234
+ mkdirSync(dirname(path), { recursive: true });
235
+ const temporary = join(project, ".affitor/backups", `.temporary-${randomUUID()}.tmp`);
236
+ safePath(project, temporary);
237
+ try {
238
+ writeFileSync(temporary, content, { mode: 0o600, flag: "wx" });
239
+ safePath(project, path);
240
+ renameSync(temporary, path);
241
+ if (readFileSync(path, "utf8") !== content)
242
+ throw new Error("Setup read-back failed.");
243
+ }
244
+ finally {
245
+ rmSync(temporary, { force: true });
246
+ }
247
+ }
248
+ /** Local, synchronous transaction. It detects ordinary concurrent edits; it is not a local sandbox. */
249
+ export function applySetup(plan, beforeWrite) {
250
+ const before = snapshots.get(plan);
251
+ if (plan.agentKeys?.some(item => item.state === "pending"))
252
+ throw new Error("Setup agent credentials have not been prepared.");
253
+ if (!before)
254
+ throw new Error("Generate a fresh setup plan before applying it.");
255
+ const applied = [];
256
+ let backupCreated = false;
257
+ let privateWritten = false;
258
+ try {
259
+ for (const action of plan.actions) {
260
+ if (readTarget(plan.project, action.path) !== before.get(action.path))
261
+ throw new Error("A setup file changed after planning. Run setup again.");
262
+ }
263
+ for (const action of plan.actions.filter(action => action.operation !== "unchanged")) {
264
+ beforeWrite?.(action);
265
+ if (readTarget(plan.project, action.path) !== before.get(action.path))
266
+ throw new Error("A setup file changed after planning. Run setup again.");
267
+ if (action.backup && !existsSync(action.backup)) {
268
+ const guard = readTarget(plan.project, join(plan.project, ".affitor/backups/.gitignore"));
269
+ if (guard === null || !["*", "*\n", "*\r\n"].includes(guard))
270
+ throw new Error("Unsafe setup backup ignore guard.");
271
+ safePath(plan.project, action.backup);
272
+ mkdirSync(dirname(action.backup), { recursive: true });
273
+ backupCreated = true;
274
+ writeFileSync(action.backup, before.get(action.path), { flag: "wx", mode: 0o600 });
275
+ }
276
+ applied.push(action);
277
+ if (plan.agentKeys?.some(item => item.path === action.path))
278
+ privateWritten = true;
279
+ atomicWrite(plan.project, action.path, action.content);
280
+ }
281
+ }
282
+ catch {
283
+ let concurrent = false;
284
+ for (const action of applied.reverse()) {
285
+ // Never restore over a newer edit by somebody else.
286
+ try {
287
+ const original = before.get(action.path);
288
+ const current = readTarget(plan.project, action.path);
289
+ if ((backupCreated || privateWritten) && [join(plan.project, ".affitor/backups/.gitignore"), join(plan.project, ".affitor/agents/.gitignore")].includes(action.path) && original === null && current === action.content)
290
+ continue;
291
+ if (current === original)
292
+ continue;
293
+ if (current !== action.content) {
294
+ concurrent = true;
295
+ continue;
296
+ }
297
+ if (original === null)
298
+ rmSync(action.path);
299
+ else
300
+ atomicWrite(plan.project, action.path, original);
301
+ }
302
+ catch {
303
+ concurrent = true;
304
+ }
305
+ }
306
+ throw new Error(concurrent ? "Setup failed; a concurrent edit was preserved. Check the files and private backups before retrying." : "Setup failed. Written files were rolled back; private backups were kept. Run a fresh dry-run.");
307
+ }
308
+ }
309
+ /** No marker means Git really has nowhere to discover a worktree (GIT_* overrides are dropped). */
310
+ function hasGitAncestor(project) {
311
+ let current = project;
312
+ for (;;) {
313
+ try {
314
+ lstatSync(join(current, ".git"));
315
+ return true;
316
+ }
317
+ catch (error) {
318
+ if (error.code !== "ENOENT")
319
+ return null;
320
+ }
321
+ const parent = dirname(current);
322
+ if (parent === current)
323
+ return false;
324
+ current = parent;
325
+ }
326
+ }
327
+ export function credentialWarnings(project, relativePath = ".affitor/.env") {
328
+ const env = agentChildEnvironment(process.env, "");
329
+ delete env.AFFITOR_API_KEY;
330
+ // Fixed locale permits only Git's exact no-repository result; other failures stay unknown.
331
+ env.LC_ALL = "C";
332
+ const run = (args) => spawnSync("git", ["-C", project, ...args], { env, encoding: "utf8", timeout: 1500, windowsHide: true });
333
+ const discovery = run(["rev-parse", "--is-inside-work-tree"]);
334
+ const failed = ["credential_check_failed"];
335
+ if (discovery.error || discovery.signal)
336
+ return failed;
337
+ if (discovery.status === 128) {
338
+ const noRepository = /^fatal: not a git repository \(or any of the parent directories\): \.git\r?\n?$/.test(discovery.stderr ?? "");
339
+ return noRepository && discovery.stdout === "" && hasGitAncestor(project) === false ? [] : failed;
340
+ }
341
+ if (discovery.status !== 0 || discovery.stdout.trim() !== "true")
342
+ return failed;
343
+ const checked = run(["ls-files", "--error-unmatch", "--", relativePath]);
344
+ if (checked.error || checked.signal)
345
+ return failed;
346
+ if (checked.status === 0)
347
+ return ["credential_tracked"];
348
+ return checked.status === 1 ? [] : failed;
349
+ }
350
+ export function doctor(cwd, clients) {
351
+ return clients.map(client => {
352
+ try {
353
+ const root = realpathSync(resolve(cwd));
354
+ const privatePath = join(root, `.affitor/agents/${client}.json`);
355
+ const rawConfig = client === "codex" ? null : readTarget(root, join(root, configFile(client)));
356
+ const entry = rawConfig ? JSON.parse(rawConfig)?.mcpServers?.affitor : null;
357
+ const perClient = existsSync(privatePath) || (Array.isArray(entry?.args) && entry.args.includes(client));
358
+ const plan = planSetup(cwd, [client], { agentKeys: perClient });
359
+ const saved = perClient ? readPlannedAgentCredential(plan, client) : null;
360
+ if (saved)
361
+ stageAgentCredential(plan, client, saved, false);
362
+ const keyPath = join(plan.project, ".affitor/.env");
363
+ const credential = perClient ? saved?.api_key : parseProgramCredential(process.env.AFFITOR_API_KEY, () => {
364
+ const stat = lstatSync(keyPath);
365
+ return stat.isFile() && !stat.isSymbolicLink() ? readFileSync(keyPath, "utf8") : null;
366
+ });
367
+ return { client, warnings: credentialWarnings(plan.project, perClient ? `.affitor/agents/${client}.json` : ".affitor/.env"), notes: plan.notes, status: client === "codex" ? "manual" : plan.actions.some(a => a.operation === "create") ? "missing" : plan.actions.some(a => a.operation === "update") ? "stale" : "aligned", credential: credential ? "present_unverified" : "missing", liveSession: "not_checked", manual: plan.manual };
368
+ }
369
+ catch {
370
+ return { client, warnings: [], notes: [], status: "invalid", credential: "not_checked", liveSession: "not_checked", manual: [] };
371
+ }
372
+ });
373
+ }
374
+ //# sourceMappingURL=agent-setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-setup.js","sourceRoot":"","sources":["../../src/lib/agent-setup.ts"],"names":[],"mappings":"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"}
@@ -235,7 +235,7 @@ export function writeEnvExample(config, apiKey, cwd) {
235
235
 
236
236
  AFFITOR_API_KEY=${apiKey}
237
237
  AFFITOR_PROGRAM_ID=${config.program_id}
238
- # STRIPE_CONNECTED_ACCOUNT_ID= (connect Stripe in the Affitor dashboard: program Settings, Connect Stripe)
238
+ # STRIPE_CONNECTED_ACCOUNT_ID= (connect Stripe in the Affitor dashboard: Program settings → Payments, Connect Stripe)
239
239
  `;
240
240
  writeFileSync(join(dir, ".env.example"), content);
241
241
  }
@@ -305,7 +305,7 @@ curl -X POST ${config.api_url}/api/v1/track/lead \\
305
305
 
306
306
  ### 3. Sale/Revenue Tracking
307
307
 
308
- **Option A: Stripe (recommended)**: connect Stripe in the Affitor dashboard (program Settings, Connect Stripe). Affitor's webhook records sales; add Affitor metadata to your checkout so sales are attributed reliably.
308
+ **Option A: Stripe (recommended)**: connect Stripe in the Affitor dashboard (Program settings → Payments, Connect Stripe). Affitor's webhook records sales; add Affitor metadata to your checkout so sales are attributed reliably.
309
309
 
310
310
  **Option B: Sale API (any payment provider)**
311
311