@sideboard-ai/core 0.1.324 → 0.1.325
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-5ZY3ZUUO.js → abletime-M7STTMZT.js} +6 -5
- package/dist/{abletime-CU2UPMJF.js → abletime-VL234MCP.js} +5 -4
- package/dist/{abletime-oauth-7EOSBEFM.js → abletime-oauth-LMMGMAPA.js} +3 -3
- package/dist/{abletime-oauth-4TTCR3CT.js → abletime-oauth-P4ZFBEAL.js} +3 -3
- package/dist/{abletime-rest-3TG4G7LW.js → abletime-rest-DLV7EIWS.js} +3 -3
- package/dist/{abletime-rest-KOKE7V4B.js → abletime-rest-GOI7HELR.js} +3 -3
- package/dist/agents/claude-runner.cjs +59 -22
- package/dist/agents/claude-runner.js +39 -16
- package/dist/agents/cursor-runner.cjs +96 -31
- package/dist/agents/cursor-runner.js +74 -24
- package/dist/{agents-YK65UDLT.js → agents-LDRM3BTY.js} +9 -8
- package/dist/{agents-LUSTCMDN.js → agents-MBIEAETM.js} +12 -11
- package/dist/{app-settings-I5HM5RMP.js → app-settings-E7DMMEKC.js} +1 -1
- package/dist/{app-settings-XIF4EC4K.js → app-settings-UQHUNOLV.js} +1 -1
- package/dist/{chunk-INBUV7HY.js → chunk-2UP3XD2D.js} +2 -2
- package/dist/{chunk-EQ52JR3Q.js → chunk-5MXLDDYF.js} +1 -1
- package/dist/{chunk-NCHOTN3C.js → chunk-5YCKATG6.js} +4 -3
- package/dist/{chunk-BYUCNIXK.js → chunk-7G27TB4M.js} +6 -6
- package/dist/chunk-7LUOLYFM.js +1445 -0
- package/dist/{chunk-Y3WREIPQ.js → chunk-A76MKMSF.js} +12 -210
- package/dist/{chunk-JE3JLHMO.js → chunk-APKUI4BP.js} +3 -3
- package/dist/{chunk-FR3SAYUL.js → chunk-AQEKPJWU.js} +5 -5
- package/dist/{chunk-QOS4465Y.js → chunk-BOFYI6LC.js} +1 -1
- package/dist/{chunk-FUFNMUNR.js → chunk-BTF3ATST.js} +7 -8
- package/dist/{chunk-OIHRC2ZJ.js → chunk-CI4M54LS.js} +22 -2
- package/dist/chunk-DBKHL7NC.js +214 -0
- package/dist/{chunk-ROOZDDFA.js → chunk-EO6ZFLG6.js} +7 -8
- package/dist/chunk-EZR6W4B3.js +1259 -0
- package/dist/{chunk-MZIZTSR2.js → chunk-F65JMKUR.js} +2 -2
- package/dist/chunk-F6GE7V3Q.js +216 -0
- package/dist/{chunk-7MQSYPAY.js → chunk-GNLKBS3U.js} +206 -188
- package/dist/{chunk-EKU7FQVG.js → chunk-H36GKGU2.js} +2 -2
- package/dist/{chunk-7D5QIU3N.js → chunk-HG6KS7OT.js} +294 -265
- package/dist/chunk-MBT6WDAB.js +28 -0
- package/dist/{chunk-JH5SMVM5.js → chunk-MFMDZAA6.js} +262 -233
- package/dist/{chunk-7PVT73H6.js → chunk-NWGINMEA.js} +12 -210
- package/dist/{chunk-QIC2JXHW.js → chunk-OOXRMTU6.js} +1 -1
- package/dist/{chunk-5XNT6BCG.js → chunk-OPXEJJBM.js} +1 -1
- package/dist/chunk-OYRN356W.js +80 -0
- package/dist/chunk-PPTJMBUY.js +25 -0
- package/dist/{chunk-B4CDSSRN.js → chunk-Q3FHTGIW.js} +2 -0
- package/dist/{chunk-EJ66LEKH.js → chunk-RZJTGBXY.js} +22 -2
- package/dist/{chunk-DF5BM5OY.js → chunk-SACHHTBJ.js} +207 -186
- package/dist/{chunk-5GDJSFCT.js → chunk-SK6NYGPD.js} +2 -2
- package/dist/{chunk-74OPNF7U.js → chunk-SQQBU7Z6.js} +2 -2
- package/dist/{chunk-Q3YJZPQI.js → chunk-SS6CYGLF.js} +3 -3
- package/dist/{chunk-YDUHLWI5.js → chunk-SUZOPJZC.js} +21 -7
- package/dist/{chunk-ZHGMRBSC.js → chunk-U5WO6MEB.js} +3 -3
- package/dist/{chunk-NXUN4U5P.js → chunk-VAFQS4D2.js} +2 -2
- package/dist/chunk-W3ZLE4PO.js +77 -0
- package/dist/{chunk-RR4WCGNB.js → chunk-WYEST76H.js} +7 -7
- package/dist/{chunk-ODH3XHMI.js → chunk-ZEUMWHOH.js} +5 -5
- package/dist/{chunk-ZIRQZUZY.js → chunk-ZHDXLDLA.js} +3 -3
- package/dist/{chunk-IFWGG2M2.js → chunk-ZSHS46V5.js} +2 -0
- package/dist/{conductor-JFABMXDA.js → conductor-D4KFZF54.js} +6 -6
- package/dist/{conductor-SPZOTC7W.js → conductor-KB7L7NQN.js} +7 -7
- package/dist/{coordinator-prompt-K66RGNWK.js → coordinator-prompt-OBXEC63K.js} +4 -4
- package/dist/{coordinator-prompt-Z6UFHFDH.js → coordinator-prompt-SUO4FRY3.js} +4 -4
- package/dist/{cursor-recover-TEBFKAZ4.js → cursor-recover-7F46PAJ5.js} +1 -1
- package/dist/{cursor-recover-OWPQUHFH.js → cursor-recover-BDIAZIE3.js} +1 -1
- package/dist/{global-workspace-A6UO6PJV.js → global-workspace-UHU2FXTY.js} +4 -4
- package/dist/{global-workspace-RHEO55B4.js → global-workspace-Z2SURNHA.js} +4 -4
- package/dist/index.cjs +21112 -20864
- package/dist/index.d.cts +25 -9
- package/dist/index.d.ts +25 -9
- package/dist/index.js +343 -1678
- package/dist/linear-HFUOUJ5H.js +67 -0
- package/dist/linear-SIHEBU3X.js +69 -0
- package/dist/linear-list-63I7QUC6.js +6 -0
- package/dist/linear-list-JFV3EES6.js +8 -0
- package/dist/mcp/run-stdio.cjs +15654 -15398
- package/dist/mcp/run-stdio.js +67 -1247
- package/dist/{optional-cli-RMMS5L6F.js → optional-cli-U2GUA2X6.js} +3 -3
- package/dist/{optional-cli-Y3Z3GIPZ.js → optional-cli-ULDP3O5S.js} +4 -4
- package/dist/{orchestrator-7VTAUY24.js → orchestrator-3H4KNGPN.js} +15 -13
- package/dist/{orchestrator-2O6OJQLX.js → orchestrator-6ROMEWBP.js} +14 -12
- package/dist/{thread-store-3F7GR64A.js → thread-store-4ZN3DS2W.js} +1 -1
- package/dist/{thread-store-JRSL4HQY.js → thread-store-IC4BQXDW.js} +1 -1
- package/dist/{workspaces-NRKEXOYR.js → workspaces-MG5JHRKW.js} +4 -4
- package/dist/{workspaces-42E6AGXD.js → workspaces-QJNKEGEM.js} +4 -4
- package/dist/{worktree-ZDA2UJ7C.js → worktree-KSJPTHGZ.js} +3 -3
- package/dist/{worktree-4NGXCCUO.js → worktree-MYJYUHZM.js} +3 -3
- package/package.json +1 -1
|
@@ -3,223 +3,31 @@
|
|
|
3
3
|
import {
|
|
4
4
|
abletimeRestUrl,
|
|
5
5
|
textFromAbleTimeDoc
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-VAFQS4D2.js";
|
|
7
7
|
import {
|
|
8
8
|
assertAbleTimeCredential,
|
|
9
9
|
callAbleTimeTool,
|
|
10
10
|
normalizeAbleTimeHost,
|
|
11
11
|
rewriteAbleTimeError
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-AQEKPJWU.js";
|
|
13
|
+
import {
|
|
14
|
+
downloadAuthenticatedFile,
|
|
15
|
+
extractHttpUrls,
|
|
16
|
+
hostMatches,
|
|
17
|
+
issueAttachmentWorktreePath,
|
|
18
|
+
looksLikeFileUrl,
|
|
19
|
+
looksLikeHttpUrl,
|
|
20
|
+
mergeIssueAttachments
|
|
21
|
+
} from "./chunk-F6GE7V3Q.js";
|
|
13
22
|
import {
|
|
14
23
|
httpFetch
|
|
15
24
|
} from "./chunk-2GPQZZLY.js";
|
|
16
|
-
import {
|
|
17
|
-
ATTACHMENTS_DIR,
|
|
18
|
-
attachmentsGitignoreBody
|
|
19
|
-
} from "./chunk-N2WW62LF.js";
|
|
20
25
|
import {
|
|
21
26
|
getAbleTimeAccessToken,
|
|
22
27
|
getAbleTimeHost,
|
|
23
28
|
isAbleTimeConnected,
|
|
24
29
|
saveAbleTimeConnection
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
|
|
27
|
-
// src/integrations/issue-attachments.ts
|
|
28
|
-
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
29
|
-
import { basename, extname, join } from "path";
|
|
30
|
-
import { randomUUID } from "crypto";
|
|
31
|
-
var ISSUE_ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;
|
|
32
|
-
var MARKDOWN_IMAGE_RE = /!\[[^\]]*]\(\s*<?(https?:\/\/[^)\s>]+)>?/gi;
|
|
33
|
-
var MARKDOWN_LINK_RE = /(?<!!)\[[^\]]*]\(\s*<?(https?:\/\/[^)\s>]+)>?/gi;
|
|
34
|
-
var HTML_SRC_RE = /\b(?:src|href)\s*=\s*["'](https?:\/\/[^"']+)["']/gi;
|
|
35
|
-
var BARE_URL_RE = /https?:\/\/[^\s<>"'`)]+/gi;
|
|
36
|
-
var EXT_BY_MIME = {
|
|
37
|
-
"image/png": ".png",
|
|
38
|
-
"image/jpeg": ".jpg",
|
|
39
|
-
"image/jpg": ".jpg",
|
|
40
|
-
"image/gif": ".gif",
|
|
41
|
-
"image/webp": ".webp",
|
|
42
|
-
"image/svg+xml": ".svg",
|
|
43
|
-
"application/pdf": ".pdf",
|
|
44
|
-
"text/plain": ".txt",
|
|
45
|
-
"text/markdown": ".md",
|
|
46
|
-
"application/json": ".json",
|
|
47
|
-
"application/zip": ".zip"
|
|
48
|
-
};
|
|
49
|
-
function issueAttachmentWorktreePath(repoPath) {
|
|
50
|
-
const raw = (repoPath ?? "").trim();
|
|
51
|
-
return raw || process.cwd();
|
|
52
|
-
}
|
|
53
|
-
function ensureIssueAttachmentsDir(worktreePath) {
|
|
54
|
-
const dir = join(worktreePath, ATTACHMENTS_DIR);
|
|
55
|
-
mkdirSync(dir, { recursive: true });
|
|
56
|
-
const gi = join(dir, ".gitignore");
|
|
57
|
-
if (!existsSync(gi)) {
|
|
58
|
-
writeFileSync(gi, attachmentsGitignoreBody(), "utf8");
|
|
59
|
-
}
|
|
60
|
-
return dir;
|
|
61
|
-
}
|
|
62
|
-
function hostnameOf(url) {
|
|
63
|
-
try {
|
|
64
|
-
return new URL(url).hostname.toLowerCase();
|
|
65
|
-
} catch {
|
|
66
|
-
return "";
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
function hostMatches(url, suffixes) {
|
|
70
|
-
const host = hostnameOf(url);
|
|
71
|
-
if (!host) return false;
|
|
72
|
-
return suffixes.some((suffix) => host === suffix || host.endsWith(`.${suffix}`));
|
|
73
|
-
}
|
|
74
|
-
function looksLikeHttpUrl(value) {
|
|
75
|
-
return /^https?:\/\//i.test(value.trim());
|
|
76
|
-
}
|
|
77
|
-
function looksLikeFileUrl(url) {
|
|
78
|
-
try {
|
|
79
|
-
const path = new URL(url).pathname;
|
|
80
|
-
return /\.[a-z0-9]{2,8}$/i.test(path);
|
|
81
|
-
} catch {
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
function filenameFromUrl(url, fallback = "attachment") {
|
|
86
|
-
try {
|
|
87
|
-
const parsed = new URL(url);
|
|
88
|
-
const last = decodeURIComponent(basename(parsed.pathname)).replace(/[/\\]/g, "_");
|
|
89
|
-
if (last && last !== "/" && last !== ".") return last;
|
|
90
|
-
} catch {
|
|
91
|
-
}
|
|
92
|
-
return fallback;
|
|
93
|
-
}
|
|
94
|
-
function filenameFromContentDisposition(header) {
|
|
95
|
-
if (!header) return void 0;
|
|
96
|
-
const star = header.match(/filename\*\s*=\s*(?:UTF-8''|utf-8'')([^;]+)/i);
|
|
97
|
-
if (star?.[1]) {
|
|
98
|
-
try {
|
|
99
|
-
return decodeURIComponent(star[1].trim().replace(/^["']|["']$/g, ""));
|
|
100
|
-
} catch {
|
|
101
|
-
return star[1].trim().replace(/^["']|["']$/g, "");
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
const plain = header.match(/filename\s*=\s*("(?:\\.|[^"])*"|[^;]+)/i);
|
|
105
|
-
if (!plain?.[1]) return void 0;
|
|
106
|
-
return plain[1].trim().replace(/^["']|["']$/g, "").replace(/\\"/g, '"');
|
|
107
|
-
}
|
|
108
|
-
function uniqueAttachmentFileName(dir, originalName) {
|
|
109
|
-
const safe = originalName.replace(/[/\\]/g, "_").replace(/^\.+/, "") || "file";
|
|
110
|
-
if (!existsSync(join(dir, safe))) return safe;
|
|
111
|
-
const ext = extname(safe);
|
|
112
|
-
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
113
|
-
for (let i = 1; i < 1e4; i++) {
|
|
114
|
-
const candidate = `${stem}-${i}${ext}`;
|
|
115
|
-
if (!existsSync(join(dir, candidate))) return candidate;
|
|
116
|
-
}
|
|
117
|
-
return `${stem}-${randomUUID()}${ext}`;
|
|
118
|
-
}
|
|
119
|
-
function extractHttpUrls(markdown) {
|
|
120
|
-
const text = markdown ?? "";
|
|
121
|
-
if (!text.trim()) return [];
|
|
122
|
-
const found = [];
|
|
123
|
-
const seen = /* @__PURE__ */ new Set();
|
|
124
|
-
const push = (raw) => {
|
|
125
|
-
const url = raw.replace(/[).,;]+$/, "");
|
|
126
|
-
if (!looksLikeHttpUrl(url) || seen.has(url)) return;
|
|
127
|
-
seen.add(url);
|
|
128
|
-
found.push(url);
|
|
129
|
-
};
|
|
130
|
-
for (const re of [MARKDOWN_IMAGE_RE, MARKDOWN_LINK_RE, HTML_SRC_RE, BARE_URL_RE]) {
|
|
131
|
-
re.lastIndex = 0;
|
|
132
|
-
let match;
|
|
133
|
-
while (match = re.exec(text)) {
|
|
134
|
-
if (match[1]) push(match[1]);
|
|
135
|
-
else if (re === BARE_URL_RE) push(match[0]);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return found;
|
|
139
|
-
}
|
|
140
|
-
function mergeIssueAttachments(items) {
|
|
141
|
-
const out = [];
|
|
142
|
-
const seen = /* @__PURE__ */ new Set();
|
|
143
|
-
for (const item of items) {
|
|
144
|
-
if (!item) continue;
|
|
145
|
-
const url = item.url.trim();
|
|
146
|
-
const id = item.id.trim() || url;
|
|
147
|
-
if (!id && !url) continue;
|
|
148
|
-
const key = url || id;
|
|
149
|
-
if (seen.has(key) || seen.has(id)) continue;
|
|
150
|
-
seen.add(key);
|
|
151
|
-
if (id !== key) seen.add(id);
|
|
152
|
-
out.push({
|
|
153
|
-
id: id || url,
|
|
154
|
-
name: item.name.trim() || filenameFromUrl(url),
|
|
155
|
-
url,
|
|
156
|
-
...item.contentType ? { contentType: item.contentType } : {},
|
|
157
|
-
...item.sourceType ? { sourceType: item.sourceType } : {}
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
return out;
|
|
161
|
-
}
|
|
162
|
-
function extensionForContentType(contentType, name) {
|
|
163
|
-
if (extname(name)) return name;
|
|
164
|
-
const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase() ?? "";
|
|
165
|
-
const ext = EXT_BY_MIME[mime];
|
|
166
|
-
return ext ? `${name}${ext}` : name;
|
|
167
|
-
}
|
|
168
|
-
function assertNotHtml(contentType, url) {
|
|
169
|
-
const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase() ?? "";
|
|
170
|
-
if (mime === "text/html" || mime === "application/xhtml+xml") {
|
|
171
|
-
throw new Error(
|
|
172
|
-
`Attachment at ${url} returned HTML, not a file. Use the listed file URL (uploads / user-attachments), not a ticket or PR page.`
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
async function downloadAuthenticatedFile(opts) {
|
|
177
|
-
const url = opts.url.trim();
|
|
178
|
-
if (!looksLikeHttpUrl(url)) {
|
|
179
|
-
throw new Error(`Attachment URL must be http(s) (got ${url || "empty"})`);
|
|
180
|
-
}
|
|
181
|
-
const res = await httpFetch(url, {
|
|
182
|
-
method: "GET",
|
|
183
|
-
redirect: "follow",
|
|
184
|
-
headers: {
|
|
185
|
-
Accept: "*/*",
|
|
186
|
-
...opts.headers ?? {}
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
if (!res.ok) {
|
|
190
|
-
const detail = await res.text().catch(() => "");
|
|
191
|
-
throw new Error(
|
|
192
|
-
`Attachment download failed ${res.status}${detail ? `: ${detail.slice(0, 200)}` : ""} (${url})`
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
const contentType = res.headers.get("content-type") ?? void 0;
|
|
196
|
-
assertNotHtml(contentType, url);
|
|
197
|
-
const lengthHeader = res.headers.get("content-length");
|
|
198
|
-
if (lengthHeader) {
|
|
199
|
-
const length = Number(lengthHeader);
|
|
200
|
-
if (Number.isFinite(length) && length > ISSUE_ATTACHMENT_MAX_BYTES) {
|
|
201
|
-
throw new Error(
|
|
202
|
-
`Attachment is ${length} bytes; max is ${ISSUE_ATTACHMENT_MAX_BYTES} (${url})`
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
const buf = Buffer.from(await res.arrayBuffer());
|
|
207
|
-
if (buf.length > ISSUE_ATTACHMENT_MAX_BYTES) {
|
|
208
|
-
throw new Error(
|
|
209
|
-
`Attachment is ${buf.length} bytes; max is ${ISSUE_ATTACHMENT_MAX_BYTES} (${url})`
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
const dir = ensureIssueAttachmentsDir(opts.worktreePath);
|
|
213
|
-
const hinted = opts.name?.trim() || filenameFromContentDisposition(res.headers.get("content-disposition")) || filenameFromUrl(url);
|
|
214
|
-
const name = uniqueAttachmentFileName(dir, extensionForContentType(contentType, hinted));
|
|
215
|
-
writeFileSync(join(dir, name), buf);
|
|
216
|
-
return {
|
|
217
|
-
name,
|
|
218
|
-
path: `${ATTACHMENTS_DIR}/${name}`,
|
|
219
|
-
bytes: buf.length,
|
|
220
|
-
...contentType ? { contentType } : {}
|
|
221
|
-
};
|
|
222
|
-
}
|
|
30
|
+
} from "./chunk-CI4M54LS.js";
|
|
223
31
|
|
|
224
32
|
// src/integrations/abletime-attachments.ts
|
|
225
33
|
function asRecord(value) {
|
|
@@ -841,12 +649,6 @@ async function verifyAbleTimeConnection(input) {
|
|
|
841
649
|
}
|
|
842
650
|
|
|
843
651
|
export {
|
|
844
|
-
issueAttachmentWorktreePath,
|
|
845
|
-
hostMatches,
|
|
846
|
-
looksLikeHttpUrl,
|
|
847
|
-
extractHttpUrls,
|
|
848
|
-
mergeIssueAttachments,
|
|
849
|
-
downloadAuthenticatedFile,
|
|
850
652
|
downloadAbleTimeAttachment,
|
|
851
653
|
taskUrl,
|
|
852
654
|
mapAbleTimeTask,
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
resolveGithubRepoSlug,
|
|
6
6
|
resolveOriginRemote,
|
|
7
7
|
resolveRepoRoot
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BTF3ATST.js";
|
|
9
9
|
import {
|
|
10
10
|
allocateTeamName,
|
|
11
11
|
createEmptyThread,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
teamSlugFromName,
|
|
15
15
|
updateThread,
|
|
16
16
|
writeThread
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-ZSHS46V5.js";
|
|
18
18
|
import {
|
|
19
19
|
ATTACHMENTS_DIR,
|
|
20
20
|
attachmentsGitignoreBody
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
resolveThreadDefaults,
|
|
32
32
|
resolveViewerProfile,
|
|
33
33
|
resolveViewerProfileForRepo
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-RZJTGBXY.js";
|
|
35
35
|
import {
|
|
36
36
|
appDataDir,
|
|
37
37
|
globalAgentCwd,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
getAbleTimeHost,
|
|
8
8
|
isAbleTimeConnected
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-CI4M54LS.js";
|
|
10
10
|
|
|
11
11
|
// src/integrations/abletime-mcp.ts
|
|
12
12
|
var DEFAULT_ABLETIME_HOST = "https://track.abletime.com";
|
|
@@ -155,7 +155,7 @@ function textsFromUnknown(value) {
|
|
|
155
155
|
return "";
|
|
156
156
|
}
|
|
157
157
|
async function abletimeMcpRequest(method, params, opts) {
|
|
158
|
-
const rawToken = opts?.token ?? await import("./abletime-oauth-
|
|
158
|
+
const rawToken = opts?.token ?? await import("./abletime-oauth-P4ZFBEAL.js").then((m) => m.ensureAbleTimeAccessToken());
|
|
159
159
|
if (!rawToken?.trim()) {
|
|
160
160
|
throw new Error("AbleTime is not connected \u2014 paste a personal access token in Account settings");
|
|
161
161
|
}
|
|
@@ -226,9 +226,9 @@ async function callAbleTimeTool(name, args = {}, opts) {
|
|
|
226
226
|
if (!opts?.token && !isAbleTimeConnected()) {
|
|
227
227
|
throw new Error("AbleTime is not connected \u2014 paste a personal access token in Account settings");
|
|
228
228
|
}
|
|
229
|
-
const rawToken = opts?.token ?? await import("./abletime-oauth-
|
|
229
|
+
const rawToken = opts?.token ?? await import("./abletime-oauth-P4ZFBEAL.js").then((m) => m.ensureAbleTimeAccessToken());
|
|
230
230
|
if (rawToken && ableTimeUsesRest(rawToken)) {
|
|
231
|
-
const { callAbleTimeRestTool } = await import("./abletime-rest-
|
|
231
|
+
const { callAbleTimeRestTool } = await import("./abletime-rest-DLV7EIWS.js");
|
|
232
232
|
return callAbleTimeRestTool(name, args, { ...opts, token: rawToken });
|
|
233
233
|
}
|
|
234
234
|
const requestOpts = { ...opts, pm: opts?.pm ?? abletimeToolUsesPm(name) };
|
|
@@ -244,7 +244,7 @@ async function callAbleTimeTool(name, args = {}, opts) {
|
|
|
244
244
|
return await call();
|
|
245
245
|
}
|
|
246
246
|
if (rawToken && ableTimeUsesRest(rawToken) && isAbleTimeRejectedCredential(message)) {
|
|
247
|
-
const { callAbleTimeRestTool } = await import("./abletime-rest-
|
|
247
|
+
const { callAbleTimeRestTool } = await import("./abletime-rest-DLV7EIWS.js");
|
|
248
248
|
return callAbleTimeRestTool(name, args, { ...opts, token: rawToken });
|
|
249
249
|
}
|
|
250
250
|
throw err instanceof Error ? new Error(rewriteAbleTimeError(err.message)) : err;
|
|
@@ -125,7 +125,7 @@ async function connectedCliPresence(integrations) {
|
|
|
125
125
|
const ids = connectedOptionalServices(integrations).filter((spec) => spec.cli).map((spec) => spec.id);
|
|
126
126
|
if (ids.length === 0) return void 0;
|
|
127
127
|
try {
|
|
128
|
-
const { optionalCliPresence } = await import("./optional-cli-
|
|
128
|
+
const { optionalCliPresence } = await import("./optional-cli-U2GUA2X6.js");
|
|
129
129
|
return await optionalCliPresence(ids);
|
|
130
130
|
} catch {
|
|
131
131
|
return void 0;
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
normalizeTakenSlug,
|
|
5
5
|
normalizeWorktreePath,
|
|
6
6
|
takenSlugsFromThread
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZSHS46V5.js";
|
|
8
8
|
import {
|
|
9
9
|
ensureWorktreeSideboardIgnored
|
|
10
10
|
} from "./chunk-QKHEVSB5.js";
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
import {
|
|
26
26
|
getGithubGitAuthMode,
|
|
27
27
|
getGithubPat
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-RZJTGBXY.js";
|
|
29
29
|
import {
|
|
30
30
|
worktreesRoot
|
|
31
31
|
} from "./chunk-H4UEFJRI.js";
|
|
@@ -291,12 +291,11 @@ function codexSandboxWritableRootsArgs(roots) {
|
|
|
291
291
|
return ["-c", `sandbox_workspace_write.writable_roots=${JSON.stringify(abs)}`];
|
|
292
292
|
}
|
|
293
293
|
function codexUnattendedGitConfigArgs(sandbox, opts) {
|
|
294
|
-
const args = [
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
"-c",
|
|
298
|
-
|
|
299
|
-
];
|
|
294
|
+
const args = ["-c", 'shell_environment_policy.inherit="all"'];
|
|
295
|
+
for (const [key, value] of Object.entries(opts?.preserveEnv ?? {})) {
|
|
296
|
+
if (!/^GIT_CONFIG_KEY_\d+$/.test(key) || !value) continue;
|
|
297
|
+
args.push("-c", `shell_environment_policy.set.${key}=${JSON.stringify(value)}`);
|
|
298
|
+
}
|
|
300
299
|
if (sandbox === "workspace-write") {
|
|
301
300
|
args.push("-c", "sandbox_workspace_write.network_access=true");
|
|
302
301
|
args.push(...codexSandboxWritableRootsArgs(opts?.writableRoots ?? []));
|
|
@@ -471,6 +471,20 @@ function fromInclusiveInputUsage(opts) {
|
|
|
471
471
|
function requestOccupancy(u) {
|
|
472
472
|
return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
|
|
473
473
|
}
|
|
474
|
+
function subtractUsage(total, part) {
|
|
475
|
+
if (!total) return null;
|
|
476
|
+
const cacheRead = Math.max(0, (total.cacheReadTokens ?? 0) - (part.cacheReadTokens ?? 0));
|
|
477
|
+
const cacheWrite = Math.max(0, (total.cacheWriteTokens ?? 0) - (part.cacheWriteTokens ?? 0));
|
|
478
|
+
return {
|
|
479
|
+
inputTokens: Math.max(0, total.inputTokens - part.inputTokens),
|
|
480
|
+
outputTokens: Math.max(0, total.outputTokens - part.outputTokens),
|
|
481
|
+
cacheReadTokens: cacheRead || void 0,
|
|
482
|
+
cacheWriteTokens: cacheWrite || void 0,
|
|
483
|
+
costUsd: total.costUsd != null && part.costUsd != null ? Math.max(0, total.costUsd - part.costUsd) : total.costUsd,
|
|
484
|
+
sessionCostUsd: total.sessionCostUsd,
|
|
485
|
+
lastRequestTokens: total.lastRequestTokens
|
|
486
|
+
};
|
|
487
|
+
}
|
|
474
488
|
function mergeUsage(a, b) {
|
|
475
489
|
return {
|
|
476
490
|
inputTokens: (a?.inputTokens ?? 0) + b.inputTokens,
|
|
@@ -562,7 +576,8 @@ function previousCostBaseline(messages) {
|
|
|
562
576
|
}
|
|
563
577
|
return {
|
|
564
578
|
sessionCostUsd: lastSession ?? summed,
|
|
565
|
-
lastCostUsd: lastCost
|
|
579
|
+
lastCostUsd: lastCost,
|
|
580
|
+
hasSessionSnapshot: lastSession != null
|
|
566
581
|
};
|
|
567
582
|
}
|
|
568
583
|
function turnCostUsdFromProviderSnapshot(opts) {
|
|
@@ -576,6 +591,9 @@ function turnCostUsdFromProviderSnapshot(opts) {
|
|
|
576
591
|
if (session + USD_EPS >= previous) {
|
|
577
592
|
return roundUsd(Math.max(0, session - previous));
|
|
578
593
|
}
|
|
594
|
+
if (opts.previousHasSessionSnapshot) {
|
|
595
|
+
return roundUsd(session);
|
|
596
|
+
}
|
|
579
597
|
if (last != null && session + USD_EPS >= last) {
|
|
580
598
|
return roundUsd(Math.max(0, session - last));
|
|
581
599
|
}
|
|
@@ -590,7 +608,8 @@ function withTurnScopedCost(usage, previousMessages) {
|
|
|
590
608
|
reportedTurnCostUsd: usage.costUsd,
|
|
591
609
|
sessionCostUsd: usage.sessionCostUsd,
|
|
592
610
|
previousSessionCostUsd: baseline.sessionCostUsd,
|
|
593
|
-
previousLastCostUsd: baseline.lastCostUsd
|
|
611
|
+
previousLastCostUsd: baseline.lastCostUsd,
|
|
612
|
+
previousHasSessionSnapshot: baseline.hasSessionSnapshot
|
|
594
613
|
});
|
|
595
614
|
if (costUsd == null) {
|
|
596
615
|
if (usage.costUsd == null) return usage;
|
|
@@ -2371,6 +2390,7 @@ export {
|
|
|
2371
2390
|
formatViewerContextDirective,
|
|
2372
2391
|
formatViewerContextReminder,
|
|
2373
2392
|
fromInclusiveInputUsage,
|
|
2393
|
+
subtractUsage,
|
|
2374
2394
|
sumUsageList,
|
|
2375
2395
|
applyTurnUsage,
|
|
2376
2396
|
contextTokens,
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import {
|
|
2
|
+
httpFetch
|
|
3
|
+
} from "./chunk-JAT3JFOS.js";
|
|
4
|
+
import {
|
|
5
|
+
ATTACHMENTS_DIR,
|
|
6
|
+
attachmentsGitignoreBody
|
|
7
|
+
} from "./chunk-6K64FJDD.js";
|
|
8
|
+
|
|
9
|
+
// src/integrations/issue-attachments.ts
|
|
10
|
+
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
11
|
+
import { basename, extname, join } from "path";
|
|
12
|
+
import { randomUUID } from "crypto";
|
|
13
|
+
var ISSUE_ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;
|
|
14
|
+
var MARKDOWN_IMAGE_RE = /!\[[^\]]*]\(\s*<?(https?:\/\/[^)\s>]+)>?/gi;
|
|
15
|
+
var MARKDOWN_LINK_RE = /(?<!!)\[[^\]]*]\(\s*<?(https?:\/\/[^)\s>]+)>?/gi;
|
|
16
|
+
var HTML_SRC_RE = /\b(?:src|href)\s*=\s*["'](https?:\/\/[^"']+)["']/gi;
|
|
17
|
+
var BARE_URL_RE = /https?:\/\/[^\s<>"'`)]+/gi;
|
|
18
|
+
var EXT_BY_MIME = {
|
|
19
|
+
"image/png": ".png",
|
|
20
|
+
"image/jpeg": ".jpg",
|
|
21
|
+
"image/jpg": ".jpg",
|
|
22
|
+
"image/gif": ".gif",
|
|
23
|
+
"image/webp": ".webp",
|
|
24
|
+
"image/svg+xml": ".svg",
|
|
25
|
+
"application/pdf": ".pdf",
|
|
26
|
+
"text/plain": ".txt",
|
|
27
|
+
"text/markdown": ".md",
|
|
28
|
+
"application/json": ".json",
|
|
29
|
+
"application/zip": ".zip"
|
|
30
|
+
};
|
|
31
|
+
function issueAttachmentWorktreePath(repoPath) {
|
|
32
|
+
const raw = (repoPath ?? "").trim();
|
|
33
|
+
return raw || process.cwd();
|
|
34
|
+
}
|
|
35
|
+
function ensureIssueAttachmentsDir(worktreePath) {
|
|
36
|
+
const dir = join(worktreePath, ATTACHMENTS_DIR);
|
|
37
|
+
mkdirSync(dir, { recursive: true });
|
|
38
|
+
const gi = join(dir, ".gitignore");
|
|
39
|
+
if (!existsSync(gi)) {
|
|
40
|
+
writeFileSync(gi, attachmentsGitignoreBody(), "utf8");
|
|
41
|
+
}
|
|
42
|
+
return dir;
|
|
43
|
+
}
|
|
44
|
+
function hostnameOf(url) {
|
|
45
|
+
try {
|
|
46
|
+
return new URL(url).hostname.toLowerCase();
|
|
47
|
+
} catch {
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function hostMatches(url, suffixes) {
|
|
52
|
+
const host = hostnameOf(url);
|
|
53
|
+
if (!host) return false;
|
|
54
|
+
return suffixes.some((suffix) => host === suffix || host.endsWith(`.${suffix}`));
|
|
55
|
+
}
|
|
56
|
+
function looksLikeHttpUrl(value) {
|
|
57
|
+
return /^https?:\/\//i.test(value.trim());
|
|
58
|
+
}
|
|
59
|
+
function looksLikeFileUrl(url) {
|
|
60
|
+
try {
|
|
61
|
+
const path = new URL(url).pathname;
|
|
62
|
+
return /\.[a-z0-9]{2,8}$/i.test(path);
|
|
63
|
+
} catch {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function filenameFromUrl(url, fallback = "attachment") {
|
|
68
|
+
try {
|
|
69
|
+
const parsed = new URL(url);
|
|
70
|
+
const last = decodeURIComponent(basename(parsed.pathname)).replace(/[/\\]/g, "_");
|
|
71
|
+
if (last && last !== "/" && last !== ".") return last;
|
|
72
|
+
} catch {
|
|
73
|
+
}
|
|
74
|
+
return fallback;
|
|
75
|
+
}
|
|
76
|
+
function filenameFromContentDisposition(header) {
|
|
77
|
+
if (!header) return void 0;
|
|
78
|
+
const star = header.match(/filename\*\s*=\s*(?:UTF-8''|utf-8'')([^;]+)/i);
|
|
79
|
+
if (star?.[1]) {
|
|
80
|
+
try {
|
|
81
|
+
return decodeURIComponent(star[1].trim().replace(/^["']|["']$/g, ""));
|
|
82
|
+
} catch {
|
|
83
|
+
return star[1].trim().replace(/^["']|["']$/g, "");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const plain = header.match(/filename\s*=\s*("(?:\\.|[^"])*"|[^;]+)/i);
|
|
87
|
+
if (!plain?.[1]) return void 0;
|
|
88
|
+
return plain[1].trim().replace(/^["']|["']$/g, "").replace(/\\"/g, '"');
|
|
89
|
+
}
|
|
90
|
+
function uniqueAttachmentFileName(dir, originalName) {
|
|
91
|
+
const safe = originalName.replace(/[/\\]/g, "_").replace(/^\.+/, "") || "file";
|
|
92
|
+
if (!existsSync(join(dir, safe))) return safe;
|
|
93
|
+
const ext = extname(safe);
|
|
94
|
+
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
95
|
+
for (let i = 1; i < 1e4; i++) {
|
|
96
|
+
const candidate = `${stem}-${i}${ext}`;
|
|
97
|
+
if (!existsSync(join(dir, candidate))) return candidate;
|
|
98
|
+
}
|
|
99
|
+
return `${stem}-${randomUUID()}${ext}`;
|
|
100
|
+
}
|
|
101
|
+
function extractHttpUrls(markdown) {
|
|
102
|
+
const text = markdown ?? "";
|
|
103
|
+
if (!text.trim()) return [];
|
|
104
|
+
const found = [];
|
|
105
|
+
const seen = /* @__PURE__ */ new Set();
|
|
106
|
+
const push = (raw) => {
|
|
107
|
+
const url = raw.replace(/[).,;]+$/, "");
|
|
108
|
+
if (!looksLikeHttpUrl(url) || seen.has(url)) return;
|
|
109
|
+
seen.add(url);
|
|
110
|
+
found.push(url);
|
|
111
|
+
};
|
|
112
|
+
for (const re of [MARKDOWN_IMAGE_RE, MARKDOWN_LINK_RE, HTML_SRC_RE, BARE_URL_RE]) {
|
|
113
|
+
re.lastIndex = 0;
|
|
114
|
+
let match;
|
|
115
|
+
while (match = re.exec(text)) {
|
|
116
|
+
if (match[1]) push(match[1]);
|
|
117
|
+
else if (re === BARE_URL_RE) push(match[0]);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return found;
|
|
121
|
+
}
|
|
122
|
+
function mergeIssueAttachments(items) {
|
|
123
|
+
const out = [];
|
|
124
|
+
const seen = /* @__PURE__ */ new Set();
|
|
125
|
+
for (const item of items) {
|
|
126
|
+
if (!item) continue;
|
|
127
|
+
const url = item.url.trim();
|
|
128
|
+
const id = item.id.trim() || url;
|
|
129
|
+
if (!id && !url) continue;
|
|
130
|
+
const key = url || id;
|
|
131
|
+
if (seen.has(key) || seen.has(id)) continue;
|
|
132
|
+
seen.add(key);
|
|
133
|
+
if (id !== key) seen.add(id);
|
|
134
|
+
out.push({
|
|
135
|
+
id: id || url,
|
|
136
|
+
name: item.name.trim() || filenameFromUrl(url),
|
|
137
|
+
url,
|
|
138
|
+
...item.contentType ? { contentType: item.contentType } : {},
|
|
139
|
+
...item.sourceType ? { sourceType: item.sourceType } : {}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
144
|
+
function extensionForContentType(contentType, name) {
|
|
145
|
+
if (extname(name)) return name;
|
|
146
|
+
const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase() ?? "";
|
|
147
|
+
const ext = EXT_BY_MIME[mime];
|
|
148
|
+
return ext ? `${name}${ext}` : name;
|
|
149
|
+
}
|
|
150
|
+
function assertNotHtml(contentType, url) {
|
|
151
|
+
const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase() ?? "";
|
|
152
|
+
if (mime === "text/html" || mime === "application/xhtml+xml") {
|
|
153
|
+
throw new Error(
|
|
154
|
+
`Attachment at ${url} returned HTML, not a file. Use the listed file URL (uploads / user-attachments), not a ticket or PR page.`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async function downloadAuthenticatedFile(opts) {
|
|
159
|
+
const url = opts.url.trim();
|
|
160
|
+
if (!looksLikeHttpUrl(url)) {
|
|
161
|
+
throw new Error(`Attachment URL must be http(s) (got ${url || "empty"})`);
|
|
162
|
+
}
|
|
163
|
+
const res = await httpFetch(url, {
|
|
164
|
+
method: "GET",
|
|
165
|
+
redirect: "follow",
|
|
166
|
+
headers: {
|
|
167
|
+
Accept: "*/*",
|
|
168
|
+
...opts.headers ?? {}
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
if (!res.ok) {
|
|
172
|
+
const detail = await res.text().catch(() => "");
|
|
173
|
+
throw new Error(
|
|
174
|
+
`Attachment download failed ${res.status}${detail ? `: ${detail.slice(0, 200)}` : ""} (${url})`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
const contentType = res.headers.get("content-type") ?? void 0;
|
|
178
|
+
assertNotHtml(contentType, url);
|
|
179
|
+
const lengthHeader = res.headers.get("content-length");
|
|
180
|
+
if (lengthHeader) {
|
|
181
|
+
const length = Number(lengthHeader);
|
|
182
|
+
if (Number.isFinite(length) && length > ISSUE_ATTACHMENT_MAX_BYTES) {
|
|
183
|
+
throw new Error(
|
|
184
|
+
`Attachment is ${length} bytes; max is ${ISSUE_ATTACHMENT_MAX_BYTES} (${url})`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
189
|
+
if (buf.length > ISSUE_ATTACHMENT_MAX_BYTES) {
|
|
190
|
+
throw new Error(
|
|
191
|
+
`Attachment is ${buf.length} bytes; max is ${ISSUE_ATTACHMENT_MAX_BYTES} (${url})`
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
const dir = ensureIssueAttachmentsDir(opts.worktreePath);
|
|
195
|
+
const hinted = opts.name?.trim() || filenameFromContentDisposition(res.headers.get("content-disposition")) || filenameFromUrl(url);
|
|
196
|
+
const name = uniqueAttachmentFileName(dir, extensionForContentType(contentType, hinted));
|
|
197
|
+
writeFileSync(join(dir, name), buf);
|
|
198
|
+
return {
|
|
199
|
+
name,
|
|
200
|
+
path: `${ATTACHMENTS_DIR}/${name}`,
|
|
201
|
+
bytes: buf.length,
|
|
202
|
+
...contentType ? { contentType } : {}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export {
|
|
207
|
+
issueAttachmentWorktreePath,
|
|
208
|
+
hostMatches,
|
|
209
|
+
looksLikeHttpUrl,
|
|
210
|
+
looksLikeFileUrl,
|
|
211
|
+
extractHttpUrls,
|
|
212
|
+
mergeIssueAttachments,
|
|
213
|
+
downloadAuthenticatedFile
|
|
214
|
+
};
|
|
@@ -20,14 +20,14 @@ import {
|
|
|
20
20
|
import {
|
|
21
21
|
getGithubGitAuthMode,
|
|
22
22
|
getGithubPat
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-CI4M54LS.js";
|
|
24
24
|
import {
|
|
25
25
|
allocateTeamName,
|
|
26
26
|
listThreads,
|
|
27
27
|
normalizeTakenSlug,
|
|
28
28
|
normalizeWorktreePath,
|
|
29
29
|
takenSlugsFromThread
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-Q3FHTGIW.js";
|
|
31
31
|
import {
|
|
32
32
|
worktreesRoot
|
|
33
33
|
} from "./chunk-WOU343SI.js";
|
|
@@ -282,12 +282,11 @@ function codexSandboxWritableRootsArgs(roots) {
|
|
|
282
282
|
return ["-c", `sandbox_workspace_write.writable_roots=${JSON.stringify(abs)}`];
|
|
283
283
|
}
|
|
284
284
|
function codexUnattendedGitConfigArgs(sandbox, opts) {
|
|
285
|
-
const args = [
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
"-c",
|
|
289
|
-
|
|
290
|
-
];
|
|
285
|
+
const args = ["-c", 'shell_environment_policy.inherit="all"'];
|
|
286
|
+
for (const [key, value] of Object.entries(opts?.preserveEnv ?? {})) {
|
|
287
|
+
if (!/^GIT_CONFIG_KEY_\d+$/.test(key) || !value) continue;
|
|
288
|
+
args.push("-c", `shell_environment_policy.set.${key}=${JSON.stringify(value)}`);
|
|
289
|
+
}
|
|
291
290
|
if (sandbox === "workspace-write") {
|
|
292
291
|
args.push("-c", "sandbox_workspace_write.network_access=true");
|
|
293
292
|
args.push(...codexSandboxWritableRootsArgs(opts?.writableRoots ?? []));
|