bazilion 0.11.0 → 0.12.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/dist/cli.js +433 -146
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +1382 -232
- package/dist/daemon.js.map +1 -1
- package/dist/migrations/0001_init.sql +81 -0
- package/dist/web/client/assets/AgentTabs-R6gSjIj3.js +1 -0
- package/dist/web/client/assets/{ProductionTeamPolicyEditor-B6dbpuYy.js → ProductionTeamPolicyEditor-CSL3W7XM.js} +2 -2
- package/dist/web/client/assets/{ProfileCommunicationEditor-Bf8UvmZT.js → ProfileCommunicationEditor-CwU0QkmE.js} +1 -1
- package/dist/web/client/assets/{TeamTabs-sQBHChtd.js → TeamTabs-C1Hakkff.js} +1 -1
- package/dist/web/client/assets/{TemplatesTabs-DPsuwsWB.js → TemplatesTabs-klEydJ8-.js} +1 -1
- package/dist/web/client/assets/{_id-C9rkCclz.js → _id-BOC7ioJu.js} +1 -1
- package/dist/web/client/assets/{_id-DYASsGQ8.js → _id-CnVq-rED.js} +1 -1
- package/dist/web/client/assets/{_id-DE4IY5bL.js → _id-e4u7dmBb.js} +1 -1
- package/dist/web/client/assets/{_id-D65IzC8H.js → _id-wkjjWLz0.js} +1 -1
- package/dist/web/client/assets/{activity-C7o6-xHg.js → activity-uqhwzmiy.js} +1 -1
- package/dist/web/client/assets/{agents-UroO4d25.js → agents-B2usE-L_.js} +1 -1
- package/dist/web/client/assets/{agents-h8yWXQ2H.js → agents-FaQtkAWs.js} +1 -1
- package/dist/web/client/assets/{approvals-DKhF0YLC.js → approvals-DqLE6ttw.js} +1 -1
- package/dist/web/client/assets/attention-CkGozYnJ.js +1 -0
- package/dist/web/client/assets/attention-Gavt2yEp.js +1 -0
- package/dist/web/client/assets/chevron-down-CJk0zGNT.js +1 -0
- package/dist/web/client/assets/{config-q8JDresK.js → config-xrXoDEWM.js} +1 -1
- package/dist/web/client/assets/{context-CBucAoi6.js → context-ZWqx3uiC.js} +1 -1
- package/dist/web/client/assets/inbox-BoIvl9ZF.js +1 -0
- package/dist/web/client/assets/{index-DUXAevpZ.js → index-nb2MV8X1.js} +3 -3
- package/dist/web/client/assets/learning-6_oYn1l7.js +1 -0
- package/dist/web/client/assets/{login-CNAV9Wer.js → login-DM1ytxQL.js} +1 -1
- package/dist/web/client/assets/{mcp-BKdEFwHO.js → mcp-CetZbyUh.js} +1 -1
- package/dist/web/client/assets/{members-BDqZQh26.js → members-DdqWtwZd.js} +1 -1
- package/dist/web/client/assets/{memory-DVdEVr6L.js → memory-FNrxFHmC.js} +1 -1
- package/dist/web/client/assets/plus-C3GroITC.js +1 -0
- package/dist/web/client/assets/{policy-DdDctqvg.js → policy-BKPejYRI.js} +1 -1
- package/dist/web/client/assets/{routes-BEfALSZv.js → routes-CH1ZTTo-.js} +1 -1
- package/dist/web/client/assets/{services-DZP2ybzb.js → services-zk9SqN06.js} +1 -1
- package/dist/web/client/assets/{skills-DoeIjITs.js → skills-tXDpomHW.js} +1 -1
- package/dist/web/client/assets/styles-DMltY3su.css +2 -0
- package/dist/web/client/assets/{teams-W3j-UoJ9.js → teams-BZYjekBN.js} +1 -1
- package/dist/web/client/assets/{teams-DlHRnrQw.js → teams-D1c8zlxs.js} +1 -1
- package/dist/web/client/assets/{telegram-2OdeGv4E.js → telegram-DCe1CWMt.js} +1 -1
- package/dist/web/client/assets/{tokens-MuBfmgue.js → tokens-DAPjRS0N.js} +1 -1
- package/dist/web/client/assets/triggers-D8R-5guA.js +1 -0
- package/dist/web/client/assets/{welcome-CvNr5IMi.js → welcome-CuK0shDJ.js} +1 -1
- package/dist/web/server/assets/{AgentTabs-DoMDJBXH.js → AgentTabs-aXdsiiMp.js} +5 -0
- package/dist/web/server/assets/{_id-Cg7x6q3g.js → _id-BHYLL8M-.js} +2 -2
- package/dist/web/server/assets/{_id-DqON-59C.js → _id-FcHdSocl.js} +1 -1
- package/dist/web/server/assets/{_tanstack-start-manifest_v-BXauUXg6.js → _tanstack-start-manifest_v-fLsYERQ-.js} +76 -53
- package/dist/web/server/assets/attention-BW_6ddkj.js +11 -0
- package/dist/web/server/assets/attention-BxkTf337.js +14 -0
- package/dist/web/server/assets/attention-CM-Ks1N9.js +19 -0
- package/dist/web/server/assets/attention-w21GQIGH.js +264 -0
- package/dist/web/server/assets/{inbox-CUIyf9MT.js → inbox-BLUzA5sQ.js} +40 -3
- package/dist/web/server/assets/{inbox-B3-TRsNI.js → inbox-CzlKT9Wg.js} +5 -3
- package/dist/web/server/assets/{inbox-BardsGyy.js → inbox-ZvDNAjaM.js} +1 -1
- package/dist/web/server/assets/learning-8zav4pIT.js +33 -0
- package/dist/web/server/assets/learning-B7PBkvER.js +16 -0
- package/dist/web/server/assets/learning-Cq7K2heb.js +312 -0
- package/dist/web/server/assets/{router-C5_NjTsP.js → router-CQuj7553.js} +80 -47
- package/dist/web/server/assets/{triggers-CBl4yMyw.js → triggers-BZPl5CHs.js} +1 -1
- package/dist/web/server/assets/{triggers-_3rdhwSN.js → triggers-CSNNzRIi.js} +2 -2
- package/dist/web/server/server.js +11 -3
- package/dist/worker.js +166 -36
- package/dist/worker.js.map +1 -1
- package/package.json +3 -3
- package/dist/web/client/assets/AgentTabs-B3hq5a3e.js +0 -1
- package/dist/web/client/assets/chevron-down-BK6NPMMP.js +0 -1
- package/dist/web/client/assets/inbox-BwoRikj1.js +0 -1
- package/dist/web/client/assets/plus-b4yFXP0O.js +0 -1
- package/dist/web/client/assets/styles-BYM0UGdF.css +0 -2
- package/dist/web/client/assets/triggers-CX7RMQFQ.js +0 -1
package/dist/worker.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// ../daemon/src/runtime/worker/entry.ts
|
|
4
|
-
import { randomUUID as
|
|
4
|
+
import { randomUUID as randomUUID19 } from "crypto";
|
|
5
|
+
import { mkdtempSync as mkdtempSync3, rmSync as rmSync12 } from "fs";
|
|
5
6
|
import { join as join19 } from "path";
|
|
7
|
+
import { Type as Type3 } from "typebox";
|
|
6
8
|
|
|
7
9
|
// ../daemon/src/core/agent/delete.ts
|
|
8
10
|
import { randomUUID } from "crypto";
|
|
@@ -18,8 +20,11 @@ import { join as join2 } from "path";
|
|
|
18
20
|
// ../daemon/src/core/profile/identity.ts
|
|
19
21
|
import { readFileSync as readFileSync2 } from "fs";
|
|
20
22
|
|
|
21
|
-
// ../daemon/src/core/
|
|
23
|
+
// ../daemon/src/core/repos/agentLessonProposals.ts
|
|
22
24
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
25
|
+
|
|
26
|
+
// ../daemon/src/core/agent/spawn.ts
|
|
27
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
23
28
|
import { mkdirSync as mkdirSync3, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
24
29
|
import { join as join7 } from "path";
|
|
25
30
|
|
|
@@ -85,14 +90,17 @@ function resolvePaths(home) {
|
|
|
85
90
|
import { existsSync as existsSync6, rmSync as rmSync4 } from "fs";
|
|
86
91
|
|
|
87
92
|
// ../daemon/src/core/repos/teamTemplates.ts
|
|
88
|
-
import { randomUUID as
|
|
93
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
89
94
|
|
|
90
95
|
// ../daemon/src/core/profile/update.ts
|
|
91
96
|
import { writeFileSync as writeFileSync5 } from "fs";
|
|
92
97
|
import { join as join10 } from "path";
|
|
93
98
|
|
|
99
|
+
// ../daemon/src/core/repos/agentReviews.ts
|
|
100
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
101
|
+
|
|
94
102
|
// ../daemon/src/core/repos/communicationApprovals.ts
|
|
95
|
-
import { createHash, randomUUID as
|
|
103
|
+
import { createHash, randomUUID as randomUUID6 } from "crypto";
|
|
96
104
|
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
97
105
|
|
|
98
106
|
// ../daemon/src/core/services.ts
|
|
@@ -529,6 +537,13 @@ var SERVICES = [
|
|
|
529
537
|
label: "Extra environment allowlist",
|
|
530
538
|
placeholder: "MY_SAFE_VARIABLE,ANOTHER_SAFE_VARIABLE",
|
|
531
539
|
description: "Optional comma-separated variable names copied into the container. Provider credentials remain excluded unless explicitly named."
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
envVar: "BAZILION_AGENT_LOOP_MAX_HOPS",
|
|
543
|
+
kind: "config",
|
|
544
|
+
label: "Agent-message hop limit",
|
|
545
|
+
placeholder: "8",
|
|
546
|
+
description: "Maximum causal hops in an agent-to-agent message chain before the daemon stops it. Default 8."
|
|
532
547
|
}
|
|
533
548
|
]
|
|
534
549
|
},
|
|
@@ -634,22 +649,22 @@ var CONFIG_KEYS = [
|
|
|
634
649
|
var CONFIG_KEY_SET = new Set(CONFIG_KEYS);
|
|
635
650
|
|
|
636
651
|
// ../daemon/src/core/repos/mcpServers.ts
|
|
637
|
-
import { randomUUID as
|
|
652
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
638
653
|
|
|
639
654
|
// ../daemon/src/core/repos/messages.ts
|
|
640
|
-
import { randomUUID as
|
|
655
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
641
656
|
|
|
642
657
|
// ../daemon/src/core/repos/secrets.ts
|
|
643
658
|
import { createCipheriv, createDecipheriv, pbkdf2Sync, randomBytes } from "crypto";
|
|
644
659
|
|
|
645
660
|
// ../daemon/src/core/repos/triggerDispatches.ts
|
|
646
|
-
import { randomUUID as
|
|
661
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
647
662
|
|
|
648
663
|
// ../daemon/src/core/repos/triggers.ts
|
|
649
|
-
import { randomUUID as
|
|
664
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
650
665
|
|
|
651
666
|
// ../daemon/src/core/repos/webTokens.ts
|
|
652
|
-
import { createHash as createHash2, randomBytes as randomBytes2, randomUUID as
|
|
667
|
+
import { createHash as createHash2, randomBytes as randomBytes2, randomUUID as randomUUID11 } from "crypto";
|
|
653
668
|
|
|
654
669
|
// ../daemon/src/core/secrets.ts
|
|
655
670
|
import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
|
|
@@ -695,20 +710,20 @@ function parseSkillFile(path) {
|
|
|
695
710
|
}
|
|
696
711
|
|
|
697
712
|
// ../daemon/src/core/team/delete.ts
|
|
698
|
-
import { randomUUID as
|
|
713
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
699
714
|
import { existsSync as existsSync9, renameSync as renameSync2, rmSync as rmSync6 } from "fs";
|
|
700
715
|
|
|
701
716
|
// ../daemon/src/core/team-policy/adopt.ts
|
|
702
|
-
import { randomUUID as
|
|
717
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
703
718
|
|
|
704
719
|
// ../daemon/src/core/team-policy/authorization.ts
|
|
705
|
-
import { createHash as createHash3, randomUUID as
|
|
720
|
+
import { createHash as createHash3, randomUUID as randomUUID14 } from "crypto";
|
|
706
721
|
|
|
707
722
|
// ../daemon/src/core/team-policy/source.ts
|
|
708
|
-
import { randomUUID as
|
|
723
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
709
724
|
|
|
710
725
|
// ../daemon/src/core/team-policy/spawn.ts
|
|
711
|
-
import { randomUUID as
|
|
726
|
+
import { randomUUID as randomUUID16 } from "crypto";
|
|
712
727
|
import { readdirSync as readdirSync4, rmSync as rmSync8 } from "fs";
|
|
713
728
|
|
|
714
729
|
// ../daemon/src/core/team-policy/rm-with-retry.ts
|
|
@@ -1348,11 +1363,34 @@ ${agent.team.userMd.trim()}`
|
|
|
1348
1363
|
This team's USER.md is empty. As you learn STABLE facts about the human (preferences, role, working hours, how they like to be addressed), populate it via \`user_md_get\` then \`user_md_write\` (always get first \u2014 you need the etag). Reserve this for things you're confident are durable \u2014 project knowledge belongs in \`memory_write\`, personal notes about yourself in \`home_write\` on IDENTITY.md. **Do NOT send peer messages announcing USER.md changes \u2014 every agent in the team sees the new content in their system prompt on their next turn automatically.**`
|
|
1349
1364
|
);
|
|
1350
1365
|
}
|
|
1366
|
+
const reviewedLessons = boundReviewedLessons(agent.privateLessons);
|
|
1367
|
+
if (reviewedLessons.length > 0) {
|
|
1368
|
+
parts.push(
|
|
1369
|
+
`# Reviewed lessons
|
|
1370
|
+
|
|
1371
|
+
These private lessons were explicitly approved by the human for your behavior. Follow them when relevant; current user instructions and higher-priority policy still win.
|
|
1372
|
+
|
|
1373
|
+
${reviewedLessons.map((lesson) => `- ${lesson}`).join("\n")}`
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1351
1376
|
parts.push(
|
|
1352
1377
|
"# Memory\n\nYou share a persistent memory backend with every other agent in this team. Use `memory_write` to remember things across sessions, and `memory_search` / `memory_read` / `memory_list` to recall them. This memory is for project knowledge \u2014 codebase notes, decisions, things the user told you about the work. For personal notes about yourself (preferences, persona quirks), use `home_write` on IDENTITY.md instead. Always check memory at the start of a session: another agent in the team may have already learned something useful. **Do NOT send peer messages announcing memory writes \u2014 every agent has access to the same store via `memory_search` and will find your note when they need it.**"
|
|
1353
1378
|
);
|
|
1354
1379
|
return parts.join("\n\n---\n\n");
|
|
1355
1380
|
}
|
|
1381
|
+
function boundReviewedLessons(lessons, maxCharacters = 8e3) {
|
|
1382
|
+
const selected = [];
|
|
1383
|
+
let used = 0;
|
|
1384
|
+
for (const raw of lessons) {
|
|
1385
|
+
const lesson = raw.trim();
|
|
1386
|
+
if (!lesson) continue;
|
|
1387
|
+
const remaining = maxCharacters - used;
|
|
1388
|
+
if (remaining <= 0) break;
|
|
1389
|
+
selected.push(lesson.slice(0, remaining));
|
|
1390
|
+
used += Math.min(lesson.length, remaining);
|
|
1391
|
+
}
|
|
1392
|
+
return selected;
|
|
1393
|
+
}
|
|
1356
1394
|
|
|
1357
1395
|
// ../daemon/src/runtime/shell/tooling.ts
|
|
1358
1396
|
import { existsSync as existsSync11, lstatSync as lstatSync2, realpathSync as realpathSync2 } from "fs";
|
|
@@ -1743,7 +1781,7 @@ function createApprovalGatedBashTool(base, host) {
|
|
|
1743
1781
|
|
|
1744
1782
|
// ../daemon/src/runtime/shell/docker.ts
|
|
1745
1783
|
import { spawn } from "child_process";
|
|
1746
|
-
import { randomUUID as
|
|
1784
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
1747
1785
|
import { closeSync as closeSync2, constants as constants2, mkdtempSync as mkdtempSync2, openSync as openSync2, rmSync as rmSync10, writeFileSync as writeFileSync7 } from "fs";
|
|
1748
1786
|
import { access, realpath, stat } from "fs/promises";
|
|
1749
1787
|
import { tmpdir as tmpdir2 } from "os";
|
|
@@ -1894,7 +1932,7 @@ function createDockerBashOperations(options) {
|
|
|
1894
1932
|
const dockerClientEnv = await resolveLocalDockerClientEnv(dockerPath, hostEnv);
|
|
1895
1933
|
const resolvedImage = await inspectSandboxImage(dockerPath, image, dockerClientEnv);
|
|
1896
1934
|
if (signal?.aborted) throw new Error("aborted");
|
|
1897
|
-
const containerName = `bazilion-bash-${process.pid}-${
|
|
1935
|
+
const containerName = `bazilion-bash-${process.pid}-${randomUUID17().replaceAll("-", "")}`;
|
|
1898
1936
|
const spec = buildDockerRunSpec({
|
|
1899
1937
|
image,
|
|
1900
1938
|
env,
|
|
@@ -3668,7 +3706,8 @@ async function createBazilionSession(opts) {
|
|
|
3668
3706
|
mcpTools,
|
|
3669
3707
|
fileSink,
|
|
3670
3708
|
bashApprovalHost,
|
|
3671
|
-
refreshApiKey
|
|
3709
|
+
refreshApiKey,
|
|
3710
|
+
restricted
|
|
3672
3711
|
} = opts;
|
|
3673
3712
|
const { providerName, modelId } = splitModelString(agent.model);
|
|
3674
3713
|
if (enabledProviders.size > 0 && !enabledProviders.has(providerName)) {
|
|
@@ -3700,9 +3739,9 @@ async function createBazilionSession(opts) {
|
|
|
3700
3739
|
}
|
|
3701
3740
|
const cwd = agent.team.path;
|
|
3702
3741
|
if (!existsSync13(cwd)) mkdirSync5(cwd, { recursive: true });
|
|
3703
|
-
const promptSkills = loadPromptSkills(paths.skillsDir, agent.skills);
|
|
3742
|
+
const promptSkills = restricted ? [] : loadPromptSkills(paths.skillsDir, agent.skills);
|
|
3704
3743
|
const uploadsDir = join18(agent.agent.dir, "uploads");
|
|
3705
|
-
const shellTools = createSessionShellTools(cwd, env, {
|
|
3744
|
+
const shellTools = restricted ? null : createSessionShellTools(cwd, env, {
|
|
3706
3745
|
...existsSync13(uploadsDir) ? { inputsDir: uploadsDir } : {},
|
|
3707
3746
|
skillMounts: promptSkills.map((skill) => ({
|
|
3708
3747
|
source: skill.hostDir,
|
|
@@ -3710,9 +3749,9 @@ async function createBazilionSession(opts) {
|
|
|
3710
3749
|
})),
|
|
3711
3750
|
approvalHost: bashApprovalHost
|
|
3712
3751
|
});
|
|
3713
|
-
const sessionDir = join18(paths.agentDir(agent.agent.id), "sessions");
|
|
3752
|
+
const sessionDir = restricted?.sessionDir ?? join18(paths.agentDir(agent.agent.id), "sessions");
|
|
3714
3753
|
mkdirSync5(sessionDir, { recursive: true });
|
|
3715
|
-
const existing = findMostRecent(sessionDir);
|
|
3754
|
+
const existing = restricted ? null : findMostRecent(sessionDir);
|
|
3716
3755
|
const sessionManager = existing ? SessionManager.open(existing, sessionDir, cwd) : SessionManager.create(cwd, sessionDir);
|
|
3717
3756
|
const settingsManager = SettingsManager.inMemory({
|
|
3718
3757
|
compaction: { enabled: false },
|
|
@@ -3723,13 +3762,13 @@ async function createBazilionSession(opts) {
|
|
|
3723
3762
|
provider: { maxRetryDelayMs: 8e3 }
|
|
3724
3763
|
}
|
|
3725
3764
|
});
|
|
3726
|
-
const bazilionPrompt = buildSystemPrompt(agent, {
|
|
3765
|
+
const bazilionPrompt = restricted?.systemPrompt ?? buildSystemPrompt(agent, {
|
|
3727
3766
|
skills: promptSkills,
|
|
3728
|
-
sandboxMode: shellTools
|
|
3767
|
+
sandboxMode: shellTools?.config.sandboxMode ?? "off"
|
|
3729
3768
|
});
|
|
3730
3769
|
const resourceLoader = createBazilionResourceLoader(bazilionPrompt);
|
|
3731
3770
|
await resourceLoader.reload();
|
|
3732
|
-
const bazilionTools = createBazilionCustomTools({
|
|
3771
|
+
const bazilionTools = restricted ? restricted.tools : createBazilionCustomTools({
|
|
3733
3772
|
agent,
|
|
3734
3773
|
memory,
|
|
3735
3774
|
messagingHost,
|
|
@@ -3740,13 +3779,13 @@ async function createBazilionSession(opts) {
|
|
|
3740
3779
|
fileSink,
|
|
3741
3780
|
env
|
|
3742
3781
|
});
|
|
3743
|
-
const customTools = shellTools
|
|
3744
|
-
const allowedTools = [...shellTools
|
|
3782
|
+
const customTools = shellTools?.customBash ? [...bazilionTools, shellTools.customBash] : bazilionTools;
|
|
3783
|
+
const allowedTools = [...shellTools?.hostToolNames ?? [], ...customTools.map((t) => t.name)];
|
|
3745
3784
|
const { session } = await createAgentSession({
|
|
3746
3785
|
cwd,
|
|
3747
3786
|
agentDir: join18(paths.home, "pi"),
|
|
3748
3787
|
model,
|
|
3749
|
-
thinkingLevel: toPiThinkingLevel(agent.reasoningLevel),
|
|
3788
|
+
thinkingLevel: toPiThinkingLevel(restricted?.reasoningLevel ?? agent.reasoningLevel),
|
|
3750
3789
|
tools: allowedTools,
|
|
3751
3790
|
customTools,
|
|
3752
3791
|
sessionManager,
|
|
@@ -3902,7 +3941,7 @@ function assertOpenAICodexProvider(requested, expected) {
|
|
|
3902
3941
|
}
|
|
3903
3942
|
|
|
3904
3943
|
// ../daemon/src/runtime/worker/ipc-client.ts
|
|
3905
|
-
import { randomUUID as
|
|
3944
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
3906
3945
|
function createIpcClient(channel) {
|
|
3907
3946
|
const pending = /* @__PURE__ */ new Map();
|
|
3908
3947
|
let disconnected = false;
|
|
@@ -3929,7 +3968,7 @@ function createIpcClient(channel) {
|
|
|
3929
3968
|
if (!send) {
|
|
3930
3969
|
return Promise.reject(new Error("worker: no IPC channel \u2014 daemon must spawn with stdio:ipc"));
|
|
3931
3970
|
}
|
|
3932
|
-
const id =
|
|
3971
|
+
const id = randomUUID18();
|
|
3933
3972
|
const message = { type: "rpc", id, method, args };
|
|
3934
3973
|
return new Promise((resolve5, reject) => {
|
|
3935
3974
|
pending.set(id, { resolve: (value) => resolve5(value), reject });
|
|
@@ -3968,6 +4007,9 @@ async function readInput() {
|
|
|
3968
4007
|
"worker: stdin must include {agent, message, enabledProviders, turnId, bashApprovalMode}"
|
|
3969
4008
|
);
|
|
3970
4009
|
}
|
|
4010
|
+
if (parsed.mode === "review" && !parsed.review?.reviewId) {
|
|
4011
|
+
throw new Error("worker: review mode requires review metadata");
|
|
4012
|
+
}
|
|
3971
4013
|
const providerName = parsed.agent.model.split(":", 1)[0] ?? "";
|
|
3972
4014
|
if (parsed.apiKeyRefreshEnabled && (providerName !== "openai-codex" || typeof parsed.apiKey !== "string")) {
|
|
3973
4015
|
throw new Error("worker: API key refresh requires an openai-codex turn with an initial token");
|
|
@@ -4006,7 +4048,7 @@ function createIpcBashApprovalHost(call, input) {
|
|
|
4006
4048
|
return {
|
|
4007
4049
|
async requestApproval(request) {
|
|
4008
4050
|
const result = await call("bashApproval", {
|
|
4009
|
-
id:
|
|
4051
|
+
id: randomUUID19(),
|
|
4010
4052
|
turnId: input.turnId,
|
|
4011
4053
|
toolCallId: request.toolCallId,
|
|
4012
4054
|
agentId: input.agent.agent.id,
|
|
@@ -4046,7 +4088,9 @@ async function main() {
|
|
|
4046
4088
|
mcpTools,
|
|
4047
4089
|
images,
|
|
4048
4090
|
turnId,
|
|
4049
|
-
bashApprovalMode
|
|
4091
|
+
bashApprovalMode,
|
|
4092
|
+
mode = "chat",
|
|
4093
|
+
review
|
|
4050
4094
|
} = await readInput();
|
|
4051
4095
|
const paths = resolvePaths();
|
|
4052
4096
|
const memory = qmdBackend(join19(agent.team.path, "memory"));
|
|
@@ -4072,6 +4116,52 @@ async function main() {
|
|
|
4072
4116
|
turnId,
|
|
4073
4117
|
bashApprovalMode
|
|
4074
4118
|
});
|
|
4119
|
+
const reviewSessionDir = mode === "review" ? mkdtempSync3(join19(paths.logsDir, "review-session-")) : null;
|
|
4120
|
+
const proposals = [];
|
|
4121
|
+
let proposalBatchSubmitted = false;
|
|
4122
|
+
const allowedEvidence = new Set(
|
|
4123
|
+
(review?.evidence ?? []).map((item) => `${item.sessionId}:${item.entryOrdinal}`)
|
|
4124
|
+
);
|
|
4125
|
+
const reviewTools = [
|
|
4126
|
+
{
|
|
4127
|
+
name: "propose_lesson",
|
|
4128
|
+
label: "propose_lesson",
|
|
4129
|
+
description: "Submit zero to five evidence-backed lesson proposals in one final batch. This is the only available action.",
|
|
4130
|
+
parameters: Type3.Object({
|
|
4131
|
+
proposals: Type3.Array(
|
|
4132
|
+
Type3.Object({
|
|
4133
|
+
scope: Type3.Union([Type3.Literal("private"), Type3.Literal("shared")]),
|
|
4134
|
+
text: Type3.String({ minLength: 1, maxLength: 500 }),
|
|
4135
|
+
evidenceEntryIds: Type3.Array(
|
|
4136
|
+
Type3.Object({ sessionId: Type3.String(), entryOrdinal: Type3.Integer({ minimum: 0 }) }),
|
|
4137
|
+
{ minItems: 1 }
|
|
4138
|
+
)
|
|
4139
|
+
}),
|
|
4140
|
+
{ maxItems: 5 }
|
|
4141
|
+
)
|
|
4142
|
+
}),
|
|
4143
|
+
async execute(_toolCallId, params) {
|
|
4144
|
+
if (proposalBatchSubmitted) throw new Error("propose_lesson may be called only once");
|
|
4145
|
+
proposalBatchSubmitted = true;
|
|
4146
|
+
const input = params;
|
|
4147
|
+
for (const candidate of input.proposals) {
|
|
4148
|
+
const text = candidate.text.trim();
|
|
4149
|
+
if (!text || text.length > 500) throw new Error("proposal text must be 1-500 characters");
|
|
4150
|
+
for (const evidence of candidate.evidenceEntryIds) {
|
|
4151
|
+
if (!allowedEvidence.has(`${evidence.sessionId}:${evidence.entryOrdinal}`)) {
|
|
4152
|
+
throw new Error("proposal cites evidence outside the supplied digest");
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4155
|
+
proposals.push({ ...candidate, text });
|
|
4156
|
+
}
|
|
4157
|
+
return {
|
|
4158
|
+
content: [{ type: "text", text: `accepted ${proposals.length} proposals` }],
|
|
4159
|
+
details: {},
|
|
4160
|
+
terminate: true
|
|
4161
|
+
};
|
|
4162
|
+
}
|
|
4163
|
+
}
|
|
4164
|
+
];
|
|
4075
4165
|
const { session, dispose } = await createBazilionSession({
|
|
4076
4166
|
agent,
|
|
4077
4167
|
paths,
|
|
@@ -4087,12 +4177,25 @@ async function main() {
|
|
|
4087
4177
|
mcpTools,
|
|
4088
4178
|
bashApprovalHost,
|
|
4089
4179
|
// deliver_file emits a `file` event straight onto our stdout frame stream.
|
|
4090
|
-
fileSink: (f) => emit({ kind: "event", event: { type: "file", ...f } })
|
|
4180
|
+
fileSink: (f) => emit({ kind: "event", event: { type: "file", ...f } }),
|
|
4181
|
+
...mode === "review" && reviewSessionDir ? {
|
|
4182
|
+
restricted: {
|
|
4183
|
+
systemPrompt: REVIEW_SYSTEM_PROMPT,
|
|
4184
|
+
tools: reviewTools,
|
|
4185
|
+
sessionDir: reviewSessionDir,
|
|
4186
|
+
reasoningLevel: agent.agent.reviewReasoningLevel
|
|
4187
|
+
}
|
|
4188
|
+
} : {}
|
|
4091
4189
|
});
|
|
4092
4190
|
abortSession = () => {
|
|
4093
4191
|
void session.abort();
|
|
4094
4192
|
};
|
|
4193
|
+
let reviewValidationFailures = 0;
|
|
4095
4194
|
const unsubscribe = session.subscribe((piEvent) => {
|
|
4195
|
+
if (mode === "review" && piEvent.type === "tool_execution_end" && piEvent.toolName === "propose_lesson" && piEvent.isError) {
|
|
4196
|
+
reviewValidationFailures += 1;
|
|
4197
|
+
if (reviewValidationFailures >= 2) void session.abort();
|
|
4198
|
+
}
|
|
4096
4199
|
for (const ev of translatePiEvent(piEvent)) {
|
|
4097
4200
|
emit({ kind: "event", event: ev });
|
|
4098
4201
|
}
|
|
@@ -4105,10 +4208,19 @@ async function main() {
|
|
|
4105
4208
|
}));
|
|
4106
4209
|
await session.prompt(message, promptImages.length > 0 ? { images: promptImages } : void 0);
|
|
4107
4210
|
await session.agent.waitForIdle();
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4211
|
+
if (mode === "review" && reviewValidationFailures >= 2) {
|
|
4212
|
+
throw new Error("review output remained invalid after one schema-repair attempt");
|
|
4213
|
+
}
|
|
4214
|
+
if (mode === "review" && !proposalBatchSubmitted) {
|
|
4215
|
+
throw new Error("review output did not submit a proposal batch");
|
|
4216
|
+
}
|
|
4217
|
+
if (mode === "review") emit({ kind: "review_result", proposals });
|
|
4218
|
+
else {
|
|
4219
|
+
emit({
|
|
4220
|
+
kind: "done",
|
|
4221
|
+
messages: piMessagesToProviderView(session.agent.state.messages)
|
|
4222
|
+
});
|
|
4223
|
+
}
|
|
4112
4224
|
} catch (err) {
|
|
4113
4225
|
if (!aborted) {
|
|
4114
4226
|
emit({ kind: "event", event: { type: "error", error: err.message } });
|
|
@@ -4120,6 +4232,7 @@ async function main() {
|
|
|
4120
4232
|
process.off("SIGTERM", onSignal);
|
|
4121
4233
|
process.off("SIGINT", onSignal);
|
|
4122
4234
|
dispose();
|
|
4235
|
+
if (reviewSessionDir) rmSync12(reviewSessionDir, { recursive: true, force: true });
|
|
4123
4236
|
try {
|
|
4124
4237
|
process.disconnect?.();
|
|
4125
4238
|
} catch {
|
|
@@ -4133,4 +4246,21 @@ main().catch((err) => {
|
|
|
4133
4246
|
}
|
|
4134
4247
|
process.exit(1);
|
|
4135
4248
|
});
|
|
4249
|
+
var REVIEW_SYSTEM_PROMPT = `You are a restricted learning reviewer. Analyze only the supplied
|
|
4250
|
+
transcript digest and approved-lesson index. You cannot act on the world. Call propose_lesson once
|
|
4251
|
+
with zero to five proposals, then stop.
|
|
4252
|
+
|
|
4253
|
+
If propose_lesson rejects malformed output, correct the schema exactly once. If that repair is also
|
|
4254
|
+
rejected, stop; the review will fail.
|
|
4255
|
+
|
|
4256
|
+
Classify before proposing:
|
|
4257
|
+
1. Stable human preference or biography belongs to USER.md: do not propose it.
|
|
4258
|
+
2. Agent-specific verified behavior or strategy is private.
|
|
4259
|
+
3. Reusable verified Team project knowledge, decisions, or procedures are shared.
|
|
4260
|
+
4. Everything else produces no proposal.
|
|
4261
|
+
|
|
4262
|
+
Zero proposals is a successful result. Never save transient or environment-dependent failures,
|
|
4263
|
+
unresolved attempts, guesses, contradicted claims, one-off narratives, status updates, secrets,
|
|
4264
|
+
credentials, sensitive personal data, raw logs, copied text, or duplicates. Each proposal must cite
|
|
4265
|
+
at least one supplied evidence entry and one observation may appear in only one proposal.`;
|
|
4136
4266
|
//# sourceMappingURL=worker.js.map
|