@evandu/super-pi 0.1.30 → 0.1.32
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/README.md +2 -2
- package/dist/client/assets/index-BBfRhf7h.js +50 -0
- package/dist/client/assets/index-sZQBUBuS.css +1 -0
- package/dist/client/index.html +2 -2
- package/dist/server/application/run-service.js +79 -2
- package/dist/server/http-server.js +19 -0
- package/dist/server/model-filter.js +3 -2
- package/dist/server/runtime.d.ts +10 -3
- package/dist/server/runtime.js +53 -5
- package/dist/server/store.d.ts +3 -0
- package/dist/server/store.js +6 -0
- package/dist/server/terminal.d.ts +1 -2
- package/dist/server/terminal.js +2 -3
- package/dist/server/tool-calls.d.ts +21 -0
- package/dist/server/tool-calls.js +40 -0
- package/dist/server/types.d.ts +18 -0
- package/package.json +3 -2
- package/dist/client/assets/index-B1SZQFnC.js +0 -50
- package/dist/client/assets/index-CtKhGxRQ.css +0 -1
package/dist/server/terminal.js
CHANGED
|
@@ -164,8 +164,7 @@ const MAX_CHUNK_BYTES = 64 * 1024;
|
|
|
164
164
|
/** Hard per-session backlog. Beyond this the session is considered runaway and is killed. */
|
|
165
165
|
const MAX_BACKLOG_BYTES = 4 * 1024 * 1024;
|
|
166
166
|
/**
|
|
167
|
-
* Reads the opt-in flag. Anything other than an explicit truthy string leaves the terminal OFF
|
|
168
|
-
* typo in a deployment config fails closed rather than silently exposing a shell.
|
|
167
|
+
* Reads the opt-in flag. Anything other than an explicit truthy string leaves the terminal OFF.
|
|
169
168
|
*/
|
|
170
169
|
export function isTerminalEnabled(env = process.env) {
|
|
171
170
|
const raw = env.SUPER_PI_TERMINAL?.trim().toLowerCase();
|
|
@@ -174,7 +173,7 @@ export function isTerminalEnabled(env = process.env) {
|
|
|
174
173
|
/** The sentence a browser shows when the terminal is missing. Says WHICH of the three gates closed. */
|
|
175
174
|
export function terminalDisabledReason(env = process.env) {
|
|
176
175
|
if (!isTerminalEnabled(env))
|
|
177
|
-
return "终端未启用。设置 SUPER_PI_TERMINAL=1
|
|
176
|
+
return "终端未启用。设置 SUPER_PI_TERMINAL=1 后重启即可使用。";
|
|
178
177
|
if (ptyLoadFailure)
|
|
179
178
|
return `node-pty 未能加载(${ptyLoadFailure})。请重新安装依赖,或确认 node-pty 版本不低于 ${MINIMUM_PTY_VERSION}。`;
|
|
180
179
|
return "";
|
|
@@ -62,6 +62,27 @@ export declare function extractToolResultText(result: unknown): ToolResultSummar
|
|
|
62
62
|
* shape can be regression-tested at all.
|
|
63
63
|
*/
|
|
64
64
|
export declare function describeToolCall(name: string, args: unknown): string | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* THE SAME LINE, READ OUT OF A CALL THAT IS STILL BEING WRITTEN.
|
|
67
|
+
*
|
|
68
|
+
* The block for a call appears the instant the model starts writing it, and for an `edit` that is several
|
|
69
|
+
* seconds before the arguments are complete. Showing 「工具 · 正在生成参数…」 through all of it says the
|
|
70
|
+
* reader nothing they can act on - not WHICH tool, and not what it is aimed at, which are the two things
|
|
71
|
+
* the finished block is going to say. So the same `describeToolCall` mapping runs against the fragments
|
|
72
|
+
* that have arrived so far.
|
|
73
|
+
*
|
|
74
|
+
* TWO STEPS, because a partial JSON document almost never parses. The fragments are tried whole first -
|
|
75
|
+
* that is the case where the last one closed the object. Failing that, the FIRST `"key": "value"` pair in
|
|
76
|
+
* the text is read out on its own, and its value does not have to be CLOSED - a fragment usually stops
|
|
77
|
+
* mid-string, and a path that has arrived half-written still says more than a placeholder does. A fragment
|
|
78
|
+
* that has produced neither yet yields `undefined`, and the caller decides what an unknown call says
|
|
79
|
+
* rather than this module inventing a word for it.
|
|
80
|
+
*
|
|
81
|
+
* The pair is read with a pattern rather than by parsing a repaired document: repairing JSON is a parser's
|
|
82
|
+
* job, and a half-repaired document here would risk naming the wrong file - the one thing this line must
|
|
83
|
+
* never do.
|
|
84
|
+
*/
|
|
85
|
+
export declare function describeToolCallInProgress(name: string, argumentsSoFar: string): string | undefined;
|
|
65
86
|
/**
|
|
66
87
|
* Every parameter of one call, as a bounded list of `key`/`value` pairs a block can show when expanded.
|
|
67
88
|
*
|
|
@@ -152,6 +152,46 @@ export function describeToolCall(name, args) {
|
|
|
152
152
|
}
|
|
153
153
|
return undefined;
|
|
154
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* THE SAME LINE, READ OUT OF A CALL THAT IS STILL BEING WRITTEN.
|
|
157
|
+
*
|
|
158
|
+
* The block for a call appears the instant the model starts writing it, and for an `edit` that is several
|
|
159
|
+
* seconds before the arguments are complete. Showing 「工具 · 正在生成参数…」 through all of it says the
|
|
160
|
+
* reader nothing they can act on - not WHICH tool, and not what it is aimed at, which are the two things
|
|
161
|
+
* the finished block is going to say. So the same `describeToolCall` mapping runs against the fragments
|
|
162
|
+
* that have arrived so far.
|
|
163
|
+
*
|
|
164
|
+
* TWO STEPS, because a partial JSON document almost never parses. The fragments are tried whole first -
|
|
165
|
+
* that is the case where the last one closed the object. Failing that, the FIRST `"key": "value"` pair in
|
|
166
|
+
* the text is read out on its own, and its value does not have to be CLOSED - a fragment usually stops
|
|
167
|
+
* mid-string, and a path that has arrived half-written still says more than a placeholder does. A fragment
|
|
168
|
+
* that has produced neither yet yields `undefined`, and the caller decides what an unknown call says
|
|
169
|
+
* rather than this module inventing a word for it.
|
|
170
|
+
*
|
|
171
|
+
* The pair is read with a pattern rather than by parsing a repaired document: repairing JSON is a parser's
|
|
172
|
+
* job, and a half-repaired document here would risk naming the wrong file - the one thing this line must
|
|
173
|
+
* never do.
|
|
174
|
+
*/
|
|
175
|
+
export function describeToolCallInProgress(name, argumentsSoFar) {
|
|
176
|
+
const text = argumentsSoFar.trim();
|
|
177
|
+
if (!text)
|
|
178
|
+
return undefined;
|
|
179
|
+
try {
|
|
180
|
+
const parsed = JSON.parse(text);
|
|
181
|
+
const described = describeToolCall(name, parsed);
|
|
182
|
+
if (described)
|
|
183
|
+
return described;
|
|
184
|
+
}
|
|
185
|
+
catch { /* the document is still being written, which is the normal case here */ }
|
|
186
|
+
const pair = /"([A-Za-z_][A-Za-z0-9_-]*)"\s*:\s*"((?:[^"\\]|\\.)*)/.exec(text);
|
|
187
|
+
if (!pair)
|
|
188
|
+
return undefined;
|
|
189
|
+
// The closing quote is OPTIONAL in the pattern because a fragment almost always stops mid-string, and a
|
|
190
|
+
// path that has arrived half-written is still worth more than the placeholder word. What is captured is
|
|
191
|
+
// unescaped because an escaped quote is part of the VALUE, not the end of it - without this, a file
|
|
192
|
+
// named with a quote in it would be displayed with a backslash the reader never typed.
|
|
193
|
+
return describeToolCall(name, { [pair[1]]: pair[2].replace(/\\(["\\])/g, "$1") });
|
|
194
|
+
}
|
|
155
195
|
/**
|
|
156
196
|
* How one non-string argument value is NAMED without being read.
|
|
157
197
|
*
|
package/dist/server/types.d.ts
CHANGED
|
@@ -131,6 +131,10 @@ export type ToolCallBlock = {
|
|
|
131
131
|
* distinction that matters when a reader copies it.
|
|
132
132
|
*/
|
|
133
133
|
live?: string;
|
|
134
|
+
/** The model is still GENERATING this call's arguments. Nothing has reached the host yet, so this is
|
|
135
|
+
* the only thing on screen during a long parameter stream - an 'edit' block carries a whole file's
|
|
136
|
+
* replacement text, and without this the screen is blank until the last token arrives. */
|
|
137
|
+
preparing?: boolean;
|
|
134
138
|
at?: number;
|
|
135
139
|
};
|
|
136
140
|
/**
|
|
@@ -164,7 +168,21 @@ export type ToolCallNotice = {
|
|
|
164
168
|
durationMs?: number;
|
|
165
169
|
result?: ToolResultSummary;
|
|
166
170
|
live?: string;
|
|
171
|
+
preparing?: boolean;
|
|
167
172
|
};
|
|
173
|
+
/** WHAT THE RUNTIME HANDS A CALLER WHEN THE MODEL STARTS, OR CONTINUES, BUILDING A TOOL CALL. *
|
|
174
|
+
*
|
|
175
|
+
* `detail` is the line naming what the call is aimed at - the file for a `read`, the command for a `bash`
|
|
176
|
+
* - read out of the arguments as far as they have arrived. It is `undefined` when nothing identifying has
|
|
177
|
+
* been written yet, which is a different fact from an empty one: the caller has a placeholder word for the
|
|
178
|
+
* second case and must not invent one for the first.
|
|
179
|
+
*/
|
|
180
|
+
export interface ToolCallPreparing {
|
|
181
|
+
contentIndex: number;
|
|
182
|
+
name: string;
|
|
183
|
+
delta?: string;
|
|
184
|
+
detail?: string;
|
|
185
|
+
}
|
|
168
186
|
/**
|
|
169
187
|
* `archivedAt` is the whole archive mechanism: a state MARKER, not a move. The conversation object never
|
|
170
188
|
* changes workspace or position, so archiving and restoring are a stamp and a clear of one optional field.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evandu/super-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"description": "Web control plane and companion for Pi",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -96,7 +96,8 @@
|
|
|
96
96
|
"scripts/queue-dock.test.mjs",
|
|
97
97
|
"scripts/md-render-browser.test.mjs",
|
|
98
98
|
"scripts/right-sidebar-browser.test.mjs",
|
|
99
|
-
"scripts/sidebar-tools-browser.test.mjs",
|
|
99
|
+
"scripts/sidebar-tools-browser.test.mjs",
|
|
100
|
+
"scripts/session-context-menu-browser.test.mjs",
|
|
100
101
|
"scripts/tool-call-blocks-browser.test.mjs",
|
|
101
102
|
"scripts/files-tab-browser.test.mjs",
|
|
102
103
|
"scripts/msg-tabs-browser.test.mjs",
|