@caupulican/pi-adaptative 0.80.3 → 0.80.5
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 +15 -1
- package/dist/core/reload-blockers.d.ts +36 -0
- package/dist/core/reload-blockers.d.ts.map +1 -0
- package/dist/core/reload-blockers.js +164 -0
- package/dist/core/reload-blockers.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +11 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +92 -30
- package/dist/modes/interactive/interactive-mode.js.map +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
|
@@ -20,13 +20,14 @@ import { createCompactionSummaryMessage } from "../../core/messages.js";
|
|
|
20
20
|
import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScope } from "../../core/model-resolver.js";
|
|
21
21
|
import { DefaultPackageManager } from "../../core/package-manager.js";
|
|
22
22
|
import { BUILT_IN_PROVIDER_DISPLAY_NAMES } from "../../core/provider-display-names.js";
|
|
23
|
+
import { getPendingReloadBlockers } from "../../core/reload-blockers.js";
|
|
23
24
|
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
24
25
|
import { SessionManager } from "../../core/session-manager.js";
|
|
25
26
|
import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
|
|
26
27
|
import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
|
|
27
28
|
import { getChangelogPath, getNewEntries, parseChangelog } from "../../utils/changelog.js";
|
|
28
29
|
import { copyToClipboard } from "../../utils/clipboard.js";
|
|
29
|
-
import {
|
|
30
|
+
import { readClipboardImage } from "../../utils/clipboard-image.js";
|
|
30
31
|
import { parseGitUrl } from "../../utils/git.js";
|
|
31
32
|
import { getCwdRelativePath, resolvePath } from "../../utils/paths.js";
|
|
32
33
|
import { getPiUserAgent } from "../../utils/pi-user-agent.js";
|
|
@@ -206,6 +207,8 @@ export class InteractiveMode {
|
|
|
206
207
|
isInitialized = false;
|
|
207
208
|
onInputCallback;
|
|
208
209
|
pendingUserInputs = [];
|
|
210
|
+
pendingClipboardImages = [];
|
|
211
|
+
clipboardImageCounter = 0;
|
|
209
212
|
loadingAnimation = undefined;
|
|
210
213
|
workingMessage = undefined;
|
|
211
214
|
workingVisible = true;
|
|
@@ -641,7 +644,7 @@ export class InteractiveMode {
|
|
|
641
644
|
while (true) {
|
|
642
645
|
const userInput = await this.getUserInput();
|
|
643
646
|
try {
|
|
644
|
-
await this.session.prompt(userInput);
|
|
647
|
+
await this.session.prompt(userInput.text, { images: userInput.images });
|
|
645
648
|
}
|
|
646
649
|
catch (error) {
|
|
647
650
|
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
@@ -2107,22 +2110,50 @@ export class InteractiveMode {
|
|
|
2107
2110
|
try {
|
|
2108
2111
|
const image = await readClipboardImage();
|
|
2109
2112
|
if (!image) {
|
|
2113
|
+
this.showStatus("No image found on the clipboard");
|
|
2110
2114
|
return;
|
|
2111
2115
|
}
|
|
2112
|
-
|
|
2113
|
-
const
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2116
|
+
const label = this.nextClipboardImageLabel();
|
|
2117
|
+
const mimeType = image.mimeType.split(";")[0]?.trim().toLowerCase() || image.mimeType;
|
|
2118
|
+
this.pendingClipboardImages.push({
|
|
2119
|
+
label,
|
|
2120
|
+
content: {
|
|
2121
|
+
type: "image",
|
|
2122
|
+
data: Buffer.from(image.bytes).toString("base64"),
|
|
2123
|
+
mimeType,
|
|
2124
|
+
},
|
|
2125
|
+
});
|
|
2126
|
+
this.editor.insertTextAtCursor?.(`${label} `);
|
|
2127
|
+
this.showStatus(`Attached clipboard image ${label} (${mimeType})`);
|
|
2120
2128
|
this.ui.requestRender();
|
|
2121
2129
|
}
|
|
2122
|
-
catch {
|
|
2123
|
-
|
|
2130
|
+
catch (error) {
|
|
2131
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2132
|
+
this.showWarning(`Failed to paste image: ${message}`);
|
|
2124
2133
|
}
|
|
2125
2134
|
}
|
|
2135
|
+
nextClipboardImageLabel() {
|
|
2136
|
+
if (this.pendingClipboardImages.length === 0) {
|
|
2137
|
+
this.clipboardImageCounter = 0;
|
|
2138
|
+
}
|
|
2139
|
+
this.clipboardImageCounter += 1;
|
|
2140
|
+
return `[Image #${this.clipboardImageCounter}]`;
|
|
2141
|
+
}
|
|
2142
|
+
takeClipboardImagesForText(text) {
|
|
2143
|
+
if (this.pendingClipboardImages.length === 0) {
|
|
2144
|
+
return undefined;
|
|
2145
|
+
}
|
|
2146
|
+
const images = this.pendingClipboardImages
|
|
2147
|
+
.filter((image) => text.includes(image.label))
|
|
2148
|
+
.map((image) => image.content);
|
|
2149
|
+
this.pendingClipboardImages = [];
|
|
2150
|
+
this.clipboardImageCounter = 0;
|
|
2151
|
+
return images.length > 0 ? images : undefined;
|
|
2152
|
+
}
|
|
2153
|
+
buildUserInputSubmission(text) {
|
|
2154
|
+
const images = this.takeClipboardImagesForText(text);
|
|
2155
|
+
return images ? { text, images } : { text };
|
|
2156
|
+
}
|
|
2126
2157
|
setupEditorSubmitHandler() {
|
|
2127
2158
|
this.defaultEditor.onSubmit = async (text) => {
|
|
2128
2159
|
text = text.trim();
|
|
@@ -2286,16 +2317,18 @@ export class InteractiveMode {
|
|
|
2286
2317
|
await this.session.prompt(text);
|
|
2287
2318
|
}
|
|
2288
2319
|
else {
|
|
2289
|
-
this.
|
|
2320
|
+
const images = this.takeClipboardImagesForText(text);
|
|
2321
|
+
this.queueCompactionMessage(text, "steer", images);
|
|
2290
2322
|
}
|
|
2291
2323
|
return;
|
|
2292
2324
|
}
|
|
2293
2325
|
// If streaming, use prompt() with steer behavior
|
|
2294
2326
|
// This handles extension commands (execute immediately), prompt template expansion, and queueing
|
|
2295
2327
|
if (this.session.isStreaming) {
|
|
2328
|
+
const images = this.takeClipboardImagesForText(text);
|
|
2296
2329
|
this.editor.addToHistory?.(text);
|
|
2297
2330
|
this.editor.setText("");
|
|
2298
|
-
await this.session.prompt(text, { streamingBehavior: "steer" });
|
|
2331
|
+
await this.session.prompt(text, { streamingBehavior: "steer", images });
|
|
2299
2332
|
this.updatePendingMessagesDisplay();
|
|
2300
2333
|
this.ui.requestRender();
|
|
2301
2334
|
return;
|
|
@@ -2303,11 +2336,12 @@ export class InteractiveMode {
|
|
|
2303
2336
|
// Normal message submission
|
|
2304
2337
|
// First, move any pending bash components to chat
|
|
2305
2338
|
this.flushPendingBashComponents();
|
|
2339
|
+
const submission = this.buildUserInputSubmission(text);
|
|
2306
2340
|
if (this.onInputCallback) {
|
|
2307
|
-
this.onInputCallback(
|
|
2341
|
+
this.onInputCallback(submission);
|
|
2308
2342
|
}
|
|
2309
2343
|
else {
|
|
2310
|
-
this.pendingUserInputs.push(
|
|
2344
|
+
this.pendingUserInputs.push(submission);
|
|
2311
2345
|
}
|
|
2312
2346
|
this.editor.addToHistory?.(text);
|
|
2313
2347
|
};
|
|
@@ -2776,9 +2810,9 @@ export class InteractiveMode {
|
|
|
2776
2810
|
return queuedInput;
|
|
2777
2811
|
}
|
|
2778
2812
|
return new Promise((resolve) => {
|
|
2779
|
-
this.onInputCallback = (
|
|
2813
|
+
this.onInputCallback = (submission) => {
|
|
2780
2814
|
this.onInputCallback = undefined;
|
|
2781
|
-
resolve(
|
|
2815
|
+
resolve(submission);
|
|
2782
2816
|
};
|
|
2783
2817
|
});
|
|
2784
2818
|
}
|
|
@@ -2975,23 +3009,25 @@ export class InteractiveMode {
|
|
|
2975
3009
|
await this.session.prompt(text);
|
|
2976
3010
|
}
|
|
2977
3011
|
else {
|
|
2978
|
-
this.
|
|
3012
|
+
const images = this.takeClipboardImagesForText(text);
|
|
3013
|
+
this.queueCompactionMessage(text, "followUp", images);
|
|
2979
3014
|
}
|
|
2980
3015
|
return;
|
|
2981
3016
|
}
|
|
2982
3017
|
// Alt+Enter queues a follow-up message (waits until agent finishes)
|
|
2983
3018
|
// This handles extension commands (execute immediately), prompt template expansion, and queueing
|
|
2984
3019
|
if (this.session.isStreaming) {
|
|
3020
|
+
const images = this.takeClipboardImagesForText(text);
|
|
2985
3021
|
this.editor.addToHistory?.(text);
|
|
2986
3022
|
this.editor.setText("");
|
|
2987
|
-
await this.session.prompt(text, { streamingBehavior: "followUp" });
|
|
3023
|
+
await this.session.prompt(text, { streamingBehavior: "followUp", images });
|
|
2988
3024
|
this.updatePendingMessagesDisplay();
|
|
2989
3025
|
this.ui.requestRender();
|
|
2990
3026
|
}
|
|
2991
3027
|
// If not streaming, Alt+Enter acts like regular Enter (trigger onSubmit)
|
|
2992
3028
|
else if (this.editor.onSubmit) {
|
|
3029
|
+
await this.editor.onSubmit(text);
|
|
2993
3030
|
this.editor.setText("");
|
|
2994
|
-
this.editor.onSubmit(text);
|
|
2995
3031
|
}
|
|
2996
3032
|
}
|
|
2997
3033
|
handleDequeue() {
|
|
@@ -3246,8 +3282,8 @@ export class InteractiveMode {
|
|
|
3246
3282
|
}
|
|
3247
3283
|
return allQueued.length;
|
|
3248
3284
|
}
|
|
3249
|
-
queueCompactionMessage(text, mode) {
|
|
3250
|
-
this.compactionQueuedMessages.push({ text, mode });
|
|
3285
|
+
queueCompactionMessage(text, mode, images) {
|
|
3286
|
+
this.compactionQueuedMessages.push({ text, mode, images });
|
|
3251
3287
|
this.editor.addToHistory?.(text);
|
|
3252
3288
|
this.editor.setText("");
|
|
3253
3289
|
this.updatePendingMessagesDisplay();
|
|
@@ -3282,10 +3318,10 @@ export class InteractiveMode {
|
|
|
3282
3318
|
await this.session.prompt(message.text);
|
|
3283
3319
|
}
|
|
3284
3320
|
else if (message.mode === "followUp") {
|
|
3285
|
-
await this.session.followUp(message.text);
|
|
3321
|
+
await this.session.followUp(message.text, message.images);
|
|
3286
3322
|
}
|
|
3287
3323
|
else {
|
|
3288
|
-
await this.session.steer(message.text);
|
|
3324
|
+
await this.session.steer(message.text, message.images);
|
|
3289
3325
|
}
|
|
3290
3326
|
}
|
|
3291
3327
|
this.updatePendingMessagesDisplay();
|
|
@@ -3308,7 +3344,7 @@ export class InteractiveMode {
|
|
|
3308
3344
|
await this.session.prompt(message.text);
|
|
3309
3345
|
}
|
|
3310
3346
|
// Send first prompt (starts streaming)
|
|
3311
|
-
const promptPromise = this.session.prompt(firstPrompt.text).catch((error) => {
|
|
3347
|
+
const promptPromise = this.session.prompt(firstPrompt.text, { images: firstPrompt.images }).catch((error) => {
|
|
3312
3348
|
restoreQueue(error);
|
|
3313
3349
|
});
|
|
3314
3350
|
// Queue remaining messages
|
|
@@ -3317,10 +3353,10 @@ export class InteractiveMode {
|
|
|
3317
3353
|
await this.session.prompt(message.text);
|
|
3318
3354
|
}
|
|
3319
3355
|
else if (message.mode === "followUp") {
|
|
3320
|
-
await this.session.followUp(message.text);
|
|
3356
|
+
await this.session.followUp(message.text, message.images);
|
|
3321
3357
|
}
|
|
3322
3358
|
else {
|
|
3323
|
-
await this.session.steer(message.text);
|
|
3359
|
+
await this.session.steer(message.text, message.images);
|
|
3324
3360
|
}
|
|
3325
3361
|
}
|
|
3326
3362
|
this.updatePendingMessagesDisplay();
|
|
@@ -3684,6 +3720,9 @@ export class InteractiveMode {
|
|
|
3684
3720
|
const promptPath = path.join(dir, `${runId}.prompt.md`);
|
|
3685
3721
|
const outFd = fs.openSync(logPath, "a");
|
|
3686
3722
|
const kind = options.promptKind ?? "auto";
|
|
3723
|
+
const sessionDir = path.join(dir, "sessions");
|
|
3724
|
+
const sessionId = `auto-learn-${kind}-${runId}`;
|
|
3725
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
3687
3726
|
const prompt = this.buildAutoLearnPrompt(reason, settings, {
|
|
3688
3727
|
kind,
|
|
3689
3728
|
turnDigest: options.turnDigest,
|
|
@@ -3696,6 +3735,10 @@ export class InteractiveMode {
|
|
|
3696
3735
|
`Auto Learn ${runId}`,
|
|
3697
3736
|
"--model",
|
|
3698
3737
|
modelPattern,
|
|
3738
|
+
"--session-dir",
|
|
3739
|
+
sessionDir,
|
|
3740
|
+
"--session-id",
|
|
3741
|
+
sessionId,
|
|
3699
3742
|
prompt,
|
|
3700
3743
|
];
|
|
3701
3744
|
const child = spawn(spawnTarget.command, args, {
|
|
@@ -3728,6 +3771,8 @@ export class InteractiveMode {
|
|
|
3728
3771
|
expiresAt: now + settings.leaseMinutes * 60 * 1000,
|
|
3729
3772
|
cwd: this.sessionManager.getCwd(),
|
|
3730
3773
|
logPath,
|
|
3774
|
+
sessionDir,
|
|
3775
|
+
sessionId,
|
|
3731
3776
|
promptPath,
|
|
3732
3777
|
kind,
|
|
3733
3778
|
autonomyMode: this.settingsManager.getAutonomySettings().mode,
|
|
@@ -3914,13 +3959,30 @@ export class InteractiveMode {
|
|
|
3914
3959
|
const cooldownText = decision.cooldownRemainingMs > 0 ? `${Math.ceil(decision.cooldownRemainingMs / 60000)}m remaining` : "ready";
|
|
3915
3960
|
const runLines = runs.length
|
|
3916
3961
|
? runs
|
|
3917
|
-
.map(([id, run]) =>
|
|
3962
|
+
.map(([id, run]) => {
|
|
3963
|
+
const session = [
|
|
3964
|
+
run.sessionId ? `session=${run.sessionId}` : "",
|
|
3965
|
+
run.sessionDir ? `sessionDir=${run.sessionDir}` : "",
|
|
3966
|
+
]
|
|
3967
|
+
.filter(Boolean)
|
|
3968
|
+
.join(", ");
|
|
3969
|
+
const sessionText = session ? `, ${session}` : "";
|
|
3970
|
+
return `- ${id}: ${run.model}, kind=${run.kind ?? "auto"}, authority=${run.authority ?? "unknown"}, pid=${run.pid ?? "?"}${sessionText}, log=${run.logPath}`;
|
|
3971
|
+
})
|
|
3918
3972
|
.join("\n")
|
|
3919
3973
|
: "- none";
|
|
3974
|
+
const reloadBlockers = getPendingReloadBlockers({
|
|
3975
|
+
ownPid: process.pid,
|
|
3976
|
+
ownSessionId: this.sessionManager.getSessionId(),
|
|
3977
|
+
ownSessionFile: this.sessionManager.getSessionFile(),
|
|
3978
|
+
});
|
|
3979
|
+
const reloadBlockerLines = reloadBlockers.pending
|
|
3980
|
+
? reloadBlockers.descriptions.map((description) => `- ${description}`).join("\n")
|
|
3981
|
+
: "- none";
|
|
3920
3982
|
const reflectionLast = state.lastReflectionByTenant?.[this.getAutoLearnTenantKey()] ?? 0;
|
|
3921
3983
|
const reflectionCooldownRemainingMs = Math.max(0, reflectionLast + settings.reflectionCooldownMinutes * 60 * 1000 - Date.now());
|
|
3922
3984
|
const reflectionCooldownText = reflectionCooldownRemainingMs > 0 ? `${Math.ceil(reflectionCooldownRemainingMs / 60000)}m remaining` : "ready";
|
|
3923
|
-
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}`;
|
|
3985
|
+
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}\nPi auto-reload blockers: ${reloadBlockers.pending ? reloadBlockers.reason : "none"}\n${reloadBlockerLines}\nRuns:\n${runLines}`;
|
|
3924
3986
|
}
|
|
3925
3987
|
formatAutonomyStatus() {
|
|
3926
3988
|
const autonomy = this.settingsManager.getAutonomySettings();
|