larkway 0.3.26 → 0.3.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +9 -9
- package/dist/main.js +243 -490
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -124047,9 +124047,9 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
124047
124047
|
*/
|
|
124048
124048
|
allowed_threads: external_exports.array(external_exports.string().min(1)).default([]),
|
|
124049
124049
|
/**
|
|
124050
|
-
*
|
|
124051
|
-
*
|
|
124052
|
-
*
|
|
124050
|
+
* Historical post-first gate retained for config compatibility. The default
|
|
124051
|
+
* runtime no longer uses post-first lazy card creation; CardKit is the main
|
|
124052
|
+
* surface and legacy cards remain the visible fallback.
|
|
124053
124053
|
*/
|
|
124054
124054
|
lazy_card_creation: external_exports.boolean().default(true),
|
|
124055
124055
|
/**
|
|
@@ -124059,8 +124059,8 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
124059
124059
|
*/
|
|
124060
124060
|
kill_switch: external_exports.boolean().default(false),
|
|
124061
124061
|
/**
|
|
124062
|
-
* Gate for real post outbound. Defaults on
|
|
124063
|
-
*
|
|
124062
|
+
* Gate for real post outbound. Defaults on so create-only visible fallback
|
|
124063
|
+
* posts remain available when CardKit and legacy card rendering both fail.
|
|
124064
124064
|
*/
|
|
124065
124065
|
post_outbound_enabled: external_exports.boolean().default(true),
|
|
124066
124066
|
/**
|
|
@@ -124082,8 +124082,8 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
124082
124082
|
*/
|
|
124083
124083
|
allowed_mention_open_ids: external_exports.array(external_exports.string().min(1)).default([]),
|
|
124084
124084
|
/**
|
|
124085
|
-
*
|
|
124086
|
-
*
|
|
124085
|
+
* Historical post dispatch cap retained for schema compatibility and
|
|
124086
|
+
* isolated dispatcher tests.
|
|
124087
124087
|
*/
|
|
124088
124088
|
max_posts_per_turn: external_exports.number().int().min(0).max(10).default(1),
|
|
124089
124089
|
/**
|
|
@@ -124102,8 +124102,8 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
124102
124102
|
*/
|
|
124103
124103
|
max_post_attempts: external_exports.number().int().min(1).max(5).default(3),
|
|
124104
124104
|
/**
|
|
124105
|
-
*
|
|
124106
|
-
*
|
|
124105
|
+
* Historical threshold for removed lazy card creation experiments. Bounded
|
|
124106
|
+
* so older config remains parseable without growing arbitrary business rules.
|
|
124107
124107
|
*/
|
|
124108
124108
|
text_threshold_chars: external_exports.number().int().min(1).max(2e4).default(1200)
|
|
124109
124109
|
}).default(responseSurfacePrototypeConfigDefaults);
|
package/dist/main.js
CHANGED
|
@@ -118708,9 +118708,9 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
118708
118708
|
*/
|
|
118709
118709
|
allowed_threads: external_exports.array(external_exports.string().min(1)).default([]),
|
|
118710
118710
|
/**
|
|
118711
|
-
*
|
|
118712
|
-
*
|
|
118713
|
-
*
|
|
118711
|
+
* Historical post-first gate retained for config compatibility. The default
|
|
118712
|
+
* runtime no longer uses post-first lazy card creation; CardKit is the main
|
|
118713
|
+
* surface and legacy cards remain the visible fallback.
|
|
118714
118714
|
*/
|
|
118715
118715
|
lazy_card_creation: external_exports.boolean().default(true),
|
|
118716
118716
|
/**
|
|
@@ -118720,8 +118720,8 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
118720
118720
|
*/
|
|
118721
118721
|
kill_switch: external_exports.boolean().default(false),
|
|
118722
118722
|
/**
|
|
118723
|
-
* Gate for real post outbound. Defaults on
|
|
118724
|
-
*
|
|
118723
|
+
* Gate for real post outbound. Defaults on so create-only visible fallback
|
|
118724
|
+
* posts remain available when CardKit and legacy card rendering both fail.
|
|
118725
118725
|
*/
|
|
118726
118726
|
post_outbound_enabled: external_exports.boolean().default(true),
|
|
118727
118727
|
/**
|
|
@@ -118743,8 +118743,8 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
118743
118743
|
*/
|
|
118744
118744
|
allowed_mention_open_ids: external_exports.array(external_exports.string().min(1)).default([]),
|
|
118745
118745
|
/**
|
|
118746
|
-
*
|
|
118747
|
-
*
|
|
118746
|
+
* Historical post dispatch cap retained for schema compatibility and
|
|
118747
|
+
* isolated dispatcher tests.
|
|
118748
118748
|
*/
|
|
118749
118749
|
max_posts_per_turn: external_exports.number().int().min(0).max(10).default(1),
|
|
118750
118750
|
/**
|
|
@@ -118763,8 +118763,8 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
118763
118763
|
*/
|
|
118764
118764
|
max_post_attempts: external_exports.number().int().min(1).max(5).default(3),
|
|
118765
118765
|
/**
|
|
118766
|
-
*
|
|
118767
|
-
*
|
|
118766
|
+
* Historical threshold for removed lazy card creation experiments. Bounded
|
|
118767
|
+
* so older config remains parseable without growing arbitrary business rules.
|
|
118768
118768
|
*/
|
|
118769
118769
|
text_threshold_chars: external_exports.number().int().min(1).max(2e4).default(1200)
|
|
118770
118770
|
}).default(responseSurfacePrototypeConfigDefaults);
|
|
@@ -118793,9 +118793,6 @@ function shouldProvideResponseSurfaceCardKitClient(config) {
|
|
|
118793
118793
|
function isResponseSurfaceCardKitAvailable(config, facts, opts) {
|
|
118794
118794
|
return !!(opts.cardKitClientAvailable && shouldProvideResponseSurfaceCardKitClient(config) && isResponseSurfacePrototypeAllowlisted(config, facts));
|
|
118795
118795
|
}
|
|
118796
|
-
function isResponseSurfacePostOutboundAvailable(config, facts, opts) {
|
|
118797
|
-
return !!(opts.postClientAvailable && shouldProvideResponseSurfacePostClient(config) && isResponseSurfacePrototypeAllowlisted(config, facts));
|
|
118798
|
-
}
|
|
118799
118796
|
|
|
118800
118797
|
// src/bridge/stateFile.ts
|
|
118801
118798
|
var optionalUrl = external_exports.preprocess(
|
|
@@ -119755,93 +119752,6 @@ async function finalizeExistingCardKitCard(opts) {
|
|
|
119755
119752
|
return sequence;
|
|
119756
119753
|
}
|
|
119757
119754
|
|
|
119758
|
-
// src/bridge/surfaceController.ts
|
|
119759
|
-
var SurfaceController = class _SurfaceController {
|
|
119760
|
-
decision;
|
|
119761
|
-
constructor(decision) {
|
|
119762
|
-
this.decision = decision;
|
|
119763
|
-
}
|
|
119764
|
-
static create(input) {
|
|
119765
|
-
const cfg = input.prototypeConfig;
|
|
119766
|
-
if (!cfg?.enabled) {
|
|
119767
|
-
return new _SurfaceController({
|
|
119768
|
-
startCardImmediately: true,
|
|
119769
|
-
prototypeEnabled: false,
|
|
119770
|
-
lazyCardCreationEnabled: false,
|
|
119771
|
-
reason: "prototype-disabled"
|
|
119772
|
-
});
|
|
119773
|
-
}
|
|
119774
|
-
if (cfg.kill_switch) {
|
|
119775
|
-
return new _SurfaceController({
|
|
119776
|
-
startCardImmediately: true,
|
|
119777
|
-
prototypeEnabled: false,
|
|
119778
|
-
lazyCardCreationEnabled: false,
|
|
119779
|
-
reason: "kill-switch-active"
|
|
119780
|
-
});
|
|
119781
|
-
}
|
|
119782
|
-
if (!isResponseSurfacePrototypeAllowlisted(cfg, {
|
|
119783
|
-
chatId: input.chatId,
|
|
119784
|
-
threadId: input.threadId
|
|
119785
|
-
})) {
|
|
119786
|
-
return new _SurfaceController({
|
|
119787
|
-
startCardImmediately: true,
|
|
119788
|
-
prototypeEnabled: false,
|
|
119789
|
-
lazyCardCreationEnabled: false,
|
|
119790
|
-
reason: "not-allowlisted"
|
|
119791
|
-
});
|
|
119792
|
-
}
|
|
119793
|
-
if (!cfg.lazy_card_creation) {
|
|
119794
|
-
return new _SurfaceController({
|
|
119795
|
-
startCardImmediately: true,
|
|
119796
|
-
prototypeEnabled: true,
|
|
119797
|
-
lazyCardCreationEnabled: false,
|
|
119798
|
-
reason: "lazy-card-disabled"
|
|
119799
|
-
});
|
|
119800
|
-
}
|
|
119801
|
-
if (!cfg.post_outbound_enabled) {
|
|
119802
|
-
return new _SurfaceController({
|
|
119803
|
-
startCardImmediately: true,
|
|
119804
|
-
prototypeEnabled: true,
|
|
119805
|
-
lazyCardCreationEnabled: false,
|
|
119806
|
-
reason: "post-outbound-disabled"
|
|
119807
|
-
});
|
|
119808
|
-
}
|
|
119809
|
-
if (!input.postOutboundAvailable) {
|
|
119810
|
-
return new _SurfaceController({
|
|
119811
|
-
startCardImmediately: true,
|
|
119812
|
-
prototypeEnabled: true,
|
|
119813
|
-
lazyCardCreationEnabled: false,
|
|
119814
|
-
reason: "post-outbound-unavailable-card-fallback"
|
|
119815
|
-
});
|
|
119816
|
-
}
|
|
119817
|
-
if (input.postLedgerAvailable === false) {
|
|
119818
|
-
return new _SurfaceController({
|
|
119819
|
-
startCardImmediately: true,
|
|
119820
|
-
prototypeEnabled: true,
|
|
119821
|
-
lazyCardCreationEnabled: false,
|
|
119822
|
-
reason: "post-ledger-unavailable-card-fallback"
|
|
119823
|
-
});
|
|
119824
|
-
}
|
|
119825
|
-
if (input.visibleFallbackAvailable === false) {
|
|
119826
|
-
return new _SurfaceController({
|
|
119827
|
-
startCardImmediately: true,
|
|
119828
|
-
prototypeEnabled: true,
|
|
119829
|
-
lazyCardCreationEnabled: false,
|
|
119830
|
-
reason: "visible-fallback-unavailable-card-fallback"
|
|
119831
|
-
});
|
|
119832
|
-
}
|
|
119833
|
-
return new _SurfaceController({
|
|
119834
|
-
startCardImmediately: false,
|
|
119835
|
-
prototypeEnabled: true,
|
|
119836
|
-
lazyCardCreationEnabled: true,
|
|
119837
|
-
reason: "lazy-card-ready"
|
|
119838
|
-
});
|
|
119839
|
-
}
|
|
119840
|
-
shouldStartCardImmediately() {
|
|
119841
|
-
return this.decision.startCardImmediately;
|
|
119842
|
-
}
|
|
119843
|
-
};
|
|
119844
|
-
|
|
119845
119755
|
// src/lark/postContent.ts
|
|
119846
119756
|
function assertSafeUserId(userId) {
|
|
119847
119757
|
if (!/^[A-Za-z0-9_:-]+$/.test(userId)) {
|
|
@@ -120609,162 +120519,6 @@ async function dispatchResponseSurface(input) {
|
|
|
120609
120519
|
return result;
|
|
120610
120520
|
}
|
|
120611
120521
|
|
|
120612
|
-
// src/bridge/postProgress.ts
|
|
120613
|
-
var DEFAULT_PLACEHOLDER_TEXT = "\u52AA\u529B\u56DE\u7B54\u4E2D...";
|
|
120614
|
-
var DEFAULT_PATCH_INTERVAL_MS2 = 1500;
|
|
120615
|
-
var DEFAULT_MAX_PROGRESS_EDITS = 16;
|
|
120616
|
-
function normalizeText2(text) {
|
|
120617
|
-
return text.replace(/\r\n/g, "\n").trim();
|
|
120618
|
-
}
|
|
120619
|
-
function progressText(raw, fallback) {
|
|
120620
|
-
const text = normalizeText2(raw);
|
|
120621
|
-
if (!text) return fallback;
|
|
120622
|
-
return text.length > 3500 ? `${text.slice(0, 3500)}
|
|
120623
|
-
|
|
120624
|
-
_\u5904\u7406\u4E2D\u5185\u5BB9\u8F83\u957F\uFF0C\u7EC8\u7A3F\u4F1A\u6536\u655B\u3002_` : text;
|
|
120625
|
-
}
|
|
120626
|
-
var LivePostProgressHandle = class {
|
|
120627
|
-
messageId;
|
|
120628
|
-
idempotencyKey;
|
|
120629
|
-
role = "primary";
|
|
120630
|
-
postClient;
|
|
120631
|
-
patchIntervalMs;
|
|
120632
|
-
maxProgressEdits;
|
|
120633
|
-
initialText;
|
|
120634
|
-
textBuffer = "";
|
|
120635
|
-
lastPatchedText = "";
|
|
120636
|
-
progressEdits = 0;
|
|
120637
|
-
pendingPatch = null;
|
|
120638
|
-
inFlight = Promise.resolve();
|
|
120639
|
-
closed = false;
|
|
120640
|
-
constructor(opts) {
|
|
120641
|
-
this.postClient = opts.postClient;
|
|
120642
|
-
this.messageId = opts.messageId;
|
|
120643
|
-
this.idempotencyKey = opts.idempotencyKey;
|
|
120644
|
-
this.initialText = opts.initialText;
|
|
120645
|
-
this.lastPatchedText = opts.initialText;
|
|
120646
|
-
this.patchIntervalMs = opts.patchIntervalMs;
|
|
120647
|
-
this.maxProgressEdits = opts.maxProgressEdits;
|
|
120648
|
-
}
|
|
120649
|
-
handle(event) {
|
|
120650
|
-
if (this.closed) return;
|
|
120651
|
-
if (event.type === "answer_delta") {
|
|
120652
|
-
this.textBuffer += event.text;
|
|
120653
|
-
} else if (event.type === "answer_snapshot") {
|
|
120654
|
-
this.textBuffer = event.text;
|
|
120655
|
-
} else {
|
|
120656
|
-
return;
|
|
120657
|
-
}
|
|
120658
|
-
this.schedulePatch();
|
|
120659
|
-
}
|
|
120660
|
-
async finalize(opts) {
|
|
120661
|
-
await this.drain();
|
|
120662
|
-
const finalText = normalizeText2(opts.text) || this.initialText;
|
|
120663
|
-
await this.update(finalText, opts.mentions);
|
|
120664
|
-
}
|
|
120665
|
-
async drain() {
|
|
120666
|
-
this.closed = true;
|
|
120667
|
-
if (this.pendingPatch) {
|
|
120668
|
-
clearTimeout(this.pendingPatch);
|
|
120669
|
-
this.pendingPatch = null;
|
|
120670
|
-
}
|
|
120671
|
-
await this.inFlight;
|
|
120672
|
-
}
|
|
120673
|
-
close() {
|
|
120674
|
-
this.closed = true;
|
|
120675
|
-
if (this.pendingPatch) {
|
|
120676
|
-
clearTimeout(this.pendingPatch);
|
|
120677
|
-
this.pendingPatch = null;
|
|
120678
|
-
}
|
|
120679
|
-
}
|
|
120680
|
-
schedulePatch() {
|
|
120681
|
-
if (this.pendingPatch || this.progressEdits >= this.maxProgressEdits) return;
|
|
120682
|
-
this.pendingPatch = setTimeout(() => {
|
|
120683
|
-
this.pendingPatch = null;
|
|
120684
|
-
void this.patchProgress();
|
|
120685
|
-
}, this.patchIntervalMs);
|
|
120686
|
-
this.pendingPatch.unref?.();
|
|
120687
|
-
}
|
|
120688
|
-
async patchProgress() {
|
|
120689
|
-
if (this.closed || this.progressEdits >= this.maxProgressEdits) return;
|
|
120690
|
-
const nextText = progressText(this.textBuffer, this.initialText);
|
|
120691
|
-
if (nextText === this.lastPatchedText) return;
|
|
120692
|
-
this.progressEdits += 1;
|
|
120693
|
-
this.inFlight = this.inFlight.then(() => this.update(nextText)).catch((err) => {
|
|
120694
|
-
console.warn("[post_progress] progress update failed (continuing):", err);
|
|
120695
|
-
});
|
|
120696
|
-
await this.inFlight;
|
|
120697
|
-
}
|
|
120698
|
-
async update(text, mentions = []) {
|
|
120699
|
-
const content = buildPostContent({ text, mentions });
|
|
120700
|
-
await this.postClient.updatePost(this.messageId, content);
|
|
120701
|
-
this.lastPatchedText = text;
|
|
120702
|
-
}
|
|
120703
|
-
};
|
|
120704
|
-
async function createPostProgressHandle(opts) {
|
|
120705
|
-
const role = "primary";
|
|
120706
|
-
const initialText = normalizeText2(opts.initialText ?? DEFAULT_PLACEHOLDER_TEXT);
|
|
120707
|
-
const idempotencyKey2 = derivePostIdempotencyKey({
|
|
120708
|
-
botId: opts.facts.botId,
|
|
120709
|
-
threadId: opts.facts.threadId,
|
|
120710
|
-
triggerMessageId: opts.facts.triggerMessageId,
|
|
120711
|
-
role,
|
|
120712
|
-
logicalIndex: 0,
|
|
120713
|
-
contentDigest: digestPostContent("live-progress-placeholder")
|
|
120714
|
-
});
|
|
120715
|
-
const sent = await opts.postClient.createPostReply(
|
|
120716
|
-
opts.replyToMessageId,
|
|
120717
|
-
buildPostContent({ text: initialText }),
|
|
120718
|
-
{
|
|
120719
|
-
replyInThread: opts.replyInThread,
|
|
120720
|
-
idempotencyKey: idempotencyKey2
|
|
120721
|
-
}
|
|
120722
|
-
);
|
|
120723
|
-
return new LivePostProgressHandle({
|
|
120724
|
-
postClient: opts.postClient,
|
|
120725
|
-
messageId: sent.messageId,
|
|
120726
|
-
idempotencyKey: idempotencyKey2,
|
|
120727
|
-
initialText,
|
|
120728
|
-
patchIntervalMs: opts.patchIntervalMs ?? DEFAULT_PATCH_INTERVAL_MS2,
|
|
120729
|
-
maxProgressEdits: opts.maxProgressEdits ?? DEFAULT_MAX_PROGRESS_EDITS
|
|
120730
|
-
});
|
|
120731
|
-
}
|
|
120732
|
-
|
|
120733
|
-
// src/bridge/postBudget.ts
|
|
120734
|
-
function scopeKey(scope) {
|
|
120735
|
-
return `${scope.botId}\0${scope.chatId}\0${scope.threadId}`;
|
|
120736
|
-
}
|
|
120737
|
-
var ResponseSurfacePostBudget = class {
|
|
120738
|
-
buckets = /* @__PURE__ */ new Map();
|
|
120739
|
-
reserve(input) {
|
|
120740
|
-
const nowMs = input.nowMs ?? Date.now();
|
|
120741
|
-
const limit = Math.max(0, Math.floor(input.maxPosts));
|
|
120742
|
-
const windowMs = Math.max(1, Math.floor(input.windowMs));
|
|
120743
|
-
const key = scopeKey(input.scope);
|
|
120744
|
-
const cutoff = nowMs - windowMs;
|
|
120745
|
-
const existing = (this.buckets.get(key) ?? []).filter((ts) => ts > cutoff);
|
|
120746
|
-
if (limit < 1 || existing.length >= limit) {
|
|
120747
|
-
this.buckets.set(key, existing);
|
|
120748
|
-
return {
|
|
120749
|
-
allowed: false,
|
|
120750
|
-
used: existing.length,
|
|
120751
|
-
limit,
|
|
120752
|
-
windowMs,
|
|
120753
|
-
resetAt: existing.length > 0 ? new Date(Math.min(...existing) + windowMs).toISOString() : void 0,
|
|
120754
|
-
reason: "post-window-exhausted"
|
|
120755
|
-
};
|
|
120756
|
-
}
|
|
120757
|
-
const next = [...existing, nowMs];
|
|
120758
|
-
this.buckets.set(key, next);
|
|
120759
|
-
return {
|
|
120760
|
-
allowed: true,
|
|
120761
|
-
used: next.length,
|
|
120762
|
-
limit,
|
|
120763
|
-
windowMs
|
|
120764
|
-
};
|
|
120765
|
-
}
|
|
120766
|
-
};
|
|
120767
|
-
|
|
120768
120522
|
// src/bridge/handler.ts
|
|
120769
120523
|
var DEFAULT_CARDKIT_RESPONSE_SURFACE_TIMEOUT_MS = 20 * 60 * 1e3;
|
|
120770
120524
|
function execGit(cwd, args) {
|
|
@@ -121021,7 +120775,6 @@ async function createOnlyPostFallback(opts) {
|
|
|
121021
120775
|
}
|
|
121022
120776
|
var BridgeHandler = class {
|
|
121023
120777
|
deps;
|
|
121024
|
-
responseSurfacePostBudget = new ResponseSurfacePostBudget();
|
|
121025
120778
|
closed = false;
|
|
121026
120779
|
constructor(deps) {
|
|
121027
120780
|
this.deps = deps;
|
|
@@ -121134,31 +120887,19 @@ var BridgeHandler = class {
|
|
|
121134
120887
|
const isTopLevel = !(typeof parsed.raw.root_id === "string" && parsed.raw.root_id);
|
|
121135
120888
|
const replyInThread = isTopLevel;
|
|
121136
120889
|
const prototypeConfig = this.deps.botConfig?.response_surface_prototype;
|
|
121137
|
-
const postOutboundAvailable = isResponseSurfacePostOutboundAvailable(
|
|
121138
|
-
prototypeConfig,
|
|
121139
|
-
{ chatId: parsed.chatId, threadId },
|
|
121140
|
-
{ postClientAvailable: !!this.deps.postClient }
|
|
121141
|
-
);
|
|
121142
120890
|
const cardKitAvailable = isResponseSurfaceCardKitAvailable(
|
|
121143
120891
|
prototypeConfig,
|
|
121144
120892
|
{ chatId: parsed.chatId, threadId },
|
|
121145
120893
|
{ cardKitClientAvailable: !!this.deps.cardKitClient }
|
|
121146
120894
|
);
|
|
121147
|
-
const surfaceController = SurfaceController.create({
|
|
121148
|
-
prototypeConfig,
|
|
121149
|
-
chatId: parsed.chatId,
|
|
121150
|
-
threadId,
|
|
121151
|
-
postOutboundAvailable: false,
|
|
121152
|
-
postLedgerAvailable: true,
|
|
121153
|
-
visibleFallbackAvailable: true
|
|
121154
|
-
});
|
|
121155
120895
|
let card;
|
|
121156
120896
|
let cardKitProgress;
|
|
121157
120897
|
let cardKitRecord;
|
|
121158
120898
|
let cardKitStartFailed = false;
|
|
121159
|
-
let
|
|
121160
|
-
let
|
|
121161
|
-
|
|
120899
|
+
let legacyCardStartFailed = false;
|
|
120900
|
+
let legacyCardStartFailureReason;
|
|
120901
|
+
let startFailurePostFallbackSent = false;
|
|
120902
|
+
if (!cardKitAvailable) {
|
|
121162
120903
|
try {
|
|
121163
120904
|
card = await this.deps.cardRenderer.start(messageId, { replyInThread, threadId });
|
|
121164
120905
|
await recordEvent({
|
|
@@ -121168,6 +120909,8 @@ var BridgeHandler = class {
|
|
|
121168
120909
|
reason: "\u5DF2\u4EA4\u7ED9\u672C\u5730 Agent \u5904\u7406\u3002"
|
|
121169
120910
|
});
|
|
121170
120911
|
} catch (err) {
|
|
120912
|
+
legacyCardStartFailed = true;
|
|
120913
|
+
legacyCardStartFailureReason = String(err);
|
|
121171
120914
|
console.error("[bridge.handler] Failed to start card for thread", threadId, err);
|
|
121172
120915
|
await recordEvent({
|
|
121173
120916
|
status: "running",
|
|
@@ -121183,7 +120926,7 @@ var BridgeHandler = class {
|
|
|
121183
120926
|
status: "running",
|
|
121184
120927
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
121185
120928
|
appendPath: "\u5EF6\u8FDF\u521B\u5EFA\u5361\u7247",
|
|
121186
|
-
reason: "
|
|
120929
|
+
reason: "CardKit response surface is available; legacy card is reserved for fallback."
|
|
121187
120930
|
});
|
|
121188
120931
|
}
|
|
121189
120932
|
try {
|
|
@@ -121405,72 +121148,34 @@ var BridgeHandler = class {
|
|
|
121405
121148
|
}
|
|
121406
121149
|
}
|
|
121407
121150
|
}
|
|
121408
|
-
if (!card &&
|
|
121409
|
-
const budget = prototypeConfig ? this.responseSurfacePostBudget.reserve({
|
|
121410
|
-
scope: {
|
|
121411
|
-
botId: this.deps.botConfig?.id ?? "v1-default",
|
|
121412
|
-
chatId: parsed.chatId,
|
|
121413
|
-
threadId
|
|
121414
|
-
},
|
|
121415
|
-
maxPosts: prototypeConfig.max_posts_per_window,
|
|
121416
|
-
windowMs: prototypeConfig.post_window_ms
|
|
121417
|
-
}) : void 0;
|
|
121418
|
-
if (budget?.allowed === false) {
|
|
121419
|
-
console.warn("[bridge.handler] post progress budget exhausted; using card fallback");
|
|
121420
|
-
progressPostStartFailed = true;
|
|
121421
|
-
} else {
|
|
121422
|
-
try {
|
|
121423
|
-
progressPost = await createPostProgressHandle({
|
|
121424
|
-
postClient: this.deps.postClient,
|
|
121425
|
-
replyToMessageId: messageId,
|
|
121426
|
-
replyInThread,
|
|
121427
|
-
facts: {
|
|
121428
|
-
botId: this.deps.botConfig?.id ?? "v1-default",
|
|
121429
|
-
threadId,
|
|
121430
|
-
triggerMessageId: messageId
|
|
121431
|
-
},
|
|
121432
|
-
initialText: "\u52AA\u529B\u56DE\u7B54\u4E2D..."
|
|
121433
|
-
});
|
|
121434
|
-
await this.deps.client.removeProcessingReaction?.(messageId);
|
|
121435
|
-
await recordEvent({
|
|
121436
|
-
status: "running",
|
|
121437
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
121438
|
-
appendPath: "\u5DF2\u521B\u5EFA post",
|
|
121439
|
-
reason: "response surface \u4F7F\u7528 post \u4F5C\u4E3A\u672C\u8F6E\u4E3B\u56DE\u590D\u9762\u3002"
|
|
121440
|
-
});
|
|
121441
|
-
} catch (err) {
|
|
121442
|
-
progressPostStartFailed = true;
|
|
121443
|
-
console.warn("[bridge.handler] create progress post failed; using card fallback:", err);
|
|
121444
|
-
}
|
|
121445
|
-
}
|
|
121446
|
-
}
|
|
121447
|
-
if (!card && (progressPostStartFailed || cardKitStartFailed)) {
|
|
121151
|
+
if (!card && cardKitStartFailed) {
|
|
121448
121152
|
try {
|
|
121449
121153
|
card = await this.deps.cardRenderer.start(messageId, { replyInThread, threadId });
|
|
121450
121154
|
await this.deps.client.removeProcessingReaction?.(messageId);
|
|
121451
121155
|
await recordEvent({
|
|
121452
121156
|
status: "running",
|
|
121453
121157
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
121454
|
-
appendPath:
|
|
121455
|
-
reason:
|
|
121158
|
+
appendPath: "CardKit \u5931\u8D25\uFF0C\u5DF2\u521B\u5EFA\u5361\u7247",
|
|
121159
|
+
reason: "CardKit \u4E3B\u9762\u521B\u5EFA\u5931\u8D25\uFF0Cbridge \u4F7F\u7528\u53EF\u89C1\u5361\u7247\u515C\u5E95\u3002"
|
|
121456
121160
|
});
|
|
121457
121161
|
} catch (err) {
|
|
121458
121162
|
console.error(
|
|
121459
121163
|
"[bridge.handler] visible card fallback start failed after primary surface start failure:",
|
|
121460
121164
|
err
|
|
121461
121165
|
);
|
|
121462
|
-
await createOnlyPostFallback({
|
|
121166
|
+
const postFallback = await createOnlyPostFallback({
|
|
121463
121167
|
postClient: this.deps.postClient,
|
|
121464
121168
|
replyToMessageId: messageId,
|
|
121465
121169
|
replyInThread,
|
|
121466
121170
|
botId: this.deps.botConfig?.id ?? "v1-default",
|
|
121467
121171
|
threadId,
|
|
121468
121172
|
triggerMessageId: messageId,
|
|
121469
|
-
finalText:
|
|
121173
|
+
finalText: "CardKit \u4E3B\u56DE\u590D\u9762\u521B\u5EFA\u5931\u8D25, legacy \u53EF\u89C1\u5361\u7247\u515C\u5E95\u4E5F\u521B\u5EFA\u5931\u8D25\u3002",
|
|
121470
121174
|
failureReason: String(err),
|
|
121471
121175
|
title: "Larkway fallback",
|
|
121472
121176
|
logPrefix: "[bridge.handler]"
|
|
121473
121177
|
});
|
|
121178
|
+
if (postFallback) startFailurePostFallbackSent = true;
|
|
121474
121179
|
await this.deps.client.removeProcessingReaction?.(messageId);
|
|
121475
121180
|
await recordEvent({
|
|
121476
121181
|
status: "running",
|
|
@@ -121560,7 +121265,6 @@ var BridgeHandler = class {
|
|
|
121560
121265
|
for await (const ev of handle.events) {
|
|
121561
121266
|
if (cardKitProgress) cardKitProgress.handle(ev);
|
|
121562
121267
|
else if (card) card.handle(ev);
|
|
121563
|
-
else progressPost?.handle(ev);
|
|
121564
121268
|
if (ev.type === "system_init") {
|
|
121565
121269
|
sessionId = ev.sessionId;
|
|
121566
121270
|
}
|
|
@@ -121707,7 +121411,6 @@ var BridgeHandler = class {
|
|
|
121707
121411
|
}
|
|
121708
121412
|
}
|
|
121709
121413
|
} else {
|
|
121710
|
-
await progressPost?.drain();
|
|
121711
121414
|
const surfaceDispatch = await dispatchResponseSurface({
|
|
121712
121415
|
state: reportedState,
|
|
121713
121416
|
prototypeConfig,
|
|
@@ -121725,80 +121428,90 @@ var BridgeHandler = class {
|
|
|
121725
121428
|
postOutboundAvailable: false,
|
|
121726
121429
|
postLedgerAvailable: true,
|
|
121727
121430
|
visibleFallbackAvailable: true,
|
|
121728
|
-
postClient: this.deps.postClient
|
|
121729
|
-
livePost: progressPost ? {
|
|
121730
|
-
messageId: progressPost.messageId,
|
|
121731
|
-
idempotencyKey: progressPost.idempotencyKey,
|
|
121732
|
-
role: progressPost.role
|
|
121733
|
-
} : void 0,
|
|
121734
|
-
postBudget: prototypeConfig ? {
|
|
121735
|
-
reserve: () => this.responseSurfacePostBudget.reserve({
|
|
121736
|
-
scope: {
|
|
121737
|
-
botId: this.deps.botConfig?.id ?? "v1-default",
|
|
121738
|
-
chatId: parsed.chatId,
|
|
121739
|
-
threadId
|
|
121740
|
-
},
|
|
121741
|
-
maxPosts: prototypeConfig.max_posts_per_window,
|
|
121742
|
-
windowMs: prototypeConfig.post_window_ms
|
|
121743
|
-
})
|
|
121744
|
-
} : void 0
|
|
121431
|
+
postClient: this.deps.postClient
|
|
121745
121432
|
});
|
|
121746
121433
|
if (surfaceDispatch.card) {
|
|
121747
121434
|
if (!card) {
|
|
121748
|
-
card = await this.deps.cardRenderer.start(messageId, { replyInThread, threadId });
|
|
121749
121435
|
try {
|
|
121750
|
-
await
|
|
121751
|
-
|
|
121752
|
-
|
|
121753
|
-
|
|
121754
|
-
|
|
121755
|
-
|
|
121756
|
-
|
|
121757
|
-
|
|
121758
|
-
|
|
121759
|
-
|
|
121760
|
-
|
|
121761
|
-
|
|
121762
|
-
|
|
121763
|
-
let keepCardFileForRetry = false;
|
|
121764
|
-
if (surfaceDispatch.post?.requiresFallbackLedgerMark) {
|
|
121765
|
-
try {
|
|
121766
|
-
await markPostLedgerFallbackVisible(
|
|
121767
|
-
worktreePath,
|
|
121768
|
-
surfaceDispatch.post.idempotencyKey,
|
|
121769
|
-
{
|
|
121770
|
-
fallbackCardMessageId: card.messageId,
|
|
121771
|
-
error: surfaceDispatch.post.fallbackError ?? surfaceDispatch.card.failureReason ?? "post outbound failed; visible card fallback used"
|
|
121772
|
-
}
|
|
121773
|
-
);
|
|
121436
|
+
card = await this.deps.cardRenderer.start(messageId, { replyInThread, threadId });
|
|
121437
|
+
try {
|
|
121438
|
+
await writeCardFile(worktreePath, {
|
|
121439
|
+
messageId: card.messageId,
|
|
121440
|
+
chatId: parsed.chatId,
|
|
121441
|
+
threadId,
|
|
121442
|
+
botId: this.deps.botConfig?.id ?? "",
|
|
121443
|
+
replyInThread,
|
|
121444
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
121445
|
+
});
|
|
121446
|
+
} catch (err) {
|
|
121447
|
+
console.warn("[bridge.handler] writeCardFile(late) failed (continuing):", err);
|
|
121448
|
+
}
|
|
121774
121449
|
} catch (err) {
|
|
121775
|
-
|
|
121776
|
-
|
|
121777
|
-
"[bridge.handler] fallback ledger mark failed after visible card finalize; keeping card.json for retry:",
|
|
121450
|
+
console.error(
|
|
121451
|
+
"[bridge.handler] late visible card fallback start failed; creating post fallback:",
|
|
121778
121452
|
err
|
|
121779
121453
|
);
|
|
121454
|
+
const failureReason2 = [
|
|
121455
|
+
legacyCardStartFailed ? `initial legacy visible card start failed: ${legacyCardStartFailureReason ?? "unknown"}` : void 0,
|
|
121456
|
+
`late legacy visible card fallback start failed: ${String(err)}`
|
|
121457
|
+
].filter((part) => !!part).join("; ");
|
|
121458
|
+
const postFallback = await createOnlyPostFallback({
|
|
121459
|
+
postClient: this.deps.postClient,
|
|
121460
|
+
replyToMessageId: messageId,
|
|
121461
|
+
replyInThread,
|
|
121462
|
+
botId: this.deps.botConfig?.id ?? "v1-default",
|
|
121463
|
+
threadId,
|
|
121464
|
+
triggerMessageId: messageId,
|
|
121465
|
+
finalText: surfaceDispatch.card.finalText ?? "Larkway completed but no visible card was available.",
|
|
121466
|
+
failureReason: failureReason2,
|
|
121467
|
+
title: surfaceDispatch.card.titleOverride ?? "Larkway fallback",
|
|
121468
|
+
logPrefix: "[bridge.handler]"
|
|
121469
|
+
});
|
|
121470
|
+
if (!postFallback) throw err;
|
|
121780
121471
|
}
|
|
121781
121472
|
}
|
|
121782
|
-
if (
|
|
121783
|
-
|
|
121784
|
-
|
|
121785
|
-
|
|
121786
|
-
|
|
121787
|
-
|
|
121788
|
-
|
|
121789
|
-
|
|
121790
|
-
|
|
121791
|
-
|
|
121792
|
-
|
|
121793
|
-
|
|
121794
|
-
|
|
121795
|
-
|
|
121796
|
-
|
|
121797
|
-
|
|
121473
|
+
if (card) {
|
|
121474
|
+
await card.finalize(surfaceDispatch.card);
|
|
121475
|
+
let keepCardFileForRetry = false;
|
|
121476
|
+
if (surfaceDispatch.post?.requiresFallbackLedgerMark) {
|
|
121477
|
+
try {
|
|
121478
|
+
await markPostLedgerFallbackVisible(
|
|
121479
|
+
worktreePath,
|
|
121480
|
+
surfaceDispatch.post.idempotencyKey,
|
|
121481
|
+
{
|
|
121482
|
+
fallbackCardMessageId: card.messageId,
|
|
121483
|
+
error: surfaceDispatch.post.fallbackError ?? surfaceDispatch.card.failureReason ?? "post outbound failed; visible card fallback used"
|
|
121484
|
+
}
|
|
121485
|
+
);
|
|
121486
|
+
} catch (err) {
|
|
121487
|
+
keepCardFileForRetry = true;
|
|
121488
|
+
console.warn(
|
|
121489
|
+
"[bridge.handler] fallback ledger mark failed after visible card finalize; keeping card.json for retry:",
|
|
121490
|
+
err
|
|
121491
|
+
);
|
|
121492
|
+
}
|
|
121493
|
+
}
|
|
121494
|
+
if (surfaceDispatch.post?.requiresPolicyLedgerMark) {
|
|
121495
|
+
try {
|
|
121496
|
+
await markPostLedgerPolicyBlockedVisible(
|
|
121497
|
+
worktreePath,
|
|
121498
|
+
surfaceDispatch.post.idempotencyKey,
|
|
121499
|
+
{
|
|
121500
|
+
fallbackCardMessageId: card.messageId,
|
|
121501
|
+
error: surfaceDispatch.post.policyError ?? surfaceDispatch.card.failureReason ?? "mention policy blocked; visible card fallback used"
|
|
121502
|
+
}
|
|
121503
|
+
);
|
|
121504
|
+
} catch (err) {
|
|
121505
|
+
keepCardFileForRetry = true;
|
|
121506
|
+
console.warn(
|
|
121507
|
+
"[bridge.handler] policy-blocked ledger mark failed after visible card finalize; keeping card.json for retry:",
|
|
121508
|
+
err
|
|
121509
|
+
);
|
|
121510
|
+
}
|
|
121511
|
+
}
|
|
121512
|
+
if (!keepCardFileForRetry) {
|
|
121513
|
+
await deleteCardFile(worktreePath);
|
|
121798
121514
|
}
|
|
121799
|
-
}
|
|
121800
|
-
if (!keepCardFileForRetry) {
|
|
121801
|
-
await deleteCardFile(worktreePath);
|
|
121802
121515
|
}
|
|
121803
121516
|
}
|
|
121804
121517
|
}
|
|
@@ -121877,25 +121590,10 @@ var BridgeHandler = class {
|
|
|
121877
121590
|
}
|
|
121878
121591
|
}
|
|
121879
121592
|
}
|
|
121880
|
-
if (!card &&
|
|
121881
|
-
|
|
121882
|
-
|
|
121883
|
-
|
|
121884
|
-
});
|
|
121885
|
-
} catch (postFinalizeErr) {
|
|
121886
|
-
console.error(
|
|
121887
|
-
"[bridge.handler] progress post failure update failed; creating card fallback:",
|
|
121888
|
-
postFinalizeErr
|
|
121889
|
-
);
|
|
121890
|
-
try {
|
|
121891
|
-
card = await this.deps.cardRenderer.start(messageId, { replyInThread, threadId });
|
|
121892
|
-
} catch (cardStartErr) {
|
|
121893
|
-
console.error("[bridge.handler] failure card start also failed:", cardStartErr);
|
|
121894
|
-
await createHardFailurePostFallback(
|
|
121895
|
-
`progress post failure update failed: ${String(postFinalizeErr)}; legacy visible card fallback also failed: ${String(cardStartErr)}`
|
|
121896
|
-
);
|
|
121897
|
-
}
|
|
121898
|
-
}
|
|
121593
|
+
if (!card && !cardKitProgress && !startFailurePostFallbackSent) {
|
|
121594
|
+
await createHardFailurePostFallback(
|
|
121595
|
+
legacyCardStartFailed ? `legacy visible card was unavailable before agent failure: ${legacyCardStartFailureReason ?? "unknown"}` : "no visible response surface was available before agent failure"
|
|
121596
|
+
);
|
|
121899
121597
|
}
|
|
121900
121598
|
if (card) {
|
|
121901
121599
|
try {
|
|
@@ -126045,127 +125743,104 @@ function buildCodexEnv(botGitIdentity, gitlabToken) {
|
|
|
126045
125743
|
}
|
|
126046
125744
|
return env;
|
|
126047
125745
|
}
|
|
126048
|
-
function
|
|
126049
|
-
|
|
126050
|
-
|
|
126051
|
-
return ["--dangerously-bypass-approvals-and-sandbox"];
|
|
126052
|
-
case "acceptEdits":
|
|
126053
|
-
return ["--dangerously-bypass-approvals-and-sandbox"];
|
|
126054
|
-
case "ask":
|
|
126055
|
-
return ["--sandbox", "read-only"];
|
|
126056
|
-
}
|
|
125746
|
+
function buildCodexCommand(opts, codexBinPath = "codex") {
|
|
125747
|
+
void opts;
|
|
125748
|
+
return [codexBinPath, ["app-server", "--stdio"]];
|
|
126057
125749
|
}
|
|
126058
|
-
function
|
|
126059
|
-
return mode === "
|
|
125750
|
+
function codexThreadSandboxMode(mode) {
|
|
125751
|
+
return mode === "ask" ? "read-only" : "danger-full-access";
|
|
126060
125752
|
}
|
|
126061
|
-
function
|
|
126062
|
-
|
|
126063
|
-
|
|
126064
|
-
|
|
126065
|
-
|
|
126066
|
-
|
|
126067
|
-
];
|
|
126068
|
-
if (opts.resumeSessionId != null) {
|
|
126069
|
-
const resumeFlags = [
|
|
126070
|
-
"--json",
|
|
126071
|
-
"--skip-git-repo-check",
|
|
126072
|
-
...resumePermissionFlag(mode)
|
|
126073
|
-
];
|
|
126074
|
-
return [
|
|
126075
|
-
codexBinPath,
|
|
126076
|
-
["exec", "resume", opts.resumeSessionId, ...resumeFlags, "-"]
|
|
126077
|
-
];
|
|
126078
|
-
}
|
|
126079
|
-
const freshFlags = opts.cwd != null ? ["-C", opts.cwd, ...commonFlags] : commonFlags;
|
|
126080
|
-
return [codexBinPath, ["exec", ...freshFlags]];
|
|
125753
|
+
function codexTurnSandboxPolicy(mode) {
|
|
125754
|
+
if (mode === "ask") return { type: "readOnly", networkAccess: false };
|
|
125755
|
+
return { type: "dangerFullAccess" };
|
|
125756
|
+
}
|
|
125757
|
+
function codexApprovalPolicy(mode) {
|
|
125758
|
+
return mode === "ask" ? "on-request" : "never";
|
|
126081
125759
|
}
|
|
126082
|
-
var
|
|
125760
|
+
var CodexAppServerLineParser = class {
|
|
126083
125761
|
answerExtractor = new AnswerChannelExtractor();
|
|
126084
|
-
*
|
|
126085
|
-
const trimmed = line.trim();
|
|
126086
|
-
if (trimmed === "") return;
|
|
126087
|
-
let obj;
|
|
126088
|
-
try {
|
|
126089
|
-
obj = JSON.parse(trimmed);
|
|
126090
|
-
} catch {
|
|
126091
|
-
yield { type: "raw", raw: trimmed };
|
|
126092
|
-
return;
|
|
126093
|
-
}
|
|
125762
|
+
*parseMessage(obj) {
|
|
126094
125763
|
if (typeof obj !== "object" || obj === null) {
|
|
126095
125764
|
yield { type: "raw", raw: obj };
|
|
126096
125765
|
return;
|
|
126097
125766
|
}
|
|
126098
125767
|
const record = obj;
|
|
126099
|
-
const
|
|
126100
|
-
if (
|
|
126101
|
-
yield { type: "
|
|
125768
|
+
const method = record["method"];
|
|
125769
|
+
if (typeof method !== "string") {
|
|
125770
|
+
yield { type: "raw", raw: obj };
|
|
126102
125771
|
return;
|
|
126103
125772
|
}
|
|
126104
|
-
|
|
125773
|
+
const params = asRecord(record["params"]);
|
|
125774
|
+
if (method === "thread/started") {
|
|
125775
|
+
const thread = asRecord(params?.["thread"]);
|
|
125776
|
+
const threadId = typeof thread?.["id"] === "string" ? thread["id"] : void 0;
|
|
125777
|
+
if (threadId) yield { type: "system_init", sessionId: threadId, raw: obj };
|
|
125778
|
+
return;
|
|
125779
|
+
}
|
|
125780
|
+
if (method === "turn/completed") {
|
|
126105
125781
|
yield { type: "result", stopReason: "end_turn", raw: obj };
|
|
126106
125782
|
return;
|
|
126107
125783
|
}
|
|
126108
|
-
|
|
126109
|
-
|
|
126110
|
-
|
|
126111
|
-
yield* this.answerExtractor.ingestSnapshot(agentMessageText, obj);
|
|
126112
|
-
return;
|
|
126113
|
-
}
|
|
126114
|
-
yield* this.answerExtractor.ingestGrowingSnapshot(agentMessageText, obj);
|
|
125784
|
+
if (method === "item/agentMessage/delta") {
|
|
125785
|
+
const delta = typeof params?.["delta"] === "string" ? params["delta"] : "";
|
|
125786
|
+
yield* this.answerExtractor.ingestDelta(delta, obj);
|
|
126115
125787
|
return;
|
|
126116
125788
|
}
|
|
126117
|
-
if (
|
|
126118
|
-
const item =
|
|
126119
|
-
if (
|
|
126120
|
-
|
|
126121
|
-
|
|
126122
|
-
|
|
126123
|
-
|
|
126124
|
-
|
|
126125
|
-
|
|
126126
|
-
|
|
126127
|
-
};
|
|
126128
|
-
return;
|
|
126129
|
-
}
|
|
125789
|
+
if (method === "item/started") {
|
|
125790
|
+
const item = asRecord(params?.["item"]);
|
|
125791
|
+
if (item?.["type"] === "commandExecution" && typeof item["command"] === "string") {
|
|
125792
|
+
yield {
|
|
125793
|
+
type: "tool_use",
|
|
125794
|
+
toolName: "shell",
|
|
125795
|
+
toolInput: { command: item["command"] },
|
|
125796
|
+
raw: obj
|
|
125797
|
+
};
|
|
125798
|
+
return;
|
|
126130
125799
|
}
|
|
126131
|
-
yield { type: "raw", raw: obj };
|
|
126132
125800
|
return;
|
|
126133
125801
|
}
|
|
126134
|
-
if (
|
|
126135
|
-
const item =
|
|
126136
|
-
if (
|
|
126137
|
-
|
|
126138
|
-
|
|
126139
|
-
|
|
126140
|
-
|
|
126141
|
-
|
|
125802
|
+
if (method === "item/completed") {
|
|
125803
|
+
const item = asRecord(params?.["item"]);
|
|
125804
|
+
if (item?.["type"] === "commandExecution") {
|
|
125805
|
+
yield { type: "tool_result", raw: obj };
|
|
125806
|
+
return;
|
|
125807
|
+
}
|
|
125808
|
+
if (item?.["type"] === "agentMessage" && typeof item["text"] === "string") {
|
|
125809
|
+
yield* this.answerExtractor.ingestSnapshot(item["text"], obj);
|
|
125810
|
+
return;
|
|
126142
125811
|
}
|
|
126143
|
-
yield { type: "raw", raw: obj };
|
|
126144
125812
|
return;
|
|
126145
125813
|
}
|
|
126146
125814
|
yield { type: "raw", raw: obj };
|
|
126147
125815
|
}
|
|
126148
125816
|
};
|
|
126149
|
-
function
|
|
126150
|
-
|
|
126151
|
-
|
|
126152
|
-
|
|
126153
|
-
|
|
126154
|
-
const
|
|
126155
|
-
|
|
125817
|
+
function asRecord(value) {
|
|
125818
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
125819
|
+
}
|
|
125820
|
+
function extractThreadIdFromThreadResponse(obj) {
|
|
125821
|
+
const record = asRecord(obj);
|
|
125822
|
+
const result = asRecord(record?.["result"]);
|
|
125823
|
+
const thread = asRecord(result?.["thread"]);
|
|
125824
|
+
const threadId = thread?.["id"];
|
|
125825
|
+
return typeof threadId === "string" ? threadId : void 0;
|
|
126156
125826
|
}
|
|
126157
125827
|
function runCodex(opts, codexBinPath = "codex") {
|
|
126158
125828
|
const timeoutMs = opts.timeoutMs ?? 15 * 60 * 1e3;
|
|
126159
125829
|
const [bin, args] = buildCodexCommand(opts, codexBinPath);
|
|
126160
125830
|
const env = buildCodexEnv(opts.botGitIdentity, opts.gitlabToken);
|
|
125831
|
+
const mode = opts.permissionMode ?? "acceptEdits";
|
|
125832
|
+
const requestById = /* @__PURE__ */ new Map();
|
|
125833
|
+
let nextRequestId = 1;
|
|
126161
125834
|
const child = spawn3(bin, args, {
|
|
126162
125835
|
env,
|
|
126163
125836
|
stdio: ["pipe", "pipe", "pipe"],
|
|
126164
125837
|
...opts.cwd != null ? { cwd: opts.cwd } : {}
|
|
126165
125838
|
});
|
|
126166
|
-
|
|
126167
|
-
|
|
126168
|
-
|
|
125839
|
+
function sendRequest(method, params) {
|
|
125840
|
+
const id = nextRequestId++;
|
|
125841
|
+
requestById.set(id, method);
|
|
125842
|
+
child.stdin?.write(JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n");
|
|
125843
|
+
return id;
|
|
126169
125844
|
}
|
|
126170
125845
|
let discoveredSessionId;
|
|
126171
125846
|
let killScheduled = false;
|
|
@@ -126179,6 +125854,10 @@ function runCodex(opts, codexBinPath = "codex") {
|
|
|
126179
125854
|
}, SIGKILL_GRACE_MS2);
|
|
126180
125855
|
killTimer.unref();
|
|
126181
125856
|
}
|
|
125857
|
+
function stopAppServerAfterTurn() {
|
|
125858
|
+
if (child.killed || killScheduled) return;
|
|
125859
|
+
child.kill("SIGTERM");
|
|
125860
|
+
}
|
|
126182
125861
|
const TOTAL_TIMEOUT_EXTRA_MS = SIGKILL_GRACE_MS2 + 2e3;
|
|
126183
125862
|
let totalTimeoutFallbackHandle;
|
|
126184
125863
|
let _forceFinalizeForTimeout = () => {
|
|
@@ -126201,6 +125880,8 @@ function runCodex(opts, codexBinPath = "codex") {
|
|
|
126201
125880
|
const stderrChunks = [];
|
|
126202
125881
|
child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
|
|
126203
125882
|
const rlAbortController = new AbortController();
|
|
125883
|
+
let finishAppServerTurn;
|
|
125884
|
+
let failAppServerTurn;
|
|
126204
125885
|
const done = new Promise(
|
|
126205
125886
|
(resolve2, reject) => {
|
|
126206
125887
|
let settled = false;
|
|
@@ -126230,6 +125911,17 @@ stderr: ${stderr}` : "")
|
|
|
126230
125911
|
}
|
|
126231
125912
|
resolve2({ exitCode, sessionId: discoveredSessionId });
|
|
126232
125913
|
};
|
|
125914
|
+
const finalizeReject = (err) => {
|
|
125915
|
+
if (settled) return;
|
|
125916
|
+
settled = true;
|
|
125917
|
+
clearTimeout(timeoutHandle);
|
|
125918
|
+
clearTimeout(killTimer);
|
|
125919
|
+
clearTimeout(totalTimeoutFallbackHandle);
|
|
125920
|
+
rlAbortController.abort();
|
|
125921
|
+
reject(err);
|
|
125922
|
+
};
|
|
125923
|
+
finishAppServerTurn = finalizeResolve;
|
|
125924
|
+
failAppServerTurn = finalizeReject;
|
|
126233
125925
|
_forceFinalizeForTimeout = () => {
|
|
126234
125926
|
if (settled) return;
|
|
126235
125927
|
console.warn(
|
|
@@ -126277,15 +125969,76 @@ stderr: ${stderr}` : "")
|
|
|
126277
125969
|
crlfDelay: Infinity,
|
|
126278
125970
|
signal: rlAbortController.signal
|
|
126279
125971
|
});
|
|
126280
|
-
const parser = new
|
|
125972
|
+
const parser = new CodexAppServerLineParser();
|
|
125973
|
+
let turnCompleted = false;
|
|
125974
|
+
sendRequest("initialize", {
|
|
125975
|
+
clientInfo: { name: "larkway", version: "0.3" },
|
|
125976
|
+
capabilities: {}
|
|
125977
|
+
});
|
|
126281
125978
|
try {
|
|
126282
125979
|
for await (const line of rl) {
|
|
126283
|
-
|
|
125980
|
+
const trimmed = line.trim();
|
|
125981
|
+
if (!trimmed) continue;
|
|
125982
|
+
let obj;
|
|
125983
|
+
try {
|
|
125984
|
+
obj = JSON.parse(trimmed);
|
|
125985
|
+
} catch {
|
|
125986
|
+
yield { type: "raw", raw: trimmed };
|
|
125987
|
+
continue;
|
|
125988
|
+
}
|
|
125989
|
+
const response = asRecord(obj);
|
|
125990
|
+
if (typeof response?.["id"] === "number") {
|
|
125991
|
+
const id = response["id"];
|
|
125992
|
+
const method = requestById.get(id);
|
|
125993
|
+
requestById.delete(id);
|
|
125994
|
+
const error = asRecord(response["error"]);
|
|
125995
|
+
if (error) {
|
|
125996
|
+
const message = typeof error["message"] === "string" ? error["message"] : JSON.stringify(error);
|
|
125997
|
+
failAppServerTurn?.(new Error(`codex app-server ${method ?? "request"} failed: ${message}`));
|
|
125998
|
+
stopAppServerAfterTurn();
|
|
125999
|
+
return;
|
|
126000
|
+
}
|
|
126001
|
+
if (method === "initialize") {
|
|
126002
|
+
const threadMethod = opts.resumeSessionId != null ? "thread/resume" : "thread/start";
|
|
126003
|
+
const threadParams = opts.resumeSessionId != null ? { threadId: opts.resumeSessionId } : { ephemeral: false, sessionStartSource: "startup" };
|
|
126004
|
+
if (opts.cwd != null) threadParams["cwd"] = opts.cwd;
|
|
126005
|
+
threadParams["approvalPolicy"] = codexApprovalPolicy(mode);
|
|
126006
|
+
threadParams["sandbox"] = codexThreadSandboxMode(mode);
|
|
126007
|
+
sendRequest(threadMethod, threadParams);
|
|
126008
|
+
continue;
|
|
126009
|
+
}
|
|
126010
|
+
if (method === "thread/start" || method === "thread/resume") {
|
|
126011
|
+
const threadId = extractThreadIdFromThreadResponse(obj);
|
|
126012
|
+
if (threadId) {
|
|
126013
|
+
discoveredSessionId = threadId;
|
|
126014
|
+
yield { type: "system_init", sessionId: threadId, raw: obj };
|
|
126015
|
+
const turnParams = {
|
|
126016
|
+
threadId,
|
|
126017
|
+
input: [{ type: "text", text: opts.prompt, text_elements: [] }],
|
|
126018
|
+
approvalPolicy: codexApprovalPolicy(mode),
|
|
126019
|
+
sandboxPolicy: codexTurnSandboxPolicy(mode)
|
|
126020
|
+
};
|
|
126021
|
+
if (opts.cwd != null) turnParams["cwd"] = opts.cwd;
|
|
126022
|
+
sendRequest("turn/start", turnParams);
|
|
126023
|
+
}
|
|
126024
|
+
continue;
|
|
126025
|
+
}
|
|
126026
|
+
continue;
|
|
126027
|
+
}
|
|
126028
|
+
for (const event of parser.parseMessage(obj)) {
|
|
126284
126029
|
if (event.type === "system_init") {
|
|
126285
126030
|
discoveredSessionId = event.sessionId;
|
|
126286
126031
|
}
|
|
126032
|
+
if (event.type === "result") {
|
|
126033
|
+
turnCompleted = true;
|
|
126034
|
+
}
|
|
126287
126035
|
yield event;
|
|
126288
126036
|
}
|
|
126037
|
+
if (turnCompleted) {
|
|
126038
|
+
stopAppServerAfterTurn();
|
|
126039
|
+
finishAppServerTurn?.(0);
|
|
126040
|
+
return;
|
|
126041
|
+
}
|
|
126289
126042
|
}
|
|
126290
126043
|
} catch (err) {
|
|
126291
126044
|
const isAbort = err instanceof Error && (err.name === "AbortError" || err.code === "ABORT_ERR");
|