@kynver-app/openclaw-agent-os 0.1.31 → 0.1.35
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 +308 -3
- package/dist/index.js.map +3 -3
- package/openclaw.plugin.json +6 -0
- package/package.json +1 -1
- package/scripts/bootstrap-openclaw.mjs +8 -2
package/dist/index.js
CHANGED
|
@@ -63,6 +63,11 @@ var pluginConfigSchema = {
|
|
|
63
63
|
default: true,
|
|
64
64
|
description: "Inject a system-context block telling OpenClaw turns to use AgentOS (get_context, search_memory, write_memory, sessions, projects, goals) as the primary continuity store and to treat local markdown memory as fallback only."
|
|
65
65
|
},
|
|
66
|
+
enableTelegramReplyContext: {
|
|
67
|
+
type: "boolean",
|
|
68
|
+
default: true,
|
|
69
|
+
description: "Preserve Telegram reply-thread context on visible outbound messages via reply_dispatch + message_sending hooks (reply_to tags and Re: subject prefixes)."
|
|
70
|
+
},
|
|
66
71
|
runtimeSkillManifestTtlMs: {
|
|
67
72
|
type: "number",
|
|
68
73
|
default: 6e4,
|
|
@@ -86,6 +91,11 @@ var pluginConfigSchema = {
|
|
|
86
91
|
harnessRepo: {
|
|
87
92
|
type: "string",
|
|
88
93
|
description: "Default git repo path for harness run create/dispatch. Required when enableHarnessTools is true. Falls back to KYNVER_HARNESS_REPO."
|
|
94
|
+
},
|
|
95
|
+
enableTelegramToolErrorFilter: {
|
|
96
|
+
type: "boolean",
|
|
97
|
+
default: true,
|
|
98
|
+
description: "When true, suppress raw failed exec/tool/worktree lines on Telegram and webchat direct chat (OpenClaw message_sending hook)."
|
|
89
99
|
}
|
|
90
100
|
}
|
|
91
101
|
};
|
|
@@ -106,11 +116,13 @@ function resolvePluginConfig(rawEntry) {
|
|
|
106
116
|
enableSessionLifecycle: typeof raw?.enableSessionLifecycle === "boolean" ? raw.enableSessionLifecycle : true,
|
|
107
117
|
enableRuntimeSkillManifest: typeof raw?.enableRuntimeSkillManifest === "boolean" ? raw.enableRuntimeSkillManifest : true,
|
|
108
118
|
enableContinuityGuidance: typeof raw?.enableContinuityGuidance === "boolean" ? raw.enableContinuityGuidance : true,
|
|
119
|
+
enableTelegramReplyContext: typeof raw?.enableTelegramReplyContext === "boolean" ? raw.enableTelegramReplyContext : true,
|
|
109
120
|
runtimeSkillManifestTtlMs: typeof raw?.runtimeSkillManifestTtlMs === "number" && Number.isFinite(raw.runtimeSkillManifestTtlMs) && raw.runtimeSkillManifestTtlMs > 0 ? raw.runtimeSkillManifestTtlMs : 6e4,
|
|
110
121
|
runtimeSkillManifestTimeoutMs: typeof raw?.runtimeSkillManifestTimeoutMs === "number" && Number.isFinite(raw.runtimeSkillManifestTimeoutMs) && raw.runtimeSkillManifestTimeoutMs > 0 ? raw.runtimeSkillManifestTimeoutMs : 1e4,
|
|
111
122
|
runtimeSkillManifestMaxSkills: typeof raw?.runtimeSkillManifestMaxSkills === "number" && Number.isFinite(raw.runtimeSkillManifestMaxSkills) && raw.runtimeSkillManifestMaxSkills > 0 ? Math.floor(raw.runtimeSkillManifestMaxSkills) : 25,
|
|
112
123
|
enableHarnessTools: typeof raw?.enableHarnessTools === "boolean" ? raw.enableHarnessTools : false,
|
|
113
|
-
harnessRepo: typeof raw?.harnessRepo === "string" && raw.harnessRepo.trim() ? raw.harnessRepo.trim() : process.env.KYNVER_HARNESS_REPO?.trim() || void 0
|
|
124
|
+
harnessRepo: typeof raw?.harnessRepo === "string" && raw.harnessRepo.trim() ? raw.harnessRepo.trim() : process.env.KYNVER_HARNESS_REPO?.trim() || void 0,
|
|
125
|
+
enableTelegramToolErrorFilter: typeof raw?.enableTelegramToolErrorFilter === "boolean" ? raw.enableTelegramToolErrorFilter : true
|
|
114
126
|
};
|
|
115
127
|
}
|
|
116
128
|
|
|
@@ -729,6 +741,14 @@ function directRequestForTool(toolName2, params, resolvedSlug) {
|
|
|
729
741
|
method: "GET",
|
|
730
742
|
path: `/command-center${queryString(params, ["since", "limit", "harnessLimit"])}`
|
|
731
743
|
};
|
|
744
|
+
case "agent_os_command_center_dashboard_contract_get":
|
|
745
|
+
return {
|
|
746
|
+
route: "by-id",
|
|
747
|
+
agentOsId: stringParam(params.agentOsId),
|
|
748
|
+
slug,
|
|
749
|
+
method: "GET",
|
|
750
|
+
path: `/command-center/dashboard-contract${queryString(params, ["since", "limit"])}`
|
|
751
|
+
};
|
|
732
752
|
case "agent_os_task_next_action": {
|
|
733
753
|
const taskId = requiredString(params.taskId, "taskId");
|
|
734
754
|
return {
|
|
@@ -933,8 +953,20 @@ function buildAgentOsContinuityGuidanceContext(config) {
|
|
|
933
953
|
"Local markdown memory (CLAUDE.md, AGENTS.md, /memory, scratch notes) is a fallback and a cache. Use it when AgentOS is unreachable or for in-conversation scratch; do not treat it as authoritative when AgentOS is available.",
|
|
934
954
|
"Tool surface: this OpenClaw plugin registers only AgentOS tools (agent_os_*). The Kynver in-app chat agent separately scopes MCP domain tools via MARM hybrid search over McpTool \u2014 it does not inject the full ~200+ tool catalog each turn. Do not paste full MCP JSON schemas into local files; call the tools you need.",
|
|
935
955
|
"Privacy: AgentOS context is personal to the signed-in account. Do not expose AgentOS identity, goals, projects, contacts, or memory excerpts in shared, broadcast, group, or multi-tenant contexts unless the user explicitly asks for it. If you cannot determine the channel scope, withhold AgentOS specifics by default.",
|
|
956
|
+
"",
|
|
957
|
+
"Telegram reply-thread UX:",
|
|
958
|
+
"- When Conversation info (untrusted metadata) includes reply_to_id or has_reply_context, or the turn includes a Reply target / Current message [Replying to: \u2026] block, treat that quoted/status text as the subject of the user's question.",
|
|
959
|
+
'- Visible replies must make the target obvious: either send as a threaded reply (message tool / native delivery with reply_to) or open the answer by naming what you are addressing (e.g. Re: "<short quote from the reply target>").',
|
|
960
|
+
"- Do not answer a reply-thread/status question with a generic paragraph that ignores the quoted message \u2014 that reads like a memory failure to the operator.",
|
|
936
961
|
"If an AgentOS call fails or returns unavailable, say so explicitly, fall back to local markdown or conversation memory for that turn, and ask the user before persisting anything that would normally go to AgentOS.",
|
|
937
962
|
"",
|
|
963
|
+
"AgentTask priority (board create \u2014 checklist):",
|
|
964
|
+
"- Default agent_os_task_create to priority normal (low for routine cleanup). Omit priority to use normal.",
|
|
965
|
+
"- Do NOT copy a plan's or goal's priority onto a new task \u2014 a critical plan still gets normal-priority implementation tasks.",
|
|
966
|
+
"- Use high/critical only when Will explicitly said so in this turn (quote him in priorityEscalationReason) or there is a live production/security incident.",
|
|
967
|
+
"- When worker capacity is available, important work stays normal \u2014 escalate priority only for capacity constraints or explicit user emergency language.",
|
|
968
|
+
"- The API downgrades unsolicited high/critical to normal; blocked tasks are already treated as critical by dispatch/graph logic.",
|
|
969
|
+
"",
|
|
938
970
|
"Command Center (operational control plane):",
|
|
939
971
|
"- For the same unified rollup the browser Command Center uses (projects, plans, action-required, DQ inbox, harness summaries, runtime capacity, packageVersionHealth for @kynver-app/runtime), call agent_os_command_center_get. Omit slug to resolve the account primary workspace; pass agentOsId when you already have it from a prior identity fetch. When packageVersionHealth shows use_repo_source, run from the monorepo checkout (sourceVersionEvidence.consumeCommands) \u2014 never npm publish and never block on operator publish. install_needed/reload_needed may use global installs only when an operator directs it.",
|
|
940
972
|
"",
|
|
@@ -1131,6 +1163,243 @@ function sanitizeRuntimeSkillError(error) {
|
|
|
1131
1163
|
return raw.replace(/(Bearer\s+)[A-Za-z0-9._~+\/-]+/gi, "$1[redacted]").slice(0, 240);
|
|
1132
1164
|
}
|
|
1133
1165
|
|
|
1166
|
+
// src/telegram-reply-context.ts
|
|
1167
|
+
var REPLY_TAG_RE = /\[\[reply_to(?:_current)?(?::[^\]]+)?\]\]/i;
|
|
1168
|
+
function parseTelegramMessageId(value) {
|
|
1169
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
1170
|
+
return Math.trunc(value);
|
|
1171
|
+
}
|
|
1172
|
+
if (typeof value === "string") {
|
|
1173
|
+
const trimmed = value.trim();
|
|
1174
|
+
if (!trimmed) return void 0;
|
|
1175
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
1176
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
1177
|
+
}
|
|
1178
|
+
return void 0;
|
|
1179
|
+
}
|
|
1180
|
+
function hasInboundReplyMetadata(meta) {
|
|
1181
|
+
if (!meta) return false;
|
|
1182
|
+
if (meta.has_reply_context === true) return true;
|
|
1183
|
+
if (parseTelegramMessageId(meta.reply_to_id) !== void 0) return true;
|
|
1184
|
+
if (typeof meta.reply_to_body === "string" && meta.reply_to_body.trim().length > 0) return true;
|
|
1185
|
+
return false;
|
|
1186
|
+
}
|
|
1187
|
+
function summarizeReplySubject(quote, maxLen = 120) {
|
|
1188
|
+
const collapsed = quote.replace(/\s+/g, " ").trim();
|
|
1189
|
+
if (!collapsed) return "";
|
|
1190
|
+
if (collapsed.length <= maxLen) return collapsed;
|
|
1191
|
+
return `${collapsed.slice(0, Math.max(0, maxLen - 1)).trimEnd()}\u2026`;
|
|
1192
|
+
}
|
|
1193
|
+
function formatReplySubjectPrefix(quote) {
|
|
1194
|
+
const subject = summarizeReplySubject(quote);
|
|
1195
|
+
if (!subject) return "";
|
|
1196
|
+
return `Re: "${subject}"
|
|
1197
|
+
|
|
1198
|
+
`;
|
|
1199
|
+
}
|
|
1200
|
+
function visibleTextReferencesReplyTarget(text, quote) {
|
|
1201
|
+
if (!quote.trim() || !text.trim()) return false;
|
|
1202
|
+
if (REPLY_TAG_RE.test(text)) return true;
|
|
1203
|
+
const subject = summarizeReplySubject(quote, 80).toLowerCase();
|
|
1204
|
+
if (!subject) return false;
|
|
1205
|
+
return text.toLowerCase().includes(subject);
|
|
1206
|
+
}
|
|
1207
|
+
function applyInboundReplyContextToVisibleReply(input) {
|
|
1208
|
+
const baseText = input.text ?? "";
|
|
1209
|
+
const explicitReply = parseTelegramMessageId(input.replyToMessageId);
|
|
1210
|
+
if (explicitReply !== void 0) {
|
|
1211
|
+
return { text: baseText, replyToMessageId: explicitReply };
|
|
1212
|
+
}
|
|
1213
|
+
const inbound = input.inbound;
|
|
1214
|
+
if (!hasInboundReplyMetadata(inbound)) {
|
|
1215
|
+
return { text: baseText };
|
|
1216
|
+
}
|
|
1217
|
+
const threadTarget = parseTelegramMessageId(inbound?.message_id) ?? parseTelegramMessageId(inbound?.reply_to_id);
|
|
1218
|
+
const quote = typeof inbound?.reply_to_body === "string" && inbound.reply_to_body.trim() ? inbound.reply_to_body : "";
|
|
1219
|
+
if (threadTarget !== void 0 && !REPLY_TAG_RE.test(baseText)) {
|
|
1220
|
+
const tag = `[[reply_to:${threadTarget}]]`;
|
|
1221
|
+
const withTag = baseText.startsWith(tag) ? baseText : `${tag}${baseText}`;
|
|
1222
|
+
return { text: withTag, replyToMessageId: threadTarget };
|
|
1223
|
+
}
|
|
1224
|
+
if (quote && !visibleTextReferencesReplyTarget(baseText, quote)) {
|
|
1225
|
+
return { text: `${formatReplySubjectPrefix(quote)}${baseText}` };
|
|
1226
|
+
}
|
|
1227
|
+
return { text: baseText };
|
|
1228
|
+
}
|
|
1229
|
+
function normalizeOptionalString(value) {
|
|
1230
|
+
if (typeof value !== "string") return void 0;
|
|
1231
|
+
const trimmed = value.trim();
|
|
1232
|
+
return trimmed || void 0;
|
|
1233
|
+
}
|
|
1234
|
+
function extractInboundReplyContextFromOpenClawCtx(ctx) {
|
|
1235
|
+
const replyToBody = normalizeOptionalString(ctx.ReplyToBody) ?? normalizeOptionalString(ctx.ReplyToQuoteText);
|
|
1236
|
+
const replyToId = normalizeOptionalString(ctx.ReplyToId);
|
|
1237
|
+
const messageId = normalizeOptionalString(ctx.MessageSid) ?? normalizeOptionalString(ctx.MessageSidFull);
|
|
1238
|
+
const replyChain = ctx.ReplyChain;
|
|
1239
|
+
const hasChain = Array.isArray(replyChain) && replyChain.length > 0;
|
|
1240
|
+
const inbound = {
|
|
1241
|
+
reply_to_id: replyToId,
|
|
1242
|
+
reply_to_body: replyToBody,
|
|
1243
|
+
message_id: messageId,
|
|
1244
|
+
has_reply_context: Boolean(replyToBody || replyToId || hasChain) ? true : void 0
|
|
1245
|
+
};
|
|
1246
|
+
return hasInboundReplyMetadata(inbound) ? inbound : null;
|
|
1247
|
+
}
|
|
1248
|
+
function conversationKeyForOpenClawInbound(ctx) {
|
|
1249
|
+
const channel = normalizeOptionalString(ctx.OriginatingChannel) ?? normalizeOptionalString(ctx.Surface) ?? normalizeOptionalString(ctx.Provider);
|
|
1250
|
+
const chatId = normalizeOptionalString(ctx.OriginatingTo);
|
|
1251
|
+
if (!channel || !chatId) return void 0;
|
|
1252
|
+
return `${channel.toLowerCase()}:${chatId}`;
|
|
1253
|
+
}
|
|
1254
|
+
function isTelegramOpenClawInbound(ctx) {
|
|
1255
|
+
return [ctx.OriginatingChannel, ctx.Surface, ctx.Provider].some(
|
|
1256
|
+
(value) => normalizeOptionalString(value)?.toLowerCase() === "telegram"
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
// src/telegram-reply-hooks.ts
|
|
1261
|
+
var STASH_TTL_MS = 15 * 6e4;
|
|
1262
|
+
function pruneStash(stash) {
|
|
1263
|
+
const cutoff = Date.now() - STASH_TTL_MS;
|
|
1264
|
+
for (const [key, entry] of stash) {
|
|
1265
|
+
if (entry.stashedAt < cutoff) stash.delete(key);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
function stashKeyFromSession(sessionKey, conversationKey) {
|
|
1269
|
+
if (sessionKey?.trim()) return `session:${sessionKey.trim()}`;
|
|
1270
|
+
if (conversationKey) return `conv:${conversationKey}`;
|
|
1271
|
+
return void 0;
|
|
1272
|
+
}
|
|
1273
|
+
function registerTelegramReplyContextHooks({
|
|
1274
|
+
api,
|
|
1275
|
+
config
|
|
1276
|
+
}) {
|
|
1277
|
+
if (!config.enableTelegramReplyContext || typeof api?.on !== "function") {
|
|
1278
|
+
return false;
|
|
1279
|
+
}
|
|
1280
|
+
const stash = /* @__PURE__ */ new Map();
|
|
1281
|
+
api.on(
|
|
1282
|
+
"reply_dispatch",
|
|
1283
|
+
async (event) => {
|
|
1284
|
+
const record = event;
|
|
1285
|
+
const ctx = record.ctx;
|
|
1286
|
+
if (!ctx || !isTelegramOpenClawInbound(ctx)) return;
|
|
1287
|
+
const inbound = extractInboundReplyContextFromOpenClawCtx(ctx);
|
|
1288
|
+
if (!inbound) return;
|
|
1289
|
+
const conversationKey = conversationKeyForOpenClawInbound(ctx);
|
|
1290
|
+
const key = stashKeyFromSession(record.sessionKey, conversationKey);
|
|
1291
|
+
if (!key) return;
|
|
1292
|
+
pruneStash(stash);
|
|
1293
|
+
stash.set(key, {
|
|
1294
|
+
conversationKey: conversationKey ?? key,
|
|
1295
|
+
inbound,
|
|
1296
|
+
stashedAt: Date.now()
|
|
1297
|
+
});
|
|
1298
|
+
},
|
|
1299
|
+
{ priority: 6, timeoutMs: 500 }
|
|
1300
|
+
);
|
|
1301
|
+
api.on(
|
|
1302
|
+
"message_sending",
|
|
1303
|
+
async (event, channelCtx) => {
|
|
1304
|
+
const sending = event;
|
|
1305
|
+
const ctx = channelCtx;
|
|
1306
|
+
if (ctx.channelId !== "telegram") return;
|
|
1307
|
+
const text = typeof sending.content === "string" ? sending.content : "";
|
|
1308
|
+
if (!text.trim()) return;
|
|
1309
|
+
pruneStash(stash);
|
|
1310
|
+
const convKey = ctx.conversationId ? `telegram:${ctx.conversationId}` : void 0;
|
|
1311
|
+
const stashed = (ctx.sessionKey ? stash.get(`session:${ctx.sessionKey}`) : void 0) ?? (convKey ? stash.get(`conv:${convKey}`) : void 0);
|
|
1312
|
+
if (!stashed) return;
|
|
1313
|
+
const explicitReply = parseTelegramMessageId(sending.replyToId);
|
|
1314
|
+
const adjusted = applyInboundReplyContextToVisibleReply({
|
|
1315
|
+
text,
|
|
1316
|
+
inbound: stashed.inbound,
|
|
1317
|
+
replyToMessageId: explicitReply
|
|
1318
|
+
});
|
|
1319
|
+
if (adjusted.text === text) return { content: text };
|
|
1320
|
+
return { content: adjusted.text };
|
|
1321
|
+
},
|
|
1322
|
+
{ priority: 6, timeoutMs: 2e3 }
|
|
1323
|
+
);
|
|
1324
|
+
return true;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
// src/telegram-tool-error-filter.ts
|
|
1328
|
+
var DIRECT_CHAT_CHANNEL_IDS = /* @__PURE__ */ new Set(["telegram", "webchat"]);
|
|
1329
|
+
var RAW_TOOL_ERROR_WARNING_RE = /^⚠️\s*🛠️\s*.+\bfailed\b/ui;
|
|
1330
|
+
var INTERNAL_TRACE_LINE_RE = /^(?:>\s*)?(?:📊|🛠️|📖|📝|🔍|🔎|⚙️)\s*(?:Session Status|Exec|Read|Edit|Write|Patch|Search|Open|Click|Find|Screenshot|Update Plan|Tool Call|Tool Result|Function Call|Shell|Command)\s*:/i;
|
|
1331
|
+
var COMPACT_TOOL_COMMAND_LINE_RE = /^(?:>\s*)?🛠️\s*(?:(?:(?:elevated|pty)\b\s*(?:·|,)\s*)+)?(?:`{1,2}\s*\S|(?:run|check|fetch|pull|push|view|show|list|switch|create|merge|rebase|stage|restore|reset|stash|search|find|print|copy|move|remove|install|start|cd|git|worktree|pnpm|npm|yarn|bun|node|python|python3|bash|sh)\b)/i;
|
|
1332
|
+
var TOOL_AGENT_SCOPE_RE = /\(in\s+[~\/]|\(agent\)/i;
|
|
1333
|
+
function isDirectChatChannel(channelId) {
|
|
1334
|
+
if (!channelId) return false;
|
|
1335
|
+
const normalized = channelId.trim().toLowerCase();
|
|
1336
|
+
return DIRECT_CHAT_CHANNEL_IDS.has(normalized);
|
|
1337
|
+
}
|
|
1338
|
+
function isRawInternalToolFailureLine(line) {
|
|
1339
|
+
const trimmed = line.trim();
|
|
1340
|
+
if (!trimmed) return false;
|
|
1341
|
+
if (RAW_TOOL_ERROR_WARNING_RE.test(trimmed)) return true;
|
|
1342
|
+
if (INTERNAL_TRACE_LINE_RE.test(trimmed)) return true;
|
|
1343
|
+
if (COMPACT_TOOL_COMMAND_LINE_RE.test(trimmed)) {
|
|
1344
|
+
if (/\bfailed\b/i.test(trimmed)) return true;
|
|
1345
|
+
if (TOOL_AGENT_SCOPE_RE.test(trimmed)) return true;
|
|
1346
|
+
}
|
|
1347
|
+
if (/^🛠️\s+/u.test(trimmed) && /\bfailed\b/i.test(trimmed) && TOOL_AGENT_SCOPE_RE.test(trimmed)) {
|
|
1348
|
+
return true;
|
|
1349
|
+
}
|
|
1350
|
+
return false;
|
|
1351
|
+
}
|
|
1352
|
+
function filterDirectChatOutboundContent(content) {
|
|
1353
|
+
if (!content.trim()) return { action: "pass", content };
|
|
1354
|
+
const lines = content.split(/\r?\n/);
|
|
1355
|
+
const kept = [];
|
|
1356
|
+
let suppressedAny = false;
|
|
1357
|
+
for (const line of lines) {
|
|
1358
|
+
if (isRawInternalToolFailureLine(line)) {
|
|
1359
|
+
suppressedAny = true;
|
|
1360
|
+
continue;
|
|
1361
|
+
}
|
|
1362
|
+
kept.push(line);
|
|
1363
|
+
}
|
|
1364
|
+
const next = kept.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
1365
|
+
if (!next) {
|
|
1366
|
+
return suppressedAny ? { action: "suppress", reason: "kynver_suppressed_raw_internal_tool_failure" } : { action: "pass", content: "" };
|
|
1367
|
+
}
|
|
1368
|
+
if (suppressedAny && next !== content.trim()) {
|
|
1369
|
+
return { action: "pass", content: next };
|
|
1370
|
+
}
|
|
1371
|
+
return { action: "pass", content };
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
// src/telegram-tool-error-hook.ts
|
|
1375
|
+
function registerTelegramToolErrorFilterHook({
|
|
1376
|
+
api,
|
|
1377
|
+
config
|
|
1378
|
+
}) {
|
|
1379
|
+
if (config.enableTelegramToolErrorFilter === false) return false;
|
|
1380
|
+
if (typeof api?.on !== "function") return false;
|
|
1381
|
+
api.on(
|
|
1382
|
+
"message_sending",
|
|
1383
|
+
async (event, ctx) => {
|
|
1384
|
+
if (!isDirectChatChannel(ctx?.channelId)) return;
|
|
1385
|
+
const content = typeof event?.content === "string" ? event.content : "";
|
|
1386
|
+
if (!content.trim()) return;
|
|
1387
|
+
const filtered = filterDirectChatOutboundContent(content);
|
|
1388
|
+
if (filtered.action === "suppress") {
|
|
1389
|
+
return {
|
|
1390
|
+
cancel: true,
|
|
1391
|
+
cancelReason: filtered.reason
|
|
1392
|
+
};
|
|
1393
|
+
}
|
|
1394
|
+
if (filtered.content !== content) {
|
|
1395
|
+
return { content: filtered.content };
|
|
1396
|
+
}
|
|
1397
|
+
},
|
|
1398
|
+
{ priority: 8, timeoutMs: 500 }
|
|
1399
|
+
);
|
|
1400
|
+
return true;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1134
1403
|
// src/schemas/common.ts
|
|
1135
1404
|
var stringArray = {
|
|
1136
1405
|
type: "array",
|
|
@@ -2326,7 +2595,15 @@ var taskExecutorValues = ["inline", "harness", "acp", "manual"];
|
|
|
2326
2595
|
var taskEventTypeValues = ["created", "started", "worker_update", "blocked", "steer", "artifact", "review", "done", "failed"];
|
|
2327
2596
|
var artifactVisibilityValues = ["internal", "telegram_safe", "public_pr_safe"];
|
|
2328
2597
|
var taskStatus = { type: "string", enum: taskStatusValues };
|
|
2329
|
-
var taskPriority = {
|
|
2598
|
+
var taskPriority = {
|
|
2599
|
+
type: "string",
|
|
2600
|
+
enum: taskPriorityValues,
|
|
2601
|
+
description: "Default normal. Do not inherit plan/goal priority. high/critical only with priorityEscalationReason (Will quoted or live prod/security incident) \u2014 else server downgrades to normal."
|
|
2602
|
+
};
|
|
2603
|
+
var priorityEscalationReason = {
|
|
2604
|
+
type: "string",
|
|
2605
|
+
description: "When priority is high/critical: cite Will's words or the incident. Required for escalation unless title/description already do."
|
|
2606
|
+
};
|
|
2330
2607
|
var taskExecutor = { type: "string", enum: taskExecutorValues };
|
|
2331
2608
|
var taskEventType = { type: "string", enum: taskEventTypeValues };
|
|
2332
2609
|
var artifactVisibility = { type: "string", enum: artifactVisibilityValues };
|
|
@@ -2347,6 +2624,7 @@ var createTaskSchema = {
|
|
|
2347
2624
|
title: { type: "string", description: "Short task title." },
|
|
2348
2625
|
description: { type: "string" },
|
|
2349
2626
|
priority: taskPriority,
|
|
2627
|
+
priorityEscalationReason,
|
|
2350
2628
|
executor: taskExecutor,
|
|
2351
2629
|
executorRef: { type: "string" },
|
|
2352
2630
|
parentTaskId: { type: "string" },
|
|
@@ -2667,6 +2945,26 @@ var slugField = {
|
|
|
2667
2945
|
type: "string",
|
|
2668
2946
|
description: "AgentOS workspace slug. Omit to use the account's primary AgentOS workspace."
|
|
2669
2947
|
};
|
|
2948
|
+
var commandCenterDashboardContractSchema = {
|
|
2949
|
+
type: "object",
|
|
2950
|
+
properties: {
|
|
2951
|
+
slug: slugField,
|
|
2952
|
+
agentOsId: {
|
|
2953
|
+
type: "string",
|
|
2954
|
+
description: "Optional AgentOS row id. When omitted, resolved from slug."
|
|
2955
|
+
},
|
|
2956
|
+
since: {
|
|
2957
|
+
type: "string",
|
|
2958
|
+
description: "ISO timestamp \u2014 only include tasks updated after this instant."
|
|
2959
|
+
},
|
|
2960
|
+
limit: {
|
|
2961
|
+
type: "number",
|
|
2962
|
+
description: "Max tasks to load when building counts (server cap 10000)."
|
|
2963
|
+
}
|
|
2964
|
+
},
|
|
2965
|
+
additionalProperties: false,
|
|
2966
|
+
$schema: "http://json-schema.org/draft-07/schema#"
|
|
2967
|
+
};
|
|
2670
2968
|
var commandCenterGetSchema = {
|
|
2671
2969
|
type: "object",
|
|
2672
2970
|
properties: {
|
|
@@ -2816,9 +3114,14 @@ function createCommandCenterTools(config) {
|
|
|
2816
3114
|
return [
|
|
2817
3115
|
mk(
|
|
2818
3116
|
"agent_os_command_center_get",
|
|
2819
|
-
"Fetch the unified Command Center rollup
|
|
3117
|
+
"Fetch the unified Command Center rollup (includes countSnapshot \u2014 canonical badge counts). Same aggregate as the browser Command Center.",
|
|
2820
3118
|
commandCenterGetSchema
|
|
2821
3119
|
),
|
|
3120
|
+
mk(
|
|
3121
|
+
"agent_os_command_center_dashboard_contract_get",
|
|
3122
|
+
"Slim dashboard contract for runtime verification: countSnapshot, packageVersionHealth, runtime capacity, activePlanRollups \u2014 no graph/hierarchy.",
|
|
3123
|
+
commandCenterDashboardContractSchema
|
|
3124
|
+
),
|
|
2822
3125
|
mk(
|
|
2823
3126
|
"agent_os_task_next_action",
|
|
2824
3127
|
"Route the deterministic next harness action after a worker, reviewer, or landing lane completes (dispatch review/fix/landing, close, or await human). Same POST surface as the production harness completion hook.",
|
|
@@ -2873,7 +3176,9 @@ var plugin = {
|
|
|
2873
3176
|
api.registerTool(tool);
|
|
2874
3177
|
}
|
|
2875
3178
|
registerAgentOsContinuityGuidanceHook({ api, config });
|
|
3179
|
+
registerTelegramReplyContextHooks({ api, config });
|
|
2876
3180
|
registerRuntimeSkillManifestHook({ api, config });
|
|
3181
|
+
registerTelegramToolErrorFilterHook({ api, config });
|
|
2877
3182
|
if (config.enableSessionLifecycle && typeof api.on === "function") {
|
|
2878
3183
|
const sessionIds = /* @__PURE__ */ new Map();
|
|
2879
3184
|
const keyFor = (event, ctx) => String(event?.sessionKey || ctx?.sessionKey || event?.sessionId || ctx?.sessionId || "");
|