unfairly 0.8.3 → 0.8.4

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 (218) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/LICENSE +15 -0
  3. package/dist/auth/browser-flow.d.ts +0 -1
  4. package/dist/auth/browser-flow.js +5 -81
  5. package/dist/cmd/connect.d.ts +0 -1
  6. package/dist/cmd/connect.js +1 -164
  7. package/dist/cmd/init.d.ts +0 -1
  8. package/dist/cmd/init.js +2 -138
  9. package/dist/cmd/invite.d.ts +0 -1
  10. package/dist/cmd/invite.js +4 -73
  11. package/dist/cmd/join.d.ts +0 -1
  12. package/dist/cmd/join.js +1 -91
  13. package/dist/cmd/login.d.ts +0 -1
  14. package/dist/cmd/login.js +3 -41
  15. package/dist/cmd/mcp.d.ts +0 -1
  16. package/dist/cmd/mcp.js +2 -86
  17. package/dist/cmd/pace.d.ts +2 -2
  18. package/dist/cmd/pace.js +4 -426
  19. package/dist/cmd/parse-share-input.d.ts +0 -1
  20. package/dist/cmd/parse-share-input.js +1 -56
  21. package/dist/cmd/pull.d.ts +0 -1
  22. package/dist/cmd/pull.js +7 -143
  23. package/dist/cmd/push.d.ts +0 -1
  24. package/dist/cmd/push.js +1 -85
  25. package/dist/cmd/resolve.d.ts +0 -1
  26. package/dist/cmd/resolve.js +1 -35
  27. package/dist/cmd/setup.d.ts +0 -1
  28. package/dist/cmd/setup.js +2 -345
  29. package/dist/cmd/status-card.d.ts +0 -1
  30. package/dist/cmd/status-card.js +2 -156
  31. package/dist/cmd/status.d.ts +0 -1
  32. package/dist/cmd/status.js +3 -29
  33. package/dist/cmd/watch.d.ts +0 -1
  34. package/dist/cmd/watch.js +1 -26
  35. package/dist/hosts/claude-code.d.ts +0 -1
  36. package/dist/hosts/claude-code.js +3 -180
  37. package/dist/hosts/claude-desktop.d.ts +0 -1
  38. package/dist/hosts/claude-desktop.js +3 -222
  39. package/dist/hosts/codex.d.ts +0 -1
  40. package/dist/hosts/codex.js +20 -234
  41. package/dist/hosts/shell-env.d.ts +0 -1
  42. package/dist/hosts/shell-env.js +9 -81
  43. package/dist/index.d.ts +0 -1
  44. package/dist/index.js +14 -206
  45. package/dist/lib/client.d.ts +0 -1
  46. package/dist/lib/client.js +1 -58
  47. package/dist/lib/events/emit.d.ts +0 -1
  48. package/dist/lib/events/emit.js +1 -28
  49. package/dist/lib/index.d.ts +0 -1
  50. package/dist/lib/index.js +1 -11
  51. package/dist/lib/transport.d.ts +0 -1
  52. package/dist/lib/transport.js +1 -85
  53. package/dist/lib/types/index.d.ts +0 -1
  54. package/dist/lib/types/index.js +1 -50
  55. package/dist/lib/vault/checkpoint.d.ts +0 -1
  56. package/dist/lib/vault/checkpoint.js +1 -18
  57. package/dist/lib/vault/read.d.ts +0 -1
  58. package/dist/lib/vault/read.js +1 -9
  59. package/dist/lib/vault/search.d.ts +0 -1
  60. package/dist/lib/vault/search.js +1 -10
  61. package/dist/pace/device.d.ts +0 -1
  62. package/dist/pace/device.js +2 -149
  63. package/dist/pace/enroll.d.ts +0 -1
  64. package/dist/pace/enroll.js +2 -138
  65. package/dist/pace/identity.d.ts +0 -1
  66. package/dist/pace/identity.js +1 -17
  67. package/dist/pace/install.d.ts +0 -1
  68. package/dist/pace/install.js +4 -127
  69. package/dist/pace/local-evidence.d.ts +0 -1
  70. package/dist/pace/local-evidence.js +2 -228
  71. package/dist/pace/local-sessions.d.ts +0 -1
  72. package/dist/pace/local-sessions.js +1 -254
  73. package/dist/pace/managed-config.d.ts +0 -1
  74. package/dist/pace/managed-config.js +8 -102
  75. package/dist/pace/normalize.d.ts +0 -1
  76. package/dist/pace/normalize.js +1 -293
  77. package/dist/pace/repository.d.ts +0 -1
  78. package/dist/pace/repository.js +2 -120
  79. package/dist/pace/schema.d.ts +0 -1
  80. package/dist/pace/schema.js +1 -134
  81. package/dist/pace/session-summary.d.ts +0 -1
  82. package/dist/pace/session-summary.js +2 -140
  83. package/dist/pace/spool.d.ts +0 -1
  84. package/dist/pace/spool.js +8 -87
  85. package/dist/pace-runtime.d.ts +0 -1
  86. package/dist/pace-runtime.js +2 -67
  87. package/dist/sync/api.d.ts +0 -1
  88. package/dist/sync/api.js +1 -55
  89. package/dist/sync/autoloader.d.ts +0 -1
  90. package/dist/sync/autoloader.js +5 -127
  91. package/dist/sync/conflict.d.ts +0 -1
  92. package/dist/sync/conflict.js +5 -15
  93. package/dist/sync/credentials.d.ts +0 -1
  94. package/dist/sync/credentials.js +1 -51
  95. package/dist/sync/files.d.ts +0 -1
  96. package/dist/sync/files.js +1 -71
  97. package/dist/sync/manifest.d.ts +0 -1
  98. package/dist/sync/manifest.js +1 -37
  99. package/dist/sync/repo-root.d.ts +0 -1
  100. package/dist/sync/repo-root.js +1 -24
  101. package/dist/sync/stitch-claude-md.d.ts +0 -1
  102. package/dist/sync/stitch-claude-md.js +8 -48
  103. package/dist/ui/colors.d.ts +0 -1
  104. package/dist/ui/colors.js +1 -28
  105. package/dist/ui/screens.d.ts +0 -1
  106. package/dist/ui/screens.js +5 -135
  107. package/package.json +5 -12
  108. package/plugin/.cursor-plugin/plugin.json +0 -2
  109. package/plugin/.mcp.json +1 -1
  110. package/plugin/LICENSE +15 -0
  111. package/plugin/gemini/gemini-extension.json +1 -1
  112. package/plugin/mcp.json +1 -1
  113. package/plugin/plugin.json +0 -2
  114. package/plugin/runtime/unfairly-intelligence.mjs +14 -5512
  115. package/dist/auth/browser-flow.d.ts.map +0 -1
  116. package/dist/auth/browser-flow.js.map +0 -1
  117. package/dist/cmd/connect.d.ts.map +0 -1
  118. package/dist/cmd/connect.js.map +0 -1
  119. package/dist/cmd/init.d.ts.map +0 -1
  120. package/dist/cmd/init.js.map +0 -1
  121. package/dist/cmd/invite.d.ts.map +0 -1
  122. package/dist/cmd/invite.js.map +0 -1
  123. package/dist/cmd/join.d.ts.map +0 -1
  124. package/dist/cmd/join.js.map +0 -1
  125. package/dist/cmd/login.d.ts.map +0 -1
  126. package/dist/cmd/login.js.map +0 -1
  127. package/dist/cmd/mcp.d.ts.map +0 -1
  128. package/dist/cmd/mcp.js.map +0 -1
  129. package/dist/cmd/pace.d.ts.map +0 -1
  130. package/dist/cmd/pace.js.map +0 -1
  131. package/dist/cmd/parse-share-input.d.ts.map +0 -1
  132. package/dist/cmd/parse-share-input.js.map +0 -1
  133. package/dist/cmd/pull.d.ts.map +0 -1
  134. package/dist/cmd/pull.js.map +0 -1
  135. package/dist/cmd/push.d.ts.map +0 -1
  136. package/dist/cmd/push.js.map +0 -1
  137. package/dist/cmd/resolve.d.ts.map +0 -1
  138. package/dist/cmd/resolve.js.map +0 -1
  139. package/dist/cmd/setup.d.ts.map +0 -1
  140. package/dist/cmd/setup.js.map +0 -1
  141. package/dist/cmd/status-card.d.ts.map +0 -1
  142. package/dist/cmd/status-card.js.map +0 -1
  143. package/dist/cmd/status.d.ts.map +0 -1
  144. package/dist/cmd/status.js.map +0 -1
  145. package/dist/cmd/watch.d.ts.map +0 -1
  146. package/dist/cmd/watch.js.map +0 -1
  147. package/dist/hosts/claude-code.d.ts.map +0 -1
  148. package/dist/hosts/claude-code.js.map +0 -1
  149. package/dist/hosts/claude-desktop.d.ts.map +0 -1
  150. package/dist/hosts/claude-desktop.js.map +0 -1
  151. package/dist/hosts/codex.d.ts.map +0 -1
  152. package/dist/hosts/codex.js.map +0 -1
  153. package/dist/hosts/shell-env.d.ts.map +0 -1
  154. package/dist/hosts/shell-env.js.map +0 -1
  155. package/dist/index.d.ts.map +0 -1
  156. package/dist/index.js.map +0 -1
  157. package/dist/lib/client.d.ts.map +0 -1
  158. package/dist/lib/client.js.map +0 -1
  159. package/dist/lib/events/emit.d.ts.map +0 -1
  160. package/dist/lib/events/emit.js.map +0 -1
  161. package/dist/lib/index.d.ts.map +0 -1
  162. package/dist/lib/index.js.map +0 -1
  163. package/dist/lib/transport.d.ts.map +0 -1
  164. package/dist/lib/transport.js.map +0 -1
  165. package/dist/lib/types/index.d.ts.map +0 -1
  166. package/dist/lib/types/index.js.map +0 -1
  167. package/dist/lib/vault/checkpoint.d.ts.map +0 -1
  168. package/dist/lib/vault/checkpoint.js.map +0 -1
  169. package/dist/lib/vault/read.d.ts.map +0 -1
  170. package/dist/lib/vault/read.js.map +0 -1
  171. package/dist/lib/vault/search.d.ts.map +0 -1
  172. package/dist/lib/vault/search.js.map +0 -1
  173. package/dist/pace/device.d.ts.map +0 -1
  174. package/dist/pace/device.js.map +0 -1
  175. package/dist/pace/enroll.d.ts.map +0 -1
  176. package/dist/pace/enroll.js.map +0 -1
  177. package/dist/pace/identity.d.ts.map +0 -1
  178. package/dist/pace/identity.js.map +0 -1
  179. package/dist/pace/install.d.ts.map +0 -1
  180. package/dist/pace/install.js.map +0 -1
  181. package/dist/pace/local-evidence.d.ts.map +0 -1
  182. package/dist/pace/local-evidence.js.map +0 -1
  183. package/dist/pace/local-sessions.d.ts.map +0 -1
  184. package/dist/pace/local-sessions.js.map +0 -1
  185. package/dist/pace/managed-config.d.ts.map +0 -1
  186. package/dist/pace/managed-config.js.map +0 -1
  187. package/dist/pace/normalize.d.ts.map +0 -1
  188. package/dist/pace/normalize.js.map +0 -1
  189. package/dist/pace/repository.d.ts.map +0 -1
  190. package/dist/pace/repository.js.map +0 -1
  191. package/dist/pace/schema.d.ts.map +0 -1
  192. package/dist/pace/schema.js.map +0 -1
  193. package/dist/pace/session-summary.d.ts.map +0 -1
  194. package/dist/pace/session-summary.js.map +0 -1
  195. package/dist/pace/spool.d.ts.map +0 -1
  196. package/dist/pace/spool.js.map +0 -1
  197. package/dist/pace-runtime.d.ts.map +0 -1
  198. package/dist/pace-runtime.js.map +0 -1
  199. package/dist/sync/api.d.ts.map +0 -1
  200. package/dist/sync/api.js.map +0 -1
  201. package/dist/sync/autoloader.d.ts.map +0 -1
  202. package/dist/sync/autoloader.js.map +0 -1
  203. package/dist/sync/conflict.d.ts.map +0 -1
  204. package/dist/sync/conflict.js.map +0 -1
  205. package/dist/sync/credentials.d.ts.map +0 -1
  206. package/dist/sync/credentials.js.map +0 -1
  207. package/dist/sync/files.d.ts.map +0 -1
  208. package/dist/sync/files.js.map +0 -1
  209. package/dist/sync/manifest.d.ts.map +0 -1
  210. package/dist/sync/manifest.js.map +0 -1
  211. package/dist/sync/repo-root.d.ts.map +0 -1
  212. package/dist/sync/repo-root.js.map +0 -1
  213. package/dist/sync/stitch-claude-md.d.ts.map +0 -1
  214. package/dist/sync/stitch-claude-md.js.map +0 -1
  215. package/dist/ui/colors.d.ts.map +0 -1
  216. package/dist/ui/colors.js.map +0 -1
  217. package/dist/ui/screens.d.ts.map +0 -1
  218. package/dist/ui/screens.js.map +0 -1
