@mgsoftwarebv/mg-dashboard-mcp 7.4.15 → 7.4.17
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 +272 -142
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1010,9 +1010,9 @@ ${raw2.substring(0, 500)}` }] };
|
|
|
1010
1010
|
return { content: [{ type: "text", text: `No environment variables for ${project}/${env}.` }] };
|
|
1011
1011
|
}
|
|
1012
1012
|
const lines = vars.map((v) => `${v.isSecret ? "[secret]" : " "} ${v.name}`).sort();
|
|
1013
|
-
const
|
|
1013
|
+
const text21 = `Env vars for ${project}/${env} (${vars.length}) \u2014 values hidden, use action="get" with a key:
|
|
1014
1014
|
` + "-".repeat(50) + "\n" + lines.join("\n");
|
|
1015
|
-
return { content: [{ type: "text", text:
|
|
1015
|
+
return { content: [{ type: "text", text: text21 }] };
|
|
1016
1016
|
}
|
|
1017
1017
|
if (action === "get") {
|
|
1018
1018
|
const key2 = String(args2.key ?? "");
|
|
@@ -1099,9 +1099,9 @@ async function fetchAndFormatRun(conn, proxy, sshExec2, instance, runId) {
|
|
|
1099
1099
|
return { content: [{ type: "text", text: `Invalid API response:
|
|
1100
1100
|
${rawJson.substring(0, 500)}` }] };
|
|
1101
1101
|
}
|
|
1102
|
-
let
|
|
1103
|
-
if (logs)
|
|
1104
|
-
return { content: [{ type: "text", text:
|
|
1102
|
+
let text21 = formatRunDetail(run);
|
|
1103
|
+
if (logs) text21 += "\n\n--- Logs ---\n" + logs;
|
|
1104
|
+
return { content: [{ type: "text", text: text21 }] };
|
|
1105
1105
|
}
|
|
1106
1106
|
async function waitForCompletion(conn, proxy, sshExec2, instance, runId, waitSeconds) {
|
|
1107
1107
|
const pollInterval = 3e3;
|
|
@@ -1123,10 +1123,10 @@ async function waitForCompletion(conn, proxy, sshExec2, instance, runId, waitSec
|
|
|
1123
1123
|
continue;
|
|
1124
1124
|
}
|
|
1125
1125
|
if (TERMINAL_STATUSES.has(run.status)) {
|
|
1126
|
-
let
|
|
1126
|
+
let text21 = formatRunDetail(run);
|
|
1127
1127
|
const logs = await fetchRunLogs(runId, conn, proxy, sshExec2);
|
|
1128
|
-
if (logs)
|
|
1129
|
-
return { content: [{ type: "text", text:
|
|
1128
|
+
if (logs) text21 += "\n\n--- Logs ---\n" + logs;
|
|
1129
|
+
return { content: [{ type: "text", text: text21 }] };
|
|
1130
1130
|
}
|
|
1131
1131
|
}
|
|
1132
1132
|
return {
|
|
@@ -1138,32 +1138,65 @@ async function waitForCompletion(conn, proxy, sshExec2, instance, runId, waitSec
|
|
|
1138
1138
|
}
|
|
1139
1139
|
|
|
1140
1140
|
// src/github-code-access-tools.ts
|
|
1141
|
+
var FILE_PROPERTIES = {
|
|
1142
|
+
repository: {
|
|
1143
|
+
type: "string",
|
|
1144
|
+
description: "owner/repo, e.g. MGSoftwareBV/tickets-v2. Org must be allowlisted (CODE_BATTLE_GITHUB_ORGS)."
|
|
1145
|
+
},
|
|
1146
|
+
path: {
|
|
1147
|
+
type: "string",
|
|
1148
|
+
description: "File path inside the repo (not a directory)."
|
|
1149
|
+
},
|
|
1150
|
+
ref: {
|
|
1151
|
+
type: "string",
|
|
1152
|
+
description: "Optional commit sha, branch, or tag. Defaults to the repository default branch."
|
|
1153
|
+
}
|
|
1154
|
+
};
|
|
1155
|
+
var FILE_DESCRIPTION = "Read ONE source file from an ingested GitHub org/repo (CODE_BATTLE_GITHUB_ORGS, default MGSoftwareBV). Path + optional ref (defaults to the repo default branch). Returns metadata + text content (secrets redacted). Credential paths (.env, keys) are denied. Binary files return { binary: true } with no payload. Use list-dir to browse a folder first. Compact diffs stay on get_mg_dashboard_diff.";
|
|
1141
1156
|
var GITHUB_CODE_ACCESS_TOOLS = [
|
|
1142
1157
|
{
|
|
1143
|
-
name: "
|
|
1144
|
-
description:
|
|
1158
|
+
name: "read-file",
|
|
1159
|
+
description: FILE_DESCRIPTION,
|
|
1160
|
+
inputSchema: {
|
|
1161
|
+
type: "object",
|
|
1162
|
+
properties: FILE_PROPERTIES,
|
|
1163
|
+
required: ["repository", "path"]
|
|
1164
|
+
}
|
|
1165
|
+
},
|
|
1166
|
+
{
|
|
1167
|
+
name: "list-dir",
|
|
1168
|
+
description: "List ONE directory on an ingested GitHub org/repo (CODE_BATTLE_GITHUB_ORGS). Path is optional (empty or '/' = repo root). Ref is optional (defaults to the repo default branch). Returns name/path/type/size/sha per entry. Credential files are omitted. No file contents, no clone.",
|
|
1145
1169
|
inputSchema: {
|
|
1146
1170
|
type: "object",
|
|
1147
1171
|
properties: {
|
|
1148
1172
|
repository: {
|
|
1149
1173
|
type: "string",
|
|
1150
|
-
description: "owner/repo, e.g. MGSoftwareBV/
|
|
1174
|
+
description: "owner/repo, e.g. MGSoftwareBV/tickets-v2. Org must be allowlisted."
|
|
1151
1175
|
},
|
|
1152
|
-
|
|
1176
|
+
path: {
|
|
1153
1177
|
type: "string",
|
|
1154
|
-
description: "
|
|
1178
|
+
description: "Directory path (e.g. wbso-planning). Empty string or '/' for the repository root."
|
|
1155
1179
|
},
|
|
1156
|
-
|
|
1180
|
+
ref: {
|
|
1157
1181
|
type: "string",
|
|
1158
|
-
description: "
|
|
1182
|
+
description: "Optional commit sha, branch, or tag. Defaults to the repository default branch."
|
|
1159
1183
|
}
|
|
1160
1184
|
},
|
|
1161
|
-
required: ["repository"
|
|
1185
|
+
required: ["repository"]
|
|
1186
|
+
}
|
|
1187
|
+
},
|
|
1188
|
+
{
|
|
1189
|
+
name: "get_mg_dashboard_file",
|
|
1190
|
+
description: `${FILE_DESCRIPTION} Alias of read-file.`,
|
|
1191
|
+
inputSchema: {
|
|
1192
|
+
type: "object",
|
|
1193
|
+
properties: FILE_PROPERTIES,
|
|
1194
|
+
required: ["repository", "path"]
|
|
1162
1195
|
}
|
|
1163
1196
|
},
|
|
1164
1197
|
{
|
|
1165
1198
|
name: "get_mg_dashboard_diff",
|
|
1166
|
-
description: "Fetch a COMPACT unified diff for one commit sha XOR one pull request number, same org allowlist as
|
|
1199
|
+
description: "Fetch a COMPACT unified diff for one commit sha XOR one pull request number, same org allowlist as read-file. Returns per-file path/status/+/- and a truncated patch (secrets redacted). Binary files are omitted. Does not change get_mg_dashboard_commits (metadata-only by design).",
|
|
1167
1200
|
inputSchema: {
|
|
1168
1201
|
type: "object",
|
|
1169
1202
|
properties: {
|
|
@@ -1184,25 +1217,49 @@ var GITHUB_CODE_ACCESS_TOOLS = [
|
|
|
1184
1217
|
}
|
|
1185
1218
|
}
|
|
1186
1219
|
];
|
|
1220
|
+
function optionalString(value) {
|
|
1221
|
+
if (typeof value !== "string") return void 0;
|
|
1222
|
+
const trimmed = value.trim();
|
|
1223
|
+
return trimmed ? trimmed : void 0;
|
|
1224
|
+
}
|
|
1187
1225
|
async function handleGithubCodeAccessTool(name, args2, ctx) {
|
|
1188
|
-
if (name === "get_mg_dashboard_file") {
|
|
1189
|
-
const repository =
|
|
1190
|
-
const
|
|
1191
|
-
const
|
|
1192
|
-
if (!repository || !
|
|
1226
|
+
if (name === "get_mg_dashboard_file" || name === "read-file") {
|
|
1227
|
+
const repository = optionalString(args2.repository) ?? "";
|
|
1228
|
+
const path = optionalString(args2.path) ?? "";
|
|
1229
|
+
const ref = optionalString(args2.ref);
|
|
1230
|
+
if (!repository || !path) {
|
|
1193
1231
|
return {
|
|
1194
1232
|
content: [
|
|
1195
1233
|
{
|
|
1196
1234
|
type: "text",
|
|
1197
|
-
text: "Error: repository
|
|
1235
|
+
text: "Error: repository and path are required"
|
|
1198
1236
|
}
|
|
1199
1237
|
]
|
|
1200
1238
|
};
|
|
1201
1239
|
}
|
|
1202
|
-
return proxyJson(ctx, "/api/activity/file", {
|
|
1240
|
+
return proxyJson(ctx, "/api/activity/file", {
|
|
1241
|
+
repository,
|
|
1242
|
+
path,
|
|
1243
|
+
...ref ? { ref } : {}
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1246
|
+
if (name === "list-dir") {
|
|
1247
|
+
const repository = optionalString(args2.repository) ?? "";
|
|
1248
|
+
if (!repository) {
|
|
1249
|
+
return {
|
|
1250
|
+
content: [{ type: "text", text: "Error: repository is required" }]
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
const path = typeof args2.path === "string" ? args2.path : "";
|
|
1254
|
+
const ref = optionalString(args2.ref);
|
|
1255
|
+
return proxyJson(ctx, "/api/activity/list-dir", {
|
|
1256
|
+
repository,
|
|
1257
|
+
path,
|
|
1258
|
+
...ref ? { ref } : {}
|
|
1259
|
+
});
|
|
1203
1260
|
}
|
|
1204
1261
|
if (name === "get_mg_dashboard_diff") {
|
|
1205
|
-
const repository =
|
|
1262
|
+
const repository = optionalString(args2.repository) ?? "";
|
|
1206
1263
|
if (!repository) {
|
|
1207
1264
|
return {
|
|
1208
1265
|
content: [
|
|
@@ -1210,7 +1267,7 @@ async function handleGithubCodeAccessTool(name, args2, ctx) {
|
|
|
1210
1267
|
]
|
|
1211
1268
|
};
|
|
1212
1269
|
}
|
|
1213
|
-
const sha =
|
|
1270
|
+
const sha = optionalString(args2.sha);
|
|
1214
1271
|
const pullNumber = typeof args2.pullNumber === "number" ? args2.pullNumber : void 0;
|
|
1215
1272
|
const hasSha = Boolean(sha);
|
|
1216
1273
|
const hasPr = pullNumber != null;
|
|
@@ -3935,10 +3992,10 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
3935
3992
|
// }) as any;
|
|
3936
3993
|
// return merged;
|
|
3937
3994
|
// }
|
|
3938
|
-
catchall(
|
|
3995
|
+
catchall(index18) {
|
|
3939
3996
|
return new _ZodObject({
|
|
3940
3997
|
...this._def,
|
|
3941
|
-
catchall:
|
|
3998
|
+
catchall: index18
|
|
3942
3999
|
});
|
|
3943
4000
|
}
|
|
3944
4001
|
pick(mask) {
|
|
@@ -4256,9 +4313,9 @@ function mergeValues(a, b) {
|
|
|
4256
4313
|
return { valid: false };
|
|
4257
4314
|
}
|
|
4258
4315
|
const newArray = [];
|
|
4259
|
-
for (let
|
|
4260
|
-
const itemA = a[
|
|
4261
|
-
const itemB = b[
|
|
4316
|
+
for (let index18 = 0; index18 < a.length; index18++) {
|
|
4317
|
+
const itemA = a[index18];
|
|
4318
|
+
const itemB = b[index18];
|
|
4262
4319
|
const sharedValue = mergeValues(itemA, itemB);
|
|
4263
4320
|
if (!sharedValue.valid) {
|
|
4264
4321
|
return { valid: false };
|
|
@@ -4464,10 +4521,10 @@ var ZodMap = class extends ZodType {
|
|
|
4464
4521
|
}
|
|
4465
4522
|
const keyType = this._def.keyType;
|
|
4466
4523
|
const valueType = this._def.valueType;
|
|
4467
|
-
const pairs = [...ctx.data.entries()].map(([key, value],
|
|
4524
|
+
const pairs = [...ctx.data.entries()].map(([key, value], index18) => {
|
|
4468
4525
|
return {
|
|
4469
|
-
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [
|
|
4470
|
-
value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [
|
|
4526
|
+
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index18, "key"])),
|
|
4527
|
+
value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index18, "value"]))
|
|
4471
4528
|
};
|
|
4472
4529
|
});
|
|
4473
4530
|
if (ctx.common.async) {
|
|
@@ -5785,92 +5842,9 @@ pgTable(
|
|
|
5785
5842
|
),
|
|
5786
5843
|
index("idx_agent_memory_repo").on(table.gitRepository),
|
|
5787
5844
|
index("idx_agent_memory_user").on(table.userId),
|
|
5788
|
-
index("idx_agent_memory_kind").on(table.kind)
|
|
5789
|
-
index("idx_agent_memory_category").on(table.category)
|
|
5790
|
-
]
|
|
5791
|
-
);
|
|
5792
|
-
var agentWorldAgent = pgTable(
|
|
5793
|
-
"agent_world_agent",
|
|
5794
|
-
{
|
|
5795
|
-
id: uuid("id").primaryKey().defaultRandom(),
|
|
5796
|
-
name: text("name").notNull(),
|
|
5797
|
-
color: text("color").notNull(),
|
|
5798
|
-
/** Personality sliders 0–100: curiosity, sociability, diligence, calm. */
|
|
5799
|
-
personality: jsonb("personality").$type().notNull().default({
|
|
5800
|
-
curiosity: 50,
|
|
5801
|
-
sociability: 50,
|
|
5802
|
-
diligence: 50,
|
|
5803
|
-
calm: 50
|
|
5804
|
-
}),
|
|
5805
|
-
/** Needs 0–100: higher = more urgent. */
|
|
5806
|
-
needs: jsonb("needs").$type().notNull().default({ energy: 40, coffee: 30, focus: 35, social: 25 }),
|
|
5807
|
-
position: jsonb("position").$type().notNull().default({ x: 0, y: 0, z: 0 }),
|
|
5808
|
-
target: jsonb("target").$type(),
|
|
5809
|
-
activity: text("activity").notNull().default("idle"),
|
|
5810
|
-
waypoint: text("waypoint"),
|
|
5811
|
-
memories: jsonb("memories").$type().notNull().default([]),
|
|
5812
|
-
diaryCount: integer("diary_count").notNull().default(0),
|
|
5813
|
-
lastSay: text("last_say"),
|
|
5814
|
-
lastSayAt: timestamp("last_say_at", { withTimezone: true }),
|
|
5815
|
-
sortOrder: integer("sort_order").notNull().default(0),
|
|
5816
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5817
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
5818
|
-
},
|
|
5819
|
-
(table) => [index("idx_agent_world_agent_sort").on(table.sortOrder)]
|
|
5820
|
-
);
|
|
5821
|
-
pgTable(
|
|
5822
|
-
"agent_world_event",
|
|
5823
|
-
{
|
|
5824
|
-
id: uuid("id").primaryKey().defaultRandom(),
|
|
5825
|
-
/** say | diary | think | god | activity | memo | system */
|
|
5826
|
-
type: text("type").notNull(),
|
|
5827
|
-
agentId: uuid("agent_id").references(() => agentWorldAgent.id, {
|
|
5828
|
-
onDelete: "set null"
|
|
5829
|
-
}),
|
|
5830
|
-
message: text("message").notNull(),
|
|
5831
|
-
meta: jsonb("meta").$type().notNull().default({}),
|
|
5832
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
5833
|
-
},
|
|
5834
|
-
(table) => [
|
|
5835
|
-
index("idx_agent_world_event_created").on(table.createdAt),
|
|
5836
|
-
index("idx_agent_world_event_type").on(table.type),
|
|
5837
|
-
index("idx_agent_world_event_agent").on(table.agentId),
|
|
5838
|
-
// Diary / per-agent feed: WHERE agent_id ORDER BY created_at DESC LIMIT N
|
|
5839
|
-
index("idx_agent_world_event_agent_created").on(
|
|
5840
|
-
table.agentId,
|
|
5841
|
-
table.createdAt
|
|
5842
|
-
)
|
|
5843
|
-
]
|
|
5844
|
-
);
|
|
5845
|
-
pgTable(
|
|
5846
|
-
"agent_world_memo",
|
|
5847
|
-
{
|
|
5848
|
-
id: uuid("id").primaryKey().defaultRandom(),
|
|
5849
|
-
agentId: uuid("agent_id").references(() => agentWorldAgent.id, {
|
|
5850
|
-
onDelete: "set null"
|
|
5851
|
-
}),
|
|
5852
|
-
title: text("title").notNull(),
|
|
5853
|
-
content: text("content").notNull(),
|
|
5854
|
-
location: text("location").notNull().default("whiteboard"),
|
|
5855
|
-
reads: integer("reads").notNull().default(0),
|
|
5856
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5857
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
5858
|
-
},
|
|
5859
|
-
(table) => [
|
|
5860
|
-
index("idx_agent_world_memo_created").on(table.createdAt),
|
|
5861
|
-
index("idx_agent_world_memo_location").on(table.location)
|
|
5845
|
+
index("idx_agent_memory_kind").on(table.kind)
|
|
5862
5846
|
]
|
|
5863
5847
|
);
|
|
5864
|
-
pgTable("agent_world_state", {
|
|
5865
|
-
id: text("id").primaryKey().default("world"),
|
|
5866
|
-
tick: integer("tick").notNull().default(0),
|
|
5867
|
-
/** Simulated minutes since day start (0–1439 wraps). */
|
|
5868
|
-
simMinutes: integer("sim_minutes").notNull().default(540),
|
|
5869
|
-
paused: boolean("paused").notNull().default(false),
|
|
5870
|
-
lastThinkAt: timestamp("last_think_at", { withTimezone: true }),
|
|
5871
|
-
lastThinkAgentId: uuid("last_think_agent_id"),
|
|
5872
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
5873
|
-
});
|
|
5874
5848
|
var contentSourceType = pgEnum("content_source_type", [
|
|
5875
5849
|
"own_site",
|
|
5876
5850
|
"client_site",
|
|
@@ -9539,7 +9513,7 @@ function getEncryptionKey() {
|
|
|
9539
9513
|
throw new Error("ENCRYPTION_KEY must be a 64-character hex string");
|
|
9540
9514
|
return buf;
|
|
9541
9515
|
}
|
|
9542
|
-
function encrypt(
|
|
9516
|
+
function encrypt(text21) {
|
|
9543
9517
|
const key = getEncryptionKey();
|
|
9544
9518
|
const iv = randomBytes(ENC_IV_LENGTH);
|
|
9545
9519
|
const cipher = createCipheriv(
|
|
@@ -9547,7 +9521,7 @@ function encrypt(text22) {
|
|
|
9547
9521
|
new Uint8Array(key),
|
|
9548
9522
|
new Uint8Array(iv)
|
|
9549
9523
|
);
|
|
9550
|
-
let encrypted = cipher.update(
|
|
9524
|
+
let encrypted = cipher.update(text21, "utf8", "hex");
|
|
9551
9525
|
encrypted += cipher.final("hex");
|
|
9552
9526
|
const authTag = cipher.getAuthTag();
|
|
9553
9527
|
return Buffer.concat([
|
|
@@ -10267,10 +10241,10 @@ async function r2GetObjectRange(bucket, key, range) {
|
|
|
10267
10241
|
const body = result.Body;
|
|
10268
10242
|
if (!body?.transformToString)
|
|
10269
10243
|
throw new Error("R2 returned no readable body");
|
|
10270
|
-
const
|
|
10244
|
+
const text21 = await body.transformToString();
|
|
10271
10245
|
const header = `# range: bytes ${range.offset}-${end} of ${size} (${effectiveLen} bytes)`;
|
|
10272
10246
|
return `${header}
|
|
10273
|
-
${
|
|
10247
|
+
${text21}`;
|
|
10274
10248
|
} catch (e) {
|
|
10275
10249
|
throw r2WrapError(bucket, key, e);
|
|
10276
10250
|
}
|
|
@@ -10633,15 +10607,15 @@ async function sftpRead(opts, filePath, proxy, options) {
|
|
|
10633
10607
|
clearTimeout(timer);
|
|
10634
10608
|
cleanup?.();
|
|
10635
10609
|
cleanup = void 0;
|
|
10636
|
-
const
|
|
10610
|
+
const text21 = Buffer.concat(
|
|
10637
10611
|
chunks.map((ch) => new Uint8Array(ch))
|
|
10638
10612
|
).toString("utf-8");
|
|
10639
10613
|
if (!isWholeFileRequest) {
|
|
10640
10614
|
const header = `# range: bytes ${offset}-${offset + effectiveLen - 1} of ${total} (${effectiveLen} bytes)`;
|
|
10641
10615
|
resolve(`${header}
|
|
10642
|
-
${
|
|
10616
|
+
${text21}`);
|
|
10643
10617
|
} else {
|
|
10644
|
-
resolve(
|
|
10618
|
+
resolve(text21);
|
|
10645
10619
|
}
|
|
10646
10620
|
});
|
|
10647
10621
|
rs.on("error", (e) => {
|
|
@@ -10676,6 +10650,8 @@ var RAW_JSON_TOOLS = /* @__PURE__ */ new Set([
|
|
|
10676
10650
|
"get_mg_dashboard_commits",
|
|
10677
10651
|
"get_mg_dashboard_file",
|
|
10678
10652
|
"get_mg_dashboard_diff",
|
|
10653
|
+
"read-file",
|
|
10654
|
+
"list-dir",
|
|
10679
10655
|
"extract_article",
|
|
10680
10656
|
// Content family (2026-DASMG-040/041/042) — compact JSON consumed verbatim.
|
|
10681
10657
|
// Consolidated action-based tools (the Cursor surface); each proxies to the
|
|
@@ -10794,11 +10770,11 @@ function getKnownContainers(serverId, maxAgeMs = 5 * 6e4) {
|
|
|
10794
10770
|
if (Date.now() - e.capturedAt > maxAgeMs) return void 0;
|
|
10795
10771
|
return e.names;
|
|
10796
10772
|
}
|
|
10797
|
-
function truncateForLLM(
|
|
10798
|
-
const totalBytes = Buffer.byteLength(
|
|
10773
|
+
function truncateForLLM(text21, maxBytes) {
|
|
10774
|
+
const totalBytes = Buffer.byteLength(text21, "utf8");
|
|
10799
10775
|
if (totalBytes <= maxBytes)
|
|
10800
|
-
return { text:
|
|
10801
|
-
const buf = Buffer.from(
|
|
10776
|
+
return { text: text21, truncated: false, totalBytes, shownBytes: totalBytes };
|
|
10777
|
+
const buf = Buffer.from(text21, "utf8");
|
|
10802
10778
|
let cut = maxBytes;
|
|
10803
10779
|
while (cut > 0 && (buf[cut] & 192) === 128) cut--;
|
|
10804
10780
|
const head = buf.subarray(0, cut).toString("utf8");
|
|
@@ -10829,10 +10805,10 @@ function postprocessResult(result, meta) {
|
|
|
10829
10805
|
if (!result.content?.length) return result;
|
|
10830
10806
|
if (RAW_JSON_TOOLS.has(meta.toolName)) return result;
|
|
10831
10807
|
const block = result.content[0];
|
|
10832
|
-
let
|
|
10833
|
-
const trunc = truncateForLLM(
|
|
10808
|
+
let text21 = String(block.text ?? "");
|
|
10809
|
+
const trunc = truncateForLLM(text21, RESPONSE_MAX_BYTES);
|
|
10834
10810
|
if (trunc.truncated) {
|
|
10835
|
-
|
|
10811
|
+
text21 = trunc.text + "\n\n... " + buildTruncationHint(
|
|
10836
10812
|
meta.toolName,
|
|
10837
10813
|
meta.args,
|
|
10838
10814
|
trunc.totalBytes,
|
|
@@ -10846,11 +10822,11 @@ function postprocessResult(result, meta) {
|
|
|
10846
10822
|
const parts = [`took ${tookStr}`, sizeStr];
|
|
10847
10823
|
if (meta.serverIdLabel) parts.push(`server: ${meta.serverIdLabel}`);
|
|
10848
10824
|
if (meta.cached) parts.push("cached");
|
|
10849
|
-
|
|
10825
|
+
text21 = `${text21}
|
|
10850
10826
|
|
|
10851
10827
|
[${parts.join(", ")}]`;
|
|
10852
10828
|
}
|
|
10853
|
-
return { ...result, content: [{ ...block, text:
|
|
10829
|
+
return { ...result, content: [{ ...block, text: text21 }] };
|
|
10854
10830
|
}
|
|
10855
10831
|
function buildPipelineScript(commands, shell, marker, stopOnError) {
|
|
10856
10832
|
if (shell === "powershell") {
|
|
@@ -13458,6 +13434,42 @@ var TOOLS = [
|
|
|
13458
13434
|
required: ["slug", "detail"]
|
|
13459
13435
|
}
|
|
13460
13436
|
},
|
|
13437
|
+
{
|
|
13438
|
+
name: "wiki-review-queue",
|
|
13439
|
+
description: "List the knowledge-wiki review queue without the Dashboard UI: open flags first (they jump the queue), then needs-work pages, oldest drafts, and proposed insights. Each item includes slug, status, folder, and updated date. Read a candidate with get-wiki-page, then finish it with wiki-review (action=review for durable pages, action=accept for wiki/insights/*). Folder-filtered to the API key owner's wiki areas.",
|
|
13440
|
+
inputSchema: {
|
|
13441
|
+
type: "object",
|
|
13442
|
+
properties: {
|
|
13443
|
+
limit: {
|
|
13444
|
+
type: "number",
|
|
13445
|
+
description: "Max items per bucket (flags, needs-work, drafts, proposed insights). 1-100, default 50."
|
|
13446
|
+
}
|
|
13447
|
+
}
|
|
13448
|
+
}
|
|
13449
|
+
},
|
|
13450
|
+
{
|
|
13451
|
+
name: "wiki-review",
|
|
13452
|
+
description: "Finish a knowledge-wiki queue item without the Dashboard UI. Same write as wiki-graph: updates page status, resolves open flags on that slug, and closes a linked review-ticket when promoting. action=review \u2192 status reviewed on a durable page (not wiki/insights/*). action=accept \u2192 status accepted on a wiki/insights/* proposal. Read the page with get-wiki-page first. Does not edit page body \u2014 only status/frontmatter. Does not resolve Refront pipeline tickets on behalf of operators.",
|
|
13453
|
+
inputSchema: {
|
|
13454
|
+
type: "object",
|
|
13455
|
+
properties: {
|
|
13456
|
+
slug: {
|
|
13457
|
+
type: "string",
|
|
13458
|
+
description: "Page slug from wiki-review-queue or get-wiki-page, e.g. 'wiki/engineering/team-memory' or 'wiki/insights/2026-08-14-example'."
|
|
13459
|
+
},
|
|
13460
|
+
action: {
|
|
13461
|
+
type: "string",
|
|
13462
|
+
enum: ["accept", "review"],
|
|
13463
|
+
description: "review = mark a durable page reviewed; accept = accept an insight proposal."
|
|
13464
|
+
},
|
|
13465
|
+
note: {
|
|
13466
|
+
type: "string",
|
|
13467
|
+
description: "Optional note appended under ## Review notes (max 2000 chars)."
|
|
13468
|
+
}
|
|
13469
|
+
},
|
|
13470
|
+
required: ["slug", "action"]
|
|
13471
|
+
}
|
|
13472
|
+
},
|
|
13461
13473
|
// ----- Cursor Remote (Agent Control) -----
|
|
13462
13474
|
{
|
|
13463
13475
|
name: "cursor-remote-list",
|
|
@@ -13761,6 +13773,8 @@ async function executeToolCall(name, a, _serverId) {
|
|
|
13761
13773
|
}
|
|
13762
13774
|
case "get_mg_dashboard_file":
|
|
13763
13775
|
case "get_mg_dashboard_diff":
|
|
13776
|
+
case "read-file":
|
|
13777
|
+
case "list-dir":
|
|
13764
13778
|
return handleGithubCodeAccessTool(name, a, {
|
|
13765
13779
|
dashboardBaseUrl,
|
|
13766
13780
|
apiKey: apiKey ?? ""
|
|
@@ -13915,7 +13929,7 @@ async function executeToolCall(name, a, _serverId) {
|
|
|
13915
13929
|
]
|
|
13916
13930
|
};
|
|
13917
13931
|
}
|
|
13918
|
-
const lines = data.hits.map((hit,
|
|
13932
|
+
const lines = data.hits.map((hit, index18) => {
|
|
13919
13933
|
const when = hit.lastMessageAt ? new Date(hit.lastMessageAt).toISOString().slice(0, 10) : "unknown date";
|
|
13920
13934
|
const repo = hit.repo ?? "unknown repo";
|
|
13921
13935
|
const sim = hit.similarity !== null ? ` \xB7 ${(hit.similarity * 100).toFixed(0)}% match` : "";
|
|
@@ -13925,7 +13939,7 @@ async function executeToolCall(name, a, _serverId) {
|
|
|
13925
13939
|
...Array.isArray(hit.tech) ? hit.tech.slice(0, 4) : []
|
|
13926
13940
|
].filter(Boolean);
|
|
13927
13941
|
const tags = facets.length > 0 ? ` \xB7 ${facets.join(", ")}` : "";
|
|
13928
|
-
return `${
|
|
13942
|
+
return `${index18 + 1}. [${repo} \xB7 ${when}${sim}${tags}] ${hit.title}
|
|
13929
13943
|
id: ${hit.id}
|
|
13930
13944
|
${(hit.summary ?? hit.snippet).replace(/\s+/g, " ").slice(0, 500)}`;
|
|
13931
13945
|
});
|
|
@@ -14132,12 +14146,12 @@ Searchable via search-team-memory once indexing completes (usually immediate).`
|
|
|
14132
14146
|
]
|
|
14133
14147
|
};
|
|
14134
14148
|
}
|
|
14135
|
-
const lines = data.hits.map((hit,
|
|
14149
|
+
const lines = data.hits.map((hit, index18) => {
|
|
14136
14150
|
const sim = hit.similarity !== null ? ` \xB7 ${Math.round(hit.similarity * 100)}% match` : "";
|
|
14137
14151
|
const tags = hit.tags.length ? ` \xB7 ${hit.tags.slice(0, 5).join(", ")}` : "";
|
|
14138
14152
|
const sources = hit.sources.length ? `
|
|
14139
14153
|
sources: ${hit.sources.slice(0, 6).map((s) => `${s.type}:${s.ref}`).join(", ")}` : "";
|
|
14140
|
-
return `${
|
|
14154
|
+
return `${index18 + 1}. [${hit.status} \xB7 updated ${hit.pageUpdatedOn ?? "unknown"}${sim}${tags}] ${hit.title}
|
|
14141
14155
|
slug: ${hit.slug}${sources}
|
|
14142
14156
|
${(hit.summary ?? hit.snippet).replace(/\s+/g, " ").slice(0, 400)}`;
|
|
14143
14157
|
});
|
|
@@ -14311,6 +14325,122 @@ Archived sources (${archiveOnly.length}):
|
|
|
14311
14325
|
]
|
|
14312
14326
|
};
|
|
14313
14327
|
}
|
|
14328
|
+
case "wiki-review-queue": {
|
|
14329
|
+
let formatItems2 = function(items) {
|
|
14330
|
+
if (items.length === 0) return "(none)";
|
|
14331
|
+
return items.map(
|
|
14332
|
+
(item, index18) => `${index18 + 1}. [${item.status} \xB7 ${item.folder} \xB7 updated ${item.updated ?? "unknown"}] ${item.title}
|
|
14333
|
+
slug: ${item.slug}`
|
|
14334
|
+
).join("\n");
|
|
14335
|
+
};
|
|
14336
|
+
var formatItems = formatItems2;
|
|
14337
|
+
const limit = typeof a.limit === "number" ? a.limit : void 0;
|
|
14338
|
+
const res = await fetch(`${dashboardBaseUrl}/api/wiki/review-queue`, {
|
|
14339
|
+
method: "POST",
|
|
14340
|
+
headers: {
|
|
14341
|
+
"content-type": "application/json",
|
|
14342
|
+
authorization: `Bearer ${apiKey}`
|
|
14343
|
+
},
|
|
14344
|
+
body: JSON.stringify({ limit })
|
|
14345
|
+
});
|
|
14346
|
+
if (!res.ok) {
|
|
14347
|
+
const detail = await res.text().catch(() => "");
|
|
14348
|
+
return {
|
|
14349
|
+
content: [
|
|
14350
|
+
{
|
|
14351
|
+
type: "text",
|
|
14352
|
+
text: `Error: wiki review queue failed (${res.status}). ${detail.slice(0, 300)}`
|
|
14353
|
+
}
|
|
14354
|
+
]
|
|
14355
|
+
};
|
|
14356
|
+
}
|
|
14357
|
+
const data = await res.json();
|
|
14358
|
+
const countLine = Object.entries(data.counts).sort(([left], [right]) => left.localeCompare(right)).map(([status, count]) => `${status} ${count}`).join(" \xB7 ");
|
|
14359
|
+
const flagLines = data.flags.length === 0 ? "(none)" : data.flags.map((flag, index18) => {
|
|
14360
|
+
const detail = flag.detail.replace(/\s+/g, " ").slice(0, 240);
|
|
14361
|
+
return `${index18 + 1}. [${flag.kind} \xB7 ${flag.folder}${flag.status ? ` \xB7 page ${flag.status}` : ""}] ${flag.title}
|
|
14362
|
+
slug: ${flag.slug}
|
|
14363
|
+
${detail}`;
|
|
14364
|
+
}).join("\n");
|
|
14365
|
+
return {
|
|
14366
|
+
content: [
|
|
14367
|
+
{
|
|
14368
|
+
type: "text",
|
|
14369
|
+
text: `Wiki review queue${countLine ? ` (${countLine})` : ""}.
|
|
14370
|
+
Open flags jump the queue. Read a slug with get-wiki-page, then wiki-review action=review (durable page) or action=accept (insight).
|
|
14371
|
+
|
|
14372
|
+
Flags (${data.flags.length})
|
|
14373
|
+
${flagLines}
|
|
14374
|
+
|
|
14375
|
+
Needs-work (${data.needsWork.length})
|
|
14376
|
+
${formatItems2(data.needsWork)}
|
|
14377
|
+
|
|
14378
|
+
Drafts (${data.drafts.length})
|
|
14379
|
+
${formatItems2(data.drafts)}
|
|
14380
|
+
|
|
14381
|
+
Proposed insights (${data.proposedInsights.length})
|
|
14382
|
+
${formatItems2(data.proposedInsights)}`
|
|
14383
|
+
}
|
|
14384
|
+
]
|
|
14385
|
+
};
|
|
14386
|
+
}
|
|
14387
|
+
case "wiki-review": {
|
|
14388
|
+
const slug = typeof a.slug === "string" ? a.slug.trim() : "";
|
|
14389
|
+
const action = typeof a.action === "string" ? a.action.trim() : "";
|
|
14390
|
+
if (!slug || action !== "accept" && action !== "review") {
|
|
14391
|
+
return {
|
|
14392
|
+
content: [
|
|
14393
|
+
{
|
|
14394
|
+
type: "text",
|
|
14395
|
+
text: 'Error: slug and action ("accept" or "review") are required'
|
|
14396
|
+
}
|
|
14397
|
+
]
|
|
14398
|
+
};
|
|
14399
|
+
}
|
|
14400
|
+
const note = typeof a.note === "string" ? a.note.trim() : "";
|
|
14401
|
+
const res = await fetch(`${dashboardBaseUrl}/api/wiki/review`, {
|
|
14402
|
+
method: "POST",
|
|
14403
|
+
headers: {
|
|
14404
|
+
"content-type": "application/json",
|
|
14405
|
+
authorization: `Bearer ${apiKey}`
|
|
14406
|
+
},
|
|
14407
|
+
body: JSON.stringify({
|
|
14408
|
+
slug,
|
|
14409
|
+
action,
|
|
14410
|
+
...note ? { note } : {}
|
|
14411
|
+
})
|
|
14412
|
+
});
|
|
14413
|
+
if (!res.ok) {
|
|
14414
|
+
const errDetail = await res.text().catch(() => "");
|
|
14415
|
+
return {
|
|
14416
|
+
content: [
|
|
14417
|
+
{
|
|
14418
|
+
type: "text",
|
|
14419
|
+
text: `Error: wiki review failed (${res.status}). ${errDetail.slice(0, 300)}`
|
|
14420
|
+
}
|
|
14421
|
+
]
|
|
14422
|
+
};
|
|
14423
|
+
}
|
|
14424
|
+
const data = await res.json();
|
|
14425
|
+
if (!data.found || !data.result) {
|
|
14426
|
+
return {
|
|
14427
|
+
content: [
|
|
14428
|
+
{
|
|
14429
|
+
type: "text",
|
|
14430
|
+
text: `No wiki page found for slug "${slug}" (or it is outside this API key's wiki areas). Check the slug via wiki-review-queue or get-wiki-page.`
|
|
14431
|
+
}
|
|
14432
|
+
]
|
|
14433
|
+
};
|
|
14434
|
+
}
|
|
14435
|
+
return {
|
|
14436
|
+
content: [
|
|
14437
|
+
{
|
|
14438
|
+
type: "text",
|
|
14439
|
+
text: `Set ${data.result.slug} to ${data.result.status}. Open flags on this slug are resolved.` + (action === "accept" ? " Insight is accepted \u2014 executor/distiller can act on it; do not resolve Refront pipeline tickets for Sidney/Jordan." : " Durable page is reviewed.")
|
|
14440
|
+
}
|
|
14441
|
+
]
|
|
14442
|
+
};
|
|
14443
|
+
}
|
|
14314
14444
|
// ----- Cursor Remote (Agent Control) -----
|
|
14315
14445
|
case "cursor-remote-list": {
|
|
14316
14446
|
const onlineOnly = a.onlineOnly === true;
|
|
@@ -15394,8 +15524,8 @@ ${sample.join("\n")}${files.length > 5 ? `
|
|
|
15394
15524
|
};
|
|
15395
15525
|
const filtered = sortRows(applyFilter(only.rows));
|
|
15396
15526
|
if (format === "json") {
|
|
15397
|
-
const
|
|
15398
|
-
return { content: [{ type: "text", text:
|
|
15527
|
+
const text22 = filtered.map((c) => JSON.stringify(c)).join("\n") || "(no containers)";
|
|
15528
|
+
return { content: [{ type: "text", text: text22 }] };
|
|
15399
15529
|
}
|
|
15400
15530
|
if (groupByProject) {
|
|
15401
15531
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -15422,8 +15552,8 @@ ${sample.join("\n")}${files.length > 5 ? `
|
|
|
15422
15552
|
}
|
|
15423
15553
|
const header = `${"NAMES".padEnd(36)} ${"IMAGE".padEnd(40)} ${"STATUS".padEnd(24)} ${"HEALTH".padEnd(10)} ${"PORTS".padEnd(40)} PROJECT`;
|
|
15424
15554
|
const body = filtered.map((r) => `${fmtRow(r)} ${r.Project || ""}`);
|
|
15425
|
-
const
|
|
15426
|
-
return { content: [{ type: "text", text:
|
|
15555
|
+
const text21 = filtered.length === 0 ? "(no containers match)" : [header, ...body].join("\n");
|
|
15556
|
+
return { content: [{ type: "text", text: text21 }] };
|
|
15427
15557
|
}
|
|
15428
15558
|
if (format === "json") {
|
|
15429
15559
|
const lines = [];
|
package/package.json
CHANGED