@knowsuchagency/fulcrum 2.15.2 → 2.15.3

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
@@ -46235,7 +46235,7 @@ async function runMcpServer(urlOverride, portOverride) {
46235
46235
  const client = new FulcrumClient(urlOverride, portOverride);
46236
46236
  const server = new McpServer({
46237
46237
  name: "fulcrum",
46238
- version: "2.15.2"
46238
+ version: "2.15.3"
46239
46239
  });
46240
46240
  registerTools(server, client);
46241
46241
  const transport = new StdioServerTransport;
@@ -48584,7 +48584,7 @@ var marketplace_default = `{
48584
48584
  "name": "fulcrum",
48585
48585
  "source": "./",
48586
48586
  "description": "Task orchestration for Claude Code",
48587
- "version": "2.15.2",
48587
+ "version": "2.15.3",
48588
48588
  "skills": [
48589
48589
  "./skills/fulcrum"
48590
48590
  ],
@@ -49772,7 +49772,7 @@ function compareVersions(v1, v2) {
49772
49772
  var package_default = {
49773
49773
  name: "@knowsuchagency/fulcrum",
49774
49774
  private: true,
49775
- version: "2.15.2",
49775
+ version: "2.15.3",
49776
49776
  description: "Harness Attention. Orchestrate Agents. Ship.",
49777
49777
  license: "PolyForm-Perimeter-1.0.0",
49778
49778
  type: "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowsuchagency/fulcrum",
3
- "version": "2.15.2",
3
+ "version": "2.15.3",
4
4
  "description": "Harness Attention. Orchestrate Agents. Ship.",
5
5
  "license": "PolyForm-Perimeter-1.0.0",
6
6
  "repository": {
package/server/index.js CHANGED
@@ -1200858,7 +1200858,7 @@ var init_slack = __esm(() => {
1200858
1200858
  });
1200859
1200859
 
1200860
1200860
  // server/services/channels/session-mapper.ts
1200861
- function getOrCreateSession(connectionId, channelUserId, channelUserName, sessionKey) {
1200861
+ function getOrCreateSession(connectionId, channelUserId, channelUserName, sessionKey, channelType) {
1200862
1200862
  const lookupKey = sessionKey ?? channelUserId;
1200863
1200863
  const now = new Date().toISOString();
1200864
1200864
  const existingMapping = db2.select().from(messagingSessionMappings).where(and(eq(messagingSessionMappings.connectionId, connectionId), eq(messagingSessionMappings.channelUserId, lookupKey))).get();
@@ -1200879,7 +1200879,7 @@ function getOrCreateSession(connectionId, channelUserId, channelUserName, sessio
1200879
1200879
  });
1200880
1200880
  }
1200881
1200881
  const sessionId = nanoid();
1200882
- const sessionTitle = channelUserName ? `Chat with ${channelUserName}` : `Chat ${channelUserId}`;
1200882
+ const sessionTitle = channelType ? `${channelType.charAt(0).toUpperCase() + channelType.slice(1)} Chat` : channelUserName ? `Chat with ${channelUserName}` : `Chat ${channelUserId}`;
1200883
1200883
  const newSession = {
1200884
1200884
  id: sessionId,
1200885
1200885
  title: sessionTitle,
@@ -1200920,12 +1200920,12 @@ function getOrCreateSession(connectionId, channelUserId, channelUserName, sessio
1200920
1200920
  });
1200921
1200921
  return { mapping, session: session3, isNew: true };
1200922
1200922
  }
1200923
- function resetSession(connectionId, channelUserId, channelUserName, sessionKey) {
1200923
+ function resetSession(connectionId, channelUserId, channelUserName, sessionKey, channelType) {
1200924
1200924
  const now = new Date().toISOString();
1200925
1200925
  const lookupKey = sessionKey ?? channelUserId;
1200926
1200926
  const existingMapping = db2.select().from(messagingSessionMappings).where(and(eq(messagingSessionMappings.connectionId, connectionId), eq(messagingSessionMappings.channelUserId, lookupKey))).get();
1200927
1200927
  const sessionId = nanoid();
1200928
- const sessionTitle = channelUserName ? `Chat with ${channelUserName}` : `Chat ${channelUserId}`;
1200928
+ const sessionTitle = channelType ? `${channelType.charAt(0).toUpperCase() + channelType.slice(1)} Chat` : channelUserName ? `Chat with ${channelUserName}` : `Chat ${channelUserId}`;
1200929
1200929
  const newSession = {
1200930
1200930
  id: sessionId,
1200931
1200931
  title: sessionTitle,
@@ -1200967,11 +1200967,43 @@ function resetSession(connectionId, channelUserId, channelUserName, sessionKey)
1200967
1200967
  function listSessionMappings(connectionId) {
1200968
1200968
  return db2.select().from(messagingSessionMappings).where(eq(messagingSessionMappings.connectionId, connectionId)).all();
1200969
1200969
  }
1200970
+ function migrateSessionTitles() {
1200971
+ const rows = db2.select({
1200972
+ sessionId: messagingSessionMappings.sessionId,
1200973
+ connectionId: messagingSessionMappings.connectionId,
1200974
+ sessionTitle: chatSessions.title
1200975
+ }).from(messagingSessionMappings).innerJoin(chatSessions, eq(messagingSessionMappings.sessionId, chatSessions.id)).where(or(like(chatSessions.title, "Chat with %"), like(chatSessions.title, "Chat %"))).all();
1200976
+ if (rows.length === 0)
1200977
+ return;
1200978
+ const dbConnections = db2.select({ id: messagingConnections.id, channelType: messagingConnections.channelType }).from(messagingConnections).all();
1200979
+ const dbConnectionMap = new Map(dbConnections.map((c) => [c.id, c.channelType]));
1200980
+ let updated = 0;
1200981
+ for (const row of rows) {
1200982
+ const channelType = CONNECTION_ID_TO_CHANNEL[row.connectionId] ?? dbConnectionMap.get(row.connectionId);
1200983
+ if (!channelType)
1200984
+ continue;
1200985
+ const newTitle = `${channelType.charAt(0).toUpperCase() + channelType.slice(1)} Chat`;
1200986
+ if (row.sessionTitle !== newTitle) {
1200987
+ db2.update(chatSessions).set({ title: newTitle }).where(eq(chatSessions.id, row.sessionId)).run();
1200988
+ updated++;
1200989
+ }
1200990
+ }
1200991
+ if (updated > 0) {
1200992
+ log2.messaging.info("Migrated channel session titles", { updated, total: rows.length });
1200993
+ }
1200994
+ }
1200995
+ var CONNECTION_ID_TO_CHANNEL;
1200970
1200996
  var init_session_mapper = __esm(() => {
1200971
1200997
  init_nanoid();
1200972
1200998
  init_drizzle_orm();
1200973
1200999
  init_db2();
1200974
1201000
  init_logger3();
1201001
+ CONNECTION_ID_TO_CHANNEL = {
1201002
+ "slack-channel": "slack",
1201003
+ "discord-channel": "discord",
1201004
+ "telegram-channel": "telegram",
1201005
+ "email-channel": "email"
1201006
+ };
1200975
1201007
  });
1200976
1201008
 
1200977
1201009
  // server/services/channels/system-prompts.ts
@@ -1201547,7 +1201579,7 @@ async function handleIncomingMessage(msg) {
1201547
1201579
  return;
1201548
1201580
  }
1201549
1201581
  const emailThreadId = msg.channelType === "email" ? msg.metadata?.threadId : undefined;
1201550
- const { session: session3 } = getOrCreateSession(msg.connectionId, msg.senderId, msg.senderName, emailThreadId);
1201582
+ const { session: session3 } = getOrCreateSession(msg.connectionId, msg.senderId, msg.senderName, emailThreadId, msg.channelType);
1201551
1201583
  log2.messaging.info("Routing message to assistant", {
1201552
1201584
  connectionId: msg.connectionId,
1201553
1201585
  senderId: msg.senderId,
@@ -1201585,7 +1201617,7 @@ async function handleIncomingMessage(msg) {
1201585
1201617
  }
1201586
1201618
  }
1201587
1201619
  async function handleResetCommand(msg) {
1201588
- resetSession(msg.connectionId, msg.senderId, msg.senderName);
1201620
+ resetSession(msg.connectionId, msg.senderId, msg.senderName, undefined, msg.channelType);
1201589
1201621
  if (msg.channelType === "slack") {
1201590
1201622
  const blocks = [
1201591
1201623
  {
@@ -1201659,7 +1201691,7 @@ Just send any message and I'll do my best to help!`;
1201659
1201691
  }
