@evandu/super-pi 0.1.104 → 0.1.106
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/dist/.super-pi-check-inputs.json +2 -2
- package/dist/client/.super-pi-client-sources.json +8 -7
- package/dist/client/assets/index-DBR_t9lF.js +79 -0
- package/dist/client/assets/index-mo5Dvh_v.css +1 -0
- package/dist/client/index.html +2 -2
- package/dist/server/application/catalog-service.d.ts +9 -0
- package/dist/server/application/catalog-service.js +11 -0
- package/dist/server/application/provider-service.d.ts +77 -0
- package/dist/server/application/provider-service.js +165 -0
- package/dist/server/application/run-service.d.ts +19 -0
- package/dist/server/application/run-service.js +78 -0
- package/dist/server/command-handler.d.ts +16 -1
- package/dist/server/command-handler.js +40 -1
- package/dist/server/content-search.d.ts +32 -0
- package/dist/server/content-search.js +155 -0
- package/dist/server/file-changes.d.ts +119 -0
- package/dist/server/file-changes.js +278 -0
- package/dist/server/file-diff.d.ts +38 -0
- package/dist/server/file-diff.js +97 -0
- package/dist/server/file-index.d.ts +56 -0
- package/dist/server/file-index.js +150 -0
- package/dist/server/files.d.ts +8 -0
- package/dist/server/files.js +3 -1
- package/dist/server/git.d.ts +17 -0
- package/dist/server/git.js +39 -0
- package/dist/server/http-server.js +121 -1
- package/dist/server/index.js +28 -1
- package/dist/server/pi-session-events.d.ts +9 -0
- package/dist/server/pi-session-events.js +12 -0
- package/dist/server/pi-session-pool.d.ts +19 -1
- package/dist/server/pi-session-pool.js +13 -1
- package/dist/server/pi-session.d.ts +10 -0
- package/dist/server/pi-session.js +11 -0
- package/dist/server/providers.d.ts +160 -0
- package/dist/server/providers.js +396 -0
- package/dist/server/runtime.d.ts +67 -0
- package/dist/server/runtime.js +54 -2
- package/dist/server/server-context.d.ts +15 -0
- package/dist/server/types.d.ts +143 -0
- package/package.json +14 -1
- package/dist/client/assets/index-DDkbPYLz.css +0 -1
- package/dist/client/assets/index-mAu39Bra.js +0 -74
package/dist/server/runtime.js
CHANGED
|
@@ -22,6 +22,7 @@ import { TASK_CONVERSATION_ENV, TASK_DEPTH_ENV, TASK_ENDPOINT_ENV, TASK_EXEC_END
|
|
|
22
22
|
import { BLOCKING_UI_METHODS, EXTENSION_UI_METHODS, } from "./types.js";
|
|
23
23
|
import { loadConversationImages } from "./upload.js";
|
|
24
24
|
import { describeToolCall, describeToolCallArgs, describeToolCallInProgress, extractPartialResultText, extractToolResultText, readQuestionCall } from "./tool-calls.js";
|
|
25
|
+
import { toolTargetPath } from "./file-changes.js";
|
|
25
26
|
const traceLatency = (conversationId, phase, startedAt, extra = "") => {
|
|
26
27
|
if (process.env.SUPER_PI_TRACE_LATENCY !== "1")
|
|
27
28
|
return;
|
|
@@ -342,6 +343,17 @@ export class PiRpcRuntime {
|
|
|
342
343
|
* otherwise be re-imported on every picker open.
|
|
343
344
|
*/
|
|
344
345
|
sdkCatalogPromise;
|
|
346
|
+
/**
|
|
347
|
+
* Bumped whenever the set of models Pi knows about changes.
|
|
348
|
+
*
|
|
349
|
+
* A live session holds its own `ModelRuntime`, built when the session was built, and that runtime
|
|
350
|
+
* does not know about a provider added afterwards. Pi's refusal to switch to a model its runtime
|
|
351
|
+
* does not have is swallowed by the session pool into a warning, so the turn would go on running
|
|
352
|
+
* the OLD model while the picker said the new one - a control that lies. The sessions are made
|
|
353
|
+
* STALE by this counter instead: each one is rebuilt at its next turn, which is a moment when
|
|
354
|
+
* throwing a session away costs nothing, and the new one is built with a runtime that knows.
|
|
355
|
+
*/
|
|
356
|
+
modelEpoch = 0;
|
|
345
357
|
/** Latches the "no extension on disk" warning, so it is said once rather than once per turn. */
|
|
346
358
|
warnedMissingExtension = false;
|
|
347
359
|
/** Latches the "Pi's SDK is not installed" warning, for the same reason. */
|
|
@@ -429,7 +441,7 @@ export class PiRpcRuntime {
|
|
|
429
441
|
// ABOUT that session and stop being true with it.
|
|
430
442
|
this.sessionHosts.delete(conversationId);
|
|
431
443
|
this.reportedSessionFiles.delete(conversationId);
|
|
432
|
-
}, options.sessionFactory ?? createPiSession, (conversationId) => mintCapability(conversationId));
|
|
444
|
+
}, options.sessionFactory ?? createPiSession, (conversationId) => mintCapability(conversationId), () => this.modelEpoch);
|
|
433
445
|
}
|
|
434
446
|
/**
|
|
435
447
|
* The configuration of the session that was built for a conversation, for tests to inspect.
|
|
@@ -719,6 +731,7 @@ export class PiRpcRuntime {
|
|
|
719
731
|
const queue = new TurnQueue();
|
|
720
732
|
const handlers = {
|
|
721
733
|
onToolCall: input.onToolCall,
|
|
734
|
+
onFileWrite: input.onFileWrite,
|
|
722
735
|
onToolUpdate: input.onToolUpdate,
|
|
723
736
|
onToolPreparing: input.onToolPreparing,
|
|
724
737
|
onToolEnd: input.onToolEnd,
|
|
@@ -1052,7 +1065,7 @@ export class PiRpcRuntime {
|
|
|
1052
1065
|
* Still used for the memory review, the knowledge reranker, and as the fallback when Pi's SDK is not
|
|
1053
1066
|
* installed. The main conversation path does NOT come here - see `answer`.
|
|
1054
1067
|
*/
|
|
1055
|
-
async *answerOneShot({ conversation, prompt, signal, cwd, host, onPiQueue, onSteerDelivered, onUserEntry, onSessionFile, onToolCall, onToolUpdate, onToolPreparing, onToolEnd, onThinking, onThinkingEnd, images, memoryReview, memorySourceConversationId, knowledgeRerank }) {
|
|
1068
|
+
async *answerOneShot({ conversation, prompt, signal, cwd, host, onPiQueue, onSteerDelivered, onUserEntry, onSessionFile, onToolCall, onFileWrite, onToolUpdate, onToolPreparing, onToolEnd, onThinking, onThinkingEnd, images, memoryReview, memorySourceConversationId, knowledgeRerank }) {
|
|
1056
1069
|
const latencyStartedAt = performance.now();
|
|
1057
1070
|
traceLatency(conversation.id, "answer.begin", latencyStartedAt);
|
|
1058
1071
|
await mkdir(this.sessionDir, { recursive: true });
|
|
@@ -1379,6 +1392,19 @@ export class PiRpcRuntime {
|
|
|
1379
1392
|
catch (error) {
|
|
1380
1393
|
console.warn(`PiRpcRuntime: the tool call handler threw: ${error instanceof Error ? error.message : "unknown error"}`);
|
|
1381
1394
|
}
|
|
1395
|
+
// THE FILE-WRITING CALL, announced before it runs. This is the ONLY moment the old content
|
|
1396
|
+
// is still on the disk, so this is where a baseline has to be taken - and it is taken by a
|
|
1397
|
+
// listener that does its own I/O, off the drain loop's path, because a disk read between
|
|
1398
|
+
// yields would stall the stream.
|
|
1399
|
+
const writePath = toolTargetPath(name, record.args);
|
|
1400
|
+
if (writePath) {
|
|
1401
|
+
try {
|
|
1402
|
+
onFileWrite?.(writePath, name, record.toolCallId ?? undefined);
|
|
1403
|
+
}
|
|
1404
|
+
catch (error) {
|
|
1405
|
+
console.warn(`PiRpcRuntime: the file-write handler threw: ${error instanceof Error ? error.message : "unknown error"}`);
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1382
1408
|
continue;
|
|
1383
1409
|
}
|
|
1384
1410
|
if (record.type === "tool_execution_end") {
|
|
@@ -2242,6 +2268,32 @@ export class PiRpcRuntime {
|
|
|
2242
2268
|
}
|
|
2243
2269
|
return answer;
|
|
2244
2270
|
}
|
|
2271
|
+
/**
|
|
2272
|
+
* Throws away every cached answer about the models Pi offers.
|
|
2273
|
+
*
|
|
2274
|
+
* Called when the model list itself changes - which today means a person added a provider
|
|
2275
|
+
* through the settings window. The caches are three deep and all three have to go: the TTL map
|
|
2276
|
+
* (ten minutes), the in-flight map (a read that is already running would answer with the old
|
|
2277
|
+
* list), and the SDK catalog, which is remembered for the life of the process because it holds
|
|
2278
|
+
* objects that read the auth store and the model store from disk - and those files are exactly
|
|
2279
|
+
* what just changed.
|
|
2280
|
+
*/
|
|
2281
|
+
invalidateCatalog() {
|
|
2282
|
+
this.catalogs.clear();
|
|
2283
|
+
this.pendingCatalogs.clear();
|
|
2284
|
+
this.sdkCatalogPromise = undefined;
|
|
2285
|
+
}
|
|
2286
|
+
/**
|
|
2287
|
+
* Makes every live session stale, so the next turn builds one that knows the current models.
|
|
2288
|
+
*
|
|
2289
|
+
* WHY A COUNTER AND NOT A REBUILD. Rebuilding a session means throwing it away and reading its
|
|
2290
|
+
* transcript back, and a turn may be RUNNING right now. The counter is read by the session pool
|
|
2291
|
+
* as part of the fingerprint, so each session notices at its next acquire - between turns, where
|
|
2292
|
+
* a rebuild is free.
|
|
2293
|
+
*/
|
|
2294
|
+
bumpModelEpoch() {
|
|
2295
|
+
this.modelEpoch += 1;
|
|
2296
|
+
}
|
|
2245
2297
|
/**
|
|
2246
2298
|
* The model/thinking catalog, from Pi, cached.
|
|
2247
2299
|
*
|
|
@@ -7,6 +7,7 @@ import type { ConversationService } from "./application/conversation-service.js"
|
|
|
7
7
|
import type { RunService } from "./application/run-service.js";
|
|
8
8
|
import type { ExtensionUiService } from "./application/extension-ui-service.js";
|
|
9
9
|
import type { CatalogService } from "./application/catalog-service.js";
|
|
10
|
+
import type { ProviderService } from "./application/provider-service.js";
|
|
10
11
|
import type { ExecService } from "./exec-service.js";
|
|
11
12
|
import type { ToolRegistry } from "./tool-registry.js";
|
|
12
13
|
import type { ToolRunner } from "./tool-runner.js";
|
|
@@ -49,9 +50,23 @@ export interface ServerContext {
|
|
|
49
50
|
runService: RunService;
|
|
50
51
|
extensionUiService: ExtensionUiService;
|
|
51
52
|
catalogService: CatalogService;
|
|
53
|
+
/** The providers a person added through the settings window. */
|
|
54
|
+
providerService: ProviderService;
|
|
52
55
|
execService: ExecService;
|
|
53
56
|
toolRegistry: ToolRegistry;
|
|
54
57
|
toolRunner: ToolRunner;
|
|
58
|
+
/**
|
|
59
|
+
* WHAT THE AGENT CHANGED, and what each file looked like before.
|
|
60
|
+
*
|
|
61
|
+
* The tracker is here because TWO layers need it: the run service writes to it (a write tool is
|
|
62
|
+
* announced, so the "before" is captured) and the HTTP layer reads from it (a diff request asks for
|
|
63
|
+
* the "before" of one file). Putting it in the context rather than inside either service is what
|
|
64
|
+
* keeps it ONE tracker - two trackers would be two answers to "what did the agent change", and only
|
|
65
|
+
* one of them would have the baselines.
|
|
66
|
+
*/
|
|
67
|
+
fileChanges?: import("./file-changes.js").FileChangeTracker;
|
|
68
|
+
/** Shared file indexes: the HTTP layer starts them lazily and write paths refresh known entries. */
|
|
69
|
+
fileIndexes?: Map<string, import("./file-index.js").FileIndex>;
|
|
55
70
|
/** Absent only if construction failed; a runtime with no Pi reports itself through `available`. */
|
|
56
71
|
toolLlm?: import("./tool-llm.js").ToolLlmService;
|
|
57
72
|
/**
|
package/dist/server/types.d.ts
CHANGED
|
@@ -377,6 +377,29 @@ export type ModelOption = ModelSelection & {
|
|
|
377
377
|
* honest answer is "the list could not be read". `fetchedAt` travels with the value so a stale
|
|
378
378
|
* cache is visible rather than silent.
|
|
379
379
|
*/
|
|
380
|
+
/**
|
|
381
|
+
* A provider a person added through the settings window, as the BROWSER sees it.
|
|
382
|
+
*
|
|
383
|
+
* The API key is a FACT here and not a value: `hasKey` says whether one is stored, and the key
|
|
384
|
+
* itself never leaves the server. It is in Super Pi's own registry and in Pi's `auth.json`, both of
|
|
385
|
+
* them files with restrictive permissions, and in neither the state snapshot nor any event.
|
|
386
|
+
*/
|
|
387
|
+
export type PublicProviderModel = {
|
|
388
|
+
id: string;
|
|
389
|
+
name: string;
|
|
390
|
+
reasoning: boolean;
|
|
391
|
+
imageInput: boolean;
|
|
392
|
+
contextWindow: number;
|
|
393
|
+
maxTokens: number;
|
|
394
|
+
};
|
|
395
|
+
export type PublicProvider = {
|
|
396
|
+
id: string;
|
|
397
|
+
name: string;
|
|
398
|
+
baseUrl: string;
|
|
399
|
+
api: string;
|
|
400
|
+
hasKey: boolean;
|
|
401
|
+
models: PublicProviderModel[];
|
|
402
|
+
};
|
|
380
403
|
export type ModelCatalog = {
|
|
381
404
|
source: "pi" | "unavailable";
|
|
382
405
|
models: ModelOption[];
|
|
@@ -874,6 +897,54 @@ export type ClientCommandBody =
|
|
|
874
897
|
type: "model.rules.set";
|
|
875
898
|
rules: ModelFilterRule[];
|
|
876
899
|
}
|
|
900
|
+
/**
|
|
901
|
+
* Adds a provider, or adds a model to one, or updates one.
|
|
902
|
+
*
|
|
903
|
+
* The key is OPTIONAL and its absence means "keep the stored one": the key is never shown again
|
|
904
|
+
* once it is saved, so an empty field is the normal state of the form for a provider that already
|
|
905
|
+
* has one. `clearKey` is how a person asks for it to be removed.
|
|
906
|
+
*/
|
|
907
|
+
| {
|
|
908
|
+
type: "providers.set";
|
|
909
|
+
provider: {
|
|
910
|
+
id: string;
|
|
911
|
+
name?: string;
|
|
912
|
+
baseUrl: string;
|
|
913
|
+
api: string;
|
|
914
|
+
apiKey?: string;
|
|
915
|
+
clearKey?: boolean;
|
|
916
|
+
models: {
|
|
917
|
+
id: string;
|
|
918
|
+
name?: string;
|
|
919
|
+
reasoning?: boolean;
|
|
920
|
+
imageInput?: boolean;
|
|
921
|
+
contextWindow?: number;
|
|
922
|
+
maxTokens?: number;
|
|
923
|
+
supportsDeveloperRole?: boolean;
|
|
924
|
+
supportsReasoningEffort?: boolean;
|
|
925
|
+
}[];
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
/** Removes a provider Super Pi manages. One it does not manage is refused. */
|
|
929
|
+
| {
|
|
930
|
+
type: "providers.remove";
|
|
931
|
+
providerId: string;
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Removes ONE model from a provider, leaving the provider and its other models alone.
|
|
935
|
+
*
|
|
936
|
+
* Separate from `providers.remove` because a provider is a GROUP of models sharing one address
|
|
937
|
+
* and one key: taking one model out must not cost the others their credential.
|
|
938
|
+
*/
|
|
939
|
+
| {
|
|
940
|
+
type: "providers.removeModel";
|
|
941
|
+
providerId: string;
|
|
942
|
+
modelId: string;
|
|
943
|
+
}
|
|
944
|
+
/** Asks for the providers Super Pi manages. The answer carries no key. */
|
|
945
|
+
| {
|
|
946
|
+
type: "providers.fetch";
|
|
947
|
+
}
|
|
877
948
|
/**
|
|
878
949
|
* Sets the app-wide default model. `null` clears it back to "Pi's own default" - the same
|
|
879
950
|
* "absence, not a frozen copy" convention the workspace defaults use, so removing the default
|
|
@@ -1210,9 +1281,69 @@ export type MountedToolSummary = {
|
|
|
1210
1281
|
description?: string;
|
|
1211
1282
|
enabled: boolean;
|
|
1212
1283
|
};
|
|
1284
|
+
/**
|
|
1285
|
+
* A file the agent changed, as the Files panel learns about it.
|
|
1286
|
+
*
|
|
1287
|
+
* `path` is workspace-relative and `/`-separated, the same spelling every other file path uses on the
|
|
1288
|
+
* wire. `baseline` is the content BEFORE the agent's write, or `null` when there was none - which is
|
|
1289
|
+
* how a NEW file is told from an EDITED one, and the two are different things to a reader.
|
|
1290
|
+
*
|
|
1291
|
+
* `baselineUnknown` says the "before" could not be read, as opposed to not existing. A diff view that
|
|
1292
|
+
* shows an empty "before" for a file that existed is a lie, and this flag is what keeps it from being
|
|
1293
|
+
* one.
|
|
1294
|
+
*/
|
|
1295
|
+
export type ChangedFile = {
|
|
1296
|
+
path: string;
|
|
1297
|
+
/** The content before the agent wrote it, or `null` when the file did not exist then. */
|
|
1298
|
+
baseline: string | null;
|
|
1299
|
+
/** True when the baseline is missing because it could not be read, not because the file was new. */
|
|
1300
|
+
baselineUnknown?: boolean;
|
|
1301
|
+
/** The conversation the change belongs to, so a workspace's changes can be attributed to a session. */
|
|
1302
|
+
conversationId?: string;
|
|
1303
|
+
/** When it happened, so the panel can order a turn's changes the way they happened. */
|
|
1304
|
+
at: number;
|
|
1305
|
+
};
|
|
1213
1306
|
export type ServerEvent = {
|
|
1214
1307
|
type: "tools.updated";
|
|
1215
1308
|
tools: MountedToolSummary[];
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* THE AGENT CHANGED THESE FILES.
|
|
1312
|
+
*
|
|
1313
|
+
* WHY THIS EXISTS. The Files panel could browse the workspace but could not show a CHANGE, and a panel
|
|
1314
|
+
* that cannot show a change is a browser rather than a workbench: the user asked for the opposite - being
|
|
1315
|
+
* able to see the files is what makes the agent's edits reviewable. The server already knew which files
|
|
1316
|
+
* the agent wrote (the tool call names the path) and the knowledge went no further than one line on a
|
|
1317
|
+
* card, so a file the agent had rewritten looked exactly like a file it had never touched.
|
|
1318
|
+
*
|
|
1319
|
+
* A SNAPSHOT rather than a delta, like every other state-bearing event here: the client replaces its
|
|
1320
|
+
* list with this one, so a browser that missed an event rebuilds the list from the next one rather than
|
|
1321
|
+
* accumulating a partial truth.
|
|
1322
|
+
*
|
|
1323
|
+
* `dropped` says how many baselines were evicted because the per-workspace cap was reached. It is
|
|
1324
|
+
* reported rather than hidden, because a list that is shorter than the agent's actual work - with no
|
|
1325
|
+
* explanation - reads as "the agent only changed these" and is wrong.
|
|
1326
|
+
*/
|
|
1327
|
+
| {
|
|
1328
|
+
type: "files.changed";
|
|
1329
|
+
workspaceId: string;
|
|
1330
|
+
changes: ChangedFile[];
|
|
1331
|
+
dropped: number;
|
|
1332
|
+
} | {
|
|
1333
|
+
type: "files.index";
|
|
1334
|
+
workspaceId: string;
|
|
1335
|
+
version: number;
|
|
1336
|
+
changed: {
|
|
1337
|
+
path: string;
|
|
1338
|
+
kind: "file" | "directory";
|
|
1339
|
+
size: number | null;
|
|
1340
|
+
mtimeMs: number | null;
|
|
1341
|
+
etag: string | null;
|
|
1342
|
+
text: boolean | null;
|
|
1343
|
+
}[];
|
|
1344
|
+
removed: string[];
|
|
1345
|
+
complete: boolean;
|
|
1346
|
+
skipped: string[];
|
|
1216
1347
|
} | {
|
|
1217
1348
|
type: "operation.result";
|
|
1218
1349
|
requestId: string;
|
|
@@ -1330,6 +1461,18 @@ export type ServerEvent = {
|
|
|
1330
1461
|
type: "model.catalog.all";
|
|
1331
1462
|
catalog: ModelCatalog;
|
|
1332
1463
|
}
|
|
1464
|
+
/**
|
|
1465
|
+
* The providers Super Pi manages. Sent when they change, and when a client connects.
|
|
1466
|
+
*
|
|
1467
|
+
* `apis` travels with them so the form's API-type list has ONE source of truth: the list of
|
|
1468
|
+
* adapters Pi ships is a fact about the Pi that is installed, and a copy of it in the browser
|
|
1469
|
+
* would be a copy that goes stale.
|
|
1470
|
+
*/
|
|
1471
|
+
| {
|
|
1472
|
+
type: "providers.list";
|
|
1473
|
+
providers: PublicProvider[];
|
|
1474
|
+
apis: string[];
|
|
1475
|
+
}
|
|
1333
1476
|
/**
|
|
1334
1477
|
* The answer to conversation.autoRename. Carries a title OR an error and never both, because the client
|
|
1335
1478
|
* has exactly two things to say about it: here is the new name, or here is why there isnt one.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evandu/super-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.106",
|
|
4
4
|
"description": "Web control plane and companion for Pi",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -87,6 +87,10 @@
|
|
|
87
87
|
"scripts/tool-calls.test.mjs",
|
|
88
88
|
"scripts/files-api.test.mjs",
|
|
89
89
|
"scripts/files-missing-path.test.mjs",
|
|
90
|
+
"scripts/file-changes.test.mjs",
|
|
91
|
+
"scripts/file-index.test.mjs",
|
|
92
|
+
"scripts/file-content-search.test.mjs",
|
|
93
|
+
"scripts/file-diff-client.test.mjs",
|
|
90
94
|
"scripts/task-tool.test.mjs",
|
|
91
95
|
"scripts/fork-server.test.mjs",
|
|
92
96
|
"scripts/styles-no-dangling.test.mjs",
|
|
@@ -94,6 +98,8 @@
|
|
|
94
98
|
"scripts/agent-config-regression.test.mjs",
|
|
95
99
|
"scripts/model-filter.test.mjs",
|
|
96
100
|
"scripts/settings-default-model.test.mjs",
|
|
101
|
+
"scripts/provider-registry.test.mjs",
|
|
102
|
+
"scripts/provider-pi-reads.test.mjs",
|
|
97
103
|
"scripts/active-memory.test.mjs",
|
|
98
104
|
"scripts/knowledge-base.test.mjs",
|
|
99
105
|
"scripts/tool-runner.test.mjs",
|
|
@@ -128,6 +134,9 @@
|
|
|
128
134
|
"scripts/session-context-menu-browser.test.mjs",
|
|
129
135
|
"scripts/tool-call-blocks-browser.test.mjs",
|
|
130
136
|
"scripts/files-tab-browser.test.mjs",
|
|
137
|
+
"scripts/file-quickopen-browser.test.mjs",
|
|
138
|
+
"scripts/file-content-search-browser.test.mjs",
|
|
139
|
+
"scripts/file-changes-browser.test.mjs",
|
|
131
140
|
"scripts/msg-tabs-browser.test.mjs",
|
|
132
141
|
"scripts/tabs-on-top-browser.test.mjs",
|
|
133
142
|
"scripts/subagent-source.test.mjs",
|
|
@@ -140,6 +149,7 @@
|
|
|
140
149
|
"scripts/theme-switch-state.test.mjs",
|
|
141
150
|
"scripts/settings-window-structure.test.mjs",
|
|
142
151
|
"scripts/settings-model-browser.test.mjs",
|
|
152
|
+
"scripts/provider-browser.test.mjs",
|
|
143
153
|
"scripts/file-tab-selected-contrast.test.mjs",
|
|
144
154
|
"scripts/help-window.test.mjs",
|
|
145
155
|
"scripts/composer-regression-browser.test.mjs",
|
|
@@ -151,8 +161,11 @@
|
|
|
151
161
|
],
|
|
152
162
|
"dependencies": {
|
|
153
163
|
"@earendil-works/pi-coding-agent": "^0.86.1",
|
|
164
|
+
"@types/diff": "^5.2.3",
|
|
154
165
|
"@xterm/addon-fit": "^0.11.0",
|
|
155
166
|
"@xterm/xterm": "^6.0.0",
|
|
167
|
+
"diff": "^5.2.2",
|
|
168
|
+
"fuse.js": "^7.5.0",
|
|
156
169
|
"node-pty": "^1.2.0-beta.15",
|
|
157
170
|
"ws": "latest"
|
|
158
171
|
},
|