ticketlens 0.43.1 → 0.43.3
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/package.json
CHANGED
|
@@ -207,7 +207,7 @@ async function applySummarize(brief, args, opts, configDir, conn, licensedFn, up
|
|
|
207
207
|
const cliToken = opts.cliToken ?? readCliToken(configDir);
|
|
208
208
|
const provider = opts.provider ?? resolveAiProvider(args, credentials);
|
|
209
209
|
const aiInput = augmentBriefForAi(brief, ticket?.localAttachments);
|
|
210
|
-
const summary = await summarizerFn({ brief: aiInput, mode, credentials, cliToken, provider });
|
|
210
|
+
const summary = await summarizerFn({ brief: aiInput, mode, credentials, cliToken, provider, ticketKey });
|
|
211
211
|
if (ticketKey && !opts.summarizer) writeSummaryCache(ticketKey, profileName, summary, configDir);
|
|
212
212
|
const divider = '─'.repeat(60);
|
|
213
213
|
return brief + `\n\n${divider}\n─── AI Summary ${'─'.repeat(45)}\n${summary}\n${divider}\n`;
|
|
@@ -241,7 +241,7 @@ async function applyHandoff(ticket, args, opts, configDir, licensedFn, upgradeFn
|
|
|
241
241
|
const cliToken = opts.cliToken ?? readCliToken(configDir);
|
|
242
242
|
const provider = opts.provider ?? resolveAiProvider(args, credentials);
|
|
243
243
|
const input = buildHandoffInput(ticket);
|
|
244
|
-
const body = await summarizerFn({ brief: input, mode, credentials, cliToken, prompt: HANDOFF_PROMPT, maxTokens: 512, provider });
|
|
244
|
+
const body = await summarizerFn({ brief: input, mode, credentials, cliToken, prompt: HANDOFF_PROMPT, maxTokens: 512, provider, ticketKey: ticket?.key ?? null });
|
|
245
245
|
return `## Handoff Brief — ${ticket.key}\n\n${body}\n`;
|
|
246
246
|
} catch (err) {
|
|
247
247
|
const onErrorFn = opts.onError ?? ((msg) => process.stderr.write(msg + '\n'));
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Centralised here to avoid triplicating the regex and warning logic.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export const DEFAULT_API_BASE = '
|
|
6
|
+
export const DEFAULT_API_BASE = 'http://api.ticketlens.test';
|
|
7
7
|
export const DEFAULT_SITE_BASE = 'https://ticketlens.app';
|
|
8
8
|
|
|
9
9
|
// Matches localhost, 127.0.0.1, and any hostname ending in .test or .local,
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { existsSync } from 'node:fs';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
2
|
|
|
5
3
|
const TICKET_KEY_RE = /([A-Z][A-Z0-9]+-\d+)/g;
|
|
6
4
|
const SPAWN_OPTS = { encoding: 'utf8', timeout: 10_000 };
|
|
@@ -29,13 +27,13 @@ export function detectBase(execFn, cwd) {
|
|
|
29
27
|
* @param {object} [opts]
|
|
30
28
|
* @param {string} [opts.cwd] Working directory (default: process.cwd())
|
|
31
29
|
* @param {Function} [opts.execFn] spawnSync replacement (injectable for tests)
|
|
32
|
-
* @param {Function} [opts.fsCheck] existsSync replacement (injectable for tests)
|
|
33
30
|
* @returns {Array<{branch:string, base:string|null, tickets:string[], files:string[]}>|null}
|
|
34
31
|
* One-element array for the current branch, or null if not in a git repo / detached HEAD.
|
|
35
32
|
*/
|
|
36
|
-
export function scanCurrentBranch({ cwd = process.cwd(), execFn = spawnSync
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
export function scanCurrentBranch({ cwd = process.cwd(), execFn = spawnSync } = {}) {
|
|
34
|
+
// rev-parse fails outside a repo and searches upward like git itself, so it
|
|
35
|
+
// doubles as the repo check and works from subdirectories (backlog #45).
|
|
36
|
+
// GIT_DIR/GIT_WORK_TREE overrides are honored, matching real git semantics.
|
|
39
37
|
const branch = run(execFn, ['rev-parse', '--abbrev-ref', 'HEAD'], cwd)?.trim();
|
|
40
38
|
if (!branch || branch === 'HEAD') return null;
|
|
41
39
|
|
|
@@ -50,11 +50,6 @@ export function buildCompareUrl({ owner, repo, base, head, title, body, ticketKe
|
|
|
50
50
|
* @param {string} markdown - the exact markdown assemblePr() already produced
|
|
51
51
|
* @param {object} [opts]
|
|
52
52
|
* @returns {Promise<{ok: true, url: string} | {ok: false, reason: string, message: string}>}
|
|
53
|
-
*
|
|
54
|
-
* Known limitation (pre-existing in branch-scanner.mjs, not fixed here — see
|
|
55
|
-
* backlog): run from a repo subdirectory misreports 'no-branch' even on a
|
|
56
|
-
* real branch, since scanCurrentBranch only checks for .git at cwd exactly,
|
|
57
|
-
* not via git's own upward search. Run from the repo root.
|
|
58
53
|
*/
|
|
59
54
|
export async function openPr(ticketKey, markdown, {
|
|
60
55
|
cwd = process.cwd(),
|
|
@@ -17,13 +17,13 @@ const DEFAULT_MAX_TOKENS = 256;
|
|
|
17
17
|
* @param {number} [opts.timeoutMs]
|
|
18
18
|
* @returns {Promise<string>} Summary text
|
|
19
19
|
*/
|
|
20
|
-
export async function summarize({ brief, mode, credentials = null, cliToken = null, fetcher = globalThis.fetch, timeoutMs = 30_000, prompt, maxTokens, provider }) {
|
|
20
|
+
export async function summarize({ brief, mode, credentials = null, cliToken = null, fetcher = globalThis.fetch, timeoutMs = 30_000, prompt, maxTokens, provider, ticketKey }) {
|
|
21
21
|
const effectivePrompt = prompt ?? DEFAULT_PROMPT;
|
|
22
22
|
const effectiveMaxTokens = maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
23
23
|
if (mode === 'byok') {
|
|
24
24
|
return byok({ brief, credentials, fetcher, timeoutMs, prompt: effectivePrompt, maxTokens: effectiveMaxTokens, provider });
|
|
25
25
|
}
|
|
26
|
-
return cloud({ brief, cliToken, fetcher, timeoutMs });
|
|
26
|
+
return cloud({ brief, ticketKey, cliToken, fetcher, timeoutMs });
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
async function byok({ brief, credentials, fetcher, timeoutMs, prompt, maxTokens, provider }) {
|
|
@@ -137,8 +137,10 @@ async function callGroq({ brief, apiKey, fetcher, timeoutMs, prompt, maxTokens }
|
|
|
137
137
|
return data.choices[0].message.content;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
async function cloud({ brief, cliToken, fetcher, timeoutMs }) {
|
|
140
|
+
async function cloud({ brief, ticketKey, cliToken, fetcher, timeoutMs }) {
|
|
141
141
|
if (!cliToken) throw new Error('Not logged in. Run `ticketlens login` first.');
|
|
142
|
+
const payload = { brief };
|
|
143
|
+
if (ticketKey) payload.ticketKey = ticketKey;
|
|
142
144
|
const res = await fetcher(`${apiBase()}/v1/summarize`, {
|
|
143
145
|
method: 'POST',
|
|
144
146
|
signal: AbortSignal.timeout(timeoutMs),
|
|
@@ -146,7 +148,7 @@ async function cloud({ brief, cliToken, fetcher, timeoutMs }) {
|
|
|
146
148
|
'Content-Type': 'application/json',
|
|
147
149
|
'Authorization': `Bearer ${cliToken}`,
|
|
148
150
|
},
|
|
149
|
-
body: JSON.stringify(
|
|
151
|
+
body: JSON.stringify(payload),
|
|
150
152
|
});
|
|
151
153
|
|
|
152
154
|
if (!res.ok) {
|