codiedev 0.3.4 → 0.3.6
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/cli.js +13 -0
- package/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.js +263 -0
- package/dist/commands/reverseTicket.d.ts +1 -0
- package/dist/commands/reverseTicket.js +150 -0
- package/dist/connect.js +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -22,6 +22,8 @@ const ping_1 = require("./commands/ping");
|
|
|
22
22
|
const inbox_1 = require("./commands/inbox");
|
|
23
23
|
const note_1 = require("./commands/note");
|
|
24
24
|
const promote_1 = require("./commands/promote");
|
|
25
|
+
const reverseTicket_1 = require("./commands/reverseTicket");
|
|
26
|
+
const doctor_1 = require("./commands/doctor");
|
|
25
27
|
const HELP = `
|
|
26
28
|
CodieDev CLI
|
|
27
29
|
|
|
@@ -31,6 +33,7 @@ CodieDev CLI
|
|
|
31
33
|
|
|
32
34
|
Connect:
|
|
33
35
|
codiedev connect Link Claude Code / Codex to your org
|
|
36
|
+
codiedev doctor Verify your setup after connecting
|
|
34
37
|
|
|
35
38
|
Artifacts:
|
|
36
39
|
codiedev push <file.md> Author or update an artifact
|
|
@@ -38,6 +41,8 @@ Artifacts:
|
|
|
38
41
|
Fetch an artifact (stdout by default)
|
|
39
42
|
codiedev promote <artifact-id> Promote an auto-extracted artifact
|
|
40
43
|
to an authored one
|
|
44
|
+
codiedev reverse-ticket <pr-url> Generate a Jira ticket from a merged PR
|
|
45
|
+
(auto-matches spec + thread + transcript)
|
|
41
46
|
|
|
42
47
|
Messaging:
|
|
43
48
|
codiedev ping <user> "<msg>" [--with <key>]
|
|
@@ -311,6 +316,10 @@ async function main() {
|
|
|
311
316
|
case "connect":
|
|
312
317
|
await (0, connect_1.runConnect)();
|
|
313
318
|
return;
|
|
319
|
+
case "doctor":
|
|
320
|
+
case "verify":
|
|
321
|
+
await (0, doctor_1.runDoctor)(rest);
|
|
322
|
+
return;
|
|
314
323
|
case "push":
|
|
315
324
|
await (0, push_1.runPush)(rest);
|
|
316
325
|
return;
|
|
@@ -339,6 +348,10 @@ async function main() {
|
|
|
339
348
|
case "promote":
|
|
340
349
|
await (0, promote_1.runPromote)(rest);
|
|
341
350
|
return;
|
|
351
|
+
case "reverse-ticket":
|
|
352
|
+
case "reverseTicket":
|
|
353
|
+
await (0, reverseTicket_1.runReverseTicket)(rest);
|
|
354
|
+
return;
|
|
342
355
|
default:
|
|
343
356
|
console.error(`Unknown command: ${command}`);
|
|
344
357
|
console.error(HELP);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runDoctor(_args: string[]): Promise<void>;
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runDoctor = runDoctor;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
const child_process_1 = require("child_process");
|
|
41
|
+
const shared_1 = require("./shared");
|
|
42
|
+
const utils_1 = require("../utils");
|
|
43
|
+
const CLAUDE_SETTINGS_PATH = path.join(os.homedir(), ".claude", "settings.json");
|
|
44
|
+
const CLAUDE_INSTRUCTIONS_PATH = path.join(os.homedir(), ".claude", "CLAUDE.md");
|
|
45
|
+
const CODEX_HOOKS_PATH = path.join(os.homedir(), ".codex", "hooks.json");
|
|
46
|
+
const CODEX_INSTRUCTIONS_PATH = path.join(os.homedir(), ".codex", "AGENTS.md");
|
|
47
|
+
function symbol(status) {
|
|
48
|
+
if (status === "pass")
|
|
49
|
+
return "✓";
|
|
50
|
+
if (status === "warn")
|
|
51
|
+
return "!";
|
|
52
|
+
return "✗";
|
|
53
|
+
}
|
|
54
|
+
function claudeCodeInstalled() {
|
|
55
|
+
return fs.existsSync(path.join(os.homedir(), ".claude"));
|
|
56
|
+
}
|
|
57
|
+
function codexInstalled() {
|
|
58
|
+
return fs.existsSync(path.join(os.homedir(), ".codex"));
|
|
59
|
+
}
|
|
60
|
+
function hasCodiedevHook(settingsPath, hookKey) {
|
|
61
|
+
try {
|
|
62
|
+
if (!fs.existsSync(settingsPath))
|
|
63
|
+
return false;
|
|
64
|
+
const raw = fs.readFileSync(settingsPath, "utf8");
|
|
65
|
+
const parsed = JSON.parse(raw);
|
|
66
|
+
const hooks = parsed.hooks?.[hookKey];
|
|
67
|
+
if (!Array.isArray(hooks))
|
|
68
|
+
return false;
|
|
69
|
+
return hooks.some((h) => {
|
|
70
|
+
const inner = h.hooks;
|
|
71
|
+
if (!Array.isArray(inner))
|
|
72
|
+
return false;
|
|
73
|
+
return inner.some((x) => (x.command ?? "").includes("codiedev-hook"));
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function hasCodiedevInstructions(instructionsPath) {
|
|
81
|
+
try {
|
|
82
|
+
if (!fs.existsSync(instructionsPath))
|
|
83
|
+
return false;
|
|
84
|
+
const raw = fs.readFileSync(instructionsPath, "utf8");
|
|
85
|
+
return raw.includes("codiedev-cli:begin");
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function hasGhCli() {
|
|
92
|
+
try {
|
|
93
|
+
(0, child_process_1.execSync)("gh --version", { stdio: ["pipe", "pipe", "pipe"] });
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function runDoctor(_args) {
|
|
101
|
+
const checks = [];
|
|
102
|
+
console.log("\nCodieDev doctor — checking your setup…\n");
|
|
103
|
+
// 1. Config file
|
|
104
|
+
const config = (0, utils_1.readConfig)();
|
|
105
|
+
if (!config) {
|
|
106
|
+
checks.push({
|
|
107
|
+
name: "CodieDev config (~/.codiedev/config.json)",
|
|
108
|
+
status: "fail",
|
|
109
|
+
detail: "Not found. Run `codiedev connect` first.",
|
|
110
|
+
});
|
|
111
|
+
report(checks);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
checks.push({
|
|
115
|
+
name: "CodieDev config",
|
|
116
|
+
status: "pass",
|
|
117
|
+
detail: `connected to ${config.companyName}`,
|
|
118
|
+
});
|
|
119
|
+
// 2. Token still valid + backend reachable (re-validate)
|
|
120
|
+
try {
|
|
121
|
+
const res = await fetch(`${config.backendUrl}/api/cli/validateToken`, {
|
|
122
|
+
method: "POST",
|
|
123
|
+
headers: { "Content-Type": "application/json" },
|
|
124
|
+
body: JSON.stringify({ token: config.token }),
|
|
125
|
+
});
|
|
126
|
+
if (res.ok) {
|
|
127
|
+
checks.push({
|
|
128
|
+
name: "Backend reachable + token valid",
|
|
129
|
+
status: "pass",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
checks.push({
|
|
134
|
+
name: "Backend reachable + token valid",
|
|
135
|
+
status: "fail",
|
|
136
|
+
detail: `HTTP ${res.status} — run \`codiedev connect\` with a fresh token`,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
checks.push({
|
|
142
|
+
name: "Backend reachable + token valid",
|
|
143
|
+
status: "fail",
|
|
144
|
+
detail: err.message,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
// 3. Authenticated endpoint smoke test (inbox query)
|
|
148
|
+
try {
|
|
149
|
+
await (0, shared_1.apiRequest)("GET", "/api/cli/inbox", {
|
|
150
|
+
config,
|
|
151
|
+
query: { limit: 1 },
|
|
152
|
+
});
|
|
153
|
+
checks.push({
|
|
154
|
+
name: "Authenticated endpoint smoke test (`codiedev inbox`)",
|
|
155
|
+
status: "pass",
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
checks.push({
|
|
160
|
+
name: "Authenticated endpoint smoke test",
|
|
161
|
+
status: "fail",
|
|
162
|
+
detail: err.message,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// 4. Tracked repos
|
|
166
|
+
const repoCount = config.repos?.length ?? 0;
|
|
167
|
+
checks.push({
|
|
168
|
+
name: "Tracked repos",
|
|
169
|
+
status: repoCount > 0 ? "pass" : "warn",
|
|
170
|
+
detail: repoCount > 0
|
|
171
|
+
? `${repoCount} repo${repoCount === 1 ? "" : "s"}`
|
|
172
|
+
: "0 — link repos in the portal so sessions get captured",
|
|
173
|
+
});
|
|
174
|
+
// 5. Claude Code setup (if present)
|
|
175
|
+
if (claudeCodeInstalled()) {
|
|
176
|
+
checks.push({
|
|
177
|
+
name: "Claude Code detected",
|
|
178
|
+
status: "pass",
|
|
179
|
+
detail: "~/.claude",
|
|
180
|
+
});
|
|
181
|
+
checks.push({
|
|
182
|
+
name: "Claude Code SessionEnd hook",
|
|
183
|
+
status: hasCodiedevHook(CLAUDE_SETTINGS_PATH, "SessionEnd") ? "pass" : "fail",
|
|
184
|
+
detail: hasCodiedevHook(CLAUDE_SETTINGS_PATH, "SessionEnd")
|
|
185
|
+
? "~/.claude/settings.json"
|
|
186
|
+
: "missing — re-run `codiedev connect`",
|
|
187
|
+
});
|
|
188
|
+
checks.push({
|
|
189
|
+
name: "Claude Code agent instructions",
|
|
190
|
+
status: hasCodiedevInstructions(CLAUDE_INSTRUCTIONS_PATH) ? "pass" : "fail",
|
|
191
|
+
detail: hasCodiedevInstructions(CLAUDE_INSTRUCTIONS_PATH)
|
|
192
|
+
? "~/.claude/CLAUDE.md"
|
|
193
|
+
: "missing — re-run `codiedev connect`",
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
checks.push({
|
|
198
|
+
name: "Claude Code",
|
|
199
|
+
status: "warn",
|
|
200
|
+
detail: "not installed on this machine",
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
// 6. Codex setup (if present)
|
|
204
|
+
if (codexInstalled()) {
|
|
205
|
+
checks.push({
|
|
206
|
+
name: "Codex detected",
|
|
207
|
+
status: "pass",
|
|
208
|
+
detail: "~/.codex",
|
|
209
|
+
});
|
|
210
|
+
checks.push({
|
|
211
|
+
name: "Codex Stop hook",
|
|
212
|
+
status: hasCodiedevHook(CODEX_HOOKS_PATH, "Stop") ? "pass" : "fail",
|
|
213
|
+
detail: hasCodiedevHook(CODEX_HOOKS_PATH, "Stop")
|
|
214
|
+
? "~/.codex/hooks.json"
|
|
215
|
+
: "missing — re-run `codiedev connect`",
|
|
216
|
+
});
|
|
217
|
+
checks.push({
|
|
218
|
+
name: "Codex agent instructions",
|
|
219
|
+
status: hasCodiedevInstructions(CODEX_INSTRUCTIONS_PATH) ? "pass" : "fail",
|
|
220
|
+
detail: hasCodiedevInstructions(CODEX_INSTRUCTIONS_PATH)
|
|
221
|
+
? "~/.codex/AGENTS.md"
|
|
222
|
+
: "missing — re-run `codiedev connect`",
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
checks.push({
|
|
227
|
+
name: "Codex",
|
|
228
|
+
status: "warn",
|
|
229
|
+
detail: "not installed on this machine",
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
// 7. gh CLI (optional — only needed for reverse-ticket)
|
|
233
|
+
checks.push({
|
|
234
|
+
name: "GitHub CLI (`gh`) for reverse-ticket command",
|
|
235
|
+
status: hasGhCli() ? "pass" : "warn",
|
|
236
|
+
detail: hasGhCli()
|
|
237
|
+
? "installed"
|
|
238
|
+
: "not installed — only needed if you use `codiedev reverse-ticket <pr-url>`",
|
|
239
|
+
});
|
|
240
|
+
report(checks);
|
|
241
|
+
const failures = checks.filter((c) => c.status === "fail");
|
|
242
|
+
if (failures.length > 0) {
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function report(checks) {
|
|
247
|
+
for (const c of checks) {
|
|
248
|
+
const sym = symbol(c.status);
|
|
249
|
+
const line = c.detail ? ` ${sym} ${c.name} — ${c.detail}` : ` ${sym} ${c.name}`;
|
|
250
|
+
console.log(line);
|
|
251
|
+
}
|
|
252
|
+
const fails = checks.filter((c) => c.status === "fail").length;
|
|
253
|
+
const warns = checks.filter((c) => c.status === "warn").length;
|
|
254
|
+
const passes = checks.filter((c) => c.status === "pass").length;
|
|
255
|
+
console.log();
|
|
256
|
+
if (fails === 0) {
|
|
257
|
+
console.log(`All core checks passed (${passes} ok${warns > 0 ? `, ${warns} warning${warns === 1 ? "" : "s"}` : ""}). You're set.`);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
console.log(`${fails} check${fails === 1 ? "" : "s"} failed. Re-run \`codiedev connect\` or check your token at https://codiedev.com/portal/integrations/claude-code`);
|
|
261
|
+
}
|
|
262
|
+
console.log();
|
|
263
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runReverseTicket(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runReverseTicket = runReverseTicket;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const shared_1 = require("./shared");
|
|
6
|
+
function parsePrUrl(url) {
|
|
7
|
+
const m = url.match(/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/);
|
|
8
|
+
if (!m)
|
|
9
|
+
return null;
|
|
10
|
+
return { owner: m[1], repo: m[2], number: Number(m[3]) };
|
|
11
|
+
}
|
|
12
|
+
function checkGhCli() {
|
|
13
|
+
try {
|
|
14
|
+
(0, child_process_1.execSync)("gh --version", { stdio: ["pipe", "pipe", "pipe"] });
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function ghApi(path) {
|
|
22
|
+
const out = (0, child_process_1.execSync)(`gh api "${path}"`, {
|
|
23
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
24
|
+
maxBuffer: 50 * 1024 * 1024,
|
|
25
|
+
}).toString("utf8");
|
|
26
|
+
return JSON.parse(out);
|
|
27
|
+
}
|
|
28
|
+
function ghRaw(path) {
|
|
29
|
+
return (0, child_process_1.execSync)(`gh api -H "Accept: application/vnd.github.v3.diff" "${path}"`, {
|
|
30
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
31
|
+
maxBuffer: 50 * 1024 * 1024,
|
|
32
|
+
}).toString("utf8");
|
|
33
|
+
}
|
|
34
|
+
function parseArgs(args) {
|
|
35
|
+
let prUrl;
|
|
36
|
+
let forcedKey;
|
|
37
|
+
let noTruncate = false;
|
|
38
|
+
for (let i = 0; i < args.length; i++) {
|
|
39
|
+
const a = args[i];
|
|
40
|
+
if ((a === "--with" || a === "-w") && i + 1 < args.length) {
|
|
41
|
+
forcedKey = args[++i];
|
|
42
|
+
}
|
|
43
|
+
else if (a.startsWith("--with=")) {
|
|
44
|
+
forcedKey = a.slice("--with=".length);
|
|
45
|
+
}
|
|
46
|
+
else if (a === "--full") {
|
|
47
|
+
noTruncate = true;
|
|
48
|
+
}
|
|
49
|
+
else if (!a.startsWith("--") && !prUrl) {
|
|
50
|
+
prUrl = a;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (!prUrl) {
|
|
54
|
+
console.error("Usage: codiedev reverse-ticket <pr-url> [--with <artifact-key>] [--full]");
|
|
55
|
+
console.error("");
|
|
56
|
+
console.error("Example: codiedev reverse-ticket https://github.com/signalandcode/repo/pull/42");
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
return { prUrl, forcedKey, noTruncate };
|
|
60
|
+
}
|
|
61
|
+
async function runReverseTicket(args) {
|
|
62
|
+
const { prUrl, forcedKey, noTruncate } = parseArgs(args);
|
|
63
|
+
const parsed = parsePrUrl(prUrl);
|
|
64
|
+
if (!parsed) {
|
|
65
|
+
console.error("Couldn't parse PR URL. Expected format: https://github.com/<owner>/<repo>/pull/<number>");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
if (!checkGhCli()) {
|
|
69
|
+
console.error("This command needs the `gh` CLI installed and authenticated.");
|
|
70
|
+
console.error(" brew install gh (macOS)");
|
|
71
|
+
console.error(" gh auth login");
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
const config = (0, shared_1.requireConfig)();
|
|
75
|
+
console.log(`Fetching PR ${parsed.owner}/${parsed.repo}#${parsed.number}…`);
|
|
76
|
+
let prJson;
|
|
77
|
+
let filesJson;
|
|
78
|
+
let diff;
|
|
79
|
+
try {
|
|
80
|
+
prJson = ghApi(`/repos/${parsed.owner}/${parsed.repo}/pulls/${parsed.number}`);
|
|
81
|
+
filesJson = ghApi(`/repos/${parsed.owner}/${parsed.repo}/pulls/${parsed.number}/files`);
|
|
82
|
+
// Diff is nice-to-have; truncate if huge.
|
|
83
|
+
try {
|
|
84
|
+
const rawDiff = ghRaw(`/repos/${parsed.owner}/${parsed.repo}/pulls/${parsed.number}`);
|
|
85
|
+
diff = noTruncate ? rawDiff : rawDiff.slice(0, 12_000);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Skip diff on failure — the writer works without it.
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
console.error(`Failed to fetch PR via gh api: ${err.message}`);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
const bundle = {
|
|
96
|
+
repo: `${parsed.owner}/${parsed.repo}`,
|
|
97
|
+
number: parsed.number,
|
|
98
|
+
title: prJson.title ?? "",
|
|
99
|
+
body: prJson.body ?? "",
|
|
100
|
+
author: prJson.user?.login ?? "unknown",
|
|
101
|
+
authorEmail: prJson.user?.email ?? undefined,
|
|
102
|
+
mergedAt: prJson.merged_at
|
|
103
|
+
? Date.parse(prJson.merged_at)
|
|
104
|
+
: prJson.closed_at
|
|
105
|
+
? Date.parse(prJson.closed_at)
|
|
106
|
+
: Date.now(),
|
|
107
|
+
filesChanged: (filesJson ?? []).map((f) => f.filename),
|
|
108
|
+
diff,
|
|
109
|
+
htmlUrl: prJson.html_url ?? prUrl,
|
|
110
|
+
};
|
|
111
|
+
console.log(` title: ${bundle.title}`);
|
|
112
|
+
console.log(` author: ${bundle.author}`);
|
|
113
|
+
console.log(` files: ${bundle.filesChanged.length}`);
|
|
114
|
+
console.log(` merged: ${new Date(bundle.mergedAt).toISOString()}`);
|
|
115
|
+
console.log("");
|
|
116
|
+
console.log("Generating ticket…");
|
|
117
|
+
console.log("");
|
|
118
|
+
try {
|
|
119
|
+
const res = await (0, shared_1.apiRequest)("POST", "/api/cli/reverseTicket", {
|
|
120
|
+
config,
|
|
121
|
+
body: {
|
|
122
|
+
pr: bundle,
|
|
123
|
+
forcedArtifactKey: forcedKey,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
if (res.match) {
|
|
127
|
+
console.log(`✓ Matched artifact: ${res.match.key} (score=${res.match.score.toFixed(2)})`);
|
|
128
|
+
console.log(` signals · body=${res.match.signals.bodyMention} · files=${res.match.signals.fileOverlap.toFixed(2)} · transcript=${res.match.signals.transcriptEdit}`);
|
|
129
|
+
}
|
|
130
|
+
else if (res.candidates.length > 0) {
|
|
131
|
+
console.log(`? Ambiguous / low confidence. Candidates:`);
|
|
132
|
+
for (const c of res.candidates.slice(0, 3)) {
|
|
133
|
+
console.log(` - ${c.key} (score=${c.score.toFixed(2)})`);
|
|
134
|
+
}
|
|
135
|
+
console.log(` Re-run with --with <key> to force a specific artifact.`);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
console.log("· No matched artifact. Ticket generated from PR diff alone.");
|
|
139
|
+
}
|
|
140
|
+
console.log(` prompt tokens (est): ${res.tokensInEstimate}`);
|
|
141
|
+
console.log("");
|
|
142
|
+
console.log("─────────── Generated ticket ───────────");
|
|
143
|
+
console.log("");
|
|
144
|
+
console.log(res.ticket);
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
console.error(`Reverse-ticket failed: ${err.message}`);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
}
|
package/dist/connect.js
CHANGED
|
@@ -185,9 +185,9 @@ async function runConnect() {
|
|
|
185
185
|
for (const target of installed) {
|
|
186
186
|
console.log(` - ${target}`);
|
|
187
187
|
}
|
|
188
|
-
console.log("Sessions will be captured automatically
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
console.log();
|
|
188
|
+
console.log("Sessions will be captured automatically.");
|
|
192
189
|
}
|
|
190
|
+
console.log();
|
|
191
|
+
console.log("Run `codiedev doctor` to verify everything's wired up.");
|
|
192
|
+
console.log();
|
|
193
193
|
}
|