@jvittechs/j 1.0.58 → 1.0.60
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/{chunk-S7QUPWSM.js → chunk-22FXNN76.js} +194 -110
- package/dist/chunk-22FXNN76.js.map +1 -0
- package/dist/{chunk-DVBQLA4R.js → chunk-5RDBJYO2.js} +31 -3
- package/dist/chunk-5RDBJYO2.js.map +1 -0
- package/dist/{chunk-Z464RBPB.js → chunk-OJYJGHQX.js} +85 -14
- package/dist/chunk-OJYJGHQX.js.map +1 -0
- package/dist/cli.js +129 -46
- package/dist/cli.js.map +1 -1
- package/dist/{components.service-JUUV4CUI.js → components.service-NWAWKII3.js} +1 -2
- package/dist/show-LDL5KXZ6.js +8 -0
- package/dist/summary-4ZVFN4XV.js +10 -0
- package/package.json +1 -1
- package/dist/chunk-DGUM43GV.js +0 -11
- package/dist/chunk-DVBQLA4R.js.map +0 -1
- package/dist/chunk-S7QUPWSM.js.map +0 -1
- package/dist/chunk-Z464RBPB.js.map +0 -1
- package/dist/show-AJ5M3SKQ.js +0 -9
- package/dist/summary-R4WPFJ2U.js +0 -11
- package/dist/summary-R4WPFJ2U.js.map +0 -1
- /package/dist/{chunk-DGUM43GV.js.map → components.service-NWAWKII3.js.map} +0 -0
- /package/dist/{components.service-JUUV4CUI.js.map → show-LDL5KXZ6.js.map} +0 -0
- /package/dist/{show-AJ5M3SKQ.js.map → summary-4ZVFN4XV.js.map} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ConfigService,
|
|
2
3
|
SettingsService
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OJYJGHQX.js";
|
|
4
5
|
|
|
5
6
|
// src/commands/tasks/summary.ts
|
|
6
7
|
import { Command } from "commander";
|
|
@@ -8,8 +9,8 @@ import chalk2 from "chalk";
|
|
|
8
9
|
import boxen from "boxen";
|
|
9
10
|
|
|
10
11
|
// src/services/task.service.ts
|
|
11
|
-
import { promises as
|
|
12
|
-
import { join
|
|
12
|
+
import { promises as fs, existsSync } from "fs";
|
|
13
|
+
import { join, dirname } from "path";
|
|
13
14
|
import { execSync } from "child_process";
|
|
14
15
|
import chalk from "chalk";
|
|
15
16
|
|
|
@@ -51,77 +52,52 @@ var PRIORITY_LABELS = {
|
|
|
51
52
|
3: "Low"
|
|
52
53
|
};
|
|
53
54
|
|
|
54
|
-
// src/services/
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
55
|
+
// src/services/cloud-task-provider.ts
|
|
56
|
+
function mapCloudToLocal(ct) {
|
|
57
|
+
return {
|
|
58
|
+
id: ct.task_id,
|
|
59
|
+
type: ct.type,
|
|
60
|
+
parent: ct.parent || "",
|
|
61
|
+
title: ct.title,
|
|
62
|
+
status: ct.status,
|
|
63
|
+
assigned_to: ct.assigned_to || "",
|
|
64
|
+
claimed_at: ct.claimed_at || "",
|
|
65
|
+
priority: ct.priority ?? 2,
|
|
66
|
+
depends_on: Array.isArray(ct.depends_on) ? ct.depends_on : parseJsonArray(ct.depends_on),
|
|
67
|
+
tags: Array.isArray(ct.tags) ? ct.tags : parseJsonArray(ct.tags),
|
|
68
|
+
branch: ct.branch || "",
|
|
69
|
+
notes: ct.notes || "",
|
|
70
|
+
created: ct.created_at?.split("T")[0] || ct.created_at || "",
|
|
71
|
+
updated: ct.updated_at?.split("T")[0] || ct.updated_at || ""
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function parseJsonArray(val) {
|
|
75
|
+
if (Array.isArray(val)) return val;
|
|
76
|
+
if (typeof val === "string") {
|
|
69
77
|
try {
|
|
70
|
-
|
|
71
|
-
return true;
|
|
78
|
+
return JSON.parse(val);
|
|
72
79
|
} catch {
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Load configuration from file
|
|
78
|
-
* @returns Config object or null if not found
|
|
79
|
-
*/
|
|
80
|
-
async load() {
|
|
81
|
-
if (!await this.exists()) {
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
try {
|
|
85
|
-
const content = await fs.readFile(this.configPath, "utf-8");
|
|
86
|
-
return JSON.parse(content);
|
|
87
|
-
} catch (error) {
|
|
88
|
-
throw new Error(
|
|
89
|
-
`Failed to load config: ${error instanceof Error ? error.message : String(error)}`
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Save configuration to file
|
|
95
|
-
* Creates directory if it doesn't exist
|
|
96
|
-
* Sets proper file permissions (600)
|
|
97
|
-
*/
|
|
98
|
-
async save(config) {
|
|
99
|
-
try {
|
|
100
|
-
await fs.mkdir(this.configDir, { recursive: true, mode: 448 });
|
|
101
|
-
await fs.writeFile(this.configPath, JSON.stringify(config, null, 2), {
|
|
102
|
-
mode: 384
|
|
103
|
-
});
|
|
104
|
-
} catch (error) {
|
|
105
|
-
throw new Error(
|
|
106
|
-
`Failed to save config: ${error instanceof Error ? error.message : String(error)}`
|
|
107
|
-
);
|
|
80
|
+
return [];
|
|
108
81
|
}
|
|
109
82
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
function mapLocalToCloud(task) {
|
|
86
|
+
return {
|
|
87
|
+
task_id: task.id,
|
|
88
|
+
title: task.title,
|
|
89
|
+
type: task.type || "task",
|
|
90
|
+
parent: task.parent || "",
|
|
91
|
+
status: task.status,
|
|
92
|
+
assigned_to: task.assigned_to || "",
|
|
93
|
+
claimed_at: task.claimed_at || "",
|
|
94
|
+
priority: task.priority ?? 2,
|
|
95
|
+
depends_on: task.depends_on || [],
|
|
96
|
+
tags: task.tags || [],
|
|
97
|
+
branch: task.branch || "",
|
|
98
|
+
notes: task.notes || ""
|
|
99
|
+
};
|
|
100
|
+
}
|
|
125
101
|
var CloudTaskProvider = class {
|
|
126
102
|
apiUrl;
|
|
127
103
|
accessKey;
|
|
@@ -176,16 +152,19 @@ var CloudTaskProvider = class {
|
|
|
176
152
|
// CRUD
|
|
177
153
|
// ============================================
|
|
178
154
|
async readAll() {
|
|
179
|
-
|
|
155
|
+
const rows = await this.request(
|
|
156
|
+
`/api/tasks?projectId=${encodeURIComponent(this.projectId)}`
|
|
157
|
+
);
|
|
158
|
+
return rows.map(mapCloudToLocal);
|
|
180
159
|
}
|
|
181
160
|
async add(input) {
|
|
182
161
|
const all = await this.readAll().catch(() => []);
|
|
183
162
|
const maxNum = all.reduce((max, t) => {
|
|
184
163
|
const n = parseInt(t.id.replace("T-", ""), 10);
|
|
185
|
-
return n
|
|
164
|
+
return isNaN(n) ? max : Math.max(max, n);
|
|
186
165
|
}, 0);
|
|
187
166
|
const taskId = `T-${String(maxNum + 1).padStart(3, "0")}`;
|
|
188
|
-
|
|
167
|
+
const row = await this.request("/api/tasks", {
|
|
189
168
|
method: "POST",
|
|
190
169
|
body: JSON.stringify({
|
|
191
170
|
task_id: taskId,
|
|
@@ -200,15 +179,17 @@ var CloudTaskProvider = class {
|
|
|
200
179
|
notes: input.notes || ""
|
|
201
180
|
})
|
|
202
181
|
});
|
|
182
|
+
return mapCloudToLocal(row);
|
|
203
183
|
}
|
|
204
184
|
async update(id, updates) {
|
|
205
|
-
|
|
185
|
+
const row = await this.request(
|
|
206
186
|
`/api/tasks/${encodeURIComponent(id)}?projectId=${encodeURIComponent(this.projectId)}`,
|
|
207
187
|
{
|
|
208
188
|
method: "PATCH",
|
|
209
189
|
body: JSON.stringify(updates)
|
|
210
190
|
}
|
|
211
191
|
);
|
|
192
|
+
return mapCloudToLocal(row);
|
|
212
193
|
}
|
|
213
194
|
async deleteTask(id) {
|
|
214
195
|
await this.request(
|
|
@@ -230,13 +211,15 @@ var CloudTaskProvider = class {
|
|
|
230
211
|
if (options?.status) params.set("status", options.status);
|
|
231
212
|
if (options?.type) params.set("type", options.type);
|
|
232
213
|
if (options?.parent !== void 0) params.set("parent", options.parent);
|
|
233
|
-
|
|
214
|
+
const rows = await this.request(`/api/tasks?${params}`);
|
|
215
|
+
return rows.map(mapCloudToLocal);
|
|
234
216
|
}
|
|
235
217
|
async getById(id) {
|
|
236
218
|
try {
|
|
237
|
-
|
|
219
|
+
const row = await this.request(
|
|
238
220
|
`/api/tasks/${encodeURIComponent(id)}?projectId=${encodeURIComponent(this.projectId)}`
|
|
239
221
|
);
|
|
222
|
+
return mapCloudToLocal(row);
|
|
240
223
|
} catch {
|
|
241
224
|
return null;
|
|
242
225
|
}
|
|
@@ -284,22 +267,33 @@ var CloudTaskProvider = class {
|
|
|
284
267
|
// WORKFLOW
|
|
285
268
|
// ============================================
|
|
286
269
|
async getReady() {
|
|
287
|
-
|
|
270
|
+
const rows = await this.request(
|
|
271
|
+
`/api/tasks/ready?projectId=${encodeURIComponent(this.projectId)}`
|
|
272
|
+
);
|
|
273
|
+
return rows.map(mapCloudToLocal);
|
|
288
274
|
}
|
|
289
275
|
async pick(id, agentId) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
276
|
+
const row = await this.request(
|
|
277
|
+
`/api/tasks/${encodeURIComponent(id)}/pick`,
|
|
278
|
+
{
|
|
279
|
+
method: "POST",
|
|
280
|
+
body: JSON.stringify({
|
|
281
|
+
project_id: this.projectId,
|
|
282
|
+
agent_id: agentId || "cli"
|
|
283
|
+
})
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
return mapCloudToLocal(row);
|
|
297
287
|
}
|
|
298
288
|
async markDone(id) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
289
|
+
const row = await this.request(
|
|
290
|
+
`/api/tasks/${encodeURIComponent(id)}/done`,
|
|
291
|
+
{
|
|
292
|
+
method: "POST",
|
|
293
|
+
body: JSON.stringify({ project_id: this.projectId })
|
|
294
|
+
}
|
|
295
|
+
);
|
|
296
|
+
return mapCloudToLocal(row);
|
|
303
297
|
}
|
|
304
298
|
async cancel(id) {
|
|
305
299
|
await this.request(`/api/tasks/${encodeURIComponent(id)}/cancel`, {
|
|
@@ -317,19 +311,19 @@ var CloudTaskProvider = class {
|
|
|
317
311
|
}
|
|
318
312
|
async push(tasks) {
|
|
319
313
|
for (const task of tasks) {
|
|
314
|
+
const cloudFields = mapLocalToCloud(task);
|
|
320
315
|
try {
|
|
321
316
|
await this.request(
|
|
322
317
|
`/api/tasks/${encodeURIComponent(task.id)}?projectId=${encodeURIComponent(this.projectId)}`,
|
|
323
|
-
{ method: "PATCH", body: JSON.stringify(
|
|
318
|
+
{ method: "PATCH", body: JSON.stringify(cloudFields) }
|
|
324
319
|
);
|
|
325
320
|
} catch {
|
|
326
321
|
try {
|
|
327
322
|
await this.request("/api/tasks", {
|
|
328
323
|
method: "POST",
|
|
329
324
|
body: JSON.stringify({
|
|
330
|
-
|
|
331
|
-
project_id: this.projectId
|
|
332
|
-
...task
|
|
325
|
+
...cloudFields,
|
|
326
|
+
project_id: this.projectId
|
|
333
327
|
})
|
|
334
328
|
});
|
|
335
329
|
} catch {
|
|
@@ -349,27 +343,45 @@ var TaskService = class {
|
|
|
349
343
|
_providerReady;
|
|
350
344
|
constructor(cwd) {
|
|
351
345
|
this.cwd = cwd || process.cwd();
|
|
352
|
-
this.tasksPath =
|
|
346
|
+
this.tasksPath = join(this.cwd, TASKS_FILE);
|
|
353
347
|
this._providerReady = this._initCloudProvider();
|
|
354
348
|
}
|
|
355
349
|
/**
|
|
356
|
-
* Initialise cloud provider if settings.yaml has tasks.cloud = true
|
|
350
|
+
* Initialise cloud provider if settings.yaml has tasks.cloud = true.
|
|
351
|
+
* Auto-registers the project on the server on first use.
|
|
357
352
|
*/
|
|
358
353
|
async _initCloudProvider() {
|
|
359
354
|
try {
|
|
360
355
|
const settings = new SettingsService(this.cwd);
|
|
361
356
|
if (!settings.isTaskCloudEnabled()) return;
|
|
362
|
-
const projectId = settings.getProjectId();
|
|
363
|
-
if (!projectId) return;
|
|
364
357
|
const config = await new ConfigService().load();
|
|
365
358
|
if (!config?.apiUrl || !config?.accessKey) return;
|
|
366
|
-
|
|
359
|
+
const repoUrl = settings.resolveGitRepoUrl();
|
|
360
|
+
if (!repoUrl) return;
|
|
361
|
+
let projectId = settings.getProjectId();
|
|
362
|
+
if (!projectId) return;
|
|
363
|
+
const provider = new CloudTaskProvider(config, projectId);
|
|
364
|
+
try {
|
|
365
|
+
const registeredId = await provider.ensureProjectRegistered(repoUrl);
|
|
366
|
+
if (registeredId && registeredId !== projectId) {
|
|
367
|
+
projectId = registeredId;
|
|
368
|
+
await settings.set("tasks.projectId", registeredId);
|
|
369
|
+
this._cloudProvider = new CloudTaskProvider(config, registeredId);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
} catch {
|
|
373
|
+
}
|
|
374
|
+
this._cloudProvider = provider;
|
|
367
375
|
} catch {
|
|
368
376
|
}
|
|
369
377
|
}
|
|
370
378
|
/**
|
|
371
379
|
* Wait for provider initialisation (call before any cloud operation)
|
|
372
380
|
*/
|
|
381
|
+
async waitForInit() {
|
|
382
|
+
await this._providerReady;
|
|
383
|
+
}
|
|
384
|
+
/** @internal alias kept for backward compat */
|
|
373
385
|
async ready() {
|
|
374
386
|
await this._providerReady;
|
|
375
387
|
}
|
|
@@ -390,7 +402,7 @@ var TaskService = class {
|
|
|
390
402
|
* If not, print a helpful message and exit.
|
|
391
403
|
*/
|
|
392
404
|
static ensureJai1Dir(cwd) {
|
|
393
|
-
const dir =
|
|
405
|
+
const dir = join(cwd || process.cwd(), ".jai1");
|
|
394
406
|
if (!existsSync(dir)) {
|
|
395
407
|
console.error(chalk.red("\u274C Th\u01B0 m\u1EE5c .jai1 kh\xF4ng t\u1ED3n t\u1EA1i trong project n\xE0y."));
|
|
396
408
|
console.error("");
|
|
@@ -407,12 +419,16 @@ var TaskService = class {
|
|
|
407
419
|
// READ
|
|
408
420
|
// ============================================
|
|
409
421
|
/**
|
|
410
|
-
* Read all tasks from JSONL file
|
|
422
|
+
* Read all tasks from JSONL file (or cloud API if cloud mode)
|
|
411
423
|
*/
|
|
412
424
|
async readAll() {
|
|
425
|
+
await this.ready();
|
|
426
|
+
if (this._cloudProvider) {
|
|
427
|
+
return this._cloudProvider.readAll();
|
|
428
|
+
}
|
|
413
429
|
try {
|
|
414
430
|
await this.ensureTasksFileNotDirectory();
|
|
415
|
-
const content = await
|
|
431
|
+
const content = await fs.readFile(this.tasksPath, "utf-8");
|
|
416
432
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
417
433
|
return lines.map((line) => TaskSchema.parse(JSON.parse(line)));
|
|
418
434
|
} catch (error) {
|
|
@@ -426,6 +442,10 @@ var TaskService = class {
|
|
|
426
442
|
* Find task by ID
|
|
427
443
|
*/
|
|
428
444
|
async findById(id) {
|
|
445
|
+
await this.ready();
|
|
446
|
+
if (this._cloudProvider) {
|
|
447
|
+
return this._cloudProvider.getById(id);
|
|
448
|
+
}
|
|
429
449
|
const tasks = await this.readAll();
|
|
430
450
|
return tasks.find((t) => t.id === id) || null;
|
|
431
451
|
}
|
|
@@ -433,6 +453,17 @@ var TaskService = class {
|
|
|
433
453
|
* Filter tasks by criteria
|
|
434
454
|
*/
|
|
435
455
|
async filter(criteria) {
|
|
456
|
+
await this.ready();
|
|
457
|
+
if (this._cloudProvider) {
|
|
458
|
+
const listInput = {};
|
|
459
|
+
if (criteria.status) listInput.status = criteria.status;
|
|
460
|
+
if (criteria.parent) listInput.parent = criteria.parent;
|
|
461
|
+
const tasks2 = await this._cloudProvider.list(listInput);
|
|
462
|
+
if (criteria.assignee) {
|
|
463
|
+
return tasks2.filter((t) => t.assigned_to === criteria.assignee);
|
|
464
|
+
}
|
|
465
|
+
return tasks2;
|
|
466
|
+
}
|
|
436
467
|
const tasks = await this.readAll();
|
|
437
468
|
return tasks.filter((t) => {
|
|
438
469
|
if (criteria.status && t.status !== criteria.status) return false;
|
|
@@ -446,6 +477,12 @@ var TaskService = class {
|
|
|
446
477
|
* status=todo, all depends_on done or cancelled, assigned_to empty
|
|
447
478
|
*/
|
|
448
479
|
async getReady(parent) {
|
|
480
|
+
await this.ready();
|
|
481
|
+
if (this._cloudProvider) {
|
|
482
|
+
const ready = await this._cloudProvider.getReady();
|
|
483
|
+
if (parent) return ready.filter((t) => t.parent === parent);
|
|
484
|
+
return ready;
|
|
485
|
+
}
|
|
449
486
|
const tasks = await this.readAll();
|
|
450
487
|
const resolvedIds = new Set(
|
|
451
488
|
tasks.filter((t) => t.status === "done" || t.status === "cancelled").map((t) => t.id)
|
|
@@ -478,6 +515,11 @@ var TaskService = class {
|
|
|
478
515
|
* Get stats by status
|
|
479
516
|
*/
|
|
480
517
|
async getStats() {
|
|
518
|
+
await this.ready();
|
|
519
|
+
if (this._cloudProvider) {
|
|
520
|
+
const stats = await this._cloudProvider.getStats();
|
|
521
|
+
return { ...stats, blocked: 0 };
|
|
522
|
+
}
|
|
481
523
|
const tasks = await this.readAll();
|
|
482
524
|
const resolvedIds = new Set(
|
|
483
525
|
tasks.filter((t) => t.status === "done" || t.status === "cancelled").map((t) => t.id)
|
|
@@ -507,6 +549,12 @@ var TaskService = class {
|
|
|
507
549
|
* todo = otherwise (blocked or waiting)
|
|
508
550
|
*/
|
|
509
551
|
async getParents(statusFilter) {
|
|
552
|
+
await this.ready();
|
|
553
|
+
if (this._cloudProvider) {
|
|
554
|
+
const parents2 = await this._cloudProvider.getParents();
|
|
555
|
+
if (statusFilter) return parents2.filter((p) => p.status === statusFilter);
|
|
556
|
+
return parents2;
|
|
557
|
+
}
|
|
510
558
|
const tasks = await this.readAll();
|
|
511
559
|
const resolvedIds = new Set(
|
|
512
560
|
tasks.filter((t) => t.status === "done" || t.status === "cancelled").map((t) => t.id)
|
|
@@ -621,6 +669,10 @@ var TaskService = class {
|
|
|
621
669
|
* Update a task by ID
|
|
622
670
|
*/
|
|
623
671
|
async update(id, changes) {
|
|
672
|
+
await this.ready();
|
|
673
|
+
if (this._cloudProvider) {
|
|
674
|
+
return this._cloudProvider.update(id, changes);
|
|
675
|
+
}
|
|
624
676
|
const tasks = await this.readAll();
|
|
625
677
|
const index = tasks.findIndex((t) => t.id === id);
|
|
626
678
|
if (index === -1) {
|
|
@@ -636,6 +688,7 @@ var TaskService = class {
|
|
|
636
688
|
* Add dependency: child depends on parent
|
|
637
689
|
*/
|
|
638
690
|
async addDependency(childId, parentId) {
|
|
691
|
+
await this.ready();
|
|
639
692
|
const tasks = await this.readAll();
|
|
640
693
|
const child = tasks.find((t) => t.id === childId);
|
|
641
694
|
const parent = tasks.find((t) => t.id === parentId);
|
|
@@ -656,6 +709,10 @@ var TaskService = class {
|
|
|
656
709
|
* Mark task as done
|
|
657
710
|
*/
|
|
658
711
|
async markDone(id) {
|
|
712
|
+
await this.ready();
|
|
713
|
+
if (this._cloudProvider) {
|
|
714
|
+
return this._cloudProvider.markDone(id);
|
|
715
|
+
}
|
|
659
716
|
return this.update(id, { status: "done" });
|
|
660
717
|
}
|
|
661
718
|
/**
|
|
@@ -669,6 +726,10 @@ var TaskService = class {
|
|
|
669
726
|
* Cancel a task: set status=cancelled, clear assignment
|
|
670
727
|
*/
|
|
671
728
|
async cancel(id) {
|
|
729
|
+
await this.ready();
|
|
730
|
+
if (this._cloudProvider) {
|
|
731
|
+
return this._cloudProvider.cancel(id);
|
|
732
|
+
}
|
|
672
733
|
return this.update(id, {
|
|
673
734
|
status: "cancelled",
|
|
674
735
|
assigned_to: "",
|
|
@@ -679,6 +740,10 @@ var TaskService = class {
|
|
|
679
740
|
* Delete a task completely and clean up depends_on references
|
|
680
741
|
*/
|
|
681
742
|
async deleteTask(id) {
|
|
743
|
+
await this.ready();
|
|
744
|
+
if (this._cloudProvider) {
|
|
745
|
+
return this._cloudProvider.deleteTask(id);
|
|
746
|
+
}
|
|
682
747
|
return this.deleteTasks([id]);
|
|
683
748
|
}
|
|
684
749
|
/**
|
|
@@ -686,6 +751,13 @@ var TaskService = class {
|
|
|
686
751
|
* Validates all IDs exist before deleting any.
|
|
687
752
|
*/
|
|
688
753
|
async deleteTasks(ids) {
|
|
754
|
+
await this.ready();
|
|
755
|
+
if (this._cloudProvider) {
|
|
756
|
+
for (const id of ids) {
|
|
757
|
+
await this._cloudProvider.deleteTask(id);
|
|
758
|
+
}
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
689
761
|
const tasks = await this.readAll();
|
|
690
762
|
const deleteSet = new Set(ids);
|
|
691
763
|
const notFound = ids.filter((id) => !tasks.find((t) => t.id === id));
|
|
@@ -708,6 +780,15 @@ var TaskService = class {
|
|
|
708
780
|
* Returns the list of deleted tasks for display purposes.
|
|
709
781
|
*/
|
|
710
782
|
async deleteGroup(parentName) {
|
|
783
|
+
await this.ready();
|
|
784
|
+
if (this._cloudProvider) {
|
|
785
|
+
const groupTasks2 = await this._cloudProvider.list({ parent: parentName });
|
|
786
|
+
if (groupTasks2.length === 0) {
|
|
787
|
+
throw new Error(`No tasks found in group: ${parentName}`);
|
|
788
|
+
}
|
|
789
|
+
await this._cloudProvider.deleteGroup(parentName);
|
|
790
|
+
return groupTasks2;
|
|
791
|
+
}
|
|
711
792
|
const tasks = await this.readAll();
|
|
712
793
|
const groupTasks = tasks.filter((t) => t.parent === parentName);
|
|
713
794
|
if (groupTasks.length === 0) {
|
|
@@ -721,6 +802,10 @@ var TaskService = class {
|
|
|
721
802
|
* Pick next task: claim for current user
|
|
722
803
|
*/
|
|
723
804
|
async pick(taskId) {
|
|
805
|
+
await this.ready();
|
|
806
|
+
if (this._cloudProvider) {
|
|
807
|
+
return this._cloudProvider.pick(taskId, this.getCurrentUser());
|
|
808
|
+
}
|
|
724
809
|
const username = this.getCurrentUser();
|
|
725
810
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
726
811
|
return this.update(taskId, {
|
|
@@ -814,9 +899,9 @@ var TaskService = class {
|
|
|
814
899
|
* - Dirty working tree → stash/unstash automatically
|
|
815
900
|
*/
|
|
816
901
|
async syncPush() {
|
|
817
|
-
const cwd =
|
|
902
|
+
const cwd = this.cwd;
|
|
818
903
|
const branch = SYNC_BRANCH;
|
|
819
|
-
const tasksFullPath =
|
|
904
|
+
const tasksFullPath = join(cwd, TASKS_FILE);
|
|
820
905
|
if (!existsSync(tasksFullPath)) {
|
|
821
906
|
return;
|
|
822
907
|
}
|
|
@@ -880,7 +965,7 @@ var TaskService = class {
|
|
|
880
965
|
* - tasks.jsonl doesn't exist on remote branch → returns empty
|
|
881
966
|
*/
|
|
882
967
|
async syncPull() {
|
|
883
|
-
const cwd =
|
|
968
|
+
const cwd = this.cwd;
|
|
884
969
|
const branch = SYNC_BRANCH;
|
|
885
970
|
let merged = 0;
|
|
886
971
|
let conflicts = 0;
|
|
@@ -926,16 +1011,16 @@ var TaskService = class {
|
|
|
926
1011
|
async appendTask(task) {
|
|
927
1012
|
await this.ensureTasksFileNotDirectory();
|
|
928
1013
|
const dir = dirname(this.tasksPath);
|
|
929
|
-
await
|
|
1014
|
+
await fs.mkdir(dir, { recursive: true });
|
|
930
1015
|
const line = JSON.stringify(task) + "\n";
|
|
931
|
-
await
|
|
1016
|
+
await fs.appendFile(this.tasksPath, line, "utf-8");
|
|
932
1017
|
}
|
|
933
1018
|
async writeAll(tasks) {
|
|
934
1019
|
await this.ensureTasksFileNotDirectory();
|
|
935
1020
|
const dir = dirname(this.tasksPath);
|
|
936
|
-
await
|
|
1021
|
+
await fs.mkdir(dir, { recursive: true });
|
|
937
1022
|
const content = tasks.map((t) => JSON.stringify(t)).join("\n") + "\n";
|
|
938
|
-
await
|
|
1023
|
+
await fs.writeFile(this.tasksPath, content, "utf-8");
|
|
939
1024
|
}
|
|
940
1025
|
getCurrentUser() {
|
|
941
1026
|
try {
|
|
@@ -963,7 +1048,7 @@ var TaskService = class {
|
|
|
963
1048
|
}
|
|
964
1049
|
async ensureTasksFileNotDirectory() {
|
|
965
1050
|
try {
|
|
966
|
-
const stat = await
|
|
1051
|
+
const stat = await fs.stat(this.tasksPath);
|
|
967
1052
|
if (stat.isDirectory()) {
|
|
968
1053
|
throw new Error(
|
|
969
1054
|
`Invalid tasks path: expected file at ${TASKS_FILE} but found a directory. Please remove the directory and re-run the command.`
|
|
@@ -1030,7 +1115,6 @@ function createTaskSummaryCommand() {
|
|
|
1030
1115
|
}
|
|
1031
1116
|
|
|
1032
1117
|
export {
|
|
1033
|
-
ConfigService,
|
|
1034
1118
|
STATUS_ICONS,
|
|
1035
1119
|
BLOCKED_ICON,
|
|
1036
1120
|
PRIORITY_ICONS,
|
|
@@ -1039,4 +1123,4 @@ export {
|
|
|
1039
1123
|
handleTaskSummary,
|
|
1040
1124
|
createTaskSummaryCommand
|
|
1041
1125
|
};
|
|
1042
|
-
//# sourceMappingURL=chunk-
|
|
1126
|
+
//# sourceMappingURL=chunk-22FXNN76.js.map
|