@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 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.0"
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.0",
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.0",
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.0",
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowsuchagency/fulcrum",
3
- "version": "5.13.0",
3
+ "version": "5.13.2",
4
4
  "description": "Harness Attention. Orchestrate Agents. Ship.",
5
5
  "license": "PolyForm-Perimeter-1.0.0",
6
6
  "repository": {
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 child = spawn2(this.binary, ["--session", this.session, "server"], {
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 { workspace } = await svc.ensureWorkspace({
13748
- label: target.workspaceLabel,
13749
- cwd: target.workspaceCwd
13750
- });
13751
- const tab = await svc.createTab({
13752
- workspaceId: workspace.workspace_id,
13753
- label: target.tabLabel,
13754
- cwd: target.workspaceCwd
13755
- });
13756
- const dtach = getDtachService();
13757
- const socketPath = dtach.getSocketPath(terminalId);
13758
- await svc.runInPane(tab.root_pane.pane_id, `stty -echoctl && exec dtach -a ${socketPath} -z`);
13759
- try {
13760
- await svc.reportAgent(tab.root_pane.pane_id, {
13761
- source: "fulcrum",
13762
- agent: target.agent,
13763
- state: "working",
13764
- message: target.tabLabel
13765
- });
13766
- log2.terminal.info("herdr agent reported", {
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
- } catch (err) {
13772
- log2.terminal.warn("reportAgent failed (non-fatal)", {
13773
- terminalId,
13774
- paneId: tab.root_pane.pane_id,
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: workspace.workspace_id,
13781
- herdrTabId: tab.tab.tab_id,
13782
- herdrPaneId: tab.root_pane.pane_id,
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: tab.root_pane.pane_id
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?.herdrTabId)
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.closeTab(row.herdrTabId);
13817
- log2.terminal.info("herdr mirror closed", { terminalId, tabId: row.herdrTabId });
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
- tabId: row.herdrTabId,
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.0"
1282737
+ version: "5.13.2"
1282683
1282738
  });
1282684
1282739
  const client3 = new FulcrumClient(`http://localhost:${port}`);
1282685
1282740
  registerTools(server2, client3);