@knowsuchagency/fulcrum 1.4.0 → 1.5.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/bin/fulcrum.js +542 -181
- package/dist/assets/{index-J3L6hPet.js → index-fIJu9jIH.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +1 -1
package/bin/fulcrum.js
CHANGED
|
@@ -43866,12 +43866,16 @@ function registerTools(server, client) {
|
|
|
43866
43866
|
return handleToolError(err);
|
|
43867
43867
|
}
|
|
43868
43868
|
});
|
|
43869
|
-
server.tool("get_task", "Get details of a specific task by ID", {
|
|
43869
|
+
server.tool("get_task", "Get details of a specific task by ID, including dependencies and attachments", {
|
|
43870
43870
|
id: exports_external.string().describe("Task ID (UUID)")
|
|
43871
43871
|
}, async ({ id }) => {
|
|
43872
43872
|
try {
|
|
43873
|
-
const task = await
|
|
43874
|
-
|
|
43873
|
+
const [task, dependencies, attachments] = await Promise.all([
|
|
43874
|
+
client.getTask(id),
|
|
43875
|
+
client.getTaskDependencies(id),
|
|
43876
|
+
client.listTaskAttachments(id)
|
|
43877
|
+
]);
|
|
43878
|
+
return formatSuccess({ ...task, dependencies, attachments });
|
|
43875
43879
|
} catch (err) {
|
|
43876
43880
|
return handleToolError(err);
|
|
43877
43881
|
}
|
|
@@ -46168,15 +46172,62 @@ var STATUS_MAP = {
|
|
|
46168
46172
|
cancel: "CANCELED",
|
|
46169
46173
|
"in-progress": "IN_PROGRESS"
|
|
46170
46174
|
};
|
|
46171
|
-
function formatTask(task) {
|
|
46175
|
+
function formatTask(task, dependencies, attachments) {
|
|
46172
46176
|
console.log(`${task.title}`);
|
|
46173
|
-
console.log(` ID:
|
|
46174
|
-
console.log(` Status:
|
|
46175
|
-
|
|
46177
|
+
console.log(` ID: ${task.id}`);
|
|
46178
|
+
console.log(` Status: ${task.status}`);
|
|
46179
|
+
if (task.description) {
|
|
46180
|
+
console.log(` Description: ${task.description}`);
|
|
46181
|
+
}
|
|
46182
|
+
if (task.repoName)
|
|
46183
|
+
console.log(` Repo: ${task.repoName}`);
|
|
46176
46184
|
if (task.branch)
|
|
46177
|
-
console.log(` Branch:
|
|
46185
|
+
console.log(` Branch: ${task.branch}`);
|
|
46186
|
+
if (task.worktreePath)
|
|
46187
|
+
console.log(` Worktree: ${task.worktreePath}`);
|
|
46178
46188
|
if (task.prUrl)
|
|
46179
|
-
console.log(` PR:
|
|
46189
|
+
console.log(` PR: ${task.prUrl}`);
|
|
46190
|
+
if (task.links && task.links.length > 0) {
|
|
46191
|
+
console.log(` Links: ${task.links.map((l2) => l2.label || l2.url).join(", ")}`);
|
|
46192
|
+
}
|
|
46193
|
+
if (task.labels && task.labels.length > 0) {
|
|
46194
|
+
console.log(` Labels: ${task.labels.join(", ")}`);
|
|
46195
|
+
}
|
|
46196
|
+
if (task.dueDate)
|
|
46197
|
+
console.log(` Due: ${task.dueDate}`);
|
|
46198
|
+
if (task.projectId)
|
|
46199
|
+
console.log(` Project: ${task.projectId}`);
|
|
46200
|
+
console.log(` Agent: ${task.agent}`);
|
|
46201
|
+
if (task.aiMode)
|
|
46202
|
+
console.log(` AI Mode: ${task.aiMode}`);
|
|
46203
|
+
if (task.agentOptions && Object.keys(task.agentOptions).length > 0) {
|
|
46204
|
+
console.log(` Options: ${JSON.stringify(task.agentOptions)}`);
|
|
46205
|
+
}
|
|
46206
|
+
if (dependencies) {
|
|
46207
|
+
if (dependencies.isBlocked) {
|
|
46208
|
+
console.log(` Blocked: Yes`);
|
|
46209
|
+
}
|
|
46210
|
+
if (dependencies.dependsOn.length > 0) {
|
|
46211
|
+
console.log(` Depends on: ${dependencies.dependsOn.length} task(s)`);
|
|
46212
|
+
for (const dep of dependencies.dependsOn) {
|
|
46213
|
+
if (dep.task) {
|
|
46214
|
+
console.log(` - ${dep.task.title} [${dep.task.status}]`);
|
|
46215
|
+
}
|
|
46216
|
+
}
|
|
46217
|
+
}
|
|
46218
|
+
if (dependencies.dependents.length > 0) {
|
|
46219
|
+
console.log(` Blocking: ${dependencies.dependents.length} task(s)`);
|
|
46220
|
+
}
|
|
46221
|
+
}
|
|
46222
|
+
if (attachments && attachments.length > 0) {
|
|
46223
|
+
console.log(` Attachments: ${attachments.length} file(s)`);
|
|
46224
|
+
}
|
|
46225
|
+
if (task.notes) {
|
|
46226
|
+
console.log(` Notes: ${task.notes}`);
|
|
46227
|
+
}
|
|
46228
|
+
console.log(` Created: ${task.createdAt}`);
|
|
46229
|
+
if (task.startedAt)
|
|
46230
|
+
console.log(` Started: ${task.startedAt}`);
|
|
46180
46231
|
}
|
|
46181
46232
|
async function findCurrentTask(client, pathOverride) {
|
|
46182
46233
|
if (process.env.FULCRUM_TASK_ID) {
|
|
@@ -46204,9 +46255,17 @@ async function handleCurrentTaskCommand(action, rest, flags) {
|
|
|
46204
46255
|
if (!action) {
|
|
46205
46256
|
const task2 = await findCurrentTask(client, pathOverride);
|
|
46206
46257
|
if (isJsonOutput()) {
|
|
46207
|
-
|
|
46258
|
+
const [dependencies, attachments] = await Promise.all([
|
|
46259
|
+
client.getTaskDependencies(task2.id),
|
|
46260
|
+
client.listTaskAttachments(task2.id)
|
|
46261
|
+
]);
|
|
46262
|
+
output({ ...task2, dependencies, attachments });
|
|
46208
46263
|
} else {
|
|
46209
|
-
|
|
46264
|
+
const [dependencies, attachments] = await Promise.all([
|
|
46265
|
+
client.getTaskDependencies(task2.id),
|
|
46266
|
+
client.listTaskAttachments(task2.id)
|
|
46267
|
+
]);
|
|
46268
|
+
formatTask(task2, dependencies, attachments);
|
|
46210
46269
|
}
|
|
46211
46270
|
return;
|
|
46212
46271
|
}
|
|
@@ -46297,22 +46356,62 @@ init_client();
|
|
|
46297
46356
|
import { basename as basename3 } from "path";
|
|
46298
46357
|
init_errors();
|
|
46299
46358
|
var VALID_STATUSES = ["TO_DO", "IN_PROGRESS", "IN_REVIEW", "CANCELED"];
|
|
46300
|
-
function formatTask2(task) {
|
|
46359
|
+
function formatTask2(task, dependencies, attachments) {
|
|
46301
46360
|
console.log(`${task.title}`);
|
|
46302
|
-
console.log(` ID:
|
|
46303
|
-
console.log(` Status:
|
|
46361
|
+
console.log(` ID: ${task.id}`);
|
|
46362
|
+
console.log(` Status: ${task.status}`);
|
|
46363
|
+
if (task.description) {
|
|
46364
|
+
console.log(` Description: ${task.description}`);
|
|
46365
|
+
}
|
|
46304
46366
|
if (task.repoName)
|
|
46305
|
-
console.log(` Repo:
|
|
46367
|
+
console.log(` Repo: ${task.repoName}`);
|
|
46306
46368
|
if (task.branch)
|
|
46307
|
-
console.log(` Branch:
|
|
46369
|
+
console.log(` Branch: ${task.branch}`);
|
|
46370
|
+
if (task.worktreePath)
|
|
46371
|
+
console.log(` Worktree: ${task.worktreePath}`);
|
|
46308
46372
|
if (task.prUrl)
|
|
46309
|
-
console.log(` PR:
|
|
46310
|
-
if (task.
|
|
46311
|
-
console.log(`
|
|
46312
|
-
|
|
46313
|
-
|
|
46373
|
+
console.log(` PR: ${task.prUrl}`);
|
|
46374
|
+
if (task.links && task.links.length > 0) {
|
|
46375
|
+
console.log(` Links: ${task.links.map((l2) => l2.label || l2.url).join(", ")}`);
|
|
46376
|
+
}
|
|
46377
|
+
if (task.labels && task.labels.length > 0) {
|
|
46378
|
+
console.log(` Labels: ${task.labels.join(", ")}`);
|
|
46379
|
+
}
|
|
46314
46380
|
if (task.dueDate)
|
|
46315
|
-
console.log(` Due:
|
|
46381
|
+
console.log(` Due: ${task.dueDate}`);
|
|
46382
|
+
if (task.projectId)
|
|
46383
|
+
console.log(` Project: ${task.projectId}`);
|
|
46384
|
+
console.log(` Agent: ${task.agent}`);
|
|
46385
|
+
if (task.aiMode)
|
|
46386
|
+
console.log(` AI Mode: ${task.aiMode}`);
|
|
46387
|
+
if (task.agentOptions && Object.keys(task.agentOptions).length > 0) {
|
|
46388
|
+
console.log(` Options: ${JSON.stringify(task.agentOptions)}`);
|
|
46389
|
+
}
|
|
46390
|
+
if (dependencies) {
|
|
46391
|
+
if (dependencies.isBlocked) {
|
|
46392
|
+
console.log(` Blocked: Yes`);
|
|
46393
|
+
}
|
|
46394
|
+
if (dependencies.dependsOn.length > 0) {
|
|
46395
|
+
console.log(` Depends on: ${dependencies.dependsOn.length} task(s)`);
|
|
46396
|
+
for (const dep of dependencies.dependsOn) {
|
|
46397
|
+
if (dep.task) {
|
|
46398
|
+
console.log(` - ${dep.task.title} [${dep.task.status}]`);
|
|
46399
|
+
}
|
|
46400
|
+
}
|
|
46401
|
+
}
|
|
46402
|
+
if (dependencies.dependents.length > 0) {
|
|
46403
|
+
console.log(` Blocking: ${dependencies.dependents.length} task(s)`);
|
|
46404
|
+
}
|
|
46405
|
+
}
|
|
46406
|
+
if (attachments && attachments.length > 0) {
|
|
46407
|
+
console.log(` Attachments: ${attachments.length} file(s)`);
|
|
46408
|
+
}
|
|
46409
|
+
if (task.notes) {
|
|
46410
|
+
console.log(` Notes: ${task.notes}`);
|
|
46411
|
+
}
|
|
46412
|
+
console.log(` Created: ${task.createdAt}`);
|
|
46413
|
+
if (task.startedAt)
|
|
46414
|
+
console.log(` Started: ${task.startedAt}`);
|
|
46316
46415
|
}
|
|
46317
46416
|
function formatTaskList(tasks) {
|
|
46318
46417
|
if (tasks.length === 0) {
|
|
@@ -46394,10 +46493,14 @@ async function handleTasksCommand(action, positional, flags) {
|
|
|
46394
46493
|
throw new CliError("MISSING_ID", "Task ID required", ExitCodes.INVALID_ARGS);
|
|
46395
46494
|
}
|
|
46396
46495
|
const task = await client.getTask(id);
|
|
46496
|
+
const [dependencies, attachments] = await Promise.all([
|
|
46497
|
+
client.getTaskDependencies(id),
|
|
46498
|
+
client.listTaskAttachments(id)
|
|
46499
|
+
]);
|
|
46397
46500
|
if (isJsonOutput()) {
|
|
46398
|
-
output(task);
|
|
46501
|
+
output({ ...task, dependencies, attachments });
|
|
46399
46502
|
} else {
|
|
46400
|
-
formatTask2(task);
|
|
46503
|
+
formatTask2(task, dependencies, attachments);
|
|
46401
46504
|
}
|
|
46402
46505
|
break;
|
|
46403
46506
|
}
|
|
@@ -46649,8 +46752,98 @@ Labels:`);
|
|
|
46649
46752
|
}
|
|
46650
46753
|
break;
|
|
46651
46754
|
}
|
|
46755
|
+
case "attachments": {
|
|
46756
|
+
const [subAction, taskIdOrFile, fileOrAttachmentId] = positional;
|
|
46757
|
+
if (!subAction || subAction === "help") {
|
|
46758
|
+
console.log("Usage:");
|
|
46759
|
+
console.log(" fulcrum tasks attachments list <task-id>");
|
|
46760
|
+
console.log(" fulcrum tasks attachments upload <task-id> <file-path>");
|
|
46761
|
+
console.log(" fulcrum tasks attachments delete <task-id> <attachment-id>");
|
|
46762
|
+
console.log(" fulcrum tasks attachments path <task-id> <attachment-id>");
|
|
46763
|
+
break;
|
|
46764
|
+
}
|
|
46765
|
+
if (subAction === "list") {
|
|
46766
|
+
const taskId = taskIdOrFile;
|
|
46767
|
+
if (!taskId) {
|
|
46768
|
+
throw new CliError("MISSING_ID", "Task ID required", ExitCodes.INVALID_ARGS);
|
|
46769
|
+
}
|
|
46770
|
+
const attachments = await client.listTaskAttachments(taskId);
|
|
46771
|
+
if (isJsonOutput()) {
|
|
46772
|
+
output(attachments);
|
|
46773
|
+
} else {
|
|
46774
|
+
if (attachments.length === 0) {
|
|
46775
|
+
console.log("No attachments");
|
|
46776
|
+
} else {
|
|
46777
|
+
console.log(`
|
|
46778
|
+
Attachments (${attachments.length}):`);
|
|
46779
|
+
for (const att of attachments) {
|
|
46780
|
+
console.log(` ${att.filename}`);
|
|
46781
|
+
console.log(` ID: ${att.id}`);
|
|
46782
|
+
console.log(` Type: ${att.mimeType}`);
|
|
46783
|
+
console.log(` Size: ${att.size} bytes`);
|
|
46784
|
+
}
|
|
46785
|
+
}
|
|
46786
|
+
}
|
|
46787
|
+
break;
|
|
46788
|
+
}
|
|
46789
|
+
if (subAction === "upload") {
|
|
46790
|
+
const taskId = taskIdOrFile;
|
|
46791
|
+
const filePath = fileOrAttachmentId;
|
|
46792
|
+
if (!taskId) {
|
|
46793
|
+
throw new CliError("MISSING_ID", "Task ID required", ExitCodes.INVALID_ARGS);
|
|
46794
|
+
}
|
|
46795
|
+
if (!filePath) {
|
|
46796
|
+
throw new CliError("MISSING_FILE", "File path required", ExitCodes.INVALID_ARGS);
|
|
46797
|
+
}
|
|
46798
|
+
const attachment = await client.uploadTaskAttachment(taskId, filePath);
|
|
46799
|
+
if (isJsonOutput()) {
|
|
46800
|
+
output(attachment);
|
|
46801
|
+
} else {
|
|
46802
|
+
console.log(`Uploaded: ${attachment.filename}`);
|
|
46803
|
+
console.log(` ID: ${attachment.id}`);
|
|
46804
|
+
}
|
|
46805
|
+
break;
|
|
46806
|
+
}
|
|
46807
|
+
if (subAction === "delete") {
|
|
46808
|
+
const taskId = taskIdOrFile;
|
|
46809
|
+
const attachmentId = fileOrAttachmentId;
|
|
46810
|
+
if (!taskId) {
|
|
46811
|
+
throw new CliError("MISSING_ID", "Task ID required", ExitCodes.INVALID_ARGS);
|
|
46812
|
+
}
|
|
46813
|
+
if (!attachmentId) {
|
|
46814
|
+
throw new CliError("MISSING_ATTACHMENT_ID", "Attachment ID required", ExitCodes.INVALID_ARGS);
|
|
46815
|
+
}
|
|
46816
|
+
await client.deleteTaskAttachment(taskId, attachmentId);
|
|
46817
|
+
if (isJsonOutput()) {
|
|
46818
|
+
output({ success: true, deleted: attachmentId });
|
|
46819
|
+
} else {
|
|
46820
|
+
console.log(`Deleted attachment: ${attachmentId}`);
|
|
46821
|
+
}
|
|
46822
|
+
break;
|
|
46823
|
+
}
|
|
46824
|
+
if (subAction === "path") {
|
|
46825
|
+
const taskId = taskIdOrFile;
|
|
46826
|
+
const attachmentId = fileOrAttachmentId;
|
|
46827
|
+
if (!taskId) {
|
|
46828
|
+
throw new CliError("MISSING_ID", "Task ID required", ExitCodes.INVALID_ARGS);
|
|
46829
|
+
}
|
|
46830
|
+
if (!attachmentId) {
|
|
46831
|
+
throw new CliError("MISSING_ATTACHMENT_ID", "Attachment ID required", ExitCodes.INVALID_ARGS);
|
|
46832
|
+
}
|
|
46833
|
+
const result = await client.getTaskAttachmentPath(taskId, attachmentId);
|
|
46834
|
+
if (isJsonOutput()) {
|
|
46835
|
+
output(result);
|
|
46836
|
+
} else {
|
|
46837
|
+
console.log(`Path: ${result.path}`);
|
|
46838
|
+
console.log(`Filename: ${result.filename}`);
|
|
46839
|
+
console.log(`Type: ${result.mimeType}`);
|
|
46840
|
+
}
|
|
46841
|
+
break;
|
|
46842
|
+
}
|
|
46843
|
+
throw new CliError("UNKNOWN_SUBACTION", `Unknown attachments action: ${subAction}. Valid: list, upload, delete, path`, ExitCodes.INVALID_ARGS);
|
|
46844
|
+
}
|
|
46652
46845
|
default:
|
|
46653
|
-
throw new CliError("UNKNOWN_ACTION", `Unknown action: ${action}. Valid: list, get, create, update, move, delete, add-label, remove-label, set-due-date, add-dependency, remove-dependency, list-dependencies, labels`, ExitCodes.INVALID_ARGS);
|
|
46846
|
+
throw new CliError("UNKNOWN_ACTION", `Unknown action: ${action}. Valid: list, get, create, update, move, delete, add-label, remove-label, set-due-date, add-dependency, remove-dependency, list-dependencies, labels, attachments`, ExitCodes.INVALID_ARGS);
|
|
46654
46847
|
}
|
|
46655
46848
|
}
|
|
46656
46849
|
|
|
@@ -47618,7 +47811,7 @@ async function handleFsCommand(action, positional, flags) {
|
|
|
47618
47811
|
// cli/src/commands/up.ts
|
|
47619
47812
|
import { spawn } from "child_process";
|
|
47620
47813
|
import { existsSync as existsSync4 } from "fs";
|
|
47621
|
-
import { dirname as
|
|
47814
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
47622
47815
|
import { fileURLToPath } from "url";
|
|
47623
47816
|
init_errors();
|
|
47624
47817
|
|
|
@@ -47902,22 +48095,38 @@ function installUv() {
|
|
|
47902
48095
|
|
|
47903
48096
|
// cli/src/commands/claude.ts
|
|
47904
48097
|
init_errors();
|
|
48098
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
47905
48099
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, existsSync as existsSync3, rmSync, readFileSync as readFileSync4 } from "fs";
|
|
47906
48100
|
import { homedir as homedir2 } from "os";
|
|
47907
|
-
import { join as join3 } from "path";
|
|
48101
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
47908
48102
|
|
|
47909
|
-
// plugins/fulcrum/.claude-plugin/
|
|
47910
|
-
var
|
|
48103
|
+
// plugins/fulcrum/.claude-plugin/marketplace.json
|
|
48104
|
+
var marketplace_default = `{
|
|
47911
48105
|
"name": "fulcrum",
|
|
47912
|
-
"
|
|
47913
|
-
"version": "1.4.0",
|
|
47914
|
-
"author": {
|
|
48106
|
+
"owner": {
|
|
47915
48107
|
"name": "Fulcrum"
|
|
47916
48108
|
},
|
|
47917
|
-
"
|
|
47918
|
-
|
|
47919
|
-
|
|
47920
|
-
|
|
48109
|
+
"plugins": [
|
|
48110
|
+
{
|
|
48111
|
+
"name": "fulcrum",
|
|
48112
|
+
"source": "./",
|
|
48113
|
+
"description": "Task orchestration for Claude Code",
|
|
48114
|
+
"version": "1.5.0",
|
|
48115
|
+
"skills": [
|
|
48116
|
+
"./skills/fulcrum"
|
|
48117
|
+
],
|
|
48118
|
+
"keywords": [
|
|
48119
|
+
"fulcrum",
|
|
48120
|
+
"task",
|
|
48121
|
+
"orchestration",
|
|
48122
|
+
"worktree"
|
|
48123
|
+
]
|
|
48124
|
+
}
|
|
48125
|
+
],
|
|
48126
|
+
"metadata": {
|
|
48127
|
+
"description": "Fulcrum task orchestration plugin marketplace",
|
|
48128
|
+
"version": "1.0.0"
|
|
48129
|
+
}
|
|
47921
48130
|
}
|
|
47922
48131
|
`;
|
|
47923
48132
|
|
|
@@ -47984,38 +48193,25 @@ Send a notification: \`fulcrum notify $ARGUMENTS\`
|
|
|
47984
48193
|
Format: fulcrum notify "Title" "Message body"
|
|
47985
48194
|
`;
|
|
47986
48195
|
|
|
47987
|
-
// plugins/fulcrum/
|
|
47988
|
-
var linear_default = `---
|
|
47989
|
-
description: Link a Linear ticket to the current fulcrum task
|
|
47990
|
-
---
|
|
47991
|
-
Link the Linear ticket to this task: \`fulcrum current-task linear $ARGUMENTS\`
|
|
47992
|
-
`;
|
|
47993
|
-
|
|
47994
|
-
// plugins/fulcrum/commands/review.md
|
|
47995
|
-
var review_default = `---
|
|
47996
|
-
description: Mark the current fulcrum task as ready for review
|
|
47997
|
-
---
|
|
47998
|
-
Mark this task ready for review: \`fulcrum current-task review\`
|
|
47999
|
-
|
|
48000
|
-
This sends a notification to the user.
|
|
48001
|
-
`;
|
|
48002
|
-
|
|
48003
|
-
// plugins/fulcrum/skills/vibora/SKILL.md
|
|
48196
|
+
// plugins/fulcrum/skills/fulcrum/SKILL.md
|
|
48004
48197
|
var SKILL_default = `---
|
|
48005
48198
|
name: fulcrum
|
|
48006
|
-
description:
|
|
48199
|
+
description: AI orchestration and task management platform. Use this skill when working in a Fulcrum task worktree, managing tasks/projects, or interacting with the Fulcrum server.
|
|
48007
48200
|
---
|
|
48008
48201
|
|
|
48009
|
-
# Fulcrum - AI
|
|
48202
|
+
# Fulcrum - AI Orchestration Platform
|
|
48010
48203
|
|
|
48011
48204
|
## Overview
|
|
48012
48205
|
|
|
48013
|
-
Fulcrum is
|
|
48206
|
+
Fulcrum is an AI orchestration and task management platform. It provides task tracking, project management, and tools for AI agents to work autonomously across isolated git worktrees.
|
|
48014
48207
|
|
|
48015
|
-
**
|
|
48016
|
-
-
|
|
48017
|
-
-
|
|
48018
|
-
-
|
|
48208
|
+
**Key Features:**
|
|
48209
|
+
- Task management with kanban boards and status tracking
|
|
48210
|
+
- Project and repository organization
|
|
48211
|
+
- Git worktree isolation for parallel development
|
|
48212
|
+
- Docker Compose app deployment
|
|
48213
|
+
- Multi-channel notifications
|
|
48214
|
+
- MCP tools for AI agent integration
|
|
48019
48215
|
|
|
48020
48216
|
## When to Use This Skill
|
|
48021
48217
|
|
|
@@ -48023,9 +48219,9 @@ Use the Fulcrum CLI when:
|
|
|
48023
48219
|
- **Working in a task worktree** - Use \`current-task\` commands to manage your current task
|
|
48024
48220
|
- **Updating task status** - Mark tasks as in-progress, ready for review, done, or canceled
|
|
48025
48221
|
- **Linking PRs** - Associate a GitHub PR with the current task
|
|
48026
|
-
- **Linking Linear tickets** - Connect a Linear issue to the current task
|
|
48027
48222
|
- **Linking URLs** - Attach any relevant URLs (design docs, specs, external resources) to the task
|
|
48028
48223
|
- **Sending notifications** - Alert the user when work is complete or needs attention
|
|
48224
|
+
- **Managing projects and repositories** - Create, update, and organize projects
|
|
48029
48225
|
|
|
48030
48226
|
Use the Fulcrum MCP tools when:
|
|
48031
48227
|
- **Executing commands remotely** - Run shell commands on the Fulcrum server from Claude Desktop
|
|
@@ -48038,7 +48234,7 @@ Use the Fulcrum MCP tools when:
|
|
|
48038
48234
|
When running inside a Fulcrum task worktree, use these commands to manage the current task:
|
|
48039
48235
|
|
|
48040
48236
|
\`\`\`bash
|
|
48041
|
-
# Get current task info (
|
|
48237
|
+
# Get current task info (comprehensive output with dependencies, attachments, etc.)
|
|
48042
48238
|
fulcrum current-task
|
|
48043
48239
|
|
|
48044
48240
|
# Update task status
|
|
@@ -48075,7 +48271,7 @@ fulcrum tasks list --label="bug" # Filter by label
|
|
|
48075
48271
|
fulcrum tasks labels # Show all labels with counts
|
|
48076
48272
|
fulcrum tasks labels --search="comm" # Find labels matching substring
|
|
48077
48273
|
|
|
48078
|
-
# Get a specific task
|
|
48274
|
+
# Get a specific task (includes dependencies and attachments)
|
|
48079
48275
|
fulcrum tasks get <task-id>
|
|
48080
48276
|
|
|
48081
48277
|
# Create a new task
|
|
@@ -48090,6 +48286,25 @@ fulcrum tasks move <task-id> --status=IN_REVIEW
|
|
|
48090
48286
|
# Delete a task
|
|
48091
48287
|
fulcrum tasks delete <task-id>
|
|
48092
48288
|
fulcrum tasks delete <task-id> --delete-worktree # Also delete worktree
|
|
48289
|
+
|
|
48290
|
+
# Labels
|
|
48291
|
+
fulcrum tasks add-label <task-id> <label>
|
|
48292
|
+
fulcrum tasks remove-label <task-id> <label>
|
|
48293
|
+
|
|
48294
|
+
# Due dates
|
|
48295
|
+
fulcrum tasks set-due-date <task-id> 2026-01-25 # Set due date
|
|
48296
|
+
fulcrum tasks set-due-date <task-id> none # Clear due date
|
|
48297
|
+
|
|
48298
|
+
# Dependencies
|
|
48299
|
+
fulcrum tasks add-dependency <task-id> <depends-on-task-id>
|
|
48300
|
+
fulcrum tasks remove-dependency <task-id> <dependency-id>
|
|
48301
|
+
fulcrum tasks list-dependencies <task-id>
|
|
48302
|
+
|
|
48303
|
+
# Attachments
|
|
48304
|
+
fulcrum tasks attachments list <task-id>
|
|
48305
|
+
fulcrum tasks attachments upload <task-id> <file-path>
|
|
48306
|
+
fulcrum tasks attachments delete <task-id> <attachment-id>
|
|
48307
|
+
fulcrum tasks attachments path <task-id> <attachment-id> # Get local file path
|
|
48093
48308
|
\`\`\`
|
|
48094
48309
|
|
|
48095
48310
|
### notifications
|
|
@@ -48123,7 +48338,28 @@ fulcrum notifications set slack webhookUrl <url>
|
|
|
48123
48338
|
fulcrum up # Start Fulcrum server daemon
|
|
48124
48339
|
fulcrum down # Stop Fulcrum server
|
|
48125
48340
|
fulcrum status # Check if server is running
|
|
48126
|
-
fulcrum
|
|
48341
|
+
fulcrum doctor # Check all dependencies and versions
|
|
48342
|
+
\`\`\`
|
|
48343
|
+
|
|
48344
|
+
### Configuration
|
|
48345
|
+
|
|
48346
|
+
\`\`\`bash
|
|
48347
|
+
fulcrum config list # List all config values
|
|
48348
|
+
fulcrum config get <key> # Get a specific value
|
|
48349
|
+
fulcrum config set <key> <value> # Set a value
|
|
48350
|
+
fulcrum config reset <key> # Reset to default
|
|
48351
|
+
\`\`\`
|
|
48352
|
+
|
|
48353
|
+
### Agent Plugin Installation
|
|
48354
|
+
|
|
48355
|
+
\`\`\`bash
|
|
48356
|
+
# Claude Code integration
|
|
48357
|
+
fulcrum claude install # Install Fulcrum plugin for Claude Code
|
|
48358
|
+
fulcrum claude uninstall # Uninstall plugin
|
|
48359
|
+
|
|
48360
|
+
# OpenCode integration
|
|
48361
|
+
fulcrum opencode install # Install Fulcrum plugin for OpenCode
|
|
48362
|
+
fulcrum opencode uninstall # Uninstall plugin
|
|
48127
48363
|
\`\`\`
|
|
48128
48364
|
|
|
48129
48365
|
### Git Operations
|
|
@@ -48131,7 +48367,15 @@ fulcrum health # Check server health
|
|
|
48131
48367
|
\`\`\`bash
|
|
48132
48368
|
fulcrum git status # Git status for current worktree
|
|
48133
48369
|
fulcrum git diff # Git diff for current worktree
|
|
48370
|
+
fulcrum git diff --staged # Show staged changes only
|
|
48371
|
+
fulcrum git branches --repo=/path/to/repo # List branches
|
|
48372
|
+
\`\`\`
|
|
48373
|
+
|
|
48374
|
+
### Worktrees
|
|
48375
|
+
|
|
48376
|
+
\`\`\`bash
|
|
48134
48377
|
fulcrum worktrees list # List all worktrees
|
|
48378
|
+
fulcrum worktrees delete --path=/path/to/worktree # Delete a worktree
|
|
48135
48379
|
\`\`\`
|
|
48136
48380
|
|
|
48137
48381
|
### projects
|
|
@@ -48314,10 +48558,11 @@ These flags work with most commands:
|
|
|
48314
48558
|
|
|
48315
48559
|
- \`--port=<port>\` - Server port (default: 7777)
|
|
48316
48560
|
- \`--url=<url>\` - Override full server URL
|
|
48317
|
-
- \`--
|
|
48561
|
+
- \`--json\` - Output as JSON for programmatic use
|
|
48318
48562
|
|
|
48319
48563
|
## Task Statuses
|
|
48320
48564
|
|
|
48565
|
+
- \`TO_DO\` - Task not yet started
|
|
48321
48566
|
- \`IN_PROGRESS\` - Task is being worked on
|
|
48322
48567
|
- \`IN_REVIEW\` - Task is complete and awaiting review
|
|
48323
48568
|
- \`DONE\` - Task is finished
|
|
@@ -48354,7 +48599,7 @@ search_tools { category: "filesystem" }
|
|
|
48354
48599
|
### Task Tools
|
|
48355
48600
|
|
|
48356
48601
|
- \`list_tasks\` - List tasks with flexible filtering (search, labels, statuses, date range, overdue)
|
|
48357
|
-
- \`get_task\` - Get task details by ID
|
|
48602
|
+
- \`get_task\` - Get task details by ID (includes dependencies and attachments)
|
|
48358
48603
|
- \`create_task\` - Create a new task with worktree
|
|
48359
48604
|
- \`update_task\` - Update task metadata
|
|
48360
48605
|
- \`delete_task\` - Delete a task
|
|
@@ -48362,10 +48607,24 @@ search_tools { category: "filesystem" }
|
|
|
48362
48607
|
- \`add_task_link\` - Add URL link to task
|
|
48363
48608
|
- \`remove_task_link\` - Remove link from task
|
|
48364
48609
|
- \`list_task_links\` - List all task links
|
|
48365
|
-
- \`
|
|
48366
|
-
- \`
|
|
48610
|
+
- \`add_task_tag\` - Add a label to a task (returns similar labels to catch typos)
|
|
48611
|
+
- \`remove_task_tag\` - Remove a label from a task
|
|
48367
48612
|
- \`set_task_due_date\` - Set or clear task due date
|
|
48368
|
-
- \`
|
|
48613
|
+
- \`list_tags\` - List all unique labels in use with optional search
|
|
48614
|
+
|
|
48615
|
+
#### Task Dependencies
|
|
48616
|
+
|
|
48617
|
+
- \`get_task_dependencies\` - Get dependencies and dependents of a task, and whether it is blocked
|
|
48618
|
+
- \`add_task_dependency\` - Add a dependency (task cannot start until dependency is done)
|
|
48619
|
+
- \`remove_task_dependency\` - Remove a dependency
|
|
48620
|
+
- \`get_task_dependency_graph\` - Get all tasks and dependencies as a graph for visualization
|
|
48621
|
+
|
|
48622
|
+
#### Task Attachments
|
|
48623
|
+
|
|
48624
|
+
- \`list_task_attachments\` - List all file attachments for a task
|
|
48625
|
+
- \`upload_task_attachment\` - Upload a file to a task from a local path
|
|
48626
|
+
- \`delete_task_attachment\` - Delete a file attachment from a task
|
|
48627
|
+
- \`get_task_attachment_path\` - Get the local file path for a task attachment
|
|
48369
48628
|
|
|
48370
48629
|
#### Task Search and Filtering
|
|
48371
48630
|
|
|
@@ -48402,6 +48661,21 @@ This helps handle typos and variations - search first, then use the exact label
|
|
|
48402
48661
|
- \`update_project\` - Update name, description, status
|
|
48403
48662
|
- \`delete_project\` - Delete project and optionally directory/app
|
|
48404
48663
|
- \`scan_projects\` - Scan directory for git repos
|
|
48664
|
+
|
|
48665
|
+
#### Project Tags
|
|
48666
|
+
|
|
48667
|
+
- \`add_project_tag\` - Add a tag to a project (creates new if needed)
|
|
48668
|
+
- \`remove_project_tag\` - Remove a tag from a project
|
|
48669
|
+
|
|
48670
|
+
#### Project Attachments
|
|
48671
|
+
|
|
48672
|
+
- \`list_project_attachments\` - List all file attachments for a project
|
|
48673
|
+
- \`upload_project_attachment\` - Upload a file to a project from a local path
|
|
48674
|
+
- \`delete_project_attachment\` - Delete a file attachment from a project
|
|
48675
|
+
- \`get_project_attachment_path\` - Get the local file path for a project attachment
|
|
48676
|
+
|
|
48677
|
+
#### Project Links
|
|
48678
|
+
|
|
48405
48679
|
- \`list_project_links\` - List all URL links attached to a project
|
|
48406
48680
|
- \`add_project_link\` - Add a URL link to a project (auto-detects type)
|
|
48407
48681
|
- \`remove_project_link\` - Remove a URL link from a project
|
|
@@ -48524,87 +48798,47 @@ Clean up a session when you're done to free resources.
|
|
|
48524
48798
|
`;
|
|
48525
48799
|
|
|
48526
48800
|
// cli/src/commands/claude.ts
|
|
48527
|
-
var
|
|
48801
|
+
var MARKETPLACE_DIR = join3(homedir2(), ".fulcrum", "claude-plugin");
|
|
48802
|
+
var MARKETPLACE_NAME = "fulcrum";
|
|
48803
|
+
var PLUGIN_NAME = "fulcrum";
|
|
48804
|
+
var PLUGIN_ID = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
|
|
48528
48805
|
var PLUGIN_FILES = [
|
|
48529
|
-
{ path: ".claude-plugin/
|
|
48806
|
+
{ path: ".claude-plugin/marketplace.json", content: marketplace_default },
|
|
48530
48807
|
{ path: "hooks/hooks.json", content: hooks_default },
|
|
48531
48808
|
{ path: ".mcp.json", content: _mcp_default },
|
|
48532
48809
|
{ path: "commands/pr.md", content: pr_default },
|
|
48533
48810
|
{ path: "commands/task-info.md", content: task_info_default },
|
|
48534
48811
|
{ path: "commands/notify.md", content: notify_default },
|
|
48535
|
-
{ path: "
|
|
48536
|
-
{ path: "commands/review.md", content: review_default },
|
|
48537
|
-
{ path: "skills/vibora/SKILL.md", content: SKILL_default }
|
|
48812
|
+
{ path: "skills/fulcrum/SKILL.md", content: SKILL_default }
|
|
48538
48813
|
];
|
|
48539
|
-
var
|
|
48540
|
-
var
|
|
48541
|
-
|
|
48542
|
-
|
|
48814
|
+
var LEGACY_PLUGIN_DIR = join3(homedir2(), ".claude", "plugins", "fulcrum");
|
|
48815
|
+
var LEGACY_CACHE_DIR = join3(homedir2(), ".claude", "plugins", "cache", "fulcrum");
|
|
48816
|
+
function runClaude(args) {
|
|
48817
|
+
const result = spawnSync2("claude", args, { encoding: "utf-8" });
|
|
48818
|
+
return {
|
|
48819
|
+
success: result.status === 0,
|
|
48820
|
+
output: (result.stdout || "") + (result.stderr || "")
|
|
48821
|
+
};
|
|
48822
|
+
}
|
|
48823
|
+
function getBundledVersion() {
|
|
48543
48824
|
try {
|
|
48544
|
-
const parsed = JSON.parse(
|
|
48545
|
-
return parsed.version || "1.0.0";
|
|
48825
|
+
const parsed = JSON.parse(marketplace_default);
|
|
48826
|
+
return parsed.plugins?.[0]?.version || "1.0.0";
|
|
48546
48827
|
} catch {
|
|
48547
48828
|
return "1.0.0";
|
|
48548
48829
|
}
|
|
48549
48830
|
}
|
|
48550
|
-
function
|
|
48551
|
-
const
|
|
48552
|
-
|
|
48553
|
-
|
|
48554
|
-
if (existsSync3(INSTALLED_PLUGINS_PATH)) {
|
|
48555
|
-
try {
|
|
48556
|
-
data = JSON.parse(readFileSync4(INSTALLED_PLUGINS_PATH, "utf-8"));
|
|
48557
|
-
} catch {}
|
|
48558
|
-
}
|
|
48559
|
-
data.plugins = data.plugins || {};
|
|
48560
|
-
data.plugins[PLUGIN_ID] = [
|
|
48561
|
-
{
|
|
48562
|
-
scope: "user",
|
|
48563
|
-
installPath: PLUGIN_DIR,
|
|
48564
|
-
version: version3,
|
|
48565
|
-
installedAt: now,
|
|
48566
|
-
lastUpdated: now
|
|
48567
|
-
}
|
|
48568
|
-
];
|
|
48569
|
-
const dir = INSTALLED_PLUGINS_PATH.substring(0, INSTALLED_PLUGINS_PATH.lastIndexOf("/"));
|
|
48570
|
-
mkdirSync3(dir, { recursive: true });
|
|
48571
|
-
writeFileSync3(INSTALLED_PLUGINS_PATH, JSON.stringify(data, null, 2), "utf-8");
|
|
48572
|
-
}
|
|
48573
|
-
function enablePlugin() {
|
|
48574
|
-
let data = {};
|
|
48575
|
-
if (existsSync3(CLAUDE_SETTINGS_PATH)) {
|
|
48576
|
-
try {
|
|
48577
|
-
data = JSON.parse(readFileSync4(CLAUDE_SETTINGS_PATH, "utf-8"));
|
|
48578
|
-
} catch {}
|
|
48831
|
+
function getInstalledVersion() {
|
|
48832
|
+
const installedMarketplace = join3(MARKETPLACE_DIR, ".claude-plugin", "marketplace.json");
|
|
48833
|
+
if (!existsSync3(installedMarketplace)) {
|
|
48834
|
+
return null;
|
|
48579
48835
|
}
|
|
48580
|
-
const enabledPlugins = data.enabledPlugins || {};
|
|
48581
|
-
enabledPlugins[PLUGIN_ID] = true;
|
|
48582
|
-
data.enabledPlugins = enabledPlugins;
|
|
48583
|
-
const dir = CLAUDE_SETTINGS_PATH.substring(0, CLAUDE_SETTINGS_PATH.lastIndexOf("/"));
|
|
48584
|
-
mkdirSync3(dir, { recursive: true });
|
|
48585
|
-
writeFileSync3(CLAUDE_SETTINGS_PATH, JSON.stringify(data, null, 2), "utf-8");
|
|
48586
|
-
}
|
|
48587
|
-
function unregisterPlugin() {
|
|
48588
|
-
if (!existsSync3(INSTALLED_PLUGINS_PATH))
|
|
48589
|
-
return;
|
|
48590
48836
|
try {
|
|
48591
|
-
const
|
|
48592
|
-
|
|
48593
|
-
|
|
48594
|
-
|
|
48595
|
-
|
|
48596
|
-
} catch {}
|
|
48597
|
-
}
|
|
48598
|
-
function disablePlugin() {
|
|
48599
|
-
if (!existsSync3(CLAUDE_SETTINGS_PATH))
|
|
48600
|
-
return;
|
|
48601
|
-
try {
|
|
48602
|
-
const data = JSON.parse(readFileSync4(CLAUDE_SETTINGS_PATH, "utf-8"));
|
|
48603
|
-
if (data.enabledPlugins && data.enabledPlugins[PLUGIN_ID] !== undefined) {
|
|
48604
|
-
delete data.enabledPlugins[PLUGIN_ID];
|
|
48605
|
-
writeFileSync3(CLAUDE_SETTINGS_PATH, JSON.stringify(data, null, 2), "utf-8");
|
|
48606
|
-
}
|
|
48607
|
-
} catch {}
|
|
48837
|
+
const installed = JSON.parse(readFileSync4(installedMarketplace, "utf-8"));
|
|
48838
|
+
return installed.plugins?.[0]?.version || null;
|
|
48839
|
+
} catch {
|
|
48840
|
+
return null;
|
|
48841
|
+
}
|
|
48608
48842
|
}
|
|
48609
48843
|
async function handleClaudeCommand(action) {
|
|
48610
48844
|
if (action === "install") {
|
|
@@ -48618,38 +48852,39 @@ async function handleClaudeCommand(action) {
|
|
|
48618
48852
|
throw new CliError("INVALID_ACTION", "Unknown action. Usage: fulcrum claude install | fulcrum claude uninstall", ExitCodes.INVALID_ARGS);
|
|
48619
48853
|
}
|
|
48620
48854
|
function needsPluginUpdate() {
|
|
48621
|
-
const
|
|
48622
|
-
if (!
|
|
48623
|
-
return true;
|
|
48624
|
-
}
|
|
48625
|
-
try {
|
|
48626
|
-
const installed = JSON.parse(readFileSync4(installedPluginJson, "utf-8"));
|
|
48627
|
-
const bundled = JSON.parse(plugin_default);
|
|
48628
|
-
return installed.version !== bundled.version;
|
|
48629
|
-
} catch {
|
|
48855
|
+
const installedVersion = getInstalledVersion();
|
|
48856
|
+
if (!installedVersion) {
|
|
48630
48857
|
return true;
|
|
48631
48858
|
}
|
|
48859
|
+
const bundledVersion = getBundledVersion();
|
|
48860
|
+
return installedVersion !== bundledVersion;
|
|
48632
48861
|
}
|
|
48633
48862
|
async function installClaudePlugin(options = {}) {
|
|
48634
48863
|
const { silent = false } = options;
|
|
48635
48864
|
const log = silent ? () => {} : console.log;
|
|
48636
48865
|
try {
|
|
48637
48866
|
log("Installing Claude Code plugin...");
|
|
48638
|
-
if (existsSync3(
|
|
48639
|
-
|
|
48640
|
-
rmSync(PLUGIN_DIR, { recursive: true });
|
|
48867
|
+
if (existsSync3(MARKETPLACE_DIR)) {
|
|
48868
|
+
rmSync(MARKETPLACE_DIR, { recursive: true });
|
|
48641
48869
|
}
|
|
48642
48870
|
for (const file2 of PLUGIN_FILES) {
|
|
48643
|
-
const fullPath = join3(
|
|
48644
|
-
|
|
48645
|
-
mkdirSync3(dir, { recursive: true });
|
|
48871
|
+
const fullPath = join3(MARKETPLACE_DIR, file2.path);
|
|
48872
|
+
mkdirSync3(dirname2(fullPath), { recursive: true });
|
|
48646
48873
|
writeFileSync3(fullPath, file2.content, "utf-8");
|
|
48647
48874
|
}
|
|
48648
|
-
log("\u2713
|
|
48649
|
-
|
|
48650
|
-
|
|
48651
|
-
|
|
48652
|
-
|
|
48875
|
+
log("\u2713 Created plugin files at " + MARKETPLACE_DIR);
|
|
48876
|
+
runClaude(["plugin", "marketplace", "remove", MARKETPLACE_NAME]);
|
|
48877
|
+
const addResult = runClaude(["plugin", "marketplace", "add", MARKETPLACE_DIR]);
|
|
48878
|
+
if (!addResult.success) {
|
|
48879
|
+
throw new Error("Failed to add marketplace: " + addResult.output);
|
|
48880
|
+
}
|
|
48881
|
+
log("\u2713 Registered marketplace");
|
|
48882
|
+
const installResult = runClaude(["plugin", "install", PLUGIN_ID, "--scope", "user"]);
|
|
48883
|
+
if (!installResult.success) {
|
|
48884
|
+
throw new Error("Failed to install plugin: " + installResult.output);
|
|
48885
|
+
}
|
|
48886
|
+
log("\u2713 Installed plugin");
|
|
48887
|
+
cleanupLegacyPaths(log);
|
|
48653
48888
|
log("");
|
|
48654
48889
|
log("Installation complete! Restart Claude Code to apply changes.");
|
|
48655
48890
|
} catch (err) {
|
|
@@ -48658,32 +48893,35 @@ async function installClaudePlugin(options = {}) {
|
|
|
48658
48893
|
}
|
|
48659
48894
|
async function uninstallClaudePlugin() {
|
|
48660
48895
|
try {
|
|
48661
|
-
|
|
48662
|
-
|
|
48663
|
-
|
|
48664
|
-
|
|
48665
|
-
|
|
48666
|
-
|
|
48667
|
-
|
|
48668
|
-
|
|
48669
|
-
|
|
48670
|
-
console.log("
|
|
48671
|
-
|
|
48672
|
-
console.log("");
|
|
48673
|
-
console.log("Uninstall complete! Restart Claude Code to apply changes.");
|
|
48674
|
-
} else {
|
|
48675
|
-
console.log("");
|
|
48676
|
-
console.log("Plugin files were not found, but registration entries have been cleaned up.");
|
|
48677
|
-
}
|
|
48896
|
+
runClaude(["plugin", "uninstall", PLUGIN_ID]);
|
|
48897
|
+
console.log("\u2713 Uninstalled plugin");
|
|
48898
|
+
runClaude(["plugin", "marketplace", "remove", MARKETPLACE_NAME]);
|
|
48899
|
+
console.log("\u2713 Removed marketplace");
|
|
48900
|
+
if (existsSync3(MARKETPLACE_DIR)) {
|
|
48901
|
+
rmSync(MARKETPLACE_DIR, { recursive: true });
|
|
48902
|
+
console.log("\u2713 Removed plugin files from " + MARKETPLACE_DIR);
|
|
48903
|
+
}
|
|
48904
|
+
cleanupLegacyPaths(console.log);
|
|
48905
|
+
console.log("");
|
|
48906
|
+
console.log("Uninstall complete! Restart Claude Code to apply changes.");
|
|
48678
48907
|
} catch (err) {
|
|
48679
48908
|
throw new CliError("UNINSTALL_FAILED", `Failed to uninstall Claude plugin: ${err instanceof Error ? err.message : String(err)}`, ExitCodes.ERROR);
|
|
48680
48909
|
}
|
|
48681
48910
|
}
|
|
48911
|
+
function cleanupLegacyPaths(log) {
|
|
48912
|
+
const legacyPaths = [LEGACY_PLUGIN_DIR, LEGACY_CACHE_DIR];
|
|
48913
|
+
for (const path of legacyPaths) {
|
|
48914
|
+
if (existsSync3(path)) {
|
|
48915
|
+
rmSync(path, { recursive: true });
|
|
48916
|
+
log("\u2713 Removed legacy files from " + path);
|
|
48917
|
+
}
|
|
48918
|
+
}
|
|
48919
|
+
}
|
|
48682
48920
|
// package.json
|
|
48683
48921
|
var package_default = {
|
|
48684
48922
|
name: "@knowsuchagency/fulcrum",
|
|
48685
48923
|
private: true,
|
|
48686
|
-
version: "1.
|
|
48924
|
+
version: "1.5.0",
|
|
48687
48925
|
description: "Harness Attention. Orchestrate Agents. Ship.",
|
|
48688
48926
|
license: "PolyForm-Perimeter-1.0.0",
|
|
48689
48927
|
type: "module",
|
|
@@ -48776,14 +49014,14 @@ var package_default = {
|
|
|
48776
49014
|
// cli/src/commands/up.ts
|
|
48777
49015
|
function getPackageRoot() {
|
|
48778
49016
|
const currentFile = fileURLToPath(import.meta.url);
|
|
48779
|
-
let dir =
|
|
49017
|
+
let dir = dirname3(currentFile);
|
|
48780
49018
|
for (let i2 = 0;i2 < 5; i2++) {
|
|
48781
49019
|
if (existsSync4(join4(dir, "server", "index.js"))) {
|
|
48782
49020
|
return dir;
|
|
48783
49021
|
}
|
|
48784
|
-
dir =
|
|
49022
|
+
dir = dirname3(dir);
|
|
48785
49023
|
}
|
|
48786
|
-
return
|
|
49024
|
+
return dirname3(dirname3(dirname3(currentFile)));
|
|
48787
49025
|
}
|
|
48788
49026
|
async function handleUpCommand(flags) {
|
|
48789
49027
|
const autoYes = flags.yes === "true" || flags.y === "true";
|
|
@@ -49572,8 +49810,8 @@ export const FulcrumPlugin: Plugin = async ({ $, directory }) => {
|
|
|
49572
49810
|
// cli/src/commands/opencode.ts
|
|
49573
49811
|
var OPENCODE_DIR = join5(homedir3(), ".opencode");
|
|
49574
49812
|
var OPENCODE_CONFIG_PATH = join5(OPENCODE_DIR, "opencode.json");
|
|
49575
|
-
var
|
|
49576
|
-
var PLUGIN_PATH = join5(
|
|
49813
|
+
var PLUGIN_DIR = join5(homedir3(), ".config", "opencode", "plugin");
|
|
49814
|
+
var PLUGIN_PATH = join5(PLUGIN_DIR, "fulcrum.ts");
|
|
49577
49815
|
var FULCRUM_MCP_CONFIG = {
|
|
49578
49816
|
type: "local",
|
|
49579
49817
|
command: ["fulcrum", "mcp"],
|
|
@@ -49593,7 +49831,7 @@ async function handleOpenCodeCommand(action) {
|
|
|
49593
49831
|
async function installOpenCodeIntegration() {
|
|
49594
49832
|
try {
|
|
49595
49833
|
console.log("Installing OpenCode plugin...");
|
|
49596
|
-
mkdirSync4(
|
|
49834
|
+
mkdirSync4(PLUGIN_DIR, { recursive: true });
|
|
49597
49835
|
writeFileSync4(PLUGIN_PATH, fulcrum_opencode_default, "utf-8");
|
|
49598
49836
|
console.log("\u2713 Installed plugin at " + PLUGIN_PATH);
|
|
49599
49837
|
console.log("Configuring MCP server...");
|
|
@@ -50351,6 +50589,127 @@ var tasksListDependenciesCommand = defineCommand({
|
|
|
50351
50589
|
await handleTasksCommand("list-dependencies", [args.id], toFlags(args));
|
|
50352
50590
|
}
|
|
50353
50591
|
});
|
|
50592
|
+
var tasksLabelsCommand = defineCommand({
|
|
50593
|
+
meta: {
|
|
50594
|
+
name: "labels",
|
|
50595
|
+
description: "List all labels in use across tasks"
|
|
50596
|
+
},
|
|
50597
|
+
args: {
|
|
50598
|
+
...globalArgs,
|
|
50599
|
+
search: {
|
|
50600
|
+
type: "string",
|
|
50601
|
+
description: "Filter labels by substring match"
|
|
50602
|
+
}
|
|
50603
|
+
},
|
|
50604
|
+
async run({ args }) {
|
|
50605
|
+
if (args.json)
|
|
50606
|
+
setJsonOutput(true);
|
|
50607
|
+
await handleTasksCommand("labels", [], toFlags(args));
|
|
50608
|
+
}
|
|
50609
|
+
});
|
|
50610
|
+
var tasksAttachmentsListCommand = defineCommand({
|
|
50611
|
+
meta: {
|
|
50612
|
+
name: "list",
|
|
50613
|
+
description: "List attachments for a task"
|
|
50614
|
+
},
|
|
50615
|
+
args: {
|
|
50616
|
+
...globalArgs,
|
|
50617
|
+
id: {
|
|
50618
|
+
type: "positional",
|
|
50619
|
+
description: "Task ID",
|
|
50620
|
+
required: true
|
|
50621
|
+
}
|
|
50622
|
+
},
|
|
50623
|
+
async run({ args }) {
|
|
50624
|
+
if (args.json)
|
|
50625
|
+
setJsonOutput(true);
|
|
50626
|
+
await handleTasksCommand("attachments", ["list", args.id], toFlags(args));
|
|
50627
|
+
}
|
|
50628
|
+
});
|
|
50629
|
+
var tasksAttachmentsUploadCommand = defineCommand({
|
|
50630
|
+
meta: {
|
|
50631
|
+
name: "upload",
|
|
50632
|
+
description: "Upload a file to a task"
|
|
50633
|
+
},
|
|
50634
|
+
args: {
|
|
50635
|
+
...globalArgs,
|
|
50636
|
+
id: {
|
|
50637
|
+
type: "positional",
|
|
50638
|
+
description: "Task ID",
|
|
50639
|
+
required: true
|
|
50640
|
+
},
|
|
50641
|
+
file: {
|
|
50642
|
+
type: "positional",
|
|
50643
|
+
description: "File path to upload",
|
|
50644
|
+
required: true
|
|
50645
|
+
}
|
|
50646
|
+
},
|
|
50647
|
+
async run({ args }) {
|
|
50648
|
+
if (args.json)
|
|
50649
|
+
setJsonOutput(true);
|
|
50650
|
+
await handleTasksCommand("attachments", ["upload", args.id, args.file], toFlags(args));
|
|
50651
|
+
}
|
|
50652
|
+
});
|
|
50653
|
+
var tasksAttachmentsDeleteCommand = defineCommand({
|
|
50654
|
+
meta: {
|
|
50655
|
+
name: "delete",
|
|
50656
|
+
description: "Delete an attachment from a task"
|
|
50657
|
+
},
|
|
50658
|
+
args: {
|
|
50659
|
+
...globalArgs,
|
|
50660
|
+
id: {
|
|
50661
|
+
type: "positional",
|
|
50662
|
+
description: "Task ID",
|
|
50663
|
+
required: true
|
|
50664
|
+
},
|
|
50665
|
+
"attachment-id": {
|
|
50666
|
+
type: "positional",
|
|
50667
|
+
description: "Attachment ID",
|
|
50668
|
+
required: true
|
|
50669
|
+
}
|
|
50670
|
+
},
|
|
50671
|
+
async run({ args }) {
|
|
50672
|
+
if (args.json)
|
|
50673
|
+
setJsonOutput(true);
|
|
50674
|
+
await handleTasksCommand("attachments", ["delete", args.id, args["attachment-id"]], toFlags(args));
|
|
50675
|
+
}
|
|
50676
|
+
});
|
|
50677
|
+
var tasksAttachmentsPathCommand = defineCommand({
|
|
50678
|
+
meta: {
|
|
50679
|
+
name: "path",
|
|
50680
|
+
description: "Get local file path for an attachment"
|
|
50681
|
+
},
|
|
50682
|
+
args: {
|
|
50683
|
+
...globalArgs,
|
|
50684
|
+
id: {
|
|
50685
|
+
type: "positional",
|
|
50686
|
+
description: "Task ID",
|
|
50687
|
+
required: true
|
|
50688
|
+
},
|
|
50689
|
+
"attachment-id": {
|
|
50690
|
+
type: "positional",
|
|
50691
|
+
description: "Attachment ID",
|
|
50692
|
+
required: true
|
|
50693
|
+
}
|
|
50694
|
+
},
|
|
50695
|
+
async run({ args }) {
|
|
50696
|
+
if (args.json)
|
|
50697
|
+
setJsonOutput(true);
|
|
50698
|
+
await handleTasksCommand("attachments", ["path", args.id, args["attachment-id"]], toFlags(args));
|
|
50699
|
+
}
|
|
50700
|
+
});
|
|
50701
|
+
var tasksAttachmentsCommand = defineCommand({
|
|
50702
|
+
meta: {
|
|
50703
|
+
name: "attachments",
|
|
50704
|
+
description: "Manage task attachments"
|
|
50705
|
+
},
|
|
50706
|
+
subCommands: {
|
|
50707
|
+
list: tasksAttachmentsListCommand,
|
|
50708
|
+
upload: tasksAttachmentsUploadCommand,
|
|
50709
|
+
delete: tasksAttachmentsDeleteCommand,
|
|
50710
|
+
path: tasksAttachmentsPathCommand
|
|
50711
|
+
}
|
|
50712
|
+
});
|
|
50354
50713
|
var tasksCommand = defineCommand({
|
|
50355
50714
|
meta: {
|
|
50356
50715
|
name: "tasks",
|
|
@@ -50368,7 +50727,9 @@ var tasksCommand = defineCommand({
|
|
|
50368
50727
|
"set-due-date": tasksSetDueDateCommand,
|
|
50369
50728
|
"add-dependency": tasksAddDependencyCommand,
|
|
50370
50729
|
"remove-dependency": tasksRemoveDependencyCommand,
|
|
50371
|
-
"list-dependencies": tasksListDependenciesCommand
|
|
50730
|
+
"list-dependencies": tasksListDependenciesCommand,
|
|
50731
|
+
labels: tasksLabelsCommand,
|
|
50732
|
+
attachments: tasksAttachmentsCommand
|
|
50372
50733
|
}
|
|
50373
50734
|
});
|
|
50374
50735
|
var projectsListCommand = defineCommand({
|
|
@@ -122,7 +122,7 @@ ${n.map(([a,s])=>{const o=s.theme?.[r]||s.color;return o?` --color-${a}: ${o};`
|
|
|
122
122
|
|
|
123
123
|
${e}`,d=Cp(u);return`opencode --agent ${bgt(o)} --prompt ${d}${l}`},notFoundPatterns:[/opencode: command not found/,/opencode: not found/,/'opencode' is not recognized/,/command not found: opencode/],processPattern:/\bopencode\b/i},d6={claude:ygt,opencode:vgt};function xgt(e,t){return d6[e].buildCommand(t)}function _gt(e,t){if(t)return d6[t].notFoundPatterns.some(r=>r.test(e))?t:null;for(const[n,r]of Object.entries(d6))if(r.notFoundPatterns.some(i=>i.test(e)))return n;return null}function Kae({taskName:e,cwd:t,taskId:n,className:r,agent:i="claude",aiMode:a,description:s,startupScript:o,agentOptions:l,opencodeModel:u,serverPort:d=7777,autoFocus:c=!1}){const p=w.useRef(null),m=w.useRef(null),x=w.useRef(!1),_=w.useRef(c),b=w.useRef(null),v=w.useRef(!1),y=w.useRef(!1),[E,T]=w.useState(null),[k,C]=w.useState(!1),[O,A]=w.useState(!1),[N,I]=w.useState(!1),[D,P]=w.useState(null),{resolvedTheme:L}=Wf(),j=L==="dark",F=j?dme:cme,{data:$}=gfe(),{data:V}=bfe(),Y=w.useRef($),B=w.useRef(V);w.useEffect(()=>{Y.current=$},[$]),w.useEffect(()=>{B.current=V},[V]),w.useEffect(()=>{Mt.taskTerminal.debug("cwd changed, resetting refs",{cwd:t}),v.current=!1,y.current=!1,x.current=!1,T(null),C(!1)},[t]);const{setTerminalFocused:z}=U8(),{terminals:H,terminalsLoaded:q,connected:U,createTerminal:X,attachXterm:J,resizeTerminal:ne,setupImagePaste:Z,writeToTerminal:K,consumePendingStartup:ee,clearStartingUp:ae}=wB(),se=w.useRef(J),ie=w.useRef(Z),me=w.useRef(K),ye=w.useRef(ee),ue=w.useRef(ae);w.useEffect(()=>{se.current=J},[J]),w.useEffect(()=>{ie.current=Z},[Z]),w.useEffect(()=>{me.current=K},[K]),w.useEffect(()=>{ye.current=ee},[ee]),w.useEffect(()=>{ue.current=ae},[ae]),w.useEffect(()=>{_.current=c},[c]);const Ee=E?H.find(Le=>Le.id===E):null,be=Ee?.status;w.useEffect(()=>{if(!p.current||m.current)return;const Le=new sme.Terminal({cursorBlink:!0,fontSize:14,fontFamily:"monospace",theme:F,scrollback:1e4,rightClickSelectsWord:!0,scrollOnUserInput:!1}),Ce=new ome.FitAddon,Pe=new lme.WebLinksAddon;Le.loadAddon(Ce),Le.loadAddon(Pe),Le.open(p.current);const xe=ume(Le);m.current=Le,b.current=Ce,I(!0),requestAnimationFrame(()=>{Ce.fit()});const _e=setTimeout(()=>{Ce.fit(),Le.refresh(0,Le.rows-1)},100),Ae=()=>z(!0),pe=()=>z(!1);return Le.textarea&&(Le.textarea.addEventListener("focus",Ae),Le.textarea.addEventListener("blur",pe)),()=>{clearTimeout(_e),xe(),Le.textarea&&(Le.textarea.removeEventListener("focus",Ae),Le.textarea.removeEventListener("blur",pe)),z(!1),Le.dispose(),m.current=null,b.current=null,I(!1)}},[z]);const Oe=w.useCallback(()=>{if(!b.current||!m.current)return;b.current.fit();const{cols:Le,rows:Ce}=m.current;E&&ne(E,Le,Ce)},[E,ne]);w.useEffect(()=>{if(!p.current)return;const Le=()=>{requestAnimationFrame(Oe)};window.addEventListener("resize",Le);const Ce=()=>{document.visibilityState==="visible"&&requestAnimationFrame(()=>{Oe(),m.current&&m.current.refresh(0,m.current.rows-1)})};document.addEventListener("visibilitychange",Ce);const Pe=new ResizeObserver(Le);Pe.observe(p.current);const xe=new IntersectionObserver(_e=>{_e[0]?.isIntersecting&&requestAnimationFrame(()=>{Oe(),m.current&&m.current.refresh(0,m.current.rows-1)})},{threshold:.1});return xe.observe(p.current),()=>{window.removeEventListener("resize",Le),document.removeEventListener("visibilitychange",Ce),Pe.disconnect(),xe.disconnect()}},[Oe]),w.useEffect(()=>{if(!U||!t||!N||!q){Mt.taskTerminal.debug("Terminal effect: waiting for conditions",{connected:U,cwd:t,xtermOpened:N,terminalsLoaded:q});return}Mt.taskTerminal.info("Looking for terminal",{cwd:t,terminalCount:H.length,availableTerminals:H.map(Ce=>({id:Ce.id,name:Ce.name,cwd:Ce.cwd,tabId:Ce.tabId}))});const Le=H.find(Ce=>Ce.cwd===t);if(Le){Mt.taskTerminal.info("Found existing terminal",{terminalId:Le.id,name:Le.name,cwd:t}),T(Le.id);return}if(!v.current&&m.current){Mt.taskTerminal.info("Creating new terminal",{reason:"no_existing_terminal_for_cwd",cwd:t,taskName:e,taskId:n,agent:i}),v.current=!0,C(!0);const{cols:Ce,rows:Pe}=m.current;X({name:e,cols:Ce,rows:Pe,cwd:t,taskId:n,startup:{startupScript:o,agent:i,agentOptions:l,opencodeModel:u,aiMode:a,description:s,taskName:e,serverPort:d}})}else v.current&&Mt.taskTerminal.debug("Terminal creation already in progress",{cwd:t,createdTerminalRef:v.current})},[U,t,N,q,H,e,X]),w.useEffect(()=>{if(!t)return;const Le=H.find(Pe=>Pe.cwd===t);if(!Le)return;const Ce=E&&H.some(Pe=>Pe.id===E);(!E||!Ce)&&(Mt.taskTerminal.debug("setting terminalId",{newId:Le.id,prevId:E,reason:E?"tempId replaced":"initial",cwd:t,terminalCount:H.length}),T(Le.id),C(!1),E&&!Ce&&(y.current=!1))},[H,t,E]),w.useEffect(()=>{if(Mt.taskTerminal.debug("attach effect",{terminalId:E,hasTermRef:!!m.current,hasContainerRef:!!p.current,attachedRef:y.current}),!E||!m.current||!p.current||y.current)return;Mt.taskTerminal.debug("attach effect passed guards, calling attachXterm",{terminalId:E});const Le=xe=>{requestAnimationFrame(Oe);const _e=ye.current(xe);if(Mt.taskTerminal.debug("onAttached checking pending startup",{terminalId:xe,hasPendingStartup:!!_e}),!_e){if(_.current&&!x.current&&m.current){const fe=()=>{const ge=m.current;!x.current&&ge&&(ge.focus(),ge.textarea===document.activeElement&&(x.current=!0))};setTimeout(fe,50),setTimeout(fe,200),setTimeout(fe,500)}return}Mt.taskTerminal.info("onAttached: running startup commands",{terminalId:xe}),A(!0);const{startupScript:Ae,agent:pe="claude",agentOptions:Me,opencodeModel:we,aiMode:Ve,description:Xe,taskName:ht,serverPort:ot}=_e;Ae&&setTimeout(()=>{const fe="FULCRUM_STARTUP_"+Date.now(),ge=`source /dev/stdin <<'${fe}'
|
|
124
124
|
${Ae}
|
|
125
|
-
${fe}`;me.current(xe,ge+"\r")},100);const lt=ot??7777,ze=lt!==7777?` --port=${lt}`:"",yt=`You are working in a Fulcrum task worktree. Commit after completing each logical unit of work (feature, fix, refactor) to preserve progress. When you finish working and need user input, run: fulcrum current-task review${ze}. When linking a PR: fulcrum current-task pr <url>${ze}. When linking a URL: fulcrum current-task link <url>${ze}. For notifications: fulcrum notify "Title" "Message"${ze}.`,Ie=Xe?`${ht}: ${Xe}`:ht,Ue=xgt(pe,{prompt:Ie,systemPrompt:yt,mode:Ve==="plan"?"plan":"default",additionalOptions:Me??{},opencodeModel:we,opencodeDefaultAgent:Y.current,opencodePlanAgent:B.current});setTimeout(()=>{if(me.current(xe,Ue+"\r"),A(!1),ue.current(xe),_.current&&!x.current&&m.current){const fe=()=>{const ge=m.current;!x.current&&ge&&(ge.focus(),ge.textarea===document.activeElement&&(x.current=!0))};setTimeout(fe,50),setTimeout(fe,200),setTimeout(fe,500)}},Ae?5e3:100)},Ce=se.current(E,m.current,{onAttached:Le}),Pe=ie.current(p.current,E);return y.current=!0,Mt.taskTerminal.debug("attachedRef set to true",{terminalId:E}),()=>{Mt.taskTerminal.debug("cleanup running, setting attachedRef to false",{terminalId:E}),Ce(),Pe(),y.current=!1}},[E,Oe]),w.useEffect(()=>{m.current&&(m.current.options.theme=F,m.current.refresh(0,m.current.rows-1))},[F]),w.useEffect(()=>{if(!c||x.current||!m.current||!E||k||O)return;const Le=[0,50,150,300,500],Ce=[];return Le.forEach(Pe=>{const xe=setTimeout(()=>{const _e=m.current;!x.current&&_e&&(_e.focus(),_e.textarea===document.activeElement&&(x.current=!0))},Pe);Ce.push(xe)}),()=>{Ce.forEach(clearTimeout)}},[c,k,O,E]),w.useEffect(()=>{if(!m.current||D)return;const Le=m.current,Ce=()=>{const xe=Le.buffer.active;for(let _e=Math.max(0,xe.cursorY-3);_e<=xe.cursorY;_e++){const Ae=xe.getLine(_e);if(Ae){const pe=Ae.translateToString(),Me=_gt(pe,i);if(Me){P(Me);return}}}},Pe=Le.onLineFeed(Ce);return()=>{Pe.dispose()}},[D,i]);const je=w.useCallback(Le=>{E&&me.current(E,Le)},[E]);return t?f.jsxs("div",{className:"flex h-full min-h-0 flex-col",children:[!U&&f.jsx("div",{className:"shrink-0 px-2 py-1 bg-muted-foreground/20 text-muted-foreground text-xs",children:"Connecting to terminal server..."}),be==="error"&&f.jsx("div",{className:"shrink-0 px-2 py-1 bg-destructive/20 text-destructive text-xs",children:"Terminal failed to start. The worktree directory may not exist."}),be==="exited"&&f.jsxs("div",{className:"shrink-0 px-2 py-1 bg-muted text-muted-foreground text-xs",children:["Terminal exited (code: ",Ee?.exitCode,")"]}),f.jsxs("div",{className:"relative min-h-0 min-w-0 flex-1",children:[f.jsx("div",{ref:p,className:Ne("h-full w-full overflow-hidden p-2 bg-terminal-background",r)}),k&&!E&&f.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-terminal-background",children:f.jsxs("div",{className:"flex flex-col items-center gap-3",children:[f.jsx(re,{icon:Ot,size:24,strokeWidth:2,className:Ne("animate-spin",j?"text-white/50":"text-black/50")}),f.jsx("span",{className:Ne("font-mono text-sm",j?"text-white/50":"text-black/50"),children:"Initializing terminal..."})]})}),O&&f.jsx("div",{className:"pointer-events-none absolute inset-0 z-10 flex items-center justify-center bg-terminal-background/90",children:f.jsxs("div",{className:"flex flex-col items-center gap-3",children:[f.jsx(re,{icon:Ot,size:24,strokeWidth:2,className:Ne("animate-spin",j?"text-white/60":"text-black/60")}),f.jsxs("span",{className:Ne("font-mono text-sm",j?"text-white/60":"text-black/60"),children:["Starting ",bo[i],"..."]})]})}),D&&f.jsx("div",{className:"pointer-events-none absolute bottom-4 left-4 right-4 z-10",children:f.jsxs("div",{className:Ne("pointer-events-auto flex items-start gap-3 rounded-lg border p-4","bg-amber-500/10 border-amber-500/30"),children:[f.jsx(re,{icon:fr,size:18,strokeWidth:2,className:"shrink-0 mt-0.5 text-amber-600 dark:text-amber-400"}),f.jsxs("div",{className:"flex-1 space-y-2",children:[f.jsxs("p",{className:"text-sm font-medium text-amber-600 dark:text-amber-400",children:[bo[D]," CLI not found"]}),f.jsxs("p",{className:"text-xs text-amber-600/80 dark:text-amber-400/80",children:["Install it with:"," ",f.jsx("code",{className:"rounded bg-amber-500/20 px-1.5 py-0.5 font-mono",children:Efe[D]})]}),f.jsx("a",{href:Sfe[D],target:"_blank",rel:"noopener noreferrer",className:"inline-block text-xs font-medium text-amber-600 hover:text-amber-700 dark:text-amber-400 dark:hover:text-amber-300 underline",children:"View documentation"})]}),f.jsx("button",{onClick:()=>P(null),className:"shrink-0 p-1 rounded text-amber-600 hover:text-amber-700 hover:bg-amber-500/20 dark:text-amber-400 dark:hover:text-amber-300",children:f.jsx(re,{icon:Bn,size:14,strokeWidth:2})})]})}),f.jsx("button",{onClick:()=>m.current?.scrollToBottom(),className:Ne("absolute top-2 right-5 p-1 transition-colors",j?"text-white/50 hover:text-white/80":"text-black/50 hover:text-black/80"),children:f.jsx(re,{icon:Tce,size:20,strokeWidth:2})})]}),f.jsx("div",{className:"h-2 shrink-0 bg-terminal-background"}),f.jsx(HC,{onSend:je})]}):f.jsx("div",{className:Ne("flex h-full items-center justify-center text-muted-foreground text-sm bg-terminal-background",r),children:"No worktree path configured for this task"})}function Egt(e){const{viewState:t,setDiffOptions:n}=SB(e),{collapsedFiles:r}=t.diffOptions,i=w.useCallback(l=>{const u=r.includes(l);n({collapsedFiles:u?r.filter(d=>d!==l):[...r,l]})},[r,n]),a=w.useCallback(l=>{n({collapsedFiles:l})},[n]),s=w.useCallback(()=>{n({collapsedFiles:[]})},[n]),o=w.useCallback(l=>r.includes(l),[r]);return{options:t.diffOptions,setOption:(l,u)=>{n({[l]:u})},setOptions:n,toggleFileCollapse:i,collapseAll:a,expandAll:s,isFileCollapsed:o}}function Sgt(e){const t=[];let n=null,r=0,i=0;for(const a of e.split(`
|
|
125
|
+
${fe}`;me.current(xe,ge+"\r")},100);const lt=ot??7777,ze=lt!==7777?` --port=${lt}`:"",yt=`You are working in a Fulcrum task worktree. Reference the fulcrum skill for complete CLI documentation (attachments, dependencies, notifications, etc.). Commit after completing each logical unit of work (feature, fix, refactor) to preserve progress. When you finish working and need user input, run: fulcrum current-task review${ze}. When linking a PR: fulcrum current-task pr <url>${ze}. When linking a URL: fulcrum current-task link <url>${ze}. For notifications: fulcrum notify "Title" "Message"${ze}.`,Ie=Xe?`${ht}: ${Xe}`:ht,Ue=xgt(pe,{prompt:Ie,systemPrompt:yt,mode:Ve==="plan"?"plan":"default",additionalOptions:Me??{},opencodeModel:we,opencodeDefaultAgent:Y.current,opencodePlanAgent:B.current});setTimeout(()=>{if(me.current(xe,Ue+"\r"),A(!1),ue.current(xe),_.current&&!x.current&&m.current){const fe=()=>{const ge=m.current;!x.current&&ge&&(ge.focus(),ge.textarea===document.activeElement&&(x.current=!0))};setTimeout(fe,50),setTimeout(fe,200),setTimeout(fe,500)}},Ae?5e3:100)},Ce=se.current(E,m.current,{onAttached:Le}),Pe=ie.current(p.current,E);return y.current=!0,Mt.taskTerminal.debug("attachedRef set to true",{terminalId:E}),()=>{Mt.taskTerminal.debug("cleanup running, setting attachedRef to false",{terminalId:E}),Ce(),Pe(),y.current=!1}},[E,Oe]),w.useEffect(()=>{m.current&&(m.current.options.theme=F,m.current.refresh(0,m.current.rows-1))},[F]),w.useEffect(()=>{if(!c||x.current||!m.current||!E||k||O)return;const Le=[0,50,150,300,500],Ce=[];return Le.forEach(Pe=>{const xe=setTimeout(()=>{const _e=m.current;!x.current&&_e&&(_e.focus(),_e.textarea===document.activeElement&&(x.current=!0))},Pe);Ce.push(xe)}),()=>{Ce.forEach(clearTimeout)}},[c,k,O,E]),w.useEffect(()=>{if(!m.current||D)return;const Le=m.current,Ce=()=>{const xe=Le.buffer.active;for(let _e=Math.max(0,xe.cursorY-3);_e<=xe.cursorY;_e++){const Ae=xe.getLine(_e);if(Ae){const pe=Ae.translateToString(),Me=_gt(pe,i);if(Me){P(Me);return}}}},Pe=Le.onLineFeed(Ce);return()=>{Pe.dispose()}},[D,i]);const je=w.useCallback(Le=>{E&&me.current(E,Le)},[E]);return t?f.jsxs("div",{className:"flex h-full min-h-0 flex-col",children:[!U&&f.jsx("div",{className:"shrink-0 px-2 py-1 bg-muted-foreground/20 text-muted-foreground text-xs",children:"Connecting to terminal server..."}),be==="error"&&f.jsx("div",{className:"shrink-0 px-2 py-1 bg-destructive/20 text-destructive text-xs",children:"Terminal failed to start. The worktree directory may not exist."}),be==="exited"&&f.jsxs("div",{className:"shrink-0 px-2 py-1 bg-muted text-muted-foreground text-xs",children:["Terminal exited (code: ",Ee?.exitCode,")"]}),f.jsxs("div",{className:"relative min-h-0 min-w-0 flex-1",children:[f.jsx("div",{ref:p,className:Ne("h-full w-full overflow-hidden p-2 bg-terminal-background",r)}),k&&!E&&f.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-terminal-background",children:f.jsxs("div",{className:"flex flex-col items-center gap-3",children:[f.jsx(re,{icon:Ot,size:24,strokeWidth:2,className:Ne("animate-spin",j?"text-white/50":"text-black/50")}),f.jsx("span",{className:Ne("font-mono text-sm",j?"text-white/50":"text-black/50"),children:"Initializing terminal..."})]})}),O&&f.jsx("div",{className:"pointer-events-none absolute inset-0 z-10 flex items-center justify-center bg-terminal-background/90",children:f.jsxs("div",{className:"flex flex-col items-center gap-3",children:[f.jsx(re,{icon:Ot,size:24,strokeWidth:2,className:Ne("animate-spin",j?"text-white/60":"text-black/60")}),f.jsxs("span",{className:Ne("font-mono text-sm",j?"text-white/60":"text-black/60"),children:["Starting ",bo[i],"..."]})]})}),D&&f.jsx("div",{className:"pointer-events-none absolute bottom-4 left-4 right-4 z-10",children:f.jsxs("div",{className:Ne("pointer-events-auto flex items-start gap-3 rounded-lg border p-4","bg-amber-500/10 border-amber-500/30"),children:[f.jsx(re,{icon:fr,size:18,strokeWidth:2,className:"shrink-0 mt-0.5 text-amber-600 dark:text-amber-400"}),f.jsxs("div",{className:"flex-1 space-y-2",children:[f.jsxs("p",{className:"text-sm font-medium text-amber-600 dark:text-amber-400",children:[bo[D]," CLI not found"]}),f.jsxs("p",{className:"text-xs text-amber-600/80 dark:text-amber-400/80",children:["Install it with:"," ",f.jsx("code",{className:"rounded bg-amber-500/20 px-1.5 py-0.5 font-mono",children:Efe[D]})]}),f.jsx("a",{href:Sfe[D],target:"_blank",rel:"noopener noreferrer",className:"inline-block text-xs font-medium text-amber-600 hover:text-amber-700 dark:text-amber-400 dark:hover:text-amber-300 underline",children:"View documentation"})]}),f.jsx("button",{onClick:()=>P(null),className:"shrink-0 p-1 rounded text-amber-600 hover:text-amber-700 hover:bg-amber-500/20 dark:text-amber-400 dark:hover:text-amber-300",children:f.jsx(re,{icon:Bn,size:14,strokeWidth:2})})]})}),f.jsx("button",{onClick:()=>m.current?.scrollToBottom(),className:Ne("absolute top-2 right-5 p-1 transition-colors",j?"text-white/50 hover:text-white/80":"text-black/50 hover:text-black/80"),children:f.jsx(re,{icon:Tce,size:20,strokeWidth:2})})]}),f.jsx("div",{className:"h-2 shrink-0 bg-terminal-background"}),f.jsx(HC,{onSend:je})]}):f.jsx("div",{className:Ne("flex h-full items-center justify-center text-muted-foreground text-sm bg-terminal-background",r),children:"No worktree path configured for this task"})}function Egt(e){const{viewState:t,setDiffOptions:n}=SB(e),{collapsedFiles:r}=t.diffOptions,i=w.useCallback(l=>{const u=r.includes(l);n({collapsedFiles:u?r.filter(d=>d!==l):[...r,l]})},[r,n]),a=w.useCallback(l=>{n({collapsedFiles:l})},[n]),s=w.useCallback(()=>{n({collapsedFiles:[]})},[n]),o=w.useCallback(l=>r.includes(l),[r]);return{options:t.diffOptions,setOption:(l,u)=>{n({[l]:u})},setOptions:n,toggleFileCollapse:i,collapseAll:a,expandAll:s,isFileCollapsed:o}}function Sgt(e){const t=[];let n=null,r=0,i=0;for(const a of e.split(`
|
|
126
126
|
`))if(a.startsWith("diff --git"))n={path:a.match(/diff --git a\/(.+?) b\//)?.[1]??"unknown",lines:[],additions:0,deletions:0},t.push(n),n.lines.push({type:"header",content:a});else if(a.startsWith("index ")||a.startsWith("---")||a.startsWith("+++"))n?.lines.push({type:"header",content:a});else if(a.startsWith("@@")){const s=a.match(/@@ -(\d+),?\d* \+(\d+),?\d* @@/);s&&(r=parseInt(s[1],10),i=parseInt(s[2],10)),n?.lines.push({type:"hunk",content:a})}else a.startsWith("+")?n&&(n.additions++,n.lines.push({type:"added",content:a.slice(1),newLineNumber:i++})):a.startsWith("-")?n&&(n.deletions++,n.lines.push({type:"removed",content:a.slice(1),oldLineNumber:r++})):a.startsWith(" ")&&n?.lines.push({type:"context",content:a.slice(1),oldLineNumber:r++,newLineNumber:i++});return t}function wgt({file:e,wrap:t,isCollapsed:n,onToggle:r}){return f.jsxs(g9,{open:!n,onOpenChange:()=>r(),children:[f.jsx(b9,{asChild:!0,children:f.jsxs("div",{className:"flex items-center gap-2 px-2 py-1.5 bg-card border-b border-border cursor-pointer hover:bg-muted select-none",children:[f.jsx(re,{icon:n?$u:gd,size:12,strokeWidth:2,className:"text-muted-foreground shrink-0"}),f.jsx("span",{className:"font-mono text-xs text-foreground truncate flex-1",children:e.path}),f.jsxs("span",{className:"text-xs text-muted-foreground shrink-0",children:[e.additions>0&&f.jsxs("span",{className:"text-accent",children:["+",e.additions]}),e.additions>0&&e.deletions>0&&" ",e.deletions>0&&f.jsxs("span",{className:"text-destructive",children:["-",e.deletions]})]})]})}),f.jsx(y9,{children:f.jsx("div",{className:"font-mono text-xs",children:e.lines.slice(1).map((i,a)=>f.jsxs("div",{className:Ne("flex px-2 py-0.5",i.type==="added"&&"bg-accent/10",i.type==="removed"&&"bg-destructive/10",i.type==="header"&&"bg-muted/50 text-muted-foreground",i.type==="hunk"&&"bg-accent/10 text-accent"),children:[(i.type==="added"||i.type==="removed"||i.type==="context")&&f.jsxs(f.Fragment,{children:[f.jsx("span",{className:"w-10 shrink-0 select-none pr-2 text-right text-muted-foreground",children:i.oldLineNumber??""}),f.jsx("span",{className:"w-10 shrink-0 select-none pr-2 text-right text-muted-foreground",children:i.newLineNumber??""})]}),f.jsxs("span",{className:Ne("w-4 shrink-0 select-none text-center",i.type==="added"&&"text-accent",i.type==="removed"&&"text-destructive"),children:[i.type==="added"&&"+",i.type==="removed"&&"-"]}),f.jsx("span",{className:Ne("flex-1",t?"whitespace-pre-wrap break-all":"whitespace-pre",i.type==="added"&&"text-accent",i.type==="removed"&&"text-destructive"),children:i.content})]},a))})})]})}function Xae({taskId:e,worktreePath:t,baseBranch:n}){const{options:r,setOption:i,toggleFileCollapse:a,collapseAll:s,expandAll:o,isFileCollapsed:l}=Egt(e),{wrap:u,ignoreWhitespace:d,includeUntracked:c,collapsedFiles:p}=r,{data:m,isLoading:x,error:_}=cMe(t,{ignoreWhitespace:d,includeUntracked:c,baseBranch:n}),b=w.useMemo(()=>m?.diff?Sgt(m.diff):[],[m?.diff]),v=w.useMemo(()=>b.map(C=>C.path),[b]),y=b.length>0&&p.length===b.length,E=w.useMemo(()=>b.reduce((C,O)=>C+O.additions,0),[b]),T=w.useMemo(()=>b.reduce((C,O)=>C+O.deletions,0),[b]);if(w.useEffect(()=>{const C=O=>{if(O.shiftKey&&O.key==="C"&&!O.ctrlKey&&!O.metaKey&&!O.altKey){const A=O.target;if(A.tagName==="INPUT"||A.tagName==="TEXTAREA"||A.isContentEditable)return;O.preventDefault(),y?o():s(v)}};return window.addEventListener("keydown",C),()=>window.removeEventListener("keydown",C)},[y,v,s,o]),!t)return f.jsx("div",{className:"flex h-full items-center justify-center text-muted-foreground text-sm",children:"No worktree selected"});if(x)return f.jsx("div",{className:"flex h-full items-center justify-center text-muted-foreground text-sm",children:"Loading diff..."});if(_)return f.jsx("div",{className:"flex h-full items-center justify-center text-destructive text-sm",children:_.message});const k=m?.files?.some(C=>C.status==="untracked")??!1;return b.length===0?f.jsxs("div",{className:"flex h-full flex-col items-center justify-center text-muted-foreground text-sm gap-2",children:[f.jsx("p",{children:"No changes detected"}),m?.files&&m.files.length>0&&f.jsxs("div",{className:"text-xs",children:[f.jsx("p",{className:"text-center mb-2",children:"Modified files:"}),f.jsxs("div",{className:"flex flex-col gap-1",children:[m.files.map(C=>f.jsxs("div",{className:"flex gap-2",children:[f.jsxs("span",{className:Ne("w-4 text-center",C.status==="added"&&"text-accent",C.status==="deleted"&&"text-destructive",C.status==="modified"&&"text-muted-foreground",C.status==="untracked"&&"text-muted-foreground"),children:[C.status==="added"&&"A",C.status==="deleted"&&"D",C.status==="modified"&&"M",C.status==="untracked"&&"?"]}),f.jsx("span",{children:C.path})]},C.path)),k&&f.jsxs("label",{className:"flex items-center gap-2 cursor-pointer text-muted-foreground hover:text-foreground mt-1",children:[f.jsx("input",{type:"checkbox",checked:c,onChange:C=>i("includeUntracked",C.target.checked),className:"w-4 h-3"}),f.jsx("span",{children:"Show untracked files"})]})]})]})]}):f.jsxs("div",{className:"flex flex-col h-full bg-background",children:[f.jsxs("div",{className:"flex items-center gap-3 px-2 py-1.5 bg-card border-b border-border text-xs",children:[m?.branch&&f.jsxs("span",{className:"text-muted-foreground",children:[m.branch,m.isBranchDiff&&m.baseBranch&&f.jsxs("span",{className:"opacity-70",children:[" (vs ",m.baseBranch,")"]})]}),(E>0||T>0)&&f.jsxs("span",{className:"text-muted-foreground",children:[f.jsxs("span",{className:"text-accent",children:["+",E]})," ",f.jsxs("span",{className:"text-destructive",children:["-",T]})]}),f.jsx("div",{className:"flex-1"}),f.jsxs("button",{onClick:()=>y?o():s(v),className:"flex items-center gap-1 px-1.5 py-0.5 text-muted-foreground hover:text-foreground rounded hover:bg-muted/50",title:y?"Expand all (Shift+C)":"Collapse all (Shift+C)",children:[f.jsx(re,{icon:y?Hce:Fce,size:12,strokeWidth:2}),f.jsx("span",{className:"hidden sm:inline",children:y?"Expand":"Collapse"})]}),f.jsxs("label",{className:"flex items-center gap-1.5 cursor-pointer text-muted-foreground hover:text-foreground",children:[f.jsx("input",{type:"checkbox",checked:u,onChange:C=>i("wrap",C.target.checked),className:"w-3 h-3"}),"Wrap"]}),f.jsxs("label",{className:"flex items-center gap-1.5 cursor-pointer text-muted-foreground hover:text-foreground",children:[f.jsx("input",{type:"checkbox",checked:d,onChange:C=>i("ignoreWhitespace",C.target.checked),className:"w-3 h-3"}),"Ignore whitespace"]}),f.jsxs("label",{className:"flex items-center gap-1.5 cursor-pointer text-muted-foreground hover:text-foreground",children:[f.jsx("input",{type:"checkbox",checked:c,onChange:C=>i("includeUntracked",C.target.checked),className:"w-3 h-3"}),"Untracked"]})]}),f.jsx(sm,{className:"flex-1 min-h-0",children:b.map(C=>f.jsx(wgt,{file:C,wrap:u,isCollapsed:l(C.path),onToggle:()=>a(C.path)},C.path))})]})}function Cgt(e){const{viewState:t,setBrowserUrl:n}=SB(e);return{url:t.browserUrl,setUrl:n}}function Zae({taskId:e}){const{url:t,setUrl:n}=Cgt(e),[r,i]=w.useState(t),[a,s]=w.useState(0);w.useEffect(()=>{i(t)},[t]);const o=w.useCallback(()=>{s(u=>u+1)},[]),l=w.useCallback(u=>{u.preventDefault();let d=r.trim();!d.startsWith("http://")&&!d.startsWith("https://")&&(d=`http://${d}`),n(d),s(c=>c+1)},[r,n]);return f.jsxs("div",{className:"flex h-full flex-col bg-background",children:[f.jsxs("div",{className:"flex shrink-0 items-center gap-1 border-b border-border bg-card px-2 py-1.5",children:[f.jsx(Te,{variant:"ghost",size:"icon-xs",disabled:!0,children:f.jsx(re,{icon:rd,size:14,strokeWidth:2})}),f.jsx(Te,{variant:"ghost",size:"icon-xs",disabled:!0,children:f.jsx(re,{icon:$u,size:14,strokeWidth:2})}),f.jsx(Te,{variant:"ghost",size:"icon-xs",onClick:o,children:f.jsx(re,{icon:iA,size:14,strokeWidth:2})}),f.jsx("form",{onSubmit:l,className:"flex-1",children:f.jsx($t,{value:r,onChange:u=>i(u.target.value),className:"h-7 bg-background text-xs",placeholder:"Enter URL..."})})]}),f.jsx("div",{className:"flex-1 overflow-hidden bg-card",children:f.jsx("iframe",{src:t,className:"h-full w-full border-0",title:"Browser Preview",sandbox:"allow-scripts allow-same-origin allow-forms allow-popups"},a)})]})}const Tgt="";function Qae(e){const t=[];function n(r){for(const i of r)t.push(`${i.type}:${i.path}`),i.children&&n(i.children)}return n(e),t.sort().join("|")}function kgt({worktreePath:e,currentTree:t,onTreeChanged:n,pollInterval:r=5e3,enabled:i=!0}){const a=w.useRef(null),s=w.useRef(null),o=w.useRef(n);w.useEffect(()=>{o.current=n},[n]),w.useEffect(()=>{t&&(s.current=Qae(t))},[t]);const l=w.useCallback(async()=>{if(e)try{const u=await ft(`${Tgt}/api/fs/tree?root=${encodeURIComponent(e)}`),d=Qae(u.entries);s.current!==null&&d!==s.current&&(s.current=d,o.current(u.entries))}catch{}},[e]);w.useEffect(()=>{if(!i||!e||!t){a.current&&(clearInterval(a.current),a.current=null);return}return a.current=setInterval(l,r),()=>{a.current&&(clearInterval(a.current),a.current=null)}},[i,e,t,r,l]),w.useEffect(()=>{s.current=null},[e])}function Agt(e){const t=[];function n(r){for(const i of r)i.type==="file"?t.push({name:i.name,path:i.path}):i.children&&n(i.children)}return n(e),t}function r1e(e){const t=e.split(".").pop()?.toLowerCase()||"";return["png","jpg","jpeg","gif","svg","webp","ico"].includes(t)?NNe:["ts","tsx","js","jsx","json","css","html","md","yaml","yml","toml","sh","py","rs","go","sql"].includes(t)?ENe:Dce}function i1e({entry:e,depth:t,selectedFile:n,expandedDirs:r,onSelectFile:i,onToggleDir:a}){const s=r.includes(e.path),o=n===e.path,l=e.type==="directory",u=w.useCallback(()=>{l?a(e.path):i(e.path)},[l,e.path,i,a]);return f.jsxs("div",{children:[f.jsxs("div",{className:Ne("flex items-center gap-1.5 px-2 py-0.5 cursor-pointer text-sm hover:bg-muted/50",o&&"bg-primary/10 text-primary"),style:{paddingLeft:`${t*12+8}px`},onClick:u,children:[f.jsx(re,{icon:l?s?Kj:Ya:r1e(e.name),size:14,strokeWidth:2,className:Ne("shrink-0",l?"text-accent":"text-muted-foreground")}),f.jsx("span",{className:"break-all",children:e.name})]}),l&&s&&e.children&&f.jsx("div",{children:e.children.map(d=>f.jsx(i1e,{entry:d,depth:t+1,selectedFile:n,expandedDirs:r,onSelectFile:i,onToggleDir:a},d.path))})]})}function Ogt({entries:e,selectedFile:t,expandedDirs:n,onSelectFile:r,onToggleDir:i,onCollapseAll:a}){const{t:s}=Nt("repositories"),[o,l]=w.useState(""),u=w.useMemo(()=>Agt(e),[e]),d=w.useMemo(()=>{if(!o.trim())return null;const p=o.trim();return u.map(m=>({...m,score:Math.max(Cs(m.name,p),Cs(m.path,p))})).filter(m=>m.score>0).sort((m,x)=>x.score-m.score)},[u,o]),c=w.useCallback(()=>{l("")},[]);return e.length===0?f.jsx("div",{className:"flex items-center justify-center h-full text-muted-foreground text-sm",children:s("detailView.fileTree.noFiles")}):f.jsxs("div",{className:"flex flex-col h-full bg-background",children:[f.jsxs("div",{className:"flex shrink-0 items-center justify-between px-2 py-1 border-b border-border bg-card",children:[f.jsx("span",{className:"text-xs text-muted-foreground",children:s("detailView.fileTree.title")}),f.jsx("button",{onClick:a,className:"p-1 text-muted-foreground hover:text-foreground rounded hover:bg-muted/50",title:s("detailView.fileTree.collapseAll"),children:f.jsx(re,{icon:Fce,size:14,strokeWidth:2})})]}),f.jsx("div",{className:"shrink-0 px-2 py-1.5 border-b border-border bg-card",children:f.jsxs("div",{className:"relative",children:[f.jsx("input",{type:"text",value:o,onChange:p=>l(p.target.value),placeholder:s("detailView.fileTree.searchPlaceholder"),className:"w-full text-sm bg-muted/50 border border-border rounded px-2 py-1 pr-7 placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring"}),o&&f.jsx("button",{onClick:c,className:"absolute right-1.5 top-1/2 -translate-y-1/2 p-0.5 text-muted-foreground hover:text-foreground rounded hover:bg-muted",children:f.jsx(re,{icon:Bn,size:12,strokeWidth:2})})]})}),f.jsx("div",{className:"py-1 flex-1 overflow-auto",children:d?d.length>0?d.map(p=>f.jsxs("div",{className:Ne("flex items-center gap-1.5 px-2 py-0.5 cursor-pointer text-sm hover:bg-muted/50",t===p.path&&"bg-primary/10 text-primary"),onClick:()=>r(p.path),children:[f.jsx(re,{icon:r1e(p.name),size:14,strokeWidth:2,className:"shrink-0 text-muted-foreground"}),f.jsx("span",{className:"truncate",title:p.path,children:p.name}),f.jsx("span",{className:"text-xs text-muted-foreground truncate ml-auto",children:p.path.split("/").slice(0,-1).join("/")})]},p.path)):f.jsx("div",{className:"px-2 py-4 text-center text-sm text-muted-foreground",children:"No matching files"}):e.map(p=>f.jsx(i1e,{entry:p,depth:0,selectedFile:t,expandedDirs:n,onSelectFile:r,onToggleDir:i},p.path))})]})}const Rgt="";function Ngt({worktreePath:e,filePath:t,currentMtime:n,isDirty:r,pollInterval:i=3e3,enabled:a=!0}){const[s,o]=w.useState(!1),l=w.useRef(null),u=w.useRef(null),d=w.useCallback(async()=>{if(!(!e||!t||!n))try{const p=new URLSearchParams({path:t,root:e}),m=await ft(`${Rgt}/api/fs/file-stat?${p}`);m.exists&&m.mtime!==n&&u.current!==m.mtime&&(u.current=m.mtime,o(!0))}catch{}},[e,t,n]);w.useEffect(()=>{if(!a||!t||!n){l.current&&(clearInterval(l.current),l.current=null);return}u.current=null;const p=setTimeout(d,500);return l.current=setInterval(d,i),()=>{clearTimeout(p),l.current&&(clearInterval(l.current),l.current=null)}},[a,t,n,i,d]),w.useEffect(()=>{o(!1),u.current=null},[t]);const c=w.useCallback(()=>{o(!1)},[]);return{hasExternalChange:s,isConflict:s&&r,resetExternalChange:c}}function Jae(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function Igt(e){if(Array.isArray(e))return e}function Dgt(e,t,n){return(t=$gt(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Lgt(e,t){var n=e==null?null:typeof Symbol<"u"&&e[Symbol.iterator]||e["@@iterator"];if(n!=null){var r,i,a,s,o=[],l=!0,u=!1;try{if(a=(n=n.call(e)).next,t!==0)for(;!(l=(r=a.call(n)).done)&&(o.push(r.value),o.length!==t);l=!0);}catch(d){u=!0,i=d}finally{try{if(!l&&n.return!=null&&(s=n.return(),Object(s)!==s))return}finally{if(u)throw i}}return o}}function Pgt(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
|
|
127
127
|
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function ese(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(i){return Object.getOwnPropertyDescriptor(e,i).enumerable})),n.push.apply(n,r)}return n}function tse(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?arguments[t]:{};t%2?ese(Object(n),!0).forEach(function(r){Dgt(e,r,n[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):ese(Object(n)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(n,r))})}return e}function Mgt(e,t){if(e==null)return{};var n,r,i=jgt(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)===-1&&{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function jgt(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function Fgt(e,t){return Igt(e)||Lgt(e,t)||Ugt(e,t)||Pgt()}function Bgt(e,t){if(typeof e!="object"||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t);if(typeof r!="object")return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return(t==="string"?String:Number)(e)}function $gt(e){var t=Bgt(e,"string");return typeof t=="symbol"?t:t+""}function Ugt(e,t){if(e){if(typeof e=="string")return Jae(e,t);var n={}.toString.call(e).slice(8,-1);return n==="Object"&&e.constructor&&(n=e.constructor.name),n==="Map"||n==="Set"?Array.from(e):n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Jae(e,t):void 0}}function zgt(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function nse(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(i){return Object.getOwnPropertyDescriptor(e,i).enumerable})),n.push.apply(n,r)}return n}function rse(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?arguments[t]:{};t%2?nse(Object(n),!0).forEach(function(r){zgt(e,r,n[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):nse(Object(n)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(n,r))})}return e}function Hgt(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return function(r){return t.reduceRight(function(i,a){return a(i)},r)}}function R0(e){return function t(){for(var n=this,r=arguments.length,i=new Array(r),a=0;a<r;a++)i[a]=arguments[a];return i.length>=e.length?e.apply(this,i):function(){for(var s=arguments.length,o=new Array(s),l=0;l<s;l++)o[l]=arguments[l];return t.apply(n,[].concat(i,o))}}}function ek(e){return{}.toString.call(e).includes("Object")}function Wgt(e){return!Object.keys(e).length}function Dx(e){return typeof e=="function"}function Vgt(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function qgt(e,t){return ek(t)||jf("changeType"),Object.keys(t).some(function(n){return!Vgt(e,n)})&&jf("changeField"),t}function Ggt(e){Dx(e)||jf("selectorType")}function Ygt(e){Dx(e)||ek(e)||jf("handlerType"),ek(e)&&Object.values(e).some(function(t){return!Dx(t)})&&jf("handlersType")}function Kgt(e){e||jf("initialIsRequired"),ek(e)||jf("initialType"),Wgt(e)&&jf("initialContent")}function Xgt(e,t){throw new Error(e[t]||e.default)}var Zgt={initialIsRequired:"initial state is required",initialType:"initial state should be an object",initialContent:"initial state shouldn't be an empty object",handlerType:"handler should be an object or a function",handlersType:"all handlers should be a functions",selectorType:"selector should be a function",changeType:"provided value of changes should be an object",changeField:'it seams you want to change a field in the state which is not specified in the "initial" state',default:"an unknown error accured in `state-local` package"},jf=R0(Xgt)(Zgt),dw={changes:qgt,selector:Ggt,handler:Ygt,initial:Kgt};function Qgt(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};dw.initial(e),dw.handler(t);var n={current:e},r=R0(tbt)(n,t),i=R0(ebt)(n),a=R0(dw.changes)(e),s=R0(Jgt)(n);function o(){var u=arguments.length>0&&arguments[0]!==void 0?arguments[0]:function(d){return d};return dw.selector(u),u(n.current)}function l(u){Hgt(r,i,a,s)(u)}return[o,l]}function Jgt(e,t){return Dx(t)?t(e.current):t}function ebt(e,t){return e.current=rse(rse({},e.current),t),t}function tbt(e,t,n){return Dx(t)?t(e.current):Object.keys(n).forEach(function(r){var i;return(i=t[r])===null||i===void 0?void 0:i.call(t,e.current[r])}),n}var nbt={create:Qgt},rbt={paths:{vs:"https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs"}};function ibt(e){return function t(){for(var n=this,r=arguments.length,i=new Array(r),a=0;a<r;a++)i[a]=arguments[a];return i.length>=e.length?e.apply(this,i):function(){for(var s=arguments.length,o=new Array(s),l=0;l<s;l++)o[l]=arguments[l];return t.apply(n,[].concat(i,o))}}}function abt(e){return{}.toString.call(e).includes("Object")}function sbt(e){return e||ise("configIsRequired"),abt(e)||ise("configType"),e.urls?(obt(),{paths:{vs:e.urls.monacoBase}}):e}function obt(){console.warn(a1e.deprecation)}function lbt(e,t){throw new Error(e[t]||e.default)}var a1e={configIsRequired:"the configuration object is required",configType:"the configuration object should be an object",default:"an unknown error accured in `@monaco-editor/loader` package",deprecation:`Deprecation warning!
|
|
128
128
|
You are using deprecated way of configuration.
|
package/dist/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" type="image/png" href="/logo.png" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Project Fulcrum</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-fIJu9jIH.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-_aUlx8a1.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|