@sideboard-ai/core 0.1.323 → 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-2ZXORBEJ.js → agents-LDRM3BTY.js} +9 -8
- package/dist/{agents-SPRAOMGI.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-SKO7IGKU.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-6W3XRKD5.js → chunk-APKUI4BP.js} +6 -7
- 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-4C5PQ7JA.js → chunk-GNLKBS3U.js} +206 -188
- package/dist/{chunk-EKU7FQVG.js → chunk-H36GKGU2.js} +2 -2
- package/dist/{chunk-53SBTCKF.js → chunk-HG6KS7OT.js} +294 -265
- package/dist/chunk-MBT6WDAB.js +28 -0
- package/dist/{chunk-D3VSKNVA.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-JDX3474T.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-RTVS3M74.js → chunk-WYEST76H.js} +7 -7
- package/dist/{chunk-ODH3XHMI.js → chunk-ZEUMWHOH.js} +5 -5
- package/dist/{chunk-MYVKOIIY.js → chunk-ZHDXLDLA.js} +6 -7
- package/dist/{chunk-IFWGG2M2.js → chunk-ZSHS46V5.js} +2 -0
- package/dist/{conductor-52KTQ3IM.js → conductor-D4KFZF54.js} +6 -6
- package/dist/{conductor-FB7MKLRN.js → conductor-KB7L7NQN.js} +7 -7
- package/dist/{coordinator-prompt-7HXV7HJ5.js → coordinator-prompt-OBXEC63K.js} +4 -4
- package/dist/{coordinator-prompt-7W7WPY4X.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-EI3KBGZE.js → global-workspace-UHU2FXTY.js} +4 -4
- package/dist/{global-workspace-5BWUTSPJ.js → global-workspace-Z2SURNHA.js} +4 -4
- package/dist/index.cjs +21115 -20868
- package/dist/index.d.cts +28 -12
- package/dist/index.d.ts +28 -12
- 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 +15909 -15654
- 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-RMPZETOO.js → orchestrator-3H4KNGPN.js} +15 -13
- package/dist/{orchestrator-2RDE2YS3.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-LJQS73K6.js → workspaces-MG5JHRKW.js} +4 -4
- package/dist/{workspaces-OPQ5NMM6.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
|
@@ -1,223 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
downloadAuthenticatedFile,
|
|
3
|
+
extractHttpUrls,
|
|
4
|
+
hostMatches,
|
|
5
|
+
issueAttachmentWorktreePath,
|
|
6
|
+
looksLikeFileUrl,
|
|
7
|
+
looksLikeHttpUrl,
|
|
8
|
+
mergeIssueAttachments
|
|
9
|
+
} from "./chunk-DBKHL7NC.js";
|
|
1
10
|
import {
|
|
2
11
|
abletimeRestUrl,
|
|
3
12
|
textFromAbleTimeDoc
|
|
4
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-H36GKGU2.js";
|
|
5
14
|
import {
|
|
6
15
|
assertAbleTimeCredential,
|
|
7
16
|
callAbleTimeTool,
|
|
8
17
|
normalizeAbleTimeHost,
|
|
9
18
|
rewriteAbleTimeError
|
|
10
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-ZEUMWHOH.js";
|
|
11
20
|
import {
|
|
12
21
|
httpFetch
|
|
13
22
|
} from "./chunk-JAT3JFOS.js";
|
|
14
|
-
import {
|
|
15
|
-
ATTACHMENTS_DIR,
|
|
16
|
-
attachmentsGitignoreBody
|
|
17
|
-
} from "./chunk-6K64FJDD.js";
|
|
18
23
|
import {
|
|
19
24
|
getAbleTimeAccessToken,
|
|
20
25
|
getAbleTimeHost,
|
|
21
26
|
isAbleTimeConnected,
|
|
22
27
|
saveAbleTimeConnection
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
|
|
25
|
-
// src/integrations/issue-attachments.ts
|
|
26
|
-
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
27
|
-
import { basename, extname, join } from "path";
|
|
28
|
-
import { randomUUID } from "crypto";
|
|
29
|
-
var ISSUE_ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;
|
|
30
|
-
var MARKDOWN_IMAGE_RE = /!\[[^\]]*]\(\s*<?(https?:\/\/[^)\s>]+)>?/gi;
|
|
31
|
-
var MARKDOWN_LINK_RE = /(?<!!)\[[^\]]*]\(\s*<?(https?:\/\/[^)\s>]+)>?/gi;
|
|
32
|
-
var HTML_SRC_RE = /\b(?:src|href)\s*=\s*["'](https?:\/\/[^"']+)["']/gi;
|
|
33
|
-
var BARE_URL_RE = /https?:\/\/[^\s<>"'`)]+/gi;
|
|
34
|
-
var EXT_BY_MIME = {
|
|
35
|
-
"image/png": ".png",
|
|
36
|
-
"image/jpeg": ".jpg",
|
|
37
|
-
"image/jpg": ".jpg",
|
|
38
|
-
"image/gif": ".gif",
|
|
39
|
-
"image/webp": ".webp",
|
|
40
|
-
"image/svg+xml": ".svg",
|
|
41
|
-
"application/pdf": ".pdf",
|
|
42
|
-
"text/plain": ".txt",
|
|
43
|
-
"text/markdown": ".md",
|
|
44
|
-
"application/json": ".json",
|
|
45
|
-
"application/zip": ".zip"
|
|
46
|
-
};
|
|
47
|
-
function issueAttachmentWorktreePath(repoPath) {
|
|
48
|
-
const raw = (repoPath ?? "").trim();
|
|
49
|
-
return raw || process.cwd();
|
|
50
|
-
}
|
|
51
|
-
function ensureIssueAttachmentsDir(worktreePath) {
|
|
52
|
-
const dir = join(worktreePath, ATTACHMENTS_DIR);
|
|
53
|
-
mkdirSync(dir, { recursive: true });
|
|
54
|
-
const gi = join(dir, ".gitignore");
|
|
55
|
-
if (!existsSync(gi)) {
|
|
56
|
-
writeFileSync(gi, attachmentsGitignoreBody(), "utf8");
|
|
57
|
-
}
|
|
58
|
-
return dir;
|
|
59
|
-
}
|
|
60
|
-
function hostnameOf(url) {
|
|
61
|
-
try {
|
|
62
|
-
return new URL(url).hostname.toLowerCase();
|
|
63
|
-
} catch {
|
|
64
|
-
return "";
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
function hostMatches(url, suffixes) {
|
|
68
|
-
const host = hostnameOf(url);
|
|
69
|
-
if (!host) return false;
|
|
70
|
-
return suffixes.some((suffix) => host === suffix || host.endsWith(`.${suffix}`));
|
|
71
|
-
}
|
|
72
|
-
function looksLikeHttpUrl(value) {
|
|
73
|
-
return /^https?:\/\//i.test(value.trim());
|
|
74
|
-
}
|
|
75
|
-
function looksLikeFileUrl(url) {
|
|
76
|
-
try {
|
|
77
|
-
const path = new URL(url).pathname;
|
|
78
|
-
return /\.[a-z0-9]{2,8}$/i.test(path);
|
|
79
|
-
} catch {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
function filenameFromUrl(url, fallback = "attachment") {
|
|
84
|
-
try {
|
|
85
|
-
const parsed = new URL(url);
|
|
86
|
-
const last = decodeURIComponent(basename(parsed.pathname)).replace(/[/\\]/g, "_");
|
|
87
|
-
if (last && last !== "/" && last !== ".") return last;
|
|
88
|
-
} catch {
|
|
89
|
-
}
|
|
90
|
-
return fallback;
|
|
91
|
-
}
|
|
92
|
-
function filenameFromContentDisposition(header) {
|
|
93
|
-
if (!header) return void 0;
|
|
94
|
-
const star = header.match(/filename\*\s*=\s*(?:UTF-8''|utf-8'')([^;]+)/i);
|
|
95
|
-
if (star?.[1]) {
|
|
96
|
-
try {
|
|
97
|
-
return decodeURIComponent(star[1].trim().replace(/^["']|["']$/g, ""));
|
|
98
|
-
} catch {
|
|
99
|
-
return star[1].trim().replace(/^["']|["']$/g, "");
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
const plain = header.match(/filename\s*=\s*("(?:\\.|[^"])*"|[^;]+)/i);
|
|
103
|
-
if (!plain?.[1]) return void 0;
|
|
104
|
-
return plain[1].trim().replace(/^["']|["']$/g, "").replace(/\\"/g, '"');
|
|
105
|
-
}
|
|
106
|
-
function uniqueAttachmentFileName(dir, originalName) {
|
|
107
|
-
const safe = originalName.replace(/[/\\]/g, "_").replace(/^\.+/, "") || "file";
|
|
108
|
-
if (!existsSync(join(dir, safe))) return safe;
|
|
109
|
-
const ext = extname(safe);
|
|
110
|
-
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
111
|
-
for (let i = 1; i < 1e4; i++) {
|
|
112
|
-
const candidate = `${stem}-${i}${ext}`;
|
|
113
|
-
if (!existsSync(join(dir, candidate))) return candidate;
|
|
114
|
-
}
|
|
115
|
-
return `${stem}-${randomUUID()}${ext}`;
|
|
116
|
-
}
|
|
117
|
-
function extractHttpUrls(markdown) {
|
|
118
|
-
const text = markdown ?? "";
|
|
119
|
-
if (!text.trim()) return [];
|
|
120
|
-
const found = [];
|
|
121
|
-
const seen = /* @__PURE__ */ new Set();
|
|
122
|
-
const push = (raw) => {
|
|
123
|
-
const url = raw.replace(/[).,;]+$/, "");
|
|
124
|
-
if (!looksLikeHttpUrl(url) || seen.has(url)) return;
|
|
125
|
-
seen.add(url);
|
|
126
|
-
found.push(url);
|
|
127
|
-
};
|
|
128
|
-
for (const re of [MARKDOWN_IMAGE_RE, MARKDOWN_LINK_RE, HTML_SRC_RE, BARE_URL_RE]) {
|
|
129
|
-
re.lastIndex = 0;
|
|
130
|
-
let match;
|
|
131
|
-
while (match = re.exec(text)) {
|
|
132
|
-
if (match[1]) push(match[1]);
|
|
133
|
-
else if (re === BARE_URL_RE) push(match[0]);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return found;
|
|
137
|
-
}
|
|
138
|
-
function mergeIssueAttachments(items) {
|
|
139
|
-
const out = [];
|
|
140
|
-
const seen = /* @__PURE__ */ new Set();
|
|
141
|
-
for (const item of items) {
|
|
142
|
-
if (!item) continue;
|
|
143
|
-
const url = item.url.trim();
|
|
144
|
-
const id = item.id.trim() || url;
|
|
145
|
-
if (!id && !url) continue;
|
|
146
|
-
const key = url || id;
|
|
147
|
-
if (seen.has(key) || seen.has(id)) continue;
|
|
148
|
-
seen.add(key);
|
|
149
|
-
if (id !== key) seen.add(id);
|
|
150
|
-
out.push({
|
|
151
|
-
id: id || url,
|
|
152
|
-
name: item.name.trim() || filenameFromUrl(url),
|
|
153
|
-
url,
|
|
154
|
-
...item.contentType ? { contentType: item.contentType } : {},
|
|
155
|
-
...item.sourceType ? { sourceType: item.sourceType } : {}
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
return out;
|
|
159
|
-
}
|
|
160
|
-
function extensionForContentType(contentType, name) {
|
|
161
|
-
if (extname(name)) return name;
|
|
162
|
-
const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase() ?? "";
|
|
163
|
-
const ext = EXT_BY_MIME[mime];
|
|
164
|
-
return ext ? `${name}${ext}` : name;
|
|
165
|
-
}
|
|
166
|
-
function assertNotHtml(contentType, url) {
|
|
167
|
-
const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase() ?? "";
|
|
168
|
-
if (mime === "text/html" || mime === "application/xhtml+xml") {
|
|
169
|
-
throw new Error(
|
|
170
|
-
`Attachment at ${url} returned HTML, not a file. Use the listed file URL (uploads / user-attachments), not a ticket or PR page.`
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
async function downloadAuthenticatedFile(opts) {
|
|
175
|
-
const url = opts.url.trim();
|
|
176
|
-
if (!looksLikeHttpUrl(url)) {
|
|
177
|
-
throw new Error(`Attachment URL must be http(s) (got ${url || "empty"})`);
|
|
178
|
-
}
|
|
179
|
-
const res = await httpFetch(url, {
|
|
180
|
-
method: "GET",
|
|
181
|
-
redirect: "follow",
|
|
182
|
-
headers: {
|
|
183
|
-
Accept: "*/*",
|
|
184
|
-
...opts.headers ?? {}
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
if (!res.ok) {
|
|
188
|
-
const detail = await res.text().catch(() => "");
|
|
189
|
-
throw new Error(
|
|
190
|
-
`Attachment download failed ${res.status}${detail ? `: ${detail.slice(0, 200)}` : ""} (${url})`
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
const contentType = res.headers.get("content-type") ?? void 0;
|
|
194
|
-
assertNotHtml(contentType, url);
|
|
195
|
-
const lengthHeader = res.headers.get("content-length");
|
|
196
|
-
if (lengthHeader) {
|
|
197
|
-
const length = Number(lengthHeader);
|
|
198
|
-
if (Number.isFinite(length) && length > ISSUE_ATTACHMENT_MAX_BYTES) {
|
|
199
|
-
throw new Error(
|
|
200
|
-
`Attachment is ${length} bytes; max is ${ISSUE_ATTACHMENT_MAX_BYTES} (${url})`
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
const buf = Buffer.from(await res.arrayBuffer());
|
|
205
|
-
if (buf.length > ISSUE_ATTACHMENT_MAX_BYTES) {
|
|
206
|
-
throw new Error(
|
|
207
|
-
`Attachment is ${buf.length} bytes; max is ${ISSUE_ATTACHMENT_MAX_BYTES} (${url})`
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
const dir = ensureIssueAttachmentsDir(opts.worktreePath);
|
|
211
|
-
const hinted = opts.name?.trim() || filenameFromContentDisposition(res.headers.get("content-disposition")) || filenameFromUrl(url);
|
|
212
|
-
const name = uniqueAttachmentFileName(dir, extensionForContentType(contentType, hinted));
|
|
213
|
-
writeFileSync(join(dir, name), buf);
|
|
214
|
-
return {
|
|
215
|
-
name,
|
|
216
|
-
path: `${ATTACHMENTS_DIR}/${name}`,
|
|
217
|
-
bytes: buf.length,
|
|
218
|
-
...contentType ? { contentType } : {}
|
|
219
|
-
};
|
|
220
|
-
}
|
|
28
|
+
} from "./chunk-RZJTGBXY.js";
|
|
221
29
|
|
|
222
30
|
// src/integrations/abletime-attachments.ts
|
|
223
31
|
function asRecord(value) {
|
|
@@ -839,12 +647,6 @@ async function verifyAbleTimeConnection(input) {
|
|
|
839
647
|
}
|
|
840
648
|
|
|
841
649
|
export {
|
|
842
|
-
issueAttachmentWorktreePath,
|
|
843
|
-
hostMatches,
|
|
844
|
-
looksLikeHttpUrl,
|
|
845
|
-
extractHttpUrls,
|
|
846
|
-
mergeIssueAttachments,
|
|
847
|
-
downloadAuthenticatedFile,
|
|
848
650
|
downloadAbleTimeAttachment,
|
|
849
651
|
taskUrl,
|
|
850
652
|
mapAbleTimeTask,
|
|
@@ -79,7 +79,7 @@ function extractJsonErrorMessage(obj) {
|
|
|
79
79
|
const candidates = [
|
|
80
80
|
typeof obj.message === "string" ? obj.message : null,
|
|
81
81
|
typeof obj.error === "string" ? obj.error : null,
|
|
82
|
-
nested && typeof nested.message === "string" ? nested.message : null,
|
|
82
|
+
nested && typeof nested.message === "string" ? nested.message : typeof nested?.data?.message === "string" ? nested.data.message : null,
|
|
83
83
|
typeof obj.result === "string" ? obj.result : null,
|
|
84
84
|
typeof obj.detail === "string" ? obj.detail : null
|
|
85
85
|
];
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
// src/integrations/issue-since.ts
|
|
5
|
+
var ISSUE_SINCE_ERROR = "updatedSince must be an ISO datetime, YYYY-MM-DD, or relative time (yesterday, 2d, 3 hours ago)";
|
|
6
|
+
var DATE_ONLY_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
7
|
+
var DATE_TIME_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/;
|
|
8
|
+
var RELATIVE_RE = /^(\d+)\s*(hours?|hrs?|h|days?|d|weeks?|wks?|w)(?:\s+ago)?$/i;
|
|
9
|
+
function startOfLocalDay(date) {
|
|
10
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
11
|
+
}
|
|
12
|
+
function addLocalDays(date, days) {
|
|
13
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);
|
|
14
|
+
}
|
|
15
|
+
function parseIssueSince(input, now = /* @__PURE__ */ new Date()) {
|
|
16
|
+
const raw = input.trim();
|
|
17
|
+
if (!raw) throw new Error(ISSUE_SINCE_ERROR);
|
|
18
|
+
const dateOnly = raw.match(DATE_ONLY_RE);
|
|
19
|
+
if (dateOnly) {
|
|
20
|
+
const year = Number(dateOnly[1]);
|
|
21
|
+
const month = Number(dateOnly[2]);
|
|
22
|
+
const day = Number(dateOnly[3]);
|
|
23
|
+
const local = new Date(year, month - 1, day);
|
|
24
|
+
if (local.getFullYear() !== year || local.getMonth() !== month - 1 || local.getDate() !== day) {
|
|
25
|
+
throw new Error(ISSUE_SINCE_ERROR);
|
|
26
|
+
}
|
|
27
|
+
return startOfLocalDay(local).toISOString();
|
|
28
|
+
}
|
|
29
|
+
if (DATE_TIME_RE.test(raw)) {
|
|
30
|
+
const ms = Date.parse(raw);
|
|
31
|
+
if (!Number.isFinite(ms)) throw new Error(ISSUE_SINCE_ERROR);
|
|
32
|
+
return new Date(ms).toISOString();
|
|
33
|
+
}
|
|
34
|
+
const lower = raw.toLowerCase();
|
|
35
|
+
if (lower === "today") return startOfLocalDay(now).toISOString();
|
|
36
|
+
if (lower === "yesterday") return addLocalDays(startOfLocalDay(now), -1).toISOString();
|
|
37
|
+
if (lower === "last week" || lower === "lastweek") {
|
|
38
|
+
return addLocalDays(startOfLocalDay(now), -7).toISOString();
|
|
39
|
+
}
|
|
40
|
+
const relative = lower.match(RELATIVE_RE);
|
|
41
|
+
if (relative) {
|
|
42
|
+
const n = Number(relative[1]);
|
|
43
|
+
if (!Number.isInteger(n) || n < 1) throw new Error(ISSUE_SINCE_ERROR);
|
|
44
|
+
const unit = relative[2];
|
|
45
|
+
if (unit.startsWith("h")) return new Date(now.getTime() - n * 36e5).toISOString();
|
|
46
|
+
if (unit.startsWith("w")) return addLocalDays(startOfLocalDay(now), -7 * n).toISOString();
|
|
47
|
+
return addLocalDays(startOfLocalDay(now), -n).toISOString();
|
|
48
|
+
}
|
|
49
|
+
throw new Error(ISSUE_SINCE_ERROR);
|
|
50
|
+
}
|
|
51
|
+
function formatGitHubSearchUpdatedSince(iso) {
|
|
52
|
+
return iso.replace(/\.\d{3}Z$/, "Z");
|
|
53
|
+
}
|
|
54
|
+
function issueMatchesUpdatedSince(issue, sinceIso) {
|
|
55
|
+
const ts = issue.updatedAt || issue.createdAt;
|
|
56
|
+
if (!ts) return false;
|
|
57
|
+
const value = Date.parse(ts);
|
|
58
|
+
const since = Date.parse(sinceIso);
|
|
59
|
+
return Number.isFinite(value) && Number.isFinite(since) && value >= since;
|
|
60
|
+
}
|
|
61
|
+
var ISSUE_COMMENT_PREVIEW_CHARS = 240;
|
|
62
|
+
function previewIssueCommentBody(body) {
|
|
63
|
+
const flat = body.replace(/\s+/g, " ").trim();
|
|
64
|
+
if (flat.length <= ISSUE_COMMENT_PREVIEW_CHARS) return flat;
|
|
65
|
+
return `${flat.slice(0, ISSUE_COMMENT_PREVIEW_CHARS - 1).trimEnd()}\u2026`;
|
|
66
|
+
}
|
|
67
|
+
function issueActivityKind(issue, sinceIso) {
|
|
68
|
+
const created = issue.createdAt ? Date.parse(issue.createdAt) : Number.NaN;
|
|
69
|
+
const since = Date.parse(sinceIso);
|
|
70
|
+
if (Number.isFinite(created) && Number.isFinite(since) && created >= since) return "created";
|
|
71
|
+
return "updated";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export {
|
|
75
|
+
parseIssueSince,
|
|
76
|
+
formatGitHubSearchUpdatedSince,
|
|
77
|
+
issueMatchesUpdatedSince,
|
|
78
|
+
previewIssueCommentBody,
|
|
79
|
+
issueActivityKind
|
|
80
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/agents/linear-list.ts
|
|
2
|
+
var LIST_TIMEOUT_MS = 15e3;
|
|
3
|
+
async function listAssignedLinearIssues(opts) {
|
|
4
|
+
try {
|
|
5
|
+
const { listLinearIssuesDirect } = await import("./linear-HFUOUJ5H.js");
|
|
6
|
+
const listed = listLinearIssuesDirect({ limit: 50 }).catch(() => []);
|
|
7
|
+
let timer;
|
|
8
|
+
try {
|
|
9
|
+
return await Promise.race([
|
|
10
|
+
listed,
|
|
11
|
+
new Promise((resolve) => {
|
|
12
|
+
timer = setTimeout(() => resolve([]), opts?.timeoutMs ?? LIST_TIMEOUT_MS);
|
|
13
|
+
})
|
|
14
|
+
]);
|
|
15
|
+
} finally {
|
|
16
|
+
if (timer) clearTimeout(timer);
|
|
17
|
+
}
|
|
18
|
+
} catch {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
listAssignedLinearIssues
|
|
25
|
+
};
|
|
@@ -1081,6 +1081,7 @@ function normalizeThread(raw) {
|
|
|
1081
1081
|
approvedMcpServers: normalizeApprovedMcpServers(raw.approvedMcpServers),
|
|
1082
1082
|
lastError: raw.lastError ?? null,
|
|
1083
1083
|
agentPid: raw.agentPid ?? null,
|
|
1084
|
+
agentPidStartedAt: raw.agentPidStartedAt ?? null,
|
|
1084
1085
|
attachments: Array.isArray(raw.attachments) ? raw.attachments : [],
|
|
1085
1086
|
pendingTurnAttachments: Array.isArray(raw.pendingTurnAttachments) ? raw.pendingTurnAttachments : [],
|
|
1086
1087
|
queueAttachments: Array.isArray(raw.queueAttachments) ? raw.queueAttachments : [],
|
|
@@ -1159,6 +1160,7 @@ function createEmptyThread(partial) {
|
|
|
1159
1160
|
agent: partial.agent,
|
|
1160
1161
|
lastError: null,
|
|
1161
1162
|
agentPid: null,
|
|
1163
|
+
agentPidStartedAt: null,
|
|
1162
1164
|
...partial.accountId !== void 0 ? { accountId: partial.accountId } : {}
|
|
1163
1165
|
};
|
|
1164
1166
|
}
|
|
@@ -683,6 +683,20 @@ function fromInclusiveInputUsage(opts) {
|
|
|
683
683
|
function requestOccupancy(u) {
|
|
684
684
|
return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
|
|
685
685
|
}
|
|
686
|
+
function subtractUsage(total, part) {
|
|
687
|
+
if (!total) return null;
|
|
688
|
+
const cacheRead = Math.max(0, (total.cacheReadTokens ?? 0) - (part.cacheReadTokens ?? 0));
|
|
689
|
+
const cacheWrite = Math.max(0, (total.cacheWriteTokens ?? 0) - (part.cacheWriteTokens ?? 0));
|
|
690
|
+
return {
|
|
691
|
+
inputTokens: Math.max(0, total.inputTokens - part.inputTokens),
|
|
692
|
+
outputTokens: Math.max(0, total.outputTokens - part.outputTokens),
|
|
693
|
+
cacheReadTokens: cacheRead || void 0,
|
|
694
|
+
cacheWriteTokens: cacheWrite || void 0,
|
|
695
|
+
costUsd: total.costUsd != null && part.costUsd != null ? Math.max(0, total.costUsd - part.costUsd) : total.costUsd,
|
|
696
|
+
sessionCostUsd: total.sessionCostUsd,
|
|
697
|
+
lastRequestTokens: total.lastRequestTokens
|
|
698
|
+
};
|
|
699
|
+
}
|
|
686
700
|
function mergeUsage(a, b) {
|
|
687
701
|
return {
|
|
688
702
|
inputTokens: (a?.inputTokens ?? 0) + b.inputTokens,
|
|
@@ -777,7 +791,8 @@ function previousCostBaseline(messages) {
|
|
|
777
791
|
}
|
|
778
792
|
return {
|
|
779
793
|
sessionCostUsd: lastSession ?? summed,
|
|
780
|
-
lastCostUsd: lastCost
|
|
794
|
+
lastCostUsd: lastCost,
|
|
795
|
+
hasSessionSnapshot: lastSession != null
|
|
781
796
|
};
|
|
782
797
|
}
|
|
783
798
|
function turnCostUsdFromProviderSnapshot(opts) {
|
|
@@ -791,6 +806,9 @@ function turnCostUsdFromProviderSnapshot(opts) {
|
|
|
791
806
|
if (session + USD_EPS >= previous) {
|
|
792
807
|
return roundUsd(Math.max(0, session - previous));
|
|
793
808
|
}
|
|
809
|
+
if (opts.previousHasSessionSnapshot) {
|
|
810
|
+
return roundUsd(session);
|
|
811
|
+
}
|
|
794
812
|
if (last != null && session + USD_EPS >= last) {
|
|
795
813
|
return roundUsd(Math.max(0, session - last));
|
|
796
814
|
}
|
|
@@ -805,7 +823,8 @@ function withTurnScopedCost(usage, previousMessages) {
|
|
|
805
823
|
reportedTurnCostUsd: usage.costUsd,
|
|
806
824
|
sessionCostUsd: usage.sessionCostUsd,
|
|
807
825
|
previousSessionCostUsd: baseline.sessionCostUsd,
|
|
808
|
-
previousLastCostUsd: baseline.lastCostUsd
|
|
826
|
+
previousLastCostUsd: baseline.lastCostUsd,
|
|
827
|
+
previousHasSessionSnapshot: baseline.hasSessionSnapshot
|
|
809
828
|
});
|
|
810
829
|
if (costUsd == null) {
|
|
811
830
|
if (usage.costUsd == null) return usage;
|
|
@@ -2605,6 +2624,7 @@ export {
|
|
|
2605
2624
|
saveSecretVault,
|
|
2606
2625
|
fromInclusiveInputUsage,
|
|
2607
2626
|
requestOccupancy,
|
|
2627
|
+
subtractUsage,
|
|
2608
2628
|
mergeUsage,
|
|
2609
2629
|
sumUsageList,
|
|
2610
2630
|
applyTurnUsage,
|