@chibitek/chibi 0.1.160 → 0.1.161

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.
Files changed (73) hide show
  1. package/dist/assets/{abnfDiagram-O67JEVCF-CpuRvzQ3.js → abnfDiagram-O67JEVCF-Bb-Unz3V.js} +1 -1
  2. package/dist/assets/{arc-ko1e0R6h.js → arc-HBMH7B4K.js} +1 -1
  3. package/dist/assets/{architectureDiagram-NJMV4G6O-OZ3SsOOa.js → architectureDiagram-NJMV4G6O-CYwkb2PE.js} +1 -1
  4. package/dist/assets/{blockDiagram-BEXU5L5S-DLRkBkjs.js → blockDiagram-BEXU5L5S-DPYYNxBH.js} +1 -1
  5. package/dist/assets/{c4Diagram-YGBWAQC7-e8Q3qMnw.js → c4Diagram-YGBWAQC7-DZ9hKDlA.js} +1 -1
  6. package/dist/assets/channel-Nx85fHZ4.js +1 -0
  7. package/dist/assets/{chunk-2Q5K7J3B-hCDqaM4Q.js → chunk-2Q5K7J3B-OKrUlts6.js} +1 -1
  8. package/dist/assets/{chunk-3FUC2YCW-Dy3Pahu-.js → chunk-3FUC2YCW-Tuur0lqz.js} +2 -2
  9. package/dist/assets/{chunk-5VM5RSS4-QMK3iFBF.js → chunk-5VM5RSS4-BL8QOZeP.js} +1 -1
  10. package/dist/assets/{chunk-GTNCS2PH-6fyp9ERp.js → chunk-GTNCS2PH-DMi8-ixt.js} +1 -1
  11. package/dist/assets/{chunk-GWA4HPMP-DWvOhTaO.js → chunk-GWA4HPMP-Dd7yNJ0G.js} +1 -1
  12. package/dist/assets/{chunk-JWPE2WC7-DgohMW2S.js → chunk-JWPE2WC7-g2dOoIMX.js} +1 -1
  13. package/dist/assets/{chunk-NETBCI7D-sRGeD2Y7.js → chunk-NETBCI7D-Cum7feOh.js} +1 -1
  14. package/dist/assets/{chunk-WEXAMYUT-CZslD_VF.js → chunk-WEXAMYUT-BzCC1jc4.js} +1 -1
  15. package/dist/assets/{chunk-XXDRQBXY-D7ocO3VN.js → chunk-XXDRQBXY-Ck63jUMo.js} +1 -1
  16. package/dist/assets/{classDiagram-v2-NBCMYWYE-T1lLqHHW.js → classDiagram-v2-NBCMYWYE-DFSuRVMZ.js} +1 -1
  17. package/dist/assets/{cose-bilkent-JH36ORCC-BdeLiJr3.js → cose-bilkent-JH36ORCC-CegRj_kY.js} +1 -1
  18. package/dist/assets/{cynefin-OW5HDTMX-BydCA0pv.js → cynefin-OW5HDTMX-cZS_kt1A.js} +1 -1
  19. package/dist/assets/{cynefinDiagram-VND7K2PF-DBxckjwQ.js → cynefinDiagram-VND7K2PF-DfQa9Rht.js} +1 -1
  20. package/dist/assets/{dagre-6A5THRUB-CAsvq6Zk.js → dagre-6A5THRUB-DJ9qftJu.js} +1 -1
  21. package/dist/assets/{diagram-22UHCM2B-DTwH3rA_.js → diagram-22UHCM2B-KXUGUahJ.js} +1 -1
  22. package/dist/assets/{diagram-3UASUU5V-BNYj1bey.js → diagram-3UASUU5V-BudCYrCp.js} +1 -1
  23. package/dist/assets/{diagram-ATOU4E4O-CihwYFxb.js → diagram-ATOU4E4O-Du2O03NS.js} +1 -1
  24. package/dist/assets/{diagram-CDSNMT55-nouwk3s2.js → diagram-CDSNMT55-DXybXGYf.js} +1 -1
  25. package/dist/assets/{diagram-MLGK6HIB-BoKewJeA.js → diagram-MLGK6HIB-DfrknXGE.js} +1 -1
  26. package/dist/assets/{diagram-MPIPVDR6-CrE1m9DQ.js → diagram-MPIPVDR6-C29FmaJm.js} +1 -1
  27. package/dist/assets/{ebnfDiagram-ZINNZB2B-DRj0aU4Y.js → ebnfDiagram-ZINNZB2B-BF9wS0Nz.js} +1 -1
  28. package/dist/assets/{elk-276RUBZZ-Do0JzCG5.js → elk-276RUBZZ-B2Fah1VF.js} +1 -1
  29. package/dist/assets/{erDiagram-OPXOYQCR-CRsI9pXb.js → erDiagram-OPXOYQCR-Di3q4bpF.js} +1 -1
  30. package/dist/assets/{flowDiagram-KWPJA3E3-dtD6wm3G.js → flowDiagram-KWPJA3E3-D1UiqwbF.js} +1 -1
  31. package/dist/assets/{ganttDiagram-FUAMR5RP-Cn7KyLCo.js → ganttDiagram-FUAMR5RP-BjZqMt7o.js} +1 -1
  32. package/dist/assets/{gitGraphDiagram-X574FWY7-CGH_VWzq.js → gitGraphDiagram-X574FWY7-DiZtdip7.js} +1 -1
  33. package/dist/assets/{index-BIcziktH.js → index-XFwW09vd.js} +3 -3
  34. package/dist/assets/{index-Bk8iAodB.js → index-dbQveHan.js} +1 -1
  35. package/dist/assets/{infoDiagram-VRGFBTTK-CQKsYTCL.js → infoDiagram-VRGFBTTK-BJUJCgio.js} +1 -1
  36. package/dist/assets/{ishikawaDiagram-OU5B5YK6-D5catDe0.js → ishikawaDiagram-OU5B5YK6-BX0XdHUx.js} +1 -1
  37. package/dist/assets/{journeyDiagram-ZHPQQLJL-KjY8mki9.js → journeyDiagram-ZHPQQLJL-Bg904IIx.js} +1 -1
  38. package/dist/assets/{kanban-definition-PNTS6WVX-BKCyJtge.js → kanban-definition-PNTS6WVX-hkZMFMHZ.js} +1 -1
  39. package/dist/assets/{linear-B-_obUkq.js → linear-Bh29RTbQ.js} +1 -1
  40. package/dist/assets/{mermaid.core-DlSzuDKt.js → mermaid.core-aqB1jW_w.js} +5 -5
  41. package/dist/assets/{mindmap-definition-NLK3R4M7-BFQSaYKh.js → mindmap-definition-NLK3R4M7-D5GMV-Zd.js} +1 -1
  42. package/dist/assets/{pegDiagram-GJSIUBJH-l51izlev.js → pegDiagram-GJSIUBJH-7_wFtkFH.js} +1 -1
  43. package/dist/assets/{pieDiagram-5QR66LMP-6NEXRoZX.js → pieDiagram-5QR66LMP-DXtZBQ4f.js} +1 -1
  44. package/dist/assets/{quadrantDiagram-O4NWA36T-BCC9XlOe.js → quadrantDiagram-O4NWA36T-C1v3ydTF.js} +1 -1
  45. package/dist/assets/{railroadDiagram-XR7U4H2S-Dd4TmJ86.js → railroadDiagram-XR7U4H2S-CLmhiOXg.js} +1 -1
  46. package/dist/assets/{requirementDiagram-PLB6GJNP-C1E5DaDb.js → requirementDiagram-PLB6GJNP-BKxI2rh_.js} +1 -1
  47. package/dist/assets/{sankeyDiagram-IPEJSGJF-Ci6r7abb.js → sankeyDiagram-IPEJSGJF-gKK-Qs7b.js} +1 -1
  48. package/dist/assets/{sequenceDiagram-PO4LG4MO-BJ-I6WOh.js → sequenceDiagram-PO4LG4MO-BT94Uowp.js} +1 -1
  49. package/dist/assets/{sizeCapture-INFHLROL-Cs5QbLOP.js → sizeCapture-INFHLROL-RDJL6sCM.js} +1 -1
  50. package/dist/assets/{stateDiagram-v2-GCMORJYK-Bw--rdvq.js → stateDiagram-v2-GCMORJYK-DqHMzv-J.js} +1 -1
  51. package/dist/assets/{swimlanes-2SLR337P-B1O9IEz5.js → swimlanes-2SLR337P-B-NN0ql6.js} +1 -1
  52. package/dist/assets/swimlanesDiagram-TC7HE7FX-BO2gR34z.js +8 -0
  53. package/dist/assets/{timeline-definition-EJHVYXUP-CTZ7DXaw.js → timeline-definition-EJHVYXUP-C51S9tpN.js} +1 -1
  54. package/dist/assets/{usecaseDiagram-POWQR4AR-DjwgNG0H.js → usecaseDiagram-POWQR4AR-DyfNMmhq.js} +1 -1
  55. package/dist/assets/{vennDiagram-UO4OBE2U-DrdJG55h.js → vennDiagram-UO4OBE2U-D924r33S.js} +1 -1
  56. package/dist/assets/{wardleyDiagram-VNRHLVJA-HVq776nz.js → wardleyDiagram-VNRHLVJA-DXSfsjUr.js} +1 -1
  57. package/dist/assets/{xychartDiagram-PMCCYNJV-DPf9VEua.js → xychartDiagram-PMCCYNJV-mYX9tnBU.js} +1 -1
  58. package/dist/index.html +1 -1
  59. package/dist-server/index.js +26 -6
  60. package/dist-server/openmausbot.js +24 -3
  61. package/dist-server/pair-cli.js +24 -3
  62. package/dist-server/server/checkpoint-recovery.js +18 -0
  63. package/dist-server/server/drivers/acp/core.js +17 -17
  64. package/dist-server/server/engine-failover.js +4 -4
  65. package/dist-server/server/index.js +5 -6
  66. package/package.json +1 -1
  67. package/dist/assets/channel-Lp7erhx-.js +0 -1
  68. package/dist/assets/swimlanesDiagram-TC7HE7FX-C6wGgYKP.js +0 -8
  69. package/dist-server/connector-proxy.js +0 -205
  70. package/dist-server/server/composio.js +0 -1051
  71. package/dist-server/server/connector-proxy.js +0 -249
  72. package/dist-server/server/mcp-public-registry.js +0 -325
  73. package/dist-server/shared/connector-availability.js +0 -12
