flightdesk 0.1.11 → 0.1.13
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/main.js +94 -8
- package/main.js.map +4 -4
- package/package.json +1 -1
package/main.js
CHANGED
|
@@ -3935,17 +3935,30 @@ async function watchCommand(options) {
|
|
|
3935
3935
|
try {
|
|
3936
3936
|
const tasks = await api.listTasks();
|
|
3937
3937
|
const activeTasks = tasks.filter(
|
|
3938
|
-
(t) => ["DISPATCHED", "IN_PROGRESS", "BRANCH_CREATED"].includes(t.status)
|
|
3938
|
+
(t) => ["DISPATCHED", "IN_PROGRESS", "BRANCH_CREATED"].includes(t.status) || t.status === "PENDING" && t.sessionViewUrl
|
|
3939
3939
|
);
|
|
3940
3940
|
if (activeTasks.length === 0) {
|
|
3941
3941
|
console.log(" No active tasks to monitor");
|
|
3942
3942
|
return;
|
|
3943
3943
|
}
|
|
3944
|
+
const needsReconciliation = activeTasks.filter((t) => {
|
|
3945
|
+
if (t.prUrl && !["PR_OPEN", "MERGED", "ARCHIVED"].includes(t.status)) return true;
|
|
3946
|
+
if (t.branchName && t.status === "PENDING") return true;
|
|
3947
|
+
if (t.sessionViewUrl && t.status === "PENDING") return true;
|
|
3948
|
+
return false;
|
|
3949
|
+
});
|
|
3950
|
+
if (needsReconciliation.length > 0) {
|
|
3951
|
+
console.log(` \u26A0\uFE0F ${needsReconciliation.length} task(s) need status reconciliation`);
|
|
3952
|
+
}
|
|
3944
3953
|
console.log(` Found ${activeTasks.length} active task(s)`);
|
|
3945
3954
|
for (const task2 of activeTasks) {
|
|
3946
3955
|
console.log(`
|
|
3947
3956
|
\u{1F4CB} ${task2.title}`);
|
|
3948
3957
|
console.log(` Status: ${task2.status}`);
|
|
3958
|
+
const reconciled = await reconcileTaskStatus(api, task2);
|
|
3959
|
+
if (reconciled) {
|
|
3960
|
+
continue;
|
|
3961
|
+
}
|
|
3949
3962
|
if (task2.sessionViewUrl && playwrightAvailable) {
|
|
3950
3963
|
console.log(` Checking session...`);
|
|
3951
3964
|
const sessionInfo = await monitorSession(task2.sessionViewUrl, {
|
|
@@ -3979,6 +3992,39 @@ Watching... (Ctrl+C to stop)
|
|
|
3979
3992
|
await new Promise((_resolve) => {
|
|
3980
3993
|
});
|
|
3981
3994
|
}
|
|
3995
|
+
async function reconcileTaskStatus(api, task2) {
|
|
3996
|
+
let expectedStatus = null;
|
|
3997
|
+
let reason = "";
|
|
3998
|
+
if (task2.prUrl) {
|
|
3999
|
+
if (!["PR_OPEN", "MERGED", "ARCHIVED", "REVIEW_RUNNING", "REVIEW_DONE", "QA_READY", "QA_APPROVED"].includes(task2.status)) {
|
|
4000
|
+
expectedStatus = "PR_OPEN";
|
|
4001
|
+
reason = `has PR URL but status is ${task2.status}`;
|
|
4002
|
+
}
|
|
4003
|
+
} else if (task2.branchName) {
|
|
4004
|
+
if (["PENDING", "DISPATCHED"].includes(task2.status)) {
|
|
4005
|
+
expectedStatus = "IN_PROGRESS";
|
|
4006
|
+
reason = `has branch but status is ${task2.status}`;
|
|
4007
|
+
}
|
|
4008
|
+
} else if (task2.sessionViewUrl) {
|
|
4009
|
+
if (task2.status === "PENDING") {
|
|
4010
|
+
expectedStatus = "DISPATCHED";
|
|
4011
|
+
reason = `has session URL but status is PENDING`;
|
|
4012
|
+
}
|
|
4013
|
+
}
|
|
4014
|
+
if (expectedStatus) {
|
|
4015
|
+
console.log(` \u{1F527} Status reconciliation: ${reason}`);
|
|
4016
|
+
console.log(` Updating: ${task2.status} \u2192 ${expectedStatus}`);
|
|
4017
|
+
try {
|
|
4018
|
+
await api.updateTask(task2.id, { status: expectedStatus });
|
|
4019
|
+
console.log(" \u2705 Status reconciled");
|
|
4020
|
+
return true;
|
|
4021
|
+
} catch (error) {
|
|
4022
|
+
console.log(` \u274C Failed to reconcile: ${error}`);
|
|
4023
|
+
return false;
|
|
4024
|
+
}
|
|
4025
|
+
}
|
|
4026
|
+
return false;
|
|
4027
|
+
}
|
|
3982
4028
|
async function processSessionInfo(api, task2, info) {
|
|
3983
4029
|
if (info.status === "error") {
|
|
3984
4030
|
console.log(` \u274C Error: ${info.error}`);
|
|
@@ -4380,9 +4426,9 @@ async function syncCommand() {
|
|
|
4380
4426
|
const api = FlightDeskAPI.fromConfig(config, org2);
|
|
4381
4427
|
const projects = await api.listProjects();
|
|
4382
4428
|
console.log(` Found ${projects.length} project(s)`);
|
|
4383
|
-
for (const
|
|
4384
|
-
if (
|
|
4385
|
-
newMappings[
|
|
4429
|
+
for (const project2 of projects) {
|
|
4430
|
+
if (project2.githubRepo) {
|
|
4431
|
+
newMappings[project2.githubRepo] = org2.id;
|
|
4386
4432
|
totalProjects++;
|
|
4387
4433
|
}
|
|
4388
4434
|
}
|
|
@@ -4669,16 +4715,23 @@ Summary:`);
|
|
|
4669
4715
|
`);
|
|
4670
4716
|
let created = 0;
|
|
4671
4717
|
let failed = 0;
|
|
4672
|
-
for (const { session, project } of importableSessions) {
|
|
4718
|
+
for (const { session, project: project2 } of importableSessions) {
|
|
4673
4719
|
try {
|
|
4674
4720
|
const task2 = await api.createTask({
|
|
4675
|
-
projectId:
|
|
4721
|
+
projectId: project2.id,
|
|
4676
4722
|
title: session.title,
|
|
4677
4723
|
description: `Imported from Claude Code session`
|
|
4678
4724
|
});
|
|
4725
|
+
let status = "DISPATCHED";
|
|
4726
|
+
if (session.archived) {
|
|
4727
|
+
status = "ARCHIVED";
|
|
4728
|
+
} else if (session.branchName) {
|
|
4729
|
+
status = "IN_PROGRESS";
|
|
4730
|
+
}
|
|
4679
4731
|
await api.updateTask(task2.id, {
|
|
4680
4732
|
branchName: session.branchName,
|
|
4681
|
-
sessionViewUrl: session.url
|
|
4733
|
+
sessionViewUrl: session.url,
|
|
4734
|
+
status
|
|
4682
4735
|
});
|
|
4683
4736
|
console.log(` \u2705 ${session.title.slice(0, 50)}`);
|
|
4684
4737
|
created++;
|
|
@@ -4794,9 +4847,40 @@ async function scanClaudeSessions(options) {
|
|
|
4794
4847
|
}
|
|
4795
4848
|
}
|
|
4796
4849
|
|
|
4850
|
+
// apps/cli/src/commands/project.ts
|
|
4851
|
+
async function projectCommand(action, options) {
|
|
4852
|
+
const { config, org: org2 } = requireActiveOrg();
|
|
4853
|
+
const api = FlightDeskAPI.fromConfig(config, org2);
|
|
4854
|
+
switch (action) {
|
|
4855
|
+
case "list":
|
|
4856
|
+
await listProjects(api);
|
|
4857
|
+
break;
|
|
4858
|
+
default:
|
|
4859
|
+
console.error(`Unknown action: ${action}`);
|
|
4860
|
+
process.exit(1);
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4863
|
+
async function listProjects(api) {
|
|
4864
|
+
const projects = await api.listProjects();
|
|
4865
|
+
if (projects.length === 0) {
|
|
4866
|
+
console.log("No projects found.");
|
|
4867
|
+
console.log("\nCreate a project at https://app.flightdesk.dev/app/projects/new");
|
|
4868
|
+
return;
|
|
4869
|
+
}
|
|
4870
|
+
console.log("Projects:\n");
|
|
4871
|
+
const maxNameLen = Math.max(...projects.map((p) => p.name.length), 4);
|
|
4872
|
+
for (const project2 of projects) {
|
|
4873
|
+
const name = project2.name.padEnd(maxNameLen);
|
|
4874
|
+
const repo = project2.githubRepo || "(no repo)";
|
|
4875
|
+
console.log(` ${project2.id} ${name} ${repo}`);
|
|
4876
|
+
}
|
|
4877
|
+
console.log(`
|
|
4878
|
+
${projects.length} project(s)`);
|
|
4879
|
+
}
|
|
4880
|
+
|
|
4797
4881
|
// apps/cli/src/main.ts
|
|
4798
4882
|
var program2 = new Command();
|
|
4799
|
-
program2.name("flightdesk").description("FlightDesk CLI - AI task management for Claude Code sessions").version("0.1.
|
|
4883
|
+
program2.name("flightdesk").description("FlightDesk CLI - AI task management for Claude Code sessions").version("0.1.13").option("--dev", "Use local development API (localhost:3000)").option("--api <url>", "Use custom API URL");
|
|
4800
4884
|
program2.hook("preAction", () => {
|
|
4801
4885
|
const opts = program2.opts();
|
|
4802
4886
|
if (opts.api) {
|
|
@@ -4811,6 +4895,8 @@ program2.hook("preAction", () => {
|
|
|
4811
4895
|
program2.command("init").description("Configure FlightDesk CLI with your API credentials").action(initCommand);
|
|
4812
4896
|
program2.command("auth").description("Log in to Claude for session monitoring").action(authCommand);
|
|
4813
4897
|
program2.command("register <project-id> [task-id]").description("Register a Claude Code session with a FlightDesk task").option("--view-url <url>", "Claude Code session view URL").option("--teleport-id <id>", "Claude Code teleport ID").option("--title <title>", "Task title (creates new task if task-id not provided)").option("--description <description>", "Task description").action(registerCommand);
|
|
4898
|
+
var project = program2.command("project").description("Project management commands");
|
|
4899
|
+
project.command("list").description("List projects in the active organization").action(() => projectCommand("list", {}));
|
|
4814
4900
|
var task = program2.command("task").description("Task management commands");
|
|
4815
4901
|
task.command("create").description("Create a new task").requiredOption("-p, --project <id>", "Project ID").requiredOption("-t, --title <title>", "Task title").option("-d, --description <description>", "Task description").action((options) => taskCommand("create", options));
|
|
4816
4902
|
task.command("list").description("List tasks").option("-p, --project <id>", "Filter by project ID").option("--status <status>", "Filter by status").action((options) => taskCommand("list", options));
|