@phi-code-admin/phi-code 0.76.16 → 0.77.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +20 -3
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/api-key-store.d.ts +1 -1
- package/dist/core/api-key-store.d.ts.map +1 -1
- package/dist/core/api-key-store.js +5 -2
- package/dist/core/api-key-store.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -3
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +4 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +7 -2
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +4 -0
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/keybindings.d.ts +5 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +4 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +6 -2
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +9 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +36 -5
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +15 -4
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +2 -0
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +3 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +1 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +12 -1
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +3 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +27 -7
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +16 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js +4 -2
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +9 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +29 -4
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +10 -4
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +7 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +80 -8
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/sleep.d.ts.map +1 -1
- package/dist/utils/sleep.js +7 -3
- package/dist/utils/sleep.js.map +1 -1
- package/extensions/phi/benchmark.ts +9 -2
- package/extensions/phi/init.ts +4 -1
- package/extensions/phi/keys.ts +13 -0
- package/extensions/phi/memory.ts +4 -1
- package/extensions/phi/orchestrator.ts +115 -25
- package/extensions/phi/providers/opencode-go.ts +39 -13
- package/extensions/phi/setup.ts +8 -1
- package/extensions/phi/web-search.ts +15 -3
- package/package.json +1 -1
|
@@ -125,6 +125,10 @@ export class InteractiveMode {
|
|
|
125
125
|
version;
|
|
126
126
|
isInitialized = false;
|
|
127
127
|
onInputCallback;
|
|
128
|
+
// Input mode: "act" sends messages to the agent directly; "plan" routes the next
|
|
129
|
+
// message through the /plan orchestrator (5 sequential phases, one model per phase).
|
|
130
|
+
// Toggled with Tab (when the editor is empty); shown by the footer Act/Plan indicator.
|
|
131
|
+
inputMode = "act";
|
|
128
132
|
loadingAnimation = undefined;
|
|
129
133
|
workingMessage = undefined;
|
|
130
134
|
workingVisible = true;
|
|
@@ -234,6 +238,7 @@ export class InteractiveMode {
|
|
|
234
238
|
this.footerDataProvider = new FooterDataProvider(this.sessionManager.getCwd());
|
|
235
239
|
this.footer = new FooterComponent(this.session, this.footerDataProvider);
|
|
236
240
|
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
241
|
+
this.footer.setMode(this.inputMode);
|
|
237
242
|
// Load hide thinking block setting
|
|
238
243
|
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
|
239
244
|
// Register themes from resource loader and initialize
|
|
@@ -927,8 +932,11 @@ export class InteractiveMode {
|
|
|
927
932
|
if (exact)
|
|
928
933
|
return exact;
|
|
929
934
|
let current = p;
|
|
930
|
-
|
|
931
|
-
|
|
935
|
+
// Walk up parent directories independently of the path separator so resource
|
|
936
|
+
// scope labels also resolve on Windows (backslash-separated paths).
|
|
937
|
+
while (current.includes("/") || current.includes("\\")) {
|
|
938
|
+
const idx = Math.max(current.lastIndexOf("/"), current.lastIndexOf("\\"));
|
|
939
|
+
current = current.substring(0, idx);
|
|
932
940
|
const parent = sourceInfos.get(current);
|
|
933
941
|
if (parent)
|
|
934
942
|
return parent;
|
|
@@ -1260,6 +1268,9 @@ export class InteractiveMode {
|
|
|
1260
1268
|
this.streamingComponent = undefined;
|
|
1261
1269
|
this.streamingMessage = undefined;
|
|
1262
1270
|
this.pendingTools.clear();
|
|
1271
|
+
// Drop deferred bash components from the previous session: otherwise the next
|
|
1272
|
+
// submit re-injects a stale component into the new session's chat.
|
|
1273
|
+
this.pendingBashComponents = [];
|
|
1263
1274
|
this.renderInitialMessages();
|
|
1264
1275
|
}
|
|
1265
1276
|
/**
|
|
@@ -1942,6 +1953,7 @@ export class InteractiveMode {
|
|
|
1942
1953
|
this.defaultEditor.onCtrlD = () => this.handleCtrlD();
|
|
1943
1954
|
this.defaultEditor.onAction("app.suspend", () => this.handleCtrlZ());
|
|
1944
1955
|
this.defaultEditor.onAction("app.thinking.cycle", () => this.cycleThinkingLevel());
|
|
1956
|
+
this.defaultEditor.onAction("app.mode.toggle", () => this.toggleInputMode());
|
|
1945
1957
|
this.defaultEditor.onAction("app.model.cycleForward", () => this.cycleModel("forward"));
|
|
1946
1958
|
this.defaultEditor.onAction("app.model.cycleBackward", () => this.cycleModel("backward"));
|
|
1947
1959
|
// Global debug handler on TUI (works regardless of focus)
|
|
@@ -1993,6 +2005,12 @@ export class InteractiveMode {
|
|
|
1993
2005
|
text = text.trim();
|
|
1994
2006
|
if (!text)
|
|
1995
2007
|
return;
|
|
2008
|
+
// In Plan mode, route plain prose through the /plan orchestrator. Slash
|
|
2009
|
+
// commands and bash (! / !!) still run normally, so the user can keep
|
|
2010
|
+
// driving the session while staying in Plan mode.
|
|
2011
|
+
if (this.inputMode === "plan" && !text.startsWith("/") && !text.startsWith("!")) {
|
|
2012
|
+
text = `/plan ${text}`;
|
|
2013
|
+
}
|
|
1996
2014
|
// Handle commands
|
|
1997
2015
|
if (text === "/settings") {
|
|
1998
2016
|
this.showSettingsSelector();
|
|
@@ -2833,6 +2851,30 @@ export class InteractiveMode {
|
|
|
2833
2851
|
}
|
|
2834
2852
|
this.ui.requestRender();
|
|
2835
2853
|
}
|
|
2854
|
+
/**
|
|
2855
|
+
* Toggle between Act mode (messages go straight to the agent) and Plan mode
|
|
2856
|
+
* (the next message is routed through the /plan orchestrator). Bound to Tab when
|
|
2857
|
+
* the editor is empty. The active mode is reflected by the footer Act/Plan indicator.
|
|
2858
|
+
*/
|
|
2859
|
+
toggleInputMode() {
|
|
2860
|
+
const next = this.inputMode === "act" ? "plan" : "act";
|
|
2861
|
+
// Plan mode depends on the /plan orchestrator extension. If it is not loaded
|
|
2862
|
+
// (e.g. extensions disabled), stay in Act mode and explain why.
|
|
2863
|
+
if (next === "plan" && !this.session.extensionRunner.getCommand("plan")) {
|
|
2864
|
+
this.showWarning("Plan mode unavailable: the /plan orchestrator extension is not loaded.");
|
|
2865
|
+
return;
|
|
2866
|
+
}
|
|
2867
|
+
this.inputMode = next;
|
|
2868
|
+
this.footer.setMode(next);
|
|
2869
|
+
this.footer.invalidate();
|
|
2870
|
+
if (next === "plan") {
|
|
2871
|
+
this.showStatus("Plan mode ON — your next message launches the /plan orchestrator (5 phases, one model per phase). Tab on an empty prompt to return to Act.");
|
|
2872
|
+
}
|
|
2873
|
+
else {
|
|
2874
|
+
this.showStatus("Act mode ON — messages go straight to the agent. Tab on an empty prompt for Plan mode.");
|
|
2875
|
+
}
|
|
2876
|
+
this.ui.requestRender();
|
|
2877
|
+
}
|
|
2836
2878
|
cycleThinkingLevel() {
|
|
2837
2879
|
const newLevel = this.session.cycleThinkingLevel();
|
|
2838
2880
|
if (newLevel === undefined) {
|
|
@@ -2882,6 +2924,11 @@ export class InteractiveMode {
|
|
|
2882
2924
|
toggleThinkingBlockVisibility() {
|
|
2883
2925
|
this.hideThinkingBlock = !this.hideThinkingBlock;
|
|
2884
2926
|
this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock);
|
|
2927
|
+
// Preserve in-flight tool components across the rebuild. rebuildChatFromMessages()
|
|
2928
|
+
// clears pendingTools and only repopulates from persisted messages, so a tool that
|
|
2929
|
+
// has not produced its result yet would be orphaned and its later updates/result
|
|
2930
|
+
// lost. Keep the existing components (with their accumulated output) to re-attach.
|
|
2931
|
+
const inFlightTools = new Map(this.pendingTools);
|
|
2885
2932
|
// Rebuild chat from session messages
|
|
2886
2933
|
this.chatContainer.clear();
|
|
2887
2934
|
this.rebuildChatFromMessages();
|
|
@@ -2890,6 +2937,17 @@ export class InteractiveMode {
|
|
|
2890
2937
|
this.streamingComponent.setHideThinkingBlock(this.hideThinkingBlock);
|
|
2891
2938
|
this.streamingComponent.updateContent(this.streamingMessage);
|
|
2892
2939
|
this.chatContainer.addChild(this.streamingComponent);
|
|
2940
|
+
// Re-attach in-flight tool components after the streaming message so their
|
|
2941
|
+
// subsequent updates and results still resolve via pendingTools.
|
|
2942
|
+
for (const content of this.streamingMessage.content) {
|
|
2943
|
+
if (content.type === "toolCall") {
|
|
2944
|
+
const existing = inFlightTools.get(content.id);
|
|
2945
|
+
if (existing && !this.pendingTools.has(content.id)) {
|
|
2946
|
+
this.chatContainer.addChild(existing);
|
|
2947
|
+
this.pendingTools.set(content.id, existing);
|
|
2948
|
+
}
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2893
2951
|
}
|
|
2894
2952
|
this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
|
|
2895
2953
|
}
|
|
@@ -2907,15 +2965,23 @@ export class InteractiveMode {
|
|
|
2907
2965
|
fs.writeFileSync(tmpFile, currentText, "utf-8");
|
|
2908
2966
|
// Stop TUI to release terminal
|
|
2909
2967
|
this.ui.stop();
|
|
2910
|
-
//
|
|
2911
|
-
|
|
2968
|
+
// Parse the editor command respecting quoted tokens so editor paths that
|
|
2969
|
+
// contain spaces (common on Windows, e.g. '"C:\\Program Files\\...\\Code.exe"
|
|
2970
|
+
// --wait') are not split apart. A naive split(" ") would break them.
|
|
2971
|
+
const tokens = editorCmd.match(/"[^"]*"|\S+/g) ?? [editorCmd];
|
|
2972
|
+
const [editor, ...editorArgs] = tokens.map((t) => t.replace(/^"|"$/g, ""));
|
|
2912
2973
|
// Spawn editor synchronously with inherited stdio for interactive editing
|
|
2913
2974
|
const result = spawnSync(editor, [...editorArgs, tmpFile], {
|
|
2914
2975
|
stdio: "inherit",
|
|
2915
2976
|
shell: process.platform === "win32",
|
|
2916
2977
|
});
|
|
2917
|
-
//
|
|
2918
|
-
|
|
2978
|
+
// Surface a launch failure (binary not found / not executable) instead of
|
|
2979
|
+
// silently doing nothing; result.status is null in that case.
|
|
2980
|
+
if (result.error) {
|
|
2981
|
+
this.showWarning(`Failed to launch editor: ${result.error.message}`);
|
|
2982
|
+
}
|
|
2983
|
+
else if (result.status === 0) {
|
|
2984
|
+
// On successful exit, replace editor content.
|
|
2919
2985
|
const newContent = fs.readFileSync(tmpFile, "utf-8").replace(/\n$/, "");
|
|
2920
2986
|
this.editor.setText(newContent);
|
|
2921
2987
|
}
|
|
@@ -3013,6 +3079,11 @@ export class InteractiveMode {
|
|
|
3013
3079
|
const hintText = theme.fg("dim", `↳ ${dequeueHint} to edit all queued messages`);
|
|
3014
3080
|
this.pendingMessagesContainer.addChild(new TruncatedText(hintText, 1, 0));
|
|
3015
3081
|
}
|
|
3082
|
+
// Re-attach deferred bash components: the clear() above detached them, but they
|
|
3083
|
+
// may still be streaming output and must stay visible until flushed to chat.
|
|
3084
|
+
for (const component of this.pendingBashComponents) {
|
|
3085
|
+
this.pendingMessagesContainer.addChild(component);
|
|
3086
|
+
}
|
|
3016
3087
|
}
|
|
3017
3088
|
restoreQueuedMessagesToEditor(options) {
|
|
3018
3089
|
const { steering, followUp } = this.clearAllQueues();
|
|
@@ -4172,8 +4243,9 @@ export class InteractiveMode {
|
|
|
4172
4243
|
this.showError("GitHub CLI (gh) is not installed. Install it from https://cli.github.com/");
|
|
4173
4244
|
return;
|
|
4174
4245
|
}
|
|
4175
|
-
// Export to a temp file
|
|
4176
|
-
|
|
4246
|
+
// Export to a temp file with a unique name so concurrent phi instances
|
|
4247
|
+
// running /share do not overwrite or delete each other's export.
|
|
4248
|
+
const tmpFile = path.join(os.tmpdir(), `pi-session-${crypto.randomUUID()}.html`);
|
|
4177
4249
|
try {
|
|
4178
4250
|
await this.session.exportToHtml(tmpFile);
|
|
4179
4251
|
}
|