perchai-cli 2.4.21 → 2.4.22
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/perch.mjs +53 -19
- package/package.json +1 -1
package/dist/perch.mjs
CHANGED
|
@@ -75566,7 +75566,6 @@ var init_payroll = __esm({
|
|
|
75566
75566
|
// lib/perchBusinessTools/index.ts
|
|
75567
75567
|
var init_perchBusinessTools = __esm({
|
|
75568
75568
|
"lib/perchBusinessTools/index.ts"() {
|
|
75569
|
-
"use strict";
|
|
75570
75569
|
init_generateAPAuditPacket();
|
|
75571
75570
|
init_inventoryFolder();
|
|
75572
75571
|
init_loadBusinessTables();
|
|
@@ -75900,6 +75899,7 @@ function isTurnAbortedError(error) {
|
|
|
75900
75899
|
var TURN_STOPPED_BY_USER_MESSAGE;
|
|
75901
75900
|
var init_turnAbort = __esm({
|
|
75902
75901
|
"features/perchTerminal/runtime/turnAbort.ts"() {
|
|
75902
|
+
"use strict";
|
|
75903
75903
|
TURN_STOPPED_BY_USER_MESSAGE = "Turn stopped by user.";
|
|
75904
75904
|
}
|
|
75905
75905
|
});
|
|
@@ -259813,7 +259813,7 @@ var require_websocket = __commonJS({
|
|
|
259813
259813
|
var http2 = __require("http");
|
|
259814
259814
|
var net = __require("net");
|
|
259815
259815
|
var tls = __require("tls");
|
|
259816
|
-
var { randomBytes, createHash:
|
|
259816
|
+
var { randomBytes, createHash: createHash5 } = __require("crypto");
|
|
259817
259817
|
var { Duplex, Readable } = __require("stream");
|
|
259818
259818
|
var { URL: URL2 } = __require("url");
|
|
259819
259819
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -260481,7 +260481,7 @@ var require_websocket = __commonJS({
|
|
|
260481
260481
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
260482
260482
|
return;
|
|
260483
260483
|
}
|
|
260484
|
-
const digest =
|
|
260484
|
+
const digest = createHash5("sha1").update(key + GUID).digest("base64");
|
|
260485
260485
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
260486
260486
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
260487
260487
|
return;
|
|
@@ -260850,7 +260850,7 @@ var require_websocket_server = __commonJS({
|
|
|
260850
260850
|
var EventEmitter3 = __require("events");
|
|
260851
260851
|
var http2 = __require("http");
|
|
260852
260852
|
var { Duplex } = __require("stream");
|
|
260853
|
-
var { createHash:
|
|
260853
|
+
var { createHash: createHash5 } = __require("crypto");
|
|
260854
260854
|
var extension2 = require_extension();
|
|
260855
260855
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
260856
260856
|
var subprotocol2 = require_subprotocol();
|
|
@@ -261157,7 +261157,7 @@ var require_websocket_server = __commonJS({
|
|
|
261157
261157
|
);
|
|
261158
261158
|
}
|
|
261159
261159
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
261160
|
-
const digest =
|
|
261160
|
+
const digest = createHash5("sha1").update(key + GUID).digest("base64");
|
|
261161
261161
|
const headers = [
|
|
261162
261162
|
"HTTP/1.1 101 Switching Protocols",
|
|
261163
261163
|
"Upgrade: websocket",
|
|
@@ -283093,6 +283093,7 @@ __export(perch_cli_exports, {
|
|
|
283093
283093
|
runPerchCli: () => runPerchCli
|
|
283094
283094
|
});
|
|
283095
283095
|
import fs14 from "node:fs";
|
|
283096
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
283096
283097
|
import os5 from "node:os";
|
|
283097
283098
|
import path14 from "node:path";
|
|
283098
283099
|
import readline from "node:readline/promises";
|
|
@@ -283123,7 +283124,8 @@ ${HELP_TEXT}`);
|
|
|
283123
283124
|
const connection = await connectModelProxy({ appUrl: parsed.appUrl });
|
|
283124
283125
|
try {
|
|
283125
283126
|
const threadId = parsed.threadId?.trim() || "cli-default";
|
|
283126
|
-
const
|
|
283127
|
+
const threadScopeKey = await resolveCliThreadScopeKey(connection);
|
|
283128
|
+
const persisted = await hydrateCliThreadState(threadId, threadScopeKey);
|
|
283127
283129
|
const hostedContext = await fetchCliHostedContext(connection, {
|
|
283128
283130
|
query: parsed.prompt,
|
|
283129
283131
|
threadId
|
|
@@ -283165,6 +283167,7 @@ ${HELP_TEXT}`);
|
|
|
283165
283167
|
});
|
|
283166
283168
|
await persistCliThreadState({
|
|
283167
283169
|
threadId: result3.threadId,
|
|
283170
|
+
threadScopeKey,
|
|
283168
283171
|
recentMessages: nextRecentMessages,
|
|
283169
283172
|
contextSnapshot: result3.contextSnapshot ?? persisted?.contextSnapshot ?? null
|
|
283170
283173
|
});
|
|
@@ -283439,14 +283442,15 @@ async function runReadlineInteractivePerchCli(writer, deps, options) {
|
|
|
283439
283442
|
terminal: true
|
|
283440
283443
|
});
|
|
283441
283444
|
const state = createInteractiveCliState(options);
|
|
283442
|
-
await hydrateInteractiveCliState(state);
|
|
283443
283445
|
const connectModelProxy = deps.connectModelProxy ?? connectCliModelProxy;
|
|
283444
283446
|
let connection = await connectModelProxy({ appUrl: state.appUrl });
|
|
283445
283447
|
if (!state.appUrl && connection.appUrl) state.appUrl = connection.appUrl;
|
|
283448
|
+
await syncInteractiveCliThreadScope(state, connection, { force: true });
|
|
283446
283449
|
const reconnect = async () => {
|
|
283447
283450
|
connection.restore();
|
|
283448
283451
|
connection = await connectModelProxy({ appUrl: state.appUrl });
|
|
283449
283452
|
if (!state.appUrl && connection.appUrl) state.appUrl = connection.appUrl;
|
|
283453
|
+
await syncInteractiveCliThreadScope(state, connection);
|
|
283450
283454
|
};
|
|
283451
283455
|
writer.stdout(renderInteractiveStartup(state, connection));
|
|
283452
283456
|
try {
|
|
@@ -283532,14 +283536,15 @@ async function runInkInteractivePerchCli(writer, deps, options) {
|
|
|
283532
283536
|
init_build2().then(() => build_exports)
|
|
283533
283537
|
]);
|
|
283534
283538
|
const state = createInteractiveCliState(options);
|
|
283535
|
-
await hydrateInteractiveCliState(state);
|
|
283536
283539
|
const connectModelProxy = deps.connectModelProxy ?? connectCliModelProxy;
|
|
283537
283540
|
let connection = await connectModelProxy({ appUrl: state.appUrl });
|
|
283538
283541
|
if (!state.appUrl && connection.appUrl) state.appUrl = connection.appUrl;
|
|
283542
|
+
await syncInteractiveCliThreadScope(state, connection, { force: true });
|
|
283539
283543
|
const reconnect = async () => {
|
|
283540
283544
|
connection.restore();
|
|
283541
283545
|
connection = await connectModelProxy({ appUrl: state.appUrl });
|
|
283542
283546
|
if (!state.appUrl && connection.appUrl) state.appUrl = connection.appUrl;
|
|
283547
|
+
await syncInteractiveCliThreadScope(state, connection);
|
|
283543
283548
|
};
|
|
283544
283549
|
const runTurn = deps.runCliTurn ?? runPerchCliTurn;
|
|
283545
283550
|
const instance = Ink2.render(
|
|
@@ -284340,7 +284345,7 @@ async function runInteractiveSlashCommand(input) {
|
|
|
284340
284345
|
input.state.contextSnapshot = null;
|
|
284341
284346
|
input.state.persistedThreadUpdatedAt = null;
|
|
284342
284347
|
clearThreadSession(input.state.threadId);
|
|
284343
|
-
await deleteCliThreadState(input.state.threadId);
|
|
284348
|
+
await deleteCliThreadState(input.state.threadId, input.state.threadScopeKey);
|
|
284344
284349
|
writeModeLine(input.writer, "memory", "cleared");
|
|
284345
284350
|
return "continue";
|
|
284346
284351
|
case "login":
|
|
@@ -284539,6 +284544,7 @@ function createInteractiveCliState(options) {
|
|
|
284539
284544
|
personaId: options.personaId ?? "saffron",
|
|
284540
284545
|
permissionMode: options.permissionMode ?? "default",
|
|
284541
284546
|
threadId: options.threadId?.trim() || "cli-default",
|
|
284547
|
+
threadScopeKey: null,
|
|
284542
284548
|
desktopConnected: options.desktopConnected ?? false,
|
|
284543
284549
|
cliLocalTools: options.cliLocalTools ?? true,
|
|
284544
284550
|
appUrl: resolveCliAppUrl(options.appUrl ?? null, null),
|
|
@@ -284548,14 +284554,25 @@ function createInteractiveCliState(options) {
|
|
|
284548
284554
|
};
|
|
284549
284555
|
}
|
|
284550
284556
|
async function hydrateInteractiveCliState(state) {
|
|
284551
|
-
const persisted = await hydrateCliThreadState(state.threadId);
|
|
284557
|
+
const persisted = await hydrateCliThreadState(state.threadId, state.threadScopeKey);
|
|
284552
284558
|
if (!persisted) return;
|
|
284553
284559
|
state.recentMessages = persisted.recentMessages;
|
|
284554
284560
|
state.contextSnapshot = persisted.contextSnapshot;
|
|
284555
284561
|
state.persistedThreadUpdatedAt = persisted.updatedAt;
|
|
284556
284562
|
}
|
|
284557
|
-
async function
|
|
284558
|
-
const
|
|
284563
|
+
async function syncInteractiveCliThreadScope(state, connection, options = {}) {
|
|
284564
|
+
const nextScopeKey = await resolveCliThreadScopeKey(connection);
|
|
284565
|
+
if (!options.force && state.threadScopeKey === nextScopeKey) return;
|
|
284566
|
+
state.threadScopeKey = nextScopeKey;
|
|
284567
|
+
state.recentMessages = [];
|
|
284568
|
+
state.contextSnapshot = null;
|
|
284569
|
+
state.persistedThreadUpdatedAt = null;
|
|
284570
|
+
clearThreadSession(state.threadId);
|
|
284571
|
+
await hydrateInteractiveCliState(state);
|
|
284572
|
+
}
|
|
284573
|
+
async function hydrateCliThreadState(threadId, threadScopeKey) {
|
|
284574
|
+
const persisted = await readCliThreadState(threadId, threadScopeKey);
|
|
284575
|
+
clearThreadSession(threadId);
|
|
284559
284576
|
if (!persisted) return null;
|
|
284560
284577
|
if (persisted.threadSession) {
|
|
284561
284578
|
await saveThreadSession(persisted.threadSession);
|
|
@@ -284565,6 +284582,7 @@ async function hydrateCliThreadState(threadId) {
|
|
|
284565
284582
|
async function persistInteractiveCliState(state) {
|
|
284566
284583
|
await persistCliThreadState({
|
|
284567
284584
|
threadId: state.threadId,
|
|
284585
|
+
threadScopeKey: state.threadScopeKey,
|
|
284568
284586
|
recentMessages: state.recentMessages,
|
|
284569
284587
|
contextSnapshot: state.contextSnapshot
|
|
284570
284588
|
});
|
|
@@ -284580,13 +284598,13 @@ async function persistCliThreadState(input) {
|
|
|
284580
284598
|
threadSession,
|
|
284581
284599
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
284582
284600
|
};
|
|
284583
|
-
const filePath = cliThreadStatePath(input.threadId);
|
|
284601
|
+
const filePath = cliThreadStatePath(input.threadId, input.threadScopeKey);
|
|
284584
284602
|
await fs14.promises.mkdir(path14.dirname(filePath), { recursive: true, mode: 448 });
|
|
284585
284603
|
await fs14.promises.writeFile(filePath, JSON.stringify(payload, null, 2), { mode: 384 });
|
|
284586
284604
|
}
|
|
284587
|
-
async function readCliThreadState(threadId) {
|
|
284605
|
+
async function readCliThreadState(threadId, threadScopeKey) {
|
|
284588
284606
|
try {
|
|
284589
|
-
const raw = await fs14.promises.readFile(cliThreadStatePath(threadId), "utf8");
|
|
284607
|
+
const raw = await fs14.promises.readFile(cliThreadStatePath(threadId, threadScopeKey), "utf8");
|
|
284590
284608
|
const parsed = JSON.parse(raw);
|
|
284591
284609
|
if (parsed.version !== 1 || parsed.threadId !== threadId) return null;
|
|
284592
284610
|
return {
|
|
@@ -284601,12 +284619,28 @@ async function readCliThreadState(threadId) {
|
|
|
284601
284619
|
return null;
|
|
284602
284620
|
}
|
|
284603
284621
|
}
|
|
284604
|
-
async function deleteCliThreadState(threadId) {
|
|
284605
|
-
await fs14.promises.rm(cliThreadStatePath(threadId), { force: true }).catch(() => void 0);
|
|
284622
|
+
async function deleteCliThreadState(threadId, threadScopeKey) {
|
|
284623
|
+
await fs14.promises.rm(cliThreadStatePath(threadId, threadScopeKey), { force: true }).catch(() => void 0);
|
|
284606
284624
|
}
|
|
284607
|
-
function cliThreadStatePath(threadId) {
|
|
284625
|
+
function cliThreadStatePath(threadId, threadScopeKey) {
|
|
284608
284626
|
const base = process.env.PERCH_CLI_STATE_DIR?.trim() || path14.join(os5.homedir(), ".perch", "threads");
|
|
284609
|
-
return path14.join(base, `${safeCliThreadId(threadId)}.json`);
|
|
284627
|
+
return path14.join(base, safeCliThreadScopeKey(threadScopeKey), `${safeCliThreadId(threadId)}.json`);
|
|
284628
|
+
}
|
|
284629
|
+
async function resolveCliThreadScopeKey(connection) {
|
|
284630
|
+
const session = await readStoredCliAuthSession().catch(() => null);
|
|
284631
|
+
const sessionUsable = isStoredCliAuthSessionUsable(session);
|
|
284632
|
+
const authenticated = Boolean(connection?.authenticated || sessionUsable);
|
|
284633
|
+
const appUrl = connection?.appUrl ?? session?.appUrl ?? "local";
|
|
284634
|
+
const userId = connection?.userId ?? session?.userId ?? null;
|
|
284635
|
+
const email = connection?.email ?? session?.email ?? null;
|
|
284636
|
+
const fallbackToken = authenticated && !userId && !email ? session?.accessToken ?? null : null;
|
|
284637
|
+
const authKey = authenticated ? `user:${userId ?? ""}|email:${email ?? ""}|token:${fallbackToken ? createHash4("sha256").update(fallbackToken).digest("hex").slice(0, 20) : ""}` : "anonymous";
|
|
284638
|
+
const raw = `app:${appUrl}|${authKey}`;
|
|
284639
|
+
const prefix = authenticated ? "user" : "anon";
|
|
284640
|
+
return `${prefix}-${createHash4("sha256").update(raw).digest("hex").slice(0, 20)}`;
|
|
284641
|
+
}
|
|
284642
|
+
function safeCliThreadScopeKey(threadScopeKey) {
|
|
284643
|
+
return (threadScopeKey?.trim() || "anon-local").replace(/[^a-zA-Z0-9_.-]+/g, "_").slice(0, 96);
|
|
284610
284644
|
}
|
|
284611
284645
|
function safeCliThreadId(threadId) {
|
|
284612
284646
|
return threadId.trim().replace(/[^a-zA-Z0-9_.-]+/g, "_").slice(0, 96) || "cli-default";
|