@ycodium-ai/plugin-im 0.2.3216 → 0.2.3230
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/assets/ui.js +3 -3
- package/dist/index.js +882 -372
- package/locales/en.json +17 -0
- package/locales/zh-CN.json +17 -0
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -126258,67 +126258,96 @@ var keepNewest = (record4, limit) => {
|
|
|
126258
126258
|
return entries.length <= limit ? record4 : Object.fromEntries(entries.slice(entries.length - limit));
|
|
126259
126259
|
};
|
|
126260
126260
|
|
|
126261
|
-
// src/
|
|
126262
|
-
var
|
|
126263
|
-
const
|
|
126264
|
-
|
|
126265
|
-
|
|
126266
|
-
|
|
126267
|
-
|
|
126268
|
-
|
|
126269
|
-
|
|
126270
|
-
|
|
126271
|
-
if (oldest !== void 0) entries.delete(oldest);
|
|
126272
|
-
}
|
|
126273
|
-
},
|
|
126274
|
-
/** 忘掉键满足条件的那些。 */
|
|
126275
|
-
forget: (matches) => {
|
|
126276
|
-
for (const key of [...entries.keys()]) if (matches(key)) entries.delete(key);
|
|
126261
|
+
// src/executionTurn.ts
|
|
126262
|
+
var indexExecution = (execution) => {
|
|
126263
|
+
const intentsByMessageId = /* @__PURE__ */ new Map();
|
|
126264
|
+
const intentsById = /* @__PURE__ */ new Map();
|
|
126265
|
+
const turnsById = /* @__PURE__ */ new Map();
|
|
126266
|
+
for (const intent of execution.turnIntents) {
|
|
126267
|
+
if (!intentsByMessageId.has(intent.messageId)) intentsByMessageId.set(intent.messageId, intent);
|
|
126268
|
+
if (!intentsById.has(intent.intentId)) intentsById.set(intent.intentId, intent);
|
|
126269
|
+
if (intent.turn?.turnId != null && !turnsById.has(intent.turn.turnId)) {
|
|
126270
|
+
turnsById.set(intent.turn.turnId, intent.turn);
|
|
126277
126271
|
}
|
|
126278
|
-
}
|
|
126272
|
+
}
|
|
126273
|
+
if (execution.latestTurn != null && !turnsById.has(execution.latestTurn.turnId)) {
|
|
126274
|
+
turnsById.set(execution.latestTurn.turnId, execution.latestTurn);
|
|
126275
|
+
}
|
|
126276
|
+
return { execution, intentsByMessageId, intentsById, turnsById };
|
|
126279
126277
|
};
|
|
126278
|
+
var executionTurnFor = (snapshot, turnId) => snapshot.turnsById.get(turnId);
|
|
126280
126279
|
|
|
126281
|
-
// src/
|
|
126282
|
-
var
|
|
126283
|
-
|
|
126284
|
-
|
|
126285
|
-
var
|
|
126286
|
-
|
|
126287
|
-
const
|
|
126288
|
-
|
|
126280
|
+
// src/intentStatus.ts
|
|
126281
|
+
var isLiveIntentStatus = (status) => status === "queued" || status === "preparing" || status === "dispatching" || status === "running" || status === "reconciling" || status === "blocked";
|
|
126282
|
+
|
|
126283
|
+
// src/conclusionTurn.ts
|
|
126284
|
+
var conclusionOf = (turn) => turn.state === "completed" || turn.state === "interrupted" || turn.state === "error" ? { kind: "settled", ...turn, state: turn.state } : { kind: "pending" };
|
|
126285
|
+
var conclusionTurnFor = (snapshot, userMessageId) => {
|
|
126286
|
+
const { execution } = snapshot;
|
|
126287
|
+
const initial = snapshot.intentsByMessageId.get(userMessageId);
|
|
126288
|
+
if (initial === void 0) {
|
|
126289
|
+
const latest = execution.latestTurn;
|
|
126290
|
+
return latest?.userMessageId === userMessageId ? conclusionOf(latest) : { kind: "gone" };
|
|
126291
|
+
}
|
|
126292
|
+
let intent = initial;
|
|
126293
|
+
const visited = /* @__PURE__ */ new Set();
|
|
126294
|
+
while (intent.status === "cancelled" || intent.status === "abandoned") {
|
|
126295
|
+
if (visited.has(intent.intentId)) return { kind: "gone" };
|
|
126296
|
+
visited.add(intent.intentId);
|
|
126297
|
+
const replacementId = intent.replacementIntentId;
|
|
126298
|
+
const replacement = replacementId == null ? void 0 : snapshot.intentsById.get(replacementId);
|
|
126299
|
+
if (replacement === void 0) return { kind: "gone" };
|
|
126300
|
+
intent = replacement;
|
|
126301
|
+
}
|
|
126302
|
+
const action = intent.action;
|
|
126303
|
+
const turn = intent.turn;
|
|
126304
|
+
if (action?.kind === "steer" && intent.deliveredTurnId === action.turnId) {
|
|
126305
|
+
return {
|
|
126306
|
+
kind: "merged",
|
|
126307
|
+
turnId: action.turnId,
|
|
126308
|
+
turn: executionTurnFor(snapshot, action.turnId)
|
|
126309
|
+
};
|
|
126310
|
+
}
|
|
126311
|
+
if (turn !== null) return conclusionOf(turn);
|
|
126312
|
+
if (action?.kind === "steer") return { kind: "pending" };
|
|
126313
|
+
return { kind: isLiveIntentStatus(intent.status) ? "pending" : "gone" };
|
|
126289
126314
|
};
|
|
126290
|
-
var
|
|
126291
|
-
const
|
|
126292
|
-
|
|
126293
|
-
|
|
126294
|
-
|
|
126295
|
-
|
|
126296
|
-
|
|
126297
|
-
|
|
126315
|
+
var groupConclusionDebts = (snapshot, threadId, debts) => {
|
|
126316
|
+
const resolved = new Map(
|
|
126317
|
+
debts.filter((debt) => debt.threadId === threadId).map((debt) => [
|
|
126318
|
+
debt.userMessageId,
|
|
126319
|
+
{ debt, result: conclusionTurnFor(snapshot, debt.userMessageId) }
|
|
126320
|
+
])
|
|
126321
|
+
);
|
|
126322
|
+
const byTurn = /* @__PURE__ */ new Map();
|
|
126323
|
+
for (const { debt, result: result2 } of resolved.values()) {
|
|
126324
|
+
if (result2.kind !== "settled" && result2.kind !== "merged") continue;
|
|
126325
|
+
const group = byTurn.get(result2.turnId) ?? [];
|
|
126326
|
+
group.push(debt);
|
|
126327
|
+
byTurn.set(result2.turnId, group);
|
|
126328
|
+
}
|
|
126329
|
+
for (const [turnId, candidates] of byTurn) {
|
|
126330
|
+
const ownerId = turnId === null ? void 0 : executionTurnFor(snapshot, turnId)?.userMessageId;
|
|
126331
|
+
const owner = ownerId === void 0 ? void 0 : resolved.get(ownerId);
|
|
126332
|
+
if (owner !== void 0 && owner.result.kind !== "gone" && !candidates.includes(owner.debt))
|
|
126333
|
+
candidates.push(owner.debt);
|
|
126334
|
+
}
|
|
126335
|
+
return { resolved, byTurn };
|
|
126336
|
+
};
|
|
126337
|
+
var conclusionDebtForTurn = (snapshot, turnId, candidates, isDelivered) => {
|
|
126338
|
+
const turn = turnId === null ? void 0 : executionTurnFor(snapshot, turnId);
|
|
126339
|
+
const own = candidates.find((debt2) => debt2.userMessageId === turn?.userMessageId);
|
|
126340
|
+
const handled = turn?.userMessageId !== void 0 && isDelivered(turn.userMessageId) || candidates.length === 0 && snapshot.execution.turnIntents.some((intent) => {
|
|
126341
|
+
if (!isDelivered(intent.messageId)) return false;
|
|
126342
|
+
const result2 = conclusionTurnFor(snapshot, intent.messageId);
|
|
126343
|
+
return (result2.kind === "merged" || result2.kind === "settled") && result2.turnId === turnId;
|
|
126344
|
+
});
|
|
126345
|
+
const debt = handled ? void 0 : own ?? candidates[0];
|
|
126298
126346
|
return {
|
|
126299
|
-
|
|
126300
|
-
|
|
126301
|
-
|
|
126302
|
-
|
|
126303
|
-
note: (threadId, userMessageId, binding) => {
|
|
126304
|
-
if (binding.reply === void 0) return;
|
|
126305
|
-
const turns = byThread.get(threadId) ?? makeBoundedMap(TURNS_PER_THREAD);
|
|
126306
|
-
byThread.set(threadId, turns);
|
|
126307
|
-
turns.set(userMessageId, { chatKey: chatKeyOf(binding), anchor: binding.reply });
|
|
126308
|
-
},
|
|
126309
|
-
/**
|
|
126310
|
-
* 给发往这条会话的聊天挂上 `turnId` 那一轮的锚点(null 的含义见上);取不到就原样返回。
|
|
126311
|
-
*
|
|
126312
|
-
* 锚点只配给它那条消息所在的聊天:会话可以被另一个聊天接走(`/resume`),而回复接口只按被
|
|
126313
|
-
* 回复的消息寻址,挂错了答复就发回原来的聊天。
|
|
126314
|
-
*/
|
|
126315
|
-
anchored: async (binding, threadId, turnId) => {
|
|
126316
|
-
const turns = byThread.get(threadId);
|
|
126317
|
-
if (turns === void 0) return binding;
|
|
126318
|
-
const asked = await userMessageOfTurn(threadId, turnId);
|
|
126319
|
-
const noted = asked === void 0 ? void 0 : turns.get(asked);
|
|
126320
|
-
return noted?.chatKey === chatKeyOf(binding) ? { ...binding, reply: noted.anchor } : binding;
|
|
126321
|
-
}
|
|
126347
|
+
debt,
|
|
126348
|
+
handled,
|
|
126349
|
+
userMessageId: turn?.userMessageId,
|
|
126350
|
+
redundant: candidates.filter((candidate) => candidate !== debt)
|
|
126322
126351
|
};
|
|
126323
126352
|
};
|
|
126324
126353
|
|
|
@@ -126336,11 +126365,14 @@ var foldConclusionEvent = (state, name, data) => {
|
|
|
126336
126365
|
const pending = conclusionDebtsOf(state);
|
|
126337
126366
|
if (name === "conclusion-delivered") {
|
|
126338
126367
|
const { [key]: _delivered, ...rest } = pending;
|
|
126368
|
+
const turnUserMessageId = data["turnUserMessageId"];
|
|
126369
|
+
const turnKey2 = typeof turnUserMessageId === "string" && turnUserMessageId !== "" ? keyOf(threadId, turnUserMessageId) : key;
|
|
126370
|
+
const { [turnKey2]: _turnDelivered, ...remaining } = rest;
|
|
126339
126371
|
return {
|
|
126340
126372
|
...state,
|
|
126341
|
-
conclusions:
|
|
126373
|
+
conclusions: remaining,
|
|
126342
126374
|
deliveredConclusions: keepNewest(
|
|
126343
|
-
{ ...state.deliveredConclusions, [key]: true },
|
|
126375
|
+
{ ...state.deliveredConclusions, [key]: true, [turnKey2]: true },
|
|
126344
126376
|
CONCLUSION_DEBT_LIMIT
|
|
126345
126377
|
)
|
|
126346
126378
|
};
|
|
@@ -126368,13 +126400,35 @@ var makeConclusionLedger = (core) => {
|
|
|
126368
126400
|
core.host.onDispose(() => {
|
|
126369
126401
|
disposed = true;
|
|
126370
126402
|
});
|
|
126371
|
-
const settle = (debt) => {
|
|
126403
|
+
const settle = ({ debt, turnUserMessageId }) => {
|
|
126372
126404
|
core.commit("conclusion-delivered", {
|
|
126373
126405
|
threadId: debt.threadId,
|
|
126374
|
-
userMessageId: debt.userMessageId
|
|
126406
|
+
userMessageId: debt.userMessageId,
|
|
126407
|
+
...turnUserMessageId !== void 0 && turnUserMessageId !== debt.userMessageId ? { turnUserMessageId } : {}
|
|
126375
126408
|
});
|
|
126376
126409
|
};
|
|
126410
|
+
const forExecutionTurn = (snapshot, threadId, turnId, grouped) => {
|
|
126411
|
+
if (disposed) return { selection: void 0, handled: true };
|
|
126412
|
+
const pending = conclusionDebtsOf(core.state);
|
|
126413
|
+
const candidates = (grouped ?? groupConclusionDebts(snapshot, threadId, Object.values(pending))).byTurn.get(turnId);
|
|
126414
|
+
const currentCandidates = candidates?.filter(
|
|
126415
|
+
(debt) => pending[keyOf(threadId, debt.userMessageId)] !== void 0
|
|
126416
|
+
);
|
|
126417
|
+
if (currentCandidates?.length === 0) return { selection: void 0, handled: true };
|
|
126418
|
+
const selected = conclusionDebtForTurn(
|
|
126419
|
+
snapshot,
|
|
126420
|
+
turnId,
|
|
126421
|
+
currentCandidates ?? [],
|
|
126422
|
+
(messageId) => delivered(keyOf(threadId, messageId))
|
|
126423
|
+
);
|
|
126424
|
+
for (const debt of selected.redundant) settle({ debt, turnUserMessageId: void 0 });
|
|
126425
|
+
return {
|
|
126426
|
+
selection: selected.debt === void 0 ? void 0 : { debt: selected.debt, turnUserMessageId: selected.userMessageId },
|
|
126427
|
+
handled: selected.handled || selected.debt !== void 0 && inFlight.has(keyOf(threadId, selected.debt.userMessageId))
|
|
126428
|
+
};
|
|
126429
|
+
};
|
|
126377
126430
|
return {
|
|
126431
|
+
forExecutionTurn,
|
|
126378
126432
|
starting: (threadId) => {
|
|
126379
126433
|
const gate = Promise.withResolvers();
|
|
126380
126434
|
const pending = registering.get(threadId) ?? /* @__PURE__ */ new Set();
|
|
@@ -126406,18 +126460,32 @@ var makeConclusionLedger = (core) => {
|
|
|
126406
126460
|
unpersisted.delete(key);
|
|
126407
126461
|
if (added) await recover?.(debt);
|
|
126408
126462
|
},
|
|
126463
|
+
/** selection 为 null 表示执行视图不可读且本会话仍有欠账,须等恢复器判定后投递。 */
|
|
126409
126464
|
forTurn: async (threadId, turnId = null) => {
|
|
126410
126465
|
await Promise.all(registering.get(threadId) ?? []);
|
|
126411
|
-
const execution = await core.host.projections.getThreadExecution(threadId)
|
|
126412
|
-
|
|
126413
|
-
|
|
126466
|
+
const execution = await core.host.projections.getThreadExecution(threadId).catch((error) => {
|
|
126467
|
+
const owes = Object.values(conclusionDebtsOf(core.state)).some(
|
|
126468
|
+
(debt) => debt.threadId === threadId
|
|
126469
|
+
);
|
|
126470
|
+
if (!owes) return null;
|
|
126471
|
+
core.host.log.warn("chat deferred a conclusion until its execution can be read", {
|
|
126472
|
+
threadId,
|
|
126473
|
+
error: describeError(error)
|
|
126474
|
+
});
|
|
126475
|
+
return void 0;
|
|
126476
|
+
});
|
|
126477
|
+
if (execution === void 0) return { selection: null, handled: false, execution: null };
|
|
126414
126478
|
return {
|
|
126415
|
-
|
|
126416
|
-
|
|
126417
|
-
|
|
126479
|
+
execution,
|
|
126480
|
+
...execution === null ? { selection: void 0, handled: false } : forExecutionTurn(
|
|
126481
|
+
indexExecution(execution),
|
|
126482
|
+
threadId,
|
|
126483
|
+
turnId ?? execution.latestTurn?.turnId ?? null
|
|
126484
|
+
)
|
|
126418
126485
|
};
|
|
126419
126486
|
},
|
|
126420
|
-
deliver: async (
|
|
126487
|
+
deliver: async (selection, send) => {
|
|
126488
|
+
const { debt } = selection;
|
|
126421
126489
|
const key = keyOf(debt.threadId, debt.userMessageId);
|
|
126422
126490
|
if (disposed || delivered(key) || inFlight.has(key) || conclusionDebtsOf(core.state)[key] === void 0)
|
|
126423
126491
|
return false;
|
|
@@ -126426,16 +126494,17 @@ var makeConclusionLedger = (core) => {
|
|
|
126426
126494
|
const sent = await send(
|
|
126427
126495
|
() => !delivered(key) && conclusionDebtsOf(core.state)[key] !== void 0
|
|
126428
126496
|
);
|
|
126429
|
-
if (sent) settle(
|
|
126497
|
+
if (sent) settle(selection);
|
|
126430
126498
|
return sent;
|
|
126431
126499
|
} finally {
|
|
126432
126500
|
inFlight.delete(key);
|
|
126433
126501
|
}
|
|
126434
126502
|
},
|
|
126435
|
-
discard: (
|
|
126503
|
+
discard: (selection) => {
|
|
126504
|
+
const { debt } = selection;
|
|
126436
126505
|
const key = keyOf(debt.threadId, debt.userMessageId);
|
|
126437
126506
|
if (!disposed && !delivered(key) && !inFlight.has(key) && conclusionDebtsOf(core.state)[key] !== void 0) {
|
|
126438
|
-
settle(
|
|
126507
|
+
settle(selection);
|
|
126439
126508
|
}
|
|
126440
126509
|
}
|
|
126441
126510
|
};
|
|
@@ -127450,6 +127519,26 @@ var makeChatQueue = (core) => {
|
|
|
127450
127519
|
// src/chatSetup.ts
|
|
127451
127520
|
import { threadOrNull } from "@ycodium-ai/plugin-api";
|
|
127452
127521
|
|
|
127522
|
+
// src/boundedMap.ts
|
|
127523
|
+
var makeBoundedMap = (limit) => {
|
|
127524
|
+
const entries = /* @__PURE__ */ new Map();
|
|
127525
|
+
return {
|
|
127526
|
+
get: (key) => entries.get(key),
|
|
127527
|
+
set: (key, value2) => {
|
|
127528
|
+
entries.delete(key);
|
|
127529
|
+
entries.set(key, value2);
|
|
127530
|
+
if (entries.size > limit) {
|
|
127531
|
+
const oldest = entries.keys().next().value;
|
|
127532
|
+
if (oldest !== void 0) entries.delete(oldest);
|
|
127533
|
+
}
|
|
127534
|
+
},
|
|
127535
|
+
/** 忘掉键满足条件的那些。 */
|
|
127536
|
+
forget: (matches) => {
|
|
127537
|
+
for (const key of [...entries.keys()]) if (matches(key)) entries.delete(key);
|
|
127538
|
+
}
|
|
127539
|
+
};
|
|
127540
|
+
};
|
|
127541
|
+
|
|
127453
127542
|
// src/cooldown.ts
|
|
127454
127543
|
var makeCooldown = (windowMs, now, maxKeys = Number.POSITIVE_INFINITY) => {
|
|
127455
127544
|
const lastAt = /* @__PURE__ */ new Map();
|
|
@@ -133277,6 +133366,87 @@ var makeCommands = (core, deps) => {
|
|
|
133277
133366
|
return { handleCommand, executeCommand, targetOf };
|
|
133278
133367
|
};
|
|
133279
133368
|
|
|
133369
|
+
// src/connectionError.ts
|
|
133370
|
+
var NETWORK_HINTS = {
|
|
133371
|
+
ENOTFOUND: "networkDns",
|
|
133372
|
+
EAI_AGAIN: "networkDns",
|
|
133373
|
+
ECONNREFUSED: "networkRefused",
|
|
133374
|
+
ECONNRESET: "networkReset",
|
|
133375
|
+
EPIPE: "networkReset",
|
|
133376
|
+
UND_ERR_SOCKET: "networkReset",
|
|
133377
|
+
ENETUNREACH: "networkUnreachable",
|
|
133378
|
+
EHOSTUNREACH: "networkUnreachable",
|
|
133379
|
+
ERR_NETWORK_ACCESS_DENIED: "networkUnreachable",
|
|
133380
|
+
CERT_HAS_EXPIRED: "networkTls",
|
|
133381
|
+
CERT_NOT_YET_VALID: "networkTls",
|
|
133382
|
+
DEPTH_ZERO_SELF_SIGNED_CERT: "networkTls",
|
|
133383
|
+
SELF_SIGNED_CERT_IN_CHAIN: "networkTls",
|
|
133384
|
+
UNABLE_TO_VERIFY_LEAF_SIGNATURE: "networkTls",
|
|
133385
|
+
UNABLE_TO_GET_ISSUER_CERT_LOCALLY: "networkTls",
|
|
133386
|
+
ERR_TLS_CERT_ALTNAME_INVALID: "networkTls",
|
|
133387
|
+
ERR_SSL_WRONG_VERSION_NUMBER: "networkTls",
|
|
133388
|
+
ERR_TLS_HANDSHAKE_TIMEOUT: "networkTls",
|
|
133389
|
+
ERR_SSL_TLSV1_ALERT_INTERNAL_ERROR: "networkTls",
|
|
133390
|
+
ETIMEDOUT: "networkTimeout",
|
|
133391
|
+
UND_ERR_CONNECT_TIMEOUT: "networkTimeout",
|
|
133392
|
+
UND_ERR_HEADERS_TIMEOUT: "networkTimeout",
|
|
133393
|
+
UND_ERR_BODY_TIMEOUT: "networkTimeout",
|
|
133394
|
+
timeout: "networkTimeout",
|
|
133395
|
+
ERR_PROXY_CONNECTION_FAILED: "networkProxy"
|
|
133396
|
+
};
|
|
133397
|
+
var NETWORK_REASONS = new Set(Object.keys(NETWORK_HINTS));
|
|
133398
|
+
var GENERIC_REASONS = /* @__PURE__ */ new Set(["timeout"]);
|
|
133399
|
+
var MAX_NODES = 16;
|
|
133400
|
+
var recordOf = (value2) => value2 !== null && typeof value2 === "object" ? value2 : void 0;
|
|
133401
|
+
var httpStatusOf = (value2) => typeof value2 === "number" && Number.isInteger(value2) && value2 >= 100 && value2 <= 599 ? value2 : void 0;
|
|
133402
|
+
var networkReason = (value2) => typeof value2 === "string" && NETWORK_REASONS.has(value2) ? value2 : void 0;
|
|
133403
|
+
var canonicalCode = (entry) => entry["name"] === "TimeoutError" ? "timeout" : entry["code"];
|
|
133404
|
+
var visitedErrors = (error) => {
|
|
133405
|
+
const queue = [error];
|
|
133406
|
+
const seen = /* @__PURE__ */ new Set();
|
|
133407
|
+
const chain = [];
|
|
133408
|
+
while (queue.length > 0 && chain.length < MAX_NODES) {
|
|
133409
|
+
const entry = recordOf(queue.shift());
|
|
133410
|
+
if (entry === void 0 || seen.has(entry)) continue;
|
|
133411
|
+
seen.add(entry);
|
|
133412
|
+
chain.push(entry);
|
|
133413
|
+
if (recordOf(entry["cause"]) !== void 0) queue.push(entry["cause"]);
|
|
133414
|
+
if (Array.isArray(entry["errors"])) queue.push(...entry["errors"].slice(0, MAX_NODES));
|
|
133415
|
+
}
|
|
133416
|
+
return chain;
|
|
133417
|
+
};
|
|
133418
|
+
var connectionFacts = (error) => {
|
|
133419
|
+
const nodes = visitedErrors(error).map((entry) => {
|
|
133420
|
+
const response = recordOf(entry["response"]);
|
|
133421
|
+
const fromCode = networkReason(canonicalCode(entry));
|
|
133422
|
+
return {
|
|
133423
|
+
reasons: fromCode === void 0 ? [] : [fromCode],
|
|
133424
|
+
httpStatus: httpStatusOf(entry["status"] ?? entry["statusCode"] ?? response?.["status"])
|
|
133425
|
+
};
|
|
133426
|
+
});
|
|
133427
|
+
const all2 = [...new Set(nodes.flatMap((node) => node.reasons))];
|
|
133428
|
+
const precise = all2.filter((reason) => !GENERIC_REASONS.has(reason));
|
|
133429
|
+
const httpStatus = nodes.find((node) => node.httpStatus !== void 0)?.httpStatus;
|
|
133430
|
+
return {
|
|
133431
|
+
reasons: precise.length > 0 ? precise : all2,
|
|
133432
|
+
...httpStatus !== void 0 ? { httpStatus } : {}
|
|
133433
|
+
};
|
|
133434
|
+
};
|
|
133435
|
+
var connectionHint = (error) => {
|
|
133436
|
+
const { reasons, httpStatus } = connectionFacts(error);
|
|
133437
|
+
if (reasons.length > 1) return "networkMultipleCauses";
|
|
133438
|
+
const mapped = reasons[0] !== void 0 ? NETWORK_HINTS[reasons[0]] : void 0;
|
|
133439
|
+
if (mapped !== void 0) return mapped;
|
|
133440
|
+
if (httpStatus === 407) return "networkProxy";
|
|
133441
|
+
if (httpStatus === 429) return "platformRateLimited";
|
|
133442
|
+
if (httpStatus !== void 0 && httpStatus >= 500) return "platformUnavailable";
|
|
133443
|
+
return void 0;
|
|
133444
|
+
};
|
|
133445
|
+
var connectionHintFields = (error, platformHint) => {
|
|
133446
|
+
const hint = platformHint ?? connectionHint(error);
|
|
133447
|
+
return hint === void 0 ? {} : { hint };
|
|
133448
|
+
};
|
|
133449
|
+
|
|
133280
133450
|
// src/inboundStore.ts
|
|
133281
133451
|
import * as NodeCrypto from "node:crypto";
|
|
133282
133452
|
import * as NodeFSP from "node:fs/promises";
|
|
@@ -133604,18 +133774,14 @@ var makeInboundStore = (input) => {
|
|
|
133604
133774
|
write(rowId, row);
|
|
133605
133775
|
return result2.promise;
|
|
133606
133776
|
};
|
|
133607
|
-
const
|
|
133777
|
+
const claimReceipt = (rowId, id, message, receivedAt = 0) => {
|
|
133608
133778
|
const row = rowOf(rowId);
|
|
133609
|
-
|
|
133610
|
-
try {
|
|
133611
|
-
assertReadable(row);
|
|
133612
|
-
} catch (error) {
|
|
133613
|
-
return Promise.reject(error);
|
|
133614
|
-
}
|
|
133779
|
+
assertReadable(row);
|
|
133615
133780
|
const pending = row.claims.get(id);
|
|
133616
|
-
if (pending !== void 0) return
|
|
133781
|
+
if (pending !== void 0) return { first: false, persisted: pending };
|
|
133617
133782
|
const seen = row.data.seenIds.includes(id);
|
|
133618
|
-
if (seen && (row.claimRevisions.get(id) ?? 0) <= row.persisted)
|
|
133783
|
+
if (seen && (row.claimRevisions.get(id) ?? 0) <= row.persisted)
|
|
133784
|
+
return { first: false, persisted: Promise.resolve() };
|
|
133619
133785
|
if (!seen) {
|
|
133620
133786
|
if (message !== void 0) {
|
|
133621
133787
|
const inbox = row.data.inbox ?? [];
|
|
@@ -133659,7 +133825,17 @@ var makeInboundStore = (input) => {
|
|
|
133659
133825
|
row.claims.delete(id);
|
|
133660
133826
|
};
|
|
133661
133827
|
void result2.then(forget, forget);
|
|
133662
|
-
return
|
|
133828
|
+
return { first: !seen, persisted: result2 };
|
|
133829
|
+
};
|
|
133830
|
+
const claim = (rowId, id, message, receivedAt = 0) => {
|
|
133831
|
+
const row = rowOf(rowId);
|
|
133832
|
+
if (!row.loaded) return load(rowId).then(() => claim(rowId, id, message, receivedAt));
|
|
133833
|
+
try {
|
|
133834
|
+
const receipt = claimReceipt(rowId, id, message, receivedAt);
|
|
133835
|
+
return receipt.persisted.then(() => receipt.first);
|
|
133836
|
+
} catch (error) {
|
|
133837
|
+
return Promise.reject(error);
|
|
133838
|
+
}
|
|
133663
133839
|
};
|
|
133664
133840
|
const removeEntry = (rowId, key, failure2) => {
|
|
133665
133841
|
const row = rowOf(rowId);
|
|
@@ -133785,6 +133961,7 @@ var makeInboundStore = (input) => {
|
|
|
133785
133961
|
return {
|
|
133786
133962
|
load,
|
|
133787
133963
|
claim,
|
|
133964
|
+
claimReceipt,
|
|
133788
133965
|
get: (rowId, key) => {
|
|
133789
133966
|
const row = rowOf(rowId);
|
|
133790
133967
|
assertReadable(row);
|
|
@@ -133822,6 +133999,8 @@ var makeInboundStore = (input) => {
|
|
|
133822
133999
|
assertReadable(row);
|
|
133823
134000
|
if (row.data.inbox !== void 0)
|
|
133824
134001
|
row.data.inbox = row.data.inbox.filter((e) => e.key !== key);
|
|
134002
|
+
row.data.seenIds = row.data.seenIds.filter((id) => id !== key);
|
|
134003
|
+
row.claimRevisions.delete(key);
|
|
133825
134004
|
row.revision++;
|
|
133826
134005
|
},
|
|
133827
134006
|
reset,
|
|
@@ -133962,7 +134141,9 @@ var startConnections = (core, inboundHandlersFor, inboundState, recovery) => {
|
|
|
133962
134141
|
...inbound,
|
|
133963
134142
|
// 停用先封接收,保持发送连接直到已接收工作 drain 完成。
|
|
133964
134143
|
onMessage: (message) => {
|
|
133965
|
-
if (
|
|
134144
|
+
if (closed || disposed)
|
|
134145
|
+
return Promise.reject(new Error("inbound connection is closed"));
|
|
134146
|
+
return inbound.onMessage(message);
|
|
133966
134147
|
},
|
|
133967
134148
|
onButton: (...args2) => closed || disposed ? null : inbound.onButton(...args2),
|
|
133968
134149
|
onPanelClick: (click) => closed || disposed ? null : inbound.onPanelClick?.(click) ?? null,
|
|
@@ -133980,7 +134161,7 @@ var startConnections = (core, inboundHandlersFor, inboundState, recovery) => {
|
|
|
133980
134161
|
state: "failed",
|
|
133981
134162
|
...status.reason === void 0 ? {} : { reason: status.reason },
|
|
133982
134163
|
...status.error === void 0 ? {} : { error: redactor.redact(describeError(status.error)) },
|
|
133983
|
-
...status.
|
|
134164
|
+
...connectionHintFields(status.error, status.hint)
|
|
133984
134165
|
});
|
|
133985
134166
|
}
|
|
133986
134167
|
});
|
|
@@ -133993,7 +134174,7 @@ var startConnections = (core, inboundHandlersFor, inboundState, recovery) => {
|
|
|
133993
134174
|
record4(bot.rowId, {
|
|
133994
134175
|
state: "failed",
|
|
133995
134176
|
error: detail,
|
|
133996
|
-
...error instanceof InboxUnreadableError ? { reason: "inbox-unreadable", hint: "inboxUnreadable" } :
|
|
134177
|
+
...error instanceof InboxUnreadableError ? { reason: "inbox-unreadable", hint: "inboxUnreadable" } : connectionHintFields(error)
|
|
133997
134178
|
});
|
|
133998
134179
|
host.log.warn("chat could not start an inbound connection", {
|
|
133999
134180
|
bot: bot.displayName,
|
|
@@ -135109,6 +135290,45 @@ var makeGreetings = (core, enqueueForChat, now) => {
|
|
|
135109
135290
|
};
|
|
135110
135291
|
};
|
|
135111
135292
|
|
|
135293
|
+
// src/replyAnchors.ts
|
|
135294
|
+
var THREAD_LIMIT = 256;
|
|
135295
|
+
var TURNS_PER_THREAD = 16;
|
|
135296
|
+
var anchorOfMessage = (adapter, message) => adapter?.quotesReplies === true ? { messageId: message.messageId, inThread: message.replyInThread === true } : void 0;
|
|
135297
|
+
var makeReplyAnchors = (host) => {
|
|
135298
|
+
const byThread = makeBoundedMap(THREAD_LIMIT);
|
|
135299
|
+
const userMessageOfTurn = async (threadId, turnId) => {
|
|
135300
|
+
const execution = await host.projections.getThreadExecution(threadId).catch(() => null);
|
|
135301
|
+
if (execution === null) return void 0;
|
|
135302
|
+
const wanted = turnId ?? execution.session?.activeTurnId ?? execution.latestTurn?.turnId;
|
|
135303
|
+
return wanted == null ? void 0 : executionTurnFor(indexExecution(execution), wanted)?.userMessageId;
|
|
135304
|
+
};
|
|
135305
|
+
return {
|
|
135306
|
+
/**
|
|
135307
|
+
* 开轮时记一笔:`userMessageId` 是派给宿主的那条用户消息,`binding` 是收到聊天消息的那个
|
|
135308
|
+
* 聊天(带着它的锚点)。没有锚点(平台不引用)就不记。
|
|
135309
|
+
*/
|
|
135310
|
+
note: (threadId, userMessageId, binding) => {
|
|
135311
|
+
if (binding.reply === void 0) return;
|
|
135312
|
+
const turns = byThread.get(threadId) ?? makeBoundedMap(TURNS_PER_THREAD);
|
|
135313
|
+
byThread.set(threadId, turns);
|
|
135314
|
+
turns.set(userMessageId, { chatKey: chatKeyOf(binding), anchor: binding.reply });
|
|
135315
|
+
},
|
|
135316
|
+
/**
|
|
135317
|
+
* 给发往这条会话的聊天挂上 `turnId` 那一轮的锚点(null 的含义见上);取不到就原样返回。
|
|
135318
|
+
*
|
|
135319
|
+
* 锚点只配给它那条消息所在的聊天:会话可以被另一个聊天接走(`/resume`),而回复接口只按被
|
|
135320
|
+
* 回复的消息寻址,挂错了答复就发回原来的聊天。
|
|
135321
|
+
*/
|
|
135322
|
+
anchored: async (binding, threadId, turnId) => {
|
|
135323
|
+
const turns = byThread.get(threadId);
|
|
135324
|
+
if (turns === void 0) return binding;
|
|
135325
|
+
const asked = await userMessageOfTurn(threadId, turnId);
|
|
135326
|
+
const noted = asked === void 0 ? void 0 : turns.get(asked);
|
|
135327
|
+
return noted?.chatKey === chatKeyOf(binding) ? { ...binding, reply: noted.anchor } : binding;
|
|
135328
|
+
}
|
|
135329
|
+
};
|
|
135330
|
+
};
|
|
135331
|
+
|
|
135112
135332
|
// src/inbound.ts
|
|
135113
135333
|
var ARCHIVED_REPLY_COOLDOWN_MS = 10 * 6e4;
|
|
135114
135334
|
var UNSUPPORTED_REPLY_COOLDOWN_MS = 6e4;
|
|
@@ -135336,40 +135556,44 @@ var makeInbound = (core, deps) => {
|
|
|
135336
135556
|
noteChatAlias: (alias, chatId) => noteChatAlias(bot, alias, chatId),
|
|
135337
135557
|
knowsChatAlias: (alias) => chatAliasOf(core.state, bot.rowId, alias) !== void 0,
|
|
135338
135558
|
onGreeting: (chatId, senderId) => greet(bot.rowId, chatId, senderId),
|
|
135339
|
-
onMessage: (received) => {
|
|
135559
|
+
onMessage: async (received) => {
|
|
135340
135560
|
const current = currentBot(bot.rowId);
|
|
135341
|
-
if (!accepting || current === void 0)
|
|
135561
|
+
if (!accepting || current === void 0) throw new Error("inbound is not accepting messages");
|
|
135342
135562
|
const message = settleChat(current, received);
|
|
135343
135563
|
const work = workForMessage(message);
|
|
135344
|
-
|
|
135564
|
+
const adapter = adapterFor(current.platform);
|
|
135345
135565
|
let saved;
|
|
135346
135566
|
try {
|
|
135347
|
-
saved = persistInbound(
|
|
135567
|
+
saved = persistInbound(adapter, message);
|
|
135348
135568
|
} catch (error) {
|
|
135349
135569
|
host.log.warn("chat could not serialize inbound; processing without restart protection", {
|
|
135350
135570
|
rowId: current.rowId,
|
|
135351
135571
|
error: describeError(error)
|
|
135352
135572
|
});
|
|
135353
135573
|
}
|
|
135574
|
+
const claim = inboundState.claimReceipt(current.rowId, work.key, saved, now());
|
|
135575
|
+
if (!claim.first) return claim.persisted;
|
|
135576
|
+
const receipt = claim.persisted.catch((error) => {
|
|
135577
|
+
inboundState.abandon(current.rowId, work.key);
|
|
135578
|
+
host.log.warn(
|
|
135579
|
+
adapter?.redeliversUnacknowledged ? "chat could not save inbound state; waiting for platform redelivery" : "chat could not save inbound state; processing without restart protection",
|
|
135580
|
+
{ rowId: current.rowId, error: describeError(error) }
|
|
135581
|
+
);
|
|
135582
|
+
throw error;
|
|
135583
|
+
});
|
|
135584
|
+
const enqueue = () => {
|
|
135585
|
+
const arrived = bindingOf2(current, message.chatId);
|
|
135586
|
+
if (message.chatKind !== void 0 && chatOf(core.state, chatKeyOf(arrived)).chatKind !== message.chatKind) {
|
|
135587
|
+
commit("chat-updated", { chatKey: chatKeyOf(arrived), chatKind: message.chatKind });
|
|
135588
|
+
}
|
|
135589
|
+
enqueueForChat(chatKeyOf(arrived), () => resumeMessage(current, message, work));
|
|
135590
|
+
};
|
|
135354
135591
|
track(
|
|
135355
|
-
|
|
135356
|
-
()
|
|
135357
|
-
},
|
|
135358
|
-
(error) => {
|
|
135359
|
-
inboundState.abandon(current.rowId, work.key);
|
|
135360
|
-
host.log.warn(
|
|
135361
|
-
"chat could not save inbound state; processing without restart protection",
|
|
135362
|
-
{ rowId: current.rowId, error: describeError(error) }
|
|
135363
|
-
);
|
|
135364
|
-
}
|
|
135365
|
-
).then(() => {
|
|
135366
|
-
const arrived = bindingOf2(current, message.chatId);
|
|
135367
|
-
if (message.chatKind !== void 0 && chatOf(core.state, chatKeyOf(arrived)).chatKind !== message.chatKind) {
|
|
135368
|
-
commit("chat-updated", { chatKey: chatKeyOf(arrived), chatKind: message.chatKind });
|
|
135369
|
-
}
|
|
135370
|
-
enqueueForChat(chatKeyOf(arrived), () => resumeMessage(current, message, work));
|
|
135592
|
+
receipt.then(enqueue, () => {
|
|
135593
|
+
if (!adapter?.redeliversUnacknowledged) enqueue();
|
|
135371
135594
|
})
|
|
135372
135595
|
);
|
|
135596
|
+
return receipt;
|
|
135373
135597
|
}
|
|
135374
135598
|
});
|
|
135375
135599
|
const replay = makeInboxReplay(
|
|
@@ -135509,11 +135733,11 @@ var parseNumberedReply = (item, text4, t) => {
|
|
|
135509
135733
|
// src/questionFlow.ts
|
|
135510
135734
|
var makeQuestionFlow = (host) => {
|
|
135511
135735
|
const { t } = host;
|
|
135512
|
-
const
|
|
135513
|
-
const itemOf = (requestId, questionId) =>
|
|
135736
|
+
const recordOf2 = (requestId) => questionsOf(host.state())[requestId];
|
|
135737
|
+
const itemOf = (requestId, questionId) => recordOf2(requestId)?.items.find((item) => item.id === questionId);
|
|
135514
135738
|
const hasButtons = (chatKey) => host.target(chatKey)?.adapter.choiceCards !== void 0;
|
|
135515
135739
|
const redraw = async (requestId, questionId) => {
|
|
135516
|
-
const record4 =
|
|
135740
|
+
const record4 = recordOf2(requestId);
|
|
135517
135741
|
const item = itemOf(requestId, questionId);
|
|
135518
135742
|
const target2 = record4 === void 0 ? void 0 : host.target(record4.chatKey);
|
|
135519
135743
|
if (record4 === void 0 || item?.cardId === void 0 || target2 === void 0) return;
|
|
@@ -135529,7 +135753,7 @@ var makeQuestionFlow = (host) => {
|
|
|
135529
135753
|
}
|
|
135530
135754
|
};
|
|
135531
135755
|
const freeze = async (requestId, questionId) => {
|
|
135532
|
-
const record4 =
|
|
135756
|
+
const record4 = recordOf2(requestId);
|
|
135533
135757
|
const item = itemOf(requestId, questionId);
|
|
135534
135758
|
const target2 = record4 === void 0 ? void 0 : host.target(record4.chatKey);
|
|
135535
135759
|
if (record4 === void 0 || item?.cardId === void 0 || target2 === void 0) return;
|
|
@@ -135550,7 +135774,7 @@ var makeQuestionFlow = (host) => {
|
|
|
135550
135774
|
}
|
|
135551
135775
|
};
|
|
135552
135776
|
const sayNext = async (requestId) => {
|
|
135553
|
-
const record4 =
|
|
135777
|
+
const record4 = recordOf2(requestId);
|
|
135554
135778
|
if (record4 === void 0 || record4.resolved) return;
|
|
135555
135779
|
const item = record4.items.find(isUnanswered);
|
|
135556
135780
|
if (item === void 0) return;
|
|
@@ -135560,7 +135784,7 @@ var makeQuestionFlow = (host) => {
|
|
|
135560
135784
|
);
|
|
135561
135785
|
};
|
|
135562
135786
|
const post = async (requestId) => {
|
|
135563
|
-
const first =
|
|
135787
|
+
const first = recordOf2(requestId);
|
|
135564
135788
|
const target2 = first === void 0 ? void 0 : host.target(first.chatKey);
|
|
135565
135789
|
if (first === void 0 || target2 === void 0) return;
|
|
135566
135790
|
const cards = target2.adapter.choiceCards;
|
|
@@ -135569,7 +135793,7 @@ var makeQuestionFlow = (host) => {
|
|
|
135569
135793
|
return;
|
|
135570
135794
|
}
|
|
135571
135795
|
for (const questionId of first.items.map((item) => item.id)) {
|
|
135572
|
-
const record4 =
|
|
135796
|
+
const record4 = recordOf2(requestId);
|
|
135573
135797
|
const item = itemOf(requestId, questionId);
|
|
135574
135798
|
if (record4 === void 0 || record4.resolved || item === void 0) return;
|
|
135575
135799
|
try {
|
|
@@ -135579,7 +135803,7 @@ var makeQuestionFlow = (host) => {
|
|
|
135579
135803
|
);
|
|
135580
135804
|
if (cardId === null) continue;
|
|
135581
135805
|
host.commit("question-carded", { requestId, questionId, cardId });
|
|
135582
|
-
const after =
|
|
135806
|
+
const after = recordOf2(requestId);
|
|
135583
135807
|
if (after?.resolved === true || itemOf(requestId, questionId)?.answer !== void 0) {
|
|
135584
135808
|
await freeze(requestId, questionId);
|
|
135585
135809
|
}
|
|
@@ -135596,7 +135820,7 @@ var makeQuestionFlow = (host) => {
|
|
|
135596
135820
|
host.warn("chat cannot show questions on this platform");
|
|
135597
135821
|
return;
|
|
135598
135822
|
}
|
|
135599
|
-
const fresh = pending.filter((request) =>
|
|
135823
|
+
const fresh = pending.filter((request) => recordOf2(request.requestId) === void 0);
|
|
135600
135824
|
for (const request of buttons ? fresh : fresh.slice(0, 1)) {
|
|
135601
135825
|
host.commit("question-offered", {
|
|
135602
135826
|
chatKey,
|
|
@@ -135619,18 +135843,18 @@ var makeQuestionFlow = (host) => {
|
|
|
135619
135843
|
...question.multiSelect ? { submitToken: host.newToken() } : {}
|
|
135620
135844
|
}))
|
|
135621
135845
|
});
|
|
135622
|
-
if (
|
|
135846
|
+
if (recordOf2(request.requestId) === void 0) continue;
|
|
135623
135847
|
host.outbound(chatKey, () => post(request.requestId));
|
|
135624
135848
|
}
|
|
135625
135849
|
};
|
|
135626
135850
|
const answer = async (requestId, questionId, value2, label) => {
|
|
135627
|
-
const before =
|
|
135851
|
+
const before = recordOf2(requestId);
|
|
135628
135852
|
const item = itemOf(requestId, questionId);
|
|
135629
135853
|
if (before === void 0 || before.resolved || item === void 0 || !isUnanswered(item)) {
|
|
135630
135854
|
return false;
|
|
135631
135855
|
}
|
|
135632
135856
|
host.commit("question-answered", { requestId, questionId, answer: value2, label });
|
|
135633
|
-
const after =
|
|
135857
|
+
const after = recordOf2(requestId);
|
|
135634
135858
|
if (after === void 0) return false;
|
|
135635
135859
|
const complete = after.items.every((entry) => !isUnanswered(entry));
|
|
135636
135860
|
if (complete) host.commit("question-resolved", { requestId, ending: "here" });
|
|
@@ -135709,7 +135933,7 @@ var makeQuestionFlow = (host) => {
|
|
|
135709
135933
|
};
|
|
135710
135934
|
const answerText = (input) => answer(input.requestId, input.questionId, input.value, input.label);
|
|
135711
135935
|
const resolved = (requestId, outcome) => {
|
|
135712
|
-
const record4 =
|
|
135936
|
+
const record4 = recordOf2(requestId);
|
|
135713
135937
|
if (record4 === void 0 || record4.resolved) return;
|
|
135714
135938
|
const ending = outcome === "answered" ? "elsewhere" : "cancelled";
|
|
135715
135939
|
host.commit("question-resolved", { requestId, ending });
|
|
@@ -135803,19 +136027,11 @@ var queueCardOf = (record4, view, note, t) => {
|
|
|
135803
136027
|
var queueViewKey = (view, note) => JSON.stringify([view, note]);
|
|
135804
136028
|
|
|
135805
136029
|
// src/queueFlow.ts
|
|
135806
|
-
var LIVE_STATUSES = /* @__PURE__ */ new Set([
|
|
135807
|
-
"queued",
|
|
135808
|
-
"preparing",
|
|
135809
|
-
"dispatching",
|
|
135810
|
-
"running",
|
|
135811
|
-
"reconciling",
|
|
135812
|
-
"blocked"
|
|
135813
|
-
]);
|
|
135814
136030
|
var makeQueueFlow = (host, deps) => {
|
|
135815
136031
|
const { t } = host;
|
|
135816
136032
|
const shown = /* @__PURE__ */ new Map();
|
|
135817
136033
|
const notes = /* @__PURE__ */ new Map();
|
|
135818
|
-
const
|
|
136034
|
+
const recordOf2 = (intentId) => queueOf(host.state())[intentId];
|
|
135819
136035
|
const factsOf = (execution, intentId) => ({
|
|
135820
136036
|
activeTurnId: execution.activeTurnId,
|
|
135821
136037
|
queuePaused: execution.queuePaused,
|
|
@@ -135834,7 +136050,7 @@ var makeQueueFlow = (host, deps) => {
|
|
|
135834
136050
|
const intent = execution?.intents.find((entry) => entry.messageId === messageId);
|
|
135835
136051
|
if (execution === null || intent === void 0 || intent.status !== "queued") return;
|
|
135836
136052
|
const waiting = execution.activeTurnId !== null || execution.queuePaused || execution.intents.some(
|
|
135837
|
-
(other) => other.intentId !== intent.intentId &&
|
|
136053
|
+
(other) => other.intentId !== intent.intentId && isLiveIntentStatus(other.status) && other.sequence < intent.sequence
|
|
135838
136054
|
);
|
|
135839
136055
|
if (!waiting) return;
|
|
135840
136056
|
const cards = target2.adapter.choiceCards;
|
|
@@ -135853,7 +136069,7 @@ var makeQueueFlow = (host, deps) => {
|
|
|
135853
136069
|
resumeToken: host.newToken()
|
|
135854
136070
|
});
|
|
135855
136071
|
host.outbound(chatKey, async () => {
|
|
135856
|
-
const record4 =
|
|
136072
|
+
const record4 = recordOf2(intentId);
|
|
135857
136073
|
if (record4 === void 0) return;
|
|
135858
136074
|
try {
|
|
135859
136075
|
const latest = await deps.readExecution(threadId) ?? execution;
|
|
@@ -135879,7 +136095,7 @@ var makeQueueFlow = (host, deps) => {
|
|
|
135879
136095
|
});
|
|
135880
136096
|
};
|
|
135881
136097
|
const redraw = async (intentId, released) => {
|
|
135882
|
-
const record4 =
|
|
136098
|
+
const record4 = recordOf2(intentId);
|
|
135883
136099
|
const target2 = record4 === void 0 ? void 0 : host.target(record4.chatKey);
|
|
135884
136100
|
if (record4 === void 0 || record4.settled !== void 0 || target2 === void 0) return;
|
|
135885
136101
|
if (record4.cardId === void 0) return;
|
|
@@ -138283,6 +138499,9 @@ var fetchUserName = async (input) => {
|
|
|
138283
138499
|
};
|
|
138284
138500
|
var sendChatText = async (input) => postMessage({ ...input, operation: "send", msgType: "text", content: { text: input.text } });
|
|
138285
138501
|
var LARK_WORKING_REACTION = "OnIt";
|
|
138502
|
+
var LARK_DONE_REACTION = "DONE";
|
|
138503
|
+
var LARK_FAILED_REACTION = "ERROR";
|
|
138504
|
+
var LARK_REACTION_TIMEOUT_MS = 2e3;
|
|
138286
138505
|
var addReaction = async (input) => {
|
|
138287
138506
|
const response = await input.http(
|
|
138288
138507
|
`${LARK_BASE}/im/v1/messages/${encodeURIComponent(input.messageId)}/reactions`,
|
|
@@ -138292,7 +138511,8 @@ var addReaction = async (input) => {
|
|
|
138292
138511
|
authorization: `Bearer ${input.token}`,
|
|
138293
138512
|
"content-type": "application/json; charset=utf-8"
|
|
138294
138513
|
},
|
|
138295
|
-
body: JSON.stringify({ reaction_type: { emoji_type: input.emojiType } })
|
|
138514
|
+
body: JSON.stringify({ reaction_type: { emoji_type: input.emojiType } }),
|
|
138515
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
138296
138516
|
}
|
|
138297
138517
|
);
|
|
138298
138518
|
const body = await readEnvelope("reactions.create", response);
|
|
@@ -138303,7 +138523,8 @@ var removeReaction = async (input) => {
|
|
|
138303
138523
|
`${LARK_BASE}/im/v1/messages/${encodeURIComponent(input.messageId)}/reactions/${encodeURIComponent(input.reactionId)}`,
|
|
138304
138524
|
{
|
|
138305
138525
|
method: "DELETE",
|
|
138306
|
-
headers: { authorization: `Bearer ${input.token}` }
|
|
138526
|
+
headers: { authorization: `Bearer ${input.token}` },
|
|
138527
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
138307
138528
|
}
|
|
138308
138529
|
);
|
|
138309
138530
|
await readEnvelope("reactions.delete", response);
|
|
@@ -144071,7 +144292,7 @@ var cardActionOperator = (event) => {
|
|
|
144071
144292
|
};
|
|
144072
144293
|
var startLarkInbound = (input) => {
|
|
144073
144294
|
const dispatcher = new import_node_sdk.EventDispatcher({}).register({
|
|
144074
|
-
"im.message.receive_v1": (event) => {
|
|
144295
|
+
"im.message.receive_v1": async (event) => {
|
|
144075
144296
|
const mode = input.groupMention ?? "always";
|
|
144076
144297
|
const parse = (groupMention) => parseInboundMessage(
|
|
144077
144298
|
event,
|
|
@@ -144081,17 +144302,16 @@ var startLarkInbound = (input) => {
|
|
|
144081
144302
|
);
|
|
144082
144303
|
const parsed = parse(mode);
|
|
144083
144304
|
if (parsed !== null) {
|
|
144084
|
-
input.onMessage(parsed);
|
|
144305
|
+
await input.onMessage(parsed);
|
|
144085
144306
|
return {};
|
|
144086
144307
|
}
|
|
144087
144308
|
const chat = event.message;
|
|
144088
144309
|
if (mode === "always" && input.isSoloGroup !== void 0 && chat?.chat_type !== "p2p") {
|
|
144089
144310
|
const chatId = chat?.chat_id;
|
|
144090
144311
|
if (typeof chatId === "string") {
|
|
144091
|
-
|
|
144092
|
-
|
|
144093
|
-
|
|
144094
|
-
});
|
|
144312
|
+
const solo = await input.isSoloGroup(chatId).catch(() => false);
|
|
144313
|
+
const relaxed = solo ? parse("never") : null;
|
|
144314
|
+
if (relaxed !== null) await input.onMessage(relaxed);
|
|
144095
144315
|
}
|
|
144096
144316
|
}
|
|
144097
144317
|
return {};
|
|
@@ -144129,7 +144349,7 @@ var startLarkInbound = (input) => {
|
|
|
144129
144349
|
state: "failed",
|
|
144130
144350
|
reason: hint === "larkCredentials" ? "credentials-rejected" : "disconnected",
|
|
144131
144351
|
error,
|
|
144132
|
-
...
|
|
144352
|
+
...connectionHintFields(error, hint)
|
|
144133
144353
|
});
|
|
144134
144354
|
}
|
|
144135
144355
|
};
|
|
@@ -144188,6 +144408,22 @@ var larkInboundPersistence = (contextFor) => ({
|
|
|
144188
144408
|
}
|
|
144189
144409
|
});
|
|
144190
144410
|
|
|
144411
|
+
// src/deadline.ts
|
|
144412
|
+
var withDeadline2 = async (timeoutMs, load) => {
|
|
144413
|
+
const signal = AbortSignal.timeout(timeoutMs);
|
|
144414
|
+
let onAbort = () => {
|
|
144415
|
+
};
|
|
144416
|
+
const aborted = new Promise((_, reject) => {
|
|
144417
|
+
onAbort = () => reject(signal.reason);
|
|
144418
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
144419
|
+
});
|
|
144420
|
+
try {
|
|
144421
|
+
return await Promise.race([load(signal), aborted]);
|
|
144422
|
+
} finally {
|
|
144423
|
+
signal.removeEventListener("abort", onAbort);
|
|
144424
|
+
}
|
|
144425
|
+
};
|
|
144426
|
+
|
|
144191
144427
|
// src/boundedSeen.ts
|
|
144192
144428
|
var makeBoundedSeen = (limit) => {
|
|
144193
144429
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -144206,22 +144442,6 @@ var makeBoundedSeen = (limit) => {
|
|
|
144206
144442
|
};
|
|
144207
144443
|
};
|
|
144208
144444
|
|
|
144209
|
-
// src/deadline.ts
|
|
144210
|
-
var withDeadline2 = async (timeoutMs, load) => {
|
|
144211
|
-
const signal = AbortSignal.timeout(timeoutMs);
|
|
144212
|
-
let onAbort = () => {
|
|
144213
|
-
};
|
|
144214
|
-
const aborted = new Promise((_, reject) => {
|
|
144215
|
-
onAbort = () => reject(signal.reason);
|
|
144216
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
144217
|
-
});
|
|
144218
|
-
try {
|
|
144219
|
-
return await Promise.race([load(signal), aborted]);
|
|
144220
|
-
} finally {
|
|
144221
|
-
signal.removeEventListener("abort", onAbort);
|
|
144222
|
-
}
|
|
144223
|
-
};
|
|
144224
|
-
|
|
144225
144445
|
// src/replyReference.ts
|
|
144226
144446
|
import * as NodeCrypto4 from "node:crypto";
|
|
144227
144447
|
|
|
@@ -144670,10 +144890,12 @@ var makeLarkAdapter = (deps) => {
|
|
|
144670
144890
|
};
|
|
144671
144891
|
const soloGroupFor = (context2) => async (chatId) => {
|
|
144672
144892
|
const info = await context2.chatInfo(chatId);
|
|
144673
|
-
|
|
144893
|
+
if (info?.userCount === void 0 || info.botCount === void 0) return false;
|
|
144894
|
+
return info.userCount <= 1 && info.botCount <= 1;
|
|
144674
144895
|
};
|
|
144675
144896
|
return {
|
|
144676
144897
|
platform: "lark",
|
|
144898
|
+
redeliversUnacknowledged: true,
|
|
144677
144899
|
...larkInboundPersistence((rowId) => messageContexts.get(rowId)?.context),
|
|
144678
144900
|
botIdentity: (bot) => larkCredentials(bot).appId,
|
|
144679
144901
|
icon: "lark",
|
|
@@ -144781,15 +145003,27 @@ var makeLarkAdapter = (deps) => {
|
|
|
144781
145003
|
const key = JSON.stringify([message.chatId, topic?.threadId]);
|
|
144782
145004
|
const earlier = pendingDeliveries.get(key);
|
|
144783
145005
|
if (earlier === void 0 && pending === null && reference2 === null && !(prepared instanceof Promise) && !(source instanceof Promise)) {
|
|
144784
|
-
deliver(prepared, source);
|
|
145006
|
+
return deliver(prepared, source);
|
|
144785
145007
|
} else {
|
|
144786
|
-
const completed = Promise.all([
|
|
145008
|
+
const completed = Promise.all([
|
|
145009
|
+
earlier?.catch(() => {
|
|
145010
|
+
}),
|
|
145011
|
+
pending,
|
|
145012
|
+
reference2,
|
|
145013
|
+
source,
|
|
145014
|
+
prepared
|
|
145015
|
+
]).then(([, , replyTo, names, ready]) => {
|
|
144787
145016
|
if (pendingDeliveries.get(key) === completed) pendingDeliveries.delete(key);
|
|
144788
|
-
if (open)
|
|
144789
|
-
|
|
145017
|
+
if (!open) throw new Error("lark inbound connection is closed");
|
|
145018
|
+
return deliver(ready, names, replyTo ?? void 0);
|
|
145019
|
+
}).catch((error) => {
|
|
145020
|
+
handlers.onError(describeError(error));
|
|
145021
|
+
throw error;
|
|
145022
|
+
}).finally(() => {
|
|
144790
145023
|
if (pendingDeliveries.get(key) === completed) pendingDeliveries.delete(key);
|
|
144791
145024
|
});
|
|
144792
145025
|
pendingDeliveries.set(key, completed);
|
|
145026
|
+
return completed;
|
|
144793
145027
|
}
|
|
144794
145028
|
}
|
|
144795
145029
|
});
|
|
@@ -144841,12 +145075,11 @@ var makeLarkAdapter = (deps) => {
|
|
|
144841
145075
|
detail: `token ok; expiresIn=${String(expiresInSeconds)}s`
|
|
144842
145076
|
};
|
|
144843
145077
|
} catch (error) {
|
|
144844
|
-
const hint = larkConnectionHint(error);
|
|
144845
145078
|
return {
|
|
144846
145079
|
stage: "tenant_access_token",
|
|
144847
145080
|
ok: false,
|
|
144848
145081
|
detail: describeError(error),
|
|
144849
|
-
...
|
|
145082
|
+
...connectionHintFields(error, larkConnectionHint(error))
|
|
144850
145083
|
};
|
|
144851
145084
|
}
|
|
144852
145085
|
},
|
|
@@ -144951,13 +145184,22 @@ var makeLarkAdapter = (deps) => {
|
|
|
144951
145184
|
messageId,
|
|
144952
145185
|
emojiType: LARK_WORKING_REACTION
|
|
144953
145186
|
}),
|
|
144954
|
-
clearAcknowledge: async (binding, messageId, ackId) => {
|
|
144955
|
-
await
|
|
144956
|
-
|
|
144957
|
-
|
|
144958
|
-
messageId,
|
|
144959
|
-
|
|
144960
|
-
|
|
145187
|
+
clearAcknowledge: async (binding, messageId, ackId, outcome) => {
|
|
145188
|
+
const token = await tenantToken(binding);
|
|
145189
|
+
await withDeadline2(
|
|
145190
|
+
LARK_REACTION_TIMEOUT_MS,
|
|
145191
|
+
(signal) => removeReaction({ http: deps.http, token, messageId, reactionId: ackId, signal })
|
|
145192
|
+
);
|
|
145193
|
+
const emojiType = outcome === "done" ? LARK_DONE_REACTION : outcome === "failed" ? LARK_FAILED_REACTION : null;
|
|
145194
|
+
if (emojiType === null) return;
|
|
145195
|
+
try {
|
|
145196
|
+
await withDeadline2(
|
|
145197
|
+
LARK_REACTION_TIMEOUT_MS,
|
|
145198
|
+
(signal) => addReaction({ http: deps.http, token, messageId, emojiType, signal })
|
|
145199
|
+
);
|
|
145200
|
+
} catch (error) {
|
|
145201
|
+
deps.log.warn("lark could not react to the message", { error: describeError(error) });
|
|
145202
|
+
}
|
|
144961
145203
|
},
|
|
144962
145204
|
fetchResource: async (binding, input) => {
|
|
144963
145205
|
const resource = input.resource;
|
|
@@ -145194,6 +145436,13 @@ var en_default = {
|
|
|
145194
145436
|
turnFailedNoDetail: "This turn didn't finish. Reference {{ref}}. Send the message again; if it keeps failing, send /new to start a new conversation.",
|
|
145195
145437
|
turnFailedBrief: "This turn didn't finish: {{detail}}\nSend the message again; if it keeps failing, send /new to start a new conversation.",
|
|
145196
145438
|
turnFailedBriefNoDetail: "This turn didn't finish. Send the message again; if it keeps failing, send /new to start a new conversation.",
|
|
145439
|
+
turnFailedWithReference: "{{message}}\nReference {{ref}}.",
|
|
145440
|
+
turnFailedQuota: "The model quota or balance is insufficient, so this turn didn't finish. Send /model to switch to another model, or ask an administrator to add quota, then try again.",
|
|
145441
|
+
turnFailedRateLimit: "The model service is rate-limiting requests, so this turn didn't finish. Please try again later.",
|
|
145442
|
+
turnFailedContextLimit: "This conversation exceeds the model context limit, so this turn didn't finish. Send /new to start a new conversation, then send your request again.",
|
|
145443
|
+
turnFailedAuth: "The model credentials are missing or invalid, so this turn didn't finish. Ask an administrator to check the model settings, then try again.",
|
|
145444
|
+
turnFailedModelUnavailable: "The current model does not exist or does not support the selected settings, so this turn didn't finish. Send /model to list models, then send /model followed by a number (for example /model 2) to pick one for this chat, and send your request again.",
|
|
145445
|
+
turnFailedTransport: "The model service is temporarily unreachable, so this turn didn't finish. Please try again later.",
|
|
145197
145446
|
attachmentReceived: "Got {{names}} ({{count}} waiting). Tell me what to do with them.",
|
|
145198
145447
|
attachmentFailed: "Could not take {{name}}: {{reason}}.",
|
|
145199
145448
|
attachmentReason: {
|
|
@@ -145545,6 +145794,16 @@ var en_default = {
|
|
|
145545
145794
|
failed: "Connection failed",
|
|
145546
145795
|
notSaved: "Save this row first (credentials are read from saved config only).",
|
|
145547
145796
|
hint: {
|
|
145797
|
+
networkMultipleCauses: "This failure has more than one network cause. Check this machine's network and this bot's Proxy setting, then check again.",
|
|
145798
|
+
networkDns: "The service's domain name could not be resolved. Check this machine's DNS and network settings, then check again.",
|
|
145799
|
+
networkRefused: "The connection was refused. Check whether a firewall or security software on this machine or its network is blocking it, then check again.",
|
|
145800
|
+
networkReset: "The connection was cut off by the other side. Check this machine's network and whether the target service is running normally, then check again.",
|
|
145801
|
+
networkUnreachable: "The target network is unreachable. Check this machine's outbound network access and access restrictions, then check again.",
|
|
145802
|
+
networkTls: "TLS or certificate validation failed. Check this machine's system clock, certificate chain and network settings, and whether a proxy or security software is intercepting HTTPS, then check again.",
|
|
145803
|
+
networkTimeout: "The request timed out. Check whether the target service is running normally and check this machine's network, then check again.",
|
|
145804
|
+
networkProxy: "Proxy connection or authentication failed. Check this row's Proxy setting and the selected proxy's configuration on this machine; if no proxy is set, check other proxies on this machine or its network, then check again.",
|
|
145805
|
+
platformRateLimited: "The platform is rate limiting requests. Try again later.",
|
|
145806
|
+
platformUnavailable: "The target service is temporarily having problems. Try again later.",
|
|
145548
145807
|
connecting: "Still connecting. There is usually a result within 20 seconds; check again in a moment.",
|
|
145549
145808
|
badToken: "This does not look like a bot token. Copy it again from BotFather: digits, a colon, then the key.",
|
|
145550
145809
|
unauthorized: "Telegram does not accept this token. It may have been revoked; get the current one from BotFather. Save the corrected token here to reconnect automatically; if nothing needs changing, use Reconnect below.",
|
|
@@ -145964,6 +146223,13 @@ var zh_CN_default = {
|
|
|
145964
146223
|
turnFailedNoDetail: "\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\u3002\u53C2\u8003\u53F7 {{ref}}\u3002\u53EF\u4EE5\u76F4\u63A5\u518D\u53D1\u4E00\u6B21\uFF1B\u4E00\u76F4\u4E0D\u884C\u5C31\u53D1 /new \u5F00\u4E2A\u65B0\u4F1A\u8BDD\u3002",
|
|
145965
146224
|
turnFailedBrief: "\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\uFF1A{{detail}}\n\u53EF\u4EE5\u76F4\u63A5\u518D\u53D1\u4E00\u6B21\uFF1B\u4E00\u76F4\u4E0D\u884C\u5C31\u53D1 /new \u5F00\u4E2A\u65B0\u4F1A\u8BDD\u3002",
|
|
145966
146225
|
turnFailedBriefNoDetail: "\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\u3002\u53EF\u4EE5\u76F4\u63A5\u518D\u53D1\u4E00\u6B21\uFF1B\u4E00\u76F4\u4E0D\u884C\u5C31\u53D1 /new \u5F00\u4E2A\u65B0\u4F1A\u8BDD\u3002",
|
|
146226
|
+
turnFailedWithReference: "{{message}}\n\u53C2\u8003\u53F7 {{ref}}\u3002",
|
|
146227
|
+
turnFailedQuota: "\u6A21\u578B\u989D\u5EA6\u6216\u4F59\u989D\u4E0D\u8DB3\uFF0C\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\u3002\u53EF\u4EE5\u53D1 /model \u6362\u4E2A\u6A21\u578B\u518D\u8BD5\uFF0C\u6216\u8BF7\u7BA1\u7406\u5458\u8865\u5145\u989D\u5EA6\u540E\u91CD\u8BD5\u3002",
|
|
146228
|
+
turnFailedRateLimit: "\u6A21\u578B\u670D\u52A1\u6B63\u5728\u9650\u6D41\uFF0C\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\u3002\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
|
|
146229
|
+
turnFailedContextLimit: "\u5F53\u524D\u4F1A\u8BDD\u5185\u5BB9\u8D85\u8FC7\u6A21\u578B\u4E0A\u4E0B\u6587\u4E0A\u9650\uFF0C\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\u3002\u8BF7\u53D1 /new \u5F00\u4E2A\u65B0\u4F1A\u8BDD\uFF0C\u518D\u628A\u8BF7\u6C42\u91CD\u65B0\u53D1\u4E00\u904D\u3002",
|
|
146230
|
+
turnFailedAuth: "\u6A21\u578B\u51ED\u636E\u7F3A\u5931\u6216\u65E0\u6548\uFF0C\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\u3002\u8BF7\u7BA1\u7406\u5458\u68C0\u67E5\u6A21\u578B\u914D\u7F6E\uFF0C\u4E4B\u540E\u4F60\u518D\u53D1\u4E00\u6B21\u3002",
|
|
146231
|
+
turnFailedModelUnavailable: "\u5F53\u524D\u6A21\u578B\u4E0D\u5B58\u5728\u6216\u4E0D\u652F\u6301\u6240\u9009\u914D\u7F6E\uFF0C\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\u3002\u8BF7\u53D1 /model \u67E5\u770B\u53EF\u9009\u6A21\u578B\uFF0C\u518D\u53D1 /model \u52A0\u7F16\u53F7\uFF08\u4F8B\u5982 /model 2\uFF09\u4E3A\u8FD9\u4E2A\u804A\u5929\u9009\u4E00\u4E2A\uFF0C\u7136\u540E\u91CD\u53D1\u8BF7\u6C42\u3002",
|
|
146232
|
+
turnFailedTransport: "\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u6A21\u578B\u670D\u52A1\uFF0C\u8FD9\u4E00\u8F6E\u6CA1\u80FD\u5B8C\u6210\u3002\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
|
|
145967
146233
|
attachmentReceived: "\u6536\u5230 {{names}}\uFF08\u73B0\u6709 {{count}} \u4E2A\u5F85\u5904\u7406\uFF09\u3002\u8BF4\u4E00\u53E5\u60F3\u8BA9\u6211\u600E\u4E48\u5904\u7406\u3002",
|
|
145968
146234
|
attachmentFailed: "\u6CA1\u80FD\u6536\u4E0B {{name}}\uFF1A{{reason}}\u3002",
|
|
145969
146235
|
attachmentReason: {
|
|
@@ -146315,6 +146581,16 @@ var zh_CN_default = {
|
|
|
146315
146581
|
failed: "\u8FDE\u63A5\u5931\u8D25",
|
|
146316
146582
|
notSaved: "\u8BF7\u5148\u4FDD\u5B58\u8FD9\u4E00\u884C\u518D\u68C0\u67E5\u8FDE\u63A5\uFF08\u51ED\u636E\u53EA\u4ECE\u5DF2\u4FDD\u5B58\u914D\u7F6E\u8BFB\u53D6\uFF09\u3002",
|
|
146317
146583
|
hint: {
|
|
146584
|
+
networkMultipleCauses: "\u8FD9\u6B21\u5931\u8D25\u80CC\u540E\u4E0D\u6B62\u4E00\u79CD\u7F51\u7EDC\u95EE\u9898\u3002\u8BF7\u68C0\u67E5\u8FD9\u53F0\u673A\u5668\u7684\u7F51\u7EDC\u548C\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u300C\u4EE3\u7406\u300D\u8BBE\u7F6E\uFF0C\u518D\u68C0\u67E5\u4E00\u6B21\u3002",
|
|
146585
|
+
networkDns: "\u670D\u52A1\u57DF\u540D\u89E3\u6790\u5931\u8D25\u3002\u8BF7\u68C0\u67E5\u8FD9\u53F0\u673A\u5668\u7684 DNS \u548C\u7F51\u7EDC\u8BBE\u7F6E\uFF0C\u518D\u68C0\u67E5\u4E00\u6B21\u3002",
|
|
146586
|
+
networkRefused: "\u76EE\u6807\u62D2\u7EDD\u4E86\u8FDE\u63A5\u3002\u8BF7\u68C0\u67E5\u8FD9\u53F0\u673A\u5668\u548C\u6240\u5728\u7F51\u7EDC\u7684\u9632\u706B\u5899\u3001\u5B89\u5168\u8F6F\u4EF6\u662F\u5426\u62E6\u4E86\u8FD9\u4E2A\u8FDE\u63A5\uFF0C\u518D\u68C0\u67E5\u4E00\u6B21\u3002",
|
|
146587
|
+
networkReset: "\u8FDE\u63A5\u88AB\u5BF9\u65B9\u4E2D\u65AD\u3002\u8BF7\u68C0\u67E5\u8FD9\u53F0\u673A\u5668\u7684\u7F51\u7EDC\uFF0C\u4EE5\u53CA\u76EE\u6807\u670D\u52A1\u662F\u5426\u5728\u6B63\u5E38\u8FD0\u884C\uFF0C\u518D\u68C0\u67E5\u4E00\u6B21\u3002",
|
|
146588
|
+
networkUnreachable: "\u76EE\u6807\u7F51\u7EDC\u4E0D\u53EF\u8FBE\u3002\u8BF7\u68C0\u67E5\u8FD9\u53F0\u673A\u5668\u7684\u7F51\u7EDC\u51FA\u53E3\u548C\u8BBF\u95EE\u9650\u5236\uFF0C\u518D\u68C0\u67E5\u4E00\u6B21\u3002",
|
|
146589
|
+
networkTls: "TLS \u6216\u8BC1\u4E66\u6821\u9A8C\u5931\u8D25\u3002\u8BF7\u68C0\u67E5\u8FD9\u53F0\u673A\u5668\u7684\u7CFB\u7EDF\u65F6\u95F4\u3001\u8BC1\u4E66\u94FE\u548C\u7F51\u7EDC\u8BBE\u7F6E\uFF0C\u4EE5\u53CA\u4EE3\u7406\u6216\u5B89\u5168\u8F6F\u4EF6\u662F\u5426\u62E6\u622A\u4E86 HTTPS \u8FDE\u63A5\uFF0C\u518D\u68C0\u67E5\u4E00\u6B21\u3002",
|
|
146590
|
+
networkTimeout: "\u8BF7\u6C42\u8D85\u65F6\u3002\u8BF7\u786E\u8BA4\u76EE\u6807\u670D\u52A1\u662F\u5426\u5728\u6B63\u5E38\u8FD0\u884C\uFF0C\u5E76\u68C0\u67E5\u8FD9\u53F0\u673A\u5668\u7684\u7F51\u7EDC\uFF0C\u518D\u68C0\u67E5\u4E00\u6B21\u3002",
|
|
146591
|
+
networkProxy: "\u4EE3\u7406\u8FDE\u63A5\u6216\u8BA4\u8BC1\u5931\u8D25\u3002\u8BF7\u68C0\u67E5\u8FD9\u4E00\u884C\u7684\u300C\u4EE3\u7406\u300D\u8BBE\u7F6E\u548C\u6240\u9009\u4EE3\u7406\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u7684\u914D\u7F6E\uFF1B\u6CA1\u8BBE\u4EE3\u7406\u7684\u8BDD\uFF0C\u68C0\u67E5\u8FD9\u53F0\u673A\u5668\u6216\u6240\u5728\u7F51\u7EDC\u4E0A\u7684\u5176\u4ED6\u4EE3\u7406\uFF0C\u518D\u68C0\u67E5\u4E00\u6B21\u3002",
|
|
146592
|
+
platformRateLimited: "\u5E73\u53F0\u6B63\u5728\u9650\u6D41\u3002\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
|
|
146593
|
+
platformUnavailable: "\u76EE\u6807\u670D\u52A1\u6682\u65F6\u5F02\u5E38\u3002\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
|
|
146318
146594
|
connecting: "\u8FD8\u5728\u8FDE\u63A5\uFF0C\u4E00\u822C 20 \u79D2\u5185\u4F1A\u6709\u7ED3\u679C\uFF0C\u7A0D\u540E\u518D\u68C0\u67E5\u4E00\u6B21\u3002",
|
|
146319
146595
|
badToken: "\u8FD9\u4E0D\u50CF\u673A\u5668\u4EBA\u7684 token\u3002\u5230 BotFather \u91CD\u65B0\u590D\u5236\u4E00\u4EFD\uFF1A\u6570\u5B57\u3001\u5192\u53F7\uFF0C\u540E\u9762\u662F\u5BC6\u94A5\u3002",
|
|
146320
146596
|
unauthorized: "Telegram \u4E0D\u8BA4\u8FD9\u4E2A token\uFF0C\u53EF\u80FD\u5DF2\u7ECF\u4F5C\u5E9F\u3002\u5230 BotFather \u53D6\u73B0\u5728\u7684\u90A3\u4E00\u4EFD\u3002\u6539\u597D\u540E\u5728\u8FD9\u91CC\u4FDD\u5B58\uFF0C\u673A\u5668\u4EBA\u4F1A\u81EA\u52A8\u91CD\u65B0\u8FDE\u63A5\uFF1B\u6CA1\u6709\u8981\u6539\u7684\u4E5F\u53EF\u4EE5\u70B9\u4E0B\u65B9\u7684\u300C\u91CD\u65B0\u8FDE\u63A5\u300D\u3002",
|
|
@@ -146643,13 +146919,13 @@ var makeModelPlan = (core, deps) => {
|
|
|
146643
146919
|
import { readThreadFailed, threadOrNull as threadOrNull5 } from "@ycodium-ai/plugin-api";
|
|
146644
146920
|
|
|
146645
146921
|
// src/conclusionOutbox.ts
|
|
146646
|
-
var enqueueConclusion = (core, ledger, binding,
|
|
146922
|
+
var enqueueConclusion = (core, ledger, binding, selection, send) => core.outbound(
|
|
146647
146923
|
chatKeyOf(binding),
|
|
146648
146924
|
async () => {
|
|
146649
|
-
if (
|
|
146650
|
-
else await ledger.deliver(
|
|
146925
|
+
if (selection === void 0) await send();
|
|
146926
|
+
else await ledger.deliver(selection, send);
|
|
146651
146927
|
},
|
|
146652
|
-
{ droppable:
|
|
146928
|
+
{ droppable: selection !== void 0 }
|
|
146653
146929
|
);
|
|
146654
146930
|
|
|
146655
146931
|
// src/conclusionRecovery.ts
|
|
@@ -146665,60 +146941,100 @@ var makeConclusionRecovery = (core, ledger, delivery, failures) => {
|
|
|
146665
146941
|
error: describeError(error)
|
|
146666
146942
|
});
|
|
146667
146943
|
};
|
|
146668
|
-
const
|
|
146944
|
+
const recoverThread = async (threadId, debts, requestedMessageId) => {
|
|
146669
146945
|
await core.ready;
|
|
146670
146946
|
if (disposed) return;
|
|
146671
146947
|
try {
|
|
146672
|
-
const execution = await core.host.projections.getThreadExecution(
|
|
146948
|
+
const execution = await core.host.projections.getThreadExecution(threadId);
|
|
146673
146949
|
if (disposed) return;
|
|
146674
146950
|
if (execution === null) {
|
|
146675
|
-
|
|
146676
|
-
|
|
146677
|
-
|
|
146678
|
-
|
|
146679
|
-
if (latest?.userMessageId !== debt.userMessageId) {
|
|
146680
|
-
core.host.log.info("chat discarded a conclusion whose turn is no longer latest", {
|
|
146681
|
-
...debt
|
|
146682
|
-
});
|
|
146683
|
-
ledger.discard(debt);
|
|
146684
|
-
return;
|
|
146685
|
-
}
|
|
146686
|
-
if (latest.state === "running" || execution.session?.activeTurnId != null) return;
|
|
146687
|
-
if (latest.completedAt !== null && Date.parse(latest.completedAt) < Date.now() - MAX_AGE_MS) {
|
|
146688
|
-
core.host.log.info("chat discarded a conclusion older than seven days", { ...debt });
|
|
146689
|
-
ledger.discard(debt);
|
|
146951
|
+
for (const debt of debts) {
|
|
146952
|
+
if (requestedMessageId === void 0 || debt.userMessageId === requestedMessageId)
|
|
146953
|
+
ledger.discard({ debt, turnUserMessageId: void 0 });
|
|
146954
|
+
}
|
|
146690
146955
|
return;
|
|
146691
146956
|
}
|
|
146692
|
-
const
|
|
146693
|
-
|
|
146694
|
-
|
|
146695
|
-
|
|
146696
|
-
|
|
146697
|
-
|
|
146698
|
-
|
|
146699
|
-
debt
|
|
146700
|
-
|
|
146701
|
-
|
|
146702
|
-
latest.turnId,
|
|
146703
|
-
owed
|
|
146704
|
-
);
|
|
146957
|
+
const snapshot = indexExecution(execution);
|
|
146958
|
+
const grouped = groupConclusionDebts(snapshot, threadId, debts);
|
|
146959
|
+
const { resolved, byTurn } = grouped;
|
|
146960
|
+
for (const { debt, result: result2 } of resolved.values()) {
|
|
146961
|
+
if (result2.kind === "gone") {
|
|
146962
|
+
if (requestedMessageId === void 0 || debt.userMessageId === requestedMessageId) {
|
|
146963
|
+
core.host.log.info("chat discarded a conclusion whose message has no turn", {
|
|
146964
|
+
...debt
|
|
146965
|
+
});
|
|
146966
|
+
ledger.discard({ debt, turnUserMessageId: void 0 });
|
|
146705
146967
|
}
|
|
146706
|
-
const send = await delivery.prepareConclusion(debt.threadId, latest.turnId);
|
|
146707
|
-
return send(binding, { recovered: true, streaming: false, owed });
|
|
146708
|
-
} catch (error) {
|
|
146709
|
-
couldNotRecover(debt, error);
|
|
146710
|
-
return false;
|
|
146711
146968
|
}
|
|
146712
|
-
}
|
|
146969
|
+
}
|
|
146970
|
+
const requested = requestedMessageId === void 0 ? void 0 : resolved.get(requestedMessageId)?.result;
|
|
146971
|
+
for (const turnId of byTurn.keys()) {
|
|
146972
|
+
if (requestedMessageId !== void 0 && (requested?.kind !== "settled" && requested?.kind !== "merged" || requested.turnId !== turnId))
|
|
146973
|
+
continue;
|
|
146974
|
+
const { selection, handled } = ledger.forExecutionTurn(snapshot, threadId, turnId, grouped);
|
|
146975
|
+
if (handled || selection === void 0 || requestedMessageId !== void 0 && selection.debt.userMessageId !== requestedMessageId)
|
|
146976
|
+
continue;
|
|
146977
|
+
const result2 = resolved.get(selection.debt.userMessageId).result;
|
|
146978
|
+
if (result2.kind === "pending" || result2.kind === "gone") continue;
|
|
146979
|
+
recoverTurn(selection, result2.kind === "settled" ? result2 : result2.turn, execution);
|
|
146980
|
+
}
|
|
146713
146981
|
} catch (error) {
|
|
146714
|
-
couldNotRecover(debt, error);
|
|
146982
|
+
for (const debt of debts) couldNotRecover(debt, error);
|
|
146983
|
+
}
|
|
146984
|
+
};
|
|
146985
|
+
const recoverTurn = (selection, turn, execution) => {
|
|
146986
|
+
const { debt } = selection;
|
|
146987
|
+
if (turn === void 0 || turn.state === "pending" || turn.state === "running" || execution.session?.activeTurnId === turn.turnId)
|
|
146988
|
+
return;
|
|
146989
|
+
if (turn.completedAt !== null && Date.parse(turn.completedAt) < Date.now() - MAX_AGE_MS) {
|
|
146990
|
+
core.host.log.info("chat discarded a conclusion older than seven days", { ...debt });
|
|
146991
|
+
ledger.discard(selection);
|
|
146992
|
+
return;
|
|
146715
146993
|
}
|
|
146994
|
+
const binding = core.bindingForChatKey(selection.debt.chatKey);
|
|
146995
|
+
if (binding === void 0) return;
|
|
146996
|
+
enqueueConclusion(core, ledger, binding, selection, async (owed) => {
|
|
146997
|
+
try {
|
|
146998
|
+
if (turn.state === "error") {
|
|
146999
|
+
const session = execution.latestTurn?.state === "error" && execution.latestTurn.turnId === turn.turnId ? execution.session : void 0;
|
|
147000
|
+
return delivery.sendText(
|
|
147001
|
+
binding,
|
|
147002
|
+
debt.threadId,
|
|
147003
|
+
failures.forFailure(debt.threadId, session?.lastError, session?.failureCategory),
|
|
147004
|
+
true,
|
|
147005
|
+
turn.turnId,
|
|
147006
|
+
owed
|
|
147007
|
+
);
|
|
147008
|
+
}
|
|
147009
|
+
const send = await delivery.prepareConclusion(debt.threadId, turn.turnId);
|
|
147010
|
+
return send(binding, { recovered: true, streaming: false, owed });
|
|
147011
|
+
} catch (error) {
|
|
147012
|
+
couldNotRecover(debt, error);
|
|
147013
|
+
return false;
|
|
147014
|
+
}
|
|
147015
|
+
});
|
|
147016
|
+
};
|
|
147017
|
+
const recoverConclusion = async (debt) => {
|
|
147018
|
+
await core.ready;
|
|
147019
|
+
await recoverThread(
|
|
147020
|
+
debt.threadId,
|
|
147021
|
+
Object.values(conclusionDebtsOf(core.state)).filter(
|
|
147022
|
+
(candidate) => candidate.threadId === debt.threadId
|
|
147023
|
+
),
|
|
147024
|
+
debt.userMessageId
|
|
147025
|
+
);
|
|
146716
147026
|
};
|
|
146717
147027
|
const recoverConclusions = async () => {
|
|
146718
147028
|
await core.ready;
|
|
147029
|
+
const byThread = /* @__PURE__ */ new Map();
|
|
146719
147030
|
for (const debt of Object.values(conclusionDebtsOf(core.state))) {
|
|
147031
|
+
const group = byThread.get(debt.threadId) ?? [];
|
|
147032
|
+
group.push(debt);
|
|
147033
|
+
byThread.set(debt.threadId, group);
|
|
147034
|
+
}
|
|
147035
|
+
for (const [threadId, debts] of byThread) {
|
|
146720
147036
|
if (disposed) return;
|
|
146721
|
-
await
|
|
147037
|
+
await recoverThread(threadId, debts);
|
|
146722
147038
|
}
|
|
146723
147039
|
};
|
|
146724
147040
|
return { recoverConclusion, recoverConclusions };
|
|
@@ -146799,19 +147115,19 @@ var makeNotifications = (core, deps) => {
|
|
|
146799
147115
|
await ready;
|
|
146800
147116
|
const targets = targetsForProject(threadId, await projectOfThread(threadId));
|
|
146801
147117
|
const owes = Object.values(conclusionDebtsOf(core.state)).some(
|
|
146802
|
-
(
|
|
147118
|
+
(debt) => debt.threadId === threadId
|
|
146803
147119
|
);
|
|
146804
|
-
const {
|
|
146805
|
-
if (
|
|
146806
|
-
const binding = bindingForChatKey(debt.chatKey);
|
|
147120
|
+
const { selection, handled, execution } = said || owes || targets.length > 0 ? await conclusions.forTurn(threadId) : { selection: void 0, handled: false, execution: null };
|
|
147121
|
+
if (selection !== void 0 && selection !== null) {
|
|
147122
|
+
const binding = bindingForChatKey(selection.debt.chatKey);
|
|
146807
147123
|
if (binding !== void 0 && !streamsTo(binding, threadId) && execution?.session?.activeTurnId == null && execution?.latestTurn?.state !== "running" && execution?.latestTurn?.state !== "error" && payload.session?.status !== "error") {
|
|
146808
147124
|
const turnId = execution?.latestTurn?.turnId ?? null;
|
|
146809
|
-
enqueueConclusion(core, conclusions, binding,
|
|
147125
|
+
enqueueConclusion(core, conclusions, binding, selection, async (owed) => {
|
|
146810
147126
|
const send = await delivery.prepareConclusion(threadId, turnId);
|
|
146811
147127
|
return send(binding, { recovered: false, streaming: false, owed });
|
|
146812
147128
|
});
|
|
146813
147129
|
}
|
|
146814
|
-
} else if (said && !handled) {
|
|
147130
|
+
} else if (selection !== null && said && !handled) {
|
|
146815
147131
|
const send = await delivery.prepareConclusion(threadId);
|
|
146816
147132
|
for (const binding of targets) {
|
|
146817
147133
|
const streaming = streamsTo(binding, threadId);
|
|
@@ -146841,20 +147157,21 @@ var makeNotifications = (core, deps) => {
|
|
|
146841
147157
|
threadsWithSomethingToReport.delete(threadId);
|
|
146842
147158
|
await ready;
|
|
146843
147159
|
const targets = targetsForProject(threadId, await projectOfThread(threadId));
|
|
146844
|
-
const {
|
|
146845
|
-
const debtBinding =
|
|
146846
|
-
const recipients =
|
|
146847
|
-
const textTargets = handled ? [] : recipients.filter(
|
|
147160
|
+
const { selection, handled, execution } = await conclusions.forTurn(threadId);
|
|
147161
|
+
const debtBinding = selection == null ? void 0 : bindingForChatKey(selection.debt.chatKey);
|
|
147162
|
+
const recipients = selection == null ? targets : debtBinding === void 0 ? [] : [debtBinding];
|
|
147163
|
+
const textTargets = handled || selection === null ? [] : recipients.filter(
|
|
146848
147164
|
(binding) => !(streamsTo(binding, threadId) && turnCards.covers(threadId))
|
|
146849
147165
|
);
|
|
146850
147166
|
const drawingTurn = turnCards.drawingTurn(threadId);
|
|
146851
|
-
const
|
|
147167
|
+
const failure2 = readThreadFailed(event);
|
|
147168
|
+
const notice = textTargets.length > 0 || drawingTurn !== null ? failures.forFailure(threadId, failure2?.detail, failure2?.failureCategory) : null;
|
|
146852
147169
|
if (notice !== null && drawingTurn !== null)
|
|
146853
147170
|
failures.holdForCard(threadId, drawingTurn, notice);
|
|
146854
|
-
if (notice !== null) {
|
|
147171
|
+
if (notice !== null && selection !== null) {
|
|
146855
147172
|
for (const binding of textTargets) {
|
|
146856
147173
|
const send = (owed) => delivery.sendText(binding, threadId, notice, false, null, owed);
|
|
146857
|
-
enqueueConclusion(core, conclusions, binding,
|
|
147174
|
+
enqueueConclusion(core, conclusions, binding, selection, send);
|
|
146858
147175
|
}
|
|
146859
147176
|
}
|
|
146860
147177
|
for (const binding of targets) {
|
|
@@ -147426,6 +147743,17 @@ var makeProjectRows = (core) => {
|
|
|
147426
147743
|
};
|
|
147427
147744
|
|
|
147428
147745
|
// src/failureNotices.ts
|
|
147746
|
+
var PROVIDER_FAILURES = {
|
|
147747
|
+
quota: { code: "MODEL_QUOTA", messageKey: "reply.turnFailedQuota" },
|
|
147748
|
+
"rate-limit": { code: "MODEL_RATE_LIMIT", messageKey: "reply.turnFailedRateLimit" },
|
|
147749
|
+
"context-limit": { code: "MODEL_CONTEXT_LIMIT", messageKey: "reply.turnFailedContextLimit" },
|
|
147750
|
+
auth: { code: "MODEL_AUTH", messageKey: "reply.turnFailedAuth" },
|
|
147751
|
+
"model-unavailable": {
|
|
147752
|
+
code: "MODEL_UNAVAILABLE",
|
|
147753
|
+
messageKey: "reply.turnFailedModelUnavailable"
|
|
147754
|
+
},
|
|
147755
|
+
transport: { code: "MODEL_TRANSPORT", messageKey: "reply.turnFailedTransport" }
|
|
147756
|
+
};
|
|
147429
147757
|
var excerptSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
147430
147758
|
var graphemeExcerpt = (value2) => {
|
|
147431
147759
|
const characters = Array.from(
|
|
@@ -147463,9 +147791,20 @@ var makeFailureNotices = (core) => {
|
|
|
147463
147791
|
return core.t("reply.turnRetrying", { ref: reference2 });
|
|
147464
147792
|
},
|
|
147465
147793
|
/** 一次失败通知的那句话(带新参考号,同号进日志):实时失败事件与重启补发各取一次。 */
|
|
147466
|
-
forFailure: (threadId, detail) => {
|
|
147794
|
+
forFailure: (threadId, detail, category) => {
|
|
147467
147795
|
const reference2 = diagnosticRef("msg");
|
|
147468
|
-
|
|
147796
|
+
const failure2 = category === void 0 || category === "unknown" ? null : PROVIDER_FAILURES[category];
|
|
147797
|
+
core.host.log.warn("chat turn failed", {
|
|
147798
|
+
threadId,
|
|
147799
|
+
reference: reference2,
|
|
147800
|
+
code: failure2?.code ?? null,
|
|
147801
|
+
detail
|
|
147802
|
+
});
|
|
147803
|
+
if (failure2 !== null)
|
|
147804
|
+
return core.t("reply.turnFailedWithReference", {
|
|
147805
|
+
message: core.t(failure2.messageKey),
|
|
147806
|
+
ref: reference2
|
|
147807
|
+
});
|
|
147469
147808
|
const said = reasonOf2(detail);
|
|
147470
147809
|
const text4 = said === "" ? core.t("reply.turnFailedNoDetail", { ref: reference2 }) : core.t("reply.turnFailed", { detail: said, ref: reference2 });
|
|
147471
147810
|
return text4;
|
|
@@ -147478,11 +147817,13 @@ var makeFailureNotices = (core) => {
|
|
|
147478
147817
|
* 卡收尾(无论怎么收的都调):清掉这条会话的寄存。失败收尾时,寄存是这一轮的就用它(同一个号),
|
|
147479
147818
|
* 否则只写原因与下一步,不另取号。不是失败收尾回 null。
|
|
147480
147819
|
*/
|
|
147481
|
-
forCard: (threadId, turnId, detail, failed) => {
|
|
147820
|
+
forCard: (threadId, turnId, detail, failed, category) => {
|
|
147482
147821
|
const held = heldForCard.get(threadId);
|
|
147483
147822
|
heldForCard.delete(threadId);
|
|
147484
147823
|
if (!failed) return null;
|
|
147485
147824
|
if (held !== void 0 && held.turnId === turnId) return held.text;
|
|
147825
|
+
if (category !== void 0 && category !== "unknown")
|
|
147826
|
+
return core.t(PROVIDER_FAILURES[category].messageKey);
|
|
147486
147827
|
const said = reasonOf2(detail);
|
|
147487
147828
|
return said === "" ? core.t("reply.turnFailedBriefNoDetail") : core.t("reply.turnFailedBrief", { detail: said });
|
|
147488
147829
|
}
|
|
@@ -147833,7 +148174,8 @@ var makeReplyCards = (core, failures, anchors, conclusions, delivery) => {
|
|
|
147833
148174
|
threadId,
|
|
147834
148175
|
turnId,
|
|
147835
148176
|
session?.lastError,
|
|
147836
|
-
outcome === "failed"
|
|
148177
|
+
outcome === "failed",
|
|
148178
|
+
session?.failureCategory
|
|
147837
148179
|
);
|
|
147838
148180
|
if (errorText2 !== null) return { status: "error", errorText: errorText2 };
|
|
147839
148181
|
if (stopped || outcome === "stopped") {
|
|
@@ -147844,10 +148186,11 @@ var makeReplyCards = (core, failures, anchors, conclusions, delivery) => {
|
|
|
147844
148186
|
onOpened: (card) => commit("turn-card-opened", card),
|
|
147845
148187
|
onClosed: (cardId) => commit("turn-card-closed", { cardId }),
|
|
147846
148188
|
finalize: async (threadId, turnId, chatKey, send) => {
|
|
147847
|
-
const {
|
|
148189
|
+
const { selection, handled } = await conclusions.forTurn(threadId, turnId);
|
|
147848
148190
|
if (handled) return true;
|
|
147849
|
-
if (
|
|
147850
|
-
if (
|
|
148191
|
+
if (selection === null) return false;
|
|
148192
|
+
if (selection === void 0) return send();
|
|
148193
|
+
if (!await conclusions.deliver(selection, send)) return false;
|
|
147851
148194
|
const binding = bindingForChatKey(chatKey);
|
|
147852
148195
|
if (binding === void 0) return true;
|
|
147853
148196
|
const sendConclusion = await delivery.prepareConclusion(threadId, turnId);
|
|
@@ -147855,8 +148198,8 @@ var makeReplyCards = (core, failures, anchors, conclusions, delivery) => {
|
|
|
147855
148198
|
return true;
|
|
147856
148199
|
},
|
|
147857
148200
|
fallback: async (threadId, turnId, chatKey, view) => {
|
|
147858
|
-
const {
|
|
147859
|
-
if (handled) return;
|
|
148201
|
+
const { selection, handled } = await conclusions.forTurn(threadId, turnId);
|
|
148202
|
+
if (handled || selection === null) return;
|
|
147860
148203
|
const binding = bindingForChatKey(chatKey);
|
|
147861
148204
|
if (binding === void 0) return;
|
|
147862
148205
|
const text4 = [view.body, view.errorText ?? ""].filter((part) => part !== "").join("\n\n");
|
|
@@ -147864,7 +148207,7 @@ var makeReplyCards = (core, failures, anchors, conclusions, delivery) => {
|
|
|
147864
148207
|
core,
|
|
147865
148208
|
conclusions,
|
|
147866
148209
|
binding,
|
|
147867
|
-
|
|
148210
|
+
selection,
|
|
147868
148211
|
(owed) => delivery.sendText(binding, threadId, text4, false, turnId, owed)
|
|
147869
148212
|
);
|
|
147870
148213
|
},
|
|
@@ -148323,12 +148666,14 @@ import * as NodeCrypto6 from "node:crypto";
|
|
|
148323
148666
|
// src/telegramApiResponse.ts
|
|
148324
148667
|
var TelegramApiError = class extends Error {
|
|
148325
148668
|
code;
|
|
148669
|
+
status;
|
|
148326
148670
|
/** 限流(429)时平台给的等待秒数;别的错误没有。 */
|
|
148327
148671
|
retryAfterSeconds;
|
|
148328
|
-
constructor(method, code2, description, retryAfterSeconds) {
|
|
148329
|
-
super(`telegram ${method} failed (${String(code2 ?? "?")}): ${description}
|
|
148672
|
+
constructor(method, code2, description, retryAfterSeconds, options) {
|
|
148673
|
+
super(`telegram ${method} failed (${String(code2 ?? "?")}): ${description}`, options);
|
|
148330
148674
|
this.name = "TelegramApiError";
|
|
148331
148675
|
this.code = code2;
|
|
148676
|
+
this.status = options?.status;
|
|
148332
148677
|
this.retryAfterSeconds = retryAfterSeconds;
|
|
148333
148678
|
}
|
|
148334
148679
|
};
|
|
@@ -148343,7 +148688,8 @@ var readTelegramResponse = async (method, response) => {
|
|
|
148343
148688
|
method,
|
|
148344
148689
|
response.status === 401 ? 401 : envelope?.error_code ?? (response.ok ? void 0 : response.status),
|
|
148345
148690
|
envelope?.description ?? "no reason",
|
|
148346
|
-
envelope?.parameters?.retry_after
|
|
148691
|
+
envelope?.parameters?.retry_after,
|
|
148692
|
+
{ status: response.status }
|
|
148347
148693
|
);
|
|
148348
148694
|
}
|
|
148349
148695
|
return envelope.result;
|
|
@@ -148477,7 +148823,13 @@ var makeTelegramApi = (input) => {
|
|
|
148477
148823
|
return await input.http(url, { ...init, signal: AbortSignal.timeout(timeoutMs) });
|
|
148478
148824
|
} catch (error) {
|
|
148479
148825
|
if (error instanceof Error && error.name === "TimeoutError") {
|
|
148480
|
-
throw new TelegramApiError(
|
|
148826
|
+
throw new TelegramApiError(
|
|
148827
|
+
method,
|
|
148828
|
+
void 0,
|
|
148829
|
+
`timed out after ${String(timeoutMs)} ms`,
|
|
148830
|
+
void 0,
|
|
148831
|
+
{ cause: error }
|
|
148832
|
+
);
|
|
148481
148833
|
}
|
|
148482
148834
|
throw error;
|
|
148483
148835
|
}
|
|
@@ -148702,6 +149054,98 @@ var TELEGRAM_MENU = [
|
|
|
148702
149054
|
];
|
|
148703
149055
|
var telegramCommandMenu = (t) => TELEGRAM_MENU.map((item) => ({ command: item.command, description: t(item.key) }));
|
|
148704
149056
|
|
|
149057
|
+
// src/telegramConnectionCheck.ts
|
|
149058
|
+
var webhookHost = (url) => {
|
|
149059
|
+
try {
|
|
149060
|
+
return new URL(url).host;
|
|
149061
|
+
} catch {
|
|
149062
|
+
return "(unreadable)";
|
|
149063
|
+
}
|
|
149064
|
+
};
|
|
149065
|
+
var NOT_BOT_DETAIL = "token is not a bot's";
|
|
149066
|
+
var webhookActiveDetail = (url) => `webhook is set (host ${webhookHost(url)})`;
|
|
149067
|
+
var transportFailure = (stage, error) => ({
|
|
149068
|
+
ok: false,
|
|
149069
|
+
stage,
|
|
149070
|
+
detail: describeError(error),
|
|
149071
|
+
error
|
|
149072
|
+
});
|
|
149073
|
+
var probeTelegramBot = async (api) => {
|
|
149074
|
+
let own;
|
|
149075
|
+
try {
|
|
149076
|
+
own = await api.getMe();
|
|
149077
|
+
} catch (error) {
|
|
149078
|
+
return transportFailure("getMe", error);
|
|
149079
|
+
}
|
|
149080
|
+
if (own.is_bot !== true) {
|
|
149081
|
+
return { ok: false, stage: "getMe", hint: "notBot", detail: NOT_BOT_DETAIL };
|
|
149082
|
+
}
|
|
149083
|
+
let webhook = "";
|
|
149084
|
+
try {
|
|
149085
|
+
webhook = (await api.getWebhookInfo()).url ?? "";
|
|
149086
|
+
} catch (error) {
|
|
149087
|
+
return transportFailure("getWebhookInfo", error);
|
|
149088
|
+
}
|
|
149089
|
+
if (webhook !== "") {
|
|
149090
|
+
return {
|
|
149091
|
+
ok: false,
|
|
149092
|
+
stage: "getWebhookInfo",
|
|
149093
|
+
hint: "webhookActive",
|
|
149094
|
+
detail: webhookActiveDetail(webhook)
|
|
149095
|
+
};
|
|
149096
|
+
}
|
|
149097
|
+
return { ok: true, username: own.username, id: own.id };
|
|
149098
|
+
};
|
|
149099
|
+
var TelegramConnectGateError = class extends Error {
|
|
149100
|
+
hint;
|
|
149101
|
+
constructor(hint, detail) {
|
|
149102
|
+
super(detail);
|
|
149103
|
+
this.name = "TelegramConnectGateError";
|
|
149104
|
+
this.hint = hint;
|
|
149105
|
+
}
|
|
149106
|
+
};
|
|
149107
|
+
var assertTelegramPollingReady = async (api) => {
|
|
149108
|
+
const probed = await probeTelegramBot(api);
|
|
149109
|
+
if (!probed.ok) {
|
|
149110
|
+
if ("error" in probed) throw probed.error;
|
|
149111
|
+
throw new TelegramConnectGateError(probed.hint, probed.detail);
|
|
149112
|
+
}
|
|
149113
|
+
return { username: probed.username ?? null, id: probed.id };
|
|
149114
|
+
};
|
|
149115
|
+
var telegramPollingFailureHint = (error) => error instanceof TelegramConnectGateError ? error.hint : error instanceof TelegramApiError && error.code === 409 ? "webhookActive" : void 0;
|
|
149116
|
+
var checkTelegramConnection = async (bot, token, apiFor) => {
|
|
149117
|
+
if (token === "") {
|
|
149118
|
+
return { stage: "credentials", ok: false, detail: "missing bot token in saved config" };
|
|
149119
|
+
}
|
|
149120
|
+
if (!isTelegramToken(token)) {
|
|
149121
|
+
return {
|
|
149122
|
+
stage: "token-format",
|
|
149123
|
+
ok: false,
|
|
149124
|
+
detail: "saved token is not in the BotFather format",
|
|
149125
|
+
hint: "badToken"
|
|
149126
|
+
};
|
|
149127
|
+
}
|
|
149128
|
+
const api = await apiFor(bot);
|
|
149129
|
+
const probed = await probeTelegramBot(api);
|
|
149130
|
+
if (probed.ok) {
|
|
149131
|
+
const name = probed.username;
|
|
149132
|
+
const username = name !== void 0 && name !== "" ? `@${name}` : "(no username)";
|
|
149133
|
+
return { stage: "getMe", ok: true, detail: `username=${username} webhook=none` };
|
|
149134
|
+
}
|
|
149135
|
+
if ("error" in probed) {
|
|
149136
|
+
return {
|
|
149137
|
+
stage: probed.stage,
|
|
149138
|
+
ok: false,
|
|
149139
|
+
detail: probed.detail,
|
|
149140
|
+
...connectionHintFields(
|
|
149141
|
+
probed.error,
|
|
149142
|
+
probed.stage === "getMe" && isTelegramCredentialsRejected(probed.error) ? "unauthorized" : void 0
|
|
149143
|
+
)
|
|
149144
|
+
};
|
|
149145
|
+
}
|
|
149146
|
+
return { stage: probed.stage, ok: false, detail: probed.detail, hint: probed.hint };
|
|
149147
|
+
};
|
|
149148
|
+
|
|
148705
149149
|
// src/telegramChoice.ts
|
|
148706
149150
|
var renderChoiceCard = (card) => ({
|
|
148707
149151
|
text: [card.title, card.heading ?? "", card.body, card.note ?? ""].filter((part) => part !== "").join("\n\n"),
|
|
@@ -148893,15 +149337,13 @@ var tokenFingerprint = (bot) => NodeCrypto6.createHash("sha256").update(tokenOf(
|
|
|
148893
149337
|
var REACTION_WORKING = "\u{1F440}";
|
|
148894
149338
|
var REACTION_DONE = "\u{1F44D}";
|
|
148895
149339
|
var REACTION_FAILED = "\u{1F44E}";
|
|
148896
|
-
var telegramConfigIssues = (binding) =>
|
|
148897
|
-
|
|
148898
|
-
|
|
148899
|
-
|
|
148900
|
-
|
|
148901
|
-
} catch {
|
|
148902
|
-
return "(unreadable)";
|
|
148903
|
-
}
|
|
149340
|
+
var telegramConfigIssues = (binding) => {
|
|
149341
|
+
const token = tokenOf(binding);
|
|
149342
|
+
if (token === "") return [{ column: "telegramToken", code: "required" }];
|
|
149343
|
+
if (!isTelegramToken(token)) return [{ column: "telegramToken", code: "format" }];
|
|
149344
|
+
return [];
|
|
148904
149345
|
};
|
|
149346
|
+
var defaultSleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
148905
149347
|
var makeTelegramAdapter = (deps) => {
|
|
148906
149348
|
const apis = /* @__PURE__ */ new Map();
|
|
148907
149349
|
const sleep4 = deps.sleep ?? defaultSleep;
|
|
@@ -148996,13 +149438,14 @@ var makeTelegramAdapter = (deps) => {
|
|
|
148996
149438
|
});
|
|
148997
149439
|
return {
|
|
148998
149440
|
platform: "telegram",
|
|
149441
|
+
redeliversUnacknowledged: true,
|
|
148999
149442
|
botIdentity: tokenFingerprint,
|
|
149000
149443
|
icon: "telegram",
|
|
149001
149444
|
label: "Telegram",
|
|
149002
149445
|
quotesReplies: true,
|
|
149003
149446
|
columns: COLUMNS2,
|
|
149004
149447
|
validate: telegramConfigIssues,
|
|
149005
|
-
isConfigured: (binding) => telegramConfigIssues(binding).
|
|
149448
|
+
isConfigured: (binding) => telegramConfigIssues(binding).every((issue) => issue.code !== "required"),
|
|
149006
149449
|
connect: async (binding, handlers) => {
|
|
149007
149450
|
let stop = () => {
|
|
149008
149451
|
};
|
|
@@ -149040,8 +149483,8 @@ var makeTelegramAdapter = (deps) => {
|
|
|
149040
149483
|
liveApi = api;
|
|
149041
149484
|
if (!running) return;
|
|
149042
149485
|
if (botUsername == null) {
|
|
149043
|
-
const own = await api
|
|
149044
|
-
botUsername = own.username
|
|
149486
|
+
const own = await assertTelegramPollingReady(api);
|
|
149487
|
+
botUsername = own.username;
|
|
149045
149488
|
botId = own.id;
|
|
149046
149489
|
if (running) handlers.onConnectionState?.({ state: "connected" });
|
|
149047
149490
|
}
|
|
@@ -149107,14 +149550,16 @@ var makeTelegramAdapter = (deps) => {
|
|
|
149107
149550
|
}
|
|
149108
149551
|
}
|
|
149109
149552
|
if (!running) break;
|
|
149110
|
-
advanceOffset(update);
|
|
149111
149553
|
const senderId = message.from === void 0 ? null : String(message.from.id);
|
|
149112
149554
|
const senderName2 = telegramDisplayName(message.from);
|
|
149113
149555
|
const chatKind = message.chat.type === "private" ? "private" : "group";
|
|
149114
149556
|
if (message.voice !== void 0 || text4 === "" && resource === null) {
|
|
149115
149557
|
const unsupported = unsupportedTypeOf(message);
|
|
149116
|
-
if (unsupported === null)
|
|
149117
|
-
|
|
149558
|
+
if (unsupported === null) {
|
|
149559
|
+
advanceOffset(update);
|
|
149560
|
+
continue;
|
|
149561
|
+
}
|
|
149562
|
+
await handlers.onMessage({
|
|
149118
149563
|
messageId: String(message.message_id),
|
|
149119
149564
|
chatId: chatIdOf(message),
|
|
149120
149565
|
senderId,
|
|
@@ -149123,11 +149568,13 @@ var makeTelegramAdapter = (deps) => {
|
|
|
149123
149568
|
resources: [],
|
|
149124
149569
|
unsupportedType: unsupported
|
|
149125
149570
|
});
|
|
149571
|
+
if (!running) break;
|
|
149572
|
+
advanceOffset(update);
|
|
149126
149573
|
continue;
|
|
149127
149574
|
}
|
|
149128
149575
|
const parentChatId = parentChatIdOf(message);
|
|
149129
149576
|
const replyTo = telegramReplyReference(message, botUsername, botId);
|
|
149130
|
-
handlers.onMessage({
|
|
149577
|
+
await handlers.onMessage({
|
|
149131
149578
|
messageId: String(message.message_id),
|
|
149132
149579
|
chatId: chatIdOf(message),
|
|
149133
149580
|
...parentChatId === void 0 ? {} : { parentChatId },
|
|
@@ -149147,6 +149594,8 @@ var makeTelegramAdapter = (deps) => {
|
|
|
149147
149594
|
}
|
|
149148
149595
|
]
|
|
149149
149596
|
});
|
|
149597
|
+
if (!running) break;
|
|
149598
|
+
advanceOffset(update);
|
|
149150
149599
|
}
|
|
149151
149600
|
} catch (error) {
|
|
149152
149601
|
if (!running) return;
|
|
@@ -149161,7 +149610,12 @@ var makeTelegramAdapter = (deps) => {
|
|
|
149161
149610
|
});
|
|
149162
149611
|
return;
|
|
149163
149612
|
}
|
|
149164
|
-
if (checkingConnection)
|
|
149613
|
+
if (checkingConnection)
|
|
149614
|
+
handlers.onConnectionState?.({
|
|
149615
|
+
state: "failed",
|
|
149616
|
+
error,
|
|
149617
|
+
...connectionHintFields(error, telegramPollingFailureHint(error))
|
|
149618
|
+
});
|
|
149165
149619
|
handlers.onError(error instanceof Error ? error.message : String(error));
|
|
149166
149620
|
await Promise.race([(deps.sleep ?? defaultSleep)(backoff), stopped]);
|
|
149167
149621
|
backoff = Math.min(backoff * 2, BACKOFF_MAX_MS);
|
|
@@ -149183,50 +149637,7 @@ var makeTelegramAdapter = (deps) => {
|
|
|
149183
149637
|
const api = await apiFor(binding);
|
|
149184
149638
|
await api.sendMessage(binding.chatId, text4, options?.retry, binding.reply?.messageId);
|
|
149185
149639
|
},
|
|
149186
|
-
checkConnection:
|
|
149187
|
-
const token = tokenOf(bot);
|
|
149188
|
-
if (token === "") {
|
|
149189
|
-
return { stage: "credentials", ok: false, detail: "missing bot token in saved config" };
|
|
149190
|
-
}
|
|
149191
|
-
if (!isTelegramToken(token)) {
|
|
149192
|
-
return {
|
|
149193
|
-
stage: "token-format",
|
|
149194
|
-
ok: false,
|
|
149195
|
-
detail: "saved token is not in the BotFather format",
|
|
149196
|
-
hint: "badToken"
|
|
149197
|
-
};
|
|
149198
|
-
}
|
|
149199
|
-
const api = await apiFor(bot);
|
|
149200
|
-
let username;
|
|
149201
|
-
try {
|
|
149202
|
-
const me = await api.getMe();
|
|
149203
|
-
if (me.is_bot !== true) {
|
|
149204
|
-
return { stage: "getMe", ok: false, detail: "token is not a bot's", hint: "notBot" };
|
|
149205
|
-
}
|
|
149206
|
-
username = me.username !== void 0 && me.username !== "" ? `@${me.username}` : "(no username)";
|
|
149207
|
-
} catch (error) {
|
|
149208
|
-
return {
|
|
149209
|
-
stage: "getMe",
|
|
149210
|
-
ok: false,
|
|
149211
|
-
detail: describeError(error),
|
|
149212
|
-
...isTelegramCredentialsRejected(error) ? { hint: "unauthorized" } : {}
|
|
149213
|
-
};
|
|
149214
|
-
}
|
|
149215
|
-
try {
|
|
149216
|
-
const webhook = (await api.getWebhookInfo()).url ?? "";
|
|
149217
|
-
if (webhook !== "") {
|
|
149218
|
-
return {
|
|
149219
|
-
stage: "getWebhookInfo",
|
|
149220
|
-
ok: false,
|
|
149221
|
-
detail: `webhook is set (host ${webhookHost(webhook)})`,
|
|
149222
|
-
hint: "webhookActive"
|
|
149223
|
-
};
|
|
149224
|
-
}
|
|
149225
|
-
} catch (error) {
|
|
149226
|
-
return { stage: "getWebhookInfo", ok: false, detail: describeError(error) };
|
|
149227
|
-
}
|
|
149228
|
-
return { stage: "getMe", ok: true, detail: `username=${username} webhook=none` };
|
|
149229
|
-
},
|
|
149640
|
+
checkConnection: (bot) => checkTelegramConnection(bot, tokenOf(bot), apiFor),
|
|
149230
149641
|
sendTyping: async (binding) => {
|
|
149231
149642
|
await (await apiFor(binding)).sendTyping(binding.chatId);
|
|
149232
149643
|
},
|
|
@@ -149727,12 +150138,10 @@ var makeTurns = (core, deps) => {
|
|
|
149727
150138
|
);
|
|
149728
150139
|
if (!dispatched) return null;
|
|
149729
150140
|
topicRoot?.confirmConsumed();
|
|
149730
|
-
|
|
149731
|
-
|
|
149732
|
-
|
|
149733
|
-
|
|
149734
|
-
);
|
|
149735
|
-
}
|
|
150141
|
+
await deps.conclusions.owe(
|
|
150142
|
+
{ chatKey, threadId, userMessageId, recordedAt: (/* @__PURE__ */ new Date()).toISOString() },
|
|
150143
|
+
replayed ? deps.recoverConclusion : void 0
|
|
150144
|
+
);
|
|
149736
150145
|
} finally {
|
|
149737
150146
|
registered();
|
|
149738
150147
|
}
|
|
@@ -149969,7 +150378,13 @@ var probe = async (adapters, bot) => {
|
|
|
149969
150378
|
result2.hint
|
|
149970
150379
|
);
|
|
149971
150380
|
} catch (error) {
|
|
149972
|
-
return reportOf(
|
|
150381
|
+
return reportOf(
|
|
150382
|
+
bot,
|
|
150383
|
+
"check",
|
|
150384
|
+
false,
|
|
150385
|
+
redactor.redact(describeError(error)),
|
|
150386
|
+
connectionHint(error)
|
|
150387
|
+
);
|
|
149973
150388
|
}
|
|
149974
150389
|
};
|
|
149975
150390
|
var emitReport = (emit, report, action) => {
|
|
@@ -150495,6 +150910,16 @@ var makeWechatAdapter = (deps) => {
|
|
|
150495
150910
|
};
|
|
150496
150911
|
};
|
|
150497
150912
|
|
|
150913
|
+
// src/wecomAckError.ts
|
|
150914
|
+
var WecomAckError = class extends Error {
|
|
150915
|
+
code;
|
|
150916
|
+
constructor(code2, msg) {
|
|
150917
|
+
super(`WeCom ack failed: ${String(code2)} ${msg}`);
|
|
150918
|
+
this.name = "WecomAckError";
|
|
150919
|
+
this.code = code2;
|
|
150920
|
+
}
|
|
150921
|
+
};
|
|
150922
|
+
|
|
150498
150923
|
// src/wecomUpload.ts
|
|
150499
150924
|
import * as NodeCrypto8 from "node:crypto";
|
|
150500
150925
|
var WECOM_CHUNK_BYTES = 512 * 1024;
|
|
@@ -150707,15 +151132,12 @@ var parseWecomMessage = (frame, botId) => {
|
|
|
150707
151132
|
};
|
|
150708
151133
|
};
|
|
150709
151134
|
var splitForWecom = (text4, limit = WECOM_TEXT_MAX_CHARS) => splitMessage(text4, limit);
|
|
150710
|
-
var
|
|
150711
|
-
|
|
150712
|
-
|
|
150713
|
-
constructor(code2, msg) {
|
|
150714
|
-
super(`WeCom ack failed: ${String(code2)} ${msg}`);
|
|
150715
|
-
this.name = "WecomAckError";
|
|
150716
|
-
this.code = code2;
|
|
151135
|
+
var sendWecomText = async (text4, sendChunk) => {
|
|
151136
|
+
for (const [index, content] of splitForWecom(text4).entries()) {
|
|
151137
|
+
await sendChunk(content, index === 0);
|
|
150717
151138
|
}
|
|
150718
151139
|
};
|
|
151140
|
+
var decoder = new TextDecoder();
|
|
150719
151141
|
var subscriptionHint = (error) => {
|
|
150720
151142
|
if (!(error instanceof WecomAckError)) return void 0;
|
|
150721
151143
|
switch (error.code) {
|
|
@@ -150848,41 +151270,39 @@ var runWecomClient = (input) => {
|
|
|
150848
151270
|
return false;
|
|
150849
151271
|
}
|
|
150850
151272
|
);
|
|
150851
|
-
const
|
|
150852
|
-
|
|
150853
|
-
|
|
150854
|
-
|
|
150855
|
-
|
|
150856
|
-
|
|
150857
|
-
|
|
150858
|
-
|
|
150859
|
-
|
|
150860
|
-
|
|
150861
|
-
|
|
150862
|
-
}
|
|
150863
|
-
});
|
|
150864
|
-
continue;
|
|
150865
|
-
}
|
|
150866
|
-
const requestId = nextRequestId("aibot_send_msg");
|
|
150867
|
-
const ack = new Promise((resolve2, reject) => {
|
|
150868
|
-
pendingAcks.set(requestId, { resolve: () => resolve2(), reject });
|
|
150869
|
-
setTimeout(() => {
|
|
150870
|
-
if (pendingAcks.delete(requestId)) resolve2();
|
|
150871
|
-
}, SEND_ACK_TIMEOUT_MS);
|
|
151273
|
+
const sendTextChunk = async (chatId, content, firstChunk) => {
|
|
151274
|
+
const inboundRequestId = firstChunk ? pendingRequests.get(chatId) : void 0;
|
|
151275
|
+
if (inboundRequestId !== void 0) {
|
|
151276
|
+
pendingRequests.delete(chatId);
|
|
151277
|
+
await send({
|
|
151278
|
+
cmd: "aibot_respond_msg",
|
|
151279
|
+
headers: { req_id: inboundRequestId },
|
|
151280
|
+
body: {
|
|
151281
|
+
msgtype: "stream",
|
|
151282
|
+
stream: { id: nextRequestId("stream"), finish: true, content }
|
|
151283
|
+
}
|
|
150872
151284
|
});
|
|
150873
|
-
|
|
150874
|
-
|
|
150875
|
-
|
|
150876
|
-
|
|
150877
|
-
|
|
150878
|
-
|
|
150879
|
-
|
|
150880
|
-
|
|
150881
|
-
|
|
150882
|
-
|
|
150883
|
-
|
|
150884
|
-
|
|
150885
|
-
|
|
151285
|
+
return;
|
|
151286
|
+
}
|
|
151287
|
+
const requestId = nextRequestId("aibot_send_msg");
|
|
151288
|
+
const ack = new Promise((resolve2, reject) => {
|
|
151289
|
+
pendingAcks.set(requestId, { resolve: () => resolve2(), reject });
|
|
151290
|
+
setTimeout(() => {
|
|
151291
|
+
if (pendingAcks.delete(requestId)) resolve2();
|
|
151292
|
+
}, SEND_ACK_TIMEOUT_MS);
|
|
151293
|
+
});
|
|
151294
|
+
try {
|
|
151295
|
+
await Promise.all([
|
|
151296
|
+
send({
|
|
151297
|
+
cmd: "aibot_send_msg",
|
|
151298
|
+
headers: { req_id: requestId },
|
|
151299
|
+
body: { chatid: chatId, msgtype: "markdown", markdown: { content } }
|
|
151300
|
+
}),
|
|
151301
|
+
ack
|
|
151302
|
+
]);
|
|
151303
|
+
} catch (error) {
|
|
151304
|
+
pendingAcks.delete(requestId);
|
|
151305
|
+
throw error;
|
|
150886
151306
|
}
|
|
150887
151307
|
};
|
|
150888
151308
|
const request = async (cmd, body) => {
|
|
@@ -150959,7 +151379,8 @@ var runWecomClient = (input) => {
|
|
|
150959
151379
|
};
|
|
150960
151380
|
};
|
|
150961
151381
|
return {
|
|
150962
|
-
sendText,
|
|
151382
|
+
sendText: (chatId, text4) => sendWecomText(text4, (content, firstChunk) => sendTextChunk(chatId, content, firstChunk)),
|
|
151383
|
+
sendTextChunk,
|
|
150963
151384
|
sendMedia,
|
|
150964
151385
|
rememberConversation: (chatId, conversation) => {
|
|
150965
151386
|
conversations.set(chatId, conversation);
|
|
@@ -151064,6 +151485,38 @@ var fetchWecomMedia = async (input) => {
|
|
|
151064
151485
|
return { bytes, name };
|
|
151065
151486
|
};
|
|
151066
151487
|
|
|
151488
|
+
// src/wecomSendError.ts
|
|
151489
|
+
var WecomSendError = class extends Error {
|
|
151490
|
+
operation;
|
|
151491
|
+
code;
|
|
151492
|
+
providerCode;
|
|
151493
|
+
constructor(cause, operation, code2, providerCode) {
|
|
151494
|
+
super(
|
|
151495
|
+
providerCode === void 0 && cause instanceof Error ? cause.message : `WeCom ${operation} failed (${code2}, provider=${providerCode ?? "-"})`,
|
|
151496
|
+
{ cause }
|
|
151497
|
+
);
|
|
151498
|
+
this.name = "WecomSendError";
|
|
151499
|
+
this.operation = operation;
|
|
151500
|
+
this.code = code2;
|
|
151501
|
+
this.providerCode = providerCode;
|
|
151502
|
+
}
|
|
151503
|
+
};
|
|
151504
|
+
var wecomSendError = (error, operation) => {
|
|
151505
|
+
if (error instanceof ImNotConnectedError || error instanceof WecomSendError || error instanceof Error && error.name === "AbortError" || error instanceof TypeError || error instanceof ReferenceError || error instanceof SyntaxError)
|
|
151506
|
+
return error;
|
|
151507
|
+
const providerCode = error instanceof WecomAckError ? error.code : void 0;
|
|
151508
|
+
let code2 = providerCode === void 0 ? "channel-delivery-uncertain" : "channel-delivery-failed";
|
|
151509
|
+
if (providerCode === 48002) code2 = "channel-permission";
|
|
151510
|
+
if (providerCode === 45009) code2 = "channel-rate-limit";
|
|
151511
|
+
return new WecomSendError(error, operation, code2, providerCode);
|
|
151512
|
+
};
|
|
151513
|
+
var wecomSendDiagnostic = (error) => error instanceof WecomSendError ? {
|
|
151514
|
+
operation: error.operation,
|
|
151515
|
+
code: error.code,
|
|
151516
|
+
providerCode: error.providerCode
|
|
151517
|
+
} : void 0;
|
|
151518
|
+
var wecomSendVerdict = (error) => error instanceof ImNotConnectedError || error instanceof WecomSendError && error.code === "channel-rate-limit" ? { retry: true } : NO_RETRY;
|
|
151519
|
+
|
|
151067
151520
|
// src/wecomAdapter.ts
|
|
151068
151521
|
var WECOM_CARD_THROTTLE_MS = 400;
|
|
151069
151522
|
var LIVE_STREAM_LIMIT = 200;
|
|
@@ -151090,6 +151543,16 @@ var makeWecomAdapter = (deps) => {
|
|
|
151090
151543
|
const clients = /* @__PURE__ */ new Map();
|
|
151091
151544
|
const managedConnections = /* @__PURE__ */ new Map();
|
|
151092
151545
|
const t = deps.translate;
|
|
151546
|
+
const sending = async (operation, request) => {
|
|
151547
|
+
try {
|
|
151548
|
+
return await request();
|
|
151549
|
+
} catch (error) {
|
|
151550
|
+
const failure2 = wecomSendError(error, operation);
|
|
151551
|
+
const diagnostic = wecomSendDiagnostic(failure2);
|
|
151552
|
+
if (diagnostic !== void 0) deps.log.warn("wecom send failed", diagnostic);
|
|
151553
|
+
throw failure2;
|
|
151554
|
+
}
|
|
151555
|
+
};
|
|
151093
151556
|
const liveStreams = /* @__PURE__ */ new Map();
|
|
151094
151557
|
const rememberStream = (key, entry) => {
|
|
151095
151558
|
liveStreams.set(key, entry);
|
|
@@ -151110,19 +151573,19 @@ var makeWecomAdapter = (deps) => {
|
|
|
151110
151573
|
shown = `${t("card.truncated", { count: body.length - kept.length })}
|
|
151111
151574
|
${kept}`;
|
|
151112
151575
|
}
|
|
151113
|
-
await entry.stream.send(joinParts(head, shown, foot), false);
|
|
151576
|
+
await sending("replyStream", () => entry.stream.send(joinParts(head, shown, foot), false));
|
|
151114
151577
|
return;
|
|
151115
151578
|
}
|
|
151116
151579
|
const chunks = splitForWecom(joinParts(head, body, foot));
|
|
151117
|
-
const delivered = await entry.stream.send(chunks[0] ?? "", true);
|
|
151580
|
+
const delivered = await sending("replyStream", () => entry.stream.send(chunks[0] ?? "", true));
|
|
151118
151581
|
for (const chunk of delivered ? chunks.slice(1) : chunks) {
|
|
151119
|
-
await entry.client.sendText(entry.chatId, chunk);
|
|
151582
|
+
await sending("sendMessage", () => entry.client.sendText(entry.chatId, chunk));
|
|
151120
151583
|
}
|
|
151121
151584
|
};
|
|
151122
151585
|
const sendMedia = async (binding, kind, media) => {
|
|
151123
151586
|
const client = clients.get(binding.rowId);
|
|
151124
151587
|
if (client === void 0) throw new Error("WeCom is not connected right now");
|
|
151125
|
-
await client.sendMedia(binding.chatId, kind, media);
|
|
151588
|
+
await sending("sendMedia", () => client.sendMedia(binding.chatId, kind, media));
|
|
151126
151589
|
deps.log.info("wecom delivered a file", { name: media.name, as: kind });
|
|
151127
151590
|
};
|
|
151128
151591
|
return {
|
|
@@ -151167,7 +151630,7 @@ ${kept}`;
|
|
|
151167
151630
|
if (message.chatType !== "single") return;
|
|
151168
151631
|
client.rememberRequest(message.chatId, message.requestId);
|
|
151169
151632
|
client.rememberConversation(message.chatId, message.conversation);
|
|
151170
|
-
handlers.onMessage({
|
|
151633
|
+
void handlers.onMessage({
|
|
151171
151634
|
// 不保存短效 req_id:重启后的回话走新连接的 aibot_send_msg 主动发送,
|
|
151172
151635
|
// 不冒充原消息的回答,也不复用旧连接的 rememberRequest / 流状态。
|
|
151173
151636
|
messageId: message.messageId,
|
|
@@ -151184,6 +151647,10 @@ ${kept}`;
|
|
|
151184
151647
|
mimeType: resource.mimeType,
|
|
151185
151648
|
kind: resource.kind
|
|
151186
151649
|
}))
|
|
151650
|
+
}).catch((error) => {
|
|
151651
|
+
deps.log.warn("wecom could not persist inbound message", {
|
|
151652
|
+
error: describeError(error)
|
|
151653
|
+
});
|
|
151187
151654
|
});
|
|
151188
151655
|
}
|
|
151189
151656
|
}
|
|
@@ -151233,13 +151700,26 @@ ${kept}`;
|
|
|
151233
151700
|
}
|
|
151234
151701
|
};
|
|
151235
151702
|
},
|
|
151236
|
-
|
|
151237
|
-
|
|
151238
|
-
|
|
151239
|
-
|
|
151240
|
-
|
|
151241
|
-
|
|
151242
|
-
|
|
151703
|
+
sendText: async (binding, text4, options) => {
|
|
151704
|
+
await sendWecomText(
|
|
151705
|
+
text4,
|
|
151706
|
+
(chunk, firstChunk) => sendWithRetry(
|
|
151707
|
+
async () => {
|
|
151708
|
+
const client = clients.get(binding.rowId);
|
|
151709
|
+
if (client === void 0) {
|
|
151710
|
+
throw new ImNotConnectedError(
|
|
151711
|
+
`wecom bot '${binding.displayName}' has no connection.`
|
|
151712
|
+
);
|
|
151713
|
+
}
|
|
151714
|
+
await sending(
|
|
151715
|
+
"sendMessage",
|
|
151716
|
+
() => client.sendTextChunk(binding.chatId, chunk, firstChunk)
|
|
151717
|
+
);
|
|
151718
|
+
},
|
|
151719
|
+
wecomSendVerdict,
|
|
151720
|
+
options?.retry
|
|
151721
|
+
)
|
|
151722
|
+
);
|
|
151243
151723
|
},
|
|
151244
151724
|
checkConnection: async (bot) => {
|
|
151245
151725
|
const managed = managedConnections.get(bot.rowId);
|
|
@@ -151313,7 +151793,10 @@ ${kept}`;
|
|
|
151313
151793
|
}
|
|
151314
151794
|
},
|
|
151315
151795
|
askApproval: async (binding, request) => {
|
|
151316
|
-
|
|
151796
|
+
const client = clients.get(binding.rowId);
|
|
151797
|
+
const text4 = numberedApprovalText(request);
|
|
151798
|
+
if (client !== void 0)
|
|
151799
|
+
await sending("sendMessage", () => client.sendText(binding.chatId, text4));
|
|
151317
151800
|
return null;
|
|
151318
151801
|
},
|
|
151319
151802
|
turnCards: {
|
|
@@ -151370,6 +151853,7 @@ var REQUEST_TIMEOUT_MS = 15e3;
|
|
|
151370
151853
|
var MEDIA_TIMEOUT_MS = 6e4;
|
|
151371
151854
|
var WecomAppApiError = class extends Error {
|
|
151372
151855
|
code;
|
|
151856
|
+
status;
|
|
151373
151857
|
providerCode;
|
|
151374
151858
|
hint;
|
|
151375
151859
|
invalidUsers;
|
|
@@ -151377,6 +151861,7 @@ var WecomAppApiError = class extends Error {
|
|
|
151377
151861
|
super(message);
|
|
151378
151862
|
this.name = "WecomAppApiError";
|
|
151379
151863
|
this.code = code2;
|
|
151864
|
+
this.status = extras?.status;
|
|
151380
151865
|
this.providerCode = extras?.providerCode;
|
|
151381
151866
|
this.hint = extras?.hint;
|
|
151382
151867
|
this.invalidUsers = extras?.invalidUsers ?? [];
|
|
@@ -151586,30 +152071,31 @@ var WecomAppApi = class {
|
|
|
151586
152071
|
});
|
|
151587
152072
|
}
|
|
151588
152073
|
}
|
|
151589
|
-
#apiError(errcode, errmsg, invalidUsers) {
|
|
152074
|
+
#apiError(errcode, errmsg, invalidUsers, status) {
|
|
151590
152075
|
const code2 = String(errcode);
|
|
152076
|
+
const details = { providerCode: code2, status };
|
|
151591
152077
|
const message = typeof errmsg === "string" && errmsg !== "" ? `WeCom API failed (${code2}): ${errmsg}` : `WeCom API failed (${code2}).`;
|
|
151592
152078
|
if (TOKEN_INVALID_CODES.has(code2)) this.invalidateToken();
|
|
151593
152079
|
if (errcode === 60020) {
|
|
151594
152080
|
return new WecomAppApiError("trusted-ip", "WeCom rejected the outbound IP (errcode 60020).", {
|
|
151595
|
-
|
|
152081
|
+
...details,
|
|
151596
152082
|
hint: "wecomTrustedIp"
|
|
151597
152083
|
});
|
|
151598
152084
|
}
|
|
151599
152085
|
if (errcode === 81013) {
|
|
151600
152086
|
return new WecomAppApiError("invalid-user", message, {
|
|
151601
|
-
|
|
152087
|
+
...details,
|
|
151602
152088
|
hint: "wecomInvalidUser",
|
|
151603
152089
|
invalidUsers: parseInvalidUsers(invalidUsers)
|
|
151604
152090
|
});
|
|
151605
152091
|
}
|
|
151606
152092
|
if (errcode === 40056) {
|
|
151607
152093
|
return new WecomAppApiError("invalid-agent", message, {
|
|
151608
|
-
|
|
152094
|
+
...details,
|
|
151609
152095
|
hint: "wecomInvalidAgent"
|
|
151610
152096
|
});
|
|
151611
152097
|
}
|
|
151612
|
-
return new WecomAppApiError("api-failed", message,
|
|
152098
|
+
return new WecomAppApiError("api-failed", message, details);
|
|
151613
152099
|
}
|
|
151614
152100
|
async #withRequest(url, init, timeoutMs, read) {
|
|
151615
152101
|
const deadline = new AbortController();
|
|
@@ -151636,15 +152122,29 @@ var WecomAppApi = class {
|
|
|
151636
152122
|
} catch {
|
|
151637
152123
|
throw new WecomAppApiError(
|
|
151638
152124
|
"bad-response",
|
|
151639
|
-
`WeCom returned non-JSON (HTTP ${String(response.status)})
|
|
152125
|
+
`WeCom returned non-JSON (HTTP ${String(response.status)}).`,
|
|
152126
|
+
{ status: response.status }
|
|
151640
152127
|
);
|
|
151641
152128
|
}
|
|
151642
152129
|
if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
|
|
151643
|
-
throw new WecomAppApiError("bad-response", "WeCom returned a non-object JSON body."
|
|
152130
|
+
throw new WecomAppApiError("bad-response", "WeCom returned a non-object JSON body.", {
|
|
152131
|
+
status: response.status
|
|
152132
|
+
});
|
|
151644
152133
|
}
|
|
151645
152134
|
const result2 = payload;
|
|
151646
152135
|
const errcode = Number(result2["errcode"] ?? 0);
|
|
151647
|
-
if (errcode !== 0)
|
|
152136
|
+
if (errcode !== 0) {
|
|
152137
|
+
throw this.#apiError(errcode, result2["errmsg"], result2["invaliduser"], response.status);
|
|
152138
|
+
}
|
|
152139
|
+
if (!response.ok) {
|
|
152140
|
+
throw new WecomAppApiError(
|
|
152141
|
+
"bad-response",
|
|
152142
|
+
`WeCom returned HTTP ${String(response.status)}.`,
|
|
152143
|
+
{
|
|
152144
|
+
status: response.status
|
|
152145
|
+
}
|
|
152146
|
+
);
|
|
152147
|
+
}
|
|
151648
152148
|
return result2;
|
|
151649
152149
|
});
|
|
151650
152150
|
}
|
|
@@ -152279,12 +152779,19 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
152279
152779
|
}
|
|
152280
152780
|
const messageId = message.msgid ?? `${chatId}:${message.createTime ?? Date.now()}`;
|
|
152281
152781
|
const base2 = { messageId, chatId, senderId: chatId };
|
|
152782
|
+
const receive = (inbound) => {
|
|
152783
|
+
void handlers.onMessage(inbound).catch((error) => {
|
|
152784
|
+
deps.log.warn("wecom-app could not persist inbound message", {
|
|
152785
|
+
error: describeError(error)
|
|
152786
|
+
});
|
|
152787
|
+
});
|
|
152788
|
+
};
|
|
152282
152789
|
if (message.msgtype === "text") {
|
|
152283
|
-
|
|
152790
|
+
receive({ ...base2, text: message.text?.content?.trim() ?? "", resources: [] });
|
|
152284
152791
|
return;
|
|
152285
152792
|
}
|
|
152286
152793
|
if (message.msgtype === "image" && message.mediaId !== void 0 && message.mediaId !== "") {
|
|
152287
|
-
|
|
152794
|
+
receive({
|
|
152288
152795
|
...base2,
|
|
152289
152796
|
text: "",
|
|
152290
152797
|
resources: [
|
|
@@ -152293,7 +152800,7 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
152293
152800
|
});
|
|
152294
152801
|
return;
|
|
152295
152802
|
}
|
|
152296
|
-
|
|
152803
|
+
receive({
|
|
152297
152804
|
...base2,
|
|
152298
152805
|
text: "",
|
|
152299
152806
|
resources: [],
|
|
@@ -152373,7 +152880,10 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
152373
152880
|
stage: "gettoken",
|
|
152374
152881
|
ok: false,
|
|
152375
152882
|
detail: describeError(error),
|
|
152376
|
-
...
|
|
152883
|
+
...connectionHintFields(
|
|
152884
|
+
error,
|
|
152885
|
+
error instanceof WecomAppApiError ? error.hint : void 0
|
|
152886
|
+
)
|
|
152377
152887
|
};
|
|
152378
152888
|
}
|
|
152379
152889
|
},
|
|
@@ -152392,7 +152902,7 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
152392
152902
|
const report = (state) => {
|
|
152393
152903
|
if (closed) return;
|
|
152394
152904
|
handlers.onConnectionState?.(
|
|
152395
|
-
state.state === "failed" && state.error instanceof WecomAppApiError && state.error.hint !== void 0 ? { ...state, hint: state.error.hint } : state
|
|
152905
|
+
state.state === "failed" && state.error instanceof WecomAppApiError && state.error.hint !== void 0 ? { ...state, hint: state.error.hint } : state.state === "failed" ? { ...state, ...connectionHintFields(state.error, state.hint) } : state
|
|
152396
152906
|
);
|
|
152397
152907
|
};
|
|
152398
152908
|
apis.set(bot.rowId, { api, report });
|
|
@@ -152503,7 +153013,7 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
152503
153013
|
// src/index.ts
|
|
152504
153014
|
var definition = {
|
|
152505
153015
|
id: "im",
|
|
152506
|
-
apiVersion:
|
|
153016
|
+
apiVersion: 23,
|
|
152507
153017
|
// 第二个参数只给插件自己的测试夹具:换掉文件 IO 与派发重试的等待。宿主只传 ctx。
|
|
152508
153018
|
activate: async (ctx, testing = {}) => {
|
|
152509
153019
|
const { dispatchSleep } = testing;
|