@@ -48,6 +48,7 @@ import { commandSummary, toolDetailPreview } from "../../tool-summary.js";
48
48
  import { extractMcpImages } from "../../mcp-tool-images.js";
49
49
  import { mcpToolRefFromLabel } from "../../../shared/mcp-tool-ref.js";
50
50
  import { redactSecretsInText } from "../../redact.js";
51
+ import { isBrokenAntigravityCheckpoint, isAntigravityCheckpointReply } from "../../checkpoint-recovery.js";
51
52
  import { recoveryPromptFor } from "../../resume-recovery.js";
52
53
  import { isModelRejection } from "../retry.js";
53
54
  import { engineFailureFromCode, isCredentialDead, isOpaqueRequestRejection, logAuthFailure, parseResetAt, resetHintFromData } from "../../engine-failure.js";
@@ -464,14 +465,15 @@ export function createAcpDriver(support) {
464
465
  // turn synchronously must find this session free
465
466
  session.current = null;
466
467
  active.delete(threadId);
468
+ if (isAntigravityCheckpointReply(DRIVER_KIND, current.state.text)) {
469
+ ok = false;
470
+ stopReason = "invalid_checkpoint";
471
+ emit({ ...base(threadId, current.turnId), type: "runtime.error", message: current.state.text.trim() });
472
+ closeSession(threadId, "invalid-checkpoint");
473
+ }
467
474
  current.flushAssistantText();
468
- // `end_turn` with nothing to show for it — no reply, no image, no
469
- // tool result — is a lost turn, not a success. An engine can report
470
- // exactly that (a provider may cut a reasoning-only stream and
471
- // still answer end_turn), and ok:true would end the thread quietly
472
- // while the person's message went unanswered. Keep the completion,
473
- // but report it as a failure so terminal chips, incidents and
474
- // follow-ups see what happened.
475
+ // A successful end_turn without a reply or tool result is a lost
476
+ // turn. Report failure so terminal chips and follow-ups reflect it.
475
477
  let finalOk = ok;
476
478
  let finalStopReason = stopReason;
477
479
  if (finalOk && finalStopReason === null && !current.state.producedItem) {
@@ -1467,7 +1469,9 @@ export function createAcpDriver(support) {
1467
1469
  type: "runtime.error",
1468
1470
  message: errorMessage,
1469
1471
  });
1470
- settle(threadId, session, false, reason ?? "failed");
1472
+ if (isBrokenAntigravityCheckpoint(DRIVER_KIND, errorMessage))
1473
+ closeSession(threadId, "invalid-checkpoint");
1474
+ settle(threadId, session, false, isBrokenAntigravityCheckpoint(DRIVER_KIND, errorMessage) ? "invalid_checkpoint" : reason ?? "failed");
1471
1475
  }
