@iloom/cli 0.9.0 → 0.9.2
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/LICENSE +1 -1
- package/README.md +21 -2
- package/dist/{ClaudeContextManager-X2Y72GRL.js → ClaudeContextManager-HR5JQKAI.js} +4 -4
- package/dist/{ClaudeService-7P32TTES.js → ClaudeService-TK7FMC2X.js} +3 -3
- package/dist/{GitHubService-ACZVNTJE.js → GitHubService-TGWJN4V4.js} +3 -3
- package/dist/{LoomLauncher-3I47SUPV.js → LoomLauncher-73NXL2CL.js} +4 -4
- package/dist/README.md +21 -2
- package/dist/{SettingsManager-QR7V2IW2.js → SettingsManager-AW3JTJHD.js} +2 -2
- package/dist/{build-IC4CJRMP.js → build-THZI572G.js} +6 -6
- package/dist/{chunk-Z6F5CUS6.js → chunk-3I4ONZRT.js} +3 -3
- package/dist/{chunk-THS5L54H.js → chunk-4CO6KG5S.js} +50 -3
- package/dist/chunk-4CO6KG5S.js.map +1 -0
- package/dist/{chunk-MZPRBNYC.js → chunk-6IIL5M2L.js} +2 -2
- package/dist/{chunk-2JPXGGP4.js → chunk-A7NJF73J.js} +2 -2
- package/dist/{chunk-H6ST2TGP.js → chunk-AR5QKYNE.js} +3 -3
- package/dist/{chunk-PL2FDYEK.js → chunk-CWRI4JC3.js} +2 -2
- package/dist/{chunk-I23OQB4Y.js → chunk-DGG2VY7B.js} +6 -5
- package/dist/chunk-DGG2VY7B.js.map +1 -0
- package/dist/{chunk-RNBIISBZ.js → chunk-FJDRTVJX.js} +50 -5
- package/dist/chunk-FJDRTVJX.js.map +1 -0
- package/dist/{chunk-NTTSUAVM.js → chunk-IZIYLYPK.js} +2 -2
- package/dist/{chunk-TGRK3CHF.js → chunk-KJTVU3HZ.js} +4 -4
- package/dist/{chunk-SC6X5EBG.js → chunk-KXGQYLFZ.js} +3 -3
- package/dist/{chunk-USSL2X4A.js → chunk-NUACL52E.js} +2 -2
- package/dist/{chunk-JT5LZRMI.js → chunk-NWMORW3U.js} +2 -2
- package/dist/{chunk-PVW6JE7E.js → chunk-OFDN5NKS.js} +4 -3
- package/dist/{chunk-PVW6JE7E.js.map → chunk-OFDN5NKS.js.map} +1 -1
- package/dist/{chunk-HZXBHMVM.js → chunk-R4YWBGY6.js} +3 -3
- package/dist/{chunk-XFEK2X2D.js → chunk-RI2YL6TK.js} +9 -3
- package/dist/chunk-RI2YL6TK.js.map +1 -0
- package/dist/{chunk-6Y3FTRJL.js → chunk-SOSQILHO.js} +102 -51
- package/dist/chunk-SOSQILHO.js.map +1 -0
- package/dist/{chunk-4GAJJUYS.js → chunk-TC7APDKU.js} +2 -2
- package/dist/{chunk-UDZCTLD6.js → chunk-ULSWCPQG.js} +3 -3
- package/dist/{chunk-5LVVQGB3.js → chunk-VPTAX5TR.js} +7 -7
- package/dist/chunk-VPTAX5TR.js.map +1 -0
- package/dist/{chunk-RD7OPXZK.js → chunk-W6DP5RVR.js} +3 -3
- package/dist/{chunk-XJHQVOT6.js → chunk-WHI5KEOX.js} +2 -2
- package/dist/{chunk-2HZX6AMR.js → chunk-YKFCCV6S.js} +2 -2
- package/dist/{chunk-OAVJR4PM.js → chunk-Z2TWEXR7.js} +2 -2
- package/dist/{cleanup-M6N7KV7E.js → cleanup-PJRIFFU4.js} +16 -16
- package/dist/cli.js +79 -62
- package/dist/cli.js.map +1 -1
- package/dist/{commit-ORHR53KW.js → commit-IVP3M4HG.js} +10 -9
- package/dist/commit-IVP3M4HG.js.map +1 -0
- package/dist/{compile-EOWJORKO.js → compile-R2J65HBQ.js} +6 -6
- package/dist/{contribute-4KCEOHSH.js → contribute-VDZXHK5Y.js} +4 -4
- package/dist/{dev-server-Q6M62ATG.js → dev-server-7F622OEO.js} +8 -8
- package/dist/{feedback-XRI7SGYX.js → feedback-E7VET7CL.js} +6 -6
- package/dist/{git-W3XUIFTR.js → git-2QDQ2X2S.js} +3 -3
- package/dist/{ignite-3FHQY23X.js → ignite-IW35CDBD.js} +10 -10
- package/dist/index.d.ts +18 -0
- package/dist/index.js +14 -6
- package/dist/index.js.map +1 -1
- package/dist/{init-ALYWKNWG.js → init-676DHF6R.js} +5 -5
- package/dist/issues-PJSOLOBJ.js +138 -0
- package/dist/issues-PJSOLOBJ.js.map +1 -0
- package/dist/{lint-IHUH45OC.js → lint-CJM7BAIM.js} +6 -6
- package/dist/mcp/issue-management-server.js +5 -4
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/{open-KWOV2OFO.js → open-544H7JF5.js} +8 -8
- package/dist/{plan-P6MXL7AU.js → plan-Q7ELXDLC.js} +12 -12
- package/dist/prompts/init-prompt.txt +39 -21
- package/dist/{rebase-AJOJOZUG.js → rebase-YND35CIE.js} +5 -5
- package/dist/{recap-GKJXMDXW.js → recap-3W7COH7D.js} +5 -5
- package/dist/{run-QEUVZF7J.js → run-QUXJKDQQ.js} +8 -8
- package/dist/schema/settings.schema.json +15 -0
- package/dist/{shell-DAAVG4YN.js → shell-QGECBLST.js} +5 -5
- package/dist/{summary-WNEYCO4S.js → summary-G2T4452H.js} +9 -9
- package/dist/{test-5GPWWO3P.js → test-EA5NQFDC.js} +6 -6
- package/dist/{test-git-EJUKDB7F.js → test-git-M7LSLEFL.js} +3 -3
- package/dist/{test-prefix-23TOBUXY.js → test-prefix-64NAAUON.js} +3 -3
- package/dist/{test-webserver-CKROHFBQ.js → test-webserver-OK6Z5FJM.js} +5 -5
- package/dist/{vscode-6TOLFCI2.js → vscode-AR5NNXXI.js} +5 -5
- package/package.json +1 -1
- package/dist/chunk-5LVVQGB3.js.map +0 -1
- package/dist/chunk-6Y3FTRJL.js.map +0 -1
- package/dist/chunk-I23OQB4Y.js.map +0 -1
- package/dist/chunk-RNBIISBZ.js.map +0 -1
- package/dist/chunk-THS5L54H.js.map +0 -1
- package/dist/chunk-XFEK2X2D.js.map +0 -1
- package/dist/commit-ORHR53KW.js.map +0 -1
- /package/dist/{ClaudeContextManager-X2Y72GRL.js.map → ClaudeContextManager-HR5JQKAI.js.map} +0 -0
- /package/dist/{ClaudeService-7P32TTES.js.map → ClaudeService-TK7FMC2X.js.map} +0 -0
- /package/dist/{GitHubService-ACZVNTJE.js.map → GitHubService-TGWJN4V4.js.map} +0 -0
- /package/dist/{LoomLauncher-3I47SUPV.js.map → LoomLauncher-73NXL2CL.js.map} +0 -0
- /package/dist/{SettingsManager-QR7V2IW2.js.map → SettingsManager-AW3JTJHD.js.map} +0 -0
- /package/dist/{build-IC4CJRMP.js.map → build-THZI572G.js.map} +0 -0
- /package/dist/{chunk-Z6F5CUS6.js.map → chunk-3I4ONZRT.js.map} +0 -0
- /package/dist/{chunk-MZPRBNYC.js.map → chunk-6IIL5M2L.js.map} +0 -0
- /package/dist/{chunk-2JPXGGP4.js.map → chunk-A7NJF73J.js.map} +0 -0
- /package/dist/{chunk-H6ST2TGP.js.map → chunk-AR5QKYNE.js.map} +0 -0
- /package/dist/{chunk-PL2FDYEK.js.map → chunk-CWRI4JC3.js.map} +0 -0
- /package/dist/{chunk-NTTSUAVM.js.map → chunk-IZIYLYPK.js.map} +0 -0
- /package/dist/{chunk-TGRK3CHF.js.map → chunk-KJTVU3HZ.js.map} +0 -0
- /package/dist/{chunk-SC6X5EBG.js.map → chunk-KXGQYLFZ.js.map} +0 -0
- /package/dist/{chunk-USSL2X4A.js.map → chunk-NUACL52E.js.map} +0 -0
- /package/dist/{chunk-JT5LZRMI.js.map → chunk-NWMORW3U.js.map} +0 -0
- /package/dist/{chunk-HZXBHMVM.js.map → chunk-R4YWBGY6.js.map} +0 -0
- /package/dist/{chunk-4GAJJUYS.js.map → chunk-TC7APDKU.js.map} +0 -0
- /package/dist/{chunk-UDZCTLD6.js.map → chunk-ULSWCPQG.js.map} +0 -0
- /package/dist/{chunk-RD7OPXZK.js.map → chunk-W6DP5RVR.js.map} +0 -0
- /package/dist/{chunk-XJHQVOT6.js.map → chunk-WHI5KEOX.js.map} +0 -0
- /package/dist/{chunk-2HZX6AMR.js.map → chunk-YKFCCV6S.js.map} +0 -0
- /package/dist/{chunk-OAVJR4PM.js.map → chunk-Z2TWEXR7.js.map} +0 -0
- /package/dist/{cleanup-M6N7KV7E.js.map → cleanup-PJRIFFU4.js.map} +0 -0
- /package/dist/{compile-EOWJORKO.js.map → compile-R2J65HBQ.js.map} +0 -0
- /package/dist/{contribute-4KCEOHSH.js.map → contribute-VDZXHK5Y.js.map} +0 -0
- /package/dist/{dev-server-Q6M62ATG.js.map → dev-server-7F622OEO.js.map} +0 -0
- /package/dist/{feedback-XRI7SGYX.js.map → feedback-E7VET7CL.js.map} +0 -0
- /package/dist/{git-W3XUIFTR.js.map → git-2QDQ2X2S.js.map} +0 -0
- /package/dist/{ignite-3FHQY23X.js.map → ignite-IW35CDBD.js.map} +0 -0
- /package/dist/{init-ALYWKNWG.js.map → init-676DHF6R.js.map} +0 -0
- /package/dist/{lint-IHUH45OC.js.map → lint-CJM7BAIM.js.map} +0 -0
- /package/dist/{open-KWOV2OFO.js.map → open-544H7JF5.js.map} +0 -0
- /package/dist/{plan-P6MXL7AU.js.map → plan-Q7ELXDLC.js.map} +0 -0
- /package/dist/{rebase-AJOJOZUG.js.map → rebase-YND35CIE.js.map} +0 -0
- /package/dist/{recap-GKJXMDXW.js.map → recap-3W7COH7D.js.map} +0 -0
- /package/dist/{run-QEUVZF7J.js.map → run-QUXJKDQQ.js.map} +0 -0
- /package/dist/{shell-DAAVG4YN.js.map → shell-QGECBLST.js.map} +0 -0
- /package/dist/{summary-WNEYCO4S.js.map → summary-G2T4452H.js.map} +0 -0
- /package/dist/{test-5GPWWO3P.js.map → test-EA5NQFDC.js.map} +0 -0
- /package/dist/{test-git-EJUKDB7F.js.map → test-git-M7LSLEFL.js.map} +0 -0
- /package/dist/{test-prefix-23TOBUXY.js.map → test-prefix-64NAAUON.js.map} +0 -0
- /package/dist/{test-webserver-CKROHFBQ.js.map → test-webserver-OK6Z5FJM.js.map} +0 -0
- /package/dist/{vscode-6TOLFCI2.js.map → vscode-AR5NNXXI.js.map} +0 -0
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
} from "./chunk-BYUMEDDD.js";
|
|
5
5
|
import {
|
|
6
6
|
ShellCompletion
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NWMORW3U.js";
|
|
8
8
|
import {
|
|
9
9
|
FirstRunManager
|
|
10
10
|
} from "./chunk-Q7POFB5Q.js";
|
|
11
11
|
import {
|
|
12
12
|
AgentManager
|
|
13
13
|
} from "./chunk-B7U6OKUR.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-TC7APDKU.js";
|
|
15
15
|
import {
|
|
16
16
|
parseGitRemotes
|
|
17
17
|
} from "./chunk-FXDYIV3K.js";
|
|
@@ -21,8 +21,8 @@ import {
|
|
|
21
21
|
import {
|
|
22
22
|
getRepoRoot,
|
|
23
23
|
isFileGitignored
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-AR5QKYNE.js";
|
|
25
|
+
import "./chunk-RI2YL6TK.js";
|
|
26
26
|
import "./chunk-KBEIQP4G.js";
|
|
27
27
|
import "./chunk-7JDMYTFZ.js";
|
|
28
28
|
import {
|
|
@@ -425,4 +425,4 @@ var InitCommand = class {
|
|
|
425
425
|
export {
|
|
426
426
|
InitCommand
|
|
427
427
|
};
|
|
428
|
-
//# sourceMappingURL=init-
|
|
428
|
+
//# sourceMappingURL=init-676DHF6R.js.map
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
IssueTrackerFactory
|
|
4
|
+
} from "./chunk-KXGQYLFZ.js";
|
|
5
|
+
import {
|
|
6
|
+
fetchLinearIssueList
|
|
7
|
+
} from "./chunk-FJDRTVJX.js";
|
|
8
|
+
import {
|
|
9
|
+
findMainWorktreePathWithSettings
|
|
10
|
+
} from "./chunk-AR5QKYNE.js";
|
|
11
|
+
import {
|
|
12
|
+
SettingsManager
|
|
13
|
+
} from "./chunk-RI2YL6TK.js";
|
|
14
|
+
import "./chunk-KBEIQP4G.js";
|
|
15
|
+
import "./chunk-OFDN5NKS.js";
|
|
16
|
+
import {
|
|
17
|
+
fetchGitHubIssueList,
|
|
18
|
+
fetchGitHubPRList
|
|
19
|
+
} from "./chunk-4CO6KG5S.js";
|
|
20
|
+
import "./chunk-7JDMYTFZ.js";
|
|
21
|
+
import {
|
|
22
|
+
getLogger
|
|
23
|
+
} from "./chunk-6MLEBAYZ.js";
|
|
24
|
+
import "./chunk-VT4PDUYT.js";
|
|
25
|
+
|
|
26
|
+
// src/commands/issues.ts
|
|
27
|
+
import os from "os";
|
|
28
|
+
import path from "path";
|
|
29
|
+
import fs from "fs-extra";
|
|
30
|
+
import crypto from "crypto";
|
|
31
|
+
var CACHE_TTL_MS = 2 * 60 * 1e3;
|
|
32
|
+
var CACHE_DIR = path.join(os.homedir(), ".config", "iloom-ai", "cache");
|
|
33
|
+
function getCacheFilePath(projectPath, provider, limit) {
|
|
34
|
+
const hash = crypto.createHash("md5").update(`${projectPath}:${provider}:${limit}`).digest("hex").slice(0, 12);
|
|
35
|
+
return path.join(CACHE_DIR, `issues-${hash}.json`);
|
|
36
|
+
}
|
|
37
|
+
async function readCacheFile(cacheFilePath) {
|
|
38
|
+
try {
|
|
39
|
+
if (!fs.existsSync(cacheFilePath)) return null;
|
|
40
|
+
const content = await fs.readFile(cacheFilePath, "utf8");
|
|
41
|
+
const cache = JSON.parse(content);
|
|
42
|
+
if (Date.now() - cache.timestamp < CACHE_TTL_MS) return cache.data;
|
|
43
|
+
return null;
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function writeCacheFile(cacheFilePath, data, projectPath, provider) {
|
|
49
|
+
try {
|
|
50
|
+
await fs.ensureDir(CACHE_DIR);
|
|
51
|
+
const cache = { timestamp: Date.now(), projectPath, provider, data };
|
|
52
|
+
await fs.writeFile(cacheFilePath, JSON.stringify(cache, null, 2), "utf8");
|
|
53
|
+
} catch {
|
|
54
|
+
getLogger().debug(`Failed to write issues cache to ${cacheFilePath}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
var IssuesCommand = class {
|
|
58
|
+
constructor(settingsManager) {
|
|
59
|
+
this.settingsManager = settingsManager ?? new SettingsManager();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Execute the issues command
|
|
63
|
+
* @param options - Command options
|
|
64
|
+
* @returns Array of issue list items
|
|
65
|
+
*/
|
|
66
|
+
async execute(options) {
|
|
67
|
+
var _a, _b, _c, _d;
|
|
68
|
+
const logger = getLogger();
|
|
69
|
+
const limit = (options == null ? void 0 : options.limit) ?? 100;
|
|
70
|
+
let resolvedProjectPath;
|
|
71
|
+
if (options == null ? void 0 : options.projectPath) {
|
|
72
|
+
resolvedProjectPath = options.projectPath;
|
|
73
|
+
} else {
|
|
74
|
+
try {
|
|
75
|
+
resolvedProjectPath = await findMainWorktreePathWithSettings();
|
|
76
|
+
} catch {
|
|
77
|
+
logger.debug("Failed to resolve worktree path, falling back to cwd");
|
|
78
|
+
resolvedProjectPath = process.cwd();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const settings = await this.settingsManager.loadSettings(resolvedProjectPath);
|
|
82
|
+
const provider = IssueTrackerFactory.getProviderName(settings);
|
|
83
|
+
const cacheFilePath = getCacheFilePath(resolvedProjectPath, provider, limit);
|
|
84
|
+
const cached = await readCacheFile(cacheFilePath);
|
|
85
|
+
if (cached !== null) {
|
|
86
|
+
logger.debug(`Returning cached issues (${cached.length} items)`);
|
|
87
|
+
return cached.map((item) => ({ type: "issue", ...item }));
|
|
88
|
+
}
|
|
89
|
+
let results;
|
|
90
|
+
if (provider === "github") {
|
|
91
|
+
results = await fetchGitHubIssueList({
|
|
92
|
+
limit,
|
|
93
|
+
cwd: resolvedProjectPath
|
|
94
|
+
});
|
|
95
|
+
} else if (provider === "linear") {
|
|
96
|
+
const teamId = (_b = (_a = settings.issueManagement) == null ? void 0 : _a.linear) == null ? void 0 : _b.teamId;
|
|
97
|
+
if (!teamId) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
"Linear team ID not configured. Set issueManagement.linear.teamId in your settings.json."
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
const apiToken = ((_d = (_c = settings.issueManagement) == null ? void 0 : _c.linear) == null ? void 0 : _d.apiToken) ?? process.env.LINEAR_API_TOKEN;
|
|
103
|
+
results = await fetchLinearIssueList(teamId, {
|
|
104
|
+
limit,
|
|
105
|
+
...apiToken ? { apiToken } : {}
|
|
106
|
+
});
|
|
107
|
+
} else {
|
|
108
|
+
throw new Error(`Unsupported issue tracker provider: ${provider}`);
|
|
109
|
+
}
|
|
110
|
+
results.forEach((item) => {
|
|
111
|
+
item.type = "issue";
|
|
112
|
+
});
|
|
113
|
+
try {
|
|
114
|
+
const prs = await fetchGitHubPRList({
|
|
115
|
+
limit,
|
|
116
|
+
cwd: resolvedProjectPath
|
|
117
|
+
});
|
|
118
|
+
const prItems = prs.map((pr) => ({ ...pr, type: "pr" }));
|
|
119
|
+
results = [...results, ...prItems];
|
|
120
|
+
} catch (error) {
|
|
121
|
+
const stderr = error.stderr ?? "";
|
|
122
|
+
const isExpectedError = error instanceof Error && (error.message.includes("not logged in") || error.message.includes("auth login") || error.message.includes("rate limit") || error.message.includes("ETIMEDOUT") || error.message.includes("ECONNREFUSED") || stderr.includes("not logged in") || stderr.includes("rate limit"));
|
|
123
|
+
if (isExpectedError) {
|
|
124
|
+
logger.warn(`PR fetch failed (non-fatal), continuing with issues only: ${error.message}`);
|
|
125
|
+
} else {
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
results.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
130
|
+
results = results.slice(0, limit);
|
|
131
|
+
await writeCacheFile(cacheFilePath, results, resolvedProjectPath, provider);
|
|
132
|
+
return results;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
export {
|
|
136
|
+
IssuesCommand
|
|
137
|
+
};
|
|
138
|
+
//# sourceMappingURL=issues-PJSOLOBJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/issues.ts"],"sourcesContent":["import os from 'os'\nimport path from 'path'\nimport fs from 'fs-extra'\nimport crypto from 'crypto'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { IssueTrackerFactory } from '../lib/IssueTrackerFactory.js'\nimport { findMainWorktreePathWithSettings } from '../utils/git.js'\nimport { fetchGitHubIssueList, fetchGitHubPRList } from '../utils/github.js'\nimport { fetchLinearIssueList } from '../utils/linear.js'\nimport { getLogger } from '../utils/logger-context.js'\n\n/**\n * Unified output interface for issues from any provider\n */\nexport interface IssueListItem {\n id: string\n title: string\n updatedAt: string\n url: string\n state: string\n type?: 'issue' | 'pr'\n}\n\n/**\n * File-based cache structure (follows UpdateNotifier pattern)\n */\ninterface IssuesCacheFile {\n timestamp: number // Date.now() when cached\n projectPath: string // for verification\n provider: string // 'github' | 'linear'\n data: IssueListItem[]\n}\n\n// Cache configuration\nconst CACHE_TTL_MS = 2 * 60 * 1000 // 2 minutes\nconst CACHE_DIR = path.join(os.homedir(), '.config', 'iloom-ai', 'cache')\n\n/**\n * Generate a deterministic cache file path from project path + provider\n */\nfunction getCacheFilePath(projectPath: string, provider: string, limit: number): string {\n const hash = crypto.createHash('md5').update(`${projectPath}:${provider}:${limit}`).digest('hex').slice(0, 12)\n return path.join(CACHE_DIR, `issues-${hash}.json`)\n}\n\n/**\n * Read cache file, return null if missing/expired/corrupted\n * Follows UpdateNotifier.getCachedCheck pattern\n */\nasync function readCacheFile(cacheFilePath: string): Promise<IssueListItem[] | null> {\n try {\n if (!fs.existsSync(cacheFilePath)) return null\n const content = await fs.readFile(cacheFilePath, 'utf8')\n const cache = JSON.parse(content) as IssuesCacheFile\n if (Date.now() - cache.timestamp < CACHE_TTL_MS) return cache.data\n return null // expired\n } catch {\n return null // corrupted or unreadable, treat as cache miss\n }\n}\n\n/**\n * Write cache file following UpdateNotifier.saveCacheFile pattern\n */\nasync function writeCacheFile(\n cacheFilePath: string,\n data: IssueListItem[],\n projectPath: string,\n provider: string,\n): Promise<void> {\n try {\n await fs.ensureDir(CACHE_DIR)\n const cache: IssuesCacheFile = { timestamp: Date.now(), projectPath, provider, data }\n await fs.writeFile(cacheFilePath, JSON.stringify(cache, null, 2), 'utf8')\n } catch {\n // Cache write failure is non-fatal, just log debug\n getLogger().debug(`Failed to write issues cache to ${cacheFilePath}`)\n }\n}\n\nexport interface IssuesCommandOptions {\n projectPath?: string | undefined\n limit?: number | undefined\n}\n\n/**\n * IssuesCommand: List open issues from the configured issue tracker\n *\n * Returns JSON array of issues. Uses file-based caching with ~2 minute TTL.\n * Follows the ProjectsCommand pattern for structure.\n */\nexport class IssuesCommand {\n private readonly settingsManager: SettingsManager\n\n constructor(settingsManager?: SettingsManager) {\n this.settingsManager = settingsManager ?? new SettingsManager()\n }\n\n /**\n * Execute the issues command\n * @param options - Command options\n * @returns Array of issue list items\n */\n async execute(options?: IssuesCommandOptions): Promise<IssueListItem[]> {\n const logger = getLogger()\n const limit = options?.limit ?? 100\n\n // 1. Resolve project root\n let resolvedProjectPath: string\n if (options?.projectPath) {\n resolvedProjectPath = options.projectPath\n } else {\n try {\n resolvedProjectPath = await findMainWorktreePathWithSettings()\n } catch {\n logger.debug('Failed to resolve worktree path, falling back to cwd')\n resolvedProjectPath = process.cwd()\n }\n }\n\n // 2. Load settings from resolved root\n const settings = await this.settingsManager.loadSettings(resolvedProjectPath)\n\n // 3. Determine provider\n const provider = IssueTrackerFactory.getProviderName(settings)\n\n // 4. Check file-based cache\n const cacheFilePath = getCacheFilePath(resolvedProjectPath, provider, limit)\n const cached = await readCacheFile(cacheFilePath)\n if (cached !== null) {\n logger.debug(`Returning cached issues (${cached.length} items)`)\n // Backfill type field for cache entries from before PR support was added\n return cached.map(item => ({ type: 'issue' as const, ...item }))\n }\n\n // 5. Fetch issues based on provider\n let results: IssueListItem[]\n\n if (provider === 'github') {\n results = await fetchGitHubIssueList({\n limit,\n cwd: resolvedProjectPath,\n })\n } else if (provider === 'linear') {\n const teamId = settings.issueManagement?.linear?.teamId\n if (!teamId) {\n throw new Error(\n 'Linear team ID not configured. Set issueManagement.linear.teamId in your settings.json.',\n )\n }\n const apiToken = settings.issueManagement?.linear?.apiToken ?? process.env.LINEAR_API_TOKEN\n results = await fetchLinearIssueList(teamId, {\n limit,\n ...(apiToken ? { apiToken } : {}),\n })\n } else {\n throw new Error(`Unsupported issue tracker provider: ${provider}`)\n }\n\n // Tag issues with type\n results.forEach(item => { item.type = 'issue' })\n\n // 6. Fetch PRs from GitHub (PRs are a GitHub concept regardless of issue tracker)\n try {\n const prs = await fetchGitHubPRList({\n limit,\n cwd: resolvedProjectPath,\n })\n const prItems: IssueListItem[] = prs.map(pr => ({ ...pr, type: 'pr' as const }))\n results = [...results, ...prItems]\n } catch (error) {\n // Only catch expected, non-fatal errors from gh CLI\n // Per CLAUDE.md: \"DO NOT SWALLOW ERRORS\" -- must check specifically\n const stderr = (error as NodeJS.ErrnoException & { stderr?: string }).stderr ?? ''\n const isExpectedError = error instanceof Error && (\n error.message.includes('not logged in') ||\n error.message.includes('auth login') ||\n error.message.includes('rate limit') ||\n error.message.includes('ETIMEDOUT') ||\n error.message.includes('ECONNREFUSED') ||\n stderr.includes('not logged in') ||\n stderr.includes('rate limit')\n )\n if (isExpectedError) {\n logger.warn(`PR fetch failed (non-fatal), continuing with issues only: ${error.message}`)\n } else {\n throw error // Re-throw unexpected errors -- do not swallow\n }\n }\n\n // 7. Sort by updatedAt descending and apply limit\n results.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime())\n results = results.slice(0, limit)\n\n // 8. Write results to cache file\n await writeCacheFile(cacheFilePath, results, resolvedProjectPath, provider)\n\n return results\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ScriptCommandBase
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-KJTVU3HZ.js";
|
|
5
|
+
import "./chunk-YKFCCV6S.js";
|
|
6
6
|
import "./chunk-4LKGCFGG.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-TC7APDKU.js";
|
|
8
8
|
import "./chunk-VOGGLPG5.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-AR5QKYNE.js";
|
|
10
|
+
import "./chunk-RI2YL6TK.js";
|
|
11
11
|
import "./chunk-KBEIQP4G.js";
|
|
12
12
|
import "./chunk-6MLEBAYZ.js";
|
|
13
13
|
import "./chunk-VT4PDUYT.js";
|
|
@@ -24,4 +24,4 @@ var LintCommand = class extends ScriptCommandBase {
|
|
|
24
24
|
export {
|
|
25
25
|
LintCommand
|
|
26
26
|
};
|
|
27
|
-
//# sourceMappingURL=lint-
|
|
27
|
+
//# sourceMappingURL=lint-CJM7BAIM.js.map
|
|
@@ -988,8 +988,9 @@ function getLinearApiToken() {
|
|
|
988
988
|
}
|
|
989
989
|
return token;
|
|
990
990
|
}
|
|
991
|
-
function createLinearClient() {
|
|
992
|
-
|
|
991
|
+
function createLinearClient(apiToken) {
|
|
992
|
+
const token = apiToken ?? getLinearApiToken();
|
|
993
|
+
return new LinearClient({ apiKey: token });
|
|
993
994
|
}
|
|
994
995
|
function handleLinearError(error, context) {
|
|
995
996
|
logger.debug(`${context}: Handling error`, { error });
|
|
@@ -1208,10 +1209,10 @@ async function fetchLinearIssueComments(identifier) {
|
|
|
1208
1209
|
handleLinearError(error, "fetchLinearIssueComments");
|
|
1209
1210
|
}
|
|
1210
1211
|
}
|
|
1211
|
-
async function getLinearChildIssues(identifier) {
|
|
1212
|
+
async function getLinearChildIssues(identifier, options) {
|
|
1212
1213
|
try {
|
|
1213
1214
|
logger.debug(`Fetching child issues for Linear issue: ${identifier}`);
|
|
1214
|
-
const client = createLinearClient();
|
|
1215
|
+
const client = createLinearClient(options == null ? void 0 : options.apiToken);
|
|
1215
1216
|
const issue = await client.issue(identifier);
|
|
1216
1217
|
if (!issue) {
|
|
1217
1218
|
throw new LinearServiceError("NOT_FOUND", `Linear issue ${identifier} not found`);
|