@krapht/ork 1.0.0-alpha.13 → 1.0.0-alpha.15
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/__build_info__-Bsb1kjgF.mjs +340 -0
- package/dist/{store-CM3cERGl.mjs → attach-BHO3X3cf.mjs} +36 -91
- package/dist/{attach-E6NNyA3T.mjs → attach-CPespxlQ.mjs} +6 -5
- package/dist/bin.mjs +148 -1444
- package/dist/brief-za0ozN_E.mjs +58 -0
- package/dist/{builtin-files-n6o6oWpB.mjs → builtin-files-2bHf76x-.mjs} +1 -1
- package/dist/{chips-CyeB_rhR.mjs → chips-BqcT58qr.mjs} +1 -1
- package/dist/{completion-SNNNxnv9.mjs → completion-CQ2UYKuJ.mjs} +52 -11
- package/dist/context-BNqDw9z1.mjs +106 -0
- package/dist/{find-CjsNYAAf.mjs → find-BYLlszqj.mjs} +1 -1
- package/dist/follow-ups-B4GJ3Vzw.mjs +461 -0
- package/dist/{format-C60TFpRe.mjs → format-C8MsFj8_.mjs} +30 -16
- package/dist/{help-groups-CyfPWlST.mjs → help-groups-CQ98mLjF.mjs} +20 -6
- package/dist/{in-a-run-BYjTXaST.mjs → in-a-run-Bp0k0J09.mjs} +1 -1
- package/dist/{__build_info__-Da73_nBs.mjs → install-DWtXTq4y.mjs} +3 -227
- package/dist/{limits-C5QKZNLT.mjs → limits-B1qzS4cX.mjs} +1 -1
- package/dist/{mcp-bcctR-wc.mjs → mcp-BOrVkyhN.mjs} +6 -6
- package/dist/{once-DPQu5Q3H.mjs → once-C1fL3GVo.mjs} +4 -4
- package/dist/orphan-guard-BFKg8VSd.mjs +58 -0
- package/dist/{output-CnRzrbUM.mjs → output-B1kwo0YU.mjs} +17 -1
- package/dist/{pause-BPvlDIvz.mjs → pause-DOMK-R8V.mjs} +4 -4
- package/dist/post-BzA6Qobq.mjs +44 -0
- package/dist/{relay-C8W0t_zc.mjs → relay-OWuu4fib.mjs} +2 -2
- package/dist/run--4-1xAF2.mjs +1451 -0
- package/dist/{run-CQIfq918.mjs → run-CiPsW9Kf.mjs} +1 -1
- package/dist/send-CnNNW-ot.mjs +105 -0
- package/dist/{src-CqRqsb2t.mjs → src-B9zWIVqo.mjs} +226 -44
- package/dist/{src-CGJGL1sZ.mjs → src-DQKz2eOH.mjs} +326 -81
- package/dist/{src-D93tHZ5B.mjs → src-DcrhgipG.mjs} +107 -47
- package/dist/{src-BeR6f70A.mjs → src-Dr_fTSu-.mjs} +5858 -3746
- package/dist/store-oKJ-cCf3.mjs +16 -0
- package/dist/ui/assets/app-Bdc6OBeZ.css +1 -0
- package/dist/ui/assets/app-Drp8Dm9y.js +111 -0
- package/dist/ui/assets/{index-CWwm8HTG.js → index-BtwkftKe.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-D2Ydofq0.mjs → ui-CzKlsCnm.mjs} +4 -4
- package/dist/{usage-6WIowblz.mjs → usage-DHGNk2JL.mjs} +13 -141
- package/dist/{context-DHudLA5e.mjs → validate-Bs_gg22g.mjs} +17 -107
- package/dist/{verdict-CIy8tAyX.mjs → verdict-CMvPCpWC.mjs} +2 -2
- package/dist/{watch-uOU_WeBI.mjs → watch-CCCfw3n7.mjs} +24 -8
- package/dist/{workflows-7tQdMnrA.mjs → workflows-CW28ZU-z.mjs} +3 -3
- package/dist/{worktrees-ZCII298F.mjs → worktrees-CyE8aF6j.mjs} +3 -5
- package/package.json +2 -2
- package/dist/clean-Bh4KZgzc.mjs +0 -91
- package/dist/decide-DuIHACvH.mjs +0 -50
- package/dist/list-BUb5Uc3H.mjs +0 -117
- package/dist/remove-BkFWGVYo.mjs +0 -201
- package/dist/report-CEN8VoUb.mjs +0 -140
- package/dist/send-CaZlGG5a.mjs +0 -163
- package/dist/ui/assets/app-DYRC0V4p.js +0 -111
- package/dist/ui/assets/app-QoHVi-mb.css +0 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Dr as placeFor, Er as placeFiles, Fr as estimateTokens, Gn as FEEDBACK_SEVERITIES, Ir as guardedBase, Lr as plainPathInside, Mr as inside, Pr as LESSON_CAP_TOKENS, Rr as writePlainFile, Wn as FEEDBACK_KINDS, Zn as publishPost, er as fingerprint, fr as maskSecrets, nr as targetOf } from "./src-Dr_fTSu-.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { existsSync,
|
|
4
|
-
import { homedir } from "node:os";
|
|
3
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
5
4
|
import { spawn } from "node:child_process";
|
|
6
5
|
// ../core/src/feedback/actions.ts
|
|
7
6
|
const ALLOWED = { ok: true };
|
|
@@ -363,174 +362,6 @@ const previewPost = (store, item, ask) => {
|
|
|
363
362
|
})
|
|
364
363
|
};
|
|
365
364
|
};
|
|
366
|
-
// ../core/src/remote/session.ts
|
|
367
|
-
const chattable = (type) => type === "agent.leader" || type === "agent.worker";
|
|
368
|
-
/** Reads `node`'s session from a run's events, and every node's last output. */
|
|
369
|
-
const nodeSession = (events, node) => {
|
|
370
|
-
const session = {
|
|
371
|
-
known: false,
|
|
372
|
-
chattable: false,
|
|
373
|
-
running: false
|
|
374
|
-
};
|
|
375
|
-
const outputs = {};
|
|
376
|
-
for (const { event } of events) {
|
|
377
|
-
if (event.type === "run.started") {
|
|
378
|
-
const declared = event.nodes.find((n) => n.id === node);
|
|
379
|
-
if (declared !== void 0) {
|
|
380
|
-
session.known = true;
|
|
381
|
-
session.chattable = chattable(declared.type);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
if (event.type === "node.finished") outputs[event.id] = event.output;
|
|
385
|
-
if (!("id" in event) || event.id !== node) continue;
|
|
386
|
-
if (event.type === "node.started") {
|
|
387
|
-
session.known = true;
|
|
388
|
-
session.chattable = chattable(event.nodeType);
|
|
389
|
-
session.running = true;
|
|
390
|
-
}
|
|
391
|
-
if (event.type === "node.finished") session.running = false;
|
|
392
|
-
if (event.type === "worktree" && event.action === "created") session.checkout = {
|
|
393
|
-
path: event.path,
|
|
394
|
-
...event.branch === void 0 ? {} : { branch: event.branch },
|
|
395
|
-
own: true,
|
|
396
|
-
owner: node
|
|
397
|
-
};
|
|
398
|
-
if (event.type !== "node.event") continue;
|
|
399
|
-
const inner = event.event;
|
|
400
|
-
if (inner.fork === true) continue;
|
|
401
|
-
if (inner.type === "session.started") {
|
|
402
|
-
session.sessionId = inner.sessionId;
|
|
403
|
-
if (inner.cwd !== void 0) session.cwd = inner.cwd;
|
|
404
|
-
if (inner.driver !== void 0) session.driver = inner.driver;
|
|
405
|
-
if (inner.model !== "") session.model = inner.model;
|
|
406
|
-
}
|
|
407
|
-
if (inner.type === "session.finished" && inner.outcome.sessionId !== "") session.sessionId = inner.outcome.sessionId;
|
|
408
|
-
}
|
|
409
|
-
return {
|
|
410
|
-
session,
|
|
411
|
-
outputs
|
|
412
|
-
};
|
|
413
|
-
};
|
|
414
|
-
/** The dist-tags every install follows, toward and after 1.0.0. */
|
|
415
|
-
const CHANNEL_TAGS = [
|
|
416
|
-
"latest",
|
|
417
|
-
"alpha",
|
|
418
|
-
"beta",
|
|
419
|
-
"rc"
|
|
420
|
-
];
|
|
421
|
-
/** The dist-tag of snapshots from `main`, followed only by a canary. */
|
|
422
|
-
const CANARY_TAG = "canary";
|
|
423
|
-
const updateCachePath = (home = homedir()) => path.join(home, ".ork", "update-check.json");
|
|
424
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
425
|
-
const text = (record, key) => {
|
|
426
|
-
const value = record[key];
|
|
427
|
-
return typeof value === "string" ? value : void 0;
|
|
428
|
-
};
|
|
429
|
-
const notifiedOf = (value) => {
|
|
430
|
-
if (!isRecord(value)) return void 0;
|
|
431
|
-
const version = text(value, "version");
|
|
432
|
-
const at = text(value, "at");
|
|
433
|
-
return version === void 0 || at === void 0 ? void 0 : {
|
|
434
|
-
version,
|
|
435
|
-
at
|
|
436
|
-
};
|
|
437
|
-
};
|
|
438
|
-
/** The cache, or `null` when there is none or it cannot be read. */
|
|
439
|
-
const readUpdateCache = (file) => {
|
|
440
|
-
let parsed;
|
|
441
|
-
try {
|
|
442
|
-
parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
443
|
-
} catch {
|
|
444
|
-
return null;
|
|
445
|
-
}
|
|
446
|
-
if (!isRecord(parsed)) return null;
|
|
447
|
-
const checkedAt = text(parsed, "checkedAt");
|
|
448
|
-
if (checkedAt === void 0) return null;
|
|
449
|
-
const latest = text(parsed, "latest");
|
|
450
|
-
const notified = notifiedOf(parsed["notified"]);
|
|
451
|
-
return {
|
|
452
|
-
checkedAt,
|
|
453
|
-
...latest === void 0 ? {} : { latest },
|
|
454
|
-
...notified === void 0 ? {} : { notified }
|
|
455
|
-
};
|
|
456
|
-
};
|
|
457
|
-
/** Writes the cache whole (a temporary file, then a rename). */
|
|
458
|
-
const writeUpdateCache = (file, cache) => {
|
|
459
|
-
mkdirSync(path.dirname(file), { recursive: true });
|
|
460
|
-
const temporary = `${file}.${process.pid}.tmp`;
|
|
461
|
-
writeFileSync(temporary, `${JSON.stringify(cache, null, 2)}\n`);
|
|
462
|
-
renameSync(temporary, file);
|
|
463
|
-
};
|
|
464
|
-
const age = (iso, now) => {
|
|
465
|
-
const time = Date.parse(iso);
|
|
466
|
-
return Number.isNaN(time) ? Infinity : now.getTime() - time;
|
|
467
|
-
};
|
|
468
|
-
/** Whether it is time to ask the registry again. */
|
|
469
|
-
const checkDue = (cache, now) => cache === null || age(cache.checkedAt, now) >= 864e5;
|
|
470
|
-
/** Whether `version` is a canary snapshot: its pre-release starts `canary`. */
|
|
471
|
-
const isCanary = (version) => parseVersion(version)?.pre[0]?.startsWith(CANARY_TAG) === true;
|
|
472
|
-
/**
|
|
473
|
-
* The newest version, by semver precedence, among the dist-tags `current`
|
|
474
|
-
* follows: the channel tags, and `canary` too when `current` is a canary. A tag
|
|
475
|
-
* whose value doesn't parse is skipped; `null` when none does.
|
|
476
|
-
*/
|
|
477
|
-
const newestTagged = (tags, current) => {
|
|
478
|
-
return (current !== void 0 && isCanary(current) ? [...CHANNEL_TAGS, "canary"] : CHANNEL_TAGS).flatMap((tag) => {
|
|
479
|
-
const value = tags[tag];
|
|
480
|
-
const version = typeof value === "string" ? parseVersion(value) : null;
|
|
481
|
-
return typeof value === "string" && version !== null ? [{
|
|
482
|
-
value,
|
|
483
|
-
version
|
|
484
|
-
}] : [];
|
|
485
|
-
}).reduce((best, candidate) => best === null || compareVersions(candidate.version, best.version) > 0 ? candidate : best, null)?.value ?? null;
|
|
486
|
-
};
|
|
487
|
-
/**
|
|
488
|
-
* The newest version on the registry that the running version follows ({@link
|
|
489
|
-
* newestTagged}), or `null` on any failure.
|
|
490
|
-
*/
|
|
491
|
-
const fetchLatest = async (name, options = {}) => {
|
|
492
|
-
const registry = (options.registry ?? "https://registry.npmjs.org").replace(/\/+$/u, "");
|
|
493
|
-
const get = options.fetch ?? globalThis.fetch;
|
|
494
|
-
try {
|
|
495
|
-
const response = await get(`${registry}/-/package/${name}/dist-tags`, {
|
|
496
|
-
headers: { accept: "application/json" },
|
|
497
|
-
signal: AbortSignal.timeout(options.timeoutMs ?? 5e3)
|
|
498
|
-
});
|
|
499
|
-
if (!response.ok) return null;
|
|
500
|
-
const tags = await response.json();
|
|
501
|
-
return isRecord(tags) ? newestTagged(tags, options.current) : null;
|
|
502
|
-
} catch {
|
|
503
|
-
return null;
|
|
504
|
-
}
|
|
505
|
-
};
|
|
506
|
-
/**
|
|
507
|
-
* Asks the registry and records the answer. A failed check is recorded too, so
|
|
508
|
-
* an offline machine is not asked again until the interval passes; the last
|
|
509
|
-
* known version is kept. `options.current` is the running version.
|
|
510
|
-
*/
|
|
511
|
-
const refreshUpdateCache = async (file, name, now, options = {}) => {
|
|
512
|
-
const before = readUpdateCache(file);
|
|
513
|
-
const latest = await fetchLatest(name, options) ?? before?.latest;
|
|
514
|
-
const cache = {
|
|
515
|
-
...before,
|
|
516
|
-
checkedAt: now.toISOString(),
|
|
517
|
-
...latest === void 0 ? {} : { latest }
|
|
518
|
-
};
|
|
519
|
-
writeUpdateCache(file, cache);
|
|
520
|
-
return cache;
|
|
521
|
-
};
|
|
522
|
-
/** The newer version the cache knows of, if any. */
|
|
523
|
-
const newerVersion = (cache, current) => cache?.latest !== void 0 && isNewer(cache.latest, current) ? cache.latest : null;
|
|
524
|
-
/**
|
|
525
|
-
* The version to tell the user about now: newer than theirs, and not already
|
|
526
|
-
* told today. `null` when there is nothing to say.
|
|
527
|
-
*/
|
|
528
|
-
const pendingNotice = (cache, current, now) => {
|
|
529
|
-
const newer = newerVersion(cache, current);
|
|
530
|
-
if (newer === null) return null;
|
|
531
|
-
const told = cache?.notified;
|
|
532
|
-
return told?.version === newer && age(told.at, now) < 864e5 ? null : newer;
|
|
533
|
-
};
|
|
534
365
|
/**
|
|
535
366
|
* Runs the command; resolves its exit code. Without `onOutput` it writes on the
|
|
536
367
|
* terminal.
|
|
@@ -558,59 +389,4 @@ const runInstall = (argv, onOutput) => new Promise((resolve) => {
|
|
|
558
389
|
resolve(code ?? 1);
|
|
559
390
|
});
|
|
560
391
|
});
|
|
561
|
-
|
|
562
|
-
/**
|
|
563
|
-
* @file The environment's say over the update check (ADR-038): the variables
|
|
564
|
-
* that turn it off (`ORK_NO_UPDATE_CHECK`, the common `NO_UPDATE_NOTIFIER`,
|
|
565
|
-
* and `CI`), and the registry to ask instead of npm's. The CLI adds its own
|
|
566
|
-
* rules about where a notice may go; the server behind `ork ui` uses only
|
|
567
|
-
* these.
|
|
568
|
-
*/
|
|
569
|
-
/** Turns the automatic check and its notice off. */
|
|
570
|
-
const NO_UPDATE_ENV = "ORK_NO_UPDATE_CHECK";
|
|
571
|
-
/** A registry to ask instead of npm's, e.g. a company mirror. */
|
|
572
|
-
const UPDATE_REGISTRY_ENV = "ORK_UPDATE_REGISTRY";
|
|
573
|
-
/** The variables that turn the check off, in the order they are looked at. */
|
|
574
|
-
const UPDATE_SWITCHES = [
|
|
575
|
-
NO_UPDATE_ENV,
|
|
576
|
-
"NO_UPDATE_NOTIFIER",
|
|
577
|
-
"CI"
|
|
578
|
-
];
|
|
579
|
-
/** Set to anything but empty, `0` or `false`. */
|
|
580
|
-
const isSwitchedOn = (value) => value !== void 0 && value !== "" && value !== "0" && value.toLowerCase() !== "false";
|
|
581
|
-
/** The variable that turns the check off in `env`, or `null` when none does. */
|
|
582
|
-
const updateSwitchOff = (env) => UPDATE_SWITCHES.find((name) => isSwitchedOn(env[name])) ?? null;
|
|
583
|
-
/** The registry `ORK_UPDATE_REGISTRY` names, if it names one. */
|
|
584
|
-
const registryOf = (env) => {
|
|
585
|
-
const registry = env[UPDATE_REGISTRY_ENV];
|
|
586
|
-
return registry === void 0 || registry === "" ? void 0 : registry;
|
|
587
|
-
};
|
|
588
|
-
/** The host of a registry that isn't an http(s) URL, past any `user:pass@`. */
|
|
589
|
-
const hostOf = (registry) => registry.replace(/^[a-z][\w+.-]*:\/\//iu, "").replace(/^[^/?#]*@/u, "").split(/[/?#]/u)[0] ?? "";
|
|
590
|
-
/**
|
|
591
|
-
* The registry as it may be shown (on a page, in a message): an http(s) URL
|
|
592
|
-
* without its user name and password, which a mirror's URL may carry; anything
|
|
593
|
-
* else only as its host.
|
|
594
|
-
*/
|
|
595
|
-
const registryShown = (registry) => {
|
|
596
|
-
try {
|
|
597
|
-
const url = new URL(registry);
|
|
598
|
-
if (url.protocol === "http:" || url.protocol === "https:") {
|
|
599
|
-
if (url.username === "" && url.password === "") return registry;
|
|
600
|
-
url.username = "";
|
|
601
|
-
url.password = "";
|
|
602
|
-
return url.href;
|
|
603
|
-
}
|
|
604
|
-
} catch {}
|
|
605
|
-
return hostOf(registry);
|
|
606
|
-
};
|
|
607
|
-
// src/__build_info__.ts
|
|
608
|
-
/**
|
|
609
|
-
* @file The published package's name and version, bound to
|
|
610
|
-
* `packages/cli/package.json`. Do not edit by hand: `pnpm changesets:version`
|
|
611
|
-
* and `pnpm build` rewrite it (`tools/release/build-info.ts`), and a test
|
|
612
|
-
* fails when it is stale.
|
|
613
|
-
*/
|
|
614
|
-
const ORK_NAME = "@krapht/ork";
|
|
615
|
-
const ORK_VERSION = "1.0.0-alpha.13";
|
|
616
|
-
export { feedbackActions as C, placeOf as S, previewPost as _, registryShown as a, acceptItem as b, checkDue as c, pendingNotice as d, readUpdateCache as f, nodeSession as g, writeUpdateCache as h, registryOf as i, fetchLatest as l, updateCachePath as m, ORK_VERSION as n, updateSwitchOff as o, refreshUpdateCache as p, isSwitchedOn as r, runInstall as s, ORK_NAME as t, newerVersion as u, checkNote as v, openFixRun as w, lessonPlaceOf as x, recordNote as y };
|
|
392
|
+
export { acceptItem as a, feedbackActions as c, recordNote as i, openFixRun as l, previewPost as n, lessonPlaceOf as o, checkNote as r, placeOf as s, runInstall as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as capsHere, bt as limitsReport, vt as NOT_STARTED, yt as limitsNow } from "./src-Dr_fTSu-.mjs";
|
|
2
2
|
// src/run/limits.ts
|
|
3
3
|
/**
|
|
4
4
|
* @file The limits across runs that apply here (RFC-007): the user's settings
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as ORK_VERSION } from "./__build_info__-
|
|
3
|
-
import { p as runMarkerIn } from "./src-
|
|
4
|
-
import { n as explainNode } from "./context-
|
|
5
|
-
import { a as openMcp, c as refused, o as tool, s as answer } from "./src-
|
|
1
|
+
import { A as isNewer } from "./src-Dr_fTSu-.mjs";
|
|
2
|
+
import { n as ORK_VERSION } from "./__build_info__-Bsb1kjgF.mjs";
|
|
3
|
+
import { p as runMarkerIn } from "./src-DcrhgipG.mjs";
|
|
4
|
+
import { n as explainNode } from "./context-BNqDw9z1.mjs";
|
|
5
|
+
import { a as openMcp, c as refused, o as tool, s as answer } from "./src-DQKz2eOH.mjs";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -43,7 +43,7 @@ const orkMcpServer = (options = {}) => {
|
|
|
43
43
|
...options.script === void 0 ? {} : { script: options.script }
|
|
44
44
|
});
|
|
45
45
|
const all = [...opened.tools, explainTool(opened, options.home)];
|
|
46
|
-
const tools = options.expects !== void 0 && isNewer(options.expects, "1.0.0-alpha.
|
|
46
|
+
const tools = options.expects !== void 0 && isNewer(options.expects, "1.0.0-alpha.15") ? tooOld(all, options.expects) : all;
|
|
47
47
|
const server = new McpServer({
|
|
48
48
|
name: "ork",
|
|
49
49
|
version: ORK_VERSION
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import "./src-
|
|
2
|
-
import { t as runOnce } from "./run-
|
|
3
|
-
import {
|
|
4
|
-
import { t as ago } from "./format-
|
|
1
|
+
import "./src-Dr_fTSu-.mjs";
|
|
2
|
+
import { t as runOnce } from "./run-CiPsW9Kf.mjs";
|
|
3
|
+
import { c as write, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
|
|
4
|
+
import { t as ago } from "./format-C8MsFj8_.mjs";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import { defineCommand, parseArgs } from "citty";
|
|
7
7
|
// src/commands/once.ts
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Readable, Writable } from "node:stream";
|
|
2
|
+
// ../core/src/machine/orphan-guard.ts
|
|
3
|
+
/**
|
|
4
|
+
* @file The orphan guard: a node's processes end with `ork`, whatever ends
|
|
5
|
+
* `ork` (SIGKILL, the OOM killer, a crash exit). A child started in its own
|
|
6
|
+
* process group (`detached: true`) under `sh` also starts a small watcher in
|
|
7
|
+
* that group, which reads a pipe that only `ork` holds open. `ork` never
|
|
8
|
+
* writes to it, so when `ork` dies the read sees EOF, and the watcher sends
|
|
9
|
+
* its own group (`kill 0`, never another's) SIGTERM, then SIGKILL after
|
|
10
|
+
* {@link KILL_AFTER_MS}. A line on the pipe instead lets the watcher exit
|
|
11
|
+
* quietly, and so does killing it, which is how a node that ends normally
|
|
12
|
+
* leaves its leftover background processes alone. POSIX only. Two uses:
|
|
13
|
+
*
|
|
14
|
+
* - A shell that outlives the program (the tool runner's timing wrapper):
|
|
15
|
+
* `${orphanGuard(4)} w=$!; "$0" "$@" 4<&-; s=$?; kill -s KILL $w`, then
|
|
16
|
+
* spawn with a `"pipe"` at `stdio[4]` and call
|
|
17
|
+
* `holdGuard(child.stdio[4])`.
|
|
18
|
+
* - A shell that `exec`s the program (a session, so its pid stays the
|
|
19
|
+
* driver's): `${orphanGuard(3)} exec 3<&-; exec "$0" "$@"` (a bare `exec`
|
|
20
|
+
* closes the pipe: macOS's `sh` keeps a copy of one an `exec` command
|
|
21
|
+
* closes, which the driver would inherit), with a `"pipe"` at `stdio[3]`;
|
|
22
|
+
* nothing is left to kill the watcher, so call the function `holdGuard`
|
|
23
|
+
* returns once the driver has exited (on `exit`: the pipe holds `close`).
|
|
24
|
+
*/
|
|
25
|
+
/** How long the group gets to end after SIGTERM before SIGKILL. */
|
|
26
|
+
const KILL_AFTER_MS = 2e3;
|
|
27
|
+
/** The file descriptors a redirect can name in every POSIX shell. */
|
|
28
|
+
const SHELL_FDS = [
|
|
29
|
+
3,
|
|
30
|
+
4,
|
|
31
|
+
5,
|
|
32
|
+
6,
|
|
33
|
+
7,
|
|
34
|
+
8,
|
|
35
|
+
9
|
|
36
|
+
];
|
|
37
|
+
/**
|
|
38
|
+
* Shell text that starts the watcher in the background on pipe `fd` (3 to 9);
|
|
39
|
+
* it ends with `&`, so `$!` after it is the watcher's pid. The watcher holds no
|
|
40
|
+
* other descriptor, so it never keeps the child's output pipes open.
|
|
41
|
+
*/
|
|
42
|
+
const orphanGuard = (fd) => {
|
|
43
|
+
const others = SHELL_FDS.filter((other) => other !== fd).map((other) => `${String(other)}>&-`).join(" ");
|
|
44
|
+
return `{ read -r _ork <&${String(fd)} || { trap '' TERM; kill -s TERM 0; sleep ${String(KILL_AFTER_MS / 1e3)}; kill -s KILL 0; }; } </dev/null >/dev/null 2>&1 ${others} & `;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Keeps `ork`'s end of the watch pipe (`child.stdio[fd]`) open and drained, so
|
|
48
|
+
* it never holds back the child's `close`; returns the release, which writes
|
|
49
|
+
* the line that lets the watcher exit without touching its group.
|
|
50
|
+
*/
|
|
51
|
+
const holdGuard = (pipe) => {
|
|
52
|
+
pipe?.on("error", () => {});
|
|
53
|
+
if (pipe instanceof Readable) pipe.resume();
|
|
54
|
+
return () => {
|
|
55
|
+
if (pipe instanceof Writable && pipe.writable) pipe.write("\n");
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
export { holdGuard as n, orphanGuard as r, KILL_AFTER_MS as t };
|
|
@@ -412,6 +412,22 @@ const detachHint = (id) => `ork attach ${id} · ork logs ${id} -f · ork tree ${
|
|
|
412
412
|
/** What a run spent: `$0.0312`, or `$0.00` for nothing. */
|
|
413
413
|
const cost = (usd) => usd === 0 ? "$0.00" : `$${usd.toFixed(4)}`;
|
|
414
414
|
/**
|
|
415
|
+
* A dollar total that misses sessions on a driver with no dollars (RFC-015),
|
|
416
|
+
* said so, with the counted tokens beside it: `$1.2000 (partial) · 3.0k
|
|
417
|
+
* tokens`. A complete total reads as `cost` does.
|
|
418
|
+
*/
|
|
419
|
+
const costOf = (usd, partial, tokens) => {
|
|
420
|
+
if (partial !== true) return cost(usd);
|
|
421
|
+
const units = tokens === void 0 ? "" : ` · ${shortCount(tokens)} tokens`;
|
|
422
|
+
return `${cost(usd)} (partial)${units}`;
|
|
423
|
+
};
|
|
424
|
+
/** `950`, `12.3k`, `1.2M`. */
|
|
425
|
+
const shortCount = (n) => {
|
|
426
|
+
if (n < 1e3) return String(n);
|
|
427
|
+
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
428
|
+
return `${(n / 1e6).toFixed(1)}M`;
|
|
429
|
+
};
|
|
430
|
+
/**
|
|
415
431
|
* Asks a yes-or-no question on the terminal (stderr), through the kit's confirm
|
|
416
432
|
* prompt; anything but yes is no. A trailing `[y/N]` in `question` is dropped:
|
|
417
433
|
* the prompt adds its own.
|
|
@@ -420,4 +436,4 @@ const confirm = (question) => confirm$1({
|
|
|
420
436
|
input: process.stdin,
|
|
421
437
|
output: process.stderr
|
|
422
438
|
}, { question: question.replace(/\s*\[y\/N\]\s*$/u, "") });
|
|
423
|
-
export {
|
|
439
|
+
export { termOf as C, wrap as D, widthOf as E, readKeys as O, takePlainFlag as S, hang as T, interrupt as _, plain as a, canKey as b, write as c, CHIP as d, NODE_PALETTE as f, createRegion as g, paint as h, detachHint as i, writeErr as l, bold as m, cost as n, shortCount as o, apply as p, costOf as r, style as s, confirm as t, confirmOrStop as u, readLine as v, cut as w, plainEnv as x, withdrawn as y };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { U as
|
|
2
|
-
import { t as findRun } from "./find-
|
|
3
|
-
import {
|
|
4
|
-
import { i as continueRefusal } from "./in-a-run-
|
|
1
|
+
import { U as openStore, bn as requestPause, yn as requestContinue } from "./src-Dr_fTSu-.mjs";
|
|
2
|
+
import { t as findRun } from "./find-BYLlszqj.mjs";
|
|
3
|
+
import { c as write, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
|
|
4
|
+
import { i as continueRefusal } from "./in-a-run-Bp0k0J09.mjs";
|
|
5
5
|
import { defineCommand } from "citty";
|
|
6
6
|
// src/commands/pause.ts
|
|
7
7
|
/**
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Qn as redact } from "./src-Dr_fTSu-.mjs";
|
|
2
|
+
// ../core/src/follow-ups/post.ts
|
|
3
|
+
/** Posts `f`'s draft as a GitHub comment once `confirmed`, and marks it done. */
|
|
4
|
+
const postFollowUpMessage = async (f, options) => {
|
|
5
|
+
const draft = f.draft;
|
|
6
|
+
if (f.kind !== "message" || draft?.channel !== "github") return {
|
|
7
|
+
ok: false,
|
|
8
|
+
error: "only a message drafted for the github channel is posted; send the others yourself"
|
|
9
|
+
};
|
|
10
|
+
if (!options.confirmed) return {
|
|
11
|
+
ok: false,
|
|
12
|
+
error: "posting to GitHub needs the maintainer's confirmation"
|
|
13
|
+
};
|
|
14
|
+
const body = redact(draft.text, {
|
|
15
|
+
roots: [f.project],
|
|
16
|
+
home: options.home
|
|
17
|
+
});
|
|
18
|
+
const on = /\/pull\/\d+/u.test(draft.to) ? "pr" : "issue";
|
|
19
|
+
const result = await options.gh([
|
|
20
|
+
on,
|
|
21
|
+
"comment",
|
|
22
|
+
draft.to,
|
|
23
|
+
"--body",
|
|
24
|
+
body
|
|
25
|
+
], { cwd: f.project });
|
|
26
|
+
if (!result.ok) return {
|
|
27
|
+
ok: false,
|
|
28
|
+
error: `gh failed: ${result.stderr.trim() || result.stdout.trim() || "no output"}`
|
|
29
|
+
};
|
|
30
|
+
const url = result.stdout.trim().split("\n").findLast((line) => line.startsWith("https://"));
|
|
31
|
+
const done = {
|
|
32
|
+
...f,
|
|
33
|
+
status: "done",
|
|
34
|
+
note: `posted${url === void 0 ? "" : ` as ${url}`}`,
|
|
35
|
+
updatedAt: options.now?.() ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
36
|
+
};
|
|
37
|
+
options.rows.putFollowUp(done);
|
|
38
|
+
return {
|
|
39
|
+
ok: true,
|
|
40
|
+
followUp: done,
|
|
41
|
+
...url === void 0 ? {} : { url }
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
export { postFollowUpMessage as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { U as openStore, _n as linkNodes, hn as addressOf, vn as unlinkNodes } from "./src-Dr_fTSu-.mjs";
|
|
2
|
+
import { c as write, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
// src/commands/relay.ts
|
|
5
5
|
/**
|