1472
1476
  }
1473
1477
  catch (e) {
@@ -1492,18 +1496,14 @@ export function createAcpDriver(support) {
1492
1496
  ...(needsAuth ? { setup: true } : {}),
1493
1497
  ...(failure ? { failure } : {}),
1494
1498
  });
1495
- // Internal RPC failures can leave a live child poisoned just
1496
- // like a silent prompt. Evict before completion listeners can
1497
- // start the next turn. Never replay this accepted prompt: it
1498
- // may already have executed tools. The next explicit turn can
1499
- // resume the recorded session on a fresh process.
1500
- // An agent refused by its provider mid-prompt is still running
1501
- // (retrying on its own): it goes too.
1502
- if ((logAuth || (!needsAuth && (stalled || e?.acpSessionFailure === true
1499
+ // Evict unusable sessions without replaying accepted prompts.
1500
+ // The harness invalidates broken checkpoints durably so the
1501
+ // next explicit turn rebuilds from the retained transcript.
1502
+ if ((logAuth || (!needsAuth && (stalled || isBrokenAntigravityCheckpoint(DRIVER_KIND, message) || e?.acpSessionFailure === true
1503
1503
  || code === "upstream_outage"))) && session.child.exitCode === null && !session.closing) {
1504
1504
  closeSession(threadId, logAuth ? "provider-auth" : stalled ? "prompt-stall" : "rpc-failure");
1505
1505
  }
1506
- settle(threadId, session, false, needsAuth ? "auth_required" : "rpc_error");
1506
+ settle(threadId, session, false, needsAuth ? "auth_required" : isBrokenAntigravityCheckpoint(DRIVER_KIND, message) ? "invalid_checkpoint" : "rpc_error");
1507
1507
  }
1508
1508
  }
1509
1509
  })();
