open-multi-agent-kit 0.98.1 → 0.98.2
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/CHANGELOG.md +14 -0
- package/README.md +2 -2
- package/dist/cli/mcp-attach.d.ts +15 -0
- package/dist/cli/mcp-attach.d.ts.map +1 -0
- package/dist/cli/mcp-attach.js +14 -0
- package/dist/cli/mcp-attach.js.map +1 -0
- package/dist/core/agent-session.d.ts +7 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +66 -14
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +19 -2
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +57 -6
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/oauth-recovery.d.ts +29 -0
- package/dist/core/compaction/oauth-recovery.d.ts.map +1 -0
- package/dist/core/compaction/oauth-recovery.js +40 -0
- package/dist/core/compaction/oauth-recovery.js.map +1 -0
- package/dist/core/model-registry.d.ts +10 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +16 -2
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/provider-resilience.d.ts +8 -0
- package/dist/core/provider-resilience.d.ts.map +1 -1
- package/dist/core/provider-resilience.js +17 -0
- package/dist/core/provider-resilience.js.map +1 -1
- package/dist/core/provider-usage.d.ts +1 -1
- package/dist/core/provider-usage.d.ts.map +1 -1
- package/dist/core/provider-usage.js +3 -2
- package/dist/core/provider-usage.js.map +1 -1
- package/dist/core/session-failure-cause.d.ts.map +1 -1
- package/dist/core/session-failure-cause.js +7 -1
- package/dist/core/session-failure-cause.js.map +1 -1
- package/dist/core/session-termination.d.ts.map +1 -1
- package/dist/core/session-termination.js +3 -1
- package/dist/core/session-termination.js.map +1 -1
- package/dist/core/verified-bash-runtime.d.ts.map +1 -1
- package/dist/core/verified-bash-runtime.js +6 -4
- package/dist/core/verified-bash-runtime.js.map +1 -1
- package/dist/guardrails/workspace-fingerprint.d.ts +2 -0
- package/dist/guardrails/workspace-fingerprint.d.ts.map +1 -1
- package/dist/guardrails/workspace-fingerprint.js +12 -10
- package/dist/guardrails/workspace-fingerprint.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +7 -0
- package/dist/main.js.map +1 -1
- package/docs/book-to-skill.md +17 -0
- package/docs/docs.json +4 -0
- package/docs/index.md +2 -0
- package/docs/mcp.md +10 -2
- package/docs/security.md +4 -9
- package/examples/extensions/custom-provider-anthropic/index.ts +4 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +18 -18
- package/package.json +6 -6
|
@@ -31,6 +31,7 @@ import { parseBangInvocation } from "./bang-skill-invocation.js";
|
|
|
31
31
|
import { getCompactionHeadroomThreshold } from "./compaction/compaction.js";
|
|
32
32
|
import { createCompactionHysteresisConfig, createCompactionHysteresisState, stepCompactionHysteresis, } from "./compaction/hysteresis.js";
|
|
33
33
|
import { calculateContextTokens, collectEntriesForBranchSummary, compact, estimateContextTokens, estimateProjectedContextTokens, generateBranchSummary, prepareCompaction, resolveCompactionModel, } from "./compaction/index.js";
|
|
34
|
+
import { summarizeWithOAuthRecovery } from "./compaction/oauth-recovery.js";
|
|
34
35
|
import { compactionEmitWillRetry } from "./compaction/resume-policy.js";
|
|
35
36
|
import { isSessionModelOverflow, shouldSkipCompactionCheck } from "./compaction-gate.js";
|
|
36
37
|
import { estimateToolResultReserve, } from "./context-budget-reserved-tokens.js";
|
|
@@ -55,6 +56,16 @@ const DISABLED_ENV_VALUES = new Set(["0", "false", "off", "disable", "disabled"]
|
|
|
55
56
|
const MAX_OVERFLOW_RECOVERY_ATTEMPTS = 2;
|
|
56
57
|
const OVERFLOW_RECOVERY_EMERGENCY_TOKENS = 4_096;
|
|
57
58
|
const MAX_RESOURCE_OBSERVATION_JOURNALS = 32;
|
|
59
|
+
/**
|
|
60
|
+
* Token headroom demanded before a compaction run.
|
|
61
|
+
*
|
|
62
|
+
* Compaction resolves auth once and then reuses that token for a summarization
|
|
63
|
+
* that can stream for minutes and be retried with backoff. A token accepted
|
|
64
|
+
* with only seconds of validity left comes back as a provider 401 mid-run
|
|
65
|
+
* ("authentication token is expired"), which reads as a compaction failure.
|
|
66
|
+
* Refreshing up front is cheap; failing a long compaction is not.
|
|
67
|
+
*/
|
|
68
|
+
const COMPACTION_MIN_TOKEN_VALIDITY_MS = 10 * 60 * 1000;
|
|
58
69
|
function isDisabledEnvValue(value) {
|
|
59
70
|
return value !== undefined && DISABLED_ENV_VALUES.has(value.trim().toLowerCase());
|
|
60
71
|
}
|
|
@@ -712,8 +723,8 @@ export class AgentSession {
|
|
|
712
723
|
_getBashSandboxPreflight(override) {
|
|
713
724
|
return this._bashRuntime.sandboxPreflight(override);
|
|
714
725
|
}
|
|
715
|
-
async _getRequiredRequestAuth(model) {
|
|
716
|
-
const result = await this._modelRegistry.getApiKeyAndHeaders(model);
|
|
726
|
+
async _getRequiredRequestAuth(model, options) {
|
|
727
|
+
const result = await this._modelRegistry.getApiKeyAndHeaders(model, options);
|
|
717
728
|
if (!result.ok) {
|
|
718
729
|
if (result.error.startsWith("No API key found")) {
|
|
719
730
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
@@ -732,10 +743,11 @@ export class AgentSession {
|
|
|
732
743
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
733
744
|
}
|
|
734
745
|
async _getCompactionRequestAuth(model) {
|
|
746
|
+
const options = { minRemainingMs: COMPACTION_MIN_TOKEN_VALIDITY_MS };
|
|
735
747
|
if (isBuiltinStreamFn(this.agent.streamFn)) {
|
|
736
|
-
return this._getRequiredRequestAuth(model);
|
|
748
|
+
return this._getRequiredRequestAuth(model, options);
|
|
737
749
|
}
|
|
738
|
-
const result = await this._modelRegistry.getApiKeyAndHeaders(model);
|
|
750
|
+
const result = await this._modelRegistry.getApiKeyAndHeaders(model, options);
|
|
739
751
|
return result.ok ? { apiKey: result.apiKey, headers: result.headers } : {};
|
|
740
752
|
}
|
|
741
753
|
/**
|
|
@@ -2814,6 +2826,21 @@ export class AgentSession {
|
|
|
2814
2826
|
* Used when the primary model's quota is exhausted (same-model retry is
|
|
2815
2827
|
* useless until reset; another provider can still save the compaction).
|
|
2816
2828
|
*/
|
|
2829
|
+
/**
|
|
2830
|
+
* Summarize for manual and automatic compaction alike. If the provider
|
|
2831
|
+
* rejects the OAuth token as expired despite a still-future stored expiry
|
|
2832
|
+
* (ChatGPT `401 token_expired`), the credential is force-refreshed once and
|
|
2833
|
+
* the summarization retried; the retry classifier rightly never replays a 401.
|
|
2834
|
+
*/
|
|
2835
|
+
_summarizeCompaction(input) {
|
|
2836
|
+
const { model } = input;
|
|
2837
|
+
return summarizeWithOAuthRecovery({
|
|
2838
|
+
apiKey: input.apiKey,
|
|
2839
|
+
provider: model.provider,
|
|
2840
|
+
refreshRejectedToken: (rejected) => this._modelRegistry.refreshRejectedOAuthToken(model, rejected),
|
|
2841
|
+
run: (requestApiKey) => compact(input.preparation, model, requestApiKey, input.headers, input.customInstructions, input.signal, this.thinkingLevel, this.agent.streamFn, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason: input.reason }), this._compactionFailoverModels(model)),
|
|
2842
|
+
});
|
|
2843
|
+
}
|
|
2817
2844
|
_compactionFailoverModels(primary) {
|
|
2818
2845
|
const candidates = resolveFailoverCandidates(this.settingsManager.getProviderResilienceSettings());
|
|
2819
2846
|
const available = this._modelRegistry.getAvailable();
|
|
@@ -2838,11 +2865,14 @@ export class AgentSession {
|
|
|
2838
2865
|
this._compactionAbortController = new AbortController();
|
|
2839
2866
|
this._emit({ type: "compaction_start", reason: "manual" });
|
|
2840
2867
|
let committedCompaction = false;
|
|
2868
|
+
// Hoisted so a failure is attributed to the model that actually summarized,
|
|
2869
|
+
// which `compaction.model` may make different from the session model.
|
|
2870
|
+
let compactionModel;
|
|
2841
2871
|
try {
|
|
2842
2872
|
if (!this.model) {
|
|
2843
2873
|
throw new Error(formatNoModelSelectedMessage());
|
|
2844
2874
|
}
|
|
2845
|
-
|
|
2875
|
+
compactionModel = this._resolveCompactionModel(this.model);
|
|
2846
2876
|
const { apiKey, headers } = await this._getCompactionRequestAuth(compactionModel);
|
|
2847
2877
|
const settings = this.settingsManager.getCompactionSettings();
|
|
2848
2878
|
const begun = this._beginCompactionTransaction(compactionModel, false);
|
|
@@ -2886,8 +2916,15 @@ export class AgentSession {
|
|
|
2886
2916
|
details = extensionCompaction.details;
|
|
2887
2917
|
}
|
|
2888
2918
|
else {
|
|
2889
|
-
|
|
2890
|
-
|
|
2919
|
+
const result = await this._summarizeCompaction({
|
|
2920
|
+
preparation,
|
|
2921
|
+
model: compactionModel,
|
|
2922
|
+
apiKey,
|
|
2923
|
+
headers,
|
|
2924
|
+
customInstructions,
|
|
2925
|
+
signal: this._compactionAbortController.signal,
|
|
2926
|
+
reason: "manual",
|
|
2927
|
+
});
|
|
2891
2928
|
summary = result.summary;
|
|
2892
2929
|
firstKeptEntryId = result.firstKeptEntryId;
|
|
2893
2930
|
tokensBefore = result.tokensBefore;
|
|
@@ -2941,7 +2978,11 @@ export class AgentSession {
|
|
|
2941
2978
|
message: terminationMessage(message, "Manual compaction failed."),
|
|
2942
2979
|
cause: { area: "compaction", code: compactionCode },
|
|
2943
2980
|
sideEffects: committedCompaction ? "confirmed" : "none",
|
|
2944
|
-
...(
|
|
2981
|
+
...(compactionModel
|
|
2982
|
+
? { provider: compactionModel.provider, model: compactionModel.id }
|
|
2983
|
+
: this.model
|
|
2984
|
+
? { provider: this.model.provider, model: this.model.id }
|
|
2985
|
+
: {}),
|
|
2945
2986
|
}));
|
|
2946
2987
|
this._emit({
|
|
2947
2988
|
type: "compaction_end",
|
|
@@ -3134,6 +3175,8 @@ export class AgentSession {
|
|
|
3134
3175
|
: configuredSettings;
|
|
3135
3176
|
this._emit({ type: "compaction_start", reason });
|
|
3136
3177
|
this._autoCompactionAbortController = new AbortController();
|
|
3178
|
+
// Hoisted so the failure message names the model that actually summarized.
|
|
3179
|
+
let compactionModel;
|
|
3137
3180
|
try {
|
|
3138
3181
|
if (!this.model) {
|
|
3139
3182
|
this._emit({
|
|
@@ -3145,11 +3188,13 @@ export class AgentSession {
|
|
|
3145
3188
|
});
|
|
3146
3189
|
return false;
|
|
3147
3190
|
}
|
|
3148
|
-
|
|
3191
|
+
compactionModel = this._resolveCompactionModel(this.model);
|
|
3149
3192
|
let apiKey;
|
|
3150
3193
|
let headers;
|
|
3151
3194
|
if (isBuiltinStreamFn(this.agent.streamFn)) {
|
|
3152
|
-
const authResult = await this._modelRegistry.getApiKeyAndHeaders(compactionModel
|
|
3195
|
+
const authResult = await this._modelRegistry.getApiKeyAndHeaders(compactionModel, {
|
|
3196
|
+
minRemainingMs: COMPACTION_MIN_TOKEN_VALIDITY_MS,
|
|
3197
|
+
});
|
|
3153
3198
|
if (!authResult.ok || !authResult.apiKey) {
|
|
3154
3199
|
const providerLabel = compactionModel.provider;
|
|
3155
3200
|
this._emit({
|
|
@@ -3219,8 +3264,14 @@ export class AgentSession {
|
|
|
3219
3264
|
details = extensionCompaction.details;
|
|
3220
3265
|
}
|
|
3221
3266
|
else {
|
|
3222
|
-
|
|
3223
|
-
|
|
3267
|
+
const compactResult = await this._summarizeCompaction({
|
|
3268
|
+
preparation,
|
|
3269
|
+
model: compactionModel,
|
|
3270
|
+
apiKey,
|
|
3271
|
+
headers,
|
|
3272
|
+
signal: this._autoCompactionAbortController.signal,
|
|
3273
|
+
reason,
|
|
3274
|
+
});
|
|
3224
3275
|
summary = compactResult.summary;
|
|
3225
3276
|
firstKeptEntryId = compactResult.firstKeptEntryId;
|
|
3226
3277
|
tokensBefore = compactResult.tokensBefore;
|
|
@@ -3288,6 +3339,7 @@ export class AgentSession {
|
|
|
3288
3339
|
}
|
|
3289
3340
|
catch (error) {
|
|
3290
3341
|
const errorMessage = error instanceof Error ? error.message : "compaction failed";
|
|
3342
|
+
const modelLabel = compactionModel ? ` (${compactionModel.provider}/${compactionModel.id})` : "";
|
|
3291
3343
|
this._emit({
|
|
3292
3344
|
type: "compaction_end",
|
|
3293
3345
|
reason,
|
|
@@ -3295,8 +3347,8 @@ export class AgentSession {
|
|
|
3295
3347
|
aborted: false,
|
|
3296
3348
|
willRetry: false,
|
|
3297
3349
|
errorMessage: reason === "overflow"
|
|
3298
|
-
? `Context overflow recovery failed: ${errorMessage}`
|
|
3299
|
-
: `Auto-compaction failed: ${errorMessage}`,
|
|
3350
|
+
? `Context overflow recovery failed${modelLabel}: ${errorMessage}`
|
|
3351
|
+
: `Auto-compaction failed${modelLabel}: ${errorMessage}`,
|
|
3300
3352
|
});
|
|
3301
3353
|
return false;
|
|
3302
3354
|
}
|