@knowsuchagency/fulcrum 3.6.11 → 3.7.1
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
|
@@ -46445,7 +46445,7 @@ async function runMcpServer(urlOverride, portOverride) {
|
|
|
46445
46445
|
const client = new FulcrumClient(urlOverride, portOverride);
|
|
46446
46446
|
const server = new McpServer({
|
|
46447
46447
|
name: "fulcrum",
|
|
46448
|
-
version: "3.
|
|
46448
|
+
version: "3.7.1"
|
|
46449
46449
|
});
|
|
46450
46450
|
registerTools(server, client);
|
|
46451
46451
|
const transport = new StdioServerTransport;
|
|
@@ -48794,7 +48794,7 @@ var marketplace_default = `{
|
|
|
48794
48794
|
"name": "fulcrum",
|
|
48795
48795
|
"source": "./",
|
|
48796
48796
|
"description": "Task orchestration for Claude Code",
|
|
48797
|
-
"version": "3.
|
|
48797
|
+
"version": "3.7.1",
|
|
48798
48798
|
"skills": [
|
|
48799
48799
|
"./skills/fulcrum"
|
|
48800
48800
|
],
|
|
@@ -49998,7 +49998,7 @@ function compareVersions(v1, v2) {
|
|
|
49998
49998
|
var package_default = {
|
|
49999
49999
|
name: "@knowsuchagency/fulcrum",
|
|
50000
50000
|
private: true,
|
|
50001
|
-
version: "3.
|
|
50001
|
+
version: "3.7.1",
|
|
50002
50002
|
description: "Harness Attention. Orchestrate Agents. Ship.",
|
|
50003
50003
|
license: "PolyForm-Perimeter-1.0.0",
|
|
50004
50004
|
type: "module",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE `google_accounts` ADD `last_gmail_history_id` text;
|
|
@@ -463,6 +463,13 @@
|
|
|
463
463
|
"when": 1771757600000,
|
|
464
464
|
"tag": "0065_add_last_channel_sync_at",
|
|
465
465
|
"breakpoints": true
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
"idx": 66,
|
|
469
|
+
"version": "6",
|
|
470
|
+
"when": 1771844000000,
|
|
471
|
+
"tag": "0066_persist_gmail_history_id",
|
|
472
|
+
"breakpoints": true
|
|
466
473
|
}
|
|
467
474
|
]
|
|
468
475
|
}
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -4724,6 +4724,7 @@ var init_schema = __esm(() => {
|
|
|
4724
4724
|
lastCalendarSyncError: text("last_calendar_sync_error"),
|
|
4725
4725
|
lastGmailSyncAt: text("last_gmail_sync_at"),
|
|
4726
4726
|
lastGmailSyncError: text("last_gmail_sync_error"),
|
|
4727
|
+
lastGmailHistoryId: text("last_gmail_history_id"),
|
|
4727
4728
|
sendAsEmail: text("send_as_email"),
|
|
4728
4729
|
needsReauth: integer("needs_reauth", { mode: "boolean" }).default(false),
|
|
4729
4730
|
createdAt: text("created_at").notNull(),
|
|
@@ -336873,7 +336874,7 @@ function storeEmail(params) {
|
|
|
336873
336874
|
connectionId: params.connectionId,
|
|
336874
336875
|
messageId: params.messageId
|
|
336875
336876
|
});
|
|
336876
|
-
return;
|
|
336877
|
+
return false;
|
|
336877
336878
|
}
|
|
336878
336879
|
const snippet = params.textContent ? params.textContent.slice(0, 200).replace(/\s+/g, " ").trim() : undefined;
|
|
336879
336880
|
const metadata = {
|
|
@@ -336910,6 +336911,7 @@ function storeEmail(params) {
|
|
|
336910
336911
|
messageId: params.messageId,
|
|
336911
336912
|
direction: params.direction
|
|
336912
336913
|
});
|
|
336914
|
+
return true;
|
|
336913
336915
|
}
|
|
336914
336916
|
function getStoredEmails(options) {
|
|
336915
336917
|
const conditions2 = [
|
|
@@ -337098,7 +337100,7 @@ class EmailChannel {
|
|
|
337098
337100
|
continue;
|
|
337099
337101
|
const authResult = await checkAuthorization(this.connectionId, headers, this.credentials?.allowedSenders || [], this.credentials?.imap.user.toLowerCase() ?? "");
|
|
337100
337102
|
if (headers.messageId) {
|
|
337101
|
-
storeEmail({
|
|
337103
|
+
const isNew = storeEmail({
|
|
337102
337104
|
connectionId: this.connectionId,
|
|
337103
337105
|
messageId: headers.messageId,
|
|
337104
337106
|
threadId: authResult.threadId,
|
|
@@ -337114,6 +337116,8 @@ class EmailChannel {
|
|
|
337114
337116
|
emailDate: headers.date ?? undefined,
|
|
337115
337117
|
imapUid: message.uid
|
|
337116
337118
|
});
|
|
337119
|
+
if (!isNew)
|
|
337120
|
+
continue;
|
|
337117
337121
|
}
|
|
337118
337122
|
const incomingMessage = {
|
|
337119
337123
|
channelType: "email",
|
|
@@ -1135469,6 +1135473,14 @@ class GmailBackend {
|
|
|
1135469
1135473
|
this.isShuttingDown = false;
|
|
1135470
1135474
|
try {
|
|
1135471
1135475
|
this.updateStatus("connecting");
|
|
1135476
|
+
const account = db2.select().from(googleAccounts).where(eq(googleAccounts.id, this.googleAccountId)).get();
|
|
1135477
|
+
if (account?.lastGmailHistoryId) {
|
|
1135478
|
+
this.lastHistoryId = account.lastGmailHistoryId;
|
|
1135479
|
+
log2.messaging.info("Restored Gmail historyId from DB", {
|
|
1135480
|
+
connectionId: this.connectionId,
|
|
1135481
|
+
lastHistoryId: this.lastHistoryId
|
|
1135482
|
+
});
|
|
1135483
|
+
}
|
|
1135472
1135484
|
await listMessages(this.googleAccountId, { maxResults: 1 });
|
|
1135473
1135485
|
this.updateStatus("connected");
|
|
1135474
1135486
|
this.startPolling();
|
|
@@ -1135503,6 +1135515,7 @@ class GmailBackend {
|
|
|
1135503
1135515
|
maxResults: 20
|
|
1135504
1135516
|
});
|
|
1135505
1135517
|
this.lastHistoryId = result.latestHistoryId;
|
|
1135518
|
+
db2.update(googleAccounts).set({ lastGmailHistoryId: result.latestHistoryId }).where(eq(googleAccounts.id, this.googleAccountId)).run();
|
|
1135506
1135519
|
const account = db2.select().from(googleAccounts).where(eq(googleAccounts.id, this.googleAccountId)).get();
|
|
1135507
1135520
|
const selfEmail = account?.email?.toLowerCase() ?? "";
|
|
1135508
1135521
|
const settings = getSettings();
|
|
@@ -1135545,7 +1135558,7 @@ class GmailBackend {
|
|
|
1135545
1135558
|
contentType: null
|
|
1135546
1135559
|
}, allowedSenders, selfEmail);
|
|
1135547
1135560
|
if (msg.messageId) {
|
|
1135548
|
-
storeEmail({
|
|
1135561
|
+
const isNew = storeEmail({
|
|
1135549
1135562
|
connectionId: this.connectionId,
|
|
1135550
1135563
|
messageId: msg.messageId,
|
|
1135551
1135564
|
threadId: authResult.threadId,
|
|
@@ -1135558,6 +1135571,8 @@ class GmailBackend {
|
|
|
1135558
1135571
|
subject: msg.subject ?? undefined,
|
|
1135559
1135572
|
textContent: msg.body ?? undefined
|
|
1135560
1135573
|
});
|
|
1135574
|
+
if (!isNew)
|
|
1135575
|
+
continue;
|
|
1135561
1135576
|
}
|
|
1135562
1135577
|
const incomingMessage = {
|
|
1135563
1135578
|
channelType: "email",
|
|
@@ -1135672,6 +1135687,22 @@ function getChannelMessages(options = {}) {
|
|
|
1135672
1135687
|
function getChannelMessageById(id) {
|
|
1135673
1135688
|
return db2.select().from(channelMessages).where(eq(channelMessages.id, id)).get();
|
|
1135674
1135689
|
}
|
|
1135690
|
+
function getRecentChannelMessages(connectionId, options = {}) {
|
|
1135691
|
+
const { before, limit = 5 } = options;
|
|
1135692
|
+
const conditions2 = [
|
|
1135693
|
+
eq(channelMessages.connectionId, connectionId)
|
|
1135694
|
+
];
|
|
1135695
|
+
if (before) {
|
|
1135696
|
+
conditions2.push(lt(channelMessages.messageTimestamp, before));
|
|
1135697
|
+
}
|
|
1135698
|
+
const results = db2.select({
|
|
1135699
|
+
direction: channelMessages.direction,
|
|
1135700
|
+
senderName: channelMessages.senderName,
|
|
1135701
|
+
content: channelMessages.content,
|
|
1135702
|
+
messageTimestamp: channelMessages.messageTimestamp
|
|
1135703
|
+
}).from(channelMessages).where(and(...conditions2)).orderBy(desc(channelMessages.messageTimestamp)).limit(limit).all();
|
|
1135704
|
+
return results.reverse();
|
|
1135705
|
+
}
|
|
1135675
1135706
|
function getRecentOutgoingMessages(connectionId, options = {}) {
|
|
1135676
1135707
|
const { since, limit = 20 } = options;
|
|
1135677
1135708
|
const conditions2 = [
|
|
@@ -1150349,7 +1150380,25 @@ async function* streamOpencodeObserverMessage(sessionId, userMessage, options) {
|
|
|
1150349
1150380
|
const client3 = await getClient();
|
|
1150350
1150381
|
const settings = getSettings();
|
|
1150351
1150382
|
const model = options.model || settings.assistant.observerOpencodeModel || settings.agent.opencodeModel;
|
|
1150352
|
-
|
|
1150383
|
+
let contextualMessage = "";
|
|
1150384
|
+
if (options.channelHistory && options.channelHistory.length > 0) {
|
|
1150385
|
+
const historyLines = options.channelHistory.map((msg) => {
|
|
1150386
|
+
const time2 = new Date(msg.messageTimestamp).toLocaleTimeString("en-US", {
|
|
1150387
|
+
hour: "2-digit",
|
|
1150388
|
+
minute: "2-digit",
|
|
1150389
|
+
hour12: false
|
|
1150390
|
+
});
|
|
1150391
|
+
const label = msg.direction === "outgoing" ? "You" : msg.senderName || "Unknown";
|
|
1150392
|
+
const truncated = msg.content.length > 500 ? msg.content.slice(0, 500) + "..." : msg.content;
|
|
1150393
|
+
return `[${time2}] ${label}: ${truncated}`;
|
|
1150394
|
+
});
|
|
1150395
|
+
contextualMessage += `[Recent messages on this channel:
|
|
1150396
|
+
${historyLines.join(`
|
|
1150397
|
+
`)}]
|
|
1150398
|
+
|
|
1150399
|
+
`;
|
|
1150400
|
+
}
|
|
1150401
|
+
contextualMessage += `[${options.channelType.toUpperCase()} message from ${options.senderName || options.senderId}]
|
|
1150353
1150402
|
|
|
1150354
1150403
|
${userMessage}`;
|
|
1150355
1150404
|
const fullPrompt = `${getObserverSystemPrompt()}
|
|
@@ -1150869,6 +1150918,10 @@ async function processObserveOnlyMessage(msg) {
|
|
|
1150869
1150918
|
});
|
|
1150870
1150919
|
return;
|
|
1150871
1150920
|
}
|
|
1150921
|
+
const channelHistory = msg.channelType !== "email" ? getRecentChannelMessages(msg.connectionId, {
|
|
1150922
|
+
before: (msg.timestamp ?? new Date).toISOString(),
|
|
1150923
|
+
limit: 5
|
|
1150924
|
+
}) : [];
|
|
1150872
1150925
|
const observeSessionKey = `observe-${msg.connectionId}`;
|
|
1150873
1150926
|
const { session: session3 } = getOrCreateSession(msg.connectionId, observeSessionKey, "Observer", undefined, msg.channelType);
|
|
1150874
1150927
|
const settings = getSettings();
|
|
@@ -1150879,7 +1150932,8 @@ async function processObserveOnlyMessage(msg) {
|
|
|
1150879
1150932
|
const stream2 = _deps.streamOpencodeObserverMessage(session3.id, msg.content, {
|
|
1150880
1150933
|
channelType: msg.channelType,
|
|
1150881
1150934
|
senderId: msg.senderId,
|
|
1150882
|
-
senderName: msg.senderName
|
|
1150935
|
+
senderName: msg.senderName,
|
|
1150936
|
+
channelHistory
|
|
1150883
1150937
|
});
|
|
1150884
1150938
|
for await (const event of stream2) {
|
|
1150885
1150939
|
if (event.type === "error") {
|
|
@@ -1150919,7 +1150973,8 @@ async function processObserveOnlyMessage(msg) {
|
|
|
1150919
1150973
|
systemPromptAdditions: systemPrompt,
|
|
1150920
1150974
|
modelId: observerModelId,
|
|
1150921
1150975
|
securityTier: "observer",
|
|
1150922
|
-
ephemeral: true
|
|
1150976
|
+
ephemeral: true,
|
|
1150977
|
+
...channelHistory.length > 0 && { channelHistory }
|
|
1150923
1150978
|
});
|
|
1150924
1150979
|
for await (const event of stream2) {
|
|
1150925
1150980
|
if (event.type === "error") {
|
|
@@ -1255379,7 +1255434,7 @@ mcpRoutes.all("/", async (c) => {
|
|
|
1255379
1255434
|
});
|
|
1255380
1255435
|
const server2 = new McpServer({
|
|
1255381
1255436
|
name: "fulcrum",
|
|
1255382
|
-
version: "3.
|
|
1255437
|
+
version: "3.7.1"
|
|
1255383
1255438
|
});
|
|
1255384
1255439
|
const client3 = new FulcrumClient(`http://localhost:${port}`);
|
|
1255385
1255440
|
registerTools(server2, client3);
|