@raysonmeng/agentbridge 0.1.18 → 0.1.20
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/.claude-plugin/marketplace.json +1 -1
- package/dist/cli.js +26 -12
- package/dist/daemon.js +442 -29
- package/package.json +1 -1
- package/plugins/agentbridge/.claude-plugin/plugin.json +1 -1
- package/plugins/agentbridge/server/bridge-server.js +32 -14
- package/plugins/agentbridge/server/daemon.js +442 -29
package/package.json
CHANGED
|
@@ -13858,6 +13858,9 @@ class StateDirResolver {
|
|
|
13858
13858
|
get killedFile() {
|
|
13859
13859
|
return join(this.stateDir, "killed");
|
|
13860
13860
|
}
|
|
13861
|
+
get admissionQuotaFile() {
|
|
13862
|
+
return join(this.stateDir, "admission-quota.json");
|
|
13863
|
+
}
|
|
13861
13864
|
get updateCheckFile() {
|
|
13862
13865
|
return join(this.stateDir, "update-check.json");
|
|
13863
13866
|
}
|
|
@@ -14099,6 +14102,8 @@ function renderBudgetSnapshot(snapshot, options = {}) {
|
|
|
14099
14102
|
} else {
|
|
14100
14103
|
lines.push(`\u6682\u505C\uFF1A\u53CC\u4FA7\u8054\u5408\u6682\u505C\uFF08\u95F8\u95E8\u5173\u95ED\uFF09 \u2014 ${reason}${resume}`);
|
|
14101
14104
|
}
|
|
14105
|
+
} else if (snapshot.gateState === "admission-closed") {
|
|
14106
|
+
lines.push("\u6682\u505C\uFF1A\u5426 \xB7 \u6536\u5C3E\u4FDD\u62A4\uFF1Aadmission-closed\uFF08Codex \u4FA7\u4EC5\u653E\u884C wrap-up/steer\uFF0C\u65B0\u4EFB\u52A1\u4F1A\u88AB\u62D2 budget_admission\uFF09");
|
|
14102
14107
|
} else {
|
|
14103
14108
|
lines.push("\u6682\u505C\uFF1A\u5426");
|
|
14104
14109
|
}
|
|
@@ -14156,7 +14161,8 @@ var CLAUDE_INSTRUCTIONS = [
|
|
|
14156
14161
|
"",
|
|
14157
14162
|
"## Budget awareness",
|
|
14158
14163
|
"- Use the get_budget tool to check both agents' subscription quota (5h/weekly windows, drift, pause state).",
|
|
14159
|
-
"- If the reply tool returns a budget-pause error, do NOT retry; checkpoint your work and wait for the resume notice."
|
|
14164
|
+
"- If the reply tool returns a budget-pause error (code budget_paused), do NOT retry; checkpoint your work and wait for the resume notice.",
|
|
14165
|
+
"- If the reply tool returns a budget_admission error, the 5h window is in finishing-protection: new tasks are declined, but you may bring the CURRENT collaboration to a checkpoint by resending with wrap_up=true (a small per-window quota). Do NOT start new work; once the quota is used or you are done, write a checkpoint and wait for the 5h window to refresh."
|
|
14160
14166
|
].join(`
|
|
14161
14167
|
`);
|
|
14162
14168
|
|
|
@@ -14400,6 +14406,10 @@ chat_id: ${this.sessionId}`);
|
|
|
14400
14406
|
idempotency_key: {
|
|
14401
14407
|
type: "string",
|
|
14402
14408
|
description: "Optional client-generated key (non-empty, max 128 chars) that makes this reply idempotent: a retry carrying the same key is NOT re-injected \u2014 the bridge answers duplicate_in_flight / duplicate_terminal instead. Use a fresh key per logical message."
|
|
14409
|
+
},
|
|
14410
|
+
wrap_up: {
|
|
14411
|
+
type: "boolean",
|
|
14412
|
+
description: "Set true ONLY to declare a finishing turn when the budget gate is in 5h finishing-protection (you got a budget_admission error or a system_budget_admission notice). A wrap-up reply is let through the admission gate up to a small per-5h-window quota so you can bring the current collaboration to a checkpoint; do NOT use it to start new work. Leave false/unset for normal replies."
|
|
14403
14413
|
}
|
|
14404
14414
|
},
|
|
14405
14415
|
required: ["text"]
|
|
@@ -14552,7 +14562,8 @@ chat_id: ${this.sessionId}`);
|
|
|
14552
14562
|
isError: true
|
|
14553
14563
|
};
|
|
14554
14564
|
}
|
|
14555
|
-
const
|
|
14565
|
+
const wrapUp = args?.wrap_up === true;
|
|
14566
|
+
const result = await this.replySender(bridgeMsg, requireReply, onBusy, idempotencyKey, wrapUp);
|
|
14556
14567
|
if (!result.success) {
|
|
14557
14568
|
this.log(`Reply delivery failed: ${result.error}${result.code ? ` (code=${result.code})` : ""}`);
|
|
14558
14569
|
const codePrefix = result.code ? ` [${result.code}]` : "";
|
|
@@ -14622,11 +14633,11 @@ function defineNumber(value, fallback) {
|
|
|
14622
14633
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
14623
14634
|
}
|
|
14624
14635
|
var BUILD_INFO = Object.freeze({
|
|
14625
|
-
version: defineString("0.1.
|
|
14626
|
-
commit: defineString("
|
|
14636
|
+
version: defineString("0.1.20", "0.0.0-source"),
|
|
14637
|
+
commit: defineString("d6034c6", "source"),
|
|
14627
14638
|
bundle: defineBundle("plugin"),
|
|
14628
14639
|
contractVersion: defineNumber(1, CONTRACT_VERSION),
|
|
14629
|
-
codeHash: defineString("
|
|
14640
|
+
codeHash: defineString("d2425ba159fe", "source")
|
|
14630
14641
|
});
|
|
14631
14642
|
function sameRuntimeContract(a, b) {
|
|
14632
14643
|
if (!a || !b)
|
|
@@ -14873,7 +14884,7 @@ class DaemonClient extends EventEmitter2 {
|
|
|
14873
14884
|
this.ws = null;
|
|
14874
14885
|
this.rejectPendingReplies("Daemon connection closed");
|
|
14875
14886
|
}
|
|
14876
|
-
async sendReply(message, requireReply, onBusy, idempotencyKey) {
|
|
14887
|
+
async sendReply(message, requireReply, onBusy, idempotencyKey, wrapUp) {
|
|
14877
14888
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
14878
14889
|
return { success: false, error: "AgentBridge daemon is not connected." };
|
|
14879
14890
|
}
|
|
@@ -14888,7 +14899,8 @@ class DaemonClient extends EventEmitter2 {
|
|
|
14888
14899
|
message,
|
|
14889
14900
|
...requireReply ? { requireReply: true } : {},
|
|
14890
14901
|
...onBusy && onBusy !== "reject" ? { onBusy } : {},
|
|
14891
|
-
...idempotencyKey ? { idempotencyKey } : {}
|
|
14902
|
+
...idempotencyKey ? { idempotencyKey } : {},
|
|
14903
|
+
...wrapUp ? { wrapUp: true } : {}
|
|
14892
14904
|
});
|
|
14893
14905
|
return pending;
|
|
14894
14906
|
}
|
|
@@ -15666,7 +15678,9 @@ var DEFAULT_BUDGET_CONFIG = {
|
|
|
15666
15678
|
reserveSlopePctPerHour: 0.4,
|
|
15667
15679
|
reserveMaxPct: 7,
|
|
15668
15680
|
finishingHorizonMinutes: 30,
|
|
15669
|
-
resumeHysteresisPct: 5
|
|
15681
|
+
resumeHysteresisPct: 5,
|
|
15682
|
+
admissionAt: 85,
|
|
15683
|
+
wrapUpQuota: 2
|
|
15670
15684
|
},
|
|
15671
15685
|
allocation: {
|
|
15672
15686
|
minRunwayRatio: 50,
|
|
@@ -15734,7 +15748,9 @@ function findShapeViolation(raw) {
|
|
|
15734
15748
|
"reserveSlopePctPerHour",
|
|
15735
15749
|
"reserveMaxPct",
|
|
15736
15750
|
"finishingHorizonMinutes",
|
|
15737
|
-
"resumeHysteresisPct"
|
|
15751
|
+
"resumeHysteresisPct",
|
|
15752
|
+
"admissionAt",
|
|
15753
|
+
"wrapUpQuota"
|
|
15738
15754
|
]) {
|
|
15739
15755
|
if (key in maximize && !isCoercibleNumber(maximize[key])) {
|
|
15740
15756
|
return `budget.maximize.${key} is present but not a number`;
|
|
@@ -15759,7 +15775,7 @@ function hasCustomDecisionValues(config2) {
|
|
|
15759
15775
|
const d = DEFAULT_CONFIG;
|
|
15760
15776
|
const b = config2.budget;
|
|
15761
15777
|
const db = d.budget;
|
|
15762
|
-
return config2.idleShutdownSeconds !== d.idleShutdownSeconds || config2.turnCoordination.attentionWindowSeconds !== d.turnCoordination.attentionWindowSeconds || config2.codex.appPort !== d.codex.appPort || config2.codex.proxyPort !== d.codex.proxyPort || b.enabled !== db.enabled || b.pollSeconds !== db.pollSeconds || b.pauseAt !== db.pauseAt || b.resumeBelow !== db.resumeBelow || b.syncDriftPct !== db.syncDriftPct || b.parallel.minRemainingPct !== db.parallel.minRemainingPct || b.parallel.timeWindowSec !== db.parallel.timeWindowSec || b.codexTierControl !== db.codexTierControl || b.maximize.targetUtil !== db.maximize.targetUtil || b.maximize.reserveSlopePctPerHour !== db.maximize.reserveSlopePctPerHour || b.maximize.reserveMaxPct !== db.maximize.reserveMaxPct || b.maximize.finishingHorizonMinutes !== db.maximize.finishingHorizonMinutes || b.maximize.resumeHysteresisPct !== db.maximize.resumeHysteresisPct || b.allocation.minRunwayRatio !== db.allocation.minRunwayRatio || b.allocation.minRunwayGapHours !== db.allocation.minRunwayGapHours;
|
|
15778
|
+
return config2.idleShutdownSeconds !== d.idleShutdownSeconds || config2.turnCoordination.attentionWindowSeconds !== d.turnCoordination.attentionWindowSeconds || config2.codex.appPort !== d.codex.appPort || config2.codex.proxyPort !== d.codex.proxyPort || b.enabled !== db.enabled || b.pollSeconds !== db.pollSeconds || b.pauseAt !== db.pauseAt || b.resumeBelow !== db.resumeBelow || b.syncDriftPct !== db.syncDriftPct || b.parallel.minRemainingPct !== db.parallel.minRemainingPct || b.parallel.timeWindowSec !== db.parallel.timeWindowSec || b.codexTierControl !== db.codexTierControl || b.maximize.targetUtil !== db.maximize.targetUtil || b.maximize.reserveSlopePctPerHour !== db.maximize.reserveSlopePctPerHour || b.maximize.reserveMaxPct !== db.maximize.reserveMaxPct || b.maximize.finishingHorizonMinutes !== db.maximize.finishingHorizonMinutes || b.maximize.resumeHysteresisPct !== db.maximize.resumeHysteresisPct || b.maximize.admissionAt !== db.maximize.admissionAt || b.maximize.wrapUpQuota !== db.maximize.wrapUpQuota || b.allocation.minRunwayRatio !== db.allocation.minRunwayRatio || b.allocation.minRunwayGapHours !== db.allocation.minRunwayGapHours;
|
|
15763
15779
|
}
|
|
15764
15780
|
function normalizeInteger(value, fallback) {
|
|
15765
15781
|
if (typeof value === "number" && Number.isFinite(value))
|
|
@@ -15799,9 +15815,11 @@ function normalizeMaximizeConfig(raw, pauseAt, fallback = DEFAULT_BUDGET_CONFIG.
|
|
|
15799
15815
|
reserveSlopePctPerHour: normalizeBoundedNumber(m.reserveSlopePctPerHour, fallback.reserveSlopePctPerHour, 0, 5),
|
|
15800
15816
|
reserveMaxPct: normalizeBoundedInteger(m.reserveMaxPct, fallback.reserveMaxPct, 0, 30),
|
|
15801
15817
|
finishingHorizonMinutes: normalizeBoundedInteger(m.finishingHorizonMinutes, fallback.finishingHorizonMinutes, 5, 180),
|
|
15802
|
-
resumeHysteresisPct: normalizeBoundedInteger(m.resumeHysteresisPct, fallback.resumeHysteresisPct, 1, 30)
|
|
15818
|
+
resumeHysteresisPct: normalizeBoundedInteger(m.resumeHysteresisPct, fallback.resumeHysteresisPct, 1, 30),
|
|
15819
|
+
admissionAt: normalizeBoundedInteger(m.admissionAt, fallback.admissionAt, 50, 99),
|
|
15820
|
+
wrapUpQuota: Math.floor(normalizeBoundedInteger(m.wrapUpQuota, fallback.wrapUpQuota, 0, 10))
|
|
15803
15821
|
};
|
|
15804
|
-
if (normalized.targetUtil <= pauseAt) {
|
|
15822
|
+
if (normalized.targetUtil <= pauseAt || normalized.admissionAt >= normalized.targetUtil) {
|
|
15805
15823
|
return { ...DEFAULT_BUDGET_CONFIG.maximize };
|
|
15806
15824
|
}
|
|
15807
15825
|
return normalized;
|
|
@@ -16383,7 +16401,7 @@ if (process.env.AGENTBRIDGE_TRACE === "1") {
|
|
|
16383
16401
|
});
|
|
16384
16402
|
} catch {}
|
|
16385
16403
|
}
|
|
16386
|
-
claude.setReplySender(async (msg, requireReply, onBusy, idempotencyKey) => {
|
|
16404
|
+
claude.setReplySender(async (msg, requireReply, onBusy, idempotencyKey, wrapUp) => {
|
|
16387
16405
|
if (msg.source !== "claude") {
|
|
16388
16406
|
return { success: false, error: "Invalid message source" };
|
|
16389
16407
|
}
|
|
@@ -16393,7 +16411,7 @@ claude.setReplySender(async (msg, requireReply, onBusy, idempotencyKey) => {
|
|
|
16393
16411
|
error: disabledReplyError(daemonDisabledReason ?? "killed")
|
|
16394
16412
|
};
|
|
16395
16413
|
}
|
|
16396
|
-
return daemonClient.sendReply(msg, requireReply, onBusy, idempotencyKey);
|
|
16414
|
+
return daemonClient.sendReply(msg, requireReply, onBusy, idempotencyKey, wrapUp);
|
|
16397
16415
|
});
|
|
16398
16416
|
claude.setResumeAckHandler((resumeId, status) => {
|
|
16399
16417
|
if (daemonDisabled) {
|