@basegrid_tech/mcp 0.18.12 → 0.18.14-beta.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/dist/index.js +371 -26
- package/package.json +12 -12
package/dist/index.js
CHANGED
|
@@ -69,6 +69,8 @@ var DEFAULT_WORKSPACE = {
|
|
|
69
69
|
iconColor: "#6b7280",
|
|
70
70
|
order: 0
|
|
71
71
|
};
|
|
72
|
+
var MCP_ASK_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
73
|
+
var MCP_TOOL_TIMEOUT_MS = MCP_ASK_TIMEOUT_MS + 6e4;
|
|
72
74
|
var QUICK_COMMAND_LIMITS = {
|
|
73
75
|
maxCommands: 40,
|
|
74
76
|
maxLabel: 80,
|
|
@@ -102,6 +104,29 @@ var DEFAULT_AGENT_COMMANDS = {
|
|
|
102
104
|
}
|
|
103
105
|
};
|
|
104
106
|
|
|
107
|
+
// ../shared/src/config-save-mutation.ts
|
|
108
|
+
function applyTaskConfigMutation(currentTasks, mutation) {
|
|
109
|
+
if (!mutation) return currentTasks;
|
|
110
|
+
if (mutation.kind === "create") {
|
|
111
|
+
if (currentTasks.some((task) => task.id === mutation.task.id)) return currentTasks;
|
|
112
|
+
return [...currentTasks, mutation.task];
|
|
113
|
+
}
|
|
114
|
+
if (mutation.kind === "delete") {
|
|
115
|
+
const doomed = new Set(mutation.ids);
|
|
116
|
+
return currentTasks.filter((task) => !doomed.has(task.id));
|
|
117
|
+
}
|
|
118
|
+
const patches = new Map(mutation.patches.map((patch) => [patch.id, patch]));
|
|
119
|
+
return currentTasks.map((task) => {
|
|
120
|
+
const patch = patches.get(task.id);
|
|
121
|
+
if (!patch) return task;
|
|
122
|
+
const next = { ...task, ...patch.updates };
|
|
123
|
+
for (const key of patch.clear ?? []) {
|
|
124
|
+
delete next[key];
|
|
125
|
+
}
|
|
126
|
+
return next;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
105
130
|
// ../server/src/database.ts
|
|
106
131
|
import Database from "libsql";
|
|
107
132
|
import path3 from "path";
|
|
@@ -162,6 +187,32 @@ var DEFAULT_NO_PROXY_HOSTS = [
|
|
|
162
187
|
];
|
|
163
188
|
var DEFAULT_NO_PROXY = DEFAULT_NO_PROXY_HOSTS.join(",");
|
|
164
189
|
|
|
190
|
+
// ../shared/src/connector-identity.ts
|
|
191
|
+
var IDENTITY_FIELDS = [
|
|
192
|
+
"owner",
|
|
193
|
+
// github
|
|
194
|
+
"repo",
|
|
195
|
+
// github
|
|
196
|
+
"orgId",
|
|
197
|
+
// yandex tracker
|
|
198
|
+
"queue",
|
|
199
|
+
// yandex tracker
|
|
200
|
+
"teamKey"
|
|
201
|
+
// linear
|
|
202
|
+
];
|
|
203
|
+
function connectionIdentityKey(connectorId, filters) {
|
|
204
|
+
if (!filters) return "";
|
|
205
|
+
const parts = [];
|
|
206
|
+
for (const key of IDENTITY_FIELDS) {
|
|
207
|
+
const value = filters[key];
|
|
208
|
+
if (typeof value !== "string") continue;
|
|
209
|
+
const normalized = value.trim().toLowerCase();
|
|
210
|
+
if (!normalized) continue;
|
|
211
|
+
parts.push(`${key}=${normalized}`);
|
|
212
|
+
}
|
|
213
|
+
return parts.length > 0 ? `${connectorId}:${parts.join("&")}` : "";
|
|
214
|
+
}
|
|
215
|
+
|
|
165
216
|
// ../shared/src/quick-commands.ts
|
|
166
217
|
function normalizeQuickCommands(input) {
|
|
167
218
|
if (!Array.isArray(input)) return [];
|
|
@@ -185,8 +236,13 @@ function normalizeOne(raw, seenIds) {
|
|
|
185
236
|
const label = clampString(obj.label, QUICK_COMMAND_LIMITS.maxLabel);
|
|
186
237
|
if (!label) return null;
|
|
187
238
|
const scope = normalizeScope(obj.scope);
|
|
188
|
-
const kind = obj.kind === "terminal"
|
|
239
|
+
const kind = obj.kind === "terminal" || obj.kind === "agent" || obj.kind === "snippet" ? obj.kind : null;
|
|
189
240
|
if (!kind) return null;
|
|
241
|
+
if (kind === "snippet") {
|
|
242
|
+
const text2 = clampString(obj.text, QUICK_COMMAND_LIMITS.maxBody);
|
|
243
|
+
if (!text2) return null;
|
|
244
|
+
return { id, label, scope, kind, text: text2 };
|
|
245
|
+
}
|
|
190
246
|
if (kind === "agent") {
|
|
191
247
|
const prompt = clampString(obj.prompt, QUICK_COMMAND_LIMITS.maxBody);
|
|
192
248
|
if (!prompt) return null;
|
|
@@ -485,7 +541,8 @@ function createSchema() {
|
|
|
485
541
|
);
|
|
486
542
|
|
|
487
543
|
-- Quick commands (\u043F\u043E\u0440\u0442 \u0444\u0438\u0447\u0438 \u0438\u0437 orca): \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0435 \u0438\u043C\u0435\u043D\u043E\u0432\u0430\u043D\u043D\u044B\u0435 \u043A\u043E\u043C\u0430\u043D\u0434\u044B.
|
|
488
|
-
-- kind='agent' \u2192 \u0437\u0430\u043F\u0443\u0441\u043A \u0430\u0433\u0435\u043D\u0442\u0430 \u0441 \u043F\u0440\u043E\u043C\u043F\u0442\u043E\u043C; kind='terminal' \u2192 \u0448\u0435\u043B\u043B-\u043A\u043E\u043C\u0430\u043D\u0434\u0430
|
|
544
|
+
-- kind='agent' \u2192 \u0437\u0430\u043F\u0443\u0441\u043A \u0430\u0433\u0435\u043D\u0442\u0430 \u0441 \u043F\u0440\u043E\u043C\u043F\u0442\u043E\u043C; kind='terminal' \u2192 \u0448\u0435\u043B\u043B-\u043A\u043E\u043C\u0430\u043D\u0434\u0430;
|
|
545
|
+
-- kind='snippet' \u2192 \u0433\u043E\u0442\u043E\u0432\u044B\u0439 \u0442\u0435\u043A\u0441\u0442, \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0432\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u0432 \u0438\u043D\u043F\u0443\u0442 \u0441\u0435\u0441\u0441\u0438\u0438.
|
|
489
546
|
-- scope \u0445\u0440\u0430\u043D\u0438\u0442\u0441\u044F JSON-\u0441\u0442\u0440\u043E\u043A\u043E\u0439 \u0434\u043B\u044F \u0431\u0443\u0434\u0443\u0449\u0435\u0439 \u043F\u0440\u0438\u0432\u044F\u0437\u043A\u0438 \u043A \u043F\u0440\u043E\u0435\u043A\u0442\u0443 (\u0441\u0435\u0439\u0447\u0430\u0441 global).
|
|
490
547
|
CREATE TABLE IF NOT EXISTS quick_commands (
|
|
491
548
|
id TEXT PRIMARY KEY,
|
|
@@ -498,7 +555,8 @@ function createSchema() {
|
|
|
498
555
|
command TEXT,
|
|
499
556
|
append_enter INTEGER NOT NULL DEFAULT 1,
|
|
500
557
|
position INTEGER NOT NULL DEFAULT 0,
|
|
501
|
-
shell TEXT
|
|
558
|
+
shell TEXT,
|
|
559
|
+
snippet_text TEXT
|
|
502
560
|
);
|
|
503
561
|
|
|
504
562
|
CREATE TABLE IF NOT EXISTS remote_hosts (
|
|
@@ -571,6 +629,7 @@ function createSchema() {
|
|
|
571
629
|
agent_session_id TEXT,
|
|
572
630
|
branch TEXT,
|
|
573
631
|
use_worktree INTEGER DEFAULT 0,
|
|
632
|
+
worktree_path TEXT,
|
|
574
633
|
created_at TEXT NOT NULL,
|
|
575
634
|
updated_at TEXT NOT NULL,
|
|
576
635
|
completed_at TEXT
|
|
@@ -756,12 +815,39 @@ function createSchema() {
|
|
|
756
815
|
updated_at INTEGER NOT NULL
|
|
757
816
|
);
|
|
758
817
|
|
|
818
|
+
-- \u0427\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0438\u043D\u043F\u0443\u0442\u0430 \u0441\u0435\u0441\u0441\u0438\u0438: \u043D\u0430\u0431\u0440\u0430\u043D\u043D\u044B\u0439, \u043D\u043E \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043D\u044B\u0439 \u0442\u0435\u043A\u0441\u0442 (HTML
|
|
819
|
+
-- \u0440\u0435\u0434\u0430\u043A\u0442\u043E\u0440\u0430 PromptInput) \u0438 \u043C\u0435\u0442\u0430\u0434\u0430\u043D\u043D\u044B\u0435 \u0435\u0433\u043E \u0447\u0438\u043F\u043E\u0432. \u041A\u043B\u044E\u0447 \u2014 terminal_id,
|
|
820
|
+
-- \u043F\u043E\u044D\u0442\u043E\u043C\u0443 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u043F\u0435\u0440\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F (issue #921). \u0421\u0442\u0440\u043E\u043A\u0430
|
|
821
|
+
-- \u0436\u0438\u0432\u0451\u0442 \u0440\u043E\u0432\u043D\u043E \u0441\u0442\u043E\u043B\u044C\u043A\u043E \u0436\u0435, \u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0441\u0442\u0440\u043E\u043A\u0430 \u0441\u0435\u0441\u0441\u0438\u0438: \u0435\u0451 \u0443\u0434\u0430\u043B\u044F\u044E\u0442 \u0432\u043C\u0435\u0441\u0442\u0435 \u0441
|
|
822
|
+
-- \u0441\u0435\u0441\u0441\u0438\u0435\u0439 (deleteSessionById \u0438 \u0441\u043E\u0441\u0435\u0434\u0438) \u0438 \u043F\u043E\u0434\u0447\u0438\u0449\u0430\u044E\u0442 \u043D\u0430 \u0441\u0442\u0430\u0440\u0442\u0435
|
|
823
|
+
-- (pruneOrphanInputDrafts).
|
|
824
|
+
CREATE TABLE IF NOT EXISTS session_input_drafts (
|
|
825
|
+
terminal_id TEXT PRIMARY KEY,
|
|
826
|
+
html TEXT NOT NULL,
|
|
827
|
+
attachments TEXT NOT NULL DEFAULT '[]',
|
|
828
|
+
updated_at INTEGER NOT NULL
|
|
829
|
+
);
|
|
830
|
+
|
|
759
831
|
CREATE TABLE IF NOT EXISTS worktree_notes (
|
|
760
832
|
worktree_path TEXT PRIMARY KEY,
|
|
761
833
|
body TEXT NOT NULL,
|
|
762
834
|
updated_at INTEGER NOT NULL
|
|
763
835
|
);
|
|
764
836
|
|
|
837
|
+
-- \u0421\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0440\u0430\u0431\u043E\u0442\u044B \u0432 \u0432\u043E\u0440\u043A\u0442\u0440\u0438: \u0433\u0434\u0435 \u043C\u044B \u0432 \u0446\u0435\u043F\u043E\u0447\u043A\u0435 \xAB\u043E\u0431\u0441\u0443\u0436\u0434\u0435\u043D\u0438\u0435 \u2192 \u0440\u0435\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u044F \u2192
|
|
838
|
+
-- \u043F\u0440\u0438\u0451\u043C\u043A\u0430\xBB \u0438 \u0447\u0442\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044F \u0434\u0430\u043B\u044C\u0448\u0435. \u0416\u0438\u0432\u0451\u0442 \u043D\u0430 \u0432\u043E\u0440\u043A\u0442\u0440\u0438, \u0430 \u043D\u0435 \u043D\u0430 \u0441\u0435\u0441\u0441\u0438\u0438
|
|
839
|
+
-- (\u0438\u0445 \u0432 \u043E\u0434\u043D\u043E\u0439 \u0432\u043E\u0440\u043A\u0442\u0440\u0438 \u043D\u0435\u0441\u043A\u043E\u043B\u044C\u043A\u043E, \u0438 \u043E\u043D\u0438 \u0440\u0430\u0437\u043E\u0448\u043B\u0438\u0441\u044C \u0431\u044B) \u0438 \u043D\u0435 \u043D\u0430 \u0437\u0430\u0434\u0430\u0447\u0435
|
|
840
|
+
-- (\u0437\u0430\u0434\u0430\u0447 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043D\u0435\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0438\u043B\u0438 \u043D\u0438 \u043E\u0434\u043D\u043E\u0439). \u0423\u043C\u0438\u0440\u0430\u0435\u0442 \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 \u0432\u043E\u0440\u043A\u0442\u0440\u0438 \u2014
|
|
841
|
+
-- \u0441\u043C. deleteWorktreeListEntry.
|
|
842
|
+
CREATE TABLE IF NOT EXISTS worktree_flow (
|
|
843
|
+
worktree_path TEXT PRIMARY KEY,
|
|
844
|
+
step TEXT NOT NULL,
|
|
845
|
+
criteria TEXT NOT NULL DEFAULT '[]',
|
|
846
|
+
work_session_id TEXT,
|
|
847
|
+
accept_session_id TEXT,
|
|
848
|
+
updated_at INTEGER NOT NULL
|
|
849
|
+
);
|
|
850
|
+
|
|
765
851
|
CREATE TABLE IF NOT EXISTS worktree_view_modes (
|
|
766
852
|
worktree_path TEXT PRIMARY KEY,
|
|
767
853
|
view_mode TEXT NOT NULL,
|
|
@@ -852,6 +938,17 @@ function createSchema() {
|
|
|
852
938
|
function migrateSchema(d) {
|
|
853
939
|
const row = d.prepare("SELECT value FROM schema_meta WHERE key = 'schema_version'").get();
|
|
854
940
|
const version = row ? parseInt(row.value, 10) : 0;
|
|
941
|
+
{
|
|
942
|
+
const flowCols = d.prepare("PRAGMA table_info(worktree_flow)").all();
|
|
943
|
+
if (flowCols.length > 0) {
|
|
944
|
+
if (!flowCols.some((c) => c.name === "work_session_id")) {
|
|
945
|
+
d.exec("ALTER TABLE worktree_flow ADD COLUMN work_session_id TEXT");
|
|
946
|
+
}
|
|
947
|
+
if (!flowCols.some((c) => c.name === "accept_session_id")) {
|
|
948
|
+
d.exec("ALTER TABLE worktree_flow ADD COLUMN accept_session_id TEXT");
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}
|
|
855
952
|
if (version < 1) {
|
|
856
953
|
d.transaction(() => {
|
|
857
954
|
const projectCols = d.prepare("PRAGMA table_info(projects)").all();
|
|
@@ -1608,6 +1705,120 @@ function migrateSchema(d) {
|
|
|
1608
1705
|
})();
|
|
1609
1706
|
logger_default.info("[database] migrated schema to version 37 (session_activity timestamp index)");
|
|
1610
1707
|
}
|
|
1708
|
+
if (version < 38) {
|
|
1709
|
+
d.transaction(() => {
|
|
1710
|
+
const cols = d.prepare("PRAGMA table_info(quick_commands)").all();
|
|
1711
|
+
if (!cols.some((c) => c.name === "snippet_text")) {
|
|
1712
|
+
d.exec("ALTER TABLE quick_commands ADD COLUMN snippet_text TEXT");
|
|
1713
|
+
}
|
|
1714
|
+
d.prepare(
|
|
1715
|
+
"INSERT OR REPLACE INTO schema_meta (key, value) VALUES ('schema_version', '38')"
|
|
1716
|
+
).run();
|
|
1717
|
+
})();
|
|
1718
|
+
logger_default.info("[database] migrated schema to version 38 (quick command snippets)");
|
|
1719
|
+
}
|
|
1720
|
+
if (version < 39) {
|
|
1721
|
+
d.transaction(() => {
|
|
1722
|
+
const cols = d.prepare("PRAGMA table_info(source_connections)").all();
|
|
1723
|
+
if (cols.length === 0) {
|
|
1724
|
+
d.prepare(
|
|
1725
|
+
"INSERT OR REPLACE INTO schema_meta (key, value) VALUES ('schema_version', '39')"
|
|
1726
|
+
).run();
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1729
|
+
if (!cols.some((c) => c.name === "identity_key")) {
|
|
1730
|
+
d.exec("ALTER TABLE source_connections ADD COLUMN identity_key TEXT NOT NULL DEFAULT ''");
|
|
1731
|
+
}
|
|
1732
|
+
const rows = d.prepare(
|
|
1733
|
+
`SELECT c.id, c.connector_id, c.filters, c.created_at, c.sync_cursor,
|
|
1734
|
+
c.status_mapping, c.sync_interval_minutes, c.execution_project,
|
|
1735
|
+
(SELECT count(*) FROM task_source_links l WHERE l.connection_id = c.id) AS link_count
|
|
1736
|
+
FROM source_connections c`
|
|
1737
|
+
).all();
|
|
1738
|
+
const setIdentity = d.prepare("UPDATE source_connections SET identity_key = ? WHERE id = ?");
|
|
1739
|
+
const setFilters = d.prepare("UPDATE source_connections SET filters = ? WHERE id = ?");
|
|
1740
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1741
|
+
for (const row2 of rows) {
|
|
1742
|
+
let filters;
|
|
1743
|
+
try {
|
|
1744
|
+
filters = JSON.parse(row2.filters);
|
|
1745
|
+
} catch {
|
|
1746
|
+
filters = {};
|
|
1747
|
+
}
|
|
1748
|
+
if (row2.connector_id === "github" && "state" in filters) {
|
|
1749
|
+
delete filters.state;
|
|
1750
|
+
setFilters.run(JSON.stringify(filters), row2.id);
|
|
1751
|
+
}
|
|
1752
|
+
const key = connectionIdentityKey(row2.connector_id, filters);
|
|
1753
|
+
setIdentity.run(key, row2.id);
|
|
1754
|
+
if (!key) continue;
|
|
1755
|
+
const bucket = groups.get(key) ?? [];
|
|
1756
|
+
bucket.push({ ...row2, parsedFilters: filters });
|
|
1757
|
+
groups.set(key, bucket);
|
|
1758
|
+
}
|
|
1759
|
+
const relinkLinks = d.prepare(
|
|
1760
|
+
"UPDATE OR IGNORE task_source_links SET connection_id = ? WHERE connection_id = ?"
|
|
1761
|
+
);
|
|
1762
|
+
const relinkHistory = d.prepare(
|
|
1763
|
+
"UPDATE sync_history SET connection_id = ? WHERE connection_id = ?"
|
|
1764
|
+
);
|
|
1765
|
+
const adoptSettings = d.prepare(
|
|
1766
|
+
`UPDATE source_connections
|
|
1767
|
+
SET filters = ?, status_mapping = ?, sync_interval_minutes = ?,
|
|
1768
|
+
execution_project = ?, sync_cursor = ?
|
|
1769
|
+
WHERE id = ?`
|
|
1770
|
+
);
|
|
1771
|
+
const dropConn = d.prepare("DELETE FROM source_connections WHERE id = ?");
|
|
1772
|
+
let collapsed = 0;
|
|
1773
|
+
let strandedLinks = 0;
|
|
1774
|
+
for (const bucket of groups.values()) {
|
|
1775
|
+
if (bucket.length < 2) continue;
|
|
1776
|
+
const byWeight = [...bucket].sort(
|
|
1777
|
+
(a, b) => b.link_count - a.link_count || a.created_at.localeCompare(b.created_at)
|
|
1778
|
+
);
|
|
1779
|
+
const keep = byWeight[0];
|
|
1780
|
+
const dupes = byWeight.slice(1);
|
|
1781
|
+
const newest = [...bucket].sort((a, b) => b.created_at.localeCompare(a.created_at))[0];
|
|
1782
|
+
const cursors = bucket.map((c) => c.sync_cursor).filter((c) => !!c);
|
|
1783
|
+
const earliest = cursors.length > 0 ? cursors.sort()[0] : null;
|
|
1784
|
+
for (const dupe of dupes) {
|
|
1785
|
+
const moved = Number(relinkLinks.run(keep.id, dupe.id).changes);
|
|
1786
|
+
strandedLinks += dupe.link_count - moved;
|
|
1787
|
+
relinkHistory.run(keep.id, dupe.id);
|
|
1788
|
+
dropConn.run(dupe.id);
|
|
1789
|
+
collapsed++;
|
|
1790
|
+
}
|
|
1791
|
+
adoptSettings.run(
|
|
1792
|
+
JSON.stringify(newest.parsedFilters),
|
|
1793
|
+
newest.status_mapping,
|
|
1794
|
+
newest.sync_interval_minutes,
|
|
1795
|
+
newest.execution_project,
|
|
1796
|
+
earliest,
|
|
1797
|
+
keep.id
|
|
1798
|
+
);
|
|
1799
|
+
}
|
|
1800
|
+
const catchUpFrom = new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString();
|
|
1801
|
+
d.prepare(
|
|
1802
|
+
`UPDATE source_connections
|
|
1803
|
+
SET sync_cursor = CASE WHEN created_at > ? THEN created_at ELSE ? END
|
|
1804
|
+
WHERE sync_cursor IS NOT NULL AND sync_cursor > ?`
|
|
1805
|
+
).run(catchUpFrom, catchUpFrom, catchUpFrom);
|
|
1806
|
+
d.exec(`
|
|
1807
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_source_connections_identity
|
|
1808
|
+
ON source_connections(identity_key)
|
|
1809
|
+
WHERE identity_key <> ''
|
|
1810
|
+
`);
|
|
1811
|
+
d.prepare(
|
|
1812
|
+
"INSERT OR REPLACE INTO schema_meta (key, value) VALUES ('schema_version', '39')"
|
|
1813
|
+
).run();
|
|
1814
|
+
if (collapsed > 0) {
|
|
1815
|
+
logger_default.warn(
|
|
1816
|
+
`[database] collapsed ${collapsed} duplicate source connection(s)` + (strandedLinks > 0 ? `; ${strandedLinks} duplicate task link(s) dropped` : "")
|
|
1817
|
+
);
|
|
1818
|
+
}
|
|
1819
|
+
})();
|
|
1820
|
+
logger_default.info("[database] migrated schema to version 39 (source_connections.identity_key)");
|
|
1821
|
+
}
|
|
1611
1822
|
}
|
|
1612
1823
|
function verifySchema(d) {
|
|
1613
1824
|
const expectedTables = [
|
|
@@ -1634,7 +1845,8 @@ function verifySchema(d) {
|
|
|
1634
1845
|
last_sync_at TEXT,
|
|
1635
1846
|
last_sync_error TEXT,
|
|
1636
1847
|
sync_cursor TEXT,
|
|
1637
|
-
created_at TEXT NOT NULL
|
|
1848
|
+
created_at TEXT NOT NULL,
|
|
1849
|
+
identity_key TEXT NOT NULL DEFAULT ''
|
|
1638
1850
|
)`
|
|
1639
1851
|
},
|
|
1640
1852
|
{
|
|
@@ -1767,6 +1979,10 @@ function verifySchema(d) {
|
|
|
1767
1979
|
{
|
|
1768
1980
|
column: "source_external_id",
|
|
1769
1981
|
ddl: "ALTER TABLE tasks ADD COLUMN source_external_id TEXT"
|
|
1982
|
+
},
|
|
1983
|
+
{
|
|
1984
|
+
column: "worktree_path",
|
|
1985
|
+
ddl: "ALTER TABLE tasks ADD COLUMN worktree_path TEXT"
|
|
1770
1986
|
}
|
|
1771
1987
|
],
|
|
1772
1988
|
task_source_links: [
|
|
@@ -1804,8 +2020,17 @@ function verifySchema(d) {
|
|
|
1804
2020
|
ddl: "ALTER TABLE external_worktree_settings ADD COLUMN hidden_paths TEXT NOT NULL DEFAULT '[]'"
|
|
1805
2021
|
}
|
|
1806
2022
|
],
|
|
1807
|
-
quick_commands: [
|
|
1808
|
-
|
|
2023
|
+
quick_commands: [
|
|
2024
|
+
{ column: "shell", ddl: "ALTER TABLE quick_commands ADD COLUMN shell TEXT" },
|
|
2025
|
+
{ column: "snippet_text", ddl: "ALTER TABLE quick_commands ADD COLUMN snippet_text TEXT" }
|
|
2026
|
+
],
|
|
2027
|
+
account: [{ column: "member_since", ddl: "ALTER TABLE account ADD COLUMN member_since TEXT" }],
|
|
2028
|
+
source_connections: [
|
|
2029
|
+
{
|
|
2030
|
+
column: "identity_key",
|
|
2031
|
+
ddl: "ALTER TABLE source_connections ADD COLUMN identity_key TEXT NOT NULL DEFAULT ''"
|
|
2032
|
+
}
|
|
2033
|
+
]
|
|
1809
2034
|
};
|
|
1810
2035
|
for (const [table, columns] of Object.entries(expectedByTable)) {
|
|
1811
2036
|
const existing = new Set(
|
|
@@ -1821,6 +2046,15 @@ function verifySchema(d) {
|
|
|
1821
2046
|
}
|
|
1822
2047
|
}
|
|
1823
2048
|
}
|
|
2049
|
+
try {
|
|
2050
|
+
d.exec(`
|
|
2051
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_source_connections_identity
|
|
2052
|
+
ON source_connections(identity_key)
|
|
2053
|
+
WHERE identity_key <> ''
|
|
2054
|
+
`);
|
|
2055
|
+
} catch (err) {
|
|
2056
|
+
logger_default.error({ err }, "[database] self-heal: failed to ensure source connection identity index");
|
|
2057
|
+
}
|
|
1824
2058
|
}
|
|
1825
2059
|
function loadConfig() {
|
|
1826
2060
|
const d = getDb();
|
|
@@ -1876,6 +2110,7 @@ var DEFAULTS_KEYS_MAP = {
|
|
|
1876
2110
|
claudeDefaultEffort: true,
|
|
1877
2111
|
codexDefaultModel: true,
|
|
1878
2112
|
codexDefaultEffort: true,
|
|
2113
|
+
geminiDefaultModel: true,
|
|
1879
2114
|
language: true,
|
|
1880
2115
|
hasSeededDefaultTaskWorkflow: true,
|
|
1881
2116
|
defaultSpinnerVariant: true,
|
|
@@ -1892,6 +2127,7 @@ var DEFAULTS_KEYS_MAP = {
|
|
|
1892
2127
|
reviewClaudeModel: true,
|
|
1893
2128
|
reviewCodexModel: true,
|
|
1894
2129
|
reviewCodexEffort: true,
|
|
2130
|
+
reviewGeminiModel: true,
|
|
1895
2131
|
aiCommitModel: true,
|
|
1896
2132
|
aiCommitThinkingLevel: true,
|
|
1897
2133
|
aiCommitCustomPrompt: true,
|
|
@@ -1975,7 +2211,8 @@ function loadQuickCommands(d) {
|
|
|
1975
2211
|
model: r.model ?? void 0,
|
|
1976
2212
|
command: r.command ?? void 0,
|
|
1977
2213
|
appendEnter: r.append_enter !== 0,
|
|
1978
|
-
shell: r.shell ?? void 0
|
|
2214
|
+
shell: r.shell ?? void 0,
|
|
2215
|
+
text: r.snippet_text ?? void 0
|
|
1979
2216
|
}));
|
|
1980
2217
|
return normalizeQuickCommands(raw);
|
|
1981
2218
|
}
|
|
@@ -2084,8 +2321,8 @@ function saveConfig(config) {
|
|
|
2084
2321
|
}
|
|
2085
2322
|
d.prepare("DELETE FROM quick_commands").run();
|
|
2086
2323
|
const insertQuickCommand = d.prepare(
|
|
2087
|
-
`INSERT INTO quick_commands (id, label, kind, scope, agent_type, prompt, model, command, append_enter, position, shell)
|
|
2088
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
2324
|
+
`INSERT INTO quick_commands (id, label, kind, scope, agent_type, prompt, model, command, append_enter, position, shell, snippet_text)
|
|
2325
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
2089
2326
|
);
|
|
2090
2327
|
const normalizedQuickCommands = normalizeQuickCommands(config.quickCommands ?? []);
|
|
2091
2328
|
normalizedQuickCommands.forEach((q, index) => {
|
|
@@ -2100,7 +2337,8 @@ function saveConfig(config) {
|
|
|
2100
2337
|
q.kind === "terminal" ? q.command : null,
|
|
2101
2338
|
q.kind === "terminal" && q.appendEnter ? 1 : 0,
|
|
2102
2339
|
index,
|
|
2103
|
-
q.kind === "terminal" ? q.shell ?? null : null
|
|
2340
|
+
q.kind === "terminal" ? q.shell ?? null : null,
|
|
2341
|
+
q.kind === "snippet" ? q.text : null
|
|
2104
2342
|
);
|
|
2105
2343
|
});
|
|
2106
2344
|
d.prepare("DELETE FROM agent_commands").run();
|
|
@@ -2139,17 +2377,17 @@ function saveConfig(config) {
|
|
|
2139
2377
|
h.sshOptions ?? null
|
|
2140
2378
|
);
|
|
2141
2379
|
}
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
(r) => r.id
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2380
|
+
if (config.tasks) {
|
|
2381
|
+
const nextTaskIds = new Set(config.tasks.map((t) => t.id));
|
|
2382
|
+
const existingTaskIds = d.prepare("SELECT id FROM tasks").all().map((r) => r.id);
|
|
2383
|
+
const deleteTask = d.prepare("DELETE FROM tasks WHERE id = ?");
|
|
2384
|
+
for (const id of existingTaskIds) {
|
|
2385
|
+
if (!nextTaskIds.has(id)) deleteTask.run(id);
|
|
2386
|
+
}
|
|
2149
2387
|
}
|
|
2150
2388
|
const insertTask = d.prepare(
|
|
2151
|
-
`INSERT INTO tasks (id, project_name, title, description, status, "order", assigned_session_id, assigned_agent, agent_session_id, branch, use_worktree, created_at, updated_at, completed_at, source_connector_id, source_external_url, source_external_id)
|
|
2152
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2389
|
+
`INSERT INTO tasks (id, project_name, title, description, status, "order", assigned_session_id, assigned_agent, agent_session_id, branch, use_worktree, worktree_path, created_at, updated_at, completed_at, source_connector_id, source_external_url, source_external_id)
|
|
2390
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2153
2391
|
ON CONFLICT(id) DO UPDATE SET
|
|
2154
2392
|
project_name = excluded.project_name,
|
|
2155
2393
|
title = excluded.title,
|
|
@@ -2161,6 +2399,7 @@ function saveConfig(config) {
|
|
|
2161
2399
|
agent_session_id = excluded.agent_session_id,
|
|
2162
2400
|
branch = excluded.branch,
|
|
2163
2401
|
use_worktree = excluded.use_worktree,
|
|
2402
|
+
worktree_path = excluded.worktree_path,
|
|
2164
2403
|
created_at = excluded.created_at,
|
|
2165
2404
|
updated_at = excluded.updated_at,
|
|
2166
2405
|
completed_at = excluded.completed_at,
|
|
@@ -2181,6 +2420,7 @@ function saveConfig(config) {
|
|
|
2181
2420
|
t.agentSessionId ?? null,
|
|
2182
2421
|
t.branch ?? null,
|
|
2183
2422
|
t.useWorktree ? 1 : 0,
|
|
2423
|
+
t.worktreePath ?? null,
|
|
2184
2424
|
t.createdAt,
|
|
2185
2425
|
t.updatedAt,
|
|
2186
2426
|
t.completedAt ?? null,
|
|
@@ -2223,8 +2463,8 @@ function dbGetTask(id) {
|
|
|
2223
2463
|
}
|
|
2224
2464
|
function dbInsertTask(task) {
|
|
2225
2465
|
getDb().prepare(
|
|
2226
|
-
`INSERT INTO tasks (id, project_name, title, description, status, "order", assigned_session_id, assigned_agent, agent_session_id, branch, use_worktree, created_at, updated_at, completed_at, source_connector_id, source_external_url, source_external_id)
|
|
2227
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
2466
|
+
`INSERT INTO tasks (id, project_name, title, description, status, "order", assigned_session_id, assigned_agent, agent_session_id, branch, use_worktree, worktree_path, created_at, updated_at, completed_at, source_connector_id, source_external_url, source_external_id)
|
|
2467
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
2228
2468
|
).run(
|
|
2229
2469
|
task.id,
|
|
2230
2470
|
task.projectName,
|
|
@@ -2237,6 +2477,7 @@ function dbInsertTask(task) {
|
|
|
2237
2477
|
task.agentSessionId ?? null,
|
|
2238
2478
|
task.branch ?? null,
|
|
2239
2479
|
task.useWorktree ? 1 : 0,
|
|
2480
|
+
task.worktreePath ?? null,
|
|
2240
2481
|
task.createdAt,
|
|
2241
2482
|
task.updatedAt,
|
|
2242
2483
|
task.completedAt ?? null,
|
|
@@ -2259,6 +2500,7 @@ function dbUpdateTask(id, updates) {
|
|
|
2259
2500
|
addSet(sets, params, "status", updates.status);
|
|
2260
2501
|
addSet(sets, params, '"order"', updates.order);
|
|
2261
2502
|
addSet(sets, params, "branch", updates.branch);
|
|
2503
|
+
addSet(sets, params, "worktree_path", updates.worktreePath);
|
|
2262
2504
|
if (updates.useWorktree !== void 0) {
|
|
2263
2505
|
sets.push("use_worktree = ?");
|
|
2264
2506
|
params.push(updates.useWorktree ? 1 : 0);
|
|
@@ -2473,6 +2715,7 @@ function rowToTask(r) {
|
|
|
2473
2715
|
...r.agent_session_id != null && { agentSessionId: r.agent_session_id },
|
|
2474
2716
|
...r.branch != null && { branch: r.branch },
|
|
2475
2717
|
...r.use_worktree != null && r.use_worktree !== 0 && { useWorktree: true },
|
|
2718
|
+
...r.worktree_path != null && { worktreePath: r.worktree_path },
|
|
2476
2719
|
createdAt: r.created_at,
|
|
2477
2720
|
updatedAt: r.updated_at,
|
|
2478
2721
|
...r.completed_at != null && { completedAt: r.completed_at },
|
|
@@ -2749,9 +2992,40 @@ var ConfigManager = class {
|
|
|
2749
2992
|
}
|
|
2750
2993
|
return seeded;
|
|
2751
2994
|
}
|
|
2995
|
+
/** Авторитетный список задач читаем прямо из БД, минуя `cachedConfig`:
|
|
2996
|
+
* задачи пишутся и мимо ConfigManager (backfill коннектора, MCP
|
|
2997
|
+
* stdio-процесс), а кэш инвалидируется только собственными
|
|
2998
|
+
* saveConfig/notifyChanged. Сохранение поверх тёплого кэша означало бы
|
|
2999
|
+
* «удалить всё, что появилось после последней записи».
|
|
3000
|
+
*
|
|
3001
|
+
* Возвращает null, если чтение упало: подставлять сюда fallback из
|
|
3002
|
+
* loadConfig() нельзя — он отдаёт `tasks: []`, что для dbSaveConfig
|
|
3003
|
+
* равносильно «удалить все задачи». */
|
|
3004
|
+
readPersistedTasks() {
|
|
3005
|
+
try {
|
|
3006
|
+
return loadConfig().tasks ?? [];
|
|
3007
|
+
} catch (err) {
|
|
3008
|
+
logger_default.error({ err }, "[config-manager] failed to read tasks before save");
|
|
3009
|
+
return null;
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
2752
3012
|
saveConfig(config) {
|
|
2753
3013
|
try {
|
|
2754
|
-
|
|
3014
|
+
const mutation = config.__taskMutation;
|
|
3015
|
+
const persisted = { ...config };
|
|
3016
|
+
delete persisted.__taskMutation;
|
|
3017
|
+
delete config.__taskMutation;
|
|
3018
|
+
const currentTasks = this.readPersistedTasks();
|
|
3019
|
+
if (currentTasks === null) {
|
|
3020
|
+
delete persisted.tasks;
|
|
3021
|
+
} else {
|
|
3022
|
+
const tasks = applyTaskConfigMutation(currentTasks, mutation);
|
|
3023
|
+
if (config.tasks !== void 0 || currentTasks.length || mutation) {
|
|
3024
|
+
persisted.tasks = tasks;
|
|
3025
|
+
config.tasks = tasks;
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
saveConfig(persisted);
|
|
2755
3029
|
this.cachedConfig = null;
|
|
2756
3030
|
} catch (err) {
|
|
2757
3031
|
logger_default.error({ err }, "[config-manager] saveConfig failed");
|
|
@@ -4081,10 +4355,12 @@ function registerWorkspaceTools(server) {
|
|
|
4081
4355
|
|
|
4082
4356
|
// src/tools/ask-user-question.ts
|
|
4083
4357
|
import { z as z7 } from "zod";
|
|
4084
|
-
var ASK_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
4085
4358
|
var questionSchema = z7.object({
|
|
4086
4359
|
question: z7.string().min(1).max(1e3).describe("The question to ask the user."),
|
|
4087
|
-
|
|
4360
|
+
// 12 символов — потолок «чипа» в карточке (как у встроенного
|
|
4361
|
+
// AskUserQuestion). Обрезаем, а не отвергаем: завалить схему из-за косметики
|
|
4362
|
+
// значит не задать вопрос вовсе, и модель узнает об этом только по ошибке.
|
|
4363
|
+
header: z7.string().max(200).optional().transform((value) => value?.slice(0, 12)).describe("Very short label/chip shown above the question (kept to 12 chars)."),
|
|
4088
4364
|
multiSelect: z7.boolean().optional().describe("Allow multiple options to be selected. Defaults to single-select."),
|
|
4089
4365
|
options: z7.array(z7.string().min(1).max(200)).min(2).max(4).describe(
|
|
4090
4366
|
'Available choices (2\u20134). Do NOT include "Other" yourself \u2014 the UI adds it automatically when supported.'
|
|
@@ -4131,7 +4407,7 @@ function registerAskUserQuestionTool(server) {
|
|
|
4131
4407
|
const res = await rpcCall(
|
|
4132
4408
|
"mcp:askUserQuestion",
|
|
4133
4409
|
{ terminalId, questions: normalized },
|
|
4134
|
-
{ timeoutMs:
|
|
4410
|
+
{ timeoutMs: MCP_ASK_TIMEOUT_MS }
|
|
4135
4411
|
);
|
|
4136
4412
|
if (res.skipped || !res.answers) {
|
|
4137
4413
|
return {
|
|
@@ -4564,6 +4840,74 @@ function registerEmulatorTools(server) {
|
|
|
4564
4840
|
);
|
|
4565
4841
|
}
|
|
4566
4842
|
|
|
4843
|
+
// src/tools/flow.ts
|
|
4844
|
+
import { z as z9 } from "zod";
|
|
4845
|
+
function registerFlowTools(server) {
|
|
4846
|
+
server.tool(
|
|
4847
|
+
"set_acceptance_criteria",
|
|
4848
|
+
"Record the acceptance criteria for the work in this worktree: what a person will do and what they should see. Call this at the end of a discussion, before any code is written \u2014 the criteria are handed to the session that implements the work and to the one that accepts it. Replaces the list you recorded before, but never the criteria the human added by hand. Requires the BaseGrid app to be running.",
|
|
4849
|
+
{
|
|
4850
|
+
worktree_path: V.absolutePath.describe(
|
|
4851
|
+
"Absolute path of the worktree you are working in (your cwd)"
|
|
4852
|
+
),
|
|
4853
|
+
criteria: z9.array(
|
|
4854
|
+
z9.object({
|
|
4855
|
+
text: V.title.describe("One checkable criterion, phrased as a user would"),
|
|
4856
|
+
task_id: V.id.optional().describe("Task this criterion comes from, if any")
|
|
4857
|
+
})
|
|
4858
|
+
).min(1).max(30).describe("The full list \u2014 it replaces whatever was recorded before")
|
|
4859
|
+
},
|
|
4860
|
+
async (args) => {
|
|
4861
|
+
const flow = await rpcCall("worktree:flow:setCriteria", {
|
|
4862
|
+
cwd: args.worktree_path,
|
|
4863
|
+
// Пункты, дописанные человеком в полосе, вызов не трогает.
|
|
4864
|
+
fromAgent: true,
|
|
4865
|
+
criteria: args.criteria.map((c) => ({
|
|
4866
|
+
text: c.text,
|
|
4867
|
+
...c.task_id ? { taskId: c.task_id } : {}
|
|
4868
|
+
}))
|
|
4869
|
+
});
|
|
4870
|
+
return { content: [{ type: "text", text: JSON.stringify(flow, null, 2) }] };
|
|
4871
|
+
}
|
|
4872
|
+
);
|
|
4873
|
+
server.tool(
|
|
4874
|
+
"set_criterion_status",
|
|
4875
|
+
"Record the verdict for ONE acceptance criterion during an acceptance pass, by its 1-based number as shown in the list. Only the acceptance tab may record verdicts \u2014 from the work tab the call is rejected. Call it as soon as you close a criterion, not in a batch at the end: the bar above the tabs is the scoreboard the human watches while you work. A verdict left only in your reply dies with the session \u2014 this one survives it. Requires the BaseGrid app to be running.",
|
|
4876
|
+
{
|
|
4877
|
+
worktree_path: V.absolutePath.describe(
|
|
4878
|
+
"Absolute path of the worktree you are working in (your cwd)"
|
|
4879
|
+
),
|
|
4880
|
+
index: z9.number().int().min(1).max(30).describe("1-based position of the criterion in the recorded list"),
|
|
4881
|
+
status: z9.enum(["passed", "failed"]).describe("passed only when you actually ran it \u2014 never for something you only read"),
|
|
4882
|
+
evidence: V.title.optional().describe("What closed it: the command you ran, the file, the behaviour you saw")
|
|
4883
|
+
},
|
|
4884
|
+
async (args) => {
|
|
4885
|
+
const terminalId = process.env.BASEGRID_TERMINAL_ID;
|
|
4886
|
+
const flow = await rpcCall("worktree:flow:setCriterionStatus", {
|
|
4887
|
+
cwd: args.worktree_path,
|
|
4888
|
+
index: args.index,
|
|
4889
|
+
status: args.status,
|
|
4890
|
+
...args.evidence ? { evidence: args.evidence } : {},
|
|
4891
|
+
...terminalId ? { terminalId } : {}
|
|
4892
|
+
});
|
|
4893
|
+
return { content: [{ type: "text", text: JSON.stringify(flow, null, 2) }] };
|
|
4894
|
+
}
|
|
4895
|
+
);
|
|
4896
|
+
server.tool(
|
|
4897
|
+
"get_acceptance_criteria",
|
|
4898
|
+
"Read the acceptance criteria and current step recorded for a worktree. Returns null when nothing has been recorded yet.",
|
|
4899
|
+
{
|
|
4900
|
+
worktree_path: V.absolutePath.describe("Absolute path of the worktree (your cwd)")
|
|
4901
|
+
},
|
|
4902
|
+
async (args) => {
|
|
4903
|
+
const flow = await rpcCall("worktree:flow:get", {
|
|
4904
|
+
cwd: args.worktree_path
|
|
4905
|
+
});
|
|
4906
|
+
return { content: [{ type: "text", text: JSON.stringify(flow, null, 2) }] };
|
|
4907
|
+
}
|
|
4908
|
+
);
|
|
4909
|
+
}
|
|
4910
|
+
|
|
4567
4911
|
// src/server.ts
|
|
4568
4912
|
function createMcpServer(version) {
|
|
4569
4913
|
const server = new McpServer({ name: "basegrid", version }, { capabilities: { tools: {} } });
|
|
@@ -4575,6 +4919,7 @@ function createMcpServer(version) {
|
|
|
4575
4919
|
registerWorkspaceTools(server);
|
|
4576
4920
|
registerAskUserQuestionTool(server);
|
|
4577
4921
|
registerEmulatorTools(server);
|
|
4922
|
+
registerFlowTools(server);
|
|
4578
4923
|
return server;
|
|
4579
4924
|
}
|
|
4580
4925
|
|
|
@@ -4587,7 +4932,7 @@ console.warn = (...args) => _origError("[mcp:warn]", ...args);
|
|
|
4587
4932
|
console.error = (...args) => _origError("[mcp:error]", ...args);
|
|
4588
4933
|
async function main() {
|
|
4589
4934
|
configManager.init();
|
|
4590
|
-
const version = true ? "0.18.
|
|
4935
|
+
const version = true ? "0.18.14-beta.1" : createRequire(import.meta.url)("../package.json").version;
|
|
4591
4936
|
const server = createMcpServer(version);
|
|
4592
4937
|
const transport = new StdioServerTransport();
|
|
4593
4938
|
await server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basegrid_tech/mcp",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.14-beta.1",
|
|
4
4
|
"description": "BaseGrid MCP server — task management, git, and workflow tools for AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -35,17 +35,17 @@
|
|
|
35
35
|
"dev": "tsx src/index.ts"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@modelcontextprotocol/sdk": "
|
|
39
|
-
"libsql": "
|
|
40
|
-
"pino": "
|
|
41
|
-
"ws": "
|
|
42
|
-
"zod": "
|
|
38
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
39
|
+
"libsql": "0.5.29",
|
|
40
|
+
"pino": "10.3.1",
|
|
41
|
+
"ws": "8.21.0",
|
|
42
|
+
"zod": "4.3.6"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@basegrid/server": "
|
|
46
|
-
"@basegrid/shared": "
|
|
47
|
-
"tsup": "
|
|
48
|
-
"tsx": "
|
|
49
|
-
"typescript": "
|
|
45
|
+
"@basegrid/server": "workspace:*",
|
|
46
|
+
"@basegrid/shared": "workspace:*",
|
|
47
|
+
"tsup": "8.5.1",
|
|
48
|
+
"tsx": "4.21.0",
|
|
49
|
+
"typescript": "6.0.3"
|
|
50
50
|
}
|
|
51
|
-
}
|
|
51
|
+
}
|