@paigy/harness 0.3.7 → 0.3.8
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 +3 -1
- package/dist/cli.js +84 -15
- package/dist/main.js +77 -8
- package/package.json +13 -12
package/README.md
CHANGED
|
@@ -236,7 +236,9 @@ which still belongs to paigy-listen).
|
|
|
236
236
|
## The window is not distributable (yet)
|
|
237
237
|
|
|
238
238
|
npm is the ONLY shipping channel: `@paigy/harness` installs the CLI and the whole
|
|
239
|
-
bridge
|
|
239
|
+
bridge. The host service updates itself once no session is running (`src/update.ts`), and
|
|
240
|
+
re-running `curl -fsSL https://paigy.ai/install | sh` updates it on demand and restarts it —
|
|
241
|
+
a bare `npm i -g` leaves the running host on the old code. The Electron window runs
|
|
240
242
|
from source (`electron .`) — there is no packaging, no Developer ID signing or
|
|
241
243
|
notarization, and therefore no auto-update (macOS auto-update requires the signing).
|
|
242
244
|
A downloaded unsigned app would hit Gatekeeper's "damaged" dialog, which is worse
|
package/dist/cli.js
CHANGED
|
@@ -14929,7 +14929,7 @@ var require_mock_interceptor = __commonJS({
|
|
|
14929
14929
|
var require_mock_client = __commonJS({
|
|
14930
14930
|
"../../node_modules/.pnpm/undici@6.27.0/node_modules/undici/lib/mock/mock-client.js"(exports, module) {
|
|
14931
14931
|
"use strict";
|
|
14932
|
-
var { promisify } = __require("util");
|
|
14932
|
+
var { promisify: promisify2 } = __require("util");
|
|
14933
14933
|
var Client = require_client();
|
|
14934
14934
|
var { buildMockDispatch } = require_mock_utils();
|
|
14935
14935
|
var {
|
|
@@ -14969,7 +14969,7 @@ var require_mock_client = __commonJS({
|
|
|
14969
14969
|
return new MockInterceptor(opts, this[kDispatches]);
|
|
14970
14970
|
}
|
|
14971
14971
|
async [kClose]() {
|
|
14972
|
-
await
|
|
14972
|
+
await promisify2(this[kOriginalClose])();
|
|
14973
14973
|
this[kConnected] = 0;
|
|
14974
14974
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
14975
14975
|
}
|
|
@@ -14982,7 +14982,7 @@ var require_mock_client = __commonJS({
|
|
|
14982
14982
|
var require_mock_pool = __commonJS({
|
|
14983
14983
|
"../../node_modules/.pnpm/undici@6.27.0/node_modules/undici/lib/mock/mock-pool.js"(exports, module) {
|
|
14984
14984
|
"use strict";
|
|
14985
|
-
var { promisify } = __require("util");
|
|
14985
|
+
var { promisify: promisify2 } = __require("util");
|
|
14986
14986
|
var Pool = require_pool();
|
|
14987
14987
|
var { buildMockDispatch } = require_mock_utils();
|
|
14988
14988
|
var {
|
|
@@ -15022,7 +15022,7 @@ var require_mock_pool = __commonJS({
|
|
|
15022
15022
|
return new MockInterceptor(opts, this[kDispatches]);
|
|
15023
15023
|
}
|
|
15024
15024
|
async [kClose]() {
|
|
15025
|
-
await
|
|
15025
|
+
await promisify2(this[kOriginalClose])();
|
|
15026
15026
|
this[kConnected] = 0;
|
|
15027
15027
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
15028
15028
|
}
|
|
@@ -27558,6 +27558,9 @@ var init_dist = __esm({
|
|
|
27558
27558
|
* harness availabilities + granted workspaces — the option set the phone's
|
|
27559
27559
|
* "new session" sheet offers. Absent for ordinary MCP agents. */
|
|
27560
27560
|
runtime: external_exports.object({
|
|
27561
|
+
/** The @paigy/harness this host is running — a machine the self-update has not reached
|
|
27562
|
+
* shows its age here (`apps/desktop/src/update.ts`). */
|
|
27563
|
+
version: external_exports.string().optional(),
|
|
27561
27564
|
harnesses: external_exports.array(external_exports.object({ name: external_exports.string(), label: external_exports.string(), status: external_exports.string() })).optional(),
|
|
27562
27565
|
workspaces: external_exports.array(external_exports.string()).optional()
|
|
27563
27566
|
}).optional(),
|
|
@@ -33278,7 +33281,7 @@ import { hostname } from "os";
|
|
|
33278
33281
|
import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
33279
33282
|
import { execSync } from "child_process";
|
|
33280
33283
|
import { homedir as homedir7 } from "os";
|
|
33281
|
-
import { join as
|
|
33284
|
+
import { join as join6 } from "path";
|
|
33282
33285
|
|
|
33283
33286
|
// src/harness/session.ts
|
|
33284
33287
|
import { spawn } from "child_process";
|
|
@@ -35770,6 +35773,9 @@ var ConnectionSummarySchema2 = external_exports.object({
|
|
|
35770
35773
|
* harness availabilities + granted workspaces — the option set the phone's
|
|
35771
35774
|
* "new session" sheet offers. Absent for ordinary MCP agents. */
|
|
35772
35775
|
runtime: external_exports.object({
|
|
35776
|
+
/** The @paigy/harness this host is running — a machine the self-update has not reached
|
|
35777
|
+
* shows its age here (`apps/desktop/src/update.ts`). */
|
|
35778
|
+
version: external_exports.string().optional(),
|
|
35773
35779
|
harnesses: external_exports.array(external_exports.object({ name: external_exports.string(), label: external_exports.string(), status: external_exports.string() })).optional(),
|
|
35774
35780
|
workspaces: external_exports.array(external_exports.string()).optional()
|
|
35775
35781
|
}).optional(),
|
|
@@ -36511,7 +36517,7 @@ init_dist();
|
|
|
36511
36517
|
init_catalog();
|
|
36512
36518
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
36513
36519
|
import { homedir as homedir5 } from "os";
|
|
36514
|
-
import { join as
|
|
36520
|
+
import { join as join5 } from "path";
|
|
36515
36521
|
|
|
36516
36522
|
// src/workspaces.ts
|
|
36517
36523
|
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -36550,8 +36556,67 @@ function resolveWakeDir(pinned, deps) {
|
|
|
36550
36556
|
return listWorkspaces(deps)[0];
|
|
36551
36557
|
}
|
|
36552
36558
|
|
|
36559
|
+
// src/update.ts
|
|
36560
|
+
import { execFile } from "child_process";
|
|
36561
|
+
import { createRequire } from "module";
|
|
36562
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
36563
|
+
import { promisify } from "util";
|
|
36564
|
+
var SERVICE_LABEL = "ai.paigy.harness";
|
|
36565
|
+
var VERSION = createRequire(import.meta.url)("../package.json").version;
|
|
36566
|
+
var REGISTRY = "https://registry.npmjs.org/@paigy/harness/latest";
|
|
36567
|
+
var CHECK_MS = 60 * 6e4;
|
|
36568
|
+
function newer(latest, current) {
|
|
36569
|
+
const parts = (v) => /^\d+\.\d+\.\d+$/.test(v) ? v.split(".").map(Number) : null;
|
|
36570
|
+
const [a, b] = [parts(latest), parts(current)];
|
|
36571
|
+
if (!a || !b) return false;
|
|
36572
|
+
for (let i = 0; i < 3; i++) if (a[i] !== b[i]) return a[i] > b[i];
|
|
36573
|
+
return false;
|
|
36574
|
+
}
|
|
36575
|
+
function updateAction(o) {
|
|
36576
|
+
if (!o.service || !o.latest || o.latest === o.failed || !newer(o.latest, o.current)) return "none";
|
|
36577
|
+
return o.sessions > 0 ? "wait" : "install";
|
|
36578
|
+
}
|
|
36579
|
+
async function latestVersion() {
|
|
36580
|
+
const res = await fetch(REGISTRY, { signal: AbortSignal.timeout(1e4) });
|
|
36581
|
+
return res.ok ? (await res.json()).version ?? null : null;
|
|
36582
|
+
}
|
|
36583
|
+
async function install(version) {
|
|
36584
|
+
const bin = dirname3(process.execPath);
|
|
36585
|
+
await promisify(execFile)(join4(bin, "npm"), ["install", "-g", `@paigy/harness@${version}`], {
|
|
36586
|
+
env: { ...process.env, PATH: `${bin}:${process.env.PATH ?? ""}`, npm_config_update_notifier: "false" },
|
|
36587
|
+
timeout: 5 * 6e4
|
|
36588
|
+
});
|
|
36589
|
+
}
|
|
36590
|
+
function selfUpdater(deps) {
|
|
36591
|
+
const service = deps.service ?? process.env.XPC_SERVICE_NAME === SERVICE_LABEL;
|
|
36592
|
+
let latest = null;
|
|
36593
|
+
let checkedAt = -Infinity;
|
|
36594
|
+
let failed;
|
|
36595
|
+
let waiting = false;
|
|
36596
|
+
return async () => {
|
|
36597
|
+
if (!service) return;
|
|
36598
|
+
const now = (deps.now ?? Date.now)();
|
|
36599
|
+
if (now - checkedAt >= CHECK_MS) {
|
|
36600
|
+
checkedAt = now;
|
|
36601
|
+
latest = await (deps.latest ?? latestVersion)().catch(() => latest);
|
|
36602
|
+
}
|
|
36603
|
+
const action = updateAction({ current: VERSION, latest, service, sessions: deps.sessions(), failed });
|
|
36604
|
+
if (action === "wait" && !waiting) deps.log(`\u21E1 @paigy/harness ${latest} is out \u2014 updating once no session is running`);
|
|
36605
|
+
waiting = action === "wait";
|
|
36606
|
+
if (action !== "install" || !latest) return;
|
|
36607
|
+
try {
|
|
36608
|
+
await (deps.install ?? install)(latest);
|
|
36609
|
+
deps.log(`\u21E1 updated @paigy/harness ${VERSION} \u2192 ${latest} \u2014 restarting`);
|
|
36610
|
+
(deps.exit ?? (() => process.exit(0)))();
|
|
36611
|
+
} catch (e) {
|
|
36612
|
+
failed = latest;
|
|
36613
|
+
deps.log(`\u26A0 could not update to @paigy/harness ${latest}: ${e.message.split("\n")[0]} \u2014 run: npm install -g @paigy/harness`);
|
|
36614
|
+
}
|
|
36615
|
+
};
|
|
36616
|
+
}
|
|
36617
|
+
|
|
36553
36618
|
// src/host.ts
|
|
36554
|
-
var HOST_FILE =
|
|
36619
|
+
var HOST_FILE = join5(homedir5(), ".paigy", "host.json");
|
|
36555
36620
|
var runKey = (slot) => `slot:${slot}`;
|
|
36556
36621
|
var claimedRun = (sessionId2) => {
|
|
36557
36622
|
const slot = sessionSlot(sessionId2);
|
|
@@ -36581,11 +36646,15 @@ function startHost(opts) {
|
|
|
36581
36646
|
}
|
|
36582
36647
|
}
|
|
36583
36648
|
};
|
|
36649
|
+
const update = selfUpdater({ sessions: () => runs.size, log: opts.log });
|
|
36584
36650
|
const beat = () => {
|
|
36585
36651
|
void refreshIdentities();
|
|
36652
|
+
void update().catch(() => {
|
|
36653
|
+
});
|
|
36586
36654
|
for (const r of runs.values()) if (r.token) void heartbeat(void 0, { token: r.token }).catch(() => {
|
|
36587
36655
|
});
|
|
36588
36656
|
void heartbeat({
|
|
36657
|
+
version: VERSION,
|
|
36589
36658
|
harnesses: detectAll().map((a) => ({ name: a.name, label: a.label, status: a.status })),
|
|
36590
36659
|
workspaces: listWorkspaces(opts.wsDeps)
|
|
36591
36660
|
}, asHost).catch(() => {
|
|
@@ -36875,7 +36944,7 @@ function printConnectLines(link, userCode) {
|
|
|
36875
36944
|
console.log(` or scan the QR above \xB7 or type ${userCode} in Paigy \u2192 Devices \u2192 Connect a computer`);
|
|
36876
36945
|
}
|
|
36877
36946
|
function forwardCodexThreadId() {
|
|
36878
|
-
const cfg =
|
|
36947
|
+
const cfg = join6(process.env.CODEX_HOME || join6(homedir7(), ".codex"), "config.toml");
|
|
36879
36948
|
if (!existsSync5(cfg)) return;
|
|
36880
36949
|
const text = readFileSync4(cfg, "utf8");
|
|
36881
36950
|
const head = "[mcp_servers.paigy]\n";
|
|
@@ -36988,7 +37057,7 @@ async function main() {
|
|
|
36988
37057
|
const wsDeps = { file: workspacesFile() };
|
|
36989
37058
|
for (const dir of parsed.grant) addWorkspace(dir, wsDeps);
|
|
36990
37059
|
if (!listWorkspaces(wsDeps).length) {
|
|
36991
|
-
const guess =
|
|
37060
|
+
const guess = join6(homedir7(), "projects");
|
|
36992
37061
|
if (existsSync5(guess)) {
|
|
36993
37062
|
addWorkspace(guess, wsDeps);
|
|
36994
37063
|
console.log(`\u2713 workspace granted: ${guess} (change with --grant DIR)`);
|
|
@@ -37029,7 +37098,7 @@ async function main() {
|
|
|
37029
37098
|
}
|
|
37030
37099
|
}
|
|
37031
37100
|
try {
|
|
37032
|
-
const settings =
|
|
37101
|
+
const settings = join6(homedir7(), ".claude", "settings.json");
|
|
37033
37102
|
if (which("claude") && existsSync5(settings)) {
|
|
37034
37103
|
const cfg = JSON.parse(readFileSync4(settings, "utf8"));
|
|
37035
37104
|
if (!cfg["statusLine"]) {
|
|
@@ -37084,7 +37153,7 @@ async function main() {
|
|
|
37084
37153
|
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
37085
37154
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
37086
37155
|
<plist version="1.0"><dict>
|
|
37087
|
-
<key>Label</key><string
|
|
37156
|
+
<key>Label</key><string>${SERVICE_LABEL}</string>
|
|
37088
37157
|
<key>ProgramArguments</key><array>
|
|
37089
37158
|
<string>${process.execPath}</string>
|
|
37090
37159
|
<string>${bin}</string>
|
|
@@ -37095,13 +37164,13 @@ async function main() {
|
|
|
37095
37164
|
<key>SoftResourceLimits</key><dict>
|
|
37096
37165
|
<key>NumberOfFiles</key><integer>65536</integer>
|
|
37097
37166
|
</dict>
|
|
37098
|
-
<key>StandardOutPath</key><string>${
|
|
37099
|
-
<key>StandardErrorPath</key><string>${
|
|
37167
|
+
<key>StandardOutPath</key><string>${join6(homedir7(), ".paigy", "host.log")}</string>
|
|
37168
|
+
<key>StandardErrorPath</key><string>${join6(homedir7(), ".paigy", "host.log")}</string>
|
|
37100
37169
|
</dict></plist>
|
|
37101
37170
|
`;
|
|
37102
|
-
const dir =
|
|
37171
|
+
const dir = join6(homedir7(), "Library", "LaunchAgents");
|
|
37103
37172
|
mkdirSync3(dir, { recursive: true });
|
|
37104
|
-
const path =
|
|
37173
|
+
const path = join6(dir, `${SERVICE_LABEL}.plist`);
|
|
37105
37174
|
writeFileSync4(path, plist);
|
|
37106
37175
|
execSync(`launchctl unload ${path} 2>/dev/null; launchctl load ${path}`, { shell: "/bin/sh" });
|
|
37107
37176
|
console.log(`\u2713 host installed as a login service (${path}) \u2014 logs at ~/.paigy/host.log`);
|
package/dist/main.js
CHANGED
|
@@ -4580,7 +4580,7 @@ import { app, BrowserWindow, dialog, ipcMain } from "electron";
|
|
|
4580
4580
|
import { spawn as spawn2 } from "child_process";
|
|
4581
4581
|
import { readFileSync as readFileSync4 } from "fs";
|
|
4582
4582
|
import { fileURLToPath } from "url";
|
|
4583
|
-
import { dirname as
|
|
4583
|
+
import { dirname as dirname4, join as join6 } from "path";
|
|
4584
4584
|
|
|
4585
4585
|
// ../../packages/sdk/dist/index.js
|
|
4586
4586
|
import { createRequire as __sdkCreateRequire } from "module";
|
|
@@ -13073,6 +13073,9 @@ var ConnectionSummarySchema = external_exports.object({
|
|
|
13073
13073
|
* harness availabilities + granted workspaces — the option set the phone's
|
|
13074
13074
|
* "new session" sheet offers. Absent for ordinary MCP agents. */
|
|
13075
13075
|
runtime: external_exports.object({
|
|
13076
|
+
/** The @paigy/harness this host is running — a machine the self-update has not reached
|
|
13077
|
+
* shows its age here (`apps/desktop/src/update.ts`). */
|
|
13078
|
+
version: external_exports.string().optional(),
|
|
13076
13079
|
harnesses: external_exports.array(external_exports.object({ name: external_exports.string(), label: external_exports.string(), status: external_exports.string() })).optional(),
|
|
13077
13080
|
workspaces: external_exports.array(external_exports.string()).optional()
|
|
13078
13081
|
}).optional(),
|
|
@@ -16106,6 +16109,9 @@ var ConnectionSummarySchema2 = external_exports.object({
|
|
|
16106
16109
|
* harness availabilities + granted workspaces — the option set the phone's
|
|
16107
16110
|
* "new session" sheet offers. Absent for ordinary MCP agents. */
|
|
16108
16111
|
runtime: external_exports.object({
|
|
16112
|
+
/** The @paigy/harness this host is running — a machine the self-update has not reached
|
|
16113
|
+
* shows its age here (`apps/desktop/src/update.ts`). */
|
|
16114
|
+
version: external_exports.string().optional(),
|
|
16109
16115
|
harnesses: external_exports.array(external_exports.object({ name: external_exports.string(), label: external_exports.string(), status: external_exports.string() })).optional(),
|
|
16110
16116
|
workspaces: external_exports.array(external_exports.string()).optional()
|
|
16111
16117
|
}).optional(),
|
|
@@ -16649,7 +16655,7 @@ function detectAll(deps = {}) {
|
|
|
16649
16655
|
// src/host.ts
|
|
16650
16656
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
16651
16657
|
import { homedir as homedir5 } from "os";
|
|
16652
|
-
import { join as
|
|
16658
|
+
import { join as join5 } from "path";
|
|
16653
16659
|
|
|
16654
16660
|
// src/workspaces.ts
|
|
16655
16661
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -17274,8 +17280,67 @@ function runHarness(opts) {
|
|
|
17274
17280
|
};
|
|
17275
17281
|
}
|
|
17276
17282
|
|
|
17283
|
+
// src/update.ts
|
|
17284
|
+
import { execFile } from "child_process";
|
|
17285
|
+
import { createRequire } from "module";
|
|
17286
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
17287
|
+
import { promisify } from "util";
|
|
17288
|
+
var SERVICE_LABEL = "ai.paigy.harness";
|
|
17289
|
+
var VERSION = createRequire(import.meta.url)("../package.json").version;
|
|
17290
|
+
var REGISTRY = "https://registry.npmjs.org/@paigy/harness/latest";
|
|
17291
|
+
var CHECK_MS = 60 * 6e4;
|
|
17292
|
+
function newer(latest, current) {
|
|
17293
|
+
const parts = (v) => /^\d+\.\d+\.\d+$/.test(v) ? v.split(".").map(Number) : null;
|
|
17294
|
+
const [a, b] = [parts(latest), parts(current)];
|
|
17295
|
+
if (!a || !b) return false;
|
|
17296
|
+
for (let i = 0; i < 3; i++) if (a[i] !== b[i]) return a[i] > b[i];
|
|
17297
|
+
return false;
|
|
17298
|
+
}
|
|
17299
|
+
function updateAction(o) {
|
|
17300
|
+
if (!o.service || !o.latest || o.latest === o.failed || !newer(o.latest, o.current)) return "none";
|
|
17301
|
+
return o.sessions > 0 ? "wait" : "install";
|
|
17302
|
+
}
|
|
17303
|
+
async function latestVersion() {
|
|
17304
|
+
const res = await fetch(REGISTRY, { signal: AbortSignal.timeout(1e4) });
|
|
17305
|
+
return res.ok ? (await res.json()).version ?? null : null;
|
|
17306
|
+
}
|
|
17307
|
+
async function install(version) {
|
|
17308
|
+
const bin = dirname3(process.execPath);
|
|
17309
|
+
await promisify(execFile)(join4(bin, "npm"), ["install", "-g", `@paigy/harness@${version}`], {
|
|
17310
|
+
env: { ...process.env, PATH: `${bin}:${process.env.PATH ?? ""}`, npm_config_update_notifier: "false" },
|
|
17311
|
+
timeout: 5 * 6e4
|
|
17312
|
+
});
|
|
17313
|
+
}
|
|
17314
|
+
function selfUpdater(deps) {
|
|
17315
|
+
const service = deps.service ?? process.env.XPC_SERVICE_NAME === SERVICE_LABEL;
|
|
17316
|
+
let latest = null;
|
|
17317
|
+
let checkedAt = -Infinity;
|
|
17318
|
+
let failed;
|
|
17319
|
+
let waiting = false;
|
|
17320
|
+
return async () => {
|
|
17321
|
+
if (!service) return;
|
|
17322
|
+
const now = (deps.now ?? Date.now)();
|
|
17323
|
+
if (now - checkedAt >= CHECK_MS) {
|
|
17324
|
+
checkedAt = now;
|
|
17325
|
+
latest = await (deps.latest ?? latestVersion)().catch(() => latest);
|
|
17326
|
+
}
|
|
17327
|
+
const action = updateAction({ current: VERSION, latest, service, sessions: deps.sessions(), failed });
|
|
17328
|
+
if (action === "wait" && !waiting) deps.log(`\u21E1 @paigy/harness ${latest} is out \u2014 updating once no session is running`);
|
|
17329
|
+
waiting = action === "wait";
|
|
17330
|
+
if (action !== "install" || !latest) return;
|
|
17331
|
+
try {
|
|
17332
|
+
await (deps.install ?? install)(latest);
|
|
17333
|
+
deps.log(`\u21E1 updated @paigy/harness ${VERSION} \u2192 ${latest} \u2014 restarting`);
|
|
17334
|
+
(deps.exit ?? (() => process.exit(0)))();
|
|
17335
|
+
} catch (e) {
|
|
17336
|
+
failed = latest;
|
|
17337
|
+
deps.log(`\u26A0 could not update to @paigy/harness ${latest}: ${e.message.split("\n")[0]} \u2014 run: npm install -g @paigy/harness`);
|
|
17338
|
+
}
|
|
17339
|
+
};
|
|
17340
|
+
}
|
|
17341
|
+
|
|
17277
17342
|
// src/host.ts
|
|
17278
|
-
var HOST_FILE =
|
|
17343
|
+
var HOST_FILE = join5(homedir5(), ".paigy", "host.json");
|
|
17279
17344
|
function readHostState() {
|
|
17280
17345
|
try {
|
|
17281
17346
|
const s = JSON.parse(readFileSync3(HOST_FILE, "utf8"));
|
|
@@ -17323,11 +17388,15 @@ function startHost(opts) {
|
|
|
17323
17388
|
}
|
|
17324
17389
|
}
|
|
17325
17390
|
};
|
|
17391
|
+
const update = selfUpdater({ sessions: () => runs.size, log: opts.log });
|
|
17326
17392
|
const beat = () => {
|
|
17327
17393
|
void refreshIdentities();
|
|
17394
|
+
void update().catch(() => {
|
|
17395
|
+
});
|
|
17328
17396
|
for (const r of runs.values()) if (r.token) void heartbeat(void 0, { token: r.token }).catch(() => {
|
|
17329
17397
|
});
|
|
17330
17398
|
void heartbeat({
|
|
17399
|
+
version: VERSION,
|
|
17331
17400
|
harnesses: detectAll().map((a) => ({ name: a.name, label: a.label, status: a.status })),
|
|
17332
17401
|
workspaces: listWorkspaces(opts.wsDeps)
|
|
17333
17402
|
}, asHost).catch(() => {
|
|
@@ -18112,7 +18181,7 @@ async function brokerView(deps) {
|
|
|
18112
18181
|
}
|
|
18113
18182
|
|
|
18114
18183
|
// src/main.ts
|
|
18115
|
-
var here =
|
|
18184
|
+
var here = dirname4(fileURLToPath(import.meta.url));
|
|
18116
18185
|
var wsDeps = { file: workspacesFile() };
|
|
18117
18186
|
var DEVICE_SLOT = "Desktop";
|
|
18118
18187
|
var deviceToken = () => readToken(DEVICE_SLOT);
|
|
@@ -18120,7 +18189,7 @@ var win = null;
|
|
|
18120
18189
|
function log(message) {
|
|
18121
18190
|
win?.webContents.send("paigy:log", message);
|
|
18122
18191
|
}
|
|
18123
|
-
var ICON =
|
|
18192
|
+
var ICON = join6(here, "..", "assets", "icon.png");
|
|
18124
18193
|
function createWindow() {
|
|
18125
18194
|
win = new BrowserWindow({
|
|
18126
18195
|
// Sized for the working log, which is now the window's centerpiece; the layout is a
|
|
@@ -18132,9 +18201,9 @@ function createWindow() {
|
|
|
18132
18201
|
minHeight: 520,
|
|
18133
18202
|
icon: ICON,
|
|
18134
18203
|
// Windows/Linux window icon; macOS uses the dock icon below
|
|
18135
|
-
webPreferences: { preload:
|
|
18204
|
+
webPreferences: { preload: join6(here, "preload.cjs"), contextIsolation: true, nodeIntegration: false }
|
|
18136
18205
|
});
|
|
18137
|
-
void win.loadFile(
|
|
18206
|
+
void win.loadFile(join6(here, "..", "renderer", "index.html"));
|
|
18138
18207
|
}
|
|
18139
18208
|
var host = null;
|
|
18140
18209
|
app.whenReady().then(() => {
|
|
@@ -18213,7 +18282,7 @@ ipcMain.handle("paigy:agent", async (_e, name) => {
|
|
|
18213
18282
|
});
|
|
18214
18283
|
ipcMain.handle("paigy:agent-log", (_e, name) => {
|
|
18215
18284
|
try {
|
|
18216
|
-
const all = readFileSync4(
|
|
18285
|
+
const all = readFileSync4(join6(homedir7(), ".paigy", "host.log"), "utf8").split("\n");
|
|
18217
18286
|
const mine = all.filter((l) => l.includes(`[${name}]`) || /[▶✖◉⚠]/.test(l) && l.includes(name));
|
|
18218
18287
|
return mine.slice(-500).join("\n");
|
|
18219
18288
|
} catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paigy/harness",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"description": "Run Claude Code / Codex on this machine, bridged to Paigy — launchable from your phone.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -9,6 +9,14 @@
|
|
|
9
9
|
"paigy-harness": "dist/cli.js",
|
|
10
10
|
"paigy": "dist/cli.js"
|
|
11
11
|
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsup",
|
|
14
|
+
"dev": "pnpm build && electron .",
|
|
15
|
+
"start": "electron .",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"prepublishOnly": "pnpm --filter @paigy/schema build && pnpm --filter @paigy/crypto build && pnpm --filter @paigy/sdk build && pnpm build"
|
|
19
|
+
},
|
|
12
20
|
"dependencies": {},
|
|
13
21
|
"devDependencies": {
|
|
14
22
|
"@types/node": "^22.0.0",
|
|
@@ -17,10 +25,10 @@
|
|
|
17
25
|
"tsup": "^8.3.5",
|
|
18
26
|
"typescript": "^5.7.2",
|
|
19
27
|
"vitest": "^2.1.8",
|
|
28
|
+
"@paigy/schema": "workspace:*",
|
|
29
|
+
"@paigy/sdk": "workspace:*",
|
|
20
30
|
"qrcode": "^1.5.4",
|
|
21
|
-
"zod": "^3.24.1"
|
|
22
|
-
"@paigy/schema": "0.0.0",
|
|
23
|
-
"@paigy/sdk": "0.2.1"
|
|
31
|
+
"zod": "^3.24.1"
|
|
24
32
|
},
|
|
25
33
|
"files": [
|
|
26
34
|
"dist/cli.js",
|
|
@@ -28,12 +36,5 @@
|
|
|
28
36
|
],
|
|
29
37
|
"publishConfig": {
|
|
30
38
|
"access": "public"
|
|
31
|
-
},
|
|
32
|
-
"scripts": {
|
|
33
|
-
"build": "tsup",
|
|
34
|
-
"dev": "pnpm build && electron .",
|
|
35
|
-
"start": "electron .",
|
|
36
|
-
"typecheck": "tsc --noEmit",
|
|
37
|
-
"test": "vitest run"
|
|
38
39
|
}
|
|
39
|
-
}
|
|
40
|
+
}
|