@paigy/harness 0.2.2 → 0.2.5
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 +9 -0
- package/dist/cli.js +38 -14
- package/dist/main.js +39 -15
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -168,6 +168,15 @@ macOS launchd agent so hosting survives reboots — the host loop IS the service
|
|
|
168
168
|
launchd just keeps it alive (the old "no daemon" note was about the WAKE channel,
|
|
169
169
|
which still belongs to paigy-listen).
|
|
170
170
|
|
|
171
|
+
## The window is not distributable (yet)
|
|
172
|
+
|
|
173
|
+
npm is the ONLY shipping channel: `@paigy/harness` installs the CLI and the whole
|
|
174
|
+
bridge, and updates with `npm i -g @paigy/harness@latest`. The Electron window runs
|
|
175
|
+
from source (`electron .`) — there is no packaging, no Developer ID signing or
|
|
176
|
+
notarization, and therefore no auto-update (macOS auto-update requires the signing).
|
|
177
|
+
A downloaded unsigned app would hit Gatekeeper's "damaged" dialog, which is worse
|
|
178
|
+
than no download button. Steps for when it's time: #854.
|
|
179
|
+
|
|
171
180
|
## Run it
|
|
172
181
|
|
|
173
182
|
```sh
|
package/dist/cli.js
CHANGED
|
@@ -11631,10 +11631,10 @@ var require_headers = __commonJS({
|
|
|
11631
11631
|
const lowercaseName = isLowerCase ? name : name.toLowerCase();
|
|
11632
11632
|
const exists = this[kHeadersMap].get(lowercaseName);
|
|
11633
11633
|
if (exists) {
|
|
11634
|
-
const
|
|
11634
|
+
const delimiter3 = lowercaseName === "cookie" ? "; " : ", ";
|
|
11635
11635
|
this[kHeadersMap].set(lowercaseName, {
|
|
11636
11636
|
name: exists.name,
|
|
11637
|
-
value: `${exists.value}${
|
|
11637
|
+
value: `${exists.value}${delimiter3}${value}`
|
|
11638
11638
|
});
|
|
11639
11639
|
} else {
|
|
11640
11640
|
this[kHeadersMap].set(lowercaseName, { name, value });
|
|
@@ -23091,7 +23091,7 @@ var require_lib = __commonJS({
|
|
|
23091
23091
|
import { spawnSync } from "child_process";
|
|
23092
23092
|
import { existsSync } from "fs";
|
|
23093
23093
|
import { homedir } from "os";
|
|
23094
|
-
import { join } from "path";
|
|
23094
|
+
import { delimiter, dirname, join } from "path";
|
|
23095
23095
|
var CATALOG = [
|
|
23096
23096
|
{
|
|
23097
23097
|
name: "claude",
|
|
@@ -23115,7 +23115,13 @@ var CATALOG = [
|
|
|
23115
23115
|
}
|
|
23116
23116
|
];
|
|
23117
23117
|
function probeDirs(home = homedir()) {
|
|
23118
|
-
return [
|
|
23118
|
+
return [
|
|
23119
|
+
dirname(process.execPath),
|
|
23120
|
+
join(home, ".local", "bin"),
|
|
23121
|
+
"/usr/local/bin",
|
|
23122
|
+
"/opt/homebrew/bin",
|
|
23123
|
+
join(home, ".npm-global", "bin")
|
|
23124
|
+
];
|
|
23119
23125
|
}
|
|
23120
23126
|
function which(bin) {
|
|
23121
23127
|
const hit = spawnSync("which", [bin], { encoding: "utf8" });
|
|
@@ -23132,7 +23138,11 @@ function runProbe(argv) {
|
|
|
23132
23138
|
if (!cmd) return false;
|
|
23133
23139
|
const resolved = which(cmd);
|
|
23134
23140
|
if (!resolved) return false;
|
|
23135
|
-
return spawnSync(resolved, args, {
|
|
23141
|
+
return spawnSync(resolved, args, {
|
|
23142
|
+
timeout: 1e4,
|
|
23143
|
+
stdio: "ignore",
|
|
23144
|
+
env: { ...process.env, PATH: [process.env.PATH, ...probeDirs()].filter(Boolean).join(delimiter) }
|
|
23145
|
+
}).status === 0;
|
|
23136
23146
|
}
|
|
23137
23147
|
function detect(entry, deps = {}) {
|
|
23138
23148
|
const find = deps.which ?? which;
|
|
@@ -29735,7 +29745,12 @@ var UserAnswerSchema = external_exports.discriminatedUnion("kind", [
|
|
|
29735
29745
|
external_exports.object({ kind: external_exports.literal("ranked"), optionIds: external_exports.array(external_exports.string()), labels: external_exports.array(external_exports.string()).optional() }),
|
|
29736
29746
|
external_exports.object({ kind: external_exports.literal("clarify"), chunks: external_exports.array(external_exports.string()).min(1) }),
|
|
29737
29747
|
external_exports.object({ kind: external_exports.literal("confirm"), approved: external_exports.boolean() }),
|
|
29738
|
-
external_exports.object({ kind: external_exports.literal("turns"), turns: external_exports.array(TurnSchema).min(1) })
|
|
29748
|
+
external_exports.object({ kind: external_exports.literal("turns"), turns: external_exports.array(TurnSchema).min(1) }),
|
|
29749
|
+
/** An auto-answer derived from the user's PAST decisions (broker/precedent-design.md §2):
|
|
29750
|
+
* delivered through the same settle/await path as a human answer, carrying the judge's
|
|
29751
|
+
* derivation and the precedent ids it grew from. Always paired with a visible trail
|
|
29752
|
+
* card the user can reply to — the broker never overrides the user. */
|
|
29753
|
+
external_exports.object({ kind: external_exports.literal("precedent"), answer: external_exports.string(), derivation: external_exports.string(), sources: external_exports.array(external_exports.string()).min(1) })
|
|
29739
29754
|
]);
|
|
29740
29755
|
var IntentSchema = external_exports.object({
|
|
29741
29756
|
// The full vocabulary the bot's mapper emits (mapper.INTENT_KINDS) — the schema lagged
|
|
@@ -30804,7 +30819,7 @@ function landIntents(intents) {
|
|
|
30804
30819
|
});
|
|
30805
30820
|
}
|
|
30806
30821
|
async function checkReplies(opts = {}) {
|
|
30807
|
-
const token =
|
|
30822
|
+
const token = authToken(opts.token);
|
|
30808
30823
|
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/pending`, {
|
|
30809
30824
|
headers: { authorization: `Bearer ${token}` }
|
|
30810
30825
|
}));
|
|
@@ -31084,7 +31099,12 @@ var UserAnswerSchema2 = external_exports.discriminatedUnion("kind", [
|
|
|
31084
31099
|
external_exports.object({ kind: external_exports.literal("ranked"), optionIds: external_exports.array(external_exports.string()), labels: external_exports.array(external_exports.string()).optional() }),
|
|
31085
31100
|
external_exports.object({ kind: external_exports.literal("clarify"), chunks: external_exports.array(external_exports.string()).min(1) }),
|
|
31086
31101
|
external_exports.object({ kind: external_exports.literal("confirm"), approved: external_exports.boolean() }),
|
|
31087
|
-
external_exports.object({ kind: external_exports.literal("turns"), turns: external_exports.array(TurnSchema2).min(1) })
|
|
31102
|
+
external_exports.object({ kind: external_exports.literal("turns"), turns: external_exports.array(TurnSchema2).min(1) }),
|
|
31103
|
+
/** An auto-answer derived from the user's PAST decisions (broker/precedent-design.md §2):
|
|
31104
|
+
* delivered through the same settle/await path as a human answer, carrying the judge's
|
|
31105
|
+
* derivation and the precedent ids it grew from. Always paired with a visible trail
|
|
31106
|
+
* card the user can reply to — the broker never overrides the user. */
|
|
31107
|
+
external_exports.object({ kind: external_exports.literal("precedent"), answer: external_exports.string(), derivation: external_exports.string(), sources: external_exports.array(external_exports.string()).min(1) })
|
|
31088
31108
|
]);
|
|
31089
31109
|
var IntentSchema2 = external_exports.object({
|
|
31090
31110
|
// The full vocabulary the bot's mapper emits (mapper.INTENT_KINDS) — the schema lagged
|
|
@@ -31956,6 +31976,9 @@ function spokenText(answer) {
|
|
|
31956
31976
|
// A call log: the user's replies are the instruction, the bot's prompts are not.
|
|
31957
31977
|
case "turns":
|
|
31958
31978
|
return answer.turns.map((t) => t.reply).join(" ").trim() || null;
|
|
31979
|
+
// An auto-answer derived from the user's past decisions — reads like a fast human.
|
|
31980
|
+
case "precedent":
|
|
31981
|
+
return answer.answer;
|
|
31959
31982
|
case "ignored":
|
|
31960
31983
|
return null;
|
|
31961
31984
|
}
|
|
@@ -31967,7 +31990,7 @@ var clip = (s) => (s.length > 120 ? `${s.slice(0, 117)}\u2026` : s) || "(no text
|
|
|
31967
31990
|
import { spawn } from "child_process";
|
|
31968
31991
|
import { existsSync as existsSync3 } from "fs";
|
|
31969
31992
|
import { homedir as homedir3 } from "os";
|
|
31970
|
-
import {
|
|
31993
|
+
import { resolve, delimiter as delimiter2 } from "path";
|
|
31971
31994
|
|
|
31972
31995
|
// src/harness/acp.ts
|
|
31973
31996
|
var none = { events: [], writes: [] };
|
|
@@ -32200,7 +32223,7 @@ function startSession(opts) {
|
|
|
32200
32223
|
// PATH knows neither — live catch 2026-08-04: the first slot-wake ENOENT'd).
|
|
32201
32224
|
env: {
|
|
32202
32225
|
...process.env,
|
|
32203
|
-
PATH: [process.env.PATH,
|
|
32226
|
+
PATH: [process.env.PATH, ...probeDirs()].filter(Boolean).join(delimiter2),
|
|
32204
32227
|
...opts.token ? { PAIGY_TOKEN: opts.token } : {}
|
|
32205
32228
|
},
|
|
32206
32229
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -32329,7 +32352,7 @@ function runHarness(opts) {
|
|
|
32329
32352
|
|
|
32330
32353
|
// src/workspaces.ts
|
|
32331
32354
|
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
32332
|
-
import { dirname as
|
|
32355
|
+
import { dirname as dirname3, join as join3, resolve as resolve2 } from "path";
|
|
32333
32356
|
import { homedir as homedir4 } from "os";
|
|
32334
32357
|
function workspacesFile() {
|
|
32335
32358
|
return join3(homedir4(), ".paigy", "workspaces.json");
|
|
@@ -32347,7 +32370,7 @@ function addWorkspace(dir, deps) {
|
|
|
32347
32370
|
const all = listWorkspaces(deps);
|
|
32348
32371
|
if (!all.includes(next)) {
|
|
32349
32372
|
all.push(next);
|
|
32350
|
-
mkdirSync2(
|
|
32373
|
+
mkdirSync2(dirname3(deps.file), { recursive: true });
|
|
32351
32374
|
writeFileSync2(deps.file, JSON.stringify(all, null, 2));
|
|
32352
32375
|
}
|
|
32353
32376
|
return all;
|
|
@@ -32387,11 +32410,12 @@ function startHost(opts) {
|
|
|
32387
32410
|
}
|
|
32388
32411
|
}
|
|
32389
32412
|
const SLOT_HARNESS = { "mcp-agent": "claude", codex: "codex" };
|
|
32413
|
+
const WAKE_PROMPT = "You were woken because Paigy work is waiting for you. Call check_replies now and handle everything it returns, then follow your paigy instructions to stay in the loop.";
|
|
32390
32414
|
async function sweepSlots() {
|
|
32391
32415
|
const workspace = listWorkspaces(opts.wsDeps)[0];
|
|
32392
32416
|
if (!workspace) return;
|
|
32393
32417
|
for (const slot of listSlots()) {
|
|
32394
|
-
const harness = SLOT_HARNESS[slot];
|
|
32418
|
+
const harness = SLOT_HARNESS[slot] ?? (slot === "Desktop" ? void 0 : "claude");
|
|
32395
32419
|
const key = `slot:${slot}`;
|
|
32396
32420
|
if (!harness || runs.has(key)) continue;
|
|
32397
32421
|
const token = readToken(slot);
|
|
@@ -32403,7 +32427,7 @@ function startHost(opts) {
|
|
|
32403
32427
|
harness,
|
|
32404
32428
|
cwd: workspace,
|
|
32405
32429
|
mode: "bypass",
|
|
32406
|
-
prompt:
|
|
32430
|
+
prompt: WAKE_PROMPT,
|
|
32407
32431
|
exclusive: true,
|
|
32408
32432
|
token,
|
|
32409
32433
|
// A dead run must not squat the slot — evict so the next wake can respawn.
|
package/dist/main.js
CHANGED
|
@@ -4577,7 +4577,7 @@ var require_lib = __commonJS({
|
|
|
4577
4577
|
import { app, BrowserWindow, dialog, ipcMain } from "electron";
|
|
4578
4578
|
import { spawn as spawn2 } from "child_process";
|
|
4579
4579
|
import { fileURLToPath } from "url";
|
|
4580
|
-
import { dirname as
|
|
4580
|
+
import { dirname as dirname4, join as join4 } from "path";
|
|
4581
4581
|
|
|
4582
4582
|
// ../../packages/sdk/dist/index.js
|
|
4583
4583
|
import { createRequire as __sdkCreateRequire } from "module";
|
|
@@ -11157,7 +11157,12 @@ var UserAnswerSchema = external_exports.discriminatedUnion("kind", [
|
|
|
11157
11157
|
external_exports.object({ kind: external_exports.literal("ranked"), optionIds: external_exports.array(external_exports.string()), labels: external_exports.array(external_exports.string()).optional() }),
|
|
11158
11158
|
external_exports.object({ kind: external_exports.literal("clarify"), chunks: external_exports.array(external_exports.string()).min(1) }),
|
|
11159
11159
|
external_exports.object({ kind: external_exports.literal("confirm"), approved: external_exports.boolean() }),
|
|
11160
|
-
external_exports.object({ kind: external_exports.literal("turns"), turns: external_exports.array(TurnSchema).min(1) })
|
|
11160
|
+
external_exports.object({ kind: external_exports.literal("turns"), turns: external_exports.array(TurnSchema).min(1) }),
|
|
11161
|
+
/** An auto-answer derived from the user's PAST decisions (broker/precedent-design.md §2):
|
|
11162
|
+
* delivered through the same settle/await path as a human answer, carrying the judge's
|
|
11163
|
+
* derivation and the precedent ids it grew from. Always paired with a visible trail
|
|
11164
|
+
* card the user can reply to — the broker never overrides the user. */
|
|
11165
|
+
external_exports.object({ kind: external_exports.literal("precedent"), answer: external_exports.string(), derivation: external_exports.string(), sources: external_exports.array(external_exports.string()).min(1) })
|
|
11161
11166
|
]);
|
|
11162
11167
|
var IntentSchema = external_exports.object({
|
|
11163
11168
|
// The full vocabulary the bot's mapper emits (mapper.INTENT_KINDS) — the schema lagged
|
|
@@ -12226,7 +12231,7 @@ function landIntents(intents) {
|
|
|
12226
12231
|
});
|
|
12227
12232
|
}
|
|
12228
12233
|
async function checkReplies(opts = {}) {
|
|
12229
|
-
const token =
|
|
12234
|
+
const token = authToken(opts.token);
|
|
12230
12235
|
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/pending`, {
|
|
12231
12236
|
headers: { authorization: `Bearer ${token}` }
|
|
12232
12237
|
}));
|
|
@@ -12278,7 +12283,7 @@ import { hostname } from "os";
|
|
|
12278
12283
|
import { spawnSync } from "child_process";
|
|
12279
12284
|
import { existsSync as existsSync2 } from "fs";
|
|
12280
12285
|
import { homedir as homedir2 } from "os";
|
|
12281
|
-
import { join as join2 } from "path";
|
|
12286
|
+
import { delimiter, dirname, join as join2 } from "path";
|
|
12282
12287
|
var CATALOG = [
|
|
12283
12288
|
{
|
|
12284
12289
|
name: "claude",
|
|
@@ -12302,7 +12307,13 @@ var CATALOG = [
|
|
|
12302
12307
|
}
|
|
12303
12308
|
];
|
|
12304
12309
|
function probeDirs(home = homedir2()) {
|
|
12305
|
-
return [
|
|
12310
|
+
return [
|
|
12311
|
+
dirname(process.execPath),
|
|
12312
|
+
join2(home, ".local", "bin"),
|
|
12313
|
+
"/usr/local/bin",
|
|
12314
|
+
"/opt/homebrew/bin",
|
|
12315
|
+
join2(home, ".npm-global", "bin")
|
|
12316
|
+
];
|
|
12306
12317
|
}
|
|
12307
12318
|
function which(bin) {
|
|
12308
12319
|
const hit = spawnSync("which", [bin], { encoding: "utf8" });
|
|
@@ -12319,7 +12330,11 @@ function runProbe(argv) {
|
|
|
12319
12330
|
if (!cmd) return false;
|
|
12320
12331
|
const resolved = which(cmd);
|
|
12321
12332
|
if (!resolved) return false;
|
|
12322
|
-
return spawnSync(resolved, args, {
|
|
12333
|
+
return spawnSync(resolved, args, {
|
|
12334
|
+
timeout: 1e4,
|
|
12335
|
+
stdio: "ignore",
|
|
12336
|
+
env: { ...process.env, PATH: [process.env.PATH, ...probeDirs()].filter(Boolean).join(delimiter) }
|
|
12337
|
+
}).status === 0;
|
|
12323
12338
|
}
|
|
12324
12339
|
function detect(entry, deps = {}) {
|
|
12325
12340
|
const find = deps.which ?? which;
|
|
@@ -12346,7 +12361,7 @@ function detectAll(deps = {}) {
|
|
|
12346
12361
|
|
|
12347
12362
|
// src/workspaces.ts
|
|
12348
12363
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
12349
|
-
import { dirname, join as join3, resolve } from "path";
|
|
12364
|
+
import { dirname as dirname2, join as join3, resolve } from "path";
|
|
12350
12365
|
import { homedir as homedir3 } from "os";
|
|
12351
12366
|
function workspacesFile() {
|
|
12352
12367
|
return join3(homedir3(), ".paigy", "workspaces.json");
|
|
@@ -12364,14 +12379,14 @@ function addWorkspace(dir, deps) {
|
|
|
12364
12379
|
const all = listWorkspaces(deps);
|
|
12365
12380
|
if (!all.includes(next)) {
|
|
12366
12381
|
all.push(next);
|
|
12367
|
-
mkdirSync2(
|
|
12382
|
+
mkdirSync2(dirname2(deps.file), { recursive: true });
|
|
12368
12383
|
writeFileSync2(deps.file, JSON.stringify(all, null, 2));
|
|
12369
12384
|
}
|
|
12370
12385
|
return all;
|
|
12371
12386
|
}
|
|
12372
12387
|
function removeWorkspace(dir, deps) {
|
|
12373
12388
|
const all = listWorkspaces(deps).filter((w) => w !== dir);
|
|
12374
|
-
mkdirSync2(
|
|
12389
|
+
mkdirSync2(dirname2(deps.file), { recursive: true });
|
|
12375
12390
|
writeFileSync2(deps.file, JSON.stringify(all, null, 2));
|
|
12376
12391
|
return all;
|
|
12377
12392
|
}
|
|
@@ -12380,7 +12395,7 @@ function removeWorkspace(dir, deps) {
|
|
|
12380
12395
|
import { spawn } from "child_process";
|
|
12381
12396
|
import { existsSync as existsSync4 } from "fs";
|
|
12382
12397
|
import { homedir as homedir4 } from "os";
|
|
12383
|
-
import {
|
|
12398
|
+
import { resolve as resolve2, delimiter as delimiter2 } from "path";
|
|
12384
12399
|
|
|
12385
12400
|
// src/harness/acp.ts
|
|
12386
12401
|
var none = { events: [], writes: [] };
|
|
@@ -12613,7 +12628,7 @@ function startSession(opts) {
|
|
|
12613
12628
|
// PATH knows neither — live catch 2026-08-04: the first slot-wake ENOENT'd).
|
|
12614
12629
|
env: {
|
|
12615
12630
|
...process.env,
|
|
12616
|
-
PATH: [process.env.PATH,
|
|
12631
|
+
PATH: [process.env.PATH, ...probeDirs()].filter(Boolean).join(delimiter2),
|
|
12617
12632
|
...opts.token ? { PAIGY_TOKEN: opts.token } : {}
|
|
12618
12633
|
},
|
|
12619
12634
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -12876,7 +12891,12 @@ var UserAnswerSchema2 = external_exports.discriminatedUnion("kind", [
|
|
|
12876
12891
|
external_exports.object({ kind: external_exports.literal("ranked"), optionIds: external_exports.array(external_exports.string()), labels: external_exports.array(external_exports.string()).optional() }),
|
|
12877
12892
|
external_exports.object({ kind: external_exports.literal("clarify"), chunks: external_exports.array(external_exports.string()).min(1) }),
|
|
12878
12893
|
external_exports.object({ kind: external_exports.literal("confirm"), approved: external_exports.boolean() }),
|
|
12879
|
-
external_exports.object({ kind: external_exports.literal("turns"), turns: external_exports.array(TurnSchema2).min(1) })
|
|
12894
|
+
external_exports.object({ kind: external_exports.literal("turns"), turns: external_exports.array(TurnSchema2).min(1) }),
|
|
12895
|
+
/** An auto-answer derived from the user's PAST decisions (broker/precedent-design.md §2):
|
|
12896
|
+
* delivered through the same settle/await path as a human answer, carrying the judge's
|
|
12897
|
+
* derivation and the precedent ids it grew from. Always paired with a visible trail
|
|
12898
|
+
* card the user can reply to — the broker never overrides the user. */
|
|
12899
|
+
external_exports.object({ kind: external_exports.literal("precedent"), answer: external_exports.string(), derivation: external_exports.string(), sources: external_exports.array(external_exports.string()).min(1) })
|
|
12880
12900
|
]);
|
|
12881
12901
|
var IntentSchema2 = external_exports.object({
|
|
12882
12902
|
// The full vocabulary the bot's mapper emits (mapper.INTENT_KINDS) — the schema lagged
|
|
@@ -13737,6 +13757,9 @@ function spokenText(answer) {
|
|
|
13737
13757
|
// A call log: the user's replies are the instruction, the bot's prompts are not.
|
|
13738
13758
|
case "turns":
|
|
13739
13759
|
return answer.turns.map((t) => t.reply).join(" ").trim() || null;
|
|
13760
|
+
// An auto-answer derived from the user's past decisions — reads like a fast human.
|
|
13761
|
+
case "precedent":
|
|
13762
|
+
return answer.answer;
|
|
13740
13763
|
case "ignored":
|
|
13741
13764
|
return null;
|
|
13742
13765
|
}
|
|
@@ -13858,11 +13881,12 @@ function startHost(opts) {
|
|
|
13858
13881
|
}
|
|
13859
13882
|
}
|
|
13860
13883
|
const SLOT_HARNESS = { "mcp-agent": "claude", codex: "codex" };
|
|
13884
|
+
const WAKE_PROMPT = "You were woken because Paigy work is waiting for you. Call check_replies now and handle everything it returns, then follow your paigy instructions to stay in the loop.";
|
|
13861
13885
|
async function sweepSlots() {
|
|
13862
13886
|
const workspace = listWorkspaces(opts.wsDeps)[0];
|
|
13863
13887
|
if (!workspace) return;
|
|
13864
13888
|
for (const slot of listSlots()) {
|
|
13865
|
-
const harness = SLOT_HARNESS[slot];
|
|
13889
|
+
const harness = SLOT_HARNESS[slot] ?? (slot === "Desktop" ? void 0 : "claude");
|
|
13866
13890
|
const key = `slot:${slot}`;
|
|
13867
13891
|
if (!harness || runs.has(key)) continue;
|
|
13868
13892
|
const token = readToken(slot);
|
|
@@ -13874,7 +13898,7 @@ function startHost(opts) {
|
|
|
13874
13898
|
harness,
|
|
13875
13899
|
cwd: workspace,
|
|
13876
13900
|
mode: "bypass",
|
|
13877
|
-
prompt:
|
|
13901
|
+
prompt: WAKE_PROMPT,
|
|
13878
13902
|
exclusive: true,
|
|
13879
13903
|
token,
|
|
13880
13904
|
// A dead run must not squat the slot — evict so the next wake can respawn.
|
|
@@ -13913,7 +13937,7 @@ function startHost(opts) {
|
|
|
13913
13937
|
}
|
|
13914
13938
|
|
|
13915
13939
|
// src/main.ts
|
|
13916
|
-
var here =
|
|
13940
|
+
var here = dirname4(fileURLToPath(import.meta.url));
|
|
13917
13941
|
var wsDeps = { file: workspacesFile() };
|
|
13918
13942
|
var DEVICE_SLOT = "Desktop";
|
|
13919
13943
|
var deviceToken = () => readToken(DEVICE_SLOT) || readToken();
|
package/package.json
CHANGED
|
@@ -1,20 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paigy/harness",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Run Claude Code / Codex on this machine, bridged to Paigy
|
|
3
|
+
"version": "0.2.5",
|
|
4
|
+
"description": "Run Claude Code / Codex on this machine, bridged to Paigy — launchable from your phone.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/main.js",
|
|
8
8
|
"bin": {
|
|
9
9
|
"paigy-harness": "dist/cli.js"
|
|
10
10
|
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "tsup",
|
|
13
|
-
"dev": "pnpm build && electron .",
|
|
14
|
-
"start": "electron .",
|
|
15
|
-
"typecheck": "tsc --noEmit",
|
|
16
|
-
"test": "vitest run"
|
|
17
|
-
},
|
|
18
11
|
"dependencies": {},
|
|
19
12
|
"devDependencies": {
|
|
20
13
|
"@types/node": "^22.0.0",
|
|
@@ -23,10 +16,10 @@
|
|
|
23
16
|
"tsup": "^8.3.5",
|
|
24
17
|
"typescript": "^5.7.2",
|
|
25
18
|
"vitest": "^2.1.8",
|
|
26
|
-
"@paigy/schema": "workspace:*",
|
|
27
|
-
"@paigy/sdk": "workspace:*",
|
|
28
19
|
"qrcode": "^1.5.4",
|
|
29
|
-
"zod": "^3.24.1"
|
|
20
|
+
"zod": "^3.24.1",
|
|
21
|
+
"@paigy/schema": "0.0.0",
|
|
22
|
+
"@paigy/sdk": "0.1.0"
|
|
30
23
|
},
|
|
31
24
|
"files": [
|
|
32
25
|
"dist/cli.js",
|
|
@@ -34,5 +27,12 @@
|
|
|
34
27
|
],
|
|
35
28
|
"publishConfig": {
|
|
36
29
|
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsup",
|
|
33
|
+
"dev": "pnpm build && electron .",
|
|
34
|
+
"start": "electron .",
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"test": "vitest run"
|
|
37
37
|
}
|
|
38
|
-
}
|
|
38
|
+
}
|