@integrity-labs/agt-cli 0.28.153 → 0.28.155

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.
@@ -14035,6 +14035,54 @@ function emitPreambleStripTelemetry(channel, shape) {
14035
14035
  }
14036
14036
  }
14037
14037
 
14038
+ // src/transient-api-error.ts
14039
+ var CODE_KIND = {
14040
+ "429": "rate_limit",
14041
+ "500": "server_error",
14042
+ "503": "unavailable",
14043
+ "529": "overloaded"
14044
+ };
14045
+ var FRIENDLY_TRANSIENT_MESSAGE = "Sorry, I hit a brief technical hiccup just now and couldn't finish that. Please give me a moment and try again shortly.";
14046
+ function detectTransientApiError(text) {
14047
+ if (!text) return null;
14048
+ const head = text.replace(/^\s+/, "").slice(0, 200);
14049
+ const code = head.match(/^api error:\s*(\d{3})\b/i)?.[1] ?? head.match(
14050
+ /^(\d{3})\s+(?:overloaded|service unavailable|internal server error|too many requests|server error)\b/i
14051
+ )?.[1];
14052
+ if (code) {
14053
+ const kind = CODE_KIND[code];
14054
+ if (kind) return { code, kind };
14055
+ }
14056
+ const typeToken = head.match(/^[^a-z0-9]*(overloaded_error|rate_limit_error)\b/i)?.[1];
14057
+ if (typeToken) {
14058
+ return typeToken.toLowerCase() === "overloaded_error" ? { code: "529", kind: "overloaded" } : { code: "429", kind: "rate_limit" };
14059
+ }
14060
+ return null;
14061
+ }
14062
+ function rewriteTransientApiError(text) {
14063
+ const match = detectTransientApiError(text);
14064
+ if (!match) return { text, rewritten: false, original: null, match: null };
14065
+ return { text: FRIENDLY_TRANSIENT_MESSAGE, rewritten: true, original: text, match };
14066
+ }
14067
+ function emitTransientApiErrorTelemetry(channel, match, original) {
14068
+ if (!match) return;
14069
+ const agentCode = process.env.AGT_AGENT_CODE_NAME ?? "unknown";
14070
+ try {
14071
+ process.stderr.write(
14072
+ `agt.egress.transient_api_error ${JSON.stringify({
14073
+ channel,
14074
+ agent_code: agentCode,
14075
+ code: match.code,
14076
+ kind: match.kind,
14077
+ // Raw error kept for operators (truncated); never shown to the end user.
14078
+ raw: (original ?? "").replace(/\s+/g, " ").trim().slice(0, 300)
14079
+ })}
14080
+ `
14081
+ );
14082
+ } catch {
14083
+ }
14084
+ }
14085
+
14038
14086
  // src/direct-chat-claim-tracker.ts
