@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.
- package/dist/assets/{abnfDiagram-O67JEVCF-CpuRvzQ3.js → abnfDiagram-O67JEVCF-Bb-Unz3V.js} +1 -1
- package/dist/assets/{arc-ko1e0R6h.js → arc-HBMH7B4K.js} +1 -1
- package/dist/assets/{architectureDiagram-NJMV4G6O-OZ3SsOOa.js → architectureDiagram-NJMV4G6O-CYwkb2PE.js} +1 -1
- package/dist/assets/{blockDiagram-BEXU5L5S-DLRkBkjs.js → blockDiagram-BEXU5L5S-DPYYNxBH.js} +1 -1
- package/dist/assets/{c4Diagram-YGBWAQC7-e8Q3qMnw.js → c4Diagram-YGBWAQC7-DZ9hKDlA.js} +1 -1
- package/dist/assets/channel-Nx85fHZ4.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-hCDqaM4Q.js → chunk-2Q5K7J3B-OKrUlts6.js} +1 -1
- package/dist/assets/{chunk-3FUC2YCW-Dy3Pahu-.js → chunk-3FUC2YCW-Tuur0lqz.js} +2 -2
- package/dist/assets/{chunk-5VM5RSS4-QMK3iFBF.js → chunk-5VM5RSS4-BL8QOZeP.js} +1 -1
- package/dist/assets/{chunk-GTNCS2PH-6fyp9ERp.js → chunk-GTNCS2PH-DMi8-ixt.js} +1 -1
- package/dist/assets/{chunk-GWA4HPMP-DWvOhTaO.js → chunk-GWA4HPMP-Dd7yNJ0G.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-DgohMW2S.js → chunk-JWPE2WC7-g2dOoIMX.js} +1 -1
- package/dist/assets/{chunk-NETBCI7D-sRGeD2Y7.js → chunk-NETBCI7D-Cum7feOh.js} +1 -1
- package/dist/assets/{chunk-WEXAMYUT-CZslD_VF.js → chunk-WEXAMYUT-BzCC1jc4.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-D7ocO3VN.js → chunk-XXDRQBXY-Ck63jUMo.js} +1 -1
- package/dist/assets/{classDiagram-v2-NBCMYWYE-T1lLqHHW.js → classDiagram-v2-NBCMYWYE-DFSuRVMZ.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-BdeLiJr3.js → cose-bilkent-JH36ORCC-CegRj_kY.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-BydCA0pv.js → cynefin-OW5HDTMX-cZS_kt1A.js} +1 -1
- package/dist/assets/{cynefinDiagram-VND7K2PF-DBxckjwQ.js → cynefinDiagram-VND7K2PF-DfQa9Rht.js} +1 -1
- package/dist/assets/{dagre-6A5THRUB-CAsvq6Zk.js → dagre-6A5THRUB-DJ9qftJu.js} +1 -1
- package/dist/assets/{diagram-22UHCM2B-DTwH3rA_.js → diagram-22UHCM2B-KXUGUahJ.js} +1 -1
- package/dist/assets/{diagram-3UASUU5V-BNYj1bey.js → diagram-3UASUU5V-BudCYrCp.js} +1 -1
- package/dist/assets/{diagram-ATOU4E4O-CihwYFxb.js → diagram-ATOU4E4O-Du2O03NS.js} +1 -1
- package/dist/assets/{diagram-CDSNMT55-nouwk3s2.js → diagram-CDSNMT55-DXybXGYf.js} +1 -1
- package/dist/assets/{diagram-MLGK6HIB-BoKewJeA.js → diagram-MLGK6HIB-DfrknXGE.js} +1 -1
- package/dist/assets/{diagram-MPIPVDR6-CrE1m9DQ.js → diagram-MPIPVDR6-C29FmaJm.js} +1 -1
- package/dist/assets/{ebnfDiagram-ZINNZB2B-DRj0aU4Y.js → ebnfDiagram-ZINNZB2B-BF9wS0Nz.js} +1 -1
- package/dist/assets/{elk-276RUBZZ-Do0JzCG5.js → elk-276RUBZZ-B2Fah1VF.js} +1 -1
- package/dist/assets/{erDiagram-OPXOYQCR-CRsI9pXb.js → erDiagram-OPXOYQCR-Di3q4bpF.js} +1 -1
- package/dist/assets/{flowDiagram-KWPJA3E3-dtD6wm3G.js → flowDiagram-KWPJA3E3-D1UiqwbF.js} +1 -1
- package/dist/assets/{ganttDiagram-FUAMR5RP-Cn7KyLCo.js → ganttDiagram-FUAMR5RP-BjZqMt7o.js} +1 -1
- package/dist/assets/{gitGraphDiagram-X574FWY7-CGH_VWzq.js → gitGraphDiagram-X574FWY7-DiZtdip7.js} +1 -1
- package/dist/assets/{index-BIcziktH.js → index-XFwW09vd.js} +3 -3
- package/dist/assets/{index-Bk8iAodB.js → index-dbQveHan.js} +1 -1
- package/dist/assets/{infoDiagram-VRGFBTTK-CQKsYTCL.js → infoDiagram-VRGFBTTK-BJUJCgio.js} +1 -1
- package/dist/assets/{ishikawaDiagram-OU5B5YK6-D5catDe0.js → ishikawaDiagram-OU5B5YK6-BX0XdHUx.js} +1 -1
- package/dist/assets/{journeyDiagram-ZHPQQLJL-KjY8mki9.js → journeyDiagram-ZHPQQLJL-Bg904IIx.js} +1 -1
- package/dist/assets/{kanban-definition-PNTS6WVX-BKCyJtge.js → kanban-definition-PNTS6WVX-hkZMFMHZ.js} +1 -1
- package/dist/assets/{linear-B-_obUkq.js → linear-Bh29RTbQ.js} +1 -1
- package/dist/assets/{mermaid.core-DlSzuDKt.js → mermaid.core-aqB1jW_w.js} +5 -5
- package/dist/assets/{mindmap-definition-NLK3R4M7-BFQSaYKh.js → mindmap-definition-NLK3R4M7-D5GMV-Zd.js} +1 -1
- package/dist/assets/{pegDiagram-GJSIUBJH-l51izlev.js → pegDiagram-GJSIUBJH-7_wFtkFH.js} +1 -1
- package/dist/assets/{pieDiagram-5QR66LMP-6NEXRoZX.js → pieDiagram-5QR66LMP-DXtZBQ4f.js} +1 -1
- package/dist/assets/{quadrantDiagram-O4NWA36T-BCC9XlOe.js → quadrantDiagram-O4NWA36T-C1v3ydTF.js} +1 -1
- package/dist/assets/{railroadDiagram-XR7U4H2S-Dd4TmJ86.js → railroadDiagram-XR7U4H2S-CLmhiOXg.js} +1 -1
- package/dist/assets/{requirementDiagram-PLB6GJNP-C1E5DaDb.js → requirementDiagram-PLB6GJNP-BKxI2rh_.js} +1 -1
- package/dist/assets/{sankeyDiagram-IPEJSGJF-Ci6r7abb.js → sankeyDiagram-IPEJSGJF-gKK-Qs7b.js} +1 -1
- package/dist/assets/{sequenceDiagram-PO4LG4MO-BJ-I6WOh.js → sequenceDiagram-PO4LG4MO-BT94Uowp.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-Cs5QbLOP.js → sizeCapture-INFHLROL-RDJL6sCM.js} +1 -1
- package/dist/assets/{stateDiagram-v2-GCMORJYK-Bw--rdvq.js → stateDiagram-v2-GCMORJYK-DqHMzv-J.js} +1 -1
- package/dist/assets/{swimlanes-2SLR337P-B1O9IEz5.js → swimlanes-2SLR337P-B-NN0ql6.js} +1 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-BO2gR34z.js +8 -0
- package/dist/assets/{timeline-definition-EJHVYXUP-CTZ7DXaw.js → timeline-definition-EJHVYXUP-C51S9tpN.js} +1 -1
- package/dist/assets/{usecaseDiagram-POWQR4AR-DjwgNG0H.js → usecaseDiagram-POWQR4AR-DyfNMmhq.js} +1 -1
- package/dist/assets/{vennDiagram-UO4OBE2U-DrdJG55h.js → vennDiagram-UO4OBE2U-D924r33S.js} +1 -1
- package/dist/assets/{wardleyDiagram-VNRHLVJA-HVq776nz.js → wardleyDiagram-VNRHLVJA-DXSfsjUr.js} +1 -1
- package/dist/assets/{xychartDiagram-PMCCYNJV-DPf9VEua.js → xychartDiagram-PMCCYNJV-mYX9tnBU.js} +1 -1
- package/dist/index.html +1 -1
- package/dist-server/index.js +26 -6
- package/dist-server/openmausbot.js +24 -3
- package/dist-server/pair-cli.js +24 -3
- package/dist-server/server/checkpoint-recovery.js +18 -0
- package/dist-server/server/drivers/acp/core.js +17 -17
- package/dist-server/server/engine-failover.js +4 -4
- package/dist-server/server/index.js +5 -6
- package/package.json +1 -1
- package/dist/assets/channel-Lp7erhx-.js +0 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-C6wGgYKP.js +0 -8
- package/dist-server/connector-proxy.js +0 -205
- package/dist-server/server/composio.js +0 -1051
- package/dist-server/server/connector-proxy.js +0 -249
- package/dist-server/server/mcp-public-registry.js +0 -325
- 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
|
-
//
|
|
469
|
-
//
|
|
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
|
-
|
|
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
|
-
//
|
|
1496
|
-
//
|
|
1497
|
-
//
|
|
1498
|
-
|
|
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
|
-
/**
|
|
53
|
-
*
|
|
54
|
-
* turn
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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 +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));
|