mu-agent 0.1.13 → 0.2.0
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 +47 -0
- package/README.md +5 -3
- package/dist/bundle/chunks/{chunk-WDURT4ZM.js → chunk-AN7MSYCK.js} +1 -1
- package/dist/bundle/chunks/{chunk-3J3HSHLX.js → chunk-BK7M6BDT.js} +3 -3
- package/dist/bundle/chunks/{virtual-modules-TJPHLTRT.js → virtual-modules-U6MRV5BC.js} +1 -1
- package/dist/bundle/cli-runtime.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/judge/dist/auth.js +3 -0
- package/judge/dist/mude.js +1338 -0
- package/judge/dist/setup.js +15 -4
- package/judge/manifest.json +139 -71
- package/judge/mu/{chunk-SKGYWHW6.js → chunk-6XRUK3PM.js} +1 -1
- package/judge/mu/{cloud-code-V7FOGB4J.js → cloud-code-XR7SZMJC.js} +1 -1
- package/judge/mu/index.js +501 -214
- package/kyrn/bin/kyrn-doctor +67 -13
- package/kyrn/bin/mu.mjs +143 -9
- package/kyrn/local-judge/mude-requirements.lock.txt +746 -0
- package/package.json +2 -2
package/judge/mu/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
init_pi_host_modules,
|
|
10
10
|
pi_host_modules_exports,
|
|
11
11
|
require_pi_ai
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-6XRUK3PM.js";
|
|
13
13
|
import {
|
|
14
14
|
__commonJS,
|
|
15
15
|
__require,
|
|
@@ -27412,7 +27412,7 @@ var require_pi_tui = __commonJS({
|
|
|
27412
27412
|
});
|
|
27413
27413
|
|
|
27414
27414
|
// packages/kyrn-judge/src/extension/kyrn-judge.ts
|
|
27415
|
-
var
|
|
27415
|
+
var import_pi_coding_agent17 = __toESM(require_pi_coding_agent(), 1);
|
|
27416
27416
|
import { homedir as homedir12 } from "node:os";
|
|
27417
27417
|
import { join as join49 } from "node:path";
|
|
27418
27418
|
|
|
@@ -27464,8 +27464,27 @@ var BUILT_IN_JUDGES = {
|
|
|
27464
27464
|
// Terminal-Bench 2.1 (Oct 2026): on tool output it is wrong or late. All 15 passages it withheld as injections were
|
|
27465
27465
|
// clean (directory listings, href lists, headers, JSON), its one admission drop was a makefile, and most of its
|
|
27466
27466
|
// calls on both failed or came too late. So screening tool output (`screen`) goes to the next tier, or to the
|
|
27467
|
-
// rules.
|
|
27468
|
-
|
|
27467
|
+
// rules. It also read a finished "Done. Created /app/meeting_scheduled.ics …" as a promise of more work, twice in one
|
|
27468
|
+
// run (constraints-scheduling): 4 extra requests and the model searching / for test files. So whether a closing
|
|
27469
|
+
// message promised more (`intent`, turn.continue) goes to the next tier too; `continuation.localPromised` asks it.
|
|
27470
|
+
laya: {
|
|
27471
|
+
type: "local",
|
|
27472
|
+
profile: { capabilities: { relate: false, rate: false, meta: false, screen: false, intent: false } }
|
|
27473
|
+
},
|
|
27474
|
+
// mude, the decision model trained for mu's judgment layer, on this Mac (`mu judge mude install`, Apple silicon):
|
|
27475
|
+
// the System One server that comes in its package, on 127.0.0.1:8790, with the key the install wrote to the .env.
|
|
27476
|
+
// Trusted on every capability: on mu's own dev scenarios (an internal benchmark, not public yet) it did as well as Jev
|
|
27477
|
+
// or better on relate, rate, meta, screening tool output (`tool.admission`) and promises (`turn.continue`), and on
|
|
27478
|
+
// classify but for one check: a tool's description screened for injected instructions (`tool.description`), where
|
|
27479
|
+
// Jev did better. Nothing measured it on injections in fetched content (`tool.injection`). So with a judge behind it,
|
|
27480
|
+
// `mu judge mude` routes those two checks to that judge (`routes` in mu.json). It answers in about 0.1 s here.
|
|
27481
|
+
mude: {
|
|
27482
|
+
type: "typesafe",
|
|
27483
|
+
baseUrl: "http://127.0.0.1:8790/v1/systemone",
|
|
27484
|
+
model: "mude",
|
|
27485
|
+
apiKeyEnv: "MU_JUDGE_MUDE_KEY",
|
|
27486
|
+
timeoutMs: 4e3
|
|
27487
|
+
},
|
|
27469
27488
|
mock: { type: "mock" }
|
|
27470
27489
|
};
|
|
27471
27490
|
var DEFAULT_CONFIG = {
|
|
@@ -27477,6 +27496,9 @@ var DEFAULT_CONFIG = {
|
|
|
27477
27496
|
// swarm.patch is off: it sees only paths and line counts, which the delegate result already lists, and it held
|
|
27478
27497
|
// up every delegate call that brought back a patch.
|
|
27479
27498
|
"swarm.patch": "off",
|
|
27499
|
+
// capability.disclosure is off: asked on every message, it opened nothing in 162 benchmark questions and 34 in
|
|
27500
|
+
// real sessions, while it held up the start of the turn. Packs stay hidden, and find_capability opens one.
|
|
27501
|
+
"capability.disclosure": "off",
|
|
27480
27502
|
// Its rules deliver what matters; in single-prompt runs a "next_turn" verdict never reached anyone.
|
|
27481
27503
|
"notify.routing": "shadow",
|
|
27482
27504
|
// About a second on every mid-run message, and no verdict has changed anything yet.
|
|
@@ -27655,9 +27677,17 @@ var Judge = class {
|
|
|
27655
27677
|
const startedAt = performance.now();
|
|
27656
27678
|
let responses;
|
|
27657
27679
|
try {
|
|
27658
|
-
|
|
27680
|
+
const requests = Promise.all(
|
|
27659
27681
|
chunks.map((questions) => this.provider.evaluate({ state: request.state, questions, signal }))
|
|
27660
27682
|
);
|
|
27683
|
+
const deadline = new Promise((_, reject) => {
|
|
27684
|
+
const timer = setTimeout(
|
|
27685
|
+
() => reject(new JudgeError("timeout", `Judge call exceeded ${this.timeoutMs} ms`)),
|
|
27686
|
+
this.timeoutMs
|
|
27687
|
+
);
|
|
27688
|
+
requests.finally(() => clearTimeout(timer)).catch(() => void 0);
|
|
27689
|
+
});
|
|
27690
|
+
responses = await Promise.race([requests, deadline]);
|
|
27661
27691
|
} catch (error) {
|
|
27662
27692
|
if (request.signal?.aborted) throw new JudgeError("aborted", "Judge call was aborted", { cause: error });
|
|
27663
27693
|
if (timeout.aborted) {
|
|
@@ -28294,9 +28324,14 @@ var DecisionEngine = class {
|
|
|
28294
28324
|
setDefaultMode(mode) {
|
|
28295
28325
|
this.defaultMode = mode;
|
|
28296
28326
|
}
|
|
28297
|
-
/**
|
|
28298
|
-
|
|
28299
|
-
|
|
28327
|
+
/**
|
|
28328
|
+
* The points whose mode, as it takes effect, differs from the default: what a status display lists after it. A
|
|
28329
|
+
* built-in shadow that gives way to a default of off is not one.
|
|
28330
|
+
*/
|
|
28331
|
+
overrides() {
|
|
28332
|
+
return new Map(
|
|
28333
|
+
[...this.modes.keys()].map((specId) => [specId, this.getMode(specId)]).filter(([, mode]) => mode !== this.defaultMode)
|
|
28334
|
+
);
|
|
28300
28335
|
}
|
|
28301
28336
|
async evaluate(spec, input, state, signal) {
|
|
28302
28337
|
const questions = spec.questionsFor ? spec.questionsFor(input) : spec.questions;
|
|
@@ -28308,9 +28343,10 @@ var DecisionEngine = class {
|
|
|
28308
28343
|
if (shared) this.lastUsedAt = Date.now();
|
|
28309
28344
|
try {
|
|
28310
28345
|
const known = this.knownSecrets();
|
|
28346
|
+
const asked = redactJson(questions, known);
|
|
28311
28347
|
const result = await this.judgeFor(spec.id).evaluate({
|
|
28312
28348
|
state: redactJson(state, known),
|
|
28313
|
-
questions:
|
|
28349
|
+
questions: asked,
|
|
28314
28350
|
signal,
|
|
28315
28351
|
capabilities
|
|
28316
28352
|
});
|
|
@@ -28321,7 +28357,9 @@ var DecisionEngine = class {
|
|
|
28321
28357
|
usage: result.usage,
|
|
28322
28358
|
modelId: result.modelId,
|
|
28323
28359
|
warnings: result.warnings.length > 0 ? result.warnings : void 0,
|
|
28324
|
-
tiers: result.tiers
|
|
28360
|
+
tiers: result.tiers,
|
|
28361
|
+
// Fixed questions are the spec's own (`specId`, `specVersion`); built ones exist nowhere else.
|
|
28362
|
+
questions: this.recordState && spec.questionsFor ? asked : void 0
|
|
28325
28363
|
};
|
|
28326
28364
|
const verdict3 = spec.policy(result.answers, input);
|
|
28327
28365
|
if (verdict3 === ABSTAIN) {
|
|
@@ -28389,7 +28427,8 @@ var DecisionEngine = class {
|
|
|
28389
28427
|
warnings: evaluation.warnings,
|
|
28390
28428
|
tiers: evaluation.tiers,
|
|
28391
28429
|
stateDigest: createHash("sha256").update(JSON.stringify(state)).digest("hex"),
|
|
28392
|
-
state: this.recordState ? state : void 0
|
|
28430
|
+
state: this.recordState ? state : void 0,
|
|
28431
|
+
questions: evaluation.questions
|
|
28393
28432
|
};
|
|
28394
28433
|
await this.record(record4);
|
|
28395
28434
|
return {
|
|
@@ -28954,89 +28993,6 @@ var toolAdmissionBatch = defineDecision({
|
|
|
28954
28993
|
// packages/kyrn-judge/src/extension/runtime.ts
|
|
28955
28994
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
28956
28995
|
|
|
28957
|
-
// packages/kyrn-judge/src/catalog/catalog.ts
|
|
28958
|
-
var CapabilityCatalog = class {
|
|
28959
|
-
entries = /* @__PURE__ */ new Map();
|
|
28960
|
-
opened = /* @__PURE__ */ new Map();
|
|
28961
|
-
activated = /* @__PURE__ */ new Set();
|
|
28962
|
-
/** Registering the same id again replaces the entry: an MCP server list can be reloaded. */
|
|
28963
|
-
register(capability) {
|
|
28964
|
-
this.entries.set(capability.id, capability);
|
|
28965
|
-
}
|
|
28966
|
-
get(id) {
|
|
28967
|
-
return this.entries.get(id);
|
|
28968
|
-
}
|
|
28969
|
-
list() {
|
|
28970
|
-
return [...this.entries.values()];
|
|
28971
|
-
}
|
|
28972
|
-
isOpen(id) {
|
|
28973
|
-
const capability = this.entries.get(id);
|
|
28974
|
-
return capability !== void 0 && (capability.exposure === "always" || this.opened.has(id));
|
|
28975
|
-
}
|
|
28976
|
-
/** Judged capabilities that are still hidden. */
|
|
28977
|
-
hidden() {
|
|
28978
|
-
return this.list().filter((capability) => !this.isOpen(capability.id));
|
|
28979
|
-
}
|
|
28980
|
-
/** Tools that must stay out of the model's tool list right now. */
|
|
28981
|
-
hiddenTools() {
|
|
28982
|
-
const open = new Set(
|
|
28983
|
-
this.list().filter((capability) => this.isOpen(capability.id)).flatMap((capability) => capability.tools)
|
|
28984
|
-
);
|
|
28985
|
-
return new Set(
|
|
28986
|
-
this.hidden().flatMap((capability) => capability.tools).filter((tool) => !open.has(tool))
|
|
28987
|
-
);
|
|
28988
|
-
}
|
|
28989
|
-
/**
|
|
28990
|
-
* Opens a capability and starts what backs it. Resolves to false when the id
|
|
28991
|
-
* is unknown or it was open already. A failing `activate` leaves it closed and
|
|
28992
|
-
* rethrows, so the caller can say why.
|
|
28993
|
-
*/
|
|
28994
|
-
async open(id, by, turn) {
|
|
28995
|
-
const capability = this.entries.get(id);
|
|
28996
|
-
if (!capability || this.isOpen(id)) return false;
|
|
28997
|
-
if (capability.activate && !this.activated.has(id)) {
|
|
28998
|
-
await capability.activate();
|
|
28999
|
-
this.activated.add(id);
|
|
29000
|
-
}
|
|
29001
|
-
this.opened.set(id, { id, by, turn });
|
|
29002
|
-
return true;
|
|
29003
|
-
}
|
|
29004
|
-
/** Everything opened so far, in order. */
|
|
29005
|
-
history() {
|
|
29006
|
-
return [...this.opened.values()];
|
|
29007
|
-
}
|
|
29008
|
-
/** Hidden capabilities whose title, id or description contains any of the words; all of them for an empty query. */
|
|
29009
|
-
search(query) {
|
|
29010
|
-
const words2 = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
29011
|
-
return this.hidden().filter((capability) => {
|
|
29012
|
-
const text7 = `${capability.id} ${capability.title} ${capability.description}`.toLowerCase();
|
|
29013
|
-
return words2.length === 0 || words2.some((word) => text7.includes(word));
|
|
29014
|
-
});
|
|
29015
|
-
}
|
|
29016
|
-
};
|
|
29017
|
-
|
|
29018
|
-
// packages/kyrn-judge/src/ledger.ts
|
|
29019
|
-
var MemoryLedger = class {
|
|
29020
|
-
records = [];
|
|
29021
|
-
capacity;
|
|
29022
|
-
constructor(capacity = 500) {
|
|
29023
|
-
this.capacity = capacity;
|
|
29024
|
-
}
|
|
29025
|
-
append(record4) {
|
|
29026
|
-
this.records.push(record4);
|
|
29027
|
-
if (this.records.length > this.capacity) this.records.shift();
|
|
29028
|
-
}
|
|
29029
|
-
};
|
|
29030
|
-
var CompositeLedger = class {
|
|
29031
|
-
sinks;
|
|
29032
|
-
constructor(sinks) {
|
|
29033
|
-
this.sinks = sinks;
|
|
29034
|
-
}
|
|
29035
|
-
async append(record4) {
|
|
29036
|
-
await Promise.allSettled(this.sinks.map(async (sink) => sink.append(record4)));
|
|
29037
|
-
}
|
|
29038
|
-
};
|
|
29039
|
-
|
|
29040
28996
|
// packages/kyrn-judge/src/cascade.ts
|
|
29041
28997
|
function capabilityOf(question, declared) {
|
|
29042
28998
|
return declared ?? (question.type === "score" ? "rate" : "classify");
|
|
@@ -29149,6 +29105,89 @@ var CascadeJudge = class {
|
|
|
29149
29105
|
}
|
|
29150
29106
|
};
|
|
29151
29107
|
|
|
29108
|
+
// packages/kyrn-judge/src/catalog/catalog.ts
|
|
29109
|
+
var CapabilityCatalog = class {
|
|
29110
|
+
entries = /* @__PURE__ */ new Map();
|
|
29111
|
+
opened = /* @__PURE__ */ new Map();
|
|
29112
|
+
activated = /* @__PURE__ */ new Set();
|
|
29113
|
+
/** Registering the same id again replaces the entry: an MCP server list can be reloaded. */
|
|
29114
|
+
register(capability) {
|
|
29115
|
+
this.entries.set(capability.id, capability);
|
|
29116
|
+
}
|
|
29117
|
+
get(id) {
|
|
29118
|
+
return this.entries.get(id);
|
|
29119
|
+
}
|
|
29120
|
+
list() {
|
|
29121
|
+
return [...this.entries.values()];
|
|
29122
|
+
}
|
|
29123
|
+
isOpen(id) {
|
|
29124
|
+
const capability = this.entries.get(id);
|
|
29125
|
+
return capability !== void 0 && (capability.exposure === "always" || this.opened.has(id));
|
|
29126
|
+
}
|
|
29127
|
+
/** Judged capabilities that are still hidden. */
|
|
29128
|
+
hidden() {
|
|
29129
|
+
return this.list().filter((capability) => !this.isOpen(capability.id));
|
|
29130
|
+
}
|
|
29131
|
+
/** Tools that must stay out of the model's tool list right now. */
|
|
29132
|
+
hiddenTools() {
|
|
29133
|
+
const open = new Set(
|
|
29134
|
+
this.list().filter((capability) => this.isOpen(capability.id)).flatMap((capability) => capability.tools)
|
|
29135
|
+
);
|
|
29136
|
+
return new Set(
|
|
29137
|
+
this.hidden().flatMap((capability) => capability.tools).filter((tool) => !open.has(tool))
|
|
29138
|
+
);
|
|
29139
|
+
}
|
|
29140
|
+
/**
|
|
29141
|
+
* Opens a capability and starts what backs it. Resolves to false when the id
|
|
29142
|
+
* is unknown or it was open already. A failing `activate` leaves it closed and
|
|
29143
|
+
* rethrows, so the caller can say why.
|
|
29144
|
+
*/
|
|
29145
|
+
async open(id, by, turn) {
|
|
29146
|
+
const capability = this.entries.get(id);
|
|
29147
|
+
if (!capability || this.isOpen(id)) return false;
|
|
29148
|
+
if (capability.activate && !this.activated.has(id)) {
|
|
29149
|
+
await capability.activate();
|
|
29150
|
+
this.activated.add(id);
|
|
29151
|
+
}
|
|
29152
|
+
this.opened.set(id, { id, by, turn });
|
|
29153
|
+
return true;
|
|
29154
|
+
}
|
|
29155
|
+
/** Everything opened so far, in order. */
|
|
29156
|
+
history() {
|
|
29157
|
+
return [...this.opened.values()];
|
|
29158
|
+
}
|
|
29159
|
+
/** Hidden capabilities whose title, id or description contains any of the words; all of them for an empty query. */
|
|
29160
|
+
search(query) {
|
|
29161
|
+
const words2 = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
29162
|
+
return this.hidden().filter((capability) => {
|
|
29163
|
+
const text7 = `${capability.id} ${capability.title} ${capability.description}`.toLowerCase();
|
|
29164
|
+
return words2.length === 0 || words2.some((word) => text7.includes(word));
|
|
29165
|
+
});
|
|
29166
|
+
}
|
|
29167
|
+
};
|
|
29168
|
+
|
|
29169
|
+
// packages/kyrn-judge/src/ledger.ts
|
|
29170
|
+
var MemoryLedger = class {
|
|
29171
|
+
records = [];
|
|
29172
|
+
capacity;
|
|
29173
|
+
constructor(capacity = 500) {
|
|
29174
|
+
this.capacity = capacity;
|
|
29175
|
+
}
|
|
29176
|
+
append(record4) {
|
|
29177
|
+
this.records.push(record4);
|
|
29178
|
+
if (this.records.length > this.capacity) this.records.shift();
|
|
29179
|
+
}
|
|
29180
|
+
};
|
|
29181
|
+
var CompositeLedger = class {
|
|
29182
|
+
sinks;
|
|
29183
|
+
constructor(sinks) {
|
|
29184
|
+
this.sinks = sinks;
|
|
29185
|
+
}
|
|
29186
|
+
async append(record4) {
|
|
29187
|
+
await Promise.allSettled(this.sinks.map(async (sink) => sink.append(record4)));
|
|
29188
|
+
}
|
|
29189
|
+
};
|
|
29190
|
+
|
|
29152
29191
|
// packages/kyrn-judge/src/providers/classifier.ts
|
|
29153
29192
|
var text2 = (value) => value === null || value === void 0 ? "" : typeof value === "string" ? value : JSON.stringify(value);
|
|
29154
29193
|
function toWire(question) {
|
|
@@ -29688,7 +29727,8 @@ var DEFAULT_TIMEOUT_MS2 = {
|
|
|
29688
29727
|
var KEYS_FOR_ELSEWHERE = /* @__PURE__ */ new Set([
|
|
29689
29728
|
"MU_JUDGE_OPENROUTER_API_KEY",
|
|
29690
29729
|
"MU_JUDGE_CUSTOM_API_KEY",
|
|
29691
|
-
"MU_JUDGE_CLM_API_KEY"
|
|
29730
|
+
"MU_JUDGE_CLM_API_KEY",
|
|
29731
|
+
"MU_JUDGE_MUDE_KEY"
|
|
29692
29732
|
]);
|
|
29693
29733
|
function resolveJudgeConfig(name, config) {
|
|
29694
29734
|
if (name.startsWith("llm:")) return { type: "llm", model: name.slice("llm:".length) };
|
|
@@ -30003,11 +30043,10 @@ var KyrnRuntime = class {
|
|
|
30003
30043
|
* again. Undefined before a turn has chosen, or while the decision is off.
|
|
30004
30044
|
*/
|
|
30005
30045
|
capabilitiesOpen;
|
|
30006
|
-
/**
|
|
30007
|
-
|
|
30008
|
-
|
|
30009
|
-
|
|
30010
|
-
judgeParallel;
|
|
30046
|
+
/** The judges in use, in order: the configured tiers, or what `/mu judge` switched to. */
|
|
30047
|
+
tiers;
|
|
30048
|
+
/** Decisions answered by their own judges (`routes` in mu.json, `/mu route`). */
|
|
30049
|
+
routes = /* @__PURE__ */ new Map();
|
|
30011
30050
|
latestCtx;
|
|
30012
30051
|
firstUserMessage = "";
|
|
30013
30052
|
turnStartListeners = [];
|
|
@@ -30022,7 +30061,7 @@ var KyrnRuntime = class {
|
|
|
30022
30061
|
this.pi = pi;
|
|
30023
30062
|
this.config = config;
|
|
30024
30063
|
if (problem) this.problems.push(problem);
|
|
30025
|
-
this.
|
|
30064
|
+
this.tiers = config.tiers;
|
|
30026
30065
|
const sessionLedger = {
|
|
30027
30066
|
append: (record4) => {
|
|
30028
30067
|
pi.appendEntry(LEDGER_ENTRY_TYPE, record4);
|
|
@@ -30053,6 +30092,8 @@ var KyrnRuntime = class {
|
|
|
30053
30092
|
route(specId, tiers) {
|
|
30054
30093
|
const before = this.problems.length;
|
|
30055
30094
|
this.engine.setJudgeFor(specId, tiers.length > 0 ? this.buildConfiguredJudge(tiers) : void 0);
|
|
30095
|
+
if (tiers.length > 0) this.routes.set(specId, tiers);
|
|
30096
|
+
else this.routes.delete(specId);
|
|
30056
30097
|
return this.problems.slice(before);
|
|
30057
30098
|
}
|
|
30058
30099
|
buildConfiguredJudge(tiers) {
|
|
@@ -30071,10 +30112,40 @@ var KyrnRuntime = class {
|
|
|
30071
30112
|
this.problems.push(...built.problems);
|
|
30072
30113
|
return built.judge;
|
|
30073
30114
|
}
|
|
30115
|
+
/**
|
|
30116
|
+
* True when the first judge answers concurrent calls concurrently (a hosted model). The local
|
|
30117
|
+
* sidecar answers one at a time, and there the work of a turn is best asked in order of importance.
|
|
30118
|
+
*/
|
|
30119
|
+
get judgeParallel() {
|
|
30120
|
+
return resolveJudgeConfig(this.tiers[0] ?? "", this.config)?.type !== "local";
|
|
30121
|
+
}
|
|
30122
|
+
/**
|
|
30123
|
+
* Whether the judge that answers `specId`'s questions takes many of them in one request. That is the first of its
|
|
30124
|
+
* judges (its route, else the tiers) trusted on `capability`: the cascade passes over the others. With `laya,jev`,
|
|
30125
|
+
* Jev answers `screen` questions, which Laya is not trusted on, so they go in batches; only a local judge that
|
|
30126
|
+
* answers them itself, whose window holds one, is asked one at a time.
|
|
30127
|
+
*/
|
|
30128
|
+
answersInBatches(specId, capability) {
|
|
30129
|
+
for (const judge of this.judgesFor(specId)) {
|
|
30130
|
+
if (isTrusted(judge.profile, capability)) return judge.type !== "local";
|
|
30131
|
+
}
|
|
30132
|
+
return this.judgeParallel;
|
|
30133
|
+
}
|
|
30134
|
+
/**
|
|
30135
|
+
* Whether any judge of `specId` (its route, else the tiers) is trusted on `capability`. When none is, the cascade
|
|
30136
|
+
* gives each such question a neutral answer without asking.
|
|
30137
|
+
*/
|
|
30138
|
+
trusts(specId, capability) {
|
|
30139
|
+
return this.judgesFor(specId).some((judge) => isTrusted(judge.profile, capability));
|
|
30140
|
+
}
|
|
30141
|
+
judgesFor(specId) {
|
|
30142
|
+
return (this.routes.get(specId) ?? this.tiers).flatMap((name) => resolveJudgeConfig(name, this.config) ?? []);
|
|
30143
|
+
}
|
|
30074
30144
|
/** Switch the decision model at runtime, e.g. `/mu judge laya,jev`. */
|
|
30075
30145
|
useJudges(tiers) {
|
|
30076
30146
|
const before = this.problems.length;
|
|
30077
30147
|
this.engine.setJudge(this.buildConfiguredJudge(tiers));
|
|
30148
|
+
this.tiers = tiers;
|
|
30078
30149
|
return this.problems.slice(before);
|
|
30079
30150
|
}
|
|
30080
30151
|
/**
|
|
@@ -30236,6 +30307,7 @@ var KyrnRuntime = class {
|
|
|
30236
30307
|
const current = clip(this.turn.userMessage, 200);
|
|
30237
30308
|
return { goal, currentSubgoal: current && current !== goal ? current : void 0 };
|
|
30238
30309
|
}
|
|
30310
|
+
/** Sets mu's line in the footer; undefined takes it down. */
|
|
30239
30311
|
status(text7) {
|
|
30240
30312
|
const ctx = this.latestCtx;
|
|
30241
30313
|
if (ctx?.hasUI) ctx.ui.setStatus(STATUS_KEY, text7);
|
|
@@ -30414,8 +30486,13 @@ function registerAdmission(runtime) {
|
|
|
30414
30486
|
batchChunks: 16,
|
|
30415
30487
|
/** Requests in flight at once: batches for a hosted judge, chunks for the local sidecar. */
|
|
30416
30488
|
concurrency: 4,
|
|
30417
|
-
/**
|
|
30418
|
-
|
|
30489
|
+
/**
|
|
30490
|
+
* A verdict later than this is not worth holding the result for: the output goes in whole, the verdict is only
|
|
30491
|
+
* recorded. In the owner's sessions 35 of 42 verdicts came within 2 s, the one that dropped anything in 0.4 s,
|
|
30492
|
+
* and the 3 that came between 2 and 4 s dropped nothing, while 19 of 57 results waited the whole 4 s for a
|
|
30493
|
+
* verdict that came later or never.
|
|
30494
|
+
*/
|
|
30495
|
+
waitMs: 2e3,
|
|
30419
30496
|
/**
|
|
30420
30497
|
* Tools whose output is never judged: file contents and pages the model asked for, and sub-agent reports the bees
|
|
30421
30498
|
* already shaped.
|
|
@@ -30443,7 +30520,7 @@ function registerAdmission(runtime) {
|
|
|
30443
30520
|
})
|
|
30444
30521
|
);
|
|
30445
30522
|
const judgeChunks = async (call, middle, signal) => {
|
|
30446
|
-
if (!runtime.
|
|
30523
|
+
if (!runtime.answersInBatches(toolAdmission.id, "screen")) {
|
|
30447
30524
|
const decisions2 = await runtime.engine.decideMany(
|
|
30448
30525
|
toolAdmission,
|
|
30449
30526
|
middle.map((chunk) => ({ call, chunk })),
|
|
@@ -32007,7 +32084,7 @@ function isReadOnlyChain(command, powershell = false) {
|
|
|
32007
32084
|
}
|
|
32008
32085
|
function isMutatingCall(toolName, input) {
|
|
32009
32086
|
if (READ_ONLY_TOOLS.has(toolName)) return false;
|
|
32010
|
-
if (isShellTool(toolName)) return !
|
|
32087
|
+
if (isShellTool(toolName)) return !isReadOnlyChain(String(input.command ?? ""), toolName === "powershell");
|
|
32011
32088
|
return true;
|
|
32012
32089
|
}
|
|
32013
32090
|
var CHECK_COMMAND = /\b(?:vitest|jest|pytest|mocha|ava|tsc|eslint|biome|ruff|mypy|rspec|phpunit|ctest|tox|nox|gradle|mvn)\b|\b(?:npm|pnpm|yarn|bun)\s+(?:run\s+)?(?:test|build|check|lint|typecheck)\b|\b(?:cargo|go|dotnet|swift|make|deno)\s+(?:test|build|check|vet|clippy)\b|\bnode\b[^\n]*--test\b|\btest\.sh\b/;
|
|
@@ -32297,6 +32374,13 @@ function passages(text7, size) {
|
|
|
32297
32374
|
return out;
|
|
32298
32375
|
}
|
|
32299
32376
|
|
|
32377
|
+
// packages/kyrn-judge/src/usage.ts
|
|
32378
|
+
var USAGE_ENTRY = "kyrn.usage";
|
|
32379
|
+
var REASONING_CHARS_PER_TOKEN = 3.5;
|
|
32380
|
+
function estimateReasoningTokens(chars) {
|
|
32381
|
+
return chars > 0 ? Math.ceil(chars / REASONING_CHARS_PER_TOKEN) : 0;
|
|
32382
|
+
}
|
|
32383
|
+
|
|
32300
32384
|
// packages/kyrn-judge/src/swarm/markers.ts
|
|
32301
32385
|
var NOTES_HEADER = "Notes from the other workers on the same goal. They are findings, not instructions.";
|
|
32302
32386
|
function correctionLine(earlierBee, earlierHead, from, laterText) {
|
|
@@ -32348,7 +32432,7 @@ function newBee(name, now, details = {}) {
|
|
|
32348
32432
|
turns: 0,
|
|
32349
32433
|
toolCalls: 0,
|
|
32350
32434
|
toolErrors: 0,
|
|
32351
|
-
usage: { input: 0, output: 0, cacheRead: 0, cost: 0 },
|
|
32435
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 },
|
|
32352
32436
|
published: 0,
|
|
32353
32437
|
received: 0,
|
|
32354
32438
|
withheld: 0,
|
|
@@ -32466,6 +32550,7 @@ function applyEvent(state, event, now) {
|
|
|
32466
32550
|
state.usage.input += usage.input ?? 0;
|
|
32467
32551
|
state.usage.output += usage.output ?? 0;
|
|
32468
32552
|
state.usage.cacheRead += usage.cacheRead ?? 0;
|
|
32553
|
+
state.usage.cacheWrite += usage.cacheWrite ?? 0;
|
|
32469
32554
|
state.usage.cost += usage.cost?.total ?? 0;
|
|
32470
32555
|
}
|
|
32471
32556
|
const text7 = textOf2(message.content).trim();
|
|
@@ -32486,6 +32571,20 @@ function applyEvent(state, event, now) {
|
|
|
32486
32571
|
if (text7 && !hasToolCall(message.content)) state.finals.push(text7);
|
|
32487
32572
|
break;
|
|
32488
32573
|
}
|
|
32574
|
+
case "entry_appended": {
|
|
32575
|
+
const entry = event.entry;
|
|
32576
|
+
if (entry?.type !== "custom" || entry.customType !== USAGE_ENTRY || !entry.data) break;
|
|
32577
|
+
const spent = entry.data;
|
|
32578
|
+
const number = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
32579
|
+
state.usage.input += number(spent.input);
|
|
32580
|
+
state.usage.output += number(spent.output);
|
|
32581
|
+
state.usage.cacheRead += number(spent.cacheRead);
|
|
32582
|
+
state.usage.cacheWrite += number(spent.cacheWrite);
|
|
32583
|
+
state.usage.cost += number(spent.cost);
|
|
32584
|
+
if (spent.estimated)
|
|
32585
|
+
state.usage.estimatedOutput = (state.usage.estimatedOutput ?? 0) + number(spent.estimatedOutput);
|
|
32586
|
+
break;
|
|
32587
|
+
}
|
|
32489
32588
|
case "tool_execution_start": {
|
|
32490
32589
|
const name = event.toolName ?? "tool";
|
|
32491
32590
|
state.toolCalls++;
|
|
@@ -32592,6 +32691,26 @@ var setError = (bee, reason, coded) => {
|
|
|
32592
32691
|
bee.errorCode = coded?.code;
|
|
32593
32692
|
bee.errorParams = coded?.params;
|
|
32594
32693
|
};
|
|
32694
|
+
function subagentUsage(kind, bee) {
|
|
32695
|
+
if (bee.startedAt === void 0) return void 0;
|
|
32696
|
+
const { input, output, cacheRead, cacheWrite, cost, estimatedOutput } = bee.usage;
|
|
32697
|
+
return {
|
|
32698
|
+
source: "subagent",
|
|
32699
|
+
kind,
|
|
32700
|
+
name: bee.name,
|
|
32701
|
+
...bee.role ? { role: bee.role } : {},
|
|
32702
|
+
...bee.model ? { model: bee.model } : {},
|
|
32703
|
+
input,
|
|
32704
|
+
output,
|
|
32705
|
+
cacheRead,
|
|
32706
|
+
cacheWrite,
|
|
32707
|
+
cost,
|
|
32708
|
+
...estimatedOutput ? { estimated: true, estimatedOutput } : {},
|
|
32709
|
+
...bee.status === "done" ? {} : { partial: true },
|
|
32710
|
+
status: bee.status,
|
|
32711
|
+
turns: bee.turns
|
|
32712
|
+
};
|
|
32713
|
+
}
|
|
32595
32714
|
function controlPath(dir, index) {
|
|
32596
32715
|
return join8(dir, "control", `bee-${index}.json`);
|
|
32597
32716
|
}
|
|
@@ -32611,6 +32730,8 @@ var SwarmRun = class {
|
|
|
32611
32730
|
onChange;
|
|
32612
32731
|
/** Hive only: the state of the shared board, read fresh for every snapshot. */
|
|
32613
32732
|
board;
|
|
32733
|
+
/** Called once for each bee that started, when it has ended however it ended. */
|
|
32734
|
+
onBeeEnd;
|
|
32614
32735
|
specs;
|
|
32615
32736
|
limits;
|
|
32616
32737
|
controllers;
|
|
@@ -32850,6 +32971,10 @@ ${draft.text.trim()}`);
|
|
|
32850
32971
|
failure = error;
|
|
32851
32972
|
}
|
|
32852
32973
|
this.outcomes[index] = this.outcome(index, returned, failure);
|
|
32974
|
+
try {
|
|
32975
|
+
this.onBeeEnd?.(bee);
|
|
32976
|
+
} catch {
|
|
32977
|
+
}
|
|
32853
32978
|
this.busy--;
|
|
32854
32979
|
this.onChange?.();
|
|
32855
32980
|
}
|
|
@@ -35350,6 +35475,7 @@ ${result.page.text.slice(0, textChars)}`
|
|
|
35350
35475
|
}
|
|
35351
35476
|
|
|
35352
35477
|
// packages/kyrn-judge/src/extension/features/catalog.ts
|
|
35478
|
+
var import_pi_coding_agent2 = __toESM(require_pi_coding_agent(), 1);
|
|
35353
35479
|
var import_typebox3 = __toESM(require_typebox(), 1);
|
|
35354
35480
|
|
|
35355
35481
|
// packages/kyrn-judge/src/decisions/capability-disclosure.ts
|
|
@@ -35471,14 +35597,39 @@ var UNATTENDED_HIDDEN = [
|
|
|
35471
35597
|
function line(capability) {
|
|
35472
35598
|
return `- ${capability.id} \xB7 ${capability.title}: ${capability.description}`;
|
|
35473
35599
|
}
|
|
35600
|
+
var KINDS3 = ["mcp", "pack", "lsp", "tool"];
|
|
35601
|
+
var KIND_NAMES = {
|
|
35602
|
+
mcp: "MCP server",
|
|
35603
|
+
pack: "pack",
|
|
35604
|
+
lsp: "language server",
|
|
35605
|
+
tool: "tool"
|
|
35606
|
+
};
|
|
35607
|
+
var LISTED = 20;
|
|
35608
|
+
function installedLine(capabilities) {
|
|
35609
|
+
const judged = capabilities.filter((capability) => capability.exposure === "judged").sort((a, b) => KINDS3.indexOf(a.kind) - KINDS3.indexOf(b.kind));
|
|
35610
|
+
if (judged.length === 0) return void 0;
|
|
35611
|
+
const shown2 = judged.slice(0, LISTED).map((capability) => `${capability.id} (${KIND_NAMES[capability.kind]})`);
|
|
35612
|
+
const more = judged.length - shown2.length;
|
|
35613
|
+
return `Installed: ${shown2.join(", ")}${more > 0 ? `, and ${more} more` : ""}.`;
|
|
35614
|
+
}
|
|
35615
|
+
function hidesNothing(runtime) {
|
|
35616
|
+
return !runtime.options("catalog", { enabled: true }).enabled;
|
|
35617
|
+
}
|
|
35474
35618
|
function registerCatalog(runtime) {
|
|
35475
35619
|
const options = runtime.options("catalog", {
|
|
35476
35620
|
enabled: true,
|
|
35477
|
-
|
|
35621
|
+
/** Counted from the arrival of the message, as preflight's wait is. */
|
|
35622
|
+
waitMs: 3e3,
|
|
35478
35623
|
/** Ask which capabilities a task needs in a `mu --print` or json run too. Off: they stay hidden, and nothing waits. */
|
|
35479
35624
|
askUnattended: false,
|
|
35480
35625
|
/** Tools and skills, by name, left out of the request in a `mu --print` or json run. */
|
|
35481
35626
|
unattendedHidden: UNATTENDED_HIDDEN,
|
|
35627
|
+
/**
|
|
35628
|
+
* Keep `find_capability` in such a run when an MCP server that can be hidden is installed. Nobody asks the judge
|
|
35629
|
+
* there, so without it the server can't be reached. Packs alone don't keep it: a benchmark run has no server, and
|
|
35630
|
+
* its requests stay as lean as they were.
|
|
35631
|
+
*/
|
|
35632
|
+
unattendedFindWithMcp: true,
|
|
35482
35633
|
/** Sub-agents open the capabilities this session has open instead of asking the judge again. */
|
|
35483
35634
|
subagentsInherit: true
|
|
35484
35635
|
});
|
|
@@ -35488,15 +35639,15 @@ function registerCatalog(runtime) {
|
|
|
35488
35639
|
const leftOut = /* @__PURE__ */ new Set();
|
|
35489
35640
|
const inherited = inheritedNames(CAPABILITIES_OPEN_ENV);
|
|
35490
35641
|
let inheritedOpened = false;
|
|
35491
|
-
const asks = () => !inherited && (options.askUnattended || !isUnattended(runtime.ctx));
|
|
35642
|
+
const asks = () => runtime.mode(capabilityDisclosure.id) !== "off" && !inherited && (options.askUnattended || !isUnattended(runtime.ctx));
|
|
35492
35643
|
let chosen = false;
|
|
35493
35644
|
if (options.subagentsInherit) {
|
|
35494
|
-
runtime.capabilitiesOpen = () => chosen
|
|
35645
|
+
runtime.capabilitiesOpen = () => chosen ? catalog.history().map((record4) => record4.id) : void 0;
|
|
35495
35646
|
}
|
|
35496
35647
|
const disclose = (words2, candidates, signal) => runtime.engine.decide(capabilityDisclosure, { userMessage: words2, capabilities: candidates }, { signal });
|
|
35497
35648
|
let early;
|
|
35498
35649
|
runtime.atTurnStart((words2) => {
|
|
35499
|
-
if (
|
|
35650
|
+
if (!asks()) return;
|
|
35500
35651
|
const candidates = catalog.hidden();
|
|
35501
35652
|
if (candidates.length === 0) return;
|
|
35502
35653
|
const decision = disclose(words2, candidates);
|
|
@@ -35506,8 +35657,8 @@ function registerCatalog(runtime) {
|
|
|
35506
35657
|
});
|
|
35507
35658
|
const withheld = /* @__PURE__ */ new Set();
|
|
35508
35659
|
const released = /* @__PURE__ */ new Set();
|
|
35509
|
-
const applyLoadout = (
|
|
35510
|
-
const hidden = new Set(
|
|
35660
|
+
const applyLoadout = () => {
|
|
35661
|
+
const hidden = new Set(catalog.hiddenTools());
|
|
35511
35662
|
for (const name of leftOut) hidden.add(name);
|
|
35512
35663
|
const active2 = new Set(pi.getActiveTools());
|
|
35513
35664
|
for (const tool of hidden) {
|
|
@@ -35527,15 +35678,27 @@ function registerCatalog(runtime) {
|
|
|
35527
35678
|
runtime.present("capability.opened", { id, by, title: capability?.title, tools: capability?.tools });
|
|
35528
35679
|
return capability;
|
|
35529
35680
|
};
|
|
35681
|
+
let described = false;
|
|
35682
|
+
let findReachesMcp = false;
|
|
35530
35683
|
pi.on(
|
|
35531
35684
|
"before_agent_start",
|
|
35532
35685
|
failOpen(async (event, ctx) => {
|
|
35533
35686
|
runtime.touch(ctx);
|
|
35687
|
+
if (!described) {
|
|
35688
|
+
described = true;
|
|
35689
|
+
findReachesMcp = options.unattendedFindWithMcp && catalog.list().some((capability) => capability.kind === "mcp" && capability.exposure === "judged");
|
|
35690
|
+
const installed = installedLine(catalog.list());
|
|
35691
|
+
if (installed)
|
|
35692
|
+
pi.registerTool({ ...findCapability, description: `${findCapability.description} ${installed}` });
|
|
35693
|
+
}
|
|
35534
35694
|
if (isUnattended(ctx)) {
|
|
35535
35695
|
const called = event.messageType === "user" ? /^\/([^\s:]+)/.exec(event.prompt)?.[1] : void 0;
|
|
35536
35696
|
if (called && unattendedHidden.includes(called)) released.add(called);
|
|
35537
35697
|
leftOut.clear();
|
|
35538
|
-
for (const name of unattendedHidden)
|
|
35698
|
+
for (const name of unattendedHidden) {
|
|
35699
|
+
if (released.has(name) || name === "find_capability" && findReachesMcp) continue;
|
|
35700
|
+
leftOut.add(name);
|
|
35701
|
+
}
|
|
35539
35702
|
if (event.systemPromptOptions.skills) {
|
|
35540
35703
|
event.systemPromptOptions.skills = event.systemPromptOptions.skills.filter(
|
|
35541
35704
|
(skill) => !leftOut.has(skill.name)
|
|
@@ -35550,10 +35713,6 @@ function registerCatalog(runtime) {
|
|
|
35550
35713
|
applyLoadout();
|
|
35551
35714
|
return void 0;
|
|
35552
35715
|
}
|
|
35553
|
-
if (runtime.mode(capabilityDisclosure.id) === "off") {
|
|
35554
|
-
applyLoadout(true);
|
|
35555
|
-
return void 0;
|
|
35556
|
-
}
|
|
35557
35716
|
if (event.messageType === "custom") {
|
|
35558
35717
|
applyLoadout();
|
|
35559
35718
|
return void 0;
|
|
@@ -35590,7 +35749,7 @@ ${opened.map((capability) => `${line(capability)}${capability.tools.length > 0 ?
|
|
|
35590
35749
|
};
|
|
35591
35750
|
})
|
|
35592
35751
|
);
|
|
35593
|
-
|
|
35752
|
+
const findCapability = (0, import_pi_coding_agent2.defineTool)({
|
|
35594
35753
|
name: "find_capability",
|
|
35595
35754
|
label: "Find capability",
|
|
35596
35755
|
description: "List installed capabilities that are not in your tool list yet (debugger, structural search, MCP servers, review and commit helpers and more), or open one by id. Use it when a task needs a tool you do not have.",
|
|
@@ -35645,6 +35804,7 @@ Open one with find_capability({ open: "<id>" }).`;
|
|
|
35645
35804
|
};
|
|
35646
35805
|
}
|
|
35647
35806
|
});
|
|
35807
|
+
pi.registerTool(findCapability);
|
|
35648
35808
|
pi.registerCommand("capabilities", {
|
|
35649
35809
|
description: say({
|
|
35650
35810
|
zh: "\u88C5\u4E86\u54EA\u4E9B\u80FD\u529B\u3001\u8FD9\u6B21\u6253\u5F00\u4E86\u54EA\u4E9B\uFF1A/capabilities \u67E5\u770B\uFF0C/capabilities open <ID> \u6253\u5F00",
|
|
@@ -36411,6 +36571,11 @@ function registerCheckpoint(runtime, roots, deps = {}) {
|
|
|
36411
36571
|
propose: true,
|
|
36412
36572
|
/** How long a proposal waits for an answer before the run carries on. 0 waits forever. */
|
|
36413
36573
|
confirmSeconds: 120,
|
|
36574
|
+
/**
|
|
36575
|
+
* How long the end of a turn waits for `turn.rewind`'s verdict; a later one changes nothing. On Terminal-Bench
|
|
36576
|
+
* 2.1 every verdict came in 0.2-1.6 s.
|
|
36577
|
+
*/
|
|
36578
|
+
rewindWaitMs: 3e3,
|
|
36414
36579
|
/** Take checkpoints in a `mu --print` or json run too, for a session resumed later in the terminal. */
|
|
36415
36580
|
unattended: false
|
|
36416
36581
|
});
|
|
@@ -36430,6 +36595,7 @@ function registerCheckpoint(runtime, roots, deps = {}) {
|
|
|
36430
36595
|
let turn = newTurn(0);
|
|
36431
36596
|
let pending;
|
|
36432
36597
|
let lastAgentTree;
|
|
36598
|
+
let rescan;
|
|
36433
36599
|
const calls = /* @__PURE__ */ new Map();
|
|
36434
36600
|
let chain = Promise.resolve();
|
|
36435
36601
|
let busy = 0;
|
|
@@ -36572,11 +36738,23 @@ function registerCheckpoint(runtime, roots, deps = {}) {
|
|
|
36572
36738
|
}
|
|
36573
36739
|
if (call.mutating && store && turn.checkpoint) {
|
|
36574
36740
|
const opened = store;
|
|
36575
|
-
|
|
36741
|
+
rescan = exclusive(async () => {
|
|
36742
|
+
lastAgentTree = await scan(opened, limits).then(
|
|
36743
|
+
(scanned) => scanned.tree,
|
|
36744
|
+
() => void 0
|
|
36745
|
+
);
|
|
36746
|
+
});
|
|
36576
36747
|
}
|
|
36577
36748
|
return void 0;
|
|
36578
36749
|
})
|
|
36579
36750
|
);
|
|
36751
|
+
pi.on(
|
|
36752
|
+
"agent_end",
|
|
36753
|
+
failOpen(async () => {
|
|
36754
|
+
if (rescan) await within(rescan, 3e3);
|
|
36755
|
+
return void 0;
|
|
36756
|
+
})
|
|
36757
|
+
);
|
|
36580
36758
|
runtime.onTrouble((kind, detail) => {
|
|
36581
36759
|
turn.troubles++;
|
|
36582
36760
|
if (turn.troubles >= 2 && turn.trigger === void 0) {
|
|
@@ -36794,18 +36972,20 @@ ${describePlan(plan2)}`, [...Object.keys(SCOPES), "Cancel"]);
|
|
|
36794
36972
|
turn.trigger = void 0;
|
|
36795
36973
|
turn.triggerCode = void 0;
|
|
36796
36974
|
turn.asked++;
|
|
36797
|
-
const
|
|
36798
|
-
|
|
36799
|
-
|
|
36800
|
-
|
|
36801
|
-
|
|
36802
|
-
|
|
36803
|
-
|
|
36804
|
-
|
|
36805
|
-
|
|
36806
|
-
|
|
36975
|
+
const state = {
|
|
36976
|
+
goal: runtime.taskFrame()?.goal ?? checkpoint?.label ?? turnStart(ctx).label,
|
|
36977
|
+
recentSteps: turn.steps,
|
|
36978
|
+
trigger,
|
|
36979
|
+
editsSinceCheckpoint: turn.edits,
|
|
36980
|
+
lastCheckFailed: turn.lastCheckFailed
|
|
36981
|
+
};
|
|
36982
|
+
const decision = await askWithin(
|
|
36983
|
+
(signal) => runtime.engine.decide(turnRewind, state, {
|
|
36984
|
+
signal: ctx.signal ? AbortSignal.any([signal, ctx.signal]) : signal
|
|
36985
|
+
}),
|
|
36986
|
+
options.rewindWaitMs
|
|
36807
36987
|
);
|
|
36808
|
-
if (decision
|
|
36988
|
+
if (decision?.source !== "judge" || decision.outcome !== "propose") return void 0;
|
|
36809
36989
|
turn.proposed = true;
|
|
36810
36990
|
const stepBack = () => pi.sendMessage(
|
|
36811
36991
|
{
|
|
@@ -36972,13 +37152,13 @@ The agent will then start over from your request, with a note about what didn't
|
|
|
36972
37152
|
}
|
|
36973
37153
|
|
|
36974
37154
|
// packages/kyrn-judge/src/extension/features/commands.ts
|
|
36975
|
-
var
|
|
37155
|
+
var import_pi_coding_agent5 = __toESM(require_pi_coding_agent(), 1);
|
|
36976
37156
|
import { existsSync as existsSync7 } from "node:fs";
|
|
36977
37157
|
import { join as join18 } from "node:path";
|
|
36978
37158
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
36979
37159
|
|
|
36980
37160
|
// packages/kyrn-judge/src/extension/agents.ts
|
|
36981
|
-
var
|
|
37161
|
+
var import_pi_coding_agent3 = __toESM(require_pi_coding_agent(), 1);
|
|
36982
37162
|
import { readdirSync as readdirSync3, readFileSync as readFileSync7 } from "node:fs";
|
|
36983
37163
|
import { join as join16 } from "node:path";
|
|
36984
37164
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -36990,7 +37170,7 @@ function parseToolList(value) {
|
|
|
36990
37170
|
}
|
|
36991
37171
|
var NAME = /^[a-z][a-z0-9_-]{0,31}$/;
|
|
36992
37172
|
function parseAgent(content, source, filePath) {
|
|
36993
|
-
const { frontmatter, body } = (0,
|
|
37173
|
+
const { frontmatter, body } = (0, import_pi_coding_agent3.parseFrontmatter)(content);
|
|
36994
37174
|
const { name, description, model, thinking } = frontmatter;
|
|
36995
37175
|
if (typeof name !== "string" || !NAME.test(name) || name === "other") return void 0;
|
|
36996
37176
|
if (typeof description !== "string" || !description.trim()) return void 0;
|
|
@@ -37091,13 +37271,13 @@ function promptsFor(dir, wording, root) {
|
|
|
37091
37271
|
}
|
|
37092
37272
|
|
|
37093
37273
|
// packages/kyrn-judge/src/extension/features/welcome.ts
|
|
37094
|
-
var
|
|
37274
|
+
var import_pi_coding_agent4 = __toESM(require_pi_coding_agent(), 1);
|
|
37095
37275
|
var import_pi_tui = __toESM(require_pi_tui(), 1);
|
|
37096
37276
|
import { readFileSync as readFileSync9 } from "node:fs";
|
|
37097
37277
|
import { homedir as homedir4 } from "node:os";
|
|
37098
37278
|
import { basename as basename3 } from "node:path";
|
|
37099
37279
|
var WORDMARK = ["\u2588 \u2588 ", "\u2588\u2584\u2584\u2588\u2584 ", "\u2588 "];
|
|
37100
|
-
function readVersions(judgeRoot, fallbackPi =
|
|
37280
|
+
function readVersions(judgeRoot, fallbackPi = import_pi_coding_agent4.VERSION) {
|
|
37101
37281
|
const read2 = (path) => {
|
|
37102
37282
|
try {
|
|
37103
37283
|
const parsed = JSON.parse(readFileSync9(new URL(path, judgeRoot), "utf8"));
|
|
@@ -37215,7 +37395,7 @@ function leanIdentity(pointer) {
|
|
|
37215
37395
|
].join("\n");
|
|
37216
37396
|
}
|
|
37217
37397
|
function leanDocs() {
|
|
37218
|
-
return `Docs of mu and pi, for a task about them only: ${(0,
|
|
37398
|
+
return `Docs of mu and pi, for a task about them only: ${(0, import_pi_coding_agent4.getReadmePath)()} (more in docs/ beside it)`;
|
|
37219
37399
|
}
|
|
37220
37400
|
function registerWelcome(runtime) {
|
|
37221
37401
|
const options = runtime.options("welcome", {
|
|
@@ -37276,9 +37456,9 @@ function registerWelcome(runtime) {
|
|
|
37276
37456
|
cwd: current?.cwd ?? ctx.cwd,
|
|
37277
37457
|
expanded,
|
|
37278
37458
|
keys: {
|
|
37279
|
-
expand: (0,
|
|
37280
|
-
model: (0,
|
|
37281
|
-
thinking: (0,
|
|
37459
|
+
expand: (0, import_pi_coding_agent4.keyText)("app.tools.expand"),
|
|
37460
|
+
model: (0, import_pi_coding_agent4.keyText)("app.model.select"),
|
|
37461
|
+
thinking: (0, import_pi_coding_agent4.keyText)("app.thinking.cycle")
|
|
37282
37462
|
}
|
|
37283
37463
|
},
|
|
37284
37464
|
width,
|
|
@@ -37313,7 +37493,7 @@ var helpZh = () => `mu ${VERSIONS.mu} \xB7 \u5148\u5224\u65AD\u518D\u52A8\u624B\
|
|
|
37313
37493
|
|
|
37314
37494
|
\u5224\u65AD\u5C42
|
|
37315
37495
|
\u4F60\u7684\u6BCF\u6761\u6D88\u606F\u90FD\u5148\u4EA4\u7ED9\u5224\u5B9A\u5668\u8BFB\uFF1A\u8BFB\u7684\u65F6\u5019\u6D88\u606F\u505C\u5728\u8F93\u5165\u6846\u4E0A\u65B9\uFF08\u6309 esc \u53EF\u8DF3\u8FC7\u7B49\u5F85\uFF09\uFF0C
|
|
37316
|
-
\u5224\u5B9A\u7ED3\u679C\u7559\u5728\u5BF9\u8BDD\u91CC\u8FD9\u6761\u6D88\u606F\u4E0B\u9762\u3002${(0,
|
|
37496
|
+
\u5224\u5B9A\u7ED3\u679C\u7559\u5728\u5BF9\u8BDD\u91CC\u8FD9\u6761\u6D88\u606F\u4E0B\u9762\u3002${(0, import_pi_coding_agent5.keyText)("app.tools.expand")} \u53EF\u4EE5\u770B\u6BCF\u4E2A\u5224\u5B9A\u80CC\u540E\u7684\u5168\u90E8\u56DE\u7B54\u3002
|
|
37317
37497
|
/mu judge <\u5224\u5B9A\u5668>\uFF1A\u7531\u54EA\u4E9B\u6A21\u578B\u6765\u5224\u5B9A\u3001\u6309\u4EC0\u4E48\u987A\u5E8F\uFF0C\u6BD4\u5982 laya | laya,jev | jev-opencode-free | clm | classifier:<\u63D0\u4F9B\u5546>/<\u6A21\u578B> | llm:<\u63D0\u4F9B\u5546>/<\u6A21\u578B>
|
|
37318
37498
|
/mu route <\u5224\u5B9A\u70B9> <\u5224\u5B9A\u5668|default>\uFF1A\u8BA9\u67D0\u4E00\u4E2A\u5224\u5B9A\u70B9\u7528\u81EA\u5DF1\u7684\u5224\u5B9A\u5668\uFF0C\u6BD4\u5982 browser.step llm:openai/gpt-5.6-luna
|
|
37319
37499
|
/mu mode <\u5224\u5B9A\u70B9|default> <off|shadow|active>\uFF1Aoff \u5173\u95ED\uFF0Cshadow \u5F71\u5B50\uFF08\u53EA\u8BB0\u5F55\uFF0C\u4E0D\u8D77\u4F5C\u7528\uFF09\uFF0Cactive \u751F\u6548
|
|
@@ -37324,7 +37504,7 @@ var helpZh = () => `mu ${VERSIONS.mu} \xB7 \u5148\u5224\u65AD\u518D\u52A8\u624B\
|
|
|
37324
37504
|
/board \u67E5\u770B\uFF0C/board model \u6362\u4E2A\u6A21\u578B\u6765\u8BB2
|
|
37325
37505
|
/permissions [\u6A21\u5F0F]\uFF1Amu \u4E0D\u95EE\u4F60\u5C31\u80FD\u505A\u591A\u5C11\u4E8B\uFF0C\u53EF\u9009 full\uFF08\u5B8C\u5168\u8BBF\u95EE\uFF09\u3001judge\uFF08\u5224\u5B9A\u6A21\u5F0F\uFF0C\u7531\u5224\u5B9A\u5668\u66FF\u4F60\u6279\uFF0C
|
|
37326
37506
|
\u62FF\u4E0D\u51C6\u624D\u95EE\u4F60\uFF09\u3001ask\uFF08\u6700\u5C0F\u6743\u9650\uFF0C\u9664\u4E86\u8BFB\u90FD\u8981\u95EE\u4F60\uFF09
|
|
37327
|
-
/capabilities\uFF1A\u88C5\u4E86\u54EA\u4E9B\u80FD\u529B\uFF0C\
|
|
37507
|
+
/capabilities\uFF1A\u88C5\u4E86\u54EA\u4E9B\u80FD\u529B\uFF0C\u8FD9\u6B21\u6253\u5F00\u4E86\u54EA\u4E9B\uFF1B/capabilities open <ID> \u6253\u5F00\u4E00\u4E2A
|
|
37328
37508
|
/ledger [\u6761\u6570]\uFF1A\u6700\u8FD1\u51E0\u6761\u5224\u5B9A\u548C\u7528\u65F6
|
|
37329
37509
|
/remember <\u7ECF\u9A8C>\uFF1A\u8BB0\u4E00\u6761\u7ECF\u9A8C\uFF0C\u4EE5\u540E\u7684\u4F1A\u8BDD\u90FD\u4F1A\u7528\u4E0A
|
|
37330
37510
|
/lessons [all]\uFF1A\u8FD9\u4E2A\u9879\u76EE\u7684\u7ECF\u9A8C\uFF0C\u53EC\u56DE\u548C\u7167\u505A\u4E86\u51E0\u6B21\uFF1Ball \u8FDE\u5230\u5904\u9002\u7528\u7684\u548C\u5DF2\u9000\u5F79\u7684\u4E00\u8D77\u5217
|
|
@@ -37371,7 +37551,7 @@ var helpSectionsEn = () => [
|
|
|
37371
37551
|
},
|
|
37372
37552
|
{
|
|
37373
37553
|
title: "Judgment kernel",
|
|
37374
|
-
intro: `The judge reads every message first. While it reads, your message waits above the editor (esc skips the wait); the verdict then appears under your message. ${(0,
|
|
37554
|
+
intro: `The judge reads every message first. While it reads, your message waits above the editor (esc skips the wait); the verdict then appears under your message. ${(0, import_pi_coding_agent5.keyText)("app.tools.expand")} shows the full answers behind a verdict.`,
|
|
37375
37555
|
rows: [
|
|
37376
37556
|
[
|
|
37377
37557
|
"/mu judge <judges>",
|
|
@@ -37396,7 +37576,7 @@ var helpSectionsEn = () => [
|
|
|
37396
37576
|
"/permissions [mode]",
|
|
37397
37577
|
"set how much mu can do without asking: full (Full access), judge (Judge mode: the judge allows what the task clearly needs and asks you about the rest), ask (Ask first: asks before anything but reading)"
|
|
37398
37578
|
],
|
|
37399
|
-
["/capabilities", "show what's installed and what
|
|
37579
|
+
["/capabilities", "show what's installed and what's open for this task; /capabilities open <id> opens one"],
|
|
37400
37580
|
["/ledger [n]", "show the last n verdicts and their latency"],
|
|
37401
37581
|
["/remember <lesson>", "save a lesson for future sessions"],
|
|
37402
37582
|
[
|
|
@@ -37531,11 +37711,12 @@ function registerCommands(runtime, roots) {
|
|
|
37531
37711
|
const status = (ctx) => {
|
|
37532
37712
|
const { stats } = engine;
|
|
37533
37713
|
const { savings } = runtime;
|
|
37534
|
-
const modes = [...engine.
|
|
37714
|
+
const modes = [...engine.overrides()].map(([specId, mode]) => `${specId}=${mode}`).join(" ");
|
|
37535
37715
|
const usage = ctx.getContextUsage();
|
|
37536
37716
|
const lines2 = [
|
|
37537
37717
|
`model: ${modelRef(ctx.model) ?? "none yet"} \xB7 thinking ${pi.getThinkingLevel()}${usage?.percent === void 0 || usage.percent === null ? "" : ` \xB7 context ${Math.round(usage.percent)}%`}`,
|
|
37538
|
-
|
|
37718
|
+
// With every point off no judge is asked, whichever is set up: say so, as the welcome does.
|
|
37719
|
+
`judge: ${!runtime.enabled ? "off" : engine.asksJudge() ? engine.providerId : "off \xB7 every decision point uses its fallback"}`,
|
|
37539
37720
|
...[...engine.routes()].map(([specId, judge]) => ` ${specId} -> ${judge.id}`),
|
|
37540
37721
|
`mode: default=${engine.getMode("*")}${modes ? ` ${modes}` : ""}`,
|
|
37541
37722
|
`calls: ${stats.calls} | failures: ${stats.failures} | abstentions: ${stats.abstentions} | input tokens: ${stats.inputTokens} | probes: ${stats.probes} (${stats.probeInputTokens} input tokens)`,
|
|
@@ -37638,12 +37819,13 @@ function registerCommands(runtime, roots) {
|
|
|
37638
37819
|
handler: async (_args, ctx) => {
|
|
37639
37820
|
runtime.touch(ctx);
|
|
37640
37821
|
const ok = (good) => good ? "ok " : "FIX ";
|
|
37641
|
-
const
|
|
37822
|
+
const asks = runtime.enabled && engine.asksJudge();
|
|
37823
|
+
const probe = asks ? await engine.probe() : void 0;
|
|
37642
37824
|
const browserHost = thisBrowserHost();
|
|
37643
37825
|
const chrome = findBrowser(browserHost)?.executable;
|
|
37644
37826
|
const available = ctx.modelRegistry.getAvailable();
|
|
37645
37827
|
const providers = [...new Set(available.map((model) => model.provider))];
|
|
37646
|
-
const agentsDir = join18((0,
|
|
37828
|
+
const agentsDir = join18((0, import_pi_coding_agent5.getAgentDir)(), "agents");
|
|
37647
37829
|
const roles = loadAgents(agentsDir);
|
|
37648
37830
|
const ladder = runtime.options("swarm", { enabled: true, models: [] }).models;
|
|
37649
37831
|
const missing = ladder.filter((ref) => {
|
|
@@ -37661,7 +37843,11 @@ function registerCommands(runtime, roots) {
|
|
|
37661
37843
|
ok(probe.ok),
|
|
37662
37844
|
"judge",
|
|
37663
37845
|
`${engine.providerId} ${probe.ok ? `answers in ${probe.latencyMs} ms` : `isn't answering (${probe.error}). For laya, run mu judge start`}`
|
|
37664
|
-
] : [
|
|
37846
|
+
] : [
|
|
37847
|
+
"-- ",
|
|
37848
|
+
"judge",
|
|
37849
|
+
runtime.enabled ? "off: no decision point asks one, so nothing is sent to a judge" : "off (MU_JUDGE=off)"
|
|
37850
|
+
],
|
|
37665
37851
|
[
|
|
37666
37852
|
"-- ",
|
|
37667
37853
|
"decisions",
|
|
@@ -37671,7 +37857,7 @@ function registerCommands(runtime, roots) {
|
|
|
37671
37857
|
[
|
|
37672
37858
|
"-- ",
|
|
37673
37859
|
"browse",
|
|
37674
|
-
`driven by ${engine.judgeFor("browser.step").id}. It needs a judge that can match a goal to a page (Jev or an LLM judge), e.g. /mu route browser.step llm:openai/gpt-5.6-luna`
|
|
37860
|
+
runtime.mode("browser.step") === "off" ? "off: mu's browser runs on the judge, and browser.step is off" : `driven by ${engine.judgeFor("browser.step").id}. It needs a judge that can match a goal to a page (Jev or an LLM judge), e.g. /mu route browser.step llm:openai/gpt-5.6-luna`
|
|
37675
37861
|
],
|
|
37676
37862
|
[
|
|
37677
37863
|
ok(roles.length > 0),
|
|
@@ -37708,7 +37894,7 @@ function registerCommands(runtime, roots) {
|
|
|
37708
37894
|
}
|
|
37709
37895
|
|
|
37710
37896
|
// packages/kyrn-judge/src/extension/features/compaction.ts
|
|
37711
|
-
var
|
|
37897
|
+
var import_pi_coding_agent6 = __toESM(require_pi_coding_agent(), 1);
|
|
37712
37898
|
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync6 } from "node:fs";
|
|
37713
37899
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
37714
37900
|
import { join as join19 } from "node:path";
|
|
@@ -38073,14 +38259,14 @@ function registerCompaction(runtime) {
|
|
|
38073
38259
|
const carried = previousItems(lastCompaction?.details);
|
|
38074
38260
|
const items = [
|
|
38075
38261
|
...carried ?? (preparation.previousSummary ? [{ kind: "note", text: preparation.previousSummary }] : []),
|
|
38076
|
-
...itemsFromMessages((0,
|
|
38077
|
-
...itemsFromMessages((0,
|
|
38262
|
+
...itemsFromMessages((0, import_pi_coding_agent6.convertToLlm)(spoken(preparation.messagesToSummarize))),
|
|
38263
|
+
...itemsFromMessages((0, import_pi_coding_agent6.convertToLlm)(spoken(preparation.turnPrefixMessages)), true)
|
|
38078
38264
|
];
|
|
38079
38265
|
const firstUser = items.findIndex((item) => item.kind === "user");
|
|
38080
38266
|
if (firstUser >= 0) items[firstUser] = { ...items[firstUser], pinned: true };
|
|
38081
38267
|
const keptFrom = branchEntries.findIndex((entry) => entry.id === preparation.firstKeptEntryId);
|
|
38082
38268
|
const tail = itemsFromMessages(
|
|
38083
|
-
(0,
|
|
38269
|
+
(0, import_pi_coding_agent6.convertToLlm)(
|
|
38084
38270
|
spoken(
|
|
38085
38271
|
branchEntries.slice(Math.max(0, keptFrom)).flatMap((entry) => entry.type === "message" ? [entry.message] : [])
|
|
38086
38272
|
)
|
|
@@ -38300,14 +38486,13 @@ function registerCompletion(runtime) {
|
|
|
38300
38486
|
}
|
|
38301
38487
|
|
|
38302
38488
|
// packages/kyrn-judge/src/decisions/turn-continue.ts
|
|
38489
|
+
var CAPABILITIES = { promised: "intent", work_requested: "meta", beyond_request: "relate" };
|
|
38303
38490
|
var turnContinue = defineDecision({
|
|
38304
38491
|
id: "turn.continue",
|
|
38305
38492
|
version: 2,
|
|
38306
38493
|
cacheImpact: "append-only",
|
|
38307
38494
|
latency: "inline",
|
|
38308
|
-
|
|
38309
|
-
// nothing counts as a go-ahead.
|
|
38310
|
-
capabilities: { work_requested: "meta", beyond_request: "relate" },
|
|
38495
|
+
capabilities: CAPABILITIES,
|
|
38311
38496
|
questions: {
|
|
38312
38497
|
promised: {
|
|
38313
38498
|
type: "boolean",
|
|
@@ -38358,6 +38543,10 @@ var turnContinue = defineDecision({
|
|
|
38358
38543
|
return "end";
|
|
38359
38544
|
}
|
|
38360
38545
|
});
|
|
38546
|
+
var turnContinueLocalPromised = {
|
|
38547
|
+
...turnContinue,
|
|
38548
|
+
capabilities: { ...CAPABILITIES, promised: "classify" }
|
|
38549
|
+
};
|
|
38361
38550
|
|
|
38362
38551
|
// packages/kyrn-judge/src/extension/features/continuation.ts
|
|
38363
38552
|
var CONTINUE_MESSAGE = "kyrn.nudge";
|
|
@@ -38379,41 +38568,80 @@ function stoppedOn(event) {
|
|
|
38379
38568
|
function endedEmpty(event) {
|
|
38380
38569
|
return plainEnd(event) === "";
|
|
38381
38570
|
}
|
|
38571
|
+
function madeCall(event) {
|
|
38572
|
+
return event.messages.some(
|
|
38573
|
+
(message) => message.role === "assistant" && Array.isArray(message.content) && message.content.some((part) => part?.type === "toolCall")
|
|
38574
|
+
);
|
|
38575
|
+
}
|
|
38382
38576
|
function registerContinuation(runtime) {
|
|
38383
|
-
const options = runtime.options("continuation", {
|
|
38577
|
+
const options = runtime.options("continuation", {
|
|
38578
|
+
enabled: true,
|
|
38579
|
+
waitMs: 3e3,
|
|
38580
|
+
maxNudges: 2,
|
|
38581
|
+
/** "You said you would" nudges per message of the user in an unattended run. `maxNudges` caps all of them together. */
|
|
38582
|
+
unattendedPromised: 1,
|
|
38583
|
+
/** In an unattended run, such a nudge after the agent answered a nudge without calling a tool. */
|
|
38584
|
+
promisedAfterToolless: false,
|
|
38585
|
+
/** Let the local judge (Laya) answer `promised`; by default it is not trusted on it (`intent`). */
|
|
38586
|
+
localPromised: false
|
|
38587
|
+
});
|
|
38384
38588
|
if (!options.enabled) return;
|
|
38385
38589
|
const { pi } = runtime;
|
|
38590
|
+
const spec = options.localPromised ? turnContinueLocalPromised : turnContinue;
|
|
38591
|
+
const declared = spec.capabilities;
|
|
38592
|
+
const trusted = (question) => runtime.trusts(spec.id, (typeof declared === "object" ? declared[question] : declared) ?? "classify");
|
|
38593
|
+
const canSendBack = () => trusted("irreversible") && (trusted("promised") || trusted("asks_go_ahead") && trusted("work_requested") && trusted("beyond_request"));
|
|
38594
|
+
let nudgedIn;
|
|
38595
|
+
const promisedNudges = /* @__PURE__ */ new WeakMap();
|
|
38386
38596
|
pi.on(
|
|
38387
38597
|
"agent_end",
|
|
38388
38598
|
failOpen(async (event, ctx) => {
|
|
38389
38599
|
runtime.touch(ctx);
|
|
38390
|
-
if (runtime.goalActive || runtime.harnessAbort
|
|
38600
|
+
if (runtime.goalActive || runtime.harnessAbort) return void 0;
|
|
38391
38601
|
const turn = runtime.turn;
|
|
38602
|
+
const answeredNudge = nudgedIn === turn;
|
|
38603
|
+
nudgedIn = void 0;
|
|
38604
|
+
if (runtime.nudgedEnds.has(event)) {
|
|
38605
|
+
nudgedIn = turn;
|
|
38606
|
+
return void 0;
|
|
38607
|
+
}
|
|
38392
38608
|
if (turn.continued >= options.maxNudges) return void 0;
|
|
38393
38609
|
if (endedEmpty(event)) {
|
|
38394
38610
|
turn.continued += 1;
|
|
38395
38611
|
runtime.nudgedEnds.add(event);
|
|
38612
|
+
nudgedIn = turn;
|
|
38396
38613
|
pi.sendMessage({ customType: CONTINUE_MESSAGE, content: EMPTY, display: true }, { triggerTurn: true });
|
|
38397
38614
|
return void 0;
|
|
38398
38615
|
}
|
|
38399
38616
|
const finalMessage = stoppedOn(event);
|
|
38400
|
-
if (!finalMessage) return void 0;
|
|
38617
|
+
if (!finalMessage || !canSendBack()) return void 0;
|
|
38401
38618
|
const flat4 = finalMessage.replace(/\s+/g, " ");
|
|
38402
38619
|
const input = {
|
|
38403
38620
|
userMessage: clip(turn.userMessage, 400),
|
|
38404
38621
|
finalMessage: flat4.length <= 600 ? flat4 : `\u2026${flat4.slice(-599)}`
|
|
38405
38622
|
};
|
|
38406
|
-
const ask = () => askWithin((signal) => runtime.engine.decide(
|
|
38407
|
-
if (runtime.mode(
|
|
38623
|
+
const ask = () => askWithin((signal) => runtime.engine.decide(spec, input, { signal }), options.waitMs);
|
|
38624
|
+
if (runtime.mode(spec.id) !== "active") {
|
|
38408
38625
|
void ask().catch(() => {
|
|
38409
38626
|
});
|
|
38410
38627
|
return void 0;
|
|
38411
38628
|
}
|
|
38412
38629
|
const decision = await ask();
|
|
38413
38630
|
if (decision?.source !== "judge" || decision.outcome === "end") return void 0;
|
|
38414
|
-
if (runtime.harnessAbort
|
|
38631
|
+
if (runtime.harnessAbort) return void 0;
|
|
38632
|
+
if (runtime.nudgedEnds.has(event)) {
|
|
38633
|
+
nudgedIn = turn;
|
|
38634
|
+
return void 0;
|
|
38635
|
+
}
|
|
38636
|
+
if (decision.outcome === "promised" && isUnattended(ctx)) {
|
|
38637
|
+
const promised = promisedNudges.get(turn) ?? 0;
|
|
38638
|
+
if (promised >= options.unattendedPromised) return void 0;
|
|
38639
|
+
if (answeredNudge && !options.promisedAfterToolless && !madeCall(event)) return void 0;
|
|
38640
|
+
promisedNudges.set(turn, promised + 1);
|
|
38641
|
+
}
|
|
38415
38642
|
turn.continued += 1;
|
|
38416
38643
|
runtime.nudgedEnds.add(event);
|
|
38644
|
+
nudgedIn = turn;
|
|
38417
38645
|
pi.sendMessage(
|
|
38418
38646
|
{ customType: CONTINUE_MESSAGE, content: SAID[decision.outcome], display: true },
|
|
38419
38647
|
{ triggerTurn: true }
|
|
@@ -40337,7 +40565,7 @@ var geminiCliOAuth = googleOAuth(GEMINI_CLI_LOGIN);
|
|
|
40337
40565
|
var antigravityOAuth = googleOAuth(ANTIGRAVITY_LOGIN);
|
|
40338
40566
|
|
|
40339
40567
|
// packages/kyrn-judge/src/google-login/providers.ts
|
|
40340
|
-
var cloudCode = () => (0, import_pi_ai2.lazyApi)(() => import("./cloud-code-
|
|
40568
|
+
var cloudCode = () => (0, import_pi_ai2.lazyApi)(() => import("./cloud-code-XR7SZMJC.js"));
|
|
40341
40569
|
var FREE = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
40342
40570
|
var NOT_CHAT = /image|live|computer-use|customtools|latest|deep-research|tts|embedding/;
|
|
40343
40571
|
function geminiCliModels() {
|
|
@@ -40602,11 +40830,11 @@ function riskFlag(command) {
|
|
|
40602
40830
|
const flag = RULES.find(([pattern]) => pattern.test(command) || pattern.test(plain2))?.[1];
|
|
40603
40831
|
return flag ?? (runsSavedDownload(plain2) ? "runs a downloaded script" : void 0);
|
|
40604
40832
|
}
|
|
40605
|
-
var RISK_COMMAND_CHARS =
|
|
40833
|
+
var RISK_COMMAND_CHARS = 1500;
|
|
40606
40834
|
var RISK_CONFIRM_CHARS = 1500;
|
|
40607
40835
|
function riskExcerpt(command, limit = RISK_COMMAND_CHARS) {
|
|
40608
|
-
const
|
|
40609
|
-
if (
|
|
40836
|
+
const tidy2 = (text8) => text8.split(/\r\n?|\n/).map((line2) => line2.replace(/\s+/g, " ").trim()).filter(Boolean).join("\n");
|
|
40837
|
+
if (tidy2(command).length <= limit) return tidy2(command);
|
|
40610
40838
|
const plain2 = unquoted(command);
|
|
40611
40839
|
const source = RULES.some(([pattern]) => !pattern.test(command) && pattern.test(plain2)) ? plain2 : command;
|
|
40612
40840
|
const around = Math.floor(limit / 12);
|
|
@@ -40639,7 +40867,7 @@ function riskExcerpt(command, limit = RISK_COMMAND_CHARS) {
|
|
|
40639
40867
|
else merged.push([...span]);
|
|
40640
40868
|
return merged;
|
|
40641
40869
|
}, []);
|
|
40642
|
-
const text7 = spans.map(([start, end]) => `${start > 0 ? "\u2026 " : ""}${
|
|
40870
|
+
const text7 = spans.map(([start, end]) => `${start > 0 ? "\u2026 " : ""}${tidy2(source.slice(start, end))}`).join(" ");
|
|
40643
40871
|
const tail = spans[spans.length - 1][1] < source.length ? " \u2026" : "";
|
|
40644
40872
|
return `${text7}${tail}${left > 0 ? ` (${left} more flagged parts left out)` : ""}`;
|
|
40645
40873
|
}
|
|
@@ -40676,7 +40904,7 @@ ${riskExcerpt(command, RISK_CONFIRM_CHARS)}`
|
|
|
40676
40904
|
}
|
|
40677
40905
|
|
|
40678
40906
|
// packages/kyrn-judge/src/extension/features/hive.ts
|
|
40679
|
-
var
|
|
40907
|
+
var import_pi_coding_agent8 = __toESM(require_pi_coding_agent(), 1);
|
|
40680
40908
|
var import_typebox7 = __toESM(require_typebox(), 1);
|
|
40681
40909
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
40682
40910
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
@@ -40949,7 +41177,7 @@ function hiveRequest(question) {
|
|
|
40949
41177
|
}
|
|
40950
41178
|
|
|
40951
41179
|
// packages/kyrn-judge/src/extension/features/swarm.ts
|
|
40952
|
-
var
|
|
41180
|
+
var import_pi_coding_agent7 = __toESM(require_pi_coding_agent(), 1);
|
|
40953
41181
|
var import_pi_tui3 = __toESM(require_pi_tui(), 1);
|
|
40954
41182
|
var import_typebox6 = __toESM(require_typebox(), 1);
|
|
40955
41183
|
import { spawn as spawn6 } from "node:child_process";
|
|
@@ -42279,6 +42507,12 @@ function renderSwarmResult(result, options, theme) {
|
|
|
42279
42507
|
}
|
|
42280
42508
|
};
|
|
42281
42509
|
}
|
|
42510
|
+
function recordBeeUsage(runtime, run2) {
|
|
42511
|
+
run2.onBeeEnd = (bee) => {
|
|
42512
|
+
const entry = subagentUsage(run2.kind, bee);
|
|
42513
|
+
if (entry) runtime.pi.appendEntry(USAGE_ENTRY, entry);
|
|
42514
|
+
};
|
|
42515
|
+
}
|
|
42282
42516
|
function compactSnapshot(snapshot2) {
|
|
42283
42517
|
return {
|
|
42284
42518
|
...snapshot2,
|
|
@@ -42314,7 +42548,7 @@ function registerSwarm(runtime, runner = spawnRunner) {
|
|
|
42314
42548
|
const { pi } = runtime;
|
|
42315
42549
|
const isolation = new Isolation(runtime, options);
|
|
42316
42550
|
isolation.registerTool();
|
|
42317
|
-
const agents = () => loadAgents(options.agentsDir || join25((0,
|
|
42551
|
+
const agents = () => loadAgents(options.agentsDir || join25((0, import_pi_coding_agent7.getAgentDir)(), "agents"));
|
|
42318
42552
|
const usable = () => {
|
|
42319
42553
|
const known = new Set(pi.getAllTools().map((tool) => tool.name));
|
|
42320
42554
|
return agents().filter((agent) => !agent.tools || agent.tools.some((tool) => known.has(tool)));
|
|
@@ -42466,6 +42700,7 @@ function registerSwarm(runtime, runner = spawnRunner) {
|
|
|
42466
42700
|
}))
|
|
42467
42701
|
});
|
|
42468
42702
|
streamUpdates(run2, onUpdate);
|
|
42703
|
+
recordBeeUsage(runtime, run2);
|
|
42469
42704
|
const outcomes = await run2.run(placedRunner, signal);
|
|
42470
42705
|
const reports = outcomes.map((outcome) => outcome.report);
|
|
42471
42706
|
const frames = await Promise.all(tasks.map((_task, index) => readFrameOut(frameOutPath(runDir, index))));
|
|
@@ -42504,7 +42739,7 @@ ${checklist}` : ""}${isolation.describe(outcomesOfIsolation.get(task))}`;
|
|
|
42504
42739
|
en: "List the subagent roles the delegate tool can use, and where to add your own"
|
|
42505
42740
|
}),
|
|
42506
42741
|
handler: async (_args, ctx) => {
|
|
42507
|
-
const dir = options.agentsDir || join25((0,
|
|
42742
|
+
const dir = options.agentsDir || join25((0, import_pi_coding_agent7.getAgentDir)(), "agents");
|
|
42508
42743
|
const ladder = options.models.length > 0 ? options.models.join(" < ") : "the session's current model";
|
|
42509
42744
|
ctx.ui.notify(
|
|
42510
42745
|
[
|
|
@@ -42952,7 +43187,7 @@ function registerHive(runtime, runner = spawnRunner) {
|
|
|
42952
43187
|
announceRouting(onUpdate, bees.length);
|
|
42953
43188
|
const dir = join26(tmpdir6(), `kyrn-hive-${randomUUID6().slice(0, 8)}`);
|
|
42954
43189
|
const board = new Board(dir);
|
|
42955
|
-
const roles = new Map(loadAgents(join26((0,
|
|
43190
|
+
const roles = new Map(loadAgents(join26((0, import_pi_coding_agent8.getAgentDir)(), "agents")).map((agent) => [agent.name, agent]));
|
|
42956
43191
|
const swarm = runtime.options("swarm", { enabled: true, models: [] });
|
|
42957
43192
|
const ladder = options.models.length > 0 ? options.models : swarm.models;
|
|
42958
43193
|
const current = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : void 0;
|
|
@@ -43041,6 +43276,7 @@ ${others.join("\n")}`,
|
|
|
43041
43276
|
});
|
|
43042
43277
|
run2.board = () => summarizeBoard(board);
|
|
43043
43278
|
streamUpdates(run2, onUpdate);
|
|
43279
|
+
recordBeeUsage(runtime, run2);
|
|
43044
43280
|
const firstSeen = /* @__PURE__ */ new Map();
|
|
43045
43281
|
const verified = /* @__PURE__ */ new Set();
|
|
43046
43282
|
let verifiers = 0;
|
|
@@ -43291,7 +43527,7 @@ function summarizeBoard(board) {
|
|
|
43291
43527
|
}
|
|
43292
43528
|
|
|
43293
43529
|
// packages/kyrn-judge/src/extension/features/import.ts
|
|
43294
|
-
var
|
|
43530
|
+
var import_pi_coding_agent9 = __toESM(require_pi_coding_agent(), 1);
|
|
43295
43531
|
var import_pi_tui4 = __toESM(require_pi_tui(), 1);
|
|
43296
43532
|
|
|
43297
43533
|
// packages/kyrn-judge/src/import/index.ts
|
|
@@ -45715,7 +45951,7 @@ ${theme.fg("dim", detail)}`, 0, 0));
|
|
|
45715
45951
|
zh: "\u5BFC\u5165\u8FD9\u4E2A\u9879\u76EE\u5728 Claude Code\u3001Codex \u6216 ZCode \u91CC\u7684\u5BF9\u8BDD\uFF0C\u63A5\u7740\u5728\u8FD9\u91CC\u804A\uFF1A/import-chat [\u6587\u4EF6]",
|
|
45716
45952
|
en: "Import a Claude Code, Codex or ZCode conversation from this project and continue it here: /import-chat [file]"
|
|
45717
45953
|
}),
|
|
45718
|
-
handler: async (args, ctx) => importChat(args, ctx, { agentDir: (0,
|
|
45954
|
+
handler: async (args, ctx) => importChat(args, ctx, { agentDir: (0, import_pi_coding_agent9.getAgentDir)() })
|
|
45719
45955
|
});
|
|
45720
45956
|
}
|
|
45721
45957
|
|
|
@@ -46584,7 +46820,7 @@ function expandPlaceholders(value, context) {
|
|
|
46584
46820
|
}
|
|
46585
46821
|
|
|
46586
46822
|
// packages/kyrn-judge/src/inherit/skills.ts
|
|
46587
|
-
var
|
|
46823
|
+
var import_pi_coding_agent10 = __toESM(require_pi_coding_agent(), 1);
|
|
46588
46824
|
import { readdirSync as readdirSync8, statSync as statSync11 } from "node:fs";
|
|
46589
46825
|
import { basename as basename9, join as join33 } from "node:path";
|
|
46590
46826
|
function readSkill(dir, problems) {
|
|
@@ -46593,7 +46829,7 @@ function readSkill(dir, problems) {
|
|
|
46593
46829
|
if (text7 === void 0) return void 0;
|
|
46594
46830
|
let frontmatter;
|
|
46595
46831
|
try {
|
|
46596
|
-
frontmatter = (0,
|
|
46832
|
+
frontmatter = (0, import_pi_coding_agent10.parseFrontmatter)(text7).frontmatter;
|
|
46597
46833
|
} catch {
|
|
46598
46834
|
problems.push({ source: file, message: "skipped: its frontmatter is not valid YAML" });
|
|
46599
46835
|
return void 0;
|
|
@@ -46989,7 +47225,7 @@ function looksPoisoned(text7) {
|
|
|
46989
47225
|
}
|
|
46990
47226
|
|
|
46991
47227
|
// packages/kyrn-judge/src/extension/features/tool-descriptions.ts
|
|
46992
|
-
var
|
|
47228
|
+
var import_pi_coding_agent11 = __toESM(require_pi_coding_agent(), 1);
|
|
46993
47229
|
import { createHash as createHash6 } from "node:crypto";
|
|
46994
47230
|
import { mkdirSync as mkdirSync14, readFileSync as readFileSync16, renameSync as renameSync6, writeFileSync as writeFileSync12 } from "node:fs";
|
|
46995
47231
|
import { dirname as dirname8, join as join36 } from "node:path";
|
|
@@ -47209,7 +47445,7 @@ ${describeTool(tool)}`;
|
|
|
47209
47445
|
return void 0;
|
|
47210
47446
|
})
|
|
47211
47447
|
);
|
|
47212
|
-
pi.events.on(
|
|
47448
|
+
pi.events.on(import_pi_coding_agent11.MCP_CONNECTION_EVENT, (data) => {
|
|
47213
47449
|
if (data.state !== "connected") return;
|
|
47214
47450
|
screen().catch(() => void 0);
|
|
47215
47451
|
});
|
|
@@ -48285,7 +48521,7 @@ function registerInjection(runtime) {
|
|
|
48285
48521
|
};
|
|
48286
48522
|
const judge = async (source, list3, signal) => {
|
|
48287
48523
|
if (list3.length === 0) return [];
|
|
48288
|
-
if (!runtime.
|
|
48524
|
+
if (!runtime.answersInBatches(toolInjection.id, "screen")) {
|
|
48289
48525
|
const decisions2 = await runtime.engine.decideMany(
|
|
48290
48526
|
toolInjection,
|
|
48291
48527
|
list3.map((passage) => ({ source, passage })),
|
|
@@ -48573,7 +48809,7 @@ function registerJudgeItems(runtime) {
|
|
|
48573
48809
|
}
|
|
48574
48810
|
|
|
48575
48811
|
// packages/kyrn-judge/src/extension/features/lsp.ts
|
|
48576
|
-
var
|
|
48812
|
+
var import_pi_coding_agent12 = __toESM(require_pi_coding_agent(), 1);
|
|
48577
48813
|
import { readFileSync as readFileSync17, statSync as statSync13 } from "node:fs";
|
|
48578
48814
|
import { homedir as homedir8 } from "node:os";
|
|
48579
48815
|
import { join as join37, relative as relative4, resolve as resolve8 } from "node:path";
|
|
@@ -49885,9 +50121,9 @@ var DIAGNOSTICS_MESSAGE = "kyrn.diagnostics";
|
|
|
49885
50121
|
var PROJECT_SERVERS_FILE = "lsp.json";
|
|
49886
50122
|
function projectServersTrusted(ctx, agentDir) {
|
|
49887
50123
|
if (!ctx.isProjectTrusted()) return false;
|
|
49888
|
-
if ((0,
|
|
50124
|
+
if ((0, import_pi_coding_agent12.hasTrustRequiringProjectResources)(ctx.cwd)) return true;
|
|
49889
50125
|
try {
|
|
49890
|
-
return new
|
|
50126
|
+
return new import_pi_coding_agent12.ProjectTrustStore(agentDir).get(ctx.cwd) === true;
|
|
49891
50127
|
} catch {
|
|
49892
50128
|
return false;
|
|
49893
50129
|
}
|
|
@@ -49940,12 +50176,12 @@ function registerLsp(runtime) {
|
|
|
49940
50176
|
if (table && table.cwd === ctx.cwd && !refresh2) return table;
|
|
49941
50177
|
let project;
|
|
49942
50178
|
try {
|
|
49943
|
-
const file = join37(ctx.cwd,
|
|
50179
|
+
const file = join37(ctx.cwd, import_pi_coding_agent12.CONFIG_DIR_NAME, PROJECT_SERVERS_FILE);
|
|
49944
50180
|
project = JSON.parse(readFileSync17(file, "utf8")).servers;
|
|
49945
50181
|
} catch {
|
|
49946
50182
|
project = void 0;
|
|
49947
50183
|
}
|
|
49948
|
-
const trusted = project !== void 0 && projectServersTrusted(ctx, (0,
|
|
50184
|
+
const trusted = project !== void 0 && projectServersTrusted(ctx, (0, import_pi_coding_agent12.getAgentDir)());
|
|
49949
50185
|
const merged = mergeServers(
|
|
49950
50186
|
[
|
|
49951
50187
|
{ origin: "user", servers: options.servers },
|
|
@@ -50198,7 +50434,7 @@ ${report3.text}`,
|
|
|
50198
50434
|
});
|
|
50199
50435
|
if (known.ignoredProjectFile) {
|
|
50200
50436
|
lines2.push(
|
|
50201
|
-
`${join37(
|
|
50437
|
+
`${join37(import_pi_coding_agent12.CONFIG_DIR_NAME, PROJECT_SERVERS_FILE)} configures servers for this project. It's ignored until you trust the project (/trust).`
|
|
50202
50438
|
);
|
|
50203
50439
|
}
|
|
50204
50440
|
for (const problem of known.problems) lines2.push(`problem: ${problem}`);
|
|
@@ -50212,7 +50448,7 @@ ${report3.text}`,
|
|
|
50212
50448
|
}
|
|
50213
50449
|
|
|
50214
50450
|
// packages/kyrn-judge/src/extension/features/mcp.ts
|
|
50215
|
-
var
|
|
50451
|
+
var import_pi_coding_agent13 = __toESM(require_pi_coding_agent(), 1);
|
|
50216
50452
|
import { homedir as homedir9 } from "node:os";
|
|
50217
50453
|
import { join as join39 } from "node:path";
|
|
50218
50454
|
|
|
@@ -50561,7 +50797,7 @@ function registerMcp(runtime, roots) {
|
|
|
50561
50797
|
throw new Error(reason);
|
|
50562
50798
|
}
|
|
50563
50799
|
}
|
|
50564
|
-
pi.events.on(
|
|
50800
|
+
pi.events.on(import_pi_coding_agent13.MCP_CONNECTION_EVENT, (data) => {
|
|
50565
50801
|
const event = data;
|
|
50566
50802
|
const entry = entries.get(event.server);
|
|
50567
50803
|
if (!entry?.registered) return;
|
|
@@ -50595,7 +50831,7 @@ function registerMcp(runtime, roots) {
|
|
|
50595
50831
|
const ensureLoaded = (ctx) => {
|
|
50596
50832
|
if (scan2) return;
|
|
50597
50833
|
scan2 = inheritedFor(runtime, roots, ctx, runtime.config.mcp);
|
|
50598
|
-
const piOwn = roots ? (0,
|
|
50834
|
+
const piOwn = roots ? (0, import_pi_coding_agent13.loadMcpConfig)({ agentDir: roots.agentDir, cwd: ctx.cwd, projectTrusted: ctx.isProjectTrusted() }).servers : [];
|
|
50599
50835
|
const piNames = new Set(piOwn.map((server) => server.name.replace(/-/g, "_").toLowerCase()));
|
|
50600
50836
|
const used = scan2.servers.filter((definition) => {
|
|
50601
50837
|
if (!piNames.has(definition.name.replace(/-/g, "_").toLowerCase())) return true;
|
|
@@ -50631,7 +50867,7 @@ function registerMcp(runtime, roots) {
|
|
|
50631
50867
|
failOpen((_event, ctx) => {
|
|
50632
50868
|
runtime.touch(ctx);
|
|
50633
50869
|
ensureLoaded(ctx);
|
|
50634
|
-
const everything = runtime
|
|
50870
|
+
const everything = hidesNothing(runtime);
|
|
50635
50871
|
for (const entry of entries.values()) {
|
|
50636
50872
|
if (!everything && entry.definition.exposure !== "always") continue;
|
|
50637
50873
|
if (entry.needsApproval && !store.isApproved(ctx.cwd, entry.definition)) continue;
|
|
@@ -50987,7 +51223,7 @@ function turnDigest(turn) {
|
|
|
50987
51223
|
// packages/kyrn-judge/src/memory/store.ts
|
|
50988
51224
|
import { appendFileSync as appendFileSync4, closeSync as closeSync5, fstatSync as fstatSync3, mkdirSync as mkdirSync16, openSync as openSync5, readFileSync as readFileSync19, readSync as readSync4 } from "node:fs";
|
|
50989
51225
|
import { dirname as dirname9 } from "node:path";
|
|
50990
|
-
var
|
|
51226
|
+
var KINDS4 = ["correction", "preference", "pitfall", "workaround", "fact"];
|
|
50991
51227
|
var ORIGINS = ["user", "outcome", "model", "subagent", "command"];
|
|
50992
51228
|
var STATUSES = ["active", "retired", "superseded"];
|
|
50993
51229
|
function isRecord5(value) {
|
|
@@ -51001,7 +51237,7 @@ function draftOf(value) {
|
|
|
51001
51237
|
const draft = { id: value.id };
|
|
51002
51238
|
if (isText3(value.trigger)) draft.trigger = value.trigger;
|
|
51003
51239
|
if (isText3(value.lesson)) draft.lesson = value.lesson;
|
|
51004
|
-
const kind = oneOf(
|
|
51240
|
+
const kind = oneOf(KINDS4, value.kind);
|
|
51005
51241
|
if (kind) draft.kind = kind;
|
|
51006
51242
|
const status = oneOf(STATUSES, value.status);
|
|
51007
51243
|
if (status) draft.status = status;
|
|
@@ -51269,8 +51505,8 @@ function registerMemory(runtime, roots) {
|
|
|
51269
51505
|
path: "",
|
|
51270
51506
|
maxCandidates: 24,
|
|
51271
51507
|
maxInjected: 5,
|
|
51272
|
-
/** How long the turn waits for the recall verdict, counted from the arrival of the message. */
|
|
51273
|
-
waitMs:
|
|
51508
|
+
/** How long the turn waits for the recall verdict, counted from the arrival of the message, as preflight's wait is. */
|
|
51509
|
+
waitMs: 3e3,
|
|
51274
51510
|
/** A lesson recalled this many times that the judge never saw followed is retired. 0 keeps every lesson. */
|
|
51275
51511
|
retireAfter: 8,
|
|
51276
51512
|
/** Kept lessons a new one is compared with before it is stored: those sharing the most words with it. */
|
|
@@ -52481,7 +52717,7 @@ function installHint(binary, platform) {
|
|
|
52481
52717
|
}
|
|
52482
52718
|
|
|
52483
52719
|
// packages/kyrn-judge/src/extension/features/packs/ast-grep.ts
|
|
52484
|
-
var
|
|
52720
|
+
var import_pi_coding_agent14 = __toESM(require_pi_coding_agent(), 1);
|
|
52485
52721
|
var import_typebox11 = __toESM(require_typebox(), 1);
|
|
52486
52722
|
import { readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
52487
52723
|
import { resolve as resolve10 } from "node:path";
|
|
@@ -52781,7 +53017,7 @@ function astGrepPack(shared, options) {
|
|
|
52781
53017
|
{
|
|
52782
53018
|
read: (path) => readFile3(path),
|
|
52783
53019
|
write: (path, data) => writeFile3(path, data),
|
|
52784
|
-
locked:
|
|
53020
|
+
locked: import_pi_coding_agent14.withFileMutationQueue,
|
|
52785
53021
|
resolve: (file) => resolve10(ctx.cwd, file)
|
|
52786
53022
|
},
|
|
52787
53023
|
{ apply: params.apply === true, maxDiffChars: options.maxDiffChars }
|
|
@@ -54996,7 +55232,7 @@ function registerPacks(runtime) {
|
|
|
54996
55232
|
}
|
|
54997
55233
|
const startAllWhenNothingIsHidden = async (ctx) => {
|
|
54998
55234
|
runtime.touch(ctx);
|
|
54999
|
-
if (
|
|
55235
|
+
if (hidesNothing(runtime)) {
|
|
55000
55236
|
await Promise.allSettled(packs.map(start));
|
|
55001
55237
|
}
|
|
55002
55238
|
return void 0;
|
|
@@ -55017,7 +55253,7 @@ function registerPacks(runtime) {
|
|
|
55017
55253
|
}
|
|
55018
55254
|
|
|
55019
55255
|
// packages/kyrn-judge/src/extension/features/permissions.ts
|
|
55020
|
-
var
|
|
55256
|
+
var import_pi_coding_agent15 = __toESM(require_pi_coding_agent(), 1);
|
|
55021
55257
|
import { homedir as homedir11 } from "node:os";
|
|
55022
55258
|
import { join as join45, resolve as resolve13, sep as sep3 } from "node:path";
|
|
55023
55259
|
|
|
@@ -55354,8 +55590,8 @@ function protectedPaths(roots) {
|
|
|
55354
55590
|
return real2 && real2 !== roots.agentDir ? [...spelled, real2] : spelled;
|
|
55355
55591
|
}
|
|
55356
55592
|
function projectSettings(cwd) {
|
|
55357
|
-
const spelled = join45(resolve13(cwd),
|
|
55358
|
-
const real2 = toolPath(cwd,
|
|
55593
|
+
const spelled = join45(resolve13(cwd), import_pi_coding_agent15.CONFIG_DIR_NAME);
|
|
55594
|
+
const real2 = toolPath(cwd, import_pi_coding_agent15.CONFIG_DIR_NAME) ?? spelled;
|
|
55359
55595
|
return [.../* @__PURE__ */ new Set([spelled, real2])].map((path) => `${path}${sep3}`);
|
|
55360
55596
|
}
|
|
55361
55597
|
function registerPermissions(runtime, roots) {
|
|
@@ -55950,9 +56186,10 @@ function hintIdsFor(outcome, tools, flags = {}) {
|
|
|
55950
56186
|
return ids;
|
|
55951
56187
|
}
|
|
55952
56188
|
function statusLine(label2, decision) {
|
|
56189
|
+
if (decision.mode === "off") return void 0;
|
|
55953
56190
|
const latency = decision.latencyMs === void 0 ? "" : ` \xB7 ${decision.latencyMs} ms`;
|
|
55954
56191
|
const cut = decision.warnings?.length ? ` (${decision.warnings.length} warnings)` : "";
|
|
55955
|
-
const recorded = decision.mode === "
|
|
56192
|
+
const recorded = decision.mode === "shadow" ? " \xB7 recorded only" : "";
|
|
55956
56193
|
const shown2 = decision.mode === "active" ? decision.outcome : decision.judged ?? decision.outcome;
|
|
55957
56194
|
const said = shown2.turnType === "unknown" && !decision.judged ? decision.reason ?? "no verdict" : `${turnLabel(shown2.turnType)} \xB7 ${gearLabel(shown2.gear)}`;
|
|
55958
56195
|
return `${judgeDisplayName(label2)}: ${said}${latency}${cut}${recorded}`;
|
|
@@ -55974,7 +56211,12 @@ function registerPreflight(runtime) {
|
|
|
55974
56211
|
hints: true,
|
|
55975
56212
|
/** Show the wait and the verdict in the terminal UI. */
|
|
55976
56213
|
show: true,
|
|
55977
|
-
|
|
56214
|
+
/**
|
|
56215
|
+
* Every wait before a turn ends by this much after the message arrived (`catalog`, `skills` and `memory` have
|
|
56216
|
+
* the same; the frame 3 s). In 67 judged messages from the owner's network none answered between 3 and 4 s: past
|
|
56217
|
+
* 3 s the answer came after 4.3 s or not at all, so the fourth second was always waited for nothing.
|
|
56218
|
+
*/
|
|
56219
|
+
waitMs: 3e3,
|
|
55978
56220
|
/**
|
|
55979
56221
|
* Ask in a `mu --print` or json run too. Off by default: there the verdict buys a hint that is rarely
|
|
55980
56222
|
* followed, for judge tokens and up to `waitMs` before every prompt.
|
|
@@ -56245,7 +56487,7 @@ function registerPreflight(runtime) {
|
|
|
56245
56487
|
}
|
|
56246
56488
|
|
|
56247
56489
|
// packages/kyrn-judge/src/extension/features/procedures.ts
|
|
56248
|
-
var
|
|
56490
|
+
var import_pi_coding_agent16 = __toESM(require_pi_coding_agent(), 1);
|
|
56249
56491
|
import { basename as basename14, join as join47 } from "node:path";
|
|
56250
56492
|
|
|
56251
56493
|
// packages/kyrn-judge/src/decisions/skill-capture.ts
|
|
@@ -56571,7 +56813,7 @@ ${say({
|
|
|
56571
56813
|
return;
|
|
56572
56814
|
}
|
|
56573
56815
|
if (verb === "accept") {
|
|
56574
|
-
const target = project ? join47(ctx.cwd,
|
|
56816
|
+
const target = project ? join47(ctx.cwd, import_pi_coding_agent16.CONFIG_DIR_NAME, "skills") : userSkillsDir;
|
|
56575
56817
|
if (!target) return;
|
|
56576
56818
|
const result = drafts.accept(draft.name, target);
|
|
56577
56819
|
if ("error" in result) {
|
|
@@ -56651,10 +56893,12 @@ function registerSkills(runtime) {
|
|
|
56651
56893
|
const options = runtime.options("skills", {
|
|
56652
56894
|
enabled: true,
|
|
56653
56895
|
minSkills: 4,
|
|
56654
|
-
waitMs:
|
|
56896
|
+
waitMs: 3e3,
|
|
56655
56897
|
applyLate: true,
|
|
56656
56898
|
/** Sub-agents take the skills this session hides instead of asking the judge again. */
|
|
56657
|
-
subagentsInherit: true
|
|
56899
|
+
subagentsInherit: true,
|
|
56900
|
+
/** Ask when the message arrives, alongside preflight, instead of after preflight's wait. */
|
|
56901
|
+
askEarly: true
|
|
56658
56902
|
});
|
|
56659
56903
|
if (!options.enabled) return;
|
|
56660
56904
|
const { pi } = runtime;
|
|
@@ -56681,6 +56925,18 @@ function registerSkills(runtime) {
|
|
|
56681
56925
|
late = void 0;
|
|
56682
56926
|
};
|
|
56683
56927
|
let early;
|
|
56928
|
+
let seen;
|
|
56929
|
+
const promptSkills = () => {
|
|
56930
|
+
if (seen) return seen;
|
|
56931
|
+
const ctx = runtime.ctx;
|
|
56932
|
+
const listed2 = ctx?.getSystemPromptOptions?.().skills;
|
|
56933
|
+
if (listed2) return listed2;
|
|
56934
|
+
return pi.getCommands().filter((command) => command.source === "skill").map((command) => ({
|
|
56935
|
+
name: command.name.replace(/^skill:/, ""),
|
|
56936
|
+
description: command.description ?? "",
|
|
56937
|
+
filePath: command.sourceInfo.path
|
|
56938
|
+
}));
|
|
56939
|
+
};
|
|
56684
56940
|
if (options.subagentsInherit) {
|
|
56685
56941
|
runtime.skillsHidden = () => {
|
|
56686
56942
|
if (!decided || runtime.mode(skillDisclosure.id) === "off") return void 0;
|
|
@@ -56694,12 +56950,11 @@ function registerSkills(runtime) {
|
|
|
56694
56950
|
};
|
|
56695
56951
|
}
|
|
56696
56952
|
runtime.atTurnStart((words2) => {
|
|
56697
|
-
if (inherited || runtime.mode(skillDisclosure.id) === "off") return;
|
|
56953
|
+
if (!options.askEarly || inherited || runtime.mode(skillDisclosure.id) === "off") return;
|
|
56698
56954
|
applyLate();
|
|
56699
|
-
const ctx = runtime.ctx;
|
|
56700
56955
|
let all = [];
|
|
56701
56956
|
try {
|
|
56702
|
-
all =
|
|
56957
|
+
all = promptSkills();
|
|
56703
56958
|
} catch {
|
|
56704
56959
|
return;
|
|
56705
56960
|
}
|
|
@@ -56728,6 +56983,7 @@ function registerSkills(runtime) {
|
|
|
56728
56983
|
}
|
|
56729
56984
|
const mode = runtime.mode(skillDisclosure.id);
|
|
56730
56985
|
if (mode === "active") applyLate();
|
|
56986
|
+
seen = event.systemPromptOptions.skills ?? [];
|
|
56731
56987
|
if (event.messageType === "custom") {
|
|
56732
56988
|
if (mode !== "off") {
|
|
56733
56989
|
event.systemPromptOptions.skills = (event.systemPromptOptions.skills ?? []).filter(
|
|
@@ -57186,6 +57442,29 @@ function cutAfterMs(thinkingMs, remainingMs) {
|
|
|
57186
57442
|
if (remainingMs === void 0) return thinkingMs;
|
|
57187
57443
|
return Math.min(thinkingMs, Math.max(MIN_CUT_MS, remainingMs / 2));
|
|
57188
57444
|
}
|
|
57445
|
+
function cutUsage(message, streamedChars, thinkingMs, model) {
|
|
57446
|
+
const kept = message.content.reduce(
|
|
57447
|
+
(sum, block) => sum + (block.type === "thinking" ? block.thinking.length : 0),
|
|
57448
|
+
0
|
|
57449
|
+
);
|
|
57450
|
+
const chars = Math.max(streamedChars, kept);
|
|
57451
|
+
const output = Math.max(0, estimateReasoningTokens(chars) - (message.usage?.output ?? 0));
|
|
57452
|
+
if (output === 0) return void 0;
|
|
57453
|
+
const priced = model?.provider === message.provider && model.id === message.model ? model : void 0;
|
|
57454
|
+
return {
|
|
57455
|
+
source: "watchdog-cut",
|
|
57456
|
+
model: `${message.provider}/${message.model}`,
|
|
57457
|
+
input: 0,
|
|
57458
|
+
output,
|
|
57459
|
+
cacheRead: 0,
|
|
57460
|
+
cacheWrite: 0,
|
|
57461
|
+
...priced ? { cost: priced.cost.output / 1e6 * output } : {},
|
|
57462
|
+
estimated: true,
|
|
57463
|
+
estimatedOutput: output,
|
|
57464
|
+
thoughtChars: chars,
|
|
57465
|
+
thinkingMs
|
|
57466
|
+
};
|
|
57467
|
+
}
|
|
57189
57468
|
function registerWatchdog(runtime) {
|
|
57190
57469
|
const options = runtime.options("watchdog", { enabled: true, thinkingMs: 6e5, maxCuts: 3 });
|
|
57191
57470
|
if (!options.enabled || !(options.thinkingMs > 0)) return;
|
|
@@ -57194,6 +57473,7 @@ function registerWatchdog(runtime) {
|
|
|
57194
57473
|
let timer;
|
|
57195
57474
|
let acted = false;
|
|
57196
57475
|
let thought = "";
|
|
57476
|
+
let thoughtChars = 0;
|
|
57197
57477
|
let cuts = 0;
|
|
57198
57478
|
let spare = false;
|
|
57199
57479
|
let cut;
|
|
@@ -57210,9 +57490,9 @@ function registerWatchdog(runtime) {
|
|
|
57210
57490
|
timer = void 0;
|
|
57211
57491
|
if (message !== about || acted || cut !== void 0) return;
|
|
57212
57492
|
cuts++;
|
|
57213
|
-
cut = { ms: Date.now() - startedAt, tail: thought.slice(-TAIL_CHARS2) };
|
|
57493
|
+
cut = { about, ms: Date.now() - startedAt, tail: thought.slice(-TAIL_CHARS2) };
|
|
57214
57494
|
runtime.harnessAbort = true;
|
|
57215
|
-
runtime.present("watchdog.cut", { thinkingMs: cut.ms, thoughtChars
|
|
57495
|
+
runtime.present("watchdog.cut", { thinkingMs: cut.ms, thoughtChars });
|
|
57216
57496
|
ctx.abort();
|
|
57217
57497
|
}, after);
|
|
57218
57498
|
timer.unref();
|
|
@@ -57239,6 +57519,7 @@ function registerWatchdog(runtime) {
|
|
|
57239
57519
|
stopTimer();
|
|
57240
57520
|
acted = false;
|
|
57241
57521
|
thought = "";
|
|
57522
|
+
thoughtChars = 0;
|
|
57242
57523
|
if (spare) {
|
|
57243
57524
|
spare = false;
|
|
57244
57525
|
return void 0;
|
|
@@ -57253,6 +57534,7 @@ function registerWatchdog(runtime) {
|
|
|
57253
57534
|
const update = event.assistantMessageEvent;
|
|
57254
57535
|
if (update.type === "thinking_delta") {
|
|
57255
57536
|
thought += update.delta;
|
|
57537
|
+
thoughtChars += update.delta.length;
|
|
57256
57538
|
if (thought.length > 4 * TAIL_CHARS2) thought = thought.slice(-TAIL_CHARS2);
|
|
57257
57539
|
} else if (update.type === "text_delta" || update.type === "toolcall_start") {
|
|
57258
57540
|
acted = true;
|
|
@@ -57263,8 +57545,12 @@ function registerWatchdog(runtime) {
|
|
|
57263
57545
|
);
|
|
57264
57546
|
pi.on(
|
|
57265
57547
|
"message_end",
|
|
57266
|
-
failOpen((event) => {
|
|
57267
|
-
if (event.message.role
|
|
57548
|
+
failOpen((event, ctx) => {
|
|
57549
|
+
if (event.message.role !== "assistant") return void 0;
|
|
57550
|
+
stopTimer();
|
|
57551
|
+
if (cut?.about === message && cut.usage === void 0) {
|
|
57552
|
+
cut.usage = cutUsage(event.message, thoughtChars, cut.ms, ctx.model);
|
|
57553
|
+
}
|
|
57268
57554
|
return void 0;
|
|
57269
57555
|
})
|
|
57270
57556
|
);
|
|
@@ -57276,6 +57562,7 @@ function registerWatchdog(runtime) {
|
|
|
57276
57562
|
stopTimer();
|
|
57277
57563
|
if (was === void 0) return void 0;
|
|
57278
57564
|
spare = true;
|
|
57565
|
+
if (was.usage) pi.appendEntry(USAGE_ENTRY, was.usage);
|
|
57279
57566
|
const tail = was.tail.trim();
|
|
57280
57567
|
pi.sendMessage(
|
|
57281
57568
|
{
|
|
@@ -57394,7 +57681,7 @@ function kyrnJudgeExtension(pi) {
|
|
|
57394
57681
|
function registerKyrn(pi, options) {
|
|
57395
57682
|
delete process.env.ELECTRON_RUN_AS_NODE;
|
|
57396
57683
|
registerRejectionLog(pi);
|
|
57397
|
-
const loaded = options.config || options.provider ? { config: options.config ?? DEFAULT_CONFIG, disabled: false, problem: void 0 } : loadConfig({ dir: (0,
|
|
57684
|
+
const loaded = options.config || options.provider ? { config: options.config ?? DEFAULT_CONFIG, disabled: false, problem: void 0 } : loadConfig({ dir: (0, import_pi_coding_agent17.getAgentDir)(), env: process.env });
|
|
57398
57685
|
const config = loaded.disabled ? { ...loaded.config, tiers: ["mock"], modes: { default: "off" } } : options.mode ? { ...loaded.config, modes: { ...loaded.config.modes, default: options.mode } } : loaded.config;
|
|
57399
57686
|
const runtime = new KyrnRuntime(
|
|
57400
57687
|
pi,
|
|
@@ -57406,7 +57693,7 @@ function registerKyrn(pi, options) {
|
|
|
57406
57693
|
runtime.onPresentation = options.onPresentation;
|
|
57407
57694
|
for (const capability of options.capabilities ?? []) runtime.catalog.register(capability);
|
|
57408
57695
|
registerWelcome(runtime);
|
|
57409
|
-
const roots = options.roots ?? (options.config || options.provider ? void 0 : { home: homedir12(), agentDir: (0,
|
|
57696
|
+
const roots = options.roots ?? (options.config || options.provider ? void 0 : { home: homedir12(), agentDir: (0, import_pi_coding_agent17.getAgentDir)() });
|
|
57410
57697
|
runtime.stateDir = roots ? join49(roots.agentDir, "mu") : void 0;
|
|
57411
57698
|
if (loaded.disabled) {
|
|
57412
57699
|
if (!options.only || options.only.includes("permissions")) registerPermissions(runtime, roots);
|