@sideboard-ai/core 0.1.202 → 0.1.204
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{abletime-KGPD3UUJ.js → abletime-S3UHQZVW.js} +4 -2
- package/dist/{abletime-345SE3B4.js → abletime-TONBQP4O.js} +4 -2
- package/dist/abletime-oauth-AVCEO2DY.js +314 -0
- package/dist/abletime-oauth-SD4SZY5U.js +52 -0
- package/dist/abletime-rest-6ODSXV7G.js +25 -0
- package/dist/abletime-rest-J2OBB4VA.js +24 -0
- package/dist/agents/cursor-runner.js +1 -1
- package/dist/{agents-573ZDIX6.js → agents-67K4BQFJ.js} +4 -4
- package/dist/{agents-OXX3ONVY.js → agents-BVOJNHV6.js} +5 -5
- package/dist/{app-settings-V6IHESEQ.js → app-settings-LGHMNHSP.js} +1 -1
- package/dist/{app-settings-AXCURTZJ.js → app-settings-YEPF46IJ.js} +1 -1
- package/dist/chunk-3K257PCS.js +393 -0
- package/dist/{chunk-54RSAMBH.js → chunk-5SMS6QTO.js} +2 -2
- package/dist/chunk-6Q7DFVDQ.js +309 -0
- package/dist/chunk-CYLDJWRK.js +391 -0
- package/dist/{chunk-PGQGP4FD.js → chunk-FO2NTJ7L.js} +37 -219
- package/dist/{chunk-7NKY2OX7.js → chunk-FO45DMJ5.js} +125 -109
- package/dist/{chunk-CQ5R3VPP.js → chunk-KZ7PI7FE.js} +18 -0
- package/dist/{chunk-7AHAABKN.js → chunk-QAVWH2RQ.js} +37 -229
- package/dist/{chunk-CXFW5LIH.js → chunk-QFBBUFD4.js} +38 -3
- package/dist/{chunk-RPX6VDW7.js → chunk-QUW5D62C.js} +34 -20
- package/dist/chunk-SGUVAK66.js +262 -0
- package/dist/{chunk-27GGXX27.js → chunk-ULZLWQBS.js} +128 -112
- package/dist/{chunk-LJHC62LZ.js → chunk-VIPA75ZA.js} +2 -2
- package/dist/chunk-W6VM36YO.js +272 -0
- package/dist/{chunk-NIVF5NDN.js → chunk-WF33LOP4.js} +44 -6
- package/dist/{chunk-STPZQR5B.js → chunk-WVATAIF4.js} +34 -20
- package/dist/{chunk-ISV5IFH3.js → chunk-X743YN5Y.js} +38 -3
- package/dist/{chunk-A2TAKYSG.js → chunk-YOSTWSNC.js} +27 -7
- package/dist/{coordinator-prompt-BH4EHFOO.js → coordinator-prompt-NPT555BO.js} +3 -3
- package/dist/{coordinator-prompt-TY5FHAXC.js → coordinator-prompt-WEPXXLLX.js} +3 -3
- package/dist/{global-workspace-NLLAPQJI.js → global-workspace-2I2T7FL5.js} +3 -3
- package/dist/{global-workspace-5AZEEQRU.js → global-workspace-NSILADOM.js} +3 -3
- package/dist/index.cjs +1137 -213
- package/dist/index.d.cts +87 -13
- package/dist/index.d.ts +87 -13
- package/dist/index.js +94 -19
- package/dist/mcp/run-stdio.cjs +1023 -180
- package/dist/mcp/run-stdio.js +22 -20
- package/dist/{orchestrator-JNSQDRZI.js → orchestrator-CMAVNELS.js} +6 -6
- package/dist/{orchestrator-NCYKEI3E.js → orchestrator-I7GFXLHF.js} +6 -6
- package/dist/{workspaces-RP76JH3J.js → workspaces-BOC6M7BW.js} +3 -3
- package/dist/{workspaces-PEWYWVHZ.js → workspaces-RFGZBUAR.js} +3 -3
- package/dist/{worktree-72TZWUSH.js → worktree-G3ZLM4DC.js} +4 -2
- package/dist/{worktree-ZQEUKSNE.js → worktree-WSUQMMK4.js} +4 -2
- package/package.json +1 -1
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import {
|
|
2
|
+
httpFetch
|
|
3
|
+
} from "./chunk-N7WZ6NIN.js";
|
|
4
|
+
import {
|
|
5
|
+
getAbleTimeHost,
|
|
6
|
+
isAbleTimeConnected
|
|
7
|
+
} from "./chunk-QFBBUFD4.js";
|
|
8
|
+
|
|
9
|
+
// src/integrations/abletime-mcp.ts
|
|
10
|
+
var DEFAULT_ABLETIME_HOST = "https://track.abletime.com";
|
|
11
|
+
var ABLETIME_MCP_PATH = "/api/public/v2/mcp";
|
|
12
|
+
var ABLETIME_MCP_PM_PATH = "/api/public/v2/mcp/pm";
|
|
13
|
+
var MCP_PROTOCOL_VERSION = "2025-03-26";
|
|
14
|
+
var ABLETIME_PM_TOOL_NAMES = [
|
|
15
|
+
"set_task_assignee",
|
|
16
|
+
"set_task_priority",
|
|
17
|
+
"set_task_stage",
|
|
18
|
+
"set_task_dependency",
|
|
19
|
+
"set_task_blocked",
|
|
20
|
+
"set_task_locked",
|
|
21
|
+
"set_task_schedule",
|
|
22
|
+
"clear_task_schedule",
|
|
23
|
+
"archive_task",
|
|
24
|
+
"delete_task"
|
|
25
|
+
];
|
|
26
|
+
function abletimeToolUsesPm(name) {
|
|
27
|
+
return ABLETIME_PM_TOOL_NAMES.includes(name);
|
|
28
|
+
}
|
|
29
|
+
function normalizeAbleTimeHost(raw) {
|
|
30
|
+
const trimmed = raw?.trim() || DEFAULT_ABLETIME_HOST;
|
|
31
|
+
const withScheme = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
|
|
32
|
+
return withScheme.replace(/\/+$/, "");
|
|
33
|
+
}
|
|
34
|
+
function abletimeMcpUrl(host, opts) {
|
|
35
|
+
const path = opts?.pm ? ABLETIME_MCP_PM_PATH : ABLETIME_MCP_PATH;
|
|
36
|
+
return `${normalizeAbleTimeHost(host)}${path}`;
|
|
37
|
+
}
|
|
38
|
+
var ABLETIME_PAT_PREFIX = "apt_";
|
|
39
|
+
var ABLETIME_ORG_KEY_PREFIX = "atk_";
|
|
40
|
+
var ABLETIME_OAUTH_TOKEN_PREFIX = "acn_";
|
|
41
|
+
var ORG_KEY_HINT = "AbleTime MCP needs a personal access token (apt_\u2026) from Edit Profile \u2192 API Access, not an organization API key (atk_\u2026) from Settings \u2192 Integrations \u2192 API Keys.";
|
|
42
|
+
var REJECTED_CREDENTIAL_HINT = "AbleTime rejected this credential (unknown, revoked, or expired). Reconnect via browser, or paste a personal access token (apt_\u2026) from Edit Profile \u2192 API Access. Organization API keys (atk_\u2026) use REST, not MCP.";
|
|
43
|
+
var REWRITE_APPLIED = /— Enable Agent access \(MCP\)|— AbleTime MCP needs a personal access token|— AbleTime plan does not include API access|— AbleTime rejected this credential/;
|
|
44
|
+
function normalizeAbleTimeCredential(raw) {
|
|
45
|
+
return raw.trim().replace(/^bearer\s+/i, "").trim();
|
|
46
|
+
}
|
|
47
|
+
function ableTimeCredentialKind(raw) {
|
|
48
|
+
const token = normalizeAbleTimeCredential(raw);
|
|
49
|
+
const lower = token.toLowerCase();
|
|
50
|
+
if (lower.startsWith(ABLETIME_PAT_PREFIX)) return "pat";
|
|
51
|
+
if (lower.startsWith(ABLETIME_ORG_KEY_PREFIX)) return "org";
|
|
52
|
+
if (lower.startsWith(ABLETIME_OAUTH_TOKEN_PREFIX) || token.startsWith("eyJ")) return "oauth";
|
|
53
|
+
return "unknown";
|
|
54
|
+
}
|
|
55
|
+
function ableTimeUsesRest(raw) {
|
|
56
|
+
const token = normalizeAbleTimeCredential(raw);
|
|
57
|
+
const kind = ableTimeCredentialKind(token);
|
|
58
|
+
if (kind === "org") return true;
|
|
59
|
+
if (kind === "oauth") return token.startsWith("eyJ");
|
|
60
|
+
return kind === "unknown";
|
|
61
|
+
}
|
|
62
|
+
function isAbleTimeRejectedCredential(message) {
|
|
63
|
+
return /INTEGRATION_KEY_INVALID|INTEGRATION_KEY_MISSING|INTEGRATION_PAT_REQUIRED|\b401\b/i.test(
|
|
64
|
+
message
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
function assertAbleTimeMcpCredential(raw) {
|
|
68
|
+
const token = normalizeAbleTimeCredential(raw);
|
|
69
|
+
if (!token) {
|
|
70
|
+
throw new Error("AbleTime personal access token is required");
|
|
71
|
+
}
|
|
72
|
+
if (ableTimeCredentialKind(token) === "org") {
|
|
73
|
+
throw new Error(ORG_KEY_HINT);
|
|
74
|
+
}
|
|
75
|
+
return token;
|
|
76
|
+
}
|
|
77
|
+
function assertAbleTimeCredential(raw) {
|
|
78
|
+
const token = normalizeAbleTimeCredential(raw);
|
|
79
|
+
if (!token) {
|
|
80
|
+
throw new Error("AbleTime API key or personal access token is required");
|
|
81
|
+
}
|
|
82
|
+
return token;
|
|
83
|
+
}
|
|
84
|
+
function rewriteAbleTimeError(message) {
|
|
85
|
+
if (REWRITE_APPLIED.test(message)) return message;
|
|
86
|
+
if (/INTEGRATION_AGENT_ACCESS_DISABLED/i.test(message)) {
|
|
87
|
+
return `${message} \u2014 Enable Agent access (MCP) in AbleTime Settings \u2192 Integrations \u2192 API Keys.`;
|
|
88
|
+
}
|
|
89
|
+
if (/INTEGRATION_PAT_REQUIRED/i.test(message)) {
|
|
90
|
+
return `${message} \u2014 ${ORG_KEY_HINT}`;
|
|
91
|
+
}
|
|
92
|
+
if (/INTEGRATION_PLAN_REQUIRED/i.test(message)) {
|
|
93
|
+
return `${message} \u2014 AbleTime plan does not include API access.`;
|
|
94
|
+
}
|
|
95
|
+
if (/INTEGRATION_KEY_INVALID|INTEGRATION_KEY_MISSING|401|unauthorized|invalid token/i.test(message)) {
|
|
96
|
+
return `${message} \u2014 ${REJECTED_CREDENTIAL_HINT}`;
|
|
97
|
+
}
|
|
98
|
+
return message;
|
|
99
|
+
}
|
|
100
|
+
function asRecord(value) {
|
|
101
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
102
|
+
}
|
|
103
|
+
function parseSseJson(body) {
|
|
104
|
+
const blocks = body.split(/\n\n+/);
|
|
105
|
+
let last;
|
|
106
|
+
for (const block of blocks) {
|
|
107
|
+
const data = block.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).filter((line) => line && line !== "[DONE]").join("\n");
|
|
108
|
+
if (!data) continue;
|
|
109
|
+
try {
|
|
110
|
+
last = JSON.parse(data);
|
|
111
|
+
} catch {
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (last !== void 0) return last;
|
|
115
|
+
try {
|
|
116
|
+
return JSON.parse(body);
|
|
117
|
+
} catch {
|
|
118
|
+
throw new Error(`AbleTime MCP returned a non-JSON response: ${body.slice(0, 200)}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function unwrapToolResult(result) {
|
|
122
|
+
const record = asRecord(result);
|
|
123
|
+
if (!record) return result;
|
|
124
|
+
const content = record.content;
|
|
125
|
+
if (Array.isArray(content)) {
|
|
126
|
+
const texts = content.map((part) => {
|
|
127
|
+
const item = asRecord(part);
|
|
128
|
+
if (!item) return "";
|
|
129
|
+
return typeof item.text === "string" ? item.text : "";
|
|
130
|
+
}).filter(Boolean);
|
|
131
|
+
if (texts.length === 1) {
|
|
132
|
+
const text = texts[0];
|
|
133
|
+
try {
|
|
134
|
+
return JSON.parse(text);
|
|
135
|
+
} catch {
|
|
136
|
+
return text;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (texts.length > 1) return texts.join("\n");
|
|
140
|
+
}
|
|
141
|
+
if (record.structuredContent != null) return record.structuredContent;
|
|
142
|
+
if (record.isError === true) {
|
|
143
|
+
const message = typeof record.message === "string" ? record.message : textsFromUnknown(result) || "AbleTime tool failed";
|
|
144
|
+
throw new Error(message);
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
function textsFromUnknown(value) {
|
|
149
|
+
const record = asRecord(value);
|
|
150
|
+
if (!record) return "";
|
|
151
|
+
if (typeof record.message === "string") return record.message;
|
|
152
|
+
if (typeof record.error === "string") return record.error;
|
|
153
|
+
return "";
|
|
154
|
+
}
|
|
155
|
+
async function abletimeMcpRequest(method, params, opts) {
|
|
156
|
+
const rawToken = opts?.token ?? await import("./abletime-oauth-SD4SZY5U.js").then((m) => m.ensureAbleTimeAccessToken());
|
|
157
|
+
if (!rawToken?.trim()) {
|
|
158
|
+
throw new Error("AbleTime is not connected \u2014 paste a personal access token in Account settings");
|
|
159
|
+
}
|
|
160
|
+
const token = assertAbleTimeMcpCredential(rawToken);
|
|
161
|
+
const url = abletimeMcpUrl(
|
|
162
|
+
opts?.host ?? (opts?.token ? DEFAULT_ABLETIME_HOST : getAbleTimeHost()),
|
|
163
|
+
{ pm: opts?.pm }
|
|
164
|
+
);
|
|
165
|
+
const res = await httpFetch(url, {
|
|
166
|
+
method: "POST",
|
|
167
|
+
headers: {
|
|
168
|
+
"Content-Type": "application/json",
|
|
169
|
+
Accept: "application/json, text/event-stream",
|
|
170
|
+
Authorization: `Bearer ${token}`,
|
|
171
|
+
"MCP-Protocol-Version": MCP_PROTOCOL_VERSION
|
|
172
|
+
},
|
|
173
|
+
body: JSON.stringify({
|
|
174
|
+
jsonrpc: "2.0",
|
|
175
|
+
id: 1,
|
|
176
|
+
method,
|
|
177
|
+
...params === void 0 ? {} : { params }
|
|
178
|
+
})
|
|
179
|
+
});
|
|
180
|
+
const body = await res.text().catch(() => "");
|
|
181
|
+
if (!res.ok) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
rewriteAbleTimeError(
|
|
184
|
+
`AbleTime MCP error ${res.status}${body ? `: ${body.slice(0, 240)}` : ""}`
|
|
185
|
+
)
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
189
|
+
const parsed = contentType.includes("text/event-stream") ? parseSseJson(body) : (() => {
|
|
190
|
+
try {
|
|
191
|
+
return JSON.parse(body);
|
|
192
|
+
} catch {
|
|
193
|
+
return parseSseJson(body);
|
|
194
|
+
}
|
|
195
|
+
})();
|
|
196
|
+
const rpc = asRecord(parsed);
|
|
197
|
+
if (rpc?.error) {
|
|
198
|
+
const detail = typeof rpc.error.message === "string" && rpc.error.message.trim() ? rpc.error.message : `AbleTime MCP error ${rpc.error.code ?? ""}`.trim();
|
|
199
|
+
throw new Error(rewriteAbleTimeError(detail));
|
|
200
|
+
}
|
|
201
|
+
if (rpc && "result" in rpc) return rpc.result;
|
|
202
|
+
return parsed;
|
|
203
|
+
}
|
|
204
|
+
async function initializeIfNeeded(opts) {
|
|
205
|
+
try {
|
|
206
|
+
await abletimeMcpRequest(
|
|
207
|
+
"initialize",
|
|
208
|
+
{
|
|
209
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
210
|
+
capabilities: {},
|
|
211
|
+
clientInfo: { name: "sideboard", version: "1.0.0" }
|
|
212
|
+
},
|
|
213
|
+
opts
|
|
214
|
+
);
|
|
215
|
+
} catch (err) {
|
|
216
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
217
|
+
if (/already initialized|not (required|supported)|method not found|-32601/i.test(message)) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
throw err;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async function callAbleTimeTool(name, args = {}, opts) {
|
|
224
|
+
if (!opts?.token && !isAbleTimeConnected()) {
|
|
225
|
+
throw new Error("AbleTime is not connected \u2014 paste a personal access token in Account settings");
|
|
226
|
+
}
|
|
227
|
+
const rawToken = opts?.token ?? await import("./abletime-oauth-SD4SZY5U.js").then((m) => m.ensureAbleTimeAccessToken());
|
|
228
|
+
if (rawToken && ableTimeUsesRest(rawToken)) {
|
|
229
|
+
const { callAbleTimeRestTool } = await import("./abletime-rest-J2OBB4VA.js");
|
|
230
|
+
return callAbleTimeRestTool(name, args, { ...opts, token: rawToken });
|
|
231
|
+
}
|
|
232
|
+
const requestOpts = { ...opts, pm: opts?.pm ?? abletimeToolUsesPm(name) };
|
|
233
|
+
const call = () => abletimeMcpRequest("tools/call", { name, arguments: args }, requestOpts).then((result) => {
|
|
234
|
+
return unwrapToolResult(result);
|
|
235
|
+
});
|
|
236
|
+
try {
|
|
237
|
+
return await call();
|
|
238
|
+
} catch (err) {
|
|
239
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
240
|
+
if (/initialize|session|not initialized|-32000/i.test(message)) {
|
|
241
|
+
await initializeIfNeeded(requestOpts);
|
|
242
|
+
return await call();
|
|
243
|
+
}
|
|
244
|
+
if (rawToken && ableTimeUsesRest(rawToken) && isAbleTimeRejectedCredential(message)) {
|
|
245
|
+
const { callAbleTimeRestTool } = await import("./abletime-rest-J2OBB4VA.js");
|
|
246
|
+
return callAbleTimeRestTool(name, args, { ...opts, token: rawToken });
|
|
247
|
+
}
|
|
248
|
+
throw err instanceof Error ? new Error(rewriteAbleTimeError(err.message)) : err;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export {
|
|
253
|
+
DEFAULT_ABLETIME_HOST,
|
|
254
|
+
ABLETIME_MCP_PATH,
|
|
255
|
+
ABLETIME_MCP_PM_PATH,
|
|
256
|
+
ABLETIME_PM_TOOL_NAMES,
|
|
257
|
+
abletimeToolUsesPm,
|
|
258
|
+
normalizeAbleTimeHost,
|
|
259
|
+
abletimeMcpUrl,
|
|
260
|
+
ABLETIME_PAT_PREFIX,
|
|
261
|
+
ABLETIME_ORG_KEY_PREFIX,
|
|
262
|
+
ABLETIME_OAUTH_TOKEN_PREFIX,
|
|
263
|
+
normalizeAbleTimeCredential,
|
|
264
|
+
ableTimeCredentialKind,
|
|
265
|
+
ableTimeUsesRest,
|
|
266
|
+
isAbleTimeRejectedCredential,
|
|
267
|
+
assertAbleTimeMcpCredential,
|
|
268
|
+
assertAbleTimeCredential,
|
|
269
|
+
rewriteAbleTimeError,
|
|
270
|
+
abletimeMcpRequest,
|
|
271
|
+
callAbleTimeTool
|
|
272
|
+
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
isOrchestratorThread
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-5SMS6QTO.js";
|
|
6
6
|
import {
|
|
7
7
|
applyConnectedTeamToCli,
|
|
8
8
|
brightsyMcpServerName,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
mergeAgentGitAuthEnv,
|
|
21
21
|
resolveAgentGitAuthEnv,
|
|
22
22
|
resolveCodexGitWritableRoots
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-QUW5D62C.js";
|
|
24
24
|
import {
|
|
25
25
|
enrichPathWithNpmGlobalBin,
|
|
26
26
|
isConductorBundledCli,
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
resolveClaudeExecutable,
|
|
39
39
|
unwrapStrippedElectronLaunch,
|
|
40
40
|
wrapElectronAsNodeLaunch
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-X743YN5Y.js";
|
|
42
42
|
import {
|
|
43
43
|
appDataDir
|
|
44
44
|
} from "./chunk-EQNRWDLN.js";
|
|
@@ -410,6 +410,9 @@ function humanizeAgentFailDetail(detail) {
|
|
|
410
410
|
if (/\[resource_exhausted\]|resource_exhausted|findfileswithripgrep/.test(lower)) {
|
|
411
411
|
return "Cursor local file search failed (ripgrep / resource_exhausted). Wait a minute and retry; if it keeps happening, check Cursor usage.";
|
|
412
412
|
}
|
|
413
|
+
if (looksLikeCodexMcpError(raw)) {
|
|
414
|
+
return `${raw} \u2014 skip that vendor MCP and continue (PostHog: Settings \u2192 Connectors + HTTP API).`;
|
|
415
|
+
}
|
|
413
416
|
if (/invalid user api key|invalid api key|not logged in|not authenticated|unauthorized|authentication|please run.*login|codex login|claude auth|cursor api/.test(
|
|
414
417
|
lower
|
|
415
418
|
)) {
|
|
@@ -467,9 +470,24 @@ function turnFailChatText(opts) {
|
|
|
467
470
|
|
|
468
471
|
${fail}`;
|
|
469
472
|
}
|
|
473
|
+
function looksLikeCodexMcpError(text) {
|
|
474
|
+
const t = text.trim().toLowerCase();
|
|
475
|
+
if (!t) return false;
|
|
476
|
+
if (/authrequired|authorization required/.test(t) && /mcp|posthog|rmcp|connector|plugin/.test(t)) {
|
|
477
|
+
return true;
|
|
478
|
+
}
|
|
479
|
+
if (/\bposthog\b/.test(t) && /mcp|oauth|auth|unauthorized|401|plugin|app/.test(t)) {
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
if (/\brmcp\b/.test(t) && /fatal|quit|transport|error|died|kill|auth/.test(t)) {
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
return /mcp[_ -]?(server|tool|error|transport|client)/.test(t) && /fail|error|timeout|disconnect|auth|unauthorized/.test(t);
|
|
486
|
+
}
|
|
470
487
|
function shouldFeedErrorBackToAgent(opts) {
|
|
471
488
|
const detail = opts.detail.trim();
|
|
472
489
|
const chat = (opts.assistantText ?? "").trim();
|
|
490
|
+
if (looksLikeCodexMcpError(detail)) return true;
|
|
473
491
|
if (looksLikeAgentFailureMessage(detail) || looksLikeAgentFailureMessage(chat)) {
|
|
474
492
|
return false;
|
|
475
493
|
}
|
|
@@ -2423,7 +2441,7 @@ var claudeAdapter = {
|
|
|
2423
2441
|
);
|
|
2424
2442
|
}
|
|
2425
2443
|
const mode = permissionMode(thread);
|
|
2426
|
-
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-
|
|
2444
|
+
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-2I2T7FL5.js");
|
|
2427
2445
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
2428
2446
|
const injectedServers = await buildInjectedMcpServers({
|
|
2429
2447
|
includeSideboard: true,
|
|
@@ -2755,7 +2773,18 @@ function toCodexDisableUserMcpArgs(names) {
|
|
|
2755
2773
|
return args;
|
|
2756
2774
|
}
|
|
2757
2775
|
function toCodexUnattendedAppsArgs() {
|
|
2758
|
-
return [
|
|
2776
|
+
return [
|
|
2777
|
+
"-c",
|
|
2778
|
+
"features.apps=false",
|
|
2779
|
+
"-c",
|
|
2780
|
+
"apps._default.enabled=false",
|
|
2781
|
+
"-c",
|
|
2782
|
+
"apps.posthog.enabled=false",
|
|
2783
|
+
"-c",
|
|
2784
|
+
"features.plugins=false",
|
|
2785
|
+
"-c",
|
|
2786
|
+
"mcp_servers.posthog.enabled=false"
|
|
2787
|
+
];
|
|
2759
2788
|
}
|
|
2760
2789
|
|
|
2761
2790
|
// src/agents/codex.ts
|
|
@@ -4422,11 +4451,14 @@ function staleOk(now) {
|
|
|
4422
4451
|
if (now - lastGood.at > CLAUDE_USAGE_STALE_OK_MS) return null;
|
|
4423
4452
|
return lastGood.value;
|
|
4424
4453
|
}
|
|
4454
|
+
function reuseLast() {
|
|
4455
|
+
return lastGood?.value ?? null;
|
|
4456
|
+
}
|
|
4425
4457
|
async function getClaudePlanUsage(opts = {}) {
|
|
4426
4458
|
const now = opts.now ?? Date.now();
|
|
4459
|
+
if (now < errorUntil) return reuseLast() ?? staleOk(now);
|
|
4427
4460
|
if (!opts.force) {
|
|
4428
4461
|
if (cache && now - cache.at < CLAUDE_USAGE_TTL_MS) return cache.value;
|
|
4429
|
-
if (now < errorUntil) return staleOk(now);
|
|
4430
4462
|
}
|
|
4431
4463
|
if (inflight) return inflight;
|
|
4432
4464
|
inflight = (async () => {
|
|
@@ -4457,6 +4489,12 @@ async function getClaudePlanUsage(opts = {}) {
|
|
|
4457
4489
|
cache = { at: now, value: null };
|
|
4458
4490
|
return null;
|
|
4459
4491
|
}
|
|
4492
|
+
if (res.status === 429) {
|
|
4493
|
+
errorUntil = now + CLAUDE_USAGE_ERROR_TTL_MS;
|
|
4494
|
+
const last = reuseLast();
|
|
4495
|
+
if (last) cache = { at: now, value: last };
|
|
4496
|
+
return last;
|
|
4497
|
+
}
|
|
4460
4498
|
if (!res.ok) {
|
|
4461
4499
|
errorUntil = now + CLAUDE_USAGE_ERROR_TTL_MS;
|
|
4462
4500
|
return staleOk(now);
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
getGithubGitAuthMode,
|
|
9
9
|
getGithubPat
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QFBBUFD4.js";
|
|
11
11
|
import {
|
|
12
12
|
listThreads
|
|
13
13
|
} from "./chunk-DFUES6QU.js";
|
|
@@ -2154,26 +2154,21 @@ function resolvePrSelectors(thread) {
|
|
|
2154
2154
|
function resolvePrSelector(thread) {
|
|
2155
2155
|
return resolvePrSelectors(thread)[0] ?? null;
|
|
2156
2156
|
}
|
|
2157
|
+
function connectedPrSelectors(thread, currentHeadPrUrl) {
|
|
2158
|
+
const out = [];
|
|
2159
|
+
const push = (value) => {
|
|
2160
|
+
const v = value?.trim();
|
|
2161
|
+
if (!v || out.includes(v)) return;
|
|
2162
|
+
out.push(v);
|
|
2163
|
+
};
|
|
2164
|
+
push(currentHeadPrUrl);
|
|
2165
|
+
for (const selector of resolvePrSelectors(thread)) push(selector);
|
|
2166
|
+
return out;
|
|
2167
|
+
}
|
|
2157
2168
|
async function getPrForHeadBranch(repoPath, branch) {
|
|
2158
2169
|
const head = normalizeGitBranchName(branch);
|
|
2159
2170
|
if (!head || isDefaultishSourceRef(head)) return null;
|
|
2160
2171
|
const slug = await resolveGithubRepoSlug(repoPath);
|
|
2161
|
-
const viewArgs = [
|
|
2162
|
-
"pr",
|
|
2163
|
-
"view",
|
|
2164
|
-
head,
|
|
2165
|
-
"--json",
|
|
2166
|
-
"number,title,headRefName,url,isCrossRepository,author"
|
|
2167
|
-
];
|
|
2168
|
-
if (slug) viewArgs.push("--repo", slug);
|
|
2169
|
-
const viewed = await gh(viewArgs, repoPath, { reject: false });
|
|
2170
|
-
if (viewed.exitCode === 0 && viewed.stdout.trim()) {
|
|
2171
|
-
try {
|
|
2172
|
-
return JSON.parse(viewed.stdout);
|
|
2173
|
-
} catch {
|
|
2174
|
-
return null;
|
|
2175
|
-
}
|
|
2176
|
-
}
|
|
2177
2172
|
const listHead = slug ? ghHeadRef(slug, head) : head;
|
|
2178
2173
|
const listArgs = [
|
|
2179
2174
|
"pr",
|
|
@@ -2189,10 +2184,28 @@ async function getPrForHeadBranch(repoPath, branch) {
|
|
|
2189
2184
|
];
|
|
2190
2185
|
if (slug) listArgs.push("--repo", slug);
|
|
2191
2186
|
const listed = await gh(listArgs, repoPath, { reject: false });
|
|
2192
|
-
if (listed.exitCode
|
|
2187
|
+
if (listed.exitCode === 0 && listed.stdout.trim()) {
|
|
2188
|
+
try {
|
|
2189
|
+
const rows = JSON.parse(listed.stdout);
|
|
2190
|
+
if (rows[0]) return rows[0];
|
|
2191
|
+
} catch {
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
const viewArgs = [
|
|
2195
|
+
"pr",
|
|
2196
|
+
"view",
|
|
2197
|
+
head,
|
|
2198
|
+
"--json",
|
|
2199
|
+
"number,title,headRefName,url,isCrossRepository,author,state"
|
|
2200
|
+
];
|
|
2201
|
+
if (slug) viewArgs.push("--repo", slug);
|
|
2202
|
+
const viewed = await gh(viewArgs, repoPath, { reject: false });
|
|
2203
|
+
if (viewed.exitCode !== 0 || !viewed.stdout.trim()) return null;
|
|
2193
2204
|
try {
|
|
2194
|
-
const
|
|
2195
|
-
|
|
2205
|
+
const info = JSON.parse(viewed.stdout);
|
|
2206
|
+
const state = (info.state ?? "OPEN").trim().toUpperCase();
|
|
2207
|
+
if (state !== "OPEN") return null;
|
|
2208
|
+
return info;
|
|
2196
2209
|
} catch {
|
|
2197
2210
|
return null;
|
|
2198
2211
|
}
|
|
@@ -3313,6 +3326,7 @@ export {
|
|
|
3313
3326
|
isDefaultishSourceRef,
|
|
3314
3327
|
resolvePrSelectors,
|
|
3315
3328
|
resolvePrSelector,
|
|
3329
|
+
connectedPrSelectors,
|
|
3316
3330
|
getPrForHeadBranch,
|
|
3317
3331
|
detectLocalMergeConflicts,
|
|
3318
3332
|
getPrChecks,
|
|
@@ -356,6 +356,9 @@ function normalizeVault(raw) {
|
|
|
356
356
|
if (typeof raw.abletimeAccessToken === "string" && raw.abletimeAccessToken.trim()) {
|
|
357
357
|
out.abletimeAccessToken = raw.abletimeAccessToken.trim();
|
|
358
358
|
}
|
|
359
|
+
if (typeof raw.abletimeRefreshToken === "string" && raw.abletimeRefreshToken.trim()) {
|
|
360
|
+
out.abletimeRefreshToken = raw.abletimeRefreshToken.trim();
|
|
361
|
+
}
|
|
359
362
|
if (typeof raw.vercelToken === "string" && raw.vercelToken.trim()) {
|
|
360
363
|
out.vercelToken = raw.vercelToken.trim();
|
|
361
364
|
}
|
|
@@ -437,6 +440,7 @@ function emptyPublicIntegrations() {
|
|
|
437
440
|
hasSlackAppToken: false,
|
|
438
441
|
hasGithubPat: false,
|
|
439
442
|
hasAbleTimeToken: false,
|
|
443
|
+
hasAbleTimeOAuth: false,
|
|
440
444
|
hasVercelToken: false,
|
|
441
445
|
hasSupabaseToken: false,
|
|
442
446
|
hasPosthogToken: false,
|
|
@@ -461,6 +465,7 @@ function toPublicAppSettings(settings) {
|
|
|
461
465
|
const slackAppToken = integrations.slackAppToken;
|
|
462
466
|
const githubPat = integrations.githubPat;
|
|
463
467
|
const abletimeAccessToken = integrations.abletimeAccessToken;
|
|
468
|
+
const abletimeRefreshToken = integrations.abletimeRefreshToken;
|
|
464
469
|
const vercelToken = integrations.vercelToken;
|
|
465
470
|
const supabaseAccessToken = integrations.supabaseAccessToken;
|
|
466
471
|
const posthogPersonalApiKey = integrations.posthogPersonalApiKey;
|
|
@@ -473,6 +478,7 @@ function toPublicAppSettings(settings) {
|
|
|
473
478
|
delete integrations.slackAppToken;
|
|
474
479
|
delete integrations.githubPat;
|
|
475
480
|
delete integrations.abletimeAccessToken;
|
|
481
|
+
delete integrations.abletimeRefreshToken;
|
|
476
482
|
delete integrations.vercelToken;
|
|
477
483
|
delete integrations.supabaseAccessToken;
|
|
478
484
|
delete integrations.posthogPersonalApiKey;
|
|
@@ -487,7 +493,8 @@ function toPublicAppSettings(settings) {
|
|
|
487
493
|
hasSlackClientSecret: Boolean(slackClientSecret?.trim()),
|
|
488
494
|
hasSlackAppToken: Boolean(slackAppToken?.trim()),
|
|
489
495
|
hasGithubPat: Boolean(githubPat?.trim()),
|
|
490
|
-
hasAbleTimeToken: Boolean(abletimeAccessToken?.trim()),
|
|
496
|
+
hasAbleTimeToken: Boolean(abletimeAccessToken?.trim() || abletimeRefreshToken?.trim()),
|
|
497
|
+
hasAbleTimeOAuth: Boolean(abletimeRefreshToken?.trim()),
|
|
491
498
|
hasVercelToken: Boolean(vercelToken?.trim()),
|
|
492
499
|
hasSupabaseToken: Boolean(supabaseAccessToken?.trim()),
|
|
493
500
|
hasPosthogToken: Boolean(posthogPersonalApiKey?.trim()),
|
|
@@ -633,6 +640,16 @@ function normalizeIntegrations(raw) {
|
|
|
633
640
|
const token = source.abletimeAccessToken.trim();
|
|
634
641
|
if (token) out.abletimeAccessToken = token;
|
|
635
642
|
}
|
|
643
|
+
if (typeof source.abletimeRefreshToken === "string") {
|
|
644
|
+
const token = source.abletimeRefreshToken.trim();
|
|
645
|
+
if (token) out.abletimeRefreshToken = token;
|
|
646
|
+
}
|
|
647
|
+
if (typeof source.abletimeTokenExpiresAt === "number" && Number.isFinite(source.abletimeTokenExpiresAt)) {
|
|
648
|
+
out.abletimeTokenExpiresAt = source.abletimeTokenExpiresAt;
|
|
649
|
+
} else if (typeof source.abletimeTokenExpiresAt === "string") {
|
|
650
|
+
const n = Number(source.abletimeTokenExpiresAt);
|
|
651
|
+
if (Number.isFinite(n)) out.abletimeTokenExpiresAt = n;
|
|
652
|
+
}
|
|
636
653
|
if (typeof source.abletimeHost === "string") {
|
|
637
654
|
const host = source.abletimeHost.trim();
|
|
638
655
|
if (host) out.abletimeHost = host;
|
|
@@ -921,7 +938,7 @@ function readSettingsFile() {
|
|
|
921
938
|
}
|
|
922
939
|
function diskHoldsSecrets(disk) {
|
|
923
940
|
return Boolean(
|
|
924
|
-
disk.integrations.linearApiKey || disk.integrations.linearAccessToken || disk.integrations.linearRefreshToken || disk.integrations.linearClientSecret || disk.integrations.slackClientSecret || disk.integrations.slackAppToken || disk.integrations.githubPat || disk.integrations.abletimeAccessToken || disk.integrations.vercelToken || disk.integrations.supabaseAccessToken || disk.integrations.posthogPersonalApiKey || disk.integrations.sentryAuthToken || Object.keys(disk.environment).length > 0
|
|
941
|
+
disk.integrations.linearApiKey || disk.integrations.linearAccessToken || disk.integrations.linearRefreshToken || disk.integrations.linearClientSecret || disk.integrations.slackClientSecret || disk.integrations.slackAppToken || disk.integrations.githubPat || disk.integrations.abletimeAccessToken || disk.integrations.abletimeRefreshToken || disk.integrations.vercelToken || disk.integrations.supabaseAccessToken || disk.integrations.posthogPersonalApiKey || disk.integrations.sentryAuthToken || Object.keys(disk.environment).length > 0
|
|
925
942
|
);
|
|
926
943
|
}
|
|
927
944
|
function mergeVault(disk) {
|
|
@@ -952,6 +969,9 @@ function mergeVault(disk) {
|
|
|
952
969
|
if (vault.abletimeAccessToken && !integrations.abletimeAccessToken) {
|
|
953
970
|
integrations.abletimeAccessToken = vault.abletimeAccessToken;
|
|
954
971
|
}
|
|
972
|
+
if (vault.abletimeRefreshToken && !integrations.abletimeRefreshToken) {
|
|
973
|
+
integrations.abletimeRefreshToken = vault.abletimeRefreshToken;
|
|
974
|
+
}
|
|
955
975
|
if (vault.vercelToken && !integrations.vercelToken) {
|
|
956
976
|
integrations.vercelToken = vault.vercelToken;
|
|
957
977
|
}
|
|
@@ -976,6 +996,7 @@ function persistSplit(settings) {
|
|
|
976
996
|
const slackAppToken = integrations.slackAppToken;
|
|
977
997
|
const githubPat = integrations.githubPat;
|
|
978
998
|
const abletimeAccessToken = integrations.abletimeAccessToken;
|
|
999
|
+
const abletimeRefreshToken = integrations.abletimeRefreshToken;
|
|
979
1000
|
const vercelToken = integrations.vercelToken;
|
|
980
1001
|
const supabaseAccessToken = integrations.supabaseAccessToken;
|
|
981
1002
|
const posthogPersonalApiKey = integrations.posthogPersonalApiKey;
|
|
@@ -988,6 +1009,7 @@ function persistSplit(settings) {
|
|
|
988
1009
|
delete integrations.slackAppToken;
|
|
989
1010
|
delete integrations.githubPat;
|
|
990
1011
|
delete integrations.abletimeAccessToken;
|
|
1012
|
+
delete integrations.abletimeRefreshToken;
|
|
991
1013
|
delete integrations.vercelToken;
|
|
992
1014
|
delete integrations.supabaseAccessToken;
|
|
993
1015
|
delete integrations.posthogPersonalApiKey;
|
|
@@ -1006,6 +1028,7 @@ function persistSplit(settings) {
|
|
|
1006
1028
|
slackAppToken,
|
|
1007
1029
|
githubPat,
|
|
1008
1030
|
abletimeAccessToken,
|
|
1031
|
+
abletimeRefreshToken,
|
|
1009
1032
|
vercelToken,
|
|
1010
1033
|
supabaseAccessToken,
|
|
1011
1034
|
posthogPersonalApiKey,
|
|
@@ -1192,6 +1215,8 @@ function updateIntegrationsSettings(patch) {
|
|
|
1192
1215
|
if ("abletimeAccessToken" in patch) {
|
|
1193
1216
|
if (patch.abletimeAccessToken == null || patch.abletimeAccessToken.trim() === "") {
|
|
1194
1217
|
delete integrations.abletimeAccessToken;
|
|
1218
|
+
delete integrations.abletimeRefreshToken;
|
|
1219
|
+
delete integrations.abletimeTokenExpiresAt;
|
|
1195
1220
|
delete integrations.abletimeViewerName;
|
|
1196
1221
|
} else {
|
|
1197
1222
|
integrations.abletimeAccessToken = patch.abletimeAccessToken.trim();
|
|
@@ -1544,7 +1569,9 @@ function disconnectLinearConnection() {
|
|
|
1544
1569
|
return saveAppSettings({ ...current, integrations });
|
|
1545
1570
|
}
|
|
1546
1571
|
function isAbleTimeConnected(settings = loadAppSettings()) {
|
|
1547
|
-
return Boolean(
|
|
1572
|
+
return Boolean(
|
|
1573
|
+
settings.integrations.abletimeAccessToken?.trim() || settings.integrations.abletimeRefreshToken?.trim()
|
|
1574
|
+
);
|
|
1548
1575
|
}
|
|
1549
1576
|
function getAbleTimeAccessToken(settings = loadAppSettings()) {
|
|
1550
1577
|
const token = settings.integrations.abletimeAccessToken?.trim();
|
|
@@ -1557,6 +1584,12 @@ function saveAbleTimeConnection(input) {
|
|
|
1557
1584
|
const current = loadAppSettings();
|
|
1558
1585
|
const integrations = { ...current.integrations };
|
|
1559
1586
|
integrations.abletimeAccessToken = input.accessToken.trim();
|
|
1587
|
+
if (input.refreshToken?.trim()) {
|
|
1588
|
+
integrations.abletimeRefreshToken = input.refreshToken.trim();
|
|
1589
|
+
}
|
|
1590
|
+
if (typeof input.expiresIn === "number" && Number.isFinite(input.expiresIn)) {
|
|
1591
|
+
integrations.abletimeTokenExpiresAt = Date.now() + Math.max(0, input.expiresIn) * 1e3;
|
|
1592
|
+
}
|
|
1560
1593
|
if (input.host?.trim()) {
|
|
1561
1594
|
integrations.abletimeHost = input.host.trim();
|
|
1562
1595
|
}
|
|
@@ -1569,6 +1602,8 @@ function disconnectAbleTimeConnection() {
|
|
|
1569
1602
|
const current = loadAppSettings();
|
|
1570
1603
|
const integrations = { ...current.integrations };
|
|
1571
1604
|
delete integrations.abletimeAccessToken;
|
|
1605
|
+
delete integrations.abletimeRefreshToken;
|
|
1606
|
+
delete integrations.abletimeTokenExpiresAt;
|
|
1572
1607
|
delete integrations.abletimeViewerName;
|
|
1573
1608
|
return saveAppSettings({ ...current, integrations });
|
|
1574
1609
|
}
|