taskin 2.2.1 → 2.3.0
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/index.js +102 -70
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -7291,11 +7291,15 @@ ${result.error.message}`);
|
|
|
7291
7291
|
}
|
|
7292
7292
|
/**
|
|
7293
7293
|
* Get automation level from config
|
|
7294
|
-
* Returns 'assisted' as default if not configured
|
|
7294
|
+
* Returns 'assisted' as default if not configured or if config loading fails
|
|
7295
7295
|
*/
|
|
7296
7296
|
getAutomationLevel() {
|
|
7297
|
-
|
|
7298
|
-
|
|
7297
|
+
try {
|
|
7298
|
+
const config = this.loadConfig();
|
|
7299
|
+
return config.automation?.level ?? "assisted";
|
|
7300
|
+
} catch {
|
|
7301
|
+
return "assisted";
|
|
7302
|
+
}
|
|
7299
7303
|
}
|
|
7300
7304
|
/**
|
|
7301
7305
|
* Set automation level in config
|
|
@@ -7312,8 +7316,12 @@ ${result.error.message}`);
|
|
|
7312
7316
|
* Get automation configuration
|
|
7313
7317
|
*/
|
|
7314
7318
|
getAutomationConfig() {
|
|
7315
|
-
|
|
7316
|
-
|
|
7319
|
+
try {
|
|
7320
|
+
const config = this.loadConfig();
|
|
7321
|
+
return config.automation ?? { level: "assisted" };
|
|
7322
|
+
} catch {
|
|
7323
|
+
return { level: "assisted" };
|
|
7324
|
+
}
|
|
7317
7325
|
}
|
|
7318
7326
|
/**
|
|
7319
7327
|
* Set automation configuration
|
|
@@ -8147,9 +8155,7 @@ var FileSystemTaskProvider = class {
|
|
|
8147
8155
|
}
|
|
8148
8156
|
async findTask(taskId) {
|
|
8149
8157
|
const files = await fs2.readdir(this.tasksDirectory);
|
|
8150
|
-
const taskFile = files.find(
|
|
8151
|
-
(file) => file.startsWith(`task-${taskId}-`) && file.endsWith(".md")
|
|
8152
|
-
);
|
|
8158
|
+
const taskFile = files.find((file) => file.startsWith(`task-${taskId}-`) && file.endsWith(".md"));
|
|
8153
8159
|
if (!taskFile) {
|
|
8154
8160
|
return void 0;
|
|
8155
8161
|
}
|
|
@@ -8165,7 +8171,8 @@ var FileSystemTaskProvider = class {
|
|
|
8165
8171
|
const escapedName = n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8166
8172
|
const rx = new RegExp(`^${escapedName}:\\s*(.+)$`, "im");
|
|
8167
8173
|
const m = content.match(rx);
|
|
8168
|
-
if (m)
|
|
8174
|
+
if (m)
|
|
8175
|
+
return m[1].trim();
|
|
8169
8176
|
}
|
|
8170
8177
|
return null;
|
|
8171
8178
|
};
|
|
@@ -8177,9 +8184,7 @@ var FileSystemTaskProvider = class {
|
|
|
8177
8184
|
const assigneeValue = assigneeMatch.trim();
|
|
8178
8185
|
assignee = this.userRegistry.resolveUser(assigneeValue);
|
|
8179
8186
|
if (!assignee) {
|
|
8180
|
-
console.warn(
|
|
8181
|
-
`[FS Provider] User "${assigneeValue}" not found in registry, creating temporary user`
|
|
8182
|
-
);
|
|
8187
|
+
console.warn(`[FS Provider] User "${assigneeValue}" not found in registry, creating temporary user`);
|
|
8183
8188
|
assignee = this.userRegistry.createTemporaryUser(assigneeValue);
|
|
8184
8189
|
}
|
|
8185
8190
|
}
|
|
@@ -8197,9 +8202,7 @@ var FileSystemTaskProvider = class {
|
|
|
8197
8202
|
}
|
|
8198
8203
|
async updateTask(task) {
|
|
8199
8204
|
const currentContent = await fs2.readFile(task.filePath, "utf-8");
|
|
8200
|
-
const hasSectionMetadata = /##\s*(Status|Type|Assignee)/i.test(
|
|
8201
|
-
currentContent
|
|
8202
|
-
);
|
|
8205
|
+
const hasSectionMetadata = /##\s*(Status|Type|Assignee)/i.test(currentContent);
|
|
8203
8206
|
if (hasSectionMetadata) {
|
|
8204
8207
|
const { fixTaskFile: fixTaskFile2 } = await Promise.resolve().then(() => (init_task_validator(), task_validator_exports));
|
|
8205
8208
|
await fixTaskFile2(task.filePath);
|
|
@@ -8207,24 +8210,16 @@ var FileSystemTaskProvider = class {
|
|
|
8207
8210
|
const content = await fs2.readFile(task.filePath, "utf-8");
|
|
8208
8211
|
let updatedContent;
|
|
8209
8212
|
if (/^Status:\s*.+$/im.test(content)) {
|
|
8210
|
-
updatedContent = content.replace(
|
|
8211
|
-
/^Status:\s*.+$/im,
|
|
8212
|
-
`Status: ${task.status}`
|
|
8213
|
-
);
|
|
8213
|
+
updatedContent = content.replace(/^Status:\s*.+$/im, `Status: ${task.status}`);
|
|
8214
8214
|
} else {
|
|
8215
|
-
updatedContent = content.replace(
|
|
8216
|
-
|
|
8217
|
-
`$1Status: ${task.status}
|
|
8218
|
-
`
|
|
8219
|
-
);
|
|
8215
|
+
updatedContent = content.replace(/(^#.*\n)/, `$1Status: ${task.status}
|
|
8216
|
+
`);
|
|
8220
8217
|
}
|
|
8221
8218
|
await fs2.writeFile(task.filePath, updatedContent, "utf-8");
|
|
8222
8219
|
}
|
|
8223
8220
|
async getAllTasks() {
|
|
8224
8221
|
const files = await fs2.readdir(this.tasksDirectory);
|
|
8225
|
-
const taskFiles = files.filter(
|
|
8226
|
-
(file) => file.startsWith("task-") && file.endsWith(".md")
|
|
8227
|
-
);
|
|
8222
|
+
const taskFiles = files.filter((file) => file.startsWith("task-") && file.endsWith(".md"));
|
|
8228
8223
|
const tasks = [];
|
|
8229
8224
|
for (const file of taskFiles) {
|
|
8230
8225
|
const filePath = path4.join(this.tasksDirectory, file);
|
|
@@ -8241,7 +8236,8 @@ var FileSystemTaskProvider = class {
|
|
|
8241
8236
|
const escapedName = n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8242
8237
|
const rx = new RegExp(`^${escapedName}:\\s*(.+)$`, "im");
|
|
8243
8238
|
const m = content.match(rx);
|
|
8244
|
-
if (m)
|
|
8239
|
+
if (m)
|
|
8240
|
+
return m[1].trim();
|
|
8245
8241
|
}
|
|
8246
8242
|
return null;
|
|
8247
8243
|
};
|
|
@@ -8390,9 +8386,7 @@ var UserRegistry = class {
|
|
|
8390
8386
|
console.log(`[UserRegistry] Loaded ${this.users.size} users`);
|
|
8391
8387
|
} catch (error2) {
|
|
8392
8388
|
if (error2.code === "ENOENT") {
|
|
8393
|
-
console.warn(
|
|
8394
|
-
"[UserRegistry] users.json not found, starting with empty registry"
|
|
8395
|
-
);
|
|
8389
|
+
console.warn("[UserRegistry] users.json not found, starting with empty registry");
|
|
8396
8390
|
this.users.clear();
|
|
8397
8391
|
} else {
|
|
8398
8392
|
throw error2;
|
|
@@ -8411,10 +8405,12 @@ var UserRegistry = class {
|
|
|
8411
8405
|
*/
|
|
8412
8406
|
resolveUser(nameOrId) {
|
|
8413
8407
|
const byId = this.users.get(nameOrId);
|
|
8414
|
-
if (byId)
|
|
8408
|
+
if (byId)
|
|
8409
|
+
return byId;
|
|
8415
8410
|
const slug = nameOrId.toLowerCase().replace(/\s+/g, "-");
|
|
8416
8411
|
const bySlug = this.users.get(slug);
|
|
8417
|
-
if (bySlug)
|
|
8412
|
+
if (bySlug)
|
|
8413
|
+
return bySlug;
|
|
8418
8414
|
for (const user of this.users.values()) {
|
|
8419
8415
|
if (user.name.toLowerCase() === nameOrId.toLowerCase()) {
|
|
8420
8416
|
return user;
|
|
@@ -8454,11 +8450,7 @@ var UserRegistry = class {
|
|
|
8454
8450
|
const data = {
|
|
8455
8451
|
users: Object.fromEntries(this.users.entries())
|
|
8456
8452
|
};
|
|
8457
|
-
await fs3.writeFile(
|
|
8458
|
-
this.usersFilePath,
|
|
8459
|
-
JSON.stringify(data, null, 2),
|
|
8460
|
-
"utf-8"
|
|
8461
|
-
);
|
|
8453
|
+
await fs3.writeFile(this.usersFilePath, JSON.stringify(data, null, 2), "utf-8");
|
|
8462
8454
|
}
|
|
8463
8455
|
};
|
|
8464
8456
|
|
|
@@ -9486,6 +9478,7 @@ function registerExportCommand(program2) {
|
|
|
9486
9478
|
|
|
9487
9479
|
// src/commands/finish.ts
|
|
9488
9480
|
init_esm_shims();
|
|
9481
|
+
import { execSync } from "child_process";
|
|
9489
9482
|
import path9 from "path";
|
|
9490
9483
|
|
|
9491
9484
|
// src/lib/sound-player.ts
|
|
@@ -9561,43 +9554,75 @@ async function finishTask(taskId, options) {
|
|
|
9561
9554
|
error("Task is already done");
|
|
9562
9555
|
process.exit(1);
|
|
9563
9556
|
}
|
|
9557
|
+
const configManager = new ConfigManager(monorepoRoot);
|
|
9558
|
+
const behavior = configManager.getAutomationBehavior();
|
|
9564
9559
|
if (!options.skipUpdate) {
|
|
9565
9560
|
info("Marking task as done...");
|
|
9566
9561
|
const updatedTask = await taskManager.finishTask(task.id);
|
|
9567
9562
|
success(`Task ${updatedTask.id} completed successfully! \u{1F389}`);
|
|
9568
9563
|
success(`Status changed to: ${updatedTask.status}`);
|
|
9564
|
+
if (behavior.autoCommitStatusChange) {
|
|
9565
|
+
try {
|
|
9566
|
+
execSync(
|
|
9567
|
+
`git add TASKS/task-${normalizedId}-*.md && git commit -m "docs(TASKS): task-${normalizedId} - atualiza status para done [skip-ci]"`,
|
|
9568
|
+
{ cwd: process.cwd(), stdio: "ignore" }
|
|
9569
|
+
);
|
|
9570
|
+
success("\u2713 Auto-committed status change");
|
|
9571
|
+
} catch {
|
|
9572
|
+
}
|
|
9573
|
+
}
|
|
9574
|
+
if (behavior.autoCommitFinish) {
|
|
9575
|
+
const commitType = task.type || "feat";
|
|
9576
|
+
try {
|
|
9577
|
+
execSync("git add .", { cwd: process.cwd(), stdio: "ignore" });
|
|
9578
|
+
execSync(
|
|
9579
|
+
`git commit -m "${commitType}(task-${normalizedId}): ${task.title}"`,
|
|
9580
|
+
{ cwd: process.cwd(), stdio: "ignore" }
|
|
9581
|
+
);
|
|
9582
|
+
success("\u2713 Auto-committed completed work");
|
|
9583
|
+
} catch {
|
|
9584
|
+
}
|
|
9585
|
+
}
|
|
9569
9586
|
} else {
|
|
9570
9587
|
info("Skipping status update (--skip-update flag)");
|
|
9571
9588
|
}
|
|
9572
9589
|
console.log();
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9590
|
+
if (!behavior.autoCommitFinish || options.skipUpdate) {
|
|
9591
|
+
info("Next steps (suggestions):");
|
|
9592
|
+
if (!options.skipUpdate) {
|
|
9593
|
+
const commitType = task.type || "feat";
|
|
9594
|
+
console.log(
|
|
9595
|
+
colors.secondary(
|
|
9596
|
+
` 1. Commit the status change: git add TASKS/task-${normalizedId}-*.md && git commit -m "docs(TASKS): task-${normalizedId} - atualiza status para done [skip-ci]"`
|
|
9597
|
+
)
|
|
9598
|
+
);
|
|
9599
|
+
console.log(colors.secondary(" 2. Review your changes"));
|
|
9600
|
+
console.log(
|
|
9601
|
+
colors.secondary(
|
|
9602
|
+
` 3. Commit your work: git add . && git commit -m "${commitType}(task-${normalizedId}): ${task.title}"`
|
|
9603
|
+
)
|
|
9604
|
+
);
|
|
9605
|
+
console.log(colors.secondary(" 4. Push: git push"));
|
|
9606
|
+
console.log(colors.secondary(" 5. Create a Pull Request"));
|
|
9607
|
+
} else {
|
|
9608
|
+
const commitType = task.type || "feat";
|
|
9609
|
+
console.log(colors.secondary(" 1. Review your changes"));
|
|
9610
|
+
console.log(
|
|
9611
|
+
colors.secondary(
|
|
9612
|
+
` 2. Commit your work: git add . && git commit -m "${commitType}(task-${normalizedId}): ${task.title}"`
|
|
9613
|
+
)
|
|
9614
|
+
);
|
|
9615
|
+
console.log(colors.secondary(" 3. Push: git push"));
|
|
9616
|
+
console.log(colors.secondary(" 4. Create a Pull Request"));
|
|
9617
|
+
}
|
|
9618
|
+
console.log();
|
|
9589
9619
|
} else {
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
console.log(
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
)
|
|
9596
|
-
);
|
|
9597
|
-
console.log(colors.secondary(" 3. Push: git push"));
|
|
9598
|
-
console.log(colors.secondary(" 4. Create a Pull Request"));
|
|
9620
|
+
info("All commits done automatically (autopilot mode)");
|
|
9621
|
+
info("Next steps:");
|
|
9622
|
+
console.log(colors.secondary(" 1. Push: git push"));
|
|
9623
|
+
console.log(colors.secondary(" 2. Create a Pull Request"));
|
|
9624
|
+
console.log();
|
|
9599
9625
|
}
|
|
9600
|
-
console.log();
|
|
9601
9626
|
success("Great work! \u{1F680}");
|
|
9602
9627
|
console.log();
|
|
9603
9628
|
if (options.sound !== false) {
|
|
@@ -9622,7 +9647,7 @@ init_esm_shims();
|
|
|
9622
9647
|
|
|
9623
9648
|
// src/lib/provider-installer/provider-installer.ts
|
|
9624
9649
|
init_esm_shims();
|
|
9625
|
-
import { execSync } from "child_process";
|
|
9650
|
+
import { execSync as execSync2 } from "child_process";
|
|
9626
9651
|
import { existsSync as existsSync4 } from "fs";
|
|
9627
9652
|
function detectPackageManager() {
|
|
9628
9653
|
if (existsSync4("pnpm-lock.yaml")) {
|
|
@@ -9671,7 +9696,7 @@ function installProvider(provider) {
|
|
|
9671
9696
|
default:
|
|
9672
9697
|
command = `npm install ${packageName}`;
|
|
9673
9698
|
}
|
|
9674
|
-
|
|
9699
|
+
execSync2(command, { stdio: "inherit" });
|
|
9675
9700
|
console.log(`\u2705 ${packageName} installed successfully!
|
|
9676
9701
|
`);
|
|
9677
9702
|
} catch (error2) {
|
|
@@ -14180,7 +14205,7 @@ Add any relevant notes or links here.
|
|
|
14180
14205
|
|
|
14181
14206
|
// src/commands/pause.ts
|
|
14182
14207
|
init_esm_shims();
|
|
14183
|
-
import { execSync as
|
|
14208
|
+
import { execSync as execSync3 } from "child_process";
|
|
14184
14209
|
import path13 from "path";
|
|
14185
14210
|
var pauseCommand = defineCommand({
|
|
14186
14211
|
name: "pause <task-id>",
|
|
@@ -14226,18 +14251,25 @@ async function pauseTask(taskId, options) {
|
|
|
14226
14251
|
process.exit(1);
|
|
14227
14252
|
}
|
|
14228
14253
|
const commitMessage = options.message || `WIP: task-${normalizedId} - ${task.title}`;
|
|
14254
|
+
const configManager = new ConfigManager(monorepoRoot);
|
|
14255
|
+
const behavior = configManager.getAutomationBehavior();
|
|
14229
14256
|
if (options.skipCommit) {
|
|
14230
14257
|
info("Would create commit with message:");
|
|
14231
14258
|
console.log(colors.highlight(` "${commitMessage}"`));
|
|
14232
14259
|
console.log();
|
|
14233
14260
|
info("Use without --skip-commit to actually commit");
|
|
14261
|
+
} else if (!behavior.autoCommitPause) {
|
|
14262
|
+
info("Commit suggestion (manual mode):");
|
|
14263
|
+
console.log(colors.secondary(` git add -A && git commit -m "${commitMessage}"`));
|
|
14264
|
+
console.log();
|
|
14265
|
+
info("Status will be updated to pending");
|
|
14234
14266
|
} else {
|
|
14235
14267
|
info("Creating commit...");
|
|
14236
14268
|
console.log(colors.secondary(` Message: "${commitMessage}"`));
|
|
14237
14269
|
console.log();
|
|
14238
14270
|
try {
|
|
14239
|
-
|
|
14240
|
-
|
|
14271
|
+
execSync3("git add -A", { cwd: process.cwd(), stdio: "ignore" });
|
|
14272
|
+
execSync3(`git commit -m "${commitMessage}"`, {
|
|
14241
14273
|
cwd: process.cwd(),
|
|
14242
14274
|
stdio: "ignore"
|
|
14243
14275
|
});
|
|
@@ -14246,7 +14278,7 @@ async function pauseTask(taskId, options) {
|
|
|
14246
14278
|
const updatedTask = { ...task, status: "pending" };
|
|
14247
14279
|
await taskProvider.updateTask(updatedTask);
|
|
14248
14280
|
success("Task paused successfully!");
|
|
14249
|
-
|
|
14281
|
+
success("\u2713 Auto-committed work in progress");
|
|
14250
14282
|
info("Status updated to pending");
|
|
14251
14283
|
console.log();
|
|
14252
14284
|
info("Next steps:");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "taskin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Task management system integrated with Git workflows",
|
|
5
5
|
"motivation": "Provide a CLI tool for task management integrated with Git workflows",
|
|
6
6
|
"solve": "Simplifies task tracking and management directly from the command line",
|
|
@@ -68,10 +68,10 @@
|
|
|
68
68
|
"LICENSE"
|
|
69
69
|
],
|
|
70
70
|
"dependencies": {
|
|
71
|
-
"@opentask/taskin-git-utils": "^2.
|
|
72
|
-
"@opentask/taskin-task-manager": "^1.0.
|
|
73
|
-
"@opentask/taskin-task-server-mcp": "^0.1.
|
|
74
|
-
"@opentask/taskin-task-server-ws": "^0.1.
|
|
71
|
+
"@opentask/taskin-git-utils": "^2.1.1",
|
|
72
|
+
"@opentask/taskin-task-manager": "^1.0.9",
|
|
73
|
+
"@opentask/taskin-task-server-mcp": "^0.1.7",
|
|
74
|
+
"@opentask/taskin-task-server-ws": "^0.1.4",
|
|
75
75
|
"@types/express": "^5.0.5",
|
|
76
76
|
"@types/inquirer": "^9.0.9",
|
|
77
77
|
"@types/play-sound": "^1.1.2",
|
|
@@ -82,9 +82,9 @@
|
|
|
82
82
|
"play-sound": "^1.1.6",
|
|
83
83
|
"ws": "^8.18.3",
|
|
84
84
|
"zod": "^3.25.76",
|
|
85
|
-
"@opentask/taskin-file-system-provider": "2.2.
|
|
85
|
+
"@opentask/taskin-file-system-provider": "2.2.1",
|
|
86
86
|
"@opentask/taskin-utils": "1.1.0",
|
|
87
|
-
"@opentask/taskin-types": "1.0.
|
|
87
|
+
"@opentask/taskin-types": "1.0.6"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"@types/node": "^20.19.24",
|