@@ -1,234 +1,20 @@
1
- import fs from "node:fs/promises";
2
- import os from "node:os";
3
- import path from "node:path";
4
- import { buildScopedKeyBase } from "./claude-desktop.js";
5
- const SECTION_HEADER = "[mcp_servers.unfairly]";
6
- const SHARE_TAG_PREFIX = "# share_link_id = ";
7
- /**
8
- * Build the canonical [mcp_servers.unfairly] block. We own this whole
9
- * section — anything inside it gets overwritten on re-runs.
10
- */
11
- export function buildCodexBlock(apiUrl) {
12
- const url = `${apiUrl.replace(/\/$/, "")}/api/mcp`;
13
- return [
14
- SECTION_HEADER,
15
- `url = "${url}"`,
16
- `bearer_token_env_var = "UNFAIRLY_MCP_TOKEN"`,
17
- ].join("\n");
18
- }
19
- /**
20
- * Strip ALL existing `[mcp_servers.unfairly]` blocks from a TOML string.
21
- * "Block" = the section header through (but not including) the next
22
- * top-level `[...]` table header at column 0, or end-of-file. This also
23
- * removes any trailing blank lines we previously left.
24
- *
25
- * Robust against: duplicate blocks from prior bad runs, CRLF input,
26
- * blocks at end-of-file with no trailing newline.
27
- */
28
- export function stripUnfairlyBlocks(toml) {
29
- // Normalize CRLF for matching; we'll use the same normalized form for
30
- // output. (Codex writes LF on macOS / Linux anyway.)
31
- const normalized = toml.replace(/\r\n/g, "\n");
32
- // Match each block: header line, then everything up to next top-level
33
- // [section] header or end-of-string. Multiline mode anchors `^[` to
34
- // line start. Use `g` to clean up duplicates.
35
- const blockRe = /^\[mcp_servers\.unfairly\]\s*\n[\s\S]*?(?=^\[|\Z)/gm;
36
- // Note: `\Z` not supported in JS regex. Substitute with `(?=^\[|$(?![\s\S]))`.
37
- const jsBlockRe = /^\[mcp_servers\.unfairly\]\s*\n[\s\S]*?(?=^\[|$(?![\s\S]))/gm;
38
- void blockRe; // documentation only
39
- let stripped = normalized.replace(jsBlockRe, "");
40
- // Collapse runs of 3+ blank lines that the strip may have left behind.
41
- stripped = stripped.replace(/\n{3,}/g, "\n\n");
42
- return stripped;
43
- }
44
- /**
45
- * Patch ~/.codex/config.toml to register the Unfairly MCP server with
46
- * bearer-token wiring. Idempotent: removes any existing managed block(s)
47
- * first, then appends one canonical block. Safe against duplicate sections
48
- * left over from prior bad runs.
49
- *
50
- * If ~/.codex/config.toml does not exist, returns {status: "not-installed"}
51
- * — don't create a Codex config out of thin air for a user who may not
52
- * have Codex installed.
53
- */
54
- export async function configureCodex(apiUrl) {
55
- const home = os.homedir();
56
- const filePath = path.join(home, ".codex", "config.toml");
57
- let existing;
58
- try {
59
- existing = await fs.readFile(filePath, "utf-8");
60
- }
61
- catch (err) {
62
- const e = err;
63
- if (e.code === "ENOENT") {
64
- return { status: "not-installed", path: filePath };
65
- }
66
- return {
67
- status: "error",
68
- path: filePath,
69
- message: `Could not read ${filePath}: ${e.message}`,
70
- };
71
- }
72
- const hadExistingBlock = /^\[mcp_servers\.unfairly\]/m.test(existing.replace(/\r\n/g, "\n"));
73
- const stripped = stripUnfairlyBlocks(existing);
74
- const block = buildCodexBlock(apiUrl);
75
- // Append, ensuring exactly one blank line of separation if the file is
76
- // non-empty.
77
- const trimmedTail = stripped.replace(/\n+$/, "");
78
- const next = trimmedTail.length === 0
79
- ? `${block}\n`
80
- : `${trimmedTail}\n\n${block}\n`;
81
- try {
82
- await fs.writeFile(filePath, next, "utf-8");
83
- }
84
- catch (err) {
85
- const e = err;
86
- return {
87
- status: "error",
88
- path: filePath,
89
- message: `Could not write ${filePath}: ${e.message}`,
90
- };
91
- }
92
- const action = hadExistingBlock
93
- ? "replaced"
94
- : existing.length === 0
95
- ? "created"
96
- : "appended";
97
- return { status: "configured", path: filePath, action };
98
- }
99
- /**
100
- * Build a scoped Codex block. Inlines the literal bearer_token — these
101
- * are short-lived (max 24h), one-off tokens, so env-var indirection isn't
102
- * worth the setup friction. A `# share_link_id = "<id>"` comment line
103
- * above the section header serves as the lookup tag for idempotent
104
- * rotation.
105
- */
106
- export function buildScopedCodexBlock(key, mcpUrl, token, shareLinkId) {
107
- return [
108
- `${SHARE_TAG_PREFIX}"${shareLinkId}"`,
109
- `[mcp_servers.${key}]`,
110
- `url = "${mcpUrl}"`,
111
- `bearer_token = "${token}"`,
112
- ].join("\n");
113
- }
114
- /**
115
- * Escape a string for safe inclusion inside a JS regex literal.
116
- */
117
- function escapeRe(s) {
118
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
119
- }
120
- /**
121
- * Find the existing scoped block keyed by `shareLinkId`, if any. The tag
122
- * comment must immediately precede the section header. Returns the key
123
- * from the section header, or null if no block matches.
124
- */
125
- export function findScopedBlockKey(toml, shareLinkId) {
126
- const normalized = toml.replace(/\r\n/g, "\n");
127
- const re = new RegExp(`^${escapeRe(SHARE_TAG_PREFIX)}"${escapeRe(shareLinkId)}"\\s*\\n\\[mcp_servers\\.([a-zA-Z0-9_-]+)\\]`, "m");
128
- const m = normalized.match(re);
129
- return m?.[1] ?? null;
130
- }
131
- /**
132
- * Strip a single scoped block (tag + section + body, through but not
133
- * including the next top-level `[...]` table header). Returns the
134
- * remaining TOML. No-op if the block isn't present.
135
- */
136
- export function stripScopedBlock(toml, shareLinkId) {
137
- const normalized = toml.replace(/\r\n/g, "\n");
138
- const re = new RegExp(`^${escapeRe(SHARE_TAG_PREFIX)}"${escapeRe(shareLinkId)}"\\s*\\n\\[mcp_servers\\.[a-zA-Z0-9_-]+\\]\\s*\\n[\\s\\S]*?(?=^\\[|$(?![\\s\\S]))`, "gm");
139
- let stripped = normalized.replace(re, "");
140
- stripped = stripped.replace(/\n{3,}/g, "\n\n");
141
- return stripped;
142
- }
143
- /**
144
- * Enumerate all `[mcp_servers.<key>]` keys defined in the TOML. Used to
145
- * find the lowest free numbered slot for a new scoped entry.
146
- */
147
- export function listMcpServerKeys(toml) {
148
- const normalized = toml.replace(/\r\n/g, "\n");
149
- const re = /^\[mcp_servers\.([a-zA-Z0-9_-]+)\]/gm;
150
- const keys = new Set();
151
- let m;
152
- while ((m = re.exec(normalized)) !== null) {
153
- if (m[1])
154
- keys.add(m[1]);
155
- }
156
- return [...keys];
157
- }
158
- /**
159
- * Pick the next free Codex key for a scoped entry. Same numbering scheme
160
- * as the JSON-host pickNextEntryKey: base key, then -2, -3, ... reusing
161
- * gaps.
162
- */
163
- export function pickNextCodexKey(toml, baseKey) {
164
- const existing = new Set(listMcpServerKeys(toml));
165
- if (!existing.has(baseKey))
166
- return baseKey;
167
- let n = 2;
168
- while (existing.has(`${baseKey}-${n}`))
169
- n += 1;
170
- return `${baseKey}-${n}`;
171
- }
172
- /**
173
- * Add a scoped, per-share_link MCP entry to ~/.codex/config.toml. Does
174
- * NOT touch the canonical `[mcp_servers.unfairly]` env-var block — those
175
- * are for the user's primary token. Scoped entries live alongside.
176
- *
177
- * Idempotent: if a block tagged with the same shareLinkId already
178
- * exists, rotate in place (strip + append at the same key).
179
- *
180
- * Returns `not-installed` when ~/.codex/config.toml doesn't exist
181
- * (matches `configureCodex` behavior — never creates from scratch).
182
- */
183
- export async function addScopedCodexEntry(input) {
184
- const home = os.homedir();
185
- const filePath = path.join(home, ".codex", "config.toml");
186
- let existing;
187
- try {
188
- existing = await fs.readFile(filePath, "utf-8");
189
- }
190
- catch (err) {
191
- const e = err;
192
- if (e.code === "ENOENT") {
193
- return { status: "not-installed", path: filePath };
194
- }
195
- return {
196
- status: "error",
197
- path: filePath,
198
- message: `Could not read ${filePath}: ${e.message}`,
199
- };
200
- }
201
- const baseKey = buildScopedKeyBase(input.orgSlug, input.roomSlug);
202
- const existingKey = findScopedBlockKey(existing, input.shareLinkId);
203
- let key;
204
- let replaced;
205
- let stripped;
206
- if (existingKey) {
207
- key = existingKey;
208
- replaced = true;
209
- stripped = stripScopedBlock(existing, input.shareLinkId);
210
- }
211
- else {
212
- stripped = existing;
213
- key = pickNextCodexKey(stripped, baseKey);
214
- replaced = false;
215
- }
216
- const block = buildScopedCodexBlock(key, input.mcpUrl, input.token, input.shareLinkId);
217
- const trimmedTail = stripped.replace(/\n+$/, "");
218
- const next = trimmedTail.length === 0
219
- ? `${block}\n`
220
- : `${trimmedTail}\n\n${block}\n`;
221
- try {
222
- await fs.writeFile(filePath, next, "utf-8");
223
- }
224
- catch (err) {
225
- const e = err;
226
- return {
227
- status: "error",
228
- path: filePath,
229
- message: `Could not write ${filePath}: ${e.message}`,
230
- };
231
- }
232
- return { status: "configured", path: filePath, key, replaced };
233
- }
234
- //# sourceMappingURL=codex.js.map
1
+ import u from"node:fs/promises";import h from"node:os";import x from"node:path";import{buildScopedKeyBase as _}from"./claude-desktop.js";const k="[mcp_servers.unfairly]",$="# share_link_id = ";function y(t){const n=`${t.replace(/\/$/,"")}/api/mcp`;return[k,`url = "${n}"`,'bearer_token_env_var = "UNFAIRLY_MCP_TOKEN"'].join(`
2
+ `)}function S(t){const n=t.replace(/\r\n/g,`
3
+ `),e=/^\[mcp_servers\.unfairly\]\s*\n[\s\S]*?(?=^\[|\Z)/gm,r=/^\[mcp_servers\.unfairly\]\s*\n[\s\S]*?(?=^\[|$(?![\s\S]))/gm;let o=n.replace(r,"");return o=o.replace(/\n{3,}/g,`
4
+
5
+ `),o}async function T(t){const n=h.homedir(),e=x.join(n,".codex","config.toml");let r;try{r=await u.readFile(e,"utf-8")}catch(i){const l=i;return l.code==="ENOENT"?{status:"not-installed",path:e}:{status:"error",path:e,message:`Could not read ${e}: ${l.message}`}}const o=/^\[mcp_servers\.unfairly\]/m.test(r.replace(/\r\n/g,`
6
+ `)),p=S(r),s=y(t),c=p.replace(/\n+$/,""),a=c.length===0?`${s}
7
+ `:`${c}
8
+
9
+ ${s}
10
+ `;try{await u.writeFile(e,a,"utf-8")}catch(i){return{status:"error",path:e,message:`Could not write ${e}: ${i.message}`}}const d=o?"replaced":r.length===0?"created":"appended";return{status:"configured",path:e,action:d}}function w(t,n,e,r){return[`${$}"${r}"`,`[mcp_servers.${t}]`,`url = "${n}"`,`bearer_token = "${e}"`].join(`
11
+ `)}function m(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function E(t,n){const e=t.replace(/\r\n/g,`
12
+ `),r=new RegExp(`^${m($)}"${m(n)}"\\s*\\n\\[mcp_servers\\.([a-zA-Z0-9_-]+)\\]`,"m");return e.match(r)?.[1]??null}function v(t,n){const e=t.replace(/\r\n/g,`
13
+ `),r=new RegExp(`^${m($)}"${m(n)}"\\s*\\n\\[mcp_servers\\.[a-zA-Z0-9_-]+\\]\\s*\\n[\\s\\S]*?(?=^\\[|$(?![\\s\\S]))`,"gm");let o=e.replace(r,"");return o=o.replace(/\n{3,}/g,`
14
+
15
+ `),o}function C(t){const n=t.replace(/\r\n/g,`
16
+ `),e=/^\[mcp_servers\.([a-zA-Z0-9_-]+)\]/gm,r=new Set;let o;for(;(o=e.exec(n))!==null;)o[1]&&r.add(o[1]);return[...r]}function R(t,n){const e=new Set(C(t));if(!e.has(n))return n;let r=2;for(;e.has(`${n}-${r}`);)r+=1;return`${n}-${r}`}async function b(t){const n=h.homedir(),e=x.join(n,".codex","config.toml");let r;try{r=await u.readFile(e,"utf-8")}catch(f){const g=f;return g.code==="ENOENT"?{status:"not-installed",path:e}:{status:"error",path:e,message:`Could not read ${e}: ${g.message}`}}const o=_(t.orgSlug,t.roomSlug),p=E(r,t.shareLinkId);let s,c,a;p?(s=p,c=!0,a=v(r,t.shareLinkId)):(a=r,s=R(a,o),c=!1);const d=w(s,t.mcpUrl,t.token,t.shareLinkId),i=a.replace(/\n+$/,""),l=i.length===0?`${d}
17
+ `:`${i}
18
+
19
+ ${d}
20
+ `;try{await u.writeFile(e,l,"utf-8")}catch(f){return{status:"error",path:e,message:`Could not write ${e}: ${f.message}`}}return{status:"configured",path:e,key:s,replaced:c}}export{b as addScopedCodexEntry,y as buildCodexBlock,w as buildScopedCodexBlock,T as configureCodex,E as findScopedBlockKey,C as listMcpServerKeys,R as pickNextCodexKey,v as stripScopedBlock,S as stripUnfairlyBlocks};
@@ -13,4 +13,3 @@ export type ShellEnvResult = {
13
13
  */
14
14
  export declare function writeShellEnvFile(rcPath: string, token: string): Promise<"created" | "appended" | "replaced">;
15
15
  export declare function writeShellEnv(token: string): Promise<ShellEnvResult>;
16
- //# sourceMappingURL=shell-env.d.ts.map
@@ -1,81 +1,9 @@
1
- import fs from "node:fs/promises";
2
- import os from "node:os";
3
- import path from "node:path";
4
- export const ENV_BLOCK_START = "# === unfairly cli (auto-managed — do not edit) ===";
5
- export const ENV_BLOCK_END = "# === end unfairly cli ===";
6
- /**
7
- * Detect the user's shell + the right rcfile to write env exports to.
8
- * Returns null path for unknown shells so the caller can print a manual
9
- * fallback instead of guessing.
10
- */
11
- function detectShell() {
12
- const shellEnv = process.env.SHELL ?? "";
13
- const home = os.homedir();
14
- if (shellEnv.endsWith("zsh")) {
15
- return { shell: "zsh", rcPath: path.join(home, ".zshenv") };
16
- }
17
- if (shellEnv.endsWith("bash")) {
18
- return { shell: "bash", rcPath: path.join(home, ".bash_profile") };
19
- }
20
- return { shell: "unknown", rcPath: null };
21
- }
22
- /**
23
- * Build the canonical sentinel block. Used both for writing and matching.
24
- */
25
- function buildBlock(token) {
26
- return [
27
- ENV_BLOCK_START,
28
- `export UNFAIRLY_MCP_TOKEN=${token}`,
29
- `export UNFAIRLY_TOKEN=${token}`,
30
- ENV_BLOCK_END,
31
- ].join("\n");
32
- }
33
- /**
34
- * Idempotent shell-env writer. Replaces any existing managed block in
35
- * place; appends one if none exists. Tolerates CRLF input by normalizing
36
- * before matching, then preserves the host file's existing line ending
37
- * convention on write.
38
- */
39
- export async function writeShellEnvFile(rcPath, token) {
40
- const block = buildBlock(token);
41
- let existing = "";
42
- let fileExists = true;
43
- try {
44
- existing = await fs.readFile(rcPath, "utf-8");
45
- }
46
- catch {
47
- fileExists = false;
48
- }
49
- const normalized = existing.replace(/\r\n/g, "\n");
50
- const blockRe = new RegExp(`${escapeRegex(ENV_BLOCK_START)}[\\s\\S]*?${escapeRegex(ENV_BLOCK_END)}\\n?`, "g");
51
- let next;
52
- let action;
53
- if (blockRe.test(normalized)) {
54
- blockRe.lastIndex = 0;
55
- next = normalized.replace(blockRe, block + "\n");
56
- action = "replaced";
57
- }
58
- else if (!fileExists || normalized.length === 0) {
59
- next = block + "\n";
60
- action = "created";
61
- }
62
- else {
63
- const sep = normalized.endsWith("\n") ? "" : "\n";
64
- next = `${normalized}${sep}\n${block}\n`;
65
- action = "appended";
66
- }
67
- await fs.writeFile(rcPath, next, "utf-8");
68
- return action;
69
- }
70
- export async function writeShellEnv(token) {
71
- const { shell, rcPath } = detectShell();
72
- if (!rcPath) {
73
- return { path: "", shell, action: "created" };
74
- }
75
- const action = await writeShellEnvFile(rcPath, token);
76
- return { path: rcPath, shell, action };
77
- }
78
- function escapeRegex(s) {
79
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
80
- }
81
- //# sourceMappingURL=shell-env.js.map
1
+ import a from"node:fs/promises";import x from"node:os";import h from"node:path";const p="# === unfairly cli (auto-managed \u2014 do not edit) ===",u="# === end unfairly cli ===";function E(){const e=process.env.SHELL??"",t=x.homedir();return e.endsWith("zsh")?{shell:"zsh",rcPath:h.join(t,".zshenv")}:e.endsWith("bash")?{shell:"bash",rcPath:h.join(t,".bash_profile")}:{shell:"unknown",rcPath:null}}function m(e){return[p,`export UNFAIRLY_MCP_TOKEN=${e}`,`export UNFAIRLY_TOKEN=${e}`,u].join(`
2
+ `)}async function $(e,t){const n=m(t);let l="",c=!0;try{l=await a.readFile(e,"utf-8")}catch{c=!1}const r=l.replace(/\r\n/g,`
3
+ `),s=new RegExp(`${f(p)}[\\s\\S]*?${f(u)}\\n?`,"g");let o,i;if(s.test(r))s.lastIndex=0,o=r.replace(s,n+`
4
+ `),i="replaced";else if(!c||r.length===0)o=n+`
5
+ `,i="created";else{const d=r.endsWith(`
6
+ `)?"":`
7
+ `;o=`${r}${d}
8
+ ${n}
9
+ `,i="appended"}return await a.writeFile(e,o,"utf-8"),i}async function N(e){const{shell:t,rcPath:n}=E();if(!n)return{path:"",shell:t,action:"created"};const l=await $(n,e);return{path:n,shell:t,action:l}}function f(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}export{u as ENV_BLOCK_END,p as ENV_BLOCK_START,N as writeShellEnv,$ as writeShellEnvFile};
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  #!/usr/bin/env node
2
2
  export {};
3
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,207 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { readFileSync } from "node:fs";
3
- import { promises as fs } from "node:fs";
4
- import { fileURLToPath } from "node:url";
5
- import { dirname, join } from "node:path";
6
- import yargs from "yargs";
7
- import { hideBin } from "yargs/helpers";
8
- import { inviteCommand } from "./cmd/invite.js";
9
- import { joinCommand } from "./cmd/join.js";
10
- import { connectCommand } from "./cmd/connect.js";
11
- const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8"));
12
- await yargs(hideBin(process.argv))
13
- .scriptName("unfairly")
14
- .usage("$0 [cmd] [args]")
15
- .version(pkg.version)
16
- .command("$0", "First-run: wire MCP across hosts, bind workspace if in a repo, show status otherwise", (y) => y.option("yes", {
17
- type: "boolean",
18
- alias: "y",
19
- default: false,
20
- describe: "Skip confirmation prompts",
21
- }), async (argv) => {
22
- await runBare({ yes: argv.yes });
23
- })
24
- .command("setup", "Wire MCP for Claude Desktop / Claude Code / Codex on this machine", (y) => y
25
- .option("yes", { type: "boolean", alias: "y", default: false })
26
- .option("org", { type: "string", description: "Organization ID from your team's Intelligence invite" }), async (argv) => {
27
- const { runSetup } = await import("./cmd/setup.js");
28
- await runSetup({ chainInit: false, yes: argv.yes, org: argv.org });
29
- })
30
- .command("login", "Authorize via browser; print export lines for ~/.zshenv", (y) => y.option("quiet", { type: "boolean", alias: "q", default: false }), async (argv) => {
31
- const { runLogin } = await import("./cmd/login.js");
32
- await runLogin({ quiet: argv.quiet });
33
- })
34
- .command("init", "Bind .unfairly/ to cwd and pull all accessible vaults", (y) => y
35
- .option("token", { type: "string" })
36
- .option("yes", { type: "boolean", alias: "y", default: false })
37
- .option("no-browser", { type: "boolean", default: false }), async (argv) => {
38
- const { runInit } = await import("./cmd/init.js");
39
- await runInit({
40
- token: argv.token,
41
- yes: argv.yes,
42
- noBrowser: argv["no-browser"],
43
- });
44
- })
45
- .command("pull [vault]", "Pull markdown from cloud", (y) => y.positional("vault", { type: "string" }), async (argv) => {
46
- const { runPull } = await import("./cmd/pull.js");
47
- await runPull(argv.vault);
48
- })
49
- .command("push [vault]", "Push local edits to cloud", (y) => y.positional("vault", { type: "string" }), async (argv) => {
50
- const { runPush } = await import("./cmd/push.js");
51
- await runPush(argv.vault);
52
- })
53
- .command("status", "Show local-vs-cloud sync status", () => { }, async () => {
54
- const { runStatus } = await import("./cmd/status.js");
55
- await runStatus();
56
- })
57
- .command("resolve <path>", "Mark a conflicted file as resolved", (y) => y.positional("path", { type: "string", demandOption: true }), async (argv) => {
58
- const { runResolve } = await import("./cmd/resolve.js");
59
- await runResolve(argv.path);
60
- })
61
- .command("watch", "Watch .unfairly/ for changes; debounced auto-push", () => { }, async () => {
62
- const { runWatch } = await import("./cmd/watch.js");
63
- await runWatch();
64
- })
65
- .command("mcp", "Run as stdio MCP server (sync tools)", () => { }, async () => {
66
- const { runMcp } = await import("./cmd/mcp.js");
67
- await runMcp();
68
- })
69
- .command(["intelligence <action>", "pace <action>"], "Capture, upload, or inspect Unfairly Intelligence metadata", (y) => y
70
- .positional("action", { choices: ["capture", "config", "evidence-scan", "evidence-watch", "flush", "heartbeat", "install", "pause", "playbook-use", "playbooks", "policy", "backfill", "resume", "status", "uninstall"] })
71
- .option("source", { type: "string", default: "unknown" })
72
- .option("event", { type: "string", default: "Unknown" })
73
- .option("output", { type: "string", default: "./ai-pace-managed" })
74
- .option("command", { type: "string", default: "/usr/local/bin/unfairly" })
75
- .option("managed-dir", { type: "string", default: "/usr/local/lib/ai-pace" })
76
- .option("policy", { type: "string", description: "Path to the centrally managed local-evidence policy" })
77
- .option("evidence-root", { type: "array", string: true, description: "Approved output directory to include in generated policy" })
78
- .option("include-file-names", { type: "boolean", default: false, description: "Include file basenames in local evidence; disabled by default" })
79
- .option("query", { type: "string", description: "Search approved company playbooks" })
80
- .option("playbook-id", { type: "string", description: "Opaque approved playbook ID" })
81
- .option("playbook-version", { type: "string", description: "Approved playbook version" })
82
- .option("days", { type: "number", default: 90, description: "Backfill window in days" }), async (argv) => {
83
- const { runPaceCapture, runPaceFlush, runPaceStatus } = await import("./cmd/pace.js");
84
- if (argv.action === "capture") {
85
- await runPaceCapture(argv.source, argv.event);
86
- }
87
- else if (argv.action === "config") {
88
- const { runPaceConfig } = await import("./cmd/pace.js");
89
- const files = await runPaceConfig({
90
- outputDir: argv.output,
91
- command: argv.command,
92
- managedDir: argv["managed-dir"],
93
- evidenceRoots: argv["evidence-root"],
94
- includeFileNames: argv["include-file-names"],
95
- });
96
- process.stdout.write(`${JSON.stringify({ files })}\n`);
97
- }
98
- else if (argv.action === "evidence-scan") {
99
- const { runPaceEvidenceScan } = await import("./cmd/pace.js");
100
- const result = await runPaceEvidenceScan(argv.policy);
101
- process.stdout.write(`${JSON.stringify(result)}\n`);
102
- }
103
- else if (argv.action === "evidence-watch") {
104
- const { runPaceEvidenceWatch } = await import("./cmd/pace.js");
105
- await runPaceEvidenceWatch(argv.policy);
106
- }
107
- else if (argv.action === "flush") {
108
- const result = await runPaceFlush();
109
- process.stdout.write(`${JSON.stringify(result)}\n`);
110
- }
111
- else if (argv.action === "heartbeat") {
112
- const { runPaceHeartbeat } = await import("./cmd/pace.js");
113
- const result = await runPaceHeartbeat();
114
- process.stdout.write(`${JSON.stringify(result)}\n`);
115
- }
116
- else if (argv.action === "install") {
117
- const { runPaceInstall } = await import("./cmd/pace.js");
118
- process.stdout.write(`${JSON.stringify(await runPaceInstall(), null, 2)}\n`);
119
- }
120
- else if (argv.action === "playbooks") {
121
- const { runPacePlaybooks } = await import("./cmd/pace.js");
122
- const playbooks = await runPacePlaybooks(argv.query);
123
- process.stdout.write(`${JSON.stringify({ playbooks }, null, 2)}\n`);
124
- }
125
- else if (argv.action === "playbook-use") {
126
- if (!argv["playbook-id"] || !argv["playbook-version"])
127
- throw new Error("--playbook-id and --playbook-version are required");
128
- const { runPacePlaybookUse } = await import("./cmd/pace.js");
129
- process.stdout.write(`${JSON.stringify(await runPacePlaybookUse(argv["playbook-id"], argv["playbook-version"]))}\n`);
130
- }
131
- else if (argv.action === "policy") {
132
- const { runPacePolicy } = await import("./cmd/pace.js");
133
- process.stdout.write(`${JSON.stringify(runPacePolicy(), null, 2)}\n`);
134
- }
135
- else if (argv.action === "backfill") {
136
- const { runPaceBackfill } = await import("./cmd/pace.js");
137
- process.stdout.write(`${JSON.stringify(await runPaceBackfill(argv.days))}\n`);
138
- }
139
- else if (argv.action === "pause" || argv.action === "resume") {
140
- const { runPacePause } = await import("./cmd/pace.js");
141
- process.stdout.write(`${JSON.stringify(await runPacePause(argv.action === "pause"))}\n`);
142
- }
143
- else if (argv.action === "uninstall") {
144
- const { runPaceUninstall } = await import("./cmd/pace.js");
145
- process.stdout.write(`${JSON.stringify(await runPaceUninstall())}\n`);
146
- }
147
- else {
148
- await runPaceStatus();
149
- }
150
- })
151
- .command(inviteCommand)
152
- .command(joinCommand)
153
- .command(connectCommand)
154
- .strict()
155
- .help()
156
- .parse();
157
- async function runBare(opts) {
158
- const startCwd = process.cwd();
159
- const { getToken } = await import("./sync/credentials.js");
160
- const { findRepoRoot } = await import("./sync/repo-root.js");
161
- const repoRoot = await findRepoRoot(startCwd);
162
- // If we found a repo root and we're in a subdir, chdir up so init/pull/
163
- // stitch all see the same .unfairly/ at the repo root. Explicit subcommands
164
- // (`unfairly init`) keep their existing cwd-relative behavior — only the
165
- // bare entrypoint promotes to repoRoot.
166
- if (repoRoot && repoRoot !== startCwd) {
167
- process.chdir(repoRoot);
168
- }
169
- const effectiveCwd = process.cwd();
170
- const token = await getToken();
171
- const manifestExists = await pathExists(join(effectiveCwd, ".unfairly", "manifest.json"));
172
- if (!token) {
173
- // Cold install — full setup, chain init when in repo
174
- const { runSetup } = await import("./cmd/setup.js");
175
- await runSetup({ chainInit: Boolean(repoRoot), yes: opts.yes });
176
- return;
177
- }
178
- // Existing users get the same one-command Intelligence install as a cold
179
- // setup, and a later-installed client is picked up on the next check-in.
180
- const { detectPaceClients, needsIntelligenceInstall, readOrCreatePaceDevice } = await import("./pace/device.js");
181
- const device = await readOrCreatePaceDevice();
182
- const detected = await detectPaceClients();
183
- if (needsIntelligenceInstall(device, detected)) {
184
- process.stderr.write("\nInstalling Unfairly Intelligence across detected AI clients…\n");
185
- const { runPaceInstall } = await import("./cmd/pace.js");
186
- await runPaceInstall();
187
- }
188
- if (!manifestExists && repoRoot) {
189
- // Token exists, no workspace bound, in a repo — offer init only
190
- const { runInit } = await import("./cmd/init.js");
191
- await runInit({ yes: opts.yes });
192
- return;
193
- }
194
- // Daily check-in
195
- const { runStatusCard } = await import("./cmd/status-card.js");
196
- await runStatusCard();
197
- }
198
- async function pathExists(p) {
199
- try {
200
- await fs.access(p);
201
- return true;
202
- }
203
- catch {
204
- return false;
205
- }
206
- }
207
- //# sourceMappingURL=index.js.map
2
+ import{readFileSync as w}from"node:fs";import{promises as b}from"node:fs";import{fileURLToPath as h}from"node:url";import{dirname as k,join as c}from"node:path";import P from"yargs";import{hideBin as g}from"yargs/helpers";import{inviteCommand as S}from"./cmd/invite.js";import{joinCommand as C}from"./cmd/join.js";import{connectCommand as I}from"./cmd/connect.js";const O=JSON.parse(w(c(k(h(import.meta.url)),"..","package.json"),"utf8"));await P(g(process.argv)).scriptName("unfairly").usage("$0 [cmd] [args]").version(O.version).command("$0","First-run: wire MCP across hosts, bind workspace if in a repo, show status otherwise",t=>t.option("yes",{type:"boolean",alias:"y",default:!1,describe:"Skip confirmation prompts"}),async t=>{await N({yes:t.yes})}).command("setup","Wire MCP for Claude Desktop / Claude Code / Codex on this machine",t=>t.option("yes",{type:"boolean",alias:"y",default:!1}).option("org",{type:"string",description:"Organization ID from your team's Intelligence invite"}),async t=>{const{runSetup:o}=await import("./cmd/setup.js");await o({chainInit:!1,yes:t.yes,org:t.org})}).command("login","Authorize via browser; print export lines for ~/.zshenv",t=>t.option("quiet",{type:"boolean",alias:"q",default:!1}),async t=>{const{runLogin:o}=await import("./cmd/login.js");await o({quiet:t.quiet})}).command("init","Bind .unfairly/ to cwd and pull all accessible vaults",t=>t.option("token",{type:"string"}).option("yes",{type:"boolean",alias:"y",default:!1}).option("no-browser",{type:"boolean",default:!1}),async t=>{const{runInit:o}=await import("./cmd/init.js");await o({token:t.token,yes:t.yes,noBrowser:t["no-browser"]})}).command("pull [vault]","Pull markdown from cloud",t=>t.positional("vault",{type:"string"}),async t=>{const{runPull:o}=await import("./cmd/pull.js");await o(t.vault)}).command("push [vault]","Push local edits to cloud",t=>t.positional("vault",{type:"string"}),async t=>{const{runPush:o}=await import("./cmd/push.js");await o(t.vault)}).command("status","Show local-vs-cloud sync status",()=>{},async()=>{const{runStatus:t}=await import("./cmd/status.js");await t()}).command("resolve <path>","Mark a conflicted file as resolved",t=>t.positional("path",{type:"string",demandOption:!0}),async t=>{const{runResolve:o}=await import("./cmd/resolve.js");await o(t.path)}).command("watch","Watch .unfairly/ for changes; debounced auto-push",()=>{},async()=>{const{runWatch:t}=await import("./cmd/watch.js");await t()}).command("mcp","Run as stdio MCP server (sync tools)",()=>{},async()=>{const{runMcp:t}=await import("./cmd/mcp.js");await t()}).command(["intelligence <action>","pace <action>"],"Capture, upload, or inspect Unfairly Intelligence metadata",t=>t.positional("action",{choices:["capture","config","evidence-scan","evidence-watch","flush","heartbeat","install","pause","playbook-use","playbooks","policy","backfill","resume","status","uninstall"]}).option("source",{type:"string",default:"unknown"}).option("event",{type:"string",default:"Unknown"}).option("output",{type:"string",default:"./ai-pace-managed"}).option("command",{type:"string",default:"/usr/local/bin/unfairly"}).option("managed-dir",{type:"string",default:"/usr/local/lib/ai-pace"}).option("policy",{type:"string",description:"Path to the centrally managed local-evidence policy"}).option("evidence-root",{type:"array",string:!0,description:"Approved output directory to include in generated policy"}).option("include-file-names",{type:"boolean",default:!1,description:"Include file basenames in local evidence; disabled by default"}).option("query",{type:"string",description:"Search approved company playbooks"}).option("playbook-id",{type:"string",description:"Opaque approved playbook ID"}).option("playbook-version",{type:"string",description:"Approved playbook version"}).option("days",{type:"number",default:90,description:"Backfill window in days"}),async t=>{const{runPaceCapture:o,runPaceFlush:n,runPaceStatus:s}=await import("./cmd/pace.js");if(t.action==="capture")await o(t.source,t.event);else if(t.action==="config"){const{runPaceConfig:i}=await import("./cmd/pace.js"),e=await i({outputDir:t.output,command:t.command,managedDir:t["managed-dir"],evidenceRoots:t["evidence-root"],includeFileNames:t["include-file-names"]});process.stdout.write(`${JSON.stringify({files:e})}
3
+ `)}else if(t.action==="evidence-scan"){const{runPaceEvidenceScan:i}=await import("./cmd/pace.js"),e=await i(t.policy);process.stdout.write(`${JSON.stringify(e)}
4
+ `)}else if(t.action==="evidence-watch"){const{runPaceEvidenceWatch:i}=await import("./cmd/pace.js");await i(t.policy)}else if(t.action==="flush"){const i=await n();process.stdout.write(`${JSON.stringify(i)}
5
+ `)}else if(t.action==="heartbeat"){const{runPaceHeartbeat:i}=await import("./cmd/pace.js"),e=await i();process.stdout.write(`${JSON.stringify(e)}
6
+ `)}else if(t.action==="install"){const{runPaceInstall:i}=await import("./cmd/pace.js");process.stdout.write(`${JSON.stringify(await i(),null,2)}
7
+ `)}else if(t.action==="playbooks"){const{runPacePlaybooks:i}=await import("./cmd/pace.js"),e=await i(t.query);process.stdout.write(`${JSON.stringify({playbooks:e},null,2)}
8
+ `)}else if(t.action==="playbook-use"){if(!t["playbook-id"]||!t["playbook-version"])throw new Error("--playbook-id and --playbook-version are required");const{runPacePlaybookUse:i}=await import("./cmd/pace.js");process.stdout.write(`${JSON.stringify(await i(t["playbook-id"],t["playbook-version"]))}
9
+ `)}else if(t.action==="policy"){const{runPacePolicy:i}=await import("./cmd/pace.js");process.stdout.write(`${JSON.stringify(i(),null,2)}
10
+ `)}else if(t.action==="backfill"){const{runPaceBackfill:i}=await import("./cmd/pace.js");process.stdout.write(`${JSON.stringify(await i(t.days))}
11
+ `)}else if(t.action==="pause"||t.action==="resume"){const{runPacePause:i}=await import("./cmd/pace.js");process.stdout.write(`${JSON.stringify(await i(t.action==="pause"))}
12
+ `)}else if(t.action==="uninstall"){const{runPaceUninstall:i}=await import("./cmd/pace.js");process.stdout.write(`${JSON.stringify(await i())}
13
+ `)}else await s()}).command(S).command(C).command(I).strict().help().parse();async function N(t){const o=process.cwd(),{getToken:n}=await import("./sync/credentials.js"),{findRepoRoot:s}=await import("./sync/repo-root.js"),i=await s(o);i&&i!==o&&process.chdir(i);const e=process.cwd(),r=await n(),l=await v(c(e,".unfairly","manifest.json"));if(!r){const{runSetup:a}=await import("./cmd/setup.js");await a({chainInit:!!i,yes:t.yes});return}const{detectPaceClients:p,needsIntelligenceInstall:u,readOrCreatePaceDevice:d}=await import("./pace/device.js"),m=await d(),y=await p();if(u(m,y)){process.stderr.write(`
14
+ Installing Unfairly Intelligence across detected AI clients\u2026
15
+ `);const{runPaceInstall:a}=await import("./cmd/pace.js");await a()}if(!l&&i){const{runInit:a}=await import("./cmd/init.js");await a({yes:t.yes});return}const{runStatusCard:f}=await import("./cmd/status-card.js");await f()}async function v(t){try{return await b.access(t),!0}catch{return!1}}
@@ -43,4 +43,3 @@ export type UnfairlyClient = {
43
43
  raw: TransportFn;
44
44
  };
45
45
  export declare function createUnfairlyClient(opts?: UnfairlyClientOptions): UnfairlyClient;
46
- //# sourceMappingURL=client.d.ts.map