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.
- package/CHANGELOG.md +4 -0
- package/LICENSE +15 -0
- package/dist/auth/browser-flow.d.ts +0 -1
- package/dist/auth/browser-flow.js +5 -81
- package/dist/cmd/connect.d.ts +0 -1
- package/dist/cmd/connect.js +1 -164
- package/dist/cmd/init.d.ts +0 -1
- package/dist/cmd/init.js +2 -138
- package/dist/cmd/invite.d.ts +0 -1
- package/dist/cmd/invite.js +4 -73
- package/dist/cmd/join.d.ts +0 -1
- package/dist/cmd/join.js +1 -91
- package/dist/cmd/login.d.ts +0 -1
- package/dist/cmd/login.js +3 -41
- package/dist/cmd/mcp.d.ts +0 -1
- package/dist/cmd/mcp.js +2 -86
- package/dist/cmd/pace.d.ts +2 -2
- package/dist/cmd/pace.js +4 -426
- package/dist/cmd/parse-share-input.d.ts +0 -1
- package/dist/cmd/parse-share-input.js +1 -56
- package/dist/cmd/pull.d.ts +0 -1
- package/dist/cmd/pull.js +7 -143
- package/dist/cmd/push.d.ts +0 -1
- package/dist/cmd/push.js +1 -85
- package/dist/cmd/resolve.d.ts +0 -1
- package/dist/cmd/resolve.js +1 -35
- package/dist/cmd/setup.d.ts +0 -1
- package/dist/cmd/setup.js +2 -345
- package/dist/cmd/status-card.d.ts +0 -1
- package/dist/cmd/status-card.js +2 -156
- package/dist/cmd/status.d.ts +0 -1
- package/dist/cmd/status.js +3 -29
- package/dist/cmd/watch.d.ts +0 -1
- package/dist/cmd/watch.js +1 -26
- package/dist/hosts/claude-code.d.ts +0 -1
- package/dist/hosts/claude-code.js +3 -180
- package/dist/hosts/claude-desktop.d.ts +0 -1
- package/dist/hosts/claude-desktop.js +3 -222
- package/dist/hosts/codex.d.ts +0 -1
- package/dist/hosts/codex.js +20 -234
- package/dist/hosts/shell-env.d.ts +0 -1
- package/dist/hosts/shell-env.js +9 -81
- package/dist/index.d.ts +0 -1
- package/dist/index.js +14 -206
- package/dist/lib/client.d.ts +0 -1
- package/dist/lib/client.js +1 -58
- package/dist/lib/events/emit.d.ts +0 -1
- package/dist/lib/events/emit.js +1 -28
- package/dist/lib/index.d.ts +0 -1
- package/dist/lib/index.js +1 -11
- package/dist/lib/transport.d.ts +0 -1
- package/dist/lib/transport.js +1 -85
- package/dist/lib/types/index.d.ts +0 -1
- package/dist/lib/types/index.js +1 -50
- package/dist/lib/vault/checkpoint.d.ts +0 -1
- package/dist/lib/vault/checkpoint.js +1 -18
- package/dist/lib/vault/read.d.ts +0 -1
- package/dist/lib/vault/read.js +1 -9
- package/dist/lib/vault/search.d.ts +0 -1
- package/dist/lib/vault/search.js +1 -10
- package/dist/pace/device.d.ts +0 -1
- package/dist/pace/device.js +2 -149
- package/dist/pace/enroll.d.ts +0 -1
- package/dist/pace/enroll.js +2 -138
- package/dist/pace/identity.d.ts +0 -1
- package/dist/pace/identity.js +1 -17
- package/dist/pace/install.d.ts +0 -1
- package/dist/pace/install.js +4 -127
- package/dist/pace/local-evidence.d.ts +0 -1
- package/dist/pace/local-evidence.js +2 -228
- package/dist/pace/local-sessions.d.ts +0 -1
- package/dist/pace/local-sessions.js +1 -254
- package/dist/pace/managed-config.d.ts +0 -1
- package/dist/pace/managed-config.js +8 -102
- package/dist/pace/normalize.d.ts +0 -1
- package/dist/pace/normalize.js +1 -293
- package/dist/pace/repository.d.ts +0 -1
- package/dist/pace/repository.js +2 -120
- package/dist/pace/schema.d.ts +0 -1
- package/dist/pace/schema.js +1 -134
- package/dist/pace/session-summary.d.ts +0 -1
- package/dist/pace/session-summary.js +2 -140
- package/dist/pace/spool.d.ts +0 -1
- package/dist/pace/spool.js +8 -87
- package/dist/pace-runtime.d.ts +0 -1
- package/dist/pace-runtime.js +2 -67
- package/dist/sync/api.d.ts +0 -1
- package/dist/sync/api.js +1 -55
- package/dist/sync/autoloader.d.ts +0 -1
- package/dist/sync/autoloader.js +5 -127
- package/dist/sync/conflict.d.ts +0 -1
- package/dist/sync/conflict.js +5 -15
- package/dist/sync/credentials.d.ts +0 -1
- package/dist/sync/credentials.js +1 -51
- package/dist/sync/files.d.ts +0 -1
- package/dist/sync/files.js +1 -71
- package/dist/sync/manifest.d.ts +0 -1
- package/dist/sync/manifest.js +1 -37
- package/dist/sync/repo-root.d.ts +0 -1
- package/dist/sync/repo-root.js +1 -24
- package/dist/sync/stitch-claude-md.d.ts +0 -1
- package/dist/sync/stitch-claude-md.js +8 -48
- package/dist/ui/colors.d.ts +0 -1
- package/dist/ui/colors.js +1 -28
- package/dist/ui/screens.d.ts +0 -1
- package/dist/ui/screens.js +5 -135
- package/package.json +5 -12
- package/plugin/.cursor-plugin/plugin.json +0 -2
- package/plugin/.mcp.json +1 -1
- package/plugin/LICENSE +15 -0
- package/plugin/gemini/gemini-extension.json +1 -1
- package/plugin/mcp.json +1 -1
- package/plugin/plugin.json +0 -2
- package/plugin/runtime/unfairly-intelligence.mjs +14 -5512
- package/dist/auth/browser-flow.d.ts.map +0 -1
- package/dist/auth/browser-flow.js.map +0 -1
- package/dist/cmd/connect.d.ts.map +0 -1
- package/dist/cmd/connect.js.map +0 -1
- package/dist/cmd/init.d.ts.map +0 -1
- package/dist/cmd/init.js.map +0 -1
- package/dist/cmd/invite.d.ts.map +0 -1
- package/dist/cmd/invite.js.map +0 -1
- package/dist/cmd/join.d.ts.map +0 -1
- package/dist/cmd/join.js.map +0 -1
- package/dist/cmd/login.d.ts.map +0 -1
- package/dist/cmd/login.js.map +0 -1
- package/dist/cmd/mcp.d.ts.map +0 -1
- package/dist/cmd/mcp.js.map +0 -1
- package/dist/cmd/pace.d.ts.map +0 -1
- package/dist/cmd/pace.js.map +0 -1
- package/dist/cmd/parse-share-input.d.ts.map +0 -1
- package/dist/cmd/parse-share-input.js.map +0 -1
- package/dist/cmd/pull.d.ts.map +0 -1
- package/dist/cmd/pull.js.map +0 -1
- package/dist/cmd/push.d.ts.map +0 -1
- package/dist/cmd/push.js.map +0 -1
- package/dist/cmd/resolve.d.ts.map +0 -1
- package/dist/cmd/resolve.js.map +0 -1
- package/dist/cmd/setup.d.ts.map +0 -1
- package/dist/cmd/setup.js.map +0 -1
- package/dist/cmd/status-card.d.ts.map +0 -1
- package/dist/cmd/status-card.js.map +0 -1
- package/dist/cmd/status.d.ts.map +0 -1
- package/dist/cmd/status.js.map +0 -1
- package/dist/cmd/watch.d.ts.map +0 -1
- package/dist/cmd/watch.js.map +0 -1
- package/dist/hosts/claude-code.d.ts.map +0 -1
- package/dist/hosts/claude-code.js.map +0 -1
- package/dist/hosts/claude-desktop.d.ts.map +0 -1
- package/dist/hosts/claude-desktop.js.map +0 -1
- package/dist/hosts/codex.d.ts.map +0 -1
- package/dist/hosts/codex.js.map +0 -1
- package/dist/hosts/shell-env.d.ts.map +0 -1
- package/dist/hosts/shell-env.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/client.d.ts.map +0 -1
- package/dist/lib/client.js.map +0 -1
- package/dist/lib/events/emit.d.ts.map +0 -1
- package/dist/lib/events/emit.js.map +0 -1
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/transport.d.ts.map +0 -1
- package/dist/lib/transport.js.map +0 -1
- package/dist/lib/types/index.d.ts.map +0 -1
- package/dist/lib/types/index.js.map +0 -1
- package/dist/lib/vault/checkpoint.d.ts.map +0 -1
- package/dist/lib/vault/checkpoint.js.map +0 -1
- package/dist/lib/vault/read.d.ts.map +0 -1
- package/dist/lib/vault/read.js.map +0 -1
- package/dist/lib/vault/search.d.ts.map +0 -1
- package/dist/lib/vault/search.js.map +0 -1
- package/dist/pace/device.d.ts.map +0 -1
- package/dist/pace/device.js.map +0 -1
- package/dist/pace/enroll.d.ts.map +0 -1
- package/dist/pace/enroll.js.map +0 -1
- package/dist/pace/identity.d.ts.map +0 -1
- package/dist/pace/identity.js.map +0 -1
- package/dist/pace/install.d.ts.map +0 -1
- package/dist/pace/install.js.map +0 -1
- package/dist/pace/local-evidence.d.ts.map +0 -1
- package/dist/pace/local-evidence.js.map +0 -1
- package/dist/pace/local-sessions.d.ts.map +0 -1
- package/dist/pace/local-sessions.js.map +0 -1
- package/dist/pace/managed-config.d.ts.map +0 -1
- package/dist/pace/managed-config.js.map +0 -1
- package/dist/pace/normalize.d.ts.map +0 -1
- package/dist/pace/normalize.js.map +0 -1
- package/dist/pace/repository.d.ts.map +0 -1
- package/dist/pace/repository.js.map +0 -1
- package/dist/pace/schema.d.ts.map +0 -1
- package/dist/pace/schema.js.map +0 -1
- package/dist/pace/session-summary.d.ts.map +0 -1
- package/dist/pace/session-summary.js.map +0 -1
- package/dist/pace/spool.d.ts.map +0 -1
- package/dist/pace/spool.js.map +0 -1
- package/dist/pace-runtime.d.ts.map +0 -1
- package/dist/pace-runtime.js.map +0 -1
- package/dist/sync/api.d.ts.map +0 -1
- package/dist/sync/api.js.map +0 -1
- package/dist/sync/autoloader.d.ts.map +0 -1
- package/dist/sync/autoloader.js.map +0 -1
- package/dist/sync/conflict.d.ts.map +0 -1
- package/dist/sync/conflict.js.map +0 -1
- package/dist/sync/credentials.d.ts.map +0 -1
- package/dist/sync/credentials.js.map +0 -1
- package/dist/sync/files.d.ts.map +0 -1
- package/dist/sync/files.js.map +0 -1
- package/dist/sync/manifest.d.ts.map +0 -1
- package/dist/sync/manifest.js.map +0 -1
- package/dist/sync/repo-root.d.ts.map +0 -1
- package/dist/sync/repo-root.js.map +0 -1
- package/dist/sync/stitch-claude-md.d.ts.map +0 -1
- package/dist/sync/stitch-claude-md.js.map +0 -1
- package/dist/ui/colors.d.ts.map +0 -1
- package/dist/ui/colors.js.map +0 -1
- package/dist/ui/screens.d.ts.map +0 -1
- package/dist/ui/screens.js.map +0 -1
package/dist/hosts/codex.js
CHANGED
|
@@ -1,234 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
package/dist/hosts/shell-env.js
CHANGED
|
@@ -1,81 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
package/dist/index.js
CHANGED
|
@@ -1,207 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
await
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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}}
|
package/dist/lib/client.d.ts
CHANGED