pipe-kan 0.31.0 → 0.32.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/dist/pipe-kan.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/server.ts
4
- import { readFileSync as readFileSync6, writeSync } from "node:fs";
4
+ import { readFileSync as readFileSync7, writeSync } from "node:fs";
5
5
  import { createServer } from "node:http";
6
6
  import { tmpdir as tmpdir3 } from "node:os";
7
- import { join as join10 } from "node:path";
7
+ import { join as join11 } from "node:path";
8
8
 
9
9
  // src/app.ts
10
10
  import { readFileSync as readFileSync2 } from "node:fs";
@@ -399,8 +399,16 @@ function parseFlags(flags) {
399
399
  statusEq.push(status);
400
400
  continue;
401
401
  }
402
- if (token === "--projects") {
403
- [projectsValue, i] = takeValue(list, i, "--projects");
402
+ if (token === "--projects" || token.startsWith("--projects=")) {
403
+ const parts = [];
404
+ if (token.startsWith("--projects=")) {
405
+ parts.push(token.slice("--projects=".length));
406
+ }
407
+ while (i + 1 < list.length && !list[i + 1].startsWith("-")) {
408
+ i++;
409
+ parts.push(list[i]);
410
+ }
411
+ projectsValue = parts.join(",");
404
412
  continue;
405
413
  }
406
414
  if (token === "-q" || token === "--jql") {
@@ -2272,6 +2280,123 @@ async function refreshFromJira(app, kind, opts = {}) {
2272
2280
  await app.refresh();
2273
2281
  }
2274
2282
 
2283
+ // src/factory-ledger.ts
2284
+ import { existsSync as existsSync2, readFileSync as readFileSync3, statSync } from "node:fs";
2285
+ import { homedir as homedir3 } from "node:os";
2286
+ import { join as join4 } from "node:path";
2287
+ var DEFAULT_LEDGER_PATH = "~/code/software-factory/asf/runtime/factory-coordinator/jobs.jsonl";
2288
+ function resolveLedgerPath(env = process.env) {
2289
+ const raw = env.FACTORY_LEDGER_PATH ?? DEFAULT_LEDGER_PATH;
2290
+ return raw.startsWith("~/") ? join4(homedir3(), raw.slice(2)) : raw;
2291
+ }
2292
+ function parseJobsJsonl(text) {
2293
+ const events = [];
2294
+ for (const line of text.split(`
2295
+ `)) {
2296
+ const trimmed = line.trim();
2297
+ if (!trimmed)
2298
+ continue;
2299
+ try {
2300
+ events.push(JSON.parse(trimmed));
2301
+ } catch {}
2302
+ }
2303
+ return events;
2304
+ }
2305
+ function lc(...parts) {
2306
+ return parts.filter(Boolean).join(" ").toLowerCase();
2307
+ }
2308
+ function deriveStageTag(events) {
2309
+ if (!events.length)
2310
+ return null;
2311
+ const last = events[events.length - 1];
2312
+ if (last.status === "done" || last.status === "cancelled")
2313
+ return null;
2314
+ const text = lc(last.detail, last.summary, last.target_agent, last.from_bot);
2315
+ const fromBot = lc(last.from_bot);
2316
+ const targetAgent = lc(last.target_agent);
2317
+ const detail = lc(last.detail);
2318
+ if (last.status === "blocked" || /needs.{0,4}judgment|green.{0,4}light|await.{0,4}ship|awaiting.{0,4}ship|needs.{0,4}input|waiting.{0,4}operator|checks.{0,4}pass|verify.{0,4}pass|human.{0,4}gate/.test(text)) {
2319
+ return "human-wait";
2320
+ }
2321
+ if (last.status === "queued" || last.status === "routed" || /grokbot.{0,4}coordinator|intake.{0,4}switchboard/.test(fromBot) || /routing|switchboard/.test(text)) {
2322
+ return "coordinator";
2323
+ }
2324
+ if (/planner|plan_|stage_1a/.test(targetAgent) || /planner|to.{0,2}spec|to.{0,2}tickets|grill.{0,4}with.{0,4}docs|stage_1/.test(text)) {
2325
+ return "planning";
2326
+ }
2327
+ if (/desk=/.test(detail) || /preflight|research.{0,4}gate|research.{0,4}dossier/.test(text)) {
2328
+ return "desk";
2329
+ }
2330
+ if (/maker|implement|referee|omp|stage_2/.test(targetAgent) || /\bmaker\b|implement|referee|stage_2|pr.{0,4}open|pull.{0,4}request/.test(text)) {
2331
+ return "maker";
2332
+ }
2333
+ return "coordinator";
2334
+ }
2335
+ function extractPrUrl(detail) {
2336
+ if (!detail)
2337
+ return;
2338
+ const m = /https:\/\/github\.com\/[^\s"']+\/pull\/\d+/.exec(detail);
2339
+ return m?.[0];
2340
+ }
2341
+ function groupByLatest(events) {
2342
+ const map = new Map;
2343
+ for (const ev of events) {
2344
+ if (!ev.id)
2345
+ continue;
2346
+ const list = map.get(ev.id);
2347
+ if (list) {
2348
+ list.push(ev);
2349
+ } else {
2350
+ map.set(ev.id, [ev]);
2351
+ }
2352
+ }
2353
+ return map;
2354
+ }
2355
+ function jobFromEvents(id, events) {
2356
+ const last = events[events.length - 1];
2357
+ const pullRequestUrl = events.map((e) => e.pull_request_url ?? extractPrUrl(e.detail)).find(Boolean);
2358
+ return {
2359
+ id,
2360
+ summary: last.summary ?? "",
2361
+ status: last.status ?? "",
2362
+ stageTag: deriveStageTag(events),
2363
+ latestTs: last.ts,
2364
+ ...pullRequestUrl ? { pullRequestUrl } : {},
2365
+ ...last.plane_project ? { planeProject: last.plane_project } : {},
2366
+ ...last.detail ? { detail: last.detail } : {},
2367
+ ...last.session ? { session: last.session } : {},
2368
+ ...last.from_bot ? { fromBot: last.from_bot } : {}
2369
+ };
2370
+ }
2371
+ function classifyJobs(events) {
2372
+ const grouped = groupByLatest(events);
2373
+ const jobs = [];
2374
+ for (const [id, evs] of grouped) {
2375
+ jobs.push(jobFromEvents(id, evs));
2376
+ }
2377
+ jobs.sort((a, b) => b.latestTs.localeCompare(a.latestTs));
2378
+ return jobs;
2379
+ }
2380
+ var _cache = null;
2381
+ function readLedger(env = process.env) {
2382
+ const path = resolveLedgerPath(env);
2383
+ if (!existsSync2(path)) {
2384
+ return { jobs: [], error: `Ledger not found: ${path}` };
2385
+ }
2386
+ try {
2387
+ const mtime = statSync(path).mtimeMs;
2388
+ if (_cache && _cache.path === path && _cache.mtime === mtime) {
2389
+ return { jobs: _cache.jobs };
2390
+ }
2391
+ const text = readFileSync3(path, "utf8");
2392
+ const jobs = classifyJobs(parseJobsJsonl(text));
2393
+ _cache = { path, mtime, jobs };
2394
+ return { jobs };
2395
+ } catch (err) {
2396
+ return { jobs: [], error: String(err) };
2397
+ }
2398
+ }
2399
+
2275
2400
  // src/app-api.ts
2276
2401
  function json(res, status, body) {
2277
2402
  res.statusCode = status;
@@ -2416,6 +2541,26 @@ function handleAppApi(req, res, app, opts = {}) {
2416
2541
  });
2417
2542
  return true;
2418
2543
  }
2544
+ if (url.pathname === "/api/factory/jobs" && method === "GET") {
2545
+ reply(req, res, async () => {
2546
+ const result = readLedger();
2547
+ json(res, result.error && result.jobs.length === 0 ? 503 : 200, result);
2548
+ });
2549
+ return true;
2550
+ }
2551
+ if (/^\/api\/factory\/jobs\/[^/]+$/.test(url.pathname) && method === "GET") {
2552
+ reply(req, res, async () => {
2553
+ const id = url.pathname.slice("/api/factory/jobs/".length);
2554
+ const result = readLedger();
2555
+ const job = result.jobs.find((j) => j.id === id);
2556
+ if (!job) {
2557
+ json(res, 404, { error: `Job not found: ${id}`, ledgerError: result.error });
2558
+ return;
2559
+ }
2560
+ json(res, 200, { job });
2561
+ });
2562
+ return true;
2563
+ }
2419
2564
  return false;
2420
2565
  }
2421
2566
 
@@ -2505,10 +2650,10 @@ function formatCard(card) {
2505
2650
  }
2506
2651
 
2507
2652
  // src/server/agent/config.ts
2508
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
2509
- import { homedir as homedir3 } from "node:os";
2510
- import { delimiter as delimiter2, dirname as dirname2, join as join4 } from "node:path";
2511
- var DEFAULT_CONFIG_PATH = join4(homedir3(), ".config", "pipe-kan", "agent.json");
2653
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "node:fs";
2654
+ import { homedir as homedir4 } from "node:os";
2655
+ import { delimiter as delimiter2, dirname as dirname2, join as join5 } from "node:path";
2656
+ var DEFAULT_CONFIG_PATH = join5(homedir4(), ".config", "pipe-kan", "agent.json");
2512
2657
  var FALLBACK_MODELS = {
2513
2658
  cursor: [
2514
2659
  { id: "composer-2", name: "Composer 2" },
@@ -2550,21 +2695,21 @@ function commandOnPath(command, env = process.env) {
2550
2695
  if (!command)
2551
2696
  return false;
2552
2697
  if (command.includes("/") || command.includes("\\"))
2553
- return existsSync2(command);
2698
+ return existsSync3(command);
2554
2699
  const pathVar = env.PATH ?? "";
2555
2700
  for (const dir of pathVar.split(delimiter2)) {
2556
2701
  if (!dir)
2557
2702
  continue;
2558
- if (existsSync2(join4(dir, command)))
2703
+ if (existsSync3(join5(dir, command)))
2559
2704
  return true;
2560
2705
  }
2561
2706
  return false;
2562
2707
  }
2563
2708
  function loadAgentConfig(path = agentConfigPath()) {
2564
- if (!existsSync2(path))
2709
+ if (!existsSync3(path))
2565
2710
  return structuredClone(DEFAULT_CONFIG);
2566
2711
  try {
2567
- const raw = JSON.parse(readFileSync3(path, "utf8"));
2712
+ const raw = JSON.parse(readFileSync4(path, "utf8"));
2568
2713
  return mergeConfig(raw);
2569
2714
  } catch {
2570
2715
  return structuredClone(DEFAULT_CONFIG);
@@ -2600,7 +2745,7 @@ function mergeConfig(raw) {
2600
2745
  }
2601
2746
  function ensureAgentConfigDir(path = agentConfigPath()) {
2602
2747
  const dir = dirname2(path);
2603
- if (!existsSync2(dir))
2748
+ if (!existsSync3(dir))
2604
2749
  mkdirSync2(dir, { recursive: true });
2605
2750
  }
2606
2751
 
@@ -2608,7 +2753,7 @@ function ensureAgentConfigDir(path = agentConfigPath()) {
2608
2753
  import { spawn as spawn2 } from "node:child_process";
2609
2754
  import { mkdtempSync, rmSync } from "node:fs";
2610
2755
  import { tmpdir as tmpdir2 } from "node:os";
2611
- import { join as join5 } from "node:path";
2756
+ import { join as join6 } from "node:path";
2612
2757
  import { Readable } from "node:stream";
2613
2758
 
2614
2759
  // node_modules/@agentclientprotocol/sdk/dist/schema/index.js
@@ -12334,7 +12479,7 @@ class AcpSession {
12334
12479
  executeTool = null;
12335
12480
  stderr = "";
12336
12481
  selectedModelId = null;
12337
- workspace = mkdtempSync(join5(tmpdir2(), "pipe-kan-agent-"));
12482
+ workspace = mkdtempSync(join6(tmpdir2(), "pipe-kan-agent-"));
12338
12483
  constructor(config) {
12339
12484
  this.config = config;
12340
12485
  this.id = crypto.randomUUID();
@@ -12646,17 +12791,17 @@ function permissionOptionForDecision(options, decision) {
12646
12791
  }
12647
12792
 
12648
12793
  // src/server/agent/skills.ts
12649
- import { existsSync as existsSync3, readFileSync as readFileSync4, readdirSync } from "node:fs";
12650
- import { homedir as homedir4 } from "node:os";
12651
- import { join as join6 } from "node:path";
12794
+ import { existsSync as existsSync4, readFileSync as readFileSync5, readdirSync } from "node:fs";
12795
+ import { homedir as homedir5 } from "node:os";
12796
+ import { join as join7 } from "node:path";
12652
12797
  import { fileURLToPath } from "node:url";
12653
12798
  function createSkillRegistry(bundledDir) {
12654
- const dir = bundledDir ?? join6(fileURLToPath(new URL(".", import.meta.url)), "..", "..", "..", ".agents", "skills");
12655
- const userDir = join6(homedir4(), ".pi", "agent", "skills");
12799
+ const dir = bundledDir ?? join7(fileURLToPath(new URL(".", import.meta.url)), "..", "..", "..", ".agents", "skills");
12800
+ const userDir = join7(homedir5(), ".pi", "agent", "skills");
12656
12801
  return {
12657
12802
  list() {
12658
12803
  const bundled = listSkills(dir);
12659
- const user = existsSync3(userDir) ? listSkills(userDir) : [];
12804
+ const user = existsSync4(userDir) ? listSkills(userDir) : [];
12660
12805
  const map = new Map;
12661
12806
  for (const skill of bundled)
12662
12807
  map.set(skill.id, skill);
@@ -12666,10 +12811,10 @@ function createSkillRegistry(bundledDir) {
12666
12811
  },
12667
12812
  load(id) {
12668
12813
  const userPath = skillPath(userDir, id);
12669
- if (existsSync3(userPath))
12814
+ if (existsSync4(userPath))
12670
12815
  return readSkill(userPath, id);
12671
12816
  const bundledPath = skillPath(dir, id);
12672
- if (existsSync3(bundledPath))
12817
+ if (existsSync4(bundledPath))
12673
12818
  return readSkill(bundledPath, id);
12674
12819
  return;
12675
12820
  }
@@ -12686,16 +12831,16 @@ function skillContextBlock(skill) {
12686
12831
  };
12687
12832
  }
12688
12833
  function listSkills(dir) {
12689
- if (!existsSync3(dir))
12834
+ if (!existsSync4(dir))
12690
12835
  return [];
12691
12836
  return readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => readSkill(skillPath(dir, entry.name), entry.name)).filter((skill) => skill !== undefined);
12692
12837
  }
12693
12838
  function skillPath(dir, id) {
12694
- return join6(dir, id, "SKILL.md");
12839
+ return join7(dir, id, "SKILL.md");
12695
12840
  }
12696
12841
  function readSkill(path, id) {
12697
12842
  try {
12698
- const text = readFileSync4(path, "utf8");
12843
+ const text = readFileSync5(path, "utf8");
12699
12844
  const front = parseFrontMatter(text);
12700
12845
  return {
12701
12846
  id,
@@ -12722,8 +12867,8 @@ function parseFrontMatter(text) {
12722
12867
  }
12723
12868
 
12724
12869
  // src/server/agent/tools.ts
12725
- import { readFileSync as readFileSync5 } from "node:fs";
12726
- import { join as join7 } from "node:path";
12870
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "node:fs";
12871
+ import { join as join8 } from "node:path";
12727
12872
  var TOOLS = [
12728
12873
  {
12729
12874
  name: "board_state",
@@ -12799,6 +12944,35 @@ var TOOLS = [
12799
12944
  labels: { type: "string", description: "Comma-separated replacement labels" }
12800
12945
  },
12801
12946
  mutates: true
12947
+ },
12948
+ {
12949
+ name: "factory_job_status",
12950
+ description: "Read the latest status and factory stage tag for one or more software-factory jobs from the local ledger. Pass a job id (gbj-YYYYMMDD-NNN) for a single job, or omit id to get the 20 most-recent active jobs.",
12951
+ parameters: {
12952
+ id: { type: "string", description: "Optional job id, e.g. gbj-20260926-011" }
12953
+ },
12954
+ mutates: false
12955
+ },
12956
+ {
12957
+ name: "factory_start_job",
12958
+ description: "Request the Grokbot Coordinator to start a new factory job. Writes a start-request to docs/factory/outbox/ for the coordinator to pick up. Requires user approval. Does NOT append to jobs.jsonl directly.",
12959
+ parameters: {
12960
+ summary: { type: "string", description: "One-line job summary" },
12961
+ repo: { type: "string", description: "Target repo path, e.g. ~/code/pipe-kan" },
12962
+ session: { type: "string", description: "Herdr session name, e.g. jira-kan" },
12963
+ notes: { type: "string", description: "Optional extra context for the coordinator" }
12964
+ },
12965
+ mutates: true
12966
+ },
12967
+ {
12968
+ name: "factory_move_job",
12969
+ description: "Request the Grokbot Coordinator to move a factory job to a new status or stage. Writes a move-request to docs/factory/outbox/ for the coordinator to pick up. Requires user approval. Does NOT append to jobs.jsonl directly.",
12970
+ parameters: {
12971
+ id: { type: "string", description: "Job id to move, e.g. gbj-20260926-011" },
12972
+ status: { type: "string", description: "Target status: queued|routed|in_progress|blocked|done|cancelled" },
12973
+ detail: { type: "string", description: "Optional detail message for the ledger event" }
12974
+ },
12975
+ mutates: true
12802
12976
  }
12803
12977
  ];
12804
12978
  var skills;
@@ -12843,7 +13017,7 @@ var EXECUTORS = {
12843
13017
  return { ok: false, error: "Path traversal not allowed" };
12844
13018
  const repoRoot = process.cwd();
12845
13019
  try {
12846
- const text = readFileSync5(join7(repoRoot, relPath), "utf8");
13020
+ const text = readFileSync6(join8(repoRoot, relPath), "utf8");
12847
13021
  return { ok: true, value: { path: relPath, text } };
12848
13022
  } catch (err) {
12849
13023
  return { ok: false, error: String(err) };
@@ -12914,6 +13088,93 @@ var EXECUTORS = {
12914
13088
  if (result.error)
12915
13089
  return { ok: false, error: result.error };
12916
13090
  return { ok: true, value: { key, __ui_action: "refresh_board" } };
13091
+ },
13092
+ factory_job_status(args) {
13093
+ const id = typeof args.id === "string" ? args.id.trim() : "";
13094
+ const ledger = readLedger();
13095
+ if (id) {
13096
+ const job = ledger.jobs.find((j) => j.id === id);
13097
+ if (!job) {
13098
+ return { ok: false, error: `Job not found: ${id}${ledger.error ? ` (${ledger.error})` : ""}` };
13099
+ }
13100
+ return { ok: true, value: { job, ledgerError: ledger.error } };
13101
+ }
13102
+ const active = ledger.jobs.filter((j) => j.stageTag !== null).slice(0, 20);
13103
+ return {
13104
+ ok: true,
13105
+ value: { jobs: active, total: ledger.jobs.length, ledgerError: ledger.error }
13106
+ };
13107
+ },
13108
+ factory_start_job(args) {
13109
+ const summary = String(args.summary ?? "").trim();
13110
+ if (!summary)
13111
+ return { ok: false, error: "Missing summary" };
13112
+ const repo = String(args.repo ?? "").trim();
13113
+ const session = String(args.session ?? "").trim();
13114
+ const notes = typeof args.notes === "string" ? args.notes.trim() : undefined;
13115
+ const ts = new Date().toISOString();
13116
+ const requestId = crypto.randomUUID();
13117
+ const outboxDir = join8(process.cwd(), "docs/factory/outbox");
13118
+ mkdirSync3(outboxDir, { recursive: true });
13119
+ const filename = `${ts.replace(/[:.]/g, "-")}-${requestId}-start.json`;
13120
+ const payload = {
13121
+ action: "start_job",
13122
+ requested_by: "pipe-kan-acp",
13123
+ ts,
13124
+ requestId,
13125
+ summary,
13126
+ ...repo ? { repo } : {},
13127
+ ...session ? { session } : {},
13128
+ ...notes ? { notes } : {}
13129
+ };
13130
+ writeFileSync3(join8(outboxDir, filename), JSON.stringify(payload, null, 2) + `
13131
+ `, "utf8");
13132
+ return {
13133
+ ok: true,
13134
+ value: {
13135
+ message: `Start request written to docs/factory/outbox/${filename}. The Grokbot Coordinator will pick this up and append the real ledger event.`,
13136
+ outboxFile: filename
13137
+ }
13138
+ };
13139
+ },
13140
+ factory_move_job(args) {
13141
+ const id = String(args.id ?? "").trim();
13142
+ const status = String(args.status ?? "").trim();
13143
+ if (!id)
13144
+ return { ok: false, error: "Missing job id" };
13145
+ if (!status)
13146
+ return { ok: false, error: "Missing target status" };
13147
+ const validStatuses = ["queued", "routed", "in_progress", "blocked", "done", "cancelled"];
13148
+ if (!validStatuses.includes(status)) {
13149
+ return {
13150
+ ok: false,
13151
+ error: `Invalid status '${status}'. Must be one of: ${validStatuses.join(", ")}`
13152
+ };
13153
+ }
13154
+ const detail = typeof args.detail === "string" ? args.detail.trim() : undefined;
13155
+ const ts = new Date().toISOString();
13156
+ const requestId = crypto.randomUUID();
13157
+ const outboxDir = join8(process.cwd(), "docs/factory/outbox");
13158
+ mkdirSync3(outboxDir, { recursive: true });
13159
+ const filename = `${ts.replace(/[:.]/g, "-")}-${requestId}-move.json`;
13160
+ const payload = {
13161
+ action: "move_job",
13162
+ requested_by: "pipe-kan-acp",
13163
+ ts,
13164
+ requestId,
13165
+ id,
13166
+ status,
13167
+ ...detail ? { detail } : {}
13168
+ };
13169
+ writeFileSync3(join8(outboxDir, filename), JSON.stringify(payload, null, 2) + `
13170
+ `, "utf8");
13171
+ return {
13172
+ ok: true,
13173
+ value: {
13174
+ message: `Move request for ${id} → ${status} written to docs/factory/outbox/${filename}. The Grokbot Coordinator will pick this up and append the real ledger event.`,
13175
+ outboxFile: filename
13176
+ }
13177
+ };
12917
13178
  }
12918
13179
  };
12919
13180
  var SYSTEM_TEXT = `Your working context is the attached Jira issues from the pipe. Answer from that payload. Do not search GitHub, git history, or local source files unless the user explicitly asks about the pipe-kan app itself.
@@ -13389,12 +13650,12 @@ function handleRequest(req, res, ctx) {
13389
13650
  }
13390
13651
 
13391
13652
  // src/jira-config.ts
13392
- import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "node:fs";
13393
- import { join as join8 } from "node:path";
13653
+ import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
13654
+ import { join as join9 } from "node:path";
13394
13655
  function writeJiraConfig(dir, server) {
13395
- mkdirSync3(dir, { recursive: true });
13396
- const path = join8(dir, "jira.config.yml");
13397
- writeFileSync3(path, [
13656
+ mkdirSync4(dir, { recursive: true });
13657
+ const path = join9(dir, "jira.config.yml");
13658
+ writeFileSync4(path, [
13398
13659
  "installation: Cloud",
13399
13660
  `server: ${server}`,
13400
13661
  `login: ${ME.emailAddress}`,
@@ -13448,8 +13709,8 @@ function stdinStat() {
13448
13709
  }
13449
13710
 
13450
13711
  // src/ui.ts
13451
- import { createReadStream, existsSync as existsSync4, statSync } from "node:fs";
13452
- import { dirname as dirname3, extname, join as join9, resolve as resolve2, sep } from "node:path";
13712
+ import { createReadStream, existsSync as existsSync5, statSync as statSync2 } from "node:fs";
13713
+ import { dirname as dirname3, extname, join as join10, resolve as resolve2, sep } from "node:path";
13453
13714
  import { fileURLToPath as fileURLToPath2 } from "node:url";
13454
13715
  var types = {
13455
13716
  ".css": "text/css; charset=utf-8",
@@ -13466,7 +13727,7 @@ function packageRoot(from = import.meta.url) {
13466
13727
  return resolve2(dirname3(fileURLToPath2(from)), "..");
13467
13728
  }
13468
13729
  function uiDir(root) {
13469
- return join9(root, "dist", "ui");
13730
+ return join10(root, "dist", "ui");
13470
13731
  }
13471
13732
  function inside(root, file) {
13472
13733
  const base = resolve2(root);
@@ -13475,12 +13736,12 @@ function inside(root, file) {
13475
13736
  }
13476
13737
  function sendUi(root, req, res) {
13477
13738
  const ui = uiDir(root);
13478
- const index = join9(ui, "index.html");
13479
- if (!existsSync4(index))
13739
+ const index = join10(ui, "index.html");
13740
+ if (!existsSync5(index))
13480
13741
  return false;
13481
13742
  const path = new URL(req.url ?? "/", "http://127.0.0.1").pathname;
13482
13743
  const wanted = resolve2(ui, `.${decodeURIComponent(path)}`);
13483
- const file = inside(ui, wanted) && existsSync4(wanted) && statSync(wanted).isFile() ? wanted : index;
13744
+ const file = inside(ui, wanted) && existsSync5(wanted) && statSync2(wanted).isFile() ? wanted : index;
13484
13745
  res.setHeader("content-type", types[extname(file)] ?? "application/octet-stream");
13485
13746
  createReadStream(file).pipe(res);
13486
13747
  return true;
@@ -13496,7 +13757,7 @@ function announce(line) {
13496
13757
  }
13497
13758
  async function runServer(opts) {
13498
13759
  const piped = await readPipe();
13499
- const raw = piped ?? JSON.parse(readFileSync6(join10(opts.root, "fixtures/issues.json"), "utf8"));
13760
+ const raw = piped ?? JSON.parse(readFileSync7(join11(opts.root, "fixtures/issues.json"), "utf8"));
13500
13761
  const flags = argvToFlags(process.argv);
13501
13762
  const { app, store, kind } = await createBoardApp({
13502
13763
  raw,
@@ -13533,7 +13794,7 @@ async function runServer(opts) {
13533
13794
  announce(`cli plane ${planeHost()} ${planeWorkspace(flags)}`);
13534
13795
  announce(`Plane host default ${DEFAULT_PLANE_HOST}`);
13535
13796
  } else {
13536
- const fakeConfig = writeJiraConfig(join10(tmpdir3(), "pipe-kan"), origin);
13797
+ const fakeConfig = writeJiraConfig(join11(tmpdir3(), "pipe-kan"), origin);
13537
13798
  announce(`cli ${kind === "jira" ? resolveJiraBin() : "store"}`);
13538
13799
  announce(`Fake Jira ${origin}/rest/api/2/search`);
13539
13800
  announce(`Fake Jira config ${fakeConfig}`);