@jmanuelcorral/openteam 0.15.1 → 0.16.1
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/README.es.md +1 -1
- package/README.md +1 -1
- package/dist/cli/graphOperator.d.ts +3 -3
- package/dist/cli/graphOperator.d.ts.map +1 -1
- package/dist/cli/opencodeVersion.d.ts +44 -0
- package/dist/cli/opencodeVersion.d.ts.map +1 -0
- package/dist/cli.js +1998 -1000
- package/dist/commands/dispatch.d.ts +23 -1
- package/dist/commands/dispatch.d.ts.map +1 -1
- package/dist/commands/doctor.d.ts +19 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/graph.d.ts +40 -2
- package/dist/commands/graph.d.ts.map +1 -1
- package/dist/config/errors.d.ts.map +1 -1
- package/dist/config/schema.d.ts +22 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/contract/opencode.d.ts +49 -3
- package/dist/contract/opencode.d.ts.map +1 -1
- package/dist/graph/certificate.d.ts.map +1 -1
- package/dist/index.d.ts +28 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +244 -41
- package/dist/local/concurrency.d.ts +74 -16
- package/dist/local/concurrency.d.ts.map +1 -1
- package/dist/orchestrator/coordinator.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -416,7 +416,8 @@ var LocalRuntimeSchema = z2.object({
|
|
|
416
416
|
baseURL: z2.string().url().optional(),
|
|
417
417
|
discovery: z2.enum(["cli", "sdk", "manual"]).optional(),
|
|
418
418
|
defaultModel: ModelRefSchema,
|
|
419
|
-
maxConcurrency: z2.number().int().positive().optional()
|
|
419
|
+
maxConcurrency: z2.number().int().positive().optional(),
|
|
420
|
+
reservedInteractiveSlots: z2.number().int().nonnegative().optional()
|
|
420
421
|
}).strict().superRefine((runtime, ctx) => {
|
|
421
422
|
const resolvedKind = runtime.kind ?? runtime.id;
|
|
422
423
|
if (!LocalRuntimeKindSchema.safeParse(resolvedKind).success) {
|
|
@@ -430,6 +431,15 @@ var LocalRuntimeSchema = z2.object({
|
|
|
430
431
|
function localRuntimeKind(runtime) {
|
|
431
432
|
return runtime.kind ?? runtime.id;
|
|
432
433
|
}
|
|
434
|
+
function effectiveMaxConcurrency(runtime) {
|
|
435
|
+
return runtime.maxConcurrency ?? DEFAULT_LOCAL_MAX_CONCURRENCY;
|
|
436
|
+
}
|
|
437
|
+
function effectiveReservedInteractiveSlots(runtime) {
|
|
438
|
+
if (runtime.reservedInteractiveSlots !== undefined) {
|
|
439
|
+
return runtime.reservedInteractiveSlots;
|
|
440
|
+
}
|
|
441
|
+
return effectiveMaxConcurrency(runtime) >= 2 ? 1 : 0;
|
|
442
|
+
}
|
|
433
443
|
var MemoryScopeSchema = z2.enum(["project", "user"]);
|
|
434
444
|
var MemoryExtractionModeSchema = z2.enum([
|
|
435
445
|
"local",
|
|
@@ -2440,6 +2450,10 @@ function splitVirtualPath(path) {
|
|
|
2440
2450
|
|
|
2441
2451
|
// src/cli/graphOperator.ts
|
|
2442
2452
|
var ALLOWED_GATE = { allowed: true, violations: [] };
|
|
2453
|
+
var ALLOWED_EVALUATION = {
|
|
2454
|
+
kind: "evaluated",
|
|
2455
|
+
gate: ALLOWED_GATE
|
|
2456
|
+
};
|
|
2443
2457
|
function journalRoot(config) {
|
|
2444
2458
|
return config.graph?.journalRoot ?? DEFAULT_GRAPH_JOURNAL_ROOT;
|
|
2445
2459
|
}
|
|
@@ -2529,7 +2543,7 @@ async function listWorktreeObservations(config, options) {
|
|
|
2529
2543
|
})));
|
|
2530
2544
|
}
|
|
2531
2545
|
function createGraphOperator(options) {
|
|
2532
|
-
const evaluateCutoverGate = options.evaluateCutoverGate ?? (async () =>
|
|
2546
|
+
const evaluateCutoverGate = options.evaluateCutoverGate ?? (async () => ALLOWED_EVALUATION);
|
|
2533
2547
|
const worktreeOptions = options.exec === undefined ? undefined : {
|
|
2534
2548
|
exec: options.exec,
|
|
2535
2549
|
repoRoot: options.repoRoot ?? process.cwd(),
|
|
@@ -2721,7 +2735,8 @@ var KNOWN_CONFIG_KEYS_BY_PATH = new Map([
|
|
|
2721
2735
|
"baseURL",
|
|
2722
2736
|
"discovery",
|
|
2723
2737
|
"defaultModel",
|
|
2724
|
-
"maxConcurrency"
|
|
2738
|
+
"maxConcurrency",
|
|
2739
|
+
"reservedInteractiveSlots"
|
|
2725
2740
|
]
|
|
2726
2741
|
],
|
|
2727
2742
|
["local.runtimes[].defaultModel", MODEL_REF_KEYS],
|
|
@@ -4287,6 +4302,36 @@ var SUPPORTED_OPENCODE_VERSIONS = [
|
|
|
4287
4302
|
"1.18.18",
|
|
4288
4303
|
"1.18.19"
|
|
4289
4304
|
];
|
|
4305
|
+
var SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)/;
|
|
4306
|
+
function parseSemver(version) {
|
|
4307
|
+
const normalized = version.trim().replace(/^[=^~v]+/, "");
|
|
4308
|
+
const match = SEMVER_RE.exec(normalized);
|
|
4309
|
+
if (match === null) {
|
|
4310
|
+
throw new Error(`invalid semver: "${version}"`);
|
|
4311
|
+
}
|
|
4312
|
+
return {
|
|
4313
|
+
major: Number(match[1]),
|
|
4314
|
+
minor: Number(match[2]),
|
|
4315
|
+
patch: Number(match[3])
|
|
4316
|
+
};
|
|
4317
|
+
}
|
|
4318
|
+
function isCertificateVersionCompatible(certifiedVersion, liveVersion) {
|
|
4319
|
+
if (certifiedVersion === liveVersion) {
|
|
4320
|
+
return true;
|
|
4321
|
+
}
|
|
4322
|
+
let certified;
|
|
4323
|
+
let live;
|
|
4324
|
+
try {
|
|
4325
|
+
certified = parseSemver(certifiedVersion);
|
|
4326
|
+
live = parseSemver(liveVersion);
|
|
4327
|
+
} catch {
|
|
4328
|
+
return false;
|
|
4329
|
+
}
|
|
4330
|
+
if (certified.major !== live.major || certified.minor !== live.minor) {
|
|
4331
|
+
return false;
|
|
4332
|
+
}
|
|
4333
|
+
return live.patch >= certified.patch;
|
|
4334
|
+
}
|
|
4290
4335
|
|
|
4291
4336
|
// src/graph/soakLedger.ts
|
|
4292
4337
|
import { z as z15 } from "zod";
|
|
@@ -4545,8 +4590,8 @@ function parseShadowCertificate(value, opencodeVersion) {
|
|
|
4545
4590
|
if (sha256Hex(canonicalCertificate(unsigned)) !== digest) {
|
|
4546
4591
|
throw new ShadowCertificateError("digest-mismatch", "certificate digest does not cover the presented evidence");
|
|
4547
4592
|
}
|
|
4548
|
-
if (certificate.opencodeVersion
|
|
4549
|
-
throw new ShadowCertificateError("opencode-mismatch", `certified for "${certificate.opencodeVersion}",
|
|
4593
|
+
if (!isCertificateVersionCompatible(certificate.opencodeVersion, opencodeVersion)) {
|
|
4594
|
+
throw new ShadowCertificateError("opencode-mismatch", `certified for "${certificate.opencodeVersion}", running "${opencodeVersion}" — evidence is accepted only on ${certificate.opencodeVersion} or a newer patch of the same minor line`);
|
|
4550
4595
|
}
|
|
4551
4596
|
return certificate;
|
|
4552
4597
|
}
|
|
@@ -4730,8 +4775,8 @@ function parseReleaseCertificate(value, opencodeVersion, expectedShadowDigest) {
|
|
|
4730
4775
|
if (sha256Hex(canonicalReleaseCertificate(unsigned)) !== digest) {
|
|
4731
4776
|
throw new ReleaseCertificateError("digest-mismatch", "certificate digest does not cover the presented evidence");
|
|
4732
4777
|
}
|
|
4733
|
-
if (certificate.opencodeVersion
|
|
4734
|
-
throw new ReleaseCertificateError("opencode-mismatch", `certified for "${certificate.opencodeVersion}",
|
|
4778
|
+
if (!isCertificateVersionCompatible(certificate.opencodeVersion, opencodeVersion)) {
|
|
4779
|
+
throw new ReleaseCertificateError("opencode-mismatch", `certified for "${certificate.opencodeVersion}", running "${opencodeVersion}" — evidence is accepted only on ${certificate.opencodeVersion} or a newer patch of the same minor line`);
|
|
4735
4780
|
}
|
|
4736
4781
|
return certificate;
|
|
4737
4782
|
}
|
|
@@ -5061,50 +5106,106 @@ var realCacheAdapter = {
|
|
|
5061
5106
|
};
|
|
5062
5107
|
|
|
5063
5108
|
// src/local/concurrency.ts
|
|
5109
|
+
var PRIORITY_BANDS = [
|
|
5110
|
+
"interactive",
|
|
5111
|
+
"worker",
|
|
5112
|
+
"background"
|
|
5113
|
+
];
|
|
5064
5114
|
function createRuntimeConcurrencyLimiter(options) {
|
|
5065
5115
|
const states = new Map;
|
|
5066
5116
|
function stateFor(runtimeId) {
|
|
5067
5117
|
let state = states.get(runtimeId);
|
|
5068
5118
|
if (state === undefined) {
|
|
5069
|
-
state = {
|
|
5119
|
+
state = {
|
|
5120
|
+
active: 0,
|
|
5121
|
+
nonInteractiveActive: 0,
|
|
5122
|
+
queues: { interactive: [], worker: [], background: [] }
|
|
5123
|
+
};
|
|
5070
5124
|
states.set(runtimeId, state);
|
|
5071
5125
|
}
|
|
5072
5126
|
return state;
|
|
5073
5127
|
}
|
|
5074
|
-
function
|
|
5128
|
+
function reservedFor(runtimeId, capacity) {
|
|
5129
|
+
const maxReserved = Math.max(0, capacity - 1);
|
|
5130
|
+
const raw = options.reservedInteractiveFor?.(runtimeId);
|
|
5131
|
+
if (raw === undefined || Number.isNaN(raw)) {
|
|
5132
|
+
return 0;
|
|
5133
|
+
}
|
|
5134
|
+
const truncated = Math.trunc(raw);
|
|
5135
|
+
if (truncated < 0) {
|
|
5136
|
+
return 0;
|
|
5137
|
+
}
|
|
5138
|
+
return Math.min(truncated, maxReserved);
|
|
5139
|
+
}
|
|
5140
|
+
function limitsFor(runtimeId) {
|
|
5141
|
+
const capacity = options.capacityFor(runtimeId);
|
|
5142
|
+
const reserved = reservedFor(runtimeId, capacity);
|
|
5143
|
+
return { capacity, nonInteractiveBudget: capacity - reserved };
|
|
5144
|
+
}
|
|
5145
|
+
function grantNext(state, runtimeId, nonInteractiveAfterRelease) {
|
|
5146
|
+
const interactiveWaiter = state.queues.interactive.shift();
|
|
5147
|
+
if (interactiveWaiter !== undefined) {
|
|
5148
|
+
return { waiter: interactiveWaiter, nonInteractive: false };
|
|
5149
|
+
}
|
|
5150
|
+
const { nonInteractiveBudget } = limitsFor(runtimeId);
|
|
5151
|
+
if (nonInteractiveAfterRelease < nonInteractiveBudget) {
|
|
5152
|
+
const workerWaiter = state.queues.worker.shift();
|
|
5153
|
+
if (workerWaiter !== undefined) {
|
|
5154
|
+
return { waiter: workerWaiter, nonInteractive: true };
|
|
5155
|
+
}
|
|
5156
|
+
const backgroundWaiter = state.queues.background.shift();
|
|
5157
|
+
if (backgroundWaiter !== undefined) {
|
|
5158
|
+
return { waiter: backgroundWaiter, nonInteractive: true };
|
|
5159
|
+
}
|
|
5160
|
+
}
|
|
5161
|
+
return;
|
|
5162
|
+
}
|
|
5163
|
+
function makeRelease(state, runtimeId, heldNonInteractive) {
|
|
5075
5164
|
let released = false;
|
|
5076
5165
|
return () => {
|
|
5077
5166
|
if (released) {
|
|
5078
5167
|
return;
|
|
5079
5168
|
}
|
|
5080
5169
|
released = true;
|
|
5081
|
-
const
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
} else {
|
|
5170
|
+
const nonInteractiveAfterRelease = state.nonInteractiveActive - (heldNonInteractive ? 1 : 0);
|
|
5171
|
+
const next = grantNext(state, runtimeId, nonInteractiveAfterRelease);
|
|
5172
|
+
if (next === undefined) {
|
|
5085
5173
|
state.active -= 1;
|
|
5174
|
+
state.nonInteractiveActive = nonInteractiveAfterRelease;
|
|
5175
|
+
return;
|
|
5086
5176
|
}
|
|
5177
|
+
state.nonInteractiveActive = nonInteractiveAfterRelease + (next.nonInteractive ? 1 : 0);
|
|
5178
|
+
next.waiter(makeRelease(state, runtimeId, next.nonInteractive));
|
|
5087
5179
|
};
|
|
5088
5180
|
}
|
|
5089
|
-
function tryAcquire(runtimeId) {
|
|
5181
|
+
function tryAcquire(runtimeId, priority = "worker") {
|
|
5090
5182
|
const state = stateFor(runtimeId);
|
|
5091
|
-
|
|
5183
|
+
const { capacity, nonInteractiveBudget } = limitsFor(runtimeId);
|
|
5184
|
+
if (priority === "interactive") {
|
|
5185
|
+
if (state.active < capacity) {
|
|
5186
|
+
state.active += 1;
|
|
5187
|
+
return makeRelease(state, runtimeId, false);
|
|
5188
|
+
}
|
|
5189
|
+
return;
|
|
5190
|
+
}
|
|
5191
|
+
if (state.active < capacity && state.nonInteractiveActive < nonInteractiveBudget) {
|
|
5092
5192
|
state.active += 1;
|
|
5093
|
-
|
|
5193
|
+
state.nonInteractiveActive += 1;
|
|
5194
|
+
return makeRelease(state, runtimeId, true);
|
|
5094
5195
|
}
|
|
5095
5196
|
return;
|
|
5096
5197
|
}
|
|
5097
5198
|
return {
|
|
5098
5199
|
tryAcquire,
|
|
5099
|
-
acquire(runtimeId) {
|
|
5100
|
-
const immediate = tryAcquire(runtimeId);
|
|
5200
|
+
acquire(runtimeId, priority = "worker") {
|
|
5201
|
+
const immediate = tryAcquire(runtimeId, priority);
|
|
5101
5202
|
if (immediate !== undefined) {
|
|
5102
5203
|
return Promise.resolve({ release: immediate, waitedMs: 0 });
|
|
5103
5204
|
}
|
|
5104
5205
|
const state = stateFor(runtimeId);
|
|
5105
5206
|
const queuedAt = options.now();
|
|
5106
5207
|
return new Promise((resolve3) => {
|
|
5107
|
-
state.
|
|
5208
|
+
state.queues[priority].push((release) => {
|
|
5108
5209
|
resolve3({ release, waitedMs: options.now() - queuedAt });
|
|
5109
5210
|
});
|
|
5110
5211
|
});
|
|
@@ -5113,7 +5214,15 @@ function createRuntimeConcurrencyLimiter(options) {
|
|
|
5113
5214
|
return states.get(runtimeId)?.active ?? 0;
|
|
5114
5215
|
},
|
|
5115
5216
|
queuedCount(runtimeId) {
|
|
5116
|
-
|
|
5217
|
+
const state = states.get(runtimeId);
|
|
5218
|
+
if (state === undefined) {
|
|
5219
|
+
return 0;
|
|
5220
|
+
}
|
|
5221
|
+
let total = 0;
|
|
5222
|
+
for (const band of PRIORITY_BANDS) {
|
|
5223
|
+
total += state.queues[band].length;
|
|
5224
|
+
}
|
|
5225
|
+
return total;
|
|
5117
5226
|
}
|
|
5118
5227
|
};
|
|
5119
5228
|
}
|
|
@@ -6291,6 +6400,9 @@ function warnUnknownRole(roleID, warn, warnedRoles) {
|
|
|
6291
6400
|
function roleFor(input) {
|
|
6292
6401
|
return getRoleProfile(input.roleID, input.config.orchestrator?.roles) ?? synthesiseFallbackProfile(input.roleID);
|
|
6293
6402
|
}
|
|
6403
|
+
function priorityForRole(role) {
|
|
6404
|
+
return role.roleID === "scribe" ? "background" : "worker";
|
|
6405
|
+
}
|
|
6294
6406
|
function mandatoryLocalRuntimeMessage(roleID) {
|
|
6295
6407
|
return `openteam: role "${roleID}" requires a local runtime, but no local runtime is reachable. ` + `This role must run locally and will not fall back to a frontier provider. ` + `Start one of the supported local runtimes (Ollama, LM Studio, or Lemonade) and try again. ` + "Run `openteam doctor` to diagnose your local runtime configuration.";
|
|
6296
6408
|
}
|
|
@@ -6654,10 +6766,11 @@ async function runRoleTaskWithCorrelation(input, deps, correlation, batch) {
|
|
|
6654
6766
|
let queueObservation;
|
|
6655
6767
|
if (runtimeId !== undefined && deps.runtimeLimiter !== undefined) {
|
|
6656
6768
|
const limiter = deps.runtimeLimiter;
|
|
6657
|
-
|
|
6769
|
+
const priority = priorityForRole(role);
|
|
6770
|
+
release = limiter.tryAcquire(runtimeId, priority);
|
|
6658
6771
|
let waitedMs = 0;
|
|
6659
6772
|
if (release === undefined) {
|
|
6660
|
-
const acquisition = await limiter.acquire(runtimeId);
|
|
6773
|
+
const acquisition = await limiter.acquire(runtimeId, priority);
|
|
6661
6774
|
release = acquisition.release;
|
|
6662
6775
|
waitedMs = acquisition.waitedMs;
|
|
6663
6776
|
}
|
|
@@ -8265,7 +8378,7 @@ function legacyRosterFindings(audit) {
|
|
|
8265
8378
|
}
|
|
8266
8379
|
return findings;
|
|
8267
8380
|
}
|
|
8268
|
-
function rosterHealthSection(audit, loadError, rosterRoleCount) {
|
|
8381
|
+
function rosterHealthSection(audit, loadError, rosterRoleCount, rosterMissing) {
|
|
8269
8382
|
const auditFindings = audit?.findings ?? legacyRosterFindings(audit ?? {});
|
|
8270
8383
|
const unparseable = auditFindings.find((finding) => finding.kind === "unparseable-roster");
|
|
8271
8384
|
const unparseableMessage = loadError ?? unparseable?.message;
|
|
@@ -8278,6 +8391,14 @@ function rosterHealthSection(audit, loadError, rosterRoleCount) {
|
|
|
8278
8391
|
];
|
|
8279
8392
|
}
|
|
8280
8393
|
if (audit === undefined) {
|
|
8394
|
+
if (rosterMissing === true) {
|
|
8395
|
+
return [
|
|
8396
|
+
" roster health:",
|
|
8397
|
+
` ✗ ${OPENTEAM_ROSTER_PATH} does not exist — no team roster has been cast.`,
|
|
8398
|
+
" consequence: without a roster openteam cannot distribute work across roles, so every request is handled by a single agent and no work splitting happens.",
|
|
8399
|
+
` remedy: run \`openteam setup\` to cast a team and write the roster (${OPENTEAM_ROSTER_PATH}), then re-run \`openteam doctor\`.`
|
|
8400
|
+
];
|
|
8401
|
+
}
|
|
8281
8402
|
return [];
|
|
8282
8403
|
}
|
|
8283
8404
|
const missing = auditFindings.filter((finding) => finding.kind === "missing-guaranteed-role").map((finding) => finding.roleID);
|
|
@@ -8313,6 +8434,14 @@ function rosterHealthSection(audit, loadError, rosterRoleCount) {
|
|
|
8313
8434
|
}
|
|
8314
8435
|
return lines;
|
|
8315
8436
|
}
|
|
8437
|
+
function orchestratorAgentSection() {
|
|
8438
|
+
return [
|
|
8439
|
+
" orchestrator agent:",
|
|
8440
|
+
` ✗ ${ORCHESTRATOR_AGENT_PATH} does not exist — opencode has no openteam coordinator agent.`,
|
|
8441
|
+
" consequence: this is the primary agent that reads the roster and calls `openteam-orchestrate` to fan work out across roles; without it opencode has no openteam coordinator, so every request is handled by a single agent and no work splitting happens.",
|
|
8442
|
+
` remedy: run \`openteam setup\` to generate ${ORCHESTRATOR_AGENT_PATH}, then re-run \`openteam doctor\`.`
|
|
8443
|
+
];
|
|
8444
|
+
}
|
|
8316
8445
|
function gitignoreSection(gitignore) {
|
|
8317
8446
|
if (gitignore.missingRules.length === 0) {
|
|
8318
8447
|
return [
|
|
@@ -8376,7 +8505,10 @@ function renderDoctor(input) {
|
|
|
8376
8505
|
if (input.diagnostics !== undefined) {
|
|
8377
8506
|
lines.push(...diagnosticsSection(input.diagnostics));
|
|
8378
8507
|
}
|
|
8379
|
-
lines.push(...rosterHealthSection(input.rosterAudit, input.rosterLoadError, input.rosterRoleCount));
|
|
8508
|
+
lines.push(...rosterHealthSection(input.rosterAudit, input.rosterLoadError, input.rosterRoleCount, input.rosterMissing));
|
|
8509
|
+
if (input.orchestratorAgentMissing === true) {
|
|
8510
|
+
lines.push(...orchestratorAgentSection());
|
|
8511
|
+
}
|
|
8380
8512
|
if (input.gitignore !== undefined) {
|
|
8381
8513
|
lines.push(...gitignoreSection(input.gitignore));
|
|
8382
8514
|
}
|
|
@@ -8460,14 +8592,31 @@ function leaseLine(lease) {
|
|
|
8460
8592
|
const state = lease.released ? "released" : "active";
|
|
8461
8593
|
return ` lease: ${lease.holder} → ${lease.runID} (${state})`;
|
|
8462
8594
|
}
|
|
8463
|
-
function
|
|
8595
|
+
function appendEffectiveLines(lines, gate) {
|
|
8596
|
+
switch (gate.kind) {
|
|
8597
|
+
case "not-applicable":
|
|
8598
|
+
return;
|
|
8599
|
+
case "passed":
|
|
8600
|
+
lines.push(" effective: active");
|
|
8601
|
+
return;
|
|
8602
|
+
case "unevaluable":
|
|
8603
|
+
lines.push(" effective: unknown — could not evaluate the cutover gate");
|
|
8604
|
+
lines.push(` ${gate.reason}`);
|
|
8605
|
+
return;
|
|
8606
|
+
case "denied":
|
|
8607
|
+
lines.push(" effective: off — cutover gate denied");
|
|
8608
|
+
for (const violation of gate.violations) {
|
|
8609
|
+
lines.push(` • ${violation.code}: ${violation.detail}`);
|
|
8610
|
+
}
|
|
8611
|
+
}
|
|
8612
|
+
}
|
|
8613
|
+
function renderGraphStatus(snapshot, gate = { kind: "not-applicable" }) {
|
|
8464
8614
|
const lines = [
|
|
8465
8615
|
"openteam graph status:",
|
|
8466
|
-
` config: ${snapshot.effectiveMode} (source: ${snapshot.source})
|
|
8467
|
-
leaseLine(snapshot.lease),
|
|
8468
|
-
` journal: ${snapshot.journal}`,
|
|
8469
|
-
` effects: ${snapshot.pendingEffects} pending, ${snapshot.unknownEffects} unknown`
|
|
8616
|
+
` config: ${snapshot.effectiveMode} (source: ${snapshot.source})`
|
|
8470
8617
|
];
|
|
8618
|
+
appendEffectiveLines(lines, gate);
|
|
8619
|
+
lines.push(leaseLine(snapshot.lease), ` journal: ${snapshot.journal}`, ` effects: ${snapshot.pendingEffects} pending, ${snapshot.unknownEffects} unknown`);
|
|
8471
8620
|
const needsReconciliation = isRecoveryRequired(snapshot.journal, snapshot.unknownEffects);
|
|
8472
8621
|
if (needsReconciliation) {
|
|
8473
8622
|
lines.push(" ⚠ Reconciliation required: journal or effects in an uncertain state.");
|
|
@@ -9911,8 +10060,7 @@ async function runAgents(deps, configPath, opencodeConfigPaths, configResolution
|
|
|
9911
10060
|
async function runGraph(positionals, deps, configPath, configResolution) {
|
|
9912
10061
|
const sub = positionals[1];
|
|
9913
10062
|
if (sub === "status") {
|
|
9914
|
-
|
|
9915
|
-
return { exitCode: 0, stdout: renderGraphStatus(snapshot) };
|
|
10063
|
+
return runGraphStatus(deps, configPath, configResolution);
|
|
9916
10064
|
}
|
|
9917
10065
|
if (sub === "cancel") {
|
|
9918
10066
|
return runGraphCancel(positionals, deps, configPath, configResolution);
|
|
@@ -9967,7 +10115,9 @@ function renderGraphOutcome(outcome) {
|
|
|
9967
10115
|
async function resolveOperatorGraphPolicy(config, operator) {
|
|
9968
10116
|
let graph = resolveGraphConfig(config, "file");
|
|
9969
10117
|
if (isGateApplicable(graph.effectiveMode)) {
|
|
9970
|
-
|
|
10118
|
+
const evaluation = await operator.evaluateCutoverGate(config);
|
|
10119
|
+
const gate = evaluation.kind === "evaluated" ? evaluation.gate : { allowed: false, violations: [] };
|
|
10120
|
+
graph = applyGraphGate(graph, gate);
|
|
9971
10121
|
}
|
|
9972
10122
|
return {
|
|
9973
10123
|
graph,
|
|
@@ -9985,6 +10135,32 @@ function checkOperatorGate(policy) {
|
|
|
9985
10135
|
stdout: renderLegacyGraphReason(decision2)
|
|
9986
10136
|
};
|
|
9987
10137
|
}
|
|
10138
|
+
async function runGraphStatus(deps, configPath, configResolution) {
|
|
10139
|
+
const snapshot = await deps.readGraphSnapshot(configPath, configResolution);
|
|
10140
|
+
if (!isGateApplicable(snapshot.effectiveMode)) {
|
|
10141
|
+
return { exitCode: 0, stdout: renderGraphStatus(snapshot) };
|
|
10142
|
+
}
|
|
10143
|
+
const operator = deps.graphOperator;
|
|
10144
|
+
if (operator === undefined) {
|
|
10145
|
+
const gate2 = {
|
|
10146
|
+
kind: "unevaluable",
|
|
10147
|
+
reason: "graph operator ports are not configured"
|
|
10148
|
+
};
|
|
10149
|
+
return { exitCode: 0, stdout: renderGraphStatus(snapshot, gate2) };
|
|
10150
|
+
}
|
|
10151
|
+
const config = await deps.loadConfig(configPath, configResolution);
|
|
10152
|
+
const evaluation = await operator.evaluateCutoverGate(config);
|
|
10153
|
+
if (evaluation.kind === "unevaluable") {
|
|
10154
|
+
const gate2 = {
|
|
10155
|
+
kind: "unevaluable",
|
|
10156
|
+
reason: evaluation.reason
|
|
10157
|
+
};
|
|
10158
|
+
return { exitCode: 0, stdout: renderGraphStatus(snapshot, gate2) };
|
|
10159
|
+
}
|
|
10160
|
+
const resolved = applyGraphGate(resolveGraphConfig(config, "file"), evaluation.gate);
|
|
10161
|
+
const gate = resolved.gateDenied === true ? { kind: "denied", violations: resolved.gateViolations ?? [] } : { kind: "passed" };
|
|
10162
|
+
return { exitCode: 0, stdout: renderGraphStatus(snapshot, gate) };
|
|
10163
|
+
}
|
|
9988
10164
|
async function runGraphCancel(positionals, deps, configPath, configResolution) {
|
|
9989
10165
|
const runID = positionals[2];
|
|
9990
10166
|
if (runID === undefined || runID.trim() === "") {
|
|
@@ -10431,6 +10607,9 @@ async function runCli(argv, deps) {
|
|
|
10431
10607
|
const summary = summarizeQueueWaits(queueEvents);
|
|
10432
10608
|
queueWait = summary !== undefined ? { summary } : {};
|
|
10433
10609
|
}
|
|
10610
|
+
const rosterMissing = deps.loadRosterForDoctor !== undefined && roster === undefined && rosterLoadError === undefined;
|
|
10611
|
+
const orchestratorAgentName = ORCHESTRATOR_AGENT_PATH.slice(ORCHESTRATOR_AGENT_PATH.lastIndexOf("/") + 1).replace(/\.md$/, "");
|
|
10612
|
+
const orchestratorAgentMissing = !agentFiles.some((file) => file.name === orchestratorAgentName);
|
|
10434
10613
|
return {
|
|
10435
10614
|
exitCode: 0,
|
|
10436
10615
|
stdout: renderDoctor({
|
|
@@ -10444,6 +10623,8 @@ async function runCli(argv, deps) {
|
|
|
10444
10623
|
...rosterAudit !== undefined ? { rosterAudit } : {},
|
|
10445
10624
|
...rosterRoleCount !== undefined ? { rosterRoleCount } : {},
|
|
10446
10625
|
...rosterLoadError !== undefined ? { rosterLoadError } : {},
|
|
10626
|
+
...rosterMissing ? { rosterMissing } : {},
|
|
10627
|
+
...orchestratorAgentMissing ? { orchestratorAgentMissing } : {},
|
|
10447
10628
|
...diagnostics !== undefined && diagnostics.length > 0 ? { diagnostics } : {},
|
|
10448
10629
|
...opencodeConfigError !== undefined ? { opencodeConfigError } : {},
|
|
10449
10630
|
...cacheEntries !== undefined ? { cacheEntries, cliVersion: deps.version } : {},
|
|
@@ -13308,7 +13489,7 @@ var createOtlpSpanExporter = (connection, config) => {
|
|
|
13308
13489
|
// package.json
|
|
13309
13490
|
var package_default = {
|
|
13310
13491
|
name: "@jmanuelcorral/openteam",
|
|
13311
|
-
version: "0.
|
|
13492
|
+
version: "0.16.1",
|
|
13312
13493
|
packageManager: "bun@1.3.14",
|
|
13313
13494
|
description: "Cost-aware, local-first routing plugin for opencode with cheapest-capable frontier fallback and multi-agent orchestration.",
|
|
13314
13495
|
license: "MIT",
|
|
@@ -13672,6 +13853,14 @@ async function buildGateInput(config, storage, opencodeVersion, warn) {
|
|
|
13672
13853
|
const operatorApproval = config.graph?.operatorApproval ?? false;
|
|
13673
13854
|
return { shadow, release, soak, migration, operatorApproval };
|
|
13674
13855
|
}
|
|
13856
|
+
var OPENCODE_VERSION_UNRESOLVED_REASON = "the opencode version is not determinable outside a running opencode session, " + "so the cutover gate cannot be verified here — the running plugin logs the " + "authoritative gate result and warns loudly on a real denial";
|
|
13857
|
+
async function evaluateCutoverGateForBoundary(config, storage, version) {
|
|
13858
|
+
if (version === undefined) {
|
|
13859
|
+
return { kind: "unevaluable", reason: OPENCODE_VERSION_UNRESOLVED_REASON };
|
|
13860
|
+
}
|
|
13861
|
+
const gateInput = await buildGateInput(config, storage, version, () => {});
|
|
13862
|
+
return { kind: "evaluated", gate: evaluateGraphGate(gateInput) };
|
|
13863
|
+
}
|
|
13675
13864
|
function recorderPortsFromStorage(storage) {
|
|
13676
13865
|
return {
|
|
13677
13866
|
fs: {
|
|
@@ -13759,7 +13948,7 @@ async function readStoredRosterForDoctor(storage) {
|
|
|
13759
13948
|
}
|
|
13760
13949
|
}
|
|
13761
13950
|
var auditStoredRosterForDoctor = (roster, configuredRoles) => typeof roster === "string" ? auditRoster(roster, configuredRoles) : auditRoster(roster, configuredRoles);
|
|
13762
|
-
function createCliDeps(config, registry, telemetryPath, sessionsDir = DEFAULT_SESSIONS_DIR, storage = createFsStorageProvider(process.cwd()), fallbackSource = "options", rawOptions) {
|
|
13951
|
+
function createCliDeps(config, registry, telemetryPath, sessionsDir = DEFAULT_SESSIONS_DIR, storage = createFsStorageProvider(process.cwd()), fallbackSource = "options", rawOptions, resolveOpencodeVersion) {
|
|
13763
13952
|
return {
|
|
13764
13953
|
loadConfig: async (path4, resolution = { explicit: false }) => {
|
|
13765
13954
|
const content = await readCliConfigFromStorage(storage, path4, resolution);
|
|
@@ -13833,7 +14022,8 @@ function createCliDeps(config, registry, telemetryPath, sessionsDir = DEFAULT_SE
|
|
|
13833
14022
|
}),
|
|
13834
14023
|
graphOperator: createGraphOperator({
|
|
13835
14024
|
storage,
|
|
13836
|
-
holder: "openteam-cli"
|
|
14025
|
+
holder: "openteam-cli",
|
|
14026
|
+
evaluateCutoverGate: async (gateConfig) => evaluateCutoverGateForBoundary(gateConfig, storage, resolveOpencodeVersion === undefined ? undefined : await resolveOpencodeVersion())
|
|
13837
14027
|
}),
|
|
13838
14028
|
configPath: DEFAULT_CONFIG_PATH,
|
|
13839
14029
|
telemetryPath,
|
|
@@ -13963,7 +14153,14 @@ var server = async (ctx, rawOptions) => {
|
|
|
13963
14153
|
injectMemory,
|
|
13964
14154
|
onRoute: (sid, model) => sessionTracker.trackRoutedModel(sid, model)
|
|
13965
14155
|
});
|
|
13966
|
-
const
|
|
14156
|
+
const getOpencodeVersion = createLazyOpencodeVersionReader(ctx.serverUrl, {
|
|
14157
|
+
client: ctx.client,
|
|
14158
|
+
onFailure: createOpencodeVersionReadFailureLogger(MAX_LOGGED_OPENCODE_VERSION_FAILURE_CAUSES, diagnostics.warn("opencode-version-read-failed", { toast: false }))
|
|
14159
|
+
});
|
|
14160
|
+
const cliDeps = createCliDeps(config, registry, telemetryPath, sessionsDir, storage, runtimeConfig.source, rawOptions, async () => {
|
|
14161
|
+
const version = await getOpencodeVersion();
|
|
14162
|
+
return version === "unknown" ? undefined : version;
|
|
14163
|
+
});
|
|
13967
14164
|
const toolcalls = createToolcallTracker({ sink });
|
|
13968
14165
|
const announcedSessions = new Set;
|
|
13969
14166
|
const announceEndpoint = (sessionID) => {
|
|
@@ -13986,10 +14183,6 @@ var server = async (ctx, rawOptions) => {
|
|
|
13986
14183
|
if (config.privacyMode === "forceLocalOnSensitive" && localDefault(config) === null) {
|
|
13987
14184
|
warnInertPrivacySetting(runtimeConfig.searchedPaths, diagnostics.warn("privacy-inert"));
|
|
13988
14185
|
}
|
|
13989
|
-
const getOpencodeVersion = createLazyOpencodeVersionReader(ctx.serverUrl, {
|
|
13990
|
-
client: ctx.client,
|
|
13991
|
-
onFailure: createOpencodeVersionReadFailureLogger(MAX_LOGGED_OPENCODE_VERSION_FAILURE_CAUSES, diagnostics.warn("opencode-version-read-failed", { toast: false }))
|
|
13992
|
-
});
|
|
13993
14186
|
if (isGateApplicable(graphConfig.effectiveMode)) {
|
|
13994
14187
|
const opencodeVersion = await getOpencodeVersion();
|
|
13995
14188
|
const gateInput = await buildGateInput(config, storage, opencodeVersion, diagnostics.warn("soak-evidence-rejected", { toast: false }));
|
|
@@ -14047,8 +14240,16 @@ var server = async (ctx, rawOptions) => {
|
|
|
14047
14240
|
const snapshots = await registry.probe(config.local.runtimes.filter((runtime) => runtime.enabled));
|
|
14048
14241
|
return reachableRuntimeIds(snapshots);
|
|
14049
14242
|
};
|
|
14243
|
+
const runtimeById = (id) => config.local.runtimes.find((runtime) => runtime.id === id);
|
|
14050
14244
|
const runtimeLimiter = createRuntimeConcurrencyLimiter({
|
|
14051
|
-
capacityFor: (id) =>
|
|
14245
|
+
capacityFor: (id) => {
|
|
14246
|
+
const runtime = runtimeById(id);
|
|
14247
|
+
return runtime === undefined ? DEFAULT_LOCAL_MAX_CONCURRENCY : effectiveMaxConcurrency(runtime);
|
|
14248
|
+
},
|
|
14249
|
+
reservedInteractiveFor: (id) => {
|
|
14250
|
+
const runtime = runtimeById(id);
|
|
14251
|
+
return runtime === undefined ? 0 : effectiveReservedInteractiveSlots(runtime);
|
|
14252
|
+
},
|
|
14052
14253
|
now
|
|
14053
14254
|
});
|
|
14054
14255
|
const orchestrateTool = createOrchestrateTool({
|
|
@@ -14146,6 +14347,7 @@ export {
|
|
|
14146
14347
|
logOpencodeServerUrl,
|
|
14147
14348
|
logAvailabilityRefreshError,
|
|
14148
14349
|
isMissingFile,
|
|
14350
|
+
evaluateCutoverGateForBoundary,
|
|
14149
14351
|
src_default as default,
|
|
14150
14352
|
createOpencodeVersionReadFailureLogger,
|
|
14151
14353
|
createLazyOpencodeVersionReader,
|
|
@@ -14153,5 +14355,6 @@ export {
|
|
|
14153
14355
|
createCliDeps,
|
|
14154
14356
|
buildGateInput,
|
|
14155
14357
|
PACKAGE_VERSION,
|
|
14358
|
+
OPENCODE_VERSION_UNRESOLVED_REASON,
|
|
14156
14359
|
MAX_LOGGED_OPENCODE_VERSION_FAILURE_CAUSES
|
|
14157
14360
|
};
|
|
@@ -7,8 +7,8 @@ import type { LocalRuntimeId } from "./types";
|
|
|
7
7
|
export type RuntimeSlotRelease = () => void;
|
|
8
8
|
/**
|
|
9
9
|
* Outcome of an `acquire`: the slot release plus how long the caller waited in
|
|
10
|
-
* the
|
|
11
|
-
* free and the acquisition resolved without queuing. It is measured with the
|
|
10
|
+
* the priority queue before the slot was granted. `waitedMs` is `0` when a slot
|
|
11
|
+
* was free and the acquisition resolved without queuing. It is measured with the
|
|
12
12
|
* injected clock (`RuntimeConcurrencyLimiterOptions.now`), so tests are
|
|
13
13
|
* deterministic and the limiter never reads wall-clock time inline.
|
|
14
14
|
*/
|
|
@@ -17,7 +17,22 @@ export type RuntimeSlotAcquisition = {
|
|
|
17
17
|
readonly waitedMs: number;
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* Priority band a caller acquires a runtime slot under (#213), highest first:
|
|
21
|
+
*
|
|
22
|
+
* - `"interactive"` — latency-sensitive, coordinator-facing work. May use the
|
|
23
|
+
* runtime's FULL capacity.
|
|
24
|
+
* - `"worker"` — ordinary fan-out generations. The DEFAULT, so every pre-#213
|
|
25
|
+
* caller keeps its behaviour unchanged.
|
|
26
|
+
* - `"background"` — bookkeeping/telemetry work (e.g. the scribe role).
|
|
27
|
+
*
|
|
28
|
+
* Queue ordering is STRICT PRIORITY ACROSS bands and FIFO WITHIN a band: on
|
|
29
|
+
* release the freed slot is granted to the longest-waiting waiter in the highest
|
|
30
|
+
* non-empty admissible band.
|
|
31
|
+
*/
|
|
32
|
+
export type RuntimeSlotPriority = "interactive" | "worker" | "background";
|
|
33
|
+
/**
|
|
34
|
+
* Per-runtime concurrency limiter with a PRIORITY queue and RESERVED interactive
|
|
35
|
+
* capacity (#144, #213).
|
|
21
36
|
*
|
|
22
37
|
* A runtime has a fixed number of slots (its configured `maxConcurrency`). The
|
|
23
38
|
* limiter caps concurrent generations to that number and QUEUES excess work
|
|
@@ -32,21 +47,55 @@ export type RuntimeSlotAcquisition = {
|
|
|
32
47
|
* concurrent-telemetry emission order of a wave is unperturbed. Only when a
|
|
33
48
|
* runtime is saturated does `acquire` return a promise that settles when a slot
|
|
34
49
|
* frees.
|
|
50
|
+
*
|
|
51
|
+
* ## Priority bands
|
|
52
|
+
*
|
|
53
|
+
* Callers pass a {@link RuntimeSlotPriority}; when omitted it defaults to
|
|
54
|
+
* `"worker"` so existing callers are unchanged. Queuing is strict priority
|
|
55
|
+
* across bands and FIFO within a band: an interactive waiter is always served
|
|
56
|
+
* before any worker, and workers before background, but two waiters of the same
|
|
57
|
+
* band keep their arrival order (so existing ordering guarantees survive).
|
|
58
|
+
*
|
|
59
|
+
* ## Reserved interactive capacity — the core of #213
|
|
60
|
+
*
|
|
61
|
+
* `reservedInteractiveFor` withholds a slice of a runtime's capacity from the
|
|
62
|
+
* non-interactive bands: `worker`/`background` callers may occupy at most
|
|
63
|
+
* `capacity - reserved` slots, while `interactive` callers may use the FULL
|
|
64
|
+
* capacity. The reserved count is clamped to `[0, capacity - 1]` so the
|
|
65
|
+
* non-interactive budget is never driven to 0 (a single-slot runtime with
|
|
66
|
+
* `reserved = 1` would otherwise deadlock every worker forever); non-integer,
|
|
67
|
+
* negative and NaN inputs are sanitised too.
|
|
68
|
+
*
|
|
69
|
+
* The non-obvious part: openteam's own INTERACTIVE/coordinator traffic reaches
|
|
70
|
+
* the local runtime as ordinary opencode chat and never passes through this
|
|
71
|
+
* limiter. Reserving a slot still helps, because the reservation caps how many
|
|
72
|
+
* slots openteam's WORKERS occupy on the shared runtime. By refusing to let
|
|
73
|
+
* workers fill the last slot, the limiter guarantees the runtime SERVER always
|
|
74
|
+
* has free headroom for the ungoverned interactive request — turning a
|
|
75
|
+
* `maxConcurrency` that equals the server's real slot count (the reported
|
|
76
|
+
* incident: a 4-slot Lemonade box with `DEFAULT_LOCAL_MAX_CONCURRENCY === 4`)
|
|
77
|
+
* from full saturation into a 3-worker + 1-reserved split with no config change.
|
|
78
|
+
* The `interactive` band exists so an in-process interactive caller can still
|
|
79
|
+
* claim the reserved slot when one is wired up.
|
|
35
80
|
*/
|
|
36
81
|
export type RuntimeConcurrencyLimiter = {
|
|
37
82
|
/**
|
|
38
|
-
* Attempts to take a slot for `runtimeId` synchronously
|
|
39
|
-
* when a slot was free
|
|
83
|
+
* Attempts to take a slot for `runtimeId` synchronously under `priority`
|
|
84
|
+
* (default `"worker"`). Returns a release when a slot was free within the
|
|
85
|
+
* band's admissible budget, or `undefined` when the runtime is at its cap (for
|
|
86
|
+
* `interactive`) or at its reserved-adjusted budget (for `worker`/
|
|
87
|
+
* `background`).
|
|
40
88
|
*/
|
|
41
|
-
tryAcquire(runtimeId: LocalRuntimeId): RuntimeSlotRelease | undefined;
|
|
89
|
+
tryAcquire(runtimeId: LocalRuntimeId, priority?: RuntimeSlotPriority): RuntimeSlotRelease | undefined;
|
|
42
90
|
/**
|
|
43
|
-
* Takes a slot for `runtimeId
|
|
44
|
-
*
|
|
45
|
-
* available. Prefer `tryAcquire` first and
|
|
46
|
-
* returns `undefined`, so the common free path
|
|
47
|
-
* is free, resolves immediately with
|
|
91
|
+
* Takes a slot for `runtimeId` under `priority` (default `"worker"`), queuing
|
|
92
|
+
* when the runtime is saturated for that band. Resolves with a release and the
|
|
93
|
+
* measured queue wait once a slot is available. Prefer `tryAcquire` first and
|
|
94
|
+
* only `await acquire` when it returns `undefined`, so the common free path
|
|
95
|
+
* stays synchronous. When a slot is free, resolves immediately with
|
|
96
|
+
* `waitedMs === 0`.
|
|
48
97
|
*/
|
|
49
|
-
acquire(runtimeId: LocalRuntimeId): Promise<RuntimeSlotAcquisition>;
|
|
98
|
+
acquire(runtimeId: LocalRuntimeId, priority?: RuntimeSlotPriority): Promise<RuntimeSlotAcquisition>;
|
|
50
99
|
/** Current in-flight count for a runtime. Exposed for tests and diagnostics. */
|
|
51
100
|
activeCount(runtimeId: LocalRuntimeId): number;
|
|
52
101
|
/** Current queued (waiting) count for a runtime. Exposed for tests. */
|
|
@@ -59,12 +108,21 @@ export type RuntimeConcurrencyLimiterOptions = {
|
|
|
59
108
|
* runtime does not declare a cap. Must return a positive integer.
|
|
60
109
|
*/
|
|
61
110
|
capacityFor: (runtimeId: LocalRuntimeId) => number;
|
|
111
|
+
/**
|
|
112
|
+
* Resolves how many of a runtime's slots are RESERVED for interactive work
|
|
113
|
+
* (#213). Optional and injected so the limiter carries no config coupling;
|
|
114
|
+
* when absent, no capacity is reserved and behaviour matches the pre-#213
|
|
115
|
+
* FIFO limiter exactly. The returned value is clamped to `[0, capacity - 1]`
|
|
116
|
+
* and sanitised (non-integer/negative/NaN handled conservatively), so it can
|
|
117
|
+
* never starve the non-interactive budget to 0.
|
|
118
|
+
*/
|
|
119
|
+
reservedInteractiveFor?: (runtimeId: LocalRuntimeId) => number;
|
|
62
120
|
/**
|
|
63
121
|
* Injected clock in epoch milliseconds, used ONLY to measure how long a
|
|
64
|
-
* saturated `acquire` waited in the
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
122
|
+
* saturated `acquire` waited in the queue. The free `tryAcquire` path never
|
|
123
|
+
* reads it, so the happy path stays allocation-free and clock-free. Injected
|
|
124
|
+
* (never `Date.now()` inline) so queue-wait telemetry is deterministic under
|
|
125
|
+
* test.
|
|
68
126
|
*/
|
|
69
127
|
now: () => number;
|
|
70
128
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"concurrency.d.ts","sourceRoot":"","sources":["../../src/local/concurrency.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"concurrency.d.ts","sourceRoot":"","sources":["../../src/local/concurrency.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,QAAQ,GAAG,YAAY,CAAC;AAQ1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC;;;;;;OAMG;IACH,UAAU,CACR,SAAS,EAAE,cAAc,EACzB,QAAQ,CAAC,EAAE,mBAAmB,GAC7B,kBAAkB,GAAG,SAAS,CAAC;IAClC;;;;;;;OAOG;IACH,OAAO,CACL,SAAS,EAAE,cAAc,EACzB,QAAQ,CAAC,EAAE,mBAAmB,GAC7B,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACnC,gFAAgF;IAChF,WAAW,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,CAAC;IAC/C,uEAAuE;IACvE,WAAW,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,CAAC;CAChD,CAAC;AAaF,MAAM,MAAM,gCAAgC,GAAG;IAC7C;;;;OAIG;IACH,WAAW,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,MAAM,CAAC;IACnD;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,MAAM,CAAC;IAC/D;;;;;;OAMG;IACH,GAAG,EAAE,MAAM,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,gCAAgC,GACxC,yBAAyB,CAuK3B"}
|