1201660
1201692
  async function handleStatusCommand(msg) {
1201661
1201693
  const emailThreadId = msg.channelType === "email" ? msg.metadata?.threadId : undefined;
1201662
- const { session: session3, mapping } = getOrCreateSession(msg.connectionId, msg.senderId, msg.senderName, emailThreadId);
1201694
+ const { session: session3, mapping } = getOrCreateSession(msg.connectionId, msg.senderId, msg.senderName, emailThreadId, msg.channelType);
1201663
1201695
  if (msg.channelType === "slack") {
1201664
1201696
  const blocks = [
1201665
1201697
  {
@@ -1201753,7 +1201785,7 @@ function splitMessage(content, maxLength) {
1201753
1201785
  }
1201754
1201786
  async function processObserveOnlyMessage(msg) {
1201755
1201787
  const observeSessionKey = `observe-${msg.connectionId}`;
1201756
- const { session: session3 } = getOrCreateSession(msg.connectionId, observeSessionKey, "Observer");
1201788
+ const { session: session3 } = getOrCreateSession(msg.connectionId, observeSessionKey, "Observer", undefined, msg.channelType);
1201757
1201789
  const settings = getSettings();
1201758
1201790
  const observerProvider = settings.assistant.observerProvider ?? settings.assistant.provider;
1201759
1201791
  if (observerProvider === "opencode") {
@@ -1202097,6 +1202129,7 @@ var init_channels = __esm(() => {
1202097
1202129
  init_telegram();
1202098
1202130
  init_slack();
1202099
1202131
  init_message_handler();
1202132
+ init_session_mapper();
1202100
1202133
  init_channel_manager();
1202101
1202134
  init_message_handler();
1202102
1202135
  init_whatsapp();
@@ -1202105,6 +1202138,7 @@ var init_channels = __esm(() => {
1202105
1202138
  init_slack();
1202106
1202139
  init_email3();
1202107
1202140
  init_session_mapper();
1202141
+ migrateSessionTitles();
1202108
1202142
  });
1202109
1202143
 
1202110
1202144
  // node_modules/cross-fetch/dist/node-ponyfill.js
@@ -1260424,7 +1260458,7 @@ mcpRoutes.all("/", async (c) => {
1260424
1260458
  });
1260425
1260459
  const server = new McpServer({
1260426
1260460
  name: "fulcrum",
1260427
- version: "2.15.2"
1260461
+ version: "2.15.3"
1260428
1260462
  });
1260429
1260463
  const client = new FulcrumClient(`http://localhost:${port}`);
1260430
1260464
  registerTools(server, client);
@@ -1263528,13 +1263562,16 @@ async function checkDatabaseAvailable() {
1263528
1263562
  encoding: "utf-8"
1263529
1263563
  }).trim();
1263530
1263564
  if (result) {
1263531
- const pid = parseInt(result.split(`
1263532
- `)[0], 10);
1263533
- return {
1263534
- available: false,
1263535
- error: `Database is already in use by process ${pid}: ${dbPath}`,
1263536
- pid
1263537
- };
1263565
+ const myPid = process.pid;
1263566
+ const otherPids = result.split(`
1263567
+ `).map(Number).filter((pid) => pid !== myPid);
1263568
+ if (otherPids.length > 0) {
1263569
+ return {
1263570
+ available: false,
1263571
+ error: `Database is already in use by process ${otherPids[0]}: ${dbPath}`,
1263572
+ pid: otherPids[0]
1263573
+ };
1263574
+ }
1263538
1263575
  }
1263539
1263576
  } catch {}
1263540
1263577
  return { available: true };