@caupulican/pi-adaptative 0.79.0 → 0.80.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 +11 -0
- package/dist/core/agent-session.d.ts +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +34 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/resource-loader.d.ts +1 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +26 -1
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-manager.d.ts +12 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +16 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +2 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +4 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +98 -3
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +12 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +330 -18
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/settings.md +30 -6
- package/docs/usage.md +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -89,6 +89,7 @@ function isDeadTerminalError(error) {
|
|
|
89
89
|
}
|
|
90
90
|
const ANTHROPIC_SUBSCRIPTION_AUTH_WARNING = "Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage.";
|
|
91
91
|
const AUTO_LEARN_DEFAULTS = {
|
|
92
|
+
enabled: false,
|
|
92
93
|
model: "active",
|
|
93
94
|
longSessionMessages: 32,
|
|
94
95
|
longSessionContextPercent: 70,
|
|
@@ -96,7 +97,53 @@ const AUTO_LEARN_DEFAULTS = {
|
|
|
96
97
|
leaseMinutes: 90,
|
|
97
98
|
maxConcurrentLearners: 2,
|
|
98
99
|
applyHighConfidence: false,
|
|
100
|
+
reflectionReview: true,
|
|
101
|
+
reflectionMinToolCalls: 5,
|
|
102
|
+
reflectionCooldownMinutes: 60,
|
|
99
103
|
};
|
|
104
|
+
const AUTONOMY_AUTO_LEARN_PRESETS = {
|
|
105
|
+
off: { ...AUTO_LEARN_DEFAULTS, enabled: false, reflectionReview: false },
|
|
106
|
+
safe: {
|
|
107
|
+
...AUTO_LEARN_DEFAULTS,
|
|
108
|
+
enabled: true,
|
|
109
|
+
longSessionMessages: 48,
|
|
110
|
+
longSessionContextPercent: 80,
|
|
111
|
+
cooldownMinutes: 180,
|
|
112
|
+
leaseMinutes: 60,
|
|
113
|
+
maxConcurrentLearners: 1,
|
|
114
|
+
applyHighConfidence: false,
|
|
115
|
+
reflectionReview: true,
|
|
116
|
+
reflectionMinToolCalls: 8,
|
|
117
|
+
reflectionCooldownMinutes: 120,
|
|
118
|
+
},
|
|
119
|
+
balanced: {
|
|
120
|
+
...AUTO_LEARN_DEFAULTS,
|
|
121
|
+
enabled: true,
|
|
122
|
+
longSessionMessages: 32,
|
|
123
|
+
longSessionContextPercent: 70,
|
|
124
|
+
cooldownMinutes: 120,
|
|
125
|
+
leaseMinutes: 90,
|
|
126
|
+
maxConcurrentLearners: 2,
|
|
127
|
+
applyHighConfidence: false,
|
|
128
|
+
reflectionReview: true,
|
|
129
|
+
reflectionMinToolCalls: 5,
|
|
130
|
+
reflectionCooldownMinutes: 60,
|
|
131
|
+
},
|
|
132
|
+
full: {
|
|
133
|
+
...AUTO_LEARN_DEFAULTS,
|
|
134
|
+
enabled: true,
|
|
135
|
+
longSessionMessages: 8,
|
|
136
|
+
longSessionContextPercent: 50,
|
|
137
|
+
cooldownMinutes: 15,
|
|
138
|
+
leaseMinutes: 90,
|
|
139
|
+
maxConcurrentLearners: 3,
|
|
140
|
+
applyHighConfidence: true,
|
|
141
|
+
reflectionReview: true,
|
|
142
|
+
reflectionMinToolCalls: 1,
|
|
143
|
+
reflectionCooldownMinutes: 0,
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
const AUTONOMY_MODES = ["off", "safe", "balanced", "full"];
|
|
100
147
|
function isAnthropicSubscriptionAuthKey(apiKey) {
|
|
101
148
|
return typeof apiKey === "string" && apiKey.startsWith("sk-ant-oat");
|
|
102
149
|
}
|
|
@@ -2067,6 +2114,11 @@ export class InteractiveMode {
|
|
|
2067
2114
|
this.editor.setText("");
|
|
2068
2115
|
return;
|
|
2069
2116
|
}
|
|
2117
|
+
if (text === "/autonomy" || text.startsWith("/autonomy ")) {
|
|
2118
|
+
this.handleAutonomyCommand(text);
|
|
2119
|
+
this.editor.setText("");
|
|
2120
|
+
return;
|
|
2121
|
+
}
|
|
2070
2122
|
if (text === "/scoped-models") {
|
|
2071
2123
|
this.editor.setText("");
|
|
2072
2124
|
await this.showModelsSelector();
|
|
@@ -2388,7 +2440,9 @@ export class InteractiveMode {
|
|
|
2388
2440
|
break;
|
|
2389
2441
|
}
|
|
2390
2442
|
case "agent_end":
|
|
2391
|
-
this.maybeStartAutoLearn()
|
|
2443
|
+
if (!this.maybeStartAutoLearn()) {
|
|
2444
|
+
this.maybeStartAutonomyReview(event.messages);
|
|
2445
|
+
}
|
|
2392
2446
|
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2393
2447
|
this.ui.terminal.setProgress(false);
|
|
2394
2448
|
}
|
|
@@ -3395,17 +3449,25 @@ export class InteractiveMode {
|
|
|
3395
3449
|
}
|
|
3396
3450
|
return { ...state, runs };
|
|
3397
3451
|
}
|
|
3452
|
+
getAutoLearnPresetForAutonomyMode(mode, current = {}) {
|
|
3453
|
+
const preset = AUTONOMY_AUTO_LEARN_PRESETS[mode] ?? AUTONOMY_AUTO_LEARN_PRESETS.off;
|
|
3454
|
+
return { ...preset, model: current.model?.trim() || preset.model };
|
|
3455
|
+
}
|
|
3398
3456
|
getEffectiveAutoLearnSettings() {
|
|
3399
3457
|
const settings = this.settingsManager.getAutoLearnSettings();
|
|
3458
|
+
const preset = this.getAutoLearnPresetForAutonomyMode(this.settingsManager.getAutonomySettings().mode, settings);
|
|
3400
3459
|
return {
|
|
3401
|
-
enabled: settings.enabled ??
|
|
3402
|
-
model: settings.model?.trim() ||
|
|
3403
|
-
longSessionMessages: settings.longSessionMessages ??
|
|
3404
|
-
longSessionContextPercent: settings.longSessionContextPercent ??
|
|
3405
|
-
cooldownMinutes: settings.cooldownMinutes ??
|
|
3406
|
-
leaseMinutes: settings.leaseMinutes ??
|
|
3407
|
-
maxConcurrentLearners: settings.maxConcurrentLearners ??
|
|
3408
|
-
applyHighConfidence: settings.applyHighConfidence ??
|
|
3460
|
+
enabled: settings.enabled ?? preset.enabled,
|
|
3461
|
+
model: settings.model?.trim() || preset.model,
|
|
3462
|
+
longSessionMessages: settings.longSessionMessages ?? preset.longSessionMessages,
|
|
3463
|
+
longSessionContextPercent: settings.longSessionContextPercent ?? preset.longSessionContextPercent,
|
|
3464
|
+
cooldownMinutes: settings.cooldownMinutes ?? preset.cooldownMinutes,
|
|
3465
|
+
leaseMinutes: settings.leaseMinutes ?? preset.leaseMinutes,
|
|
3466
|
+
maxConcurrentLearners: settings.maxConcurrentLearners ?? preset.maxConcurrentLearners,
|
|
3467
|
+
applyHighConfidence: settings.applyHighConfidence ?? preset.applyHighConfidence,
|
|
3468
|
+
reflectionReview: settings.reflectionReview ?? preset.reflectionReview,
|
|
3469
|
+
reflectionMinToolCalls: settings.reflectionMinToolCalls ?? preset.reflectionMinToolCalls,
|
|
3470
|
+
reflectionCooldownMinutes: settings.reflectionCooldownMinutes ?? preset.reflectionCooldownMinutes,
|
|
3409
3471
|
};
|
|
3410
3472
|
}
|
|
3411
3473
|
getAutoLearnTenantKey() {
|
|
@@ -3542,10 +3604,41 @@ export class InteractiveMode {
|
|
|
3542
3604
|
runningCount,
|
|
3543
3605
|
};
|
|
3544
3606
|
}
|
|
3545
|
-
|
|
3546
|
-
|
|
3607
|
+
buildAutonomyAuthorityPrompt() {
|
|
3608
|
+
const autonomy = this.settingsManager.getAutonomySettings();
|
|
3609
|
+
const selfModification = this.settingsManager.getSelfModificationSettings();
|
|
3610
|
+
if (autonomy.mode !== "full") {
|
|
3611
|
+
return [
|
|
3612
|
+
"Authority mode: proposal-gated.",
|
|
3613
|
+
"- You may autonomously query memory and run bounded learning tools.",
|
|
3614
|
+
"- Durable memory writes require the configured high-confidence policy; skills, extensions, source, settings, publishing, tagging, and releases remain proposals unless the foreground user explicitly asks.",
|
|
3615
|
+
].join("\n");
|
|
3616
|
+
}
|
|
3617
|
+
const sourceAuthority = selfModification.enabled && selfModification.sourcePath?.trim()
|
|
3618
|
+
? `- Pi source: standing authority to edit the authorized selfModification.sourcePath (${selfModification.sourcePath.trim()}) for self-evolution improvements; inspect git status first, preserve unrelated user changes, run focused validation, and leave a clear rollback/test summary.`
|
|
3619
|
+
: "- Pi source: no standing source-edit authority until selfModification.enabled and selfModification.sourcePath are set.";
|
|
3620
|
+
return [
|
|
3621
|
+
"Authority mode: FULL AUTONOMOUS standing grant.",
|
|
3622
|
+
"- Memory: may apply high-confidence durable Automata memory/corrections after duplicate and corroboration checks.",
|
|
3623
|
+
"- Skills: may create or patch user/project-owned procedural skills and support files; prefer updating existing umbrella skills; do not delete skills without making a recoverable archive/backup.",
|
|
3624
|
+
"- User/project extensions and tools: may create or patch small scoped extensions/tools under Pi user/project roots when they address repeated workflow/tooling gaps; validate and keep changes auditable.",
|
|
3625
|
+
"- Settings: may auto-tune autonomy/autoLearn settings to reduce bottlenecks; do not modify credentials, provider auth, package sources, or unrelated user preferences.",
|
|
3626
|
+
sourceAuthority,
|
|
3627
|
+
"- Hard stops without explicit foreground approval: publish, npm release, git push, tag creation, credential changes, destructive user-data deletion, network-exposed services, or authority expansion beyond this policy.",
|
|
3628
|
+
"- Audit: final output must list changed paths/settings, commands/tests run, evidence, residual risks, and rollback guidance. If no safe validation is possible, leave the change as a proposal instead of applying it.",
|
|
3629
|
+
].join("\n");
|
|
3547
3630
|
}
|
|
3548
|
-
|
|
3631
|
+
buildAutoLearnPrompt(reason, settings, options = {}) {
|
|
3632
|
+
const authorityBlock = this.buildAutonomyAuthorityPrompt();
|
|
3633
|
+
const reflectionBlock = options.kind === "reflection" && options.turnDigest
|
|
3634
|
+
? `\n\nLatest completed turn digest (bounded; use only as current-session evidence, not as longitudinal proof):\n<turn_digest>\n${options.turnDigest}\n</turn_digest>`
|
|
3635
|
+
: "";
|
|
3636
|
+
const objective = options.kind === "reflection"
|
|
3637
|
+
? "review the latest completed turn for durable memory, skill, validation, and tooling-improvement cues, then run one bounded continuous-learning pass if the learning tools are available"
|
|
3638
|
+
: "run one bounded continuous-learning pass for this Pi tenant";
|
|
3639
|
+
return `You are Pi Auto Learn running as a background learner.\n\nObjective: ${objective}.\nTrigger: ${reason}.\n\n${authorityBlock}\n\nRequired workflow:\n1. Query existing durable memory/rules first when tools allow it.\n2. Run the available Auto Learn tooling, preferably learning_run_auto, with applyHighConfidence=${settings.applyHighConfidence}.\n3. Treat the latest-turn digest as current-session evidence only; do not auto-commit one-off cues unless deterministic tooling corroborates them.\n4. In mode=full, apply safe memory/skill/user-extension/authorized-source improvements under the standing grant above; otherwise keep them proposal-gated.\n5. Never cross hard-stop boundaries from the authority policy.\n6. If the learning tools are unavailable, report BLOCKED with the missing tool names and do not improvise.\n7. Finish with PASS, BLOCKED, or FAIL and concise evidence.${reflectionBlock}`;
|
|
3640
|
+
}
|
|
3641
|
+
launchAutoLearn(reason, force = false, options = {}) {
|
|
3549
3642
|
const settings = this.getEffectiveAutoLearnSettings();
|
|
3550
3643
|
const decision = this.evaluateAutoLearn(force);
|
|
3551
3644
|
if (!decision.shouldRun) {
|
|
@@ -3563,8 +3656,14 @@ export class InteractiveMode {
|
|
|
3563
3656
|
fs.mkdirSync(dir, { recursive: true });
|
|
3564
3657
|
const runId = `${Date.now()}-${crypto.randomUUID().slice(0, 8)}`;
|
|
3565
3658
|
const logPath = path.join(dir, `${runId}.log`);
|
|
3659
|
+
const promptPath = path.join(dir, `${runId}.prompt.md`);
|
|
3566
3660
|
const outFd = fs.openSync(logPath, "a");
|
|
3567
|
-
const
|
|
3661
|
+
const kind = options.promptKind ?? "auto";
|
|
3662
|
+
const prompt = this.buildAutoLearnPrompt(reason, settings, {
|
|
3663
|
+
kind,
|
|
3664
|
+
turnDigest: options.turnDigest,
|
|
3665
|
+
});
|
|
3666
|
+
fs.writeFileSync(promptPath, prompt, "utf-8");
|
|
3568
3667
|
const args = [
|
|
3569
3668
|
...spawnTarget.argsPrefix,
|
|
3570
3669
|
"--print",
|
|
@@ -3584,7 +3683,15 @@ export class InteractiveMode {
|
|
|
3584
3683
|
fs.closeSync(outFd);
|
|
3585
3684
|
const now = Date.now();
|
|
3586
3685
|
const state = this.pruneAutoLearnState(this.readAutoLearnState(), now);
|
|
3587
|
-
|
|
3686
|
+
if (options.cooldownKind === "reflection") {
|
|
3687
|
+
state.lastReflectionByTenant = {
|
|
3688
|
+
...(state.lastReflectionByTenant ?? {}),
|
|
3689
|
+
[this.getAutoLearnTenantKey()]: now,
|
|
3690
|
+
};
|
|
3691
|
+
}
|
|
3692
|
+
else {
|
|
3693
|
+
state.lastLaunchByTenant = { ...(state.lastLaunchByTenant ?? {}), [this.getAutoLearnTenantKey()]: now };
|
|
3694
|
+
}
|
|
3588
3695
|
state.runs = {
|
|
3589
3696
|
...(state.runs ?? {}),
|
|
3590
3697
|
[runId]: {
|
|
@@ -3596,6 +3703,12 @@ export class InteractiveMode {
|
|
|
3596
3703
|
expiresAt: now + settings.leaseMinutes * 60 * 1000,
|
|
3597
3704
|
cwd: this.sessionManager.getCwd(),
|
|
3598
3705
|
logPath,
|
|
3706
|
+
promptPath,
|
|
3707
|
+
kind,
|
|
3708
|
+
autonomyMode: this.settingsManager.getAutonomySettings().mode,
|
|
3709
|
+
authority: this.settingsManager.getAutonomySettings().mode === "full"
|
|
3710
|
+
? "standing-full-autonomous"
|
|
3711
|
+
: "proposal-gated",
|
|
3599
3712
|
},
|
|
3600
3713
|
};
|
|
3601
3714
|
this.writeAutoLearnState(state);
|
|
@@ -3603,17 +3716,159 @@ export class InteractiveMode {
|
|
|
3603
3716
|
this.updateAutoLearnFooter();
|
|
3604
3717
|
return `Auto Learn started (${reason}) with ${modelPattern}. Log: ${logPath}`;
|
|
3605
3718
|
}
|
|
3719
|
+
sanitizeAutoLearnDigestText(text) {
|
|
3720
|
+
return text
|
|
3721
|
+
.replace(/-----BEGIN [A-Z ]*(?:PRIVATE|OPENSSH|RSA|DSA|EC) KEY-----[\s\S]*?-----END [A-Z ]*(?:PRIVATE|OPENSSH|RSA|DSA|EC) KEY-----/g, "[redacted-private-key]")
|
|
3722
|
+
.replace(/\b(?:sk|pk)-(?:proj-)?[A-Za-z0-9_-]{12,}/g, "[redacted-api-key]")
|
|
3723
|
+
.replace(/\bsk-ant-[A-Za-z0-9_-]{12,}/g, "[redacted-api-key]")
|
|
3724
|
+
.replace(/\b(?:ghp|gho|ghu|ghs|github_pat)_[A-Za-z0-9_]{20,}/g, "[redacted-github-token]")
|
|
3725
|
+
.replace(/\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g, "[redacted-aws-access-key]")
|
|
3726
|
+
.replace(/(?:Bearer\s+)[A-Za-z0-9._-]{16,}/gi, "Bearer [redacted]")
|
|
3727
|
+
.replace(/([?&](?:key|token|api_key|access_token|secret|password)=)[^&\s]+/gi, "$1[redacted]")
|
|
3728
|
+
.replace(/((?:access|refresh|token|apiKey|api_key|password|secret|authorization|auth)\s*[:=]\s*)[^\s,'"}]{8,}/gi, "$1[redacted]");
|
|
3729
|
+
}
|
|
3730
|
+
capAutoLearnDigestText(text, maxChars) {
|
|
3731
|
+
const compact = this.sanitizeAutoLearnDigestText(text).replace(/\s+/g, " ").trim();
|
|
3732
|
+
if (compact.length <= maxChars)
|
|
3733
|
+
return compact;
|
|
3734
|
+
return `${compact.slice(0, Math.max(0, maxChars - 20)).trimEnd()} …[truncated]`;
|
|
3735
|
+
}
|
|
3736
|
+
getAgentMessagePlainText(message) {
|
|
3737
|
+
const raw = message;
|
|
3738
|
+
const content = raw.content;
|
|
3739
|
+
if (typeof content === "string")
|
|
3740
|
+
return content;
|
|
3741
|
+
if (!Array.isArray(content))
|
|
3742
|
+
return "";
|
|
3743
|
+
const parts = [];
|
|
3744
|
+
for (const block of content) {
|
|
3745
|
+
if (!block || typeof block !== "object")
|
|
3746
|
+
continue;
|
|
3747
|
+
const item = block;
|
|
3748
|
+
if (item.type === "text" && typeof item.text === "string")
|
|
3749
|
+
parts.push(item.text);
|
|
3750
|
+
if (item.type === "toolCall" && typeof item.name === "string")
|
|
3751
|
+
parts.push(`[tool call: ${item.name}]`);
|
|
3752
|
+
}
|
|
3753
|
+
return parts.join("\n");
|
|
3754
|
+
}
|
|
3755
|
+
countAgentToolCalls(messages) {
|
|
3756
|
+
let toolCalls = 0;
|
|
3757
|
+
let toolResults = 0;
|
|
3758
|
+
for (const message of messages) {
|
|
3759
|
+
const raw = message;
|
|
3760
|
+
const role = String(raw.role ?? "");
|
|
3761
|
+
if (role === "toolResult" || role === "bashExecution")
|
|
3762
|
+
toolResults++;
|
|
3763
|
+
const content = raw.content;
|
|
3764
|
+
if (!Array.isArray(content))
|
|
3765
|
+
continue;
|
|
3766
|
+
for (const block of content) {
|
|
3767
|
+
if (block && typeof block === "object" && block.type === "toolCall") {
|
|
3768
|
+
toolCalls++;
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
return Math.max(toolCalls, toolResults);
|
|
3773
|
+
}
|
|
3774
|
+
buildAutonomyReviewDigest(messages) {
|
|
3775
|
+
const lines = [];
|
|
3776
|
+
for (const message of messages.slice(-18)) {
|
|
3777
|
+
const raw = message;
|
|
3778
|
+
const role = String(raw.role ?? "message");
|
|
3779
|
+
const label = role === "toolResult" && typeof raw.toolName === "string" ? `toolResult:${raw.toolName}` : role;
|
|
3780
|
+
const text = this.capAutoLearnDigestText(this.getAgentMessagePlainText(message), 700);
|
|
3781
|
+
if (text)
|
|
3782
|
+
lines.push(`${label}: ${text}`);
|
|
3783
|
+
}
|
|
3784
|
+
const digest = lines.join("\n---\n");
|
|
3785
|
+
return this.capAutoLearnDigestText(digest || "[No textual turn digest available.]", 6000);
|
|
3786
|
+
}
|
|
3787
|
+
evaluateAutonomyReview(messages) {
|
|
3788
|
+
const settings = this.getEffectiveAutoLearnSettings();
|
|
3789
|
+
const autonomy = this.settingsManager.getAutonomySettings();
|
|
3790
|
+
const state = this.pruneAutoLearnState(this.readAutoLearnState());
|
|
3791
|
+
this.writeAutoLearnState(state);
|
|
3792
|
+
const now = Date.now();
|
|
3793
|
+
const tenant = this.getAutoLearnTenantKey();
|
|
3794
|
+
const runningCount = Object.keys(state.runs ?? {}).length;
|
|
3795
|
+
const lastReflection = state.lastReflectionByTenant?.[tenant] ?? 0;
|
|
3796
|
+
const cooldownMs = settings.reflectionCooldownMinutes * 60 * 1000;
|
|
3797
|
+
const cooldownRemainingMs = Math.max(0, lastReflection + cooldownMs - now);
|
|
3798
|
+
const messageCount = this.getAutoLearnMessageCount();
|
|
3799
|
+
const contextPercent = this.session.getContextUsage()?.percent ?? null;
|
|
3800
|
+
const toolCalls = this.countAgentToolCalls(messages);
|
|
3801
|
+
const userText = messages
|
|
3802
|
+
.filter((message) => String(message.role ?? "") === "user")
|
|
3803
|
+
.map((message) => this.getAgentMessagePlainText(message))
|
|
3804
|
+
.join("\n");
|
|
3805
|
+
const correctionSignal = /\b(next time|for future|from now on|remember this|don't|do not|avoid|instead|you should|should have|you forgot|you missed|not what i asked|wrong again)\b/i.test(userText);
|
|
3806
|
+
const base = { messageCount, contextPercent, cooldownRemainingMs, runningCount, toolCalls };
|
|
3807
|
+
if (!settings.enabled)
|
|
3808
|
+
return { ...base, shouldRun: false, reason: "disabled" };
|
|
3809
|
+
if (!settings.reflectionReview)
|
|
3810
|
+
return { ...base, shouldRun: false, reason: "reflection disabled" };
|
|
3811
|
+
if (runningCount >= settings.maxConcurrentLearners) {
|
|
3812
|
+
return {
|
|
3813
|
+
...base,
|
|
3814
|
+
shouldRun: false,
|
|
3815
|
+
reason: `max learners running (${runningCount}/${settings.maxConcurrentLearners})`,
|
|
3816
|
+
};
|
|
3817
|
+
}
|
|
3818
|
+
if (cooldownRemainingMs > 0)
|
|
3819
|
+
return { ...base, shouldRun: false, reason: "reflection cooldown" };
|
|
3820
|
+
if (correctionSignal) {
|
|
3821
|
+
return {
|
|
3822
|
+
...base,
|
|
3823
|
+
shouldRun: true,
|
|
3824
|
+
reason: "reflection correction signal",
|
|
3825
|
+
digest: this.buildAutonomyReviewDigest(messages),
|
|
3826
|
+
};
|
|
3827
|
+
}
|
|
3828
|
+
if (autonomy.mode === "full") {
|
|
3829
|
+
return {
|
|
3830
|
+
...base,
|
|
3831
|
+
shouldRun: true,
|
|
3832
|
+
reason: "full autonomy post-turn review",
|
|
3833
|
+
digest: this.buildAutonomyReviewDigest(messages),
|
|
3834
|
+
};
|
|
3835
|
+
}
|
|
3836
|
+
if (toolCalls >= settings.reflectionMinToolCalls) {
|
|
3837
|
+
return {
|
|
3838
|
+
...base,
|
|
3839
|
+
shouldRun: true,
|
|
3840
|
+
reason: `reflection tool trigger (${toolCalls}/${settings.reflectionMinToolCalls})`,
|
|
3841
|
+
digest: this.buildAutonomyReviewDigest(messages),
|
|
3842
|
+
};
|
|
3843
|
+
}
|
|
3844
|
+
return { ...base, shouldRun: false, reason: "reflection thresholds not met" };
|
|
3845
|
+
}
|
|
3606
3846
|
maybeStartAutoLearn() {
|
|
3607
3847
|
if (process.env.PI_AUTO_LEARN_CHILD === "1")
|
|
3608
|
-
return;
|
|
3848
|
+
return false;
|
|
3609
3849
|
const decision = this.evaluateAutoLearn(false);
|
|
3610
3850
|
if (!decision.shouldRun) {
|
|
3611
3851
|
this.autoLearnLastStatus = decision.reason;
|
|
3612
3852
|
this.updateAutoLearnFooter();
|
|
3613
|
-
return;
|
|
3853
|
+
return false;
|
|
3614
3854
|
}
|
|
3615
3855
|
const message = this.launchAutoLearn(decision.reason, false);
|
|
3616
3856
|
this.showStatus(message);
|
|
3857
|
+
return message.startsWith("Auto Learn started");
|
|
3858
|
+
}
|
|
3859
|
+
maybeStartAutonomyReview(messages) {
|
|
3860
|
+
if (process.env.PI_AUTO_LEARN_CHILD === "1")
|
|
3861
|
+
return false;
|
|
3862
|
+
const decision = this.evaluateAutonomyReview(messages);
|
|
3863
|
+
if (!decision.shouldRun)
|
|
3864
|
+
return false;
|
|
3865
|
+
const message = this.launchAutoLearn(decision.reason, true, {
|
|
3866
|
+
cooldownKind: "reflection",
|
|
3867
|
+
promptKind: "reflection",
|
|
3868
|
+
turnDigest: decision.digest,
|
|
3869
|
+
});
|
|
3870
|
+
this.showStatus(message);
|
|
3871
|
+
return message.startsWith("Auto Learn started");
|
|
3617
3872
|
}
|
|
3618
3873
|
updateAutoLearnFooter() {
|
|
3619
3874
|
const settings = this.getEffectiveAutoLearnSettings();
|
|
@@ -3633,9 +3888,60 @@ export class InteractiveMode {
|
|
|
3633
3888
|
const contextText = decision.contextPercent === null ? "unknown" : `${decision.contextPercent.toFixed(1)}%`;
|
|
3634
3889
|
const cooldownText = decision.cooldownRemainingMs > 0 ? `${Math.ceil(decision.cooldownRemainingMs / 60000)}m remaining` : "ready";
|
|
3635
3890
|
const runLines = runs.length
|
|
3636
|
-
? runs
|
|
3891
|
+
? runs
|
|
3892
|
+
.map(([id, run]) => `- ${id}: ${run.model}, kind=${run.kind ?? "auto"}, authority=${run.authority ?? "unknown"}, pid=${run.pid ?? "?"}, log=${run.logPath}`)
|
|
3893
|
+
.join("\n")
|
|
3637
3894
|
: "- none";
|
|
3638
|
-
|
|
3895
|
+
const reflectionLast = state.lastReflectionByTenant?.[this.getAutoLearnTenantKey()] ?? 0;
|
|
3896
|
+
const reflectionCooldownRemainingMs = Math.max(0, reflectionLast + settings.reflectionCooldownMinutes * 60 * 1000 - Date.now());
|
|
3897
|
+
const reflectionCooldownText = reflectionCooldownRemainingMs > 0 ? `${Math.ceil(reflectionCooldownRemainingMs / 60000)}m remaining` : "ready";
|
|
3898
|
+
return `Auto Learn status\nEnabled: ${settings.enabled}\nModel: ${settings.model}\nNext decision: ${decision.shouldRun ? "ready" : decision.reason}\nMessages: ${decision.messageCount}/${settings.longSessionMessages}\nContext: ${contextText}/${settings.longSessionContextPercent}%\nCooldown: ${cooldownText}\nReflection review: ${settings.reflectionReview ? "enabled" : "disabled"} (tool trigger ${settings.reflectionMinToolCalls}, cooldown ${reflectionCooldownText})\nRunning leases: ${runs.length}/${settings.maxConcurrentLearners}\nRuns:\n${runLines}`;
|
|
3899
|
+
}
|
|
3900
|
+
formatAutonomyStatus() {
|
|
3901
|
+
const autonomy = this.settingsManager.getAutonomySettings();
|
|
3902
|
+
const settings = this.getEffectiveAutoLearnSettings();
|
|
3903
|
+
const autoLearnState = this.pruneAutoLearnState(this.readAutoLearnState());
|
|
3904
|
+
const running = Object.entries(autoLearnState.runs ?? {});
|
|
3905
|
+
const safety = autonomy.mode === "full"
|
|
3906
|
+
? "standing grant for memory, skills, user/project extensions, autonomy/autoLearn tuning, and authorized selfModification.sourcePath edits; hard stops still require explicit foreground approval"
|
|
3907
|
+
: "proposal-gated outside configured high-confidence memory policy";
|
|
3908
|
+
const reflectionLine = autonomy.mode === "full"
|
|
3909
|
+
? `Reflection review: ${settings.reflectionReview ? "enabled" : "disabled"}; post-turn when concurrency allows; cooldown=${settings.reflectionCooldownMinutes}m`
|
|
3910
|
+
: `Reflection review: ${settings.reflectionReview ? "enabled" : "disabled"}; tool trigger=${settings.reflectionMinToolCalls}; cooldown=${settings.reflectionCooldownMinutes}m`;
|
|
3911
|
+
return [
|
|
3912
|
+
"Autonomy status",
|
|
3913
|
+
`Mode: ${autonomy.mode}${autonomy.mode === "full" ? " (standing autonomy)" : ""}`,
|
|
3914
|
+
`Auto Learn: ${settings.enabled ? "enabled" : "disabled"}; model=${settings.model}; applyHighConfidence=${settings.applyHighConfidence}`,
|
|
3915
|
+
`Long-session trigger: ${settings.longSessionMessages} messages or ${settings.longSessionContextPercent}% context; cooldown=${settings.cooldownMinutes}m`,
|
|
3916
|
+
reflectionLine,
|
|
3917
|
+
`Running learners: ${running.length}/${settings.maxConcurrentLearners}`,
|
|
3918
|
+
`Standing authority: ${safety}`,
|
|
3919
|
+
`Audit/log dir: ${this.getAutoLearnDataDir()}`,
|
|
3920
|
+
"Use /autonomy off|safe|balanced|full to switch presets. Advanced overrides remain in /settings → Auto Learn Advanced.",
|
|
3921
|
+
].join("\n");
|
|
3922
|
+
}
|
|
3923
|
+
applyAutonomyMode(mode, scope = "global") {
|
|
3924
|
+
const currentAutoLearn = this.settingsManager.getAutoLearnSettings();
|
|
3925
|
+
const preset = this.getAutoLearnPresetForAutonomyMode(mode, currentAutoLearn);
|
|
3926
|
+
this.settingsManager.setAutonomySettings({ mode }, scope);
|
|
3927
|
+
this.settingsManager.setAutoLearnSettings(preset, scope);
|
|
3928
|
+
this.updateAutoLearnFooter();
|
|
3929
|
+
}
|
|
3930
|
+
handleAutonomyCommand(text) {
|
|
3931
|
+
const action = text.slice("/autonomy".length).trim() || "status";
|
|
3932
|
+
if (AUTONOMY_MODES.includes(action)) {
|
|
3933
|
+
const mode = action;
|
|
3934
|
+
this.applyAutonomyMode(mode);
|
|
3935
|
+
this.showStatus(`Autonomy mode set to ${mode}${mode === "full" ? " (standing autonomy)" : ""}.`);
|
|
3936
|
+
return;
|
|
3937
|
+
}
|
|
3938
|
+
if (action === "status") {
|
|
3939
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3940
|
+
this.chatContainer.addChild(new Text(this.formatAutonomyStatus(), 1, 0));
|
|
3941
|
+
this.ui.requestRender();
|
|
3942
|
+
return;
|
|
3943
|
+
}
|
|
3944
|
+
this.showStatus("Usage: /autonomy [status|off|safe|balanced|full]");
|
|
3639
3945
|
}
|
|
3640
3946
|
handleAutoLearnCommand(text) {
|
|
3641
3947
|
const action = text.slice("/auto-learn".length).trim() || "status";
|
|
@@ -3683,6 +3989,8 @@ export class InteractiveMode {
|
|
|
3683
3989
|
warnings: this.settingsManager.getWarnings(),
|
|
3684
3990
|
selfModification: this.settingsManager.getSelfModificationSettings(),
|
|
3685
3991
|
selfModificationScope: projectSettings.selfModification ? "project" : "global",
|
|
3992
|
+
autonomy: this.settingsManager.getAutonomySettings(),
|
|
3993
|
+
autonomyScope: projectSettings.autonomy ? "project" : "global",
|
|
3686
3994
|
autoLearn: this.settingsManager.getAutoLearnSettings(),
|
|
3687
3995
|
autoLearnScope: projectSettings.autoLearn ? "project" : "global",
|
|
3688
3996
|
autoLearnModelOptions: this.getAutoLearnModelOptions(),
|
|
@@ -3817,6 +4125,10 @@ export class InteractiveMode {
|
|
|
3817
4125
|
}
|
|
3818
4126
|
this.showStatus(`Self modification settings saved to ${scope}. Start a new session or /reload for system-prompt guardrails to fully refresh.`);
|
|
3819
4127
|
},
|
|
4128
|
+
onAutonomyChange: (settings, scope) => {
|
|
4129
|
+
this.applyAutonomyMode(settings.mode ?? "off", scope);
|
|
4130
|
+
this.showStatus(`Autonomy mode ${settings.mode ?? "off"} saved to ${scope}. Use /autonomy status.`);
|
|
4131
|
+
},
|
|
3820
4132
|
onAutoLearnChange: (settings, scope) => {
|
|
3821
4133
|
this.settingsManager.setAutoLearnSettings(settings, scope);
|
|
3822
4134
|
const validationMessage = this.validateAutoLearnModelValue(settings.model);
|