@@ -49,10 +49,10 @@ export const NO_ANSWER_FAILURE = "The engine ended the turn without an answer.";
49
49
  function unrecognisedFailure(turn) {
50
50
  return { kind: "provider_error", message: turn.lastError ?? NO_ANSWER_FAILURE };
51
51
  }
52
- /** Ways a turn ends failed that are not the engine's fault: the person (or
53
- * the harness on their behalf) stopped it. Every other failed end moves the
54
- * turn to the next engine. */
55
- const NOT_A_PROVIDER_FAILURE = new Set(["interrupted", "cancelled"]);
52
+ /** Stops that must not dispatch the request again: cancellation or a broken
53
+ * checkpoint whose accepted prompt may already have executed actions.
54
+ * The next explicit turn rebuilds that checkpoint from retained history. */
55
+ const NOT_A_PROVIDER_FAILURE = new Set(["interrupted", "cancelled", "invalid_checkpoint"]);
56
56
  export class FailoverGate {
57
57
  turns = new Map();
58
58
  onFailure;
@@ -1,3 +1,4 @@
1
+ import { invalidateBrokenCheckpoint } from "./checkpoint-recovery.js";
1
2
  import { createModelExpectation, ModelEvidenceLedger } from "./model-evidence-context.js";
2
3
  import { reactToMessage } from "./message-reactions.js";
3
4
  import { hasUnboundGoalGuard, goalGuardForEvent, addGoalGuard, removeGoalGuard, runPersonalGoalTurn, updatePersonalGoalReceipt } from "./personal-goal-turn.js";
@@ -8170,22 +8171,20 @@ bus.subscribe((event) => {
8170
8171
  });
8171
8172
  break;
8172
8173
  case "runtime.error":
8174
+ if (bot)
8175
+ invalidateBrokenCheckpoint(store, bot.id, event.providerInstanceId ? registry.get(event.providerInstanceId)?.driverKind : undefined, event);
8173
8176
  if (event.message?.trim())
8174
8177
  lastTurnError.set(event.threadId, event.message.trim().slice(0, 300));
8175
8178
  pushMessage({
8176
8179
  role: "bot",
8177
8180
  kind: "activity",
8178
- // The category travels with the line so every surface words it the
8179
- // same way; an error line is never a lost connection either way.
8181
+ // Keep the category consistent across surfaces.
8180
8182
  // The harness's own stop line is kept whole: it ends with where to fix
8181
8183
  // the account, which a 160-character cut would drop.
8182
8184
  tool: { name: `error: ${event.message.slice(0, event.category === "account" || event.category === "failover_exhausted" ? 600 : 160)}`, ok: false, setup: event.setup, ...(event.terminal ? { terminal: true } : {}),
8183
8185
  ...(event.category ? { errorCategory: event.category } : {}) },
8184
8186
  });
8185
- // a setup error means the engine could not even start: the bot is
8186
- // dead until something changes, not merely idle. The next successful
8187
- // dispatch moves it to working; turn.completed (which follows a setup
8188
- // failure) is told to leave "dead" alone.
8187
+ // Setup failures remain dead until a later successful dispatch.
8189
8188
  if (event.setup && bot)
8190
8189
  store.setTaskActivity(bot.id, event.threadId, "dead");
8191
8190
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chibitek/chibi",
3
- "version": "0.1.160",
3
+ "version": "0.1.161",
4
4
  "description": "Atomic by Chibitek: run your AI team's server anywhere and pair your devices to it",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -1 +0,0 @@
1
- import{U as a,C as n}from"./mermaid.core-DlSzuDKt.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
@@ -1,8 +0,0 @@
1
- import{c as r,s as e}from"./flowDiagram-KWPJA3E3-dtD6wm3G.js";import{_ as a}from"./mermaid.core-DlSzuDKt.js";import"./chunk-5VM5RSS4-QMK3iFBF.js";import"./chunk-XXDRQBXY-D7ocO3VN.js";import"./chunk-WEXAMYUT-CZslD_VF.js";import"./chunk-GWA4HPMP-DWvOhTaO.js";import"./channel-Lp7erhx-.js";import"./index-BIcziktH.js";var o=a(t=>`${e(t)}
2
- .swimlane.cluster:not([data-color-id]) rect {
3
- stroke: ${t.clusterBorder} !important;
4
- }
5
- [data-look="neo"].cluster rect {
6
- filter: none;
7
- }
8
- `,"getStyles"),s=o,u=r({styles:s});export{u as diagram};
@@ -1,205 +0,0 @@
1
- // server/connector-proxy.ts
2
- import readline from "node:readline";
3
- import { randomUUID } from "node:crypto";
4
- var UPSTREAM = process.env.OMB_CONNECTOR_UPSTREAM_URL ?? "";
5
- var HARNESS = process.env.OMB_HARNESS_URL ?? "http://127.0.0.1:8799";
6
- var BOT_ID = process.env.OMB_BOT_ID ?? "";
7
- var THREAD_ID = process.env.OMB_THREAD_ID ?? "";
8
- var TOKEN = process.env.OMB_CONNECTOR_TOKEN ?? process.env.OMB_COMMS_TOKEN ?? "";
9
- var MAX_RESPONSE_BYTES = 20 * 1024 * 1024;
10
- var INITIALIZE_RELAY_TIMEOUT_MS = 1e3;
11
- var RELAY_TIMEOUT_MS = 10 * 6e4;
12
- function parsedHeaders() {
13
- try {
14
- const value = JSON.parse(process.env.OMB_CONNECTOR_UPSTREAM_HEADERS ?? "{}");
15
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
16
- return Object.fromEntries(
17
- Object.entries(value).filter((entry) => typeof entry[1] === "string")
18
- );
19
- } catch {
20
- return {};
21
- }
22
- }
23
- var upstreamHeaders = parsedHeaders();
24
- var upstreamSessionId = "";
25
- var send = (message) => process.stdout.write(`${JSON.stringify(message)}
26
- `);
27
- function textResult(id, text, isError = false) {
28
- return { jsonrpc: "2.0", id, result: { content: [{ type: "text", text }], ...isError ? { isError: true } : {} } };
29
- }
30
- function jsonRpcError(id, message) {
31
- return { jsonrpc: "2.0", id, error: { code: -32e3, message } };
32
- }
33
- function initializeResult(id, protocolVersion) {
34
- return {
35
- jsonrpc: "2.0",
36
- id,
37
- result: {
38
- protocolVersion: typeof protocolVersion === "string" && protocolVersion ? protocolVersion : "2024-11-05",
39
- capabilities: { tools: {} },
40
- serverInfo: { name: "openmausbot-connectors", version: "1" }
41
- }
42
- };
43
- }
44
- async function readBounded(response) {
45
- const declared = Number(response.headers.get("content-length") ?? "0");
46
- if (declared > MAX_RESPONSE_BYTES) throw new Error("connector response exceeded 20 MB");
47
- if (!response.body) return "";
48
- const reader = response.body.getReader();
49
- const decoder = new TextDecoder();
50
- let size = 0;
51
- let text = "";
52
- for (; ; ) {
53
- const { done, value } = await reader.read();
54
- if (done) break;
55
- size += value.byteLength;
56
- if (size > MAX_RESPONSE_BYTES) {
57
- await reader.cancel();
58
- throw new Error("connector response exceeded 20 MB");
59
- }
60
- text += decoder.decode(value, { stream: true });
61
- }
62
- return text + decoder.decode();
63
- }
64
- function parseUpstream(text, id) {
65
- const trimmed = text.trim();
66
- if (!trimmed) return null;
67
- if (trimmed.startsWith("{")) return JSON.parse(trimmed);
68
- const frames = trimmed.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).filter((line) => line && line !== "[DONE]").flatMap((line) => {
69
- try {
70
- return [JSON.parse(line)];
71
- } catch {
72
- return [];
73
- }
74
- });
75
- return frames.findLast((frame) => frame.id === id) ?? frames.at(-1) ?? null;
76
- }
77
- async function relay(message, timeoutMs = RELAY_TIMEOUT_MS) {
78
- if (!UPSTREAM) throw new Error("connected apps are unavailable");
79
- const response = await fetch(UPSTREAM, {
80
- method: "POST",
81
- headers: {
82
- "content-type": "application/json",
83
- accept: "application/json, text/event-stream",
84
- ...upstreamHeaders,
85
- ...upstreamSessionId ? { "mcp-session-id": upstreamSessionId } : {}
86
- },
87
- body: JSON.stringify(message),
88
- signal: AbortSignal.timeout(timeoutMs)
89
- });
90
- const nextSession = response.headers.get("mcp-session-id");
91
- if (nextSession) upstreamSessionId = nextSession;
92
- if (!response.ok) throw new Error(`connector service returned HTTP ${response.status}`);
93
- return parseUpstream(await readBounded(response), message.id);
94
- }
95
- function connectorAdds(args) {
96
- if (!args || typeof args !== "object" || Array.isArray(args)) return [];
97
- const toolkits = args.toolkits;
98
- if (!Array.isArray(toolkits)) return [];
99
- const seen = /* @__PURE__ */ new Set();
100
- const requests = [];
101
- for (const item of toolkits) {
102
- if (typeof item === "string") {
103
- const slug2 = item.trim().toLowerCase();
104
- const key2 = JSON.stringify([slug2, ""]);
105
- if (!seen.has(key2)) {
106
- seen.add(key2);
107
- requests.push({ slug: slug2 });
108
- }
109
- continue;
110
- }
111
- if (!item || typeof item !== "object" || Array.isArray(item)) continue;
112
- const row = item;
113
- const action = String(row.action ?? "add").toLowerCase();
114
- if (!["add", "connect", "initiate"].includes(action)) continue;
115
- const slug = typeof row.toolkit === "string" ? row.toolkit : row.name;
116
- if (typeof slug !== "string") continue;
117
- const normalized = slug.trim().toLowerCase();
118
- const alias = (typeof row.alias === "string" ? row.alias : typeof row.account === "string" ? row.account : "").trim();
119
- const key = JSON.stringify([normalized, alias.toLowerCase()]);
120
- if (seen.has(key)) continue;
121
- seen.add(key);
122
- requests.push({ slug: normalized, ...alias ? { alias } : {} });
123
- }
124
- return requests;
125
- }
126
- async function showConnectorCards(items) {
127
- const response = await fetch(`${HARNESS}/api/internal/connectors/request`, {
128
- method: "POST",
129
- headers: { "content-type": "application/json", authorization: `Bearer ${TOKEN}` },
130
- body: JSON.stringify({ botId: BOT_ID, threadId: THREAD_ID, items, resumeKey: randomUUID() }),
131
- signal: AbortSignal.timeout(3e4)
132
- });
133
- if (!response.ok) {
134
- const body = await response.json().catch(() => ({}));
135
- throw new Error(String(body.error ?? `could not show connection card (HTTP ${response.status})`));
136
- }
137
- }
138
- async function handle(message) {
139
- const id = message.id;
140
- const method = String(message.method ?? "");
141
- if (method === "notifications/initialized" || method === "initialized") {
142
- if (UPSTREAM) void relay(message).catch(() => {
143
- });
144
- return;
145
- }
146
- if (method === "initialize") {
147
- if (UPSTREAM) {
148
- try {
149
- await relay(message, INITIALIZE_RELAY_TIMEOUT_MS);
150
- } catch {
151
- }
152
- }
153
- if (id !== void 0) {
154
- const params = message.params ?? {};
155
- send(initializeResult(id, params.protocolVersion));
156
- }
157
- return;
158
- }
159
- if (method === "tools/call") {
160
- const params = message.params ?? {};
161
- const name = String(params.name ?? "");
162
- const requests = /MANAGE_CONNECTIONS$/i.test(name) ? connectorAdds(params.arguments) : [];
163
- if (requests.length) {
164
- await showConnectorCards(requests);
165
- const labels = requests.map((r) => r.alias ? `${r.slug} (${r.alias})` : r.slug).join(", ");
166
- send(textResult(
167
- id,
168
- `Atomic showed the user a secure connection card for ${labels}. End this turn now. The app will continue the task automatically after the connection finishes.`
169
- ));
170
- return;
171
- }
172
- if (/WAIT_FOR_CONNECTIONS$/i.test(name)) {
173
- send(textResult(id, "Atomic is handling connection completion and will continue the task automatically."));
174
- return;
175
- }
176
- }
177
- try {
178
- const response = await relay(message);
179
- if (response && id !== void 0) send(response);
180
- } catch (error) {
181
- if (id === void 0) return;
182
- const messageText = error instanceof Error ? error.message : String(error);
183
- if (method === "tools/call") send(textResult(id, messageText, true));
184
- else send(jsonRpcError(id, messageText));
185
- }
186
- }
187
- var input = readline.createInterface({ input: process.stdin, terminal: false });
188
- input.on("line", (line) => {
189
- const trimmed = line.trim();
190
- if (!trimmed) return;
191
- let message;
192
- try {
193
- message = JSON.parse(trimmed);
194
- } catch {
195
- return;
196
- }
197
- void handle(message).catch((error) => {
198
- if (message.id === void 0) return;
199
- const method = String(message.method ?? "");
200
- const messageText = error instanceof Error ? error.message : String(error);
201
- if (method === "tools/call") send(textResult(message.id, messageText, true));
202
- else send(jsonRpcError(message.id, messageText));
203
- });
204
- });
205
- input.on("close", () => process.exit(0));