@knowsuchagency/fulcrum 5.13.0 → 5.13.2
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 +4 -4
- package/package.json +1 -1
- package/server/index.js +94 -39
package/bin/fulcrum.js
CHANGED
|
@@ -46869,7 +46869,7 @@ async function runMcpServer(urlOverride, portOverride) {
|
|
|
46869
46869
|
const client = new FulcrumClient(urlOverride, portOverride);
|
|
46870
46870
|
const server = new McpServer({
|
|
46871
46871
|
name: "fulcrum",
|
|
46872
|
-
version: "5.13.
|
|
46872
|
+
version: "5.13.2"
|
|
46873
46873
|
});
|
|
46874
46874
|
registerTools(server, client);
|
|
46875
46875
|
const transport = new StdioServerTransport;
|
|
@@ -49218,7 +49218,7 @@ var marketplace_default = `{
|
|
|
49218
49218
|
"name": "fulcrum",
|
|
49219
49219
|
"source": "./",
|
|
49220
49220
|
"description": "Task orchestration for Claude Code",
|
|
49221
|
-
"version": "5.13.
|
|
49221
|
+
"version": "5.13.2",
|
|
49222
49222
|
"skills": [
|
|
49223
49223
|
"./skills/fulcrum"
|
|
49224
49224
|
],
|
|
@@ -49241,7 +49241,7 @@ var marketplace_default = `{
|
|
|
49241
49241
|
var plugin_default = `{
|
|
49242
49242
|
"name": "fulcrum",
|
|
49243
49243
|
"description": "Fulcrum task orchestration for Claude Code",
|
|
49244
|
-
"version": "5.13.
|
|
49244
|
+
"version": "5.13.2",
|
|
49245
49245
|
"author": {
|
|
49246
49246
|
"name": "Fulcrum"
|
|
49247
49247
|
},
|
|
@@ -50280,7 +50280,7 @@ function compareVersions(v1, v2) {
|
|
|
50280
50280
|
var package_default = {
|
|
50281
50281
|
name: "@knowsuchagency/fulcrum",
|
|
50282
50282
|
private: true,
|
|
50283
|
-
version: "5.13.
|
|
50283
|
+
version: "5.13.2",
|
|
50284
50284
|
description: "Harness Attention. Orchestrate Agents. Ship.",
|
|
50285
50285
|
license: "PolyForm-Perimeter-1.0.0",
|
|
50286
50286
|
type: "module",
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -13481,11 +13481,15 @@ class HerdrService {
|
|
|
13481
13481
|
session;
|
|
13482
13482
|
binary;
|
|
13483
13483
|
requestSeq = 0;
|
|
13484
|
+
inflightEnsure = new Map;
|
|
13484
13485
|
constructor(session3, binary) {
|
|
13485
13486
|
this.session = session3;
|
|
13486
13487
|
this.binary = binary;
|
|
13487
13488
|
}
|
|
13488
13489
|
getApiSocketPath() {
|
|
13490
|
+
if (this.session === DEFAULT_SESSION) {
|
|
13491
|
+
return path5.join(CONFIG_DIR, "herdr.sock");
|
|
13492
|
+
}
|
|
13489
13493
|
return path5.join(CONFIG_DIR, "sessions", this.session, "herdr.sock");
|
|
13490
13494
|
}
|
|
13491
13495
|
isServerRunning() {
|
|
@@ -13496,7 +13500,8 @@ class HerdrService {
|
|
|
13496
13500
|
return true;
|
|
13497
13501
|
log2.terminal.info("herdr server not running; starting it", { session: this.session });
|
|
13498
13502
|
try {
|
|
13499
|
-
const
|
|
13503
|
+
const args = this.session === DEFAULT_SESSION ? ["server"] : ["--session", this.session, "server"];
|
|
13504
|
+
const child = spawn2(this.binary, args, {
|
|
13500
13505
|
stdio: "ignore",
|
|
13501
13506
|
detached: true
|
|
13502
13507
|
});
|
|
@@ -13579,6 +13584,18 @@ class HerdrService {
|
|
|
13579
13584
|
return this.call("workspace.create", opts);
|
|
13580
13585
|
}
|
|
13581
13586
|
async ensureWorkspace(opts) {
|
|
13587
|
+
const pending = this.inflightEnsure.get(opts.label);
|
|
13588
|
+
if (pending)
|
|
13589
|
+
return pending;
|
|
13590
|
+
const work = this.doEnsureWorkspace(opts);
|
|
13591
|
+
this.inflightEnsure.set(opts.label, work);
|
|
13592
|
+
try {
|
|
13593
|
+
return await work;
|
|
13594
|
+
} finally {
|
|
13595
|
+
this.inflightEnsure.delete(opts.label);
|
|
13596
|
+
}
|
|
13597
|
+
}
|
|
13598
|
+
async doEnsureWorkspace(opts) {
|
|
13582
13599
|
const existing = await this.listWorkspaces();
|
|
13583
13600
|
const hit = existing.find((w2) => w2.label === opts.label);
|
|
13584
13601
|
if (hit)
|
|
@@ -13596,6 +13613,17 @@ class HerdrService {
|
|
|
13596
13613
|
async closeTab(tabId) {
|
|
13597
13614
|
await this.call("tab.close", { tab_id: tabId });
|
|
13598
13615
|
}
|
|
13616
|
+
async splitPane(opts) {
|
|
13617
|
+
return this.call("pane.split", {
|
|
13618
|
+
target_pane_id: opts.targetPaneId,
|
|
13619
|
+
direction: opts.direction,
|
|
13620
|
+
...opts.cwd ? { cwd: opts.cwd } : {},
|
|
13621
|
+
focus: opts.focus ?? false
|
|
13622
|
+
});
|
|
13623
|
+
}
|
|
13624
|
+
async closePane(paneId) {
|
|
13625
|
+
await this.call("pane.close", { pane_id: paneId });
|
|
13626
|
+
}
|
|
13599
13627
|
async listPanes(workspaceId) {
|
|
13600
13628
|
const r = await this.call("pane.list", workspaceId ? { workspace_id: workspaceId } : {});
|
|
13601
13629
|
return r.panes ?? [];
|
|
@@ -13640,7 +13668,7 @@ function getHerdrService() {
|
|
|
13640
13668
|
}
|
|
13641
13669
|
return cached;
|
|
13642
13670
|
}
|
|
13643
|
-
var CONFIG_DIR, RESPONSE_TIMEOUT_MS = 4000, START_POLL_MS = 100, START_POLL_ATTEMPTS = 30, cached = null, cachedKey = "";
|
|
13671
|
+
var CONFIG_DIR, RESPONSE_TIMEOUT_MS = 4000, START_POLL_MS = 100, START_POLL_ATTEMPTS = 30, DEFAULT_SESSION = "default", cached = null, cachedKey = "";
|
|
13644
13672
|
var init_herdr_service = __esm(() => {
|
|
13645
13673
|
init_logger3();
|
|
13646
13674
|
init_settings();
|
|
@@ -13744,42 +13772,65 @@ async function mirrorTerminal(terminalId) {
|
|
|
13744
13772
|
});
|
|
13745
13773
|
return;
|
|
13746
13774
|
}
|
|
13747
|
-
const
|
|
13748
|
-
|
|
13749
|
-
|
|
13750
|
-
|
|
13751
|
-
|
|
13752
|
-
|
|
13753
|
-
|
|
13754
|
-
|
|
13755
|
-
|
|
13756
|
-
|
|
13757
|
-
|
|
13758
|
-
|
|
13759
|
-
|
|
13760
|
-
|
|
13761
|
-
|
|
13762
|
-
|
|
13763
|
-
|
|
13764
|
-
|
|
13765
|
-
|
|
13766
|
-
|
|
13767
|
-
terminalId,
|
|
13768
|
-
paneId: tab.root_pane.pane_id,
|
|
13769
|
-
agent: target.agent
|
|
13775
|
+
const sibling = findSiblingWithPane(row.taskId, terminalId);
|
|
13776
|
+
let workspaceId;
|
|
13777
|
+
let tabId;
|
|
13778
|
+
let paneId;
|
|
13779
|
+
let isSplit = false;
|
|
13780
|
+
if (sibling) {
|
|
13781
|
+
const split = await svc.splitPane({
|
|
13782
|
+
targetPaneId: sibling.herdrPaneId,
|
|
13783
|
+
direction: "right",
|
|
13784
|
+
cwd: target.workspaceCwd,
|
|
13785
|
+
focus: false
|
|
13786
|
+
});
|
|
13787
|
+
workspaceId = sibling.herdrWorkspaceId;
|
|
13788
|
+
tabId = sibling.herdrTabId;
|
|
13789
|
+
paneId = split.pane.pane_id;
|
|
13790
|
+
isSplit = true;
|
|
13791
|
+
} else {
|
|
13792
|
+
const { workspace } = await svc.ensureWorkspace({
|
|
13793
|
+
label: target.workspaceLabel,
|
|
13794
|
+
cwd: target.workspaceCwd
|
|
13770
13795
|
});
|
|
13771
|
-
|
|
13772
|
-
|
|
13773
|
-
|
|
13774
|
-
|
|
13775
|
-
error: String(err)
|
|
13796
|
+
const tab = await svc.createTab({
|
|
13797
|
+
workspaceId: workspace.workspace_id,
|
|
13798
|
+
label: target.tabLabel,
|
|
13799
|
+
cwd: target.workspaceCwd
|
|
13776
13800
|
});
|
|
13801
|
+
workspaceId = workspace.workspace_id;
|
|
13802
|
+
tabId = tab.tab.tab_id;
|
|
13803
|
+
paneId = tab.root_pane.pane_id;
|
|
13804
|
+
}
|
|
13805
|
+
const dtach = getDtachService();
|
|
13806
|
+
const socketPath = dtach.getSocketPath(terminalId);
|
|
13807
|
+
await svc.runInPane(paneId, `stty -echoctl && exec dtach -a ${socketPath} -z`);
|
|
13808
|
+
if (!isSplit) {
|
|
13809
|
+
try {
|
|
13810
|
+
await svc.reportAgent(paneId, {
|
|
13811
|
+
source: "fulcrum",
|
|
13812
|
+
agent: target.agent,
|
|
13813
|
+
state: "working",
|
|
13814
|
+
message: target.tabLabel
|
|
13815
|
+
});
|
|
13816
|
+
log2.terminal.info("herdr agent reported", {
|
|
13817
|
+
terminalId,
|
|
13818
|
+
paneId,
|
|
13819
|
+
agent: target.agent
|
|
13820
|
+
});
|
|
13821
|
+
} catch (err) {
|
|
13822
|
+
log2.terminal.warn("reportAgent failed (non-fatal)", {
|
|
13823
|
+
terminalId,
|
|
13824
|
+
paneId,
|
|
13825
|
+
error: String(err)
|
|
13826
|
+
});
|
|
13827
|
+
}
|
|
13777
13828
|
}
|
|
13778
13829
|
const now = new Date().toISOString();
|
|
13779
13830
|
db2.update(terminals).set({
|
|
13780
|
-
herdrWorkspaceId:
|
|
13781
|
-
herdrTabId:
|
|
13782
|
-
herdrPaneId:
|
|
13831
|
+
herdrWorkspaceId: workspaceId,
|
|
13832
|
+
herdrTabId: tabId,
|
|
13833
|
+
herdrPaneId: paneId,
|
|
13783
13834
|
updatedAt: now
|
|
13784
13835
|
}).where(eq(terminals.id, terminalId)).run();
|
|
13785
13836
|
log2.terminal.info("herdr mirror created", {
|
|
@@ -13787,7 +13838,8 @@ async function mirrorTerminal(terminalId) {
|
|
|
13787
13838
|
taskId: row.taskId,
|
|
13788
13839
|
workspaceLabel: target.workspaceLabel,
|
|
13789
13840
|
tabLabel: target.tabLabel,
|
|
13790
|
-
paneId
|
|
13841
|
+
paneId,
|
|
13842
|
+
split: isSplit
|
|
13791
13843
|
});
|
|
13792
13844
|
} catch (err) {
|
|
13793
13845
|
log2.terminal.warn("mirrorTerminal: failed (continuing without mirror)", {
|
|
@@ -13797,6 +13849,9 @@ async function mirrorTerminal(terminalId) {
|
|
|
13797
13849
|
});
|
|
13798
13850
|
}
|
|
13799
13851
|
}
|
|
13852
|
+
function findSiblingWithPane(taskId, selfTerminalId) {
|
|
13853
|
+
return db2.select().from(terminals).where(and(eq(terminals.taskId, taskId), ne(terminals.id, selfTerminalId), isNotNull(terminals.herdrPaneId), isNotNull(terminals.herdrTabId), isNotNull(terminals.herdrWorkspaceId))).get();
|
|
13854
|
+
}
|
|
13800
13855
|
async function closeMirror(terminalId) {
|
|
13801
13856
|
if (!isMirrorEnabled())
|
|
13802
13857
|
return;
|
|
@@ -13804,7 +13859,7 @@ async function closeMirror(terminalId) {
|
|
|
13804
13859
|
if (autoClose === false)
|
|
13805
13860
|
return;
|
|
13806
13861
|
const row = db2.select().from(terminals).where(eq(terminals.id, terminalId)).get();
|
|
13807
|
-
if (!row?.
|
|
13862
|
+
if (!row?.herdrPaneId)
|
|
13808
13863
|
return;
|
|
13809
13864
|
try {
|
|
13810
13865
|
const svc = getHerdrService();
|
|
@@ -13813,12 +13868,12 @@ async function closeMirror(terminalId) {
|
|
|
13813
13868
|
clearMirrorIds(terminalId);
|
|
13814
13869
|
return;
|
|
13815
13870
|
}
|
|
13816
|
-
await svc.
|
|
13817
|
-
log2.terminal.info("herdr mirror closed", { terminalId,
|
|
13871
|
+
await svc.closePane(row.herdrPaneId);
|
|
13872
|
+
log2.terminal.info("herdr mirror closed", { terminalId, paneId: row.herdrPaneId });
|
|
13818
13873
|
} catch (err) {
|
|
13819
13874
|
log2.terminal.warn("closeMirror: failed", {
|
|
13820
13875
|
terminalId,
|
|
13821
|
-
|
|
13876
|
+
paneId: row.herdrPaneId,
|
|
13822
13877
|
error: String(err)
|
|
13823
13878
|
});
|
|
13824
13879
|
} finally {
|
|
@@ -1282679,7 +1282734,7 @@ mcpRoutes.all("/", async (c) => {
|
|
|
1282679
1282734
|
});
|
|
1282680
1282735
|
const server2 = new McpServer({
|
|
1282681
1282736
|
name: "fulcrum",
|
|
1282682
|
-
version: "5.13.
|
|
1282737
|
+
version: "5.13.2"
|
|
1282683
1282738
|
});
|
|
1282684
1282739
|
const client3 = new FulcrumClient(`http://localhost:${port}`);
|
|
1282685
1282740
|
registerTools(server2, client3);
|