14039
14087
  var DirectChatClaimTracker = class {
14040
14088
  bySession = /* @__PURE__ */ new Map();
@@ -14528,7 +14576,9 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
14528
14576
  const { session_id, content: rawContent } = args;
14529
14577
  const sanitizedReply = stripRepostPreambleWithMeta(rawContent);
14530
14578
  if (sanitizedReply.stripped) emitPreambleStripTelemetry("direct_chat", sanitizedReply.shape);
14531
- const content = sanitizedReply.text;
14579
+ const apiErr = rewriteTransientApiError(sanitizedReply.text);
14580
+ if (apiErr.rewritten) emitTransientApiErrorTelemetry("direct_chat", apiErr.match, apiErr.original);
14581
+ const content = apiErr.text;
14532
14582
  const message_ids = claimTracker.peek(session_id);
14533
14583
  const streamEnabled = resolveHostBooleanFlag({
14534
14584
  key: "direct-chat-stream-reply",
@@ -15325,6 +15325,54 @@ function emitPreambleStripTelemetry(channel, shape) {
15325
15325
  }
15326
15326
  }
15327
15327
 
15328
+ // src/transient-api-error.ts
15329
+ var CODE_KIND = {
15330
+ "429": "rate_limit",
15331
+ "500": "server_error",
15332
+ "503": "unavailable",
15333
+ "529": "overloaded"
15334
+ };
15335
+ var FRIENDLY_TRANSIENT_MESSAGE = "Sorry, I hit a brief technical hiccup just now and couldn't finish that. Please give me a moment and try again shortly.";
15336
+ function detectTransientApiError(text) {
15337
+ if (!text) return null;
15338
+ const head = text.replace(/^\s+/, "").slice(0, 200);
15339
+ const code = head.match(/^api error:\s*(\d{3})\b/i)?.[1] ?? head.match(
15340
+ /^(\d{3})\s+(?:overloaded|service unavailable|internal server error|too many requests|server error)\b/i
15341
+ )?.[1];
15342
+ if (code) {
15343
+ const kind = CODE_KIND[code];
15344
+ if (kind) return { code, kind };
15345
+ }
15346
+ const typeToken = head.match(/^[^a-z0-9]*(overloaded_error|rate_limit_error)\b/i)?.[1];
15347
+ if (typeToken) {
15348
+ return typeToken.toLowerCase() === "overloaded_error" ? { code: "529", kind: "overloaded" } : { code: "429", kind: "rate_limit" };
15349
+ }
15350
+ return null;
15351
+ }
15352
+ function rewriteTransientApiError(text) {
15353
+ const match = detectTransientApiError(text);
15354
+ if (!match) return { text, rewritten: false, original: null, match: null };
15355
+ return { text: FRIENDLY_TRANSIENT_MESSAGE, rewritten: true, original: text, match };
15356
+ }
15357
+ function emitTransientApiErrorTelemetry(channel, match, original) {
15358
+ if (!match) return;
15359
+ const agentCode = process.env.AGT_AGENT_CODE_NAME ?? "unknown";
15360
+ try {
15361
+ process.stderr.write(
15362
+ `agt.egress.transient_api_error ${JSON.stringify({
15363
+ channel,
15364
+ agent_code: agentCode,
15365
+ code: match.code,
15366
+ kind: match.kind,
15367
+ // Raw error kept for operators (truncated); never shown to the end user.
15368
+ raw: (original ?? "").replace(/\s+/g, " ").trim().slice(0, 300)
15369
+ })}
15370
+ `
15371
+ );
15372
+ } catch {
15373
+ }
15374
+ }
15375
+
15328
15376
  // src/slack-pending-inbound-cleanup.ts
15329
15377
  import { existsSync as existsSync3, readdirSync as readdirSync2, statSync, unlinkSync } from "fs";
15330
15378
  import { join as join5 } from "path";
@@ -17534,7 +17582,9 @@ async function processSlackRecoveryOutboxFile(filename) {
17534
17582
  }
17535
17583
  const recovered = stripRepostPreambleWithMeta(payload.text);
17536
17584
  if (recovered.stripped) emitPreambleStripTelemetry("slack", recovered.shape);
17537
- const text = recovered.text;
17585
+ const apiErr = rewriteTransientApiError(recovered.text);
17586
+ if (apiErr.rewritten) emitTransientApiErrorTelemetry("slack", apiErr.match, apiErr.original);
17587
+ const text = apiErr.text;
17538
17588
  let sendSucceeded = false;
17539
17589
  const controller = new AbortController();
17540
17590
  const timeoutId = setTimeout(() => controller.abort(), 15e3);
@@ -19358,6 +19408,8 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
19358
19408
  };
19359
19409
  const sanitized = stripRepostPreambleWithMeta(text);
19360
19410
  if (sanitized.stripped) emitPreambleStripTelemetry("slack", sanitized.shape);
19411
+ const apiErr = rewriteTransientApiError(sanitized.text);
19412
+ if (apiErr.rewritten) emitTransientApiErrorTelemetry("slack", apiErr.match, apiErr.original);
19361
19413
  try {
19362
19414
  const res = await fetch("https://slack.com/api/chat.postMessage", {
19363
19415
  method: "POST",
@@ -19367,7 +19419,7 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
19367
19419
  },
19368
19420
  body: JSON.stringify({
19369
19421
  channel,
19370
- text: sanitized.text,
19422
+ text: apiErr.text,
19371
19423
  ...effectiveThreadTs ? { thread_ts: effectiveThreadTs } : {},
19372
19424
  ...buildAugmentedSlackMetadata() ? { metadata: buildAugmentedSlackMetadata() } : {}
19373
19425
  // ↑ Labels this message as Augmented-agent-originated so peer agents
@@ -14094,6 +14094,54 @@ function emitPreambleStripTelemetry(channel, shape) {
14094
14094
  }
14095
14095
  }
14096
14096
 
14097
+ // src/transient-api-error.ts
14098
+ var CODE_KIND = {
14099
+ "429": "rate_limit",
14100
+ "500": "server_error",
14101
+ "503": "unavailable",
14102
+ "529": "overloaded"
14103
+ };
14104
+ var FRIENDLY_TRANSIENT_MESSAGE = "Sorry, I hit a brief technical hiccup just now and couldn't finish that. Please give me a moment and try again shortly.";
14105
+ function detectTransientApiError(text) {
14106
+ if (!text) return null;
14107
+ const head = text.replace(/^\s+/, "").slice(0, 200);
14108
+ const code = head.match(/^api error:\s*(\d{3})\b/i)?.[1] ?? head.match(
14109
+ /^(\d{3})\s+(?:overloaded|service unavailable|internal server error|too many requests|server error)\b/i
14110
+ )?.[1];
14111
+ if (code) {
14112
+ const kind = CODE_KIND[code];
14113
+ if (kind) return { code, kind };
14114
+ }
14115
+ const typeToken = head.match(/^[^a-z0-9]*(overloaded_error|rate_limit_error)\b/i)?.[1];
14116
+ if (typeToken) {
14117
+ return typeToken.toLowerCase() === "overloaded_error" ? { code: "529", kind: "overloaded" } : { code: "429", kind: "rate_limit" };
14118
+ }
14119
+ return null;
14120
+ }
14121
+ function rewriteTransientApiError(text) {
14122
+ const match = detectTransientApiError(text);
14123
+ if (!match) return { text, rewritten: false, original: null, match: null };
14124
+ return { text: FRIENDLY_TRANSIENT_MESSAGE, rewritten: true, original: text, match };
14125
+ }
14126
+ function emitTransientApiErrorTelemetry(channel, match, original) {
14127
+ if (!match) return;
14128
+ const agentCode = process.env.AGT_AGENT_CODE_NAME ?? "unknown";
14129
+ try {
14130
+ process.stderr.write(
14131
+ `agt.egress.transient_api_error ${JSON.stringify({
14132
+ channel,
14133
+ agent_code: agentCode,
14134
+ code: match.code,
14135
+ kind: match.kind,
14136
+ // Raw error kept for operators (truncated); never shown to the end user.
14137
+ raw: (original ?? "").replace(/\s+/g, " ").trim().slice(0, 300)
14138
+ })}
14139
+ `
14140
+ );
14141
+ } catch {
14142
+ }
14143
+ }
14144
+
14097
14145
  // src/msteams-inbound-puller.ts
14098
14146
  import { existsSync, mkdirSync, readdirSync, utimesSync, writeFileSync } from "fs";
14099
14147
  import { join } from "path";
@@ -15465,10 +15513,12 @@ async function handleReply(args) {
15465
15513
  }
15466
15514
  const sanitized = stripRepostPreambleWithMeta(text);
15467
15515
  if (sanitized.stripped) emitPreambleStripTelemetry("teams", sanitized.shape);
15516
+ const apiErr = rewriteTransientApiError(sanitized.text);
15517
+ if (apiErr.rewritten) emitTransientApiErrorTelemetry("teams", apiErr.match, apiErr.original);
15468
15518
  try {
15469
15519
  const result = await sendActivity(serviceUrl, conversationId, {
15470
15520
  type: "message",
15471
- text: sanitized.text,
15521
+ text: apiErr.text,
15472
15522
  textFormat: "markdown",
15473
15523
  ...replyToId ? { replyToId } : {}
15474
15524
  });
@@ -16026,10 +16076,12 @@ async function processRecoveryFile(filename) {
16026
16076
  }
16027
16077
  const recovered = stripRepostPreambleWithMeta(payload.text);
16028
16078
  if (recovered.stripped) emitPreambleStripTelemetry("teams", recovered.shape);
16079
+ const apiErr = rewriteTransientApiError(recovered.text);
16080
+ if (apiErr.rewritten) emitTransientApiErrorTelemetry("teams", apiErr.match, apiErr.original);
16029
16081
  try {
16030
16082
  await sendActivity(payload.service_url, payload.conversation_id, {
16031
16083
  type: "message",
16032
- text: recovered.text,
16084
+ text: apiErr.text,
16033
16085
  ...payload.reply_to_id ? { replyToId: payload.reply_to_id } : {}
16034
16086
  });
16035
16087
  try {
@@ -16395,6 +16395,54 @@ function emitPreambleStripTelemetry(channel, shape) {
16395
16395
  }
16396
16396
  }
16397
16397
 
16398
+ // src/transient-api-error.ts
16399
+ var CODE_KIND = {
16400
+ "429": "rate_limit",
16401
+ "500": "server_error",
16402
+ "503": "unavailable",
16403
+ "529": "overloaded"
16404
+ };
16405
+ var FRIENDLY_TRANSIENT_MESSAGE = "Sorry, I hit a brief technical hiccup just now and couldn't finish that. Please give me a moment and try again shortly.";
16406
+ function detectTransientApiError(text) {
16407
+ if (!text) return null;
16408
+ const head = text.replace(/^\s+/, "").slice(0, 200);
16409
+ const code = head.match(/^api error:\s*(\d{3})\b/i)?.[1] ?? head.match(
16410
+ /^(\d{3})\s+(?:overloaded|service unavailable|internal server error|too many requests|server error)\b/i
16411
+ )?.[1];
16412
+ if (code) {
16413
+ const kind = CODE_KIND[code];
16414
+ if (kind) return { code, kind };
16415
+ }
16416
+ const typeToken = head.match(/^[^a-z0-9]*(overloaded_error|rate_limit_error)\b/i)?.[1];
16417
+ if (typeToken) {
16418
+ return typeToken.toLowerCase() === "overloaded_error" ? { code: "529", kind: "overloaded" } : { code: "429", kind: "rate_limit" };
16419
+ }
16420
+ return null;
16421
+ }
16422
+ function rewriteTransientApiError(text) {
16423
+ const match = detectTransientApiError(text);
16424
+ if (!match) return { text, rewritten: false, original: null, match: null };
16425
+ return { text: FRIENDLY_TRANSIENT_MESSAGE, rewritten: true, original: text, match };
16426
+ }
16427
+ function emitTransientApiErrorTelemetry(channel, match, original) {
16428
+ if (!match) return;
16429
+ const agentCode = process.env.AGT_AGENT_CODE_NAME ?? "unknown";
16430
+ try {
16431
+ process.stderr.write(
16432
+ `agt.egress.transient_api_error ${JSON.stringify({
16433
+ channel,
16434
+ agent_code: agentCode,
16435
+ code: match.code,
16436
+ kind: match.kind,
16437
+ // Raw error kept for operators (truncated); never shown to the end user.
16438
+ raw: (original ?? "").replace(/\s+/g, " ").trim().slice(0, 300)
16439
+ })}
16440
+ `
16441
+ );
16442
+ } catch {
16443
+ }
16444
+ }
16445
+
16398
16446
  // src/telegram-pending-inbound-cleanup.ts
16399
16447
  import { readdirSync, readFileSync as readFileSync7, statSync } from "fs";
16400
16448
  import { join as join5 } from "path";
@@ -18093,7 +18141,9 @@ async function processRecoveryOutboxFile(filename) {
18093
18141
  }
18094
18142
  const recovered = stripRepostPreambleWithMeta(payload.text);
18095
18143
  if (recovered.stripped) emitPreambleStripTelemetry("telegram", recovered.shape);
18096
- const text = recovered.text;
18144
+ const apiErr = rewriteTransientApiError(recovered.text);
18145
+ if (apiErr.rewritten) emitTransientApiErrorTelemetry("telegram", apiErr.match, apiErr.original);
18146
+ const text = apiErr.text;
18097
18147
  const body = {
18098
18148
  chat_id: payload.chat_id,
18099
18149
  text,
@@ -18791,6 +18841,8 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
18791
18841
  }
18792
18842
  const tgSanitized = stripRepostPreambleWithMeta(text);
18793
18843
  if (tgSanitized.stripped) emitPreambleStripTelemetry("telegram", tgSanitized.shape);
18844
+ const tgApiErr = rewriteTransientApiError(tgSanitized.text);
18845
+ if (tgApiErr.rewritten) emitTransientApiErrorTelemetry("telegram", tgApiErr.match, tgApiErr.original);
18794
18846
  const isPrivateChat = !chat_id.startsWith("-");
18795
18847
  const tgThrottleCfg = isPrivateChat ? relaxedThrottleConfig(configFromEnv()) : configFromEnv();
18796
18848
  const tgThrottleNow = Date.now();
@@ -18826,8 +18878,9 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
18826
18878
  void deliverQueuedReply({
18827
18879
  chatId: chat_id,
18828
18880
  // ENG-6794: deliver the pre-sanitized text (preamble already stripped
18829
- // and counted above, before the throttle decision).
18830
- text: tgSanitized.text,
18881
+ // and counted above, before the throttle decision). ENG-6861: and with
18882
+ // any raw transient API error already softened to a friendly line.
18883
+ text: tgApiErr.text,
18831
18884
  replyToMessageId: reply_to_message_id,
18832
18885
  isReplyTool: name === "telegram.reply",
18833
18886
  throttleCfg: tgThrottleCfg
@@ -18844,7 +18897,7 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
18844
18897
  };
18845
18898
  }
18846
18899
  try {
18847
- const body = { chat_id, text: tgSanitized.text };
18900
+ const body = { chat_id, text: tgApiErr.text };
18848
18901
  if (reply_to_message_id) body.reply_to_message_id = Number(reply_to_message_id);
18849
18902
  const drainCutoffMs = Date.now();
18850
18903
  const data = await telegramApiCall("sendMessage", body, 15e3);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.28.153",
3
+ "version": "0.28.155",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {