@phi-code-admin/phi-code 0.96.1 → 0.97.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 +61 -0
- package/dist/core/slash-commands.d.ts +13 -0
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +38 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +8 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +67 -5
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/extensions/phi/benchmark.ts +12 -56
- package/extensions/phi/init.ts +86 -673
- package/extensions/phi/providers/catalog.ts +133 -0
- package/extensions/phi/setup.ts +180 -280
- package/extensions/phi/smart-router.ts +0 -17
- package/package.json +3 -3
|
@@ -20,7 +20,7 @@ import { DefaultPackageManager } from "../../core/package-manager.js";
|
|
|
20
20
|
import { BUILT_IN_PROVIDER_DISPLAY_NAMES } from "../../core/provider-display-names.js";
|
|
21
21
|
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
22
22
|
import { SessionManager } from "../../core/session-manager.js";
|
|
23
|
-
import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
|
|
23
|
+
import { BUILTIN_SLASH_COMMANDS, matchBareBuiltinWithArgs } from "../../core/slash-commands.js";
|
|
24
24
|
import { getChangelogPath, getNewEntries, parseChangelog } from "../../utils/changelog.js";
|
|
25
25
|
import { copyToClipboard } from "../../utils/clipboard.js";
|
|
26
26
|
import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
|
|
@@ -123,6 +123,12 @@ export class InteractiveMode {
|
|
|
123
123
|
version;
|
|
124
124
|
isInitialized = false;
|
|
125
125
|
onInputCallback;
|
|
126
|
+
// Submissions typed while the main loop was busy (prompt preflight) or a
|
|
127
|
+
// session rebuild was in flight (/new). Queued and replayed instead of
|
|
128
|
+
// silently dropped — a prompt typed right after /new used to disappear
|
|
129
|
+
// with no feedback.
|
|
130
|
+
pendingSubmissions = [];
|
|
131
|
+
sessionTransitioning = false;
|
|
126
132
|
// Input mode: "act" sends messages to the agent directly; "plan" routes the next
|
|
127
133
|
// message through the /plan orchestrator (5 sequential phases, one model per phase).
|
|
128
134
|
// Toggled with Tab (when the editor is empty); shown by the footer Act/Plan indicator.
|
|
@@ -2098,9 +2104,17 @@ export class InteractiveMode {
|
|
|
2098
2104
|
return;
|
|
2099
2105
|
}
|
|
2100
2106
|
if (text === "/debug") {
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2107
|
+
// An extension may own /debug (the debug orchestrator does). The TUI
|
|
2108
|
+
// debug overlay only claims the bare form when nothing else does —
|
|
2109
|
+
// otherwise it would silently shadow the extension command.
|
|
2110
|
+
const extensionOwnsDebug = this.session.extensionRunner
|
|
2111
|
+
.getRegisteredCommands()
|
|
2112
|
+
.some((command) => command.name === "debug" || command.invocationName === "debug");
|
|
2113
|
+
if (!extensionOwnsDebug) {
|
|
2114
|
+
this.handleDebugCommand();
|
|
2115
|
+
this.editor.setText("");
|
|
2116
|
+
return;
|
|
2117
|
+
}
|
|
2104
2118
|
}
|
|
2105
2119
|
if (text === "/arminsayshi") {
|
|
2106
2120
|
this.handleArminSaysHi();
|
|
@@ -2122,6 +2136,18 @@ export class InteractiveMode {
|
|
|
2122
2136
|
await this.shutdown();
|
|
2123
2137
|
return;
|
|
2124
2138
|
}
|
|
2139
|
+
// A bare builtin invoked with arguments used to leak to the model as
|
|
2140
|
+
// prose ("/new please"). Surface it instead — unless an extension
|
|
2141
|
+
// registered a command with that name (it then owns the arguments).
|
|
2142
|
+
const bareWithArgs = matchBareBuiltinWithArgs(text);
|
|
2143
|
+
if (bareWithArgs &&
|
|
2144
|
+
!this.session.extensionRunner
|
|
2145
|
+
.getRegisteredCommands()
|
|
2146
|
+
.some((command) => command.name === bareWithArgs || command.invocationName === bareWithArgs)) {
|
|
2147
|
+
this.showWarning(`/${bareWithArgs} takes no arguments. Run \`/${bareWithArgs}\` alone.`);
|
|
2148
|
+
this.editor.setText(text);
|
|
2149
|
+
return;
|
|
2150
|
+
}
|
|
2125
2151
|
// Handle bash command (! for normal, !! for excluded from context)
|
|
2126
2152
|
if (text.startsWith("!")) {
|
|
2127
2153
|
const isExcluded = text.startsWith("!!");
|
|
@@ -2164,7 +2190,14 @@ export class InteractiveMode {
|
|
|
2164
2190
|
// Normal message submission
|
|
2165
2191
|
// First, move any pending bash components to chat
|
|
2166
2192
|
this.flushPendingBashComponents();
|
|
2167
|
-
if (this.onInputCallback) {
|
|
2193
|
+
if (this.sessionTransitioning || !this.onInputCallback) {
|
|
2194
|
+
// The main loop is busy (prompt preflight) or the session is being
|
|
2195
|
+
// rebuilt (/new in flight): queue and replay once ready instead of
|
|
2196
|
+
// dropping the message on the floor.
|
|
2197
|
+
this.pendingSubmissions.push(text);
|
|
2198
|
+
this.showStatus("Message queued — sending when the session is ready");
|
|
2199
|
+
}
|
|
2200
|
+
else {
|
|
2168
2201
|
this.onInputCallback(text);
|
|
2169
2202
|
}
|
|
2170
2203
|
this.editor.addToHistory?.(text);
|
|
@@ -2650,6 +2683,14 @@ export class InteractiveMode {
|
|
|
2650
2683
|
}
|
|
2651
2684
|
}
|
|
2652
2685
|
async getUserInput() {
|
|
2686
|
+
// Replay submissions queued while the loop was busy — but never during a
|
|
2687
|
+
// session rebuild (drainPendingSubmissions fires when it completes).
|
|
2688
|
+
if (!this.sessionTransitioning) {
|
|
2689
|
+
const queued = this.pendingSubmissions.shift();
|
|
2690
|
+
if (queued !== undefined) {
|
|
2691
|
+
return queued;
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2653
2694
|
return new Promise((resolve) => {
|
|
2654
2695
|
this.onInputCallback = (text) => {
|
|
2655
2696
|
this.onInputCallback = undefined;
|
|
@@ -2657,6 +2698,20 @@ export class InteractiveMode {
|
|
|
2657
2698
|
};
|
|
2658
2699
|
});
|
|
2659
2700
|
}
|
|
2701
|
+
/**
|
|
2702
|
+
* Hand one queued submission to the waiting main loop, if any. Called when
|
|
2703
|
+
* a session transition completes; the loop drains the rest through
|
|
2704
|
+
* getUserInput() as it comes back around.
|
|
2705
|
+
*/
|
|
2706
|
+
drainPendingSubmissions() {
|
|
2707
|
+
if (this.sessionTransitioning)
|
|
2708
|
+
return;
|
|
2709
|
+
const callback = this.onInputCallback;
|
|
2710
|
+
if (!callback || this.pendingSubmissions.length === 0)
|
|
2711
|
+
return;
|
|
2712
|
+
const next = this.pendingSubmissions.shift();
|
|
2713
|
+
callback(next);
|
|
2714
|
+
}
|
|
2660
2715
|
rebuildChatFromMessages() {
|
|
2661
2716
|
this.chatContainer.clear();
|
|
2662
2717
|
const context = this.sessionManager.buildSessionContext();
|
|
@@ -4530,6 +4585,9 @@ export class InteractiveMode {
|
|
|
4530
4585
|
this.loadingAnimation = undefined;
|
|
4531
4586
|
}
|
|
4532
4587
|
this.statusContainer.clear();
|
|
4588
|
+
// While the runtime rebuilds, submissions are queued (not sent into the
|
|
4589
|
+
// half-torn-down session) and replayed by the finally below.
|
|
4590
|
+
this.sessionTransitioning = true;
|
|
4533
4591
|
try {
|
|
4534
4592
|
const result = await this.runtimeHost.newSession();
|
|
4535
4593
|
if (result.cancelled) {
|
|
@@ -4543,6 +4601,10 @@ export class InteractiveMode {
|
|
|
4543
4601
|
catch (error) {
|
|
4544
4602
|
await this.handleFatalRuntimeError("Failed to create session", error);
|
|
4545
4603
|
}
|
|
4604
|
+
finally {
|
|
4605
|
+
this.sessionTransitioning = false;
|
|
4606
|
+
this.drainPendingSubmissions();
|
|
4607
|
+
}
|
|
4546
4608
|
}
|
|
4547
4609
|
handleDebugCommand() {
|
|
4548
4610
|
const width = this.ui.terminal.columns;
|