plures 1.12.0 → 1.14.0
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 +1 -1
- package/dist/{chunk-GDI4KDAH.js → chunk-7OMKME5Z.js} +3 -1
- package/dist/cli.cjs +28 -7
- package/dist/cli.js +26 -7
- package/dist/index.cjs +3 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ if (event.type === "task.completed" && event.data.result?.agreement === 1) {
|
|
|
51
51
|
- `plures.maps.createKey(app, { label? })`, `.keys(app)`, `.revokeKey(app, id)`: map keys for CI, which can only read and upload that app's map. `.workflow(app, branch?)` returns the GitHub Action that maps on every push; `npx plures map workflow` writes it to `.github/workflows/plures-map.yml`. Or use **Map with GitHub** on the app's map page and Plures opens the pull request for you, then **Turn on mapping** merges it. `plures.maps.startRun(app)` and `.runs(app)`: in CI with no Claude key, `npx plures map` starts a run where Plures runs Claude (first map free, then Claude's cost plus 30%, at most $5).
|
|
52
52
|
- In your terminal, `npx plures map` opens your map page so you can watch it build (`--no-open` to skip), keeps one live line of what it's reading, and ends by drawing the map's flows with the checks Plures suggests. On GitHub and other CI it prints a plain log.
|
|
53
53
|
- `npx plures map` shows each file as Claude Code reads it and sends the file names (never their contents) to Plures, so the map page shows the reading live and the map builds itself when it lands. `plures.maps.progress(app, { session, phase, events })` is the call behind it.
|
|
54
|
-
- `plures.github.repos()`, `.connect(app, "owner/repo")`, `.turnOn(app)`, `.status(app)`, `.disconnect(app)`: Map with GitHub from code. Plures sets the repo's map key secret and opens a pull request adding the workflow; `turnOn` merges it. Installing the Plures GitHub App needs a browser once (`install_url`). From a terminal: `npx plures map github connect`, then `npx plures map github on
|
|
54
|
+
- `plures.github.repos()`, `.connect(app, "owner/repo")`, `.turnOn(app)`, `.run(app)` (map now), `.status(app)`, `.disconnect(app)`: Map with GitHub from code. Plures sets the repo's map key secret and opens a pull request adding the workflow; `turnOn` merges it. Installing the Plures GitHub App needs a browser once (`install_url`). From a terminal: `npx plures map github connect`, then `npx plures map github on`; `npx plures map github run` maps again now.
|
|
55
55
|
- `plures.quality.sample({ rubric, output, input? })`: send every output; a share is graded by people against the rubric, with personal details taken out first. `plures.quality.rubrics.create({ name, question, options, sample_rate })`, `.retrieve(name)` (score by day, this week against the four before, drift), `.list()`, `.update()`, `.del()`. `plures.quality.compare({ release, input, a, b })` and `plures.quality.release(name)` for blind release checks. `plures.quality.export(rubric)` returns graded samples for evals or fine tuning.
|
|
56
56
|
- `plures.testMix.set({ unanimous: 70, split: 20, tie: 5, expired: 5 })`, `.get()`, `.clear()`: with a test key, makes a share of test tasks split, tie or expire at random so you can test routing to your team without changing your agent. A task can override it with `metadata.test_mix`, and `metadata.test_outcome` beats both.
|
|
57
57
|
- `plures.routing.get()`, `plures.routing.set({ groups, rules, team })`: named teams of your own people and rules by category, like `{ groups: [{ name: "Finance", emails: ["ap@acme.com"] }], rules: [{ category: "refunds", route: "team", group: "Finance" }] }`. What you send replaces what's there; the rest stays.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
var VERSION = "1.
|
|
2
|
+
var VERSION = "1.14.0";
|
|
3
3
|
var PluresError = class extends Error {
|
|
4
4
|
constructor(message, status, type) {
|
|
5
5
|
super(message);
|
|
@@ -130,6 +130,8 @@ var Plures = class {
|
|
|
130
130
|
/** Connects a repo ("owner/name"): sets its map key secret and opens the pull request. */
|
|
131
131
|
connect: (app, repo) => this.req("POST", `/api/v1/apps/${encodeURIComponent(app)}/github`, { repo }),
|
|
132
132
|
/** Turns mapping on by merging the pull request. The repo's own rules (reviews, checks) still apply. */
|
|
133
|
+
/** Map now: runs the app's map workflow on GitHub. { update: true } first updates an older workflow. Watch it on the map page. */
|
|
134
|
+
run: (app, opts = {}) => this.req("POST", `/api/v1/apps/${encodeURIComponent(app)}/github/run`, opts),
|
|
133
135
|
turnOn: (app) => this.req("POST", `/api/v1/apps/${encodeURIComponent(app)}/github/merge`, {}),
|
|
134
136
|
/** Revokes the repo's map key. Delete the workflow file in the repo to stop runs. */
|
|
135
137
|
disconnect: (app) => this.req("DELETE", `/api/v1/apps/${encodeURIComponent(app)}/github`)
|
package/dist/cli.cjs
CHANGED
|
@@ -30,7 +30,7 @@ var import_node_path = require("path");
|
|
|
30
30
|
var import_node_fs = require("fs");
|
|
31
31
|
|
|
32
32
|
// src/index.ts
|
|
33
|
-
var VERSION = "1.
|
|
33
|
+
var VERSION = "1.14.0";
|
|
34
34
|
var PluresError = class extends Error {
|
|
35
35
|
constructor(message, status, type) {
|
|
36
36
|
super(message);
|
|
@@ -161,6 +161,8 @@ var Plures = class {
|
|
|
161
161
|
/** Connects a repo ("owner/name"): sets its map key secret and opens the pull request. */
|
|
162
162
|
connect: (app2, repo) => this.req("POST", `/api/v1/apps/${encodeURIComponent(app2)}/github`, { repo }),
|
|
163
163
|
/** Turns mapping on by merging the pull request. The repo's own rules (reviews, checks) still apply. */
|
|
164
|
+
/** Map now: runs the app's map workflow on GitHub. { update: true } first updates an older workflow. Watch it on the map page. */
|
|
165
|
+
run: (app2, opts = {}) => this.req("POST", `/api/v1/apps/${encodeURIComponent(app2)}/github/run`, opts),
|
|
164
166
|
turnOn: (app2) => this.req("POST", `/api/v1/apps/${encodeURIComponent(app2)}/github/merge`, {}),
|
|
165
167
|
/** Revokes the repo's map key. Delete the workflow file in the repo to stop runs. */
|
|
166
168
|
disconnect: (app2) => this.req("DELETE", `/api/v1/apps/${encodeURIComponent(app2)}/github`)
|
|
@@ -504,7 +506,8 @@ With plures-mcp connected, just ask: ${cyan("Map this app for Plures")}`);
|
|
|
504
506
|
`);
|
|
505
507
|
const prompt = `${guide}
|
|
506
508
|
|
|
507
|
-
Write the map to ${FILE} in the current directory now. Read the code; don't run it or change anything else.`;
|
|
509
|
+
Write the map to ${FILE} in the current directory now, as JSON, with the Write tool. Read the code; don't run it or change anything else. Don't write a script to generate the map: you can't run scripts or other commands here, so write the JSON itself.`;
|
|
510
|
+
const nudge = `${FILE} doesn't exist yet. Write it now with the Write tool: the complete map as JSON, directly. You can't run scripts or commands here, so don't write one. Use what you've already read.`;
|
|
508
511
|
const live = key ? client() : null;
|
|
509
512
|
const session = (0, import_node_crypto.randomBytes)(12).toString("base64url");
|
|
510
513
|
const source = process.env.GITHUB_ACTIONS ? "github" : "cli";
|
|
@@ -530,8 +533,8 @@ Write the map to ${FILE} in the current directory now. Read the code; don't run
|
|
|
530
533
|
let result = "";
|
|
531
534
|
const ticker = fancy ? liveLine() : null;
|
|
532
535
|
ticker?.start();
|
|
533
|
-
const
|
|
534
|
-
const p = (0, import_node_child_process.spawn)("claude", [
|
|
536
|
+
const runClaude = (args) => new Promise((resolve) => {
|
|
537
|
+
const p = (0, import_node_child_process.spawn)("claude", [...args, "--output-format", "stream-json", "--verbose", "--allowedTools", "Read,Grep,Glob,Write,Bash(git rev-parse:*),Bash(git remote:*)"], { stdio: ["ignore", "pipe", "inherit"], env: childEnv });
|
|
535
538
|
let buf = "";
|
|
536
539
|
p.stdout.on("data", (chunk) => {
|
|
537
540
|
buf += chunk.toString();
|
|
@@ -567,18 +570,21 @@ Write the map to ${FILE} in the current directory now. Read the code; don't run
|
|
|
567
570
|
p.on("close", (n) => resolve(n ?? 1));
|
|
568
571
|
p.on("error", () => resolve(1));
|
|
569
572
|
});
|
|
573
|
+
const wrote = () => (0, import_node_fs.existsSync)(FILE) && (0, import_node_fs.statSync)(FILE).mtimeMs !== before;
|
|
574
|
+
let code = await runClaude(["-p", prompt]);
|
|
575
|
+
if (!wrote()) code = await runClaude(["-p", nudge, "--continue"]);
|
|
570
576
|
clearInterval(tick);
|
|
571
577
|
ticker?.stop();
|
|
572
578
|
if (result && !fancy) console.log(`
|
|
573
579
|
${result.trim()}
|
|
574
580
|
`);
|
|
575
581
|
if (fancy) console.log(` ${cyan("\u2713")} ${reads} ${reads === 1 ? "file" : "files"} read. ${dim("Sending the map to Plures. No source code is sent.")}`);
|
|
576
|
-
const ok = code === 0 && (
|
|
582
|
+
const ok = code === 0 && wrote();
|
|
577
583
|
if (!ok) {
|
|
578
584
|
phase = "failed";
|
|
579
585
|
await flush();
|
|
580
586
|
} else await flush();
|
|
581
|
-
if (
|
|
587
|
+
if (!ok) die(`Claude Code didn't write ${FILE}${process.env.CI ? ". This run costs nothing." : `. Ask it directly, then run npx plures map upload.`}`);
|
|
582
588
|
await upload(FILE);
|
|
583
589
|
}
|
|
584
590
|
async function workflow() {
|
|
@@ -617,6 +623,20 @@ Turn it on: ${cyan("npx plures map github on")}${app !== "default" ? ` --app ${a
|
|
|
617
623
|
};
|
|
618
624
|
try {
|
|
619
625
|
if (!action || action === "status") return show(await p.github.status(app));
|
|
626
|
+
if (action === "run") {
|
|
627
|
+
let r;
|
|
628
|
+
try {
|
|
629
|
+
r = await p.github.run(app);
|
|
630
|
+
} catch (e) {
|
|
631
|
+
if (!(e instanceof PluresError && e.type === "workflow_outdated")) throw e;
|
|
632
|
+
console.log(dim("This repo's map workflow is from before Map now. Updating it, which merges a small change to the workflow file."));
|
|
633
|
+
r = await p.github.run(app, { update: true });
|
|
634
|
+
}
|
|
635
|
+
const url = `${base}/dashboard/apps/${encodeURIComponent(app)}/map`;
|
|
636
|
+
console.log(`${bold("Mapping now on GitHub.")} Watch it build: ${cyan(url)}`);
|
|
637
|
+
if (fancy && !noOpen) await openBrowser(url);
|
|
638
|
+
return void r;
|
|
639
|
+
}
|
|
620
640
|
if (action === "on") {
|
|
621
641
|
const r = await p.github.turnOn(app);
|
|
622
642
|
console.log(r.already_merged ? "Mapping was already on." : `${bold("Mapping is on.")} The first run is starting on GitHub.`);
|
|
@@ -638,7 +658,7 @@ Turn it on: ${cyan("npx plures map github on")}${app !== "default" ? ` --app ${a
|
|
|
638
658
|
It adds one workflow file. Review it, then turn mapping on with ${cyan("npx plures map github on")}${app !== "default" ? ` --app ${app}` : ""}, or merge it on GitHub.`);
|
|
639
659
|
return;
|
|
640
660
|
}
|
|
641
|
-
die("npx plures map github [connect [owner/repo] | on | off]");
|
|
661
|
+
die("npx plures map github [connect [owner/repo] | on | run | off]");
|
|
642
662
|
} catch (e) {
|
|
643
663
|
if (e instanceof PluresError) die(e.message);
|
|
644
664
|
throw e;
|
|
@@ -655,6 +675,7 @@ async function main() {
|
|
|
655
675
|
npx plures map workflow add a GitHub Action that maps on every push
|
|
656
676
|
npx plures map github connect let Plures add that Action by pull request
|
|
657
677
|
npx plures map github on merge it, which turns mapping on
|
|
678
|
+
npx plures map github run map now on GitHub, and watch it build
|
|
658
679
|
|
|
659
680
|
Docs: https://plures.si/docs`);
|
|
660
681
|
return;
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
Plures,
|
|
4
4
|
PluresError,
|
|
5
5
|
VERSION
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7OMKME5Z.js";
|
|
7
7
|
|
|
8
8
|
// src/cli.ts
|
|
9
9
|
import { spawnSync, spawn } from "child_process";
|
|
@@ -288,7 +288,8 @@ With plures-mcp connected, just ask: ${cyan("Map this app for Plures")}`);
|
|
|
288
288
|
`);
|
|
289
289
|
const prompt = `${guide}
|
|
290
290
|
|
|
291
|
-
Write the map to ${FILE} in the current directory now. Read the code; don't run it or change anything else.`;
|
|
291
|
+
Write the map to ${FILE} in the current directory now, as JSON, with the Write tool. Read the code; don't run it or change anything else. Don't write a script to generate the map: you can't run scripts or other commands here, so write the JSON itself.`;
|
|
292
|
+
const nudge = `${FILE} doesn't exist yet. Write it now with the Write tool: the complete map as JSON, directly. You can't run scripts or commands here, so don't write one. Use what you've already read.`;
|
|
292
293
|
const live = key ? client() : null;
|
|
293
294
|
const session = randomBytes(12).toString("base64url");
|
|
294
295
|
const source = process.env.GITHUB_ACTIONS ? "github" : "cli";
|
|
@@ -314,8 +315,8 @@ Write the map to ${FILE} in the current directory now. Read the code; don't run
|
|
|
314
315
|
let result = "";
|
|
315
316
|
const ticker = fancy ? liveLine() : null;
|
|
316
317
|
ticker?.start();
|
|
317
|
-
const
|
|
318
|
-
const p = spawn("claude", [
|
|
318
|
+
const runClaude = (args) => new Promise((resolve) => {
|
|
319
|
+
const p = spawn("claude", [...args, "--output-format", "stream-json", "--verbose", "--allowedTools", "Read,Grep,Glob,Write,Bash(git rev-parse:*),Bash(git remote:*)"], { stdio: ["ignore", "pipe", "inherit"], env: childEnv });
|
|
319
320
|
let buf = "";
|
|
320
321
|
p.stdout.on("data", (chunk) => {
|
|
321
322
|
buf += chunk.toString();
|
|
@@ -351,18 +352,21 @@ Write the map to ${FILE} in the current directory now. Read the code; don't run
|
|
|
351
352
|
p.on("close", (n) => resolve(n ?? 1));
|
|
352
353
|
p.on("error", () => resolve(1));
|
|
353
354
|
});
|
|
355
|
+
const wrote = () => existsSync(FILE) && statSync(FILE).mtimeMs !== before;
|
|
356
|
+
let code = await runClaude(["-p", prompt]);
|
|
357
|
+
if (!wrote()) code = await runClaude(["-p", nudge, "--continue"]);
|
|
354
358
|
clearInterval(tick);
|
|
355
359
|
ticker?.stop();
|
|
356
360
|
if (result && !fancy) console.log(`
|
|
357
361
|
${result.trim()}
|
|
358
362
|
`);
|
|
359
363
|
if (fancy) console.log(` ${cyan("\u2713")} ${reads} ${reads === 1 ? "file" : "files"} read. ${dim("Sending the map to Plures. No source code is sent.")}`);
|
|
360
|
-
const ok = code === 0 &&
|
|
364
|
+
const ok = code === 0 && wrote();
|
|
361
365
|
if (!ok) {
|
|
362
366
|
phase = "failed";
|
|
363
367
|
await flush();
|
|
364
368
|
} else await flush();
|
|
365
|
-
if (
|
|
369
|
+
if (!ok) die(`Claude Code didn't write ${FILE}${process.env.CI ? ". This run costs nothing." : `. Ask it directly, then run npx plures map upload.`}`);
|
|
366
370
|
await upload(FILE);
|
|
367
371
|
}
|
|
368
372
|
async function workflow() {
|
|
@@ -401,6 +405,20 @@ Turn it on: ${cyan("npx plures map github on")}${app !== "default" ? ` --app ${a
|
|
|
401
405
|
};
|
|
402
406
|
try {
|
|
403
407
|
if (!action || action === "status") return show(await p.github.status(app));
|
|
408
|
+
if (action === "run") {
|
|
409
|
+
let r;
|
|
410
|
+
try {
|
|
411
|
+
r = await p.github.run(app);
|
|
412
|
+
} catch (e) {
|
|
413
|
+
if (!(e instanceof PluresError && e.type === "workflow_outdated")) throw e;
|
|
414
|
+
console.log(dim("This repo's map workflow is from before Map now. Updating it, which merges a small change to the workflow file."));
|
|
415
|
+
r = await p.github.run(app, { update: true });
|
|
416
|
+
}
|
|
417
|
+
const url = `${base}/dashboard/apps/${encodeURIComponent(app)}/map`;
|
|
418
|
+
console.log(`${bold("Mapping now on GitHub.")} Watch it build: ${cyan(url)}`);
|
|
419
|
+
if (fancy && !noOpen) await openBrowser(url);
|
|
420
|
+
return void r;
|
|
421
|
+
}
|
|
404
422
|
if (action === "on") {
|
|
405
423
|
const r = await p.github.turnOn(app);
|
|
406
424
|
console.log(r.already_merged ? "Mapping was already on." : `${bold("Mapping is on.")} The first run is starting on GitHub.`);
|
|
@@ -422,7 +440,7 @@ Turn it on: ${cyan("npx plures map github on")}${app !== "default" ? ` --app ${a
|
|
|
422
440
|
It adds one workflow file. Review it, then turn mapping on with ${cyan("npx plures map github on")}${app !== "default" ? ` --app ${app}` : ""}, or merge it on GitHub.`);
|
|
423
441
|
return;
|
|
424
442
|
}
|
|
425
|
-
die("npx plures map github [connect [owner/repo] | on | off]");
|
|
443
|
+
die("npx plures map github [connect [owner/repo] | on | run | off]");
|
|
426
444
|
} catch (e) {
|
|
427
445
|
if (e instanceof PluresError) die(e.message);
|
|
428
446
|
throw e;
|
|
@@ -439,6 +457,7 @@ async function main() {
|
|
|
439
457
|
npx plures map workflow add a GitHub Action that maps on every push
|
|
440
458
|
npx plures map github connect let Plures add that Action by pull request
|
|
441
459
|
npx plures map github on merge it, which turns mapping on
|
|
460
|
+
npx plures map github run map now on GitHub, and watch it build
|
|
442
461
|
|
|
443
462
|
Docs: https://plures.si/docs`);
|
|
444
463
|
return;
|
package/dist/index.cjs
CHANGED
|
@@ -26,7 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
default: () => index_default
|
|
27
27
|
});
|
|
28
28
|
module.exports = __toCommonJS(index_exports);
|
|
29
|
-
var VERSION = "1.
|
|
29
|
+
var VERSION = "1.14.0";
|
|
30
30
|
var PluresError = class extends Error {
|
|
31
31
|
constructor(message, status, type) {
|
|
32
32
|
super(message);
|
|
@@ -157,6 +157,8 @@ var Plures = class {
|
|
|
157
157
|
/** Connects a repo ("owner/name"): sets its map key secret and opens the pull request. */
|
|
158
158
|
connect: (app, repo) => this.req("POST", `/api/v1/apps/${encodeURIComponent(app)}/github`, { repo }),
|
|
159
159
|
/** Turns mapping on by merging the pull request. The repo's own rules (reviews, checks) still apply. */
|
|
160
|
+
/** Map now: runs the app's map workflow on GitHub. { update: true } first updates an older workflow. Watch it on the map page. */
|
|
161
|
+
run: (app, opts = {}) => this.req("POST", `/api/v1/apps/${encodeURIComponent(app)}/github/run`, opts),
|
|
160
162
|
turnOn: (app) => this.req("POST", `/api/v1/apps/${encodeURIComponent(app)}/github/merge`, {}),
|
|
161
163
|
/** Revokes the repo's map key. Delete the workflow file in the repo to stop runs. */
|
|
162
164
|
disconnect: (app) => this.req("DELETE", `/api/v1/apps/${encodeURIComponent(app)}/github`)
|
package/dist/index.d.cts
CHANGED
|
@@ -350,7 +350,7 @@ type WebhookEvent = {
|
|
|
350
350
|
created_at: string;
|
|
351
351
|
data: Task;
|
|
352
352
|
};
|
|
353
|
-
declare const VERSION = "1.
|
|
353
|
+
declare const VERSION = "1.14.0";
|
|
354
354
|
type GitHubLink = {
|
|
355
355
|
object: "github_link";
|
|
356
356
|
app: string;
|
|
@@ -550,6 +550,15 @@ declare class Plures {
|
|
|
550
550
|
/** Connects a repo ("owner/name"): sets its map key secret and opens the pull request. */
|
|
551
551
|
connect: (app: string, repo: string) => Promise<GitHubLink>;
|
|
552
552
|
/** Turns mapping on by merging the pull request. The repo's own rules (reviews, checks) still apply. */
|
|
553
|
+
/** Map now: runs the app's map workflow on GitHub. { update: true } first updates an older workflow. Watch it on the map page. */
|
|
554
|
+
run: (app: string, opts?: {
|
|
555
|
+
update?: boolean;
|
|
556
|
+
}) => Promise<{
|
|
557
|
+
object: "map_run_request";
|
|
558
|
+
app: string;
|
|
559
|
+
started: true;
|
|
560
|
+
updated_workflow: boolean;
|
|
561
|
+
}>;
|
|
553
562
|
turnOn: (app: string) => Promise<{
|
|
554
563
|
object: "github_merge";
|
|
555
564
|
app: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -350,7 +350,7 @@ type WebhookEvent = {
|
|
|
350
350
|
created_at: string;
|
|
351
351
|
data: Task;
|
|
352
352
|
};
|
|
353
|
-
declare const VERSION = "1.
|
|
353
|
+
declare const VERSION = "1.14.0";
|
|
354
354
|
type GitHubLink = {
|
|
355
355
|
object: "github_link";
|
|
356
356
|
app: string;
|
|
@@ -550,6 +550,15 @@ declare class Plures {
|
|
|
550
550
|
/** Connects a repo ("owner/name"): sets its map key secret and opens the pull request. */
|
|
551
551
|
connect: (app: string, repo: string) => Promise<GitHubLink>;
|
|
552
552
|
/** Turns mapping on by merging the pull request. The repo's own rules (reviews, checks) still apply. */
|
|
553
|
+
/** Map now: runs the app's map workflow on GitHub. { update: true } first updates an older workflow. Watch it on the map page. */
|
|
554
|
+
run: (app: string, opts?: {
|
|
555
|
+
update?: boolean;
|
|
556
|
+
}) => Promise<{
|
|
557
|
+
object: "map_run_request";
|
|
558
|
+
app: string;
|
|
559
|
+
started: true;
|
|
560
|
+
updated_workflow: boolean;
|
|
561
|
+
}>;
|
|
553
562
|
turnOn: (app: string) => Promise<{
|
|
554
563
|
object: "github_merge";
|
|
555
564
|
app: string;
|
package/dist/index.js
CHANGED